# -*- coding: utf-8 -*- """ Config-Tool Netzwerk-Befehle. Befehle fuer die Remote-Verwaltung laufender Trixy-Instanzen ueber das Config-Tool (TUI). """ from dataclasses import dataclass, field from trixy_core.network.cmd.base import CommandMessage @dataclass class ConfigConnect(CommandMessage): """ Verbindungsanfrage vom Config-Tool. Wird nach dem HELLO-Handshake gesendet, um sich als Config-Tool zu identifizieren. """ tool_version: str = "" @dataclass class ConfigConnectAccepted(CommandMessage): """ Verbindungsbestaetigung an das Config-Tool. Enthaelt Informationen ueber die laufende Instanz. """ instance_type: str = "" # "server", "client", "standalone" instance_version: str = "" hostname: str = "" uptime_seconds: float = 0.0 @dataclass class ConfigConnectDenied(CommandMessage): """ Verbindungsablehnung fuer das Config-Tool. """ reason: str = "" @dataclass class ConfigStatusRequest(CommandMessage): """ Anfrage fuer System-Metriken. Das Config-Tool sendet diese Anfrage periodisch, um den Health-View zu aktualisieren. """ include_network: bool = True include_disk: bool = True @dataclass class ConfigStatusResponse(CommandMessage): """ Antwort mit System-Metriken. Enthaelt OS-, RAM-, CPU-, Disk- und Netzwerk-Informationen sowie Trixy-spezifische Daten. """ # OS-Info os_name: str = "" os_version: str = "" hostname: str = "" python_version: str = "" # RAM ram_total_mb: float = 0.0 ram_used_mb: float = 0.0 ram_percent: float = 0.0 # CPU cpu_model: str = "" cpu_count: int = 0 cpu_percent: float = 0.0 cpu_freq_mhz: float = 0.0 # Disk disk_total_gb: float = 0.0 disk_used_gb: float = 0.0 disk_percent: float = 0.0 # Netzwerk (aggregiert) net_bytes_sent: int = 0 net_bytes_recv: int = 0 net_connections: int = 0 # Netzwerk pro Interface: # {name, type, is_up, bytes_sent, bytes_recv, satellites_count} # type: "wifi" | "ethernet" | "loopback" | "other" net_interfaces: list = field(default_factory=list) # Uptime uptime_seconds: float = 0.0 # Trixy-spezifisch instance_type: str = "" trixy_version: str = "" satellites_connected: int = 0 satellites_total: int = 0 plugins_loaded: list[str] = field(default_factory=list) services_running: list[str] = field(default_factory=list) @dataclass class ConfigReadRequest(CommandMessage): """ Anfrage zum Lesen einer Konfiguration. Args: config_name: Name der Konfiguration (z.B. "server", "standalone") section: Optionale Sektion (z.B. "network", "audio") """ config_name: str = "" section: str = "" @dataclass class ConfigReadResponse(CommandMessage): """ Antwort mit Konfigurationsdaten. Args: config_name: Name der Konfiguration section: Angeforderte Sektion data: Konfigurationsdaten als Dictionary readonly: Ob die Konfiguration schreibgeschuetzt ist """ config_name: str = "" section: str = "" data: dict = field(default_factory=dict) readonly: bool = False @dataclass class ConfigWriteRequest(CommandMessage): """ Anfrage zum Schreiben eines Konfigurationswerts. Args: config_name: Name der Konfiguration key_path: Punkt-separierter Pfad (z.B. "network.command_port") value: Neuer Wert """ config_name: str = "" key_path: str = "" value: object = None @dataclass class ConfigWriteResponse(CommandMessage): """ Antwort auf eine Schreibanfrage. Args: success: Ob das Schreiben erfolgreich war error: Fehlermeldung (falls nicht erfolgreich) requires_restart: Ob ein Neustart erforderlich ist """ success: bool = False error: str = "" requires_restart: bool = False @dataclass class ConfigFieldOptionsRequest(CommandMessage): """ Anfrage fuer dynamische Feld-Optionen. Fordert verfuegbare Auswahlmoeglichkeiten fuer Felder an, die dynamische Quellen verwenden (z.B. installierte Wakeword-Modelle). Args: field_sources: Liste von Quell-Bezeichnern (z.B. ["wakeword_models"]) """ field_sources: list[str] = field(default_factory=list) @dataclass class ConfigFieldOptionsResponse(CommandMessage): """ Antwort mit dynamischen Feld-Optionen. Args: options: Dictionary von Quell-Name -> Liste von (wert, anzeige) Tupeln """ options: dict[str, list[tuple[str, str]]] = field(default_factory=dict) @dataclass class ConfigSatelliteListRequest(CommandMessage): """ Anfrage fuer die Liste registrierter Satellites. """ pass @dataclass class SatelliteInfo: """ Informationen ueber einen einzelnen Satellite. """ satellite_id: str = "" alias: str = "" room_id: str = "" mac_address: str = "" ip_address: str = "" connected: bool = False version: str = "" registered_at: str = "" connected_at: str = "" has_active_conversation: bool = False @dataclass class ConfigSatelliteListResponse(CommandMessage): """ Antwort mit Satellite-Liste. Args: satellites: Liste von Satellite-Informationen registration_mode: Ob der Registrierungsmodus aktiv ist permanent_mode: Ob der permanente Modus aktiv ist """ satellites: list[dict] = field(default_factory=list) registration_mode: bool = False permanent_mode: bool = False @dataclass class ConfigSatelliteActionRequest(CommandMessage): """ Anfrage fuer eine Satellite-Aktion. Args: action: Aktions-Typ ("enable_registration", "disable_registration", "delete", "blacklist", "unblacklist") satellite_id: Betroffener Satellite (fuer delete/blacklist) mac_address: MAC-Adresse (alternativ zu satellite_id) timeout: Optionaler Timeout fuer Registration (Sekunden) """ action: str = "" satellite_id: str = "" mac_address: str = "" timeout: int = 60 @dataclass class ConfigSatelliteActionResponse(CommandMessage): """ Antwort auf eine Satellite-Aktion. Args: success: Ob die Aktion erfolgreich war error: Fehlermeldung (falls nicht erfolgreich) message: Erfolgsmeldung """ success: bool = False error: str = "" message: str = "" @dataclass class ConfigSatelliteDetailRequest(CommandMessage): """ Anfrage fuer detaillierte Satellite-Informationen. Wird fuer die Satellite Sub-Main Views benoetigt (Info, Connection, Conversation). Args: satellite_id: ID des angefragten Satellites """ satellite_id: str = "" @dataclass class ConfigSatelliteDetailResponse(CommandMessage): """ Antwort mit detaillierten Satellite-Informationen. Enthaelt alle Daten fuer die Satellite Sub-Main Views. """ satellite_id: str = "" error: str = "" # Info (F1) alias: str = "" room_id: str = "" mac_address: str = "" ip_address: str = "" version: str = "" os_name: str = "" os_version: str = "" hostname: str = "" uptime_seconds: float = 0.0 ping_ms: float = -1.0 # Connection (F2) - pro Socket sockets: dict = field(default_factory=dict) # Conversation (F3) wakeword_model: str = "" wakeword_last_detection: str = "" voice_recognition_model: str = "" voice_recognition_last_speaker: str = "" has_active_conversation: bool = False last_conversation_at: str = "" last_conversation_duration: float = 0.0 conversation_state: str = "" # Conversation-History (letzte abgeschlossene Sessions) conversation_history: list[dict] = field(default_factory=list) @dataclass class ConfigSatelliteConfigReadRequest(CommandMessage): """ Anfrage zum Lesen der Konfiguration eines Satellites. Wird vom Config-Tool an den Server gesendet. Der Server leitet die Anfrage an den Satellite weiter. Args: satellite_id: ID des Satellites config_name: Konfigurationsname (leer = Haupt-Config) section: Optionale Sektion """ satellite_id: str = "" config_name: str = "" section: str = "" @dataclass class ConfigSatelliteConfigReadResponse(CommandMessage): """ Antwort mit der Konfiguration eines Satellites. Args: satellite_id: ID des Satellites data: Konfigurationsdaten als Dictionary error: Fehlermeldung (falls nicht erfolgreich) """ satellite_id: str = "" data: dict = field(default_factory=dict) error: str = "" @dataclass class ConfigSatelliteConfigWriteRequest(CommandMessage): """ Anfrage zum Schreiben einer Konfiguration auf einem Satellite. Wird vom Config-Tool an den Server gesendet. Der Server leitet die Anfrage an den Satellite weiter. Args: satellite_id: ID des Satellites config_name: Konfigurationsname key_path: Punkt-separierter Pfad value: Neuer Wert """ satellite_id: str = "" config_name: str = "" key_path: str = "" value: object = None @dataclass class ConfigSatelliteConfigWriteResponse(CommandMessage): """ Antwort auf eine Satellite-Config-Schreibanfrage. Args: satellite_id: ID des Satellites success: Ob das Schreiben erfolgreich war error: Fehlermeldung requires_restart: Ob ein Neustart erforderlich ist """ satellite_id: str = "" success: bool = False error: str = "" requires_restart: bool = False # ── Plugin-Befehle ── @dataclass class ConfigPluginListRequest(CommandMessage): """ Anfrage fuer die Liste aller Plugins. """ pass @dataclass class ConfigPluginListResponse(CommandMessage): """ Antwort mit Plugin-Liste. Args: plugins: Liste von Plugin-Informationen (dicts) """ plugins: list[dict] = field(default_factory=list) @dataclass class ConfigPluginActionRequest(CommandMessage): """ Anfrage fuer eine Plugin-Aktion. Args: action: Aktions-Typ ("enable", "disable", "reload", oder plugin-spezifisch) plugin_name: Name des Plugins params: Optionale Parameter fuer plugin-spezifische Aktionen """ action: str = "" plugin_name: str = "" params: dict = field(default_factory=dict) @dataclass class ConfigPluginActionResponse(CommandMessage): """ Antwort auf eine Plugin-Aktion. Args: success: Ob die Aktion erfolgreich war error: Fehlermeldung message: Erfolgsmeldung result_data: Optionale Rueckgabedaten (z.B. Listen, Konfigurationsdaten) """ success: bool = False error: str = "" message: str = "" result_data: dict = field(default_factory=dict) @dataclass class ConfigPluginDetailRequest(CommandMessage): """ Anfrage fuer detaillierte Plugin-Informationen. Args: plugin_name: Name des Plugins """ plugin_name: str = "" @dataclass class ConfigPluginDetailResponse(CommandMessage): """ Antwort mit detaillierten Plugin-Informationen. Args: plugin_name: Name des Plugins error: Fehlermeldung version: Plugin-Version description: Plugin-Beschreibung author: Plugin-Autor enabled: Ob das Plugin aktiviert ist loaded: Ob on_load aufgerufen wurde config: Plugin-Konfiguration als dict intents: Registrierte Intents event_handlers: Registrierte Event-Handler custom_tabs: Zusaetzliche Tabs fuer die TUI (Name -> Tab-Daten) """ plugin_name: str = "" error: str = "" version: str = "" description: str = "" author: str = "" enabled: bool = False loaded: bool = False config: dict = field(default_factory=dict) intents: list[str] = field(default_factory=list) event_handlers: list[str] = field(default_factory=list) custom_tabs: list[dict] = field(default_factory=list) @dataclass class ConfigPluginConfigWriteRequest(CommandMessage): """ Anfrage zum Schreiben eines Plugin-Konfigurationswerts. Args: plugin_name: Name des Plugins key_path: Punkt-separierter Pfad value: Neuer Wert """ plugin_name: str = "" key_path: str = "" value: object = None @dataclass class ConfigPluginConfigWriteResponse(CommandMessage): """ Antwort auf eine Plugin-Config-Schreibanfrage. Args: success: Ob das Schreiben erfolgreich war error: Fehlermeldung """ success: bool = False error: str = "" @dataclass class ConfigMicTestStartRequest(CommandMessage): """ Anfrage zum Starten eines Mikrofon-Tests. Der Server sendet zuerst TTS an den Satellite, dann leitet er Audio-Input-Daten an das Config-Tool weiter. Args: satellite_id: ID des Satellites """ satellite_id: str = "" @dataclass class ConfigMicTestStartResponse(CommandMessage): """ Antwort auf eine Mikrofon-Test-Anfrage. Args: success: Ob der Test gestartet wurde error: Fehlermeldung """ success: bool = False error: str = "" @dataclass class ConfigMicTestStopRequest(CommandMessage): """ Anfrage zum Stoppen eines laufenden Mikrofon-Tests. Args: satellite_id: ID des Satellites """ satellite_id: str = "" @dataclass class ConfigMicTestStopResponse(CommandMessage): """ Antwort auf eine Mikrofon-Test-Stop-Anfrage. Args: success: Ob der Test gestoppt wurde error: Fehlermeldung """ success: bool = False error: str = "" @dataclass class ConfigMicTestAudioData(CommandMessage): """ Audio-Daten vom Mikrofon-Test. Wird vom Server an das Config-Tool gesendet, waehrend der Mikrofon-Test laeuft. Args: satellite_id: ID des Satellites audio_data: Rohe Audio-Daten (16KHz, mono, 16-bit PCM) sample_rate: Abtastrate channels: Kanalanzahl """ satellite_id: str = "" audio_data: bytes = b"" sample_rate: int = 16000 channels: int = 1 # ── Schedule-Befehle ── @dataclass class ConfigScheduleListRequest(CommandMessage): """Anfrage fuer die Liste aller Schedule-Jobs.""" pass @dataclass class ConfigScheduleListResponse(CommandMessage): """ Antwort mit Schedule-Job-Liste. Args: jobs: Liste von Job-Informationen (dicts mit job_id, name, description, trigger_type, state, enabled, last_run, next_run, run_count) """ jobs: list[dict] = field(default_factory=list) @dataclass class ConfigScheduleActionRequest(CommandMessage): """ Anfrage fuer eine Schedule-Job-Aktion. Args: action: Aktions-Typ ("enable", "disable", "delete", "run_now") job_id: ID des Jobs """ action: str = "" job_id: str = "" @dataclass class ConfigScheduleActionResponse(CommandMessage): """ Antwort auf eine Schedule-Job-Aktion. Args: success: Ob die Aktion erfolgreich war error: Fehlermeldung message: Erfolgsmeldung """ success: bool = False error: str = "" message: str = "" @dataclass class ConfigScheduleDetailRequest(CommandMessage): """ Anfrage fuer detaillierte Job-Informationen. Args: job_id: ID des Jobs """ job_id: str = "" @dataclass class ConfigScheduleDetailResponse(CommandMessage): """ Antwort mit detaillierten Job-Informationen. Enthaelt alle Daten fuer die Schedule Sub-Views (Info, Trigger, Conditions, Actions). Args: job_id: ID des Jobs error: Fehlermeldung name: Job-Name description: Beschreibung state: Job-Status enabled: Ob aktiviert created_at: Erstellungszeitpunkt last_run: Letzte Ausfuehrung next_run: Naechste geplante Ausfuehrung run_count: Anzahl Ausfuehrungen failure_count: Anzahl Fehler trigger: Trigger-Daten als dict (type + Felder) conditions: Conditions als list[dict] actions: Actions als list[dict] config: Job-Konfiguration (max_runs, max_failures, timeout, tags, etc.) history: Letzte Ausfuehrungsergebnisse """ job_id: str = "" error: str = "" name: str = "" description: str = "" state: str = "" enabled: bool = False created_at: str = "" last_run: str = "" next_run: str = "" run_count: int = 0 failure_count: int = 0 trigger: dict = field(default_factory=dict) conditions: list[dict] = field(default_factory=list) actions: list[dict] = field(default_factory=list) config: dict = field(default_factory=dict) history: list[dict] = field(default_factory=list) @dataclass class ConfigScheduleSaveRequest(CommandMessage): """ Anfrage zum Erstellen oder Aktualisieren eines Schedule-Jobs. Enthaelt die kompletten Job-Daten. Wenn job_id leer ist, wird ein neuer Job erstellt. Args: job_id: Job-ID (leer = neuer Job) name: Job-Name description: Beschreibung trigger: Trigger-Daten als dict (type + Felder) conditions: Conditions als list[dict] actions: Actions als list[dict] config: Job-Konfiguration als dict """ job_id: str = "" name: str = "" description: str = "" trigger: dict = field(default_factory=dict) conditions: list[dict] = field(default_factory=list) actions: list[dict] = field(default_factory=list) config: dict = field(default_factory=dict) @dataclass class ConfigScheduleSaveResponse(CommandMessage): """ Antwort auf eine Schedule-Job-Speicheranfrage. Args: success: Ob das Speichern erfolgreich war job_id: ID des erstellten/aktualisierten Jobs error: Fehlermeldung """ success: bool = False job_id: str = "" error: str = "" @dataclass class ConfigScheduleFormMetaRequest(CommandMessage): """ Anfrage fuer Formular-Metadaten der Scheduler-Komponenten. Liefert die verfuegbaren Trigger/Condition/Action-Typen mit ihren Formular-Feldern fuer die TUI. """ pass @dataclass class ConfigScheduleFormMetaResponse(CommandMessage): """ Antwort mit Formular-Metadaten. Args: triggers: Dict von Typ-Name -> {display_name, fields: list[dict]} conditions: Dict von Typ-Name -> {display_name, fields: list[dict]} actions: Dict von Typ-Name -> {display_name, fields: list[dict]} """ triggers: dict = field(default_factory=dict) conditions: dict = field(default_factory=dict) actions: dict = field(default_factory=dict) # ── Trainer-Befehle ── @dataclass class ConfigTrainerListRequest(CommandMessage): """Anfrage fuer die Liste aller verfuegbaren Trainer.""" pass @dataclass class ConfigTrainerListResponse(CommandMessage): """ Antwort mit Trainer-Liste. Args: trainers: Liste von Trainer-Informationen (dicts) """ trainers: list[dict] = field(default_factory=list) @dataclass class ConfigTrainerDetailRequest(CommandMessage): """ Anfrage fuer detaillierte Trainer-Informationen. Args: trainer_id: ID des Trainers """ trainer_id: str = "" @dataclass class ConfigTrainerDetailResponse(CommandMessage): """ Antwort mit detaillierten Trainer-Informationen. Enthaelt Info, Schemas, aktuelle Settings und Dataset-Info. """ trainer_id: str = "" error: str = "" name: str = "" description: str = "" version: str = "" author: str = "" model_type: str = "" trainer_type: str = "" settings_schema: dict = field(default_factory=dict) dataset_schema: dict = field(default_factory=dict) optional_schema: dict | None = None settings: dict = field(default_factory=dict) dataset_info: dict = field(default_factory=dict) @dataclass class ConfigTrainerSettingsWriteRequest(CommandMessage): """ Anfrage zum Schreiben von Trainer-Einstellungen. Args: trainer_id: ID des Trainers settings: Einstellungswerte als dict """ trainer_id: str = "" settings: dict = field(default_factory=dict) @dataclass class ConfigTrainerSettingsWriteResponse(CommandMessage): """ Antwort auf Trainer-Settings-Schreibanfrage. Args: success: Ob das Schreiben erfolgreich war error: Fehlermeldung """ success: bool = False error: str = "" @dataclass class ConfigTrainerValidateRequest(CommandMessage): """ Anfrage zur Validierung eines Trainers. Args: trainer_id: ID des Trainers """ trainer_id: str = "" @dataclass class ConfigTrainerValidateResponse(CommandMessage): """ Antwort auf eine Validierungsanfrage. Args: valid: Ob die Validierung erfolgreich war errors: Liste von Fehlermeldungen warnings: Liste von Warnungen gpu_available: Ob eine GPU verfuegbar ist gpu_name: Name der GPU gpu_memory_mb: GPU-Speicher in MB """ valid: bool = False errors: list[str] = field(default_factory=list) warnings: list[str] = field(default_factory=list) gpu_available: bool = False gpu_name: str = "" gpu_memory_mb: float = 0.0 @dataclass class ConfigTrainerStartRequest(CommandMessage): """ Anfrage zum Starten eines Trainings. Args: trainer_id: ID des Trainers """ trainer_id: str = "" @dataclass class ConfigTrainerStartResponse(CommandMessage): """ Antwort auf eine Training-Start-Anfrage. Args: success: Ob das Training gestartet wurde error: Fehlermeldung """ success: bool = False error: str = "" @dataclass class ConfigTrainerPauseRequest(CommandMessage): """Anfrage zum Pausieren des laufenden Trainings.""" pass @dataclass class ConfigTrainerPauseResponse(CommandMessage): """Antwort auf eine Pause-Anfrage.""" success: bool = False error: str = "" @dataclass class ConfigTrainerResumeRequest(CommandMessage): """Anfrage zum Fortsetzen eines pausierten Trainings.""" pass @dataclass class ConfigTrainerResumeResponse(CommandMessage): """Antwort auf eine Resume-Anfrage.""" success: bool = False error: str = "" @dataclass class ConfigTrainerStopRequest(CommandMessage): """Anfrage zum Stoppen des laufenden Trainings.""" pass @dataclass class ConfigTrainerStopResponse(CommandMessage): """Antwort auf eine Stop-Anfrage.""" success: bool = False error: str = "" @dataclass class ConfigTrainerProgressRequest(CommandMessage): """Anfrage fuer den aktuellen Trainings-Fortschritt.""" pass @dataclass class ConfigTrainerProgressResponse(CommandMessage): """ Antwort mit aktuellem Trainings-Fortschritt. Args: state: Trainings-Status (idle, training, paused, ...) trainer_id: ID des aktiven Trainers epoch: Aktuelle Epoche total_epochs: Gesamtzahl Epochen loss: Aktueller Training-Loss val_loss: Aktueller Validation-Loss accuracy: Aktuelle Genauigkeit learning_rate: Aktuelle Lernrate eta_seconds: Geschaetzte Restzeit vram_used_mb: GPU-Speicherverbrauch loss_history: Verlauf aller Training-Losses val_loss_history: Verlauf aller Validation-Losses message: Status-Nachricht error: Fehlermeldung """ state: str = "idle" trainer_id: str = "" epoch: int = 0 total_epochs: int = 0 loss: float = 0.0 val_loss: float = 0.0 accuracy: float = 0.0 learning_rate: float = 0.0 eta_seconds: float = 0.0 vram_used_mb: float = 0.0 loss_history: list[float] = field(default_factory=list) val_loss_history: list[float] = field(default_factory=list) message: str = "" error: str = "" @dataclass class ConfigTrainerActionRequest(CommandMessage): """ Anfrage zum Ausfuehren einer Trainer-Aktion. Args: trainer_id: ID des Trainers action: Name der Aktion (z.B. "generate_tts") params: Parameter fuer die Aktion """ trainer_id: str = "" action: str = "" params: dict = field(default_factory=dict) @dataclass class ConfigTrainerActionResponse(CommandMessage): """ Antwort auf eine Trainer-Aktion. Args: success: Ob die Aktion erfolgreich war message: Status-/Fehlermeldung data: Optionale Ergebnisdaten """ success: bool = False message: str = "" data: dict = field(default_factory=dict) # ── Satellite-Audio (F6 Audio View) ── @dataclass class SatelliteAudioRequest(CommandMessage): """ Audio-Anfrage zwischen Server und Satellite (interner Hop). Wird vom Server an einen Satellite weitergereicht. Der Satellite antwortet mit SatelliteAudioResponse. Args: action: "query" | "set_volume" | "set_mute" | "list_devices" | "list_pulse_sinks" | "set_speakers" | "list_pulse_sources" | "set_microphones" target: "output" | "input" volume: Zielwert in Prozent (0-100), nur bei set_volume muted: Mute-Zustand, nur bei set_mute source: "user" | "hid" — wird an VolumeHandler weitergereicht speakers: Liste von Speaker-Eintraegen fuer set_speakers, jeweils {"device": str, "enabled": bool, "volume": int} microphones: Liste von Mic-Eintraegen fuer set_microphones, jeweils {"device": str, "enabled": bool, "label": str} """ action: str = "query" target: str = "output" volume: int = 0 muted: bool = False source: str = "user" speakers: list = field(default_factory=list) microphones: list = field(default_factory=list) @dataclass class SatelliteAudioResponse(CommandMessage): """ Audio-Antwort des Satellites an den Server. Args: success: Ob die Aktion erfolgreich war error: Fehlermeldung output_available: Ob ALSA Output verfuegbar ist output_control: Aktiver ALSA Output Mixer-Control output_volume: Aktuelle Output-Lautstaerke (0-100) output_muted: Aktueller Output-Mute-Status input_available: Ob ALSA Capture verfuegbar ist input_control: Aktiver ALSA Capture Mixer-Control input_volume: Aktuelle Capture-Lautstaerke (0-100) input_muted: Aktueller Capture-Mute-Status input_devices: Liste der Aufnahme-Geraete output_devices: Liste der Wiedergabe-Geraete """ success: bool = True error: str = "" output_available: bool = False output_control: str = "" output_volume: int = 0 output_muted: bool = False input_available: bool = False input_control: str = "" input_volume: int = 0 input_muted: bool = False input_devices: list = field(default_factory=list) output_devices: list = field(default_factory=list) pulse_available: bool = False pulse_sinks: list = field(default_factory=list) output_speakers: list = field(default_factory=list) combined_sink_active: bool = False pulse_sources: list = field(default_factory=list) input_microphones: list = field(default_factory=list) input_mix_active: bool = False @dataclass class ConfigSatelliteAudioRequest(CommandMessage): """ Audio-Anfrage vom Config-Tool an den Server. Der Server reicht die Anfrage an den genannten Satellite weiter und liefert die Antwort zurueck. Args: satellite_id: ID des Satellites action: "query" | "set_volume" | "set_mute" | "list_devices" target: "output" | "input" volume: 0-100 (bei set_volume) muted: bool (bei set_mute) """ satellite_id: str = "" action: str = "query" target: str = "output" volume: int = 0 muted: bool = False speakers: list = field(default_factory=list) microphones: list = field(default_factory=list) @dataclass class ConfigSatelliteAudioResponse(CommandMessage): """ Audio-Antwort vom Server an das Config-Tool. Spiegelt SatelliteAudioResponse plus satellite_id. """ satellite_id: str = "" success: bool = True error: str = "" output_available: bool = False output_control: str = "" output_volume: int = 0 output_muted: bool = False input_available: bool = False input_control: str = "" input_volume: int = 0 input_muted: bool = False input_devices: list = field(default_factory=list) output_devices: list = field(default_factory=list) pulse_available: bool = False pulse_sinks: list = field(default_factory=list) output_speakers: list = field(default_factory=list) combined_sink_active: bool = False pulse_sources: list = field(default_factory=list) input_microphones: list = field(default_factory=list) input_mix_active: bool = False