微信蓝牙外设开发记录 - 2 (微信小程序与微信蓝牙BEL设备通讯)

1. 前言

    上一篇文章了关于微信蓝牙外设的广播数据格式解析,这篇文章将记录与微信蓝牙外设通讯,并且通过微信蓝牙外设协议中的数据透传通道,如何与单片机端自定义通讯。由于项目用到了安卓和微信小程序(Java Script)两个平台,本篇文章将记录微信小程序调试过程。

 

2. 微信蓝牙外设通讯流程

2.1 根据《微信蓝牙外设协议1.0.4》 中提到,蓝牙 BLE 模拟成流

蓝牙设备需暴露两个特征值(Characteristics):Write 特征值,Indication 特征值。蓝牙 设备从 Write 特征值接受数据,从Indication 特征值发送数据。 Indication 特征值类型是 bytes。 这里我们约定,把一个特征值一次传输的数据,称为一帧(不同类型的特征值一次传输的数 据长度是不一样的)

上面的意思是,对于上层也就是(微信小程序)来说,需要向设备发送数据,则通Write 特征,中写入数据,即可以传输到蓝牙设备中,而蓝牙设备返回数据到上层,则是通过Indication 特征,而不是Notify 特征。

并且还提到,通讯中,使用二进制流的形式通讯,而不是文本。

 

 2.2 蓝牙设备写过程

分帧:假设蓝牙手环上有 1k 数据,要发给手机微信。由于一个特征值长度有限(如 20 个字节),显然需要分多次才能传输完成。1k 数据,要分成 1024 字节/ 20 字节 =51 个帧。剩下的 4 个字节,不足一帧(20 个字节),需补齐为一帧并对剩下的

16 个字节赋 0。总共是 52 帧。

这的意思是,对于大部分的蓝牙BLE 设备(不管是微信蓝牙BLE外设还是普通BLE 蓝牙外设),一般一次性最多传输20 byte,

对于超过20个字节的数据,需要多次传输。

 

2.3 蓝牙外设与上层通讯协议 -- 蓝牙Airsync协议交互

交互过程是一个协作的过程,就像我们访问业务系统一样也要先登陆,再初始化后,才能进行正常的业务通信啊。那么登陆和初始化我们可以理解为应用控制信令,而后续的数据通信也是应用数据通信。

蓝牙Airsync协议使用protobuf技术进行封包和解包,详见《 Protocolbuffer序列化及其在微信蓝牙协议中的应用》。

根据《微信蓝牙外设协议1.0.4》提到,通讯包结构由两部分组成,定长包头 + 定长包体

其中,定长包头格式

定长包头
struct BpFixHead
{
unsigned char bMagicNumber;
unsigned char bVer;
unsigned short nLength;
unsigned short nCmdId;
unsigned short nSeq;
};

变长包体是使用谷歌的Protoalbuf 打包的二进制数据。

 

2.4 通讯流程

2.4.1 会话约定

a. 设备连上微信之后,需要发送 AuthReq,等收到成功的回包之后,接着还要发送 InitReq,并收到成功的回包之后,才能正常发送数据。如果设备没有 auth,手机 对设备的所有请求都返回错误码 EEC_needAuth。

b. 当出现解包异常的时候,直接断开连接。

c. Push 类的包 seq 永远为 0。Req 类和 Resp 类的包的 seq 永不为 0。

d. 服务器可随时发送 Push 包。

e. 厂商服务器发送的 Push 包(注意 Push 包是没有回包的,即没有 PushResp),如果需要设备的回包,需要由厂商自己实现。

具体方法如:厂商发送 RecvDataPush 给设备,设备收到 push 后,向厂商服务器 发送一个 SendDataRequest。这时厂商服务器可知道设备收到了 push,并且可以 从 Req 里取得设备的回应数据。

 

上述流程就是如下图所示:       

 

 

会话流程如下:

 

3. 通讯指令

3.1 命令列表

名称

描叙

 

Auth

 

登录

 

Init

 

初始化

 

SendData

 

设备发送数据给厂商或微信公众平台或微信客户端。

当 type 为空或者等于 0 时,表示发送给厂商服务器。

当 type 为 10001 时,表示发送给微信客户端 html5 设备会话

界面。

当 type 为其他时,表示发送给公众平台服务器。具体的定义

请看 附录:微信公众平台 proto 文件。举个例子,type 等于

1 时,表示手环数据。

 

RecvDataPush

 

厂商或微信客户端或微信公众平台发送数据给设备

当 type 为空或者等于 0 时,表示厂商发送设备。

当 type 为 10001 时,表示收到微信客户端 html5 设备会话界

面的数据。

当 type 为其他时,表示公众平台发送给设备。具体的定义请

看 附录:微信公众平台 proto 文件。举个例子,type 等于 1

时,表示手环数据。

 

 

3.2 AuthRequest 登录指令  (摘自 《以蓝牙开发的视觉解读微信Airsync协议》)

微信支持两种登陆身份认证,加密和不加密。这里只讨论简单的不加密认证好了。不加密时,我们一般用MAC地址方式登陆,即将AeSine付空值,AuthMethod赋值为EAM_macNoEncrypt.

Author会收到手机微信的回复,在加密时收到的是一个用于之后通信的秘钥,但在不加密是可以忽略。

 

3.3 InitRequest 初始化通讯指令(摘自 《以蓝牙开发的视觉解读微信Airsync协议》)

初始化的目的是外设生成一个随机数,以后每次通信后,该数值都会自动加1;另外,在初始化的回复中,手机微信可以告诉外设手机微信当前的用的手机操作系统的版本、当前时间、微信用户ID等等。以便于外设记录用户的信息。

 

3.4 SendData 设备发送数据指令

设备和上层可以通过这个还有RecDataPush 当type = 0 时,发送自定义数据。

 

4. 微信Proto buf 协议

4.1 proto buf 协议简介

官方文档给出的定义和描述: 

protocol buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于(数据)通信协议、数据存储等。

Protocol Buffers 是一种灵活,高效,自动化机制的结构数据序列化方法-可类比 XML,但是比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单。

ProtoBuf 是结构数据序列化[1] 方法,可简单类比于 XML[2],其具有以下特点:

  • 语言无关、平台无关。即 ProtoBuf 支持 Java、C++、Python 等多种语言,支持多个平台.
  • 高效。即比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单.
  • 扩展性、兼容性好。你可以更新数据结构,而不影响和破坏原有的旧程序.

而微信蓝牙协议中的包体就是基于proto buf 协议的,也就是上面的AuthRequset和AuthReponse、 InitRequset和InitResponse 、SendData 和 RecDataPush  都是基于proto buf 协议的。

 

4.2  微信蓝牙外设 proto 文件

syntax = "proto2";

enum EmCmdId
{
	ECI_none = 0;

	// req: 蓝牙设备 -> 微信/厂商服务器
	ECI_req_auth = 10001; 					// 登录
	ECI_req_sendData = 10002; 				// 蓝牙设备发送数据给微信或厂商
	ECI_req_init = 10003; 					// 初始化

	// resp:微信/厂商服务器 -> 蓝牙设备
	ECI_resp_auth = 20001;
	ECI_resp_sendData = 20002;
	ECI_resp_init = 20003;

	// push:微信/厂商服务器 -> 蓝牙设备
	ECI_push_recvData = 30001; 				// 微信或厂商发送数据给蓝牙设备
	ECI_push_switchView = 30002; 			// 进入/退出界面
	ECI_push_switchBackgroud = 30003; 		// 切换后台
	ECI_err_decode = 29999; 				// 解密失败的错误码。注意:这不是 cmdid。为节省固定包头大小,这种特殊的错误码放在包头的 cmdid 字段。
}

enum EmErrorCode
{
	EEC_system = -1;					 	// 通用的错误
	EEC_needAuth = -2; 						// 设备未登录
	EEC_sessionTimeout = -3; 				// session 超时,需要重新登录
	EEC_decode = -4; 						// proto 解码失败
	EEC_deviceIsBlock = -5; 				// 设备出现异常,导致被微信临时性禁止登录
	EEC_serviceUnAvalibleInBackground = -6; // ios 处于后台模式,无法正常服务
	EEC_deviceProtoVersionNeedUpdate = -7; 	// 设备的 proto 版本过老,需要更新
	EEC_phoneProtoVersionNeedUpdate = -8; 	// 微信客户端的 proto 版本过老,需要更新
	EEC_maxReqInQueue = -9; 				// 设备发送了多个请求,并且没有收到回包。微信客户端请求队列拥塞。
	EEC_userExitWxAccount = -10;			// 用户退出微信帐号。
}

message BaseRequest
{
}
message BaseResponse 
{
	required int32 ErrCode = 1;
	optional string ErrMsg = 2;
}

