| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- # -*- coding: utf-8 -*-
- """
- F2: Netzwerk-Konfiguration — WiFi-Hotspot, WLAN-Verbindung, Server-Verbindung.
- """
- from __future__ import annotations
- from textual.widgets import Checkbox, Input, Label, RadioButton, RadioSet, Static
- from .base import InstallerView
- class NetworkView(InstallerView):
- """Netzwerk-Einstellungen (F2)."""
- TITLE = "Netzwerk"
- VIEW_ID = "network"
- MODES = ["server", "client", "standalone"]
- def compose(self):
- if self._config.mode == "server":
- yield from self._compose_server()
- elif self._config.mode == "client":
- yield from self._compose_wifi_connect()
- yield from self._compose_client()
- elif self._config.mode == "standalone":
- yield from self._compose_wifi_connect()
- def _compose_server(self):
- """Server: WiFi-Hotspot Konfiguration."""
- yield Static("── WiFi-Hotspot ──", classes="section-header")
- yield Checkbox(
- "WiFi-Hotspot aktivieren",
- value=self._config.wifi_enabled,
- id="cb-wifi-enabled",
- )
- yield Label("")
- yield Label("SSID:")
- yield Input(
- value=self._config.wifi_ssid,
- placeholder="z.B. trixyone_srv",
- id="input-wifi-ssid",
- )
- yield Label("Passwort (min. 8 Zeichen):")
- yield Input(
- value=self._config.wifi_password,
- placeholder="WiFi-Passwort",
- id="input-wifi-password",
- password=True,
- )
- yield Label("Kanal (1-13):")
- yield Input(
- value=str(self._config.wifi_channel),
- placeholder="6",
- id="input-wifi-channel",
- )
- yield Label("Access-Point IP:")
- yield Input(
- value=self._config.ap_ip,
- placeholder="10.10.10.1",
- id="input-ap-ip",
- )
- yield Label("DHCP-Bereich Start:")
- yield Input(
- value=self._config.dhcp_range_start,
- placeholder="10.10.10.10",
- id="input-dhcp-start",
- )
- yield Label("DHCP-Bereich Ende:")
- yield Input(
- value=self._config.dhcp_range_end,
- placeholder="10.10.10.50",
- id="input-dhcp-end",
- )
- def _compose_wifi_connect(self):
- """Client/Standalone: WLAN-Verbindung konfigurieren."""
- yield Static("── WLAN-Verbindung ──", classes="section-header")
- yield RadioSet(
- RadioButton(
- "Keine Aenderung — bestehendes WLAN beibehalten",
- value=not self._config.wifi_connect,
- id="rb-wifi-keep",
- ),
- RadioButton(
- "WLAN konfigurieren — mit Netzwerk verbinden",
- value=self._config.wifi_connect,
- id="rb-wifi-connect",
- ),
- id="rs-wifi-connect",
- )
- yield Label("")
- yield Static("[dim]Primaeres Netz (bevorzugt, z.B. Trixy-Server-Hotspot)[/dim]")
- yield Label("SSID:")
- yield Input(
- value=self._config.wifi_connect_ssid,
- placeholder="z.B. trixyone_srv",
- id="input-wifi-connect-ssid",
- disabled=not self._config.wifi_connect,
- )
- yield Label("Passwort:")
- yield Input(
- value=self._config.wifi_connect_password,
- placeholder="WLAN-Passwort",
- id="input-wifi-connect-password",
- password=True,
- disabled=not self._config.wifi_connect,
- )
- yield Label("")
- yield Checkbox(
- "Fallback-WLAN aktivieren (z.B. Heim-WLAN)",
- value=self._config.wifi_fallback_enabled,
- id="cb-wifi-fallback",
- disabled=not self._config.wifi_connect,
- )
- yield Static(
- "[dim]Wird genutzt wenn das primaere Netz nicht erreichbar ist[/dim]"
- )
- yield Label("Fallback-SSID:")
- yield Input(
- value=self._config.wifi_fallback_ssid,
- placeholder="z.B. FRITZ!Box 7590",
- id="input-wifi-fallback-ssid",
- disabled=not (self._config.wifi_connect and self._config.wifi_fallback_enabled),
- )
- yield Label("Fallback-Passwort:")
- yield Input(
- value=self._config.wifi_fallback_password,
- placeholder="Fallback-WLAN-Passwort",
- id="input-wifi-fallback-password",
- password=True,
- disabled=not (self._config.wifi_connect and self._config.wifi_fallback_enabled),
- )
- yield Label("")
- yield Checkbox(
- "Auto-Rueckwechsel zum primaeren Netz",
- value=self._config.wifi_auto_switchback,
- id="cb-wifi-switchback",
- disabled=not (self._config.wifi_connect and self._config.wifi_fallback_enabled),
- )
- yield Static(
- "[dim]Prueft regelmaessig ob primaeres Netz wieder erreichbar ist[/dim]"
- )
- yield Label("Pruef-Intervall (Sekunden):")
- yield Input(
- value=str(self._config.wifi_switchback_interval),
- placeholder="30",
- id="input-wifi-switchback-interval",
- disabled=not (
- self._config.wifi_connect
- and self._config.wifi_fallback_enabled
- and self._config.wifi_auto_switchback
- ),
- )
- yield Label("")
- def _compose_client(self):
- """Client: Server-Verbindung."""
- yield Static("── Server-Verbindung ──", classes="section-header")
- yield Label("Server-Host:")
- yield Input(
- value=self._config.server_host,
- placeholder="z.B. 10.10.10.1",
- id="input-server-host",
- )
- yield Label("Server-Port:")
- yield Input(
- value=str(self._config.server_port),
- placeholder="2101",
- id="input-server-port",
- )
- yield Label("Raum:")
- yield Input(
- value=self._config.room,
- placeholder="z.B. Wohnzimmer",
- id="input-room",
- )
- yield Label("Alias:")
- yield Input(
- value=self._config.alias,
- placeholder="z.B. Patrick",
- id="input-alias",
- )
- def _update_wifi_field_states(self) -> None:
- """Aktualisiert disabled-Status der WLAN-Eingabefelder."""
- connect = self._config.wifi_connect
- fallback = self._config.wifi_fallback_enabled
- switchback = self._config.wifi_auto_switchback
- field_states = {
- "#input-wifi-connect-ssid": not connect,
- "#input-wifi-connect-password": not connect,
- "#cb-wifi-fallback": not connect,
- "#input-wifi-fallback-ssid": not (connect and fallback),
- "#input-wifi-fallback-password": not (connect and fallback),
- "#cb-wifi-switchback": not (connect and fallback),
- "#input-wifi-switchback-interval": not (connect and fallback and switchback),
- }
- for selector, disabled in field_states.items():
- try:
- widget = self.query_one(selector)
- widget.disabled = disabled
- except Exception:
- pass
- def on_radio_set_changed(self, event: RadioSet.Changed) -> None:
- """WLAN-Modus umschalten."""
- if event.radio_set.id == "rs-wifi-connect":
- pressed_id = event.pressed.id if event.pressed else ""
- self._config.wifi_connect = pressed_id == "rb-wifi-connect"
- self._update_wifi_field_states()
- def on_input_changed(self, event: Input.Changed) -> None:
- """Aktualisiert Konfig bei Eingabeaenderungen."""
- mapping = {
- "input-wifi-ssid": "wifi_ssid",
- "input-wifi-password": "wifi_password",
- "input-ap-ip": "ap_ip",
- "input-dhcp-start": "dhcp_range_start",
- "input-dhcp-end": "dhcp_range_end",
- "input-wifi-connect-ssid": "wifi_connect_ssid",
- "input-wifi-connect-password": "wifi_connect_password",
- "input-wifi-fallback-ssid": "wifi_fallback_ssid",
- "input-wifi-fallback-password": "wifi_fallback_password",
- "input-server-host": "server_host",
- "input-room": "room",
- "input-alias": "alias",
- }
- attr = mapping.get(event.input.id or "")
- if attr:
- setattr(self._config, attr, event.value)
- elif event.input.id == "input-wifi-channel":
- try:
- self._config.wifi_channel = int(event.value)
- except ValueError:
- pass
- elif event.input.id == "input-server-port":
- try:
- self._config.server_port = int(event.value)
- except ValueError:
- pass
- elif event.input.id == "input-wifi-switchback-interval":
- try:
- self._config.wifi_switchback_interval = int(event.value)
- except ValueError:
- pass
- def on_checkbox_changed(self, event: Checkbox.Changed) -> None:
- cb_id = event.checkbox.id or ""
- if cb_id == "cb-wifi-enabled":
- self._config.wifi_enabled = event.value
- elif cb_id == "cb-wifi-fallback":
- self._config.wifi_fallback_enabled = event.value
- self._update_wifi_field_states()
- elif cb_id == "cb-wifi-switchback":
- self._config.wifi_auto_switchback = event.value
- self._update_wifi_field_states()
- def validate(self) -> str | None:
- if self._config.mode == "server" and self._config.wifi_enabled:
- if not self._config.wifi_ssid.strip():
- return "WiFi SSID darf nicht leer sein"
- if len(self._config.wifi_password) < 8:
- return "WiFi Passwort muss mindestens 8 Zeichen haben"
- elif self._config.mode == "client":
- if not self._config.server_host.strip():
- return "Server-Host darf nicht leer sein"
- if not self._config.room.strip():
- return "Raum darf nicht leer sein"
- if not self._config.alias.strip():
- return "Alias darf nicht leer sein"
- # WLAN-Validierung (Client/Standalone)
- if self._config.wifi_connect:
- if not self._config.wifi_connect_ssid.strip():
- return "Primaere WLAN-SSID darf nicht leer sein"
- if len(self._config.wifi_connect_password) < 8:
- return "Primaeres WLAN-Passwort muss mindestens 8 Zeichen haben"
- if self._config.wifi_fallback_enabled:
- if not self._config.wifi_fallback_ssid.strip():
- return "Fallback-WLAN-SSID darf nicht leer sein"
- if len(self._config.wifi_fallback_password) < 8:
- return "Fallback-WLAN-Passwort muss mindestens 8 Zeichen haben"
- if self._config.wifi_fallback_ssid.strip() == self._config.wifi_connect_ssid.strip():
- return "Fallback- und primaere SSID muessen unterschiedlich sein"
- if self._config.wifi_switchback_interval < 10:
- return "Switchback-Intervall muss mindestens 10 Sekunden sein"
- return None
|