Help us understand the problem. What is going on with this article?

ESP32〜AWS IoTでMQTT通信して詰んだ話【ClientID】

More than 1 year has passed since last update.

IoTに関するAWS

  • AWS IoT
  • AWS IoT 1-click
  • AWS Greengrass Core
  • AWS FreeRTOS

いくつかある...
非常に関心があるのでいずれ使ってみようと思います。

AWS IoT

IoTデバイスをバックエンドやクラウドサービスと連携することができる。
通信はHTTPSやMQTT通信を用いることができる。

使用マイコン・環境

  • ESP-WROOM-32
  • Arduino IDE

MQTTプロトコルについて

1990年代後半に開発されたプロトコル!
TCP/IPベースに規定されたプロトコル!
MQTTは軽量で、しかも柔軟性がとても高いプロトコル!
M2M(Machine-to-Machine)を重要視するIoTにおいて、とてもぴったりなプロトコル!

利点
IoTではハードウェアやネットワークの面において、非常に厳しい環境で開発する場合がある。
- 待ち時間や帯域幅、デバイス面での条件が厳しい場合
- 双方向通信-Publish/Subscribe
- 1対多通信
- プロトコルヘッダサイズが小さく軽量(HTTP:50バイト,MQTT:2バイト)
- 電力消費量
- 非同期通信
- 負荷
- 通信量
- 頻繁な通信=>大量に送れる

欠点は信頼性ですかね。同期通信ではないですし...
サーバークライアント間がHTTPSやHTTPでなくMQTTだとやはり向いてないですよね。

クライアント証明

AWS IoTでは「モノ」「ポリシー」の登録。
最初に証明書を発行してもらい、RooTCA、Private_Key、Certificateをダウンロード!

Arduinoでのスケッチ

WiFiClientSecure.h - Wifi接続がよりSecureにできるようになるライブラリ
PubSubClient.h - Port:8883でMQTT通信ができるようになるライブラリ
これらを使っていきます。

AWS_IoT_ESP32.ino
#include <WiFiClientSecure.h>
#include <PubSubClient.h>

const char* ssid     = "[SSID]";
const char* password = "[Password]";

const char* server = "[end point]";
const int port = 8883;

const char* Root_CA = \
"-----BEGIN CERTIFICATE-----\n" \
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n" \
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n" \
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n" \
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n" \
"-----END CERTIFICATE-----\n";

const char* Client_cert = \
"-----BEGIN CERTIFICATE-----\n" \
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" \
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" \
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" \
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" \
"-----END CERTIFICATE-----\n";

const char* Client_private = \
"-----BEGIN RSA PRIVATE KEY-----\n" \
"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\n" \
"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\n" \
"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\n" \
"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\n" \
"-----END RSA PRIVATE KEY-----\n";

WiFiClientSecure client;
PubSubClient mqttClient(client);

void connectAWSIoT() {
    while (!mqttClient.connected()) {
        if (mqttClient.connect("ESP32")) {
            Serial.println("Connected.");
        } else {
            Serial.print("Failed. Error state=");
            Serial.print(mqttClient.state());
            // Wait 5 seconds before retrying
            delay(5000);
        }
    }
}

void setup()
{
  Serial.begin(115200);

  delay(10);

  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);
  delay(1000);

  Serial.println(Root_CA);
  Serial.println(Client_cert);
  Serial.println(Client_private);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  client.setCACert(Root_CA);
  client.setCertificate(Client_cert);
  client.setPrivateKey(Client_private);
  mqttClient.setServer(server, port);  
  mqttClient.setCallback(mqttCallback);

  connectAWSIoT();
}


long messageSentAt = 0;
int Value = 0;
char pubMessage[128];

void mqttCallback (char* topic, byte* payload, unsigned int length) {
    Serial.print("Received. topic=");
    Serial.println(topic);
    for (int i = 0; i < length; i++) {
        Serial.print((char)payload[i]);
    }
    Serial.print("\n");
}

void mqttLoop() {
    if (!mqttClient.connected()) {
        connectAWSIoT();
    }
    mqttClient.loop();
}

