iOS藍牙開發梳理:廣播端和掃描端實現


               

【前言】

 * 目前項目里有藍牙支付功能,對於藍牙開發功能,要求比較高,包括iOS與Android之間的通訊。

 * 今天整理了下iOS藍牙SDK開發流程中的知識點,總結了這篇文章,希望給各位開發藍牙功能的同學帶來幫助。

【功能目標】

  開發移動設備的藍牙功能,目的用來實現設備之間數據自由通訊(數據發,收),完成移動服務端和客服端場景交互。

【定義場景】

  1: 廣播端:服務端定義,用於被多台掃描設備同時識別並訂閱;

  2: 掃描端:客服端定義,用於掃描並訂閱廣播端設備;

【實現方案】

CoreBluetooth:iOS原生SDK。

導入:  <CoreBluetooth/CoreBluetooth.h>  。

 

開始廣播功能:

【第一步、開啟廣播】

(1):  涉及的類

1:  CBPeripheralManager

外設管理器,管理設備廣播狀態。

2:  CBUUID

唯一標識,設備的服務,特性和特征描述符。

3: CBMutableService

外設管理器的服務,用於設定服務特征。

4:  CBMutableCharacteristic

服務的特征,用於設定特征描述。

5:  CBMutableDescriptor

特征的描述。

 

(2):  類調用時序圖

  

時序圖備注: CBPeripheralManager 添加服務是很重要的一步。

 

(3):  CoreBluetooth 原生函數

1:  藍牙創建,用於權限判斷:

- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral;

2:  外設管理器添加服務完成,回調結果:

