藍(lán)牙開發(fā)模式

圖片發(fā)自簡(jiǎn)書App

首先先介紹一下藍(lán)牙開發(fā)的模式:

  1. 藍(lán)牙中心模式
  2. 藍(lán)牙外設(shè)模式
    一.藍(lán)牙中心模式

1.創(chuàng)建 CBCentralManager 中心對(duì)象
2.central掃描外設(shè) discover
3.central連接外設(shè) connect

  1. 掃描外設(shè)中的服務(wù)和特征discover
    4.1、獲取外設(shè)的 services:

執(zhí)行:discoverServices
成功后執(zhí)行:peripheral:didDiscoverServices
委托方法
4.2、獲取外設(shè)的 Characteristics,獲取 Characteristics 的值:

執(zhí)行:discoverCharacteristics:forService
成功后執(zhí)行:peripheral:didDiscoverCharacteristicsForService:error
委托方法
4.3、獲取外設(shè)的Characteristics 的 Descriptor 和 Descriptor 的值:

讀特征值:readValueForCharacteristic
讀到后進(jìn)入:didUpdateValueForCharacteristic:error委托方法
搜索 Characteristic:discoverDescriptorsForCharacteristic
搜到后進(jìn)入:didDiscoverDescriptorsForCharacteristic:error委托方法
獲取到 Descriptors 的值:peripheral:didUpdateValueForDescriptor:error
Descriptors 是對(duì) characteristic 的描述,一般是字符串
4.4、把數(shù)據(jù)寫到 Characteristic:writeCharacteristic:charactericstic:value
4.5、讀 RSSI,用通知的方式訂閱數(shù)據(jù)等。
5、與外設(shè)做數(shù)據(jù)交互 explored interact
6、訂閱 Characteristic 的通知:notifyCharacteristic:characteristic
取消通知:cancelNotifyCharacteristic:characteristic
7、斷開連接 disconnect:disconnnectPeripheral:peripheral


圖片發(fā)自簡(jiǎn)書App

二.藍(lán)牙外設(shè)模式流程

1.創(chuàng)建一個(gè) Peripheral 管理對(duì)象

peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
藍(lán)牙設(shè)備打開成功后會(huì)進(jìn)入委托方法:peripheralManagerDidUpdateState:

  1. 本地 Peripheral 設(shè)置服務(wù)、特性、描述、權(quán)限等。

創(chuàng)建 Characteristics 及其 description,創(chuàng)建 service,把 characteristics 添加到 service 中,再把 service 添加到 peripheralManager 中。

  1. Peripheral 發(fā)送廣播 advertising:peripheralManagerDidStartAdvertising:error

Peripheral 添加service:peripheralManager:didAddService:error

  1. 對(duì) central 的操作進(jìn)行響應(yīng)

讀 characteristics 請(qǐng)求:peripheralManager:didReceiveReadQuest:
寫characteristics 請(qǐng)求:peripheralManager:didReceiveWriteRequests:
訂閱特征:peripheralManager:central:didSubscribeToCharacteristic:
取消訂閱peripheralManager:central:didUnsubscribeFromCharacteristic:
一些基本屬性:

RSSI:信號(hào)強(qiáng)弱值,防丟器會(huì)用到。
UUID:唯一標(biāo)識(shí)符,用于區(qū)分設(shè)備
service UUID:服務(wù),一個(gè) Server 會(huì)包含多個(gè)characteristic,用 UUID 來區(qū)分。
characteristic:特征,用 UUID 來區(qū)分
了解了以上流程:由于蘋果的封閉生態(tài),之前對(duì)藍(lán)牙的限制比較嚴(yán)格,如果要和 iOS 設(shè)備通信,必須是經(jīng)過了 MFI 認(rèn)證的芯片才可以;藍(lán)牙4.0低功耗模式的到來,蘋果也對(duì)藍(lán)牙放開了一些限制。所以目前針對(duì) iOS 的藍(lán)牙編程主要就是針對(duì)藍(lán)牙4.0以上的低功耗藍(lán)牙,也就是 BLE 模式。
BLE 模式的特點(diǎn):

功耗低。
連接速度很快,連接距離遠(yuǎn)(100米)。
相應(yīng)的傳輸數(shù)據(jù)量小,比傳統(tǒng)藍(lán)牙傳輸?shù)男『芏啵瑩?jù)說單次發(fā)送也就20字節(jié)。

BLE 模式并不適合用來做較大數(shù)據(jù)量的傳輸使用
Bluetooth.h

@property(nonatomic,strong) CBCentralManager *centralManager;
@property(nonatomic,strong) CBPeripheral *peripheral;
@property(nonatomic,strong) CBCharacteristic *characteristic;
@property(nonatomic,strong) NSMutableArray *peripheralArray;

  • (void)initBluetooth; //初始化藍(lán)牙
  • (void)scanBluetooth; //掃描藍(lán)牙
  • (void)stopScanBluetooth; //停止掃描
  • (void)connectPeripheral:(CBPeripheral *)peripheral; //連接藍(lán)牙
  • (void)disConnectPeripheral:(CBPeripheral *)peripheral; //取消連接藍(lán)牙
  • (void)sendData:(NSData *)data; //向掃描到的藍(lán)牙Characteristic 發(fā)送數(shù)據(jù)

