diff --git a/devices.py b/devices.py index 898aba3..91dd940 100644 --- a/devices.py +++ b/devices.py @@ -278,12 +278,25 @@ def curfew_status() -> dict: } -def _shutdown_devices(device_ids: list[str]): - """Shut down a list of devices in parallel.""" +def _shutdown_devices(device_ids: list[str]) -> dict[str, dict | None]: + """Shut down a list of devices in parallel. + + Returns {dev_id: turnoff result or None on failure}. + """ + results: dict[str, dict | None] = {} if not device_ids: - return + return results with ThreadPoolExecutor(max_workers=len(device_ids)) as executor: - list(executor.submit(DEVICES[dev_id]["turnoff"]) for dev_id in device_ids) + futures = { + executor.submit(DEVICES[dev_id]["turnoff"]): dev_id + for dev_id in device_ids + } + for future, dev_id in futures.items(): + try: + results[dev_id] = future.result() + except Exception: + results[dev_id] = None + return results # ── Budget timer (runs every 10s in background) ────────────────────── @@ -415,10 +428,14 @@ def stop_timer(): # ── Orchestrator ────────────────────────────────────────────────────── def shutdown_all() -> list[dict]: - """Indiscriminately turn off all devices. Returns ordered list of action dicts.""" + """Indiscriminately turn off all devices in parallel. + + Returns ordered list of action dicts (registry order). + """ + results = _shutdown_devices(list(DEVICES)) actions = [] for dev_id, dev_info in DEVICES.items(): - result = dev_info["turnoff"]() + result = results.get(dev_id) if result: budget_minutes = _budget_to_minutes(_get_budget(dev_id)) actions.append({