蓝牙

iOS 蓝牙开发

2019-03-18  本文已影响0人  aCodeApe

自己之前做的蓝牙项目,刚开始的时候真是一脸蒙圈,摸索了很久踩了很多坑。不过现在想来其实也没什么难的,简单总结一下,但愿能够给初次开发的小伙伴一些帮助,当然如果有不足之处,也欢迎大家指正。

    //获取广播包中的数据
    NSData *data = advertisementData[@"kCBAdvDataManufacturerData"];
    //格式转换
    NSString *str = [self transformStringWithData:data];

    //mac地址匹配,连接设备,self.peripheralMacAddress即从后台获取的Mac地址
    if ([[self macAddressWith:str] isEqualToString:self.peripheralMacAddress]) {
       //匹配成功后进行外设连接操作
    }
  //对广播包中的数据进行格式转换
  - (NSString *)transformStringWithData:(NSData *)data{
     NSString *result;
    const unsigned char *dataBuffer = (const unsigned char *)[data bytes];
    if (!dataBuffer) {
        return nil;
    }
    NSUInteger dataLength = [data length];
    NSMutableString *hexString = [NSMutableString stringWithCapacity:(dataLength * 2)];
    for (int i = 0; i < dataLength; i++) {
        //02x 表示两个位置 显示的16进制
        [hexString appendString:[NSString stringWithFormat:@"%02lx",(unsigned long)dataBuffer[i]]];
    }
    result = [NSString stringWithString:hexString];
    
    return result;
}
//获取外设Mac地址 
- (NSString *)macAddressWith:(NSString *)aString{
    NSMutableString *macString = [[NSMutableString alloc] init];
    if (aString.length >= 16) {
        [macString appendString:[[aString substringWithRange:NSMakeRange(4, 2)] uppercaseString]];
        [macString appendString:@":"];
        [macString appendString:[[aString substringWithRange:NSMakeRange(6, 2)] uppercaseString]];
        [macString appendString:@":"];
        [macString appendString:[[aString substringWithRange:NSMakeRange(8, 2)] uppercaseString]];
        [macString appendString:@":"];
        [macString appendString:[[aString substringWithRange:NSMakeRange(10, 2)] uppercaseString]];
        [macString appendString:@":"];
        [macString appendString:[[aString substringWithRange:NSMakeRange(12, 2)] uppercaseString]];
        [macString appendString:@":"];
        [macString appendString:[[aString substringWithRange:NSMakeRange(14, 2)] uppercaseString]];
    }
    EBLog(@"macString:%@",macString);
    return macString;
}
// 当状态更新时调用(如果不实现会崩溃)
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
    switch (central.state) {
        case CBCentralManagerStateUnknown:
            EBLog(@"蓝牙状态-> 未知");
            break;
        case CBCentralManagerStateResetting:
            EBLog(@"蓝牙状态-> 重置");
            break;
        case CBCentralManagerStateUnsupported:
            EBLog(@"蓝牙状态-> 不支持");
            break;
        case CBCentralManagerStateUnauthorized:
            EBLog(@"蓝牙状态-> 未授权");
            break;
        case CBCentralManagerStatePoweredOff:
            EBLog(@"蓝牙状态-> 关闭");
            break;
        case CBCentralManagerStatePoweredOn:
            EBLog(@"蓝牙状态-> 可用");
            break;
        default:
            break;
    }
}

/**
 发现设备
 @param central 中心管理者
 @param peripheral 扫描到的设备
 @param advertisementData 广告信息
 @param RSSI 信号强度
 */
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI{
    EBLog(@"发现设备->\n name=%@\n advertisementData=%@\n UUIDString=%@\n services=%@\n 信号->%@",peripheral.name,advertisementData,peripheral.identifier.UUIDString,peripheral.services,RSSI);
    
    NSData *data = advertisementData[kAdDataKey];
    NSString *str = [HandleDataManager transformStringWithData:data];

    if ([[self macAddressWith:str] isEqualToString:self.peripheralMacAddress]) {
        //停止扫描
        [self.centralManager stopScan];
        
        //连接外设
        self.peripheral = peripheral;
        [self.centralManager connectPeripheral:self.peripheral options:nil];

        //将外设对象添加到数组中
        if (![self.peripheralArray containsObject:peripheral]){
            [self.peripheralArray addObject:self.peripheral];
        }
    }
}

