refactor(led): drop openvfd sysfs writes, log [vfd] at debug

- WiFi/BT/status/display: no fs/tee; preserve info-level state messages
- install: remove ExecStartPre openvfd init

Made-with: Cursor
This commit is contained in:
stswangzhiping
2026-03-27 16:31:17 +08:00
parent 6ad573e272
commit 402440aadc
2 changed files with 20 additions and 95 deletions

View File

@@ -189,8 +189,6 @@ Wants=NetworkManager.service
[Service] [Service]
Type=simple Type=simple
EnvironmentFile=$ENV_FILE EnvironmentFile=$ENV_FILE
# 部分机型无 openvfd 或路径不同不存在则跳过3528 等新板可忽略)
ExecStartPre=/bin/sh -c 'for p in /sys/devices/platform/openvfd/attr/b1 /sys/devices/platform/openvfd/attr/b2; do [ -e "$p" ] && echo 1 >"$p" 2>/dev/null || true; done'
ExecStart=$NODE_BIN $INSTALL_DIR/bin/clawd.js ExecStart=$NODE_BIN $INSTALL_DIR/bin/clawd.js
WorkingDirectory=$INSTALL_DIR WorkingDirectory=$INSTALL_DIR

View File

@@ -1,42 +1,27 @@
'use strict'; 'use strict';
const fs = require('fs'); const log = require('./logger');
const { execSync } = require('child_process');
const log = require('./logger');
/** /**
* 前面板指示灯控制 * 前面板指示灯 / VFD 逻辑(原 openvfd sysfs
* * 硬件路径因板型而异,当前不直接写 sysfs仅在 debug 记录拟写入内容,业务状态仍以 info 输出。
* WiFi 灯 (b5): 1 = 亮, 0 = 灭(正逻辑)
* - WiFi 已连接且互联网畅通 → 常亮
* - WiFi 连接中(正在尝试) → 闪烁
* - WiFi 未连接 / 无互联网 → 熄灭
* *
* WiFi 灯 (b5): 1 = 亮, 0 = 灭(正逻辑)
* BT 灯 (b6): 1 = 亮, 0 = 灭(正逻辑) * BT 灯 (b6): 1 = 亮, 0 = 灭(正逻辑)
* - BLE 配网进行中 → 闪烁 * SETUP/APPS (b1/b2): 反逻辑,与 claw 激活状态互斥
* - BLE 配网成功 → 常亮
* - 蓝牙不工作 → 熄灭
* *
* SETUP 灯 (b2): 0 = 亮, 1 = 灭(反逻辑,与 APPS 互斥) * 恢复真机显示时:可在此类 _write 中接新驱动或 CLAWD_* 路径。
* APPS 灯 (b1): 0 = 亮, 1 = 灭(反逻辑,与 SETUP 互斥)
* - claw 未激活 → SETUP 亮APPS 灭
* - claw 已激活 → APPS 亮SETUP 灭
*/ */
const LED_PATH = process.env.CLAWD_LED_PATH || '/sys/devices/platform/openvfd/attr/b5'; const BLINK_INTERVAL_MS = 500;
const BT_LED_PATH = process.env.CLAWD_BT_LED_PATH || '/sys/devices/platform/openvfd/attr/b6';
const SETUP_LED_PATH = '/sys/devices/platform/openvfd/attr/b1'; // 物理 SETUP 灯
const APPS_LED_PATH = '/sys/devices/platform/openvfd/attr/b2'; // 物理 APPS 灯
const BLINK_INTERVAL_MS = 500; // 闪烁间隔ms
class WifiLed { class WifiLed {
constructor() { constructor() {
this._blinkTimer = null; this._blinkTimer = null;
this._blinkState = false; this._blinkState = false;
this._current = null; // 'on' | 'off' | 'blink' this._current = null;
} }
/** 常亮 */
on() { on() {
if (this._current === 'on') return; if (this._current === 'on') return;
this._stopBlink(); this._stopBlink();
@@ -45,7 +30,6 @@ class WifiLed {
log.info('led', 'WiFi 指示灯 → 常亮'); log.info('led', 'WiFi 指示灯 → 常亮');
} }
/** 熄灭 */
off() { off() {
if (this._current === 'off') return; if (this._current === 'off') return;
this._stopBlink(); this._stopBlink();
@@ -54,7 +38,6 @@ class WifiLed {
log.info('led', 'WiFi 指示灯 → 熄灭'); log.info('led', 'WiFi 指示灯 → 熄灭');
} }
/** 闪烁(连接中) */
blink(intervalMs = BLINK_INTERVAL_MS) { blink(intervalMs = BLINK_INTERVAL_MS) {
if (this._current === 'blink') return; if (this._current === 'blink') return;
this._stopBlink(); this._stopBlink();
@@ -68,15 +51,12 @@ class WifiLed {
log.info('led', 'WiFi 指示灯 → 闪烁'); log.info('led', 'WiFi 指示灯 → 闪烁');
} }
/** 释放资源,关灯 */
destroy() { destroy() {
this._stopBlink(); this._stopBlink();
this._write(0); this._write(0);
this._current = 'off'; this._current = 'off';
} }
// ── 内部 ──────────────────────────────────────────────────────────────────
_stopBlink() { _stopBlink() {
if (this._blinkTimer) { if (this._blinkTimer) {
clearInterval(this._blinkTimer); clearInterval(this._blinkTimer);
@@ -85,30 +65,17 @@ class WifiLed {
} }
_write(val) { _write(val) {
try { log.debug('led', `[vfd] WiFi LED (b5) <= ${val}`);
fs.writeFileSync(LED_PATH, String(val));
} catch (e) {
log.warn('led', `写入失败 (${LED_PATH}): ${e.message}`);
}
} }
} }
// ── 蓝牙指示灯 ───────────────────────────────────────────────────────────────
/**
* BT 指示灯b6正逻辑1 = 亮0 = 灭。
* blink() — BLE 配网进行中
* on() — BLE 配网成功 / 蓝牙功能正常
* off() — 蓝牙不工作
*/
class BtLed { class BtLed {
constructor() { constructor() {
this._blinkTimer = null; this._blinkTimer = null;
this._blinkState = false; this._blinkState = false;
this._current = null; // 'on' | 'off' | 'blink' this._current = null;
} }
/** 常亮(配网成功) */
on() { on() {
if (this._current === 'on') return; if (this._current === 'on') return;
this._stopBlink(); this._stopBlink();
@@ -117,7 +84,6 @@ class BtLed {
log.info('led', 'BT 指示灯 → 常亮'); log.info('led', 'BT 指示灯 → 常亮');
} }
/** 熄灭(蓝牙不工作) */
off() { off() {
if (this._current === 'off') return; if (this._current === 'off') return;
this._stopBlink(); this._stopBlink();
@@ -126,7 +92,6 @@ class BtLed {
log.info('led', 'BT 指示灯 → 熄灭'); log.info('led', 'BT 指示灯 → 熄灭');
} }
/** 闪烁BLE 配网进行中) */
blink(intervalMs = BLINK_INTERVAL_MS) { blink(intervalMs = BLINK_INTERVAL_MS) {
if (this._current === 'blink') return; if (this._current === 'blink') return;
this._stopBlink(); this._stopBlink();
@@ -140,7 +105,6 @@ class BtLed {
log.info('led', 'BT 指示灯 → 闪烁'); log.info('led', 'BT 指示灯 → 闪烁');
} }
/** 释放资源,关灯 */
destroy() { destroy() {
this._stopBlink(); this._stopBlink();
this._write(0); this._write(0);
@@ -155,36 +119,21 @@ class BtLed {
} }
_write(val) { _write(val) {
try { log.debug('led', `[vfd] BT LED (b6) <= ${val}`);
fs.writeFileSync(BT_LED_PATH, String(val));
} catch (e) {
log.warn('led', `写入失败 (${BT_LED_PATH}): ${e.message}`);
}
} }
} }
// ── VFD 显示屏 ────────────────────────────────────────────────────────────────
const DISPLAY_PATH = '/sys/devices/platform/openvfd/attr/led';
/**
* VFD 显示屏控制。
* #m3 <text> 手动模式,显示指定文字
* #s1 系统时钟模式,显示当前时间
*/
class Display { class Display {
constructor() { constructor() {
this._blinkTimer = null; this._blinkTimer = null;
} }
/** 网络断开 / AP 模式 → 显示 "AP " */
showAP() { showAP() {
this._stopBlink(); this._stopBlink();
this._write('#m3AP '); this._write('#m3AP ');
log.info('display', '显示屏 → AP'); log.info('display', '显示屏 → AP');
} }
/** WS 连接中(失败次数 < 3→ 显示 "Conn" 闪烁 */
showConn() { showConn() {
this._stopBlink(); this._stopBlink();
this._write('#m3Conn'); this._write('#m3Conn');
@@ -198,27 +147,23 @@ class Display {
this._blinkTimer = setTimeout(blink, 1000); this._blinkTimer = setTimeout(blink, 1000);
} }
/** 网络正常但 VPS 不可达 → 显示 "Err0" */
showErr0() { showErr0() {
this._stopBlink(); this._stopBlink();
this._write('#m3Err0'); this._write('#m3Err0');
log.info('display', '显示屏 → Err0'); log.info('display', '显示屏 → Err0');
} }
/** 网络已连接 → 显示时间 */
showTime() { showTime() {
this._stopBlink(); this._stopBlink();
this._write('#s1'); this._write('#s1');
log.info('display', '显示屏 → 时间'); log.info('display', '显示屏 → 时间');
} }
/** 未激活 + 连网 → 显示 PIN 码4 位数字)并闪烁 */
showPin(pin) { showPin(pin) {
this._stopBlink(); this._stopBlink();
const s = String(pin || '').padStart(4, '0').slice(-4); const s = String(pin || '').padStart(4, '0').slice(-4);
this._write('#m2' + s); this._write('#m2' + s);
log.info('display', `显示屏 → PIN: ${s}(闪烁)`); log.info('display', `显示屏 → PIN: ${s}(闪烁)`);
// 亮 1s → 灭 0.5s → 循环
let visible = true; let visible = true;
const blink = () => { const blink = () => {
visible = !visible; visible = !visible;
@@ -237,51 +182,33 @@ class Display {
} }
_write(val) { _write(val) {
try { log.debug('display', `[vfd] ${val}`);
execSync(`echo "${val}" | tee ${DISPLAY_PATH} > /dev/null`, { timeout: 3000 });
} catch (e) {
log.warn('display', `写入失败: ${e.message}`);
}
} }
} }
// ── SETUP / APPS 状态灯 ───────────────────────────────────────────────────────
/**
* SETUP 灯b2与 APPS 灯b1互斥控制。
* 两灯均为反逻辑:写 0 = 亮,写 1 = 灭。
*/
class StatusLed { class StatusLed {
/** claw 未激活 → SETUP 亮APPS 灭 */
setSetup() { setSetup() {
this._write(SETUP_LED_PATH, 0); // SETUP 亮 this._write('SETUP', 0);
this._write(APPS_LED_PATH, 1); // APPS 灭 this._write('APPS', 1);
log.info('led', '状态灯 → SETUP未激活'); log.info('led', '状态灯 → SETUP未激活');
} }
/** claw 已激活 → APPS 亮SETUP 灭 */
setApps() { setApps() {
this._write(SETUP_LED_PATH, 1); // SETUP 灭 this._write('SETUP', 1);
this._write(APPS_LED_PATH, 0); // APPS 亮 this._write('APPS', 0);
log.info('led', '状态灯 → APPS已激活'); log.info('led', '状态灯 → APPS已激活');
} }
/** 两灯全灭(进程退出时调用) */
off() { off() {
this._write(SETUP_LED_PATH, 1); this._write('SETUP', 1);
this._write(APPS_LED_PATH, 1); this._write('APPS', 1);
} }
_write(path, val) { _write(which, val) {
try { log.debug('led', `[vfd] 状态灯 ${which} (b1/b2 反逻辑) <= ${val}`);
fs.writeFileSync(path, String(val));
} catch (e) {
log.warn('led', `写入失败 (${path}): ${e.message}`);
}
} }
} }
// 全局单例,整个进程共用
module.exports = new WifiLed(); module.exports = new WifiLed();
module.exports.bt = new BtLed(); module.exports.bt = new BtLed();
module.exports.status = new StatusLed(); module.exports.status = new StatusLed();