Bluetooth.m

// 初始化藍(lán)牙

  • (void)initBluetooth
    {
    _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];//創(chuàng)建CBCentralManager對(duì)象
    _peripheralArray = [[NSMutableArray alloc] init];
    }

//掃描藍(lán)牙

  • (void)scanBluetooth
    {
    NSLog(@"BluetoothBase scanBluetooth");
    //CBCentralManagerScanOptionAllowDuplicatesKey值為 No,表示不重復(fù)掃描已發(fā)現(xiàn)的設(shè)備
    NSDictionary *optionDic = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:CBCentralManagerScanOptionAllowDuplicatesKey];
    [_centralManager scanForPeripheralsWithServices:nil options:optionDic];//如果你將第一個(gè)參數(shù)設(shè)置為nil,Central Manager就會(huì)開始尋找所有的服務(wù)。
    }
    //停止掃描藍(lán)牙

  • (void)stopScanBluetooth
    {
    [self.centralManager stopScan];
    NSLog(@"BluetoothBase stopScanBluetooth,已經(jīng)連接外設(shè)停止掃描或者手動(dòng)停止掃描");
    }
    //連接藍(lán)牙

  • (void)connectPeripheral:(CBPeripheral *)peripheral
    {
    [self.centralManager connectPeripheral:peripheral options:nil];
    self.peripheral = peripheral;
    peripheral.delegate = self; //連接時(shí)設(shè)置代理
    }
    //取消連接藍(lán)牙

  • (void)disConnectPeripheral:(CBPeripheral *)peripheral
    {
    [_centralManager cancelPeripheralConnection:peripheral];
    }
    //如果發(fā)送的數(shù)據(jù)過大,就需要做分包處理了。至于傳輸?shù)淖畲笞止?jié)數(shù)是多大,就需要和硬件工程師討論了。pl @PlatoJobs
    //向藍(lán)牙寫入數(shù)據(jù)

  • (void)sendData:(NSData *)data
    {
    [self initBluetoothDispatch];

    if (_characteristic.properties & CBCharacteristicPropertyWrite){
    [_peripheral writeValue:data forCharacteristic:_characteristic type:CBCharacteristicWriteWithResponse];
    NSLog(@"BluetoothBase writeDataToCharacteristic:%@",[_characteristic.UUID UUIDString]);
    }else{
    NSLog(@"沒有發(fā)現(xiàn)可以寫入的characteristic");
    }
    }
    藍(lán)牙的一些代理方法(CBCentralManagerDelegate):

//centralManager已經(jīng)更新狀態(tài)

  • (void)centralManagerDidUpdateState:(CBCentralManager *)central
    {
    NSLog(@"centralManagerDidUpdateState:%ld",(long)central.state);
    switch (central.state) {
    case CBCentralManagerStateUnknown:
    NSLog(@"CBCentralManagerStateUnknown");
    break;
    case CBCentralManagerStateResetting:
    NSLog(@"CBCentralManagerStateResetting");
    break;
    case CBCentralManagerStateUnsupported:
    NSLog(@"CBCentralManagerStateUnsupported");
    break;
    case CBCentralManagerStateUnauthorized:
    NSLog(@"CBCentralManagerStateUnauthorized");
    break;
    case CBCentralManagerStatePoweredOff:
    NSLog(@"CBCentralManagerStatePoweredOff");
    break;
    case CBCentralManagerStatePoweredOn:
    [self scanBluetooth]; //很重要,當(dāng)藍(lán)牙處于打開狀態(tài),開始掃描。
    break;
    default:
    NSLog(@"藍(lán)牙未工作在正確狀態(tài)");
    break;
    }
    }

//centralManager已經(jīng)發(fā)現(xiàn)外設(shè)

