蓝牙

iOS 蓝牙BLE开发

2020-03-20  本文已影响0人  桔子橙子柚子_F

GAP(Generic Access Profile):它用来控制设备连接和广播,GAP 使你的设备被其他设备可见,并决定了你的设备是否可以或者怎样与合同设备进行交互。
GATT(Generic Attribute Profile):BLE连接都是建立在GATT协议之上的。GATT 是一个在蓝牙连接之上的发送和接收很短的数据段的通用规范,这些很短的数据段被称为属性(Attribute)。
BLE中主要有两个角色:外围设备(Peripheral)和中心设备(Central)。一个中心设备可以连接多个外围设备,一个外围设备包含一个或多个服务(services),一个服务包含一个或多个特征(characteristics)。

1、外围设备代码(CBPeripheralManager)

使用CoreBluetooth库,创建CBPeripheralManager,实现CBPeripheralManagerDelegate代理

//nil表示在主线程中执行。
self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];

创建完该对象,会回调peripheralManagerDidUpdateState:方法判断蓝牙状态,蓝牙可用,给外设配置服务和特征

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);

当中心设备读写设置CBAttributePermissionsReadEncryptionRequired/CBAttributePermissionsWriteEncryptionRequired权限的Characteristic时,会弹出弹框,请求建立安全连接


image.png

给外设配置服务特征后,会调用peripheralManager:didAddService:error: 服务特征全部添加完后发起广播,如果在广播时设置CBAdvertisementDataServiceUUIDsKey,会把该service广播出去,中心设备在扫描时可根据该uuid找到该设备。外围设备靠不断发广播,使中心设备发现它。

[self.peripheralManager startAdvertising:@{CBAdvertisementDataServiceUUIDsKey:@[[CBUUID UUIDWithString:@"0xFF66"]],CBAdvertisementDataLocalNameKey:@"ios设备"}];

当中央端连接上了此设备并订阅了特征时会回调 didSubscribeToCharacteristic:

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

当接收到中央端读的请求时会调用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、中心设备代码(CBCentralManager)

创建CBCentralManager对象,实现CBCentralManagerDelegate代理

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

回调centralManagerDidUpdateState:代理方法,当central.state==CBManagerStatePoweredOn时,开启扫描,设置serviceUUIDs可扫描特定外设,CBCentralManagerScanOptionAllowDuplicatesKey设为NO不重复扫描已发现设备,YES是允许

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

扫描到设备会回调centralManager:didDiscoverPeripheral:advertisementData:RSSI:,RSS绝对值越大,表示信号越差,设备离的越远
关闭扫描

[self.manager stopScan];

连接设备

    [self.manager connectPeripheral:periphral options:@{CBConnectPeripheralOptionNotifyOnConnectionKey:@YES}];
// 连接成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    //发现服务,实现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 {}

发现服务

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error {
//发现特征
    for (CBService *tempService in peripheral.services) {
        [peripheral discoverCharacteristics:nil forService:tempService];
    }
}

发现特征

- (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];
        }
//可写不需要回复
        if (characteristic.properties & CBCharacteristicPropertyWriteWithoutResponse) {
            [permissStr appendString:@" WriteWithoutResponse"];
        }
//Notify,需要配对
        if (characteristic.properties & CBCharacteristicPropertyNotifyEncryptionRequired) {}
}
//读数据的回调
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error;
//是否写入成功的回调
 - (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error;
上一篇下一篇

猜你喜欢

热点阅读