找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4359|回复: 0
打印 上一主题 下一主题
收起左侧

微信宠物屋 机智云系统

[复制链接]
跳转到指定楼层
楼主
ID:111475 发表于 2016-3-30 23:15 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
第一章:通信协议分析
                                                      ———以微信宠物屋为例

微信宠物屋是机智云提供的一套完整的基础例程,在了解相关通信流程之后,我们可在该程序基础上开发自己的程序,实现与云服务的对接,进而达到远程控制的目的,接下来我们就来仔细分析下机智云的“M2M”机制到底是如何“跑起来的”。
  第一节:文档说明部分详解
第一步:我们打开微信宠物屋程序gokit-mcu-master:看到他的目录结构如下











其中:MDK_Project即是STM32的程序入口,在分析程序之前我们先来看一下《宠物屋产品设备端开发指南》了解一下该程序实现的功能和串口协议的规定是怎样的。
首先:我们来看产品信息,该处定义了相关的数据点(如何建立数据点请访问www.gizwits.com)和宠物屋实现的功能,包括:调节RGB三色灯、电机转速、红外探测等。这些大家了解就行。其中需要大家特别注意的是“设备识别码”这个关键词,可以看到微信宠物屋的识别码是“6f3074fe43894547a4f1314bd7e3ae0b”,机智云对于每一款产品都会生成唯一的识别码以作区分,待会我们将在程序中找到定义识别码的位置。
其次:我们来看产品信息,可以看到流程图上清楚的介绍了整个协议工作的流程,简单分析一下,其实可以分为两部分处理:
第一部分、按键事件发生:主要用于MCU处理按键事件发生后与WIFI的通讯处理。
第二部分、串口事件发生:机智云是通过WIFI模块与MCU以串口通信来实现的,所以下面的这些有关WIFI的事件都可以归类为串口事件的发生,包括:Wifi 发送控制命令、Wifi 发送查询命令、Wifi 发送心跳命令、Wifi 状态更新、外设状态变化。