message BasePush 
{
}

// req, resp ========================================
enum EmAuthMethod
{
	EAM_md5 = 1; 			// 设备通过 Md5DeviceTypeAndDeviceId,来通过微信 app 的认证。1. 如果是用 aes 加密,注意设置 AesSign 有值。 2. 如果是没有加密,注意设置 AesSign 为空或者长度为零。
	EAM_macNoEncrypt = 2; 	// 设备通过 mac 地址字段,且没有加密,来通过微信 app 的认证。
}

// 登录 ---------------------------------------------
message AuthRequest
{
	required BaseRequest BaseRequest = 1;
	optional bytes Md5DeviceTypeAndDeviceId = 2; 			// deviceType 加 deviceId 的 md5,16 字节的二进制数据
	required int32 ProtoVersion = 3; 						// 设备支持的本 proto 文件的版本号,第一个字节表示最小版本,第二个字节表示小版本,第三字节表示大版本。版本号为 1.0.0 的话,应该填:0x010000;1.2.3 的话,填成 0x010203。
	required int32 AuthProto = 4; 							// 填 1
	required EmAuthMethod AuthMethod = 5; 					// 验证和加密的方法,见 EmAuthMethod
	optional bytes AesSign = 6; 							// 具体生成方法见文档
	optional bytes MacAddress = 7; 							// mac 地址,6 位。当设备没有烧 deviceId 的时候,可使用该 mac 地址字段来通过微信 app 的认证
	optional string TimeZone = 10; 							// 废弃
	optional string Language = 11; 							// 废弃
	optional string DeviceName = 12; 						// 废弃
}

message AuthResponse
{
	required BaseResponse BaseResponse = 1;
	required bytes AesSessionKey = 2;
}

// 初始化 --------------------------------------------
enum EmInitRespFieldFilter 
{
	EIRFF_userNickName = 0x1;
	EIRFF_platformType = 0x2;
	EIRFF_model = 0x4;
	EIRFF_os = 0x8;
	EIRFF_time = 0x10;
	EIRFF_timeZone = 0x20;
	EIRFF_timeString = 0x40;
}

// 微信连接上设备时,处于什么情景
enum EmInitScence
{
	EIS_deviceChat = 1; 		// 聊天
	EIS_autoSync = 2; 			// 自动同步
}

message InitRequest
{
	required BaseRequest BaseRequest = 1;
	optional bytes RespFieldFilter = 2; 		// 当一个 bit 被设置就表示要 resp 的某个字段:见EmInitRespFieldFilter。
	optional bytes Challenge = 3; 				// 设备用来验证手机是否安全。为设备随机生成的四个字节。
}

enum EmPlatformType
{
	EPT_ios = 1;
	EPT_andriod = 2;
	EPT_wp = 3;
	EPT_s60v3 = 4;
	EPT_s60v5 = 5;
	EPT_s40 = 6;
	EPT_bb = 7;
}

message InitResponse
{
	required BaseResponse BaseResponse = 1;
	required uint32 UserIdHigh = 2; 					// 微信用户 Id 高 32 位
	required uint32 UserIdLow = 3; 						// 微信用户 Id 低 32 位
	optional uint32 ChalleangeAnswer = 4; 				// 手机回复设备的挑战。为设备生成的字节的 crc32。
	optional EmInitScence InitScence = 5; 				// 微信连接上设备时,处于什么情景。如果该字段为空,表示处于 EIS_deviceChat 下。
	optional uint32 AutoSyncMaxDurationSecond = 6; 		// 自动同步最多持续多长,微信就会关闭连接。0xffffffff 表示无限长。
	optional string UserNickName = 11; 					// 微信用户昵称
	optional EmPlatformType PlatformType = 12; 			// 手机平台
	optional string Model = 13; 						// 手机硬件型号
	optional string Os = 14; 							// 手机 os 版本
	optional int32 Time = 15; 							// 手机当前时间
	optional int32 TimeZone = 16; 						// 手机当前时区
	optional string TimeString = 17; 					// 手机当前时间,格式如 201402281005285,具体字段意义为 2014(年)02(2 月)28(28 号)10(点)05(分钟)28(秒)5(星期五)。星期一为 1,星期天为 7。 
}

