Событие WriteWithoutResponse WriteRequested, возникшее из последовательности в Windows.Devices.Bluetooth UWP GattLocalCharacteristic - PullRequest
2 голосов
/ 22 июня 2019

С BLE GattLocalService на Windows.Devices.Bluetooth, действуя в качестве периферийного устройства с характеристикой, имеющей только свойство WriteWithoutResponse и простой уровень защиты, мы видим, что событие GattLocalCharacteristic WriteRequested возникает не в порядке по сравнению с отправляемыми байтами. Мы должны использовать только свойство WriteWithoutResponse для характеристики и не можем использовать Notify, который, кажется, работает нормально. Беда в том, что мы посылаем около 10K по BLE с MTU 20 через эту характеристику и должны собрать их по порядку, как только будут получены все байты. Хотя многие функции асинхронные, мы не можем определить порядок, в котором байты были отправлены изначально. Когда это настроено на Android или iOS, это работает отлично, но при реализации UWP мы получаем уведомление о неисправности. Понятно, что UWP использует несколько асинхронных функций, но неспособность пересобрать байты в полученном порядке довольно проблематично.

При исследовании примеров github от Microsoft они показывают, что получают только около 4 байтов на одну характеристику - порядок здесь не имеет большого значения. Мы рассмотрели использование свойства Offset в GattWriteRequest, которое, по-видимому, всегда равно 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

Возможно, мы что-то упускаем, но кажется, что в ответе либо смещение, либо функция должна вызываться последовательно. Выше мы попытались устранить проблемы с задержками GetRequestAsync, немедленно захватив последовательность вызовов. Может быть, мы просто что-то упустили в API - но, похоже, мы ничего не можем найти.

...