出于项目需要,开始研究MQTT通讯
本以为挺简单一玩意,但,实际上手,那BUG和问题是接踵而至,很搞心态!!!
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的”轻量级”通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。(来自菜鸟教程)
MQTT主要特性
- 使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合。这一点很类似于XMPP1,但是MQTT的信息冗余远小于XMPP,,因为XMPP使用XML格式文本来传递数据。
- 对负载内容屏蔽的消息传输。
- 使用TCP/IP提供网络连接。主流的MQTT是基于TCP连接进行数据推送的,但是同样有基于UDP的版本,叫做MQTT-SN。这两种版本由于基于不同的连接方式,优缺点自然也就各有不同了。
- 有三种消息发布服务质量:
- “至多一次”,消息发布完全依赖底层TCP/IP网络。会发生消息丢失或重复。这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。这一种方式主要普通APP的推送,倘若你的智能设备在消息推送时未联网,推送过去没收到,再次联网也就收不到了。
- “至少一次”,确保消息到达,但消息重复可能会发生。
- “只有一次”,确保消息到达一次。在一些要求比较严格的计费系统中,可以使用此级别。在计费系统中,消息重复或丢失会导致不正确的结果。这种最高质量的消息发布服务还可以用于即时通讯类的APP的推送,确保用户收到且只会收到一次。
- 小型传输,开销很小(固定长度的头部是2字节),协议交换最小化,以降低网络流量。
- 这就是为什么在介绍里说它非常适合”在物联网领域,传感器与服务器的通信,信息的收集”,要知道嵌入式设备的运算能力和带宽都相对薄弱,使用这种协议来传递消息再适合不过了。
- 使用Last Will和Testament特性通知有关各方客户端异常中断的机制。
- Last Will:即遗言机制,用于通知同一主题下的其他设备发送遗言的设备已经断开了连接。
- Testament:遗嘱机制,功能类似于Last Will。
第一部:搭建MQTT本地服务
此处使用行空板(UNIHIKER)搭建,采用DFROBOT提供的SIOT V2物联网平台搭建(基于本地的建立,不需要外部网站的辅助,开心)
接下来,就可以开始相关调试工作了!!!
新技术NODE-RED
鄙人第一次接触到NODE-RED
这款NODE终端工具。
Node-RED is a flow-based programming tool, originally developed by IBM’s Emerging Technology Services team and now a part of the OpenJS Foundation.[Node-RED 是一种基于流的编程工具,最初由 IBM 的 Emerging Technology Services 团队开发,现在是 OpenJS Foundation 的一部分。]
启动样式,接下来,会提供一个本地化部署的IP地址,上图中为[http://127.0.0.1:1880]
,接下来,就可以直接按住链接(CTRL),跳转到浏览器进行编程了!
大致就这个样子!
你还需要装一些好用的插件
在节点管理中找到该界面,需要安装node-red-dashboard这个插件,之后,左侧Slide中会有更多的选项卡,方便更快捷的UI操作!!!
你可以访问[http://127.0.0.1:1880/ui]
直接访问面板!
ARDUINO端[ESP8266]
为了开发板扩展,真的是煞费苦心,但突然想到自己有ESP主板扩展安装包(一个ESE可执行文件,方便了许多)。
此处提供下载链接,使用时先关闭ARDUINO IDE,运行安装包,等进度条走完,安装就完成了,之后打开IDE ,所有主板都会预装好。
链接:https://share.weiyun.com/jMqM9foz 密码:L001NG
在10086次调试后,终于,成功了!!!
NODE-RED与服务器成功接收到ESP8266数据!
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Ticker.h>
// 设置wifi接入信息(请根据您的WiFi信息进行修改)
const char* ssid = "***********";
const char* password = "***********";
const char* mqttServer = "***********";//MQTT本地地址(IPv4)
// MQTT服务端连接用户名密码
const char* mqttUserName = "***********";
const char* mqttPassword = "***********";
Ticker ticker;
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);
int count; // Ticker计数用变量
void setup() {
Serial.begin(9600);
// Ticker定时对象
ticker.attach(1, tickerCount);
//设置ESP8266工作模式为无线终端模式
WiFi.mode(WIFI_STA);
// 连接WiFi
connectWifi();
// 设置MQTT服务器和端口号
mqttClient.setServer(mqttServer, 1883);
// 连接MQTT服务器
connectMQTTServer();
}
void loop() {
// 如果开发板未能成功连接服务器,则尝试连接服务器
if (!mqttClient.connected()) {
connectMQTTServer();
}
mqttClient.loop();
// 每隔3秒钟发布一次信息
if (count >= 3){
pubMQTTmsg();
count = 0;
}
}
void tickerCount(){
count++;
}
void connectMQTTServer(){
// 根据ESP8266的MAC地址生成客户端ID(避免与其它ESP8266的客户端ID重名)
String clientId = "soit";
// 连接MQTT服务器。此处使用了程序首部定义的用户名和密码来实现MQTT服务端认证
if (mqttClient.connect(clientId.c_str(), mqttUserName, mqttPassword)) {
Serial.println("MQTT Server Connected.");
Serial.print("Server Address: ");
Serial.println(mqttServer);
Serial.print("ClientId: ");
Serial.println(clientId);
} else {
Serial.print("MQTT Server Connect Failed. Client State:");
Serial.println(mqttClient.state());
delay(500);
}
}
// 发布信息
void pubMQTTmsg(){
static int value;
// 确保不同用户进行MQTT信息发布时,ESP8266客户端名称各不相同,
String topicString = "***********";//siot主题
char publishTopic[topicString.length() + 1];
strcpy(publishTopic, topicString.c_str());
// 建立发布信息。信息内容以Hello World为起始,后面添加发布次数。
String messageString = "Hello World " + String(value++);
char publishMsg[messageString.length() + 1];
strcpy(publishMsg, messageString.c_str());
// 实现ESP8266向主题发布信息
if(mqttClient.publish(publishTopic, publishMsg)){
Serial.println("Publish Topic:");Serial.println(publishTopic);
Serial.println("Publish message:");Serial.println(publishMsg);
} else {
Serial.println("Message Publish Failed.");
}
}
// ESP8266连接wifi
void connectWifi(){
WiFi.begin(ssid, password);
//等待WiFi连接,成功连接后输出成功信息
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi Connected!");
Serial.println("");
}
- 可扩展的消息与空间协议(Extensible Messaging and Presence Protocol)
该协议的前身是Jabber,我们采取XMPP协议主来实现IM主要是考虑XMPP协议是以XML为基础的,它继承了在XML环境中灵活的发展性。这表明XMPP是可扩展的,所以XMPP信息不仅可以是简单的文本,而且可以携带复杂的数据和各种格式的文件,也就是说XMPP协议不仅可以用在人与人之间的交流,而且可以实现软件与软件或软件与人之间的交流,目前支持XMPP协议的即时通讯工具有Gtalk、FaceBook IM、Twitter、网易POPO等等通讯工具。 ↩︎
发现评论条评论