【问题标题】:BluetoothGATTSetCharacteristicValue returns E_INVALIDARG or ERROR_INVALID_FUNCTIONBluetoothGATTSetCharacteristicValue 返回 E_INVALIDARG 或 ERROR_INVALID_FUNCTION
【发布时间】:2017-09-27 14:57:07
【问题描述】:

我在 BluetoothAPIs api 之上构建了一组包含类的 C++。

我可以枚举服务、特征和描述符的打开句柄。我可以读取特征值。我遇到的问题是我无法写入特征值。

下面是写特征值的代码

void BleGattCharacteristic::setValue(UCHAR * data, ULONG size){
if (pGattCharacteristic->IsSignedWritable || pGattCharacteristic->IsWritable || pGattCharacteristic->IsWritableWithoutResponse)
{
    size_t required_size = sizeof(BTH_LE_GATT_CHARACTERISTIC_VALUE) + size;

    PBTH_LE_GATT_CHARACTERISTIC_VALUE gatt_value = (PBTH_LE_GATT_CHARACTERISTIC_VALUE)malloc(required_size);

    ZeroMemory(gatt_value, required_size);

    gatt_value->DataSize = (ULONG)size;
    memcpy(gatt_value->Data, data, size);

    HRESULT hr = BluetoothGATTSetCharacteristicValue(bleDeviceContext.getBleServiceHandle(), pGattCharacteristic, gatt_value, NULL, BLUETOOTH_GATT_FLAG_NONE);

    free(gatt_value);

    if (HRESULT_FROM_WIN32(S_OK) != hr)
    {
        stringstream msg;
        msg << "Unable to write the characeristic value. Reason: ["
            << Util.getLastError(hr) << "]";

        throw BleException(msg.str());
    }
}
else
{
    throw BleException("characteristic is not writable");
}}

对 bleDeviceContext.getBleServiceHandle() 的调用将打开的句柄返回给设备信息服务。

pGattCharacteristics 也是指向要写入的特征的指针。它是通过调用 BluetoothGATTGetCharacteristics 打开的。

我尝试了不同的标志组合,返回码没有区别。

我也尝试过使用设备的句柄而不是服务的句柄。在这种情况下,我会收到一个 ERROR_INVALID_FUNCTION 返回错误代码。

我将不胜感激任何关于我做错了什么或我可以尝试的其他可能选项的指示。

【问题讨论】:

  • 驱动程序对您的代码不满意。没有人可以运行此代码,因此您必须自己弄清楚。关键的第一步是修复错误报告代码中的错误。调用 GetLastError() 不正确,错误代码已嵌入 hr 值中。使用 if (FAILED(hr)) 来决定是否显示它。
  • Util.getLastError() 从 HR int 值生成可读错误。所以我没有看到你看到的错误。
  • @Mgetz 我不想将 com api 调用与 winapi 混合使用,因为我认为这是不好的做法。这可能是一种误导的观点。我的 Util.getLastError() 基本上完成了整个 FormatMessage 例程。如果使用 HRESULT 没问题,那么更少的 LOC 会更好。谢谢指点。
  • 旁注:deletemallocd 内存的行为未定义,您需要使用free 或使用new。但老实说,你不需要这样做,因为你有一个指向数据的指针......而且不需要制作副本。

标签: c++ winapi bluetooth-lowenergy


【解决方案1】:

1- 您必须使用服务句柄,对。
2- 我不知道你是如何设计你的类的,然后你是如何为特性值本身分配一些内存的。
我做什么(确保有足够和适当的内存来存储 Value 的数据):
a) 在 Value 对象的初始化处,调用 ::BluetoothGATTGetCharacteristicValue 两次,以获得所需的大小,然后实际为其分配一些内部内存。
b) 使用时,将内部内存设置为可能的值,然后调用 ::BluetoothGATTSetCharacteristicValue

hr=::BluetoothGATTSetCharacteristicValue(
处理,
(PBTH_LE_GATT_CHARACTERISTIC)特点,
value,//实际上是分配内存的 (PBTH_LE_GATT_CHARACTERISTIC_VALUE)
0,//BTH_LE_GATT_RELIABLE_WRITE_CONTEXT ReliableWriteContext,
BLUETOOTH_GATT_FLAG_NONE)

【讨论】:

  • 是的,代码肯定是在使用服务句柄。特征的枚举使用docs 的标准机制。我正在用不同的错误处理做同样的事情。
  • @DerekGn 您找到解决方案了吗?关于获得所需的大小,我使用来自 msdn social.msdn.microsoft.com/Forums/en-US/… 的 sn-p 然后分配内存缓冲区,并且在每次调用 ::BluetoothGATTSetCharacteristicValue... 之前和之后 仍然存在 ...与您的(本地)分配方法有点不同...
  • 好吧,我错过了理解你原来的观点,我错误地认为你指的是特征本身而不是价值。如果我理解你说的是先读取特征值,使用双重读取方法,然后使用该实例作为写入特征的值,修改实例以包含我希望发送到设备的数据。这是你的意思吗?
  • 没问题,看了我的回答,可以看出我没有解释清楚。没有什么比获取所需的 Value 大小更好的了:只需根据预期的数据计算和分配适当的大小:(
【解决方案2】:

有几件事:

typedef struct _BTH_LE_GATT_CHARACTERISTIC_VALUE {
   ULONG DataSize;
   UCHAR Data[];
} BTH_LE_GATT_CHARACTERISTIC_VALUE, *PBTH_LE_GATT_CHARACTERISTIC_VALUE;

是data structure used in the parameter CharacteristicValue 的定义方式。请注意Data 不是 分配的数组,而是一个指针。所以访问Data[0] 是未定义的行为,可以访问内存中的任何位置。相反,您需要执行gatt_value.Data = &amp;data; 将指针设置为输入参数的地址。

其次是the documentation is quite clear,为什么你可能会得到ERROR_INVALID_FUNCTION;如果另一个可靠的写入已经挂起,那么这个写入将失败。在这种情况下,您应该考虑重试逻辑。

至于E_INVALIDARG,我认为它与未定义的行为有关,但我会在修复前面提到的其他问题后进行检查。

【讨论】:

  • 我匆忙粘贴了一个 hack to far 版本的 sn-p。我已经更新到最新版本了。
  • 我简化了将一个字节写入设备的调用,而不是原始版本中的多个字节。我确信在尝试此写入时没有其他写入正在进行。测试工具基本上打开设备,枚举服务等。读取制造商名称特征,然后尝试写入专有特征值。我尝试创建一个可靠的写入上下文并在调用中使用,但没有任何额外的成功。我会重试一次
猜你喜欢
  • 2015-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多