藍牙防丟器原理、實現與Android BLE接口編程

  本文是對已實現的藍牙防丟器項目的總結,闡述藍牙防丟器的原理、實現與android客戶端的藍牙BLE接口編程。在這裏重點關注如何利用BLE接口來進行工程實現,對於BLE的協議、涉及到JNI的BLE接口內部源碼實現,筆者之後再詳細剖析。但要求讀者對BLE協議有必定的認識,如GAP、GATTprofile在BLE中的角色和做用,如何使用Service、Characteristic等。android

1、藍牙防丟器原理和產品需求編程

  藍牙防丟器的核心原理是根據接收到的藍牙設備端的無線信號強度(RSSI)來估算距離。其計算公式是:微信

  d是計算距離,RSSI是信號強度,A爲發射端和接收端相隔1米時的信號強度,n是環境衰減因子。對於不一樣的藍牙設備該值是不同的,一樣的設備在不一樣的發射功率的狀況下其信號強度也是不同的,並且對於同是1米的狀況下,環境對於信號強度也是有影響的。n是環境衰減因子,天然跟環境有關。因此在確切發射功率的狀況下,A和n對於同一款設備來講,也是一個經驗值。框架

  在實際的防丟器產品中,通常有如下功能:ide

  1. 當手機(接收端)檢測到發射端設備的距離超過必定距離時,發出告警提示,設備根據告警級別進行相應的指示,如發出不一樣頻率的音頻或者閃燈。ui

  2. 當發射設備端發現和手機端創建的鏈路斷開(意味着距離已經超過鏈接範圍)時,其會自動發出某種形式的警告。對象

 

2、藍牙防丟profile接口

      筆者以業界目前功耗最低的藍牙單芯片(Dialog公司的DA14580)來講明。針對DA14580,Dialog公司有提供開發SDK(之後會對該SDK框架進行分析,以指導開發),其中就有實現防丟profile,命名是Proximity。     該profile針對以上防丟的功能提供的Characteristic以下:開發

  1.TXP(txpower) Characteristic, 設備端須要經過主機控制接口HCI來得到發射功率參數,並以read屬性提供給master。get

  2.IAS(immediate alter service), write屬性,供master寫告警級別。當master寫入新的值時,設備端會收到write的回調,其根據告警級別進行相應告警。

  3. LLS(link loss service),write/read屬性,供master設置鏈路斷開狀況下默認的告警級別。

  RSSI經過接收端的接口來得到,並不須要設備端提供service。

  以上Characteristic都經過GATT profile提供服務,在藍牙通訊協議上,每一個Characteristic都會對應一個UUID。

 

3、android藍牙BLE接口編程

  androidBLE接口在android4.3版本以上提供。

1.   判斷當前系統是否支持BLE

  getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)

  返回真表示支持。

2.   得到藍牙適配器類

  用戶經過統一的藍牙適配器類BluetoothAdapter來使用BLE API。

  先得到藍牙管理器:

  BluetoothManagerbluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE);

  再得到藍牙適配器實例(單體對象):

  BluetoothAdaptermBluetoothAdapter = bluetoothManager.getAdapter();

3.   啓動手機藍牙硬件功能(至關於在設置界面開啓藍牙功能)

  mBluetoothAdapter.enable();

4.   開始掃描

  BluetoothAdapter.startLeScan(android.bluetooth.BluetoothAdapter.LeScanCallbackcallback)

  callback是當掃描到藍牙設備時的回調接口。實現callback中的onLeScan接口:

  @Override

      public void onLeScan(finalBluetoothDevice device, int rssi, byte[] scanRecord)

      其中,device表明掃描到的設備,能夠得到其MAC地址、設備名等等;rssi即信號強度,這是未鏈接時獲取RSSI的方法;scanRecord表明掃描設備獲得的響應參數,ibeacon即經過該參數來得到廣播內容。

      假設String bluetoothAddress = device.getAddress(),獲取藍牙48位MAC地址

5.   鏈接GATT,獲取設備端的UUID服務,並進行數據通訊交互

  經過MAC地址得到表明設備端的藍牙設備類

  BluetoothDevicedevice = mBluetoothAdapter.getRemoteDevice(bluetoothAddress);

  鏈接GATT

  BluetoothGatt mBluetoothGatt = device.connectGatt(android.content.Context context, booleanautoConnect, android.bluetooth.BluetoothGattCallback callback);

  Callback是鏈接GATT以後,全部數據交互的回調入口。分別包括:

1)設備服務發現

  @Override

          publicvoid onServicesDiscovered(BluetoothGatt gatt, int status)

  mBluetoothGatt.getServices()表明設備服務集合,

  for (BluetoothGattService gattService : mBluetoothGatt.getServices())

  對於每一個服務service,用getUuid()能夠得到服務的UUID,getCharacteristics()表明該服務的Characteristic集合。

  for(BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics)

  對於每一個Characteristic,getUuid()得到UUID,getPermissions()得到屬性權限,getValue()得到屬性值。

  在該回調中咱們只提取感興趣的三個Characteristic的UUID,對於其餘的如電池、設備服務等UUID能夠無論。

  gattCharacteristic_char5_TXP=gattCharacteristic;

      2)鏈接狀態改變

@Override

           public voidonConnectionStateChange(BluetoothGatt gatt, int status,intnewState)

      有兩種狀態,BluetoothProfile.STATE_CONNECTED表明鏈接,BluetoothProfile.STATE_DISCONNECTED表明斷開鏈接。

      3)讀回調

      @Override

           public voidonCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristiccharacteristic, intstatus)

      其對應手機端發出讀請求後,當收到設備端的數據時的回調。如

      mBluetoothGatt.readCharacteristic(gattCharacteristic_char5_TXP)

      4)設備端數據變化回調

      這裏對應設備的characteristic的屬性是notify或者indication,即至關手機端訂閱這個characteristic的值變動服務,當設備端的characteristic發生變化時,設備端會主動發出通知給手機端。

@Override

           public voidonCharacteristicChanged(BluetoothGatt gatt,

                      BluetoothGattCharacteristiccharacteristic)

           在回調中得到新的值characteristic.getValue()。

      5)獲取到RSSI值的回調

      RSSI在掃描時能夠經過掃描回調接口得到,可是在鏈接以後要不斷地使用

      mBluetoothGatt.readRemoteRssi()向底層驅動發出讀取RSSI請求,當底層獲取到新的RSSI後會進行如下回調:

      @Override

      public voidonReadRemoteRssi(BluetoothGatt gatt, int rssi, int status)

      rssi便是新的信號強度值。

      鏈接後,因爲手機和設備端的距離在發生變化,所以要不斷地讀取RSSI,實時計算二者之間的距離才能保證防丟功能的實現。

 

      Android 4.3以後的SDK有提供BLE接口使用的樣例,能夠經過研讀源碼進行理解。對防丟器的藍牙設備端和android客戶端的開發感興趣者能夠關注 微信公衆號:嵌入式企鵝圈 進行交流。謝謝!嵌入式企鵝圈分享嵌入式Linux和物聯網原創技術經驗,敬請關注:

相關文章
相關標籤/搜索