void loop() {
  mqttLoop();
}

こりゃダメだ

エラーコードは-1

スクリーンショット 2018-07-01 18.59.59.png

エラーの原因

MQTT_DISCONNECTED - the client is disconnected cleanly

MQTTでAWS IoTのモノまで到達できていないそう...

考えられる原因

  • 証明書が有効になってない -> アタッチ済み
  • 証明書や鍵の割り当て -> 何回か行なったが心配 ←怪しい
  • ポリシー -> 全権限許可
  • ポート -> 8883(MQTTの場合)
  • エンドポイント -> 間違いなさそう
  • AWS IoTはTLS.1.2のみ対応 -> ESP32:WifiClientSecureもTLS.1.2対応

  • PubSubClient::connectの引数 ← 怪しい

    • プログラム上では失敗してるが?

証明書をOpensslコマンドで確認

rootca2.pem - RootCA
[AWS_name]-certificate.pem - Certificate
[AWS_name]-private.pem - Private Key

Terminal
$ openssl s_client -connect [AWS_name].iot.ap-northeast-1.amazonaws.com:8443 -CAfile rootca2.pem -cert [AWS_name]-certificate.pem -key [AWS_name]-private.pem
CONNECTED(00000003)
depth=2 C = US, O = "VeriSign, Inc.", OU = VeriSign Trust Network, OU = "(c) 2006 VeriSign, Inc. - For authorized use only", CN = VeriSign Class 3 Public Primary Certification Authority - G5
verify return:1
depth=1 C = US, O = Symantec Corporation, OU = Symantec Trust Network, CN = Symantec Class 3 Secure Server CA - G4
verify return:1
depth=0 C = US, ST = Washington, L = Seattle, O = "Amazon.com, Inc.", CN = *.iot.ap-northeast-1.amazonaws.com
verify return:1

接続できてるので証明書の問題ではない。
(あるとしてもコピーミス)

不可解

ところでこの接続成功はなに

スクリーンショット 2018-07-01 19.50.37.png

ということはArduinoのプログラムがやはり怪しい...

追記-接続完了!

スクリーンショット 2018-07-02 22.12.16.png

犯人はこのコード

AWS_IoT_ESP32.ino
if (mqttClient.connect("ESP32")) {
            Serial.println("Connected.");
        } else {
            Serial.print("Failed. Error state=");
            Serial.print(mqttClient.state());
            // Wait 5 seconds before retrying
            delay(5000);
 }

mqttClient.connect("ESP32")

"ESP32"というのがDocumentとにらめっこした挙句、ClientIDということがわかりました。
ClientIDはAWSのポリシーで設定しておく必要があります。
デフォルトのTopicのままだとアクセスできない状態なので、以下のようにClientに変更して設定したClientIDにアクセスできるようになる。

今回ならこんな感じ
[ESP32] -> ClientID

Policy
{
    "Version": "2018-7-1",
    "Statement": [{
        "Effect": "Allow",
        "Action": ["iot:Connect"],
        "Resource": [
            "arn:aws:iot:[us-east-1:123456789012]:client/ESP32"
        ]
    }]

mqttClient.connect("ESP32")が失敗してただけで、AWS IoTに接続はできていた。
Arduinoのコード上でdisconnectedが表記されていたのはそのため。
つまり上記は何も不可解でもなかった。

展望

ここから AWS lambdaやCognitoと連携して、サービスをつくっていく

参考文献

MQTT
- https://kfep.jp/solution/iot-mqtt/mqtt
- https://www.ibm.com/developerworks/jp/iot/library/iot-mqtt-why-good-for-iot/index.html
AWS IoT
- https://www.1ft-seabass.jp/memo/2017/07/31/esp32-developer-aws-iot-tips/
- https://blog.maripo.org/2017/07/esp32-aws-iot-troubleshooting/
- https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/protocols.html
- http://ken5owata.hatenablog.com/entry/2017/10/22/102207
エラー
- https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/basic-policy-variables.html

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした