ESP32をAWS IoT Coreに接続し、MQTTで通信することができたので、備忘録としてまとめました。
目次
AWSアカウントの開設と初期設定
AWSのサービスを利用するため、AWSアカウントが必要です。
まだアカウントを開設していない場合は、開設しましょう。
以下にアカウント開設する方法と初期設定についてまとめたので、よろしければご覧ください。
AWS IoT device(モノ)を作成する
AWS IoT Coreで、AWS IoT device(モノ)を作成する手順を以下に記載します。
- AWSマネージメントコンソールにログインする。
- 「AWS IoT Core」にアクセスする。
- 左側のメニューから[管理 > モノ]をクリックし、「モノを作成」をクリックする。
- 「モノを作成」画面で「1つのモノを作成」を選択して「次へ」をクリックする。
- 「モノのプロパティを指定」画面で「モノの名前」を入力して「次へ」をクリックする。
※「モノの名前」は好きな名前にしてください。(例:MyESP32) - 「デバイス証明書を設定 - オプション」画面で「新しい証明書を自動生成(推奨)」を選択して「次へ」をクリックする。
- 「証明書にポリシーをアタッチ - オプション」画面は特に設定せず「次へ」をクリックする。
※後でポリシーを作成し、証明書にアタッチします。 - 「デバイス証明書」などをダウンロードできる画面となったら、すべてのファイルをダウンロードする。
※この証明書のファイルはこの時しかダウンロードできないので、必ずダウンロードしてください。
- ダウンロードしたら、「完了」をクリックし、「モノが正常に作成されました。」と表示されればOK。
ポリシーの作成
ポリシーはIoT Device(モノ)が実行できるアクションやアクセスできるリソースなどの許可/禁止を設定することができます。
IoT Device(モノ)向けポリシーの作成手順を以下に記載します。
- 「AWS IoT Core」にアクセスする。
- 左側のメニューから[安全性 > ポリシー]をクリックし、「ポリシーの作成」をクリックする。
- 「ポリシーの作成」画面で「名前」を入力し、「アドバンストモード」をクリックする。
※「名前」は好きな名前にしてください。(例:Esp32Policy)
- 「ポリシーの作成」画面の「ステートメントを追加」のところに以下のJSONを入力する。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iot:Connect",
"Resource": "arn:aws:iot:[リージョン名]:[アカウントID]:client/[モノの名前]"
},
{
"Effect": "Allow",
"Action": "iot:Subscribe",
"Resource": "arn:aws:iot:[リージョン名]:[アカウントID]:topicfilter/[ESP32がSubscribeするTopic名]"
},
{
"Effect": "Allow",
"Action": "iot:Receive",
"Resource": "arn:aws:iot:[リージョン名]:[アカウントID]:topic/[ESP32がSubscribeするTopic名]"
},
{
"Effect": "Allow",
"Action": "iot:Publish",
"Resource": "arn:aws:iot:[リージョン名]:[アカウントID]:topic/[ESP32がPublishするTopic名]"
}
]
}
[リージョン名]
、[アカウントID]
はご自分のAWSアカウントに合わせて記載してください。[モノの名前]
は「AWS IoT device(モノ)を作成する」で設定した名前です。(例:MyESP32)[ESP32がSubscribeするTopic名]
はIoTデバイス(ESP32)がMQTTでサブスクライブするトピック名を指定します。このトピック名はESP32のプログラムで指定できるため、任意の名称で問題ありません。(例:esp32/sub)[ESP32がPublishするTopic名]
はIoTデバイス(ESP32)がMQTTでパブリッシュするトピック名を指定します。このトピック名はESP32のプログラムで指定できるため、任意の名称で問題ありません。(例:esp32/pub)
- 「ポリシーの作成」画面の右下の「作成」ボタンをクリックする。
- 「ポリシーが正常に作成されました。」と表示されればOK。
証明書にポリシーをアタッチする
上で作成したポリシーはIoT Device向けに作成した証明書(先ほどダウンロードしたアレです。)に紐づいて管理されます。
証明書にポリシーをアタッチする手順を以下に記載します。
- 「AWS IoT Core」にアクセスする。
- 左側のメニューから[安全性 > 証明書]をクリックし、右側の「...」から「ポリシーのアタッチ」を選択する。
- 「証明書にポリシーをアタッチする」画面で、先ほど作成したポリシーを選択し、「アタッチ」ボタンをクリックする。
- 「ポリシーは正常にアタッチされました。」と表示されればOK。
開発環境の準備
Windows10 PCに以下のソフトウェアをインストールします。
- Arduino IDE
- Tera Term
Arduino IDEをインストール
Arduinoの公式ページ「https://www.arduino.cc/en/software」にアクセスして、Arduino IDEをインストールしてください。
インストール手順は以下のブログが分かりやすいです。
Tera Termをインストール
Arduinoに書き込んだプログラムの画面出力用にTeraTermを使います。
TeraTermプロジェクトの公式ページ「https://ja.osdn.net/projects/ttssh2/」にアクセスして、TeraTermをインストールしてください。
インストール手順は 以下のブログが分かりやすいです。
Arduino IDEにESP32のボードマネージャを追加する
Arduino IDEのデフォルト設定ではESP32のボードマネージャ(PCからESP32を操作するためのソフトウェア群みたいなもの)がインストールされていないです。
以下の手順でESP32のボードマネージャをArduino IDEに登録します。
- Arduino IDEを起動する。
- Arduino IDEの上部にあるメニューから[ファイル > 環境設定]で環境設定ウィンドウを開く。
- 「追加のボードマネージャのURL:」のところに「https://dl.espressif.com/dl/package_esp32_index.json」を入れる。
- Arduino IDEの上部にあるメニューから[ツール > ボード > ボードマネージャ]でボードマネージャウィンドウを開く。
- 「ESP32」と検索をして、「esp32 by Espressif Systems」をインストールする。
- Arduino IDEの上部にあるメニューから[ツール > ボード > ESP32 Dev Module]で、ボードをESP32 Dev Moduleに選択する。
- ESP32-DevKitC-32Dボードのボード情報として、以下のように設定をする。
参考:
・ESP32-DevKitC-32Dボードの基本的な使い方 ~Arduino IDE編~
Arduinoライブラリをインストールする
AWS IoT Coreと接続するために、以下のArduinoライブラリをインストールします。
- MQTT by Joel Gsewiler
- ArduinoJson by Benoit Blanchon
Arduinoライブラリのインストール手順を以下に記載します。
- Arduino IDEの上部にあるメニューから[スケッチ > ライブラリをインクルード > ライブラリを管理]をクリックする。
- 「ライブラリマネージャ」ウィンドウで「MQTT」と検索して、「MQTT by Joel Gsewiler」をインストールする。
- 同様に、「ライブラリマネージャ」ウィンドウで「ArduinoJson」と検索して、「ArduinoJson by Benoit Blanchon」をインストールする。
ESP32にプログラムを書き込む
- Arduinoで任意のPJ名(例:ESP32Button)をつけて、ArduinoのPJディレクトリにsecrets.hという名前の新しいファイルを作成する。
- メインプログラム(*.ino)に以下のプログラムを書き込む。
#include "secrets.h"
#include <WiFiClientSecure.h>
#include <MQTTClient.h>
#include <ArduinoJson.h>
#include "WiFi.h"
/***** パラメータ(ご自分の環境に合わせてください) *****/
#define AWS_IOT_PUBLISH_TOPIC "esp32/pub"
#define AWS_IOT_SUBSCRIBE_TOPIC "esp32/sub"
/***** メインプログラム *****/
void setup() {
Serial.begin(9600);
Serial.println("Hello!");
// AWS IoT COre接続機能の初期化処理を実行
setup_connection();
}
void loop() {
// AWS IoT COre接続機能のループ処理を実行
loop_connection();
}
/***** AWS IoT COre接続機能 関連プログラム *****/
WiFiClientSecure net = WiFiClientSecure();
MQTTClient client = MQTTClient(256);
unsigned int pubCount = 0;
unsigned long loopCount = 0;
// AWS IoT Core接続機能の初期化処理
void setup_connection(){
// Wi-Fiに接続する
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
// Wi-Fiに接続待ち
Serial.println("Connecting to Wi-Fi");
while (WiFi.status() != WL_CONNECTED){
delay(500);
Serial.print(".");
}
Serial.println(".");
// AWS IoT Coreに接続
net.setCACert(AWS_CERT_CA);
net.setCertificate(AWS_CERT_CRT);
net.setPrivateKey(AWS_CERT_PRIVATE);
client.begin(AWS_IOT_ENDPOINT, 8883, net);
// サブスクライブしているトピックを受信したときの割り込みハンドラを指定
client.onMessage(messageHandler);
// AWS IoT Coreに接続待ち
Serial.println("Connecting to AWS IOT");
while (!client.connect(THINGNAME)) {
Serial.print(".");
delay(100);
}
Serial.println(".");
if(!client.connected()){
Serial.println("AWS IoT Timeout!");
return;
}
// サブスクライブ開始
client.subscribe(AWS_IOT_SUBSCRIBE_TOPIC);
Serial.println("AWS IoT Connected!");
}
// AWS IoT Core接続機能のループ処理
void loop_connection(){
// 1分間隔でパブリッシュ
if(loopCount%(1*60*10)==0){
pubCount++;
Serial.println("send No."+String(pubCount));
publishMessage();
}
loopCount++;
client.loop();
delay(100);
}
// パブリッシュする
void publishMessage(){
StaticJsonDocument<200> doc;
doc["time"] = millis();
doc["sensor_a0"] = analogRead(0);
char jsonBuffer[512];
serializeJson(doc, jsonBuffer);
client.publish(AWS_IOT_PUBLISH_TOPIC, jsonBuffer);
}
// サブスクライブしているトピックを受信したときの割り込みハンドラ
void messageHandler(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
}
AWS_IOT_PUBLISH_TOPIC
はESP32がPublishするトピック名を設定してください。AWS_IOT_SUBSCRIBE_TOPIC
はESP32がSubscribeするトピック名を設定してください。- ESP32はAWS IoT Coreに接続したら、1分間隔で
AWS_IOT_PUBLISH_TOPIC
にパブリッシュし続けます。
- secret.hに以下のプログラムを書き込む。
#include <pgmspace.h>
#define SECRET
#define THINGNAME ""
const char WIFI_SSID[] = "";
const char WIFI_PASSWORD[] = "";
const char AWS_IOT_ENDPOINT[] = "xxxxx.amazonaws.com";
// Amazon Root CA 1
static const char AWS_CERT_CA[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
)EOF";
// Device Certificate
static const char AWS_CERT_CRT[] PROGMEM = R"KEY(
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
)KEY";
// Device Private Key
static const char AWS_CERT_PRIVATE[] PROGMEM = R"KEY(
-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----
)KEY";
THINGNAME
には「AWS IoT device(モノ)を作成する」で指定した「モノの名前」を設定してください。WIFI_SSID[]
とWIFI_PASSWORD[]
はご自宅のルータのアクセスポイントのSSIDとパスワードを設定してください。AWS_IOT_ENDPOINT[]
はAWS IoT Coreのデバイスデータエンドポイントを設定してください。
デバイスデータエンドポイントはAWS IoT Coreの設定ページから確認できます。AWS_CERT_CA[]
、AWS_CERT_CRT[]
、AWS_CERT_PRIVATE[]
は「AWS IoT device(モノ)を作成する」でダウンロードしたルートCA-1証明書、デバイス証明書、デバイスのプライベートキーファイルをそれぞれコピペしてください。
- ESP32を接続して、Arduino IDEの上部にあるメニューから[ツール > シリアルポート]でESP32のCOMポートを指定する。
※COMポートはデバイスマネージャで確認できます。
- Arduino IDEの右上にある「マイコンボードに書き込む」ボタンをクリックする。
- Arduino IDEの下部に「ボードへの書き込みが完了しました。」と表示されればOK。
ESP32とAWS IoT Coreの接続手順は以上で終了です。
さいごに動作検証を行いましょう。
ESP32とAWS IoT Core間のMQTT通信を検証する
以下の3通りのMQTT通信の検証を行います。
- ESP32がAWS IoT Coreに接続できたか?
- ESP32からPublishしたMQTTメッセージがAWS IoT Core側で受信できるか?
- ESP32がSubscribeしているトピックに対して、AWS IoT CoreからPublishしたら、ESP32側でメッセージを受信することができるか?
ESP32がAWS IoT Coreに接続できたか?
接続できたかどうかはESP32の画面出力を見ることで確認できます。
ESP32を起動させたとき、「AWS IoT Connected!」と表示されていれば、AWS IoT Coreに接続できてます。
Connecting to Wi-Fi
......
Connecting to AWS IOT
.
AWS IoT Connected!
ESP32からPublishしたMQTTメッセージがAWS IoT Core側で受信できるか?
AWS IoT Core側でMQTTメッセージを受信できたか確認するため、AWS IoT Coreの「MQTT テストクライアント」を開きます。
「トピックをサブスクライブする」を選択した状態で、トピックフィルターに「#」を入れて「サブスクライブ」ボタンをクリックします。
上記のような状態で、ESP32を起動させます。
ESP32は起動後に1分間隔でPublishするので、以下のように「MQTT テストクライアント」でMQTTメッセージが確認できればOKです。
ESP32がSubscribeしているトピックに対して、AWS IoT CoreからPublishしたら、ESP32側でメッセージを受信することができるか?
AWS IoT CoreからESP32がSubscribeしているトピックにメッセージをPublishするために、 AWS IoT Coreの「MQTT テストクライアント」を開きます。
「トピックに公開する」を選択した状態で、トピック名にESP32がSubscribeしているトピック名を入れて「発行」ボタンをクリックします。
ESP32側で以下のように、AWS IoT Coreから送信したメッセージが表示されればOKです。
もしうまく動作しなかった場合、、、
以下についてご確認ください。
- ソースコードで指定しているトピック名に誤りはないか?
- secret.hの設定内容に誤りはないか?
- AWS IoT Coreのポリシーに誤りはないか?
注意 MQTTテストクライアントは定期的にリセットしよう!
MQTTテストクライアントでサブスクライブすると、なぜか5分ごとにMQTTテストクライアントが追加接続されるため、アウトバンドのメッセージ数が増加していきます。
MQTTテストクライアントを使うときは、定期的にリセットしたほうがよいです。
詳細は以下のブログでまとめたので、よろしければご覧ください。
さいごに
いろいろ試行錯誤した結果、ESP32とAWS IoT Coreの接続をすることができました。
思ったより時間がかかった。
以上!
コメント