親子でできる!Scratch と AWS を使った "ものづくり" 体験 - 1. 準備 〜 疎通確認編
金澤 圭
テクニカルソリューションアーキテクトの金澤 (@ketancho) です。
今年の春から小学校でのプログラミング教育が必修化されましたね。私にはふたりの娘がいるのですが、上の子が来年から小学生になることもあり、この必修化にとても興味があります。Web で様々な情報を見ていると、自身でプログラミングをやったことがない先生や親も多いことから、試行錯誤が続いている状況なのかなと思っています。いちエンジニアとして、いち父親として、子どもたちが少しでも楽しくプログラミング、あるいはプログラミング的な考え方を学んでもらえるといいなと思っています。
そこで、この How to be a Developer カテゴリで、親子でできるプログラミング体験 ! 的な不定期連載を始めることにしました。「親子でできる」と「実際に動くものを作る」というところに重きをおきたいと思っています。国語や算数は、細かい学習要項は違えど自身も学んでいることですし、子どもに教えることができると思うんです (そんなことないぞ ! 今の小学生は難しいことやってるぞ ! というツッコミをもらいそう)。しかし、自身が学んでないことを教えるってなかなか大変ですよね ? であれば、親も子どもと一緒に学んでいくというスタンスはどうかな、という狙いで、実際に親子で試せる記事を書いていきたいと思います。
小学校プログラミング教育の手引 というサイトによると、小学 3 年生から授業のどこかでプログラミング的な考え方が出てくるようです。私自身も、2 年半後に小学 3 年生になっている娘にいいアドバイスができるように、この連載を頑張っていこうと思っています。
目次
ご注意
本記事で紹介する AWS サービスを起動する際には、料金がかかります。builders.flash メールメンバー特典の、クラウドレシピ向けクレジットコードプレゼントの入手をお勧めします。
このクラウドレシピ (ハンズオン記事) を無料でお試しいただけます »
毎月提供されるクラウドレシピのアップデート情報とともに、クレジットコードを受け取ることができます。
1. 作ったもの
連載ものとして、しばらくは Scratch を使ってものづくりをしていきたいと思います。3年前に CoderDojo という勉強会でメンターをやらせてもらったときに少し Scratch を触ったのですが、ブロックを組み合わせてビジュアルでプログラミング的思考を学べるとてもいい教材だなと思いました。
この Scratch に AWS のサービスや機能を絡めながら、何か楽しいものを作れればいいなと思っています。具体的には、AWS の各種 AI サービスを利用したオリジナルブロックを作れればと考えています。例えば、AWS には Amazon Comprehend という機械学習を使用した自然言語処理サービスがあります。このサービスを活用して “元気かどうかを判定する” ブロックといった、子どもでも理解しやすいものを作っていきたいと思います。
本連載では、下記のような流れで親子でものづくりをしていきます。
- 親が Scratch に独自ブロック (Scratch の拡張機能について) を用意します。独自ブロックは AWS サービスを呼び出し、デフォルトの Scratch にはない機能を提供します。
- お子さんはその独自ブロックを使って、何かしら面白い動きを Scratch 上で開発してもらいます。
親子でひとつのものを作り上げる中で、
親「こういうブロック作ってみたんだけど使ってみない?」
子「すごい!使ってみる!」
子「お父さん!こないだのブロックうまく動かないんだけど!!」
親「ご、ごめん。急いで直すね🙏」
といったコミュニケーションを楽しんでもらえると嬉しいです。
本当はこの記事からお子さんにも作業をしてもらいたかったのですが、Scratch に独自ブロックを作るには下準備が必要です。連載初回のこの記事は「準備編」ということで、親の作業のみを進めていきます。独自ブロックを作る下準備を行った上で、Amazon API Gateway で作った簡単な Web API を呼び出せるかの疎通確認まで行います。子どもと一緒に作るパートについては、次回以降の記事で書ければと思いますので、もう少しお待ちいただければと思います。
2. 作業の前提について
- PC に Git と Node.js がインストールされている必要があります。(親子でひとつ PC があれば問題ありません。)
- AWS アカウント、および Amazon API Gateway のリソースを作成する権限のある IAM ユーザーが必要です。
もし AWS アカウントをお持ちでない方、IAM ユーザーの作り方が分からない方は、こちらのハンズオン を参考に AWS アカウントと IAM ユーザーを作成してみてください。
3. やってみよう
それでは、ここから具体的な作業を進めていきたいと思います。初めて AWS をご利用される方、初めて Scratch を触る方でも作業を進められるように書いていければと思いますが、分かりにくい部分があればご指摘ください。(なお、筆者も Scratch の独自機能を作るのは初めてです。お作法が守れてない!などがございましたら、教えていただければ幸いです。)
作業は下記の順番で進めていきます。
- [AWS 側] Amazon API Gateway を利用し、モック Web API を作成する
- [Scratch 側] 独自ブロックの GUI を作成する
- [Scratch 側] 独自ブロックの機能を実装する
- 全体の動作テストを行う
それでは始めましょう!
4. [AWS 側] Amazon API Gateway を利用し、モック Web API を作成する
まず AWS 側の作業を進めていきます。マネジメントコンソールにログインしてください。
ログインできましたら、API Gateway の画面に遷移します。「サービスを検索する」の検索窓に “API Gateway” と入力します。
クリックすると拡大します
続いて、API タイプを選んでいきます。ここでは「REST API」 を選択してください。
クリックすると拡大します
続いて、下の画面では「REST」「新しい API」とラジオボタンを選択します。
今回は 独自ブロックからの疎通確認をするための Web API ですので、名前を “TestWebAPI” として「API の作成」ボタンを押してください。ここまでで API Gateway のリソースが作成できました。
クリックすると拡大します
続いて、Web API としての振る舞いを定義していきます。今回は Scratch からの疎通を確認できればよいので、GET リクエストを送ると固定の JSON データが返ってくるだけの Web API を作ります。アクション > メソッドの作成 と選んでください。
クリックすると拡大します
プルダウンがでてきますので、その中から「GET」を選んで、右側のチェックマークを押してください。
クリックすると拡大します
続いて、API が呼ばれた際の動きを選択します。今回は「Mock」を選んで保存としてください。
クリックすると拡大します
続いて、「統合レスポンス」をクリックします。ここで返却する固定の JSON を定義していきます。
クリックすると拡大します
こちらの画面で、左側の三角マークを 2 箇所クリック後、application/json を選択しマッピングテンプレートを修正します。
クリックすると拡大します
ここでは下記の内容を入力して、画面右下の保存ボタンをクリックしてください。(右上にもボタンがあるので間違えないようにしてください)
{
'statusCode': 200,
'body': {
"message": "Hello from API Gateway!"
}
}
クリックすると拡大します
続いて、CORS の設定を進めていきます。今回は localhost 上に独自の Scratch 環境を用意し、そこから Web API を呼び出すのでこの設定が必要になります。「左上のメソッドの実行」リンクを押してください。
クリックすると拡大します
左上の アクション > CORS 有効化 を選択してください。
クリックすると拡大します
「CORS の有効化」画面はデフォルトのまま変更せず、右下のボタンをクリックしてください。
クリックすると拡大します
ポップアップが出てくるので、そのまま右下のボタンを押します。
クリックすると拡大します
ここまでで Web API の定義は完了です。早速世の中に公開し、Scratch から呼び出せるようにしましょう。左上の アクション > API のデプロイ と進めてください。
クリックすると拡大します
デプロイされるステージで「新しいステージ」を選択後、ステージ名を「dev」とし、右下の「デプロイ」ボタンを押してください。
クリックすると拡大します
うまくデプロイできましたでしょうか?試しに作成した Web API を呼び出してみたいと思います。「URL の呼び出し」の隣にある URL をクリックしてみてください。
クリックすると拡大します
こちらのように先程入力した JSON が返ってくれば成功です。
クリックすると拡大します
こちらで Web API の作成ができました !🎉
Amazon API Gateway は、簡単に API の作成、公開、保守、モニタリングが行えるフルマネージド型サービスです。今回の記事以上のことを試してみたいという方は、実際に手を動かしながら AWS を学べる動画ハンズオン AWS Hands-on for Beginners にて、API Gateway を学べるコンテンツ をご用意していますので、こちらもあわせてご覧いただければと思います。
こちらで AWS 側の作業は完了です。続いて Scratch 側の作業をしてきましょう。
5. [Scratch 側] 拡張機能を作る準備をする
Scratch 3.0の拡張機能を作ってみよう というページに、事前準備の流れや、簡単な拡張機能の例が載っていますので、こちらを参考に作業を進めていきます。まず、Scratch 3.0の拡張機能を作ってみよう/下準備 に従ってセットアップを行います。この作業については、公式ページの手順をそのまま実行する形になりますので、リンク先をご覧ください。
その後、scratch-gui ディレクトリ上で npm start してみてください。少し待つとターミナルに "Compiled successfully." とメッセージがでてきますので、その後ブラウザで localhost:8601 にアクセスすると、こちらのような Scratch の画面が出てくるはずです。ここまで下準備完了です。
クリックすると拡大します
6. [Scratch 側] 独自ブロックの GUI を作成する
続いて、Scratch 3.0の拡張機能を作ってみよう/GUI側の設定 に従って、Scratch の GUI を拡張していきます。
まず、サイズが 600x372 の画像、サイズが 80x80 の画像を用意する必要があります。私はお絵かきツールで簡単な画像を用意し、builders-flash-blocks.png と builders-flash-blocks-small.png という名前にしています。(もし画像を用意するのがめんどくさい、という方は私の描いた画像をお使いいただければと思います)
scratch-gui/src/lib/libraries/extensions 以下に、ディレクトリをひとつ作成し (builders-flash-blocks というディレクトリ名にしています)、先程のふたつの画像を格納してください。こちらのように配置できましたでしょうか ?
クリックすると拡大します
その後、scratch-gui/src/lib/libraries/extensions/index.jsx ファイルの上部で、ふたつの画像をインポートします。
import React from 'react';
import {FormattedMessage} from 'react-intl';
// 追加(ここから)
import buildersFlashImage from './builders-flash-blocks/builders-flash-blocks.png';
import buildersFlashInsetImage from './builders-flash-blocks/builders-flash-blocks-small.png';
// 追加(ここまで)
import musicIconURL from './music/music.png';
import musicInsetIconURL from './music/music-small.svg';
// 以下略
続いて拡張ブロックの名前や説明文を追加していきます。同じファイルの中段に、その情報を追加していきます。
// 上部略
export default [
// 追加(ここから)
{
name: "びるだーずふらっしゅ",
extensionId: 'buildersflash',
iconURL: buildersFlashImage,
insetIconURL: buildersFlashInsetImage,
description: "AWS 上のリソースと繋げる拡張です",
featured: true,
internetConnectionRequired: true
},
// 追加(ここまで)
{
name: (
<FormattedMessage
defaultMessage="Music"
description="Name for the 'Music' extension"
id="gui.extension.music.name"
/>
),
// 以下略
7. [Scratch 側] 独自ブロックの機能を実装する
ここまででガワができたので、最後に機能を実装していきます。基本的な流れについては、Scratch 3.0の拡張機能を作ってみよう/基本の書式 のページが分かりやすいです。
まず scratch-vm/src/extensions 以下に、今回の独自ブロック用のディレクトリを作成します。ここでは scratch3_buildersflash という名前にしています。その下に、index.js ファイルを作成し、機能を実装していきます。
ポイントは2箇所で、まず独自ブロックごとに blocks 配列にその定義を追加します (ソースコード内ポイント 1 の部分)。BlockType がいくつか用意されているのですが、今回は COMMAND にしています。opcode の部分が後述の実装部分のメソッド名にする必要があります。
続いて、実際の動きを実装していきます。今回は先程作成したモック API を呼び出すだけのブロックを作っていくのですが、この実装については Scratch 3.0 の拡張機能を作ってみよう/応用 のページを参考にさせていただきました。Web API の URL は、前半で皆さまが作成した Web API の URL に置き換えてください。(ソースコード内ポイント 2 の部分)
(なお、blockIconURI、menuIconURI で指定しているデータですが、独自ブロックのアイコンになります。今回は簡易的なものにしていますが、40 x 40 の svg 画像をご用意いただけるとお好きなアイコンに変更可能です。)
const ArgumentType = require('../../extension-support/argument-type');
const BlockType = require('../../extension-support/block-type');
const Cast = require('../../util/cast');
const log = require('../../util/log');
const nets = require('nets');
/**
* Icon svg to be displayed at the left edge of each extension block, encoded as a data URI.
* @type {string}
*/
// eslint-disable-next-line max-len
const blockIconURI = 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHdpZHRoPSIzOC43MTI5NCIgaGVpZ2h0PSIzOC43MTI5NCI+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTIxMC42Njk4OCwtMTYxLjI5ODkzKSI+PGcgZGF0YS1wYXBlci1kYXRhPSJ7JnF1b3Q7aXNQYWludGluZ0xheWVyJnF1b3Q7OnRydWV9IiBmaWxsPSIjZmZiNTQ2IiBmaWxsLXJ1bGU9Im5vbnplcm8iIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBzdHJva2UtbGluZWNhcD0iYnV0dCIgc3Ryb2tlLWxpbmVqb2luPSJtaXRlciIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBzdHJva2UtZGFzaGFycmF5PSIiIHN0cm9rZS1kYXNob2Zmc2V0PSIwIiBmb250LWZhbWlseT0ibm9uZSIgZm9udC13ZWlnaHQ9Im5vbmUiIGZvbnQtc2l6ZT0ibm9uZSIgdGV4dC1hbmNob3I9Im5vbmUiIHN0eWxlPSJtaXgtYmxlbmQtbW9kZTogbm9ybWFsIj48cGF0aCBkPSJNMjEwLjY2OTg4LDE4MC42NTU0YzAsLTEwLjY5MDI4IDguNjY2MTksLTE5LjM1NjQ3IDE5LjM1NjQ3LC0xOS4zNTY0N2MxMC42OTAyOCwwIDE5LjM1NjQ3LDguNjY2MTkgMTkuMzU2NDcsMTkuMzU2NDdjMCwxMC42OTAyOCAtOC42NjYxOSwxOS4zNTY0NyAtMTkuMzU2NDcsMTkuMzU2NDdjLTEwLjY5MDI4LDAgLTE5LjM1NjQ3LC04LjY2NjE5IC0xOS4zNTY0NywtMTkuMzU2NDd6IiBkYXRhLXBhcGVyLWRhdGE9InsmcXVvdDtvcmlnUG9zJnF1b3Q7Om51bGx9Ii8+PC9nPjwvZz48L3N2Zz4=';
/**
* Icon svg to be displayed in the category menu, encoded as a data URI.
* @type {string}
*/
// eslint-disable-next-line max-len
const menuIconURI = 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHdpZHRoPSIzOC43MTI5NCIgaGVpZ2h0PSIzOC43MTI5NCI+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTIxMC42Njk4OCwtMTYxLjI5ODkzKSI+PGcgZGF0YS1wYXBlci1kYXRhPSJ7JnF1b3Q7aXNQYWludGluZ0xheWVyJnF1b3Q7OnRydWV9IiBmaWxsPSIjZmZiNTQ2IiBmaWxsLXJ1bGU9Im5vbnplcm8iIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIiBzdHJva2UtbGluZWNhcD0iYnV0dCIgc3Ryb2tlLWxpbmVqb2luPSJtaXRlciIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBzdHJva2UtZGFzaGFycmF5PSIiIHN0cm9rZS1kYXNob2Zmc2V0PSIwIiBmb250LWZhbWlseT0ibm9uZSIgZm9udC13ZWlnaHQ9Im5vbmUiIGZvbnQtc2l6ZT0ibm9uZSIgdGV4dC1hbmNob3I9Im5vbmUiIHN0eWxlPSJtaXgtYmxlbmQtbW9kZTogbm9ybWFsIj48cGF0aCBkPSJNMjEwLjY2OTg4LDE4MC42NTU0YzAsLTEwLjY5MDI4IDguNjY2MTksLTE5LjM1NjQ3IDE5LjM1NjQ3LC0xOS4zNTY0N2MxMC42OTAyOCwwIDE5LjM1NjQ3LDguNjY2MTkgMTkuMzU2NDcsMTkuMzU2NDdjMCwxMC42OTAyOCAtOC42NjYxOSwxOS4zNTY0NyAtMTkuMzU2NDcsMTkuMzU2NDdjLTEwLjY5MDI4LDAgLTE5LjM1NjQ3LC04LjY2NjE5IC0xOS4zNTY0NywtMTkuMzU2NDd6IiBkYXRhLXBhcGVyLWRhdGE9InsmcXVvdDtvcmlnUG9zJnF1b3Q7Om51bGx9Ii8+PC9nPjwvZz48L3N2Zz4=';
/**
* Class for the new blocks in Scratch 3.0
* @param {Runtime} runtime - the runtime instantiating this block package.
* @constructor
*/
class Scratch3NewBlocks {
constructor (runtime) {
/**
* The runtime instantiating this block package.
* @type {Runtime}
*/
this.runtime = runtime;
//this._onTargetCreated = this._onTargetCreated.bind(this);
//this.runtime.on('targetWasCreated', this._onTargetCreated);
}
/**
* @returns {object} metadata for this extension and its blocks.
*/
getInfo () {
return {
id: 'buildersflash',
name: 'New Blocks',
menuIconURI: menuIconURI,
blockIconURI: blockIconURI,
blocks: [
{
opcode: 'callTestAPI',
blockType: BlockType.COMMAND,
text: 'お父さんのテスト機能を呼び出す'
}
],
menus: {
}
};
}
callTestAPI (args) {
const ajaxPromise = new Promise(resolve => {
nets({
url: "https://a3hfx1zjrj.execute-api.ap-northeast-1.amazonaws.com/dev"
}, function(err, res, body){
resolve(body);
return body;
});
});
return ajaxPromise;
}
}
module.exports = Scratch3NewBlocks;
最後に src/extension-support/extension-manager.js に、独自ブロックの情報を追加して完成です。
//上部略
const builtinExtensions = {
// ここから
buildersflash: () => require('../extensions/scratch3_buildersflash'),
// ここまで
// This is an example that isn't loaded with the other core blocks,
// but serves as a reference for loading core blocks as extensions.
coreExample: () => require('../blocks/scratch3_core_example'),
// 以下略
8. 動かしてみる
改めて scratch-gui ディレクトリ上で npm start してみます。 ブラウザで localhost:8601 にアクセスすると、準備段階と同じ画面に遷移します。左下のプラスの青いボタンを押してみてください。
クリックすると拡大します
すると、こちらのように拡張機能が追加されているはずです。(もしうまく表示されない、という方は、npm start したターミナルでエラーが出てないか、ブラウザの開発者ツールでエラーが出てないかを確認してみてください)
続いて拡張機能の動きを確認していきます。左上のアイコンを押してみましょう。
クリックすると拡大します
こちらのような「お父さんのテスト機能を呼び出す」ブロックが表示されましたでしょうか ?
クリックすると拡大します
このブロックを右側のエリアにドラックアンドドロップし、クリックした際に、このように Web API を呼び出せていれば成功です🎉
クリックすると拡大します
9. まとめ
「親子で作る」連載シリーズの最初の記事は以上となります。「親子で」と書きましたが、今回は親が環境を整えるだけの準備編でした。この時点で 6 歳の娘に Scratch の画面を見せてみましたが「猫かわいいね」とのコメントしかもらえませんでした。まぁそうですよね。
次回から、子どもが楽しめる (かもしれない) 何かを作っていければと考えていますので、またご覧いただければと思います。それでは !
筆者プロフィール
金澤 圭 (@ketancho)
アマゾン ウェブ サービス ジャパン合同会社
技術統括本部 ソリューションアーキテクト
サーバーレスが好きなテクニカルソリューションアーキテクト。業種業界問わず、お客様のプロダクト開発をサポートさせていただいています。「AWS Hands-on for Beginners」というオンデマンドで視聴できるハンズオンも企画・推進しており、楽しく学べるコンテンツを日々考えています。好きなサービスは AWS Lambda と AWS Amplify で、好きな休日の過ごし方は娘ふたりと川の字になって昼寝です👧👧
AWS を無料でお試しいただけます