关于ESP32/8266使用async-mqtt-client库

2023-12-06  本文已影响0人  Ashin10

目标:
async-mqtt-client是一款基于Arduino的mqtt客户端连接库
服务于ESP32/8266,对于其他设备不兼容(可能)
本文会介绍async-mqtt-client的基本使用方法,解释一些接口的用途

参考资料:
marvinroger/async-mqtt-client
关键词:
async-mqtt-client
Arduino
MQTT
ESP32,ESP8266

目录

  1. 前期准备
  2. 使用介绍
  3. 其他事项

1. 前期准备

因为async-mqtt-client使用异步,会额外依赖异步库
对于ESP32核心的,依赖me-no-dev/AsyncTCP (ESP32)
8266的芯片依赖me-no-dev/ESPAsyncTCP (ESP8266)
需要额外下载对应的库,并放入依赖路径下

另外,本文主要阐述如何在ESP32中的使用
8266用法基本类似,仅在WiFi连接和计时器TimerHandle有接口区别,所以不会进行详细叙述

2. 使用介绍

先打开async-mqtt-client库中的文件夹examples,找到案例
这里选择ESP32的案例FullyFeatured-ESP32.ino
案例的前面一段都是具体的方法,直接拉到setup(),可以看到一共执行了4步

void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.println();
  
  // 1.创建了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的回调函数,处理进行WiFi连接后的事件(成功连接和连接失败)
  WiFi.onEvent(WiFiEvent);

  // 3.配置mqtt服务器,重要(都是挂载回调函数)
  mqttClient.onConnect(onMqttConnect);              // 当mqtt连接时
  mqttClient.onDisconnect(onMqttDisconnect);        // 失去连接时
  mqttClient.onSubscribe(onMqttSubscribe);          // 订阅连接时
  mqttClient.onUnsubscribe(onMqttUnsubscribe);      // 取消订阅时
  mqttClient.onMessage(onMqttMessage);              // 获取消息时
  mqttClient.onPublish(onMqttPublish);              // 发送消息时
  mqttClient.setServer(MQTT_HOST, MQTT_PORT);       // 设置mqtt服务器地址,端口

  // 4.进行WiFi连接
  connectToWifi();
}

在配置mqtt时主要关心设置订阅地址获取消息
在本案例中,订阅地址在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: 会话质量,简单来说,不重要的选择QoS0,重要的选2
  uint16_t packetIdSub = mqttClient.subscribe("test/lol", 2);
  Serial.print("Subscribing at QoS 2, packetId: ");
  Serial.println(packetIdSub);

  // 发布消息: mqttClient.publish(addr, qos, retain, payload);
  // addr,qos,和subscribe相同
  // retain: 标识是否保留消息.如果标识true则在被覆盖前都会保留内容
  // payload: 需要发布的消息
  // ↓案例发布了三种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()

接收到消息时会调用本方法(回调函数),可以在此处配置接收到消息后如何处理方式

void MQTTController::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);
    
    // 重要,消息本体为payload.原代码并没有本段
    // payload本身不包含终止符,如果直接打印/处理内容会在文本最后获取到乱码
    // 可以通过函数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)  //回调函数
);

其中回调函数使用关键词reinterpret_cast来重定义函数connectToWifi的类型
否则需要根据TimerCallbackFunction_t的格式来创建回调函数

3.2 设置WiFi信息和MQTT服务器

在使用该库的时候还需要额外设定WiFi和MQTT的配置

#define WIFI_SSID "yourSSID"
#define WIFI_PASSWORD "yourpass"

#define MQTT_HOST IPAddress(192, 168, 1, 10)  // 设置MQTT的地址
// #define MQTT_HOST "your.domain"  // 如果你是域名,则可以替换为字符串
#define MQTT_PORT 1883  // 设置端口

然后会在setup()中建立连接

// WiFi
connectToWifi();

// mqtt
mqttClient.setServer(MQTT_HOST, MQTT_PORT);
// 补充,如果需要用户名认证
setCredentials(username, password);
3.3 其他

在库下的docs文件夹内有详细的说明文档,可以自行查阅

-- 完 --

上一篇下一篇

猜你喜欢

热点阅读