[レポート] AWS IoT の賢い利用の仕方とプログラミングの勘所 #AWSSummit
こんにちは、せーのです。
今日は2018/05/30より3日間に渡って東京、品川で開催されている「AWS Summit Tokyo 2018」からセッションリポートをいたします。
このレポートはTech上級 「AWS IoT の賢い利用の仕方とプログラミングの勘所」です。スピーカーはアマゾン ウェブ サービス ジャパン株式会社 技術統括本部 ソリューションアーキテクトの小梁川 貴史氏です。
レポート
- 「こういう機能があります」という話をプログラムで表現するとどうなるか
- 作らなくていいものを作っていないか
- 開発を早くするためにご紹介します
本セッションの目的
- 本セッションの対象者
- IoTアプリの設計/開発者
- AWS IoT Coreの機能を理解されている方
MQTTプログラミング
MQTTの通信方式
- Brokerはpublisherからのメッセージを受け取り、topicへ向けて通信を送ることで当該topicを受信しているSubscriberはメッセージを受信できる
- 通信の成功 = Brokerに対するメッセージの送信の成功(Subscribeは見ていない)
- Subscribeは常時接続 = ニアリアルタイムの通信が行われる
SDK実装でpub/subをどう表現するか
- クライアント生成
- 引数でClientIDを指定
- endpoint単位で重複を許さない
- 重複した場合、最後に接続したClientIDが優先される
- Credentialの設定
- コネクションの詳細設定(オフライン時の動きとか)
- コネクションを貼る。このときkeepalive packet送信間隔(sec) を引数に持つ、default 600(s)
- Subscribe処理
- コールバック関数にどのtopicから来たのかを振り分け条件として持てば、各Subscribeごとにメソッドを作る必要はない
- Publish処理
- payloadはjson型にして、それをstringに変換して送信
AWS IoT Coreで利用できるQoS
- IoT Coreで利用可能なQoSは”0”と”1”、QoS=2は利用できない
sampleアプリ
- 各言語のIoT Device SDK内にsampleアプリが入っているので、初期導入や動作確認で参考になる
必ずしもMQTTを選択する必要はない
- 一回によるメッセージサイズ、プロトコルによってKinesis, S3などと使い分ける
- 通信プロトコルの選択の目安
- 機能差分観点
- ニアリアルタイムの双方向通信: MQTT
- データ送信しかない: MQTT or HTTP
- コスト観点
- 通信は固定線で利用可能: MQTT or HTTP
- 通信はSIMを前提に考えている
- メッセージ送信頻度が高い: MQTT
- メッセージ頻度は低い: MQTT or HTTP
- HTTPのhandshake, headerが通信コストに影響がある場合がある
- MQTTをport443で利用できるようになりました
- 8883portが空いてない企業などでも利用可能になった
- AWS IoTにおけるMQTT常時接続 $0.063/year per device
- HTTPリクエストはAWS IoTでは1msg, API Gatewayでは1requestのコストとなる
- HTTPでリアルタイム性を求めるほどコストとなる
IoT Core機能の活用
Shadowアンチパターン
- MQTTの通信におけるshadow操作の基本
- Shadowの/getにpublishするとget/acceptedへのSubscriberに投げ返される
- shadowの間違った使い方
- update thing shadowをpublish(polling timeを15へ変更)
- オペレータがshadowをアップデートすると/get/acceptedに情報が流れる
- デバイスの初期登録時に/get/acceptedがほしいから/getに対してpublishをかける
- どこか1台がルックアップすると全台にSubscribeがかかるのでコスト増、スケーラビリティが難しくなる
- 大量のthingが1つのshadow/topicを参照するような設計は非推奨。
- shadowにおいては、ここのhitngのshadowで管理
- この場合get/acceptedより$aws/things/thing_name/shadow/update/acceptedを利用するほうがコントロールしやすい
ルールエンジンの組み込み関数/topicの有効利用方法
- thing名の取得方法
- payloadのjsonの中にthing名を入れる
- MQTT接続の際に使ったclientIDをルールエンジンで取得する
SELECT * as payload, clientid() as thing/name FROM ‘data/#’
- MQTT topicを利用する
- payloadを軽くし、MQTT topicと組み合わせて使いたい
- topicデザインとしてdata/place/thing_nameのようにする
SELECT * as payload, topic(2) as place, topic(3) as thing_name FROM ‘data/#’
- Shadowの状態に合わせてルールを実行したい
- thingが特定の状態のときにのみルールの実行をしたい
SELECT * FROM ‘data/#’ WHERE get_thing_shadow(“thing_name”,,,)
- thingが特定の状態のときにのみルールの実行をしたい
- 後続処理に合わせたルールエンジンの組み込み関数の利用
- newuuid()を使って均等にKinesis Streamに分散する
- その他
- timestamp(): タイムスタンプ
- parse_time(): フォーマット
- lower() upper(): 大文字小文字化
2017年summitで発表したデザインパターンのupdate
インテリジェントシャドウパターン
- アプリからアップデートを要求する
- まずDynamoDBに入れてからLambdaを通じてIoTに流す
- IoT Device MangaementのGroup機能
- Thingの管理単位としてGroup論理表現できる
- Group単位でのPolicy設定が可能
- Index機能
- queryをかけてThingを検索する
- Jobs機能
- 大量のデバイスをアップデートかけるときグループを指定してアップデートをかけたりステータスを確認したりできる
テンポラリトークン取得パターン
- AWS IoTの証明書を利用したtoken取得
- Role Aliasを作成してHTTPS get requestするだけでtokenが取れるようになった
まとめ
いかがでしたでしょうか。こちらは現場ですぐ使えそうなトラブルやアンチパターンでしたね。まずは一度自分でサンプルを作って確認してみたいと思います。