diff --git a/README.md b/README.md index c3e4641..c228834 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,8 @@ blue:wan green:wlan mmc0:: red:power sim:en sim:en2 sim:sel sim:sel2 - 列出 `/sys/class/leds/` 下所有 LED - 查看 brightness / max_brightness / 当前 trigger -- 打开 / 关闭 LED +- 打开 / 关闭单个 LED +- 页面顶部一键关闭全部 LED - 调整亮度 - 切换 trigger,例如 `none`、`timer`、`netdev`、`mmc0` 等,具体取决于内核暴露的能力 - 设置 `timer` trigger 的 `delay_on` / `delay_off` diff --git a/led_panel.py b/led_panel.py index ed43008..ffd3b97 100755 --- a/led_panel.py +++ b/led_panel.py @@ -69,6 +69,7 @@ async function identify(name){ try{ await api('/api/identify',{name}); toast('Bl async function saveLed(name){ try{ await api('/api/save',{name}); toast('已保存 '+name+',重启后自动恢复'); setTimeout(load,300);}catch(e){toast(e.message,true);} } async function deleteSaved(name){ try{ await api('/api/delete-saved',{name}); toast('已取消持久化 '+name); setTimeout(load,300);}catch(e){toast(e.message,true);} } async function applySaved(){ try{ const r=await api('/api/apply-saved',{}); toast('已应用持久化配置:'+(r.applied||0)+' 个'); setTimeout(load,300);}catch(e){toast(e.message,true);} } +async function turnOffAll(){ try{ const r=await api('/api/all-off',{}); const failed=(r.results||[]).filter(x=>!x.ok); toast(failed.length ? ('已关闭 '+(r.changed||0)+' 个,失败 '+failed.length+' 个') : ('已关闭全部 LED:'+(r.changed||0)+' 个'), failed.length>0); setTimeout(load,300);}catch(e){toast(e.message,true);} } function colorOf(n,b){ const s=n.toLowerCase(); if(Number(b)<=0) return '#475569'; if(s.includes('red')) return '#ef4444'; if(s.includes('green')) return '#22c55e'; if(s.includes('blue')) return '#3b82f6'; if(s.includes('wlan')) return '#22c55e'; if(s.includes('wan')) return '#3b82f6'; if(s.includes('power')) return '#ef4444'; if(s.includes('sim')) return '#f59e0b'; return '#5eead4'; } function esc(s){ return String(s).replace(/[&<>'"]/g, c=>({'&':'&','<':'<','>':'>',"'":''','"':'"'}[c])); } function attr(s){ return esc(s); } @@ -253,6 +254,32 @@ def apply_saved_config() -> List[Dict[str, object]]: results.append({"name": name, "ok": False, "errors": [str(e)]}) return results + +def turn_off_all_leds() -> List[Dict[str, object]]: + results = [] + for led in list_leds(): + name = str(led["name"]) + result: Dict[str, object] = {"name": name, "ok": True, "errors": []} + try: + p = led_path(name) + if (p / "trigger").exists(): + try: + set_trigger(p, "none") + except Exception as e: + result["ok"] = False + result["errors"].append(f"trigger: {e}") + write_text(p / "brightness", "0") + try: + result["brightness"] = int(read_text(p / "brightness") or 0) + except ValueError: + result["brightness"] = read_text(p / "brightness") + except Exception as e: + result["ok"] = False + result["errors"].append(str(e)) + results.append(result) + return results + + def list_leds() -> List[Dict[str, object]]: leds = [] saved_config = load_config() @@ -317,7 +344,7 @@ class Handler(BaseHTTPRequestHandler): def do_GET(self): parsed = urllib.parse.urlparse(self.path) if parsed.path == "/": - body = f"""
{html.escape(str(LED_ROOT))} 下的 LED;配置保存到 {html.escape(str(CONFIG_PATH))};当前 - 个。页面每 5 秒自动刷新。{html.escape(str(LED_ROOT))} 下的 LED;配置保存到 {html.escape(str(CONFIG_PATH))};当前 - 个。页面每 5 秒自动刷新。