AWSIoTCore検証メモ① : AWS IoT 事始め

## AWS IoT Core　事始め
この記事ではAWS IoT Coreへデバイス単体でのモノの登録～RaspberryPiでAWS IoT CoreへのMQTTメッセージ送信ができるようになるまでの内容を記載しています。

## モノの登録
AWS IoT Coreでは デバイスを[モノ]として登録します。
とりあえずAWS IoT Core上でデバイスを登録していきます。
https://us-east-2.console.aws.amazon.com/iot/home?region=us-east-2#/home

#### デバイスの追加
AWS IoT Coreにアクセスしたら
[管理]->[モノ]->[作成]->[単一のモノを作成する]と進んでいく。
設定画面で[名前]だけ入力して次へ
タイプやグループ、属性を入力しておくと、モノが増えた時の管理が楽になるけど、
今回はモノは一つしか登録しないので割愛。
![IoTRule_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678268/69629984-aaee-bc52-3077-0900ffeb8eb1.png)

#### 証明書の発行
次へを押すと今度は証明書の作成画面が表示されます。
登録したモノがAWS IoT Coreに接続する為には証明書が必要になります。
色々管理方法があるけど今回は1-Click 証明書作成でAWS側に証明書を発行してもらいます。
証明書作成をクリック
そすると3つ証明書が作成されるのですべてダウンロードしましょう。
![IoTRule_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678268/e192eba3-e151-f372-431e-c205757de9c4.png)

で、この画面でAWS IoT CoreのルートCAもダウンロードしておきましょう。
後からダウンロードすることもできるけど、リンク探すのめんどくさいのでここでダウンロードしておきましょう。
[ルートCAのダウンロード]->[Amazon Root CA 1]を選択すると別タブで証明書が表示されるので名前を付けて保存。
保存したファイルの名前を[AmazonRootCA1.pem]に変更します。
中身はこんな感じ
![IoTRule_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678268/6d931689-94e3-5163-3a79-01d690299c35.png)

ダウンロードした4つのファイルを適当にcertフォルダを作ってまとめておきましょう。

~~~
cert
├── **********-certificate.pem.crt
├── **********-private.pem.key
├── **********-public.pem.key
└── AmazonRootCA1.pem
~~~

#### ポリシーのアタッチ
全部で4つ証明書類が準備できたら今度はポリシーをアタッチ。
まあ今回は試験的な接続なのでとりあえずownerにアタッチ。
本格的に運用を考えてる場合にはちゃんとしたポリシーを作ってアタッチしましょう。

#### モノ登録終了
ここまで終わったらモノの登録をクリック。
これでAWS IoT Core上でのモノの作成は終了です。
[AWS IoT Core]->[管理]->[モノ]を見ると上記手順で作成したモノが表示されてると思います。
![IoTRule_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678268/15e3a77c-74c0-9beb-386c-41ecab4cd7f1.png)


AWS IoT CoreとRaspberryPi間でメッセージの送信するための準備ができました。
後はRaspberryPiにさっきダウンロードした証明書類４つとSDKをインストールしてプログラム組めばAWS IoT Coreにメッセージが送信できるようになります。
ここからはAWS IoT Coreに接続するデバイスを設定していきましょう。

## デバイスの設定
今回は接続デバイスとしてRaspberryPiを使ってAWS IoT Coreと接続していきます。

### RaspberryPiの初期設定
RaspberryPiのOSインストール等の初期設定に関しては以下の記事を参照。
https://raspida.com/setup-raspbian4rpi4b-2020

OSがセットアップできたら、インストールされているパッケージを最新に更新しておきます。

~~~
#アップデートの確認
sudo yum update
#アップデートの実行
sudo yum upgrade
~~~

### python用AWS IoT CoreSDKのインストール
パッケージのアップデートが終わったら、AWS IoT Coreに接続するためのパッケージをインストールします。

~~~
sudo pip install AWS IoT CorePythonSDK
~~~
### AWS IoT Coreの証明書をRaspberryPiに書き込む
モノの登録の手順で取得した証明書ファイル４つをRaspberryPi上に保存します。
RaspberryPiへのデータ転送はFTP等使って送信できます。
Git等を使って証明書をクローニングする方法もありますが、GitHub等で公開してしまうと証明書を利用してアカウントを悪用される恐れもあるため、Gitを使う際には非公開で設定しましょう。
転送したファイルはworkフォルダ等を作ってその中に保存しておきます。
この記事では以下のフォルダ構成を基準に作業を進めて行きます。

~~~
*ユーザフォルダ*
    └──　work
        └─── cert
            ├── **********-certificate.pem.crt
            ├── **********-private.pem.key
            ├── **********-public.pem.key
            └── AmazonRootCA1.pem
~~~

### AWS IoT Coreにメッセージを送信する
AWS IoT Coreに標準機能で実装されているMQTTを使ってAWS IoT CoreにRaspberryPiからメッセージを送信します。
基本的にAWS IoT Core<-->IoTDevice間の通信にはこのMQTTを使います。
MQTTについての詳細は以下の記事を参照

https://www.advanet.co.jp/2020/10/14/mqtt-introduction/

