// 扫描到外部设备后触发//多次调用的
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(nonnull CBPeripheral *)peripheral advertisementData:(nonnull NSDictionary<NSString *,id> *)advertisementData RSSI:(nonnull NSNumber *)RSSI
{
// 扫描到的外部设备
// NSString *msg = [NSString stringWithFormat:@"信号强度: %@, 外设: %@", RSSI, peripheral];
// NSLog(@"%@",msg);
if ([peripheral.name isEqualToString:@"BLE"])
{
//连接外部设备
self.peripheral = peripheral;
[central connectPeripheral:peripheral options:nil];
//停止搜索
[central stopScan];
}
}
这时候可以打开你的外设的开关,就可以通过程序搜索出来外设的名字和信号值了;
在这里可以做处理是否直接连接外设,比如ofo是以“ofo”为开头的蓝牙名称;
连接外设时要注意强引用外设,保存一下;
我们在连接上外设后,必须要停止搜索,以免影响蓝牙连接的稳定性。
//连接失败
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
NSLog(@"%@",error.localizedDescription);
[self.centralManager connectPeripheral:self.peripheral options:nil];
}
当连接失败的时候,我们要用中心端再次尝试连接我们保存的外设。
//从服务获取特征
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
NSLog(@"%@",service.characteristics);
for (CBCharacteristic *characteristic in service.characteristics)
{
NSLog(@"%@",service.characteristics);
for (CBCharacteristic *characteristic in service.characteristics)
{
// -------- 读特征的处理 --------
if ([characteristic.UUID.description isEqualToString: @"读特征的UUID名称"])
{
NSLog(@"处理读特征");
[self.peripheral readValueForCharacteristic:characteristic];
}
// -------- 写特征的处理 --------
if ([characteristic.UUID.description isEqualToString: @"写特征的UUID名称"])
{
NSLog(@"处理写特征");
//向外设发送0001命令
NSData *data = [@"0001" dataUsingEncoding:NSUTF8StringEncoding];
[self.peripheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];
self.characteristic = characteristic;
}
// -------- 订阅特征的处理 --------
if ([characteristic.UUID isEqual:[CBUUID @"订阅特征的UUID名称"]])
{
NSLog(@"处理了订阅特征");
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
}
}
这里就是真正与外设交互的地方了,一个UUID有三种属性:可读,可写,可监听。
可读属性,一般用来读取一次时使用。比如外设的名称,电量之类的,不常用。
可写属性,就是向外设发指令。这个很重要,不过当你写入失败的时候,记得更换你writeValue方法后面的type试试,有的是有回调的,用CBCharacteristicWriteWithResponse
,有的是没有回调的,用type:CBCharacteristicWriteWithoutResponse
一般都保存下可写特征,在外面写入发指令。
可监听属性,就是接收外设发送的数据了。一般实时变化的数据都要监听外设的,很重要。值得注意的是,当监听成功后,特征的Notify
属性的值会“=Yes”
,以此判断你是否监听成功了。
//获取外设发来的数据,不论是read和notify,获取数据都是从这个方法中读取
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
NSLog(@"%@",characteristic.value);
}
这里就是从外设获取数据的方法。
向外设读特征读后,该方法只调用一次;
监听外设的监听特征后,这个方法会在外设发送一个数据时调用一次,也就是说会多次调用。
可以在这个方法里做一些数据处理,然后将数据发送给服务器。
只有调用了[peripheral setNotifyValue:YES forCharacteristic:characteristic];这个监听的方法
外设的下面这个订阅方法才会走
- (void)peripheralManager:(CBPeripheralManager *)peripheral
central:(CBCentral *)central
didSubscribeToCharacteristic:(CBCharacteristic *)characteristic;
由CBPeripheralManager调用下面这个方法可以给中心端发送数据用于中心端的监听
//!注意,characteristic.value的类型是NSData,具体开发时,会根据外设协议制定的方式去解析数据
- (BOOL)updateValue:(NSData *)value
forCharacteristic:(CBMutableCharacteristic *)characteristic
onSubscribedCentrals:(NSArray<CBCentral *> *)centrals;
中心端在下面这个代理方法中接收外设发过来的数据
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error