一、mqtt服务器环境搭建
我们的esp32开发板已经可以通过wi-fi正常连接网络,我们需要将板卡采集的数据上报到服务器,并将数据存入数据库,服务器可以下发指令到板卡执行某些动作,这样就实现了一个简单的iot平台。
物联网一般使用的是mqtt通讯协议,mqtt主要是订阅者和发布者之间的消息传递。
因此我们这里需要搭建一个mqtt服务器,这里选用的是emqx开源免费版本进行搭建。
1.1.概述
emqx 是一款开源的大规模分布式 mqtt 消息服务器,功能丰富,专为物联网和实时通信应用而设计。emqx 5.0 单集群支持 mqtt 并发连接数高达 1 亿条,单服务器的传输与处理吞吐量可达每秒百万级 mqtt 消息,同时保证毫秒级的低时延。
emqx产品优势
- **开放源码 **:基于 apache 2.0 许可证完全开源,自 2013 年起 200+ 开源版本迭代。
- **mqtt 5.0 **:100% 支持 mqtt 5.0 和 3.x 协议标准,更好的伸缩性、安全性和可靠性。
- [海量连接]:单节点支持 500 万 mqtt 设备连接,集群可扩展至 1 亿并发 mqtt 连接。
- 高性能:单节点支持每秒实时接收、移动、处理与分发数百万条的 mqtt 消息。
- 低时延:基于 erlang/otp 软实时的运行时系统设计,消息分发与投递时延低于 1 毫秒。
- 高可用:采用 masterless 的大规模分布式集群架构,实现系统高可用和水平扩展
1.2.准备工作
1.2.1.硬件
- 云端服务器(公网ip) 此项非必须,可在自已机器上进行本地搭建
- 电脑(windows 10)
1.2.2.软件
准备软件安装包:
emqx官方文档提供了详细的说明,我们的云端服务器使用的是ubuntu 22.04 64位系统,参考对应的文档选择某种安装方式即可,这里采用的是通过 apt 源安装
emqx官网: https://www.emqx.io/
1.3.安装
1.3.1.mqtt服务器搭建
1.通过以下命令配置 emqx apt 源:
curl -s https://assets.emqx.com/scripts/install-emqx-deb.sh | sudo bash
2.运行以下命令安装 emqx:
sudo apt-get install emqx
3.运行以下命令启动 emqx:
sudo systemctl start emqx
远程登录云端服务器,依次执行上面的三个命令,执行完成后emqx服务就已经启动了。
浏览器中输入访问地址: http://ip:18083/,即可打开登录界面
成功登录后可看到emqx的管理平台dashboard
1.3.2.安装mqttx客户端
客户端工具是作为验证工具,用于快速测试mqtt消息服务和应用程序开发。
mqttx官网:https://mqttx.app/zh
安装过程,到官网下载并运行安装程序
下一步,选择安装路径
点击安装,直至安装完成即可
运行主界面
默认为英文操作界面,设置为中文,点击左侧配置按钮,在language栏选择简体中文即可
1.3.3.mqttx 工具创建客户端连接
1.启动 mqttx 客户端。点击新建连接创建一个 mqtt 连接。
2.配置新建的 mqtt 连接作为消息发送客户端。
1.3.4.mqttx工具发送消息
我们已经创建了一个客户端连接并成功连接上了mqtt服务器,然后订阅一个主题hantu_iot/testtopic并向它发送一条消息。
打开mqttx工具,点击添加订阅
进入添加订阅窗口,在topic文本框中输入hantu_iot/testtopic
点击确定
按钮,即可看到已经添加了这个订阅
我们在mqttx的右角下的topic处输入hantu_iot/testtopic,并在内容框中输入一段json格式字符串,点击绿色提交按钮。
可以看到mqttx客户端向服务器提交了一条了消息,由于mqttx客户端自已也订阅了这个主题,所以它也会收到服务器分发过来的这条消息,这就实现了一次简单的发送、接收消息。
二、开发板发布和订阅消息
mqtt服务器搭建完成以后,我们就可以将开发板采集到的数据通过mqtt协议发送到mqtt服务器,并将其存储到服务器数据库当中(数据持久化),由于emqx免费版不提供数据持久化的功能,为了解决这个问题,我们会需要用到另外一个重要的工具node-red
2.1.引入第三方库
esp32最小开发板通过wifi连接到网后,通过mqtt协议收发消息,我们需要用到第三方库pubsubclient库
引入方法,我们打开arduino ide,进入项目
->导入库
–>管理库
在左侧库管理
界面搜索栏中输入我们想要查找的库名称,我们这里输入"pubsubclient",回车进行搜索
点击安装
直接进行安装即可,这里选择的版本是2.8.0
2.2.输入代码
接下来我们就可以开始编写代码了,输入以下代码
#include <arduino.h>
#include <wifi.h>
#include <pubsubclient.h>
/*=========================== 全局变量及宏定义 =============================*/
// wifi
const char *ssid = "此处为wifi网络名称";
const char *password = "此处为wifi密码";
// mqtt broker
const char *mqtt_broker = "mqtt服务器ip"; // 服务器地址
const char *clientid = "hantu-1234"; // 自定义clientid
const char *topic = "hantu_iot/testtopic"; // 定义 topic
const char *mqtt_username = "用户名"; // 用户名
const char *mqtt_password = "密码"; // 密码
const int mqtt_port = 1883; // 端口
//定义客户端
wificlient espclient;
pubsubclient client(espclient);
void setup() {
// 初始化波特率
serial.begin(9600);
// 连接wifi网络
wifi.begin(ssid, password);
serial.print("正在连接wifi");
while (wifi.status() != wl_connected) {
delay(500);
serial.println(".");
}
serial.println("连接成功");
serial.print("ip address");
serial.println(wifi.localip());
// 连接到mqtt服务器
client.setserver(mqtt_broker, mqtt_port);
// 设置mqtt保持活跃时间 ms
client.setkeepalive(60);
// 设置回调函数
client.setcallback(callback);
while (!client.connected()) {
serial.printf("the client %s connects to the public mqtt broker\n", clientid);
if (client.connect(clientid, mqtt_username, mqtt_password)) {
serial.println("esp32开发板连接mqtt服务器成功");
} else {
serial.print("failed with state ");
serial.print(client.state());
delay(2000);
}
}
// 定阅主题
client.subscribe(topic, 0);
// 发布消息
client.publish(topic, "hi emqx, i'm esp32 ^^");
}
void callback(char *topic, byte *payload, unsigned int length) {
serial.print("message arrived in topic: ");
serial.println(topic);
serial.print("message:");
for (int i = 0; i < length; i++) {
serial.print((char)payload[i]);
}
serial.println();
serial.println("-----------------------");
}
void loop() {
client.loop();
}
2.3.编译并上传程序
输入完成后,初次编译需要指定程序的存放目录,工程名称命名为mqtt_sendtoserver,然后执行上传命令即可进行代码的编译并上传至开发板,点击上传
按钮开始上传
看到这样的执行结果就说明程序已经正常上传到开发板,我们打开串口监视器
可以看到程序已经正常运行。
三、远程控制led灯
本示例学习如何远程能过网络来控制led的开和关,我们已经实现了与mqtt服务器的消息通信,接下来我们来实现远程控制板载led灯的开和关。
3.1.控制led灯程序
打开arduino ide,输入程序,命名工程名称为mqtt_led_onoff
#include <arduino.h>
#include <wifi.h>
#include <pubsubclient.h>
#include <arduinojson.h>
/*=========================== 全局变量及宏定义 =============================*/
// wifi
const char *ssid = "此处为wifi网络名称";
const char *password = "此处为wifi密码";
// mqtt broker
const char *mqtt_broker = "mqtt服务器ip"; // 服务器地址
const char *clientid = "hantu-1234"; // 自定义clientid
const char *topic = "hantu_iot/testtopic"; // 定义 topic
const char *mqtt_username = "用户名"; // 用户名
const char *mqtt_password = "密码"; // 密码
const int mqtt_port = 1883; // 端口
//定义客户端
wificlient espclient;
pubsubclient client(espclient);
/*=========================== 自定义全局变量&宏定义 =============================*/
int redpin = 25;
void setup() {
// 初始化波特率
serial.begin(9600);
// 设置led灯为输出模式
pinmode(redpin, output);
// 连接wifi网络
wifi.begin(ssid, password);
serial.print("正在连接wifi");
while (wifi.status() != wl_connected) {
delay(500);
serial.println(".");
}
serial.println("连接成功");
serial.print("ip address");
serial.println(wifi.localip());
// 连接到mqtt服务器
client.setserver(mqtt_broker, mqtt_port);
// 设置mqtt保持活跃时间 ms
client.setkeepalive(60);
// 设置回调函数
client.setcallback(callback);
while (!client.connected()) {
serial.printf("the client %s connects to the public mqtt broker\n", clientid);
if (client.connect(clientid, mqtt_username, mqtt_password)) {
serial.println("esp32开发板连接mqtt服务器成功");
} else {
serial.print("failed with state ");
serial.print(client.state());
delay(2000);
}
}
// 定阅主题
client.subscribe(topic, 0);
// 发布消息
client.publish(topic, "hi emqx, i'm esp32 ^^");
}
void callback(char *topic, byte *payload, unsigned int length) {
serial.print("message arrived in topic: ");
serial.println(topic);
serial.print("message:");
for (int i = 0; i < length; i++) {
serial.print((char)payload[i]);
}
serial.println();
serial.println("-----------------------");
//解析payload获取led灯的开和关的值
jsondocument doc;
deserializejson(doc, payload);
int led_logic = doc["led"];
if (led_logic == 1) {
digitalwrite(redpin, low);
serial.println("led灯已打开");
}
if (led_logic == 0) {
digitalwrite(redpin, high);
serial.println("led灯已关闭");
}
delay(50);
}
void loop() {
client.loop();
}
然后编译并上传程序到板卡
3.2.mqttx发送开关指令
我们打开mqttx客户端,连接到服务器,然后向开发板订阅的主题"hantu_iot/testtopic"发送消息,服务器在接收到mqttx的消息后以后在将消息推送给订阅者(开发板),从而就可以实现远程的控制
我们定义了一个简单的json字符串,只发送0或者1来进行开关
点击发送即可看到灯的开关状态
发表评论