MQTT协议 - arduino ESP32 通过精灵一号 MQTT Broker 进行通讯的代码详解


前言

之前研究了一段时间的 COAP 协议结果爱智那边没有测试工具,然后 arduino 也没有找到合适的库,我懒癌发作也懒得修这库,就只能非常尴尬先暂时放一放了。不过我在 爱智APP -> 设备 -> 设置 中发现爱智中做了一个 MQTT Broker ,也就是说我能利用精灵一号,在两块ESP32 之间进行通讯了,而且 arduino 也有现成的库,然后我就突击了一下MQTT ,把这玩意给弄起来了,这里就给大家分享一下。
在这里插入图片描述


配置 MQTT Broker

在爱智APP的设备中有个设置按钮:

在这里插入图片描述
在里面可以启用精灵一号的 MQTT Broker 功能并且进行设置:
在这里插入图片描述
在 MQTT 的设置中可以配置相关参数:
在这里插入图片描述
这些参数和与下面 ESP32 中的配置有关

代码获取

我使用的 MQTT 库直接在 IDE 的库管理器里就能下载到:
在这里插入图片描述
或者去GitHub下载:

https://github.com/adafruit/Adafruit_MQTT_Library

而示例代码,老样子在灵感桌面的秘密宝库 下载代码。
或者直接 git clone:

https://gitee.com/inspiration-desktop/eap-energy-conservation.git

在这里插入图片描述
里面有两个文件夹,分别是发布者和订阅者发的示例。

代码解析

为了方便讲解逻辑,我会打乱代码的顺序可能还会进行裁剪。本 demo 基于 MQTT 库自带的 DEMO 修改而来。

创建 MQTT 客户端

#include <WiFi.h>
//#include "WiFiClientSecure.h"
#include "WiFiClient.h"
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"

/************************* WiFi Access Point *********************************/

#define WLAN_SSID "EOS-Tenda"
#define WLAN_PASS "1234567890"

/************************* Adafruit.io Setup *********************************/

#define AIO_SERVER      "192.168.128.1"

// 在爱智APP->设备->MQTT Broker 设置,可以看到并且设置
#define AIO_SERVERPORT  1883

// 在爱智APP->设备->MQTT Broker 设置,可以看到并且设置
#define AIO_USERNAME "user"
#define AIO_KEY      "passwd"

/************ Global State (you don't need to change this!) ******************/

// 爱智似乎没有这个安全模式,于是使用了 WiFiClient 
//WiFiClientSecure client;
WiFiClient client;

// 通过传入WiFi客户端和MQTT服务端以及登录详细信息来设置MQTT客户端类,注意连入爱智必须设置 cid,可能和爱智那边设置有关系。
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, "Publish_cid", AIO_USERNAME, AIO_KEY);

需要注意的是虽然 Adafruit_MQTT_Client 有可以不带 cid 的实现

/***
 * 函数1:创建MQTT客户端
 * @param client 来源客户端,比如Wificlient eth以太网
 * @param server  mqtt服务器地址
 * @param port    mqtt服务器端口
 * @param cid     客户端id,如果是8266,可以设置为芯片id之类的,每个端都是独一无二
 * @param user    mqtt服务器账号
 * @param pass    mqtt服务器密码
 */
Adafruit_MQTT_Client(Client *client, const char *server, uint16_t port,
                       const char *cid, const char *user, const char *pass):
    Adafruit_MQTT(server, port, cid, user, pass),
    client(client)
{}

/***
 * 函数2:创建MQTT客户端
 * @param client 来源客户端,比如Wificlient eth以太网
 * @param server  mqtt服务器地址
 * @param port    mqtt服务器端口
 * @param user    mqtt服务器账号
 * @param pass    mqtt服务器密码
 */
Adafruit_MQTT_Client(Client *client, const char *server, uint16_t port,
                       const char *user="", const char *pass=""):
    Adafruit_MQTT(server, port, user, pass),
    client(client)
————————————————
版权声明:本文为CSDN博主「单片机菜鸟哥」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/dpjcn1990/article/details/103376117

但是连接爱智时 Adafruit_MQTT_Client 函数必须设置 cid 而且 cid 必须是独一无二的,否则:
在这里插入图片描述
cid 重复会导致这两个设备收到同样的,重复的连接成功消息,使设备不停的去连接精灵一号

创建 MQTT 发布主题

// 设置一个名为“test”的提要用于发布。
// 注意AIO的MQTT路径遵循: <username>/feeds/<feedname>
Adafruit_MQTT_Publish test = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/test");

创建 MQTT 订阅主题

// 设置订阅的主题。
Adafruit_MQTT_Subscribe test = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/test");

初始化流程

void setup() {
  Serial.begin(115200);
  delay(10);

  Serial.println(F("Adafruit IO MQTTS (SSL/TLS) Example"));

  // Connect to WiFi access point.
  Serial.println(); Serial.println();
  Serial.print("Connecting to ");
  Serial.println(WLAN_SSID);

  delay(1000);

  WiFi.begin(WLAN_SSID, WLAN_PASS);
  delay(2000);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();

  Serial.println("WiFi connected");
  Serial.println("IP address: "); Serial.println(WiFi.localIP());

  
// 设置测试需要的 MQTT 订阅。发布者把这一行注释掉
  mqtt.subscribe(&test);
}

MQTT 连接

// 函数用于根据需要连接并重新连接到MQTT服务器
// 应该在循环函数中调用,它将注意是否连接。
void MQTT_connect() {
  int8_t ret;

  // 如果已经停止连接。
  if (mqtt.connected()) {
    return;
  }

  Serial.print("Connecting to MQTT... ");

  uint8_t retries = 3;
  // 连接mqtt服务器
  while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
       Serial.println(mqtt.connectErrorString(ret));
       Serial.println("Retrying MQTT connection in 5 seconds...");
       mqtt.disconnect();
       delay(5000);  // wait 5 seconds
       retries--;
       if (retries == 0) {
         // basically die and wait for WDT to reset me
         while (1);
       }
  }

  Serial.println("MQTT Connected!");
}

发布者协议主循环

void loop() {
  // 确保到MQTT服务器的连接是活动的(这将创建第一个连接,
  // 并在断开连接时自动重新连接)。请参阅上面的MQTT_connect函数定义。
  MQTT_connect();

  // 现在我们可以发布东西了!
  Serial.print(F("\nSending val "));
  Serial.print(x);
  Serial.print(F(" to test feed..."));
  if (! test.publish(x++)) {
    Serial.println(F("Failed"));
  } else {
    Serial.println(F("OK!"));
  }

  // wait a couple seconds to avoid rate limit
  delay(2000);

}

订阅者协议主循环

void loop() {
  // 确保到MQTT服务器的连接是活动的(这将创建第一个连接,
  // 并在断开连接时自动重新连接)。请参阅上面的MQTT_connect函数定义。
  MQTT_connect();
  
  // 等待订阅消息循环
  Adafruit_MQTT_Subscribe *subscription;
  // 在5s内判断是否有订阅消息进来
  while ((subscription = mqtt.readSubscription(5000))) 
  {
    Serial.println("subscription");
    // 判断是否是我们对应的主题
    if (subscription == &test)
    {
      Serial.print(F("Got: "));
      // 打印主题信息内容
      Serial.println((char *)test.lastread);
    }

  // wait a couple seconds to avoid rate limit
  delay(2000);
  }
}

总结

在这里插入图片描述
精灵一号的 MQTT Broker 还是好用的,两个 ESP32 板子完美的通讯了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值