更新记录

1.0.0(2025-07-08) 下载此版本

1.0.1(2025-07-08)

  • 初始版本发布
  • 支持H5 Web Bluetooth API
  • 支持uni-app跨平台蓝牙API
  • 完整的BLE功能支持

平台兼容性

uni-app

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
- × - - -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 快应用-华为 快应用-联盟
× × × × × × - × × × ×

其他

多语言 暗黑模式 宽屏模式
× ×

jz-h5-bluetooth

跨平台蓝牙插件,支持H5 Web Bluetooth API和其他平台的uni-app蓝牙API。

注意:Web Bluetooth API需要HTTPS环境才能正常工作

v1.0.0

  • 初始版本发布
  • 支持H5 Web Bluetooth API
  • 支持uni-app跨平台蓝牙API
  • 完整的BLE功能支持

📋 Web Bluetooth API的用途和限制

Web Bluetooth API主要用途: 🔋 健康监测设备:心率计、体温计、血压计、血糖仪等 ⌚ 智能穿戴设备:智能手环、手表、运动追踪器等 🏠 智能家居设备:BLE灯泡、传感器、开关等 📍 定位设备:BLE信标(iBeacon)、防丢器等 🎮 游戏设备:支持BLE的游戏手柄等

为什么蓝牙耳机连接不了: 大多数蓝牙耳机使用经典蓝牙协议(用于音频传输) Web Bluetooth API 只支持BLE(低功耗蓝牙) 系统蓝牙支持经典蓝牙,所以可以连接耳机

为什么服务列表为空: Web Bluetooth有严格的权限控制 必须在选择设备时预先声明要访问的服务 这是为了保护用户隐私和安全

H5平台支持的设备类型

  • ✅ 智能手环、手表(小米手环、Apple Watch等)
  • ✅ 健康传感器(心率计、体温计、血压计等)
  • ✅ 智能家居设备(支持BLE的灯泡、开关等)
  • ✅ BLE信标设备(iBeacon、Eddystone等)
  • ❌ 蓝牙耳机、音箱(使用经典蓝牙)
  • ❌ 蓝牙键盘、鼠标(多数使用经典蓝牙)

如需连接音频设备:请使用原生App平台,或寻找支持BLE的音频设备

功能特点

  • ✅ 跨平台支持:H5、小程序、App
  • ✅ H5平台使用Web Bluetooth API
  • ✅ 其他平台使用uni-app原生蓝牙API
  • ✅ 统一的API接口,与uni-app蓝牙API保持一致
  • ✅ 完整的错误处理和状态管理
  • ✅ 支持设备发现、连接、服务发现、特征值读写
  • ✅ 支持数据通知和事件监听

浏览器兼容性

Web Bluetooth API兼容性:

  • ✅ Chrome 56+
  • ✅ Edge 79+
  • ✅ Opera 43+
  • ❌ Firefox(需开启实验性功能)
  • ❌ Safari(暂不支持)

详细兼容性请参考:Web Bluetooth API浏览器支持

安装使用

方法一:uni_modules安装(推荐)

  1. jz-h5-bluetooth文件夹复制到项目的uni_modules目录下
  2. 在需要使用的页面导入插件
import jzH5Bluetooth from '@/uni_modules/jz-h5-bluetooth/index.js'

方法二:ES6模块导入

import { 
  openBluetoothAdapter,
  createBLEConnection,
  writeBLECharacteristicValue
} from '@/uni_modules/jz-h5-bluetooth/index.js'

方法三:Vue插件安装

// main.js
import bluetooth, { install } from '@/uni_modules/jz-h5-bluetooth/index.js'
Vue.use(install)

// 在组件中使用
this.$bluetooth.openBluetoothAdapter(...)

API文档

蓝牙适配器

openBluetoothAdapter(options)

初始化蓝牙适配器

bluetooth.openBluetoothAdapter({
  success: (res) => {
    console.log('蓝牙适配器初始化成功', res)
  },
  fail: (err) => {
    console.log('蓝牙适配器初始化失败', err)
  }
})

// 强制重新初始化(忽略已初始化状态)
bluetooth.openBluetoothAdapter({
  force: true,
  success: (res) => {
    console.log('蓝牙适配器强制重新初始化成功', res)
  }
})

reopenBluetoothAdapter(options)

强制重新初始化蓝牙适配器(先关闭再打开)

