#c# #android #windows #uwp #bluetooth-lowenergy
#c# #Android #Windows #uwp #bluetooth-низкое энергопотребление
Вопрос:
У меня есть библиотека классов Windows, которая использует API-интерфейсы UWP BLE. Настройка такова: хост BLE: ноутбук Win 10 Периферийное устройство BLE: ноутбук Win 10 или Android
Мне нужно отправить большой файл (от нескольких K до нескольких M) на периферийное устройство и обратно (используя Write / WriteWithoutResponse и Notify), используя пользовательский сервис и характеристики.
Для беспроигрышной ситуации все, кажется, обрабатывается ОС. Хост просто вызывает это один раз
writeResult = await characteristic.WriteValueAsync(buffer, GattWriteOption.WriteWithResponse);
с большими данными и ОС, похоже, автоматически согласует максимальный MTU (517 байт на Android), разделит данные на меньшие фрагменты и отправит.
Однако на принимающей стороне,
private async void Characteristic_WriteRequestedAsync(GattLocalCharacteristic sender, GattWriteRequestedEventArgs args) {
var deferral = args.GetDeferral();
using (deferral)
{
GattWriteRequest request = await args.GetRequestAsync();
if (request == null)
{
Log(LOG_ERR, $"No access allowed to the device");
return;
}
var reader = DataReader.FromBuffer(request.Value);
string mystring = reader.ReadString(request.Value.Length);
Log(LOG_VERBOSE, $"Receiving data value length: {request.Value.Length}");
Log(LOG_VERBOSE, $"Receiving data write offset: {request.Offset}");
Log(LOG_VERBOSE, $"Receiving data write state: {request.State}");
if (request.Option == GattWriteOption.WriteWithResponse)
{
request.Respond();
}
deferral.Complete();
}
}
Приемник будет иметь несколько обратных вызовов, но в каждом обратном вызове он имеет только информацию о значении, смещении и состоянии. Как получатель узнает, какой пакет является последним, и может начать обработку данных?
Я не думаю, что проверка длины значения <максимальный размер PDU — хороший способ. И периферийные устройства Android и Windows, похоже, получают разный размер данных на пакет. (Android 517, Windows 522)
То же самое для уведомления на хосте Win, в нем практически нет ничего, что могло бы определить, является ли это последним пакетом всего сообщения.
private void NotifyCharacteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
{
Log(LOG_VERBOSE, $"Receiving value length from Notify: {args.CharacteristicValue.Length}");
}
Я думаю, что это очень простое требование и должно быть реализовано Windows. Я что-то здесь упускаю? Если нет собственной реализации Windows, мне нужно реализовать свой собственный механизм. Используя символ-терминатор в конце фактических данных? Есть предложения?
Спасибо, Анжела
Комментарии:
1. Отправьте количество байтов в начале первого сообщения, а затем читайте, пока не получите количество байтов.
2. Правильный поток — сначала отметить значения и смещения. Затем отправитель должен отправить «Выполнить запись» на уровне ATT для фиксации ранее отправленных записей, и в это время получатель должен атомарно обновить значение новым полным значением. Пока не уверен, как последний шаг должен обрабатываться в стеке Microsoft… С уведомлениями нет такого понятия, как «полное сообщение», поскольку уведомления отправляются только в одном пакете, усеченном для соответствия MTU.