项目来源韦东山老师项目:百问网嵌入式专家-韦东山嵌入式专注于嵌入式课程及硬件研发 (100ask.net)
MQTT源码来自kawaii-mqt :https://github.com/jiejieTop/mqttclient
1. MQTT协议
MQTT协议全称是MessageQueuingTelemetryTransport,翻译过来就是消息队列遥测传输协议,它是物联网常用的应用层协议,运行在TCP/IP中的应用层中,依赖TCP协议,因此它具有非常高的可靠性,同时它是基于TCP协议的<客户端-服务器>模型发布/订阅主题消息的轻量级协议,也是我们常说的发送与接收数据。
1.1 MQTT通讯模型
MQTT协议提供一对多的消息发布,可以降低应用程序的耦合性,用户只需要编写极少量的应用代码就能完成一对多的消息发布与订阅,该协议是基于<客户端-服务器>模型,在协议中主要有三种身份:发布者(Publisher)、服务器(Broker)以及订阅者(Subscriber)。其中,MQTT消息的发布者和订阅者都是客户端,服务器只是作为一个中转的存在,将发布者发布的消息进行转发给所有订阅该主题的订阅者;发布者可以发布在其权限之内的所有主题,并且消息发布者可以同时是订阅者,实现了生产者与消费者的脱耦,发布的消息可以同时被多个订阅者订阅。
2. 项目简介
该项目主要使用STM32开发板基于MQTT实现一个智能家居系统,由于STM32开发板资源的限制,没有网卡等资源,故使用ESP8266无线模块实现无线网连接。
在该项目中主要有三个角色:发布者、服务器、订阅者。
开发板既可以是发布者,也可以是订阅者:
- 开发板充当发布者时,可发布主题消息给其他设备
- 开发板充当订阅者时,可订阅其他设备发来的主题消息
为什么使用MQTT、引入服务器?
网络通信中通过IP、端口表示自己、对方。但是公网IP有限;
为了解决公网IP不够,引用局域网,在公司或者家里只有路由器才有公网IP,电脑之内都是用局域网IP,局域网中的电脑想访问物联网公网,由路由器代理;
如果只是实现局域网内使用手机控制开发上的设备,只需要开发板和手机就可以,因为同一局域网内两个设备可以通过路由器相互访问;
但是如果想实现在任何地方都可以控制开发板,则需引入服务器;手机控制开发板或者开发板想发送信息给手机,由服务器代理;
项目实现过程
- 使用串口实现开发板和ESP8266无线模块通信;
- 实现ESP8266模块的AT命令和解析
- 实现网络传输层,网络连接,读、写、关闭;
- 通过MQTT实现客服端与服务器的通信;
- 搭建mosquito服务器,实现管理客户端连接并路由消息;
- 通过MQTTX工具验证系统
3. 串口驱动
通过串口实现开发板与ESP8266通信,使开发板具有无线网功能;
- 使用Cube MX配置串口初始化
- 使用环形缓冲区保存、管理数据
- 串口写: 直接将数据写入串口DR寄存器,然后,USART硬件会自动将数据从DR寄存器移出,并通过串行线路发送给ESP8266;
- 串口读:读取环形缓冲区中数据,若没有数据就上锁,等串口中断开锁;
环形缓冲区中数据来自于串口中断处理函数保存的,当USART3接收到数据时,串口接收中断被使能(通过USART_CR1_RXNEIE位),则会产生一个接收中断(RXNE标志位被置位)。接着中断处理函数将DR寄存器中数据保存进环形缓冲区
实现环形缓冲区
#define BUFFER_SIZE 1024 /* 环形缓冲区的大小 */
typedef struct
{
unsigned char buffer[BUFFER_SIZE]; /* 缓冲区空间 */
volatile unsigned int pW; /* 写地址 */
volatile unsigned int pR; /* 读地址 */
} ring_buffer;
环形缓冲区中最重要两个状态:缓冲区满、缓冲区空
缓冲区满:写指针的下一个位置等于读指针的位置。
缓冲区空:读指针等于写指针的位置。
当缓冲区非满时可以写缓冲区,将char c写入ring_buffer *dst_buf中
当缓冲区非空时可以读缓