"""CLI-Einstiegspunkt: `python -m aubox `.""" from __future__ import annotations import argparse import sys import time from . import p10lite, usb from .kirin import KirinDload def cmd_detect(_args: argparse.Namespace) -> int: devs = usb.scan() if not devs: print("Kein bekanntes Hersteller-Gerät angeschlossen.") print("Probiere `lsusb` für die rohe Liste.") return 1 for d in devs: print(d) if d.mode.notes: print(f" {d.mode.notes}") return 0 def cmd_p10lite_frp(args: argparse.Namespace) -> int: if args.method == "erecovery": print(p10lite.erecovery_instructions()) return 0 if args.method == "dload-erase": try: plan = p10lite.dload_erase_plan() except FileNotFoundError as e: print(str(e), file=sys.stderr) return 2 print("Plan:") for stage in plan["stages"]: print(f" - {stage['label']}: {stage['file']} -> 0x{stage['addr']:08x}") print() print("Bitte jetzt Testpoint setzen und USB anschließen.") print("Warte auf Kirin DLOAD (12d1:1100)...") for _ in range(60): if usb.find_first("kirin-dload") is not None: break time.sleep(0.5) else: print("Timeout: kein Kirin DLOAD erschienen.", file=sys.stderr) return 3 print("Gerät erkannt. Sende Loader-Stages...") with KirinDload() as k: for stage in plan["stages"]: print(f" -> {stage['label']}") k.send_loader(stage["file"], stage["addr"]) # Zwischen den Stages re-enumeriert das Gerät evtl. time.sleep(2) print("Loader-Stages gesendet. Erwarteter Folgemodus:", plan["post"]) print("Nächster Schritt (manuell, bis Workflow ausgereift):") print(" fastboot devices") print(f" fastboot erase {plan['frp_partition']}") return 0 print(f"Methode {args.method!r} noch nicht implementiert.", file=sys.stderr) return 2 def cmd_web(args: argparse.Namespace) -> int: import uvicorn uvicorn.run( "aubox.web.app:app", host=args.host, port=args.port, reload=args.reload, log_level="info", ) return 0 def build_parser() -> argparse.ArgumentParser: p = argparse.ArgumentParser(prog="aubox") sub = p.add_subparsers(dest="cmd", required=True) sp_detect = sub.add_parser("detect", help="Angeschlossene Geräte erkennen") sp_detect.set_defaults(func=cmd_detect) sp_web = sub.add_parser("web", help="Lokale Web-UI starten") sp_web.add_argument("--host", default="127.0.0.1", help="Bind-Adresse (Default: 127.0.0.1, im Container 0.0.0.0)") sp_web.add_argument("--port", type=int, default=8080) sp_web.add_argument("--reload", action="store_true", help="Auto-Reload bei Code-Änderungen (Entwicklung)") sp_web.set_defaults(func=cmd_web) sp_p10 = sub.add_parser("p10lite", help="Workflows für Huawei P10 Lite") p10_sub = sp_p10.add_subparsers(dest="p10_cmd", required=True) sp_frp = p10_sub.add_parser("frp-remove", help="Google-Account-Sperre entfernen") sp_frp.add_argument( "--method", choices=["erecovery", "dload-erase", "dload-flash"], default="erecovery", help="Welcher Pfad? Default: erecovery (sicherster, kein Loader nötig)", ) sp_frp.set_defaults(func=cmd_p10lite_frp) return p def main(argv: list[str] | None = None) -> int: args = build_parser().parse_args(argv) return args.func(args) if __name__ == "__main__": raise SystemExit(main())