JavaScript内核与高级编程之:`JavaScript` 的 `Web Bluetooth` API:其在 `JavaScript` 中与蓝牙设备通信。

各位靓仔靓女们,今天老司机带大家飙一趟蓝牙,目标:用JavaScript驯服那些藏在身边的蓝牙小可爱们!准备好了吗?系好安全带,Let’s go!

Web Bluetooth API:让浏览器也能玩转蓝牙

以前我们想让网页和蓝牙设备勾搭上,那简直比登天还难。要么装插件,要么用原生应用绕弯路。现在好了,有了Web Bluetooth API,浏览器可以直接跟蓝牙设备眉来眼去,是不是感觉瞬间打开了新世界的大门?

理论先行:先搞清楚蓝牙的那些事儿

要玩转Web Bluetooth,咱们得先了解一些蓝牙的基本概念,不然就像拿着机关枪打蚊子,费力不讨好。

  • UUID (Universally Unique Identifier): 蓝牙设备上的每一个服务和特征都有一个UUID,相当于它们的身份证号码。有了UUID,我们才能找到特定的服务和特征。这玩意长得有点吓人,比如:0000ffe0-0000-1000-8000-00805f9b34fb。别怕,复制粘贴大法好!
  • Service (服务): 服务就像一个蓝牙设备的某个功能模块,比如心率监测、电量显示等等。一个设备可以有多个服务。
  • Characteristic (特征): 特征是服务内部的具体数据,比如心率的数值、电量的百分比等等。我们可以读取特征的值,也可以向特征写入值,从而控制设备。

准备工作:浏览器和蓝牙设备都要到位

首先,你的浏览器必须支持Web Bluetooth API。目前主流的Chrome、Edge等都支持,但Safari比较傲娇,暂时还不支持。

其次,你需要一个支持蓝牙的设备,并且这个设备要支持GATT (Generic Attribute Profile)。GATT是蓝牙通信的一种协议,Web Bluetooth API就是基于GATT的。常见的蓝牙设备,比如智能手表、心率带、蓝牙音箱等等,都支持GATT。

代码实战:一步一步征服蓝牙

好了,理论知识武装完毕,现在开始撸代码!

第一步:请求蓝牙设备

首先,我们要让浏览器弹出一个对话框,让用户选择要连接的蓝牙设备。

navigator.bluetooth.requestDevice({
  filters: [{ services: ['heart_rate'] }] // 筛选只显示心率设备
})
.then(device => {
  console.log('Device name:', device.name);
  //device.gatt.connect(); // 连接设备,移到 connectGATT() 中
  return device.gatt.connect(); // 返回 GATT Server 对象
})
.then(server => {
  console.log('GATT server:', server);
  // 获取心率服务,移到 getPrimaryService() 中
  return server.getPrimaryService('heart_rate');
})
.then(service => {
  console.log('Service:', service);
  // 获取心率测量特征,移到 getCharacteristic() 中
  return service.getCharacteristic('heart_rate_measurement');
})
.then(characteristic => {
  console.log('Characteristic:', characteristic);
  // 开始监听心率值的变化,移到 startNotifications() 中
  return characteristic.startNotifications();
})
.then(characteristic => {
  console.log('Notifications started');
  // 监听心率值的变化
  characteristic.addEventListener('characteristicvaluechanged', handleHeartRate);
})
.catch(error => {
  console.log('Error:', error);
});

function handleHeartRate(event) {
  const value = event.target.value;
  const heartRate = value.getUint8(1); // 获取心率值,通常在第二个字节
  console.log('Heart Rate:', heartRate);
}

这段代码做了什么?

  1. navigator.bluetooth.requestDevice():弹出设备选择对话框。filters 选项可以用来筛选设备,只显示特定的服务。这里我们只显示支持心率服务的设备。
  2. .then(device => ...):当用户选择了一个设备后,这个回调函数会被执行。我们可以在这里获取设备的信息,比如设备名称。
  3. device.gatt.connect():连接到设备的GATT服务器。
  4. .then(server => ...):连接成功后,这个回调函数会被执行。我们可以在这里获取GATT服务器对象。
  5. server.getPrimaryService('heart_rate'):获取心率服务。
  6. .then(service => ...):获取服务成功后,这个回调函数会被执行。我们可以在这里获取服务对象。
  7. service.getCharacteristic('heart_rate_measurement'):获取心率测量特征。
  8. .then(characteristic => ...):获取特征成功后,这个回调函数会被执行。我们可以在这里获取特征对象。
  9. characteristic.startNotifications():开始监听心率值的变化。
  10. .then(characteristic => ...):开启通知后,此回调函数执行,监听 characteristicvaluechanged 事件。
  11. characteristic.addEventListener('characteristicvaluechanged', handleHeartRate):监听心率值的变化。当心率值发生变化时,handleHeartRate 函数会被执行。
  12. handleHeartRate(event):处理心率值变化的函数。我们可以在这里获取心率值,并进行处理。

第二步:读取特征的值

除了监听特征值的变化,我们也可以直接读取特征的值。

// 在获取 characteristic 对象后,添加如下代码:
characteristic.readValue()
.then(value => {
  const heartRate = value.getUint8(1);
  console.log('Initial Heart Rate:', heartRate);
});

这段代码会在连接成功后,立即读取一次心率值。

第三步:写入特征的值

有些特征是可写的,我们可以通过写入值来控制设备。

// 假设我们有一个控制 LED 灯的特征,UUID 为 '0000ffe1-0000-1000-8000-00805f9b34fb'
service.getCharacteristic('0000ffe1-0000-1000-8000-00805f9b34fb')
.then(characteristic => {
  const value = new Uint8Array([1]); // 1 表示打开 LED 灯,0 表示关闭
  return characteristic.writeValue(value);
})
.then(() => {
  console.log('LED turned on');
})
.catch(error => {
  console.log('Error writing value:', error);
});