bluetooth.reopenBluetoothAdapter({
  success: (res) => {
    console.log('蓝牙适配器重新初始化成功', res)
  }
})

closeBluetoothAdapter(options)

关闭蓝牙适配器

getBluetoothAdapterState(options)

获取本机蓝牙适配器状态

设备发现

startBluetoothDevicesDiscovery(options)

开始搜寻附近的蓝牙外围设备

bluetooth.startBluetoothDevicesDiscovery({
  services: ['FEE0'], // 指定要搜索的服务UUID
  success: (res) => {
    console.log('开始搜索设备', res)
  }
})

stopBluetoothDevicesDiscovery(options)

停止搜寻附近的蓝牙外围设备

getBluetoothDevices(options)

获取在蓝牙模块生效期间所有已发现的蓝牙设备

requestBluetoothDevice(options) - H5专用

H5平台请求访问蓝牙设备

参数说明:

  • filters (Array, 可选): 设备过滤器数组
  • acceptAllDevices (Boolean, 可选): 是否接受所有设备
  • optionalServices (Array, 可选): 可选服务UUID列表

注意: filtersacceptAllDevices 不能同时使用。如果两个都没有提供,默认使用 acceptAllDevices: true

// 方式1:使用filters指定特定设备
bluetooth.requestBluetoothDevice({
  filters: [
    { services: ['battery_service'] },
    { name: 'MyDevice' },
    { namePrefix: 'Smart' }
  ],
  optionalServices: ['device_information'],
  success: (res) => {
    console.log('用户选择了设备', res.device)
  }
})

// 方式2:接受所有设备(默认方式)
bluetooth.requestBluetoothDevice({
  acceptAllDevices: true,
  optionalServices: ['battery_service', 'device_information'],
  success: (res) => {
    console.log('用户选择了设备', res.device)
  }
})

// 方式3:不提供任何参数(等同于acceptAllDevices: true)
bluetooth.requestBluetoothDevice({
  success: (res) => {
    console.log('用户选择了设备', res.device)
  }
})

rerequestBluetoothDevice(deviceId, additionalServices) - H5专用

重新请求设备权限,用于解决服务访问权限问题

// 当出现服务访问权限错误时,重新请求设备权限
bluetooth.rerequestBluetoothDevice('device_id', [
  'battery_service',
  '00001234-0000-1000-8000-00805f9b34fb'
])

requestBluetoothDeviceWithServices(serviceUuids, options) - H5专用

使用特定服务UUID请求设备(推荐方式)

// 推荐:预先指定需要访问的服务
bluetooth.requestBluetoothDeviceWithServices([
  'battery_service',
  'device_information',
  '00001234-0000-1000-8000-00805f9b34fb'
], {
  // 其他选项
  success: (res) => {
    console.log('设备选择成功', res.device)
  }
})

checkDeviceCompatibility(deviceId)

检查设备BLE兼容性(H5平台特别重要)

// 选择设备后检查兼容性
const compatResult = bluetooth.checkDeviceCompatibility(deviceId)
if (compatResult.errCode === 0) {
  const { compatible, deviceType, reason, suggestions } = compatResult

  if (!compatible) {
    console.log('设备不兼容:', reason)
    console.log('建议:', suggestions.join('\n'))

    // 如果是音频设备,提示用户换用其他设备
    if (deviceType === 'audio-device') {
      alert('该蓝牙耳机不支持Web端连接,请尝试连接智能手环、传感器等BLE设备')
    }
  } else {
    // 兼容的设备可以尝试连接
    console.log('设备兼容,可以尝试连接')
  }
}

getDeviceCompatibilityAdvice(deviceName)

获取设备兼容性建议

// 根据设备名称获取兼容性建议
const advice = bluetooth.getDeviceCompatibilityAdvice('AirPods Pro')
console.log('平台信息:', advice.currentPlatform)
console.log('特定建议:', advice.specificAdvice)
console.log('通用建议:', advice.generalAdvice)

smartRequestBluetoothDevice(expectedDeviceName, options) - H5专用

智能设备选择(根据设备名称自动推荐服务)- 推荐方法

// 智能选择小米手环(自动添加相关服务权限)
const result = await bluetooth.smartRequestBluetoothDevice('Mi Band', {
  success: (res) => {
    console.log('智能选择成功', res.device)
    // 现在可以直接访问常见服务,不会出现权限错误
  }
})

