(Решено) Bluetooth LE: установка характеристики для байтового массива отправляет неправильные значения - PullRequest
0 голосов
/ 07 июля 2019

Я использую Bluetoothleapis.h для связи с пользовательским устройством с низким энергопотреблением Bluetooth.

Устройство настроено следующим образом:

  • Пользовательская служба GATT
    • Характеристика # 1 Чтение / запись (ожидается 3 байта)
    • Характеристика # 2 Чтение / уведомление (возвращает 1 байт)

Я могу получить правильные значенияиз характеристики № 2.Однако, когда я пытаюсь отправить данные в характеристику # 1, устройство получает странные данные.

Характеристика отвечает за 3 параметра реального объекта (представьте свет с интенсивностью, цветом и т. Д.).(0,0,0) должен реагировать на выключение «света», но если я отправляю (0,0,0), я вижу, что устройство получает что-то еще (я не могу сказать, что именно, но это не таквыкл).Кажется, что состояние не меняется независимо от того, какие значения я отправляю.

Я пытался чередовать запись и запись без ответа, оба результата дают один и тот же результат.

GetCharacteristicValue интересно возвращает charValueDataSizeиз 8, хотя известно, что характеристика принимает только 3 байта.По совпадению, размер для 1-байтовой характеристики только для чтения по какой-то причине равен 9.

Я попытался ограничить размер WriteValue только 3 байтами, но в этом случае я получаю недопустимую ошибку аргумента,Ответы в другом месте на StackOverflow указали, что мне нужно использовать тот, который я получаю от GetCharacteristicValue, и перенести туда мои данные.

Учитывая тот факт, что состояние реального объекта не изменяется независимо от того, какие значения отправляются, яподозреваю, что проблема где-то в том, как я настроил байтовый массив для передачи данных.

Кроме того, вызов GetCharacteristicValue даже после установки возвращает пустой массив.

Я не уверен, чтозначения на самом деле отправляются, и мне не хватает аппаратного обеспечения для отслеживания их через Wireshark.

DWORD WriteValueToCharacteristic(__in const HANDLE deviceHandle, 
__in const CharacteristicData* pCharData, 
__in const UCHAR* writeBuffer,
__in const USHORT bufferSize,
__in const BOOL noResponse )
{
HRESULT hr;
PBTH_LE_GATT_CHARACTERISTIC pCharacteristic = pCharData->pCharacteristic;
USHORT charValueDataSize;

hr = BluetoothGATTGetCharacteristicValue
(
    deviceHandle,
    pCharacteristic,
    0,
    NULL,
    &charValueDataSize,
    BLUETOOTH_GATT_FLAG_NONE    
);

if (hr != HRESULT_FROM_WIN32(ERROR_MORE_DATA))
{
    Log(L"BluetoothGATTSetCharacteristicValue returned error %d", hr);
    FormatBluetoothError(hr);
    return -1;
}
PBTH_LE_GATT_CHARACTERISTIC_VALUE pWriteValue = (PBTH_LE_GATT_CHARACTERISTIC_VALUE)HeapAlloc
(
    GetProcessHeap(), HEAP_ZERO_MEMORY, charValueDataSize + sizeof(BTH_LE_GATT_CHARACTERISTIC_VALUE)
);

if (pWriteValue == NULL)
{
    Log(L"Out of memory.");
    return -1;
}

hr = BluetoothGATTGetCharacteristicValue
(
    deviceHandle,
    pCharacteristic,
    charValueDataSize,
    pWriteValue,
    NULL,
    BLUETOOTH_GATT_FLAG_FORCE_READ_FROM_DEVICE
);

memcpy(pWriteValue->Data, writeBuffer, bufferSize);
ULONG flags = noResponse == TRUE ? BLUETOOTH_GATT_FLAG_WRITE_WITHOUT_RESPONSE : 0;

hr = BluetoothGATTSetCharacteristicValue
(
    deviceHandle, 
    pCharacteristic, 
    pWriteValue, 
    NULL,
    flags   
);

if (hr != S_OK)
{
    Log(L"BluetoothGATTSetCharacteristicValue returned error %d", hr);
    FormatBluetoothError(hr);
    return -1;
}
HeapFree(GetProcessHeap(), 0, pWriteValue);
return ERROR_SUCCESS;
}

