Slide 1

Slide 1 text

AWS IoT CoreとM5StickCで作る ⾃動出退勤記録システム 2020/03/14 JAWS DAYS 2020 株式会社Fusic 岡嵜雄平

Slide 2

Slide 2 text

⾃⼰紹介 岡嵜 雄平(@Y_uuu) IoTエンジニア ⾃社サービスmockmockの開発・運⽤を担当 ⾃⼰紹介

Slide 3

Slide 3 text

mockmock 最近のお仕事 • IoTサーバへデバイスの代わりにデータ送信 • さまざまな⽅法でテストデータを⾃動⽣成 • 各種クラウドサービス(AWS, GCP, Azure)やSORACOMと連携 IoTのテストを⽀援する https://bit.ly/37tA9bf で検索

Slide 4

Slide 4 text

私のミッション 「IoT開発を啓蒙する」

Slide 5

Slide 5 text

IoT開発における課題 • システムの全体像を描きづらい • 技術要素が多彩(デバイス, 通信, クラウド, Web, etc) • ⼀品モノが多く、開発⼿法を画⼀化しにくい • プロジェクトにおけるステークホルダーが多い

Slide 6

Slide 6 text

解決策︓⼩さく始めて⼤きく育てる • まずは電⼦⼯作+クラウドで通知からはじめる • PoC(実証実験)で効果を測り、PDCAを回す • ⼩さくてもたたき台がある⽅が認識を合わせやすい

Slide 7

Slide 7 text

IoTシステムを ⼩さく(社内で使う想定で) 作った事例を紹介

Slide 8

Slide 8 text

システム概要 ⾃動出退勤記録システムとは

Slide 9

Slide 9 text

課題: Slackでの出退勤宣⾔がめんどう • フルフレックス制→みんな出退勤の時間がバラバラ • とあるチームはSlackに⼿動で出退勤を宣⾔する運⽤ 「しゅっしゃー」と ⼊⼒する⼿間を効率化したい

Slide 10

Slide 10 text

解決策: iBeaconで出退勤を検知 • iBeacon: スマホをBeacon化する技術 • Bluetooth Low Energyでの通信なのでバッテリー 消費が⾮常に⼩さい • iBeaconを検知したときに出勤を通知 • iBeaconを検知しなくなったときに退勤を通知 ※iBeaconの検知には⼿元にあったM5StickCを使⽤

Slide 11

Slide 11 text

簡易ダッシュボード(Beacons) • 検出中のBeaconの⼀覧を表⽰ • Beaconに⾃分を紐付けられる→Slack通知時の名前表⽰に使⽤ Beaconに⾃分を紐付け Beaconの ログ⼀覧を表⽰

Slide 12

Slide 12 text

簡易ダッシュボード(Logs) • 特定のBeaconのログを表⽰ 出勤時刻 退勤時刻

Slide 13

Slide 13 text

紐付けたBeaconを検出するとSlackへ通知

Slide 14

Slide 14 text

つまりこんな感じ – 出勤時 1. iBeaconを発信する スマホを持った⼈が出勤 2. iBeaconを検出 3. iBeaconの情報を クラウドへ送信 4. iBeaconの情報から 出社した⼈物を特定 5. Slackへ通知

Slide 15

Slide 15 text

つまりこんな感じ – 退勤時 1. iBeaconを発信する スマホを持った⼈が退勤 2. 検出されなくなった iBeaconから⼈物を特定 3. Slackへ通知

Slide 16

Slide 16 text

システム構成 • AWS Cloud内はAmplify + IoT Core + Lambdaで構築

Slide 17

Slide 17 text

システム構成 STEP1 STEP2 STEP3 • 構築⼿順はSTEP1〜3に分割して解説します

Slide 18

Slide 18 text

アジェンダ 事前準備︓システム間のI/Fを定義 STEP1: フロントエンド・バックエンドの実装 STEP2: IoTにおける送受信部の実装 STEP3: デバイス側の開発 まとめ

Slide 19

Slide 19 text

事前準備︓システム間のI/Fを定義 M5StickC, AWS, Slack

Slide 20

Slide 20 text

