import * as tools from "./tools" import {inArray, isObject, logs, sleep} from "../util"; import {showToast} from "../app"; import {checkBleAuth} from "../uniFunction"; import {ab2hex, stringToArrayBuffer} from "./hex"; import {isH5} from "@/utils/platform"; import Vue from "vue"; /** * 蓝牙工具类 * 封装小程序蓝牙流程方法 * 处理事件通信 */ export class bleBase { constructor(topClass) { this.topClass = topClass this.typeKey = '' this.option = {} this.deviceId = null this.serviceId = null this.writeId = null // 写入id this.characteristicId = null// 接收id } /** * 搜索蓝牙设备 * @param data * @param op * @param showLoad * @returns {Promise} */ getList(data = {}, op = {}, showLoad = true) { let option = { second: 5000, type: 1, fun: null, } option = Object.assign(option, op) return new Promise(async (resolve, reject) => { logs('进入 searchBle') try { await this.topClass.init() if (isH5) throw 'H5不支持蓝牙功能' await checkBleAuth() // 检查用户蓝牙授权是否通过 if (showLoad) uni.showLoading({title: '搜索设备中。。。'}) await tools._startSearch(Object.assign({ allowDuplicatesKey: true }, data)) let list = await this.bluetoothDeviceFound(option.second, option.type, option.fun) if (showLoad) uni.hideLoading() resolve(Object.values(list)) } catch (msg) { if (showLoad) uni.hideLoading() showToast(msg, 4000) resolve(new Object()) } }) } /** * 过滤并转换附加参数 ok 表示 是否通过过滤 * @param item * @returns item */ filter(item) { item.ok = false if (this.option.top) { let index = item.manufacturerData.search(this.option.top) if (this.option.indexJudge) item.ok = this.option.indexJudge(index) } else { item.ok = true } if (item.ok && this.option.macSlice) item.mac = item.manufacturerData.slice(...this.option.macSlice) if (this.option.search && !inArray(item.mac, this.option.machine)) item.ok = !1 return item } /** * 过滤设备信息 * @param second * @param type 1 普通模式(只过滤是否符合); * 2 指定模式(只有找到一个就会结束,但因为搜索未完全结束可能会返回多个的情况) * 3 无限模式 * @param fun * @returns {Promise} */ bluetoothDeviceFound(second = 5000, type = 1, fun = null) { let list = {} return new Promise(async (resolve, reject) => { try { this.topClass.bleDeviceFound((res) => { res.devices.forEach((item) => { item.manufacturerData = ab2hex(item.advertisData) item = this.filter(item) if (item.ok) { list[item.deviceId] = item if (type == 2) { tools._stopSearchBluetooth(); throw '已找到设备' } else if (type == 3 && fun) { fun({ run: true, data: item, }) } } }) }) if (second > 0) { await sleep(second) throw '搜索结束' } } catch (error) { if (type != 3) { await tools._stopSearchBluetooth(); } else if (type == 3 && fun) { fun({ run: false, }) } this.topClass.bleDeviceFound(null) return resolve(Object.values(list)) } }) } async startSearch(data) { await tools._startSearch(Object.assign({ allowDuplicatesKey: true }, data)) } stopSearch() { /* #ifndef H5 */ tools._stopSearchBluetooth(); /* #endif */ } // 二、 蓝牙连接 根据某一id连接设备,4.0 async connectionBle(deviceId) { try { if (isH5) throw 'H5无法运行' if (this.deviceId && this.deviceId == deviceId) { logs('同一台设备,跳出') return Promise.resolve() // 已连接设备与当前为同一台 } if (this.deviceId && this.deviceId != deviceId) { logs('有旧设备,关闭旧设备中') await this.closeConnection() // 结束前一台 await sleep(500) } this.topClass.addConnect(deviceId, this.typeKey) this.deviceId = deviceId logs('connectBle --- ' + this.deviceId) await tools._connectBlue(this.deviceId) await sleep(2000); await this.getBLEServices(this.option.serviceKey) await this.getCharacteristics(this.option.channelKey) await tools._notifyBLECharacteristicValueChange(this.deviceId, this.serviceId, this.characteristicId) return Promise.resolve() } catch (e) { await this.closeConnection() console.log('connectionBle catch', e) return Promise.reject('连接失败') } } async getBLEServices(serviceKey) { logs('开始蓝牙获取服务') let servicesList = await tools._getBLEServices(this.deviceId) if (!servicesList) throw '链接失败,蓝牙未找到服务号' logs('开始蓝牙获取服务', servicesList) for (let i = 0; i < servicesList.services.length; i++) { if (servicesList.services[i].isPrimary && (servicesList.services[i].uuid.indexOf(serviceKey) != -1)) { this.serviceId = servicesList.services[i].uuid return; } } } async getCharacteristics(channelKey = '') { logs('开始蓝牙通道信息') // 获取通道信息(读、写、监听) let writeKey = '' let notifyKey = '' if (isObject(channelKey)) { writeKey = channelKey.writeKey notifyKey = channelKey.notifyKey } else { writeKey = notifyKey = channelKey } let {characteristics} = await tools._getCharacteristics(this.deviceId, this.serviceId) logs(`开始蓝牙通道信息 writeKey:${writeKey} notifyKey:${notifyKey} characteristics:${characteristics}`) for (let i = 0; i < characteristics.length; i++) { let item = characteristics[i]; if (item.uuid.search(writeKey) != -1) { this.writeId = item.uuid // 写入id } if (item.uuid.search(notifyKey) != -1) { this.characteristicId = item.uuid // 写入id } } logs(`开始蓝牙通道信息 writeId:${this.writeId} characteristicId:${this.characteristicId}`) } /** * 关闭设备连接 * @param deviceId * @returns {Promise} */ async closeConnection(deviceId = '') { if (!deviceId) deviceId = this.deviceId // 断开已连接的连接 try { if (this.deviceId) await tools._closeBLEConnection(deviceId); } catch (e) { } this.deviceId = null this.serviceId = null this.writeId = null this.characteristicId = null this.topClass.delConnect(deviceId) } async sentOrder(str, type = 1) { let buffer = type != 0 ? stringToArrayBuffer(str, type) : str logs("-- 发送数据: ", ab2hex(buffer, ' ')) try { /* #ifndef H5 */ if (this.deviceId) await tools._writeBLECharacteristicValue(this.deviceId, this.serviceId, this.writeId, buffer) /* #endif */ return true } catch (error) { if (error.errCode == 10006) { this.topClass.delConnect(this.deviceId, this.typeKey) } console.error(error) logs(`发送出错 基本信息 deviceId:${this.deviceId}, serviceId:${this.serviceId}, writeId:${this.writeId}`) logs(error) } } }