蓝牙LE:设置字节数组的特征会发送错误的值

Bluetooth LE: setting characteristic to byte array sends wrong values

本文关键字:特征 错误 数组 LE 设置 字节 字节数 蓝牙      更新时间:2023-10-16

我正在使用Bluetoothleapis.h与自定义蓝牙低能设备进行通信。

以下方式设置了设备:

  • 自定义Gatt服务
  • 特征#1读/写(期望3个字节(
  • 特征#2读/notify(返回1字节(

我能够从特征2获得正确的值。但是,当我尝试将数据发送到特征#1时,设备会收到怪异的数据。

该特征负责真实对象的3个参数(想象具有强度,颜色等的光(。(0,0,0(应对"光"做出回应。离开,但是如果我发送(0,0,0(,我可以看到该设备会收到其他东西(我无法确切地说出什么,但它没有关闭(。无论我发送什么值,状态似乎都不会改变。

我尝试在写作和写无响应之间交替,都产生相同的结果。

GetCharacteristicValue有趣的是,即使已知特征仅接受3个字节,也可以返回8个charValueDataSize。巧合的是,出于某种原因,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,没有产生任何错误。

在Android上使用BLE应用时,读取和写入特征工作正常。

更新1

@shubham指出这可能是一个终点问题,因此我试图用memcpy代替以下内容:

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

但是,什么都没有改变。

更新2

我已经按照埃米尔的建议纳入了更改,并且奏效了!发布完整的代码,以防其他人遇到同一问题。

顺便说一句,即使特征被标记为可写的:正确的,可写的毫无疑问:false,我需要将标志设置为无响应,以使其被发送的值。

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;
}

我的建议是,您首先将CharvaluedAtasize设置为512 sizeof(bth_le_gatt_characteristis_value((最大可能(,然后跳过最初的读取,该读取将获得大小。然后检查PWRITEVALUE-> DATASIZE,以在成功阅读后获取实际尺寸。还要确保即使在错误的情况下也可以释放内存。