[yueqian_scut]蓝牙防丢器原理、实现与Android BLE接口编程
本文是對已實現(xiàn)的藍牙防丟器項目的總結(jié),闡述藍牙防丟器的原理、實現(xiàn)與Android客戶端的藍牙BLE接口編程。在這里重點關(guān)注如何利用BLE接口來進行工程實現(xiàn),對于BLE的協(xié)議、涉及到JNI的BLE接口內(nèi)部源碼實現(xiàn),筆者以后再詳細剖析。但要求讀者對BLE協(xié)議有一定的認識,如GAP、GATTprofile在BLE中的角色和作用,如何使用Service、Characteristic等。
一、藍牙防丟器原理和產(chǎn)品需求
藍牙防丟器的核心原理是根據(jù)接收到的藍牙設(shè)備端的無線信號強度(RSSI)來估算距離。其計算公式是:
d是計算距離,RSSI是信號強度,A為發(fā)射端和接收端相隔1米時的信號強度,n是環(huán)境衰減因子。對于不同的藍牙設(shè)備該值是不一樣的,同樣的設(shè)備在不同的發(fā)射功率的情況下其信號強度也是不一樣的,而且對于同是1米的情況下,環(huán)境對于信號強度也是有影響的。n是環(huán)境衰減因子,自然跟環(huán)境有關(guān)。所以在確切發(fā)射功率的情況下,A和n對于同一款設(shè)備來說,也是一個經(jīng)驗值。
在實際的防丟器產(chǎn)品中,一般有以下功能:
1. 當手機(接收端)檢測到發(fā)射端設(shè)備的距離超過一定距離時,發(fā)出告警提示,設(shè)備根據(jù)告警級別進行相應(yīng)的指示,如發(fā)出不同頻率的音頻或者閃燈。
2. 當發(fā)射設(shè)備端發(fā)現(xiàn)和手機端建立的鏈路斷開(意味著距離已經(jīng)超過連接范圍)時,其會自動發(fā)出某種形式的警告。
?
二、藍牙防丟profile
????? 筆者以業(yè)界目前功耗最低的藍牙單芯片(Dialog公司的DA14580)來說明。針對DA14580,Dialog公司有提供開發(fā)SDK(以后會對該SDK框架進行分析,以指導開發(fā)),其中就有實現(xiàn)防丟profile,命名是Proximity。???? 該profile針對以上防丟的功能提供的Characteristic如下:
1.TXP(txpower) Characteristic, 設(shè)備端需要通過主機控制接口HCI來獲得發(fā)射功率參數(shù),并以read屬性提供給master。
2.IAS(immediate alter service), write屬性,供master寫告警級別。當master寫入新的值時,設(shè)備端會收到write的回調(diào),其根據(jù)告警級別進行相應(yīng)告警。
3. LLS(link loss service),write/read屬性,供master設(shè)置鏈路斷開情況下默認的告警級別。
RSSI通過接收端的接口來獲得,并不需要設(shè)備端提供service。
以上Characteristic都通過GATT profile提供服務(wù),在藍牙通信協(xié)議上,每個Characteristic都會對應(yīng)一個UUID。
?
三、android藍牙BLE接口編程
androidBLE接口在android4.3版本以上提供。
1.???判斷當前系統(tǒng)是否支持BLE
getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
返回真表示支持。
2.???獲得藍牙適配器類
用戶通過統(tǒng)一的藍牙適配器類BluetoothAdapter來使用BLE API。
先獲得藍牙管理器:
BluetoothManagerbluetoothManager =?getSystemService(Context.BLUETOOTH_SERVICE);
再獲得藍牙適配器實例(單體對象):
BluetoothAdaptermBluetoothAdapter = bluetoothManager.getAdapter();
3.???啟動手機藍牙硬件功能(相當于在設(shè)置界面開啟藍牙功能)
mBluetoothAdapter.enable();
4.???開始掃描
BluetoothAdapter.startLeScan(android.bluetooth.BluetoothAdapter.LeScanCallbackcallback)
callback是當掃描到藍牙設(shè)備時的回調(diào)接口。實現(xiàn)callback中的onLeScan接口:
@Override
??????public void?onLeScan(finalBluetoothDevice device,?int?rssi,?byte[] scanRecord)
????? 其中,device代表掃描到的設(shè)備,可以獲得其MAC地址、設(shè)備名等等;rssi即信號強度,這是未連接時獲取RSSI的方法;scanRecord代表掃描設(shè)備得到的響應(yīng)參數(shù),ibeacon即通過該參數(shù)來獲得廣播內(nèi)容。
????? 假設(shè)String bluetoothAddress = device.getAddress(),獲取藍牙48位MAC地址
5.???連接GATT,獲取設(shè)備端的UUID服務(wù),并進行數(shù)據(jù)通信交互
通過MAC地址獲得代表設(shè)備端的藍牙設(shè)備類
BluetoothDevicedevice = mBluetoothAdapter.getRemoteDevice(bluetoothAddress);
連接GATT
BluetoothGatt mBluetoothGatt = device.connectGatt(android.content.Context context, booleanautoConnect, android.bluetooth.BluetoothGattCallback callback);
Callback是連接GATT之后,所有數(shù)據(jù)交互的回調(diào)入口。分別包括:
1)設(shè)備服務(wù)發(fā)現(xiàn)
@Override
??????????publicvoid?onServicesDiscovered(BluetoothGatt gatt,?int?status)
mBluetoothGatt.getServices()代表設(shè)備服務(wù)集合,
for?(BluetoothGattService gattService : mBluetoothGatt.getServices())
對于每個服務(wù)service,用getUuid()可以獲得服務(wù)的UUID,getCharacteristics()代表該服務(wù)的Characteristic集合。
for(BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics)
對于每個Characteristic,getUuid()獲得UUID,getPermissions()獲得屬性權(quán)限,getValue()獲得屬性值。
在該回調(diào)中我們只提取感興趣的三個Characteristic的UUID,對于其他的如電池、設(shè)備服務(wù)等UUID可以不管。
gattCharacteristic_char5_TXP=gattCharacteristic;
????? 2)連接狀態(tài)改變
@Override
???????????public voidonConnectionStateChange(BluetoothGatt gatt,?int?status,intnewState)
????? 有兩種狀態(tài),BluetoothProfile.STATE_CONNECTED代表連接,BluetoothProfile.STATE_DISCONNECTED代表斷開連接。
????? 3)讀回調(diào)
????? @Override
???????????public voidonCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristiccharacteristic,?int?status)
????? 其對應(yīng)手機端發(fā)出讀請求后,當收到設(shè)備端的數(shù)據(jù)時的回調(diào)。如
????? mBluetoothGatt.readCharacteristic(gattCharacteristic_char5_TXP)
????? 4)設(shè)備端數(shù)據(jù)變化回調(diào)
????? 這里對應(yīng)設(shè)備的characteristic的屬性是notify或者indication,即相當手機端訂閱這個characteristic的值變更服務(wù),當設(shè)備端的characteristic發(fā)生變化時,設(shè)備端會主動發(fā)出通知給手機端。
@Override
???????????public voidonCharacteristicChanged(BluetoothGatt gatt,
????????????????????? BluetoothGattCharacteristiccharacteristic)
?????????? 在回調(diào)中獲得新的值characteristic.getValue()。
????? 5)獲取到RSSI值的回調(diào)
????? RSSI在掃描時可以通過掃描回調(diào)接口獲得,但是在連接之后要不斷地使用
????? mBluetoothGatt.readRemoteRssi()向底層驅(qū)動發(fā)出讀取RSSI請求,當?shù)讓荧@取到新的RSSI后會進行以下回調(diào):
????? @Override
??????public voidonReadRemoteRssi(BluetoothGatt gatt,?int?rssi,?int?status)
????? rssi即是新的信號強度值。
????? 連接后,由于手機和設(shè)備端的距離在發(fā)生變化,因此要不斷地讀取RSSI,實時計算兩者之間的距離才能保證防丟功能的實現(xiàn)。
轉(zhuǎn)載于:https://www.cnblogs.com/Free-Thinker/p/5559799.html
總結(jié)
以上是生活随笔為你收集整理的[yueqian_scut]蓝牙防丢器原理、实现与Android BLE接口编程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python 爬取西刺可用代理IP,自带
- 下一篇: android midi 分析,MIDI