#!/bin/bash
# daemon_add_stop.sh — Pi の mecharm_daemon.py に「stop」の命令を 1 つ書き足して起動し直す (2026-11-05)
#
#   tools/daemon_add_stop.sh
#
# なぜ: ゲームパッドの長押しを「15° 先へ 1 回送り, 離したら止める」形にするため (jog_probe 3 回の結果).
#       今の daemon には動いている途中で止める命令がない.
# 足す命令: {"cmd": "stop"} → mc.jog_stop() と mc.stop() を順に呼ぶ (どちらかが効かなかった試しがあるので両方).
#       ほかの命令は 1 文字も変えない (unknown cmd の else の直前に足すだけ).
# 流れ:
#   1. Pi で今動いている /home/ubuntu/mecharm_daemon.py を Mac に持ち帰り, KIOXIA の archive/ に写しを残す
#   2. すでに stop があれば何もしない. なければ書き足し, 構文を確かめる
#   3. Pi へ一時名で送ってから入れ替え, systemd で起動し直し, ping と stop が返事をするか確かめる
#      うまくいかなければ, 元に戻すコマンドを出して止まる
# 流す前に: ゲームパッドなど daemon を使うものを止め, アームを HOME など安全な姿勢にしておく
#           (daemon を起動し直すと MyCobot の初期化が走る)
# 書き足した daemon は tools/pi/mecharm_daemon.py にも置く (これからの手元の正. ルートの mecharm_daemon.py は古い版なので触らない)
set -u
PI=ubuntu@192.168.2.1
KEY="$HOME/.ssh/id_rsa_pi"
SSH=(ssh -n -i "$KEY" -o ConnectTimeout=5 "$PI")
UNIT=mecharm-daemon.service
HERE="$(cd "$(dirname "$0")" && pwd)"
ROOT="$(dirname "$HERE")"
DATA_ROOT=/Volumes/KIOXIA/r2r2r-data
[ -d "$DATA_ROOT/archive" ] || { echo "ABORT: $DATA_ROOT/archive がない (KIOXIA がマウントされていない?)"; exit 1; }
STAMP=$(date +%Y%m%d_%H%M%S)
BK="$DATA_ROOT/archive/mecharm_daemon_premerge_$STAMP"
mkdir "$BK" || exit 1
WORK=$(mktemp -d)

scp -i "$KEY" -q -o ConnectTimeout=5 "$PI:/home/ubuntu/mecharm_daemon.py" "$WORK/before.py" || { echo "ABORT: Pi から持ち帰れない"; exit 1; }
cp "$WORK/before.py" "$BK/mecharm_daemon.py" || { echo "ABORT: 写しを残せない (Pi の daemon は変えていません)"; exit 1; }
echo "今の daemon の写し: $BK/mecharm_daemon.py"

python3 - "$WORK/before.py" "$WORK/after.py" <<'PY'
import sys
src = open(sys.argv[1], encoding="utf-8").read()
if 'cmd == "stop"' in src:
    print("すでに stop があります。書き足しません")
    open(sys.argv[2], "w", encoding="utf-8").write(src)
    sys.exit(0)
for need in ("_mc", "def log("):
    assert need in src, f"daemon に {need} がない (書き足す命令が動かない)"
anchor = '''    else:
        return {"ok": False, "error": f"unknown cmd: {cmd}"}'''
assert src.count(anchor) == 1, "書き足す場所 (unknown cmd の else) が 1 つに決まらない"
add = '''    # 2026-11-05: 動いている途中で止める (ゲームパッドの長押しを離したとき・L2+R2).
    # jog_probe (diag/jog_probe_20261105_*) で jog_stop と stop はどちらも効かない回があったので両方呼ぶ.
    elif cmd == "stop":
        res = {}
        for name in ("jog_stop", "stop"):
            try:
                res[name] = getattr(_mc, name)()
            except Exception as e:
                res[name] = f"{type(e).__name__}: {e}"
        log(f"stop: {res}")
        if all(isinstance(v, str) for v in res.values()):
            return {"ok": False, "error": f"stop failed: {res}"}
        return {"ok": True, "result": res}

'''
out = src.replace(anchor, add + anchor)
compile(out, "mecharm_daemon.py", "exec")
open(sys.argv[2], "w", encoding="utf-8").write(out)
print("stop を書き足しました")
PY
[ $? = 0 ] || { echo "ABORT: 書き足せない (Pi の daemon は変えていません)"; exit 1; }
cp "$WORK/after.py" "$BK/mecharm_daemon_with_stop.py" || exit 1
cp "$WORK/after.py" "$HERE/pi/mecharm_daemon.py" || exit 1
RESTORE="scp -i $KEY $BK/mecharm_daemon.py $PI:/home/ubuntu/mecharm_daemon.py && ssh -i $KEY $PI sudo systemctl restart $UNIT"
fail() { echo "ABORT: $1"; echo "元に戻すには: $RESTORE"; exit 1; }
echo "--- 差分"
diff "$WORK/before.py" "$WORK/after.py"

scp -i "$KEY" -q -o ConnectTimeout=5 "$WORK/after.py" "$PI:/home/ubuntu/mecharm_daemon.py.new" || { echo "ABORT: Pi へ送れない (Pi の daemon は変えていません)"; exit 1; }
"${SSH[@]}" "python3 -m py_compile /home/ubuntu/mecharm_daemon.py.new && mv /home/ubuntu/mecharm_daemon.py.new /home/ubuntu/mecharm_daemon.py" \
    || { echo "ABORT: Pi で入れ替えられない (Pi の daemon は変えていません)"; exit 1; }
"${SSH[@]}" "sudo systemctl restart $UNIT" || fail "systemctl restart が失敗した"
UP=no
for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do
    sleep 2
    "${SSH[@]}" "ss -ltn | grep -q ':5555 '" && { UP=yes; break; }
done
[ "$UP" = yes ] || fail "30 秒たっても 5555 が開かない"
python3 - <<'PY'
import json, socket
s = socket.create_connection(("192.168.2.1", 5555), timeout=5)
f = s.makefile("rwb")
for c in ({"cmd": "ping"}, {"cmd": "stop"}):
    f.write((json.dumps(c) + "\n").encode()); f.flush()
    r = json.loads(f.readline().decode())
    print(c["cmd"], "→", r)
    assert r.get("ok"), c["cmd"] + " が ok を返さない"
s.close()
PY
[ $? = 0 ] || fail "ping か stop が ok を返さない"
echo "できました。記録: $BK"