SetCharacteristicValue возвращает S_OK, не вызывая ошибок.

Как чтение, так и запись в характеристику работают нормально, когдас помощью приложения BLE на Android.

Обновление # 1

@ Шубхам указал, что это может быть проблема с порядком байтов, поэтому я попытался заменить memcpy на следующее:

int j = 0;
int i = charValueDataSize - 1;
while (j < bufferSize)
{
    pWriteValue->Data[i] = writeBuffer[j];
    --i;
    ++j;
}

Однако ничего не изменилось.

Обновление # 2

Я включил изменения как pэээ предложение эмиля , и это сработало!Публикация полного кода на случай, если кто-то еще столкнется с той же проблемой.

Кстати, хотя характеристика помечена как Доступная для записи: true, Writable-no-response: false, мне нужно установить флаги в no-responseдля того, чтобы значения были отправлены.

DWORD WriteValueToCharacteristic(__in const HANDLE deviceHandle, __in const CharacteristicData* pCharData, __in const UCHAR* writeBuffer, __in const USHORT bufferSize, __in const BOOL noResponse)
{
HRESULT hr;
PBTH_LE_GATT_CHARACTERISTIC pCharacteristic = pCharData->pCharacteristic;
USHORT charValueDataSize = 512;

PBTH_LE_GATT_CHARACTERISTIC_VALUE pWriteValue = (PBTH_LE_GATT_CHARACTERISTIC_VALUE)HeapAlloc
(
    GetProcessHeap(), HEAP_ZERO_MEMORY, charValueDataSize + sizeof(BTH_LE_GATT_CHARACTERISTIC_VALUE)
);

if (pWriteValue == NULL)
{
    Log(L"Out of memory.");
    return -1;
}

hr = BluetoothGATTGetCharacteristicValue
(
    deviceHandle,
    pCharacteristic,
    (ULONG)charValueDataSize,
    pWriteValue,
    NULL,
    BLUETOOTH_GATT_FLAG_FORCE_READ_FROM_DEVICE
);
if (bufferSize > pWriteValue->DataSize)
{
   if(pWriteValue->DataSize == 0) 
    {
        pWriteValue->DataSize = bufferSize;
    }
}
// after the first write, DataSize stays as 3
//pWriteValue->DataSize here is 3, as expected
//buffer size is also 3
memcpy(pWriteValue->Data, writeBuffer, bufferSize);
ULONG flags = noResponse == TRUE ? BLUETOOTH_GATT_FLAG_WRITE_WITHOUT_RESPONSE : 0;

hr = BluetoothGATTSetCharacteristicValue
(
    deviceHandle, 
    pCharacteristic, 
    pWriteValue, 
    NULL,
    flags   
);

if (hr != S_OK)
{
    Log(L"BluetoothGATTSetCharacteristicValue returned error %d", hr);
    FormatBluetoothError(hr);
    HeapFree(GetProcessHeap(), 0, pWriteValue);
    return -1;
}
HeapFree(GetProcessHeap(), 0, pWriteValue);
return ERROR_SUCCESS;
}

1 Ответ

0 голосов
/ 08 июля 2019

Я предлагаю сначала установить для charValueDataSize значение 512 + sizeof (BTH_LE_GATT_CHARACTERISTIC_VALUE) (максимально возможное) и пропустить начальное чтение, в результате которого будет получен размер.Затем проверьте pWriteValue-> DataSize, чтобы получить фактический размер после успешного чтения.Также убедитесь, что вы освобождаете свою память даже в случае ошибки.

...