ESP32からAWS-IoTにつなぐ（Espressif社のSDKを利用）

# はじめに

以前にAWSのページに載っていたチュートリアルに沿ってESP32からAWS-IoTに接続してみましたが、この仕組みをその後どう使いこなせば良いのか自分の知識ではわからず、途方に暮れてしまいました。
[ESP32にAmazon FreeRTOSを入れてAWS-IoTにつなぐ（CentOS利用）](https://qiita.com/hisashij/items/e39d9f39b21eda780674)

そこで、別の方法でAWS-IoTにつないでみることにしました。参考にしたのは、ESP32の公式SDKであるESP-IDFのPrograming Guideにある、こちらのページ。
[ESP-IDF Programming Guide - Cloud Frameworks](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/libraries-and-frameworks/cloud-frameworks.html)
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679422/dfbf9fb4-02a8-f252-e7a5-2d35fb2b37cc.png)

【今回の環境】

- 開発環境：Windows 10
- ボード：[ESP32-DevKitC-32D](http://akizukidenshi.com/catalog/goods/search.aspx?search=x&keyword=M-13628)
- ESP-IDF v4.0.1
- Toolchain v8.2.0
- [ESP-AWS-IoT SDK](https://github.com/espressif/esp-aws-iot)
 
# ESP-IDFの導入
まず開発環境のPCにESP-IDFを入れます。こちらのページを参考にして、サンプルの実行まで進めました。
[ESP32 を買って、 Windows 10 に開発環境（ESP-IDF）を構築し、ビルドして、書き込んで、Lチカを確認するまでの記録。](https://qiita.com/yamazaki3104/items/672f47086d0332536ba7)

フォルダ構成はこうしてみました。

```
C:\IoT\
 └ ESP-IDF\
 　  ├ ESP-IDF-v4.0.1\
 　  ├ Tools\
 　  └ Projects\
```

# ESP-AWS-IoTのダウンロード

上記、ESP-IDF Programming GuideのAWS IoTのリンクを叩くと、こちらのページに案内してくれます。
[GitHub - esp-aws-iot](https://github.com/espressif/esp-aws-iot)

適当な場所に移動してから、そこに書かれている通りに実行して必要なものをダウンロード。

```
cd C:\IoT\ESP-IDF\Projects
git clone --recursive https://github.com/espressif/esp-aws-iot
```

すると、以下の場所に二つのサンプルがありました。サンプルの使い方は、`esp-aws-iot\examples\README.md`に書かれています。

```
C:\IoT\
 └ ESP-IDF\
 　  └ Projects\
 　  　  └ esp-aws-iot\
 　  　  　  └ examples\
 　  　  　  　  ├ subscribe_publish\
 　  　  　  　  └ thing_shadow\
```

`subscribe_publish`はAWS-IoTへMQTTでメッセージを飛ばすだけの簡単なもの。メインのソースコードもシンプルなので自分で色々カスタマイズできそう。今回はこちらを使ってみます。

# AWS-IoTで「モノ」を登録する
`README.md`を見ると、まず以下を参考にAWS IoTのコンソールでデバイスの設定をしなさいとあります。
[AWS IoT Core の開始方法](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/iot-gs.html)

AWS IoTコンソールでは、以下を行います。

- モノの作成（鍵対と証明書の生成）
- ポリシーの作成
- 証明書へポリシーをアタッチ
- カスタムエンドポイントの確認

## モノの作成

AWS IoTのコンソールで、「管理」-「モノ」を開いて、
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679422/7f27aa9c-9dfb-d71c-0fef-c70999945558.png)

「モノの登録」へ進みます。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679422/47b8c968-477d-b5c3-585e-f74c7e44db34.png)

「単一のモノを作成する」へ。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679422/fd8ba410-26a6-50c9-b0f7-9074dd85a6ce.png)

モノに適当に名前を付けて次へ。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679422/b8a5d790-52de-45a8-70d9-cb5778c19018.png)

最も簡単な「1-Click 証明書作成」を選択。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679422/5bfc84ba-3608-9a0d-8fec-8805b546e5ba.png)

モノに埋め込むための鍵対と証明書が生成されました。AWS-IoTへ接続した際にモノを識別するために使われます。生成された３つのデータをダウンロードし、「有効化」をクリック。続いて「ポリシーをアタッチ」へ。

ところが、最初は勝手にポリシーができていたような気がするのですが、自分で一度消してしまったので改めて作ります。

