消息队列遥测传输(Message Queuing Telemetry Transport, MQTT)是基于客户端(Client)/服务器(Server)
和发布(Pulishi)/订阅(Subscribe)
范式的消息传输协议. MQTT具有轻量、开放、简单、设计易于实施等特点, 这些特性使其在许多情况非常适用, 包括机器到机器(Machine to Machine, M2M)和物联网(IoT)
等受限环境, 这些环境对代码占用空间要求严格/或网络带宽非常宝贵. MQTT必须运行在提供有序、无损、双向连接的传输协议之上–通常是TCP/IP
.
MQTT协议定义了两种类型的网络实体: 一个消息代理(Broker)、多个客户端(Client).
Broker
是一个服务器程序, 它的角色类似于邮局, 它接收所有从Client发出的消息(message), 然后将消息路由到合适的目的Client.
Client
可以是运行MQTT库并通过网络连接到Broker的任意设备(从微控制器到服务器).
每个Client都可以将消息发布(Publish
)到Broker, 或从Broker订阅(Subscribe
)消息, 因此Client有两种角色: 发布者(Publisher
)/订阅者(Subscriber
).
消息在Broker中按照主题层次结构(Topic)组织. Publisher
在发布消息时指定Topic, Broker
在接收到消息时, 根据Topic将消息发布给订阅了该Topic的Subscriber
.
MQTT Client和Broker通过TCP连接建立通信. 通常, Broker运行在服务器的1883端口上, 监听Client的连接请求.
Connect Command
包登录Broker, Broker收到该包后, 回复Connect Ack
包以确认Client的登陆请求, Client即可进行消息的订阅和发布.Publish Message
包指定发布的消息内容(Message)及主题(Topic), Broker收到该包后不进行回复, 根据消息主题将该消息转发给订阅了该主题的所有Client.Subscribe Request
包指定需要订阅的主题, Broker收到该包后回复Subscribe Ack
包确认订阅请求. 当Broker收到指定该主题的消息时, 会将该消息发布给所有订阅了该主题的Client.Unsubscribe Request
包指定取消订阅的主题, Broker收到该包后回复Unsubscribe Ack
包确认取消订阅.Disconnect Req
包退出登录, 随后进行四次握手断开TCP连接.发布消息
Ver. | Description |
---|---|
First Version | 1999. |
MQTT v3.1.0 | 2013. |
MQTT v3.1.1 | 2014. 广泛使用的版本 |
MQTT v5 | 2019. 最新版本 |
MQTT-SN | MQTT协议的变体, 面向传感器网络和非TCP/IP网络上的嵌入式设备, 如Zigbee |
目标环境: STM32F107 + 4G模块
需求: 本地采集数据并通过4G模块发布到MQTT服务器
开发环境: Keil uVision 5
使用源码: eclipse/paho.mqtt.embedded-c
MQTTPacket
内的全部内容添加到Keil工程中MQTTClient-C
的内容编写移植代码bool transport_sendPacketBuffer(unsigned char *buf, unsigned int buflen)
{
bool rc;
rc = tcp_send(buf, buflen); // 底层发送TCP数据包的函数接口 自定义
return rc;
}
int transport_getdata(unsigned char *buf, unsigned int count)
{
tcp_recv(buf, count); // 底层接收TCP数据包的函数接口 自定义
return 1;
}
bool mqtt_connect(unsigned char *buf, unsigned int buflen)
{
u32 len = 0;
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
data.clientID.csting = "me";
data.keepAliveInterval = 20;
data.cleansession = 1;
data.username.cstring = "testuser";
data.password.cstring = "testpassword";
len = MQTTSerialize_connect(buf, buflen, &data);
if(!transport_sendPacketBuffer(buf, len))
{
return 0;
}
return 1;
}
bool mqtt_publish(unsigned char *buf, unsigned int buflen, char *topicName, MQTTMessage *message)
{
u32 len = 0;
MQTTString topicString = MQTTString_initializer;
topicString.cstring = topicName;
len = MQTTSerialize_publish(buf, buf_size, 0, message->qos, message->retained, message->id, topicName, (unsigned char*)message->payload, message->payloadlen);
if(!transport_sendPacketBuffer(buf, len))
{
return 0;
}
return 1;
}
MQTTPacket.h
.eclipse/paho.mqtt.embedded-c/MQTTClient-C
里的内容.服务器: Ubuntu Server 20.04 LTS 64bit
Broker: Eclipse Mosquitto
Client: mosquitto_pub/mosquitto_sub , MQTTX
sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa
sudo apt-get update
sudo apt-get install mosquitto
vim /etc/mosquitto/mosquitto.conf
listener 1883
allow_anonymous true
mosquitto -c /etc/mosquitto/mosquitto.conf -d
-c
指定配置文件-d
在后台运行mosquittosudo apt-get install mosquitto-clients
mosquitto_pub -h hostname -p port-number -u username -P password -t message-topic -i client-id -m message
mosquitto_pub -h localhost -p 1883 -u testUser -P testPass -t "temperature/roof" -i "Client_B" -m "22"
mosquitto_sub -h hostname -p port-number -u username -P password -t message-topic -i client-id
mosquitto_sub -h localhost -p 1883 -u testUser -P testPass -t "temperature/roof" -i "Client_B"
MQTT: The Standard for IoT Messaging
Beginners Guide To The MQTT Protocol
Eclipse Mosquitto
Ian Craggs (IBM). Towards The Next Version of MQTT[EB/OL]. (2016)
川水易逝. MQTT 单片机移植 收发功能 STM32 串口 透传[EB/OL]. (2020-03-26)
AIoT-韶华分明. STM32玩转物联网实战篇:4.Mqtt通信详解(从通信原理到报文组包再到通信实战)[EB/OL]. (2022-04-15)
Mask_T. 基于STM32实现MQTT[EB/OL]. (2018-06-21)
kaiser丶H. MQTT协议在STM32上的移植[EB/OL]. (2019-12-27)
Aston_黄. MQTT通讯协议分析(一): connect连接数据包[EB/OL]. (2019-06-09)
kaiser丶H. MQTT协议在STM32上的移植[EB/OL]. (2019-12-27)
Aston_黄. MQTT通讯协议分析(一): connect连接数据包[EB/OL]. (2019-06-09)
slimmm. [linux] Ubuntu20.04上安装搭建MQTT服务器mosquitto[EB/OL]. (2020-10-12)