// 智能选择心率监测设备
const result2 = await bluetooth.smartRequestBluetoothDevice('Heart Rate Monitor')

// 智能选择ESP32设备
const result3 = await bluetooth.smartRequestBluetoothDevice('ESP32-Device')

requestCommonBluetoothDevice(options) - H5专用

通用设备选择(包含最常用的服务权限)- 解决权限问题的最佳方法

// 选择设备时自动添加常见服务权限,解决大部分"服务访问被拒绝"问题
const result = await bluetooth.requestCommonBluetoothDevice({
  success: (res) => {
    console.log('设备选择成功', res.device)
    // 现在可以访问常见的BLE服务,如电池、设备信息等
  }
})

getDeviceRecommendedServices(deviceName)

获取设备推荐服务

// 查看设备推荐的服务列表
const services = bluetooth.getDeviceRecommendedServices('Mi Band 6')
if (services.errCode === 0) {
  console.log('设备类型:', services.deviceType)
  console.log('推荐服务:', services.recommendedServices)
  console.log('服务数量:', services.serviceCount)
}

parseServices(services)

解析服务名称到UUID

// 解析服务名称
const parsed = bluetooth.parseServices(['battery_service', 'heart_rate'])
console.log('解析结果:', parsed.parsedUUIDs)
// 输出: ['0000180f-0000-1000-8000-00805f9b34fb', '0000180d-0000-1000-8000-00805f9b34fb']

BLE连接管理

createBLEConnection(options)

连接低功耗蓝牙设备

bluetooth.createBLEConnection({
  deviceId: 'device_id_here',
  timeout: 10000, // 连接超时时间
  success: (res) => {
    console.log('设备连接成功', res)
  },
  fail: (err) => {
    console.log('设备连接失败', err)
    // 可以尝试重试连接
  }
})

retryBLEConnection(options)

重试连接低功耗蓝牙设备(自动重试机制)

bluetooth.retryBLEConnection({
  deviceId: 'device_id_here',
  maxRetries: 3, // 最大重试次数,默认3次
  retryDelay: 1000, // 重试间隔时间(毫秒),默认1000ms
  timeout: 10000, // 单次连接超时时间
  success: (res) => {
    console.log('设备连接成功', res)
  },
  fail: (err) => {
    console.log('所有重试均失败', err)
  }
})

closeBLEConnection(options)

断开与低功耗蓝牙设备的连接

getConnectedBluetoothDevices(options)

根据uuid获取处于已连接状态的设备

GATT服务操作

getBLEDeviceServices(options)

获取蓝牙设备所有服务

bluetooth.getBLEDeviceServices({
  deviceId: 'device_id_here',
  success: (res) => {
    console.log('设备服务列表', res.services)
  }
})

getBLEDeviceCharacteristics(options)

获取蓝牙设备某个服务中所有特征值

bluetooth.getBLEDeviceCharacteristics({
  deviceId: 'device_id_here',
  serviceId: 'service_uuid_here',
  success: (res) => {
    console.log('特征值列表', res.characteristics)
  }
})

readBLECharacteristicValue(options)

读取低功耗蓝牙设备的特征值

writeBLECharacteristicValue(options)

向低功耗蓝牙设备特征值中写入数据

bluetooth.writeBLECharacteristicValue({
  deviceId: 'device_id_here',
  serviceId: 'service_uuid_here',
  characteristicId: 'characteristic_uuid_here',
  value: arrayBuffer, // ArrayBuffer类型数据
  success: (res) => {
    console.log('数据写入成功', res)
  }
})

notifyBLECharacteristicValueChange(options)

启用特征值变化通知

bluetooth.notifyBLECharacteristicValueChange({
  deviceId: 'device_id_here',
  serviceId: 'service_uuid_here',
  characteristicId: 'characteristic_uuid_here',
  state: true, // true启用,false禁用
  success: (res) => {
    console.log('通知设置成功', res)
  }
})

事件监听

onBluetoothAdapterStateChange(callback)

监听蓝牙适配器状态变化事件

bluetooth.onBluetoothAdapterStateChange((res) => {
  console.log('蓝牙适配器状态变化', res)
})

onBluetoothDeviceFound(callback)

监听寻找到新设备的事件

