天天看點

微信藍牙外設開發記錄 - 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 裡取得裝置的回應資料。

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

微信藍牙外設開發記錄 - 2 (微信小程式與微信藍牙BEL裝置通訊)

會話流程如下:

微信藍牙外設開發記錄 - 2 (微信小程式與微信藍牙BEL裝置通訊)

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           

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

微信藍牙外設開發記錄 - 2 (微信小程式與微信藍牙BEL裝置通訊)

4.4.3 打開控制台, 安裝谷歌的proto buf js ,輸入以下指令   

npm install -g protobufjs           

會出現,

微信藍牙外設開發記錄 - 2 (微信小程式與微信藍牙BEL裝置通訊)

出現問題是,一般情況是因為代理問題,npm代理和git代理都要設定。首先确認網絡是否需要設定代理。

解決問題方法這篇文章《npm 安裝報錯 rollbackFailedOptional verb npm-session 解決辦法》有提到,

npm換為國内鏡像cnpm,使用淘寶鏡像作為下載下傳資源,具體辦法如下,

4.4.4 修改npm的資源鏡像連結,輸入以下指令

npm config set registry http://registry.npm.taobao.org
           
微信藍牙外設開發記錄 - 2 (微信小程式與微信藍牙BEL裝置通訊)

4.4.5 再次安裝protobufjs.

微信藍牙外設開發記錄 - 2 (微信小程式與微信藍牙BEL裝置通訊)

4.4.6 安裝protobufjs 成功後,接着安裝 pbjs需要的庫 指令行執行下“pbjs”

會出現以下,表示安裝成功。O(∩_∩)O哈哈~

C:\Users\69009>pbjs
installing [email protected]^5.5.0
installing [email protected]^2.4.1
installing [email protected]^7.1.2
installing [email protected]^3.5.5
installing [email protected]^1.2.0
installing [email protected]
installing [email protected]^3.3.25
installing [email protected]^3.5.4
installing [email protected]^1.9.1
installing [email protected]^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 檔案。

微信藍牙外設開發記錄 - 2 (微信小程式與微信藍牙BEL裝置通訊)

4.5.1 将wxProtocolBuffers.proto 轉換成對應.json 檔案

在控制台輸入 

pbjs -t json wxProtocolBuffers.proto > wxProtocolBuffers.json           
微信藍牙外設開發記錄 - 2 (微信小程式與微信藍牙BEL裝置通訊)
微信藍牙外設開發記錄 - 2 (微信小程式與微信藍牙BEL裝置通訊)

4.6 将檔案和開源項目拷貝到微信小程式工程目錄下,

微信藍牙外設開發記錄 - 2 (微信小程式與微信藍牙BEL裝置通訊)

然後就可以開始使用了 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哈哈~連接配接成功

微信藍牙外設開發記錄 - 2 (微信小程式與微信藍牙BEL裝置通訊)

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 節,節日快樂,終于把這篇部落格寫完了。

參考大神文章:

https://github.com/Zhang19910325/protoBufferForWechat

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

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