タイトル長くてすみません。今年9月に下記の記事を書きました。
この中で「詳細な技術ナレッジについては、後日別記事でまとめていきたいと思います。」と書いたにもかかわらず、やるやる詐欺状態になっていたので、少しだけ Smart Class Room の裏側について紹介したいと思います。
また、先日 SORACOM さんから SORACOM LTE-M Button powered by AWS という製品が発表・発売されました。もともと AWS IoT Enterprise Button を利用してプロダクト開発していたのですが、それとの差分としては
- セルラー通信を使えるので Wi-Fi 環境のない小学校でも利用できるようになること
- また、セルラー通信により学校から家の間でもボタンからクラウドへの通信ができるようになるため、通学や帰り道をサポートする機能を構築できること
- 乾電池駆動になったので、電池交換ができるようになったこと
が挙げられます。今回、Smart Class Room を SORACOM LTE-M Button powered by AWS 対応してみたので、それについても紹介したいと思います。なお、この記事は SORACOM LTE-M Button powered by AWS Advent Calendar 2018 - Qiita の3日目の記事となります。
Smart Class Room について
簡単に言うと、授業についていけているかどうかを IoT ボタンを押すことで示し、先生はその情報を見ながら授業をインタラクティブに進めるというプロダクトです。シャイな子どもは皆の前で質問したりすることができないので、「分からない」をこっそり伝えられればという想いがあります。また、その情報を親御さんにもフィードバックし、家庭学習の力の入れどころ、つまり「今日はボタンをたくさん押していたのでヘルプしてあげてね」というレポートを送ります。このプロダクトを通じて小1の壁問題をなくす一助にしたい、という想いでプロトタイプ構築しました。飛躍している部分もありますので、もしよろしければスライドをご覧いただければと思います。
Smart Class Room のアーキテクチャについて
Smart Class Room は小学校に導入していただくサービスとして開発したため、下記の点を意識してアーキテクチャ設計しました。
- なるべく安価に構築できること
- (導入校が増えるといった)ある程度予期できる長期的スパンの利用者増に、少ないオペレーションで対応できること(オペレーションの人件費をなるべくかけなくてもいいようにすること)
- (その日だけやたらボタンが押されるといった)予期できない短期的なスパイクにも自動的に対応できること
採用したアーキテクチャの概要図です。
簡単に紹介すると、
- ボタンからの情報送信は Lambda で受け、DynamoDB にデータストアしています。図にはありませんが、ボタンと Lambda の間には AWS IoT 1-Click が挟まっています。
- 先生が理解度を確認する画面は S3 の静的ホスティングで提供しています。フロントエンドのフレームワークとして Vue.js を利用しています。
- 画面が理解度情報を取得するための API は、API Gateway と Lambda を用いています。
といった構成になっています。2つ目と3つ目についてはここ数年で定番となったサーバーレス構成で、背景にある低コスト化*1、高スケーラビリティを実現できる構成となっています。このあたりはある程度ナレッジが集まっていると思うので、この記事では1番上の部分を深掘って紹介したいと思います。なお、サーバーレスな構成を作りたい方は下記の記事もご覧いただけばお役に立てることがあるかもしれません。
AWS IoT Enterprise Button から DynamoDB までの実装の流れ
AWS IoT Enterprise Button を押下してからデータストア部分までで行っていることは下記の2つです。
- AWS IoT 1-Click を使って、ボタンが押されたときに Lambda Function を発火できるようにする
- Lambda Function で押された情報を Dynamo DB に投入する
上の発火までの流れについては公式で手厚くサポートされておりますので、こちらをご覧いただくとよいかと思います。
つづいて、Lambda Function についてです。例外ハンドリングと返り値が適当で申し訳ないのですが、下記のような実装になっています。
import boto3 import json import logging logger = logging.getLogger() logger.setLevel(logging.INFO) dynamo_comprehension_tbl = boto3.resource('dynamodb').Table("Comprehension") def lambda_handler(event, context): logger.info('Received event: ' + json.dumps(event)) dsn = event['deviceInfo']['deviceId'] click_type = event['deviceEvent']['buttonClicked']['clickType'] _insert_dynamo(dsn, click_type) def _insert_dynamo(device_id, click_type): is_understood = True if click_type == 'DOUBLE': is_understood = True elif click_type == 'SINGLE': is_understood = False else: return {"status": "NG"} dynamo_comprehension_tbl.put_item( Item={ "device_id": device_id, "is_understood": is_understood } ) return {"status": "OK"}
とてもシンプルな Lambda Function になっています。以上が、もともと構築していた Smart Class Room の実装概要となります。近々フロント部分やAPI部分も含めてGitHubに公開しようと思っておりますので、もしよろしければご覧ください。
SORACOM LTE-M Button powered by AWS 対応について
さて、ここからは SORACOM ボタンの対応について紹介します。「対応」と書いたのですが、ここまで実装してあると実はほとんどやることがありません。下記の SORACOM さん公式サイトの、ステップ1~3を実施したのみです。
ステップ2については既にプロジェクトがあるので、そのプロジェクトに紐づくようにプレイスメントを新規で作成するだけでよいことだけご注意ください。冒頭に書いたとおり、これによって Wi-Fi 環境のない小学校(普及率どれくらいなんですかね?)でも、このプロダクトをご利用いただけるようになります。
続いて、せっかくですので「セルラー通信により学校から家の間でもボタンからクラウドへの通信ができるようになるため、通学や帰り道をサポートする機能」についても簡単なものを実装してみました。IoT Button では、
- シングルクリック
- ダブルクリック
- 長押し
を検知することができます。Smart Class Room では一番最後の「長押し」をまだ使っていなかったので、「学校帰りに習い事の場所についたらボタンを長押しして親にメールする」機能を実装してみたいと思います。
SESの設定
まず、メール送受信サービスであるSESを利用するので、その設定を行います。東京リージョンでは利用できないので、バージニア北部リージョンに変更していることにご注意ください。初期設定として、利用するメールアドレスの登録・Verifyを行います。
入力したメールアドレスにメールが届くので、Verifyリンクをクリックしてください。
Lambda Function の変更
長押しされたときに、SESからメールを送るように変更しました。今回は送信、受信ともに同じメールアドレスからとしていますが、SESに独自ドメインを登録することで独自ドメインからのメール送付を行うことも可能です。
import boto3 import json import logging logger = logging.getLogger() logger.setLevel(logging.INFO) dynamo_comprehension_tbl = boto3.resource('dynamodb').Table("Comprehension") ses_client = boto3.client('ses', region_name='us-east-1') # Add def lambda_handler(event, context): logger.info('Received event: ' + json.dumps(event)) dsn = event['deviceInfo']['deviceId'] click_type = event['deviceEvent']['buttonClicked']['clickType'] if click_type == 'LONG': # Update _send_email() else: _insert_dynamo(dsn, click_type) def _insert_dynamo(device_id, click_type): is_understood = "" if click_type == 'DOUBLE': is_understood = True elif click_type == 'SINGLE': is_understood = False else: return {"status": "NG"} dynamo_comprehension_tbl.put_item( Item={ "device_id": device_id, "is_understood": is_understood } ) return {"status": "OK"} def _send_email(): # Add Function return ses_client.send_email( Source='******@gmail.com', Destination={ 'ToAddresses': [ '******@gmail.com', ] }, Message={ 'Subject': { 'Data': 'スイミングスクール到着', }, 'Body': { 'Text': { 'Data': 'スイミングスクールに着きました!がんばります!' , }, } } )
長押しすると..
変更は以上になります。ボタンを長押しすると...
無事にメールが届きました!私のような心配性のお父さんも安心ですね!
まとめと余談
IoT Button を利用したプロトタイプの技術部分の紹介と、SORACOM ボタンを用いた機能拡張について書きました。SORACOM ボタンを使うことで、他にもいろいろと社会に役立つサービスを構築できると思うので、今後も妄想を膨らませていきたいと思います。
最後に余談ですが、この記事を投稿する前日まで、EdTech Taiwan でこちらのプロダクトを展示してきました。台湾では SORACOM さんのボタンは使えませんが、せっかくですので一緒に並べさせていただきました。Smart Class Room*2 の展示の風景を載せてこの記事を終わりにしたいと思います。
*1:リクエスト課金なだけで、使われ方によってはサーバーありの方が安いのかもしれません。ただ、利用者が少ない実証実験段階ではこの構成はほとんど課金が発生しません。SOCIAL FIGHTER AWARD で発表をした9月の実績で81セント、約100円です。ドメイン登録の代金と AWS IoT 1-Click で登録したデバイス料金がほとんどを占めます。例えば、30人のクラス3クラスで実証実験したときに、増える AWS 利用料は AWS IoT 1-Click によるデバイス数増です。0.25ドル x 30人 x 3クラス で3,000円/月もあればどうにかなるでしょうか。これに Lambda などの他サービスが無料利用枠を超えた場合に、追加でお金がかかります。リクエスト課金型の構成にしているため、使われ方によって費用が変わってくることにだけご注意ください。
*2:展示をしている途中にクラスルームは class room ではなく classroom が正しいスペリングだと気が付きましたorz