AWS IoT Core 即席ハンズオン (1)

# AWS IoT Coreとは
これを読みましょう
[AWS Black Belt Online Seminar 2016 AWS IoT](https://www.slideshare.net/AmazonWebServicesJapan/aws-black-belt-online-seminar-2016-aws-iot)
[20180327 AWS Black Belt Online Seminar AWS IoT におけるデバイス管理](https://www.slideshare.net/AmazonWebServicesJapan/20180327-aws-black-belt-online-seminar-aws-iot)
[最新IoTデザインパターン AWS IoT とAWS Greengrassを用いた構築パターン](https://d1.awsstatic.com/events/jp/2017/summit/slide/D3T5-8.pdf)
*ちょっと前はAWS IoT CoreはAWS IoTというサービス名だったため、AWS IoT CoreをことをAWS IoTと書いている箇所があります*

## このハンズオンで学べること
- AWS IoT Coreの基本動作
 - Publishされたメッセージをマネジメントコンソールから確認する
 - PublishされたメッセージをDynamoDBへ保存する
- AWS IoT を初めて触る方にありがちな以下のような部分をスクリプト化してるので、すぐにAWS IoTでメッセージが送れます
    - クライアント証明書の部分が分からず結局触れなかった
    - 証明書にアタッチするポリシーの意味が分からずそっと画面を閉じた 

## AWS IoT Core 即席ハンズオン
[AWS IoT Core 即席ハンズオン (2)](https://qiita.com/asahi0301/items/140dcb7825d7c8eaaefc)

## このハンズオンで発生する料金について
- Cloud9(t2.micro)とDynamoDB(WCU/RCUともに1)を作成します。無料枠が残っている場合は0円ですが、残っていない場合でも数十円しないと思います。




## ソースコード
こちらに保存しています
https://github.com/asahi0301/aws-iot-demo

## 事前確認・準備
このハンズオンではAWS Cloud9上で実行する前提で記載しています。
Cloud9を作っていない場合は事前に作ってください。
Cloud9を作成したIAMユーザの権限が、Cloud9にそのまま割り当てられるので、IAMユーザの権限が「AdministratorAccess」になっていることを確認して、Cloud9を作ってください。(本番運用では、IAMの管理を厳密にすべきですが、ここではデモであることと作業効率を優先して、管理者権限を割り当てています)
リージョンは、Cloud9が使えるリージョンであればどこでもいいですが、私はバージニアリージョンで作りました。
*docker、git、aws cliやcredentialsなどの設定を正しく行えばローカルでも動くと思いますが、試してはいません。

## jqコマンドインストール && ソースコードのダウンロード
```
sudo yum install -y jq
git clone https://github.com/asahi0301/aws-iot-demo.git

Cloning into 'aws-iot-demo'...
remote: Enumerating objects: 23, done.
remote: Counting objects: 100% (23/23), done.
remote: Compressing objects: 100% (12/12), done.
remote: Total 23 (delta 4), reused 19 (delta 3), pack-reused 0
Unpacking objects: 100% (23/23), done.
```

##  初期セットアップスクリプトの実行
```
cd aws-iot-demo
sh 01_setup.sh

(たくさん表示されます)
```
東京リージョンのAWS IoTのマネジメントコンソールで、
証明書が登録されていることを確認
![image.png](https://qiita-image-store.s3.amazonaws.com/0/107953/c2ce9c43-5103-1403-2a37-f43565dd9af7.png)
ポリシーが登録されていることを確認
![image.png](https://qiita-image-store.s3.amazonaws.com/0/107953/4a4eff13-f58d-dce6-a391-54ad1577768f.png)
*01_setup.shを実行するたびに証明書が発行されてますが問題ありません。証明書に対して料金は発生しません*
証明書・ポリシーがない場合は、東京リージョンであることを確認してください。それでも作成されていない場合はCloud9にアタッチさせているIAMロール・ポリシーを確認して、管理者権限があることを確認してください

## publish実行スクリプトの実行
```
sh 02_demo.sh

2018-11-25 13:06:45,736 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Initializing MQTT layer...
2018-11-25 13:06:45,737 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Registering internal event callbacks to MQTT layer...
2018-11-25 13:06:45,738 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - MqttCore initialized
2018-11-25 13:06:45,738 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Client id: demo-device
2018-11-25 13:06:45,739 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Protocol version: MQTTv3.1.1
2018-11-25 13:06:45,739 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Authentication type: TLSv1.2 certificate based Mutual Auth.
2018-11-25 13:06:45,739 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring endpoint...
2018-11-25 13:06:45,740 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring certificates...
2018-11-25 13:06:45,740 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring reconnect back off timing...
2018-11-25 13:06:45,741 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Base quiet time: 1.000000 sec
2018-11-25 13:06:45,741 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Max quiet time: 32.000000 sec
2018-11-25 13:06:45,742 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Stable connection time: 20.000000 sec
2018-11-25 13:06:45,742 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring offline requests queueing: max queue size: -1
2018-11-25 13:06:45,743 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring offline requests queue draining interval: 0.500000 sec
2018-11-25 13:06:45,744 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring connect/disconnect time out: 10.000000 sec
2018-11-25 13:06:45,744 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring MQTT operation time out: 5.000000 sec
2018-11-25 13:06:45,744 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Performing sync connect...
2018-11-25 13:06:45,745 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Performing async connect...
2018-11-25 13:06:45,745 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Keep-alive: 600.000000 sec
2018-11-25 13:06:45,746 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Event consuming thread started
2018-11-25 13:06:45,747 - AWSIoTPythonSDK.core.protocol.mqtt_core - DEBUG - Passing in general notification callbacks to internal client...
2018-11-25 13:06:45,747 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Filling in fixed event callbacks: CONNACK, DISCONNECT, MESSAGE
2018-11-25 13:06:46,291 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Starting network I/O thread...
2018-11-25 13:06:46,559 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Produced [connack] event
2018-11-25 13:06:46,560 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Dispatching [connack] event
2018-11-25 13:06:46,561 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - No need for recovery
2018-11-25 13:06:46,561 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Invoking custom event callback...
2018-11-25 13:06:48,608 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Performing sync publish...
2018-11-25 13:06:48,609 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Filling in custom puback (QoS>0) event callback...
2018-11-25 13:06:48,783 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Produced [puback] event
2018-11-25 13:06:48,787 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Dispatching [puback] event
2018-11-25 13:06:48,787 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Invoking custom event callback...
2018-11-25 13:06:48,788 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - This custom event callback is for pub/sub/unsub, removing it after invocation...
Published topic demo/test: {"timestamp": 1543151208, "number": 536, "clientid": "demo-device", "sequence": 0}

2018-11-25 13:06:49,826 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Performing sync publish...
2018-11-25 13:06:49,827 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Filling in custom puback (QoS>0) event callback...
2018-11-25 13:06:49,997 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Produced [puback] event
2018-11-25 13:06:49,998 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Dispatching [puback] event
2018-11-25 13:06:49,999 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Invoking custom event callback...
2018-11-25 13:06:49,999 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - This custom event callback is for pub/sub/unsub, removing it after invocation...
Published topic demo/test: {"timestamp": 1543151209, "number": 420, "clientid": "demo-device", "sequence": 1}
```

Docker上のMQTTクライアント(AWS IoT SDK for Python)が
AWS IoT Coreへ「demo/test」というTopicに対して
{"timestamp": 1543151209, "number": XXXX, "clientid": "demo-device", "sequence": YYYY}というJSON形式のメッセージを
毎秒publishしています

## マネジメントコンソールから確認
AWS IoTのマネジメントコンソールでは、簡易的なMQTTクライアントが用意されており、AWS IoT Coreへpublishされたメッセージを確認(subscribe)できます

![image.png](https://qiita-image-store.s3.amazonaws.com/0/107953/f6bbfdd2-e384-1723-6e7d-3579c0c98cfc.png)
こんな感じで「demo/test」へpublishされた内容がリアルタイムで見えたら成功です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/107953/33231d74-a80c-64e0-c153-b3997f597963.png)

## DynamoDBテーブルの作成
```
sh 03_create-ddb-direct-table.sh 

(いろいろ出力される)
```
作成されたことを確認
(ない場合は、東京リージョンであることとIAMを確認)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/107953/8b80dd38-11f2-9b04-8fbb-4769ea0fbcdc.png)


## AWS IoT用IAMロールの作成
これから行うハンズオンでは、AWS IoTがDynamoDBへ書き込みを行うため、IAMの設定が必要になります。
IAM設定はこのデモの目的ではないため、スクリーンショットの添付のみになります

IoTを選択。ユースケースはIoT。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/107953/a1383b01-1b9a-3ef9-936c-1d82d3fc67eb.png)
そのまま次へ。タグは何もせずに次へ。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/107953/afc1928d-ef10-9275-22a0-52c304fd710a.png)
ロール名を「IoTDemoRole」にして、作成する
![image.png](https://qiita-image-store.s3.amazonaws.com/0/107953/7cac8ec8-719c-45a0-43b2-3aa6bb98caf5.png)

## AWS IoTでActionの作成
まだActionを作っていない場合は以下のような画面になるので、「ルールの作成」を選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/107953/3fdd2bb3-3c17-4979-149a-b9fa065b8d1f.png)

名前を「DemoRule」
SQLバージョンを「2016-03-23」
ルールクエリステートメントを「SELECT * FROM 'demo/test'」
![image.png](https://qiita-image-store.s3.amazonaws.com/0/107953/6f969d76-b7c8-cf65-51c8-2bb2872c2157.png)

アクションの追加を選択して、DynamoDBv2 を選択する
![image.png](https://qiita-image-store.s3.amazonaws.com/0/107953/c9022c6b-98a4-67c9-198e-7bd3cdee81b3.png)

テーブル名に先程作成した「iot-demo-direct」
IAMロール名に先程作成した「IoTDemoRole」を選択して、アクションの追加。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/107953/644cf372-0099-e57f-a351-fc488acc2cda.png)

ルールの作成に戻るので、「ルールの作成」を選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/107953/7360c526-05f9-4d69-1f32-1a700467db4a.png)

DemoRule が作成されていることを確認
![image.png](https://qiita-image-store.s3.amazonaws.com/0/107953/724ebaba-06b3-eb60-8b62-55345a352c92.png)

## DynamoDBへデータが保存されていることを確認
![image.png](https://qiita-image-store.s3.amazonaws.com/0/107953/f8e326f8-52d7-e4f2-6e7d-5f457562aa07.png)

## お片付け
今後即席ハンズオン第二弾・第三弾を出していく予定です。
Cloud9もAWS IoTもDynamoDBも全て無料枠の範囲(枠が残っている場合は)です。画面を閉じて30分経てば、Cloud9も自動で停止するので、中で動いているDockerも停止するため、ハンズオンの続きを行う方はそのまま放置でもいいかと思います
削除されたい方は、Cloud9とDynamoDBを削除すればOKです。AWS IoTの証明書やRule、IAMロールには料金はかかりません