App({ onLaunch() { this.initPpScale(); }, globalData: { // wx.request 请求的服务地址 // wxRequestUrl: "https://device.shuziweidao.com/gateway/", wxRequestUrl: "http://192.168.1.207:8889/", // 秤的所有信息 ppScale: { version: "", plugin: null, activeProtocol: null, domain1: "http://192.168.1.207:8889", // 老版本 没有鉴权 domain2: "http://192.168.1.207:8889/weight", // 新版本 有鉴权 wifi: { ssid: "", password: "" }, options: { key: "lefudc91611833e18d94", secret: "eQ50JYimMp0X7uhNLj6D3lTEk4TUUvEG7dvaqKM9t1U=" }, device: { setting: [{ "advLength": 999, "calorieStatus": 0, "createBy": null, "deviceAccuracyType": 2, "deviceCalcuteType": 3, "deviceConnectType": 2, "deviceFuncType": 223, "deviceName": "CF568_G", "devicePowerType": 3, "deviceProtocolType": 3, "deviceType": 1, "deviceUnitType": "0,1,11", "id": 65, "imgUrl": null, "macAddressStart": 6, "remark": null, "sign": "FF", "status": 0, "uhStatus": 1, "updateBy": null }, { "advLength": 999, "calorieStatus": 0, "createBy": null, "deviceAccuracyType": 2, "deviceCalcuteType": 3, "deviceConnectType": 2, "deviceFuncType": 223, "deviceName": "YX-B4-568-BW", "devicePowerType": 3, "deviceProtocolType": 3, "deviceType": 1, "deviceUnitType": "0,1,11", "id": 65, "imgUrl": null, "macAddressStart": 6, "remark": null, "sign": "FF", "status": 0, "uhStatus": 1, "updateBy": null }, { "advLength": 999, "calorieStatus": 0, "createBy": null, "deviceAccuracyType": 2, "deviceCalcuteType": 4, "deviceConnectType": 2, "deviceFuncType": 65759, "deviceName": "CF636_G", "devicePowerType": 3, "deviceProtocolType": 3, "deviceType": 1, "deviceUnitType": "0,1,2", "id": 216, "imgUrl": null, "macAddressStart": 6, "remark": null, "sign": "FF", "status": 0, "uhStatus": 1, "updateBy": null }, { "advLength": 999, "calorieStatus": 0, "createBy": null, "deviceAccuracyType": 2, "deviceCalcuteType": 4, "deviceConnectType": 2, "deviceFuncType": 65759, "deviceName": "YX-B8-636-BW", "devicePowerType": 3, "deviceProtocolType": 3, "deviceType": 1, "deviceUnitType": "0,1,2", "id": 216, "imgUrl": null, "macAddressStart": 6, "remark": null, "sign": "FF", "status": 0, "uhStatus": 1, "updateBy": null }, { "advLength": 999, "calorieStatus": 0, "createBy": null, "deviceAccuracyType": 2, "deviceCalcuteType": 4, "deviceConnectType": 2, "deviceFuncType": 223, "deviceName": "CF577", "devicePowerType": 3, "deviceProtocolType": 3, "deviceType": 1, "deviceUnitType": "0,1,11", "id": 51, "imgUrl": null, "macAddressStart": 6, "remark": null, "sign": "FF", "status": 0, "uhStatus": 1, "updateBy": null }], // 即将要搜索周边秤的配置 list: [], // 根据配置搜索到秤的列表 name: "", mac: null, // 选中的设备mac地址/SN码 connection: null, // 默认选中连接的设备 connectState: null, // 当前连接设备的状态 }, reconnect: { count: 0, // 当前已重连次数 max: 3, // 最大重连次数 timer: null // 重连定时器 } }, _callbacks: {} // 用于存储所有 globalData 属性的监听回调 }, initPpScale() { this.globalData.ppScale.plugin = requirePlugin('ppScale-plugin'); }, /** * 注册全局 bus 事件监听(connectState / syncDeviceTimeSuccess / deviceWillDisconnect) * 依赖 Blue.stop() 清空订阅,onShow 时直接调用,无需标志位 */ registerBusListeners() { const plugin = this.globalData.ppScale.plugin; // 蓝牙连接状态监听 plugin.bus.subscribe('connectState', (res) => { console.log("app.js ===> connectState", res); this.setGlobalData('ppScale.device.connectState', res); if (res == plugin.BLUE_STATE.CONNECTSUCCESS) { this.globalData.ppScale.reconnect.count = 0; } if (res == plugin.BLUE_STATE.CONNECTFAILED) { this.reconnectDevice(); } wx.hideLoading(); }); // 同步时间 plugin.bus.subscribe('syncDeviceTimeSuccess', (res) => { console.log("app.js ===> syncDeviceTimeSuccess", res); }); // 设备自动断开监听 plugin.bus.subscribe('deviceWillDisconnect', (res) => { console.log("app.js ===> deviceWillDisconnect", res); this.setGlobalData('ppScale.device.connectState', plugin.BLUE_STATE.CONNECTFAILED); }); }, /** * 自动重连设备,最多重试 max 次,超过后停止,由用户手动重连 * 只在配置页(configureDevice)活跃时执行,防止跨页面干扰 */ reconnectDevice() { const reconnect = this.globalData.ppScale.reconnect; // 仅在配置页活跃时执行重连 const pages = getCurrentPages(); const currentPage = pages[pages.length - 1]; if (!currentPage || !currentPage.route || !currentPage.route.includes('configureDevice')) { console.log("app.js ===> 非配置页,跳过自动重连"); return; } if (reconnect.count >= reconnect.max) { console.log("app.js ===> 自动重连已达上限,等待用户手动重试"); return; } reconnect.count++; console.log(`app.js ===> 自动重连第 ${reconnect.count}/${reconnect.max} 次`); // 延迟 2 秒后重连,避免连续冲突 if (reconnect.timer) { clearTimeout(reconnect.timer); } reconnect.timer = setTimeout(() => { this.globalData.ppScale.plugin.Blue.disconnect((disres) => { if (disres.errCode == 0) { console.log("app.js ===> 断开成功,开始重新扫描设备"); this.globalData.ppScale.plugin.Blue.startBluetoothDevicesDiscovery(); } else { console.log("app.js ===> 断开失败,errCode:", disres.errCode); } }); }, 2000); }, /** * 重置重连计数,用于用户手动点击重试或页面离开时调用 */ resetReconnectCount() { const reconnect = this.globalData.ppScale.reconnect; reconnect.count = 0; if (reconnect.timer) { clearTimeout(reconnect.timer); reconnect.timer = null; } }, /** * 注册 globalData 某个属性的监听 * @param {string} keyPath 要监听的 globalData 属性路径,例如 'ppScale.device.connectState' * @param {function} callback 属性变化时执行的回调函数 (newValue, oldValue) => {} */ watch(keyPath, callback) { if (!this.globalData._callbacks[keyPath]) { this.globalData._callbacks[keyPath] = []; } this.globalData._callbacks[keyPath].push(callback); }, /** * 取消 globalData 某个属性的监听 * @param {string} keyPath 要取消监听的 globalData 属性路径 * @param {function} callback 之前注册的回调函数 */ unwatch(keyPath, callback) { if (this.globalData._callbacks[keyPath]) { this.globalData._callbacks[keyPath] = this.globalData._callbacks[keyPath].filter(cb => cb !== callback); } }, /** * 设置 globalData 的值并触发所有相关监听器 * 支持点表示法设置嵌套属性,例如 'ppScale.device.connectState' * @param {string} keyPath 要设置的 globalData 属性路径 * @param {*} value 要设置的新值 */ setGlobalData(keyPath, value) { const keys = keyPath.split('.'); let current = this.globalData; let oldValue = undefined; // 遍历到目标属性的父级 for (let i = 0; i < keys.length - 1; i++) { if (!current[keys[i]]) { current[keys[i]] = {}; // 如果路径不存在,创建空对象 } current = current[keys[i]]; } // 获取旧值 oldValue = current[keys[keys.length - 1]]; // 只有当值发生变化时才更新并通知 if (oldValue !== value) { current[keys[keys.length - 1]] = value; // 设置新值 // 触发监听器 if (this.globalData._callbacks[keyPath]) { this.globalData._callbacks[keyPath].forEach(callback => { callback(value, oldValue); }); } } }, })