// 引入必要的微信小程序 API // const wx = require('wx'); class bleManager { constructor() { var that = this; that.hasPermission = false; that.publicDevice = null; that.connectWillDevice = null; that.callBackConnect = null; that.requestBlueTime = 0; ///正在执行扫描中 that.isAvailable = false; that.doStartScaning = false; that.compareList = []; that.dissmissDevice = []; that.stateChangeCallback = null; that.isConnecting = false; } ///获取比较的数据 getCompareList() { return this.compareList; } setCompareList(compareList) { this.compareList = compareList; } getDissmissDevice() { return this.dissmissDevice; } setConnectWillDevice(connectWillDevice) { this.connectWillDevice = connectWillDevice; } getCallBackConnect() { return this.callBackConnect; } setCallBackConnect(callBackConnect) { this.callBackConnect = callBackConnect; } /// 监控蓝牙打开状态 initBluetoothAdapter() { var that = this; wx.onBluetoothAdapterStateChange(function (res) { that.isAvailable = res.available; if (!that.isAvailable) { that.compareList = []; that.dissmissDevice = []; getCurrentPages()[0].closeBlueResetOffline(false, true); } }); } ///监听搜索设备列表 监听设备列表 getBluetoothDevices() { var that = this; const hexUtil = require('../utils/hexUtil'); wx.onBluetoothDeviceFound(function (res) { // console.log("蓝牙设备列表", res.length); ///第一种情况 if (res.deviceId) { if (that.callBackConnect != null) { if (that.connectWillDevice != null && res.name == that.connectWillDevice.clientType) { res.mac = res.advertisData ? hexUtil.buf2hex(res.advertisData) : ''; // if (that.callBackConnect != null) { console.log("1111", res.mac); if (that.callBackConnect != null) { that.callBackConnect(res); } } } else { if (res.name != "") { if (that.compareList.length > 0) { var has = false; for (var i = 0; i < that.compareList.length; i++) { if (res.deviceId == that.compareList[i].deviceId) { has = true; break; } } if (!has) { that.compareList.push(res); } } else { that.compareList.push(res); } } } } ///第二种情况 else if (res.devices) { if (that.callBackConnect != null) { for (var i = 0; i < res.devices.length; i++) { var temp = res.devices[i]; // if (temp.name == "MW-SR1(4G_WIFI)") { // } // if (temp.name != null) { // console.log("2222", temp.name); // } if (that.connectWillDevice != null && temp.name == that.connectWillDevice.clientType) { temp.mac = temp.advertisData ? hexUtil.buf2hex(temp.advertisData) : ''; temp.mac2 = that.ab2hex(temp.advertisData ?? "") // if (that.testData(temp)) { // return // } console.log("2222:", temp.mac, ":", temp.mac2, ":", temp.deviceId, temp, temp.connectable); // if ((temp.deviceId.indexOf("1f:de") ) > -1) { // that.callBackConnect(temp); // } that.callBackConnect(temp); break; } } } else { for (var i = 0; i < res.devices.length; i++) { if (res.devices[i].name != "") { if (that.compareList.length > 0) { var has = false; for (var j = 0; j < that.compareList.length; j++) { if (res.devices[i].deviceId == that.compareList[j].deviceId) { has = true; break; } } if (!has) { that.compareList.push(res.devices[i]); } } else { that.compareList.push(res.devices[i]); } } } } } ///第三种情况 else if (res[0]) { if (that.callBackConnect != null) { if (that.connectWillDevice != null && res[0].name == that.connectWillDevice.clientType) { res[0].mac = res[0].advertisData ? hexUtil.buf2hex(res[0].advertisData) : ''; // if (that.callBackConnect != null) { console.log("3333", res.mac); if (that.callBackConnect != null) { that.callBackConnect(res[0]); } } } else { if (res[0].name != "") { if (that.compareList.length > 0) { var has = false; for (var i = 0; i < that.compareList.length; i++) { if (res[0].deviceId == that.compareList[i].deviceId) { has = true; break; } } if (!has) { that.compareList.push(res[0]); } } else { that.compareList.push(res[0]); } } } } }); } onBLEConnectionStateChange() { ///监听已连接或没有连接 连接和断开的时候会回调 // {"deviceId":"E4:9F:80:09:40:EC","connected":false} let that = this; wx.onBLEConnectionStateChange((result) => { if (result.connected) { for (var i = 0; i < that.dissmissDevice.length; i++) { if (result.deviceId == that.dissmissDevice[i].deviceId) { that.dissmissDevice.splice(i, 1); break; } } } else { var has = false; for (var i = 0; i < that.dissmissDevice.length; i++) { if (result.deviceId == that.dissmissDevice[i].deviceId) { has = true; break; } } if (!has) { that.dissmissDevice.push(result); } } // that.disconnect(result) //断开连接是失败的。 console.log("监听到设备状态变化0:", result.deviceId, JSON.stringify(result)); that.errorDisconnect({ "deviceId": result.deviceId, "state": result.connected ? "online" : "offline" }); // ///是否已配对 // wx.isBluetoothDevicePaired({ // deviceId: result.deviceId, // ///{"isPaired":false,"errno":0,"errMsg":"isBluetoothDevicePaired:ok"} // success: (res) => { // }, // fail: (err) => { // } // }) }); } ///获取 所有搜索到的蓝牙设备 getConnectedDevices() { var that = this; const hexUtil = require('../utils/hexUtil'); // wx.getConnectedBluetoothDevices({ // // services: ['ab00'], // search: ['ab00', 'ab01', 'ab02', '0000AB00-0000-1000-8000-00805F9B34FB', '0000AB01-0000-1000-8000-00805F9B34FB', '0000AB02-0000-1000-8000-00805F9B34FB'], // success: (res) => { // // ble连接上,才会有这个返回 // console.log('根据主服务 UUID 获取已连接的蓝牙设备:', res.devices); // if (res.devices.length > 0) { // for (var i = 0; i < res.devices.length; i++) { // var device = res.devices[i]; // if (device.name != "") { // that.callBackConnect(device); // } // } // } // } // }) wx.getBluetoothDevices({ success: (res) => { console.log("搜索到的:" + res.length); if (that.callBackConnect != null) { for (var i = 0; i < res.devices.length; i++) { var temp = res.devices[i]; if (that.connectWillDevice != null && temp.name == that.connectWillDevice.clientType) { temp.mac = temp.advertisData ? hexUtil.buf2hex(temp.advertisData) : ''; if (temp.mac) { console.log("搜索到的" + JSON.stringify(temp)); } // if (that.callBackConnect != null) { if (that.testData(temp)) { return } console.log("444:" + JSON.stringify(temp)); // if ((temp.deviceId === "07:F6:F4:66:FB:FA")) { // that.callBackConnect(temp); // } that.callBackConnect(temp); } break; } } else { for (var i = 0; i < res.devices.length; i++) { if (that.compareList.length > 0) { var has = false; for (var j = 0; j < that.compareList.length; j++) { if (res.devices[i].name != "") { // if (res.devices[i].name == "MW-SR1(4G_WIFI)") { // console.log("gadsfqewrqewrqwerqrqr==000==" + JSON.stringify(res.devices[i])); // } if (res.devices[i].deviceId == that.compareList[j].deviceId) { has = true; break; } } } if (!has) { that.compareList.push(res.devices[i]); } } else { that.compareList.push(res.devices[i]); } } } }, fail: (err) => { console.error('获取蓝牙设备列表失败', err); } }); } testData(temp) { if ((temp.deviceId === "1A:B4:E0:40:22:8B" || temp.deviceId === "F3:55:1F:8D:26:A0" || temp.deviceId === "3F2F112F-ACB5-3EB3-30DA-93DE6A86228A")) { return true } return false } // 开始搜索蓝牙设备 async startScan(connectWillDevice, boolean, callBackConnect) { var that = this; ///限制搜索没有打开蓝牙一直询问打开蓝牙 const time_util = require('../utils/timeUtil'); if (!that.isAvailable) { if (callBackConnect == null) { return; } ///做搜索蓝牙适配器权限 const permissionUtil = require('../utils/permissionUtil'); // var location = await permission_util.getSetting() // if (!location) { // if (boolean != null) { // boolean(false); // console.log("没有定位权限") // } // return // } var available = await permissionUtil.openBluetoothAdapter(); that.isAvailable = available; if (!available) { that.doStartScaning = false; that.requestBlueTime = time_util.getCurrentMills(); if (boolean != null) { boolean(false); } return; } } const routeUtil = require('../utils/routeUtil'); const routeRoot = require('../utils/routeRoot'); const index = routeRoot.index; const connectBleRoot = routeRoot.connectBle; var lastPageRoute = routeUtil.getLastPageRoute(); if (lastPageRoute != index && lastPageRoute != connectBleRoot) { console.log("搜索蓝牙设备失败,请返回首页0"); return; } ///蓝牙连接 做限制 if (lastPageRoute == index) { if (that.doStartScaning == true) { console.log("搜索蓝牙设备失败,请返回首页1"); return; } } that.doStartScaning = true; var currentMill = time_util.getCurrentMills(); var waitMills = 0; var reduce = currentMill - that.requestBlueTime; const dMiliis = 6 * 1000; if (reduce > 0 && reduce < dMiliis) { waitMills = dMiliis - reduce; } if (waitMills > 0) { await time_util.delayMills(waitMills); } if (callBackConnect == null && lastPageRoute == connectBleRoot) { that.doStartScaning = false; return; } wx.stopBluetoothDevicesDiscovery({ success: (res) => { that.search(connectWillDevice, boolean, callBackConnect); }, fail: (err) => { that.doStartScaning = false; that.requestBlueTime = time_util.getCurrentMills(); if (boolean != null) { boolean(false); } } }); } search(connectWillDevice, boolean, callBackConnect) { var that = this; const timeUtil = require('../utils/timeUtil'); wx.startBluetoothDevicesDiscovery({ allowDuplicatesKey: true, success: function (res) { console.log("开始搜索设备", res); that.getConnectedDevices(); that.doStartScaning = false; that.requestBlueTime = timeUtil.getCurrentMills(); if (boolean != null) { boolean(true); } that.setConnectWillDevice(connectWillDevice); that.setCallBackConnect(callBackConnect); that.compareList = []; }, fail(err) { console.log("开始搜索设备失败", err); that.doStartScaning = false; that.requestBlueTime = timeUtil.getCurrentMills(); if (err.errMsg.indexOf("location") >= 0) { wx.showToast({ title: '搜索失败,请检查下手机设置的微信定位权限是否开启', }) } if (boolean != null) { boolean(false); } }, }) } // 停止搜索 stopSearch() { var that = this; that.setCallBackConnect(null); that.setConnectWillDevice(null); return new Promise((resolve, reject) => { wx.stopBluetoothDevicesDiscovery({ success: (res) => { resolve(res); }, fail: (err) => { reject('停止搜索失败'); } }); }); } closeBle() { console.log('关闭蓝牙了') closeBluetoothAdapter(); } // 断开与指定设备的连接 disconnect(mDevice) { var that = this; const strings = require('../utils/strings'); // 没有参数就默认断开现在连接的 let device = mDevice; if (mDevice != null) { device = mDevice; } if (strings.isEmpty(device)) { return; } let deviceId = device.deviceId if (strings.isEmpty(deviceId)) { return; } console.log('开始断开连接', device); return new Promise((resolve, reject) => { wx.closeBLEConnection({ deviceId: deviceId, success: (res) => { let publicDevice = that.publicDevice ?? {} if (deviceId == publicDevice.deviceId) { console.log('成功断开连接', res, deviceId); that.publicDevice = null; } resolve(res); }, fail: (err) => { console.log('断开连接失败', err); resolve(err); } }); }); } // 连接到指定设备 async connectToDevice(device) { var that = this; if (that.isConnecting) { // 防止多次进入连接 return; } that.isConnecting = true return new Promise((resolve, reject) => { console.log("开始连接蓝牙:", device.deviceId) wx.createBLEConnection({ deviceId: device.deviceId, success: (res) => { that.publicDevice = device console.log('连接成功:', res); that.isConnecting = false; wx.setBLEMTU({ deviceId: device.deviceId, mtu: 128, success: (mtuRes) => { console.log("设置mtu成功") }, fail: (mtuErr) => { console.log("设置mtu失败:", mtuErr) } }) resolve(true); }, fail: (err) => { // {errno: 1509007, errCode: -1, errMsg: "createBLEConnection:fail:already connect"} if (err.errno == 1509007) { that.disconnect({ "deviceId": device.deviceId }) } else { that.isConnecting = false; console.log("监听到设备状态变化3:", err); that.errorDisconnect({ "deviceId": device.deviceId, "state": "offline" }) let publicDevice = that.publicDevice ?? {} if (device.deviceId == publicDevice.deviceId) { that.publicDevice = null; } } console.error('连接失败:', err); resolve(false); } }); }); } // 发送数据到指定设备 async sendData(data, callback) { var that = this if (that.publicDevice == null) { console.log("没有连接设备"); return; } return new Promise((resolve, reject) => { var buffer = null; // todo 判断是否是buffer // if (needChange) { // buffer = data; // } else { buffer = new ArrayBuffer(data.length); // 下面是赋值,不能删 const dataView = new DataView(buffer); data.forEach((value, index) => { dataView.setUint8(index, value); // 将每个16进制数值写入到 buffer 中 }); // } // let logData = new Uint8Array(buffer); // console.log('开始发送数据:', buffer); wx.writeBLECharacteristicValue({ deviceId: that.publicDevice.deviceId, serviceId: that.publicDevice.serviceId, characteristicId: that.publicDevice.characteristicId, value: buffer, success: (res) => { console.log('发送数据成功:', dataView); if (callback) { callback(true) } resolve(true); }, fail: (err) => { if (callback) { callback(false) } console.log('监听到设备状态变化4:', err); that.errorDisconnect({ "deviceId": that.publicDevice.deviceId, "state": "offline" }) resolve(false); } }); }); } ab2hex(buffer) { var hexArr = Array.prototype.map.call( new Uint8Array(buffer), function (bit) { return ('00' + bit.toString(16)).slice(-2) } ) return hexArr.join(':'); } fiterDevice(res) { var that = this; var devices = res.devices.filter(device => { const name = device.name || ''; const localName = device.localName || ''; let isNot = that.isNotEmpty(name) || that.isNotEmpty(localName); if (isNot) { // console.log('是猫王设备名称:', device.advertisData, device.serviceData) let mac = that.ab2hex(device.advertisData) // console.log(mac) device.mac = mac } return isNot }); let newDevices = devices.map((device) => { let uuid = device.advertisServiceUUIDs[0] ?? "" return { deviceId: device.deviceId, name: device.name, localName: device.localName, uuid: uuid, mac: device.mac, connectable: device.connectable } }); return newDevices } isNotEmpty(name) { let isNot = (name !== '' && (name.startsWith("MW_") || name.startsWith("MW-") || // name.startsWith("猫王") || // name.startsWith("妙播") || // name.startsWith("AirSmart") || name === "le") ) // if (!isNot && name !== '') { // console.log('不是猫王设备名称:', name) // } return isNot; } // 发现服务 discoverServices(deviceId) { var that = this; console.log('发现服务:', deviceId); return new Promise((resolve, reject) => { wx.getBLEDeviceServices({ deviceId: deviceId, success: (res) => { // that.publicDevice .services = res.services; let service_id = ""; for (let i = 0; i < res.services.length; i++) { if (res.services[i].uuid.toUpperCase().indexOf("AB00") != -1 || res.services[i].uuid.toUpperCase().indexOf("FFC0") != -1 // res.services[i].uuid.toUpperCase().indexOf("ae800") != -1 ) { service_id = res.services[i].uuid; break; } console.log('发现服务1:', service_id); service_id = res.services[i].uuid; } if (that.publicDevice) { that.publicDevice.serviceId = service_id; console.log('发现服务2:', that.publicDevice.service_id); } resolve(service_id); // resolve(res.services); }, fail: (err) => { if (that.publicDevice) { that.publicDevice.serviceId = null; } console.error('发现服务失败:', err); reject([]); } }); }); } connect() {} // 发现特征值 read / write discoverCharacteristics(deviceId, serviceId) { var that = this; console.log('发现特征值:' + deviceId + " , " + serviceId); // if (deviceId !== that.publicDevice .deviceId) { // console.log('设备id不匹配') // return false // } return new Promise((resolve, reject) => { wx.getBLEDeviceCharacteristics({ deviceId: deviceId, serviceId: serviceId, success: (res) => { // that.characteristics[serviceId] = res.characteristics; console.log('发现特征值2:', res); // that.publicDevice .characteristics = res.characteristics; resolve(res.characteristics); }, fail: (err) => { if (that.publicDevice) { that.publicDevice.characteristics = null; } console.error('发现特征值失败:', err); reject(""); } }); }); } // 读取特征值 readCharacteristicValue(characteristicId) { var that = ths; console.log('开始读取特征值', characteristicId) return new Promise((resolve, reject) => { wx.readBLECharacteristicValue({ deviceId: that.publicDevice.deviceId, serviceId: that.publicDevice.serviceId, characteristicId: characteristicId, success: (res) => { const name = that.parseBLEValue(res.value); // 解析读取到的值 console.log('读取特征值成功:', name, res); resolve(res); }, fail: (err) => { console.error('读取特征值失败:', err); reject(""); } }); }); } // 解析读取到的设备名称 parseBLEValue(buffer) { return String.fromCharCode.apply(null, new Uint8Array(buffer)); } // 监听特征值变化 notifyCharacteristicValueChange(characteristicId, callback) { var that = this; console.log('监听特征值变化:', characteristicId, that.publicDevice.deviceId, that.publicDevice.serviceId); wx.notifyBLECharacteristicValueChange({ deviceId: that.publicDevice.deviceId, //设备mac IOS和安卓系统不一样 serviceId: that.publicDevice.serviceId, //服务通道,这里主要是notify characteristicId: characteristicId, //notify uuid state: true, success: function (res) { console.log("开启notify 成功") //TODO onBLECharacteristicValueChange 监听特征值 设备的数据在这里获取到 wx.onBLECharacteristicValueChange(function (characteristic) { let buffer = characteristic.value let dataView = new DataView(buffer) let dataResult = [] for (let i = 0; i < dataView.byteLength; i++) { // console.log("0x" + dataView.getUint8(i).toString(16)) // dataResult.push("0x" + dataView.getUint8(i).toString(16)) dataResult.push(dataView.getUint8(i)) } const result = dataResult // console.log("拿到的数据:", result) if (callback) { callback(result) } }) }, fail: function (res) { console.log("订阅特征失败:", res) } }) } setWrite(wirte, characteristicId) { var that = this; console.log('写入特征值:', characteristicId) // that.publicDevice .wirte = wirte that.publicDevice.characteristicId = characteristicId; } setStateChangeCallback(callback) { this.stateChangeCallback = callback; } errorDisconnect(result) { // this.disconnect(); console.log("监听到设备状态变化1:", result.deviceId, result.state, this.stateChangeCallback); if (this.stateChangeCallback && result.deviceId) { this.stateChangeCallback(result); } } } // const ble = new bleManager(); // 导出 bleManager 类 module.exports = bleManager;