前言
这段时间参与了一款与蓝牙外设交互的项目, 以前没有涉及过数据传输方面的开发, 踩了不少坑, 同时也学到了很多东西. 此时, 项目也即将进入尾声, 有时间把这些记录一二. 本人才疏学浅, 如有错误,大佬轻喷.
BLE4.0开发
这方面网上的Demo一大堆, 暂时不做太多的赘述, 只对坑点做一个摘要.
- 需求使然, 要对设备的接近远离有一个比较精确的计算, 使用的方案是对蓝牙的信号强度进行分析. 然而, 信号强度的波动值较大, 很难得出较为精确的值, 于是乎需要较多的信号值进行计算, iOS可以通过
[self.peripheral readRSSI]
来读取信号值强度, 但是该方法最快1s只能返回一次, 如果需要更快速的获取信号值强度, 执行scanForPeripheralsWithServices
方法设置options参数@{CBCentralManagerScanOptionAllowDuplicatesKey:@(YES)}
, 也许iBeacon会是个不错的选择, 但是这边硬件并不支持,也没有进行实际的测试. - 获取蓝牙外设mac地址的问题, 众所周知的隐私问题, 目前iOS并不能获取到. 解决方法是让硬件工程师把mac地址写入到广播包中的
kCBAdvDataManufacturerData
这个key
中,在发现外设的回调centralManager: didDiscoverPeripheral: advertisementData: RSSI:
中的advertisementData
参数中获取. (一定要写在对应kCBAdvDataManufacturerData
的字段中, 发现该设备广播包中没有这个key
, 让硬件工程师换一个字段再试试, 各个厂家的蓝牙模块不一样, 很可能硬件工程师写错了)
数据传输
首先是平台方面的人定好了数据传输协议, 我们按协议进行拼接, 然后使用拼接好的数据与外设进行交互.
数据传输协议一般分为包头和包体, 包体中也许还会进行类似的嵌套. 协议中会定义传输 的数据类型, 比如拼接过程中需要传入包体的长度(无符号双字节整型), 我们一般会用int
取到长度length, 这时候需要把int
转化为两个Byte.
// int转两个字节Byte
+ (NSData *)dataFromShort:(short)value {
Byte bytes[2] = {};
for (int i = 0; i < 2; i++) {
int offset = 16 - (i + 1) * 8;
bytes[i] = (Byte) ((value >> offset) & 0xff);
}
NSData *data = [[NSData alloc] initWithBytes:bytes length:2];
return data;
}
// int转四个字节Byte
+ (NSData *)dataFromInt:(int)value {
Byte bytes[4] = {};
for (int i = 0; i < 4; i++) {
bytes[i] = (Byte)(value >> (24 - i * 8));
}
NSData *data= [[NSData alloc] initW