feat(satellite): ADB-Rollout wartet auf die Geraete-Bestaetigung (ein Klick genuegt)

Bisher: 1. Klick -> 'unauthorized' (Fehler), am Fire TV bestaetigen, 2. Klick ->
klappt. Jetzt wartet der Satellit nach dem ersten connect bis zu ADB_AUTH_WAIT_SEC
(90s) auf die Autorisierung und installiert danach automatisch weiter — der
Dialog auf dem Fernseher erscheint ja erst DURCH das connect.

- _adb_wait_authorized(): pollt adb devices alle 2s und verbindet neu (nach dem
  Bestaetigen wechselt der Zustand oft erst mit frischem connect auf 'device').
- adb.install/adb.connect nutzen es; scheitert es doch, nennt die Meldung Wartezeit
  und Zustand statt nur 'unauthorized'.
- Brain-Timeout fuer adb.* auf 320s (Warten + Download + Installation).
- Diagnostic: Hinweis erscheint SOFORT beim Klick ('Jetzt auf den Bildschirm des
  Geraets schauen'), nicht erst als Fehler hinterher.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-09-30 01:34:18 +02:00
co-authored by Claude Opus 4.8
parent 6a8dd662fa
commit 8301342728
3 changed files with 70 additions and 13 deletions
+54 -8
View File
@@ -145,6 +145,10 @@ CONTROL_ALLOWLIST = [
# Download brauchen.
ADB_PORT = int(os.environ.get("ADB_PORT", "5555") or "5555")
ADB_TIMEOUT_SEC = float(os.environ.get("ADB_TIMEOUT_SEC", "180") or "180")
# Beim ERSTEN Verbinden zeigt das Geraet "USB-Debugging zulassen?" auf dem
# Bildschirm. Statt mit Fehler abzubrechen (und den Nutzer nochmal klicken zu
# lassen) wartet der Satellit so lange auf die Bestaetigung.
ADB_AUTH_WAIT_SEC = float(os.environ.get("ADB_AUTH_WAIT_SEC", "90") or "90")
APK_CACHE_DIR = os.environ.get("APK_CACHE_DIR", "/data/apk")
APK_MAX_BYTES = int(os.environ.get("APK_MAX_BYTES", str(64 * 1024 * 1024)) or str(64 * 1024 * 1024))
@@ -1121,6 +1125,28 @@ def _adb_state(target: str) -> str:
return ""
def _adb_wait_authorized(target: str, seconds: float) -> tuple:
"""Wartet, bis das Geraet autorisiert ist ('device').
Beim ersten Kontakt erscheint auf dem Fernseher/Handy der Dialog
"USB-Debugging zulassen?". Frueher brach die Installation hier ab und man
musste nach dem Bestaetigen ein zweites Mal starten — jetzt wartet der
Satellit einfach, bis der Nutzer bestaetigt hat. Gibt (ok, zustand).
"""
import time as _time
deadline = _time.time() + max(0.0, seconds)
last = _adb_state(target)
while _time.time() < deadline:
if last == "device":
return True, last
_time.sleep(2.0)
# Erneut verbinden: nach dem Bestaetigen wechselt der Zustand oft erst
# mit einem frischen connect von 'unauthorized'/'offline' auf 'device'.
_adb_run(["connect", target], timeout=15)
last = _adb_state(target)
return last == "device", last
def _do_adb_devices(params: dict) -> dict:
"""Listet die dem Satelliten bekannten ADB-Geraete."""
rc, out, err = _adb_run(["devices", "-l"], timeout=20)
@@ -1140,10 +1166,19 @@ def _do_adb_connect(params: dict) -> dict:
if not target:
return {"ok": False, "error": "ip/host erforderlich."}
ok, msg = _adb_connect(target)
if not ok:
state = _adb_state(target)
wait = float(params.get("auth_wait") or ADB_AUTH_WAIT_SEC)
if (not ok or state != "device") and wait > 0:
authed, state = _adb_wait_authorized(target, wait)
if not authed:
return {"ok": False, "error":
"Nicht autorisiert — auf dem Bildschirm des Geraets "
"'USB-Debugging zulassen?' bestaetigen. "
f"(gewartet: {wait:.0f}s, Zustand: '{state or '?'}')"}
msg = f"verbunden (nach Bestaetigung am Geraet)"
elif not ok:
return {"ok": False, "error": msg}
return {"ok": True, "result": {"target": target, "state": _adb_state(target),
"message": msg}}
return {"ok": True, "result": {"target": target, "state": state, "message": msg}}
def _do_adb_shell(params: dict) -> dict:
@@ -1241,12 +1276,23 @@ def _do_adb_install(params: dict) -> dict:
return {"ok": False, "error": err}
ok, msg = _adb_connect(target)
if not ok:
return {"ok": False, "error": msg}
state = _adb_state(target)
if state and state != "device":
return {"ok": False, "error": f"Geraet im Zustand '{state}' — "
"bei 'unauthorized' den Dialog auf dem Bildschirm bestaetigen."}
# Erstkontakt: Das Geraet zeigt jetzt "USB-Debugging zulassen?" auf dem
# Bildschirm. Statt abzubrechen warten wir auf die Bestaetigung — ein Klick
# im Diagnostic genuegt, kein zweiter Anlauf noetig.
wait = float(params.get("auth_wait") or ADB_AUTH_WAIT_SEC)
if (not ok or state != "device") and wait > 0:
logger.info("[adb] %s: warte bis zu %.0fs auf Autorisierung (Zustand '%s')",
target, wait, state or "?")
authed, state = _adb_wait_authorized(target, wait)
if not authed:
hint = ("Das Geraet hat die Verbindung nicht autorisiert. Auf dem "
"Bildschirm erscheint 'USB-Debugging zulassen?' — bitte "
"bestaetigen (Haken bei 'Immer erlauben'). "
f"Ich habe {wait:.0f}s gewartet, Zustand: '{state or 'nicht erreichbar'}'.")
return {"ok": False, "error": hint if (state or ok) else msg}
elif not ok:
return {"ok": False, "error": msg}
args = ["-s", target, "install", "-r"] # -r = Update statt Neuinstallation
if params.get("downgrade"):