iOS 蓝牙

作者: Snow_L | 来源:发表于2021-04-14 16:41 被阅读0次

    1.蓝牙的基础知识

    1. iOS中开发蓝牙常用的系统库是<CoreBluetooth/CoreBluetooth.h>。

    2.蓝牙外设必需为4.0及以上(2.0需要MFI认证),否则无法进行开发,蓝牙4.0设施由于低耗电,所以也叫做BLE。

    3. CoreBluetooth框架的核心其实是俩东西

        3.1 Peripheral

        3.2 Central

    4. 服务和特征(service characteristic):简而言之,外部蓝牙中它有若干个服务service(服务你能了解为蓝牙所拥有的可以力),而每个服务service下拥有若干个特征characteristic(特征你能了解为解释这个服务的属性)。

    5. Descriptor(形容)使用来形容characteristic变量的属性。例如,一个descriptor能规定一个可读的形容,或者者一个characteristic变量可接受的范围,或者者一个characteristic变量特定的单位。

    2.蓝牙流程图

    3. 蓝牙连接的主要步骤

         3.1 创建一个CBCentralManager实例来进行蓝牙管理;

         3.2 搜索扫描外围设备;

         3.3 连接外围设备;

         3.4 获得外围设备的服务;

         3.5 获得服务的特征;

         3.6 从外围设备读取数据;

         3.7 给外围设备发送(写入)数据。

    4.如何扫描蓝牙

     4.1 初始化

    dispatch_queue_t centralQueue = dispatch_queue_create(“centralQueue",DISPATCH_QUEUE_SERIAL);

    NSDictionary *dic = @{CBCentralManagerOptionRestoreIdentifierKey : restoreIdentifier};

    self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:centralQueue options:dic];

    CBCentralManagerOptionRestoreIdentifierKey对应的是一个唯一标识的字符串,用于蓝牙进程被杀掉恢复连接时使用

    4.2 扫描

    /*

     *扫描设备

     */

    - (void)scanForDevices:(NSError**)error

    {

        if (CBCentralManagerStatePoweredOn == self.centralManager.state) {

            //取回已连接的service设备

            NSArray* retrievedPeripherals = [self.centralManagerretrieveConnectedPeripheralsWithServices:@[self.serviceUUID]];

            for(CBPeripheral* peripheralinretrievedPeripherals){

                //NSLog(@"retrieved peripheral:%@", peripheral);

                [self.delegateclient:selfdidDiscoverDevice:peripheral.identifier];

            }

            //启动扫描

            if (self.advertisementUUID) {

                [self.centralManager scanForPeripheralsWithServices:@[ self.advertisementUUID ] options:@{ CBCentralManagerScanOptionAllowDuplicatesKey:@YES }];

            }else{

                [self.centralManager scanForPeripheralsWithServices:nil options:@{ CBCentralManagerScanOptionAllowDuplicatesKey:@YES }];

    //            [self.centralManager scanForPeripheralsWithServices:nil options:nil];

            }

        }else{

            if(error !=NULL) {

                *error = [NSErrorerrorWithDomain:HCErrorDomaincode:(SRVClientErrorUnknown+self.centralManager.state)userInfo:nil];

                NSLog(@"[NSError errorWithDomain:HCErrorDomain code:(SRVClientErrorUnknown + self.centralManager.state) userInfo:nil];");

            }

        }

    }

    4.3 发现外围设备

    - (void)centralManager:(CBCentralManager*)centraldidDiscoverPeripheral:(CBPeripheral*)peripheraladvertisementData:(NSDictionary*)advertisementDataRSSI:(NSNumber*)RSSI {

        NSString*peripheralName = peripheral.name;

        if(peripheralName ==nil|| peripheralName.length==0) {

            return;

        }

        if([peripheralNameisEqualToString:SRV_CLIENT_DEV_NAME] || [peripheralNameisEqualToString:SRV_CLIENT_DFU_NAME]) {

       }

    }

    4.4 连接外围设备

    //蓝牙连接成功回调

    - (void)centralManager:(CBCentralManager*)centraldidConnectPeripheral:(CBPeripheral*)peripheral {

        [self.centralManager stopScan];

        peripheral.delegate=self;

        self.commandNo=0;

        NSLog(@"[D] CentralManager Discover services.");

        NSLog(@"%@",self.peripheral);

        self.peripheral.delegate=self;

        [self.peripheral discoverServices:@[self.serviceUUID]];

        NSLog(@"%@",self.serviceUUID);

        //定时获取RSSI

        if (self.needReadRSSI) {

            [self readPeripheralRSSI];

            if(!self.rssiTimer) {

                self.rssiTimer = [NSTimer scheduledTimerWithTimeInterval:5.0

                                                              target:self

                                                            selector:@selector(readPeripheralRSSI)

                                                            userInfo:nil

                                                             repeats:YES];

            }

        }

    }

    #pragma mark 连接外设——失败

    - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{

        NSLog(@"%@", error);

    }

    #pragma mark 取消与外设的连接回调

    - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{

        NSLog(@"%@", peripheral);

    }

    4.5 获得外围设备的服务

    //发现服务的回调

    - (void)peripheral:(CBPeripheral*)peripheraldidDiscoverServices:(NSError*)error

    {

        NSLog(@"%@---didDiscoverServices",peripheral);

        if(error){

            NSLog(@"[E] peripheral didDiscoverServices error: %@", error.localizedDescription);

            [self cancelConnection];

            return;

        }

        for(CBService* serviceinperipheral.services){

            NSLog(@"[D] Discover characteristics. For service = %@", service);

            [peripheraldiscoverCharacteristics:nil forService:service];

        }

    }

    //发现特征的回调

    - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error

    {

        if(error){

            NSLog(@"[E] peripheral didDiscoverCharacteristicsForService error: %@", error.localizedDescription);

            [self cancelConnection];

            return;

        }

        NSLog(@"[D] peripheral DiscoverCharacteristics = %@", service.characteristics);

        //订阅特征

        for(CBCharacteristic*characteristicinservice.characteristics){

            if (characteristic.properties & (CBCharacteristicPropertyNotify|CBCharacteristicPropertyIndicate)){

                if(!characteristic.isNotifying) {

                    if([self.ignoreCharacteristicUUIDscontainsObject:characteristic.UUID]) {

                        continue;

                    }

                    NSLog(@"[D] Enable notify value. For characteristic = %@", characteristic);

                    //d订阅特性当数据频繁改变时用 setNotifyValue 不频繁时用readValueForCharacteristic

                    [peripheralsetNotifyValue:YESforCharacteristic:characteristic];

                }

            }

        }

    }

    // 订阅后的callback

    - (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error

    {

        if(error){

            NSLog(@"[E] peripheral didUpdateNotificationStateForCharacteristic error: %@", error.localizedDescription);

            [self cancelConnection];

            return;

        }

        if ([self isAllCharacteristicNotificationEnabled]){

            NSLog(@"订阅成功");

           //authorizeRequest 授权认证

            [self.delegate clientDidPrepareForOperation:self];

        }

    //    [self.delegate clientDidPrepareForOperation:self];

    }

    4.6 从外围设备读取数据

    // peripheral主动发数据,包括写命令后主动返回的状态 读数据的回调

    - (void)peripheral:(CBPeripheral*)peripheraldidUpdateValueForCharacteristic:(CBCharacteristic*)characteristicerror:(NSError*)error

    {

        if(error) {

            NSLog(@"[E] peripheral didUpdateValueForCharacteristic error: %@ %@", error.localizedDescription,characteristic);

            [self cancelConnection];

            [self cleanupOperationUnexpectedly];

            return;

        }

        NSLog(@"%@",peripheral);

        NSLog(@"%@",characteristic);

        [self.delegate client:self didUpdateValueForCharacteristic:characteristic.UUID value:characteristic.value];

        if([characteristic.UUIDisEqual:self.ctrlptUUID]) {

                if (CTRLPTProgressWaitResp == self.ctrlptProgress) {

              }

        }

     }

    4.7 给外围设备发送(写入)数据

    - (BOOL)performOperationSegment:(CBCharacteristic*)characteristic

    {

            BOOLisLastSegment;

            uint8_tsegment[20];

            uint16_tindex =0;

            uint16_tsegLength;

            NSIntegerforwardLength =self.forwardFlow.length;

           if((forwardLength -self.forwardOffset) > (20- index)) {

                isLastSegment =NO;

                segLength = (20- index);

            }else{

                isLastSegment =YES;

                segLength = (forwardLength -self.forwardOffset);

            }

            memcpy(&segment[index], &self.forwardFlow.bytes[self.forwardOffset], segLength);

            self.forwardOffset+= segLength;

            index += segLength;

            NSData*writeData = [NSDatadataWithBytes:segmentlength:index];

            NSLog(@"[D] Write value = %@. For characteristic = %@", writeData, characteristic);

            [self.peripheral writeValue:writeData forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];//对于操控类蓝牙,数据写入要求非常快,其中writeWithSponce写入消耗的时间是writeWithoutSponce的2.3倍,因此尽量改写成writeWithoutSponce来提升写入速率

            returnisLastSegment;

     }

    //是否写入成功的回调

    - (void)peripheral:(CBPeripheral*)peripheraldidWriteValueForCharacteristic:(CBCharacteristic*)characteristicerror:(NSError*)error

    {

        if(error) {

            NSLog(@"[E] peripheral didWriteValueForCharacteristic error: %@", error);

            [self cancelConnection];

            [self cleanupOperationUnexpectedly];

            return;

        }

        NSLog(@"写入成功----%@",characteristic);

        if([characteristic.UUIDisEqual:self.ctrlptUUID]) {

            if (CTRLPTProgressWritting == self.ctrlptProgress) {

                if([selfperformOperationSegment:characteristic]) {

                    self.ctrlptProgress = CTRLPTProgressWaitResp;

                    self.backwardFlow.length=0;

                    self.backwardOffset=0;

                }

            }

        }

    }

    4.8 如何解析蓝牙数据

    //判断是否第一个包,若是,取出包长度

                                    if(0==self.backwardOffset&& length >=2) {

                                        uint16_tcommandLength;

                                        [characteristicDatagetBytes:&commandLengthlength:sizeof(commandLength)];

                                        offset +=sizeof(commandLength);

                                        self.backwardLength= commandLength;

                                        [self.backwardFlowappendData:[characteristicDatasubdataWithRange:NSMakeRange(offset, length - offset)]];

                                    }else{

                                        [self.backwardFlowappendData:characteristicData];

                                    }

    相关文章

      网友评论

        本文标题:iOS 蓝牙

        本文链接:https://www.haomeiwen.com/subject/rhgklltx.html