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协议
应用层协议:每个应用层的都是为了解决某一类应用问题.而问题的解决又必须通过位于不同主机中的多个应用进程之间的通信和协同工作来完成.应用进程之间必须遵守严格的规则.应用层协议应当定义如下几个: 应用进程 ...
随机推荐
- [atARC080F]Prime Flip
构造一个数组$b_{i}$(初始为0),对于操作$[l_{i},r_{i}]$,令$b_{l_{i}}$和$b_{r_{i}+1}$值异或1,表示$i$和$i-1$的差值发生改变,最终即要求若干个$b ...
- [atARC100F]Colorful Sequences
考虑求任意序列中$a$出现次数之和减去不合法序列中$a$出现次数之和,前者即为$(n-m+1)k^{n-m}$(一个序列重复次数恰好为$a$出现次数),对于后者,先忽略$a$的次数,即统计有多少个不合 ...
- 什么是H5
H5其实就是HTML5 常说的H5测试,就是移动端web页面,他跟安卓app与IOS app的区别: (1)以往的app是使用的原生系统内核的,相当于直接在系统上操作,是传统意义上的软件,更加稳定 ( ...
- Codeforces 193D - Two Segments(线段树)
Codeforces 题目传送门 & 洛谷题目传送门 感觉这个 *2900 并不难啊,为什么我没想出来呢 awa 顺便膜拜 ycx 一眼秒掉此题 %%% 首先碰到这类题有两种思路,一是枚举两个 ...
- DTOJ 4027:挖煤
挖煤 [问题描述]众所周知, 小C是挖煤好手.今天他带着他的魔法镐子去挖煤 ,他的镐子一开始有$w$点魔力.他的挖煤 路线 上会依次 经过$n$个地点, 地点, 每个 地点是煤矿或者补给站,设小C当前 ...
- Mysql的delimiter
告诉MySQL解释器,该段命令是否已经结束了,mysql是否可以执行了.默认情况下,delimiter是分号;.在命令行客户端中,如果有一行命令以分号结束,那么回车后,mysql将会执行该命令. 有时 ...
- Linux之crond定时任务
1. 使用crontab工具配置的定时任务 2. 配置定时任务建议规范 3. 定时任务配置问题导致系统出现故障实例 1. 使用crontab工具配置的定时任务 名称 crontab - 维护单个用户的 ...
- git放弃修改,强制覆盖本地代码
1.git fetch --all //从远程拉取最新的代码 不merge 2.git reset --hard origin/develop //使用指定分支的代码(此处develop)强制覆盖 ...
- 非标准的xml解析器的C++实现:一、思考基本数据结构的设计
前言: 我在C++项目中使用xml作为本地简易数据管理,到目前为止有5年时间了,从最初的全文搜索标签首尾,直到目前项目中实际运用的类库细致到已经基本符合w3c标准,我一共写过3次解析器,我自己并没有多 ...
- 日常Java 2021/9/21
将Java数组中的元素前后反转.题目要求:已知一个数组arr = {11,12,13,14,15}用程序实现把该数组中的元素值交换,交换后的数组arr = { 15,14,13,12,11},并输出交 ...