首页 > 解决方案 > 在 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 上遗漏了一些东西——但我们似乎找不到任何东西。

标签: vb.netuwpbluetooth-lowenergybluetooth-gatt

解决方案


推荐阅读