【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx

时间:2022-10-15 22:03:21

忘记过去,超越自己

  • ❤️ 博客主页 单片机菜鸟哥,一个野生非专业硬件IOT爱好者 ❤️
  • ❤️ 本篇创建记录 2022-10-15 ❤️
  • ❤️ 本篇更新记录 2022-10-15 ❤️
  • ???? 欢迎关注 ????点赞 ????收藏 ⭐️留言????
  • ???? 此博客均由博主单独编写,不存在任何商业团队运营,如发现错误,请留言轰炸哦!及时修正!感谢支持!
  • ???? Arduino ESP8266教程累计帮助过超过1W+同学入门学习硬件网络编程,入选过选修课程,刊登过无线电杂志 ????

1. 前言

使用多了第三方mqtt服务器(阿里云、OneNet、巴法云等等)之后或者自己写的简单nodejs mqtt服务器之后, 又想看看能否有结合两者的优点的开发方式。

一句话,自己部署一个开源mqtt服务器,集成了绝大部分的功能和管理后台。

而一般在学习物联网中,emqx是提及最多的开源免费mqtt服务器,部署简单。
【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx

建议可以看看官方文档。

2. emqx 简介

3. emqx 部署

根据自己的具体操作系统(macOS、Linux、Windows)来下载对应的压缩包。

【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx
【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx
【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx

部署步骤:

4. emqx 运行

要想运行emqx,我们需要先知道有哪些命令行可以用。
【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx
官方关于命令行的详细介绍,我们主要先关注启动命令。
【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx

4.1 管理员权限执行 emqx start

【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx

4.2 浏览器输入 http://localhost:18083/,进入web的控制后台

【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx
输入默认账号密码:

  • 账号 admin
  • 密码 public,博哥登录成功之后改为了123456

【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx
到这里我们就算是成功运行起了emqx mqtt服务器了。

记住,它是一个mqtt broker

4.3 修改为中文界面

【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx
【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx

4.4点一下每个页面看看是些什么具体内容。

【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx

4.4.1 仪表盘,指标监控

主要是看看整个数据怎么样,订阅数消息流入主题连接等等
【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx

4.4.2 连接管理

管理每个连接的一些状态信息,连接以clientid作为一个区分。包括ip地址、心跳等等
【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx

4.4.3 mqtt主题,topic相关

【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx
包括客户端ID(clientid)、主题(topic)、质量等级(QoS)、遗嘱消息保留消息等等

4.4.4 访问控制,控制用户的访问权限

【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx
这里提供了第三方的数据源来做安全校验。比如mysql、redis、http服务器等等。

  • 认证认证只是验证了客户端的身份是否合法,主要看用户是否能登录系统,关联到username和password
    官方文档说明:emqx认证
    【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx
    EMQX 默认没有限制设备登录认证,而我们实际商用的项目中,安全认证,登录鉴权那是必不可少。我们可以直接使用数据库的sql语句来验证或者连接一个HTTPServer来做。

假设我们通过提供的HTTP服务器来做,那么设备登录认证的流程如下:

  • 设备通过MQTT连接到EMQX
  • EMQX将设备登录上来的username和password通过HTTP POST的方式传递给HTTP Server
    【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx
  • 认证结果由HTTP Server的返回状态决定EMQX是否建立/拒绝设备的连接。
  • 授权管理指对 MQTT 客户端的发布和订阅操作进行权限控制,控制的内容主要是哪些客户端可以发布或者订阅哪些 MQTT 主题
    官方文档说明:emqx授权管理
    【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx
  • 黑名单
    官方文档说明:emqx授权管理
    【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx
    【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx

4.4.5 数据集成,对接外部系统

【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx

数据集成是 EMQX 在发布订阅模型的基础之上的数据处理与分发组件,通过简单的、可视化的配置,即可将消息流以及设备事件与 Kafka、RabbitMQ 等消息中间件,以及各类 SQL / NoSQL / 时序数据库等数据系统集成。

EMQX 通过结合规则与数据桥接两个功能,提供了实时、简洁、高效的数据集成方案。 其中规则用于处理消息或事件,而数据桥接用于对接数据系统。

4.4.6 功能配置

  • 监听器(支持了tcpWebSocket连接,注意它们的端口号 8883/1883/8083/8084
    【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx
  • mqtt配置(跟mqtt协议相关内容,包括心跳、连接超时、报文最大大小等等)
    【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx

4.4.7 问题分析,比较有用是日志追踪

【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx

5. 接入esp8266 mqtt客户端测试

  • 先获取本地电脑IP地址,使用ipconfig命令
    【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx

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
【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx
去emqx后台看看。
【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx
【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx
我们构造一个日志追踪,监听几分钟,然后把日志下载下来。
【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx
【鸟哥杂谈】搭建自己的本地mqtt服务器 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

【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx
这时候是正常连接的。然后去后台设置一下黑名单看看。
【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx
【鸟哥杂谈】搭建自己的本地mqtt服务器 emqx

6. 总结

一句话,多看文档多试试,配置起来10分钟即可运行起来。