11
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

SORACOM LTE-M Button と AWS IoT Core の ThingShadow で「呼び出しシステム」

Last updated at Posted at 2018-11-03

展示会で困る事

それは展示会場で担当者が不在だった時ですよね。呼び出したいけどどうすれば?という問題を「あのボタン」で解決しようとした試みです。

こんな感じ

JAWS FESTA 2018 OSAKA でお披露目しました。
こんな感じのSPA (Single Page Application) です。

あのボタン「SORACOM LTE-M Button」を押すと、担当者に Slack のメンションが飛びます。
また、担当者が「OK ...」と Slack 上でメッセージ送信すると「現場急行中!」となる仕組みです。

web.png

名前のとなりに状況が表示されてますね。

実装

考え方ですが、担当者を "モノ" として扱い、そのステータス (= Shadow) を MQTT over Websocket でブラウザに表示するという仕組みです。

jaws-festa-2018 / architecture

各担当者は、このように「モノ」扱いです。もちろんソラコムはそういう会社じゃないですよ!便宜上、やむを得ず、しかたなく、断腸の思いでこのような実装になってるだけです!

aws-iot-core-things.png

Shadow はこの通りです。

shadow.png

アーキテクチャ

大きく2系統あります。

1系統目: SORACOM LTE-M Button から Slack へ POST

SORACOM LTE-M Button (= AWS IoT 1-Click) から起動される関数(python3.6)

Slack の Incoming Webhook を利用しています。
メンションを飛ばす方法は SlackのIncoming Webhooksでメンションを飛ばす方法 に助けていただきました。

同時に Shadow を「呼び出し中... (state=calling)」に update します。これは Websocket を通じてブラウザにリアルタイムでpushされます。

2系統目: Slack から AWS IoT Core の Shadow を更新

Slack から API Gateway を経由して AWS IoT Core の ThingShadow を更新する関数

Slack の Outgoing Webhook を利用しています。
トリガーキーワードに "ok" を指定し、担当者は ok ... と入れてもらうようにしました。
受けは API Gateway です。Slack からは Content-Type:application/x-www-form-urlencoded で送信されるので、本来は API Gateway 上で JSON 化したかったのですが、私には難しかったので Lambda proxy としてそのまま Lambda 関数に引き渡し、その関数内(Python3.6)上で urllib.parse.parse_qs(event['body']) としてパースする軟弱実装です。

image.png

その後 Shadow を「現場急行中! (state=running)」に update します。先ほど同様、ブラウザにリアルタイム push されます。

共通してやってること

一定時間経過したら stateidle に更新する関数(python3.6)

Shadow が「現場急行中!」や「呼び出し中...」のままだと格好悪いので、一定期間で「呼び出しOK! (state=idle)」に戻してあげたかったので、Lambda 関数を作っています。

各 Lambda 関数から呼び出される形のコードです。呼び出し方は後述の TIPS で紹介します。
実装は time.sleep(sec) を使いました。
→ [11/7] Amazon SQS を使ったプロセス間通信という方法を教えていただきました。今度はそれでやってみよう。

Lambda 関数から Lambda 関数を呼ぶ

Amazon SQS を使った Lambda 関数間の通信の方が良さそうですが、こういう方法もあるよという話です。

import boto3

f = boto3.client("lambda")
f.invoke(FunctionName=...,
  InvocationType='Event',
  Payload=json.dumps({'key1': 'value1'})
)

InvocationType については AWS LambdaからLambda呼んでハマった話。 / Qiita が参考になりました。
結論 'Event' が非同期呼び出し 'RequestResponse' が同期呼び出しです。

MQTT over Websocket による ThingShadow のリアルタイム表示

AWS IoT Core の ThingShadow を MQTT Subscribe して Push ベースで状態を表示する HTML

web.png

この画面は Vue.jsUIKit です。

AWS IoT Core の ThingShadow へのアクセスは AWS Cognito の "認証されていない ID に対してアクセスを有効にする" (Unauth) を利用しています。

  • AWS Cognito のリージョンは AWS IoT Core のリージョンと合わせておきましょう。
  • Unauth のロールへ "AWSIoTDataAccess" ポリシーを割り当てましょう。

AWS IoT Device SDK から Websocket で接続する方法がわからなかったので、とりあえず Paho の MQTT over Websocket で $aws/things/... を Subscribe するようにしています。

AWS IoT Core に対する ping

Websocket を使った SPA アプリケーションの起動時に AWS IoT Core のトピックに対して ping を送るようにしました。
これは Shadow である {"state":{"reported":{...}}} を読み出すのに、ともかく更新が発生する ping を publish をすることで、state 全体が subscribe に振ってくるようにしたものです。

これをやらないと、SPA アプリ起動時に各モノの状態がわからないという状態になります。
が、今から思えば AWS IoT Device SDK の awsIot.thingShadow#get() を使えばよかったんですよね。

コードを公開します。

改善ポイント

  • 呼び出し不可 (do not disturb) モードを作っても良かったかな

あとがき

さっきまで作ってた。
そのうちコードは公開します。

やっと全部書いたよ。

EoT

11
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?