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

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

在里面可以启用精灵一号的 MQTT Broker 功能并且进行设置:

在 MQTT 的设置中可以配置相关参数:

这些参数和与下面 ESP32 中的配置有关
代码获取
我使用的 MQTT 库直接在 IDE 的库管理器里就能下载到:

或者去GitHub下载:
而示例代码,老样子在灵感桌面的秘密宝库 下载代码。
或者直接 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 板子完美的通讯了。
MQTT协议 - arduino ESP32 通过精灵一号 MQTT Broker 进行通讯的代码详解的更多相关文章
- COAP协议 - arduino ESP32 M2M(端对端)通讯与代码详解
前言 最近我在研究 COAP 协议,在尝试使用 COAP 协议找了到了一个能在ESP32上用的coap-simple库,虽然库并不完善关于loop处理的部分应该是没写完,但是对于第一次接触COAP的朋 ...
- 微信JS-SDK]微信公众号JS开发之卡券领取功能详解
js sdk: http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD.952-.E6 ...
- 微信支付PHP SDK —— 公众号支付代码详解
在微信支付 开发者文档页面 下载最新的 php SDK http://mch.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1 这里假设你已经申请完微 ...
- 8 TFTP代码详解 协议写在程序中
1.版本1:发送请求 # -*- coding:utf-8 -*- import struct from socket import * #0. 获取要下载的文件名字: downloadFileNam ...
- 转:XMPP协议、MQTT协议、HTTP协议、CoAP协议的基本比较
一.先看下相关国外的专业数据对四大协议的比较: Protocol CoAP XMP ...
- 为什么最近每份 Android 简历都说 “熟悉 MQTT 协议”?
请点赞关注,你的支持对我意义重大. Hi,我是小彭.本文已收录到 GitHub · AndroidFamily 中.这里有 Android 进阶成长知识体系,有志同道合的朋友,关注公众号 [彭旭锐] ...
- 基于MQTT协议进行应用开发
官方协议有句如下的话来形容MQTT的设计思想: "It is designed for connections with remote locations where a "sma ...
- 物联网MQTT协议分析和开源Mosquitto部署验证
在<物联网核心协议—消息推送技术演进>一文中已向读者介绍了多种消息推送技术的情况,包括HTTP单向通信.Ajax轮询.Websocket.MQTT.CoAP等,其中MQTT协议为IBM制定 ...
- HTTP协议和XMPP协议、MQTT协议
应用层协议:每个应用层的都是为了解决某一类应用问题.而问题的解决又必须通过位于不同主机中的多个应用进程之间的通信和协同工作来完成.应用进程之间必须遵守严格的规则.应用层协议应当定义如下几个: 应用进程 ...
随机推荐
- Java设计模式之(四)——原型模式
1.什么是原型模式 Specify the kinds of objects to create using a prototypical instance,and create new object ...
- [nowcoder5669E]Eliminate++
枚举$a_{i}$并判断是否可行,有以下结论:若$a_{i}$可以留下来,一定存在一种合法方案使得$a_{i}$仅参与最后若干次合并,且第一次参与合并前左右都不超过2个数 证明:将大于$a_{i}$的 ...
- layui页面操作,点击一个添加页面,跳转有确定,然后点击确定后将选择的几个数据返回前一个页面获取值,然后ajax请求后台
custUserIndex.html [添加页面代码] <!DOCTYPE html> <html> <head> <meta charset="u ...
- Vulnhub-Empire: Breakout题解
Vulnhub-Empire: Breakout题解 这是Empire系列的靶机Breakout,地址:Vulnhub-EMPIRE: BREAKOUT 目标扫描 使用arp-scan 命令识别靶机I ...
- 最强最全面的Hive SQL开发指南,超四万字全面解析
本文整体分为两部分,第一部分是简写,如果能看懂会用,就直接从此部分查,方便快捷,如果不是很理解此SQL的用法,则查看第二部分,是详细说明,当然第二部分语句也会更全一些! 第一部分: hive模糊搜索表 ...
- P6072 『MdOI R1』Path
考虑我们有这样操作. 我们只要维护两点在子树内和两点在子树外的异或和即可. 前者可以类似于线段树合并的trie树合并. 后者有两种做法: 一种是把dfn序翻倍:然后子树补变成了一个区间最大异或问题,可 ...
- 洛谷 P5540 - [BalkanOI2011] timeismoney | 最小乘积生成树(最小生成树)
洛谷题面传送门 大概是一个比较 trivial 的小 trick?学过了就不要忘了哦( 莫名奇妙地想到了 yyq 的"hot tea 不常有,做过了就不能再错过了" 首先看到这种二 ...
- rust Option枚举
枚举 1 fn main() { 2 let a_binding; 3 { 4 let x = 2; 5 a_binding = x * x; 6 } 7 println!("a bindi ...
- Excel—分组然后取每组中对应时间列值最大的或者最小的
1.MAX(IF(A:A=D2,B:B)) 输入函数公式后,按Ctrl+Shift+Enter键使函数公式成为数组函数公式. Ctrl+Shift+Enter: 按住Ctrl键不放,继续按Shift键 ...
- KeepAlived双主模式高可用集群
keepalived是vrrp协议的实现,原生设计目的是为了高可用ipvs服务,keepalived能够配置文件中的定义生成ipvs规则,并能够对各RS的健康状态进行检测:通过共用的虚拟IP地址对外提 ...