重要︓IoT開発ではシステム間のI/Fを先に決める • I/Fが決まらないと各システムの開発を並⾛できない • I/Fがぶれていると後々⼤きな⼿戻りになる I/Fを先に決める

Slide 21

Slide 21 text

デバイス-クラウド間のI/F • IoT開発ではI/Fを最初に決めておく(ぶれていると後々⼤きな⼿戻りに) • 今回はAWS IoTを使う都合上、MQTTSで以下のJSONをPublishする { “uuid”: ”XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX“, “address”: ”XX:XX:XX:XX:XX:XX” }

Slide 22

Slide 22 text

クラウド-Slack間のI/F • Slackへの通知はIncoming Webhookを使⽤ • 出勤時、退勤時に以下のフォーマットでメッセージを通知する

Slide 23

Slide 23 text

STEP1: フロントエンド・バックエンドの実装 AWS Amplify, DynamoDB, AppSync, S3, Cognito

Slide 24

Slide 24 text

AWS Amplifyとは︖ • サーバーレスなWebアプリケーションを簡単に構築 • 今回使ったサービス • Congnito: ユーザ登録・認証 • AppSync・DynamoDB: GraphQLサーバ・クライアント • S3: フロントエンドアプリのホスティング

Slide 25

Slide 25 text

React + Material-UI • SPAの簡易ダッシュボードを構築 • React: フロントエンドフレームワーク • Material-UI: マテリアルデザインを採⽤したComponentセット Material-UIでデザインした簡易ダッシュボード

Slide 26

Slide 26 text

参考: Amplify + Reactのチュートリアル • このチュートリアルがとても参考になりました https://github.com/dabit3/react-notes

Slide 27

Slide 27 text

DynamoDBのテーブル構成 • ダッシュボード表⽰、出退勤通知の処理内容を想定し 以下3テーブルで構成

Slide 28

Slide 28 text

GraphQLのスキーマ定義(Beacon) • Beaconテーブルは「検出中のBeaconの⼀覧」を格納する • 検出されなくなったらTTLを使ってテーブルから⾃動削除する type Beacon @model { id: ID! address: String! detected_at: String! deleted_at: Int! } • idにはiBeaconのUUIDを使⽤ • detected_atにiBeaconを検知 した時間を格納 • deleted_atはdeletec_atの1分 後を設定(DynamoDBのTTL⽤)

Slide 29

Slide 29 text

GraphQLのスキーマ定義(AttendanceLog) • AttendanceLogテーブルは「出退勤時刻」を格納する • パーティションキーはUUID, ソートキーを出勤時刻とする type AttendanceLog @model @key(fields: ["id", "started_at"]) { id: ID! started_at: String! ended_at: String } • idにはiBeaconのUUIDを使⽤ • started_atに出勤時刻を格納 • started_atをソートキーとする • ended_atに退勤時刻を格納

Slide 30

Slide 30 text

GraphQLのスキーマ定義(IdUser) • IdUserテーブルは「UUIDとユーザ名の組み合わせ」を格納する • Web画⾯の表⽰やSlackへの通知時にUUIDをユーザ名に変換する ために使⽤する type IdUser @model { id: ID! user: String } • idにはiBeaconのUUIDを使⽤ • userにはユーザ名を格納

Slide 31

Slide 31 text

STEP2: IoTにおける送受信部の実装 AWS IoT Core, Lambda, DynamoDB

Slide 32

Slide 32 text

受信(IoT Core->DynamoDB) • デバイスからPublishされたJSONをDynamoDBの Beaconテーブルに書き込む • 同じUUIDのレコードはdeleted_atを更新して上書き

Slide 33

Slide 33 text

送信(DynamoDB->Lambda) • BeaconテーブルのDynamoDB Streamsをトリガーに Lambdaを発⽕ • イベント名に応じて処理 • INSERT: 出勤処理 • REMOVE: 退勤処理

Slide 34

Slide 34 text

送信(DynamoDB->Lambda) 出勤処理

Slide 35

Slide 35 text

送信(DynamoDB->Lambda) 退勤処理

Slide 36

Slide 36 text