/**
 连接成功
 @param central 中心管理者
 @param peripheral 连接成功的设备
 */
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
    EBLog(@"连接设备成功-> %@",peripheral.name);
    //停止扫描
    [self.centralManager stopScan];

    //设置peripheral代理
    self.peripheral.delegate = self;
    //扫描服务操作
    ......
}

/**
 连接失败
 @param central 中心管理者
 @param peripheral 连接失败的设备
 @param error 错误信息
 */
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
    if (error) {
        EBLog(@"连接失败-> %@",error.description);
    }
}

/**
 连接断开
 @param central 中心管理者
 @param peripheral 连接断开的设备
 @param error 错误信息
 */
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
    
    if (error) {
        EBLog(@"连接断开-> %@",error.description);
   }
}
/**
 扫描到服务
 @param peripheral 服务对应的设备
 @param error 扫描错误信息
 */
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
    for (CBService *service in peripheral.services) {
        EBLog(@"服务UUID: %@",service.UUID);
        // 获取对应的服务
        if ([service.UUID.UUIDString isEqualToString:@"厂商提供的服务ID"]){
            // 根据服务去扫描特征
            [self.peripheral discoverCharacteristics:nil forService:service];
        }
    }
}

/**
 扫描到对应的特征
 @param peripheral 设备
 @param service 特征对应的服务
 @param error 错误信息
 */
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
    EBLog(@"发现特征值=%@", service.characteristics);
    if (!error) {
            // 遍历所有的特征
        [service.characteristics enumerateObjectsUsingBlock:^(CBCharacteristic * _Nonnull characteristic, NSUInteger idx, BOOL * _Nonnull stop) {
            EBLog(@"特征的读写等属性=%lu", (unsigned long)characteristic.properties);

            if (characteristic.properties == CBCharacteristicPropertyNotify) {
                // 订阅, 实时接收
                [self.peripheral setNotifyValue:YES forCharacteristic:characteristic];
            }
            else if (characteristic.properties == CBCharacteristicPropertyWrite){
                self.writeCharacteristic = characteristic;
            }
        }];
    }
}

/**
 根据特征读到数据
 @param peripheral 读取到数据对应的设备
 @param characteristic 特征
 @param error 错误信息
 */
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(nonnull CBCharacteristic *)characteristic error:(nullable NSError *)error{
    EBLog(@"didUpdateValue 特征值=%@",characteristic);
    if (error) {
         EBLog(@"特征值=%@ == error %@",characteristic.UUID, error);
     }
     else{
         EBLog(@"收到特征值=%@ updated 发来的数据: %@", characteristic.UUID, characteristic.value);
         if (characteristic.value) {
         //读取到相关数据的操作
         }
     }
}

//更新描述值的时候会调用
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error {
    EBLog(@"描述(%@)",descriptor.description);
}

//发现外设的特征的描述数组
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(nonnull CBCharacteristic *)characteristic error:(nullable NSError *)error{
    // 在此处读取描述即可
    for (CBDescriptor *descriptor in characteristic.descriptors) {
        EBLog(@"发现外设的特征descriptor(%@)",descriptor);
        [self.peripheral readValueForDescriptor:descriptor];
    }
}

//写入指令是否成功回调
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error{
    if (error) {
        EBLog(@"特征值=%@ 写入失败 error %@",characteristic.UUID,error.description);
    }
    else{
        EBLog(@"特征值=%@ 写入成功",characteristic.UUID);
    }
}

- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    EBLog(@"通知发生改变->特征值=%@,isNotifying=%@",characteristic.UUID,characteristic.isNotifying?@"YES":@"NO");
    //订阅成功
    if (characteristic.isNotifying == YES) {
     
    }
}

BabyBluetooth这个库采用的链式编程思想,其中的block方法,可以重新按照功能和顺序组织代码,并提供许多方法减少蓝牙开发过程中的代码量。
详细介绍参考链接
BabyBluetooth蓝牙库介绍
BabyBluetooth源码GitHub地址

ZYBluetoothManager是一个轻量级的蓝牙工具类,简单实用,可以满足基本的需求。细节及其他功能还在不断完善与优化中,也欢迎各位大神给出宝贵意见。
源码GitHub地址:ZYBluetoothManager

上一篇下一篇

猜你喜欢

热点阅读