这段代码会向 LED 灯的特征写入一个值,打开 LED 灯。

进阶技巧:优雅地处理蓝牙连接

蓝牙连接可能会因为各种原因断开,比如设备关机、超出范围等等。我们需要优雅地处理这些情况,给用户一个友好的提示。

device.addEventListener('gattserverdisconnected', () => {
  console.log('Bluetooth Device disconnected');
  // 重新连接设备
  connectDevice(); // 需要重新定义 connectDevice() 函数
});

function connectDevice() {
  navigator.bluetooth.requestDevice({
    filters: [{ services: ['heart_rate'] }]
  })
  .then(device => {
    // ... (连接设备的逻辑)
  })
  .catch(error => {
    console.log('Error:', error);
  });
}

这段代码监听了 gattserverdisconnected 事件,当蓝牙连接断开时,会重新连接设备。

实战案例:控制智能灯泡

为了让大家更直观地了解Web Bluetooth API的用法,我们来一个实战案例:控制智能灯泡。

假设我们有一个智能灯泡,它有一个服务用来控制灯泡的亮度,UUID 为 0000ffe0-0000-1000-8000-00805f9b34fb,这个服务有一个特征用来设置亮度值,UUID 为 0000ffe1-0000-1000-8000-00805f9b34fb。亮度值的范围是 0-255。

<!DOCTYPE html>
<html>
<head>
  <title>Smart Bulb Control</title>
</head>
<body>
  <h1>Smart Bulb Control</h1>
  <input type="range" id="brightness" min="0" max="255" value="0">
  <button id="connect">Connect</button>
  <script>
    const connectButton = document.getElementById('connect');
    const brightnessInput = document.getElementById('brightness');
    let bulbCharacteristic;

    connectButton.addEventListener('click', () => {
      navigator.bluetooth.requestDevice({
        filters: [{ services: ['0000ffe0-0000-1000-8000-00805f9b34fb'] }]
      })
      .then(device => {
        return device.gatt.connect();
      })
      .then(server => {
        return server.getPrimaryService('0000ffe0-0000-1000-8000-00805f9b34fb');
      })
      .then(service => {
        return service.getCharacteristic('0000ffe1-0000-1000-8000-00805f9b34fb');
      })
      .then(characteristic => {
        bulbCharacteristic = characteristic;
        console.log('Connected to bulb');
      })
      .catch(error => {
        console.log('Error:', error);
      });
    });

    brightnessInput.addEventListener('input', () => {
      const brightness = parseInt(brightnessInput.value);
      const value = new Uint8Array([brightness]);
      if (bulbCharacteristic) {
        bulbCharacteristic.writeValue(value)
        .then(() => {
          console.log('Brightness set to:', brightness);
        })
        .catch(error => {
          console.log('Error writing value:', error);
        });
      } else {
        console.log('Not connected to bulb');
      }
    });
  </script>
</body>
</html>

这个代码实现了一个简单的智能灯泡控制页面。页面上有一个滑动条和一个连接按钮。点击连接按钮后,会弹出设备选择对话框,选择智能灯泡后,就可以通过滑动条来调节灯泡的亮度。

Web Bluetooth API 的优势与局限

  • 优势:
    • 无需插件: 摆脱了插件的束缚,直接在浏览器中使用。
    • 跨平台: 可以在任何支持Web Bluetooth API的浏览器中使用。
    • 安全性: 浏览器会提示用户授权,保护用户的隐私。
  • 局限:
    • 兼容性: 目前只有部分浏览器支持。
    • 蓝牙权限: 某些蓝牙设备可能需要配对才能使用。
    • 距离限制: 蓝牙的有效距离有限。

常见问题与解决方案

  • 设备无法连接:
    • 检查蓝牙设备是否开启。
    • 检查浏览器是否开启蓝牙。
    • 检查设备是否支持GATT协议。
    • 尝试重新启动浏览器和蓝牙设备。
  • 无法读取特征的值:
    • 检查特征是否可读。
    • 检查是否已经连接到设备。
  • 无法写入特征的值:
    • 检查特征是否可写。
    • 检查写入的值是否符合要求。

总结:拥抱蓝牙的未来

Web Bluetooth API 的出现,让网页与蓝牙设备的交互变得更加简单便捷。虽然目前还存在一些局限性,但随着技术的不断发展,相信Web Bluetooth API 会在物联网、智能家居等领域发挥越来越重要的作用。

今天的蓝牙之旅就到这里。希望大家通过今天的学习,能够掌握Web Bluetooth API的基本用法,并能够用它来开发出各种有趣的蓝牙应用。记住,编程的乐趣在于不断探索和创新,大胆尝试,你也能成为蓝牙大师!

附录:一些常用的蓝牙 UUID

服务名称 UUID 说明
心率服务 0000180D-0000-1000-8000-00805f9b34fb 用于测量心率
电量服务 0000180F-0000-1000-8000-00805f9b34fb 用于获取电量信息
设备信息服务 0000180A-0000-1000-8000-00805f9b34fb 用于获取设备制造商、型号等信息
环境感知服务 0000181A-0000-1000-8000-00805f9b34fb 用于测量温度、湿度等环境参数
血氧饱和度服务 00001810-0000-1000-8000-00805f9b34fb 用于测量血氧饱和度

这些UUID可以帮助你快速找到常用的蓝牙服务。当然,不同的设备可能会使用不同的UUID,你需要根据设备的文档来确定。

好了,今天的讲座就到这里,祝大家编码愉快!记住,遇到问题不要怕,Google一下,Stack Overflow一下,总能找到答案的!下次再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注