以下のコードをworkフォルダ内にmain.pyとして作成します
コードは以下のコードを参照

https://aws.amazon.com/jp/premiumsupport/knowledge-center/iot-core-publish-mqtt-messages-python/

~~~python:main.py
from awscrt import io, mqtt, auth, http
from AWS IoT Core import mqtt_connection_builder
import time as t
import json
#import configdata from AWSConfigFile.py
import AWSConfigFile as config

# Define ENDPOINT, CLIENT_ID, PATH_TO_CERT, PATH_TO_KEY, PATH_TO_ROOT, MESSAGE, TOPIC, and RANGE
ENDPOINT = config.ENDPOINT
CLIENT_ID = config.CLIENT_ID
PATH_TO_CERT = config.PATH_TO_CERT
PATH_TO_KEY = config.PATH_TO_KEY
PATH_TO_ROOT = config.PATH_TO_ROOT
MESSAGE = "Hello World"
TOPIC = config.TOPIC
RANGE = 20

# Spin up resources
event_loop_group = io.EventLoopGroup(1)
host_resolver = io.DefaultHostResolver(event_loop_group)
client_bootstrap = io.ClientBootstrap(event_loop_group, host_resolver)
mqtt_connection = mqtt_connection_builder.mtls_from_path(
            endpoint=ENDPOINT,
            cert_filepath=PATH_TO_CERT,
            pri_key_filepath=PATH_TO_KEY,
            client_bootstrap=client_bootstrap,
            ca_filepath=PATH_TO_ROOT,
            client_id=CLIENT_ID,
            clean_session=False,
            keep_alive_secs=6
            )
print("Connecting to {} with client ID '{}'...".format(
        ENDPOINT, CLIENT_ID))
# Make the connect() call
connect_future = mqtt_connection.connect()
# Future.result() waits until a result is available
connect_future.result()
print("Connected!")
# Publish message to server desired number of times.
print('Begin Publish')
for i in range (RANGE):
    data = "{} [{}]".format(MESSAGE, i+1)
    message = {"message" : data}
    mqtt_connection.publish(topic=TOPIC, payload=json.dumps(message), qos=mqtt.QoS.AT_LEAST_ONCE)
    print("Published: '" + json.dumps(message) + "' to the topic: " + TOPIC)
    t.sleep(0.1)
~~~
自分の場合は接続先情報などAWSの固有情報は使いまわしたいので別ファイルで記載してImportしています。
動作としてはmain.pyの中に接続先情報を直書きしても問題はありません。
以下のコードを使って設定ファイルを作る場合はAWSの固有情報などは自身の環境のものに置き換えてください。

~~~python:AWSConfigFile.py
#CertFile_Path
CERT_FOLDER_PATH = "./cert"
PATH_TO_CERT = "cert/certificate.pem.crt"
PATH_TO_KEY = "cert/private.pem.key"
PATH_TO_ROOT = "cert/root.pem"

#IoTCore_ConectionSetting
ENDPOINT = "AWS IoT CoreEndPoint"
CLIENT_ID = "ClientID"
THING_NAME = "Thing_Name"
TOPIC = "PublishTopic"
~~~
作業フォルダ内はこんな感じになってるはず。
※AWSの固有情報をmain.pyに直書きした場合はAWSConfigFile.pyは入れなくても大丈夫です。

~~~
*ユーザフォルダ*
    └──　work
        ├── cert
        │   ├── **********-certificate.pem.crt
        │   ├── **********-private.pem.key
        │   ├── **********-public.pem.key
        │   └── AmazonRootCA1.pem
        │
        ├── AWSConfigFile.py
        └── main.py

~~~

作成したコードを実行します。
workフォルダに移行して

~~~
cd /home/<Userfolder>/work
~~~

pythonを実行します

~~~
 python3 main.py
~~~

するとコード内で設定したTopic:Test/TestDataにメッセージが10件送信されます。

## 送信テスト
### AWS IoT Coreに送信されたメッセージを確認する。
AWS IoT Coreのテストからメッセージの受信テストを行うことが可能。
サブスクリプションのTopicにラズパイ側でメッセージを送っているTopicのパスを記載。
トピックへのサブスクライブを開始するとそれ以降に送信されたメッセージがテスト画面で表示されていればデバイス間とのMQTTセッションが確立されています。
![f4adcfcd-3951-ed92-a0c6-2f9cba4ee603.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678268/cfdaf334-661a-73ab-13cd-e7fb61c7372f.png)



これで、AWS IoT Coreへのデバイスの認証とメッセージの送信ができるようになりました。
前の記事に記載したユースケースの構成的に、今回の作業内容は赤枠で囲んだ範囲となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678268/e15d3e09-839d-13d6-1754-93672871c0ae.png)

次回は届いたメッセージの内容に応じて何らかのアクションを起こす[ IoTrule ]について検証を行っていきます。
[AWS IoT Core検証メモ②：IoT rule について](https://qiita.com/tomzono/private/12f6253c864f8f8c4070)

---
[AWS IoT Core検証内容一覧へ](https://qiita.com/tomzono/private/eaa786b6a1889351c752)