vb.net - 在 Windows.Devices.Bluetooth UWP GattLocalCharacteristic 上引发的 WriteWithoutResponse WriteRequested 事件无序
问题描述
使用 Windows.Devices.Bluetooth 上的 BLE GattLocalService,同时充当具有仅具有 WriteWithoutResponse 属性和普通保护级别的特征的外设,我们看到 GattLocalCharacteristic 事件 WriteRequested 与发送的字节相比出现了乱序。我们只能在特征上使用 WriteWithoutResponse 属性,而不能使用 Notify,这似乎工作正常。问题来了,我们通过这个特性在 MTU 为 20 的 BLE 上发送了大约 10K,并且需要在收到所有字节后按顺序重新组装它们。虽然许多函数是异步的,但我们似乎无法确定最初发送字节的顺序。在 Android 或 iOS 上进行设置时,它工作得非常好,但在 UWP 实现中,我们会收到乱序通知。
在研究 Microsoft 的 github 示例时,他们只显示在单个特征上接收大约 4 个字节 - 这里的顺序并不重要。我们已经查看了在 GattWriteRequest 上使用 Offset 属性,该属性似乎始终为 0。我们已经监控了对 GattLocalCharacteristic 的调用,并确定它们被无序通知。
我们试图从 Microsoft 的示例中进行调整:https ://docs.microsoft.com/en-us/windows/uwp/devices-sensors/gatt-server#write
我们对这个先前示例的 vb.NET 改编:
Private Async Sub InitializePerihperal()
Dim serviceResult As GattServiceProviderResult = Await GattServiceProvider.CreateAsync(New Guid(peripheralServiceUUID))
If serviceResult.Error <> BluetoothError.Success Then
peripheralResponseReceived = True
peripheralResponseError = "GattServiceError"
Exit Sub
End If
serviceProvider = serviceResult.ServiceProvider
Dim characResult As GattLocalCharacteristicResult
Dim propCentralToPeripheral As New GattLocalCharacteristicParameters
propCentralToPeripheral.CharacteristicProperties = GattCharacteristicProperties.WriteWithoutResponse
propCentralToPeripheral.WriteProtectionLevel = GattProtectionLevel.Plain
characResult = Await serviceProvider.Service.CreateCharacteristicAsync(New Guid(CentralToPeripheralUUID), propCentralToPeripheral)
characCentralToPeripheral = characResult.Characteristic
End Sub
Private Async Sub CentralResponseReceived(sender As GattLocalCharacteristic, args As GattWriteRequestedEventArgs) Handles characCentralToPeripheral.WriteRequested
Dim sequence As Int32 = Threading.Interlocked.Increment(PerihperalWriteSequence)
Using requestDeferral As Windows.Foundation.Deferral = args.GetDeferral
Dim request As GattWriteRequest = Await args.GetRequestAsync
Dim requestReader As DataReader = DataReader.FromBuffer(request.Value)
Dim response(CType(requestReader.UnconsumedBufferLength - 1, Int32)) As Byte
requestReader.ReadBytes(response)
'peripheralBlocks is a global ConcurrentDictionary
peripheralBlocks(sequence) = response
requestDeferral.Complete()
End Using
End Sub
我们可能遗漏了一些东西,但似乎应该按顺序调用响应上的 Offset 或函数。上面我们试图通过立即捕获调用序列来消除 GetRequestAsync 延迟问题。也许我们只是在 API 上遗漏了一些东西——但我们似乎找不到任何东西。
解决方案
推荐阅读
- docker - 如何在不启动容器的情况下从 dockerfile 创建图像
- javascript - 如何获取从本地文件获取的元数据?
- python - 无法从插件文件夹导入创建的包
- javascript - 使用 AJAX 和控制器通过下拉选择填充索引页面
- curl - 带有 CURL OAuth 的 Google Search Console API
- angular6 - Angular 6 本地设置
- fetch - fetch 从哪里获取它的端点值?
- google-apps-script - 如何将提示数据作为变量传递到 google docs 绑定脚本中?
- linux - Postfix——如何安全存储Mysql配置
- reactjs - 如何根据使用反应的条件返回 jsx?