Files
MeowOS-For-R3P2/patch_v2/meow_powermgr/test_powermgr.sh
T
MeowOS 250c9ae8b1 feat(powermgr): meow_powermgr 期0调研+期1骨架——功耗管理专项服务(POWER_MANAGER_DESIGN)
期0: POWER_HW_FACTS.md 真机只读取证——battery/无current_now(实时功率=derived+estimated
双轨)、无cpufreq(省电档无降频点)、背光量程0-101(非255)、rfkill可用、axp_battery为
幻影设备、无thermal zones、audiod STATE字段完备。

期1: patch_v2/meow_powermgr/ 单二进制双形态(meow_powermgr守护+meow_power CLI):
- svcd托管 trigger=boot/restart=on-fail;HibyOS只读降级(/tmp/meow_boot_mode!=meow
  只采样电池,不碰wlan0/bt/声卡,热切换)
- 权威充电链0-diff照抄svc_power(mp2731→fusb302→battery兜底)
- 电池深加工 state/cap/mV/health/续航估算(容量差分速率环 30s×240)
- 经验功耗模型(/usr/data/meow/power_model.conf 可调,内置默认全部标注待标定)
- IPC /usr/data/meow_pm.sock MSG_PM_QUERY(0x00D0)→MSG_PM_RESULT(0x00D1) JSON,
  subset位;meow_ipc.h 0x00D0-0x00D7 号段回填
- CLI status/estimate/model 落地(IPC优先+直读降级),history/top/events/policy 期2/3桩
- 宿主桩测试36+1例全过(MEOW_PS_DIR等假节点)+qemu-mipsel全过+真机对照svc_power
  battery口径一致(93%/4270mV);mipsel静态117KB(<200KB);-Wall -Wextra 0 warning
2026-09-01 16:21:12 +08:00

