Getting Bluetooth state after reconnection : weird issue

Hi everyone ;-)

I'm currently developing an app that is synced to a BT device.
This BT device has 2 states (let's say ON and OFF though it is still powered on, like a bulb).

When I connect to the peripheral, I get 2 characteristics : a write and a read characteristic. In order to retrieve the current state, I have to send a write frame that basically ask the peripheral to give me its current state. As a response, I get a frame that contains the current peripheral state.

If I connect to the peripheral, ask the state (ON for instance), I receive ON. I turn the peripheral OFF, I receive OFF. Now I kill my app and launch it again. The app will reconnect to the peripheral, ask the current state. The response is OFF. So far so good.... I can keep on changing the peripheral state, I always retrieve the last state of the peripheral when I relaunch the app.
Now for the weird part : I do exactly the same operations, but before launching my app, I switch again the peripheral state (in the above example, it would now be ON). I launch the app, send a write frame to the peripheral, and the response is ... OFF.

One could argue that it is a peripheral issue, but fellow colleagues on Android do not have this bug, so I guess it's on my side.


Just for the record, here are my BT implementation, which is pretty straightforward.

Code Block
extension BluetoothManager: CBPeripheralDelegate {
        func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        log("didDiscoverCharacteristicsFor \(service)")
        if let characteristics = service.characteristics {
            for characteristic in characteristics {
                if let chara = ATACharacteristics.from(characteristic) {
                    switch chara {
                    case .write:
                        log("write  ATACharacteristics\(characteristic)")
                        peripheral.setNotifyValue(true, for: characteristic)
                        self.characteristics.append(chara)
                        readStateFromBox(characteristic)
                        
                    case .read:
                        log("read  ATACharacteristics\(characteristic)")
                        self.characteristics.append(chara)
                        
                    case .nus: ()
                    }
                }
            }
        }
    }
 
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
        log("didUpdateValueFor \(characteristic)")
        if let data = characteristic.value,
           let validator = try? ATAFrameDecoder().decode(data) as? LuminousStatusFrameValidator {
            log("   data \(data as NSData)")
            updateState(from: validator)
        }
    }
    func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
        log("didWriteValueFor \(characteristic)")
        if let data = characteristic.value,
           let validator = try? ATAFrameDecoder().decode(data) as? LuminousStatusFrameValidator  {
            log("   data \(data as NSData)")
            updateState(from: validator)
        }
    }
}


Here are although the logs for both scenarios. When receiving the didWrite frame, if I get a "00" after "02a00461" it means ON, if I get a "fe", it means OFF


First the good one :
Code Block
📲 centralManagerDidUpdateState poweredOn
📲 didDiscoverServices <CBPeripheral: 0x281508000, identifier = A274CD79-938C-CAEF-2CE7-D20CB5B6961F, name = ATA-000008, state = connected>
📲 didDiscoverCharacteristicsFor <CBService: 0x2831a5280, isPrimary = YES, UUID = 6E400001-B5A3-F393-E0A9-E50E24DCCA9E>
📲 read ATACharacteristics<CBCharacteristic: 0x280006100, UUID = 6E400002-B5A3-F393-E0A9-E50E24DCCA9E, properties = 0xC, value = (null), notifying = NO>
📲 write ATACharacteristics<CBCharacteristic: 0x2800044e0, UUID = 6E400003-B5A3-F393-E0A9-E50E24DCCA9E, properties = 0x10, value = {length = 13, bytes = 0x02a00461fe0000000000122903}, notifying = NO>
📲 readStateFromBox {length = 9, bytes = 0x02a50000000001a603} for <CBCharacteristic: 0x2800044e0, UUID = 6E400003-B5A3-F393-E0A9-E50E24DCCA9E, properties = 0x10, value = {length = 13, bytes = 0x02a00461fe0000000000122903}, notifying = NO>
📲 didUpdateNotificationStateFor <CBCharacteristic: 0x2800044e0, UUID = 6E400003-B5A3-F393-E0A9-E50E24DCCA9E, properties = 0x10, value = {length = 13, bytes = 0x02a00461fe0000000000122903}, notifying = YES>
📲 didWriteValueFor <CBCharacteristic: 0x2800044e0, UUID = 6E400003-B5A3-F393-E0A9-E50E24DCCA9E, properties = 0x10, value = {length = 13, bytes = 0x02a00461fe0000000000122903}, notifying = YES>
📲 data {length = 13, bytes = 0x02a00461fe0000000000122903}
📲 updateState occupied
📲 acknowledge {length = 9, bytes = 0x0206a000000003a703} for Optional(<CBCharacteristic: 0x2800044e0, UUID = 6E400003-B5A3-F393-E0A9-E50E24DCCA9E, properties = 0x10, value = {length = 13, bytes = 0x02a00461fe0000000000122903}, notifying = YES>)


and then the bug
Code Block
📲 centralManagerDidUpdateState poweredOn
📲 didDiscoverServices <CBPeripheral: 0x2839885a0, identifier = A274CD79-938C-CAEF-2CE7-D20CB5B6961F, name = ATA-000008, state = connected>
📲 didDiscoverCharacteristicsFor <CBService: 0x281dd5100, isPrimary = YES, UUID = 6E400001-B5A3-F393-E0A9-E50E24DCCA9E>
📲 read ATACharacteristics<CBCharacteristic: 0x282c88300, UUID = 6E400002-B5A3-F393-E0A9-E50E24DCCA9E, properties = 0xC, value = (null), notifying = NO>
📲 write ATACharacteristics<CBCharacteristic: 0x282c881e0, UUID = 6E400003-B5A3-F393-E0A9-E50E24DCCA9E, properties = 0x10, value = {length = 13, bytes = 0x02a0046100000000000013d603}, notifying = NO>
📲 readStateFromBox {length = 9, bytes = 0x02a50000000001a603} for <CBCharacteristic: 0x282c881e0, UUID = 6E400003-B5A3-F393-E0A9-E50E24DCCA9E, properties = 0x10, value = {length = 13, bytes = 0x02a0046100000000000013d603}, notifying = NO>
📲 didUpdateNotificationStateFor <CBCharacteristic: 0x282c881e0, UUID = 6E400003-B5A3-F393-E0A9-E50E24DCCA9E, properties = 0x10, value = {length = 13, bytes = 0x02a0046100000000000013d603}, notifying = YES>
📲 didWriteValueFor <CBCharacteristic: 0x282c881e0, UUID = 6E400003-B5A3-F393-E0A9-E50E24DCCA9E, properties = 0x10, value = {length = 13, bytes = 0x02a0046100000000000013d603}, notifying = YES>
📲 data {length = 13, bytes = 0x02a0046100000000000013d603}
📲 updateState free
📲 acknowledge {length = 9, bytes = 0x0206a000000003a703} for Optional(<CBCharacteristic: 0x282c881e0, UUID = 6E400003-B5A3-F393-E0A9-E50E24DCCA9E, properties = 0x10, value = {length = 13, bytes = 0x02a0046100000000000013d603}, notifying = YES>)


Is there some kind of cache on BT exchanges ? I don't know why it reacts like that.

Thanks for your help.
Getting Bluetooth state after reconnection : weird issue
 
 
Q