//掃描到外設(shè),停止掃描,連接設(shè)備(每掃描到一個(gè)外設(shè)都會(huì)調(diào)用一次這個(gè)函數(shù),若要展示搜索到的藍(lán)牙,可以逐一保存 peripheral 并展示)

  • (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI
    {
    [_peripheralArray addObject:peripheral]; //保存用于連接的 peripheral
    [PRTBluetoothModel share].peripheralArray = _peripheralArray;

    [[NSNotificationCenter defaultCenter] postNotificationName:@"PRTBluetoothScanUpdatePeripheralList" object:nil];
    }
    //已經(jīng)連接外設(shè)
    //連接外設(shè)成功,掃描外設(shè)中的服務(wù)和特征

  • (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
    {
    [PRTDispatchModel share].currentDispatchMode = PRTPrinterModeBle; //將藍(lán)牙模式保存到當(dāng)前傳輸模式。

    NSLog(@"didConnectPeripheral:%@",peripheral.name);
    [[NSNotificationCenter defaultCenter] postNotificationName:@"PRTBluetoothScanDidConnectPeripheral" object:nil];

    [self stopScanBluetooth]; //連接成功后停止掃描

    [self.peripheral setDelegate:self];

    //數(shù)組中存放兩個(gè)服務(wù)的 UUID
    NSMutableArray *uuidArray = [[NSMutableArray alloc] initWithObjects:[CBUUID UUIDWithString:UUID_String_DeviceInfo_Service], [CBUUID UUIDWithString:UUIDSTR_ISSC_PROPRIETARY_SERVICE], nil];

    [peripheral discoverServices:uuidArray];//發(fā)現(xiàn)服務(wù),成功后執(zhí)行:peripheral:didDiscoverServices委托方法
    }
    //連接外設(shè)失敗

  • (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
    {
    NSLog(@"didFailToConnectPeripheral:%@",error);
    }
    //已經(jīng)發(fā)現(xiàn)服務(wù)

  • (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
    {
    NSLog(@"didDiscoverServices:%@",peripheral.name);
    if (error) {
    NSLog(@"didDiscoverServices error:%@",[error localizedDescription]);
    return;
    }

    for (CBService *service in peripheral.services) {
    //發(fā)現(xiàn)特征,成功后執(zhí)行:peripheral:didDiscoverCharacteristicsForService:error委托方法
    [peripheral discoverCharacteristics:nil forService:service];
    }
    }

//已經(jīng)為服務(wù)發(fā)現(xiàn)特征
/*
藍(lán)牙都會(huì)有幾個(gè)服務(wù),每個(gè)服務(wù)都會(huì)有幾個(gè)特征,服務(wù)和特征都是用不同的 UUID 來標(biāo)識(shí)的。
每個(gè)特征的 properties 是不同的,就是說有不同的功能屬性,有的對(duì)應(yīng)寫入,有的對(duì)應(yīng)讀取。
藍(lán)牙聯(lián)盟有一個(gè)規(guī)范,但是這個(gè)也是可以自定義的,所以不清楚的話,聯(lián)系硬件工程師問清楚
*/

  • (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
    {
    NSLog(@"didDiscoverCharacteristicsForServic:%@",service.UUID);

    CBCharacteristic *characteristic = nil;

    if ([service.UUID isEqual:[CBUUID UUIDWithString:@"這里填你的藍(lán)牙服務(wù)的 UUID"]]) {
    for (characteristic in service.characteristics)
    {
    if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"這里填你的藍(lán)牙特征的 UUID"]]) {
    self.characteristic = characteristic;//重要,將滿足條件的特征保存為全局特征,以便對(duì)齊進(jìn)行寫入操作。
    [PRTBluetoothModel share].characteristicWrite = characteristic;
    [self.peripheral setNotifyValue:YES forCharacteristic:characteristic];
    }
    }
    }

    if (error) {
    NSLog(@"didDiscoverCharacteristicsForService error:%@",[error localizedDescription]);
    }
    }
    // 已經(jīng)更新特征的值
    //獲取外設(shè)發(fā)來的數(shù)據(jù),不論是read和notify,獲取數(shù)據(jù)都是從這個(gè)方法中讀取。

  • (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
    {
    NSLog(@"didUpdateValueForCharacteristic:%@",[characteristic.UUID UUIDString]);
    if (error) {
    NSLog(@"didUpdateValueForCharacteristic error:%@",[error localizedDescription]);
    }

    for (CBDescriptor *descriptor in characteristic.descriptors) //12.23新增
    {
    [peripheral readValueForDescriptor:descriptor];
    }
    }
    //已經(jīng)寫入特征的值
    //委托方法:已經(jīng)為特征【寫入值】
    -(void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
    {
    NSLog(@"didWriteValueForCharacteristic:%@",[characteristic.UUID UUIDString]);

    if (error) {
    NSLog(@"didWriteValueForCharacteristic error:%@",[error localizedDescription]);
    }

    [peripheral readValueForCharacteristic:characteristic]; //12.23新增
    }
    //已經(jīng)發(fā)現(xiàn)特征的描述

  • (void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
    {
    NSLog(@"didDiscoverDescriptorsForCharacteristic:%@",characteristic);
    for (CBDescriptor *d in characteristic.descriptors) {
    NSLog(@"Descriptor UUID:%@",d.UUID);
    }
    }
    // 已經(jīng)更新描述的值

  • (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error
    {
    NSLog(@"didUpdateValueForDescriptor:%@",descriptor);
    [peripheral readValueForDescriptor:descriptor]; //12.23新增
    }
    //已經(jīng)更新特征的通知狀態(tài)

  • (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    NSLog(@"didUpdateNotificationStateForCharacteristic:%@",characteristic);

    [peripheral readValueForCharacteristic:characteristic]; //12.23新增
    [peripheral discoverDescriptorsForCharacteristic:characteristic];
    }

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容