fix(mp): 数据监听器改为 onLoad 全局注册一次

重构原生页面:
- 数据监听器和连接状态监听器在 onLoad 中全局注册一次
- _listenersRegistered 防止重复注册
- 连接流程不再注册监听器,只处理连接+认证
- 增加关键节点诊断日志(SDK函数类型、连接阶段、认证调用)
- 连接回调简化为只匹配 connection:true

注意:需要清除 dist/ 后完整重建(dev 模式不监听 native/ 变更)
This commit is contained in:
iven
2026-05-30 22:32:06 +08:00
parent 8d3b3a0491
commit 695b61f850

View File

@@ -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;