ESA2GJK1DH1K基础篇: APP使用SmartConfig绑定Wi-Fi 设备并通过MQTT控制设备(V0.1)

前言

实现功能概要

   STM32控制WI-Fi模块以AT指令TCP透传方式连接MQTT服务器, 实现MQTT通信控制.

  

测试准备工作(详细下载步骤请参考 硬件使用说明 )

一,下载单片机程序

  

  工程目录: STM32F10xTemplateProgect

  hex文件目录: STM32F10xTemplateProgectProgect

    

      

二,安装APP软件

  

  

  

三,调整波动开关位置,STM32和Wi-Fi通信

  

四,

V2.4版本需要短接STM32的PB2和Wi-Fi模块的RST引脚(为了做项目稳定可靠,请使用单片机硬件复位Wi-Fi)

V2.4版本需要短接STM32的PB2和Wi-Fi模块的RST引脚

V2.4版本需要短接STM32的PB2和Wi-Fi模块的RST引脚


  

V2.5.1版本内部默认PB2连接了Wi-Fi模块的RST引脚,不需要短接

V2.5.1版本内部默认PB2连接了Wi-Fi模块的RST引脚,不需要短接

V2.5.1版本内部默认PB2连接了Wi-Fi模块的RST引脚,不需要短接

开始测试

一.打开手机APP,点击右上角菜单 "添加设备" ,手动输入自家路由器密码.(路由器名称为自动获取,不需要用户填写)

             

二.长按PB5大约4S,等待指示灯快闪,松开PB5,Wi-Fi模块进入配网状态

  

三.点击APP的搜索设备按钮,开始搜索设备,搜索成功,将自动跳转到主页面,并显示设备

      

四.单片机控制Wi-Fi连接上MQTT服务器以后,指示灯1S闪耀

  

五.点击设备进入,设备控制页面,页面显示当前温湿度数据,显示当前设备的状态

  

六.远程控制继电器吸合

      

七.远程控制继电器断开

      

八.请自行控制家电(最大支持10A,注意安全!)

关于程序

  整个程序是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

  

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地址很有用(全球唯一),通信的时候可以用来区分设备.

    

MQTT实现部分

  一,前言

    对于初学者而言,如果不了解MQTT,可先看后面的关于MQTT的教程,看会以后

    再来看此部分!

    MQTT处理,采用官方C语言MQTT包+本人二次封装.(方便大家快速的移植使用)

    Wi-Fi模块发布的主题: device/设备MAC  

    Wi-Fi模块订阅的主题: user/设备MAC

    APP通过SmartConfig获取Wi-Fi的MAC,然后设置

    订阅的主题:device/设备MAC  

    发布的主题:user/设备MAC

  二,连接TCP服务器(MQTT服务器)

    AT指令配置模块连接TCP的程序处理模板是:配置AT指令模板(非阻塞版) 

    配置Wi-Fi模块连接TCP服务器是使用的  "AT+SAVETRANSLINK=1,"%s",%s,"TCP" ",IP,Port

    这个指令配置好以后,Wi-Fi模块便是透传模式,而且是自动连接

    (串口接收的数据,自动发给TCP服务器)

    (从TCP服务器接收的数据自动发给串口)

    

    

   三,连接MQTT

    SendConfigFunction(NULL,FunctionParseConnectMqtt,NULL,NULL,FunctionParseConnectMqttAck,0);break;

    打包发送连接MQTT服务器是这个函数 FunctionParseConnectMqtt

      

      

      注:调用MqttConnectMqtt函数以后,最终打包完成后的数据存储在 MqttSendData数组里面

      故:在最后的时候是调用  UsartOutStr(MqttSendData,MainLen);

  四,判断是够连接成功

    FunctionParseConnectMqttAck

    

    具体咱再后面说怎么判断的,这个涉及到官方MQTT库的数据处理方式

   五,订阅主题

    SendConfigFunction(NULL,FunctionParseMqttSubscribe,NULL,NULL,FunctionParseMqttSubscribeAck,CompareValue);break;

    订阅主题看这个函数 FunctionParseMqttSubscribe

      

      

      此函数一次性可以订阅多个主题,列如订阅两个主题

      char SubTopic1[10]="aaaaa";

      char SubTopic2[10]="bbbbb";

      MQTTString MQTTStringSubTopic[2] = MQTTString_initializer;

      int MQTTStringSubTopicQos[2] = {0,1};

      MQTTStringSubTopic[0].cstring = SubTopic1;

      MQTTStringSubTopic[1].cstring = SubTopic2;

      MainLen = MqttSubscribe(MQTTStringSubTopic,MQTTStringSubTopicQos,2,0,1);

      UsartOutStr(MqttSendData,MainLen);

      注:我设置的一次性最多订阅3个主题

      

      

      定义的主题个数大于了此变量,用户需要增大此变量

      实际订阅的主题个数 <= MaxSubTopicCount

  六,发布消息

    6.1,定义发布的主题变量

      MQTTPublishTopicStruct MqttPublishTopicStruct = MQTTPublishTopicStruct_initializer;

      该变量在主函数中定义

      

    6.2,使用该变量

      

      

      打包数据函数  MqttPublish

      

     6.3,定义多个发布的主题变量

      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接收的消息

    

    

     7.1 判断MQTT返回的是什么数据都是调用 MQTTPacket_read函数做判断

      

    7.2注意这个函数填入的第三个参数 (函数)

      

      

    7.3  官方提供的MQTT库,所有的数据判断处理都是利用该函数

      该函数的写法固定

      

      注意:由于模块配置了透传模式,Wi-Fi接收的数据直接通过串口发给了单片机

        单片机接收的数据存在了  Usart1ReadBuff  数组里面

        上面的函数中 才会写  memcpy(buf,&Usart1ReadBuff[MqttAnalyzeStruct.Len],count);

    7.4 

      if(MQTTPacket_read(MqttAnalyzeStruct.buff,MQTTAnalyzeBuffLen, transport_getdata) == XXXXX)

      实际上 MQTTPacket_read函数 就是利用 transport_getdata函数提取数据

      

      然后把提取的数据存在传进来的 buff 里面

      如果想具体提取数据则

      

  八,心跳包

    8.1 实际上 客户端发送的心跳包数据是  C0 00  服务器返回的是 D0 00

    8.2 但是对于没有监听过协议的用户,可调用 MQTTSerialize_pingreq 获取心跳包数据

      

      

APP程序

  APP目录部分说明

    

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