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还是没有收到心跳返回

重新配置模块

原文地址:https://www.cnblogs.com/yangfengwu/p/11768916.html