#!/bin/bash # 在 149 设备上自动验证 Nextion 串口屏显示 # 用法: ./scripts/verify_nextion_149.sh [remote_host] [remote_user] [remote_pass] [remote_dir] set -e REMOTE_HOST="${1:-192.168.199.149}" REMOTE_USER="${2:-root}" REMOTE_PASS="${3:-123456}" REMOTE_DIR="${4:-/root/dzxj_dtu}" PORT=5001 GREEN='\033[0;32m' RED='\033[0;31m' YELLOW='\033[1;33m' NC='\033[0m' pass_count=0 fail_count=0 info() { echo -e "${GREEN}[INFO]${NC} $1"; } warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } err() { echo -e "${RED}[FAIL]${NC} $1"; } ok() { echo -e "${GREEN}[PASS]${NC} $1"; pass_count=$((pass_count+1)); } fail() { echo -e "${RED}[FAIL]${NC} $1"; fail_count=$((fail_count+1)); } # 检查 expect 是否安装 if ! command -v expect &>/dev/null; then err "本机缺少 expect,请先安装: apt-get install expect 或 brew install expect" exit 1 fi # 检查 SSH 连通性 info "检查 149 SSH 连通性..." if ! ping -c 1 -W 2 "$REMOTE_HOST" >/dev/null 2>&1; then fail "无法 ping 通 $REMOTE_HOST" exit 1 fi ok "SSH 目标 $REMOTE_HOST 可达" # 生成远程验证 expect 脚本 VERIFY_EXP=$(mktemp /tmp/verify_nextion_149.XXXXXX.exp) cat > "$VERIFY_EXP" << 'EOF' #!/usr/bin/expect -f set timeout 30 set remote_dir [lindex $argv 0] set remote_user [lindex $argv 1] set remote_host [lindex $argv 2] set remote_pass [lindex $argv 3] set port [lindex $argv 4] spawn ssh $remote_user@$remote_host expect { "*yes/no*" { send "yes\r"; exp_continue } "*password:*" { send "$remote_pass\r" } timeout { puts "SSH_TIMEOUT"; exit 1 } } expect "*#*" # 1. 检查 /dev/ttyS9 send "echo '===CHECK_TTYS9===' && ls -la /dev/ttyS9 2>&1\r" expect "*#*" # 2. 检查屏幕串口权限 send "echo '===CHECK_PERMS===' && test -r /dev/ttyS9 && test -w /dev/ttyS9 && echo 'TTYS9_RW_OK' || echo 'TTYS9_RW_FAIL'\r" expect "*#*" # 3. 检查后端进程 send "echo '===CHECK_PROCESS===' && ps aux | grep '[p]ython.*app.py' | head -1\r" expect "*#*" # 4. 检查端口监听 send "echo '===CHECK_PORT===' && (ss -tulpn 2>/dev/null | grep :$port || netstat -tulpn 2>/dev/null | grep :$port || echo 'PORT_NOT_LISTEN')\r" expect "*#*" # 5. 调用 /api/screen/status send "echo '===SCREEN_STATUS===' && curl -s http://localhost:$port/api/screen/status\r" expect "*#*" # 6. 调用 /api/screen/refresh send "echo '===SCREEN_REFRESH===' && curl -s -X POST http://localhost:$port/api/screen/refresh\r" expect "*#*" # 7. 检查日志中是否有 Nextion 连接成功/失败 send "echo '===APP_LOG_NEXTION===' && tail -n 30 $remote_dir/backend/app_service.log | grep -i -E 'nextion|屏幕' | tail -10\r" expect "*#*" # 8. 直接向串口屏发测试指令 send "echo '===SCREEN_DIRECT_TEST===' && (echo -e 't2.txt=\"test149\"\\xff\\xff\\xff' > /dev/ttyS9 2>&1 && echo 'DIRECT_SEND_OK' || echo 'DIRECT_SEND_FAIL')\r" expect "*#*" send "exit\r" expect eof EOF chmod +x "$VERIFY_EXP" info "在 149 上执行验证..." OUTPUT=$("$VERIFY_EXP" "$REMOTE_DIR" "$REMOTE_USER" "$REMOTE_HOST" "$REMOTE_PASS" "$PORT" 2>/dev/null) rm -f "$VERIFY_EXP" # 解析输出 echo "$OUTPUT" | grep -q "===CHECK_TTYS9===" && ok "SSH 登录成功" || fail "SSH 登录失败" if echo "$OUTPUT" | grep -q "/dev/ttyS9"; then ok "/dev/ttyS9 存在" else fail "/dev/ttyS9 不存在" fi if echo "$OUTPUT" | grep -q "TTYS9_RW_OK"; then ok "/dev/ttyS9 可读可写" else fail "/dev/ttyS9 读写权限不足" fi if echo "$OUTPUT" | grep -q "python.*app.py"; then ok "后端 app.py 进程正在运行" else fail "后端 app.py 进程未运行" fi if echo "$OUTPUT" | grep -q ":$PORT"; then ok "端口 $PORT 正在监听" else fail "端口 $PORT 未监听" fi if echo "$OUTPUT" | grep -q '"success": true.*"connected": true'; then ok "屏幕串口已连接 (/api/screen/status)" elif echo "$OUTPUT" | grep -q '"success": true.*"connected": false'; then fail "屏幕串口未连接 (/api/screen/status)" else fail "无法获取 /api/screen/status" fi if echo "$OUTPUT" | grep -q '"success": true.*屏幕已刷新'; then ok "手动刷新屏幕成功 (/api/screen/refresh)" elif echo "$OUTPUT" | grep -q '"success": false'; then warn "手动刷新屏幕返回失败(可能是屏幕未连接或没有 panel)" else fail "无法调用 /api/screen/refresh" fi if echo "$OUTPUT" | grep -qi "Nextion 屏幕串口已连接\|屏幕已刷新"; then ok "应用日志中有 Nextion 相关记录" else warn "应用日志中未找到 Nextion 相关记录" fi if echo "$OUTPUT" | grep -q "DIRECT_SEND_OK"; then ok "可直接向 /dev/ttyS9 发送指令" else fail "无法直接向 /dev/ttyS9 发送指令" fi info "验证完成: 通过 $pass_count 项, 失败 $fail_count 项" if [ "$fail_count" -eq 0 ]; then info "全部检查通过。请肉眼确认屏幕上显示:终端名、版本、MQTT 状态、24 端口图标。" exit 0 else err "存在失败项,请根据上方输出排查。" exit 1 fi