Make checking parallel (faster).
This commit is contained in:
69
devices.py
69
devices.py
@ -3,6 +3,7 @@
|
|||||||
import json
|
import json
|
||||||
import subprocess
|
import subprocess
|
||||||
import threading
|
import threading
|
||||||
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
@ -274,17 +275,28 @@ def _budget_tick():
|
|||||||
if not is_curfew_allowed():
|
if not is_curfew_allowed():
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Check all devices in parallel
|
||||||
|
online_status = {}
|
||||||
|
with ThreadPoolExecutor(max_workers=3) as executor:
|
||||||
|
futures = {
|
||||||
|
executor.submit(dev_info["check"]): dev_id
|
||||||
|
for dev_id, dev_info in DEVICES.items()
|
||||||
|
}
|
||||||
|
for future in as_completed(futures):
|
||||||
|
dev_id = futures[future]
|
||||||
|
result = future.result()
|
||||||
|
if isinstance(result, dict):
|
||||||
|
online_status[dev_id] = result.get("online", False)
|
||||||
|
else:
|
||||||
|
online_status[dev_id] = bool(result)
|
||||||
|
|
||||||
|
# Process results sequentially (budget operations need to be thread-safe)
|
||||||
with _timer_lock:
|
with _timer_lock:
|
||||||
for dev_id, dev_info in DEVICES.items():
|
for dev_id, online in online_status.items():
|
||||||
|
dev_info = DEVICES[dev_id]
|
||||||
state = _load_state()
|
state = _load_state()
|
||||||
current_budget = state.get(dev_id, {}).get("budget", BUDGET_S)
|
current_budget = state.get(dev_id, {}).get("budget", BUDGET_S)
|
||||||
|
|
||||||
is_online = dev_info["check"]()
|
|
||||||
if isinstance(is_online, dict):
|
|
||||||
online = is_online.get("online", False)
|
|
||||||
else:
|
|
||||||
online = bool(is_online)
|
|
||||||
|
|
||||||
# Expired budget + device back online → shut it down
|
# Expired budget + device back online → shut it down
|
||||||
if current_budget <= 0 and online:
|
if current_budget <= 0 and online:
|
||||||
dev_info["turnoff"]()
|
dev_info["turnoff"]()
|
||||||
@ -342,14 +354,8 @@ def shutdown_all() -> list[dict]:
|
|||||||
return actions
|
return actions
|
||||||
|
|
||||||
|
|
||||||
def status_all() -> list[dict]:
|
def _check_device(dev_id: str, dev_info: dict) -> dict:
|
||||||
"""Get current status + budget for all devices. Returns ordered list."""
|
"""Check a single device and return its status dict."""
|
||||||
curfew = curfew_status()
|
|
||||||
actions = []
|
|
||||||
for dev_id, dev_info in DEVICES.items():
|
|
||||||
state = _load_state()
|
|
||||||
budget_seconds = state.get(dev_id, {}).get("budget", BUDGET_S)
|
|
||||||
|
|
||||||
is_online = dev_info["check"]()
|
is_online = dev_info["check"]()
|
||||||
if isinstance(is_online, dict):
|
if isinstance(is_online, dict):
|
||||||
online = is_online.get("online", False)
|
online = is_online.get("online", False)
|
||||||
@ -358,6 +364,8 @@ def status_all() -> list[dict]:
|
|||||||
online = bool(is_online)
|
online = bool(is_online)
|
||||||
detail = "Online" if online else "Offline"
|
detail = "Online" if online else "Offline"
|
||||||
|
|
||||||
|
state = _load_state()
|
||||||
|
budget_seconds = state.get(dev_id, {}).get("budget", BUDGET_S)
|
||||||
budget_minutes = _budget_to_minutes(budget_seconds)
|
budget_minutes = _budget_to_minutes(budget_seconds)
|
||||||
|
|
||||||
# Budget warning
|
# Budget warning
|
||||||
@ -368,9 +376,36 @@ def status_all() -> list[dict]:
|
|||||||
else:
|
else:
|
||||||
icon = dev_info["icon"]
|
icon = dev_info["icon"]
|
||||||
|
|
||||||
actions.append({
|
return {
|
||||||
"icon": icon,
|
"icon": icon,
|
||||||
"title": dev_info["name"],
|
"title": dev_info["name"],
|
||||||
"detail": f"{detail} · {budget_minutes} min left",
|
"detail": f"{detail} · {budget_minutes} min left",
|
||||||
})
|
"online": online,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def status_all() -> list[dict]:
|
||||||
|
"""Get current status + budget for all devices. Returns ordered list."""
|
||||||
|
curfew = curfew_status()
|
||||||
|
|
||||||
|
# Check all devices in parallel
|
||||||
|
results = {}
|
||||||
|
with ThreadPoolExecutor(max_workers=3) as executor:
|
||||||
|
futures = {
|
||||||
|
executor.submit(_check_device, dev_id, dev_info): dev_id
|
||||||
|
for dev_id, dev_info in DEVICES.items()
|
||||||
|
}
|
||||||
|
for future in as_completed(futures):
|
||||||
|
dev_id = futures[future]
|
||||||
|
results[dev_id] = future.result()
|
||||||
|
|
||||||
|
# Return in ordered list (DEVICES preserves insertion order)
|
||||||
|
actions = [
|
||||||
|
{
|
||||||
|
"icon": results[dev_id]["icon"],
|
||||||
|
"title": results[dev_id]["title"],
|
||||||
|
"detail": results[dev_id]["detail"],
|
||||||
|
}
|
||||||
|
for dev_id in DEVICES
|
||||||
|
]
|
||||||
return actions, curfew
|
return actions, curfew
|
||||||
|
|||||||
Reference in New Issue
Block a user