牙Mesh配網(wǎng):Unprovisioned Device Beacon原理與調(diào)試實(shí)戰(zhàn))
前陣子在幫某物聯(lián)網(wǎng)項(xiàng)目調(diào)試Mesh組網(wǎng)遇到一個(gè)特別典型的卡點(diǎn)配網(wǎng)器掃描設(shè)備時(shí)始終看不到那臺(tái)待配網(wǎng)的燈控設(shè)備。日志顯示掃描正常信道正常濾波條件也加了可就是捕捉不到那個(gè)關(guān)鍵的廣播包。折騰了大半天最后發(fā)現(xiàn)是設(shè)備端的Unprovisioned Device Beacon廣播沒(méi)被正確初始化——簡(jiǎn)單說(shuō)這臺(tái)設(shè)備壓根就沒(méi)有向外面“喊”它需要入網(wǎng)。這個(gè)場(chǎng)景在藍(lán)牙Mesh開(kāi)發(fā)里太常見(jiàn)了。很多人一上來(lái)就研究配網(wǎng)流程的加密、公鑰交換、認(rèn)證邏輯卻忽略了最前端那個(gè)不起眼的beacon。實(shí)際上整個(gè)配網(wǎng)能否成功第一步就取決于這個(gè)廣播包能不能被配網(wǎng)器穩(wěn)定地發(fā)現(xiàn)。這篇內(nèi)容我就把Unprovisioned Device Beacon這件事從頭到尾拆清楚包括它在配網(wǎng)鏈路里的定位、數(shù)據(jù)包結(jié)構(gòu)、配網(wǎng)時(shí)各階段的狀態(tài)流轉(zhuǎn)以及我在不同項(xiàng)目里踩過(guò)的坑和排查方法。不管是剛接觸藍(lán)牙Mesh的初學(xué)者還是已經(jīng)被配網(wǎng)問(wèn)題折磨過(guò)的老手這部分內(nèi)容應(yīng)該都能幫上忙。1. 未入網(wǎng)設(shè)備憑什么被“看見(jiàn)”Unprovision Beacon的定位1.1 它是配網(wǎng)流程的第一個(gè)突破口藍(lán)牙Mesh網(wǎng)絡(luò)和傳統(tǒng)BLE最直觀的區(qū)別在于Mesh里的設(shè)備不是天生就能互相通信的。一個(gè)新出廠的設(shè)備比如一個(gè)燈泡、一個(gè)傳感器它內(nèi)部其實(shí)已經(jīng)跑著完整的Mesh協(xié)議棧但并不知道自己是這個(gè)網(wǎng)絡(luò)里的誰(shuí)也不知道網(wǎng)絡(luò)密鑰是什么。在它被配置之前它就是一個(gè)“游離者”——能看到周圍的環(huán)境卻不被任何現(xiàn)有網(wǎng)絡(luò)接納。這里就出現(xiàn)了一個(gè)問(wèn)題Mesh網(wǎng)絡(luò)的配網(wǎng)器Provisioner怎么知道周圍有這么一個(gè)待入網(wǎng)的設(shè)備尤其是當(dāng)設(shè)備沒(méi)有任何屏幕、沒(méi)有按鍵、甚至沒(méi)有指示燈的時(shí)候配網(wǎng)器總得有個(gè)方式發(fā)現(xiàn)它。Unprovisioned Device Beacon未配網(wǎng)設(shè)備信標(biāo)就是這個(gè)機(jī)制的最前端。它本質(zhì)上是一個(gè)BLE廣播包周期性地向外發(fā)送包里唯一的目的就是告訴所有在監(jiān)聽(tīng)的配網(wǎng)器“我在這里我是誰(shuí)我準(zhǔn)備好被配置了?!蔽覀兂Uf(shuō)的“beacon”可能指的是蘋(píng)果的iBeacon也可能指各種室內(nèi)定位用的信標(biāo)但Unprovisioned Device Beacon是完全不同的東西。它不承載定位信息不面向普通手機(jī)應(yīng)用提供數(shù)據(jù)而是面向Mesh網(wǎng)絡(luò)的配網(wǎng)器承擔(dān)的是設(shè)備發(fā)現(xiàn)功能。沒(méi)有這個(gè)廣播包配網(wǎng)器就會(huì)對(duì)著空氣掃描后面所有流程都無(wú)從談起。1.2 兩套beacon別搞混發(fā)現(xiàn)用beacon配網(wǎng)事務(wù)則是另一套很多初學(xué)者會(huì)在這里踩一個(gè)概念上的混淆Mesh里其實(shí)有兩類和“未配網(wǎng)”密切相關(guān)的廣播。一類是Unprovisioned Device Beacon用于讓設(shè)備被發(fā)現(xiàn)另一類是配網(wǎng)過(guò)程中真正傳輸配網(wǎng)指令的廣播包走的是PB-ADVProvisioning Bearer Advertising基于廣播承載的配網(wǎng)事務(wù)機(jī)制。兩者的時(shí)間先后和職責(zé)完全不同。實(shí)際運(yùn)行中是這樣設(shè)備先以Unprovisioned Device Beacon的身份對(duì)外廣播配網(wǎng)器掃描到它之后由配網(wǎng)器主動(dòng)發(fā)起配網(wǎng)連接雙方進(jìn)入配網(wǎng)事務(wù)階段。進(jìn)入事務(wù)階段后配網(wǎng)雙方交換的是配網(wǎng)協(xié)議數(shù)據(jù)包Provisioning Protocol PDUs這些數(shù)據(jù)包通過(guò)PB-ADV廣播承載但它們的廣播類型已經(jīng)不再是Unprovisioned Device Beacon而是帶有特定配網(wǎng)事務(wù)標(biāo)識(shí)的ADV包。我在調(diào)試時(shí)就見(jiàn)過(guò)一個(gè)項(xiàng)目開(kāi)發(fā)同學(xué)一直盯著檢查Unprovisioned Device Beacon的廣播是否正確發(fā)送卻忘了配網(wǎng)事務(wù)是靠另一組廣播完成的導(dǎo)致這兩段的鏈路經(jīng)常被截?cái)?。理解了這個(gè)先后關(guān)系后面排查問(wèn)題時(shí)就不會(huì)在一個(gè)地方死磕。1.3 什么時(shí)候廣播什么時(shí)候停beacon的聲明周期Unprovisioned Device Beacon并不是設(shè)備一上電就永遠(yuǎn)廣播個(gè)不停。它的生命周期取決于設(shè)備的存儲(chǔ)狀態(tài)。設(shè)備啟動(dòng)后協(xié)議棧會(huì)先檢查非易失性存儲(chǔ)里有沒(méi)有保存有效的配網(wǎng)信息NetKey、AppKey、IV Index等。如果沒(méi)有——也就是這臺(tái)設(shè)備從未被配置過(guò)或配置信息被主動(dòng)清除過(guò)——協(xié)議棧才會(huì)啟動(dòng)beacon廣播。一旦配網(wǎng)成功設(shè)備會(huì)寫(xiě)入配網(wǎng)數(shù)據(jù)此時(shí)beacon必須立即停止。這一點(diǎn)在很多項(xiàng)目里看起來(lái)理所當(dāng)然但實(shí)際測(cè)試中經(jīng)常翻車后面我會(huì)專門講我遇到的一個(gè)案例配網(wǎng)成功后beacon沒(méi)有停導(dǎo)致設(shè)備被重復(fù)配網(wǎng)。2. 拆包看本質(zhì)Unprovisioned Device Beacon數(shù)據(jù)包結(jié)構(gòu)2.1 廣播類型0x29和AD Structure的組裝規(guī)則藍(lán)牙Mesh規(guī)范里規(guī)定Unprovisioned Device Beacon的廣播類型值為0x29。整個(gè)廣播包遵循BLE標(biāo)準(zhǔn)的AD Structure格式也就是Length、Type、Data三段式。我用一個(gè)實(shí)際抓包得到的數(shù)據(jù)來(lái)拆解AD Structure 1: Length : 0x15 (21字節(jié)) Type : 0x01 (Flags) Data : 0x06 (LE General Discoverable Mode) AD Structure 2: Length : 0x14 (20字節(jié)) Type : 0x29 (Unprovisioned Device Beacon) Data : 16字節(jié)Device UUID 2字節(jié)OOB Information第一個(gè)AD Structure是常見(jiàn)的廣播標(biāo)志告知接收方這是一個(gè)通用可發(fā)現(xiàn)的廣播設(shè)備。第二個(gè)AD Structure才是核心。當(dāng)配網(wǎng)器掃描時(shí)就是靠過(guò)濾Type字段是否等于0x29來(lái)識(shí)別潛在的可配網(wǎng)設(shè)備。這里有個(gè)細(xì)節(jié)值得注意一次廣播包里面只能有一個(gè)Type為0x29的AD Structure。如果想把Unprovisioned Device Beacon和其他數(shù)據(jù)比如廠商自定義數(shù)據(jù)、服務(wù)UUID拼在一起必須放在不同的AD Structure里。配網(wǎng)器解析時(shí)也是獨(dú)立解析每個(gè)AD Structure的不是要求整個(gè)廣播包全是beacon內(nèi)容。2.2 Device UUID設(shè)備唯一的身份證明Device UUID是整個(gè)beacon包里最重要的16字節(jié)。它不是什么隨機(jī)數(shù)而是設(shè)備的靜態(tài)標(biāo)識(shí)符在設(shè)備生產(chǎn)階段就寫(xiě)入非易失性存儲(chǔ)配網(wǎng)后也不會(huì)改變。配網(wǎng)器通過(guò)它識(shí)別設(shè)備Mesh網(wǎng)絡(luò)后續(xù)對(duì)設(shè)備的操作也基于這個(gè)UUID建立對(duì)應(yīng)關(guān)系。生產(chǎn)環(huán)節(jié)對(duì)UUID的管理是個(gè)容易被忽視的工作。有些工廠在燒錄時(shí)用的是同一個(gè)UUID模板導(dǎo)致一批設(shè)備全部撞車。那場(chǎng)面很經(jīng)典配網(wǎng)器掃描到一個(gè)UUID卻對(duì)應(yīng)了好幾臺(tái)物理設(shè)備完全無(wú)法區(qū)分。更隱蔽的問(wèn)題是UUID一旦在生產(chǎn)后需要修改牽扯到整臺(tái)設(shè)備的重新燒錄和配網(wǎng)數(shù)據(jù)清除非常麻煩。正確的是在產(chǎn)線階段就保證UUID唯一并且和產(chǎn)品序列號(hào)、MAC地址等建立映射關(guān)系寫(xiě)進(jìn)設(shè)備信息表。調(diào)試時(shí)我習(xí)慣先用串口或板載調(diào)試工具讀取設(shè)備的真實(shí)UUID再手動(dòng)添加進(jìn)配網(wǎng)器的過(guò)濾條件里而不是通過(guò)掃描列表去碰運(yùn)氣。2.3 OOB Information字段怎么用Device UUID后面跟著2字節(jié)的OOB Information。這個(gè)字段描述的是設(shè)備在配網(wǎng)認(rèn)證階段支持哪些帶外信息的輸入輸出方式。常見(jiàn)值包括OOB值含義典型場(chǎng)景0x0000不支持任何OOB僅支持None認(rèn)證0x0001支持其他OOB廠商自定義帶外通道0x0002支持URIbeacon中附帶URI Hash0x0004支持?jǐn)?shù)值輸入按鍵輸入6位數(shù)字0x0008支持?jǐn)?shù)值輸出顯示屏顯示6位數(shù)字0x0020支持字母數(shù)字輸入鍵盤輸入字母數(shù)字配網(wǎng)器發(fā)現(xiàn)beacon后會(huì)根據(jù)OOB值判斷這臺(tái)設(shè)備能采用哪種認(rèn)證方式。實(shí)際項(xiàng)目里如果配網(wǎng)器端配置了固定要求數(shù)字輸入而設(shè)備端OOB字段聲明不支持任何OOB配網(wǎng)必然失敗。這個(gè)字段的聲明和配網(wǎng)器的要求必須對(duì)得上否則就是白調(diào)試半天。我踩過(guò)的一個(gè)典型案例是設(shè)備明明帶了一塊小屏幕可以顯示動(dòng)態(tài)數(shù)字用于認(rèn)證但SDK里的OOB信息配置被某次固件更新意外改成了0x0000。配網(wǎng)器認(rèn)為設(shè)備沒(méi)有任何OOB能力只能走最簡(jiǎn)單的無(wú)認(rèn)證流程這在安全性要求高的場(chǎng)景下直接導(dǎo)致配網(wǎng)被服務(wù)端策略拒絕。2.4 可選的URI Hash字段有部分設(shè)備還會(huì)在beacon后面追加一個(gè)URI Hash字段用來(lái)進(jìn)一步標(biāo)識(shí)設(shè)備類型或產(chǎn)品信息。URI Hash簡(jiǎn)單說(shuō)就是把一個(gè)URI比如https://example.com/light/001經(jīng)過(guò)哈希算法后得到的固定長(zhǎng)度值。配網(wǎng)器可以先通過(guò)URI Hash識(shí)別出設(shè)備的類型再?zèng)Q定是否發(fā)起配網(wǎng)減少掃描到不相關(guān)設(shè)備時(shí)的干擾。如果不需要設(shè)備類型分類這個(gè)字段可以省略。包長(zhǎng)度更短廣播成功率也會(huì)更高尤其是當(dāng)廣播信道比較擁堵時(shí)。3. 配網(wǎng)鏈路全解析從被掃描到完成配置的五個(gè)階段3.1 建立邀請(qǐng)邀請(qǐng)是雙向的當(dāng)配網(wǎng)器通過(guò)Unprovisioned Device Beacon發(fā)現(xiàn)設(shè)備后會(huì)主動(dòng)向設(shè)備發(fā)送一個(gè)Provisioning Invite包。這一步很多人理解成“配網(wǎng)器向設(shè)備打招呼”實(shí)際上它是配網(wǎng)事務(wù)的正式啟動(dòng)信號(hào)。設(shè)備收到Invite包后會(huì)回復(fù)一個(gè)Invite Acknowledgement同時(shí)雙方基于這個(gè)交互確定后續(xù)的數(shù)據(jù)包格式、重傳策略和協(xié)議版本。如果設(shè)備端沒(méi)有正確維護(hù)beacon狀態(tài)或者已經(jīng)進(jìn)入半配網(wǎng)狀態(tài)比如上次配網(wǎng)超時(shí)沒(méi)有清理干凈這一階段就會(huì)多次超時(shí)。值得注意的是配網(wǎng)器此處不再監(jiān)聽(tīng)0x29類型的廣播而是直接和該設(shè)備建立點(diǎn)對(duì)點(diǎn)的配網(wǎng)承載。我在實(shí)際調(diào)試驗(yàn)證時(shí)發(fā)現(xiàn)不少SDK在進(jìn)入這一步后設(shè)備端的beacon廣播仍然在繼續(xù)這在協(xié)議層面是允許的但會(huì)增加不必要的空口占用建議在業(yè)務(wù)層面主動(dòng)處理。3.2 公鑰交換與認(rèn)證安全的關(guān)鍵環(huán)節(jié)邀請(qǐng)階段完成后配網(wǎng)雙方進(jìn)入Public Key交換階段。雙方各自的公鑰如果通過(guò)beacon的OOB字段預(yù)先聲明支持帶外交換也可以先通過(guò)帶外方式交換提高安全性。這一步完成后配網(wǎng)器會(huì)發(fā)起Authentication階段。認(rèn)證階段基于之前OOB字段聲明的能力來(lái)執(zhí)行。如果聲明的是輸出顯示設(shè)備端生成一個(gè)六位數(shù)字并顯示在屏幕或標(biāo)簽上用戶把這個(gè)數(shù)字輸入到配網(wǎng)器完成認(rèn)證如果聲明的是輸入按鈕則是配網(wǎng)器端生成數(shù)字用戶在設(shè)備上按鍵輸入。整個(gè)過(guò)程是為了防止中間人攻擊。我在這個(gè)階段最常碰到的問(wèn)題是設(shè)備端和配網(wǎng)器端的OOB類型配置不一致。很多開(kāi)發(fā)者以為只要配網(wǎng)器端支持某種方式就行忘了設(shè)備端的beacon OOB字段也要同步聲明。排查時(shí)先看抓包里beacon的OOB值再對(duì)照配網(wǎng)器端的認(rèn)證策略往往一眼就能定位。3.3 下發(fā)配網(wǎng)數(shù)據(jù)分配網(wǎng)絡(luò)地址與密鑰認(rèn)證通過(guò)后配網(wǎng)器給設(shè)備分配關(guān)鍵參數(shù)單播地址、NetKey、AppKey、IV Index等然后通過(guò)加密通道發(fā)送給設(shè)備。這個(gè)階段也是整個(gè)配網(wǎng)過(guò)程最復(fù)雜的一步包含多條配網(wǎng)協(xié)議PDU的往返交互。設(shè)備收到這些數(shù)據(jù)后會(huì)寫(xiě)入自己的非易失性存儲(chǔ)然后向配網(wǎng)器發(fā)送Provisioning Complete消息。配網(wǎng)器收到這條消息后才會(huì)認(rèn)為配網(wǎng)流程真正完成。此時(shí)設(shè)備端的協(xié)議棧會(huì)把自身狀態(tài)切換為已配網(wǎng)節(jié)點(diǎn)停止Unprovisioned Device Beacon廣播。這里我建議每一條關(guān)鍵PDU的成功與否都要看兩端日志里的狀態(tài)機(jī)轉(zhuǎn)換點(diǎn)。光看一條“配網(wǎng)成功”的日志往往不夠因?yàn)橛行㏒DK會(huì)在設(shè)備本地狀態(tài)已更新但配網(wǎng)器尚未確認(rèn)時(shí)提前報(bào)成功導(dǎo)致網(wǎng)絡(luò)里出現(xiàn)一個(gè)半配網(wǎng)狀態(tài)的尷尬節(jié)點(diǎn)。3.4 配網(wǎng)完成后的beacon狀態(tài)切換配網(wǎng)完成后設(shè)備從Unprovisioned Device狀態(tài)變成Provisioned Node狀態(tài)。此時(shí)Unprovisioned Device Beacon必須停止如果設(shè)備支持PB-GATT可能還會(huì)切換到可連接廣播狀態(tài)允許手機(jī)App通過(guò)GATT連接對(duì)它做后續(xù)配置。這一塊是很多產(chǎn)品真正上了產(chǎn)線、或者到了用戶手里之后出問(wèn)題的地方。有些設(shè)備明明已經(jīng)配好網(wǎng)在售后排查時(shí)會(huì)發(fā)現(xiàn)又被重新配了一次原因就在于設(shè)備重啟時(shí)存儲(chǔ)讀取失敗協(xié)議棧誤判設(shè)備仍未配網(wǎng)重新打開(kāi)了beacon廣播。配合抓包工具能夠清楚地看到配網(wǎng)成功的瞬間0x29類型的廣播停止發(fā)送。如果這個(gè)廣播沒(méi)?;究梢詳喽ㄊ谴鎯?chǔ)寫(xiě)入或者狀態(tài)標(biāo)志沒(méi)有正確完成這就是一個(gè)清晰的排查方向。4. 現(xiàn)場(chǎng)翻車實(shí)錄三個(gè)典型問(wèn)題及定位思路4.1 掃描不到beacon先分清“沒(méi)廣播”還是“沒(méi)掃到”這個(gè)問(wèn)題我開(kāi)場(chǎng)就提到了也是大家問(wèn)得最多的。它的排查點(diǎn)可以按下面這張表一層層排除檢查項(xiàng)怎么查常見(jiàn)根因廣播開(kāi)關(guān)看SDK日志確認(rèn)beacon enable接口被調(diào)用其他功能誤關(guān)了廣播設(shè)備狀態(tài)讀存儲(chǔ)標(biāo)志位確認(rèn)設(shè)備處于未配網(wǎng)狀態(tài)存儲(chǔ)區(qū)殘留配網(wǎng)信息廣播周期抓包確認(rèn)廣播間隔是否符合設(shè)定值周期過(guò)長(zhǎng)導(dǎo)致等待窗口不夠信道干擾觀察2.4GHz頻段占用情況Wi-Fi、藍(lán)牙設(shè)備密集配網(wǎng)器濾波檢查掃描參數(shù)中UUID過(guò)濾是否正確UUID配置成另一臺(tái)設(shè)備排查順序從設(shè)備端到配網(wǎng)器端從簡(jiǎn)單到復(fù)雜。先確認(rèn)廣播有沒(méi)有發(fā)出來(lái)再確認(rèn)配網(wǎng)器能不能掃到然后再去查信道和干擾。不要一上來(lái)就懷疑空口環(huán)境有問(wèn)題設(shè)備端SDK初始化順序?qū)е耣eacon沒(méi)啟動(dòng)這種情況我見(jiàn)到的概率遠(yuǎn)大于信道問(wèn)題。一種高效的定位方式是在設(shè)備旁邊放一個(gè)支持廣播過(guò)濾的抓包工具先看設(shè)備上電后有沒(méi)有發(fā)出任何廣播。如果沒(méi)有任何廣播報(bào)告那就是設(shè)備端的問(wèn)題如果有再對(duì)照配網(wǎng)器端的掃描報(bào)告看是不是被濾掉了。這一步能把問(wèn)題范圍縮小一大半。4.2 多設(shè)備同時(shí)配網(wǎng)碰撞和重試的權(quán)衡項(xiàng)目現(xiàn)場(chǎng)經(jīng)常是一整箱設(shè)備同時(shí)上電然后配網(wǎng)器一個(gè)個(gè)掃描配網(wǎng)。這種情況下大量設(shè)備同時(shí)廣播Unprovisioned Device Beacon三個(gè)廣播信道很容易發(fā)生碰撞導(dǎo)致部分設(shè)備遲遲不被發(fā)現(xiàn)。藍(lán)牙Mesh協(xié)議對(duì)廣播間隔有隨機(jī)退避機(jī)制設(shè)備每次廣播的時(shí)間間隔會(huì)根據(jù)一個(gè)隨機(jī)數(shù)在設(shè)定值附近浮動(dòng)避免多設(shè)備完全同步廣播。但實(shí)際項(xiàng)目里如果不設(shè)置隨機(jī)退避或間隔浮動(dòng)過(guò)窄碰撞概率會(huì)顯著上升。我的做法是把默認(rèn)廣播間隔設(shè)置到200ms~500ms范圍內(nèi)浮動(dòng)并根據(jù)設(shè)備數(shù)量做動(dòng)態(tài)調(diào)節(jié)。比如第一次上電的120秒內(nèi)廣播間隔可以短一點(diǎn)讓配網(wǎng)器盡快發(fā)現(xiàn)之后如果沒(méi)有被配網(wǎng)逐步拉長(zhǎng)間隔降低功耗。這個(gè)策略在實(shí)際項(xiàng)目里既保證了配網(wǎng)速度又照顧了長(zhǎng)期待機(jī)場(chǎng)景。4.3 配網(wǎng)成功后設(shè)備還在廣播重復(fù)入網(wǎng)隱患剛才提到的重復(fù)入網(wǎng)問(wèn)題實(shí)際調(diào)試中繞不開(kāi)。有一次我排查一個(gè)節(jié)點(diǎn)的異常行為它已經(jīng)成功入網(wǎng)也能收發(fā)Mesh消息但每次配網(wǎng)器重新掃描時(shí)還會(huì)發(fā)現(xiàn)它。抓包一看Unprovisioned Device Beacon還在周期性地發(fā)。原因出在設(shè)備SDK的通知順序上配網(wǎng)完成后協(xié)議棧先發(fā)了Provisioning Complete事件給應(yīng)用層應(yīng)用層更新了自身的業(yè)務(wù)狀態(tài)但設(shè)備存儲(chǔ)中的配網(wǎng)標(biāo)志位是在另一條邏輯里更新的而這條邏輯因?yàn)槟硞€(gè)分支條件沒(méi)滿足被跳過(guò)了。設(shè)備重啟后存儲(chǔ)讀不到配網(wǎng)標(biāo)志于是又把自己當(dāng)成未配網(wǎng)設(shè)備。這一類問(wèn)題排查起來(lái)很耗時(shí)間因?yàn)楸砻婵雌饋?lái)配網(wǎng)功能是正常的。建議在你的代碼里做一個(gè)簡(jiǎn)單的斷言配網(wǎng)完成事件之后立刻讀一次存儲(chǔ)標(biāo)志位確認(rèn)已經(jīng)寫(xiě)成功。這個(gè)斷言放在量產(chǎn)固件里也是一種保護(hù)防止用戶在配網(wǎng)后因設(shè)備重啟出現(xiàn)“已配網(wǎng)變未配網(wǎng)”的詭異現(xiàn)象。5. 抓包分析的關(guān)鍵姿勢(shì)把beacon從空中釘在紙上5.1 抓包前的準(zhǔn)備工作和過(guò)濾條件設(shè)置調(diào)試藍(lán)牙Mesh抓包能力是必須的。不要靠“我覺(jué)得應(yīng)該沒(méi)問(wèn)題”來(lái)排查直接把空中報(bào)文拿下來(lái)看很多問(wèn)題當(dāng)場(chǎng)就清楚了。抓Unprovisioned Device Beacon準(zhǔn)備工作其實(shí)就那么幾項(xiàng)抓包工具支持至少3個(gè)廣播信道的同時(shí)監(jiān)聽(tīng)天線靠近設(shè)備周圍少一些其他2.4GHz設(shè)備。抓包開(kāi)始后先不做過(guò)濾地監(jiān)聽(tīng)一段時(shí)間確認(rèn)能看到設(shè)備發(fā)出的其他廣播再添加過(guò)濾條件。過(guò)濾時(shí)我是直接過(guò)濾廣播類型0x29或者過(guò)濾beacon的AD Type字段。具體到抓包軟件里通常是通過(guò)自定義AD Type過(guò)濾表達(dá)式實(shí)現(xiàn)的不同抓包工具寫(xiě)法略有不同但原理都是匹配ad_type0x29。這里特別提醒很多抓包工具默認(rèn)只顯示設(shè)置了“可連接廣播”標(biāo)志的數(shù)據(jù)包而Unprovisioned Device Beacon不一定包含Connectable標(biāo)志容易被隱藏掉。如果發(fā)現(xiàn)抓不到先檢查工具的顯示過(guò)濾條件把所有廣播類型顯示出來(lái)再看。5.2 如何從抓包結(jié)果判斷廣播是否健康抓包結(jié)果里最值得關(guān)注的三個(gè)指標(biāo)是廣播間隔的穩(wěn)定性、RSSI的波動(dòng)范圍以及包內(nèi)數(shù)據(jù)的一致性。廣播間隔方面如果設(shè)定值是200ms實(shí)際抓包發(fā)現(xiàn)間隔忽長(zhǎng)忽短、甚至出現(xiàn)幾百毫秒的空檔說(shuō)明設(shè)備端的廣播調(diào)度有問(wèn)題可能被其他高優(yōu)先級(jí)任務(wù)搶占。RSSI波動(dòng)大說(shuō)明設(shè)備天線和抓包器之間的距離或方位在變化或者反射干擾嚴(yán)重這時(shí)候就要調(diào)整物理位置再測(cè)。數(shù)據(jù)一致性方面我遇到過(guò)設(shè)備廣播里的Device UUID和它實(shí)際調(diào)試口讀出來(lái)的UUID對(duì)不上后來(lái)發(fā)現(xiàn)是同一條SDK代碼路徑下有兩份UUID配置初始化時(shí)用了舊的緩存。這種問(wèn)題不抓包根本發(fā)現(xiàn)不了通過(guò)對(duì)比beacon里的UUID和固件配置的UUID就能迅速定位。5.3 結(jié)合協(xié)議棧日志做交叉驗(yàn)證抓包只解決了一部分問(wèn)題另一部分要靠設(shè)備端協(xié)議棧日志。拿配網(wǎng)失敗的情況舉例beacon在空中反復(fù)發(fā)出配網(wǎng)器也掃到了但配網(wǎng)流程中途斷開(kāi)。這時(shí)候抓包能告訴你的只是“連接建立失敗”或“某條消息超時(shí)”但具體是哪一層的狀態(tài)機(jī)出了問(wèn)題通常要看設(shè)備端日志里的狀態(tài)轉(zhuǎn)換記錄。聯(lián)合分析時(shí)我習(xí)慣把抓包時(shí)間戳和SDK日志時(shí)間戳對(duì)齊先看抓包里配網(wǎng)器發(fā)送Invite的時(shí)間再在SDK日志里找設(shè)備收到Invite的時(shí)間。如果兩者相差超過(guò)幾百毫秒重點(diǎn)看設(shè)備端廣播接收窗口是否被關(guān)閉如果設(shè)備端收到了但沒(méi)回復(fù)重點(diǎn)看協(xié)議棧狀態(tài)機(jī)是否卡在某個(gè)中間狀態(tài)。時(shí)間戳對(duì)齊這塊很多日志默認(rèn)打印的是系統(tǒng)啟動(dòng)后的相對(duì)時(shí)間需要換算成Unix時(shí)間戳或帶上RTC時(shí)間不然兩邊對(duì)不上。我一般會(huì)在調(diào)試固件里增加一個(gè)啟動(dòng)標(biāo)志日志打印當(dāng)前的秒級(jí)時(shí)間戳方便和抓包時(shí)間對(duì)應(yīng)。6. 經(jīng)驗(yàn)沉淀幾句不一定寫(xiě)進(jìn)文檔的實(shí)話6.1 關(guān)于廣播參數(shù)的合作經(jīng)驗(yàn)廣播間隔和功耗的關(guān)系很多人只看理論值但實(shí)際做產(chǎn)品時(shí)的權(quán)衡更多。默認(rèn)廣播間隔100ms單次廣播功耗大概0.5秒等效電流的幾分之一看似不夸張但如果一個(gè)設(shè)備被放在貨架上無(wú)人配網(wǎng)一年下來(lái)累積的功耗相當(dāng)可觀。我后來(lái)在量產(chǎn)項(xiàng)目里用的是兩段式策略開(kāi)機(jī)或復(fù)位后2分鐘內(nèi)以200ms間隔廣播方便用戶快速配網(wǎng)之后如果一直沒(méi)被配網(wǎng)切換到1秒或2秒間隔同時(shí)降低廣播發(fā)射功率。這個(gè)策略在減弱功耗的同時(shí)還要保證配網(wǎng)器靠近設(shè)備的時(shí)候能發(fā)現(xiàn)。具體的間隔數(shù)值需要根據(jù)產(chǎn)品形態(tài)和電池容量來(lái)計(jì)算沒(méi)有放之四海而皆準(zhǔn)的答案。6.2 不同SDK實(shí)現(xiàn)里的個(gè)性差異不同廠商的藍(lán)牙Mesh SDK對(duì)Unprovisioned Device Beacon的實(shí)現(xiàn)有不少細(xì)節(jié)差異。有的SDK要求開(kāi)發(fā)者在使用配網(wǎng)功能前顯式初始化beacon參數(shù)否則默認(rèn)不廣播有的SDK則把beacon和可發(fā)現(xiàn)模式綁定關(guān)閉可發(fā)現(xiàn)模式就會(huì)連beacon一起關(guān)閉。這就導(dǎo)致一個(gè)問(wèn)題從一個(gè)平臺(tái)遷移到另一個(gè)平臺(tái)時(shí)不能只看配網(wǎng)主流程的API還得把beacon初始化、OOB配置、廣播參數(shù)這些邊角功能全部檢查一遍。我最開(kāi)始做跨平臺(tái)移植的時(shí)候就吃過(guò)這個(gè)虧原來(lái)在某芯片上跑得好好的工程換到另一家的SDK后死活掃不到設(shè)備最后發(fā)現(xiàn)是beacon初始化被另一個(gè)功能函數(shù)覆蓋了。6.3 還能怎么玩URI Hash與近場(chǎng)配網(wǎng)研究Unprovisioned Device Beacon不只是為了配網(wǎng)能跑通它還可以承載一些產(chǎn)品化的玩法。比如通過(guò)URI Hash配網(wǎng)器可以在掃描階段就識(shí)別出這是一臺(tái)燈具還是傳感器自動(dòng)彈出對(duì)應(yīng)的配置頁(yè)面省去用戶手動(dòng)選擇設(shè)備類型的步驟。還有一種比較實(shí)用的擴(kuò)展思路是結(jié)合RSSI做距離門限。利用beacon廣播的RSSI強(qiáng)弱當(dāng)配網(wǎng)器靠近某臺(tái)設(shè)備到一定距離時(shí)才會(huì)觸發(fā)配網(wǎng)這樣可以防止在設(shè)備密集環(huán)境下誤配到隔壁的設(shè)備。這種方案對(duì)廣播功放射頻鏈路一致性要求高需要做相對(duì)復(fù)雜的校準(zhǔn)但在一些高端產(chǎn)品場(chǎng)景里體驗(yàn)提升非常明顯。現(xiàn)在回看Unprovisioned Device Beacon它不過(guò)是一個(gè)只有二十來(lái)字節(jié)的廣播包卻在Mesh網(wǎng)絡(luò)的入口處扮演著無(wú)可替代的角色。很多Mesh配置問(wèn)題追根溯源到最后都是回到了這個(gè)小小的beacon上。分享這些內(nèi)容也是希望大家在調(diào)Mesh配網(wǎng)時(shí)先把這個(gè)“最初的招呼”打好再談后面那些復(fù)雜的加密和握手會(huì)順手很多。