目标:
async-mqtt-client
是一款基于Arduino的mqtt客户端连接库
服务于ESP32/8266,对于其他设备不兼容(可能)
本文会介绍async-mqtt-client
的基本使用方法,解释一些接口的用途
参考资料:
marvinroger/async-mqtt-client
关键词:
async-mqtt-client
Arduino
MQTT
ESP32,ESP8266
目录
- 前期准备
- 使用介绍
- 其他事项
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
文件夹内有详细的说明文档,可以自行查阅
-- 完 --
网友评论