iOS蓝牙4.0开发03-执行常见的Periphral角色任务

来源:互联网 发布:shutting down mysql 编辑:程序博客网 时间:2024/05/21 10:01

执行常见的Periphral角色任务

第一步,建立一个Peripheral Manager,进行分配和初初始化,通过CBPeriphralManager类方法initWithDelegate:queue:options

myPeripheralManager =
        [[CBPeripheralManager alloc] initWithDelegate:self queue:nil options:nil];
peripheralManagerDidUpdateState:是peripheral manager 的代理对象的方法。
第二步,建立services和Characteristics
通过UUIDS来识别services和Characteristics,128bit的蓝牙特定UUIDS,由Core Bluetooth框架的CBUUID对象表示。
Bluetooth SIG为了方便使用提供了16-bit的UUID,可以通过使用UUIDWithString方法来简化为service预定义的16-bit UUID
例如:
CBUUID *heartRateServiceUUID = [CBUUID UUIDWithString: @"180D"];
当你建立了一个预定义16-bitUUID的CBUUID对象时,Core Bluetooth会基于Bluetooth 基础 UUID 来预先填充上128-bitUUID剩余的部分。
如果services 和 characteristics 没有预定义的Bluetooth 16-bit UUIDs,则需要产生一个128-bit UUIDs来识别它们。
在Terminal窗口里,利用命令uuidgen来产生128-bit的UUIDs,如下:
$ uuidgen
71DA3FD1-7E10-41C1-B16F-4430B506CDE7
那么使用这个UUID建立一个CBUUID对象,如下:
CBUUID *myCustomServiceUUID =
        [CBUUID UUIDWithString:@"71DA3FD1-7E10-41C1-B16F-4430B506CDE7"];
建立services 和 characteristic的树

myCharacteristic =
        [[CBMutableCharacteristic alloc] initWithType:myCharacteristicUUID
         properties:CBCharacteristicPropertyRead
         value:myValue permissions:CBAttributePermissionsReadable];
上例建立了它的properties是读,value是myValue,permissions是允许可读。注意要可写的话,value要是nil。

有了一个可变的characteristic,同时建立一个可变的services

 myService = [[CBMutableService alloc] initWithType:myServiceUUID primary:YES];
primary:YES表明是主要的service,这是相对于secondary的service而言的。建立service和characteristic的联系:

myService.characteristics = @[myCharacteristic];
第三步,出版(publish)services和characteristics

使用CBPeripheralManager类方法addService:

[myPeripheralManager addService:myService];
peripheral manager采用peripheralManager:didAddService:error方法来处理services不能被出版的情况,如下

- (void)peripheralManager:(CBPeripheralManager *)peripheral
            didAddService:(CBService *)service
                    error:(NSError *)error {
 
    if (error) {
        NSLog(@"Error publishing service: %@", [error localizedDescription]);
    }
    ...
注意:一个service 和其characteristics出版到peripheral的数据库后,service就被缓存起来,不能在改变了。

第四步,广播(advertising)services

使用CBPeripheralManager类方法startAdvertising:

 [myPeripheralManager startAdvertising:@{ CBAdvertisementDataServiceUUIDsKey :
        @[myFirstService.UUID, mySecondService.UUID] }];
peripheral manager使用方法peripheralManagerDidStartAdvertising:error来处理广播失败的情况:

- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral
                                       error:(NSError *)error {
 
    if (error) {
        NSLog(@"Error advertising: %@", [error localizedDescription]);
    }
    ...
注意:广播行为会收到app的工作状态影响(如在后台工作)

一旦开始广播数据,附近的centrals就可以发现和初识化连接了。

第五步,来自central的读写命令反馈

但连接的central要求(request)去读一个characteristic的值的时候,peripheral manager就会调用方法peripheralManager:didReceiveReadRequest

- (void)peripheralManager:(CBPeripheralManager *)peripheral
    didReceiveReadRequest:(CBATTRequest *)request {
 
    if ([request.characteristic.UUID isEqual:myCharacteristic.UUID]) {
        ...
当characteristics的UUIDs匹配后,接着要确保读的characteristic值的指针地址没有超出范围。采用下面方法来保证正确读:

if (request.offset > myCharacteristic.value.length) {
        [myPeripheralManager respondToRequest:request
            withResult:CBATTErrorInvalidOffset];
        return;
    }
read request把offset考虑进去

 request.value = [myCharacteristic.value
        subdataWithRange:NSMakeRange(request.offset,
        myCharacteristic.value.length - request.offset)];
当读命令完全正确执行(或失败)后,调用CBPeripheralManager类方法respondToRequest:withResult:

    [myPeripheralManager respondToRequest:request withResult:CBATTErrorSuccess];
    ...
每调用peripheralManager:didReceiveReadRequest:方法,就要调用一次respondToRequest:withResult:方法

写命令类似的,可以写characteristic的值:

myCharacteristic.value = request.value;
在写值要确保把offset考虑进去。

每调用peripheralManager:didReceiveWriteRequest:方法,就要调用一次respondToRequest:withResult:方法

    [myPeripheralManager respondToRequest:[requests objectAtIndex:0]
        withResult:CBATTErrorSuccess];
第六步,发送已更新的characteristic values 到已订阅(subscribed)的centrals

- (void)peripheralManager:(CBPeripheralManager *)peripheral
                  central:(CBCentral *)central
didSubscribeToCharacteristic:(CBCharacteristic *)characteristic {
 
    NSLog(@"Central subscribed to characteristic %@", characteristic);
    ...

使用上面的代理方法,表明要开始发送central更新值

接着,得到characteristic更新值,发送到central,调用CBPeripheralManager类方法updateValue:forCharacteristic:onSubscribedCentrals:

NSData *updatedValue = // fetch the characteristic's new value
    BOOL didSendValue = [myPeripheralManager updateValue:updatedValue
        forCharacteristic:characteristic onSubscribedCentrals:nil];
上面的nil,表明是所有的连接的已订阅的central都要更新。

通过方法updateValue:forCharacteristic:onSubscribedCentrals:返回一个布尔量表明更新值是否送到已订阅的central了。

如果用来发送更新值的基础队列是满的,则返回NO。当有更多的空间可用发送队别时,调用peripheralManagerIsReadyToUpdateSubscribes:

再次调用方法updateValue:forCharacteristic:onSubscribedCentrals:就可以重发值了。

注意:依据characteristic值的大小,并不是所有的值是通过notifications传输的。可以通过CBPeriphral类方法readDataForCharacteristic:来得到完整的值


0 0