更新记录
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安装(推荐)
- 将
jz-h5-bluetooth
文件夹复制到项目的uni_modules
目录下 - 在需要使用的页面导入插件
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列表
注意: filters
和 acceptAllDevices
不能同时使用。如果两个都没有提供,默认使用 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)
// 继续发现特征值...
}
}
}
}
注意事项
-
H5平台限制:
- 需要HTTPS环境
- 需要用户交互触发设备请求
- 浏览器兼容性有限
-
数据格式:
- 所有数据传输使用ArrayBuffer格式
- 插件提供了十六进制字符串转换工具
-
权限要求:
- H5平台需要用户授权
- 小程序需要配置蓝牙权限
- App需要蓝牙权限
-
错误处理:
- 所有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
选择
解决方案:
- 先调用
requestBluetoothDevice
选择设备 - 然后再调用
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 Access00001801-0000-1000-8000-00805f9b34fb
- Generic Attribute
最佳实践
-
错误处理:总是为蓝牙操作添加错误处理
try { const result = await bluetooth.createBLEConnection({ deviceId }) if (result.errCode !== 0) { console.error('连接失败:', result.errMsg) } } catch (error) { console.error('操作异常:', error.message) }
-
连接状态检查:连接前检查设备状态
if (!bluetooth.isDeviceConnected(deviceId)) { await bluetooth.createBLEConnection({ deviceId }) }
-
资源清理:页面卸载时断开所有连接
beforeDestroy() { bluetooth.disconnectAllDevices() }
许可证
MIT License
贡献
欢迎提交Issue和Pull Request来改进这个插件。