補⾜: DynamoDBのTTL発動タイミング • 仕様: 期限切れから48時間以内に削除 • https://docs.aws.amazon.com/ja_jp/amazondynamodb/lat est/developerguide/howitworks-ttl.html • 48時間だと今回のシステムには遅すぎる • 実際に動作検証→結果: 15分以内には削除される • 今回のシステムには15分が丁度良い • 今後、TTL発動タイミングを調整したくなった場合 • Dynamo DBのTTLをOFF • Cloud Watch EventをトリガとしLambdaを定周期実⾏ • LambdaにてTTLを過ぎたItemを削除する

Slide 37

Slide 37 text

STEP3: デバイス側の開発 M5StickC, IoT Core

Slide 38

Slide 38 text

今回使ったデバイス: M5StickC • ESP32-picoを搭載したスティック状の マイコンモジュール • 48 x 24 x 14mm • 0.96インチのカラー液晶パネル • 電源スイッチ、A・Bボタン • マイク • IRトランスミッタ • 外部8ピン端⼦ • USB-Cポート • GROVEポート • 6軸IMU • 無線LAN • Bluetooth • ⼩型ながらいろいろなことができるの でプロトタイピングに最適

Slide 39

Slide 39 text

Arduino IDEでプログラミング • Arduino⾔語(≒C++) • IDEでコンパイル→ 書き込み • setup()で諸々初期化 • loop()が定周期処理

Slide 40

Slide 40 text

iBeacon検出処理 • ESP32のBLEライブラリを使って、スキャン • 検出時のコールバック関数で検証 ここに検出時の処理を書く

Slide 41

Slide 41 text

iBeaconのアドバタイズパケットを判別 • 受信したデータを以下の通りチェック • 先頭2byte(Apple Company ID)が「0x4C00」であること • 次の2byte(iBeacon識別⼦)が「0x1502」であること • 受信データはBLEAdvertisedDeviceの getManufacturerData()関数により取得可能 • 値が異なるものはiBeacon以外のBLE通信なので無視

Slide 42

Slide 42 text

iBeacon情報を読み出す • それぞれ以下の⽅法で読み出す • デバイスアドレス • BLEAdvertisedDeviceのgetAddress()関数で取得 • RSSI • BLEAdvertisedDeviceのgetRSSI()関数で取得 • UUID • 受信データの4〜19byteを抜き出し、16進数表記に変換

Slide 43

Slide 43 text

MQTTS通信⽤のライブラリを準備 • ArduinoライブラリのPubSubClientをインストール

Slide 44

Slide 44 text

MQTTSでクラウドに接続する • WiFi→MQTTSの順で接続 • X.509によるTLS認証も可

Slide 45

Slide 45 text

MQTTSでJSONをpublishする • JSON⽂字列を⽣成し、指定したTOPICへpublish

Slide 46

Slide 46 text

問題: MQTTSとBLEを併⽤するとreboot • BLEとMQTTSを同時実⾏するとデバイスが再起動 • Heap領域が不⾜している模様 • やむを得ず、Mosquitto経由でIoT Coreへ Publishするよう構成を変更

Slide 47

Slide 47 text

iBeaconのパケットを送信 • ⼿持ちのAndroid端末を使⽤ • Beacon SimulatorというAndroidアプリを使⽤ https://play.google.com/store/apps/details?id =net.alea.beaconsimulator&hl=ja UUIDを⾃由に設定できる

Slide 48

Slide 48 text

(⻑い道のりでしたが) 無事完成

Slide 49

Slide 49 text

まとめ • IoTシステムは⼩さく始めて⼤きく育てる • システム間のI/Fを最初に決める

Slide 50

Slide 50 text

まとめ • 既存のサービス、プロダクトを組み合わせることで より簡単にIoTシステムを開発できる • Amplifyを使うことでサーバレスなWebアプリケーションを 簡単に構築できる • IoT Core, Lambdaと連携させることでIoTと連携できる • M5Stack, M5StickCはプロトタイピングにうってつけ

Slide 51

Slide 51 text

Thank you! Fusicは技術が好きなエンジニアを 募集しています