最近需要为一款手环开发一个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];  
}