总体来说,整个系统上电之后的流程如下:
1)MCU 先上电,初始化完成后,给模块上电;
2) 模块初始化;
3) 模块向MCU 询问必要信息,MCU 返回信息(见协议举例);
4) 进入正常工作循环;
a) 模块给MCU 下发控制命令(见协议举例);
b) MCU 返回确认,表示收到命令,正在执行(见协议举例);
c) 执行完新控制命令后,无论状态是否发生变化,MCU 都需要通知模块最新状态(见       协议举例);
d) 若MCU 检测到环境属性变化或者用户在设备上按键引起的状态变化,MCU 需要       通知模块最新状态,但是其发送的频率不能快于2 秒每次(见协议举例);
e) 若环境状态一直不变化,MCU 需要每隔10 分钟定期主动上报当前状态f) 模块会       向MCU 发送心跳,MCU 收到后按照格式返回即可(见协议举例);MCU 连续180 秒       收不到模块的数据,即可认为模块异常,可以给模块重新上电;
最后:我们来了解具体通讯协议的约定,可以看到
命令格式:header(2B)=0xFFFF, len(2B), cmd(1B), sn(1B), flags(2B),DATA(XB),checksum(1B)
说明:
1) 包头(header)固定为0xFFFF;
2) 长度(len)是指从cmd 开始到整个数据包结束所占用的字节数;
3) 命令字(cmd)表示具体的命令含义,详见协议举例;
4) 消息序号(sn)由发送方给出,接收方响应命令时需把消息序号返回给发送方;
5) 标志位(flag),本产品填写默认0;
6) p0 数据区(DATA),详细参见p0 数据区约定;
7) 检验和(checksum)的计算方式为从len~DATA,按字节求和;
8) 所有发送的命令都带有确认,如在200 毫秒内没有收到接收方的响应,发送方;应重       发,最多重发3 次;
9) 多于一个字节的整型数字以大端字节序编码(网络字节序);
10) 数字均用16 进制表示;
相信这一部分大家都能看懂,这里不再叙述,接下来看到“p0 数据区约定”,实现如下功能:
1)模块向MUC 发送控制命令时携带p0 命令和命令标志位以及可写数据区
2)MCU 主动发送状态时或者回复wifi 模块的状态查询时携带p0 命令和完整数据区
3)数据区会自动合并布尔和枚举变量,且有严格的顺序,不可任意改变
怎么来理解这三个功能呢?我们知道在机智云上定义数据点完成后,系统会自动生成对应的“串口通讯协议”如下图所示:
我们下载这份通讯协议文档打开,可以看到具体有如下命令:
1)WiFi模组请求设备信息
2)WiFi模组与设备MCU的心跳
3)设备MCU通知WiFi模组进入配置模式
4) 设备MCU重置WiFi模组
5)WiFi模组向设备MCU通知WiFi模组工作状态的变化
6) WiFi模组请求重启MCU
7)非法消息通知
8)WiFi模组读取设备的当前状态
9)设备MCU向WiFi模组主动上报当前状态
10)WiFi模组控制设备
这些命令中我们只要具体关注8、9、10三条命令即可,我们先来找到第10条命令如下:
4)对应上面“p0 数据区约定”中的功能1来看,模块向MUC 发送控制命令时携带p0 命令、命令标志位、及可写数据区三部分命令,至此大家应该清楚了,前6位代表p0 命令、attr_flags(1B)代表命令标志位、attr_vals(6B)代表可写数据区。这就告诉了我们编写mcu代码时,应该怎么样去识别WIFI发来的控制命令。那具体要怎么识别呢,往下看协议的注解:
1. 是否设置标志位(attr_flags)表示相关的数据值是否为有效值,相关的标志位为1表示值有效,为0表示值无效,
从右到左的标志位依次为:
bit0: 设置LED_OnOff
bit1: 设置LED_Color
bit2: 设置LED_R
bit3: 设置LED_G
bit4: 设置LED_B
bit5: 设置Motor_Speed
这里可以清楚的看到attr_flags占1B字节,其中bit0代表设置LED_OnOff......bit5: 设置Motor_Speed,那么对于我们的mcu接收到WIFI发来的控制命令后,我们通过识别attr_flags的每一位即可对应出需要控制的设备,如果还看不懂,一会我们分析mcu程序。
看完标志位之后我们看attr_vals(6B)  即可写数据区:








5)这里可以清楚的看到,只有相关的设置标志位(attr_flags)为1时,数据值才是有效的,需要特别注意的是“p0 数据区约定”约定第三条,数据区会自动合并布尔和枚举变量,且有严格的顺序,不可任意改变。对应上面的“byte0”合并了“bool”和“enum”类型。
至此p0 数据区约定 到此结束,后面在MCU程序中会对应具体代码讲解。
《宠物屋设备端开发指南》通讯写一部分最后一个包头排重约定
原则:我们的包头是两个连续的FF FF,如果此包中还有某字节出现FF,仅在传输和接收的时候处理,其他环节按正常数据处理;
举例:
1) 某设备上报状态帧:FF FF 00 15 05 03 00 00 04 01 01 02 03 01 00 00 00 32 FF 20 00 03 7D, 除包头外,出现了FF;
2) 在程序内部,作为正常的数据去处理;
3) 当需要传输时,将除包头外的FF后,增加一个55字节,其他不变;
4) 将上述数据处理成:FF FF 00 15 05 03 00 00 04 01 01 02 03 01 00 00 00 32 FF 55 20 00 03 7D,长度不变,校验码不变;
5) 接收方在接收过程中,如果收到字节是FF,及判断第二个字节是否也是FF,如果是FF,表示一个新包,按照新包处理;
6) 如果第二个字节是55,直接丢弃,不算接收长度,继续接收下一个字节;
7) 直到按照长度接收完,或者碰到下一个连续的FF FF;
这部分代码出现在mcu与WIFI 的串口通讯部分,所以我们一会找到mcu的串口接收程序,简而分析,即可清楚什么是包头排重约定。
《宠物屋设备端开发指南》第4部分协议举例,下节配合mcu程序讲解。








