本⽂从以下三⽅⾯讲解下蓝⽛开发1、蓝⽛相关基本知识2、蓝⽛相关类图3、蓝⽛交互流程
⼀、蓝⽛相关基本知识
涉及到蓝⽛开发,⾸先有⼏个问题是需要我们理解的
1、任何设备既可以是中⼼设备、也可以是外围设备
2、外设 和 中⼼设备 之间通过特征建⽴⼀个双向的数据通道
3、CBCentralManager主要操作中⼼设备,处理链接上外设之前的操作,链接上外设后,主要靠CBPeripheral(主要操作外设)处理外设相关操作(服务、特征、数据读写)
4、中⼼设备管理 CBCentralManager
中⼼控制类,主要管理中⼼设备,以及处理跟外设(外围设备)相关操作,主要是扫描、链接、断开外设。操作中⼼设备的核⼼类。
很重要的协议CBCentralManagerDelegate,包含中⼼设备状态(是否打开蓝⽛)回调、发现外设回调、链接外设成功回调、链接外设失败回调、外设链接断开回调等⽅法。
⼀个中⼼设备可以链接多个外围设备。
5、外围设备 CBPeripheral
外设类,包含设备的基础属性,名字,uuid等信息。向外设写⼊数据。当中⼼设备连接到外设后,需要通过外设对象的代理⽅法进⾏数据交互。操作外围设备的核⼼类。
很重要的协议CBPeripheralDelegate,包含发现服务回调、发现特征回调、特征的通知设置改变回调、特征更新回调、特征已写⼊数据回调等⽅法。⼀个设备包含多个服务、⼀个服务包含多个特征、⼀个特征⼜包含多个描述。
6、外围设备管理 CBPeripheralManager
设备的控制,主要可以为设备设置Service以及Characteristic,可以⼿动配置特定的服务和特征值,也可看作可以⾃定义蓝⽛协议,例如将⼿机作为外设时可以为⾃⼰的⼿机蓝⽛设置服务和特征值。CBCentralManager更适合将⾃⼰的软件作为中⼼。⽤的较少
7、服务 CBService
服务对象是⽤来管理外设提供的⼀些数据服务的。⼀个服务可以包含多个特征
8、特征 CBCharacteristic
通过绑定服务中的特征值来进⾏数据的读写操作。特征就是具体键值对,提供数据的地⽅。
每个特征属性分为这么⼏种:读,写,通知等⼏种⽅式。
有时读、写、通知可以是同⼀个特征,也可以读、写、通知各⽤⼀个特征表⽰。⼀个特征可以包含多个描述。⼀般我们操作到特征这⼀层
9、描述 CBDescriptor
每个characteristic可以对应⼀个或多个Description 供⽤户描述characteristic的信息或属性。
10、CBAttribute
CBService,CBCharacteristic,CBDescriptor 类都继承⾃ CBAttribute,它们有⼀个共同的属性 CBUUID,⽤来作为唯⼀的标识。
⼆、蓝⽛相关类图
下⾯⽤类图简述下:
⼀个中⼼设备可以连接多个外设,⼀个外设包含多个服务,⼀个服务包含多个特征,⼀个特征包含多个描述服务、特征、描述都⽤CBUUID唯⼀标识
三、蓝⽛交互流程
下⾯简述下以⼿机作为中⼼设备、其它作为外围设备的交互流程,⼤致流程如图所⽰下⾯是操作详解
1、创建中⼼设备管理对象(初始化中⼼设备)
CBCentralManager 的创建是异步的,如果初始化完成之后没有被当前创建它的类所持有,就会在下⼀次 RunLoop 迭代的时候释放。创建线程写nil,为主线程。
初始化成功后,就会触发 CBCentralManagerDelegate 中的中⼼设备状态更新⽅法:centralManagerDidUpdateState:
NSDictionary *options = @{CBCentralManagerOptionShowPowerAlertKey:@NO};
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:options];
/*!
* @method initWithDelegate:queue:options: *
* @param delegate The delegate that will receive central role events.
* @param queue The dispatch queue on which the events will be dispatched. * @param options An optional dictionary specifying options for the manager. *
* @discussion The initialization call. The events of the central role will be dispatched on the provided queue. * If nil, the main queue will be used. *
* @seealso CBCentralManagerOptionShowPowerAlertKey * @seealso CBCentralManagerOptionRestoreIdentifierKey * */
- (instancetype)initWithDelegate:(nullable id options:(nullable NSDictionary /*! * @method centralManagerDidUpdateState: * * @param central The central manager whose state has changed. * * @discussion Invoked whenever the central manager's state has been updated. Commands should only be issued when the state is * * @see state * */ - (void)centralManagerDidUpdateState:(CBCentralManager *)central; 2、扫描外围设备 在CBCentralManagerDelegate 中的中⼼设备状态更新⽅法:centralManagerDidUpdateState:中, 当中⼼设备处于CBManagerStatePoweredOn 状态的时候开始扫描周边设备(可以使⽤指定的 UUID 发现特定的 Service,也可以传⼊ nil,表⽰发现所有周边的蓝⽛设备,不过还是建议只发现⾃⼰需要服务的设备)。 扫描外设:scanForPeripheralsWithServices:options: 该操作由CBCentralManager对象通过scanForPeripheralsWithServices:options:⽅法实现 case CBManagerStatePoweredOn: //蓝⽛正常开启 [self startScan]; break; - (void)startScan { // [self.centralManager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];// 扫描所有设备 当指定设备不好使时可以使⽤该⽅法 // [self.centralManager scanForPeripheralsWithServices:nil options:nil];// 扫描指定设备 快速 [self.centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:self.peripheralServiceUUID]] options:nil]; [self startTime];} /*! * @method scanForPeripheralsWithServices:options: * * @param serviceUUIDs A list of * @discussion Starts scanning for peripherals that are advertising any of the services listed in serviceUUIDs. Although strongly discouraged, * if serviceUUIDs is nil all discovered peripherals will be returned. If the central is already scanning with different * serviceUUIDs or options, the provided parameters will replace them. * Applications that have specified the * caveats: the scan must specify one or more service types in serviceUUIDs, and the * @see centralManager:didDiscoverPeripheral:advertisementData:RSSI: * @seealso CBCentralManagerScanOptionAllowDuplicatesKey * @seealso CBCentralManagerScanOptionSolicitedServiceUUIDsKey * */ - (void)scanForPeripheralsWithServices:(nullable NSArray 3、发现外围设备 CBCentralManager对象执⾏扫描外设⽅法scanForPeripheralsWithServices:options:后 会触发 CBCentralManagerDelegate 中的⽅法:(发现外设)centralManager:didDiscoverPeripheral:advertisementData:RSSI: 如果在扫描时指定了明确的服务,那么此时该⽅法⾥的外设就是包含该服务的外设,如果传⼊的是nil,那么此时该⽅法⾥的外设就是周边所有打开的蓝⽛设备。 /*! * @method centralManager:didDiscoverPeripheral:advertisementData:RSSI: * * @param central The central manager providing this update. * @param peripheral A * @param advertisementData A dictionary containing any advertisement and scan response data. * @param RSSI The current RSSI of peripheral, in dBm. A value of * @discussion This method is invoked while scanning, upon the discovery of peripheral by central. A discovered peripheral must * be retained in order to use it; otherwise, it is assumed to not be of interest and will be cleaned up by the central manager. For * a list of advertisementData keys, see {@link CBAdvertisementDataLocalNameKey} and other similar constants. * * @seealso CBAdvertisementData.h * */ - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary 4、链接外设 在CBCentralManagerDelegate 中的发现外设⽅法:centralManager:didDiscoverPeripheral:advertisementData:RSSI:中,我们会链接外设:connectPeripheral:options: 该操作由CBCentralManager对象通过connectPeripheral:options:⽅法实现 我们通过名称或者⼚商数据来确定我们需要链接的外设(过滤外设),找到后停⽌扫描,然后链接该外设,即链接指定外设 [central connectPeripheral:peripheral options:nil]; /*! * @method connectPeripheral:options: * * @param peripheral The * @param options An optional dictionary specifying connection behavior options. * * @discussion Initiates a connection to peripheral. Connection attempts never time out and, depending on the outcome, will result * in a call to either {@link centralManager:didConnectPeripheral:} or {@link centralManager:didFailToConnectPeripheral:error:}. * Pending attempts are cancelled automatically upon deallocation of peripheral, and explicitly via {@link cancelPeripheralConnection}. * * @see centralManager:didConnectPeripheral: * @see centralManager:didFailToConnectPeripheral:error: * @seealso CBConnectPeripheralOptionNotifyOnConnectionKey * @seealso CBConnectPeripheralOptionNotifyOnDisconnectionKey * @seealso CBConnectPeripheralOptionNotifyOnNotificationKey * @seealso CBConnectPeripheralOptionEnableTransportBridgingKey * @seealso CBConnectPeripheralOptionRequiresANCS * */ - (void)connectPeripheral:(CBPeripheral *)peripheral options:(nullable NSDictionary 5、链接外设结果回调 CBCentralManager对象执⾏链接外设⽅法connectPeripheral:options:后会触发 CBCentralManagerDelegate 中的⽅法: 链接外设成功回调:centralManager:didConnectPeripheral: /*! * @method centralManager:didConnectPeripheral: * * @param central The central manager providing this information. * @param peripheral The * @discussion This method is invoked when a connection initiated by {@link connectPeripheral:options:} has succeeded. * */ - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral; 链接外设失败回调:centralManager:didFailToConnectPeripheral:error: /*! * @method centralManager:didFailToConnectPeripheral:error: * * @param central The central manager providing this information. * @param peripheral The * @discussion This method is invoked when a connection initiated by {@link connectPeripheral:options:} has failed to complete. As connection attempts do not * timeout, the failure of a connection is atypical and usually indicative of a transient issue. * */ - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error; 6、查找服务 在CBCentralManagerDelegate 中的链接外设成功回调⽅法:centralManager:didConnectPeripheral:中,我们会查找服务:discoverServices: 该操作由CBPeripheral对象通过discoverServices:⽅法实现 [peripheral discoverServices:@[[CBUUID UUIDWithString:self.peripheralServiceUUID]]]; /*! * @method discoverServices: * * @param serviceUUIDs A list of * @discussion Discovers available service(s) on the peripheral. * * @see peripheral:didDiscoverServices: */ - (void)discoverServices:(nullable NSArray 7、发现服务 CBPeripheral对象执⾏查找服务⽅法discoverServices:后, 会触发 CBPeripheralDelegate 中的发现服务⽅法:peripheral:didDiscoverServices: /*! * @method peripheral:didDiscoverServices: * * @param peripheral The peripheral providing this information. * @param error If an error occurred, the cause of the failure. * * @discussion This method returns the result of a @link discoverServices: @/link call. If the service(s) were read successfully, they can be retrieved via * peripheral's @link services @/link property. * */ - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error; 8、查找特征 在 CBPeripheralDelegate 中的发现服务⽅法:peripheral:didDiscoverServices:中,我们会查找特征:discoverCharacteristics:forService: 该操作由CBPeripheral对象通过discoverCharacteristics:forService:⽅法实现 [peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:self.peripheralCharacteristicRTXUUID]] forService:service]; /*! * @method discoverCharacteristics:forService: * * @param characteristicUUIDs A list of * @discussion Discovers the specified characteristic(s) of service. * * @see peripheral:didDiscoverCharacteristicsForService:error: */ - (void)discoverCharacteristics:(nullable NSArray 9、发现特征 CBPeripheral对象执⾏查找特征⽅法discoverCharacteristics:forService:后, 会触发CBPeripheralDelegate 中的发现特征⽅法:peripheral:didDiscoverCharacteristicsForService:error: /*! * @method peripheral:didDiscoverCharacteristicsForService:error: * * @param peripheral The peripheral providing this information. * @param service The * @discussion This method returns the result of a @link discoverCharacteristics:forService: @/link call. If the characteristic(s) were read successfully, * they can be retrieved via service's - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(nullable NSError *)error; 10、写特征、通知特征(读取)、读特征 在 CBPeripheralDelegate 中的发现特征⽅法:peripheral:didDiscoverCharacteristicsForService:error:中,我们会处理特征(读、写、通知),⼀般会保存写⼊特征,⽅便后期写⼊数据,打开使能通知,⽅便读取数据写: 保存写特征,⽅便后期写⼊数据。读: 通知特征和读特征都是为了读取,⼀般我们使⽤的都是通知,使⽤通知的时候,要打开使能通知(订阅), 该操作由CBPeripheral对象通过setNotifyValue:forCharacteristic:⽅法打开指定通知特征 通知特征发送的数据在didUpdateValueForCharacteristic⽅法⾥接受(读取) 该操作会回调CBPeripheralDelegate 中的⽅法peripheral:didUpdateNotificationStateForCharacteristic:error:通过characteristic.isNotifying知晓通知状态 /*! * @method peripheral:didUpdateNotificationStateForCharacteristic:error: * * @param peripheral The peripheral providing this information. * @param characteristic A * @discussion This method returns the result of a @link setNotifyValue:forCharacteristic: @/link call. */ - (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error;for (CBCharacteristic *characteristic in service.characteristics) { // if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:self.peripheralCharacteristicTXUUID]]) { // // 打开使能通知 (订阅)该特征发送的数据在didUpdateValueForCharacteristic⽅法⾥接受(读取)// [peripheral setNotifyValue:YES forCharacteristic:characteristic]; // } else if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:self.peripheralCharacteristicRXUUID]]) {// // 保存外设接受特征(写⼊特征)// self.characteristicRX = characteristic; 11、写⼊数据 写⼊⽅法:writeValue:forCharacteristic:type: 写⼊操作由CBPeripheral对象通过writeValue:forCharacteristic:type:⽅法写⼊指定写⼊特征 [self.peripheral writeValue:peripheralRXData forCharacteristic:self.characteristicRX type: CBCharacteristicWriteWithResponse]; /*! * @method writeValue:forCharacteristic:type: * * @param data The value to write. * @param characteristic The characteristic whose characteristic value will be written. * @param type The type of write to be executed. * * @discussion Writes value to characteristic's characteristic value. * If the * If the * @see peripheral:didWriteValueForCharacteristic:error: * @see peripheralIsReadyToSendWriteWithoutResponse: * @see canSendWriteWithoutResponse * @see CBCharacteristicWriteType */ - (void)writeValue:(NSData *)data forCharacteristic:(CBCharacteristic *)characteristic type:(CBCharacteristicWriteType)type; 写⼊数据有两种⽅式: /* 32 typedef NS_ENUM(NSInteger, CBCharacteristicWriteType) { 33 CBCharacteristicWriteWithResponse = 0,//写数据并且接收成功与否回执34 CBCharacteristicWriteWithoutResponse,//写数据不接收回执35 };36 */ 如果写⼊类型为CBCharacteristicWriteWithResponse 回调CBPeripheralDelegate 中的⽅法:peripheral:didWriteValueForCharacteristic:error:, 如果写⼊类型为CBCharacteristicWriteWithoutResponse不回调此⽅法,该⽅法只是告知写⼊数据是否成功 /*! * @method peripheral:didWriteValueForCharacteristic:error: * * @param peripheral The peripheral providing this information. * @param characteristic A * @discussion This method returns the result of a {@link writeValue:forCharacteristic:type:} call, when the - (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error; 写⼊数据后外设响应数据在特征值更新⽅法didUpdateValueForCharacteristic:error:中读取 12、读取数据 读取外设发送给中⼼设备的数据, ⽆论是read的回调,还是notify(订阅)的回调都是CBPeripheralDelegate 中的⽅法:特征值更新:didUpdateValueForCharacteristic:error: /*! * @method peripheral:didUpdateValueForCharacteristic:error: * * @param peripheral The peripheral providing this information. * @param characteristic A * @discussion This method is invoked after a @link readValueForCharacteristic: @/link call, or upon receipt of a notification/indication. */ - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error; 13、断开链接 断开链接:cancelPeripheralConnection: 断开链接操作由CBCentralManager对象通过cancelPeripheralConnection:⽅法实现该⽅法不会触发CBCentralManagerDelegate 中的⽅法: 断开外设(仅在异常断开时会触发):centralManager:didDisconnectPeripheral:error: /*! * @method cancelPeripheralConnection: * * @param peripheral A * @discussion Cancels an active or pending connection to peripheral. Note that this is non-blocking, and any * @see centralManager:didDisconnectPeripheral:error: * */ - (void)cancelPeripheralConnection:(CBPeripheral *)peripheral; 参考资料: CBCentralManagerStatePoweredOn. A state below CBCentralManagerStatePoweredOn * implies that scanning has stopped and any connected peripherals have been disconnected. If the state moves below * CBCentralManagerStatePoweredOff, all CBPeripheral objects obtained from this central * manager become invalid and must be retrieved or discovered again. *CBUUID objects representing the service(s) to scan for. * @param options An optional dictionary specifying options for the scan. *bluetooth-central background mode are allowed to scan while backgrounded, with twoCBCentralManagerScanOptionAllowDuplicatesKey * scan option will be ignored. *CBPeripheral object.127 is reserved and indicates the RSSI * was not available. *CBPeripheral to be connected.CBPeripheral that has connected. *CBPeripheral that has failed to connect. * @param error The cause of the failure. *CBUUID objects representing the service types to be discovered. If nil, * all services will be discovered. *CBUUID objects representing the characteristic types to be discovered. If nil, * all characteristics of service will be discovered. * @param service A GATT service. *CBService object containing the characteristic(s). * @param error If an error occurred, the cause of the failure. *characteristics property. */CBCharacteristic object. * @param error If an error occurred, the cause of the failure. *CBCharacteristicWriteWithResponse type is specified, {@link peripheral:didWriteValueForCharacteristic:error:} * is called with the result of the write request.CBCharacteristicWriteWithoutResponse type is specified, and canSendWriteWithoutResponse is false, the delivery * of the data is best-effort and may not be guaranteed. *CBCharacteristic object. * @param error If an error occurred, the cause of the failure. *CBCharacteristicWriteWithResponse type is used. */CBCharacteristic object. * @param error If an error occurred, the cause of the failure. *CBPeripheral. *CBPeripheral * commands that are still pending to peripheral may or may not complete. *
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- 7swz.com 版权所有 赣ICP备2024042798号-8
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务