You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Web Bluetooth API用JavaScript实现蓝牙外设广播

你目前用的扫描功能是Web Bluetooth的中央设备(Central)模式API,原生稳定版API没有提供BLE外设广播、作为外围设备被连接的能力,要实现你要的功能,需要使用目前仍在实验阶段的Web Bluetooth Peripheral特性,具体实现方式、限制和代码如下:

前置支持条件
  • 浏览器兼容:仅桌面端Chrome/Edge 105+、ChromeOS原生支持该特性,Firefox、Safari全版本、移动端浏览器暂不支持
  • 系统兼容:Windows 10 2004及以上、macOS 12及以上、ChromeOS可直接使用;Linux发行版需要手动开启BlueZ的实验性功能,且蓝牙适配器硬件支持BLE外设角色
  • 配置开关:本地测试时直接打开chrome://flags/#enable-experimental-web-platform-features开关,重启浏览器即可生效;如果要面向普通用户上线,需要申请对应实验特性的源试用令牌,否则普通用户无法调用相关API
  • 环境要求:必须在HTTPS页面(本地localhost调试不受HTTPS限制)下调用,否则API会被浏览器直接拦截

先做特性检测,避免直接调用报错:

if (!navigator.bluetooth || typeof navigator.bluetooth.requestPeripheral !== 'function') {
  throw new Error('当前环境不支持Web BLE外设模式,请检查浏览器、系统配置是否符合要求');
}
具体实现

1. 构造蓝牙广播数据包

广播包包含对外暴露的设备名、服务UUID、厂商自定义数据等信息,可被周围BLE扫描设备捕获。如果需要支持其他设备连接,必须将connectable字段设为true。

// 自定义服务UUID,正式使用建议生成专属128位UUID避免冲突
const CUSTOM_SERVICE_UUID = 'b3ff0001-b0a7-47d1-a954-f0dd0c5ad00d';
const CUSTOM_CHAR_UUID = 'b3ff0002-b0a7-47d1-a954-f0dd0c5ad00d';

// 广播包配置
const advConfig = {
  name: 'Laptop-BLE-Server', // 广播显示的设备名
  uuids: [CUSTOM_SERVICE_UUID], // 对外声明支持的服务列表
  connectable: true, // 允许其他设备发起连接
  txPower: -8, // 广播发射功率,单位dBm,可按需调整
  manufacturerData: [ // 厂商自定义数据,会放在广播包载荷中
    {
      companyIdentifier: 0xFF01, // 测试用厂商ID,正式商用需向蓝牙SIG申请
      data: new Uint8Array([0x11, 0x22, 0x33]) // 自定义广播内容,注意总长度不要超过广播包上限
    }
  ]
};

注意:传统BLE广播单包载荷最大31字节,不要在广播包中塞入过长的自定义数据,否则会导致广播启动失败。如果需要传输大量数据,必须等设备连接后通过GATT特征值传输。

2. 搭建GATT服务端,支持设备连接交互

仅开启可连接广播还不够,你需要在本地创建GATT服务和特征值,其他设备连接后才能读写数据、完成交互:

let bleAdapter = null;

async function startBlePeripheral() {
  // 向用户申请蓝牙外设权限
  bleAdapter = await navigator.bluetooth.requestPeripheral({
    acceptAllDevices: true
  });

  // 监听连接、断开事件
  bleAdapter.addEventListener('connect', (e) => {
    console.log('设备已连接:', e.device.name || e.device.id);
  });
  bleAdapter.addEventListener('disconnect', (e) => {
    console.log('设备已断开:', e.device.name || e.device.id);
  });

  // 创建主服务
  const customService = await bleAdapter.addService({
    uuid: CUSTOM_SERVICE_UUID,
    isPrimary: true
  });

  // 创建可读写、可推送通知的特征值
  const customChar = await customService.addCharacteristic({
    uuid: CUSTOM_CHAR_UUID,
    properties: {
      read: true,
      write: true,
      notify: true
    },
    value: new Uint8Array([0x00]) // 特征值初始内容
  });

  // 处理其他设备的读请求
  customChar.addEventListener('read', async (e) => {
    const respData = new Uint8Array([0x01, 0x02, 0x03]);
    await customChar.respondWithValue(respData);
  });

  // 处理其他设备的写请求
  customChar.addEventListener('write', async (e) => {
    const receivedData = new Uint8Array(e.value);
    console.log('收到设备写入的数据:', receivedData);
    // 返回0x00状态码代表写入成功
    await customChar.respondWithCode(0x00);

    // 如果需要主动给连接的设备推数据,直接调用writeValue即可
    // await customChar.writeValue(new Uint8Array([0xaa, 0xbb]));
  });

  // 启动广播
  await bleAdapter.startAdvertising(advConfig);
  console.log('BLE广播已启动,可被周围设备搜索连接');
}

// 调用函数启动
startBlePeripheral().catch(err => {
  console.error('启动BLE外设失败:', err);
});

3. 停止广播

不需要对外广播时,调用以下方法即可停止广播、移除所有GATT服务、断开所有已连接设备:

async function stopBlePeripheral() {
  if (!bleAdapter) return;
  await bleAdapter.stopAdvertising();
  await bleAdapter.removeAllServices();
  bleAdapter = null;
  console.log('BLE广播已停止');
}
常见问题排查
  • 其他设备搜不到广播:先检查系统蓝牙权限是否给了当前浏览器,Windows系统可在设备管理器中确认蓝牙适配器是否支持“外围设备角色”;部分笔记本的蓝牙适配器硬件不支持外设模式,这种情况无法通过软件解决
  • 广播启动报错:优先检查广播包总长度是否超限,是否有其他页面/程序已经占用了蓝牙外设广播通道
  • 设备连接后马上断开:检查是否正确添加了声明的GATT服务,如果广播中声明的服务和实际创建的服务不匹配,部分系统会主动断开连接

内容的提问来源于stack exchange,提问作者Tejas Chauhan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 00:01:24