[M5Stack Core2 for AWS] ArduinoでMQTT接続してみました

2021.07.18

1 はじめに

IoT事業部の平内(SIN)です。

今回は、ArduinoでM5Stack Core2 for AWSからMQTT接続してみました。

最初に、使用している様子です。

M5Stack Core2 for AWSを起動するとWi-Fi接続され、続いて、AWS IoT Coreへの接続とSubscribeが行われます。

プログラムは、「LEDの点灯状態」と言う変数を保持しており、その状態を、500msごとにPublishしています。 また、blinkというメッセージを受信すると、このステータスは反転され、それに応じて、LEDを点灯・消灯しています。

MQTT接続に関しては、下記の記事を参考にさせて頂きました。
AWS IoT を駆使してペットの気持ちを理解する

2 ライブラリ

使用しているライブラリは、以下のとおりです。

  • M5Core2
  • Adafruit NeoPixel(LED操作)
  • Ethernet (Wi-Fi接続)
  • PubSubClient (MQTT接続)
  • ArduinoJson(JSON操作)

platformio.ini

[env:sample002]
platform = espressif32
board = m5stack-core2
framework = arduino

monitor_speed = 115200
upload_port = /dev/cu.SLAB_USBtoUART

lib_deps = 
    m5stack/M5Core2@^0.0.4
    knolleary/PubSubClient@^2.8
    bblanchon/ArduinoJson@^6.18.1
    paulstoffregen/Ethernet@0.0.0-alpha+sha.9f41e8231b
    adafruit/Adafruit NeoPixel@^1.8.4

なお、ライブラリのインストールや、M5Core2及び、Adafruit NeoPixelについては、下記の記事をご参照ください。

3 Wi-Fi接続

Wi-Fi接続は、WiFi.begin() にSSIDとパスワードを設定して実行するだけです。WiFi.status()WL_CONNECTEDとなれば、接続完了です。

参考:https://www.arduino.cc/en/Reference/WiFiBegin

void connect_wifi() {
    WiFi.begin(WIFI_SSID, WIFI_PASSPHREASE);
    while (WiFi.status() != WL_CONNECTED){
        delay(500);
    }
}

4 MQTT接続

MQTT接続の要領は、以下のとおりです。

<br />#define DEVICE_NAME "sample002"
#define AWS_IOT_ENDPOINT "xxxxxxxxxxxxxxxx-ats.iot.ap-northeast-1.amazonaws.com"
#define AWS_IOT_PORT 8883
#define PUBLISH_TOPIC DEVICE_NAME"/status"
#define SUBSCRIBE_TOPIC DEVICE_NAME"/blink"

WiFiClientSecure https_client;
PubSubClient mqtt_client(https_client);

bool connect_awsiot() {
    // 証明書・鍵の設定
    https_client.setCACert(root_ca);
    https_client.setCertificate(certificate);
    https_client.setPrivateKey(private_key);
    // エンドポイントの設定
    mqtt_client.setServer(AWS_IOT_ENDPOINT, AWS_IOT_PORT);
    // コールバックの設定
    mqtt_client.setCallback(callback);

    while (!mqtt_client.connected()) {
        // MQTT接続
        if (mqtt_client.connect(DEVICE_NAME)) {
            // サブスクライブ
            mqtt_client.subscribe(SUBSCRIBE_TOPIC, QOS);
            return true;
        } else {
            return false;
        }
    }
}

証明書等は、別のファイルに配置しました。

certs.cpp

const char *root_ca = R"(-----BEGIN CERTIFICATE-----
XXXXXXXXXXXXXXXX
-----END CERTIFICATE-----
)";

const char *certificate = R"(-----BEGIN CERTIFICATE-----
XXXXXXXXXXXXXXXX
-----END CERTIFICATE-----
)";

const char *private_key = R"(-----BEGIN RSA PRIVATE KEY-----
XXXXXXXXXXXXXXXX
-----END RSA PRIVATE KEY-----
)";

また、Publishは、以下です。StaticJsonDocumentでJSONドキュメントを生成していますが、MQTTに送信するメッセージは、JSON以外でも問題ありません。

StaticJsonDocument<200> json_document;
char json_string[100];
json_document["blink"] = blink;
serializeJson(json_document, json_string);
mqtt_client.publish(PUBLISH_TOPIC, json_string);

参考:https://github.com/knolleary/pubsubclient

5 コード

サンプルで作成した全てのコードは、以下の通りです。

#include <M5Core2.h>

//LED
#include <Adafruit_NeoPixel.h>
#define PIN 25 
#define NUMPIXELS 9
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); //800kHzでNeoPixelを駆動

// AWS IoT 
#include <ArduinoJson.h>
#include <WiFiClient.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>
#define WIFI_SSID "MYSSID"
#define WIFI_PASSPHREASE "xxxxxxxxxxxxxxxx"
#define DEVICE_NAME "sample002"
#define AWS_IOT_ENDPOINT "xxxxxxxxxxxxxxxx.iot.ap-northeast-1.amazonaws.com"
#define AWS_IOT_PORT 8883
#define PUBLISH_TOPIC DEVICE_NAME"/status"
#define SUBSCRIBE_TOPIC DEVICE_NAME"/blink"
#define QOS 0

