更新记录
1.0.4(2025-05-25)
- 优化代码
1.0.3(2025-05-25)
- 优化
1.0.2(2025-05-24)
- 修复iOS在高版本HB的编译兼容性问题
平台兼容性
uni-app
Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
---|---|---|---|---|---|---|---|---|
√ | √ | - | - | - | - | 4.4 | 12 | - |
微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 快应用-华为 | 快应用-联盟 |
---|---|---|---|---|---|---|---|---|---|---|
× | × | × | × | × | × | - | × | × | × | × |
uni-app x
Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
---|---|---|---|---|---|
- | - | 5.0 | 12 | - | × |
蓝牙外围设备从设备广播servicecharacteristic通讯
功能
- 广播蓝牙数据,可以广播蓝牙名、serviceUuid、serviceDataUuid、serviceData、发射功率、厂家参数(ID和数据)、广播功率、是否可连接、持续时间
- 蓝牙数据通讯,增加删除service,characteristic读写
蓝牙分为中心设备(Central、Master、主设备、客户端)和外围设备(Peripheral、Slave、从设备、服务端) 手机做为客户端可以连接多个蓝牙设备,所以手机又可以叫中心设备(Central),蓝牙设备叫外围设备(Peripheral)。 例如:通过手机蓝牙开启共享单车,手机称为中心设备,共享单车称为外围设备
本插件是外围设备(Peripheral、Slave、从设备、服务端)
中心设备蓝牙请使用插件https://ext.dcloud.net.cn/plugin?name=wrs-uts-bluetoothcenter
集成步骤
接口
import {
UTSBluetoohSlave
} from "@/uni_modules/wrs-uts-bluetoothslave"
let slave = new UTSBluetoohSlave()
- 设置回调
slave.setCallback((resp) => {
this.showMsg(JSON.stringify(resp))
let opt = resp.opt
switch (opt) {
// 广播开启成功
case "onStartSuccess": {
this.showMsg("广播成功")
// 广播成功后添加service,添加了service这样客户端蓝牙才能连接通讯
this.addService()
}
break;
// 广播失败
case "onStartFailure": {
// 1: ADVERTISE_FAILED_DATA_TOO_LARGE
// 2: ADVERTISE_FAILED_TOO_MANY_ADVERTISERS
// 3: ADVERTISE_FAILED_ALREADY_STARTED
// 4: ADVERTISE_FAILED_INTERNAL_ERROR
// 5: ADVERTISE_FAILED_FEATURE_UNSUPPORTED
// 18: 广播数据包太大,不同手机品牌支持的大小不一样
// 如果有其他错误码,可以百度搜索"android AdvertiseCallback onStartFailure ${errorCode}"
let errorCode = resp.errorCode
this.showMsg("广播失败:" + JSON.stringify(resp))
}
break;
// 蓝牙连接状态变化
case "onConnectionStateChange": {
var status = resp.status;
var newState = resp
.newState; // 0: STATE_DISCONNECTED 1: STATE_CONNECTING 2: STATE_CONNECTED 3: STATE_DISCONNECTING
if (status == 0) { // 成功
if (newState == 2) { // 连接成功
this.showMsg("收到新蓝牙连接成功 name:" + resp.device.name + " mac:" + resp.device
.address)
} else if (newState == 0) { // 断开连接
this.showMsg("蓝牙断开连接")
} else if (newState == 1) { // 连接中
this.showMsg("蓝牙连接中")
} else if (newState == 3) { // 断开中
this.showMsg("蓝牙断开中")
}
} else { // 出错
this.showMsg("蓝牙出错")
}
}
break;
case "onServiceAdded": {
var status = resp.status;
if (status == 0) { // 添加成功
} else { // 添加失败
}
}
break;
// 收到客户端特征值读取请求
case "onCharacteristicReadRequest": {
this.showMsg("收到客户端特征值读取请求")
let params = {}
params.status = 0
params.address = resp.device.address
params.requestId = resp.requestId
params.offset = resp.offset
params.value = resp.characteristic.value
let suc = slave.sendResponse(params)
if (suc) {
this.showMsg("发送响应数据成功:" + params.value)
} else {
this.showMsg("发送响应数据失败")
}
}
break;
// 收到客户端特征值写入数据,即:收到对方发来的蓝牙数据
case "onCharacteristicWriteRequest": {
this.showMsg("收到对方发来的蓝牙数据:" + JSON.stringify(resp))
// {
// "characteristic": {
// "properties": 26,
// "value": [2, 6, -1],
// "uuid": "0000ff11-0000-1000-8000-00805f9b34fb",
// "permissions": 17,
// "writeType": 2,
// "instanceId": 43
// },
// "preparedWrite": false,
// "offset": 0,
// "device": {
// "bluetoothClass": {
// "majorDeviceClass": 0
// },
// "address": "46:82:6D:75:9A:EA",
// "type": 0,
// "bondState": 10
// },
// "requestId": 2,
// "value": [2],
// "responseNeeded": true,
// "opt": "onCharacteristicWriteRequest"
// }
//
let responseNeeded = resp.responseNeeded
if (responseNeeded) {
let params = {}
params.address = resp.device.address
params.requestId = resp.requestId
params.status = 0 // 0: GATT_SUCCESS
params.offset = resp.offset
params.value = resp.value
// 响应客户端,即:告诉对方蓝牙这边已经收到数据了
let respSuc = slave.sendResponse(params)
if (!respSuc) {
this.showMsg("sendResponse失败")
} else {
this.showMsg("响应客户端:" + params.value)
}
}
// 这里模拟数据处理业务,处理完成后发送处理结果给对方蓝牙,即:发数据客户端
setTimeout(() => {
let sendParams = {}
sendParams.address = resp.device.address
sendParams.serviceUuid = this.UUID_SERVICE
sendParams.characteristicUuid = resp.characteristic.uuid
sendParams.value = [0x01, 0x02, 0xFF]
slave.sendData(sendParams)
this.showMsg("发送数据给对方:"+ sendParams.value)
}, 2000);
}
break;
// 收到客户端描述读取请求,仅支持Android
case "onDescriptorReadRequest": {
this.showMsg("收到客户端描述读取请求")
let params = {}
params.address = resp.device.address
params.requestId = resp.requestId
params.offset = resp.offset
params.status = 0
params.value = resp.characteristic.value
let suc = slave.sendResponse(params)
if (suc) {
this.showMsg("发送响应数据成功")
} else {
this.showMsg("发送响应数据失败")
}
}
break;
// 收到描述写入数据,仅支持Android
case "onDescriptorWriteRequest": {
this.showMsg("收到描述写入数据")
let params = {}
params.status = 0
params.address = resp.device.address
params.requestId = resp.requestId
params.offset = resp.offset
params.value = resp.characteristic.value
let suc = slave.sendResponse(params)
if (suc) {
this.showMsg("发送响应数据成功")
} else {
this.showMsg("发送响应数据失败")
}
}
break;
// 仅支持Android
case "onExecuteWrite": {
}
break;
// 仅支持Android
case "onNotificationSent": {
}
break;
// 仅支持Android
case "onMtuChanged": {
}
break;
case "onPhyUpdate": {
// 仅支持Android
}
break;
// 仅支持Android
case "onPhyRead": {
}
break;
default:
break;
}
})
- 初始化蓝牙
var params = {};
if (this.isAndroid) {
} else {
params.CBCentralManagerOptionShowPowerAlertKey = true;
}
// 初始化,仅支持iOS
slave.initBluetooth(params);
- 广播蓝牙 android的蓝牙广播数据包大小不同机型大小不一样 广播结果在回调接口里slave.setCallback((resp) => {}) => onStartSuccess、onStartFailure
// ios仅支持localName和advertiseData.serviceUuid
let params = {}
// 仅支持ios,ios需要将localName蓝牙名放到广播里,不然扫描不到蓝牙名
params.localName = this.name
// 仅支持Android,设置广播模式,以控制广播的功率和延迟
// 0: ADVERTISE_MODE_LOW_POWER
// 1: ADVERTISE_MODE_BALANCED
// 2: ADVERTISE_MODE_LOW_LATENCY
params.advertiseMode = 2
//仅支持Android,发射功率级别
// 0: ADVERTISE_TX_POWER_ULTRA_LOW
// 1: ADVERTISE_TX_POWER_MEDIUM
// 2: ADVERTISE_TX_POWER_MEDIUM
// 3: ADVERTISE_TX_POWER_HIGH
params.txPowerLevel = 3
// 仅支持Android,设置是否可以连接
params.connectable = true
params.advertiseData = {
// includeDeviceName: true, // 仅支持Android
// includeTxPowerLevel: true, // 仅支持Android
// serviceUuid: [this.UUID_SERVICE],// 支持iOS和Android
manufacturerData: [{ // 仅支持Android
id: 1,
data: [0x01, 0x22]
}],
// serviceData:[ // 仅支持Android
// {
// uuid: this.UUID_SERVICE,
// data: [0x01, 0x22]
// },
// {
// uuid: this.UUID_SERVICE2,
// data: [0x01, 0x22]
// }
// ]
}
// 仅支持Android,
// params.scanResponse = {
// includeDeviceName: true,
// includeTxPowerLevel: true,
// manufacturerData: [{
// id: 1,
// data: [0x01, 0x22]
// }]
// }
slave.startAdvertising(params)
- 停止广播
slave.stopAdvertising()
- 开启从设备蓝牙服务,服务启动后添加service和characteristic,仅支持Android
let suc = slave.openGattServer()
- 清除service
slave.clearServices()
- 添加service
// android、ios属性 properties
// 1: PROPERTY_BROADCAST
// 2: PROPERTY_READ
// 4: PROPERTY_WRITE_NO_RESPONSE
// 8: PROPERTY_WRITE
// 16: PROPERTY_NOTIFY
// 32: PROPERTY_INDICATE
// 64: PROPERTY_SIGNED_WRITE
// 128: PROPERTY_EXTENDED_PROPS
var permissions = 0x01 | 0x10;
var value = null;
if (this.isAndroid) {
// 权限permissions
// android permissions:
// 1: PERMISSION_READ
// 2: PERMISSION_READ_ENCRYPTED
// 4: PERMISSION_READ_ENCRYPTED_MITM
// 16: PERMISSION_WRITE
// 32: PERMISSION_WRITE_ENCRYPTED
// 64: PERMISSION_WRITE_ENCRYPTED_MITM
// 128: PERMISSION_WRITE_SIGNED
// 256:PERMISSION_WRITE_SIGNED_MITM
permissions = 0x01 | 0x10;
value = [0x02, 0x06, 0xFF]
// descriptors = [{ // 描述
// uuid: this.NotificationDescriptorUUID,
// permissions: 0x01 |
// 0x10, // 仅对Android生效,0x01: PERMISSION_READ 0x10:PERMISSION_WRITE
// value: [0x02, 0x06, 0xFF]
// }];
} else {
// ios permissions:
// 0x01: CBAttributePermissionsReadable
// 0x02: CBAttributePermissionsWriteable
// 0x04: CBAttributePermissionsReadEncryptionRequired
// 0x08: CBAttributePermissionsWriteEncryptionRequired
permissions = 0x01 | 0x02;
}
let services = []
services.push({
uuid: this.UUID_SERVICE, // service的UUID
type: 0, // 0: SERVICE_TYPE_PRIMARY 1: SERVICE_TYPE_SECONDARY
characteristics: [{ // 读写特征
uuid: this.UUID_CHARACTERISTIC,
properties: 0x08 |
0x10, // 0x08: PROPERTY_WRITE 0x10: PROPERTY_NOTIFY 0x02: PROPERTY_READ
permissions: permissions,
value: value // ios下,如果要给characteristic只能是只读状态下才能赋值
}
// { // 只读特征
// uuid: this.UUID_CHARACTERISTIC2,
// properties: 0x02, // 0x08: PROPERTY_WRITE 0x10: PROPERTY_NOTIFY 0x02: PROPERTY_READ
// permissions: 0x01, // 0x10: PERMISSION_WRITE 0x01: PERMISSION_READ
// value: [0x01, 0x06, 0xFF]
// }
]
})
let suc = slave.addService(services)
if (!suc) {
this.showMsg("addService 失败")
} else {
this.showMsg("addService 成功")
}