From 695b61f850190132ead3a846896cf9235bc389e0 Mon Sep 17 00:00:00 2001 From: iven Date: Sat, 30 May 2026 22:32:06 +0800 Subject: [PATCH] =?UTF-8?q?fix(mp):=20=E6=95=B0=E6=8D=AE=E7=9B=91=E5=90=AC?= =?UTF-8?q?=E5=99=A8=E6=94=B9=E4=B8=BA=20onLoad=20=E5=85=A8=E5=B1=80?= =?UTF-8?q?=E6=B3=A8=E5=86=8C=E4=B8=80=E6=AC=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重构原生页面: - 数据监听器和连接状态监听器在 onLoad 中全局注册一次 - _listenersRegistered 防止重复注册 - 连接流程不再注册监听器,只处理连接+认证 - 增加关键节点诊断日志(SDK函数类型、连接阶段、认证调用) - 连接回调简化为只匹配 connection:true 注意:需要清除 dist/ 后完整重建(dev 模式不监听 native/ 变更) --- apps/miniprogram/native/pkg-veepoo/index.js | 109 +++++++++++--------- 1 file changed, 60 insertions(+), 49 deletions(-) diff --git a/apps/miniprogram/native/pkg-veepoo/index.js b/apps/miniprogram/native/pkg-veepoo/index.js index 1876ad3..de468a8 100644 --- a/apps/miniprogram/native/pkg-veepoo/index.js +++ b/apps/miniprogram/native/pkg-veepoo/index.js @@ -2,10 +2,11 @@ * Veepoo M2 原生小程序页面 — 连接 + 测量 * * 完全脱离 Taro 框架,直接使用微信原生 API + Veepoo SDK。 - * 连接流程严格对齐官方 Demo: - * scan → stopScan → connect(callback, 等待 connection:true) - * → registerDataListener → delay 500ms → authenticate - * → 轮询 deviceChipStatus → ready + * 流程严格对齐官方 Demo: + * onLoad 注册全局监听器 + * → scan → stopScan → connect(等待 connection:true) + * → delay 500ms → authenticate + * → SDK 事件(type=1) / Storage 轮询 → ready */ // eslint-disable-next-line no-undef const { veepooBle, veepooFeature, veepooLogger } = require('./libs/veepoo-sdk'); @@ -79,6 +80,7 @@ Page({ _connected: false, _eventChannel: null, _connecting: false, + _listenersRegistered: false, // ── 生命周期 ── @@ -88,14 +90,13 @@ Page({ // eslint-disable-next-line no-undef wx.setNavigationBarTitle({ title: 'M2 手环测量' }); this._updateSelectedDisplay('heart_rate'); - // 诊断:确认 SDK 加载状态 + + // 在页面加载时一次性注册全局 SDK 监听器 + this._registerGlobalListeners(); + + // 诊断 // eslint-disable-next-line no-undef - console.log('[veepoo-native] SDK 加载状态:', { - veepooBle: typeof veepooBle, - veepooFeature: typeof veepooFeature, - veepooLogger: typeof veepooLogger, - scanFn: typeof veepooBle.veepooWeiXinSDKStartScanDeviceAndReceiveScanningDevice, - }); + console.log('[veepoo-native] 页面已加载,全局监听器已注册'); }, onUnload: function () { @@ -118,6 +119,41 @@ Page({ } }, + // ── 全局监听器(onLoad 注册一次) ── + + _registerGlobalListeners: function () { + if (this._listenersRegistered) return; + this._listenersRegistered = true; + var self = this; + + // SDK 数据监听 — 接收所有解析后的事件(auth/measure/battery 等) + veepooBle.veepooWeiXinSDKNotifyMonitorValueChange(function (data) { + // eslint-disable-next-line no-undef + console.log('[veepoo-native] SDK 数据事件:', JSON.stringify(data).substring(0, 500)); + self._handleSdkEvent(data); + }); + + // BLE 连接状态变化 + veepooBle.veepooWeiXinSDKBLEConnectionStateChangeManager(function (res) { + // eslint-disable-next-line no-undef + console.log('[veepoo-native] 连接状态变化:', JSON.stringify(res)); + if (!res.connected) { + self._connected = false; + self._connecting = false; + self._cancelPendingMeasure(); + self.setData({ phase: 'disconnected' }); + } + }); + + // eslint-disable-next-line no-undef + console.log('[veepoo-native] SDK 函数类型:', { + scanFn: typeof veepooBle.veepooWeiXinSDKStartScanDeviceAndReceiveScanningDevice, + connectFn: typeof veepooBle.veepooWeiXinSDKBleConnectionServicesCharacteristicsNotifyManager, + dataFn: typeof veepooBle.veepooWeiXinSDKNotifyMonitorValueChange, + authFn: typeof veepooFeature.veepooBlePasswordCheckManager, + }); + }, + _updateSelectedDisplay: function (type) { var cfg = _findConfig(type); this.setData({ @@ -129,10 +165,9 @@ Page({ }); }, - // ── 连接流程(严格对齐官方 Demo) ── + // ── 连接流程 ── handleConnect: function () { - // H2 防重入 if (this.data.phase !== 'idle' && this.data.phase !== 'error' && this.data.phase !== 'disconnected') return; if (this._connecting) return; this._connecting = true; @@ -149,8 +184,7 @@ Page({ var name = (device.localName || device.name || '').toUpperCase(); var deviceId = device.deviceId || device.mac || ''; // eslint-disable-next-line no-undef - console.log('[veepoo-native] 扫描到:', name, deviceId, JSON.stringify(device).substring(0, 200)); - // 放宽匹配:包含 M2 / VPM / VEEPOO 均视为目标设备 + console.log('[veepoo-native] 扫描到:', name, deviceId); if (!self._scanFound && (name.indexOf('M2') !== -1 || name.indexOf('VPM') !== -1 || name.indexOf('VEEPOO') !== -1)) { self._scanFound = device; veepooBle.veepooWeiXinSDKStopSearchBleManager(function () { @@ -171,40 +205,35 @@ Page({ _doConnect: function (device) { this.setData({ phase: 'connecting' }); // eslint-disable-next-line no-undef - console.log('[veepoo-native] 连接设备:', device.deviceId || device.mac); + console.log('[veepoo-native] 开始连接:', device.deviceId || device.mac); var self = this; veepooBle.veepooWeiXinSDKBleConnectionServicesCharacteristicsNotifyManager(device, function (result) { // eslint-disable-next-line no-undef - console.log('[veepoo-native] 连接回调:', JSON.stringify(result)); + console.log('[veepoo-native] 连接阶段回调:', JSON.stringify(result).substring(0, 300)); - // 只响应最终回调(connection:true),忽略中间阶段(services/characteristics/errno:0) + // 只响应最终就绪回调(connection:true) if (result.connection === true) { self._connected = true; self._connecting = false; self.setData({ deviceId: device.deviceId || device.mac || '', }); - - // 按 SDK 文档顺序:连接就绪 → 注册数据监听器 → 延迟 → 认证 - // wx.onBLECharacteristicValueChange 只支持一个回调,连接后注册避免被 SDK 内部覆盖 - self._registerListeners(); - // eslint-disable-next-line no-undef + console.log('[veepoo-native] 连接就绪,500ms 后发送认证'); + setTimeout(function () { + // eslint-disable-next-line no-undef + console.log('[veepoo-native] 调用 veepooBlePasswordCheckManager'); veepooFeature.veepooBlePasswordCheckManager(); self.setData({ phase: 'authenticating' }); - // eslint-disable-next-line no-undef - console.log('[veepoo-native] 认证指令已发送'); }, 500); - // 双重检测:事件监听器(type=1)+ Storage 轮询兜底 + // Storage 轮询兜底 self._authTimer = setInterval(function () { try { // eslint-disable-next-line no-undef var status = wx.getStorageSync('deviceChipStatus'); - // eslint-disable-next-line no-undef - console.log('[veepoo-native] 轮询 deviceChipStatus=', status); if (status === 'successfulVerification' || status === 'passTheVerification') { clearInterval(self._authTimer); self._authTimer = null; @@ -219,7 +248,7 @@ Page({ self._authTimer = null; self._connecting = false; // eslint-disable-next-line no-undef - console.error('[veepoo-native] 认证超时,deviceChipStatus=', wx.getStorageSync('deviceChipStatus')); + console.error('[veepoo-native] 认证超时 deviceChipStatus=', wx.getStorageSync('deviceChipStatus')); self.setData({ phase: 'error', error: '设备认证超时,请重新连接' }); } }, 8000); @@ -227,23 +256,7 @@ Page({ }); }, - _registerListeners: function () { - var self = this; - veepooBle.veepooWeiXinSDKNotifyMonitorValueChange(function (data) { - self._handleSdkEvent(data); - }); - veepooBle.veepooWeiXinSDKBLEConnectionStateChangeManager(function (res) { - if (!res.connected) { - self._connected = false; - self._connecting = false; - self._cancelPendingMeasure(); - self.setData({ phase: 'disconnected' }); - } - }); - }, - _onReady: function () { - // C5 修复:清除 authTimeout 防止泄漏 if (this._authTimeout) { clearTimeout(this._authTimeout); this._authTimeout = null; } this._connecting = false; // eslint-disable-next-line no-undef @@ -257,11 +270,11 @@ Page({ _handleSdkEvent: function (data) { if (!data || data.type === undefined) return; var type = data.type; - // eslint-disable-next-line no-undef - console.log('[veepoo-native] SDK 事件: type=' + type, JSON.stringify(data).substring(0, 300)); if (type === SDK_EVENT_AUTH) { var password = (data.content || {}).VPDevicepassword; + // eslint-disable-next-line no-undef + console.log('[veepoo-native] 认证事件: VPDevicepassword=' + password); if (password === 'passTheVerification' || password === 'successfulVerification') { if (this._authTimer) { clearInterval(this._authTimer); this._authTimer = null; } if (this._authTimeout) { clearTimeout(this._authTimeout); this._authTimeout = null; } @@ -437,7 +450,6 @@ Page({ return (values.systolic != null ? values.systolic : '--') + '/' + (values.diastolic != null ? values.diastolic : '--'); } var v = Object.values(values)[0]; - // H5 修复:零值合法,仅 undefined/null 显示占位符 return (v !== undefined && v !== null) ? String(v) : '--'; }, @@ -486,7 +498,6 @@ Page({ case 'blood_pressure': veepooFeature.veepooSendReadUniversalBloodPressureDataManager({ switch: on ? 'start' : 'stop' }); break; - // C1 修复:体温测量传 { switch: boolean } 参数,停止时也调用 case 'temperature': veepooFeature.veepooSendTemperatureMeasurementSwitchManager({ switch: !!on }); break;