// 显示用的小工具:单位换算、每一路的健康状态。 export const mA = ua => (ua == null ? '—' : (ua / 1000).toFixed(ua >= 100000 || ua <= -100000 ? 0 : 1)) export const V = mv => (mv == null ? '—' : (mv / 1000).toFixed(3)) export const C = mc => (mc == null ? '—' : (mc / 1000).toFixed(1)) // 功率 = 电压 × 电流:mV × µA = nW,显示成 W(两位小数,手机主板一般零点几到十几瓦) export const mW = (mv, ua) => (mv == null || ua == null ? null : mv * ua / 1e6) export const W = (mv, ua) => (mv == null || ua == null ? '—' : (mv * ua / 1e9).toFixed(2)) // 五路主板合计功率(mW):只算读得到的路;一路都读不到回 null export function railsMw(rails) { let s = null for (const r of rails || []) if (r?.mv != null && r?.ua != null) s = (s ?? 0) + r.mv * r.ua / 1e6 return s } export function ago(ts) { if (!ts) return '从未' const s = Math.round((Date.now() - ts) / 1000) if (s < 60) return `${s} 秒前` if (s < 3600) return `${Math.round(s / 60)} 分钟前` if (s < 86400) return `${Math.round(s / 3600)} 小时前` return `${Math.round(s / 86400)} 天前` } export function fmtTime(ts) { if (!ts) return '' const d = new Date(ts) const p = n => String(n).padStart(2, '0') return `${d.getMonth() + 1}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}` } // 执行器状态(firmware t_actuator_state_str) export const ACT_ZH = { idle: '空闲', 'hr-off': '断电中', 'hr-ramp': '上电中', 'hr-pg': '等 PG', 'key-hold': '按键中', 'edl-short': '进 EDL', 'edl-enum': '等枚举', cleanup: '收尾', } // 一路的健康状态 → { level, text }。level 决定颜色: // ok 绿 / busy 蓝 / warn 橙 / bad 红 / off 深灰 / empty 浅灰 / lost 灰(通信中断) export function railHealth(board, r) { if (!board || board.stale || !board.online) return { level: 'lost', text: '通信中断' } if (!r) return { level: 'lost', text: '无数据' } if (!r.pr) return { level: 'empty', text: '空槽' } if (r.st && r.st !== 'idle') return { level: 'busy', text: ACT_ZH[r.st] || r.st } if (!r.en) return { level: 'off', text: '已断电' } // 固件 ≥0.1.5 刷机模式:手机充电器把节点顶高时 eFuse(TPS25940A)进入反向阻断,FLT 随之拉低 —— // 2026-09-28 台架实测与 RCB 同进同退,是正常指示,不是故障。模式外的 FLT 仍按故障标红。 if (r.chg > 0) return { level: 'busy', text: r.flt ? '刷机模式 · 充电中' : '刷机模式' } if (r.flt) return { level: 'bad', text: 'eFuse 故障' } if (r.pg === false) return { level: 'bad', text: 'PG 丢失' } if (r.mv == null || r.ua == null) return { level: 'warn', text: '读不到' } return { level: 'ok', text: '运行' } } // 状态色引用 theme.css 的变量:亮 / 暗两套,切换时自动跟着变。只用来表示状态,旁边一定有文字。 export const LEVEL_COLOR = { ok: 'var(--st-ok)', busy: 'var(--st-busy)', warn: 'var(--st-warn)', bad: 'var(--st-bad)', off: 'var(--st-off)', empty: 'var(--st-empty)', lost: 'var(--st-lost)', } export const RECOVERY_ZH = { idle: '正常', soft: '已长按电源', hard: '已断电重启', gave_up: '已放弃(需人工)', } export const REASON_ZH = { flat: '电流平直(疑似卡死)', low: '电流过低(疑似关机)', recovered: '已恢复', rate_limit: '一小时内动作过多', manual_reset: '人工复位', }