最近需要为一款手环开发一个app,之前也开发过手环,但是开发的接口什么的都是手环供应商提供的,开发起来相对简单了很多。不过这次就没那么幸运了,手环提供商仅仅给了简单的技术文档,而且还是纯英文。废话不多说了。
首先,大致情景。打开手机app,扫描蓝牙设备,扫描到手环以后连接手环,手环上传数据。这个时候,手机就是中心设备(Central ),而手环就叫做外围设备(Peripheral )。
直接上代码,首先实现两个代理CBCentralManagerDelegate 和 CBPeripheralDelegate。
1. 扫描,代码如下:
[_centralManager scanForPeripheralsWithServices:nil options:nil];
_centralManager的类型为CBCentralManager,扫描到设备以后就会调用下边的方法
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI;
在该方法中就可以实现连接了。
2. 连接,代码如下:
[_centralManager connectPeripheral:peripheral options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];
连接成功以后会调用下边的方法
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral;
在该方法中就可以来发现手环提供的服务了。
3. 发现服务,代码如下:
[_peripheral discoverServices:nil];
发现服务成功以后会调用下边的代理方法
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError*)error;
在该方法中就可以来读取服务的特征之。
4. 读取特征,代码如下:
[_peripheral discoverCharacteristics:nil forService:service];
读取到特征之以后,就会调用下边的代理方法
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error;
好的,这个时候我们就拿到特征了.
5. 读取特征值。读取特征值的方法有两种,
一种是直接读取,例如
[peripheral readValueForCharacteristic:characteristic];
读取成功以后会调用
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
另外一种,是外围设备以通知的形式向中心设备发数据,或者我们也可以叫做广播(不知道这样叫对不对),收到数据以后就会调用
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
characteristic.value就是我们读取到的数据,类型为NSData,然后就可以根据自己的需求来处理数据了。
上边我们也说了,读取特征值的方式有两种,一种直接读取,另外一种是以通知的形式读取。不过有时候我们需要这样,比如,我连接成功以后,并不是马上读取特征值,而是通过向设备发送命令,发送命令的代码如下:
//我要发送的命令是“0x01”
uint8_t val = 0x01;
NSData* valData = [NSData dataWithBytes:(void*)&val length:sizeof(val)];
[_peripheral writeValue:valData forCharacteristic:_commondCharacteristictype:CBCharacteristicWriteWithResponse];
一般情况下,用来接收命令的特征和收到命令返回数据的特征是不同的,比如我这里接收命令的特征是_commondCharacteristic,而收到命令返回数据的特征是_realTimeCharacteristic;当然了,这些都是文档比较详细的时候是这么做,这几天又遇到了一个奇葩的,一款蓝牙血糖仪,只有命令格式和返回的数据格式,但是没有特征值的介绍,没有特征值介绍?那怎样才能知道哪个是接收命令的,哪个是发送数据的,这个时候,就只能一个一个尝试了。不过尝试有一个比较快的方式,就是所有的特征值都写一遍命令,所有的特征值都取一下数据,这个时候肯定能取到数据,如果取不到,要么命令有问题,要么设备有问题,后者请联系你的上级。最后过滤特征值,然后拿到你想要的结果。
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
if (error) {
NSLog(@"didWriteValueForCharacteristic error %@", error);
return;
}
[peripheral setNotifyValue:YES forCharacteristic:_realTimeCharacteristic];
}