#!/bin/bash # iOS 添加用例批量调试:每个用例前用 WDA terminate/launch 复位到首页,跑完记录结果。 # WDA 须已在 localhost:8100。失败不阻塞,继续下一个。 set -u cd "$(dirname "$0")/.." export PLATFORM=ios SOAK_MODE=1 BUNDLE=com.wohand.wohand LOG=reports/ios-adds.log : > "$LOG" # iOS 阶段起点:清空 .results.json,使 iOS 合并报告(iOSAdds/iOSAll)只含 iOS 结果。 # 否则会 append 到 Android 阶段(run-p0-all 跑完未清)的记录后 → iOSAll 把 Android 的 ble/wifi 记录一并计入(总数虚高,如 267)。 # 仅在此清(iOS 阶段开头);run-ios-controls 不清,以便 iOSAll 含「添加+控制」全程 iOS 结果。 rm -f reports/.results.json # WDA 健康检查 + 恢复:/status 不通则重启 iproxy 端口转发(覆盖过夜端口转发断开;设备上 WDA 进程仍在即恢复)。 ensure_wda(){ for t in 1 2 3; do curl -s --max-time 5 http://localhost:8100/status 2>/dev/null | grep -q '"ready"' && return 0 echo "[wda] /status 不通,重启 iproxy(第 $t 次)..." | tee -a "$LOG" pkill -f "iproxy 8100" 2>/dev/null; sleep 1 local udid; udid=$(idevice_id -l 2>/dev/null | head -1) nohup iproxy 8100 8100 -u "$udid" >/dev/null 2>&1 & sleep 5 done curl -s --max-time 5 http://localhost:8100/status 2>/dev/null | grep -q '"ready"' && return 0 echo "[wda] !! WDA 仍不可达(设备上 WDA 进程可能已退出,需手动重启 WDA)" | tee -a "$LOG"; return 1 } reset_home(){ ensure_wda || return 1 local sid sid=$(curl -s --max-time 5 http://localhost:8100/status 2>/dev/null | grep -oE '"sessionId" *: *"[^"]*"' | sed 's/.*"\([^"]*\)"$/\1/') [ -z "$sid" ] && { echo "[reset] 无 WDA session(WDA 掉了?)" | tee -a "$LOG"; return 1; } curl -s -X POST "http://localhost:8100/session/$sid/wda/apps/terminate" -H 'Content-Type: application/json' -d "{\"bundleId\":\"$BUNDLE\"}" >/dev/null 2>&1 sleep 1 curl -s -X POST "http://localhost:8100/session/$sid/wda/apps/launch" -H 'Content-Type: application/json' -d "{\"bundleId\":\"$BUNDLE\"}" >/dev/null 2>&1 sleep 3 } # iOS 全量添加清单(对齐 Android run-p0-all.sh 的 ADD,补 iOS 专属差异): # - plug 三区域加 PLUG_OTHER_PAIRING=1(iOS 配对后弹 "Add to HomeKit",需点 Other Pairing → Yes 才进配网) # - WiFi 已统一用 Android 配置(ASUS_30),由 PLATFORM=ios + wifi.config 回落自动生效 # - 锁/摄像头(含 doorbell 视频门铃)添加跳过:iOS 需扫码/校准无方案(控制类已另覆盖) ADDS=( # —— BLE(物理接继电器口,不配网) —— "bot|npx vitest run tests/bot/bot_connect.test.ts" "meter|npx vitest run tests/meter/meter_connect.test.ts" "meter_plus|npx vitest run tests/meter/meter_plus_connect.test.ts" "outdoor_meter|npx vitest run tests/meter/outdoor_meter_connect.test.ts" "meter_pro|npx vitest run tests/meter/meter_pro_connect.test.ts" "motion_sensor|npx vitest run tests/sensor/motion_sensor_connect.test.ts" "presence_sensor|npx vitest run tests/sensor/presence_sensor_connect.test.ts" "contact_sensor|npx vitest run tests/sensor/contact_sensor_connect.test.ts" "remote|npx vitest run tests/remote/remote_connect.test.ts" "find_card|npx vitest run tests/find_card/find_card_connect.test.ts" "safety_alarm|npx vitest run tests/safety_alarm/safety_alarm_connect.test.ts" "water_detector|npx vitest run tests/water_detector/water_detector_connect.test.ts" "curtain|npx vitest run tests/curtain/curtain_connect.test.ts" "curtain3_2b|CURTAIN_DEVICE='Curtain3 2B' CURTAIN_CALIBRATE=1 npx vitest run tests/curtain/curtain_connect.test.ts" "curtain3_2025|CURTAIN_CALIBRATE=1 npx vitest run tests/curtain/curtain3_2025_connect.test.ts" "keypad_vision|npx vitest run tests/keypad/keypad_vision_connect.test.ts" "keypad_touch|npx vitest run tests/keypad/keypad_touch_connect.test.ts" # —— WiFi Hub 类 —— "hub_mini|npx vitest run tests/hub/hub_connect.test.ts" "hub_matter|npx vitest run tests/hub/hub_matter_connect.test.ts" "hub3|npx vitest run tests/hub/hub3_connect.test.ts" "hub_plus|npx vitest run tests/hub/hub_plus_connect.test.ts" "relay_switch|npx vitest run tests/hub/relay_switch_connect.test.ts" "aihub|npx vitest run tests/aihub/aihub_connect.test.ts -t '通过BLE添加'" "ai_art_frame|npx vitest run tests/aihub/ai_art_frame_connect.test.ts" # —— 插座(iOS 需 Other Pairing → Yes) —— "plug_jp|PLUG_OTHER_PAIRING=1 PLUG_MINI_CATEGORY='Plug Mini (JP)' PLUG_MINI_RELAY=plug_mini npx vitest run tests/plug/plug_mini_connect.test.ts" "plug_us|PLUG_OTHER_PAIRING=1 PLUG_MINI_CATEGORY='Plug Mini (US)' PLUG_MINI_RELAY=plug_mini_us npx vitest run tests/plug/plug_mini_connect.test.ts" "plug_eu|PLUG_OTHER_PAIRING=1 PLUG_MINI_CATEGORY='Plug Mini (EU)' PLUG_MINI_RELAY=plug_mini_eu PLUG_MINI_ONES=332918 npx vitest run tests/plug/plug_mini_connect.test.ts" # —— 环境类 —— "humidifier2|npx vitest run tests/humidifier/humidifier2_connect.test.ts" "air_purifier|npx vitest run tests/air_purifier/air_purifier_connect.test.ts" # —— 灯类(WiFi 配网 + 浮层) —— "color_bulb|npx vitest run tests/color_bulb/color_bulb_connect.test.ts" "ceiling_pro|npx vitest run tests/ceiling_light/ceiling_light_pro_connect.test.ts" "strip_light|npx vitest run tests/strip_light/strip_light_connect.test.ts" "floor_lamp|npx vitest run tests/ceiling_light/floor_lamp_connect.test.ts" "color_floor_lamp|npx vitest run tests/ceiling_light/color_floor_lamp_connect.test.ts" "neon|npx vitest run tests/strip_light/neon_light_connect.test.ts" "strip_light_3|npx vitest run tests/strip_light/strip_light_3_connect.test.ts" "eave_light|npx vitest run tests/ceiling_light/eave_light_connect.test.ts" "urc|npx vitest run tests/urc/urc_connect.test.ts" # —— 扫地机 —— "robot_s1p|npx vitest run tests/robot/robot_s1p_connect.test.ts" "robot_s10|npx vitest run tests/robot/robot_s10_connect.test.ts" # —— 摄像头/门铃添加(iOS 需扫码/校准无方案;账号已保留这两设备 → 多为已存在 SKIP,纳入为对齐 Android P0 口径)—— "doorbell|npx vitest run tests/camera/doorbell_connect.test.ts" "outdoor_ptc|npx vitest run tests/camera/outdoor_ptc_connect.test.ts" ) echo "===== $(date '+%F %T') iOS 添加批量开始 =====" | tee -a "$LOG" # 可选:跑前清空设备(保留锁/摄像头/门铃等不可重加),让添加用例真正执行(否则已存在→SKIP)。 # 过夜全量验证用 RESET_FIRST=1;默认关(避免误删)。 if [ "${RESET_FIRST:-0}" = "1" ]; then echo "[reset-except] 清空可重加设备(保留 Lock/Cam/Doorbell/Blind Tilt)..." | tee -a "$LOG" reset_home RESET_EXCEPT=1 PLATFORM=ios npx ts-node scripts/reset-except.ts >> "$LOG" 2>&1 \ && echo "[reset-except] 完成" | tee -a "$LOG" \ || echo "[reset-except] 异常(继续跑添加)" | tee -a "$LOG" fi # 跑单条添加:复位→执行→打印;含 "✗ [FAIL]" 返回 1(SKIP/已存在不算失败,不重试)。 run_add_one() { local name="$1" cmd="$2" echo "----- $(date +%T) [$name] -----" | tee -a "$LOG" reset_home eval "$cmd" > /tmp/ios-add-one.log 2>&1 grep -E '✓ \[PASS\]|✗ \[FAIL\]|○ \[SKIP\]|结果:|relay:|未触发|not found|cannot|品类' /tmp/ios-add-one.log | grep -ivE "deprecat" | tail -6 | tee -a "$LOG" grep -q '✗ \[FAIL\]' /tmp/ios-add-one.log && return 1 || return 0 } FAILED=() for entry in "${ADDS[@]}"; do name="${entry%%|*}"; cmd="${entry#*|}" run_add_one "$name" "$cmd" || FAILED+=("$entry") done # 添加失败重试(对齐 Android run-p0-all:每个最多重试 2 次;WiFi 抖动/BLE 扫描漏常一次过) if [ ${#FAILED[@]} -gt 0 ]; then echo "===== iOS 添加失败 ${#FAILED[@]} 个,重试(每个最多2次)=====" | tee -a "$LOG" for entry in "${FAILED[@]}"; do name="${entry%%|*}"; cmd="${entry#*|}"; ok=0 for att in 1 2; do echo "--- 重试 $att/2: [$name] ---" | tee -a "$LOG" if run_add_one "${name}-retry${att}" "$cmd"; then ok=1; echo "[ADD-RETRY-OK] $name" | tee -a "$LOG"; break; fi done [ $ok -eq 0 ] && echo "[ADD-RETRY-GIVEUP] $name" | tee -a "$LOG" done fi echo "===== $(date '+%F %T') 完成 =====" | tee -a "$LOG" # 汇总逐用例 HTML 报告(SOAK_MODE 已累计到 reports/.results.json) TS=$(date +%Y%m%d-%H%M%S) npx ts-node scripts/gen-combined.ts "iOSAdds_$TS" >> "$LOG" 2>&1 \ && echo "逐用例报告: reports/iOSAdds_${TS}_*.html" | tee -a "$LOG" \ || echo "报告生成失败(见 $LOG)" | tee -a "$LOG"