iOS蓝牙开发梳理:广播端和扫描端实现
<h3> <strong> <img src="https://img2020.cnblogs.com/blog/1270351/202005/1270351-20200509142226861-1960268307.png"></strong></h3><h3><strong>【前言】</strong></h3>
<p><span style="color: rgba(102, 102, 153, 1)"><strong> * 目前项目里有蓝牙支付功能,对于<strong>蓝牙开发功能,</strong>要求比较高,包括iOS与Android之间的通讯。</strong></span></p>
<p><span style="color: rgba(102, 102, 153, 1)"><strong> * 今天整理了下iOS蓝牙SDK开发流程中的知识点,总结了这篇文章,希望给各位开发蓝牙功能的同学带来帮助。</strong></span></p>
<h1><span style="font-size: 16px">【功能目标】</span></h1>
<p> 开发移动设备的蓝牙功能,目的用来实现设备之间数据自由通讯(数据发,收),完成移动服务端和客服端场景交互。</p>
<h2><span style="font-size: 15px">【定义场景】</span></h2>
<p> 1: 广播端:服务端定义,用于被多台扫描设备同时识别并订阅;</p>
<p> 2: 扫描端:客服端定义,用于扫描并订阅广播端设备;</p>
<h2><span style="font-size: 15px">【实现方案】</span></h2>
<p><span style="color: rgba(51, 153, 102, 1)">CoreBluetooth</span>:iOS原生SDK。</p>
<p>导入: <span style="color: rgba(51, 153, 102, 1)"><CoreBluetooth/CoreBluetooth.h></span> 。</p>
<p> </p>
<h2><span style="font-size: 16px; color: rgba(255, 102, 0, 1)">开始广播功能:</span></h2>
<h2><span style="font-size: 16px">【第一步、开启广播】</span></h2>
<p><strong>(1</strong><strong>): </strong>涉及的类</p>
<p>1: <span style="color: rgba(51, 153, 102, 1)">CBPeripheralManager</span>;</p>
<p>外设管理器,管理设备广播状态。</p>
<p>2: <span style="color: rgba(51, 153, 102, 1)">CBUUID</span>;</p>
<p>唯一标识,设备的服务,特性和特征描述符。</p>
<p>3: <span style="color: rgba(51, 153, 102, 1)">CBMutableService</span>;</p>
<p>外设管理器的服务,用于设定服务特征。</p>
<p>4: <span style="color: rgba(51, 153, 102, 1)">CBMutableCharacteristic</span>;</p>
<p>服务的特征,用于设定特征描述。</p>
<p>5: <span style="color: rgba(51, 153, 102, 1)">CBMutableDescriptor</span>;</p>
<p>特征的描述。</p>
<p> </p>
<p><strong>(2</strong><strong>): </strong>类调用时序图</p>
<p> <img src="https://img2020.cnblogs.com/blog/1270351/202005/1270351-20200509113540432-1394723180.png"></p>
<p>时序图备注: <span style="color: rgba(51, 153, 102, 1)">CBPeripheralManager</span> 添加服务是很重要的一步。</p>
<p> </p>
<p><strong>(3</strong><strong>): </strong><span style="color: rgba(51, 153, 102, 1)">CoreBluetooth</span> 原生函数</p>
<p>1: 蓝牙创建,用于权限判断:</p>
<p><span style="color: rgba(51, 153, 102, 1)">- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral;</span></p>
<p>2: 外设管理器添加服务完成,回调结果:</p>
<p><span style="color: rgba(51, 153, 102, 1)"><strong>- </strong>(<strong>void</strong>)<strong>peripheralManager:</strong>(<strong>CBPeripheralManager *</strong>)<strong>peripheral didAddService:</strong>(<strong>CBService *</strong>)<strong>service error:</strong>(<strong>NSError *</strong>)<strong>error</strong>;</span></p>
<p>3: 广播开启完成,回调结果:</p>
<p><span style="color: rgba(51, 153, 102, 1)"><strong>-</strong>(<strong>void</strong>)<strong>peripheralManagerDidStartAdvertising: </strong>(<strong>CBPeripheralManager *</strong>)<strong>peripheral error:</strong>(<strong>NSError *</strong>)<strong>error</strong>;</span></p>
<p> </p>
<p><strong>(</strong><strong>4</strong><strong>)</strong><strong>: </strong>广播开启失败,重启</p>
<p>1: 重置广播,目前重试次数: <span style="color: rgba(51, 153, 102, 1)"><strong>ADVERTISING_RETRY = 3</strong></span>;<span style="color: rgba(255, 102, 0, 1)">(注:根据自己需求设置)</span></p>
<p>2: 重置加载安全模块调用方法: <span style="color: rgba(51, 153, 102, 1)">[<strong>self setUpServiceSecurity</strong>]; <span style="color: rgba(255, 102, 0, 1)">(注:需要根据自己功能需求实现)</span></span></p>
<p>3: 重置外设管理器步骤: <span style="color: rgba(51, 153, 102, 1)">1:关闭广播 2:清除设备 3:重置管理器</span></p>
<p>4: 重置创建服务和特征调用方法: <span style="color: rgba(51, 153, 102, 1)"> [<strong>self setupServiceAndCharacteristics</strong>];<span style="color: rgba(255, 102, 0, 1)">(注:需要根据自己功能需求实现)</span></span></p>
<p> </p>
<p><strong>(</strong><strong>5</strong><strong>)</strong><strong>: </strong>蓝牙广播,参数配置</p>
<p>1: 广播设备名称: 可通过<span style="color: rgba(51, 153, 102, 1)">CBPeripheralManager</span> 函数:</p>
<p><span style="color: rgba(51, 153, 102, 1)">- (void)startAdvertising:(nullable NSDictionary<NSString *, id> *)advertisementData;</span></p>
<p>进行设置:<span style="color: rgba(51, 153, 102, 1)">CBAdvertisementDataLocalNameKey</span> 的值。 </p>
<p>2: 信号强度 : iOS不支持设置。</p>
<p>3: 广播频率 : iOS不支持设置。</p>
<p> </p>
<h2><span style="font-size: 16px">【第</span><span style="font-size: 16px">二步、广播被订阅】</span></h2>
<p><strong>(</strong><strong>1</strong><strong>)</strong><strong>: </strong>涉及的类</p>
<p>1: <span style="color: rgba(51, 153, 102, 1)">CBCentral</span>: 发起订阅的扫描设备;</p>
<p>2: <span style="color: rgba(51, 153, 102, 1)">CBCharacteristic</span>: 扫描设备的特性信息;</p>
<p> </p>
<p><strong>(</strong><strong>2</strong><strong>)</strong><strong>: </strong><span style="color: rgba(51, 153, 102, 1)">CoreBluetooth</span>原生函数</p>
<p>1: 订阅成功回调,记录订阅扫描设备:</p>
<p><span style="color: rgba(51, 153, 102, 1)">-(void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic;</span></p>
<p> </p>
<p><strong>(</strong><strong>3</strong><strong>)</strong><strong>: </strong>被取消订阅函数</p>
<p>l 扫描设备取消订阅,移除相应记录的设备信息:</p>
<p><span style="color: rgba(51, 153, 102, 1)">-(void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic;</span></p>
<p> </p>
<p><strong>(</strong><strong>4</strong><strong>)</strong><strong>:</strong>完成订阅</p>
<p>注:当有扫描设备订阅了广播设备后,广播端可以给扫描设备发送数据。</p>
<p> </p>
<h2><span style="font-size: 16px">【第三步、发送数据】</span></h2>
<p><strong>(</strong><strong>1</strong><strong>)</strong><strong>: </strong>涉及的类</p>
<p> <span style="color: rgba(51, 153, 102, 1)">DeviceInforModel</span>: 数据容器对象。<span style="color: rgba(255, 102, 0, 1)">(注:自定义对象,用来记录外设设备部信息和接,发数据的记录)</span></p>
<p>-属性- <span style="color: rgba(51, 153, 102, 1)">messageSentData</span>: 发送数据DATA;</p>
<p>-属性- <span style="color: rgba(51, 153, 102, 1)">sentStartIndex</span>: 发送数据开始下标;</p>
<p>-属性- <span style="color: rgba(51, 153, 102, 1)">diffLength</span>: 每个包最大字节;</p>
<p> </p>
<p><strong>(</strong><strong>2</strong><strong>)</strong><strong>: </strong>发送流程图</p>
<p> <img src="https://img2020.cnblogs.com/blog/1270351/202005/1270351-20200509114024111-8692058.png"></p>
<p>(流程图备注):</p>
<p>1: <span style="color: rgba(51, 153, 102, 1)">Start</span>: 分包首个数据包字符串标示;</p>
<p>2: <span style="color: rgba(51, 153, 102, 1)">End</span>: 分包最后一个数据包字符串标示;</p>
<p>3: <span style="color: rgba(51, 153, 102, 1)">sentStartIndex</span>: 每个发送数据包的开始标示,默认等于0;</p>
<p>4: <span style="color: rgba(51, 153, 102, 1)">messageSentData</span>:总数据中按照 sentStartIndex 截取的分包数据;</p>
<p>5: <span style="color: rgba(51, 153, 102, 1)">IsReady</span>: 外围设备已准备好发送特征值更新,有相应的回调函数;</p>
<p>6: <span style="color: rgba(51, 153, 102, 1)">sendMessagePart</span>:进入数据分包流程;</p>
<p> </p>
<p><strong>(</strong><strong>3</strong><strong>)</strong><strong>: </strong><span style="color: rgba(51, 153, 102, 1)">CoreBluetooth</span>原生函数</p>
<p>1: 发送:通过通知或指示将更新后的特征值发送给一个或多个中心。</p>
<p><span style="color: rgba(51, 153, 102, 1)">- (BOOL)updateValue:(NSData *)value forCharacteristic:(CBMutableCharacteristic *)characteristic onSubscribedCentrals:(nullable NSArray<CBCentral *> *)centrals;</span></p>
<p> </p>
<p>2: 发送结果:告诉委托本地外围设备已准备好发送特征值更新。</p>
<p><span style="color: rgba(51, 153, 102, 1)">- (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral;</span></p>
<p> </p>
<h2><span style="font-size: 16px">【第四步、接收数据】</span></h2>
<p><strong>(</strong><strong>1</strong><strong>)</strong><strong>: </strong>涉及的类</p>
<p>1: <span style="color: rgba(51, 153, 102, 1)">CBATTRequest</span>: 写入数据的请求。</p>
<p>-属性- <span style="color: rgba(51, 153, 102, 1)">lastObject</span>: 目标数据;</p>
<p> </p>
<p>2: <span style="color: rgba(51, 153, 102, 1)">DeviceInforModel</span>: 数据容器对象。<span style="color: rgba(255, 102, 0, 1)">(自定义对象,用来记录外设设备部信息和接,发数据的记录)</span></p>
<p>-属性- <span style="color: rgba(51, 153, 102, 1)">messageReceivedData</span>:发送数据DATA;</p>
<p>-属性- <span style="color: rgba(51, 153, 102, 1)">isStart</span>: 开头标示;</p>
<p>-属性- <span style="color: rgba(51, 153, 102, 1)">startMsg</span>: 开头数据;</p>
<p>-属性- <span style="color: rgba(51, 153, 102, 1)">isEnd</span>: 结尾标示;</p>
<p>-属性- <span style="color: rgba(51, 153, 102, 1)">endMsg</span>: 结尾数据;</p>
<p> </p>
<p><strong>(</strong><strong>2</strong><strong>)</strong><strong>: </strong>接收流程图</p>
<p><img src="https://img2020.cnblogs.com/blog/1270351/202005/1270351-20200509114156220-790202948.png"> </p>
<p>(流程图备注):</p>
<p>1: <span style="color: rgba(51, 153, 102, 1)">Start</span>: 分包首个数据包字符串标示,此时设置isStart=YES;</p>
<p>2: <span style="color: rgba(51, 153, 102, 1)">End</span>: 分包最后一个数据包字符串标示,此时设置isEnd=YES;</p>
<p>3: <span style="color: rgba(51, 153, 102, 1)">CBATTRequest.lastObject</span>:每个包的数据源;</p>
<p>4: <span style="color: rgba(51, 153, 102, 1)">messageReceivedData</span>: 与历史数据进行合并;</p>
<p>5: <span style="color: rgba(51, 153, 102, 1)">hasPrefix:@"End"</span>:这步判断结束标示,有End标示,合并数据,输出完整包;</p>
<p>6: <span style="color: rgba(51, 153, 102, 1)">CBATTRequest</span>: 没有End标示,等待分包数据;</p>
<p> </p>
<p><strong>(</strong><strong>3</strong><strong>)</strong><strong>: </strong><span style="color: rgba(51, 153, 102, 1)">CoreBluetooth</span>原生函数</p>
<p>l 中心设备写入数据的时候,回调函数:</p>
<p><span style="color: rgba(51, 153, 102, 1)">- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray<CBATTRequest *> *)requests;</span></p>
<p> </p>
<p>【完成:广播功能】</p>
<p>完成上面步骤,此时广播端可以自由发送和接收数据。</p>
<p> </p>
<p> </p>
<p><span style="font-size: 18px; color: rgba(255, 102, 0, 1)"><strong>开始扫描功能:</strong></span></p>
<h2><span style="font-size: 16px">【第一步、开启扫描】</span></h2>
<p><strong>(1</strong><strong>): </strong>涉及的类</p>
<p>1: <span style="color: rgba(51, 153, 102, 1)">CBCentralManager:</span>中心设备管理器。</p>
<p>2: <span style="color: rgba(51, 153, 102, 1)">CBUUID:</span> 唯一标识,设备的服务,特性和特征描述符。</p>
<p>3: <span style="color: rgba(51, 153, 102, 1)">CBService:</span> 中心设备管理器的服务,用于扫描指定服务广播。</p>
<p>4: <span style="color: rgba(51, 153, 102, 1)">CBPeripheral</span>:外设管理器,扫描到或连接的广播设备。</p>
<p>5: <span style="color: rgba(51, 153, 102, 1)">RSSI</span>: 外设型号强度值。</p>
<p> </p>
<p><strong>(2</strong><strong>): </strong>类调用时序图</p>
<p><img src="https://img2020.cnblogs.com/blog/1270351/202005/1270351-20200509131636430-1206297864.png"></p>
<p>时序图备注:在识别到广播外设 <span style="color: rgba(51, 153, 102, 1)">CBPeripheral</span>,并且完成记录后,就可以开启指定外设的连接请求,<span style="color: rgba(51, 153, 102, 1)">APP</span>级外设标示通过 <span style="color: rgba(51, 153, 102, 1)">CBService</span> 区分。</p>
<p> </p>
<p><strong>(</strong><strong>3</strong><strong>)</strong><strong>: </strong>扫描开启失败</p>
<p><span style="color: rgba(255, 102, 0, 1)">注:蓝牙功能不可用,或者未开启,会导致开启失败。</span></p>
<p><span style="color: rgba(255, 102, 0, 1)">未发现符合要求的外设时,会继续扫描。</span></p>
<p> </p>
<p><strong>(</strong><strong>4</strong><strong>)</strong><strong>: </strong>蓝牙扫描,参数配置</p>
<p>1: 扫描设备名称: iOS不支持设置,</p>
<p>备注:订阅广播端成功后,广播端区别扫描设备通过:<span style="color: rgba(51, 153, 102, 1)">central.identifier</span>;</p>
<p>2: 扫描频率: iOS不支持设置。</p>
<p> </p>
<h2><span style="font-size: 16px">【第二步、连接广播】</span></h2>
<p><strong>(1</strong><strong>): </strong>涉及的对象</p>
<p>1: <span style="color: rgba(51, 153, 102, 1)"><span style="color: rgba(255, 102, 0, 1)">self</span>. centralManager</span>:中心设备管理器;</p>
<p>2: <span style="color: rgba(51, 153, 102, 1)"><span style="color: rgba(255, 102, 0, 1)">self</span>.peripheral</span>: 中心设备管理器连接目标外设;</p>
<p>3: <span style="color: rgba(51, 153, 102, 1)"><span style="color: rgba(255, 102, 0, 1)">self</span>.service:</span> 用于查找的服务特征;</p>
<p>4: <span style="color: rgba(51, 153, 102, 1)"> service.characteristics</span>:对应服务的特征集合;</p>
<p><strong> </strong></p>
<p><strong> </strong><strong>(</strong><strong>2</strong><strong>)</strong><strong>: </strong><span style="color: rgba(51, 153, 102, 1)">CoreBluetooth</span>原生函数</p>
<p>1: 发起连接外设,调用函数:</p>
<p><span style="color: rgba(51, 153, 102, 1)">- (void)connectPeripheral:(CBPeripheral *)peripheral options:(nullable NSDictionary<NSString *, id> *)options;</span></p>
<p>2: 连接成功,回调函数:</p>
<p><span style="color: rgba(51, 153, 102, 1)">- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral;</span></p>
<p>3: 根据SERVICE_UUID来寻找服务,调用函数:</p>
<p><span style="color: rgba(51, 153, 102, 1)">- (void)discoverServices:(nullable NSArray<CBUUID *> *)serviceUUIDs;</span></p>
<p>4: 寻找到特定服务,回调函数:</p>
<p><span style="color: rgba(51, 153, 102, 1)">- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error;</span></p>
<p>5:寻找特定服务特征,回调函数:</p>
<p><span style="color: rgba(51, 153, 102, 1)">- (void)discoverCharacteristics:(nullable NSArray<CBUUID *> *)characteristicUUIDs forService:(CBService *)service;</span></p>
<p>6: 发现特征,回调函数:</p>
<p><span style="color: rgba(51, 153, 102, 1)">- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error;</span></p>
<p>7: 读取特征数据,调用函数:</p>
<p><span style="color: rgba(51, 153, 102, 1)">;</span></p>
<p>8: 发送订阅通知,调用函数(广播端会收到被订阅消息):</p>
<p><span style="color: rgba(51, 153, 102, 1)">;</span></p>
<p>9: 连接失败,回调函数:</p>
<p><span style="color: rgba(51, 153, 102, 1)">-(void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;</span></p>
<p>10: 断开连接,回调函数:</p>
<p><span style="color: rgba(51, 153, 102, 1)">- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error;</span></p>
<p> </p>
<p><strong>(</strong><strong>3</strong><strong>)</strong><strong>: </strong><span style="color: rgba(51, 153, 102, 1)">CoreBluetooth</span>连接流程图</p>
<p><img src="https://img2020.cnblogs.com/blog/1270351/202005/1270351-20200509131842542-71245977.png"></p>
<p> </p>
<h2><span style="font-size: 16px">【第三步、发送数据】</span></h2>
<p><span style="color: rgba(255, 102, 0, 1)">注:扫描端处理发送数据流程,与广播端处理发送一致,详见广播端;</span></p>
<p> </p>
<h2><span style="font-size: 16px">【第四步、接收数据】</span></h2>
<p><span style="color: rgba(255, 102, 0, 1)">注:扫描端处理接收数据流程,与广播端处理接收一致,详见广播端;</span></p>
<p> </p>
<h2><span style="font-size: 16px">【第五步、断开连接】</span></h2>
<p>1: <span style="color: rgba(51, 153, 102, 1)"><span style="color: rgba(255, 102, 0, 1)">self</span>.centralManager</span> 断开指定 外设 <span style="color: rgba(51, 153, 102, 1)"> <span style="color: rgba(255, 102, 0, 1)">self</span>.peripheral;</span></p>
<p><span style="color: rgba(51, 153, 102, 1)">;</span></p>
<p>l 断开连接,回调函数:</p>
<p><span style="color: rgba(51, 153, 102, 1)">- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error;</span> </p>
<p> </p>
<h3><strong><img src="https://img2020.cnblogs.com/blog/1270351/202005/1270351-20200509141108233-2047566786.jpg"></strong></h3>
<h2><span style="font-size: 16px">功能补充部分:</span></h2>
<p>- 前面梳理了两端数据发送,接收流程,下面补充一下实现方案:</p>
<h2><span style="font-size: 16px">【一:广播端数据读,写方案】</span></h2>
<p><span style="color: rgba(51, 153, 102, 1)">CBMutableCharacteristic</span>: 广播端主要通过设置 <span style="color: rgba(51, 153, 102, 1)">CBMutableCharacteristic </span>特性值属性实现:</p>
<p><span style="color: rgba(51, 153, 102, 1)">CBCharacteristicPropertyWrite</span>:设置广播允许写入特性值,用于接收数据;</p>
<p><span style="color: rgba(51, 153, 102, 1)">CBCharacteristicPropertyNotify</span>:设置广播允许特征值更新的通知,用于发送数据;</p>
<p><span style="color: rgba(255, 102, 0, 1)">(以下代码,案例)</span></p>
<p><span style="color: rgba(51, 153, 102, 1)">CBMutableCharacteristic *characteristic = [</span></p>
<p> <span style="color: rgba(51, 153, 102, 1)"> </span></p>
<p><span style="color: rgba(51, 153, 102, 1)"> initWithType:characteristicID</span></p>
<p><span style="color: rgba(51, 153, 102, 1)"> properties:</span></p>
<p><span style="color: rgba(51, 153, 102, 1)"> CBCharacteristicPropertyNotify| <span style="color: rgba(255, 102, 0, 1)">(注:特性支持通知方案)</span></span></p>
<p><span style="color: rgba(51, 153, 102, 1)"> CBCharacteristicPropertyWrite <span style="color: rgba(255, 102, 0, 1)">(注:特性支持写入方案)</span></span></p>
<p><span style="color: rgba(51, 153, 102, 1)"> value:nil</span></p>
<p><span style="color: rgba(51, 153, 102, 1)"> permissions:CBAttributePermissionsReadable|</span></p>
<p><span style="color: rgba(51, 153, 102, 1)"> CBAttributePermissionsWriteable];</span></p>
<p><span style="color: rgba(51, 153, 102, 1)"> CBUUID *UUID_Descriptor = ; </span></p>
<p><span style="color: rgba(51, 153, 102, 1)"> <span style="color: rgba(153, 153, 153, 1)">// 初始化一个特征的描述</span></span></p>
<p><span style="color: rgba(51, 153, 102, 1)"> CBMutableDescriptor *mDescriptor = [initWithType:UUID_Descriptor value:];</span></p>
<p><span style="color: rgba(51, 153, 102, 1)"> ];</span></p>
<p><span style="color: rgba(51, 153, 102, 1)"> <span style="color: rgba(153, 153, 153, 1)"> // 特征添加进服务</span></span></p>
<p><span style="color: rgba(51, 153, 102, 1)"> service.characteristics = @;</span></p>
<p><span style="color: rgba(51, 153, 102, 1)"> <span style="color: rgba(153, 153, 153, 1)"> // 服务加入管理</span></span></p>
<p><span style="color: rgba(51, 153, 102, 1)"> ;</span></p>
<p> </p>
<p>---- 写入方案:</p>
<p>1: 通过更新自身特性值实现写入数据,调用函数:</p>
<p><span style="color: rgba(51, 153, 102, 1)">- (BOOL)updateValue:(NSData *)value forCharacteristic:(CBMutableCharacteristic *)characteristic onSubscribedCentrals:(nullable NSArray<CBCentral *> *)centrals;</span></p>
<p>2: 当自身特性值准备更新时,回调函数(写入完成,会通知扫描端):</p>
<p><span style="color: rgba(51, 153, 102, 1)">- (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral;</span></p>
<p> </p>
<p>---- 读取方案:</p>
<p>1: 通过允许写入特性值,回调函数(扫描端写入特性值完成回调):</p>
<p><span style="color: rgba(51, 153, 102, 1)">- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray<CBATTRequest *> *)requests;</span></p>
<p> </p>
<h2><span style="font-size: 16px">【第二:扫描端数据读,写方案】</span></h2>
<p>---- 写入方案:</p>
<p>1: 扫描发送数据,调用函数(广播特性值需要支持<span style="color: rgba(51, 153, 102, 1)">writeValue</span>: ):</p>
<p><span style="color: rgba(51, 153, 102, 1)">- (void)writeValue:(NSData *)data forCharacteristic:(CBCharacteristic *)characteristic type:(CBCharacteristicWriteType)type;</span></p>
<p>2: 写入数据完成,回调结果:</p>
<p><span style="color: rgba(51, 153, 102, 1)">- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(nonnull CBCharacteristic *)characteristic error:(nullable NSError *)error;</span></p>
<p> </p>
<p>---- 读取方案:</p>
<p>1:通过实现外设代理方案:<span style="color: rgba(51, 153, 102, 1)">CBPeripheralDelegate</span>:</p>
<p><span style="color: rgba(51, 153, 102, 1)">self.peripheral.delegate = self;</span></p>
<p>2: <span style="color: rgba(51, 153, 102, 1)">CBPeripheralDelegate</span>代理回调函数:</p>
<p><span style="color: rgba(51, 153, 102, 1)">- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error;</span></p>
<p> </p>
<p><img src="https://img2020.cnblogs.com/blog/1270351/202005/1270351-20200509141502957-1037132048.png"></p>
<p> <span style="color: rgba(255, 102, 0, 1)"><strong>结语:</strong></span></p>
<p><span style="color: rgba(255, 102, 0, 1)">蓝牙广播端和扫描端的实现流程,上面梳理完成。</span></p>
<p><span style="color: rgba(255, 102, 0, 1)">蓝牙数据传输中的加密处理没有包括在里面。</span></p>
<p><span style="color: rgba(255, 102, 0, 1)">有问题欢迎一起研究讨论,本人QQ号:497609288.</span></p>
<p> </p><br><br>
来源:https://www.cnblogs.com/tangjianfeng/p/12856217.html
頁:
[1]