(void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(NSError *)error;

3:  廣播開啟完成,回調結果:

-(void)peripheralManagerDidStartAdvertising: (CBPeripheralManager *)peripheral error:(NSError *)error;

 

4廣播開啟失敗,重啟

1:   重置廣播,目前重試次數:         ADVERTISING_RETRY = 3(注:根據自己需求設置)

2:  重置加載安全模塊調用方法:       [self setUpServiceSecurity];   (注:需要根據自己功能需求實現)

3:  重置外設管理器步驟:              1:關閉廣播 2:清除設備 3:重置管理器

4:  重置創建服務和特征調用方法:  [self setupServiceAndCharacteristics];(注:需要根據自己功能需求實現)

 

5藍牙廣播,參數配置

1:  廣播設備名稱:  可通過CBPeripheralManager 函數:

- (void)startAdvertising:(nullable NSDictionary<NSString *, id> *)advertisementData;

進行設置:CBAdvertisementDataLocalNameKey 的值。 

2:  信號強度 :           iOS不支持設置。

3:  廣播頻率 :           iOS不支持設置。

 

【第二步、廣播被訂閱】

1:  涉及的類

1:  CBCentral:             發起訂閱的掃描設備;

2:  CBCharacteristic:   掃描設備的特性信息;

  

2:  CoreBluetooth原生函數

1:  訂閱成功回調,記錄訂閱掃描設備:

-(void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic;

 

3:  被取消訂閱函數

l  掃描設備取消訂閱,移除相應記錄的設備信息:

-(void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic;

 

4:完成訂閱

注:當有掃描設備訂閱了廣播設備后,廣播端可以給掃描設備發送數據。

 

【第三步、發送數據】

1:  涉及的類

  DeviceInforModel:            數據容器對象。(注:自定義對象,用來記錄外設設備部信息和接,發數據的記錄)

-屬性-  messageSentData: 發送數據DATA;

-屬性- sentStartIndex:       發送數據開始下標;

-屬性- diffLength:             每個包最大字節;

 

2:  發送流程圖

 

(流程圖備注):

1:  Start:                   分包首個數據包字符串標示;

2:  End:                    分包最后一個數據包字符串標示;

3:  sentStartIndex:     每個發送數據包的開始標示,默認等於0;

4:  messageSentData:總數據中按照 sentStartIndex 截取的分包數據;

5:  IsReady:              外圍設備已准備好發送特征值更新,有相應的回調函數;

6:  sendMessagePart:進入數據分包流程;

 

3:  CoreBluetooth原生函數

1:  發送:通過通知或指示將更新后的特征值發送給一個或多個中心。

- (BOOL)updateValue:(NSData *)value forCharacteristic:(CBMutableCharacteristic *)characteristic onSubscribedCentrals:(nullable NSArray<CBCentral *> *)centrals;

 

2:  發送結果:告訴委托本地外圍設備已准備好發送特征值更新。

- (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral;

 

【第四步、接收數據】

1:  涉及的類

1:  CBATTRequest:            寫入數據的請求。

-屬性- lastObject:             目標數據;

      

2:  DeviceInforModel:          數據容器對象。(自定義對象,用來記錄外設設備部信息和接,發數據的記錄)

-屬性-  messageReceivedData:發送數據DATA;

-屬性- isStart:                        開頭標示;

-屬性- startMsg:                     開頭數據;

-屬性- isEnd:                          結尾標示;

-屬性- endMsg:                       結尾數據;

 

2:  接收流程圖

 

(流程圖備注):

1:  Start:       分包首個數據包字符串標示,此時設置isStart=YES;

2:  End:        分包最后一個數據包字符串標示,此時設置isEnd=YES;

3:  CBATTRequest.lastObject:每個包的數據源;

4:  messageReceivedData:    與歷史數據進行合並;

5:  hasPrefix:@"End":這步判斷結束標示,有End標示,合並數據,輸出完整包;

6:  CBATTRequest:   沒有End標示,等待分包數據;

 

3:  CoreBluetooth原生函數

l  中心設備寫入數據的時候,回調函數:

- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray<CBATTRequest *> *)requests;

 

【完成:廣播功能】

完成上面步驟,此時廣播端可以自由發送和接收數據。

 

 

開始掃描功能:

【第一步、開啟掃描】

(1):  涉及的類

1:  CBCentralManager:中心設備管理器。

2:  CBUUID:               唯一標識,設備的服務,特性和特征描述符。

3:  CBService:    中心設備管理器的服務,用於掃描指定服務廣播。

4:  CBPeripheral:外設管理器,掃描到或連接的廣播設備。

5:  RSSI:            外設型號強度值。

 

(2):  類調用時序圖

時序圖備注:在識別到廣播外設 CBPeripheral,並且完成記錄后,就可以開啟指定外設的連接請求,APP級外設標示通過 CBService 區分。

 

3掃描開啟失敗

注:藍牙功能不可用,或者未開啟,會導致開啟失敗。

未發現符合要求的外設時,會繼續掃描。

 

4藍牙掃描,參數配置

1: 掃描設備名稱:     iOS不支持設置,

備注:訂閱廣播端成功后,廣播端區別掃描設備通過:central.identifier

2: 掃描頻率:          iOS不支持設置。

 

【第二步、連接廣播】

(1):  涉及的對象

1:  self. centralManager:中心設備管理器;

2:  self.peripheral:        中心設備管理器連接目標外設;

3:  self.service:                用於查找的服務特征;

4:  service.characteristics:對應服務的特征集合;

 

 2:  CoreBluetooth原生函數

1: 發起連接外設,調用函數:

- (void)connectPeripheral:(CBPeripheral *)peripheral options:(nullable NSDictionary<NSString *, id> *)options;

2: 連接成功,回調函數:

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral;

3: 根據SERVICE_UUID來尋找服務,調用函數:

- (void)discoverServices:(nullable NSArray<CBUUID *> *)serviceUUIDs;

4: 尋找到特定服務,回調函數:

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error;

5:尋找特定服務特征,回調函數:

- (void)discoverCharacteristics:(nullable NSArray<CBUUID *> *)characteristicUUIDs forService:(CBService *)service;

6:  發現特征,回調函數:

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

7:  讀取特征數據,調用函數:

[peripheral readValueForCharacteristic:self.characteristic];

8:  發送訂閱通知,調用函數(廣播端會收到被訂閱消息):

[peripheral setNotifyValue:YES forCharacteristic:self.characteristic];

9:  連接失敗,回調函數:

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

10:  斷開連接,回調函數:

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

  

3:  CoreBluetooth連接流程圖

 

【第三步、發送數據】

注:掃描端處理發送數據流程,與廣播端處理發送一致,詳見廣播端;

 

【第四步、接收數據】

注:掃描端處理接收數據流程,與廣播端處理接收一致,詳見廣播端;

 

【第五步、斷開連接】

1:  self.centralManager  斷開指定 外設  self.peripheral;

[self.centralManager cancelPeripheralConnection:self.peripheral];

l  斷開連接,回調函數:

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

 

功能補充部分:

- 前面梳理了兩端數據發送,接收流程,下面補充一下實現方案:

【一:廣播端數據讀,寫方案】

CBMutableCharacteristic:        廣播端主要通過設置 CBMutableCharacteristic 特性值屬性實現:

CBCharacteristicPropertyWrite:設置廣播允許寫入特性值,用於接收數據;

CBCharacteristicPropertyNotify:設置廣播允許特征值更新的通知,用於發送數據;

(以下代碼,案例)

CBMutableCharacteristic *characteristic = [

                                               [CBMutableCharacteristic alloc]

                                               initWithType:characteristicID

                                               properties:

                                               CBCharacteristicPropertyNotify|     (注:特性支持通知方案)

                                               CBCharacteristicPropertyWrite       (注:特性支持寫入方案)

                                               value:nil

                                               permissions:CBAttributePermissionsReadable|

                                               CBAttributePermissionsWriteable];

    CBUUID *UUID_Descriptor = [CBUUID UUIDWithString:DESCRIPTORUUID];    

    // 初始化一個特征的描述

    CBMutableDescriptor *mDescriptor = [[CBMutableDescriptor alloc]initWithType:UUID_Descriptor value:[NSData data]];

    [characteristic setDescriptors:@[mDescriptor]];

    // 特征添加進服務

    service.characteristics = @[characteristic];

    // 服務加入管理

    [self.peripheralManager addService:service];

 

----  寫入方案:

1: 通過更新自身特性值實現寫入數據,調用函數:

- (BOOL)updateValue:(NSData *)value forCharacteristic:(CBMutableCharacteristic *)characteristic onSubscribedCentrals:(nullable NSArray<CBCentral *> *)centrals;

2: 當自身特性值准備更新時,回調函數(寫入完成,會通知掃描端):

- (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral;

 

----  讀取方案:

1: 通過允許寫入特性值,回調函數(掃描端寫入特性值完成回調):

- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray<CBATTRequest *> *)requests;

  

【第二:掃描端數據讀,寫方案】

---- 寫入方案:

1: 掃描發送數據,調用函數(廣播特性值需要支持writeValue: ):

- (void)writeValue:(NSData *)data forCharacteristic:(CBCharacteristic *)characteristic type:(CBCharacteristicWriteType)type;

2: 寫入數據完成,回調結果:

- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(nonnull CBCharacteristic *)characteristic error:(nullable NSError *)error;

 

----  讀取方案:

1:通過實現外設代理方案:CBPeripheralDelegate

self.peripheral.delegate = self;

2: CBPeripheralDelegate代理回調函數:

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

 

 結語:

藍牙廣播端和掃描端的實現流程,上面梳理完成。

藍牙數據傳輸中的加密處理沒有包括在里面。

有問題歡迎一起研究討論,本人QQ號:497609288.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM