import $store from '@/store' import $model from '@/tools/model.js' import $tools from '@/tools/tools.js' import $data from '@/content.json' let unitList = [] let devicesList = [] let searchTimer = null let UNIT_MAP = $data.units // 初始化蓝牙 function openBluetoothAdapter() { devicesList = [] unitList = [] clearTimeout(searchTimer); uni.openBluetoothAdapter({ success: e => { $store.commit("changeBluetoothValue", { bleTipsText: "蓝牙搜索中", isConnectStatus: 0, unitList: $data.unitMinus, }) startBluetoothDeviceDiscovery() }, fail: e => { $store.commit("changeBluetoothValue", { bleTipsText: "连接超时,点击重新连接", isConnectStatus: 1, unitList: $data.unitMinus, }) } }); } // 开始搜寻附近的蓝牙外围设备 function startBluetoothDeviceDiscovery() { uni.startBluetoothDevicesDiscovery({ allowDuplicatesKey: true, interval: 200, success: res => { onBluetoothDeviceFound(); searchTimer = setTimeout(() => { uni.stopBluetoothDevicesDiscovery() if (!devicesList.length) { clearTimeout(searchTimer); $store.commit("changeBluetoothValue", { bleTipsText: "连接超时,点击重新连接", isConnectStatus: 1 }); } }, 30000); // 30秒超时 }, fail: res => { $store.commit("changeBluetoothValue", { bleTipsText: "连接超时,点击重新连接", isConnectStatus: 1 }) } }); } /** * 发现外围设备 */ function onBluetoothDeviceFound() { uni.onBluetoothDeviceFound(res => { res.devices.forEach(device => { device.advertisData = device.advertisData ? device.advertisData : '' let value = ab2hex(device.advertisData, "") let id = value.substring(0, 4) if (!device.name && !device.localName) { return } if (device.name.toLowerCase().indexOf('pc-c06pro') != -1 || device.name.toLowerCase().indexOf('pc-c02pro') != -1 || device.name.toLowerCase().indexOf('pc-c09pro') != -1 || (device.localName && device.localName.toLowerCase().indexOf('pc-c06pro') != -1) || (device.localName && device.localName.toLowerCase().indexOf('pc-c02pro') != -1) || (device.localName && device.localName.toLowerCase().indexOf('pc-c09pro') != -1)) { clearTimeout(searchTimer); const bytes = new Uint8Array(device.advertisData); const macBytes = bytes.slice(6, 12); device.macAddr = $tools.ab2hex(macBytes, ':').toUpperCase() stopBluetoothDevicesDiscovery() Bluetoothfilter(device) return } }) }); } // 过滤蓝牙 function Bluetoothfilter(device) { const foundDevices = devicesList const idx = inArray(foundDevices, "deviceId", device.deviceId) if (idx === -1) { devicesList.push(device); // handleDevType(device) connectDevice(device.deviceId) } } // 排查设备 function handleDevType(device) { $model.getCheckDevice({ mac: device.macAddr, }).then(res => { console.log("排查设备:", device, res) if (res.code == 0) { connectDevice(device.deviceId) } else { devicesList = [] $tools.msg('设备未登记,请联系出售方进行系统认证') $store.commit("changeBluetoothValue", { type: 1, isConnectStatus: 1, bleTipsText: "连接超时,点击重新连接", }) } }) } //连接设备 function connectDevice(device_id) { uni.createBLEConnection({ deviceId: device_id, success: res => { setTimeout(function() { getBLEDeviceServices(device_id) }, 200) }, fail: res => { $store.commit("changeBluetoothValue", { type: 1, isConnectStatus: 1, bleTipsText: "连接超时,点击重新连接", }) } }); } /** * 获取设备的UUID */ function getBLEDeviceServices(device_id) { let serviceList = []; uni.getBLEDeviceServices({ deviceId: device_id, success: res => { console.log("获取设备的UUID成功", res) stopBluetoothDevicesDiscovery(); serviceList = res.services; for (let i = 0; i < serviceList.length; i++) { let service = serviceList[i]; if (service.uuid.indexOf("FFF0") != -1) { getBLEDeviceCharacteristics(device_id, service.uuid); break; } } }, fail: res => { $store.commit("changeBluetoothValue", { type: 1, isConnectStatus: 1, bleTipsText: "连接超时,点击重新连接", }) console.log('获取设备的UUID失败:', res) } }); } /** * 获取指定服务的特征值 */ function getBLEDeviceCharacteristics(deviceId, serviceId) { let characteristicsList = []; uni.getBLEDeviceCharacteristics({ deviceId: deviceId, serviceId: serviceId, success: res => { let write, notify for (let i = 0; i < res.characteristics.length; i++) { let item = res.characteristics[i]; if (item.uuid.indexOf('0000FFF2') != -1) { write = item.uuid } else if (item.uuid.indexOf('0000FFF1') != -1) { notify = item.uuid } } getBLECharacteristicValueChange(deviceId, serviceId, notify, write) }, fail: res => { $store.commit("changeBluetoothValue", { type: 1, isConnectStatus: 1, bleTipsText: "连接超时,点击重新连接", }) console.log('获取特征值失败:', JSON.stringify(res)) } }) } function getBLECharacteristicValueChange(deviceId, serviceId, notify, write) { let that = this uni.notifyBLECharacteristicValueChange({ deviceId: deviceId, serviceId: serviceId, characteristicId: notify, state: true, success: () => { $store.commit('changeBluetoothValue', { deviceId: deviceId, serviceId: serviceId, notify: notify, write: write, unit: "g", type: 1, countWeight: "", bleTipsText: "测量中,请将食物放到秤上", isConnectStatus: 2 }) uni.onBLECharacteristicValueChange(function(res) { const value = res.value const dataView = new DataView(value) const header = dataView.getUint8(0) // MCU主动上报数据 if (header === 0xC7) { const cmd = dataView.getUint8(2) switch (cmd) { case 0x02: const statusByte = dataView.getUint8(4) const isNegative = !!(statusByte & 0x80) // 最高位表示正负 const statusType = statusByte & 0x0F // 状态类型 // 组合24位重量值 (大端序) const weightValue = (dataView.getUint8(5) << 16) | (dataView.getUint8(6) << 8) | dataView.getUint8(7) // 精度和单位 const unitByte = dataView.getUint8(8) const precision = (unitByte & 0xF0) >> 4 // 高4位精度 const unitIndex = unitByte & 0x0F // 低4位单位 // 计算实际重量 let finalWeight = weightValue / Math.pow(10, precision) console.log("类型:", cmd, "重量", finalWeight, "小数点", precision, "单位", UNIT_MAP[unitIndex]) if (isNegative) finalWeight = -finalWeight $store.commit("changeBluetoothValue", { countWeight: finalWeight, unit: UNIT_MAP[unitIndex], type: statusType }) break case 0x03: break case 0x08: const start0 = [] const value2 = $tools.ab2hex(res.value, ""); const start = parseUnitMask(value2.substring(8, 10), UNIT_MAP.slice(0, 7)) const start1 = parseUnitMask(value2.substring(10, 12), UNIT_MAP.slice(8, 10)) start.push.apply(start, start1) if (start.length) { $data.unitMinus.forEach(item => { start.forEach(item2 => { if (item.unit == item2) { start0.push(item) } }) }) } $store.commit("changeBluetoothValue", { unitList: start0.length ? start0 : $data.unitMinus }) console.log("2222222", start, start0) break } } }) }, fail: res => { console.log('获取特征值失败:', JSON.stringify(res)) } }) } function inArray(arr, key, val) { if (!arr || !arr.length || typeof arr != 'object' || !Array.isArray(arr)) { return -1 } for (let i = 0; i < arr.length; i++) { if (!key) { if (arr[i] == val) { return i } } else if (arr[i][key] === val) { return i } } return -1; } function ab2hex(buffer, split) { var hexArr = Array.prototype.map.call( new Uint8Array(buffer), function(bit) { return ('00' + bit.toString(16)).slice(-2) } ) return hexArr.join(split); } /** * 断开蓝牙模块 */ function closeBluetoothAdapter() { uni.closeBluetoothAdapter({ success: res => { clearTimeout(searchTimer); $store.commit("changeBluetoothValue", { deviceId: "", serviceId: "", notify: "", write: "", unit: "g", countWeight: '', type: 1, unitList: $data.unitMinus, isConnectStatus: 1, bleTipsText: "连接超时,点击重新连接", }) console.log('蓝牙模块关闭成功'); } }) } /** * 断开蓝牙连接 */ function closeBLEConnection(deviceId) { uni.closeBLEConnection({ deviceId: deviceId, success: res => { console.log('断开蓝牙连接成功'); } }); } // 监听蓝牙连接状态 function onBLEConnectionStateChange() { uni.onBLEConnectionStateChange(function(res) { console.log("监听蓝牙连接状态", res.connected) if (!res.connected) { $store.commit("changeBluetoothValue", { bleTipsText: "连接超时,点击重新连接", unitList: $data.unitMinus, isConnectStatus: 1, type: 1, }) closeBLEConnection() closeBluetoothAdapter() } $store.commit("changeBluetooth", res.connected); }) } /** * 停止搜索蓝牙设备 */ function stopBluetoothDevicesDiscovery() { uni.stopBluetoothDevicesDiscovery({ success: e => { console.log("停止搜索蓝牙设备", e) }, }); } //@param {number|string} hexValue - 16进制值,如 0x19 或 '0x19' // @returns {Array} 使用的单位列表 function parseUnitMask(hexValue, UNIT_MAP) { // 转换为数字 const mask = typeof hexValue === 'string' ? parseInt(hexValue, 16) : hexValue; // 验证输入 if (isNaN(mask) || mask < 0 || mask > 0xFF) { console.error('无效的位掩码值'); return []; } // 存储结果 const usedUnits = []; // 遍历每一位 for (let i = 0; i < 8; i++) { // 使用位运算检查第 i 位是否为 1 if (mask & (1 << i)) { usedUnits.push(UNIT_MAP[i]); } } return usedUnits; } export default { ab2hex, inArray, unitList, openBluetoothAdapter, startBluetoothDeviceDiscovery, onBluetoothDeviceFound, Bluetoothfilter, connectDevice, getBLEDeviceServices, getBLEDeviceCharacteristics, closeBluetoothAdapter, closeBLEConnection, getBLECharacteristicValueChange, onBLEConnectionStateChange, stopBluetoothDevicesDiscovery }