163 lines
7.3 KiB
Bash
Executable File
Raw 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
# test_powermgr.sh — meow_powermgr 宿主桩测试(假 sysfs/procfs 节点,MEOW_*_DIR env 覆盖)。
# 用法:./test_powermgr.sh [host二进制路径](默认 ./meow_powermgr_host;可传 mipsel 二进制 + QEMU 前缀)
# QEMU="qemu-mipsel" ./test_powermgr.sh ./meow_powermgr # qemu 验证
set -u
cd "$(dirname "$0")"
BIN="${1:-./meow_powermgr_host}"
Q="${QEMU:-}"
T=$(mktemp -d /tmp/pmtest.XXXXXX)
trap 'kill $DPID 2>/dev/null; rm -rf "$T"' EXIT
PASS=0; FAIL=0
ck() { # ck <名> <期望子串> <实际>
if echo "$3" | grep -qF "$2"; then PASS=$((PASS+1)); echo "PASS $1";
else FAIL=$((FAIL+1)); echo "FAIL $1: 期望含 [$2] 实际=[$3]"; fi
}
# ---- 搭假节点 ----
PS="$T/ps"; BL="$T/bl"; NET="$T/net"; RF="$T/rfkill"; BT="$T/bt"
mkdir -p "$PS/battery" "$PS/mp2731-charger" "$PS/fusb302-typec-source" "$PS/ac" \
"$BL" "$NET/wlan0" "$RF/rfkill0" "$BT"
echo 94 > "$PS/battery/capacity"
echo Discharging > "$PS/battery/status"
echo 4275000 > "$PS/battery/voltage_now"
echo Good > "$PS/battery/health"
echo Li-ion > "$PS/battery/technology"
echo Discharging > "$PS/mp2731-charger/status" # 权威链
echo 300 > "$PS/mp2731-charger/temp"
echo 0 > "$PS/fusb302-typec-source/online"
echo 0 > "$PS/ac/online"
echo 101 > "$BL/max_brightness" # R3 Pro II 实测量程 0-101
echo 50 > "$BL/actual_brightness" # 中档(49%)
echo 50 > "$BL/brightness"
echo up > "$NET/wlan0/operstate"
echo bluetooth > "$RF/rfkill0/type"
echo 1 > "$RF/rfkill0/soft" # BT 被 soft 块 → off
cat > "$T/netdev" <<'EOF'
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
wlan0: 1000000 1000 0 0 0 0 0 0 2000000 1000 0 0 0 0 0 0
EOF
echo "cpu 100 0 100 800 0 0 0 0 0 0" > "$T/proc_stat"
echo meow > "$T/boot_mode"
ENVS="MEOW_PS_DIR=$PS MEOW_BL_DIR=$BL MEOW_NET_DIR=$NET MEOW_RFKILL_DIR=$RF MEOW_BT_DIR=$BT
MEOW_NETDEV=$T/netdev MEOW_PROC_STAT=$T/proc_stat MEOW_BOOT_MODE=$T/boot_mode
MEOW_PM_MODEL=$T/model.conf MEOW_AUDIO_SOCK=$T/no_audio.sock MEOW_PM_SOCK=$T/pm.sock"
ln -sf "$(readlink -f "$BIN")" "$T/meow_power" # argv[0] 双形态
# ---- T1: 守护直读(无守护 → 降级直读) ----
OUT=$(env $ENVS $Q "$T/meow_power" status 2>/dev/null)
ck T1a "state=Discharging cap=94%" "$OUT"
echo "$OUT" | grep -q "mv=4275" && { PASS=$((PASS+1)); echo "PASS T1b mv"; } || { FAIL=$((FAIL+1)); echo "FAIL T1b: $OUT"; }
ck T1c "health=Good" "$OUT"
ck T1d "charger_temp=30.0C" "$OUT"
ck T1e "rate=null" "$OUT"
ck T1f "src=direct" "$OUT"
# ---- T2: 起守护,IPC 路径 ----
env $ENVS MEOW_PM_SAMPLE_SEC=1 MEOW_PM_MIN_SPAN_SEC=2 $Q "$BIN" --sock "$T/pm.sock" >"$T/daemon.log" 2>&1 &
DPID=$!
for i in $(seq 1 30); do [ -S "$T/pm.sock" ] && break; sleep 0.2; done
[ -S "$T/pm.sock" ] || { echo "FAIL T0: daemon socket 未出现"; cat "$T/daemon.log"; exit 1; }
PASS=$((PASS+1)); echo "PASS T0 daemon up"
OUT=$(env $ENVS $Q "$T/meow_power" status 2>/dev/null)
ck T2a "src=daemon" "$OUT"
ck T2b "cap=94%" "$OUT"
ck T2c "mode=meow" "$OUT"
# ---- T3: 容量差分速率(94→93,span≥2s)→ rate/est_left=derived ----
echo 93 > "$PS/battery/capacity"
sleep 4
OUT=$(env $ENVS $Q "$T/meow_power" status 2>/dev/null)
ck T3a "conf=derived" "$OUT"
ck T3b "est_left=" "$OUT"
echo "$OUT" | grep -q "rate=-" && { PASS=$((PASS+1)); echo "PASS T3c 放电速率为负"; } || { FAIL=$((FAIL+1)); echo "FAIL T3c: $OUT"; }
# ---- T4: estimate(模型合成;中档背光+面板+wifi idle+bt off+audio unknown) ----
OUT=$(env $ENVS $Q "$T/meow_power" estimate 2>/dev/null)
ck T4a "confidence=estimated" "$OUT"
ck T4b "待真机标定" "$OUT"
ck T4c "backlight=450" "$OUT" # 49% → 中档 450
ck T4d "panel=80" "$OUT"
ck T4e "bt=0(off)" "$OUT" # rfkill soft=1 → off
ck T4f "audio=0(unknown)" "$OUT" # 无 audiod → unknown 0mW
# est_mw = 300(base)+450+80+200(wifi idle)+0+0+cpu(0,静态proc_stat)=1030
ck T4g "est_mw=1030" "$OUT"
# ---- T5: wifi 传输档(netdev 增量 >4096/拍 → tx=600) ----
sed -i 's/wlan0: 1000000/wlan0: 1999999/; s/ 2000000 / 2999999 /' "$T/netdev"
sleep 3
OUT=$(env $ENVS $Q "$T/meow_power" estimate 2>/dev/null)
ck T5a "wifi=600(tx)" "$OUT"
# ---- T6: 息屏(actual_brightness=0)→ 背光/面板归零 ----
echo 0 > "$BL/actual_brightness"
OUT=$(env $ENVS $Q "$T/meow_power" estimate 2>/dev/null)
ck T6a "backlight=0" "$OUT"
ck T6b "panel=0" "$OUT"
echo 50 > "$BL/actual_brightness"
# ---- T7: 模型 conf 覆盖 ----
printf '# test\nbaseline_mw=999\nwifi_idle_mw=111\n' > "$T/model.conf"
OUT=$(env $ENVS $Q "$T/meow_power" model 2>/dev/null)
ck T7a "baseline_mw=999" "$OUT"
ck T7b "wifi_idle_mw=111" "$OUT"
ck T7c "bl_high_mw=900" "$OUT" # 未覆盖键留默认
rm -f "$T/model.conf"
# ---- T8: HibyOS 只读降级(不施估算;电池仍可读) ----
echo hiby > "$T/boot_mode"
sleep 2 # 等守护下一拍热切换
OUT=$(env $ENVS $Q "$T/meow_power" estimate 2>/dev/null)
ck T8a "HibyOS 只读模式" "$OUT"
OUT=$(env $ENVS $Q "$T/meow_power" status 2>/dev/null)
ck T8b "cap=93%" "$OUT" # 只读模式电池采样不受影响
ck T8c "mode=readonly" "$OUT"
echo meow > "$T/boot_mode"
sleep 2
OUT=$(env $ENVS $Q "$T/meow_power" estimate 2>/dev/null)
ck T8d "est_mw=" "$OUT" # 热切换回全功能
# ---- T9: CLI 桩(期 2/3) ----
OUT=$(env $ENVS $Q "$T/meow_power" history 2>&1); RC=$?
ck T9a "期 2" "$OUT"
[ $RC -eq 1 ] && { PASS=$((PASS+1)); echo "PASS T9b rc=1"; } || { FAIL=$((FAIL+1)); echo "FAIL T9b rc=$RC"; }
OUT=$(env $ENVS $Q "$T/meow_power" policy 2>&1)
ck T9c "期 3" "$OUT"
# ---- T10: meow_powermgr 名直调子命令也走 CLI ----
OUT=$(env $ENVS $Q "$BIN" model 2>/dev/null)
ck T10a "nominal_mah=1600" "$OUT"
# ---- T11: 守护停 → CLI 自动降级直读不崩 ----
kill $DPID 2>/dev/null; wait $DPID 2>/dev/null; DPID=""
sleep 1
OUT=$(env $ENVS $Q "$T/meow_power" status 2>/dev/null)
ck T11a "src=direct" "$OUT"
ck T11b "cap=93%" "$OUT"
# ---- T12: audiod 在场时音频链分量(真 audiod 二进制当桩:无 HELLO 直接 QUERY 协议) ----
AUDIOD_BIN=../meow_audiod/meow_audiod_host
[ -n "$Q" ] && AUDIOD_BIN=../meow_audiod/meow_audiod
if [ -x "$AUDIOD_BIN" ]; then
env MEOW_AUDIO_FORCE=1 MEOW_AUDIO_SOCK="$T/audio.sock" MEOW_AUDIO_OUT="$T/a.wav" \
MEOW_AUDIO_SINK=null $Q "$AUDIOD_BIN" --sock "$T/audio.sock" >"$T/audiod.log" 2>&1 &
APID=$!
for i in $(seq 1 30); do [ -S "$T/audio.sock" ] && break; sleep 0.2; done
env $ENVS MEOW_AUDIO_SOCK="$T/audio.sock" MEOW_PM_SAMPLE_SEC=1 MEOW_PM_MIN_SPAN_SEC=2 \
MEOW_PM_SOCK="$T/pm2.sock" $Q "$BIN" --sock "$T/pm2.sock" >"$T/daemon2.log" 2>&1 &
DPID=$!
for i in $(seq 1 30); do [ -S "$T/pm2.sock" ] && break; sleep 0.2; done
OUT=$(env $ENVS MEOW_AUDIO_SOCK="$T/audio.sock" MEOW_PM_SOCK="$T/pm2.sock" $Q "$T/meow_power" estimate 2>/dev/null)
ck T12a "audio=50(idle)" "$OUT" # audiod 在场无流 → 静态档 50
kill $DPID $APID 2>/dev/null; wait 2>/dev/null; DPID=""
else
echo "SKIP T12 (无 audiod 二进制 $AUDIOD_BIN)"
fi
echo "=============================="
echo "PASS=$PASS FAIL=$FAIL"
[ $FAIL -eq 0 ]