iOS 藍(lán)牙BLE開(kāi)發(fā)

GAP(Generic Access Profile):它用來(lái)控制設(shè)備連接和廣播,GAP 使你的設(shè)備被其他設(shè)備可見(jiàn),并決定了你的設(shè)備是否可以或者怎樣與合同設(shè)備進(jìn)行交互。
GATT(Generic Attribute Profile):BLE連接都是建立在GATT協(xié)議之上的。GATT 是一個(gè)在藍(lán)牙連接之上的發(fā)送和接收很短的數(shù)據(jù)段的通用規(guī)范,這些很短的數(shù)據(jù)段被稱為屬性(Attribute)。
BLE中主要有兩個(gè)角色:外圍設(shè)備(Peripheral)和中心設(shè)備(Central)。一個(gè)中心設(shè)備可以連接多個(gè)外圍設(shè)備,一個(gè)外圍設(shè)備包含一個(gè)或多個(gè)服務(wù)(services),一個(gè)服務(wù)包含一個(gè)或多個(gè)特征(characteristics)。

1、外圍設(shè)備代碼(CBPeripheralManager)

使用CoreBluetooth庫(kù),創(chuàng)建CBPeripheralManager,實(shí)現(xiàn)CBPeripheralManagerDelegate代理

//nil表示在主線程中執(zhí)行。
self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];

創(chuàng)建完該對(duì)象,會(huì)回調(diào)peripheralManagerDidUpdateState:方法判斷藍(lán)牙狀態(tài),藍(lán)牙可用,給外設(shè)配置服務(wù)和特征

CBMutableCharacteristic *writeReadCharacteristic = [[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:@"FF01"] properties:CBCharacteristicPropertyRead | CBCharacteristicPropertyWrite value:nil permissions:CBAttributePermissionsReadEncryptionRequired | CBAttributePermissionsWriteEncryptionRequired];
    CBMutableService *service = [[CBMutableService alloc] initWithType:[CBUUID UUIDWithString:@"FF66"] primary:YES];
    [service setCharacteristics:@[writeReadCharacteristic]];
    [self.peripheralManager addService:service];

注意CBAttributePermissions

typedef NS_OPTIONS(NSUInteger, CBAttributePermissions) {
    CBAttributePermissionsReadable                  = 0x01,         //可讀
    CBAttributePermissionsWriteable                 = 0x02,         //可寫(xiě)
    CBAttributePermissionsReadEncryptionRequired    = 0x04,                 //可讀,需要建立安全連接
    CBAttributePermissionsWriteEncryptionRequired   = 0x08             // //可寫(xiě),需要建立安全連接
} NS_ENUM_AVAILABLE(10_9, 6_0);

當(dāng)中心設(shè)備讀寫(xiě)設(shè)置CBAttributePermissionsReadEncryptionRequired/CBAttributePermissionsWriteEncryptionRequired權(quán)限的Characteristic時(shí),會(huì)彈出彈框,請(qǐng)求建立安全連接


image.png

給外設(shè)配置服務(wù)特征后,會(huì)調(diào)用peripheralManager:didAddService:error: 服務(wù)特征全部添加完后發(fā)起廣播,如果在廣播時(shí)設(shè)置CBAdvertisementDataServiceUUIDsKey,會(huì)把該service廣播出去,中心設(shè)備在掃描時(shí)可根據(jù)該uuid找到該設(shè)備。外圍設(shè)備靠不斷發(fā)廣播,使中心設(shè)備發(fā)現(xiàn)它。

[self.peripheralManager startAdvertising:@{CBAdvertisementDataServiceUUIDsKey:@[[CBUUID UUIDWithString:@"0xFF66"]],CBAdvertisementDataLocalNameKey:@"ios設(shè)備"}];

當(dāng)中央端連接上了此設(shè)備并訂閱了特征時(shí)會(huì)回調(diào) didSubscribeToCharacteristic:

- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic {
    [self.peripheralManager updateValue:[@"訂閱特征" dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:characteristic onSubscribedCentrals:nil];
}

當(dāng)接收到中央端讀的請(qǐng)求時(shí)會(huì)調(diào)用didReceiveReadRequest:

- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request {
    if (request.characteristic.properties & CBCharacteristicPropertyRead) {
        NSData *data = [@"收到讀的請(qǐng)求" dataUsingEncoding:NSUTF8StringEncoding];
        [request setValue:data];
        [self.peripheralManager respondToRequest:request withResult:CBATTErrorSuccess];
    } else {
        [self.peripheralManager respondToRequest:request withResult:CBATTErrorReadNotPermitted];
    }
}

2、中心設(shè)備代碼(CBCentralManager)

創(chuàng)建CBCentralManager對(duì)象,實(shí)現(xiàn)CBCentralManagerDelegate代理

   self.manager = [[CBCentralManager alloc]initWithDelegate:self queue:nil];

回調(diào)centralManagerDidUpdateState:代理方法,當(dāng)central.state==CBManagerStatePoweredOn時(shí),開(kāi)啟掃描,設(shè)置serviceUUIDs可掃描特定外設(shè),CBCentralManagerScanOptionAllowDuplicatesKey設(shè)為NO不重復(fù)掃描已發(fā)現(xiàn)設(shè)備,YES是允許

        [self.manager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:@"0xFF66"]] options:@{CBCentralManagerScanOptionAllowDuplicatesKey: @NO}];

掃描到設(shè)備會(huì)回調(diào)centralManager:didDiscoverPeripheral:advertisementData:RSSI:,RSS絕對(duì)值越大,表示信號(hào)越差,設(shè)備離的越遠(yuǎn)
關(guān)閉掃描

[self.manager stopScan];

連接設(shè)備

    [self.manager connectPeripheral:periphral options:@{CBConnectPeripheralOptionNotifyOnConnectionKey:@YES}];
// 連接成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    //發(fā)現(xiàn)服務(wù),實(shí)現(xiàn)CBPeripheralDelegate代理
    [peripheral discoverServices:nil];
}

// 連接失敗
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {}
// 斷開(kāi)連接
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error {}

發(fā)現(xiàn)服務(wù)

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error {
//發(fā)現(xiàn)特征
    for (CBService *tempService in peripheral.services) {
        [peripheral discoverCharacteristics:nil forService:tempService];
    }
}

發(fā)現(xiàn)特征

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{    
    for (CBCharacteristic *characteristic in service.characteristics) {
     //可讀 
        if (characteristic.properties & CBCharacteristicPropertyRead) {
             [peripheral readValueForCharacteristic:characteristic];
        }
//可寫(xiě)
        if (characteristic.properties & CBCharacteristicPropertyWrite) {
              [peripheral writeValue:[@"xxxx" dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
        }
//Notify
        if (characteristic.properties & CBCharacteristicPropertyNotify) {
            [peripheral setNotifyValue:YES forCharacteristic:characteristic];
        }
//可寫(xiě)不需要回復(fù)
        if (characteristic.properties & CBCharacteristicPropertyWriteWithoutResponse) {
            [permissStr appendString:@" WriteWithoutResponse"];
        }
//Notify,需要配對(duì)
        if (characteristic.properties & CBCharacteristicPropertyNotifyEncryptionRequired) {}
}
//讀數(shù)據(jù)的回調(diào)
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error;
//是否寫(xiě)入成功的回調(diào)
 - (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error;
最后編輯于
?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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