GAP(Generic Access Profile):它用來控制設(shè)備連接和廣播民泵,GAP 使你的設(shè)備被其他設(shè)備可見,并決定了你的設(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庫召边,創(chuàng)建CBPeripheralManager,實(shí)現(xiàn)CBPeripheralManagerDelegate代理
//nil表示在主線程中執(zhí)行裹驰。
self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
創(chuàng)建完該對象隧熙,會回調(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, //可寫
CBAttributePermissionsReadEncryptionRequired = 0x04, //可讀贞盯,需要建立安全連接
CBAttributePermissionsWriteEncryptionRequired = 0x08 // //可寫,需要建立安全連接
} NS_ENUM_AVAILABLE(10_9, 6_0);
當(dāng)中心設(shè)備讀寫設(shè)置CBAttributePermissionsReadEncryptionRequired/CBAttributePermissionsWriteEncryptionRequired權(quán)限的Characteristic時(shí)沪饺,會彈出彈框躏敢,請求建立安全連接
給外設(shè)配置服務(wù)特征后,會調(diào)用peripheralManager:didAddService:error: 服務(wù)特征全部添加完后發(fā)起廣播整葡,如果在廣播時(shí)設(shè)置CBAdvertisementDataServiceUUIDsKey父丰,會把該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í)會回調(diào) didSubscribeToCharacteristic:
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic {
[self.peripheralManager updateValue:[@"訂閱特征" dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:characteristic onSubscribedCentrals:nil];
}
當(dāng)接收到中央端讀的請求時(shí)會調(diào)用didReceiveReadRequest:
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request {
if (request.characteristic.properties & CBCharacteristicPropertyRead) {
NSData *data = [@"收到讀的請求" dataUsingEncoding:NSUTF8StringEncoding];
[request setValue:data];
[self.peripheralManager respondToRequest:request withResult:CBATTErrorSuccess];
} else {
[self.peripheralManager respondToRequest:request withResult:CBATTErrorReadNotPermitted];
}
}
2魏滚、中心設(shè)備代碼(CBCentralManager)
創(chuàng)建CBCentralManager對象镀首,實(shí)現(xiàn)CBCentralManagerDelegate代理
self.manager = [[CBCentralManager alloc]initWithDelegate:self queue:nil];
回調(diào)centralManagerDidUpdateState:代理方法,當(dāng)central.state==CBManagerStatePoweredOn時(shí)鼠次,開啟掃描更哄,設(shè)置serviceUUIDs可掃描特定外設(shè),CBCentralManagerScanOptionAllowDuplicatesKey設(shè)為NO不重復(fù)掃描已發(fā)現(xiàn)設(shè)備腥寇,YES是允許
[self.manager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:@"0xFF66"]] options:@{CBCentralManagerScanOptionAllowDuplicatesKey: @NO}];
掃描到設(shè)備會回調(diào)centralManager:didDiscoverPeripheral:advertisementData:RSSI:成翩,RSS絕對值越大,表示信號越差赦役,設(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 {}
// 斷開連接
- (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];
}
//可寫
if (characteristic.properties & CBCharacteristicPropertyWrite) {
[peripheral writeValue:[@"xxxx" dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
}
//Notify
if (characteristic.properties & CBCharacteristicPropertyNotify) {
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
//可寫不需要回復(fù)
if (characteristic.properties & CBCharacteristicPropertyWriteWithoutResponse) {
[permissStr appendString:@" WriteWithoutResponse"];
}
//Notify,需要配對
if (characteristic.properties & CBCharacteristicPropertyNotifyEncryptionRequired) {}
}
//讀數(shù)據(jù)的回調(diào)
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error;
//是否寫入成功的回調(diào)
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error;