bluetooth.onBluetoothDeviceFound((res) => {
  console.log('发现新设备', res.devices)
})

onBLEConnectionStateChange(callback)

监听低功耗蓝牙连接状态的改变事件

bluetooth.onBLEConnectionStateChange((res) => {
  console.log('BLE连接状态变化', res)
})

onBLECharacteristicValueChange(callback)

监听低功耗蓝牙设备的特征值变化事件

bluetooth.onBLECharacteristicValueChange((res) => {
  console.log('特征值变化', {
    deviceId: res.deviceId,
    serviceId: res.serviceId,
    characteristicId: res.characteristicId,
    value: res.value
  })
})

工具方法

getPlatformInfo()

获取当前平台信息

const info = bluetooth.getPlatformInfo()
console.log(info)
// {
//   platform: 'h5',
//   isH5: true,
//   webBluetoothSupported: true
// }

getDeviceConnectionState(deviceId)

获取设备连接状态

isDeviceConnected(deviceId)

检查设备是否已连接

getCachedServices(deviceId)

获取已缓存的服务列表

getCachedCharacteristics(deviceId, serviceId)

获取已缓存的特征值列表

disconnectAllDevices()

断开所有设备连接

使用示例

基本使用流程

import jzH5Bluetooth from '@/uni_modules/jz-h5-bluetooth/index.js'

export default {
  data() {
    return {
      devices: [],
      currentDevice: null
    }
  },

  async mounted() {
    // 1. 初始化蓝牙适配器
    await this.initBluetooth()

    // 2. 监听事件
    this.setupEventListeners()

    // 3. 开始搜索设备
    await this.startDiscovery()
  },

  methods: {
    async initBluetooth() {
      const result = await bluetooth.openBluetoothAdapter()
      if (result.errCode === 0) {
        console.log('蓝牙初始化成功')
      } else {
        console.error('蓝牙初始化失败:', result.errMsg)
      }
    },

    setupEventListeners() {
      bluetooth.onBluetoothDeviceFound((res) => {
        this.devices.push(...res.devices)
      })

      bluetooth.onBLECharacteristicValueChange((res) => {
        console.log('收到数据:', res)
      })
    },

    async startDiscovery() {
      if (bluetooth.getPlatformInfo().isH5) {
        // H5平台需要用户手动选择设备
        // 推荐使用 requestCommonBluetoothDevice 或 smartRequestBluetoothDevice
        // 这样可以避免服务访问权限问题

        const result = await bluetooth.requestCommonBluetoothDevice({
          success: (res) => {
            console.log('设备选择成功,已自动添加常见服务权限')
          }
        })

        // 或者根据设备名称智能选择
        // const result = await bluetooth.smartRequestBluetoothDevice('Mi Band')

        if (result.errCode === 0) {
          this.currentDevice = result.device
          await this.connectDevice()
        }
      } else {
        // 其他平台自动搜索
        await bluetooth.startBluetoothDevicesDiscovery({
          services: ['FEE0']
        })
      }
    },

    async connectDevice() {
      if (!this.currentDevice) return

      const result = await bluetooth.createBLEConnection({
        deviceId: this.currentDevice.deviceId
      })

      if (result.errCode === 0) {
        console.log('设备连接成功')
        await this.discoverServices()
      }
    },

    async discoverServices() {
      const result = await bluetooth.getBLEDeviceServices({
        deviceId: this.currentDevice.deviceId
      })

      if (result.errCode === 0) {
        console.log('发现服务:', result.services)
        // 继续发现特征值...
      }
    }
  }
}

注意事项

  1. H5平台限制

    • 需要HTTPS环境
    • 需要用户交互触发设备请求
    • 浏览器兼容性有限
  2. 数据格式

    • 所有数据传输使用ArrayBuffer格式
    • 插件提供了十六进制字符串转换工具
  3. 权限要求

    • H5平台需要用户授权
    • 小程序需要配置蓝牙权限
    • App需要蓝牙权限
  4. 错误处理

    • 所有API都返回统一格式的结果
    • errCode为0表示成功,其他为错误码

故障排除

常见错误及解决方案

1. 断开连接异常: Cannot read properties of undefined (reading 'errCode')

原因:插件返回了无效的结果对象 解决方案:已修复,插件现在会自动处理无效结果并提供有意义的错误信息

2. 设备选择失败: No device selected

