shadowとwillとretainを活用してAWS IoT CoreとPubSubする①（全体説明）

## この記事について

AWS IoTとLinuxベースのIoT gatewayで通信する為の環境構築手順をまとめます。
説明はAWS IoTとのpub/subのみでRule actionや他のサービスとの連携を具体的に構築する話はしません。

* 使用するライブラリー
　- paho.mqtt  
　- AWS IoT Device SDK v2 for Python 
　- mosquitto
* プロトコル
　- MQTT
* AWSで使用する機能
　- AWS IoT Coreのbroker　⇒　デバイス等のデータ転送
　- Device shadow　⇒　デバイスやプロセスの監視/操作
　- willとretain　⇒　AWS IoTと接続しているホスト機というか回線の監視等(retainはそれに限らず)

これらについて各ライブラリーごとにAWS機能の構築方法をまとめます。
伝承用資料もかねたいので長くなりますが細かく区切って説明します。

参考文献については不足分は後日追加とさせていただきます御了承ください。

本稿では各項目の概要説明をします。

## 用語

### MQTT  
[ja.wikipedia.org/wiki/MQTT](https://ja.wikipedia.org/wiki/MQTT)
Message Queuing Telemetry Transportの略でPub/Sub型のデータ配信をする軽量TCP/IPプロトコル。patloadはjson形式。jobをつなぐメッセージキューの機能は無い。

### pub/sub
publish(発行)/subscribe(購読)の略、HTTPのPOST/GETに類似するメソッド。

### broker
MQTTで通信する際に１対多、多対多でメッセージをpub/subするサーバー。

### topic  
MQTT接続されたネットワーク内のアドレスに相当する識別子で階層構造を作れる。データストレージのプレフィックス構造と同様に、ネットワーク/データ構造に合わせて階層を設計する。

## 使用するライブラリー  
AWS IoT Coreと通信するためのエッジ側brokerとして３つのライブラリーの使い方を解説します。

<img width= 700 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/3d92a5e3-5386-787b-5df8-75cbcc760e8e.png>

### paho-mqtt  
[Eclipse paho-mqtt Navigation](https://eclipse.dev/paho/files/paho.mqtt.python/html/client.html)
**特徴：** (Pythonのライブラリーで)AWS以外やlocalでmqttが可能なOSSのbroker

### aws-iot-device-sdk-python-v2
[AWS IoT Device SDKs](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/iot-sdks.html
)
[AWS IoT Device SDK v2 for Python](https://github.com/aws/aws-iot-device-sdk-python-v2)
**特徴：** AWS IoTの各サービスとの連携が手厚いAWS IoT専用(？)broker
C++/Python/JavaScript/Javaで用意されている

### mosquitto
[Eclipse Mosquitto™ An open source MQTT broker](https://mosquitto.org/)
**特徴：** 主要なLinuxディストリビューションとWindowsで動作するOSSのbroker

## プロトコル  

[デバイス通信プロトコル](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/protocols.html)

MQTTを使用します。
AWS IoTではMQTT以外にMQTT over WebSocket Secure (WSS)とHTTPSをサポートしますが本稿では扱いません。

<img width= 700 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/fe806a71-a517-ef36-4e65-eeab9e72c8b7.png>


## AWSリソース  
Thing、topic、証明書、IoT policyを作成します。

<img width= 700 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/7eda7cba-8876-de71-37c4-64a9e9c5c487.png>

### Thing  
AWS IoTに登録するエッジ側でインターネット接続するデバイス名です。
AWS上の仮想空間にエッジデバイスのtwinを置くようなイメージです。

### topic  
* message
* will
* shadow

で別々にtopicを設定する。
messagesとwillは任意に設計するがshadowは$awsで始まる予約リソースになる。

### 証明書
AWS IoT Coreのbroker endpointとエッジデバイスを接続する際の認証に３種類の証明書を使います。
* X.509クライアント証明書(クライアント認証)
* 公開鍵秘密鍵ペア(クライアント認証)
* ルートCA証明書(サーバー認証)

### IoT policy
接続するエッジデバイスの識別子としてclient idを設定し、client idに対して
* connect
* recieve
* publish
* subscribe

等のMQTTプロトコルによる操作権限を与えます。

## AWSで使用する機能  

### IoT Coreのbroker(pub/sub)  
**用途：**　接続したセンサー/カメラ等の測定値をサーバーに転送(pub)、クラウドからのリモート操作(sub)等

<img width= 700 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/2c2922ef-425d-f800-7e23-5e21412a5dae.png>

### Device shadow
**用途：**　接続したセンサー/カメラ等の状態監視、リモート操作等
shadow用のtopicでラズパイからAWS IoTにデバイス状態を送信し、AWS上で保存する仕組みです。

* desired
* reported
* delta

の3項目で構成され、desiredとreportedの値に差分がある時にdeltaが発生します。

<img width= 700 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/6a3df83a-84fe-e120-7f16-772ef8c039e5.png>

### shadowユースケース①デバイス自動復旧  

一例としてshadowを使ったエッジデバイスの自動復旧のフローを紹介します。

ラズパイIoT GW経由でAWS IoTにshadowを設定しているdevice_0を想定します。
ラズパイではdevice_0の稼働状態を常に監視するルーチンが回っているとします。

正常稼働時にtopic shadowでAWS IoTに送信される状態には差分が無くdeltaが発生していません。

<img width= 700 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/a33e29fd-9578-0d6f-5897-edbacc6aab87.png>

device_0が停止すると監視ルーチンが検知して、topic shadowでAWS IoTに送信されるreported stateに異常フラグを書き込んでpubします。

AWS IoT側ではdevice_0のshadowにdeltaが発生します。

<img width= 700 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/93c1b401-9293-34dd-0bb0-871102fe718c.png>

delta発生をトリガーにLambda関数を発火させて、device_0を再起動(または制御ルーチンを再起動等)させる直接/間接的なmessageをAWS側からエッジデバイスにpubします。

エッジデバイス側ではmessageをsubして命令に従ってプロセスを実行します。

<img width= 700 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/be2dc083-ef09-6dab-c4db-35395adcf5f0.png>

自律的に自動復旧が完了してupdateされたshadowによりdeltaが解消されます。

<img width= 700 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/8ab81b18-1b9f-c02c-d025-feec23fc2b25.png>

### shadowユースケース②管理consoleからのリモート操作  

もう一例、管理userがconsoleからdeltaを発生させてdevice_0をリモート停止するフローを考えてみます。

<img width= 700 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/a33e29fd-9578-0d6f-5897-edbacc6aab87.png>

管理userがconsoleからdevice_0のdesiredを"停止状態"に変更したメッセージをAWS IoTにpubしてdeltaを発生させます。

<img width= 700 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/eeb88d93-09c5-5ee7-5f95-085befe1c732.png>

delta発生をトリガーにLambda関数を発火させて、device_0を停止(または制御ルーチンを停止等)させる直接/間接的なmessageをAWS側からエッジデバイスにpubします。

エッジデバイス側ではmessageをsubして命令に従ってプロセスを実行します。

<img width= 700 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/ca917691-1af6-971a-5ddf-81796e3c6518.png>

device_0が停止してupdateされたshadowによりdeltaが解消されます。

<img width= 700 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/e7a415f8-109c-2afc-a98e-d5bf00330604.png>

### retain
[保持された MQTT メッセージ](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/mqtt.html#mqtt-retain)
**用途：**　回線異常による切断前の最後のメッセージ取得、直前のメッセージの取得等

messageをpubする際にretain flagをTrueにすることで、最後に発行したメッセージがAWS IoT上に保存されます。mqttv3の場合、既存期限の上限はありません。will messageでも利用できます。

<img width= 700 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/c6afeabe-4a0e-f27b-2971-742ff9eb7342.png>

### will
[MQTT の Last Will and Testament (LWT) メッセージ](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/mqtt.html#mqtt-lwt)
**用途：**　回線異常による切断前のリアルタイム通知等

clientとの接続がtimeoutすると格納されているwill messageはwill topicに自動的にpubされます。will messageをトリガーにLambda関数を発火させる、MQTTを永続接続している管理PCでwillのsubscriberを動かしておいてsubする等の方法でリアルタイムに回線の切断を把握することができます。

<img width= 700 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/e238f186-f491-6350-8f87-f151ffb7323b.png>


## 全投稿リスト  

以下の「shadowとwillとretainを活用してAWS IoT CoreとPubSubする」シリーズ投稿で環境構築備忘録を残します。

1. 本稿
2. [shadowとwillとretainを活用してAWS IoT CoreとPubSubする②AWSリソースの構築](https://qiita.com/Saito5656/items/62e46f009000991b2adf)
3. [shadowとwillとretainを活用してAWS IoT CoreとPubSubする③pahoでpubsub](https://qiita.com/Saito5656/items/6b3d0d70fb3eeaeb5532)
3. [shadowとwillとretainを活用してAWS IoT CoreとPubSubする④pahoでshadow update](https://qiita.com/Saito5656/items/bdeb87b04a651af2b837)
3. [shadowとwillとretainを活用してAWS IoT CoreとPubSubする⑤pahoでretainとwill](https://qiita.com/Saito5656/items/ae71d9c66f850a1e8be6)
3. [shadowとwillとretainを活用してAWS IoT CoreとPubSubする⑥awsiotsdkv2でpubsub](https://qiita.com/Saito5656/items/90d950617ef6aab0785c)
3. [shadowとwillとretainを活用してAWS IoT CoreとPubSubする⑦awsiotsdkv2でshadow update](https://qiita.com/Saito5656/items/b1163c875d56c20bfa4d)
3. [shadowとwillとretainを活用してAWS IoT CoreとPubSubする⑧awsiotsdkv2でretainとwill](https://qiita.com/Saito5656/items/6e88360a28a837f8a8c2)
3. [shadowとwillとretainを活用してAWS IoT CoreとPubSubする⑨mosquittoでpubsub](https://qiita.com/Saito5656/items/1398200115bb9c47116a)
3. [shadowとwillとretainを活用してAWS IoT CoreとPubSubする⑩mosquittoでshadow update](https://qiita.com/Saito5656/items/44bc48c4f8579d98d25a)
3. [shadowとwillとretainを活用してAWS IoT CoreとPubSubする⑪mosquittoでretainとwill](https://qiita.com/Saito5656/items/aa99f6a026c93235c776)