Closed nervus closed 1 year ago
I sign up to a notification on the GoPro and it just sends it when stuff changes on the device . I believe the problems stems from the fact that the characteristic value’s lifetime is only valid during the didUpdateValueFor: callback. - since it’s then buffered to use asynchronously the contents of the value Data() is no longer valid once the didUpdateValueFor exits. Basically imagine this timeline ( written on the phone so sorry for the coder graphics :p ) —duv(1)…duv(2)…duv(3)… etc -> didupdatevalue thread ….. cvus(1) ………………..….. Cvus(2)… cvus(3)….. characteristicValueUpdatedSubject Receive Thread In this case, by the time you receive the update from cvus(2), the characteristic value pointer has already been filled with the duv(3) data and this is pretty much what I’ve seen before doing the change. The other option was to basically copy the current characteristic value and pass the copy on so it doesn’t get overwritten next time didUpdateValue is called .
Sorry for the delay, was out of town and didn't have a laptop around. In that case we could try copying the current characteristic value like you suggest. One idea is sending out a struct with the characteristic and the data through the characteristicValueUpdatedSubject
. Something like:
public struct CharacteristicUpdatedEventData {
let characteristic: Characteristic
let value: Data?
}
class PeripheralContext {
private(set) lazy var characteristicValueUpdatedSubject = PassthroughSubject<CharacteristicUpdatedEventData, Never>()
...
}
extension Peripheral.DelegateWrapper: CBPeripheralDelegate {
...
self.context.characteristicValueUpdatedSubject.send(
CharacteristicUpdatedEventData(characteristic: Characteristic(characteristic), value: characteristic.value)
)
...
}
@manolofdez this is a good fix too. do you want this in a separate PR?
No, it's fine to leave in here.
Btw, removing the else triggers a lot of [peripheral] Received UpdateValue result for characteristic without a continuation
On Nov 20, 2022, at 6:43 PM, Manuel Fernandez @.***> wrote:
@manolofdez commented on this pull request.
In Sources/Peripheral/Peripheral.swift https://github.com/manolofdez/AsyncBluetooth/pull/10#discussion_r1027497353:
@@ -279,25 +279,25 @@ extension Peripheral.DelegateWrapper: CBPeripheralDelegate { }
func peripheral(_ cbPeripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
- Task {
- do {
- let result = CallbackUtils.result(for: (), error: error)
- try await self.context.readCharacteristicValueExecutor.setWorkCompletedForKey(
- characteristic.uuid, result: result
- )
- } catch {
- if !characteristic.isNotifying {
- if characteristic.isNotifying {
- // characteristic.value is Data() and it will get trampled if allowed to run async.
- self.context.characteristicValueUpdatedSubject.send( Characteristic(characteristic) )
- } else { Heads up this is just missing removing the else statement so that the read queue continues when you're notifying.
— Reply to this email directly, view it on GitHub https://github.com/manolofdez/AsyncBluetooth/pull/10#pullrequestreview-1187480694, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAH7GZLORGBMQ4OSXD5UEHTWJLOW5ANCNFSM54GQFQSQ. You are receiving this because you modified the open/close state.
I sign up to a notification on the GoPro and it just sends it when stuff changes on the device .
I believe the problems stems from the fact that the characteristic value’s lifetime is only valid during the didUpdateValueFor: callback. - since it’s then buffered to use asynchronously the contents of the value Data() is no longer valid once the didUpdateValueFor exits.
Basically imagine this timeline ( written on the phone so sorry for the coder graphics :p )
—duv(1)…duv(2)…duv(3)… etc -> didupdatevalue thread ….. cvus(1) ………………..….. Cvus(2)… cvus(3)….. characteristicValueUpdatedSubject Receive Thread
In this case, by the time you receive the update from cvus(2), the characteristic value pointer has already been filled with the duv(3) data and this is pretty much what I’ve seen before doing the change. The other option was to basically copy the current characteristic value and pass the copy on so it doesn’t get overwritten next time didUpdateValue is called .
Sent from my iPhone