出于项目需要,开始研究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(""); 
}

  1. 可扩展的消息与空间协议(Extensible Messaging and Presence Protocol)
    该协议的前身是Jabber,我们采取XMPP协议主来实现IM主要是考虑XMPP协议是以XML为基础的,它继承了在XML环境中灵活的发展性。这表明XMPP是可扩展的,所以XMPP信息不仅可以是简单的文本,而且可以携带复杂的数据和各种格式的文件,也就是说XMPP协议不仅可以用在人与人之间的交流,而且可以实现软件与软件或软件与人之间的交流,目前支持XMPP协议的即时通讯工具有Gtalk、FaceBook IM、Twitter、网易POPO等等通讯工具。 ↩︎
© 版权声明
分享是一种美德,转载请保留原链接