// 设备发送数据给微信或厂商 ----------------------------
// 设备数据类型
enum EmDeviceDataType
{
	EDDT_manufatureSvr = 0; 						// 厂商自定义数据
	EDDT_wxWristBand = 1; 							// 微信公众平台手环数据
	EDDT_wxDeviceHtmlChatView = 10001;				// 微信客户端设备 html5 会话界面数据
}

message SendDataRequest
{
	required BaseRequest BaseRequest = 1;
	required bytes Data = 2;
	optional EmDeviceDataType Type = 3; 			// 数据类型(如厂商自定义数据,或公众平台规定的手环数据,或微信客户端设备 html5 会话界面数据等)。不填,或者等于 0 的时候,表示设备发送厂商自定义数据到厂商服务器。
}

message SendDataResponse
{
	required BaseResponse BaseResponse = 1;
	optional bytes Data = 2;
}

// push ===================================================
// 微信或厂商发送数据给蓝牙设备 ---------------------------
message RecvDataPush
{
	required BasePush BasePush = 1;
	required bytes Data = 2;
	optional EmDeviceDataType Type = 3; 			// 数据类型(如厂商自定义数据,或公众平台规定的手环数据,或微信客户端设备 html5 会话界面数据等)。不填,或者等于 0 的时候,表示设备收到厂商自定义数据。
}

 

4.3 微信小程序使用proto buf    --- Java Script  上使用proto buf

通过查阅相关资料,发现网上Java Script 平台谷歌的 proto buf 使用都是在网页上使用的,在微信小程序中Function 和 eval 相关的动态执行代码方式都给屏蔽了,以致google官方Protobuf不能正常使用;

最终找到一个大神的大神的开源项目《微信小程序可用的Protobuf(含demo)》,找出微信小程序使用Protobuf的可行方案。

动态解析,而是根据.proto文件生成json文件再手动生成js文件,过程比较复杂。

因此,要在微信小程序上使用微信外设proto buf文件,需要使用这个开源项目。

 

4.4 安装和使用微信小程序可以Protobuf 开源项目

4.1 在《微信小程序可用的Protobuf(含demo)》 链接中,下载项目代码,将其中weichatPb文件夹加入到你的小程序项目中。

4.2 在Windows 操作系统中,安装Nodejs

4.3 到《https://nodejs.org/zh-cn/download/》 Nodejs 官网上,下载安装包。

4.4 安装Nodejs.

4.4.1 检测PATH环境变量是否配置了Node.js,点击开始=》运行=》输入"cmd" => 输入命令"path",输出如下结果:

PATH=C:\oraclexe\app\oracle\product\10.2.0\server\bin;C:\Windows\system32;
C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;
c:\python32\python;C:\MinGW\bin;C:\Program Files\GTK2-Runtime\lib;
C:\Program Files\MySQL\MySQL Server 5.5\bin;C:\Program Files\nodejs\;
C:\Users\rg\AppData\Roaming\npm

4.4.2 检查Node.js版本,在控制台输入

node --version

如果安装成功,可以看到,

4.4.3 打开控制台, 安装谷歌的proto buf js ,输入以下命令   

 npm install -g protobufjs

会出现,

出现问题是,一般情况是因为代理问题,npm代理和git代理都要设置。首先确认网络是否需要设置代理。

解决问题方法这篇文章《npm 安装报错 rollbackFailedOptional verb npm-session 解决办法》有提到,

npm换为国内镜像cnpm,使用淘宝镜像作为下载资源,具体办法如下,

4.4.4 修改npm的资源镜像链接,输入以下命令

npm config set registry http://registry.npm.taobao.org

 

4.4.5 再次安装protobufjs.

4.4.6 安装protobufjs 成功后,接着安装 pbjs需要的库 命令行执行下“pbjs”

会出现以下,表示安装成功。O(∩_∩)O哈哈~

C:\Users\69009>pbjs
installing semver@^5.5.0
installing chalk@^2.4.1
installing glob@^7.1.2
installing jsdoc@^3.5.5
installing minimist@^1.2.0
installing tmp@0.0.33
installing uglify-js@^3.3.25
installing espree@^3.5.4
installing escodegen@^1.9.1
installing estraverse@^4.2.0
protobuf.js v6.7.0 CLI for JavaScript