第二节:MCU程序详解(STM32)
注意:此节的分析需要读者有一定的STM32开发能力,如果不具备,请先学习STM32。
打开MCU程序,在main.c下我们可以看到这样一段注释:
意思已经很清楚了,大部分的命令代码机智云已经为我们实现了,这也是我在讲解《微信宠物屋-机智云接入串口通信协议文档》命令时说只需要关注8、9、10三条指令的原因了,这三条指令对应在protocol.c下的CmdSendMcuP0和CmdReportModuleStatus这两个函数下,即我们开发自己的程序时只需关注这两个函数即可。
首选来看主函数:


可以看到主函数下载完成了一堆初始化之后,在循环值进行了三个函数,第一个和第三个是串口事件处理,第二个是按键事件处理(对应之前第一节讲的流程图)。
我们先来看串口事件处理函数MessageHandle(),在这之前,我们需要考虑到串口事件发生的前提是串口已经接收到了数据帧,因此我们需要找到串口再那里接收这些命令的,我们找到串口接收函数,在STM32里串口接收是以串口中断出现的,而库函数里所有的中断都是默认在stm32f10x_it.c下的,所以在c文件下我们可找到void USART1_IRQHandler(void),这就是串口1的中断接收函数。这段代码我已经做了详细注释,大家可参考上一节的《宠物屋设备端开发指南》下的命令格式和包头排重约定仔细对照查看:
void USART1_IRQHandler(void)
{  
   uint8_t    vlue;
   short         i;

  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
  {
   USART_ClearITPendingBit(USART1,USART_IT_RXNE);
   vlue = USART_ReceiveData(USART1);
   if(get_one_package ==0) //数据包还没有接收完
      {
         if(cmd_flag1 ==0)   //初始化为0
         {
            if(vlue == 0xff)//接收到第一个0xff
            {   
               uart_Count = 0;                  
               uart_buf[uart_Count]=vlue;    //uart_buf[0]=0xff
                  uart_Count++;   
                  cmd_flag1 = 1;          //第一个0xff收到标志位
            }         
            return ;  //如果没收到返回
         }
         if(cmd_flag2 ==0)
         {
            if(cmd_flag2)                     //cmd_flag2=1
            {
                  uart_buf[uart_Count]=vlue;
                  uart_Count++;
                  if(uart_buf[1] == 0xff)      
                  {
                     cmd_flag2 = 1;     //已经收到了第二个0xFF            
                  }   
                  else
                  {
                     cmd_flag1 = 0;    //两个0XFF接收完清标志位
                  }
            }
            cmd_flag2 = 1;
         }
         uart_buf[uart_Count] = vlue;
         if(uart_Count >=4 && uart_buf[uart_Count] == 0x55 && uart_buf[uart_Count-1] == 0xFF){}  //包头排重
         else uart_Count++;
         if(uart_Count == 0x04)
         {
            cmd_len = uart_buf[2]*256 +  uart_buf[3];                                             
         }
         if(uart_Count ==  (cmd_len + 4))   //接收的数据包是否完整
         {
            get_one_package = 1; //数据包接收完成标志位
            cmd_flag1 = 0;      
         }                                          
看懂串口接收代码后,我们回到主函数,鼠标右键单击MessageHandle()选择gotodifinitionMessageHandle找到该处理函数:
可以看到if(get_one_package)这条语句,只有get_one_package=1的时候下面的程序才会执行,而get_one_package=1就是在串口接收函数里赋值的,表示接收到完整的数据帧。继续往下看到
















   


这个switch语句下的各种命令可以对应在《《微信宠物屋-机智云接入串口通信协议文档》》下的命令列表中找到,前面说过这里面大部分命令机智云已经帮我们实现了,我们只需要关注两个函数即可,这两个函数就在这个switch下面:

其实说的在简单一点:我们只需要关注控制命令这一个函数即可
不信大家可以进入到void       CmdReportModuleStatus(uint8_t *buf) 这个函数下看看都做了哪些工作:

从注释也可以看出这个函数只是描述WIFI状态变化的函数,比如我们连接的是AirLink模式还是softap模式,如果你想区分,就在这段代码下添加状态指示程序即可,我们不做过多讲解,重点用来解释控制命令函数void       CmdSendMcuP0(uint8_t *buf)
大家拿到开发板之后,应该都知道第一步需要按下按键去配置WIFI连接到云端,才能实现远程控制,所以在讲解控制命令函数void       CmdSendMcuP0(uint8_t *buf)之前,我们先来看看通过按键配置开发板的这些程序在哪里,既然是按键配置,那肯定是在按键处理函数里找喽,我们回到主函数下,找到按键处理函数       KeyHandle();         鼠标右键单击 选择 goto        difinition KeyHandle,可以看到




















这里代码已经很清楚了,就不做过多解释,这里需要大家思考的地方是,按键的长按和短按是怎么实现的呢?这里告诉大家,本mcu程序定义了定时器3中断,去判断按键的长按与短按,超过2秒即认为是长按,既然是定时器中断函数,那肯定是在stm32f10x_it.c下面喽,我们找到它,看看它的函数原型void TIM3_IRQHandler(void) :(这部分代码我在原来的基础上做了更多的注解,相信大家都能看懂的)


了解的开发板配置的代码后,我们在回头看控制命令函数void       CmdSendMcuP0(uint8_t *buf),这是最重点的部分啦,我们复制其中的重点代码做详细讲解。






这部分代码大体的工作流程是:如果串口0传来了数据(buf != NULL),先调用memcpy函数将其拷贝到m_w2m_controlMcu 结构体中去,其中结构体成员m_w2m_controlMcu.sub_cmd 是命令标志位,如果为SUB_CMD_REQUIRE_STATUS(0x02)则表示查询命令,当即上报当前的状态到服务器,如果为SUB_CMD_CONTROL_MC(0x01)则表示控制命令,控制部分就是我们需要重点实现的了。既然是控制部分,那肯定要和我们之前讲的《微信宠物屋-机智云接入串口通信协议文档.pdf》中的4.10节《WIFI模块控制设备》相联系起来了,

我们之前讲过这部分 最重要的就是attr_flags(1B) 、attr_vals(6B)这两位;忘记的同学请返回前面看一看。这两位是怎么对应程序的呢?我们来看





      


我们鼠标右键 GOTO 到  m_w2m_controlMcu.cmd_tag 里面,可以看到该结构体内容如下:


现在是不是已经和《微信宠物屋-机智云接入串口通信协议文档.pdf》中的4.10节《WIFI模块控制设备》对应起来了,哈哈,我们接着往下看程序

前面我们已经知道程序里的cmd_tag就对应《微信宠物屋-机智云接入串口通信协议文档.pdf》中的4.10节《WIFI模块控制设备》中的attr_flags(1B),是用来选择控制哪一位的,在文档中我们可以看到attr_flags的第0位是用来选择控制LED灯开关的,即只要设置了第0位为1就表示要控制LED等开关了,如下所示:

对应程序中
if((m_w2m_controlMcu.cmd_tag & 0x01) == 0x01)
即标志第0位为1,接下来就可以控制LED灯的开关了,我们接着程序往下看;


这段程序就控制了LED灯的开关,即cmd_byte的第0位为1表示灯开,为0表示灯关。
这对应《微信宠物屋-机智云接入串口通信协议文档.pdf》中的4.10节《WIFI模块控制设备》中的attr_vals(6B),即设置数据位,如下所示:
可以清楚的看到只要控制byte0(0x07)的第0位就可以控制LED灯了,第一位是用来控制LED颜色的。
这里需要说明的是一般设置数据位的数据包的byte0 是用来控制bool型变量和枚举类型变量的了,应为机智云默认是把bool变量和枚举类型合并处理的。

下面的程序基本和上面一样了,只要大家看懂了《微信宠物屋-机智云接入串口通信协议文档.pdf》中的4.10节《WIFI模块控制设备》中的attr_flags(1B) 、attr_vals(6B)这两位和程序代码中的cmd_tag、status_w的对应关系就能自己编写控制程序了。

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表