android ble mesh,Android 蓝牙Mesh组网代码详解
文章目錄前言Mesh組網(wǎng)基本理解掃描設(shè)備組網(wǎng)meshAddress添加與重連UUID連接登錄修改信息控制與接收設(shè)備數(shù)據(jù)總結(jié)
前言
上面的幾篇文章都是在說(shuō)Android網(wǎng)絡(luò)編程方面的內(nèi)容,我本來(lái)就有打算做成一個(gè)系列。但最近因?yàn)楣ぷ鞯脑?#xff0c;一直在研究藍(lán)牙m(xù)esh組網(wǎng)對(duì)藍(lán)牙設(shè)備進(jìn)行控制,研究了近兩個(gè)星期,總算有了點(diǎn)自己的理解。先對(duì)藍(lán)牙Mesh 組網(wǎng)做一個(gè)總結(jié),下面的文章會(huì)繼續(xù)寫(xiě)Android 網(wǎng)絡(luò)編程方面的內(nèi)容。網(wǎng)上關(guān)于Mesh 組網(wǎng)的理論解釋倒是很多,但是很少有關(guān)于Android 代碼具體實(shí)現(xiàn)的,這篇文章將基于Android Mesh 組網(wǎng)的代碼實(shí)現(xiàn)進(jìn)行講解,希望能帶給大家一些幫助。
Mesh組網(wǎng)基本理解
藍(lán)牙技術(shù)聯(lián)盟寫(xiě)了解密藍(lán)牙m(xù)esh系列,一共10篇文章 講述了藍(lán)牙m(xù)esh理論內(nèi)容以及整個(gè)流程 ,想要詳細(xì)了解的可以點(diǎn)擊查看。下面我們簡(jiǎn)單介紹下Mesh組網(wǎng)到底是什么:
MESH是一種新型的無(wú)線網(wǎng)絡(luò)架構(gòu),藍(lán)牙Mesh組網(wǎng)內(nèi)每臺(tái)設(shè)備均通過(guò)低功耗藍(lán)牙無(wú)線連接進(jìn)行通信,而這些設(shè)備被稱之為節(jié)點(diǎn)。每個(gè)節(jié)點(diǎn)都能發(fā)送和接收消息,消息能夠在節(jié)點(diǎn)之間被中繼,從而讓消息傳輸至比無(wú)線電波正常傳輸距離更遠(yuǎn)的位置。歸結(jié)成一句話:藍(lán)牙Mesh組網(wǎng) 就是一種在同一個(gè)網(wǎng)絡(luò)內(nèi)任意藍(lán)牙設(shè)備都進(jìn)行數(shù)據(jù)交互的技術(shù)。這樣的話,APP 只要能發(fā)現(xiàn)組網(wǎng)內(nèi)的任何一臺(tái)設(shè)備,就能由設(shè)備發(fā)現(xiàn)組網(wǎng)內(nèi)的其他Mesh設(shè)備,并和任何一臺(tái)設(shè)備建立連接并控制。
其實(shí),我對(duì)藍(lán)牙Mesh 的組網(wǎng)也僅僅限于上面的理解。作為一個(gè)Android 開(kāi)發(fā)人員,我更關(guān)注的是Android 代碼到底如何去實(shí)現(xiàn)藍(lán)牙設(shè)備的組網(wǎng)。在網(wǎng)上也找到了一些項(xiàng)目和代碼,仔細(xì)研究了下也是很迷茫。后來(lái)找到了泰凌微提供的藍(lán)牙Mesh燈項(xiàng)目以及開(kāi)放的Mesh 組網(wǎng)流程的源碼,才真正的算是實(shí)現(xiàn)了Android 組網(wǎng)。我將這個(gè)資料上傳到了百度網(wǎng)盤(pán) ,提取碼是6i57。也上傳到了資源,點(diǎn)擊即可下載,里面有一個(gè)Android Mesh組網(wǎng)的項(xiàng)目及具體源碼、SDK開(kāi)發(fā)手冊(cè)以及加密手冊(cè)。當(dāng)然,這個(gè)項(xiàng)目的知識(shí)產(chǎn)權(quán)還是歸泰凌微所有,如果有任何侵權(quán)行為聯(lián)系本人,本人將立即下架這兩個(gè)項(xiàng)目,發(fā)布的原因還是想給大家普及一下Android 如何實(shí)現(xiàn)Mesh 組網(wǎng)的,沒(méi)有任何盈利行為。
掃描設(shè)備
因?yàn)橄旅娴姆治鍪腔谏厦骓?xiàng)目的代碼去分析的,所以需要你們下載下來(lái)項(xiàng)目跑起來(lái)。
無(wú)論是連接已經(jīng)完成組網(wǎng)設(shè)備還是將一個(gè)待組網(wǎng)設(shè)備進(jìn)行組網(wǎng),APP 做的第一步永遠(yuǎn)是掃描,掃描到所有的藍(lán)牙設(shè)備,然后拿到指定的Mesh組網(wǎng)的設(shè)備進(jìn)行組網(wǎng)操作。下面是代碼分析:
在掃描界面執(zhí)行: startScan(params) 啟動(dòng)掃描,然后會(huì)執(zhí)行一個(gè)循環(huán)任務(wù)EventLoopTask,在循環(huán)任務(wù)中每200毫秒查詢一次狀態(tài),然后 startLeScan() 方法中判斷設(shè)備是否正在掃描,如果沒(méi)有,則在LeBluetooth類中開(kāi)啟掃描startScan()。
在注冊(cè)TelinkLightService的時(shí)候,會(huì)創(chuàng)建一個(gè)LightAdapter并啟動(dòng),會(huì)設(shè)置設(shè)備的掃描結(jié)果回調(diào)setLeScanCallback(LeScanCallback callback),然后當(dāng)上面的掃描開(kāi)啟后,會(huì)將掃描得到的設(shè)備返回的這個(gè)回調(diào)中的onLeScan()方法中.在這個(gè)方法中,會(huì)先對(duì)設(shè)備本身返回的信息進(jìn)行處理和判斷,符合標(biāo)準(zhǔn)的設(shè)備返回到在掃描界面設(shè)置監(jiān)聽(tīng)的performed方法中的,然后執(zhí)行onLeScan(),掃描這一步就完成了。
掃描完拿到三個(gè)信息 device rssi 以及scanRecord 。藍(lán)牙設(shè)備的地址可以根據(jù)device.getAddress()直接獲取 比如說(shuō)我拿到的燈設(shè)備 scanRecord 的數(shù)據(jù)如下:
02:01:05:05:09:4D:65:73:68:09:FF:11:02:11:02:35:43:68:38:1E:FF:11:02:11:02:35:43:68:38:21:43:01:35:00:10:19:44:45:4C:20:68:73:65:4D:20:47:53:54:42:4A:00:00:00:00:00:00:00:00:00:00:00:00
? 在DefaultAdvertiseDataFilter類中可以看到 有meshName,meshAddress,meshUUID,productUUID等數(shù)據(jù)。很明顯我們可以根據(jù)這些數(shù)據(jù)分析當(dāng)前設(shè)備在哪個(gè)mesh 下,地址又是什么。
總結(jié):執(zhí)行SDK提供的開(kāi)始掃描接口startScan()的時(shí)候,可以從設(shè)備發(fā)現(xiàn)的回調(diào)中拿到具體的藍(lán)牙設(shè)備和廣播。mac 地址和設(shè)備名稱等信息可以從設(shè)備中拿到,而設(shè)備所屬的Mesh 組網(wǎng)名稱、設(shè)備的MeshAddress(設(shè)備在組網(wǎng)內(nèi)的唯一標(biāo)識(shí),通訊地址)等信息可以在廣播中獲取到。其中productUUID是指的產(chǎn)品類型,可以在設(shè)備中自定義這個(gè)類型。而meshUUID則是廠商默認(rèn)設(shè)置的值,至于status 這個(gè)值是廠商的預(yù)留值,也是可以在設(shè)備中自定義的信息,總的來(lái)說(shuō),在這個(gè)APP 的代碼中,并沒(méi)有實(shí)際用到這三個(gè)參數(shù)。
組網(wǎng)
meshAddress
在onLeScan() 方法里,會(huì)調(diào)用一個(gè)mesh.getDeviceAddress() 的方法,這個(gè)方法很重要,這里面拿到的meshAddress就是后面要修改新加入組網(wǎng)設(shè)備的meshAddress,他在后面會(huì)被設(shè)為newMeshAddress然后保存下來(lái)。因?yàn)樵谒{(lán)牙m(xù)esh組網(wǎng)下,meshAddress是用來(lái)確定設(shè)備的,他在這個(gè)組網(wǎng)內(nèi)是唯一固定的。那這個(gè)方法實(shí)現(xiàn)的邏輯是怎樣的呢?比如說(shuō)要加入一個(gè)新設(shè)備要加入當(dāng)前的組網(wǎng),不管他原先的meshAddress是多少 ,只看我當(dāng)前組網(wǎng)下的meshAddress。比如說(shuō)有兩個(gè)設(shè)備,地址分別是 1、3,在這個(gè)方法里,會(huì)遍歷1-254的值,然后就會(huì)返回一個(gè)2 ,這個(gè)2就是要設(shè)置的新meshAddress。meshAddress的范圍就是1-254,當(dāng)然了你也可以修改這個(gè)范圍。
添加與重連
組網(wǎng)的時(shí)候,SDK提供了兩個(gè)接口,一個(gè)是添加新的設(shè)備進(jìn)行組網(wǎng),調(diào)用的是TelinkLightService.Instance().updateMesh(params);更新接口,這個(gè)接口能夠更改設(shè)備本身出廠時(shí)的參數(shù)meshName、password、ltk三個(gè)信息,這三個(gè)信息修改成功, 就標(biāo)志著設(shè)備已經(jīng)組?網(wǎng)成功,將設(shè)備成功加入到新的組網(wǎng)下。另一個(gè)是如果當(dāng)前設(shè)備的meshName,password是你要組?網(wǎng)的名稱,可以執(zhí)?**TelinkLightService.Instance().autoConnect(connectParams);**自動(dòng)重連接口,直接把APP 跟設(shè)備連接起來(lái)。
UUID
在組網(wǎng)之前,我們需要知道UUID。UUID是根據(jù)一定算法,計(jì)算得到的一長(zhǎng)串?dāng)?shù)字,這個(gè)數(shù)字的產(chǎn)生使用了多種元素,所以使得這串?dāng)?shù)字不會(huì)重復(fù),每次生成都會(huì)產(chǎn)生不一樣的序列,所以可以用來(lái)作為唯一標(biāo)識(shí)。
在藍(lán)牙協(xié)議中,UUID被用來(lái)標(biāo)識(shí)藍(lán)牙設(shè)備所提供的服務(wù),并非是標(biāo)識(shí)藍(lán)牙設(shè)備本身哦,一個(gè)藍(lán)牙設(shè)備可以提供多種服務(wù),比如A2DP(藍(lán)牙音頻傳輸)、HEADFREE(免提)、PBAP(電話本)、SPP(串口通信)等等,每種服務(wù)都對(duì)應(yīng)一個(gè)UUID,其中在藍(lán)牙協(xié)議棧里,這些默認(rèn)提供的profile是都有對(duì)應(yīng)的UUID的,也就是默認(rèn)的UUID,比如SPP,00001101-0000-1000-8000-00805F9B34FB就是一個(gè)非常 well-known的UUID,基本上所有的藍(lán)牙板不修改的話都是這個(gè)值。但是,不同的設(shè)備也不同的UUID,如果是與一個(gè)藍(lán)牙開(kāi)發(fā)板進(jìn)行通信,需要APP 和 藍(lán)牙設(shè)備的UUID 保持一致。而APP代碼中的UuidInformation類里面就可以設(shè)置你要控制的低功耗藍(lán)牙設(shè)備的UUID。一般都要修改服務(wù)、狀態(tài)通知、控制、OTA、加密這五個(gè)UUID。下面進(jìn)行的登錄,修改參數(shù)、控制設(shè)備等等操作都需要UUID 的驗(yàn)證。
下面我們主要講一下更新接口的實(shí)現(xiàn),其實(shí)自動(dòng)重連接口就是比更新接口少了修改設(shè)備信息這一步。
連接
發(fā)現(xiàn)設(shè)備后,拿到要組網(wǎng)的設(shè)備的本身的信息,然后就開(kāi)始進(jìn)行連接了。其實(shí)就是走的低功耗藍(lán)牙設(shè)備的connectGatt(this, false, mGattCallback); 連接方法。
更新參數(shù)執(zhí)行updateMesh()?法來(lái)更新設(shè)備的meshName、password、ltk,也還是會(huì)執(zhí)?行一個(gè)循環(huán)任務(wù) EventLoopTask,在循環(huán)任務(wù)中每200毫秒查詢一次狀態(tài),然后update()方法中進(jìn)行connect(),然后在LightController類中執(zhí)行connect(),最終會(huì)執(zhí)行Peripheral類的connect()?法,然后通過(guò)此BluetoothDevice的connectGatt(this, false, mGattCallback)方法獲取設(shè)備連接。?論當(dāng)連接上設(shè)備或者失去連接時(shí)會(huì)回調(diào)onConnectionStateChange(),當(dāng)連接成功后調(diào)用discoverServices函數(shù)嘗試發(fā)現(xiàn)服務(wù),當(dāng)設(shè)備是否找到服務(wù)時(shí),會(huì)回調(diào)onServicesDiscovered()函數(shù),然后會(huì)在LightPeripheral類中的onServicesDiscovered()回調(diào)給LightController,最后發(fā)給 LightAdapter類CONNECT_SUCCESS. 連接成功后會(huì)執(zhí)行登錄的?法。
登錄
登錄的過(guò)程是一個(gè)比較復(fù)雜的過(guò)程,涉及到多次的加密驗(yàn)證。這個(gè)驗(yàn)證之間的過(guò)程就會(huì)用到我們上面說(shuō)的服務(wù)特征值UUID以及加密特征值UUID。
在LightAdapter類執(zhí)行登錄login的方法,最終的實(shí)現(xiàn)是在LightController類中的login方法.參考了BLE_LIGHT加密流程簡(jiǎn)介V1.9.pdf文檔,登錄校驗(yàn)的具體實(shí)現(xiàn)如下:
根據(jù) meshName、password、randm 這 3 個(gè)參數(shù)生成一個(gè) sk,然 后把 randm 和生成的 sk 的低 8 個(gè) byte(校驗(yàn)用)一起發(fā)送給設(shè)備
設(shè)備獲取到發(fā)過(guò)來(lái)的 randm 并和 BLE Light 本身存儲(chǔ)的 meshname 和 password 進(jìn)行加密獲取一個(gè) sk,將生成的 sk 的低 8Byte 和 Master 發(fā)過(guò)來(lái)的 sk 進(jìn)行比較,如果正確,則表示認(rèn)證成功。
設(shè)備也會(huì)隨機(jī)生成8Byte的 rands、以及本地存儲(chǔ)的 mesh name、password 這 3 個(gè)參數(shù)加密生成一個(gè) sk,會(huì)把sk 和 rands 傳給APP,然后在本地會(huì)根據(jù) randm、rands、meshname、password 共同生成一個(gè)新的sk,后續(xù)的加密和解密都將使用剛剛生成的 sk。
APP 拿到設(shè)備發(fā)過(guò)來(lái)的sk后會(huì)進(jìn)行校驗(yàn),校驗(yàn)成功后獲取8Byte的 rands,并根據(jù)該 rands 和randm、mesh name、password共同生成一個(gè) sk,此時(shí),APP 和 設(shè)備 兩邊的 sk 都是一樣的,也就可以進(jìn)行正常的加密和解密,同時(shí)的,登錄的過(guò)程也就完成了。
修改信息
我上面說(shuō)過(guò),加新設(shè)備進(jìn)行組網(wǎng)的過(guò)程就是修改meshName、password、ltk,這三個(gè)參數(shù)的過(guò)程。其實(shí)這么說(shuō)也并不是特別準(zhǔn)確,其實(shí)在修改這三個(gè)參數(shù)之前還需要對(duì)比meshAddress(就是掃描設(shè)備拿到的meshAddress)與上面保存的newMeshAddress 要不要修改,因?yàn)槲覀兩厦嬲f(shuō)過(guò),因?yàn)樵谒{(lán)牙m(xù)esh組網(wǎng)下,meshAddress是用來(lái)確定設(shè)備的,他在這個(gè)組網(wǎng)內(nèi)是唯一固定的。修改成功后才能進(jìn)行下面三個(gè)參數(shù)的修改,這三個(gè)參數(shù)修改完成就標(biāo)志這新設(shè)備已經(jīng)成功組網(wǎng)。
上面我說(shuō)到LTK,可能有的朋友不知道這個(gè)是什么東西,meshName、password都很好理解,是mesh 組網(wǎng)的名稱和密碼,而LTK 是節(jié)點(diǎn)之間的通信秘鑰,只要LTK一致,同一個(gè)組網(wǎng)間的設(shè)備就能正常通信。但是在代碼中updateMesh(params)方法中,我們并沒(méi)有給LTK賦值,所以當(dāng)我們?cè)O(shè)置的時(shí)候?qū)⑹褂脧S商默認(rèn)LTK值。如果要修改自定義的LTK,可以調(diào)用params.setLtk() 方法進(jìn)行賦值。
下面是代碼分析:
登錄的sk校驗(yàn)會(huì)出現(xiàn)在LightController類的LoginCommandCallback里面,然后在LightAdapter里面的ConnectionListener() 返回一個(gè)登錄成功或者失敗的回調(diào)。登錄成功后要修改meshName, password, ltk這三個(gè)信息,這三個(gè)信息就是組網(wǎng)的標(biāo)志。修改的過(guò)程發(fā)生在LightController類的reset方法,會(huì)先判斷設(shè)備的meshAddress要不要修改,如果要修改的話就先修改meshAddress,然后在onDeviceAddressNotify()方法里繼續(xù)執(zhí)行reset方法。通過(guò)加密的方法將這三個(gè)參數(shù)發(fā)送給設(shè)備,具體的加密過(guò)程也可以參照上面的BLE_LIGHT加密流程簡(jiǎn)介V1.9.pdf 文檔去解析下,最后發(fā)發(fā)送了一個(gè)重新檢查的命令,等待設(shè)備解密并修改完成發(fā)出的確認(rèn)信息就完成了信息的修改。修改命令的回調(diào)都在ResetCommandCallback里,收到最后的TAG_RESET_MESH_CHECK的確認(rèn)后,繼續(xù)往下執(zhí)行,會(huì)發(fā)出一個(gè)RESET_MESH_SUCCESS事件 ,然后在ResetMeshListener的回調(diào)里設(shè)置STATUS_UPDATE_MESH_COMPLETED,表明已完成信息更新,掃描到的這個(gè)設(shè)備組網(wǎng)完成,最后在掃描界面onDeviceStatusChanged的方法里面繼續(xù)執(zhí)行加燈操作,直到掃不到設(shè)備。
控制與接收設(shè)備數(shù)據(jù)
控制與接收設(shè)備數(shù)據(jù)這里的代碼就比較簡(jiǎn)單了,都有特定的方法去實(shí)現(xiàn),唯一需要注意的一點(diǎn)就是發(fā)送數(shù)據(jù)的協(xié)議,一定要是當(dāng)前設(shè)備的協(xié)議,否則無(wú)法進(jìn)行控制。具體的實(shí)現(xiàn)可以參照下面的流程:
總結(jié)
以上就是藍(lán)牙Mesh 組網(wǎng)的整個(gè)流程了,下面引用一張我們ios 同事畫(huà)的流程圖理解一下:
喜歡這篇文章或者對(duì)你有幫助的話希望能點(diǎn)個(gè)贊!
總結(jié)
以上是生活随笔為你收集整理的android ble mesh,Android 蓝牙Mesh组网代码详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 春江晓景图是谁画的呢?
- 下一篇: 眼手术多少钱啊?