import Taro from "@tarojs/taro"; import { handshake1, handshake2 } from "./sendOrder"; import TASK from "./taskQueue"; const errMsg = { 0: "正常", 10000: "未初始化蓝牙适配器", 10001: "请检查手机蓝牙是否打开或微信是否授权蓝牙", 10002: "没有找到指定设备", 10003: "连接失败", 10004: "没有找到指定服务", 10005: "没有找到指定特征", 10006: "当前连接已断开", 10007: "当前特征不支持此操作", 10008: "其余所有系统上报的异常", 10009: "Android系统版本低于4.3不支持蓝牙功能", 10012: "连接超时", 10013: "连接超时", 1509008: "请检查手机定位是否打开或微信是否授权定位", }; class Bluetooth { config = { serviceId: "4E31BF4A-8507-3A2B-7344-C7EDACD38104", //设备服务id NotifyUUID: "4E31BF4B-8507-3A2B-7344-C7EDACD38104", WriteUUID: "4E31BF4C-8507-3A2B-7344-C7EDACD38104", // serviceId: 'C7E6FAE0-E966-1000-8000-BEF9C723DF6A', //设备服务id // NotifyUUID: 'C7E6FAE1-E966-1000-8000-BEF9C723DF6A', // WriteUUID: 'C7E6FAE2-E966-1000-8000-BEF9C723DF6A', }; // 连接状态 linkFlag = false; // 蓝牙是否可用 available = true; // 蓝牙初始化 isInit = false; timeout = null; timeout1 = null; // 判断是否搜索到设备 isFindBt = null; platform = Taro.getSystemInfoSync().platform; appAuthorize = Taro.getAppAuthorizeSetting(); deviceInfo = {} callBack = () => { }; searchBack = () => { }; constructor() { this.onBluetoothAdapterStateChange(); this.onBLEConnectionStateChange(); this.onBluetoothDeviceFound(); } // 错误 fail(res) { this.linkFlag = false; if (!res.errCode) return; let starIde = res.errMsg.indexOf("fail") + 5; Taro.showToast({ title: errMsg[res.errCode] || errMsg[res.errno] || res.errMsg.substring(starIde), icon: "none", duration: 3000 }); } // 监测手机蓝牙状态 onBluetoothAdapterStateChange() { Taro.onBluetoothAdapterStateChange(({ available, discovering }) => { this.available = available; // 手机蓝牙开启 if (this.available && !this.isInit) { Taro.closeBluetoothAdapter({ success: (res) => { this.openBluetoothAdapter(); }, }); console.log("手机蓝牙开启"); } // 手机蓝牙关闭 if (!available) { this.isInit = false; this.deviceInfo.state = false; this.linkFlag = false; this.callBack(this.deviceInfo); console.log("手机蓝牙关闭"); } }); } // 初始化蓝牙模块 openBluetoothAdapter() { return Taro.openBluetoothAdapter({ success: () => { console.log("初始化蓝牙模块"); this.isInit = true; this.deviceInfo = Taro.getStorageSync('deviceInfo') || {} if (this.deviceInfo.name) { this.createBleConnection() } }, fail: (err) => { this.isInit = false; this.fail(err); }, }); } // 开始搜寻附近的蓝牙外围设备 startBluetoothDevicesDiscovery() { console.log("搜索蓝牙"); if (this.appAuthorize.locationAuthorized != "authorized" && this.platform == "android") return Taro.showToast({ title: "请打开微信定位权限", icon: "none", duration: 3000 }); Taro.startBluetoothDevicesDiscovery({ // allowDuplicatesKey: true, powerLevel: "high", success: (res) => { this.isFindBt = setTimeout(() => { if (this.platform == "android") { this.stopBluetoothDevicesDiscovery(); Taro.showModal({ title: "未搜索到设备", content: "1、请检查设备是否在附近,或者设备是否被其他应用连接。2、请检查手机微信应用权限中的‘附近的设备权限’是否打开。", showCancel: false, success: () => { const pages = Taro.getCurrentPages(); if (pages?.length > 1) { Taro.navigateBack(); } }, }); } console.log("未搜索到设备"); this.isFindBt && this.clearTimeoutFn("isFindBt"); }, 6000); }, fail: (err) => { this.fail(err); this.stopBluetoothDevicesDiscovery(); }, }); } // 监听搜索到新设备的事件 // 定义一个方法用于处理蓝牙设备发现事件 onBluetoothDeviceFound(fn) { Taro.onBluetoothDeviceFound((res) => { const devices = res.devices[0]; const advertisData = this.ab2hex(devices.advertisData); const mac = this.strInsert(String(advertisData).substring(4, 16)).toLocaleUpperCase(); // 判断是否有搜索到设备 this.isFindBt && this.clearTimeoutFn("isFindBt"); // if (devices.name && devices.name == "W53A") { if (devices.name && devices.name == "LE-AB2020") { console.log(JSON.stringify(res), "搜索到设备"); const item = { deviceId: devices.deviceId, mac: mac, name: devices.name, }; fn && fn(item) } }); } // 蓝牙连接 createBleConnection() { if (!this.available || this.linkFlag) return; this.linkFlag = true; Taro.setStorageSync("deviceInfo", this.deviceInfo); console.log("正在连接设备"); Taro.createBLEConnection({ timeout: 3000, deviceId: this.deviceInfo.deviceId, success: () => { this.deviceInfo.state = true; this.getBLEDeviceServices(); // this.getBLEDeviceCharacteristics(); }, fail: (res) => { this.linkFlag = false; console.log(res, this.deviceInfo, "连接错误"); this.callBack({ ...this.deviceInfo, errCode: 10003 }); if (!this.deviceInfo.deviceId) return this.timeout && this.clearTimeoutFn("timeout"); if (this.timeout) return; if (res.errno == "1509007") { this.closeBluetoothAdapter(); } else { this.timeout = setTimeout(() => { this.timeout && this.clearTimeoutFn("timeout"); this.createBleConnection(); }, 10000); } }, }); } // 获取蓝牙多个service getBLEDeviceServices() { Taro.getBLEDeviceServices({ deviceId: this.deviceInfo.deviceId, success: (res) => { console.log(JSON.stringify(res), 'JSON.stringify(res)'); this.getBLEDeviceCharacteristics(); }, fail: (err) => this.fail(err), }); } // 获取蓝牙低功耗设备某个服务中所有特征 getBLEDeviceCharacteristics() { Taro.getBLEDeviceCharacteristics({ deviceId: this.deviceInfo.deviceId, serviceId: this.config.serviceId, success: (res) => { this.notifyBLECharacteristicValueChange(); }, fail: (err) => this.fail(err), }); } // 启用蓝牙低功耗设备特征值变化时的 notify 功能 notifyBLECharacteristicValueChange() { Taro.notifyBLECharacteristicValueChange({ deviceId: this.deviceInfo.deviceId, serviceId: this.config.serviceId, characteristicId: this.config.NotifyUUID, state: true, success: (res) => { console.log("连接成功"); Taro.setStorageSync("deviceInfo", { ...this.deviceInfo, state: false }); // handshake1() this.callBack(this.deviceInfo); }, fail: (err) => this.fail(err), }); } //监听设备返回的数据 onBLECharacteristicValueChange(fn) { Taro.onBLECharacteristicValueChange((data) => { let bytes = new Uint8Array(data.value); let value = String(this.ab2hex(bytes)).toLocaleUpperCase(); // 第二次握手 // if (bytes[2] == 0xea && bytes[3] == 0x01) { // handshake2() // } console.log(`设备回复====>${value}`); TASK.executeTask(); fn && fn(bytes, value); }); } // 向蓝牙写入数据 writeBleValue(value) { console.log("发送指令====>" + String(this.ab2hex(value)).toLocaleUpperCase()); if (!this.deviceInfo.state) { // console.log("蓝牙未连接") return } return Taro.writeBLECharacteristicValue({ deviceId: this.deviceInfo.deviceId, serviceId: this.config.serviceId, characteristicId: this.config.WriteUUID, writeType: "writeNoResponse", value: value, }); } //蓝牙断开 onBLEConnectionStateChange() { Taro.onBLEConnectionStateChange((res) => { if (!res.connected) { console.log(res, "蓝牙断开"); this.deviceInfo.state = res.connected; this.callBack(this.deviceInfo); this.linkFlag = false; if (!this.available || this.timeout || !this.isInit || !this.deviceInfo.deviceId) return; this.timeout = setTimeout(() => { this.timeout && this.clearTimeoutFn("timeout"); this.createBleConnection(); }, 1000); } }); } //停止搜寻附近的蓝牙外围设备 stopBluetoothDevicesDiscovery() { Taro.stopBluetoothDevicesDiscovery(); this.isFindBt && this.clearTimeoutFn("isFindBt"); console.log("停止搜寻"); } // 断开与蓝牙低功耗设备的连接 closeBluetoothAdapter() { this.linkFlag = false; this.deviceInfo = { state: false }; wx.removeStorageSync("deviceInfo"); Taro.closeBluetoothAdapter({ success: (res) => { console.log(this.deviceInfo, '解绑1'); this.callBack(this.deviceInfo); this.openBluetoothAdapter() }, }); } // 设备响应回调 deviceCallBack(fn) { this.callBack = fn; } // 转换二进制数据 ab2hex(buffer) { if (!buffer) return; const hexArr = Array.prototype.map.call(new Uint8Array(buffer), function (bit) { return ("00" + bit.toString(16)).slice(-2); }); return hexArr.join("").toLocaleLowerCase(); } // unBindDevice() { // this.deviceInfo = {} // wx.removeStorageSync('deviceInfo') // this.closeBluetoothAdapter() // } /** * 字符串插入字符 * @param {*} str 字符串 * @param {*} length 间隔多少个插入 * @param {*} fmt 插入符号 * @returns */ strInsert(str, length = 2, fmt = ":") { if (!str || !str.length) return ""; var reg = new RegExp("\\w{1," + length + "}", "g"); let ma = str.match(reg); return ma.join(fmt).toLocaleLowerCase(); } // 清除计时器 clearTimeoutFn(name) { clearTimeout(this[name]); this[name] = null; } } export default new Bluetooth();