28
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-07-01

#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

28
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?