来自 C# 的 BGScript GATT 特性写入不起作用

问题描述

在我的设备配置 gatt.xml 中,我添加一个带有自定义 UUID 的自定义 GATT 特性并启用了读写属性。配对后使用 Windows 蓝牙 API,当我尝试从 GATT 特征读取时,它工作正常,但写入 GATT 特征不起作用。我一直被拒绝访问,但出现异常。下面我添加了示例 gatt.xml、bgs 和 C# 代码。我正在使用 bluegiga v1.3.1_API。当前设置适用于 USB 加密狗,但我正在尝试将其替换为 Windows 蓝牙 API。

gatt.xml

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>

<service uuid="180A">
  <description>Device information</description>
  
  <characteristic uuid="2a29">
    <properties read="true" const="true" />
    <value>company name</value>
    <description>Manufacturer Name String</description>
  </characteristic>
  
  <characteristic uuid="2a24">
    <properties read="true" const="true" />
    <value>device name</value>
    <description>Model Number String</description>
  </characteristic>
      
  <characteristic uuid="2a27">
    <properties read="true" const="true"/>
    <value>2.0</value>
    <description>Hardware Revision String</description>
  </characteristic>
  
  <characteristic uuid="95551f84-7562-4c30-9455-be0750914ac2" id="xgatt_Params">
    <properties read="true" write="true"/>
    <value type="user" length="5"/>
    <description>Params</description>

  </characteristic>
      
</service>
    
</configuration>

来自 bgs 脚本的attributes_value 事件

event attributes_value(connection,reason,handle,offset,value_len,value_data)
    if handle = xgatt_Params then
        if value_len = 2 then
            if value_data(0:2) = $0115 then
                memcpy(addrPaired(0),addrConnected(0),6)
                updatePairing=1
                call attributes_user_write_response(connection,0)
            else
                call attributes_user_write_response(connection,$80)
            end if
        else
            if value_len >= numParams then
                memcpy(params(0),value_data(0),numParams)
                call updateParams()
                call attributes_user_write_response(connection,$80)
            end if
        end if
    end if
end

C# 代码

if (properties.HasFlag(GattCharacteristicProperties.Write))
{
    try
    {
        var writer = new DataWriter();
        writer.WriteByte(01);
        writer.WriteByte(15);
        var result = await characteristic.WriteValueAsync(writer.DetachBuffer(),GattWriteOption.WriteWithResponse);

        if (result == GattCommunicationStatus.Success)
        {
            Console.Write("\n Success");
        }
        else if (result == GattCommunicationStatus.AccessDenied)
        {
            Console.Write("\n Access Denied");
        }
        else if (result == GattCommunicationStatus.Unreachable)
        {
            Console.Write("\n Unreachable");
        }

        else if (result == GattCommunicationStatus.ProtocolError)
        {
            Console.Write("\n ProtocolError");
        }
    }
    catch (Exception ex) when ((uint)ex.HResult == 0x80650003 || (uint)ex.HResult == 
0x80070005)
    {
        Console.Write("\n " + ex.Message);
    }

}

解决方法

Windows 不允许写入 GAP 服务。所以我所做的是使用如下所示的自定义 UUID 制作具有特征的服务,现在它可以工作了。

<service uuid="97b6682c-ca92-11eb-b8bc-0242ac130003">
  <description>meso service</description>

  <!-- custom write-only characteristic -->
    <characteristic uuid="97b66a7a-ca92-11eb-b8bc-0242ac130003" id="xgatt_params_windows">
      <description>Data</description>
      <properties write="true" />
      <value type="user" length="5"/>
    </characteristic>
</service>

要记住的另一件事是您需要以相反的顺序从 Windows 写入十六进制值。例如,在我的 BGScript 中,它的期望值为 0115,因此您应该从窗口中反向写入该值。这完全取决于您使用的系统,例如 BigEndian(MSB 优先,例如:Motorola 处理器), 或 LittleEndian(LSB 优先,例如:Intel 处理器)。

var writer = new DataWriter();
writer.WriteByte(15);
writer.WriteByte(01);