# -*- coding: utf-8 -*- """ Installer-Konfiguration als Dataclass. Speichert alle Einstellungen die der Benutzer in der TUI vornimmt. """ from __future__ import annotations from dataclasses import dataclass, field @dataclass class InstallerConfig: """Alle Installer-Einstellungen.""" # Modus und Version (von CLI gesetzt) mode: str = "server" version: str = "1.0.0" source_archive: str = "" # System (F1) hostname: str = "trixyone" username: str = "pi" install_path: str = "/home/pi/trixy" autostart: bool = True install_service: bool = True auto_regist: bool = True # Netzwerk (F2) — Server wifi_enabled: bool = True wifi_ssid: str = "trixyone_srv" wifi_password: str = "trixy2026!" wifi_channel: int = 6 ap_ip: str = "10.10.10.1" dhcp_range_start: str = "10.10.10.10" dhcp_range_end: str = "10.10.10.50" # Netzwerk (F2) — Client/Standalone WLAN wifi_connect: bool = False # WLAN umkonfigurieren wifi_connect_ssid: str = "" # Bevorzugte SSID (z.B. Trixy-Server-Hotspot) wifi_connect_password: str = "" # Passwort fuer bevorzugte SSID # Fallback-WLAN (optional — wird genutzt wenn primaeres Netz nicht erreichbar) wifi_fallback_enabled: bool = False wifi_fallback_ssid: str = "" wifi_fallback_password: str = "" # Auto-Rueckwechsel: Wenn aktiv, wechselt der Client automatisch zurueck # zum primaeren Netz sobald es wieder erreichbar ist. wifi_auto_switchback: bool = True wifi_switchback_interval: int = 30 # Pruefintervall in Sekunden # Netzwerk (F2) — Client server_host: str = "10.10.10.1" server_port: int = 2101 room: str = "" alias: str = "" # Plugins (F3) selected_plugins: list[str] = field(default_factory=list) # NLP Backend (nur relevant wenn nlp_llm in selected_plugins) nlp_backend: str = "llama_cpp" # "llama_cpp", "ollama" oder "ollama_remote" ollama_host: str = "http://localhost:11434" # Modelle download_models: bool = False # Vereinbarung (F5) agreement_accepted: bool = False @property def venv_path(self) -> str: """Pfad zum Python venv.""" return f"{self.install_path}/venv" @property def source_path(self) -> str: """Pfad zum entpackten Quellcode.""" return f"{self.install_path}/source" def validate(self) -> list[tuple[str, str]]: """ Validiert die Konfiguration. Returns: Liste von (view_id, fehlermeldung) Tupeln. """ errors: list[tuple[str, str]] = [] # System if not self.hostname.strip(): errors.append(("system", "Hostname darf nicht leer sein")) if not self.username.strip(): errors.append(("system", "Benutzername darf nicht leer sein")) if not self.install_path.strip(): errors.append(("system", "Installationspfad darf nicht leer sein")) # Netzwerk — Server if self.mode == "server" and self.wifi_enabled: if not self.wifi_ssid.strip(): errors.append(("network", "WiFi SSID darf nicht leer sein")) if len(self.wifi_password) < 8: errors.append(("network", "WiFi Passwort muss mindestens 8 Zeichen haben")) # Netzwerk — Client if self.mode == "client": if not self.server_host.strip(): errors.append(("network", "Server-Host darf nicht leer sein")) if not self.room.strip(): errors.append(("network", "Raum darf nicht leer sein")) if not self.alias.strip(): errors.append(("network", "Alias darf nicht leer sein")) # Netzwerk — WLAN-Verbindung (Client/Standalone) if self.wifi_connect: if not self.wifi_connect_ssid.strip(): errors.append(("network", "Primaere WLAN-SSID darf nicht leer sein")) if not self.wifi_connect_password: errors.append(("network", "Primaeres WLAN-Passwort darf nicht leer sein")) if self.wifi_fallback_enabled: if not self.wifi_fallback_ssid.strip(): errors.append(("network", "Fallback-WLAN-SSID darf nicht leer sein")) if not self.wifi_fallback_password: errors.append(("network", "Fallback-WLAN-Passwort darf nicht leer sein")) if self.wifi_fallback_ssid.strip() == self.wifi_connect_ssid.strip(): errors.append(("network", "Fallback- und Primaere SSID muessen unterschiedlich sein")) if self.wifi_switchback_interval < 10: errors.append(("network", "Switchback-Intervall muss mindestens 10 Sekunden sein")) # Vereinbarung if not self.agreement_accepted: errors.append(("agreement", "Nutzungsbedingungen muessen akzeptiert werden")) # Quellarchiv if not self.source_archive: errors.append(("install", "Kein Quellarchiv angegeben")) return errors