目標:
async-mqtt-client
是一款基于Arduino的mqtt客戶端連接庫
服務(wù)于ESP32/8266,對于其他設(shè)備不兼容(可能)
本文會介紹async-mqtt-client
的基本使用方法,解釋一些接口的用途
參考資料:
marvinroger/async-mqtt-client
關(guān)鍵詞:
async-mqtt-client
Arduino
MQTT
ESP32,ESP8266
目錄
- 前期準備
- 使用介紹
- 其他事項
1. 前期準備
因為async-mqtt-client
使用異步,會額外依賴異步庫
對于ESP32核心的,依賴me-no-dev/AsyncTCP (ESP32)
8266的芯片依賴me-no-dev/ESPAsyncTCP (ESP8266)
需要額外下載對應(yīng)的庫,并放入依賴路徑下
另外,本文主要闡述如何在ESP32中的使用
8266用法基本類似,僅在WiFi連接和計時器TimerHandle有接口區(qū)別,所以不會進行詳細敘述
2. 使用介紹
先打開async-mqtt-client
庫中的文件夾examples
,找到案例
這里選擇ESP32的案例FullyFeatured-ESP32.ino
案例的前面一段都是具體的方法,直接拉到setup()
,可以看到一共執(zhí)行了4步
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println();
// 1.創(chuàng)建了2個計時器,用于重連
mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToMqtt));
wifiReconnectTimer = xTimerCreate("wifiTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToWifi));
// 2.掛載WiFi的回調(diào)函數(shù),處理進行WiFi連接后的事件(成功連接和連接失敗)
WiFi.onEvent(WiFiEvent);
// 3.配置mqtt服務(wù)器,重要(都是掛載回調(diào)函數(shù))
mqttClient.onConnect(onMqttConnect); // 當mqtt連接時
mqttClient.onDisconnect(onMqttDisconnect); // 失去連接時
mqttClient.onSubscribe(onMqttSubscribe); // 訂閱連接時
mqttClient.onUnsubscribe(onMqttUnsubscribe); // 取消訂閱時
mqttClient.onMessage(onMqttMessage); // 獲取消息時
mqttClient.onPublish(onMqttPublish); // 發(fā)送消息時
mqttClient.setServer(MQTT_HOST, MQTT_PORT); // 設(shè)置mqtt服務(wù)器地址,端口
// 4.進行WiFi連接
connectToWifi();
}
在配置mqtt時主要關(guān)心設(shè)置訂閱地址和獲取消息
在本案例中,訂閱地址在onMqttConnect()
方法中
而獲取消息在onMqttMessage()
中
分別介紹2個方法中的代碼
2.1 onMqttConnect()
void onMqttConnect(bool sessionPresent) {
// sessionPresent: 返回bool,顯示會話session連接成功與否
Serial.println("Connected to MQTT.");
Serial.print("Session present: ");
Serial.println(sessionPresent);
// 訂閱地址: mqttClient.subscribe(addr,qos)
// addr: 訂閱的地址
// QoS: 會話質(zhì)量,簡單來說,不重要的選擇QoS0,重要的選2
uint16_t packetIdSub = mqttClient.subscribe("test/lol", 2);
Serial.print("Subscribing at QoS 2, packetId: ");
Serial.println(packetIdSub);
// 發(fā)布消息: mqttClient.publish(addr, qos, retain, payload);
// addr,qos,和subscribe相同
// retain: 標識是否保留消息.如果標識true則在被覆蓋前都會保留內(nèi)容
// payload: 需要發(fā)布的消息
// ↓案例發(fā)布了三種QoS
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);
}
2.2 onMqttMessage()
接收到消息時會調(diào)用本方法(回調(diào)函數(shù)),可以在此處配置接收到消息后如何處理方式
void MQTTController::onMqttMessage(char *topic, char *payload, AsyncMqttClientMessageProperties properties, size_t len,
size_t index, size_t total) {
// 打印消息的每項參數(shù)或內(nèi)容
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);
// 重要,消息本體為payload.原代碼并沒有本段
// payload本身不包含終止符,如果直接打印/處理內(nèi)容會在文本最后獲取到亂碼
// 可以通過函數(shù)String.substring(start,end)來處理payload
Serial.print(" payload: ");
String fixedStr = ((String) payload).substring(0, len); //char不會斷幀,在此處處理
Serial.println(fixedStr); // fixedStr,處理后的字符串
}
3. 其他注意事項
3.1 定時器xTimerCreate(...)
async-mqtt-client
通過定時器來處理失去連接/連接失敗后的重連問題
這也是額外依賴了freeRTOS庫的原因
有2個定時器,格式都是類似的,這里介紹WiFi的
#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"
...
wifiReconnectTimer = xTimerCreate("wifiTimer", // 定時器名稱
pdMS_TO_TICKS(2000), //周期,tick為單位
pdFALSE, //tick到期后是否自動裝載,(pdTRUE)
(void *) 0, //定時器ID
reinterpret_cast<TimerCallbackFunction_t>(connectToWifi) //回調(diào)函數(shù)
);
其中回調(diào)函數(shù)使用關(guān)鍵詞reinterpret_cast
來重定義函數(shù)connectToWifi
的類型
否則需要根據(jù)TimerCallbackFunction_t
的格式來創(chuàng)建回調(diào)函數(shù)
3.2 設(shè)置WiFi信息和MQTT服務(wù)器
在使用該庫的時候還需要額外設(shè)定WiFi和MQTT的配置
#define WIFI_SSID "yourSSID"
#define WIFI_PASSWORD "yourpass"
#define MQTT_HOST IPAddress(192, 168, 1, 10) // 設(shè)置MQTT的地址
// #define MQTT_HOST "your.domain" // 如果你是域名,則可以替換為字符串
#define MQTT_PORT 1883 // 設(shè)置端口
然后會在setup()
中建立連接
// WiFi
connectToWifi();
// mqtt
mqttClient.setServer(MQTT_HOST, MQTT_PORT);
// 補充,如果需要用戶名認證
setCredentials(username, password);
3.3 其他
在庫下的docs
文件夾內(nèi)有詳細的說明文檔,可以自行查閱
-- 完 --