前回(AWS IoT Core 入門1 ~AWS Lambdaとの連携〜)は AWS IoT Core の入門として AWS Lambda と連携し、IoT Core による publish/subscribe 形式のテキストメッセージ通信を行いました。
今回はこの仕組みを応用し、IoT Core のメッセージ通信を利用した、「監視カメラを想定した画像投稿サービス」を構築してみます。
利用シーン
表題の画像投稿システムを利用シーンを考えます。 例えば、複数台の監視カメラを山中に置き、物体検出したらクラウド側に検出日時や検出デバイス名、画像を送信します。
確認を行うデバイスでは逐次クラウド側にアクセスし、検出した結果の一覧を閲覧することができるようにします。
IoT Coreで構築することの利点として、デバイス紛失時のセキュリティがあります。 監視カメラ側で持っている情報としては
AWS側で有効化/無効化することができる、クラウド側アクセス用の証明書
しかないので、不正があればクラウド側で無効化が可能です。 また、画像アップロードのためのURLも短い有効期間を設定したものを使うことで不正な情報が送られることがありません。
システム概要
処理として「物体検出および画像アップロード」「検出状況表示」の2つに分かれます。
物体検出及び画像アップロード
デバイス側で物体を検出し、画像の送信が必要になったとき、
/message/device/detection メッセージを送信します。
そのメッセージをAWS Lambdaが受け取り、
- 一定時間有効な画像アップロードURLをS3から取得
- 表示用レコード情報をDynamoDBに登録
します。
AWS Lambdaが /message/<name>/response メッセージとして検出したデバイスのみ受け取れるようにメッセージを送り、 デバイス側がメッセージを受け取ると検出した画像をアップロードします。
検出状況表示
検出状況表示はAWS Lambdaの一般的な使い方そのままです。
表示用デバイスからのHTTP GETアクセスに応じ、画像を保存しているS3および、検出状況を保存しているDynamoDBからデータを取得してHTMLを構築し、表示用デバイスに返します。
実装概要
本記事では実装の細かいところに踏み込まず、それぞれの要点を説明します。
IoT Core
3種類の Topic を送受信できるように設定します。
- /message/device/detection
物体検出したときにデバイス側から送信。AWS Lambdaが受信。
検出したデバイス名が情報として含められている。 - /message/<name>/response
detectionを受けてAWS Lambda側から送信。
<name> にはデバイス名が入り、detectionを送信したデバイスが受信したときに処理を行えるようにする。
画像をアップロードするためのURLが情報として含められている。 - /message/device/uploaded
デバイスが画像をアップロードした後に送信する。
※ 検出状態を『アップロード済み』として一覧表示に含めるための措置。
前回記事と同様にポリシーの設定を行い、上記Topicの有効化を行います。
/message/<name>/response についてはアスタリスクを使うことで表現可能です。
また、接続するデバイスとしては「deviceXXX」のように頭にdeviceが付くもののみを許可しました。
DynamoDB
以下のレコードを登録可能なDynamoDBを準備しておきます。
項目 | 概要 | |
---|---|---|
id | Partition key | レコード毎に作成される一意のID |
device_name | デバイス名 | |
uploaded | Sort key | 検出日時 |
image_url | 画像URL | |
upload_flag | 0: 検出時、1: 画像アップロード済み |
S3
投稿した画像を保存するためのS3 bucketを用意しておきます。
この時、HTMLに画像を表示するためのURLの公開設定を付与しておきます。
( 「S3 画像 公開」とかで検索すると方法が出てきます。説明省略。)
本当は IP アドレスフィルタリングをかけたほうが良いと思いますが、今回はお試しなので省略します。
AWS Lambda 概要
全部で3つ AWS Lambda を作成します。
それぞれ作成したらIoT Coreのtopicへの紐づけや、API Gatewayへの接続を行います。
detection topicへの対応
detection topicを受信したら反応して処理を行うAWS Lambdaを作ります。
- ランダムなID (= UUID) を1つ生成。
- DynamoDBとやり取りし、レコードを1つ追加。
- IDに対するS3のアップロードURLを生成。
- 応答用topicを作って送信。
することで、デバイス側が検出した後の処理を行います。
uploaded topicへの対応
uploaded topicを受信したら、DynamoDBの対象のレコードを検索し、upload_flagを更新します。
HTML表示
DynamoDBのレコードを検索し、画像アップロード済みのレコードを取り出してHTMLを構築して返します。
デバイス側 概要
クラウド側のそれぞれが準備でききたら、後はデバイス側を作ります。
Python スクリプトで作成しますが、今回は「IoT Coreを用いての通信」が本筋であるため、物体検出のことは忘れ、
- スクリプトが起動したら一定周期でdetection topicを送信。
- アップロードURL付きtopicを受信したら、デバイス内の画像を読み込んでアップロード。
- アップロード後にuploaded topicを送信。
という処理を作り、これを使うことにします。
結果
全て正常に動作すると、デバイスとクラウドのやり取りが行われます。
データが溜まってきたところでAPI Gateway経由でHTMLを返すAWS Lambdaにアクセスすると、画像付きの一覧表示を見ることができます。
まとめ
IoT Coreを用いた通信を使い、画像投稿サービスを作ってみました。
今回は「デバイス紛失しても (クラウド側で無効化できるので) 大きな問題にならないサービス」というかなり限定的な仕組みになってしまいましたが、topicの定義をしっかり策定して使っていくことで、便利な仕組みを構築することができそうです。