【问题标题】:CoreBluetooth: didWriteValueFor() is not called after writeValue()CoreBluetooth:在 writeValue() 之后不调用 didWriteValueFor()
【发布时间】:2018-09-03 10:13:22
【问题描述】:

根据 Apple Developer Documentation,函数 didWriteValueFor() 在 writeValue() 函数被调用之后被调用。 (见https://developer.apple.com/documentation/corebluetooth/cbperipheraldelegate/1518823-peripheral

我有一个可写的特性,我查找了https://developer.apple.com/documentation/corebluetooth/cbcharacteristicproperties/1519089-write中提到的属性

现在当我调用 writeValue() 函数时,不会调用 didWriteValueFor() 函数,为什么?我认为它与调用 didUpdateValueFor() 函数的 readValue() 函数的结构相同,这对我来说很好用。 这是我的代码:

        func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
    for characteristic in service.characteristics!{
        print(characteristic)
        if(characteristic.uuid == TX_CHARACTERISTIC){
            elsa.writeValue(dataWithHexString(hex: VALID_GET_VERSION_REQUEST), for: characteristic, type: CBCharacteristicWriteType.withResponse)//calls didWriteValueFor if Type = withResponse
        }
        if(characteristic.uuid == RX_CHARACTERISTIC){
            elsa.setNotifyValue(true, for: characteristic)//calls didUpdateNotificationStateFor
        }
    }
}

func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
    guard let data = characteristic.value else { return }
    print("\nValue: \(data.toHexEncodedString()) \nwas written to Characteristic:\n\(characteristic)")
    if(error != nil){
        print("\nError while writing on Characteristic:\n\(characteristic). Error Message:")
        print(error as Any)
    }
}

【问题讨论】:

  • 在我的脑海中,据我所知,didWrite 被称为从特征中读取的值,所以如果没有读取,didWrite 不会被调用......我很容易将其与另一种情况混为一谈,但这让我感到惊讶 - 这有点像如果您有多个想要写入特征的东西,didWrite 是 API 告诉您可以写入下一个值的方式
  • 设置断点,但我怀疑您的guard 语句正在返回,因为写入特征的值将是nil;向特征写入值不会更新其value
  • @Paulw11“将值写入特征不会更新其值”你是什么意思?您的建议是正确的,它在警卫处返回,但是当我随后读取特征的值时,它已成功写入,那么此时它怎么可能为零?
  • 我的意思是对CBCharacteristic 实例执行写入不会更新该实例的value 属性。您必须明确读取要更新的 value 属性的特征。仅仅因为您将值“X”写入特征并不意味着它仍然具有该值,因此您必须显式读取它以获取该值。
  • @Paulw11 你能看看stackoverflow.com/q/68409316/14414215 即使明确读取值(使用示例解决方案),值仍然是null。有趣的是,在 iOS12 上返回了一个值,而在 iOS14 上没有返回值

标签: ios swift core-bluetooth


【解决方案1】:

当您调用 writeValue() 时,您可以指定是否需要来自远程设备的响应。在您的情况下,您指定了 CBCharacteristicWriteType.withResponse ,它告诉远程设备它需要发回响应并指示写入是否成功。当远程设备发送响应消息时,这将触发对 didWriteValueFor() 的调用。如果您的设备未发送响应,则不会调用 didWriteValueFor()。您可以在apple documentation here 中阅读有关此内容的信息。您需要运行蓝牙嗅探器捕获来确认这一点,但我怀疑您的蓝牙设备没有正确响应 writeValue() 请求。

请注意,每个 BLE 特征都有一组属性,这些属性控制特征的行为方式。其中一些属性包括:后方、写入、无响应写入、通知、通知。检查您正在使用的特性的属性,并确保它支持“写入”属性。如果您的特征支持“无响应写入”但不支持“写入”,则您的设备不会将所需的消息发送回您的应用程序,因此不会调用 didWriteValuefor()。通常您可以在文档中找到此信息,或使用“LightBlue Explorer”等蓝牙应用来查看您设备的此信息。

【讨论】:

  • 这也是我所期待的,但我的 BLE 设备正在做我发送给他的事情,唯一的事情是没有调用 didWriteValueFor()。在 Charactersitic 上写完之后,我仍然会使用解决方法来调用 readValue
【解决方案2】:

正如@Paulw11 提到的,该值仅在显式读取后才写入。我通过在 didWrite() 函数中调用 readValue() 来解决这个问题。

更新的解决方案:

func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
    elsa.readValue(for: characteristic)
    guard let data = characteristic.value else { return }
    print("\nValue: \(data.toHexEncodedString()) \nwas written to Characteristic:\n\(characteristic)")
    if(error != nil){
        print("\nError while writing on Characteristic:\n\(characteristic). Error Message:")
        print(error as Any)
    }
}

【讨论】:

  • 你能发布你更新的解决方案吗?我不确定是什么意思。谢谢
  • 非常感谢。我尝试了您的解决方案,但仍然没有任何反应。即使确实调用了didWriteValueFor,该值仍然是null。您是否有机会在 iOS14 上使用它?我在 iOS12 上试过,值在那里/报告。 (见stackoverflow.com/q/68409316/14414215
  • @myjunk 这可能是我在 2018 年做的,当时是 iOS 11 或 iOS 12
  • 有没有机会您仍然拥有设备的代码/访问权限等并尝试使用 iOS14?如果没有,谢谢。
  • @myjunk 对不起,从那以后我没有继续这个项目
猜你喜欢
  • 2014-06-19
  • 2020-08-30
  • 2018-06-29
  • 2019-01-05
  • 1970-01-01
  • 2014-12-14
  • 2020-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多