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变量特定的单位。 3.1 创建一个CBCentralManager实例来进行蓝牙管理; 3.2 搜索扫描外围设备; 3.3 连接外围设备; 3.4 获得外围设备的服务; 3.5 获得服务的特征; 3.6 从外围设备读取数据; 3.7 给外围设备发送(写入)数据。 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* peripheral in retrievedPeripherals){ //NSLog(@"retrieved peripheral:%@", peripheral); [ self .delegateclient: self didDiscoverDevice: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* service in peripheral.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*characteristic in service.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: YES forCharacteristic: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 { BOOL isLastSegment; 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来提升写入速率 return isLastSegment; } //是否写入成功的回调 - ( 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 ([ self performOperationSegment: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]; }