万物互联的物联网时代的已经来临,ble蓝牙开发在其中扮演着举重若轻的角色。最近刚好闲一点,抽时间梳理下这块的知识点。
涉及ble蓝牙通讯的客户端(开启、扫描、连接、发送和接收数据、分包解包)和服务端(初始化广播数据、开始广播、配置Services、Server回调 *** 作)整个环节以及一些常见的问题即踩过的一些坑。
比如
1、在Android不同版本或不同手机的适配问题,扫描不到蓝牙设备
2、如何避免ble蓝牙连接出现133错误?
3、单次写的数据大小有20字节限制,如何发送长数据
蓝牙有传统(经典)蓝牙和低功耗蓝牙BLE(Bluetooth Low Energy)之分,两者的开发的API不一样,本文主讲Ble蓝牙开发,传统蓝牙不展开,有需要的可以自行了解。
相对传统蓝牙,BLE低功耗蓝牙,主要特点是快速搜索,快速连接,超低功耗保持连接和数据传输。
客户端
服务端
Android43(API Level 18)开始引入BLE的核心功能并提供了相应的 API。应用程序通过这些 API 扫描蓝牙设备、查询 services、读写设备的 characteristics(属性特征)等 *** 作。
BLE蓝牙协议是GATT协议, BLE相关类不多, 全都位于androidbluetooth包和androidbluetoothle包的几个类:
androidbluetooth
BluetoothGattService 包含多个Characteristic(属性特征值), 含有唯一的UUID作为标识
BluetoothGattCharacteristic 包含单个值和多个Descriptor, 含有唯一的UUID作为标识
BluetoothGattDescriptor 对Characteristic进行描述, 含有唯一的UUID作为标识
BluetoothGatt 客户端相关
BluetoothGattCallback 客户端连接回调
BluetoothGattServer 服务端相关
BluetoothGattServerCallback 服务端连接回调
androidbluetoothle
AdvertiseCallback 服务端的广播回调
AdvertiseData 服务端的广播数据
AdvertiseSettings 服务端的广播设置
BluetoothLeAdvertiser 服务端的广播
BluetoothLeScanner 客户端扫描相关(Android50新增)
ScanCallback 客户端扫描回调
ScanFilter 客户端扫描过滤
ScanRecord 客户端扫描结果的广播数据
ScanResult 客户端扫描结果
ScanSettings 客户端扫描设置
BLE设备分为两种设备: 客户端(也叫主机/中心设备/Central), 服务端(也叫从机/外围设备/peripheral)
客户端的核心类是 BluetoothGatt
服务端的核心类是 BluetoothGattServer 和 BluetoothLeAdvertiser
BLE数据的核心类是 BluetoothGattCharacteristic 和 BluetoothGattDescriptor
下面详细讲解下客户端和服务端的开发步骤流程
安卓手机涉及蓝牙权限问题,蓝牙开发需要在AndroidManifestxml文件中添加权限声明:
在搜索设备之前需要询问打开手机蓝牙:
注意: BLE设备地址是动态变化(每隔一段时间都会变化),而经典蓝牙设备是出厂就固定不变了!
通过扫描BLE设备,根据设备名称区分出目标设备targetDevice,下一步实现与目标设备的连接,在连接设备之前要停止搜索蓝牙;停止搜索一般需要一定的时间来完成,最好调用停止搜索函数之后加以100ms的延时,保证系统能够完全停止搜索蓝牙设备。停止搜索之后启动连接过程;
BLE蓝牙的连接方法相对简单只需调用connectGatt方法;
参数说明
与设备建立连接之后与设备通信,整个通信过程都是在BluetoothGattCallback的异步回调函数中完成;
BluetoothGattCallback中主要回调函数如下:
上述几个回调函数是BLE开发中不可缺少的;
当调用targetdDeviceconnectGatt(context, false, gattCallback)后系统会主动发起与BLE蓝牙设备的连接,若成功连接到设备将回调onConnectionStateChange方法,其处理过程如下:
判断newState == BluetoothGattSTATE_CONNECTED表明此时已经成功连接到设备;
mBluetoothGattdiscoverServices();
扫描BLE设备服务是安卓系统中关于BLE蓝牙开发的重要一步,一般在设备连接成功后调用,扫描到设备服务后回调onServicesDiscovered()函数,函数原型如下:
BLE蓝牙开发主要有负责通信的BluetoothGattService完成的。当且称为通信服务。通信服务通过硬件工程师提供的UUID获取。获取方式如下:
具体 *** 作方式如下:
开启监听,即建立与设备的通信的首发数据通道,BLE开发中只有当客户端成功开启监听后才能与服务端收发数据。开启监听的方式如下:
BLE单次写的数据量大小是有限制的, 通常是20字节 ,可以尝试通过requestMTU增大,但不保证能成功。分包写是一种解决方案,需要定义分包协议,假设每个包大小20字节,分两种包,数据包和非数据包。对于数据包,头两个字节表示包的序号,剩下的都填充数据。对于非数据包,主要是发送一些控制信息。
监听成功后通过向 writeCharacteristic写入数据实现与服务端的通信。写入方式如下:
其中:value一般为Hex格式指令,其内容由设备通信的蓝牙通信协议规定;
若写入指令成功则回调BluetoothGattCallback中的onCharacteristicWrite()方法,说明将数据已经发送给下位机;
若发送的数据符合通信协议,则服务端会向客户端回复相应的数据。发送的数据通过回调onCharacteristicChanged()方法获取,其处理方式如下:
通过向服务端发送指令获取服务端的回复数据,即可完成与设备的通信过程;
当与设备完成通信之后之后一定要断开与设备的连接。调用以下方法断开与设备的连接:
源码上传在CSDN上了,有需要的可以借鉴。
=====> Android蓝牙Ble通讯Demo示例源码–扫描,连接,发送和接收数据,分包解包
BLE单次写的数据量大小是有限制的,通常是20字节,可以尝试通过requestMTU增大,但不保证能成功。分包写是一种解决方案,需要定义分包协议,假设每个包大小20字节,分两种包,数据包和非数据包。对于数据包,头两个字节表示包的序号,剩下的都填充数据。对于非数据包,主要是发送一些控制信息。
总体流程如下:
1、定义通讯协议,如下(这里只是个举例,可以根据项目需求扩展)
2、封装通用发送数据接口(拆包)
该接口根据会发送数据内容按最大字节数拆分(一般20字节)放入队列,拆分完后,依次从队列里取出发送
3、封装通用接收数据接口(组包)
该接口根据从接收的数据按协议里的定义解析数据长度判读是否完整包,不是的话把每条消息累加起来
4、解析完整的数据包,进行业务逻辑处理
5、协议还可以引入加密解密,需要注意的选算法参数的时候,加密后的长度最好跟原数据长度一致,这样不会影响拆包组包
一般都是Android版本适配以及不同ROM机型(小米/红米、华为/荣耀等)(EMUI、MIUI、ColorOS等)的权限问题
蓝牙开发中有很多问题,要静下心分析问题,肯定可以解决的,一起加油;
蓝牙网关是一个集成蓝牙BLE、WiFi和以太网的网关设备,蓝牙BLE与WiFi之间通过串口实现通信,可灵活应用于各种物联网场景。蓝牙网关可以扫描周边的蓝牙BLE设备、蓝牙信标(Beacon),并将获得的信息通过WiFi或者以太网通过UDP或者TCP/IP的形式发送到服务器。蓝牙网关可以连接周边的蓝牙BLE设备,然后实现远程管理,例如:远程控制蓝牙BLE设备,接收蓝牙BLE设备发送的数据,并将其发送给服务器。一个蓝牙网关同时能够连接的BLE设备数量在7个左右,SKYLAB通过时分的方式可以进行轮流连接,达到与每个蓝牙BLE设备进行数据传输的目的。通过蓝牙BLE和WiFi之间的串口,将蓝牙BLE设备的数据通过WiFi或者以太网传送到服务器,并且将服务器端的数据传送到蓝牙BLE设备。Android 从 43(API Level 18) 开始支持低功耗蓝牙,但是只支持作为中心设备(Central)模式,这就意味着 Android 设备只能主动扫描和链接其他外围设备(Peripheral)。从 Android 50(API Level 21) 开始两种模式都支持。
低功耗蓝牙开发算是较偏技术,实际开发中坑是比较多的,网上有很多文章介绍使用和经验总结,但是有些问题答案不好找,甚至有些误导人,比如 :获取已经连接的蓝牙,有的是通过反射,一大堆判断,然而并不是对所有手机有用,关于Ble传输速率问题的解决,都是默认Android每次只能发送20个字节,然而也并不是,,,下面进入正文。
这里用的是 Android50 新增的扫描API,
这里说一下,如果做蓝牙设备管理页面,可能区分是否是已连接的设备,网上又通过反射或其他挺麻烦的 *** 作,也不见得获取到,官方Api 就有提供
与外围设备交互经常每次发的数据大于 mtu的,需要做分包处理,接收数据也要判断数据的完整性最后才返回原数据做处理,所以一般交互最少包含包长度,和包校验码和原数据。当然也可以加包头,指令还有其他完整性校验。下面分享几个公用方法:
我自己封装的一个BleUtil ,因为涉及跟公司业务关联性太强(主要是传输包的协议不同)就先不开源出来了,如果这边文章对大家有帮助反馈不错,我会考虑上传个demo到github供大家使用,
在这先给大家推荐一个不错 Demo ,里面除了没有分包,协议,和传输速率。基本的功能都有,而且调试数据到打印到界面上了。最主要是它可以用两个个手机一个当中心设备一个当外围设备调试。
首先传输速率优化有两个方向,1 外围设备传输到Android 。2 Android传输到外围设备。
我在开发中首先先使用上面那位仁兄的demo调试,两个Android 设备调试不延时,上一个成功马上下一个,最多一秒发11个20字节的包。
后来和我们的蓝牙设备调试时发现发送特别快,但是数据不完整,他蓝牙模块接收成功了,但是透传数据到芯片处理时发现不完整,我们的硬件小伙伴说因为 波特率 限制(差不多每10字节透传要耗时1ms)和蓝牙模块的buff (打印时是最多100byte,100打印的)限制,就算蓝牙模块每包都告诉你接收成功,也是没透传完就又接收了。后来通过调试每次发20K数据,最后是 Android 发是 20字节/130ms 稳定。给Android 发是 20字节/ 8ms 。 (天杀的20字节,网上都是说20字节最多了)
后来看了国外一家物联网公司总结的 Ble 吞吐量的文章(上面有连接),知道Android 每个延时是可以连续接收6个包的。就改为 120字节/ 16ms (为啥是16ms,不是每次间隔要6个包吗,怎么像间隔两次,这时因为波特率影响,多了5个包100字节,差不多 我们的单片机透传到蓝牙模块要多耗时不到10ms )
而Android 发数据可以申请 我们设备的mtu 来得到最多每次能发多少字节。延时还是130ms,即:241字节/ 130ms 提高12倍,这个速度还可以。
根据蓝牙BLE协议, 物理层physical layer的传输速率是1Mbps,相当于每秒125K字节。事实上,其只是基准传输速率,协议规定BLE不能连续不断地传输数据包,否则就不能称为低功耗蓝牙了。连续传输自然会带来高功耗。所以,蓝牙的最高传输速率并不由物理层的工作频率决定的。
在实际的 *** 作过程中,如果主机连线不断地发送数据包,要么丢包严重要么连接出现异常而断开。
在BLE里面,传输速度受其连接参数所影响。连接参数定义如下:
1)连接间隔。蓝牙基带是跳频工作的,主机和从机会商定多长时间进行跳频连接,连接上才能进行数据传输。这个连接和广播状态和连接状态的连接不是一样的意思。主机在从机广播时进行连接是应用层的主动软件行为。而跳频过程中的连接是蓝牙基带协议的规定,完全由硬件控制,对应用层透明。明显,如果这个连接间隔时间越短,那么传输的速度就增大。连接上传完数据后,蓝牙基带即进入休眠状态,保证低功耗。其是125毫秒一个单位。
2)连接延迟。其是为了低功耗考虑,允许从机在跳频过程中不理会主机的跳频指令,继续睡眠一段时间。而主机不能因为从机睡眠而认为其断开连接了。其是125毫秒一个单位。明显,这个数值越小,传输速度也高。
蓝牙BLE协议规定连接参数最小是5,即725毫秒;而Android手机规定连接参数最小是8,即10毫秒。iOS规定是16,即20毫秒。
连接参数完全由主机决定,但从机可以发出更新参数申请,主机可以接受也可以拒绝。android手机一部接受,而ios比较严格,拒绝的概率比较高。
参考:
在iOS和Android上最大化BLE吞吐量
最大化BLE吞吐量第2部分:使用更大的ATT MTU
蓝牙mesh网关适用于各种无线接入网。
蓝牙网关适用于宽带家庭网络无线接入网,蓝牙mesh网关适用于各种无线接入网;蓝牙网关具有可变性,而蓝牙mesh网关没有可变性。蓝牙网关一次只能监听一个频道,蓝牙mesh网关可以接入多个频道。
蓝牙网关的应用,能够满足物联网应用需求的蓝牙网关已广泛应用于室内定位、传感器控制、智能家居联网、物流控制、智能插座及彩灯控制方案中。
蓝牙网关的定义,蓝牙网关是一个集成蓝牙BLE、WiFi和以太网的网关设备,蓝牙BLE与WiFi之间通过串口实现通信,可灵活应用于各种物联网场景。
蓝牙:是一种无线技术标准,可实现固定设备、移动设备和楼宇个人域网之间的短距离数据交换。蓝牙技术最初由电信巨头爱立信公司于1994年创制,当时是作为RS232数据线的替代方案。蓝牙可连接多个设备,克服了数据同步的难题。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)