蓝牙防丢器原理、实现与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和物联网原创技术经验,敬请关注:

相关文章
相关标签/搜索