Translates between file formats and generates static code.

  -t, --target     Specifies the target format. Also accepts a path to require a custom target.

                   json          JSON representation
                   json-module   JSON representation as a module
                   proto2        Protocol Buffers, Version 2
                   proto3        Protocol Buffers, Version 3
                   static        Static code without reflection (non-functional on its own)
                   static-module Static code without reflection as a module

  -p, --path       Adds a directory to the include path.

  -o, --out        Saves to a file instead of writing to stdout.

  --sparse         Exports only those types referenced from a main file (experimental).

  Module targets only:

  -w, --wrap       Specifies the wrapper to use. Also accepts a path to require a custom wrapper.

                   default   Default wrapper supporting both CommonJS and AMD
                   commonjs  CommonJS wrapper
                   amd       AMD wrapper
                   es6       ES6 wrapper (implies --es6)
                   closure   A closure adding to protobuf.roots where protobuf is a global

  --dependency     Specifies which version of protobuf to require. Accepts any valid module id

  -r, --root       Specifies an alternative protobuf.roots name.

  -l, --lint       Linter configuration. Defaults to protobuf.js-compatible rules:

                   eslint-disable block-scoped-var, id-length, no-control-regex, no-magic-numbers, no-prototype-builtins, no-redeclare, no-shadow, no-var, sort-vars

  --es6            Enables ES6 syntax (const/let instead of var)

  Proto sources only:

  --keep-case      Keeps field casing instead of converting to camel case.

  Static targets only:

  --no-create      Does not generate create functions used for reflection compatibility.
  --no-encode      Does not generate encode functions.
  --no-decode      Does not generate decode functions.
  --no-verify      Does not generate verify functions.
  --no-convert     Does not generate convert functions like from/toObject
  --no-delimited   Does not generate delimited encode/decode functions.
  --no-beautify    Does not beautify generated code.
  --no-comments    Does not output any JSDoc comments.

  --force-long     Enfores the use of 'Long' for s-/u-/int64 and s-/fixed64 fields.
  --force-number   Enfores the use of 'number' for s-/u-/int64 and s-/fixed64 fields.
  --force-message  Enfores the use of message instances instead of plain objects.

usage: pbjs [options] file1.proto file2.json ...  (or pipe)  other | pbjs [options] -

C:\Users\69009>

4.5 使用pbjs 转换一下.proto文件

4.5.1 使用文章开始的上面的微信蓝牙外设.proto 文件的创建一个.proto 文件。

4.5.1 将wxProtocolBuffers.proto 转换成对应.json 文件

在控制台输入 

pbjs -t json wxProtocolBuffers.proto > wxProtocolBuffers.json

 

4.6 将文件和开源项目拷贝到微信小程序工程目录下,

然后就可以开始使用了 O(∩_∩)O哈哈~    O(∩_∩)O哈哈~ ,可以开始调试了。

 

5. 与微信蓝牙设备通讯记录

5.1 使用微信AirSyncDebug.apk 调试日志

*****************BLE: AFGF4 ******************

***** onTestBroadcastRecord *****
result = true, Has 0xfee7 or standard service in broadcast record

广播包:02 01 06 05 02 E7 FE E0 FF 09 FF FF FF  F3 3F 31 F3 FF 3F 0D 09 41 46 47 46 34 20 20 20 20 20 20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 

***** onTestManufatureData *****
resut= true, 广播包中 manufacture specific data 字段中MAC地址校验成功.

***** onDiscoverService *****
result = true, DiscoverService success
Discovered Services
ServiceUUID: 00001800-0000-1000-8000-00805f9b34fb
ServiceUUID: 0000fee7-0000-1000-8000-00805f9b34fb
ServiceUUID: 0000ffe0-0000-1000-8000-00805f9b34fb


***** onTestHasWeChatService *****
result = true, has WeChatService or standard service

***** onTestHasIndicateCharacteristic *****
result = true, has WeChat Indicate Characteristic

***** onTestHasWriteCharacteristic *****
result = true, has Wechat Write Characteristic

***** onTestHasReadCharacteristic *****
result = true, Has WeChat read characteristic

***** onTestWriteCharacteristicPermisson *****
result = true, has Write permission

***** onTestIndicateCharacteristicPermisson *****
result = true, has Indication permission

***** onTestReadCharacteristicPermisson *****
result = true, Read Characteristic is read able

***** onTestStartIndicating *****
result = true, can Start Indicate

***** onConnected *****
result = true, connected

------onDataReceived------
data length = 20
data dump = FE 01 00 1A 27 11 00 05 0A 00 18 84 80 04 20 01 28 02 3A 06 
data receive seq = 1

------onDataReceived------
data length = 6
data dump = F3 3F 31 F3 FF 3F 
data receive seq = 2

