1 はじめに
M5stickCでMQTTのQOS2をやってみました
pubsubclientライブラリはQOS0と1のサポートのようなので
QOS2を指定できるASyncMqttClientライブラリを利用します
pubsubclientのLimitationsの抜粋
It can only publish QoS 0 messages. It can subscribe at QoS 0 or QoS 1.
2 準備
- PlatformmIOで開発します
導入方法や設定は別ページを参照願います - PlatformIOのライブラリからASyncMqttClientをadd to projestします
- ブローカーはmosquittoを利用します
導入方法や設定は別ページを参照願います
3 振る舞い
-
Publish
Aボタンを押すとQOSを0→1→2の順番で変更しながらメッセージを送信します -
Subscribe
受信するとシリアルにデータを表示します
4 コード
exmaples/FullyFeatured-ESP8266.inoを参考にしています
4.1 ユーザー毎の変更点
4.1.1 SSID
// Wi-FiのSSID
const char *ssid = "****";
// Wi-Fiのパスワード
const char *password = "****";
4.1.2 brokerのアドレス
#define MQTT_HOST IPAddress(**, **, **, **)
4.2 コード全体
#include <M5StickC.h>
#include <WiFi.h>
#include <AsyncMqttClient.h>
// Wi-FiのSSID
const char *ssid = "****";
// Wi-Fiのパスワード
const char *password = "****";
// デバイスID
const char *deviceID = "M5Stickc_1"; // デバイスIDは機器ごとにユニークにします
// メッセージを知らせるトピック
const char *pubTopic = "/pub/M5Stickc_1";
#define MQTT_HOST IPAddress(**, **, **, **)
#define MQTT_PORT 1883
#define BTN_A_PIN 37
#define BTN_B_PIN 39
#define BTN_ON LOW
#define BTN_OFF HIGH
AsyncMqttClient mqttClient;
void connectToMqtt() {
Serial.println("Connecting to MQTT...");
mqttClient.connect();
}
void onMqttConnect(bool sessionPresent) {
M5.Lcd.println("Connected to MQTT.");
Serial.println("Connected to MQTT.");
Serial.print("Session present: ");
Serial.println(sessionPresent);
uint16_t packetIdSub = mqttClient.subscribe(pubTopic, 2);
Serial.print("Subscribing at QoS 2, packetId: ");
Serial.println(packetIdSub);
mqttClient.publish("test/lol", 0, true, "test 1");
Serial.println("Publishing at QoS 0");
uint16_t packetIdPub1 = mqttClient.publish("test/lol", 1, true, "test 2");
Serial.print("Publishing at QoS 1, packetId: ");
Serial.println(packetIdPub1);
uint16_t packetIdPub2 = mqttClient.publish("test/lol", 2, true, "test 3");
Serial.print("Publishing at QoS 2, packetId: ");
Serial.println(packetIdPub2);
}
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
Serial.println("Disconnected from MQTT.");
if (WiFi.isConnected()) {
delay(1000);
connectToMqtt();
}
}
void onMqttSubscribe(uint16_t packetId, uint8_t qos) {
Serial.println("Subscribe acknowledged.");
Serial.print(" packetId: ");
Serial.println(packetId);
Serial.print(" qos: ");
Serial.println(qos);
}
void onMqttUnsubscribe(uint16_t packetId) {
Serial.println("Unsubscribe acknowledged.");
Serial.print(" packetId: ");
Serial.println(packetId);
}
void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
Serial.println("Publish received.");
Serial.print(" topic: ");
Serial.println(topic);
Serial.print(" qos: ");
Serial.println(properties.qos);
Serial.print(" dup: ");
Serial.println(properties.dup);
Serial.print(" retain: ");
Serial.println(properties.retain);
Serial.print(" len: ");
Serial.println(len);
Serial.print(" index: ");
Serial.println(index);
Serial.print(" total: ");
Serial.println(total);
}
void onMqttPublish(uint16_t packetId) {
Serial.println("Publish acknowledged.");
Serial.print(" packetId: ");
Serial.println(packetId);
}
void setup() {
Serial.begin(115200);
// Initialize the M5Stack object
M5.begin();
pinMode(BTN_A_PIN, INPUT_PULLUP);
pinMode(BTN_B_PIN, INPUT_PULLUP);
M5.lcd.init();
// START
M5.lcd.fillScreen(BLACK);
M5.lcd.setCursor(10, 10);
M5.lcd.setTextColor(WHITE);
M5.lcd.setTextSize(1);
M5.lcd.println("START");
// Start WiFi
Serial.println("Connecting to ");
Serial.print(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print("*");
}
mqttClient.onConnect(onMqttConnect);
mqttClient.onDisconnect(onMqttDisconnect);
mqttClient.onSubscribe(onMqttSubscribe);
mqttClient.onUnsubscribe(onMqttUnsubscribe);
mqttClient.onMessage(onMqttMessage);
mqttClient.onPublish(onMqttPublish);
mqttClient.setServer(MQTT_HOST, MQTT_PORT);
connectToMqtt();
}
int publish_cnt = 0;
int publish_qos = 0;
void loop() {
if(digitalRead(BTN_A_PIN) == BTN_ON) {
Serial.println("press A");
switch(publish_qos) {
case 0:
{
mqttClient.publish(pubTopic, 0, true, "test 1");
Serial.println("Publishing at QoS 0");
}
break;
case 1:
{
uint16_t packetIdPub1 = mqttClient.publish(pubTopic, 1, true, "test 2");
Serial.print("Publishing at QoS 1, packetId: ");
Serial.println(packetIdPub1);
}
break;
case 2:
{
uint16_t packetIdPub2 = mqttClient.publish(pubTopic, 2, true, "test 3");
Serial.print("Publishing at QoS 2, packetId: ");
Serial.println(packetIdPub2);
}
break;
default:
break;
}
publish_qos++;
publish_qos %= 3;
} else {
//Serial.println("idle");
}
delay(100);
}
~~~
# 5 結果
## 5.1 シリアル
Connecting to
KAONM-A5DF7*Connecting to MQTT...
Connected to MQTT.
Session present: 0
Subscribing at QoS 2, packetId: 1
Publishing at QoS 0
Publishing at QoS 1, packetId: 2
Publishing at QoS 2, packetId: 3
Subscribe acknowledged.
packetId: 1
qos: 2
Publish acknowledged.
packetId: 2
Publish acknowledged.
packetId: 3
press A
Publishing at QoS 0
Publish received.
topic: /pub/M5Stickc_1
qos: 0
dup: 0
retain: 0
len: 6
index: 0
total: 6
press A
Publishing at QoS 1, packetId: 4
Publish acknowledged.
packetId: 4
Publish received.
topic: /pub/M5Stickc_1
qos: 1
dup: 0
retain: 0
len: 6
index: 0
total: 6
press A
Publishing at QoS 2, packetId: 5
Publish acknowledged.
packetId: 5
Publish received.
topic: /pub/M5Stickc_1
qos: 2
dup: 0
retain: 0
len: 6
index: 0
total: 6
press A
Publishing at QoS 0
Publish received.
topic: /pub/M5Stickc_1
qos: 0
dup: 0
retain: 0
len: 6
index: 0
total: 6
press A
Publishing at QoS 1, packetId: 6
Publish acknowledged.
packetId: 6
Publish received.
topic: /pub/M5Stickc_1
qos: 1
dup: 0
retain: 0
len: 6
index: 0
total: 6
press A
Publishing at QoS 2, packetId: 7
Publish acknowledged.
packetId: 7
Publish received.
topic: /pub/M5Stickc_1
qos: 2
dup: 0
retain: 0
len: 6
index: 0
total: 6
## 5.2 パケット
QOS設定が反映されているかパケットを確認します
---
### 5.2.1 QOS0
~~~
+++ publisherからbrokerへPUBLISH +++
10450,548.113687872,192.168.0.21,192.168.0.22,MQTT,79,137,42,Publish Message [/pub/M5Stickc_1]
+++ brokerからsubscriberへPUBLISH +++
10451,548.113921727,192.168.0.22,192.168.0.21,MQTT,79,42,162,Publish Message [/pub/M5Stickc_1]
~~~
~~~plantuml
publisher -> broker:10450/PUBLISH
broker -> subscriber:10451/PUBLISH
~~~
QOS0なのでPUBLISHのみ送信されています
---
### 5.2.2 QOS1
~~~
+++ publisherからbrokerへPUBLISH +++
10596,556.107138644,192.168.0.21,192.168.0.22,MQTT,81,162,67,Publish Message (id=4) [/pub/M5Stickc_1]
+++ brokerからpublisherへPUBACK +++
10597,556.107508385,192.168.0.22,192.168.0.21,MQTT,58,67,189,Publish Ack (id=4)
+++ brokerからsubscriberへPUBLISH +++
10599,556.115019813,192.168.0.22,192.168.0.21,MQTT,81,71,189,Publish Message (id=1) [/pub/M5Stickc_1]
+++ subscriberからbrokerへPUBACK +++
10604,556.359008912,192.168.0.21,192.168.0.22,MQTT,60,189,98,Publish Ack (id=1)
~~~
~~~plantuml
publisher -> broker:10596/PUBLISH
broker -> publisher:10597/PUBACK
broker -> subscriber:10599/PUBLISH
subscriber -> broker:10604/PUBACK
~~~
QOS1のPUBACKを送信しているのでQOS1になっているようです
---
### 5.2.3 QOS2
~~~
+++ publisherからbrokerへPUBLISH +++
11353,579.125283591,192.168.0.21,192.168.0.22,MQTT,81,288,193,Publish Message (id=7) [/pub/M5Stickc_1]
+++ brokerからpublisherへPUBREC +++
11355,579.125435414,192.168.0.22,192.168.0.21,MQTT,58,193,315,Publish Received (id=7)
+++ publisherからbrokerへPUBREL +++
11367,579.160742235,192.168.0.21,192.168.0.22,MQTT,60,315,197,Publish Release (id=7)
+++ brokerからpublisherへPUBCOMP +++
11368,579.160872548,192.168.0.22,192.168.0.21,MQTT,58,197,319,Publish Complete (id=7)
+++ brokerからsubscriberへPUBLISH +++
11382,579.175784206,192.168.0.22,192.168.0.21,MQTT,81,201,319,Publish Message (id=4) [/pub/M5Stickc_1]
+++ subscriberからbrokerへPUBREC +++
11389,579.201432249,192.168.0.21,192.168.0.22,MQTT,60,319,228,Publish Received (id=4)
+++ brokerからsubscriberへPUBREL +++
11390,579.201582666,192.168.0.22,192.168.0.21,MQTT,58,228,323,Publish Release (id=4)
+++ subscriberからbrokerへPUBCOMP +++
11392,579.209742013,192.168.0.21,192.168.0.22,MQTT,60,323,232,Publish Complete (id=4)
~~~
~~~plantuml
publisher -> broker:11353/PUBLISH
broker -> publisher:11355/PUBREC
publisher -> broker:11367/PUBREL
broker -> publisher:11368/PUBCOMP
broker -> subscriber:11382/PUBLISH
subscriber -> broker:11389/PUBREC
broker -> subscriber:11390/PUBREL
subscriber -> broker:11392/PUBCOMP
~~~
QOS2のPUBCOMPを送信しているのでQOS2になっているようです
終わりです