"""Terminal TUI for device status monitoring.""" import os import sys import threading import time from devices import status_all, is_curfew_allowed # ANSI escape codes CLEAR = "\033[2J\033[H" BOLD = "\033[1m" RESET = "\033[0m" GREEN = "\033[92m" RED = "\033[91m" YELLOW = "\033[93m" CYAN = "\033[96m" GRAY = "\033[90m" def _get_terminal_size(): """Get terminal width and height.""" try: return os.get_terminal_size() except OSError: return (80, 24) def _color(text: str, color_code: str) -> str: """Wrap text in ANSI color code.""" return f"{color_code}{text}{RESET}" def _separator(width: int = 60) -> str: """Create a separator line.""" return "โ”€" * width def render(devices_status, curfew, refresh_interval: int = 10): """Render the TUI screen.""" width, height = _get_terminal_size() lines = [] # Header lines.append(_color("โšก KIDS DEVICES โ€” STATUS", BOLD)) lines.append("") # Curfew status if curfew["in_curfew"]: curfew_icon = _color("๐Ÿ”ด BLOCKED", RED) else: curfew_icon = _color("๐ŸŸข ALLOWED", GREEN) lines.append(f" Curfew: {curfew_icon} | {curfew['message']}") lines.append("") # Device list for device in devices_status: icon = device["icon"] name = device["title"] detail = device["detail"] # Parse budget from detail parts = detail.split(" ยท ") status_text = parts[0] if parts else "Unknown" budget_text = parts[1] if len(parts) > 1 else "" # Color the status if "Online" in status_text: status_color = GREEN elif "Offline" in status_text: status_color = GRAY else: status_color = YELLOW status_colored = _color(status_text, status_color) # Color the budget if "๐Ÿ”ด" in device["icon"]: budget_color = RED elif "๐ŸŸ " in device["icon"]: budget_color = YELLOW else: budget_color = CYAN budget_colored = _color(budget_text, budget_color) if budget_text else "" lines.append(f" {icon} {name:<12} {status_colored} ยท {budget_colored}") # Footer with timestamp now = time.strftime("%H:%M:%S") lines.append(f" {_color('Last update:', GRAY)} {now} | Refresh: {refresh_interval}s") return "\n".join(lines) def run_tui(refresh_interval: int = 10): """Run the TUI in a loop.""" # Run in a separate thread to not block the server while True: try: devices_status, curfew = status_all() screen = render(devices_status, curfew, refresh_interval) sys.stdout.write(CLEAR + screen) sys.stdout.flush() except Exception: pass # Don't crash TUI on errors time.sleep(refresh_interval) def start_tui(refresh_interval: int = 10): """Start the TUI in a background thread.""" tui_thread = threading.Thread( target=run_tui, args=(refresh_interval,), daemon=True, ) tui_thread.start() return tui_thread