BLE 特性更改回调仅针对写入后的第一次更改执行

Posted

技术标签:

【中文标题】BLE 特性更改回调仅针对写入后的第一次更改执行【英文标题】:BLE characteristic changed callback executed only for first change after write 【发布时间】:2016-07-08 13:06:14 【问题描述】:

我尝试使用典型方法订阅 BLE 特征通知:

stCharacteristic = stService.GetCharacteristics(stCharacteristicGUID)[0];
await stCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify);
stCharacteristic.ValueChanged += stData_ValueChanged;

回调函数也有标准形式:

async void stData_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)

    var values = (await sender.ReadValueAsync()).Value.ToArray();

问题在于,当 BLE 设备更改特征值时,并不总是调用回调。当我向特征写入内容并且设备响应写入内容时,将调用回调。但是,如果设备仅自己写入特征,则不会调用回调。有趣的是数据没有丢失。当我再次写一些东西时,我收到了几次回调,其中包含 BLE 设备同时发送的所有数据。换句话说,它看起来像 Windows 或 .NET Framework 会缓存后续传入的数据,直到进行写入。仅写入第一个特征更改后会触发回调。

传入数据 - 无回调 发送数据 传入数据 - 两个回调! 发送数据 传入数据 - 一个回调 传入数据 传入数据 传入数据 发送数据 - 三个回调!

Windows 10、VS2015

【问题讨论】:

【参考方案1】:

您不必读取 ValueChanged 回调中的值。该值已存在于 GattValueChangedEventArgs 中。

除此之外 - 你的处理程序真的应该被直接调用,而不是在写入之后。您能否查看您的设备在通知之间是否断开/连接?

【讨论】:

是的,你是对的,我可以从 args 获取数据,而且我确信它更优雅。设备未断开连接。我可以在设备的日志中看到它。此外,如果断开连接,我将无法写入特征。同时我观察到有趣的事情。设备可以发送大于特征大小(20 字节)的数据包。在这种情况下,它将数据包分成 20 字节的块。我一一得到所有的块,没有任何问题。所以回调不仅针对第一个块执行。当回调立即触发时,写入后似乎有时间窗口。【参考方案2】:

原来是 Windows 10 的问题。而在 Windows 10.0.15063 和更新版本(如 10.0.16251)上,情况更糟 - 根本没有回调。幸运的是,有一个简单的解决方法,需要添加两个注册表项。这是 .reg 文件:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID\C6BFD646-3DF0-4DE5-B7AF-5FFFACB844A5]
"AccessPermission"=hex:01,00,04,80,9c,00,00,00,ac,00,00,00,00,00,00,00,14,00,\
  00,00,02,00,88,00,06,00,00,00,00,00,14,00,07,00,00,00,01,01,00,00,00,00,00,\
  05,0a,00,00,00,00,00,14,00,03,00,00,00,01,01,00,00,00,00,00,05,12,00,00,00,\
  00,00,18,00,07,00,00,00,01,02,00,00,00,00,00,05,20,00,00,00,20,02,00,00,00,\
  00,18,00,03,00,00,00,01,02,00,00,00,00,00,0f,02,00,00,00,01,00,00,00,00,00,\
  14,00,03,00,00,00,01,01,00,00,00,00,00,05,13,00,00,00,00,00,14,00,03,00,00,\
  00,01,01,00,00,00,00,00,05,14,00,00,00,01,02,00,00,00,00,00,05,20,00,00,00,\
  20,02,00,00,01,02,00,00,00,00,00,05,20,00,00,00,20,02,00,00

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID\YOURAPP.exe]
"AppID"="C6BFD646-3DF0-4DE5-B7AF-5FFFACB844A5"

将 YOURAPP.exe 更改为您的 exe 文件名。 GUID 可以更改或保持原样。应用此 .reg 文件后,每次都会立即调用回调,并且可以很好地收到通知。

在撰写此答案时,Microsoft 正在努力进行永久性修复。解决方法和讨论在这里:https://social.msdn.microsoft.com/Forums/en-US/58da3fdb-a0e1-4161-8af3-778b6839f4e1/bluetooth-bluetoothledevicefromidasync-does-not-complete-on-10015063?forum=wdk

【讨论】:

以上是关于BLE 特性更改回调仅针对写入后的第一次更改执行的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Swift 中的 BLE 外设特征写入回调中提取数据?

Android BLE 无法从设备接收 Gatt 特性通知

Android BLE Gatt 连接更改状态

Android BLE 回调 OnWriteCallback 几秒钟后停止

Databricks - 从增量表写入流到 orc 文件的读取流仅具有更改

Rails 数据更改回调