ESA2GJK1DH1K基础篇: APP使用SmartConfig绑定Wi-Fi 设备并通过MQTT控制设备-单片机源码说明
前言
注:
本程序发送心跳包,发送温湿度,返回控制数据这三个发送是单独的,有可能凑到一起发.
由于本身程序就是复杂性的程序,所以这节程序没有使用中断发送,没有使用环形队列发送,为了避免多条消息可能凑到一起发
如果嫌弃这个延时请自行优化,或者采用自己的方式解决,谢谢支持!
抱歉哈!我首先期望的是大部分人都先要看懂程序,至于其他优化我会提供个思路和源码,大家可以根据自己的情况自行优化.
用户须知
整个程序是STM32使用AT指令控制Wi-Fi模块实现SmartConfig配网和MQTT通信控制
程序的整体结构: https://www.cnblogs.com/yangfengwu/p/11669323.html
程序的按键处理: https://www.cnblogs.com/yangfengwu/p/11669354.html
串口接收数据 : https://www.cnblogs.com/yangfengwu/p/11669373.html
配置AT指令模板(阻塞版): https://www.cnblogs.com/yangfengwu/p/11673439.html
配置AT指令模板(非阻塞版): https://www.cnblogs.com/yangfengwu/p/11674814.html
打开这节源码
修改连接自己的服务器
一,如果想连接自己的MQTT服务器,可以直接更改
SmartConfig配网
一,主循环
二,AT指令配置模块启动SmartConfig的程序处理模板是:配置AT指令模板(阻塞版)
三,按键按下3S以后 变量 SmartConfigFlage = 1;
定时器里面开始控制 指示灯100Ms闪耀
四,AT指令控制Wi-Fi模块执行SmartConfig 配网程序部分
五,SmartConfig执行流程-连接路由器
实际上启用SmartConfig指令是 AT+CWSTARTSMART=3
最后的参数 1-SmartConfig配网 2-微信Airkiss配网 3-SmartConfig配网+微信Airkiss配网
下面进入了 while(1) 循环 我设置的30S超时
实际上此时Wi-Fi模块正在监听APP在空气中发出的无线信号
下图只要执行了搜索设备,APP就在不停的发出无线信号
Wi-Fi模块接收到APP发出的路由器信息以后,就会根据信息去连接路由器
Wi-Fi模块连接上了路由器以后便会返回 WIFI CONNECTED 和 WIFI GOT IP
注:只要配网一次,以后Wi-Fi模块便会自动连接此路由器,不需要重复配网!
六,SmartConfig执行流程-等待路由器把自己的MAC信息返回给APP
为了让APP确定Wi-Fi模块确实连接上了路由器,Wi-Fi连接上路由器以后
需要返回给APP自己的MAC地址和自己连接路由器后分得的IP地址
所以延时了5S时间,让Wi-Fi模块把信息发给APP
下图中,显示的就是所配网的Wi-Fi模块的MAC地址信息
当然MAC地址很有用(全球唯一),通信的时候可以用来区分设备.
控制Wi-Fi模块连接TCP服务器
配置Wi-Fi模块连接TCP服务器是使用的 "AT+SAVETRANSLINK=1,"%s",%s,"TCP" ",IP,Port
这个指令配置好以后,Wi-Fi模块便是透传模式,而且是自动连接
(串口接收的数据,自动发给TCP服务器)
(从TCP服务器接收的数据自动发给串口)
MQTT服务器规定ClientID必须每个设备不能一样,Wi-Fi模块的MAC作为了ClientID
获取ClientID部分
ClientID 最终存储在了 MQTTid数组里面
发送连接MQTT协议
判断连接状态
官方库里面判断返回的数据都是使用
MQTTPacket_read(数据解析完存到的数组,数组长度,提取数据函数)
最主要的是这个 提取数据函数
transport_getdata
这个函数的格式不能变,官方规定的就是这个格式
因为我的模块是串口透传模式,所以MQTT服务器返回的数据都返回到了串口数组里面
Usart1ReadBuff
假设我现在判断接收的数据类型,(MQTT协议里面第一个返回的数据就能判断出来数据类型)
MqttAnalyzeStruct.Len=0;
transport_getdata(buff,1);
这样执行以后 我就把第一个数据 拷贝到了 buff里面
然后我只需要判断buff数组第一个数据就可以了
其实官方就是这样做的
提取其它数据
接着看订阅
此函数一次性可以订阅多个主题,列如订阅两个主题
char SubTopic1[10]="aaaaa";
char SubTopic2[10]="bbbbb";
MQTTString MQTTStringSubTopic[2] = MQTTString_initializer;
int MQTTStringSubTopicQos[2] = {0,1};//第一个主题的消息等级0,第二个消息等级1
MQTTStringSubTopic[0].cstring = SubTopic1;
MQTTStringSubTopic[1].cstring = SubTopic2;
MainLen = MqttSubscribe(MQTTStringSubTopic,MQTTStringSubTopicQos,2,0,1);
UsartOutStr(MqttSendData,MainLen);
注:我设置的一次性最多订阅3个主题
定义的主题个数大于了此变量,用户需要增大此变量
实际订阅的主题个数 <= MaxSubTopicCount
判断订阅是否成功
发送一条上线消息
一,定义发布的主题变量
MQTTPublishTopicStruct MqttPublishTopicStruct = MQTTPublishTopicStruct_initializer;
该变量在主函数中定义
二, 使用该变量
打包数据函数 MqttPublish
三,,定义多个发布的主题变量
char Publish1[10]="qqqqq";//发布的主题
char Publish1Msg[8]="11223344";//发布的主题,携带的消息
char Publish2[10]="wwww";//发布的主题
char Publish2Msg[6]="000000";//发布的主题,携带的消息
MQTTPublishTopicStruct MqttPublishTopicStruct1 = MQTTPublishTopicStruct_initializer;
MQTTPublishTopicStruct MqttPublishTopicStruct2 = MQTTPublishTopicStruct_initializer;
MqttPublishTopicStruct1.topicName.cstring = Publish1;// 发布的主题
MainLen = MqttPublish(MqttPublishTopicStruct1,Publish1Msg,8);
UsartOutStr(MqttSendData,MainLen);//发送消息
MqttPublishTopicStruct1.topicName.cstring = Publish2;// 发布的主题
MainLen = MqttPublish(MqttPublishTopicStruct2,Publish2Msg,6);
UsartOutStr(MqttSendData,MainLen);//发送消息
连接好MQTT,订阅完主题,然后就是处理MQTT数据
三,每隔一段时间采集发送温湿度数据
看下我的心跳包处理
说下我的处理思路
首先,如果到了发送心跳包的时间了,就发送一次心跳包
然后启动超时,超过3S如果服务器没有回复心跳应答
我就再发送一次,然后启动超时,如果超过3S还是没有收到心跳返回
重新配置模块