【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx
忘记过去,超越自己
- ❤️ 博客主页 单片机菜鸟哥,一个野生非专业硬件IOT爱好者 ❤️
- ❤️ 本篇创建记录 2022-10-15 ❤️
- ❤️ 本篇更新记录 2022-10-15 ❤️
- 🎉 欢迎关注 🔎点赞 👍收藏 ⭐️留言📝
- 🙏 此博客均由博主单独编写,不存在任何商业团队运营,如发现错误,请留言轰炸哦!及时修正!感谢支持!
- 🔥 Arduino ESP8266教程累计帮助过超过1W+同学入门学习硬件网络编程,入选过选修课程,刊登过无线电杂志 🔥
目录
- 1. 前言
- 2. emqx 简介
- 3. emqx 部署
- 4. emqx 运行
- 4.1 管理员权限执行 emqx start
- 4.2 浏览器输入 http://localhost:18083/,进入web的控制后台
- 4.3 修改为中文界面
- 4.4点一下每个页面看看是些什么具体内容。
- 4.4.1 仪表盘,指标监控
- 4.4.2 连接管理
- 4.4.3 mqtt主题,topic相关
- 4.4.4 访问控制,控制用户的访问权限
- 4.4.5 数据集成,对接外部系统
- 4.4.6 功能配置
- 4.4.7 问题分析,比较有用是日志追踪
- 5. 接入esp8266 mqtt客户端测试
- 5.1 简单测试功能
- 5.2 黑名单
- 6. 总结
1. 前言
使用多了第三方mqtt服务器(阿里云、OneNet、巴法云等等)之后或者自己写的简单nodejs mqtt服务器之后, 又想看看能否有结合两者的优点的开发方式。
一句话,自己部署一个开源mqtt服务器,集成了绝大部分的功能和管理后台。
而一般在学习物联网中,emqx是提及最多的开源免费mqtt服务器
,部署简单。
建议可以看看官方文档。
- emqx使用指南官方文档
2. emqx 简介
- emqx产品概览
- EMQX版本区别
区分为免费版和企业版(付费版)。对于初学者直接免费版即可。
3. emqx 部署
根据自己的具体操作系统(macOS、Linux、Windows)来下载对应的压缩包。
- 点击下载地址,这里以windows为例
部署步骤:
-
下载好找到一个非中文目录解压
它的目录结构介绍 安装目录结构详细介绍 -
配置好环境变量
4. emqx 运行
要想运行emqx,我们需要先知道有哪些命令行可以用。
官方关于命令行的详细介绍,我们主要先关注启动命令。
4.1 管理员权限执行 emqx start
4.2 浏览器输入 http://localhost:18083/,进入web的控制后台
输入默认账号密码:
- 账号
admin
- 密码
public
,博哥登录成功之后改为了123456
。
到这里我们就算是成功运行起了emqx mqtt服务器了。
记住,它是一个
mqtt broker
。
4.3 修改为中文界面
4.4点一下每个页面看看是些什么具体内容。
4.4.1 仪表盘,指标监控
主要是看看整个数据怎么样,订阅数
,消息流入
,主题
,连接
等等
4.4.2 连接管理
管理每个连接的一些状态信息,连接以clientid作为一个区分。包括ip地址、心跳等等
4.4.3 mqtt主题,topic相关
包括客户端ID
(clientid)、主题
(topic)、质量等级
(QoS)、遗嘱消息
、保留消息
等等
4.4.4 访问控制,控制用户的访问权限
这里提供了第三方的数据源来做安全校验。比如mysql、redis、http服务器等等。
认证
(认证只是验证了客户端的身份是否合法,主要看用户是否能登录系统,关联到username和password)
官方文档说明:emqx认证
EMQX默认没有限制设备登录认证
,而我们实际商用的项目中,安全认证,登录鉴权那是必不可少。我们可以直接使用数据库的sql语句来验证或者连接一个HTTPServer来做。
假设我们通过提供的HTTP服务器来做,那么设备登录认证的流程如下:
- 设备通过MQTT连接到EMQX
- EMQX将设备登录上来的username和password通过HTTP POST的方式传递给HTTP Server
- 认证结果由HTTP Server的返回状态决定EMQX是否建立/拒绝设备的连接。
授权管理
(指对 MQTT 客户端的发布和订阅操作进行权限控制,控制的内容主要是哪些客户端可以发布或者订阅哪些 MQTT 主题)
官方文档说明:emqx授权管理
黑名单
官方文档说明:emqx授权管理
4.4.5 数据集成,对接外部系统
- 官方文档说明:emqx数据集成
数据集成是 EMQX 在发布订阅模型的基础之上的数据处理与分发组件
,通过简单的、可视化的配置,即可将消息流以及设备事件与 Kafka、RabbitMQ 等消息中间件,以及各类 SQL / NoSQL / 时序数据库等数据系统集成。
EMQX 通过结合规则与数据桥接两个功能,提供了实时、简洁、高效的数据集成方案。 其中规则用于处理消息或事件,而数据桥接用于对接数据系统。
4.4.6 功能配置
- 监听器(支持了
tcp
、WebSocket
连接,注意它们的端口号8883
/1883
/8083
/8084
)
- mqtt配置(跟mqtt协议相关内容,包括心跳、连接超时、报文最大大小等等)
4.4.7 问题分析,比较有用是日志追踪
5. 接入esp8266 mqtt客户端测试
- 先获取本地电脑IP地址,使用
ipconfig
命令
5.1 简单测试功能
- 把以下代码烧入esp8266 nodemcu,改一下ip、wifi账号密码。
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
// Update these with values suitable for your network.
const char* ssid = "TP-LINK_5344";//wifi账号
const char* password = "xxxxx";//wifi秘密
const char* mqtt_server = "192.168.1.104";//mqtt服务器
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
randomSeed(micros());
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
/**
* 消息回调
*/
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
// Switch on the LED if an 1 was received as first character
if ((char)payload[0] == '1') {
digitalWrite(BUILTIN_LED, LOW); // Turn the LED on (Note that LOW is the voltage level
// but actually the LED is on; this is because
// it is active low on the ESP-01)
} else {
digitalWrite(BUILTIN_LED, HIGH); // Turn the LED off by making the voltage HIGH
}
}
/**
* 断开重连
*/
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Create a random client ID
String clientId = "ESP8266Client-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
if (client.connect(clientId.c_str())) {
Serial.println("connected");
// Once connected, publish an announcement...
client.publish("outTopic", "hello world");
// ... and resubscribe
client.subscribe("inTopic");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void setup() {
pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output
Serial.begin(115200);
setup_wifi();
//配置mqtt服务器地址和端口
client.setServer(mqtt_server, 1883);
//设置订阅消息回调
client.setCallback(callback);
}
void loop() {
//重连机制
if (!client.connected()) {
reconnect();
}
//不断监听信息
client.loop();
long now = millis();
if (now - lastMsg > 2000) {
//每2s发布一次信息
lastMsg = now;
++value;
snprintf (msg, 50, "hello world #%ld", value);
Serial.print("Publish message: ");
Serial.println(msg);
client.publish("outTopic", msg);
}
}
这里我们订阅了主题 inTopic
,以及用来发布消息的主题 outTopic
。
去emqx后台看看。
我们构造一个日志追踪,监听几分钟,然后把日志下载下来。
2022-10-15T14:41:03+08:00 [MQTT] ESP8266Client-7f70@192.168.1.105:65216 msg: mqtt_packet_received, packet: PUBLISH(Q0, R0, D0),Topic=outTopic, PacketId=undefinedPayload=hello world #245
2022-10-15T14:41:03+08:00 [PUBLISH] ESP8266Client-7f70@192.168.1.105:65216 msg: publish_to, topic: outTopic, payload: hello world #245
2022-10-15T14:41:05+08:00 [MQTT] ESP8266Client-7f70@192.168.1.105:65216 msg: mqtt_packet_received, packet: PUBLISH(Q0, R0, D0),Topic=outTopic, PacketId=undefinedPayload=hello world #246
2022-10-15T14:41:05+08:00 [PUBLISH] ESP8266Client-7f70@192.168.1.105:65216 msg: publish_to, topic: outTopic, payload: hello world #246
2022-10-15T14:41:07+08:00 [MQTT] ESP8266Client-7f70@192.168.1.105:65216 msg: mqtt_packet_received, packet: PUBLISH(Q0, R0, D0),Topic=outTopic, PacketId=undefinedPayload=hello world #247
2022-10-15T14:41:07+08:00 [PUBLISH] ESP8266Client-7f70@192.168.1.105:65216 msg: publish_to, topic: outTopic, payload: hello world #247
2022-10-15T14:41:09+08:00 [MQTT] ESP8266Client-7f70@192.168.1.105:65216 msg: mqtt_packet_received, packet: PUBLISH(Q0, R0, D0),Topic=outTopic, PacketId=undefinedPayload=hello world #248
2022-10-15T14:41:09+08:00 [PUBLISH] ESP8266Client-7f70@192.168.1.105:65216 msg: publish_to, topic: outTopic, payload: hello world #248
2022-10-15T14:41:11+08:00 [MQTT] ESP8266Client-7f70@192.168.1.105:65216 msg: mqtt_packet_received, packet: PUBLISH(Q0, R0, D0),Topic=outTopic, PacketId=undefinedPayload=hello world #249
2022-10-15T14:41:11+08:00 [PUBLISH] ESP8266Client-7f70@192.168.1.105:65216 msg: publish_to, topic: outTopic, payload: hello world #249
2022-10-15T14:41:13+08:00 [MQTT] ESP8266Client-7f70@192.168.1.105:65216 msg: mqtt_packet_received, packet: PUBLISH(Q0, R0, D0),Topic=outTopic, PacketId=undefinedPayload=hello world #250
2022-10-15T14:41:13+08:00 [PUBLISH] ESP8266Client-7f70@192.168.1.105:65216 msg: publish_to, topic: outTopic, payload: hello world #250
2022-10-15T14:41:15+08:00 [MQTT] ESP8266Client-7f70@192.168.1.105:65216 msg: mqtt_packet_received, packet: PUBLISH(Q0, R0, D0),Topic=outTopic, PacketId=undefinedPayload=hello world #251
2022-10-15T14:41:15+08:00 [PUBLISH] ESP8266Client-7f70@192.168.1.105:65216 msg: publish_to, topic: outTopic, payload: hello world #251
2022-10-15T14:41:17+08:00 [MQTT] ESP8266Client-7f70@192.168.1.105:65216 msg: mqtt_packet_received, packet: PUBLISH(Q0, R0, D0),Topic=outTopic, PacketId=undefinedPayload=hello world #252
2022-10-15T14:41:17+08:00 [PUBLISH] ESP8266Client-7f70@192.168.1.105:65216 msg: publish_to, topic: outTopic, payload: hello world #252
2022-10-15T14:41:17+08:00 [API] ESP8266Client-7f70@ msg: trace_stopping,
可以看到日志内容能对接得上我们从 8266发送过来的数据。
5.2 黑名单
把上面的esp8266代码稍微改造一下,使用一个固定的clientid名字。
ESP8266Client-dpjcn
这时候是正常连接的。然后去后台设置一下黑名单看看。
6. 总结
一句话,多看文档多试试,配置起来10分钟即可运行起来。