Spaces:
Running
Running
| """ | |
| modules/context_display.py — FRIDAY Contextual Display | |
| Asks what's around and shows info in AR or normal mode. | |
| """ | |
| import os | |
| import json | |
| import time | |
| from typing import Optional | |
| from config import DATA_DIR | |
| CONTEXT_FILE = os.path.join(DATA_DIR, "context_display.json") | |
| def _load() -> dict: | |
| """Load context data.""" | |
| if not os.path.exists(CONTEXT_FILE): | |
| return {"presets": {}, "current_view": "normal", "ar_enabled": False} | |
| try: | |
| with open(CONTEXT_FILE, "r", encoding="utf-8") as f: | |
| return json.load(f) | |
| except Exception: | |
| return {"presets": {}, "current_view": "normal", "ar_enabled": False} | |
| def _save(data: dict) -> None: | |
| """Save context data.""" | |
| try: | |
| os.makedirs(DATA_DIR, exist_ok=True) | |
| with open(CONTEXT_FILE, "w", encoding="utf-8") as f: | |
| json.dump(data, f) | |
| except Exception: | |
| pass | |
| # === View Presets === | |
| PRESETS = { | |
| "system": ["CPU", "RAM", "GPU", "Temps", "Battery"], | |
| "network": ["WiFi", "LAN", "VPN", "Ping"], | |
| "health": ["Focus", "Breaks", "Eye strain", "Posture"], | |
| "weather": ["Temperature", "Humidity", "Forecast"], | |
| "calendar": ["Next meeting", "Events", "Free time"], | |
| "news": ["Headlines", "Tech news", "Weather alert"], | |
| "stocks": ["Portfolio", "Market", "Alerts"], | |
| "security": ["Firewall", "Network", "Logins"], | |
| } | |
| def set_view(view: str, mode: str = "normal") -> str: | |
| """ | |
| Set what to display. | |
| Args: | |
| view: View name (system, network, health, etc) | |
| mode: Display mode (ar or normal) | |
| Returns: | |
| Confirmation | |
| """ | |
| data = _load() | |
| data["current_view"] = view | |
| data["display_mode"] = mode | |
| data["ar_enabled"] = mode == "ar" | |
| _save(data) | |
| mode_text = "AR" if mode == "ar" else "normal" | |
| return f"Showing {view} in {mode_text} mode." | |
| def get_view() -> dict: | |
| """Get current view settings.""" | |
| return _load() | |
| def enable_ar() -> str: | |
| """Enable AR display mode.""" | |
| return set_view("system", "ar") | |
| def disable_ar() -> str: | |
| """Disable AR display mode.""" | |
| data = _load() | |
| data["ar_enabled"] = False | |
| data["display_mode"] = "normal" | |
| _save(data) | |
| return "AR disabled. Back to normal display." | |
| def ask_what_to_show() -> str: | |
| """FRIDAY asks what user wants to see.""" | |
| import random | |
| questions = [ | |
| "What would you like to see, boss?", | |
| "What info do you need?", | |
| "Show you the system stats?", | |
| "Want to see network status?", | |
| "Check your health metrics?", | |
| "See weather?", | |
| "Display anything specific?", | |
| ] | |
| return random.choice(questions) | |
| def suggest_views() -> list[str]: | |
| """Suggest available views.""" | |
| return list(PRESETS.keys()) | |
| # === Build Display Content === | |
| def get_system_display() -> str: | |
| """Get system info for display.""" | |
| import psutil | |
| import platform | |
| cpu = psutil.cpu_percent() | |
| ram = psutil.virtual_memory() | |
| battery = "" | |
| try: | |
| b = psutil.sensors_battery() | |
| if b: | |
| battery = f"{b.percent}%" | |
| except Exception: | |
| pass | |
| return f"CPU: {cpu}% | RAM: {ram.percent}% | {battery}" | |
| def get_network_display() -> str: | |
| """Get network info for display.""" | |
| import psutil | |
| net = psutil.net_io_counters() | |
| return f"Download: {net.bytes_recv/1024/1024:.1f}MB | Upload: {net.bytes_sent/1024/1024:.1f}MB" | |
| def get_health_display() -> str: | |
| """Get health info for display.""" | |
| try: | |
| from modules.health_monitor import get_health_summary | |
| summary = get_health_summary() | |
| focus = summary.get("total_focus_hours", 0) | |
| breaks = summary.get("breaks_taken", 0) | |
| return f"Focus: {focus:.1f}h | Breaks: {breaks}" | |
| except Exception: | |
| return "No health data" | |
| def get_weather_display() -> str: | |
| """Get weather info for display.""" | |
| try: | |
| from modules.weather import get_weather | |
| w = get_weather() | |
| return w[:100] if w else "Weather unavailable" | |
| except Exception: | |
| return "Weather unavailable" | |
| def build_display_content() -> str: | |
| """Build content based on current view.""" | |
| data = _load() | |
| view = data.get("current_view", "system") | |
| if view == "system": | |
| return get_system_display() | |
| elif view == "network": | |
| return get_network_display() | |
| elif view == "health": | |
| return get_health_display() | |
| elif view == "weather": | |
| return get_weather_display() | |
| else: | |
| return f"View: {view}" | |
| # === Voice Commands === | |
| def handle_command(command: str, speak) -> bool: | |
| """Handle context display commands.""" | |
| c = command.lower() | |
| # Ask what to show | |
| if "what do you see" in c or "what's around" in c or "what's happening" in c: | |
| result = ask_what_to_show() | |
| speak(result) | |
| return True | |
| # Enable AR | |
| if _has(c, ["show in ar", "ar display", "enable ar view"]): | |
| try: | |
| enable_ar() | |
| speak("AR enabled. What do you want to see?") | |
| except Exception as e: | |
| speak(f"AR error: {e}") | |
| return True | |
| # Disable AR | |
| if "disable ar" in c or "normal mode" in c: | |
| result = disable_ar() | |
| speak(result) | |
| return True | |
| # Show specific view | |
| for view in PRESETS.keys(): | |
| if f"show {view}" in c or f"display {view}" in c: | |
| mode = "ar" if "ar" in c else "normal" | |
| result = set_view(view, mode) | |
| speak(result) | |
| return True | |
| return False | |
| def _has(text: str, words: list) -> bool: | |
| """Check if any word in text.""" | |
| return any(w in text for w in words) |