feat: add lightweight API and web console

This commit is contained in:
way
2026-09-27 10:21:12 +08:00
parent fd4e2bf0f4
commit f42ea9d4bd
9 changed files with 382 additions and 36 deletions
+43 -18
View File
@@ -2,7 +2,7 @@
set -euo pipefail
cd "$(dirname "$0")"
for required in app/pigway_pi_control.py app/oled_font_5x7.bin config/pigway-pi-control.conf systemd/pigway-pi-control.service; do
for required in app/pigway_pi_control.py app/pigway_pi_control_api.py app/oled_font_5x7.bin web/index.html config/pigway-pi-control.conf systemd/pigway-pi-control.service systemd/pigway-pi-control-api.service; do
if [ ! -f "$required" ]; then
echo "ERROR: required file missing: $required" >&2
exit 1
@@ -37,26 +37,29 @@ fi
pkill -f '/temp_control/temp_control' 2>/dev/null || true
mkdir -p /usr/local/share/pigway-pi-control
install -m 0644 app/oled_font_5x7.bin /usr/local/share/pigway-pi-control/oled_font_5x7.bin
mkdir -p /usr/local/share/pigway-pi-control/web
install -m 0644 web/index.html /usr/local/share/pigway-pi-control/web/index.html
install -m 0755 app/pigway_pi_control.py /usr/local/sbin/pigway-pi-control
install -m 0755 app/pigway_pi_control_api.py /usr/local/sbin/pigway-pi-control-api
# Keep the complete existing configuration, including comments and custom sections.
# New options use runtime defaults until the user chooses to add them.
# The merge below adds only missing documented options.
if [ -f /etc/pigway-pi-control.conf ]; then
cp /etc/pigway-pi-control.conf "/etc/pigway-pi-control.conf.bak.$(date +%Y%m%d-%H%M%S)"
else
install -m 0644 config/pigway-pi-control.conf /etc/pigway-pi-control.conf
fi
# Preserve the existing file verbatim while exposing newly configurable RGB
# defaults. Missing keys are inserted into [led]; existing user values win.
# Preserve the existing file while exposing new defaults. Existing values win.
python3 - /etc/pigway-pi-control.conf <<'PY'
import re,sys
from pathlib import Path
path=Path(sys.argv[1])
text=path.read_text()
defaults=(
sections={
"led":(
("cpu_r",255),("cpu_g",0),("cpu_b",0),
("power_r",255),("power_g",40),("power_b",0),
("memory_r",255),("memory_g",0),("memory_b",255),
@@ -66,33 +69,49 @@ defaults=(
("warning_flash_on_ms",1500),("warning_flash_off_ms",1500),
("critical_flash_on_ms",750),("critical_flash_off_ms",750),
("emergency_flash_on_ms",300),("emergency_flash_off_ms",300),
)
missing=[(key,value) for key,value in defaults
if not re.search(rf"(?m)^\s*{re.escape(key)}\s*=",text)]
if missing:
block="\n# RGB object colors (0..255) and flash timing (milliseconds).\n"
block+="".join(f"{key} = {value}\n" for key,value in missing)
match=re.search(r"(?m)^\[led\]\s*$",text)
),
"api":(("bind","0.0.0.0"),("port",6001),("log_limit",200)),
}
for section,defaults in sections.items():
match=re.search(rf"(?m)^\[{re.escape(section)}\]\s*$",text)
if match:
next_section=re.search(r"(?m)^\[.+\]\s*$",text[match.end():])
pos=match.end()+(next_section.start() if next_section else len(text)-match.end())
text=text[:pos].rstrip()+"\n"+block+"\n"+text[pos:].lstrip("\n")
end=match.end()+(next_section.start() if next_section else len(text)-match.end())
chunk=text[match.end():end]
else:
text=text.rstrip()+"\n\n[led]\n"+block
path.write_text(text)
text=text.rstrip()+f"\n\n[{section}]\n"
match=re.search(rf"(?m)^\[{re.escape(section)}\]\s*$",text)
end=len(text); chunk=""
missing=[(key,value) for key,value in defaults
if not re.search(rf"(?m)^\s*{re.escape(key)}\s*=",chunk)]
if missing:
note="# Added by installer; existing user values are preserved.\n"
block=note+"".join(f"{key} = {value}\n" for key,value in missing)
text=text[:end].rstrip()+"\n"+block+"\n\n"+text[end:].lstrip("\n")
path.write_text(text)
PY
if [ ! -s /etc/pigway-pi-control-api.token ]; then
umask 077
python3 - <<'PY' > /etc/pigway-pi-control-api.token
import secrets
print(secrets.token_urlsafe(32))
PY
fi
chmod 0600 /etc/pigway-pi-control-api.token
install -m 0644 systemd/pigway-pi-control.service /etc/systemd/system/pigway-pi-control.service
install -m 0644 systemd/pigway-pi-control-api.service /etc/systemd/system/pigway-pi-control-api.service
echo "[6/8] 启用/重启服务..."
systemctl daemon-reload
systemctl enable pigway-pi-control.service >/dev/null
systemctl enable pigway-pi-control.service pigway-pi-control-api.service >/dev/null
systemctl restart pigway-pi-control.service
systemctl restart pigway-pi-control-api.service
echo "[7/8] 安装后自检..."
FAIL=0
check() { local label="$1"; shift; if "$@"; then printf " %-30s PASS\n" "$label"; else printf " %-30s FAIL\n" "$label"; FAIL=1; fi; }
APP=/usr/local/sbin/pigway-pi-control
check "Version 3.5.0" grep -Fq 'APP_VERSION="3.5.0"' "$APP"
check "Version 3.6.0" grep -Fq 'APP_VERSION="3.6.0"' "$APP"
check "OLED physical 128x32" grep -Fq 'W,H=128,32' "$APP"
check "OLED MUX 0x1F" grep -Fq '0xA8,0x1F' "$APP"
check "OLED pages 0..3" grep -Fq 'cmd(0x22);cmd(0);cmd(3)' "$APP"
@@ -102,6 +121,9 @@ check "UI right column x=72" grep -Fq 'draw_text_5x7(pix,72,y,right[row])' "$APP
legacy_stopped() { ! systemctl is-active --quiet temp-control.service; }
check "Legacy service stopped" legacy_stopped
check "Service running" systemctl is-active --quiet pigway-pi-control.service
check "API/Web service running" systemctl is-active --quiet pigway-pi-control-api.service
check "API/Web version 3.6.0" grep -Fq 'APP_VERSION="3.6.0"' /usr/local/sbin/pigway-pi-control-api
check "Web UI installed" test -s /usr/local/share/pigway-pi-control/web/index.html
check "P0 health monitor" grep -Fq 'throttled_state' "$APP"
check "Diagnostic command" grep -Fq -- '--diagnose' "$APP"
if [ "$FAIL" -ne 0 ]; then echo "错误:安装后自检未全部通过。"; exit 1; fi
@@ -109,6 +131,9 @@ echo "[8/8] 状态..."
systemctl --no-pager --full status pigway-pi-control.service || true
systemctl --no-pager --full status pigway-pi-control-api.service || true
echo
echo "完成。程序:/usr/local/sbin/pigway-pi-control"
echo "配置:/etc/pigway-pi-control.conf"
echo "Web/API:http://$(hostname -I | awk '{print $1}'):$(awk -F= '/^port[[:space:]]*=/{gsub(/[[:space:]]/,"",$2);print $2;exit}' /etc/pigway-pi-control.conf)"
echo "配置写入 token:sudo cat /etc/pigway-pi-control-api.token"