chakokuのブログ(rev4)

テック・コミック・DTM・・・ごくまれにチャリ

WioTerimnalからMQTTでPublishする

課題:WioTerimnalからMQTTでPublishする(最終的にはAWS IoTにPublishしたい)
取り組み:Platform-IOの環境を使って、Arduinoライブラリを頼って実装する。先人のサンプルも大量にあるようなので苦労しないと思われる。
結果:先行事例を参考にさせてもらった結果、MQTTブローカにPublishするところまではできた(ただし、認証無し、暗号化無しの一番簡単なパターン)

詳細:
ライブラリとして、PubSubClient by Nick O'Leary's libraryを使うようだ。
いろんな先行事例を参考にさせてもらって以下のコードを作った。mosquittoのブローカに対して、認証無し、暗号化無しで送付した例
(1883 : MQTT, unencrypted, unauthenticated)

#include <Arduino.h>

#define LGFX_WIO_TERMINAL
#define LGFX_AUTODETECT
#define LGFX_USE_V1

#include <LovyanGFX.hpp>
#include <LGFX_AUTODETECT.hpp> 
static LGFX lcd;

#include <rpcWiFi.h>
#include <rpcPing.h>

#define RED (uint32_t)0xFF0000
#define SERIAL_SPEED 115200

const char *SSID = "xxxxxxx";
const char *PWD = "xxxxxx";

//const char* MQTT_SERVER = "broker.mqtt-dashboard.com";  // MQTT Broker URL
const char* MQTT_SERVER = "test.mosquitto.org";                     //  1883

#include <PubSubClient.h>


WiFiClient wioClient;
PubSubClient client(wioClient);

int wifi_setup(void);

char pub_msg[50];


void setup() {
  // put your setup code here, to run once:

  //uint32_t red = 0xFF0000;
  
  lcd.init();
  lcd.setRotation(1);
  lcd.setBrightness(128);
  lcd.setColorDepth(16); 
  lcd.println("HelloWorld");
  lcd.drawLine( 0, 0, 320, 240 , RED); 
  lcd.drawString("Test(v1.1)", 10, 10);

  //Serial.println("can you see this??");

  Serial.begin(SERIAL_SPEED);
  delay(10);

  // We start by connecting to a WiFi network
  wifi_setup();

  client.setServer(MQTT_SERVER, 1883); // Connect the MQTT Server
  //client.setCallback(callback);


}

int wifi_setup(void){

   int y = 20;

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

    lcd.drawString("WiFi setup", 10, y); y += 10;
    WiFi.mode(WIFI_STA);
    lcd.drawString("WiFi disconnn", 10, y); y += 10;
    WiFi.disconnect();
    lcd.drawString("WiFi begin", 10, y);
    y += 10;
    WiFi.begin(SSID, PWD);
    lcd.drawString("WiFi started", 10, y);
    y += 10;

    while (WiFi.status() != WL_CONNECTED)
    {
        lcd.drawString("WiFi connect loop, try...", 10, y);
        y += 10;
        Serial.print("Connecting to ");
        Serial.println(SSID);
        WiFi.begin(SSID, PWD);
        delay(100);      // wait for 100msec
    }

    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
    lcd.drawString("WiFi connected", 10, y);
    y += 10;

    return 1;
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
      Serial.print("Attempting MQTT connection... ");
      // Attempt to connect
      if (client.connect("WIOTerminal")) {
        Serial.println("connected");
        // Once connected, publish an announcement...
        client.publish("wiot/1234", "5678");
        // ... and resubscribe
        //client.subscribe("vol001");
      } else {
        Serial.print("failed, rc=");
        Serial.print(client.state());
        Serial.println(" try again in 5 seconds");
        // Wait 5 seconds before retrying
        delay(5000);
      }
  }
}
void loop() {

  // put your main code here, to run repeatedly:
  static int try_count = 0;
  char str[20];
  Serial.println("loop.");
  
 if (!client.connected()) {
    Serial.println("not connected");
      reconnect();
  }else{
    Serial.println("connected");
  
  }
  lcd.drawString("enter loop", 10, 100);
  sprintf(str, "count: %d", try_count);
  lcd.drawString(str, 50, 110);
  try_count ++;

  Serial.println("publish");
  sprintf(pub_msg, "hello terminal");
  client.publish("wiot/1234", pub_msg);

  delay(5000);   // delay 5sec

}

スマフォにMQTT Clientを入れてSubscribeしてみる

■追記
最適なライブラリを使うことで、以下のコードでAWS IoT CoreにPublishできるらしい。コンパクトすぎて恐ろしい。。ESP32+MicroPythonで接続する時は結構泥沼だったけど、これはお手軽すぎる・・・

#include "rpcWiFi.h"
#include <WiFiClientSecure.h>
#include <MQTTClient.h>
#include "secrets.h"

WiFiClientSecure net;
MQTTClient mqtt;

void setup() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) yield();
  net.setCACert(AWS_CERT_CA);
  net.setCertificate(AWS_CERT_CRT);
  net.setPrivateKey(AWS_CERT_PRIVATE);
  mqtt.begin(AWS_IOT_ENDPOINT, 8883, net);
}

void loop() {
  while (!mqtt.connect(THINGNAME)) yield();
  mqtt.publish(topic, payload);
  delay(30000);
}

platformio.iniの内容は以下

[env:seeed_wio_terminal]
platform = atmelsam
board = seeed_wio_terminal
framework = arduino
lib_deps = 
	lovyan03/LovyanGFX@^1.1.2
	seeed-studio/Seeed Arduino rpcWiFi@^1.0.6
	seeed-studio/Seeed Arduino FS@^2.1.1
	seeed-studio/Seeed Arduino rpcUnified@^2.1.4
	seeed-studio/Seeed_Arduino_mbedtls@^3.0.1
	seeed-studio/Seeed Arduino SFUD@^2.0.2
	knolleary/PubSubClient@^2.8
upload_port = COM14
monitor_port = COM14

■参考記事
MQTT on Wio Terminal - Hackster.io
Wio Terminal Publishing MQTT Messages To AWS - Hackster.io
ESP8266 でIoT その3 MQTT(1) | 電子工作の環境向上
Publish and Subscribe to a ThingSpeak Channel Using Secure MQTT - MATLAB & Simulink - MathWorks