Measured on real hardware: IO1=right IO2=left IO3=top IO4=middle IO5=bottom (0x01=right 0x02=left 0x04=top 0x08=middle 0x10=bottom). The earlier verbal 'left=IO1/upper=IO2...' spec was wrong; this reverts to the original Phase-1 mapping, which the measurement confirms. - protocol.js REGION constants + getRegionName + REGION_NAMES - CRITICAL: buildVendorCommand ioMasks was built from REGION.* constants whose values just flipped, scrambling IO slot order; pin to literal [0x01..0x10] - diagnosis.js REGION_DEFS key↔mask; pd_region_map values unchanged (PD is keyed by orientation, which is stable) — right=PD5 left=PD1 top=PD2 middle=PD3,6,7 bottom=PD4 - common.js region labels back to right/left/top/middle/bottom (上/中/下) - treatment-setup / manual-treatment / treating / scan-report / ble-debug face-map bindings and REGION_MAP realigned - verified: mock pipeline lands left→IO2, middle→IO4 correctly
131 行
4.1 KiB
JavaScript
131 行
4.1 KiB
JavaScript
// TEMPORARY debug page for on-device verification (region↔IO mapping, color byte
|
|
// order, scan wave bucketing, PD polarity). Guoguo-only tooling — intentionally
|
|
// NOT i18n'd; remove this page before any release build.
|
|
var ble = require('../../services/ble')
|
|
var protocol = require('../../services/ble/protocol')
|
|
|
|
var WAVES = [
|
|
{ key: 'red', code: 2, label: '红光' },
|
|
{ key: 'ir', code: 1, label: '红外' },
|
|
{ key: 'uv', code: 3, label: '紫外' },
|
|
{ key: 'yellow', code: 4, label: '暖黄' }
|
|
]
|
|
var REGION_LABELS = { 1: '右区/IO1', 2: '左区/IO2', 4: '上区/IO3', 8: '中区/IO4', 16: '下区/IO5' }
|
|
var RUN_STATES = { 0: 'IDLE', 1: '检测', 2: '治疗', 255: '故障(0xFF)' }
|
|
|
|
function hex(bytes) {
|
|
return bytes.map(function (b) { return ('0' + b.toString(16)).slice(-2).toUpperCase() }).join(' ')
|
|
}
|
|
|
|
Page({
|
|
data: {
|
|
statusBarHeight: 44,
|
|
connected: false,
|
|
waves: WAVES,
|
|
selectedWave: 'red',
|
|
// live FFE4 status
|
|
pd: [], vbat: 0, battery: 0, fitting: -1, scanWave: '-', runState: '-', frames: 0,
|
|
logs: []
|
|
},
|
|
|
|
onLoad: function () {
|
|
this.setData({ statusBarHeight: getApp().globalData.statusBarHeight })
|
|
},
|
|
|
|
onShow: function () {
|
|
var self = this
|
|
self.setData({ connected: ble.isConnected() })
|
|
self._onAdc = function (d) {
|
|
self.setData({
|
|
pd: d.pd || [],
|
|
vbat: d.vbat || 0,
|
|
battery: d.battery || 0,
|
|
fitting: d.fitting,
|
|
scanWave: d.scan_wave || '-',
|
|
runState: RUN_STATES[d.run_state] !== undefined ? RUN_STATES[d.run_state] : String(d.run_state),
|
|
frames: self.data.frames + 1
|
|
})
|
|
}
|
|
ble.on('adc', self._onAdc)
|
|
},
|
|
|
|
onHide: function () { this._cleanup() },
|
|
onUnload: function () { this._cleanup() },
|
|
_cleanup: function () {
|
|
if (this._onAdc) { ble.off('adc', this._onAdc); this._onAdc = null }
|
|
},
|
|
|
|
onBack: function () {
|
|
wx.navigateBack({ fail: function () { wx.switchTab({ url: '/pages/profile/profile' }) } })
|
|
},
|
|
|
|
_log: function (msg) {
|
|
var logs = this.data.logs
|
|
logs.unshift(new Date().toTimeString().slice(0, 8) + ' ' + msg)
|
|
if (logs.length > 20) logs.pop()
|
|
this.setData({ logs: logs })
|
|
},
|
|
|
|
_send: function (label, options) {
|
|
var self = this
|
|
if (!ble.isConnected()) {
|
|
self.setData({ connected: false })
|
|
wx.showToast({ title: '设备未连接', icon: 'none' })
|
|
return
|
|
}
|
|
var bytes = protocol.buildVendorCommand(options)
|
|
self._log(label)
|
|
self._log('→ ' + hex(bytes))
|
|
ble.setParams(options).then(function () {
|
|
self._log('✓ 写入成功')
|
|
}).catch(function (err) {
|
|
self._log('✗ 写入失败: ' + ((err && err.msg) || JSON.stringify(err)))
|
|
})
|
|
},
|
|
|
|
onSelectWave: function (e) {
|
|
this.setData({ selectedWave: e.currentTarget.dataset.key })
|
|
},
|
|
|
|
_waveCode: function () {
|
|
var key = this.data.selectedWave
|
|
for (var i = 0; i < WAVES.length; i++) if (WAVES[i].key === key) return WAVES[i].code
|
|
return 2
|
|
},
|
|
|
|
// 点脸型图分区:该区 2 秒治疗(验证物理位置对不对)
|
|
onTapRegion: function (e) {
|
|
var mask = parseInt(e.currentTarget.dataset.mask)
|
|
this._send('治疗 2s ' + REGION_LABELS[mask] + ' ' + this.data.selectedWave, {
|
|
region_mask: mask, wavelength: this._waveCode(), brightness: 204,
|
|
hold_time: 2, control: 0x02
|
|
})
|
|
},
|
|
|
|
// 检测指令(与 auto-scan 同参:红光 128 全脸,设备自跑序贯扫描)
|
|
onScanCmd: function () {
|
|
this._send('检测指令 control=0x01', {
|
|
region_mask: 0x1F, wavelength: 2, brightness: 128,
|
|
hold_time: 0, control: 0x01
|
|
})
|
|
},
|
|
|
|
// 全脸当前波长 2 秒
|
|
onTreatAll: function () {
|
|
this._send('治疗 2s 全脸 ' + this.data.selectedWave, {
|
|
region_mask: 0x1F, wavelength: this._waveCode(), brightness: 204,
|
|
hold_time: 2, control: 0x02
|
|
})
|
|
},
|
|
|
|
// 停止 / IDLE
|
|
onStop: function () {
|
|
var self = this
|
|
self._log('停止 → IDLE 全零帧')
|
|
ble.stopTreatment().then(function () { self._log('✓ 已停止') })
|
|
.catch(function (err) { self._log('✗ 停止失败: ' + ((err && err.msg) || '')) })
|
|
},
|
|
|
|
onClearLog: function () { this.setData({ logs: [], frames: 0 }) }
|
|
})
|