關(guān)于ESP32/8266使用async-mqtt-client庫(kù)的一些基本介紹

目標(biāo):
async-mqtt-client是一款基于Arduino的mqtt客戶端連接庫(kù)
服務(wù)于ESP32/8266,對(duì)于其他設(shè)備不兼容(可能)
本文會(huì)介紹async-mqtt-client的基本使用方法,解釋一些接口的用途

參考資料:
marvinroger/async-mqtt-client
關(guān)鍵詞:
async-mqtt-client
Arduino
MQTT
ESP32,ESP8266

目錄

  1. 前期準(zhǔn)備
  2. 使用介紹
  3. 其他事項(xiàng)

1. 前期準(zhǔn)備

因?yàn)?code>async-mqtt-client使用異步,會(huì)額外依賴異步庫(kù)
對(duì)于ESP32核心的,依賴me-no-dev/AsyncTCP (ESP32)
8266的芯片依賴me-no-dev/ESPAsyncTCP (ESP8266)
需要額外下載對(duì)應(yīng)的庫(kù),并放入依賴路徑下

另外,本文主要闡述如何在ESP32中的使用
8266用法基本類似,僅在WiFi連接和計(jì)時(shí)器TimerHandle有接口區(qū)別,所以不會(huì)進(jìn)行詳細(xì)敘述

2. 使用介紹

先打開async-mqtt-client庫(kù)中的文件夾examples,找到案例
這里選擇ESP32的案例FullyFeatured-ESP32.ino
案例的前面一段都是具體的方法,直接拉到setup(),可以看到一共執(zhí)行了4步

void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.println();
  
  // 1.創(chuàng)建了2個(gè)計(jì)時(shí)器,用于重連
  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ù),處理進(jìn)行WiFi連接后的事件(成功連接和連接失敗)
  WiFi.onEvent(WiFiEvent);

  // 3.配置mqtt服務(wù)器,重要(都是掛載回調(diào)函數(shù))
  mqttClient.onConnect(onMqttConnect);              // 當(dāng)mqtt連接時(shí)
  mqttClient.onDisconnect(onMqttDisconnect);        // 失去連接時(shí)
  mqttClient.onSubscribe(onMqttSubscribe);          // 訂閱連接時(shí)
  mqttClient.onUnsubscribe(onMqttUnsubscribe);      // 取消訂閱時(shí)
  mqttClient.onMessage(onMqttMessage);              // 獲取消息時(shí)
  mqttClient.onPublish(onMqttPublish);              // 發(fā)送消息時(shí)
  mqttClient.setServer(MQTT_HOST, MQTT_PORT);       // 設(shè)置mqtt服務(wù)器地址,端口

  // 4.進(jìn)行WiFi連接
  connectToWifi();
}

在配置mqtt時(shí)主要關(guān)心設(shè)置訂閱地址獲取消息
在本案例中,訂閱地址在onMqttConnect()方法中
而獲取消息在onMqttMessage()
分別介紹2個(gè)方法中的代碼

2.1 onMqttConnect()
void onMqttConnect(bool sessionPresent) {
  // sessionPresent: 返回bool,顯示會(huì)話session連接成功與否
  Serial.println("Connected to MQTT.");
  Serial.print("Session present: ");
  Serial.println(sessionPresent);

  // 訂閱地址: mqttClient.subscribe(addr,qos)
  // addr: 訂閱的地址
  // QoS: 會(huì)話質(zhì)量,簡(jiǎn)單來(lái)說(shuō),不重要的選擇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: 標(biāo)識(shí)是否保留消息.如果標(biāo)識(shí)true則在被覆蓋前都會(huì)保留內(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()

接收到消息時(shí)會(huì)調(diào)用本方法(回調(diào)函數(shù)),可以在此處配置接收到消息后如何處理方式

void MQTTController::onMqttMessage(char *topic, char *payload, AsyncMqttClientMessageProperties properties, size_t len,
                                   size_t index, size_t total) {
    // 打印消息的每項(xiàng)參數(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.原代碼并沒(méi)有本段
    // payload本身不包含終止符,如果直接打印/處理內(nèi)容會(huì)在文本最后獲取到亂碼
    // 可以通過(guò)函數(shù)String.substring(start,end)來(lái)處理payload
    Serial.print("  payload: ");
    String fixedStr = ((String) payload).substring(0, len);       //char不會(huì)斷幀,在此處處理
    Serial.println(fixedStr);   // fixedStr,處理后的字符串
}

3. 其他注意事項(xiàng)

3.1 定時(shí)器xTimerCreate(...)

async-mqtt-client通過(guò)定時(shí)器來(lái)處理失去連接/連接失敗后的重連問(wèn)題
這也是額外依賴了freeRTOS庫(kù)的原因
有2個(gè)定時(shí)器,格式都是類似的,這里介紹WiFi的

#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"

...

wifiReconnectTimer = xTimerCreate("wifiTimer",                              // 定時(shí)器名稱
                                  pdMS_TO_TICKS(2000),      //周期,tick為單位
                                  pdFALSE,  //tick到期后是否自動(dòng)裝載,(pdTRUE)
                                  (void *) 0,     //定時(shí)器ID
                                  reinterpret_cast<TimerCallbackFunction_t>(connectToWifi)  //回調(diào)函數(shù)
);

其中回調(diào)函數(shù)使用關(guān)鍵詞reinterpret_cast來(lái)重定義函數(shù)connectToWifi的類型
否則需要根據(jù)TimerCallbackFunction_t的格式來(lái)創(chuàng)建回調(diào)函數(shù)

3.2 設(shè)置WiFi信息和MQTT服務(wù)器

在使用該庫(kù)的時(shí)候還需要額外設(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è)置端口

然后會(huì)在setup()中建立連接

// WiFi
connectToWifi();

// mqtt
mqttClient.setServer(MQTT_HOST, MQTT_PORT);
// 補(bǔ)充,如果需要用戶名認(rèn)證
setCredentials(username, password);
3.3 其他

在庫(kù)下的docs文件夾內(nèi)有詳細(xì)的說(shuō)明文檔,可以自行查閱

-- 完 --

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容