蓝牙防丢器原理、实现与Android BLE接口编程
本文是对已实现的蓝牙防丢器项目的总结,阐述蓝牙防丢器的原理、实现与android客户端的蓝牙BLE接口编程。在这里重点关注如何利用BLE接口来进行工程实现,对于BLE的协议、涉及到JNI的BLE接口内部源码实现,笔者以后再详细剖析。但要求读者对BLE协议有一定的认识,如GAP、GATTprofile在BLE中的角色和作用,如何使用Service、Characteristic等。
一、蓝牙防丢器原理和产品需求
蓝牙防丢器的核心原理是根据接收到的蓝牙设备端的无线信号强度(RSSI)来估算距离。其计算公式是:
d是计算距离,RSSI是信号强度,A为发射端和接收端相隔1米时的信号强度,n是环境衰减因子。对于不同的蓝牙设备该值是不一样的,同样的设备在不同的发射功率的情况下其信号强度也是不一样的,而且对于同是1米的情况下,环境对于信号强度也是有影响的。n是环境衰减因子,自然跟环境有关。所以在确切发射功率的情况下,A和n对于同一款设备来说,也是一个经验值。
在实际的防丢器产品中,一般有以下功能:
1. 当手机(接收端)检测到发射端设备的距离超过一定距离时,发出告警提示,设备根据告警级别进行相应的指示,如发出不同频率的音频或者闪灯。
2. 当发射设备端发现和手机端建立的链路断开(意味着距离已经超过连接范围)时,其会自动发出某种形式的警告。
二、蓝牙防丢profile
笔者以业界目前功耗最低的蓝牙单芯片(Dialog公司的DA14580)来说明。针对DA14580,Dialog公司有提供开发SDK(以后会对该SDK框架进行分析,以指导开发),其中就有实现防丢profile,命名是Proximity。 该profile针对以上防丢的功能提供的Characteristic如下:
1.TXP(txpower) Characteristic, 设备端需要通过主机控制接口HCI来获得发射功率参数,并以read属性提供给master。
2.IAS(immediate alter service), write属性,供master写告警级别。当master写入新的值时,设备端会收到write的回调,其根据告警级别进行相应告警。
3. LLS(link loss service),write/read属性,供master设置链路断开情况下默认的告警级别。
RSSI通过接收端的接口来获得,并不需要设备端提供service。
以上Characteristic都通过GATT profile提供服务,在蓝牙通信协议上,每个Characteristic都会对应一个UUID。
三、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和物联网原创技术经验,敬请关注:
蓝牙防丢器原理、实现与Android BLE接口编程的更多相关文章
- [yueqian_scut]蓝牙防丢器原理、实现与Android BLE接口编程
本文是对已实现的蓝牙防丢器项目的总结,阐述蓝牙防丢器的原理.实现与Android客户端的蓝牙BLE接口编程.在这里重点关注如何利用BLE接口来进行工程实现,对于BLE的协议.涉及到JNI的BLE接口内 ...
- Android BLE 蓝牙编程(四)
接上篇,我们已经实现了短震,长震的功能了- 现在我们需要实现点击后一直震动的功能 开始我的想法是再循环中不断执行write方法,然而这个办法行不通. 系统会报错. 那要如何实现这个想法呢?其实很简单, ...
- Android BLE 蓝牙编程(三)
上节我们已经可以连接上蓝牙设备了. 本节我们就要获取手环的电池电量和计步啦. 在介绍这个之前我们需要先了解下什么是 服务 什么是 UUID 我们记得上节中我们item监听事件的回调的返回值是Bluet ...
- Android BLE 蓝牙编程(二)
大家中秋快乐啊--哈哈,今天继续工程项目吧! 上篇我们已经实现了蓝牙设备的扫描,本篇我们来通过list展示扫描到的设备并 实现点击连接. 先贴出上篇的完整的MainActivity的方法: packa ...
- Android BLE 蓝牙编程(一)
最近在研究这个,等我有时间来写吧! 终于在端午节给自己放个假,现在就来说说关于android蓝牙ble的 最近的学习成果吧!! 需要材料(写个简单教程吧--关于小米手环的哦!嘿嘿) Android 手 ...
- android BLE Peripheral 手机模拟设备发出BLE广播 BluetoothLeAdvertiser
android 从4.3系统开始可以连接BLE设备,这个大家都知道了.iOS是从7.0版本开始支持BLE. android 进入5.0时代时,开放了一个新功能,手机可以模拟设备发出BLE广播, 这个新 ...
- Android开发之IP拨号器原理
IP拨号器,使用了Android的广播接收者(BroadCastReceiver),在广播中把已保存的ip号码放在拨打电话号码的前面(getResultData()),然后把修改后的号码设置到广播中( ...
- struts2 javaweb 过滤器、监听器 拦截器 原理
转: 过滤器.监听器 拦截器 过滤器 创建一个 Filter 只需两个步骤: (1)创建 Filter 处理类: (2)在 web.xml 文件中配置 Filter . 创建 Filter 必须实现 ...
- Struts2拦截器原理以及实例
一.Struts2拦截器定义 1. Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP的一种实现. 2. ...
随机推荐
- [作业向]tinyhttp web服务器设计及完整代码
最近看了<HTTP权威指南>和<UNP>有了写一个简单的web服务器的想法,正好这个学期没有什么课,所以就花了一个星期这样写了一个出来,鉴于本人水平有限,如果有什么设计或代码错 ...
- IIS 7完全攻略之日志记录配置(摘自网络)
IIS 7完全攻略之日志记录配置 作者:泉之源 [IT168 专稿]除了 Windows 提供的日志记录功能外,IIS 7.0 还可以提供其他日志记录功能.例如,可以选择日志文件格式并指定要记录的请求 ...
- javascript中&&和||的区别
javascript中&&和||的区别 &&和||操作符两边不是布尔类型时,系统会转换成布尔类型值再计算(空字符串.null.0都会被转成false),结果本身不变. ...
- Thrift在Windows及Linux平台下的安装和使用示例
本文章也同时发表在个人博客Thrift在Windows及Linux平台下的安装和使用示例上. thrift介绍 Apache Thrift 是 Facebook 实现的一种高效的.支持多种编程语言的R ...
- 用Qt写软件系列一:QCacheViewer(浏览器缓存查看器)
介绍 Cache技术广泛应用于计算机行业的软硬件领域.该技术既是人们对新技术探讨的结果,也是对当前软硬件计算能力的一种妥协.在浏览器中使用cache技术,可以大幅度提高web页面的响应速度,降低数据传 ...
- SQL Server视图复习
视图的好处: 第一点:使用视图,可以定制用户数据,聚焦特定的数据. 第一点:使用视图,可以定制用户数据,聚焦特定的数据. 在实际过程中,公司有不同角色的工作人员,我们以销售公司为例的话,采购人员,可以 ...
- javaScript一些函数包括调试方法(二)
Number():设法把括号里面的值,转换成一个数,转换不了为数字的话,就返回NaN. 注意:Number()函数,会拒绝任何包含,非数字字符的字符串(阿拉伯数字.一个有效的小数位.+.-符号是允许的 ...
- thread_AtomicBoolean
Boolean值的变化的时候不允许在之间插入,保持操作的原子性 它提供了原子性操作,其中exists.compareAndSet(false, true)这个操作把比较和赋值操作组成了一个原子操作,中 ...
- Winform开发框架之权限管理系统的改进
权限管理系统,一直是很多Mis系统和一些常见的管理系统所需要的,所以一般可以作为独立的模块进行开发,需要的时候进行整合即可,不需要每次从头开发,除非特殊的系统需求.我在Winform开发框架介绍中的随 ...
- C语言字符串匹配函数
C语言字符串匹配函数,保存有需要时可以用: #include <stdio.h> #include <stdlib.h> #include <string.h> # ...