更新记录
1.0.2(2024-10-28)
- 修复高版本HB只回调一次的问题
1.0.1(2024-09-16)
- 优化Android代码告警问题
1.0.0(2024-08-16)
- 判断蓝牙是否打开,打开/关闭蓝牙
- 蓝牙扫描,获取蓝牙名、mac、信号强度、广播数据等
- 设置MTU
- 获取service、characteristic
- 蓝牙通讯,读、写、notify
平台兼容性
Vue2 | Vue3 |
---|---|
√ | √ |
App | 快应用 | 微信小程序 | 支付宝小程序 | 百度小程序 | 字节小程序 | QQ小程序 |
---|---|---|---|---|---|---|
HBuilderX 3.6.8,Android:4.4,iOS:9,HarmonyNext:不确定 | × | × | × | × | × | × |
钉钉小程序 | 快手小程序 | 飞书小程序 | 京东小程序 |
---|---|---|---|
× | × | × | × |
H5-Safari | Android Browser | 微信浏览器(Android) | QQ浏览器(Android) | Chrome | IE | Edge | Firefox | PC-Safari |
---|---|---|---|---|---|---|---|---|
× | × | × | × | × | × | × | × | × |
ble蓝牙扫描连接收发数据
功能
- 判断蓝牙是否打开,打开/关闭蓝牙
- 蓝牙扫描,获取蓝牙名、mac、信号强度、广播数据等
- 设置MTU
- 获取service、characteristic
- 蓝牙通讯,读、写、notify
蓝牙分为中心设备(Central、Master、主设备、客户端)和外围设备(Peripheral、Slave、从设备、服务端) 手机做为客户端可以连接多个蓝牙设备,所以手机又可以叫中心设备(Central),蓝牙设备叫外围设备(Peripheral)。 例如:通过手机蓝牙开启共享单车,手机称为中心设备,共享单车称为外围设备
本插件是中心设备(Central、Master、主设备、客户端)
外围设备插件请使用https://ext.dcloud.net.cn/plugin?name=wrs-uts-bluetoothslave
快速接入
- 拷贝demo示例里的AndroidManifest.xml、Info.plist到项目根目录
- 集成插件步骤请参考https://www.cnblogs.com/wenrisheng/p/18323027
接口
import {
UTSBluetoothCenter
} from "@/uni_modules/wrs-uts-bluetoothcenter"
let bluetoothcenter = new UTSBluetoothCenter()
- 设置回调
// 设置回调
bluetoothcenter.setCallback((resp) => {
let opt = resp.opt;
switch (opt) {
// 蓝牙状态改变,仅支持iOS
case "onCentralManagerDidUpdateState": {
// state:
// 0: CBManagerStateUnknown
// 1: CBManagerStateResetting
// 2: CBManagerStateUnsupported
// 3: CBManagerStateUnauthorized
// 4: CBManagerStatePoweredOff
// 5: CBManagerStatePoweredOn
let state = resp.state
console.log("state:" + state)
if (state == 5) {
// 蓝牙已经打开
} else if (state == 4) {
// 蓝牙已关闭
// this.showModel("蓝牙已关闭,是否打开?", () => {
// UTSBluetoothCenter.openSettingApp()
// })
} else if (state == 3) {
} else {
}
}
break;
// 扫描到蓝牙设备
case "onScanBluetooth": {
let device = resp.device
let name = device.name
// {"opt":"onScanBluetooth","device":{"name":"MI MAX 3","deviceId":"32A699B6-AC3B-00A9-218A-3014E74A975F"},"rssi":-44,"isConnectable":1}
// {"device":{"mac":"FF:FF:99:87:09:75","deviceId":"NEMR99870975FF:FF:99:87:09:75","name":"NEMR99870975","rssi":-94},"advertisementData":{"manufacturerData":{"id":20563,"data":[75,29,64,32,64]},"txPowerLevel":3,"serviceUUIDs":["FDF0"],"localName":"NEMR99870975"},"opt":"onScanBluetooth"}
// 没有蓝牙名的过滤掉
if (name) {
if (name !== "MI MAX 3") {
// console.log(JSON.stringify(resp))
return
}
// 已经扫描到的蓝牙也过滤下,防止重复扫描问题
let deviceId = device.deviceId
let isExist = false
for (let i = 0; i < this.deviceArray.length; i++) {
if (deviceId == this.deviceArray[i].device.deviceId) {
isExist = true
break
}
}
if (!isExist) {
this.deviceArray.push(resp)
}
}
}
break;
// 蓝牙连接成功
case "onConnectSuccess": {
this.showMsg("蓝牙连接成功")
}
break;
// 蓝牙连接失败
case "onConnectFail": {
this.showMsg("蓝牙连接失败:" + JSON.stringify(resp))
}
break;
// 蓝牙断开连接
case "onDisConnected": {
// 高版本的某些iOS系统,如果发现连接成功后又马上断开了,报下面这种错误时,需要先在设置-蓝牙里面手动进行配对连接上蓝牙后,再来通过代码连接
// Error Domain=CBErrorDomain Code=7 "The specified device has disconnected from us." UserInfo={NSLocalizedDescription=The specified device has disconnected from us.
this.showMsg("蓝牙断开连接:" + JSON.stringify(resp))
}
break;
// 发现characteristic特征值
case "onFindCharacteristic": {
if (this.isAndroid) {
resp.service = JSON.parse(resp.service)
}
console.log(JSON.stringify(resp))
var deviceId = resp.device.deviceId;
var bluetooth = this.getBluetooth(deviceId);
let service = resp.service
// let characteristics = resp.characteristics
// this.$set(service, "characteristics", characteristics);
if (!bluetooth.services) {
this.$set(bluetooth, "services", []);
}
bluetooth.services.push(service);
}
break;
// 收到数据
case "onCharacteristicChanged": {
let value = resp.value
this.showMsg("收到数据:" + JSON.stringify(resp))
}
break;
default:
break;
}
})
- 蓝牙初始化
var params = {};
if (this.isAndroid) {
} else {
params.CBCentralManagerOptionShowPowerAlertKey = true;
}
// 初始化
bluetoothcenter.initBluetooth(params);
- 扫描蓝牙
扫描结果在回调里bluetoothcenter.setCallback((resp) => {}) -> onScanBluetooth
let params = {}
// params.services = ["xxx", "xxx"]
// params.CBCentralManagerScanOptionAllowDuplicatesKey = true // 仅支持iOS
bluetoothcenter.startScanBluetooth(params)
扫描到的数据主要包含有蓝牙名、rssi、mac、广播数据(蓝牙名、厂家数据、serviceUUIDs)等
ios: {"advertisementData":{"manufacturerData":[224,7,204,20,188,82,161,242,2,0],"isConnectable":1,"localName":"EDIFIER BLE"},"opt":"onScanBluetooth","device":{"name":"EDIFIER BLE","rssi":-92,"deviceId":"6EAB2BCC-001E-6664-3E1D-34004BD5C2EF"}}
android: {"device":{"mac":"FF:FF:99:87:09:75","deviceId":"NEMR99870975FF:FF:99:87:09:75","name":"NEMR99870975","rssi":-94},"advertisementData":{"manufacturerData":{"id":20563,"data":[75,29,64,32,64]},"txPowerLevel":3,"serviceUUIDs":["FDF0"],"localName":"NEMR99870975"},"opt":"onScanBluetooth"}
扫描不到蓝牙问题排查:
- Android是否有调用请求权限接口
// 请求Android动态权限
this.requestPermission([
"android.permission.BLUETOOTH_SCAN",
"android.permission.BLUETOOTH_CONNECT",
"android.permission.BLUETOOTH_ADMIN",
"android.permission.BLUETOOTH",
"android.permission.ACCESS_FINE_LOCATION",
"android.permission.ACCESS_COARSE_LOCATION",
"android.permission.READ_EXTERNAL_STORAGE",
"android.permission.WRITE_EXTERNAL_STORAGE"
])
- 某些蓝牙设备需要现在设置-> 蓝牙里面先进行蓝牙连接配对后才能扫描
- 将手机蓝牙功能先关闭重新打开后再扫描
- Android设备的定位、蓝牙功能是否已经开启
- 停止扫描
bluetoothcenter.stopScanBluetooth()
- 连接蓝牙
Android可以通过deviceId或mac连接蓝牙,iOS只能通过deviceId连接蓝牙
连接结果在回调里bluetoothcenter.setCallback((resp) => {}) -> onConnectSuccess、onConnectFail
连接成功会会自动查找service/characteristic,查找结果在回调的onFindCharacteristic里面
characteristic的读写notify属性判断请参考demo
let params = {}
params.deviceId = model.device.deviceId
// params.mac = “A4:C1:38:A1:46:C8”
console.log(`params:${JSON.stringify(params)}`)
let flag = bluetoothcenter.connectBluetooth(params)
if (!flag) {
console.log("参数错误")
}
- 断开连接
let params = {}
params.deviceId = model.device.deviceId
let flag = bluetoothcenter.disConnectBluetooth(params)
if (!flag) {
console.log("参数错误")
}
- 打开characteristic notify通知,characteristic只有打开notify通知后才能收到对方发来的数据
开启后,收到的数据在回调里bluetoothcenter.setCallback((resp) => {}) -> onCharacteristicChanged(let value = resp.value) value是十六进制数组,如果需要ascii、十六进制字符串、modbus等数据转换,请使用插件https://ext.dcloud.net.cn/plugin?id=19206
var bluetooth = this.deviceArray[i];
var service = bluetooth.services[j];
var characteristic = service.characteristics[k];
bluetoothcenter.openOrStopNotify({
deviceId: bluetooth.device.deviceId,
serviceUuid: service.uuid,
characteristicUuid: characteristic.uuid,
isOpen: true // true: 打开, false: 关闭
}, (resp) => {
if (resp.flag) { // 打开成功
} else { // 打开失败
}
});
- 发送数据
value目前只支持十六进制数组,如果需要ascii、十六进制字符串、modbus等数据转换,请使用插件https://ext.dcloud.net.cn/plugin?id=19206
var bluetooth = this.deviceArray[i];
var service = bluetooth.services[j];
var characteristic = service.characteristics[k];
bluetoothcenter.writeData({
deviceId: bluetooth.device.deviceId,
serviceUuid: service.uuid,
characteristicUuid: characteristic.uuid,
value: [0x01, 0xFF], // 要发送的数据
type: 0 // 写类型,仅支持iOS, 0: CBCharacteristicWriteWithResponse 1: CBCharacteristicWriteWithoutResponse
}, (resp) => {
});
- 读数据
var bluetooth = this.deviceArray[i];
var service = bluetooth.services[j];
var characteristic = service.characteristics[k];
bluetoothcenter.readData({
deviceId: bluetooth.device.deviceId,
serviceUuid: service.uuid,
characteristicUuid: characteristic.uuid
}, (resp) => {
});
- 设置mtu,仅支持Android
iOS蓝牙没有MTU,每次发送的数据大小由系统决定,如果数据包过大,自行拆包分段发送
let mtu = 100
UTSBluetoothCenter.setMtu(mtu, (resp)=>{
})
- 蓝牙是否已经打开,仅支持Android
ios蓝牙开启状态的监听在回调的onCentralManagerDidUpdateState里
let isEnabled = UTSBluetoohSlave.isEnable()
- 打开蓝牙,仅支持Android
UTSBluetoohSlave.enable()
- 关闭蓝牙,仅支持Android
UTSBluetoohSlave.disable()
- 设置蓝牙名,仅支持Android
let name = "xxx"
let isSuc = UTSBluetoohSlave.setName(name)
- 跳到蓝牙设置界面,仅支持Android
UTSBluetoohSlave.toBluetoothPage()
- 设置蓝牙可见性,仅支持Android
// 有时候虽然设备的蓝牙和定位权限都打开了,但是扫描不到设备(除非以前配对过)。只有进入蓝牙页面,才能被扫描搜索到。这个就涉及到蓝牙的可见性,为了保护隐私默认是不可见的,需要打开蓝牙可见性,才能被别的设备扫描搜索到
//设置蓝牙可见性的时间,方法本身规定最多可见300秒,会弹出一个确定的窗口
UTSBluetoothCenter.setDiscoverableTime(300)