Files
kushidouandClaude Fable 5 e6fbe550bb 重构屏幕控制引擎 + 新增 Web 监控面板
- ScreenManager: 基于优先级(9/5/0)的统一屏幕控制引擎,替代 _tick 中的
  散乱 if-else 逻辑
- 四个亮屏事件: scheduled(p9), sensor(p9), manual(p5), external(p0)
- GPIO 回调: 电平变化立即触发亮屏(异步线程,不阻塞轮询)
- _fast_check: 每秒轻量评估,提高息屏超时精度(±1s 替代 ±30s)
- padsleep_web: 通过 IPC 读取守护进程状态的实时 Web 面板
  (GPIO 电平/屏幕状态/ADB 连接,端口 31400)
- padsleep-web.service: 关联 padsleep.service 的自启动服务
- install.sh: 修复 venv 初始化目录上下文,使用 requirements.txt
- IpcClient: 修复 socket 复用导致交替失败的问题
- padsleep_tui: 适配 ScreenManager 状态显示

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 00:15:07 +08:00

190 lines
6.3 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# padsleep_adb 安装脚本
# 用法: sudo ./install.sh
#
# 将程序安装到 /opt/apps/padsleep,创建命令行软链接。
# 自动创建 Python 虚拟环境并安装依赖。
# 代码中 SCRIPT_DIR 使用 Path(__file__).resolve().parent
# 会自动适配安装路径,无需修改代码。
set -e
INSTALL_DIR="/opt/apps/padsleep"
BIN_DIR="/usr/local/bin"
SERVICE_DIR="/etc/systemd/system"
VENV_DIR="$INSTALL_DIR/.venv"
PYTHON_BIN="$VENV_DIR/bin/python3"
# 颜色
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
info() { echo -e "${GREEN}[INFO]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; }
# ── 检查 root ──
if [ "$EUID" -ne 0 ]; then
error "请使用 sudo 运行此安装脚本"
echo " sudo $0"
exit 1
fi
# ── 确定源目录(脚本所在目录)──
SRC_DIR="$(cd "$(dirname "$0")" && pwd)"
if [ ! -f "$SRC_DIR/padsleep.py" ]; then
error "在 $SRC_DIR 中未找到 padsleep.py"
echo "请在 padsleep_adb 项目目录中运行此脚本"
exit 1
fi
# ── 确定运行用户(sudo 的原用户)──
RUN_USER="${SUDO_USER:-}"
if [ -z "$RUN_USER" ]; then
if [ -f "$SRC_DIR/padsleep.service" ]; then
RUN_USER=$(grep '^User=' "$SRC_DIR/padsleep.service" | head -1 | cut -d= -f2)
fi
fi
if [ -z "$RUN_USER" ]; then
RUN_USER="$(whoami)"
fi
RUN_USER_HOME=$(eval echo "~$RUN_USER" 2>/dev/null || echo "/home/$RUN_USER")
info "源目录: $SRC_DIR"
info "安装目标: $INSTALL_DIR"
info "运行用户: $RUN_USER"
# ── 创建目标目录 ──
mkdir -p "$INSTALL_DIR"
info "已创建目录 $INSTALL_DIR"
# ── 复制文件 ──
cp "$SRC_DIR/padsleep.py" "$INSTALL_DIR/"
cp "$SRC_DIR/padsleep_tui.py" "$INSTALL_DIR/"
cp "$SRC_DIR/padsleep_web.py" "$INSTALL_DIR/" 2>/dev/null || true
cp -r "$SRC_DIR/templates" "$INSTALL_DIR/" 2>/dev/null || true
cp "$SRC_DIR/requirements.txt" "$INSTALL_DIR/" 2>/dev/null || true
# 配置文件:目标不存在则复制,存在则保留
if [ ! -f "$INSTALL_DIR/config.json" ]; then
cp "$SRC_DIR/config.json" "$INSTALL_DIR/"
info "已创建默认配置文件 $INSTALL_DIR/config.json"
else
warn "配置文件已存在,保留现有配置: $INSTALL_DIR/config.json"
fi
# 日志文件:创建空文件
touch "$INSTALL_DIR/padsleep.log"
chmod 644 "$INSTALL_DIR/padsleep.log"
# ── 创建 Python 虚拟环境并安装依赖 ──
# 进入目标目录确保 venv 上下文正确
cd "$INSTALL_DIR"
if [ ! -d "$VENV_DIR" ]; then
info "正在创建 Python 虚拟环境..."
python3 -m venv .venv
info "虚拟环境已创建: $VENV_DIR"
else
info "虚拟环境已存在,跳过创建"
fi
info "正在安装 Python 依赖 (requirements.txt)..."
if [ -f "$INSTALL_DIR/requirements.txt" ]; then
.venv/bin/pip install --quiet -r requirements.txt 2>&1 || {
warn "pip 安装失败,尝试逐个安装..."
.venv/bin/pip install --quiet adbutils rpi-lgpio flask flask-socketio 2>&1 || {
warn "pip 安装仍然失败,请手动执行: cd $INSTALL_DIR && .venv/bin/pip install -r requirements.txt"
}
}
else
.venv/bin/pip install --quiet adbutils rpi-lgpio flask flask-socketio 2>&1 || \
warn "pip 安装失败,请手动安装依赖"
fi
info "Python 依赖安装完成"
cd "$SRC_DIR" # 回到源目录
# 设置执行权限
chmod 755 "$INSTALL_DIR/padsleep.py"
chmod 755 "$INSTALL_DIR/padsleep_tui.py"
# 修正所有权和权限:确保运行用户有权读写配置和日志
chown -R "$RUN_USER:$RUN_USER" "$INSTALL_DIR" 2>/dev/null || chown -R "$RUN_USER" "$INSTALL_DIR" 2>/dev/null
chmod 755 "$INSTALL_DIR"
chmod 644 "$INSTALL_DIR/padsleep.log" 2>/dev/null
info "文件所有权已设置为 $RUN_USER"
# ── 创建命令包装脚本(使用 venv Python)──
create_wrapper() {
local script="$1" # padsleep.py 或 padsleep_tui.py
local link="$2" # /usr/local/bin/padsleep
# 先移除旧文件/软链接,避免 cat 跟随链接覆盖源文件
rm -f "$link"
cat > "$link" <<WRAPPER
#!/bin/bash
exec "$PYTHON_BIN" "$INSTALL_DIR/$script" "\$@"
WRAPPER
chmod 755 "$link"
}
create_wrapper "padsleep.py" "$BIN_DIR/padsleep"
create_wrapper "padsleep_tui.py" "$BIN_DIR/padsleep-config"
if [ -f "$INSTALL_DIR/padsleep_web.py" ]; then
create_wrapper "padsleep_web.py" "$BIN_DIR/padsleep-web"
fi
info "已创建命令入口:"
info " $BIN_DIR/padsleep → 启动守护进程 ($PYTHON_BIN)"
info " $BIN_DIR/padsleep-config → 启动 TUI 配置工具 ($PYTHON_BIN)"
info " $BIN_DIR/padsleep-web → 启动 Web 监控面板 ($PYTHON_BIN)"
# ── 可选:复制 systemd 服务 ──
install_service() {
local src="$1"
local dst="$2"
local script="$3"
if [ ! -f "$src" ]; then
warn "服务文件不存在: $src,跳过"
return
fi
cp "$src" "$dst"
sed -i "s|WorkingDirectory=.*|WorkingDirectory=$INSTALL_DIR|" "$dst"
sed -i "s|ExecStart=.*|ExecStart=$PYTHON_BIN $INSTALL_DIR/$script|" "$dst"
sed -i "s|^User=.*|User=$RUN_USER|" "$dst"
info "已安装 $dst"
}
install_service "$SRC_DIR/padsleep.service" "$SERVICE_DIR/padsleep.service" "padsleep.py"
install_service "$SRC_DIR/padsleep-web.service" "$SERVICE_DIR/padsleep-web.service" "padsleep_web.py"
systemctl daemon-reload
info "systemd 已重载"
echo ""
info "启用服务(自启动 + 立即启动):"
info " sudo systemctl enable --now padsleep padsleep-web"
# ── 检查 ADB ──
if command -v adb &>/dev/null; then
info "ADB 已安装: $(adb --version 2>&1 | head -1)"
else
warn "ADB 未安装,请执行: sudo apt install adb"
fi
# ── 完成 ──
echo ""
echo -e "${GREEN}═══════════════════════════════════════${NC}"
info "安装完成!"
echo ""
info "使用方法:"
echo " 1. 启动守护进程: padsleep"
echo " 2. 打开 TUI 配置界面: padsleep-config"
echo " 3. 打开 Web 监控面板: padsleep-web"
echo " 4. 注册系统服务: sudo systemctl enable --now padsleep padsleep-web"
echo " 5. Web 面板地址: http://树莓派IP:31400"
echo ""
info "配置文件: $INSTALL_DIR/config.json"
info "日志文件: $INSTALL_DIR/padsleep.log"
echo -e "${GREEN}═══════════════════════════════════════${NC}"