// 此次 serviceId characteristicId notifyId 是固定值,可以直接写在data中,如不是需要动态获取
// deviceId 需要在 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获
// serviceId 需要在 getBLEDeviceServices 接口中获取
// characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
let bluetoothData = {
devices: [], //搜索到的蓝牙设备列表
chs: [],
linkDevice: false, // 是否已经连接到当前设备
isWrite: false, //是否写入成功
deviceId: '',
serviceId: '0000000000000000000000000000',
characteristicId: '111111111111111111111111', // 特征值
notifyId: '333333333333333333333333333', // notifyId
_discoveryStarted: false,
canWrite: false, // 当前设备是否可写入
}
let timmer // 定时器
//linkData 连接当前蓝牙设备的标志, command 发送的蓝牙指令
function opereatBle(linkData, command) {
return new Promise((resolve, reject) => {
openBluetoothAdapter()
// 初始化蓝牙设备
function openBluetoothAdapter() {
wx.openBluetoothAdapter({
success: (res) => {
startBluetoothDevicesDiscovery() // 开始扫描
},
fail: (res) => {
console.log(res)
if (res.errCode === 10001) { // 10001 当前蓝牙适配器不可用
resolve(false)
}
}
})
}
// 开始扫描
function startBluetoothDevicesDiscovery() {
console.log('bluetoothData._discoveryStarted,', bluetoothData._discoveryStarted)
if (bluetoothData._discoveryStarted) {
return
}
bluetoothData._discoveryStarted = true
// 开始搜索附件的蓝牙设备
wx.startBluetoothDevicesDiscovery({
allowDuplicatesKey: true,
success: (res) => {
console.log('开始搜索附件的蓝牙设备', res)
onBluetoothDeviceFound() // 监听搜索到新设备的事件
},
})
timmer = setTimeout(() => {
console.log('===10 秒自动停止扫描===,扫描到当前设备蓝牙信息?', bluetoothData.linkDevice)
stopBluetoothDevicesDiscovery()
wx.offBluetoothDeviceFound()
closeBluetoothAdapter()
if (!bluetoothData.linkDevice|| !bluetoothData.isWrite) {
console.log('10s没有连接到当前设备,结束流程')
resolve(false)
}
}, 10000);
}
// 停止所寻附近的蓝牙设备
function stopBluetoothDevicesDiscovery() {
console.log('停止扫描')
wx.stopBluetoothDevicesDiscovery()
}
// 监听搜索到新设备的事件
function onBluetoothDeviceFound() {
wx.onBluetoothDeviceFound((res) => {
// console.log(res, 'res')
res.devices.forEach(device => {
if (!device.name && !device.localName) {
return
}
const foundDevices = bluetoothData.devices
foundDevices.push(device)
bluetoothData.devices = foundDevices
bluetoothData.devices.forEach(item => {
if (ab2str(item.advertisData) == linkData) {
// console.log(ab2str(item.advertisData), linkData, '扫描到当前设备')
createBLEConnection(item) // 连接蓝牙设备
bluetoothData.linkDevice= true // 连接到设备
stopBluetoothDevicesDiscovery() // 连接到设备后,停止继续扫描
wx.offBluetoothDeviceFound() //取消监听
}
})
})
})
}
// 连接蓝牙低功耗设备
function createBLEConnection(e) {
console.log(e, '=====连接蓝牙低功耗设备=====')
const deviceId = e.deviceId
const name = e.name
// 连接蓝牙低功耗设备
wx.createBLEConnection({
deviceId,
success: (res) => {
bluetoothData.connected = true
bluetoothData.name = name
bluetoothData.deviceId = deviceId
getBLEDeviceCharacteristics(bluetoothData.deviceId, bluetoothData.serviceId) // 监听特征值数据
}
})
stopBluetoothDevicesDiscovery() // 停止搜索蓝牙设备
}
// 关闭连接
function closeBLEConnection() {
console.log('关闭连接')
wx.closeBLEConnection({
deviceId: bluetoothData.deviceId
})
bluetoothData.connected = false
bluetoothData.chs = []
bluetoothData.canWrite = false
}
// 获取蓝牙低功耗设备某个服务中所有特征
function getBLEDeviceCharacteristics(deviceId, serviceId) {
wx.getBLEDeviceCharacteristics({
deviceId,
serviceId,
success: (res) => {
console.log('获取蓝牙某个服务的所有特征')
let data = res.characteristics.find(item => item.properties.write)
console.log('已保存读写特征值', data)
if (data) {
bluetoothData.canWrite = true
}
wx.notifyBLECharacteristicValueChange({
// 启用蓝牙低功耗设备特征值变化时的 notify 功能,
deviceId, // 蓝牙设备 id
serviceId, // 蓝牙特征对应服务的 UUID
characteristicId: bluetoothData.notifyId, // 蓝牙特征的 UUID
//characteristicId :固定值直接写入,动态值需要在getBLEDeviceCharacteristics 接口中获取
state: true, // 是否启用 notify
success(res) {
console.log('获取特征')
writeBLECharacteristicValue(command) //写入指令
wx.onBLECharacteristicValueChange(function (res) {
resolve(true)
bluetoothData.isWrite = true //写入成功
closeBLEConnection() // 写入完成,断开连接
wx.offBluetoothDeviceFound() //停止监听
closeBluetoothAdapter() // 结束流程
clearTimeout(timmer) // 写入完成,停止定时器
})
}
})
},
fail(res) {
console.error('getBLEDeviceCharacteristics', res)
}
})
}
// 向蓝牙低功耗设备特征值中写入二进制数据
function writeBLECharacteristicValue(carValue) {
console.log('开始写入数据')
// 向蓝牙设备发送一个0x00的16进制数据
let _Buffer = string2buffer(carValue)
let Num = 0;
let ByteLength = _Buffer.byteLength;
// 发送指令超过20字节,需要分包写入数据
while (ByteLength > 0) {
let TmpBuffer;
if (ByteLength > 20) {
return Delayed(0.25).then(() => {
TmpBuffer = _Buffer.slice(Num, Num + 20);
Num += 20;
ByteLength -= 20;
wx.writeBLECharacteristicValue({
deviceId: bluetoothData.deviceId,
serviceId: bluetoothData.serviceId,
characteristicId: bluetoothData.characteristicId,
value: TmpBuffer,
success(res) {
console.log('第一次写入', res)
if (ByteLength) {
writeBLECharacteristicValue(carValue.slice(Num))
}
}
})
})
} else {
return Delayed(0.25).then(() => {
TmpBuffer = _Buffer.slice(Num, Num + ByteLength);
Num += ByteLength;
ByteLength -= ByteLength;
wx.writeBLECharacteristicValue({
deviceId: bluetoothData.deviceId,
serviceId: bluetoothData.serviceId,
characteristicId: bluetoothData.characteristicId,
value: TmpBuffer,
success(res) {
console.log('第二次写入', res)
}
})
})
}
}
}
// 关闭蓝牙模块
function closeBluetoothAdapter() {
// console.log('关闭蓝牙模块')
wx.closeBluetoothAdapter()
bluetoothData._discoveryStarted = false
}
})
}
// ArrayBuffer转字符串实例
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint8Array(buf));
}
function string2buffer(str) {
// 首先将字符串转为16进制
let val = ""
for (let i = 0; i < str.length; i++) {
if (val === '') {
val = str.charCodeAt(i).toString(16)
} else {
val += ',' + str.charCodeAt(i).toString(16)
}
}
let endStr = val + '0d,0a' // 0d,0a => /r , /n
// 将16进制转化为ArrayBuffer
return new Uint8Array(endStr.match(/[\da-f]{2}/gi).map(function (h) {
return parseInt(h, 16)
})).buffer
}
//分包延迟定时器
function Delayed(ms, res) {
return new Promise(function (Resolve, Reject) {
setTimeout(function () {
Resolve(res);
}, ms);
});
}
export {
opereatBle
}
页面使用:
import { opereatBle } from "./opereatBle.js"; // 引入
opereatBle(xxxx, xxxx, ).then(res=>{
if(res){
......
console.log('success')
}else{
......
console.log('failure')
}
})