С 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 - но, похоже, мы ничего не можем найти.