import {Result} from '../constant' /** * @typedef {Object} err * @property {number} errno - 错误代码 * @property {number} errCode - 错误代码 * @property {String} errMsg - 错误信息 */ // 查找设备并连接 export function searchAndConnectDevice(name, reset = true) { // 循环查找设备 let timer // 超时计时器 let timeoutTimer return new Promise(async resolve => { const result = await startBluetoothDevicesDiscovery() if (result.code === Result.Success.code) { let searchFlag = false timeoutTimer = setTimeout(async () => { await stopBluetoothDevicesDiscovery() clearInterval(timer) if (!searchFlag) { resolve(Result.NotAvailableWeChatNearbyDevicesEmpty) } else { resolve(Result.Fail) } }, 10500) timer = setInterval(async () => { const queryResult = await getBluetoothDevices() if (queryResult.code === Result.Success.code) { const deviceList = queryResult.data if (searchFlag === false && deviceList.length > 0) { searchFlag = true } for (let i = 0; i < deviceList.length; i++) { if (deviceList[i]?.name === name) { const uuid = deviceList[i]?.advertisServiceUUIDs[0] if (uuid && uuid.slice(2, 8) === '758824') { await stopBluetoothDevicesDiscovery() clearTimeout(timeoutTimer) clearInterval(timer) if (uuid.slice(30, 32) === '00' && reset) { resolve(Result.DeviceHasBeenReset) } else { const connectResult = await createBLEConnection(deviceList[i].deviceId) resolve(connectResult) } break } if (uuid && uuid.slice(0, 2) === '75') { await stopBluetoothDevicesDiscovery() clearTimeout(timeoutTimer) clearInterval(timer) if (uuid.slice(4, 6) === '00' && reset) { resolve(Result.DeviceHasBeenReset) } else { const connectResult = await createBLEConnection(deviceList[i].deviceId) resolve(connectResult) } break } } } } else { resolve(queryResult) } }, 1000) } else { resolve(result) } }) } // 蓝牙操作报错处理 async function handleError(err, event) { if (err.errCode === 10000) { const result = await openBluetoothAdapter() if (result.code === Result.Success.code) { return await event() } return result } if (err.errCode === 10001) { if (err.state === 3) { return Result.NotAvailableWeChatBluetoothPermission } return Result.NotAvailableBluetooth } if (err.errno === 3) { return Result.NotAvailableWeChatNearbyDevicesPermission } if (err.errno === 103) { return Result.NotAvailableBluetoothPermission } if (err.errno === 1509008) { return Result.NotAvailableWeChatLocationPermission } if (err.errMsg === 'openBluetoothAdapter:fail already opened') { return Result.Success } return Result.Fail } // 初始化蓝牙模块 function openBluetoothAdapter() { return new Promise(resolve => { uni.openBluetoothAdapter({ success() { resolve(Result.Success) }, async fail(err) { resolve(await handleError(err)) } }) }) } // 关闭蓝牙模块 export function closeBluetoothAdapter() { uni.closeBluetoothAdapter() } // 移除蓝牙适配器的全部监听 export function offBluetoothAdapterStateChange() { uni.offBluetoothAdapterStateChange() } // 监听蓝牙特征值改变 export function onBLECharacteristicValueChange(callback) { uni.onBLECharacteristicValueChange(res => { callback(res) }) } // 开始搜索附近的蓝牙设备 export function startBluetoothDevicesDiscovery() { return new Promise(resolve => { uni.startBluetoothDevicesDiscovery({ success() { resolve(Result.Success) }, async fail(err) { resolve(await handleError(err, startBluetoothDevicesDiscovery)) } }) }) } // 获取所有已发现的蓝牙设备 export function getBluetoothDevices() { return new Promise(resolve => { uni.getBluetoothDevices({ success(res) { resolve(new Result(Result.Success.code, res.devices)) }, async fail(err) { resolve(await handleError(err, getBluetoothDevices)) } }) }) } // 停止搜索附近的蓝牙设备 export function stopBluetoothDevicesDiscovery() { return new Promise(resolve => { uni.stopBluetoothDevicesDiscovery({ success() { resolve(Result.Success) }, async fail(err) { resolve(await handleError(err)) } }) }) } // 连接低功耗蓝牙设备 export function createBLEConnection(deviceId, reconnectNumber = 0) { return new Promise(resolve => { uni.createBLEConnection({ deviceId, timeout: 10000, async success() { const res = await getBLEDeviceServicesAndCharacteristics(deviceId) await notifyBLECharacteristicValueChange( deviceId, res.data.serviceId, res.data.notifyCharacteristicId ) // 使用同步方法获取系统信息 const systemInfo = uni.getSystemInfoSync(); if (systemInfo.platform === 'android') { // 如果是Android机型,则设置BLE MTU uni.setBLEMTU({ deviceId: deviceId, mtu: 512, fail: res => { // console.log('mtu fail', res); }, success: res => { // console.log('mtu success', res); } }); } else { // 对于非Android设备,可以在这里添加其他逻辑或者直接忽略 // console.log('当前设备不是Android,跳过设置BLE MTU'); } resolve(res) }, async fail(err) { if (err.errno === 1509007) { const res = await getBLEDeviceServicesAndCharacteristics(deviceId) await notifyBLECharacteristicValueChange( deviceId, res.data.serviceId, res.data.notifyCharacteristicId ) resolve(res) } else if (err.errno === 1509001 && reconnectNumber < 1) { resolve(Result.Fail) } else if (reconnectNumber < 1) { resolve(await createBLEConnection(deviceId, reconnectNumber + 1)) } else { resolve(Result.Fail) } } }) }) } // 获取服务及对应特征值 async function getBLEDeviceServicesAndCharacteristics(deviceId) { const {code, data} = await getBLEDeviceServices(deviceId) if (code === Result.Success.code) { const {serviceId} = data const { code, data: {notifyCharacteristicId, writeCharacteristicId} } = await getBLEDeviceCharacteristics(deviceId, serviceId) if (code === Result.Success.code) { return new Result(Result.Success.code, { deviceId, serviceId, notifyCharacteristicId, writeCharacteristicId }) } return Result.Fail } return Result.Fail } // 获取设备的服务 function getBLEDeviceServices(deviceId) { return new Promise(resolve => { uni.getBLEDeviceServices({ deviceId, success(res) { let serviceId for (let i = 0; i < res.services.length; i++) { if (res.services[i].uuid.indexOf('FFF0') !== -1) { serviceId = res.services[i].uuid } } if (!serviceId) { resolve(Result.Fail) return } resolve(new Result(Result.Success.code, {serviceId})) }, fail() { resolve(Result.Fail) } }) }) } // 获取服务的特征值 function getBLEDeviceCharacteristics(deviceId, serviceId) { return new Promise(resolve => { uni.getBLEDeviceCharacteristics({ deviceId, serviceId, success(res) { let notifyCharacteristicId let writeCharacteristicId for (let i = 0; i < res.characteristics.length; i++) { const characteristic = res.characteristics[i] if (characteristic.properties.notify) { notifyCharacteristicId = characteristic.uuid } if (characteristic.properties.write) { writeCharacteristicId = characteristic.uuid } } if (notifyCharacteristicId && writeCharacteristicId) { resolve( new Result(Result.Success.code, {notifyCharacteristicId, writeCharacteristicId}) ) } else { resolve(Result.Fail) } }, fail() { resolve(Result.Fail) } }) }) } // 订阅特征值 function notifyBLECharacteristicValueChange(deviceId, serviceId, characteristicId) { return new Promise(resolve => { uni.notifyBLECharacteristicValueChange({ deviceId, serviceId, characteristicId, state: true, success() { resolve(Result.Success) }, fail() { resolve(Result.Fail) } }) }) } // 断开与低功耗蓝牙设备的连接 export function closeBLEConnection(deviceId) { return new Promise(resolve => { uni.closeBLEConnection({ deviceId, success() { console.log('断开连接成功') resolve(Result.Success) }, fail() { console.log('断开连接失败') resolve(Result.Fail) } }) }) } // 写入特征值 export function writeBLECharacteristicValue(deviceId, serviceId, characteristicId, binaryData) { return new Promise(resolve => { const count = Math.ceil(binaryData.length / 20) let successCount = 0 for (let i = 0; i < count; i++) { const writeData = binaryData.slice(i * 20, i === count - 1 ? binaryData.length : (i + 1) * 20) uni.writeBLECharacteristicValue({ deviceId, serviceId, characteristicId, value: writeData.buffer, success(res) { successCount++ if (successCount === count) { resolve(Result.Success) } console.log("writeBLECharacteristicValue res", res) }, fail(err) { console.error("writeBLECharacteristicValue err", err) resolve(Result.Fail) } }) } }) }