【问题标题】:"GATT Error: Not paired." with web-bluetooth when device shows as connected“GATT 错误:未配对。”当设备显示为已连接时使用网络蓝牙
【发布时间】:2019-05-07 00:04:33
【问题描述】:

我正在尝试使用带有网络蓝牙 api 的 BLE 从我的 Windows 10 机器连接到 Microchip“RN4678”双模蓝牙设备。我可以找到设备 -> 服务 -> 我需要的特性,但我不断收到“GATT 错误:未配对”。尝试启动有关特性的通知时。

我的 JavaScript 经验很少,所以我认为我可能一直在错误地链接我的承诺,但是在尝试添加特征之前直接打印出设备信息显示“已连接”的值为 true。

我还验证了设备、服务和特性是否可以与我的 Android 设备上的“nRF Connect”应用程序一起正常工作。

这是我的代码:

let targetService = '49535343-fe7d-4ae5-8fa9-9fafd205e455';
let txCharacteristicId = '49535343-1e4d-4bd9-ba61-23c647249616';
let rxCharacteristicId = '49535343-8841-43f4-a8d4-ecbe34729bb3';

function onButtonClick(event) {

  // Find bluetooth device
  console.log('Requesting Bluetooth Device...');
  navigator.bluetooth.requestDevice({
    acceptAllDevices: true,
    optionalServices: [targetService]
  })
  // Connect to device
  .then(device => device.gatt.connect())
  // Get the server we want
  .then(server => {
    console.log('Getting UART transparent service...');
    return server.getPrimaryService(targetService);
  })
  // Handle the characteristics we need
  .then(service => {
    return service.getCharacteristic(txCharacteristicId)
  })
  .then(characteristic => {
    console.dir(characteristic.service.device);
    return characteristic.startNotifications();
  })
  .then(characteristic => {
    characteristic.addEventListener('characteristicvaluechanged',
                                    handleTx);
  })
  .catch(error => { 
    console.log(error);
    console.log(error.code);
    console.log(error.message); 
    console.log(error.name); 
  });

}

function handleTx(event) {
  console.log(event.target.value);
}

这是我收到的控制台消息:

index.html:18 Requesting Bluetooth Device...
index.html:27 Getting UART transparent service...
index.html:35 BluetoothDevice
                gatt: BluetoothRemoteGATTServer
                  connected: true
                  device: BluetoothDevice {id: "p+lJYscejR+Xl4eX+VbNkA==", name: "Dual-SPP", gatt: BluetoothRemoteGATTServer, ongattserverdisconnected: null}
                  __proto__: BluetoothRemoteGATTServer
                id: "p+lJYscejR+Xl4eX+VbNkA=="
                name: "Dual-SPP"
                ongattserverdisconnected: null
                __proto__: BluetoothDevice
index.html:44 DOMException
index.html:45 19
index.html:46 GATT Error: Not paired.
index.html:47 NetworkError

这是网络蓝牙 startNotifications() 函数 (https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-startnotifications) 的文档:

startNotifications() 方法在调用时必须返回一个新的 承诺承诺并并行运行以下步骤。见§5.6.4 响应通知和指示以了解接收的详细信息 通知。

  1. 如果 this.uuid 被列入读取阻止名单,则使用 SecurityError 拒绝承诺并中止这些步骤。
  2. 如果 this.service.device.gatt.connected 为 false,则使用 NetworkError 拒绝承诺并中止这些步骤。
  3. 让特征是这个。[[representedCharacteristic]]。
  4. 如果特性为 null,则返回一个因 InvalidStateError 被拒绝的 Promise 并中止这些步骤。
  5. 如果 Notify 或 Indicate 位均未在特性的属性中设置,则使用 NotSupportedError 拒绝承诺 并中止这些步骤。
  6. 如果特征的活动通知上下文集包含 navigator.bluetooth,则使用此解决承诺并中止这些步骤。
  7. 如果 UA 当前正在使用蓝牙系统,它可能会以 NetworkError 拒绝承诺并中止这些步骤。第 9 期: 实现可能能够避免这个 NetworkError,但现在 网站需要序列化他们对这个 API 的使用和/或给用户一个 重试失败操作的方法。 https://github.com/WebBluetoothCG/web-bluetooth/issues/188

  8. 如果特征具有客户端特征配置描述符,请使用任何特征描述符过程来 确保通知或指示位之一 特征的客户端特征配置描述符是 设置,匹配特征属性中的约束。 UA 应该避免设置这两个位,并且必须删除重复值更改 如果两个位都设置了事件。按照 §5.7 错误中的描述处理错误 处理。注意:某些设备具有其属性 包括通知或指示位,但没有客户端 特征配置描述符。这些不符合标准的 特征倾向于发送通知或指示 无条件地,因此该规范允许应用程序简单地 订阅他们的消息。

  9. 如果上一步返回错误,则拒绝带有该错误的 Promise 并中止这些步骤。

  10. 将 navigator.bluetooth 添加到特征的活动通知上下文集。
  11. 用这个解决承诺。启用通知后,生成的值更改事件将在 当前的微任务检查点。这允许开发人员设置 结果承诺的 .then 处理程序中的处理程序。

编辑: 我使用的是 Chrome 版本 74,Windows 10.0.17134

【问题讨论】:

  • 我会留意这个,因为我很想知道是否有人知道这里发生了什么,但我决定用网络蓝牙减少损失并购买一个贵族(节点BLE 模块)兼容 USB 到 BLE 加密狗。对于任何试图在 Windows 上开发 BLE 应用程序的人(特别是如果它只是一个物联网设备的测试应用程序,就像我的一样),我强烈建议购买加密狗并走这条路。
  • 我遇到了完全相同的问题。我正在使用 Chrome v74.0.3729.157 和 Windows 10.0.17763.503。我尝试了多种不同的实现,但最终 .startNotifications() 方法总是返回带有消息的 NetworkError:GATT Error: Not paired.

标签: javascript web-bluetooth


【解决方案1】:

我找到了适用于我的设备的解决方案,希望它也适用于您。事实证明,该设备必须之前与 Windows 操作系统配对,然后才能通过 Web 蓝牙建立连接。因此,即使网络蓝牙会“连接”并显示所有 GATT 属性 - 设备 在收到startNotifications() 命令时实际上正在断开连接(因为它没有通过操作系统配对)。此外,(在我的情况下,但这可能是特定于设备的)我的“默认密码”是 000000(需要正好是 6 个零)。与 Windows 操作系统配对时,请务必仔细检查。

编辑: 这种行为(必须在建立网络蓝牙连接之前将设备与操作系统配对)是除了 Windows 之外的 macOS 上发现的错误。请参阅此chrome-bug 了解更多信息。

【讨论】:

  • 我试过了,确实删除了 NetworkError。不幸的是,由于每约 300 毫秒失去连接,我在使用网络蓝牙时仍然遇到问题。这似乎是 Windows 10 和/或我正在使用的特定蓝牙适配器(英特尔无线蓝牙 7265)的问题。我进入Windows设备管理器并禁用了适配器的“允许计算机关闭此设备以节省电源”,但我仍然遇到问题。这是你遇到的吗?任何已知的解决方法?
  • 看起来它是一个安全问题——您也暗示了这个问题。我在我的电脑上“忘记”了设备,然后重新配对,一切似乎都在工作..
  • 很高兴你能成功。我注意到在我的情况下,有时当“配对”设备时它没有提示输入密码 - 在这些情况下,网络蓝牙不成功,我不得不“忘记”然后再次修复。
猜你喜欢
  • 1970-01-01
  • 2015-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多