新增 GPIOEventDetector 后台线程,以 50ms 间隔轮询 GPIO 引脚。 检测到电平变化时唤醒屏幕并启动 60 秒倒计时,到期无新变化则息屏。 - 添加 GPIOEventDetector 类,支持 RPi.GPIO 硬读取和 Mock 回退 - 集成到 PadSleepApp 主循环,GPIO 触发优先级高于定时亮屏时段 - TUI 状态面板新增 GPIO 行,显示引脚号和倒计时 - 支持通过配置文件调整引脚号(gpio_pin)和倒计时长度 - install.sh 修复:补装 rpi-lgpio 依赖 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
161 lines
5.3 KiB
Bash
Executable File
161 lines
5.3 KiB
Bash
Executable File
#!/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/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 虚拟环境 ──
|
||
if [ ! -d "$VENV_DIR" ]; then
|
||
info "正在创建 Python 虚拟环境..."
|
||
python3 -m venv "$VENV_DIR"
|
||
info "虚拟环境已创建: $VENV_DIR"
|
||
else
|
||
info "虚拟环境已存在,跳过创建"
|
||
fi
|
||
|
||
# ── 安装 Python 依赖 ──
|
||
info "正在安装 Python 依赖..."
|
||
"$VENV_DIR/bin/pip" install --quiet adbutils rpi-lgpio 2>&1 || {
|
||
warn "pip 安装失败,尝试离线安装..."
|
||
if [ -f "$SRC_DIR/.venv" ]; then
|
||
cp -r "$SRC_DIR/.venv" "$VENV_DIR"
|
||
fi
|
||
}
|
||
info "Python 依赖安装完成"
|
||
|
||
# 设置执行权限
|
||
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"
|
||
info "已创建命令入口:"
|
||
info " $BIN_DIR/padsleep → 启动守护进程 ($PYTHON_BIN)"
|
||
info " $BIN_DIR/padsleep-config → 启动 TUI 配置工具 ($PYTHON_BIN)"
|
||
|
||
# ── 可选:复制 systemd 服务 ──
|
||
if [ -f "$SRC_DIR/padsleep.service" ]; then
|
||
cp "$SRC_DIR/padsleep.service" "$SERVICE_DIR/padsleep.service"
|
||
sed -i "s|WorkingDirectory=.*|WorkingDirectory=$INSTALL_DIR|" "$SERVICE_DIR/padsleep.service"
|
||
sed -i "s|ExecStart=.*|ExecStart=$PYTHON_BIN $INSTALL_DIR/padsleep.py|" "$SERVICE_DIR/padsleep.service"
|
||
sed -i "s|^User=.*|User=$RUN_USER|" "$SERVICE_DIR/padsleep.service"
|
||
systemctl daemon-reload
|
||
info "已复制 systemd 服务文件: $SERVICE_DIR/padsleep.service"
|
||
info "服务用户已设为: $RUN_USER"
|
||
info "可执行以下命令启用:"
|
||
info " sudo systemctl enable --now padsleep"
|
||
fi
|
||
|
||
# ── 检查 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. 打开配置界面: padsleep-config"
|
||
echo " 3. 注册系统服务: sudo systemctl enable --now padsleep"
|
||
echo ""
|
||
info "配置文件: $INSTALL_DIR/config.json"
|
||
info "日志文件: $INSTALL_DIR/padsleep.log"
|
||
echo -e "${GREEN}═══════════════════════════════════════${NC}"
|