2022/1/18 更新说明

为了避免重复造轮子,请参考这篇文章。其中内容详细且全面,目前也已经有了中文版
1. 通过 JavaScript 与蓝牙设备通信


目标

最近正在开发一个项目,项目的需求如下:
在H5(基于vue框架)页面上,通过js调用webbluetooth接口,读取某个蓝牙设备传输的数据,并返回显示。

介绍

背景

随着PWA的兴起,越来越多的web服务被支持。但其中一个领域几乎是原生应用的专属领域:与设备通信。长期以来,开发者们一直在致力于解决这个问题。

The web is excellent for talking to servers, but not for talking to devices
……

于是乎WebBluetooth应运而生,这是一个已经在Chrome和三星互联网上实现的新规范。

WebBluetooth is a new specification that has been implemented in Chrome and Samsung Internet that allows us to communicate directly to Bluetooth Low Energy devices from the browser.

Bluetooth Low Energy (BLE)

维基百科 - 低功耗蓝牙

Generic Attribute Profile (GATT)

蓝牙BLE: GATT Profile 简介(GATT 与 GAP)

GAP 使你的设备被其他设备可见,并决定了你的设备是否可以或者怎样与合同设备进行交互。
GATT协议 - 通用属性配置

WebBluetooth API

通过使用WebBluetooth API,我们只需要几行JavaScript就可以和蓝牙设备进行沟通。

The Web Bluetooth API aims to do exactly that with a promise-based API, which allows you to interact with many BLE(Bluetooth Low Energy) enabled devices.

使用条件(prerequisites)

  1. 需要HTTPS
  2. 需要用户给予蓝牙权限,需要用户点击确认
button.addEventListener('pointerup', function(event) {
  // Call navigator.bluetooth.requestDevice
});
  1. 系统要求,具体的看这里 MDN’s Browser compatibility

A subset of the Web Bluetooth API is available in Chrome OS, Chrome for Android 6.0, Mac (Chrome 56) and Windows 10 (Chrome 70)

navigator.bluetooth.requestDevice()

接受一个定义筛选器的强制对象。这些过滤器用于仅返回匹配某些已发布的蓝牙GATT服务和/或设备名称的设备。

使用:过滤器

  • Services filter
navigator.bluetooth.requestDevice({ filters: [{ services: ['battery_service'] }] })
.then(device => { /* … */ })
.catch(error => { console.error(error); });

如果蓝牙设备不在这个服务列表里面,我们需要提供完整的Bluetooth UUID 或者16-/32-bit 的排列

navigator.bluetooth.requestDevice({
  filters: [{
    services: [0x1234, 0x12345678, '99999999-0000-1000-8000-00805f9b34fb']
  }]
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
  • Name filter
navigator.bluetooth.requestDevice({
  filters: [{
    name: 'Francois robot'
  }],
  optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
  • Manufacturer data filter
// Filter Bluetooth devices from Google company with manufacturer data bytes
// that start with [0x01, 0x02].
navigator.bluetooth.requestDevice({
  filters: [{
    manufacturerData: [{
      companyIdentifier: 0x00e0,
      dataPrefix: new Uint8Array([0x01, 0x02])
    }]
  }],
  optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
  • No filters
navigator.bluetooth.requestDevice({
  acceptAllDevices: true,
  optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });

开始

参考文献【1】 给出的是一个通过蓝牙控制灯泡颜色的例子。 我们的实验也是基于他的思路并修改,最终实现目标。

1.连接蓝牙设备

首先,要做的就是连接蓝牙设备,这里我们使用的是navigator.bluetooth.requestDevice()这个接口。

navigator.bluetooth.requestDevice({ filters: [{ services: ['battery_service'] }] })
.then(device => {
  // Human-readable name of the device.
  console.log(device.name);

  // Attempts to connect to remote GATT Server.
  return device.gatt.connect();
})
.then(server => { /* … */ })
.catch(error => { console.error(error); });

2.写入数据

3.读取数据

navigator.bluetooth.requestDevice({ filters: [{ services: ['battery_service'] }] })
.then(device => device.gatt.connect())
.then(server => {
  // Getting Battery Service…
  return server.getPrimaryService('battery_service');
})
.then(service => {
  // Getting Battery Level Characteristic…
  return service.getCharacteristic('battery_level');
})
.then(characteristic => {
  // Reading Battery Level…
  return characteristic.readValue();
})
.then(value => {
  console.log(`Battery percentage is ${value.getUint8(0)}`);
})
.catch(error => { console.error(error); });

4.获取信息并改变(返回显示)

navigator.bluetooth.requestDevice({ filters: [{ services: ['heart_rate'] }] })
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('heart_rate'))
.then(service => service.getCharacteristic('heart_rate_measurement'))
.then(characteristic => characteristic.startNotifications())
.then(characteristic => {
  characteristic.addEventListener('characteristicvaluechanged',
                                  handleCharacteristicValueChanged);
  console.log('Notifications have been started.');
})
.catch(error => { console.error(error); });

function handleCharacteristicValueChanged(event) {
  const value = event.target.value;
  console.log('Received ' + value);
  // TODO: Parse Heart Rate Measurement value.
  // See https://github.com/WebBluetoothCG/demos/blob/gh-pages/heart-rate-sensor/heartRateSensor.js
}

5.断开连接

navigator.bluetooth.requestDevice({ filters: [{ name: 'Francois robot' }] })
.then(device => {
  // Set up event listener for when device gets disconnected.
  device.addEventListener('gattserverdisconnected', onDisconnected);

  // Attempts to connect to remote GATT Server.
  return device.gatt.connect();
})
.then(server => { /* … */ })
.catch(error => { console.error(error); });

function onDisconnected(event) {
  const device = event.target;
  console.log(`Device ${device.name} is disconnected.`);
}

参考文献


2022/1/18–更新

Web H5 网页 浏览器 蓝牙 Bluetooth PWA

开发环境
  • VScode:1.63.2
  • Node.js:14.16.0
  • OS:Windows_NT x64
  • Vue.js:2.6.11
  • 蓝牙模块(-)

蓝牙模块组

开始
  1. 新建蓝牙分支(可选)
git branch bluetooth
git checkout bluetooth
  1. 定义一个请求蓝牙服务的按钮
<div @click="bluetooth()">请求蓝牙服务</div>
  1. 点击按钮请求蓝牙设备并连接
...
bluetooth() {
      //请求蓝牙设备
      navigator.bluetooth
        .requestDevice({ //显示附近所有设备
          acceptAllDevices: true 
        })
        .then((device) => { //控制台输出设备名称并连接
          console.log(device.name);
          return device.gatt.connect();
        })
        .then((server) => { //控制台输出设备服务
          console.log(server);
        })
        .catch((error) => { //错误捕捉
          console.error(error);
        });
    },
...

浏览器提示蓝牙配对

控制台输出设备连接

DEBUG
TypeError:navigator.bluetooth.requesetDevice is not a function

需要先定义一个用户交互服务才能开始请求蓝牙设备;即不能在页面加载时使用该功能。

更多

在 Chrome 中的 about://bluetooth-internals
位置可查看蓝牙内部页面,以便您可以检查附近蓝牙设备的所有信息:状态、服务、特征和描述符。
查看蓝牙设备服务

参考文档

1. 通过 JavaScript 与蓝牙设备通信

2. Web Bluetooth API

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