## ポリシーの作成

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679422/ca02fa7b-1750-3e44-0aed-32250c9ab1c4.png)

「安全性」-「ポリシー」の画面から、「ポリシーの作成」へ進みます。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679422/289f58f8-db3a-60aa-cdba-9b0e3d219957.png)

このサンプルプログラムでは以下を行っているようでしたので、

- `aws_iot_mqtt_connect()`
- `aws_iot_mqtt_subscribe()`
- `aws_iot_mqtt_publish()`

ポリシーには以下を設定しておきます。

| 項目 | 値 | 項目 | 値 | 項目 | 値 |
|:--|:--|:--|:--|:--|:--|
|アクション|iot:Connect|リソースARN|*|効果|許可|
|アクション|iot:Subscribe|リソースARN|*|効果|許可|
|アクション|iot:Publish|リソースARN|*|効果|許可|

このポリシーの設定と証明書へのアタッチを適切に行っておかないと、後で実行してAWS IoTへ接続した際にERROR -12 (NETWORK_SSL_READ_ERROR) が発生します（後述のシリアルポートに表示されます）。自分は何度かはまりました。エラーコードの意味は以下に載ってます。
[aws_iot_error.h File Reference](http://aws-iot-device-sdk-embedded-c-docs.s3-website-us-east-1.amazonaws.com/aws__iot__error_8h.html)

## ポリシーを証明書にアタッチ

先ほど作成した証明書に、いま作ったポリシーをアタッチします。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679422/c654f645-3e4a-eaf9-bb8f-67b827f9a670.png)

「安全性」-「証明書」の画面で、証明書を選択し、「アクション」の中から「ポリシーをアタッチ」を選択。

## カスタムエンドポイントの確認

最後に、「設定」のページを開いて、カスタムエンドポイント（モノの通信先）をメモっておきます。後で使います。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679422/e0f066a5-f804-1e38-ba1b-cf637c0cd3e1.png)

これでAWS IoT側の設定はいったん終了。

# サンプルのビルド＆書込み

## モノの秘密鍵と証明書を設置

ESP-IDFのコンソールを開き、まず今回使う`subscribe_publish`を適当な場所へコピー。

```
cd C:\IoT\ESP-IDF\Projects\esp-aws-iot
xcopy /i /e examples\subscribe_publish projects\subscribe_publish
```

先ほどAWS-IoTコンソールからダウンロードしたもののうち、秘密鍵と証明書を以下の名前で保存しておきます。

```
projects\subscribe_publish\main\certs\private.pem.key
projects\subscribe_publish\main\certs\certificate.pem.crt
```

## ビルド前の初期設定

コピーした`subscribe_publish`の場所へ移動して、初期設定を行います。

```
cd C:\IoT\ESP-IDF\Projects\esp-aws-iot\projects\subscribe_publish
idf.py menuconfig
```

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679422/84c256a2-486c-7a17-2157-6172b9365db6.png)

設定が必要な項目は以下の通り。保存して終了します。

| 場所 | 設定値 |
|:--|:--|
| Example Configuration -> WiFi SSID | 利用するWiFiの情報を設定 |
| Example Configuration -> WiFi Password | 利用するWiFiの情報を設定 |
| Example Configuration -> AWS IoT Client ID | モノを識別する何らかの値を入れれば良い |
| Amazon Web Services IoT Platform -> AWS IoT Endpoint Hostname | AWS IoTのカスタムエンドポイント |

## ビルド＆書込み

ビルドして書込みます。自分の環境ではCOM3でした。

```
idf.py build
idf.py -p COM3 flash
```

# 動作確認

## シリアルポートで確認

TeraTermでシリアルポートに接続し、通信速度を115,200に、データを8bitから7bitに変更。
うまくいくと、WiFi接続した後にこんなメッセージが出てきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679422/dc77e8d5-2753-2251-16cc-4a03ef38eb39.png)

## AWS IoTコンソールで確認

AWS IoTコンソールの「テスト」を開きます。
このサンプルは`test_topic/esp32`というトピックでメッセージを飛ばしているので、「トピックのサブスクリプション」欄に`test_topic/#`と入れて「サブスクライブ」すると、以下のようにメッセージを確認できます。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679422/a497e9bf-c287-04aa-2f56-a8f9a1061a1d.png)

ひとまずAWS IoTにメッセージを飛ばせたので、色々遊んでみようと思います。