简体   繁体   中英

CoreBluetooth dynamic long characteristic update on peripheral

Is it possible to update dynamic characteristic on peripheral side by update method without didReceiveReadRequest: ?

For example, I need to send to all subscribed centrals a message 'hello, my friends, I need to tell you a story' - long message and can't be processed in one update.

I have code sample so far:

#pragma mark - Update
- (BOOL)updatePeripheralManager:(CBPeripheralManager *)peripheralManager withPeripheralName:(NSString *)peripheralName withCharacteristic:(CBCharacteristic *)characteristic byData:(NSData *)data {

    self.failedUpdate = [[AIKBluetoothPeripheralManagerLastUpdate alloc] initWithPeripheralName:peripheralName withCharacteristic:characteristic withData:data];
    if (peripheralManager && characteristic && data) {        
        return [peripheralManager updateValue:data forCharacteristic:(CBMutableCharacteristic *)characteristic onSubscribedCentrals:nil];
    }
    else {
        DDLogDebug(@"%@ updatePeripheral: peripheral or characteristic or data not specified", self.debugDescription);
        return NO;
    }
}

- (void)updateContinuouslyPeripheralManager:(CBPeripheralManager *)peripheralManager withPeripheralName:(NSString *)peripheralName withCharacteristic:(CBCharacteristic *)characteristic byData:(NSData *)data {    
    NSData *chunk = data;

    while (chunk != nil && [self updatePeripheralManager:peripheralManager withPeripheralName:peripheralName withCharacteristic:characteristic byData:chunk]) {
        // request data
        chunk = [self nextChunk];
    }
}


- (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral {
    DDLogVerbose(@"%@ isReadyToUpdateSubscribers", self.debugDescription);
    DDLogDebug(@"%@ failedUpdate: %@", self.debugDescription, self.failedUpdate.debugDescription);

    NSString *peripheralName = self.failedUpdate.peripheralName;
    CBCharacteristic *characteristic = self.failedUpdate.characteristic;

    NSData *chunk = self.failedUpdate.data;
    [self updateContinuouslyPeripheralManager:self.peripheralManager withPeripheralName:peripheralName withCharacteristic:characteristic byData:chunk];
}

If you need to send to your peer a long value that doesn't fit into one packet, you should first design a protocol to disassemble your value at peripheral side and assemble it back at the central side, then cut your long value into smaller chunks, send them one-by-one and assemble them back at the receiver.

iOS8+ devices usually negotiate MTU equal to 158 bytes that can contain up to 155 bytes of payload. Knowing this, you can design the protocol as follows.

  1. If the message received by a central device starts from 0, it contains the number of packets with payload. If the message starts with 1, it contains a single data packet.
  2. Split your long string into smaller strings of 153 bytes each. Count the number of small strings. Let say there are 5 such small strings.
  3. Send 05 to the central device.
  4. For each small string with index i, create a packet with the following format: byte 0 = 1, byte 1 = i, bytes 2-154 = string contents and send them to the central device.
  5. Upon receiving a packet starting with 0 at the central device, prepare a buffer to assemble the data.
  6. After receiving a packet starting with 1, extract its contents (bytes 2-154) and add them to the buffer starting at offset 155*i, where i is the value of the first byte.
  7. After all the packets starting with byte 1 are delivered, you have your long string assembled at the central device.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM