美文网首页
关于ESP32/8266使用async-mqtt-client库

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

作者: Ashin10 | 来源:发表于2023-12-06 16:03 被阅读0次

    目标:
    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文件夹内有详细的说明文档,可以自行查阅

    -- 完 --

    相关文章

      网友评论

          本文标题:关于ESP32/8266使用async-mqtt-client库

          本文链接:https://www.haomeiwen.com/subject/giejgdtx.html