原因:用户取消了设备选择或没有找到匹配的设备 解决方案

  • 确保设备处于可发现状态
  • 重新点击设备选择按钮
  • 检查设备是否在蓝牙范围内

3. 设备连接失败: Connection failed

原因:设备连接过程中出现各种问题 解决方案

// 使用重试连接方法
await bluetooth.retryBLEConnection({
  deviceId: 'your_device_id',
  maxRetries: 3,
  retryDelay: 1000
})

4. 设备未找到:设备不在缓存中

原因:设备没有通过requestBluetoothDevice选择 解决方案

  1. 先调用requestBluetoothDevice选择设备
  2. 然后再调用createBLEConnection连接设备

5. 权限被拒绝

原因:浏览器阻止了Web Bluetooth API访问 解决方案

  • 确保网站使用HTTPS协议
  • 检查浏览器的实验性功能设置
  • 重启浏览器后重试

6. 蓝牙耳机连接失败: NetworkError: Unsupported device

原因:H5平台只支持BLE设备,大多数蓝牙耳机使用经典蓝牙协议 错误详情Connection failed: NetworkError: Unsupported device. 解决方案

// 连接前检查设备兼容性
const compatResult = bluetooth.checkDeviceCompatibility(deviceId)
if (!compatResult.compatible) {
  console.log('设备不兼容:', compatResult.reason)
  console.log('建议:', compatResult.suggestions.join('\n'))

  if (compatResult.deviceType === 'audio-device') {
    alert('蓝牙耳机不支持Web端连接,请尝试连接智能手环、传感器等BLE设备')
    return
  }
}

// 或根据设备名称获取建议
const advice = bluetooth.getDeviceCompatibilityAdvice('AirPods Pro')
if (advice.specificAdvice.includes('音频设备')) {
  console.log('建议使用原生App平台连接音频设备')
}

7. 服务发现失败: Origin is not allowed to access any service [最常见问题]

原因:H5平台Web Bluetooth API的安全限制,未在设备选择时声明要访问的服务 错误详情Origin is not allowed to access any service. Tip: Add the service UUID to 'optionalServices' in requestDevice() options.

💡 最佳解决方案(推荐)

// 方案1:使用通用设备选择(解决99%的权限问题)
const result = await bluetooth.requestCommonBluetoothDevice()

// 方案2:智能设备选择(根据设备名称自动配置服务)
const result = await bluetooth.smartRequestBluetoothDevice('Mi Band 6')

// 方案3:手动指定服务(适用于已知服务UUID的情况)
const result = await bluetooth.requestBluetoothDeviceWithServices([
  'battery_service',
  'device_information', 
  'heart_rate',
  '00001234-0000-1000-8000-00805f9b34fb' // 自定义服务UUID
])

其他解决方案

// 方法4:在 requestBluetoothDevice 时手动添加 optionalServices
await bluetooth.requestBluetoothDevice({
  acceptAllDevices: true,
  optionalServices: [
    'battery_service',
    'device_information',
    '00001234-0000-1000-8000-00805f9b34fb'
  ]
})

// 方法5:如果已选择设备,使用重新请求权限
await bluetooth.rerequestBluetoothDevice(deviceId, [
  'battery_service',
  '00001234-0000-1000-8000-00805f9b34fb'
])

常见服务UUID

  • battery_service - 电池服务
  • device_information - 设备信息服务
  • heart_rate - 心率服务
  • 00001800-0000-1000-8000-00805f9b34fb - Generic Access
  • 00001801-0000-1000-8000-00805f9b34fb - Generic Attribute

最佳实践

  1. 错误处理:总是为蓝牙操作添加错误处理

    try {
    const result = await bluetooth.createBLEConnection({ deviceId })
    if (result.errCode !== 0) {
    console.error('连接失败:', result.errMsg)
    }
    } catch (error) {
    console.error('操作异常:', error.message)
    }
  2. 连接状态检查:连接前检查设备状态

    if (!bluetooth.isDeviceConnected(deviceId)) {
    await bluetooth.createBLEConnection({ deviceId })
    }
  3. 资源清理:页面卸载时断开所有连接

    beforeDestroy() {
    bluetooth.disconnectAllDevices()
    }

许可证

MIT License

贡献

欢迎提交Issue和Pull Request来改进这个插件。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

蓝牙权限

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

暂无用户评论。

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问