***** onTestRecvAuthReqtWhenStartedIndicating *****
result = true, received auth request pack

***** onTestIsValidAuthReqPack *****
result = true, is a valid auth request pack
AuthRequestPack: FE 01 00 1A 27 11 00 05 0A 00 18 84 80 04 20 01 28 02 3A 06 F3 3F 31 F3 FF 3F 
has BaseRequest
no Md5DeviceTypeAndDeviceId field!
has MacAddress field, Mac Address = F3 3F 31 F3 FF 3F 
MacAddress BitLength = 48bit
Mac Address from broadcast record = F3:3F:31:F3:FF:3F
Mac address checkout success
has ProtoVersion field, ProtoVersion = 65540
has AuthProto field, AuthProto = 1
has AuthMethod field, AuthMethod = EAM_macNoEncrypt
no AesSign field!


**** send auth response ****
data len = 14
data dump = FE 01 00 0E 4E 21 00 05 0A 02 08 00 12 00 

------onDataReceived------
data length = 20
data dump = FE 01 00 1C 27 13 00 06 0A 00 1A 10 00 01 02 03 04 05 06 07 
data receive seq = 3

------onDataReceived------
data length = 8
data dump = 08 09 0A 0B 0C 0D 0E 0F 
data receive seq = 4

***** onTestRecvInitReqPack *****
result = true, received init request pack

***** onTestIsValidInitReqPack *****
result = true, valid init request pack: has BaseRequest
has Challenge field, Challenge = 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 


**** send init request response ****
data len = 25
data dump = FE 01 00 19 4E 23 00 06 0A 02 08 00 10 B4 24 18 F8 AC 01 20 88 C5 BB F6 0C 

5.2 微信小程序调试日志

5.2.1 蓝牙连接日志     --      O(∩_∩)O哈哈~连接成功

5.2.2 登录日志

2019-10-24 21:48:06:833: 接收长度 = 20, 数据 = FE01001A271100010A0018848004200128023A06
util.js:73 2019-10-24 21:48:06:833: 当前接收总长度 = 20
util.js:73 2019-10-24 21:48:06:833: 微信协议数据总长度 = 26
util.js:73 2019-10-24 21:48:06:834: 接收长度 = 6, 数据 = 45014DFFFF0C
util.js:73 2019-10-24 21:48:06:834: 当前接收总长度 = 26
util.js:73 2019-10-24 21:48:06:835: 接收完整一包完成,开始处理数据
util.js:73 2019-10-24 21:48:06:835: 接收完整一包数据 = FE01001A271100010A0018848004200128023A0645014DFFFF0C
util.js:73 2019-10-24 21:48:06:836: 微信协议登录验证 = FE01001A271100010A0018848004200128023A0645014DFFFF0C
util.js:73 2019-10-24 21:48:06:836: packet.protobuf = 0A0018848004200128023A0645014DFFFF0C
util.js:73 2019-10-24 21:48:06:841: Test Is Valid Auth ReqPack = {"BaseRequest":{},"ProtoVersion":65540,"AuthProto":1,"AuthMethod":"EAM_macNoEncrypt","MacAddress":"RQFN//8M"}
util.js:73 2019-10-24 21:48:06:841: MAac Address = 45:01:4D:FF:FF:0C:
util.js:73 2019-10-24 21:48:06:843: send auth response = FE0100124E2100010A06080012024F4B1200
util.js:73 2019-10-24 21:48:06:844: 发送数据 = FE0100124E2100010A06080012024F4B1200
util.js:73 2019-10-24 21:48:07:70: 发送成功

通过比较可以发现,与AirSyncDebug 解析一样。

 

5.2.3 初始化通讯日志