// certs.cpp
extern const char *root_ca;
extern const char *certificate;
extern const char *private_key;

WiFiClientSecure https_client;
PubSubClient mqtt_client(https_client);

void callback(char*, byte* , unsigned int);

// WiFi接続
void connect_wifi() {
    M5.Lcd.print("WiFi Connecting to ");
    M5.Lcd.println(WIFI_SSID);
    WiFi.begin(WIFI_SSID, WIFI_PASSPHREASE);
    while (WiFi.status() != WL_CONNECTED) {
        M5.Lcd.print(".");
        delay(500);
    }
    M5.Lcd.println("Connected");
    M5.Lcd.printf("IPv4: %s", WiFi.localIP().toString().c_str());
    M5.Lcd.println("");
}

// AWS IoT 接続
bool connect_awsiot() {
    https_client.setCACert(root_ca);
    https_client.setCertificate(certificate);
    https_client.setPrivateKey(private_key);
    mqtt_client.setServer(AWS_IOT_ENDPOINT, AWS_IOT_PORT);
    mqtt_client.setCallback(callback);

    while (!mqtt_client.connected())  {
        M5.Lcd.println("MQTT connection...");
        if (mqtt_client.connect(DEVICE_NAME)) {
            M5.Lcd.println("Connected");

            mqtt_client.subscribe(SUBSCRIBE_TOPIC, QOS);
            M5.Lcd.println("Subscribed.");
            delay(1000); // 表示したメッセージ確認できるようにするため

            return true;
        } else {
            M5.Lcd.printf("Failed, rc=%d", mqtt_client.state());
            M5.Lcd.println("");
            return false;
        }
    }
}

void setup() {
    M5.begin();
    Serial.begin(115200);
    M5.Lcd.setTextFont(4);

    connect_wifi(); // WiFi 接続
    if (connect_awsiot()) { // AWS IoT 接続
        M5.Lcd.fillScreen(WHITE);
    }
}

// 点灯の状態
bool blink = false;

// 現在の点灯状態をpublichする
void publish() {
    StaticJsonDocument<200> json_document;
    char json_string[100];
    json_document["blink"] = blink;
    serializeJson(json_document, json_string);
    mqtt_client.publish(PUBLISH_TOPIC, json_string);
}

// メッセージを受信した際に、点灯状態を切り替える
void callback(char* topic, byte* payload, unsigned int length) {
    blink ^=1;
    // blinkの状態に応じてLEDをON/OFFする
    for(int i=0;i<9;i++) {
        pixels.setPixelColor(i, pixels.Color(0, 0, blink?255:0));
    }
    pixels.show();
}

void loop() {
    mqtt_client.loop(); // Subscribeする時は、必須
    publish(); // 現在の状態をpublishする
    delay(500);
}

6 最後に

今回は、ArduinoでAWS IoT CoreへMQTT接続してみました。

M5Stack Core2 for AWSを試し初めて、だいぶ経ってしまいましたが、やっと、MQTT接続できました。 Pub/Subができるようになったので、色々、試してみたいです。

7 参考リンク


Visual Studio Code + PlatformIO 環境で M5Stack Core2 for AWS でHello Worldしてみました
[M5Stack Core2 for AWS] Core2 for AWS IoT EduKit BSPを使用してLEDを光らせてみました
[M5Stack Core2 for AWS] Core2 for AWS IoT EduKit BSPを使用してディスプレイに表示してみました
[M5Stack Core2 for AWS] Core2 for AWS IoT EduKit BSPを使用して仮想ボタンの動作を確認してみました
[M5Stack Core2 for AWS] LVCLを使用してディスプレイ上のボタンの動作を確認してみました
[M5Stack Core2 for AWS] Core2 for AWS IoT EduKit BSPを使用して電源を操作してみました
[M5Stack Core2 for AWS] Core2 for AWS IoT EduKit BSPを使用してスピーカーを操作してみました
[M5Stack Core2 for AWS] Core2 for AWS IoT EduKit BSPを使用して静電容量式タッチパネルを操作してみました
[M5Stack Core2 for AWS] Core2 for AWS IoT EduKit BSPを使用してジャイロセンサーを操作してみました
[M5Stack Core2 for AWS] PlatformIO を使用して、ArduinoでHello Worldしてみました
[M5Stack Core2 for AWS] ArduinoでLED (Adafruit NeoPixel フルカラーLED) を点灯してみました
[M5Stack Core2 for AWS] Arduinoで仮想ボタンを作成してみました
[M5Stack Core2 for AWS] ArduinoでMQTT接続してみました
[M5Stack Core2 for AWS] Arduinoでオーディオファイルを再生してみました
[M5Stack Core2 for AWS] Arduinoでマイクの利用方法を確認してみました
[M5Stack Core2 for AWS] ArduinoでGroveポートのGPIOを使用しててみました