微信硬件平台使用蓝牙作为近场控制的连接件,并拟定了《微信蓝牙外设协议》。这份协议更像一个标准,用于规范微信和蓝牙外设之间的数据交互场景和接口。但从开发者来看,要完全读懂这份协议,恐怕需要熟读很多遍,并且要结合调试才能真正实现微信Airsync通信。笔者对IOT和微信硬件平台的整个框架和技术都比较熟悉了,并且已经在TI的CC254X和Dialog的DA14580上实现了微信Airsync协议通信。现在回过头来,从开发的角度,对微信Airsync协议进行重新解读,以帮助新进入物联网领域的开发者更快地掌握微信蓝牙设备通信开发,以让产品快速接入微信硬件平台。
有关微信硬件平台和物联网的架构分析请参考笔者之前的博文,特别是《一张图读懂基于微信硬件平台的物联网架构》和《基于微信硬件公众平台的智能控制开发流程》。
一、微信蓝牙物联的技术需求
软件和协议都是需求驱动的。在物联网、移动互联网领域,理解场景是提炼需求的重要方法。那么,我们从场景分析的角度来理解微信硬件平台的蓝牙物联需求。
1. 微信蓝牙物联是一种近场控制场景
微信硬件平台支持蓝牙和Wifi/3G/GPRS接入。Wifi/3G/GPRS是一种远场控制手段,只要网络可达,那么用户可以在远场(例如办公场所)控制离用户距离很远(例如家里)的物联设备。而蓝牙接入则是一种近场控制手段,用户只能利用微信通过手机的蓝牙来控制20米左右的蓝牙设备。也即是,当蓝牙设备离开手机蓝牙的连接范围,那么用户是控制不了该设备的。
对于蓝牙外设来说,手机就像一个蓝牙网关一样,手机通过蓝牙来跟蓝牙外设进行通信,将得到的数据通过手机的wifi或者3G/4G信号与云后端(微信公众平台、第三方云服务端)交互。前者是基于微信Airsync协议,后者则是微信制定的基于TCP/IP协议的《设备接入接口协议》。
2. 蓝牙外设身份注册
微信硬件平台只提供两部分核心的物联功能,一是身份管理,二是消息推送。任何一个外设,不管是蓝牙还是wifi,它都将拥有一个唯一的设备ID。设备ID的相关描述请参考《一张图读懂基于微信硬件平台的物联网架构》,其包括设备类型(设备厂商的公众号ID)和该设备厂商自行定义的设备ID。这种设计手段和蓝牙MAC地址、网卡MAC地址的设置是一样的。设备ID就是外设的身份。
在外设向微信硬件平台注册身份前,微信硬件平台是不认识这个外设的。所以,我们在使用蓝牙外设前,需要向微信硬件平台注册身份。
对于微信硬件平台而言,设备注册其实就是平台对这个设备进行授权(加入)的过程。接口如下图。其主要通过提交自身的唯一MAC、设备ID来向平台注册。
3. 蓝牙广播
对于蓝牙设备来说,它主要的状态包括未连接和已连接两种状态。在未连接时,它需要进行广播。广播的目的是为了让手机微信能够通过蓝牙扫描得知这是一个支持蓝牙Airsync协议的设备。当手机微信识别到是一个支持该协议的外设时,手机微信会发起连接。
那么,广播数据需要包含什么格式的数据才能被手机微信所识别到呢?这就是蓝牙Airsync协议规定的内容。
4. 蓝牙通信
蓝牙连接之后,自然是数据通信的需求。对蓝牙BLE来说,数据通信都是通过访问某个characteristics来实现的。而characteristics需要支持以下场景:
1)手机微信对外设进行写控制,要求characteristics的write属性。
2)手机微信读取外设的一些信息。当外设和厂商自己研制的APP连上之后,外设处于连接状态,其不会再发出广播信息,此时微信想去连接这个外设怎么办?其是通过读取外设的信息,如MAC,来判断该外设是否支持微信。这要求characteristics的read属性。
以上两种都是手机微信作为主动方,外设是被动。接下来,我们来看看外设是主动时的场景:
3)例如,运动手环需要主动上报用户某个时段的运动步数。在这种情况下,手机微信主动读取运动步数显然是不合适的,因为手机不应该时时刻刻地读这个步数来更新。而应该是手机微信订阅characteristics的信息更新服务,即作为被动方接受外设的信息更新。
对于蓝牙外设来说,characteristics的信息更新有两种,一种是notify,一种是indicate。他们有什么区别呢?对于notify,当蓝牙外设的characteristics的值有变化时,它会主动将新的值告知手机微信,而手机微信收到这个信息更新时不需要回复。而对于indicate属性,手机微信在收到这个信息时需要给蓝牙外设一个简单的回复。
蓝牙BLE通信的characteristics的长度是有限制的,或者说每一帧数据长度是有限的,是20字节。那么,如果蓝牙外设有一串很长的数据要主动传送,很明显,它需要indicate属性才能完成这个任务,即将这段数据按20字节长度进行分帧,每次更新发送之后,需要等手机微信回复之后才能发下一个20字节,直到发完为止。
二、蓝牙微信Airsync协议开发
根据以上对蓝牙微信物联的技术需求分析,再根据蓝牙BLE的应用开发知识,我们来梳理蓝牙微信Airsync协议的开发要点。
1. 广播
蓝牙外设广播的目的是让手机微信能够识别到。微信Airsync协议是这样规定蓝牙外设广播数据格式的:
1) 声明自己的ServiceUUID是0xFEE7。
2) 在自定义厂商数据manufature specific data中需以MAC地址(身份注册时的MAC地址,也是该设备真实的MAC地址)结尾,并且要求manufature specific data的长度大于等于8.
蓝牙的广播数据格式定义请参考《Blutoothspecification 4.0》的P1735页,对应以下两个类型:
另外,微信Airsync协议提到广播设备分为两种,一种是普通设备,没有按钮,需要无时无刻地广播数据;另一种是确认设备,即有按钮,即用户按下按钮后才开始广播数据。事实上,现实生活中为了省功耗,不可能时时刻刻都在广播的,都是在用户拿手机过来后,再按下外设按钮之后才开始广播并连接的。但是微信把这种方式称为确认设备会造成困惑啊,又没解释清楚,以为广播之后还要确认什么的。这里明确解释这一点。
对于确认按钮之后的广播数据需要注意的是,在自定义厂商数据manufature specific data中需以0xfe 0x01 0x01 +MAC地址结尾。
2. 蓝牙通信服务
外设要实现以下特征,并根据具体芯片平台的接口实现各特征字的读写回调过程,以实现具体的应用需求。
即写characteristics的UUID是0xfec7, indicate characteristics的UUID是0xfec8. 这两个是必须的。而read characteristics UUID不支持也没有问题。
3. 蓝牙Airsync协议交互
满足以上两个条件代表已经能够跟手机微信进行数据通信了。但是交互过程是一个协作的过程,就像我们访问业务系统一样也要先登陆,再初始化后,才能进行正常的业务通信啊。那么登陆和初始化我们可以理解为应用控制信令,而后续的数据通信也是应用数据通信。
蓝牙Airsync协议使用protobuf技术进行封包和解包,详见《Protocolbuffer序列化及其在微信蓝牙协议中的应用》。
1) 登陆
登陆时的数据参数格式是:
微信支持两种登陆身份认证,加密和不加密。这里只讨论简单的不加密认证好了。不加密时,我们一般用MAC地址方式登陆,即将AeSine付空值,AuthMethod赋值为EAM_macNoEncrypt.
Author会收到手机微信的回复,在加密时收到的是一个用于之后通信的秘钥,但在不加密是可以忽略。
2) 初始化
初始化的目的是外设生成一个随机数,以后每次通信后,该数值都会自动加1;另外,在初始化的回复中,手机微信可以告诉外设手机微信当前的用的手机操作系统的版本、当前时间、微信用户ID等等。以便于外设记录用户的信息。
初始化的数据参数格式是:
初始化成功之后就可以正常通信了。
微信提供一个叫做airsyncDebug的工具用于调试,如果能正常与它连接通信,那就代表着可以跟微信进行正常通信了。
三、蓝牙Airsync协议学习开发步骤
1. 初步理解微信规范《蓝牙外设协议》。
2. 理解本文
3. 根据本文的分析理解微信官方实现的基于NRF81522平台的外设例程。
4. 在自己的蓝牙单芯片平台开发实现Airsync协议,并结合airsyncDebug进行调试。
你将会事半功倍!祝好运!