019-10-24 21:48:07:70: 接收长度 = 20, 数据 = FE01001C271300020A001A100001020304050607
util.js:73 2019-10-24 21:48:07:71: 当前接收总长度 = 20
util.js:73 2019-10-24 21:48:07:71: 微信协议数据总长度 = 28
util.js:73 2019-10-24 21:48:07:134: 接收长度 = 8, 数据 = 08090A0B0C0D0E0F
util.js:73 2019-10-24 21:48:07:134: 当前接收总长度 = 28
util.js:73 2019-10-24 21:48:07:134: 接收完整一包完成,开始处理数据
util.js:73 2019-10-24 21:48:07:135: 接收完整一包数据 = FE01001C271300020A001A10000102030405060708090A0B0C0D0E0F
util.js:73 2019-10-24 21:48:07:135: 微信协议设备初始化通讯 = FE01001C271300020A001A10000102030405060708090A0B0C0D0E0F
util.js:73 2019-10-24 21:48:07:135: packet.protobuf = 0A001A10000102030405060708090A0B0C0D0E0F
util.js:73 2019-10-24 21:48:07:136: Test Recv InitReq Pack = {"BaseRequest":{},"Challenge":"AAECAwQFBgcICQoLDA0ODw=="}
util.js:73 2019-10-24 21:48:07:136: Challenage = 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
util.js:73 2019-10-24 21:48:07:137: send init request response = FE0100164E2300020A06080012024F4B100018002000
util.js:73 2019-10-24 21:48:07:137: 发送数据 = FE0100164E2300020A06080012024F4B10001800
util.js:73 2019-10-24 21:48:07:350: 发送成功
util.js:73 2019-10-24 21:48:07:350: 发送数据 = 2000
util.js:73 2019-10-24 21:48:07:581: 发送成功

通过比较可以发现,与AirSyncDebug 解析一样。

通过上述步骤,登录 -》 初始化通讯 -》 成功后,就可以开始正常与蓝牙设备进行通讯了。

 

5.2.4 使用微信外设蓝牙模块,通过微信AirSync 协议透传通道与单片机通讯  - 日志

19-10-24 21:48:09:789: 读卡器协议包 = 33008001a928
util.js:73 2019-10-24 21:48:09:790: 发送数据 = FE010014753100000A00120633008001A9281800
util.js:73 2019-10-24 21:48:10:69: 发送成功
util.js:73 2019-10-24 21:48:10:217: 接收长度 = 20, 数据 = FE010023271200030A0012143300810FB9001804
util.js:73 2019-10-24 21:48:10:217: 当前接收总长度 = 20
util.js:73 2019-10-24 21:48:10:217: 微信协议数据总长度 = 35
util.js:73 2019-10-24 21:48:10:218: 接收长度 = 15, 数据 = 004F4190FD632800000C787718914E
util.js:73 2019-10-24 21:48:10:218: 当前接收总长度 = 35
util.js:73 2019-10-24 21:48:10:218: 接收完整一包完成,开始处理数据
util.js:73 2019-10-24 21:48:10:219: 接收完整一包数据 = FE010023271200030A0012143300810FB9001804004F4190FD632800000C787718914E
util.js:73 2019-10-24 21:48:10:219: Test Is Valid Send Data Request = {"BaseRequest":{},"Data":"MwCBD7kAGAQAT0GQ/WMoAAAMeHc=","Type":"EDDT_wxDeviceHtmlChatView"}
util.js:73 2019-10-24 21:48:10:219: data = 3300810FB9001804004F4190FD632800000C7877
util.js:73 2019-10-24 21:48:10:220: 微信协议通道 = FE010023271200030A0012143300810FB9001804004F4190FD632800000C787718914E

通过上述日记,我的微信小程序终于可以与微信蓝牙外设,正常收发数据了,^_^

今天是1024 节,节日快乐,终于把这篇博客写完了。

 

/**
 *         ┏┓   ┏┓+ +
 *        ┏┛┻━━━┛┻┓ + +
 *        ┃       ┃
 *        ┃   ━   ┃ ++ + + +
 *        ████━████ ┃+
 *        ┃       ┃ +
 *        ┃   ┻   ┃
 *        ┃       ┃ + +
 *        ┗━┓   ┏━┛
 *          ┃   ┃
 *          ┃   ┃ + + + +
 *          ┃   ┃    Code is far away from bug with the animal protecting
 *          ┃   ┃ +     神兽保佑,代码无bug
 *          ┃   ┃
 *          ┃   ┃  +
 *          ┃    ┗━━━┓ + +
 *          ┃        ┣┓
 *          ┃        ┏┛
 *          ┗┓┓┏━┳┓┏┛ + + + +
 *           ┃┫┫ ┃┫┫
 *           ┗┻┛ ┗┻┛+ + + +
 *
 * @author chenxi
 * @date 2019-10-24 21:59:45
 */
 

 

参考大神文章:

https://github.com/Zhang19910325/protoBufferForWechat

https://www.cnblogs.com/Free-Thinker/p/5559803.html

https://blog.csdn.net/yueqian_scut/article/details/47606599

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值