network_view.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. # -*- coding: utf-8 -*-
  2. """
  3. F2: Netzwerk-Konfiguration — WiFi-Hotspot, WLAN-Verbindung, Server-Verbindung.
  4. """
  5. from __future__ import annotations
  6. from textual.widgets import Checkbox, Input, Label, RadioButton, RadioSet, Static
  7. from .base import InstallerView
  8. class NetworkView(InstallerView):
  9. """Netzwerk-Einstellungen (F2)."""
  10. TITLE = "Netzwerk"
  11. VIEW_ID = "network"
  12. MODES = ["server", "client", "standalone"]
  13. def compose(self):
  14. if self._config.mode == "server":
  15. yield from self._compose_server()
  16. elif self._config.mode == "client":
  17. yield from self._compose_wifi_connect()
  18. yield from self._compose_client()
  19. elif self._config.mode == "standalone":
  20. yield from self._compose_wifi_connect()
  21. def _compose_server(self):
  22. """Server: WiFi-Hotspot Konfiguration."""
  23. yield Static("── WiFi-Hotspot ──", classes="section-header")
  24. yield Checkbox(
  25. "WiFi-Hotspot aktivieren",
  26. value=self._config.wifi_enabled,
  27. id="cb-wifi-enabled",
  28. )
  29. yield Label("")
  30. yield Label("SSID:")
  31. yield Input(
  32. value=self._config.wifi_ssid,
  33. placeholder="z.B. trixyone_srv",
  34. id="input-wifi-ssid",
  35. )
  36. yield Label("Passwort (min. 8 Zeichen):")
  37. yield Input(
  38. value=self._config.wifi_password,
  39. placeholder="WiFi-Passwort",
  40. id="input-wifi-password",
  41. password=True,
  42. )
  43. yield Label("Kanal (1-13):")
  44. yield Input(
  45. value=str(self._config.wifi_channel),
  46. placeholder="6",
  47. id="input-wifi-channel",
  48. )
  49. yield Label("Access-Point IP:")
  50. yield Input(
  51. value=self._config.ap_ip,
  52. placeholder="10.10.10.1",
  53. id="input-ap-ip",
  54. )
  55. yield Label("DHCP-Bereich Start:")
  56. yield Input(
  57. value=self._config.dhcp_range_start,
  58. placeholder="10.10.10.10",
  59. id="input-dhcp-start",
  60. )
  61. yield Label("DHCP-Bereich Ende:")
  62. yield Input(
  63. value=self._config.dhcp_range_end,
  64. placeholder="10.10.10.50",
  65. id="input-dhcp-end",
  66. )
  67. def _compose_wifi_connect(self):
  68. """Client/Standalone: WLAN-Verbindung konfigurieren."""
  69. yield Static("── WLAN-Verbindung ──", classes="section-header")
  70. yield RadioSet(
  71. RadioButton(
  72. "Keine Aenderung — bestehendes WLAN beibehalten",
  73. value=not self._config.wifi_connect,
  74. id="rb-wifi-keep",
  75. ),
  76. RadioButton(
  77. "WLAN konfigurieren — mit Netzwerk verbinden",
  78. value=self._config.wifi_connect,
  79. id="rb-wifi-connect",
  80. ),
  81. id="rs-wifi-connect",
  82. )
  83. yield Label("")
  84. yield Label("WLAN SSID:")
  85. yield Input(
  86. value=self._config.wifi_connect_ssid,
  87. placeholder="z.B. trixyone_srv",
  88. id="input-wifi-connect-ssid",
  89. disabled=not self._config.wifi_connect,
  90. )
  91. yield Label("WLAN Passwort:")
  92. yield Input(
  93. value=self._config.wifi_connect_password,
  94. placeholder="WLAN-Passwort",
  95. id="input-wifi-connect-password",
  96. password=True,
  97. disabled=not self._config.wifi_connect,
  98. )
  99. yield Label("")
  100. def _compose_client(self):
  101. """Client: Server-Verbindung."""
  102. yield Static("── Server-Verbindung ──", classes="section-header")
  103. yield Label("Server-Host:")
  104. yield Input(
  105. value=self._config.server_host,
  106. placeholder="z.B. 10.10.10.1",
  107. id="input-server-host",
  108. )
  109. yield Label("Server-Port:")
  110. yield Input(
  111. value=str(self._config.server_port),
  112. placeholder="2101",
  113. id="input-server-port",
  114. )
  115. yield Label("Raum:")
  116. yield Input(
  117. value=self._config.room,
  118. placeholder="z.B. Wohnzimmer",
  119. id="input-room",
  120. )
  121. yield Label("Alias:")
  122. yield Input(
  123. value=self._config.alias,
  124. placeholder="z.B. Patrick",
  125. id="input-alias",
  126. )
  127. def on_radio_set_changed(self, event: RadioSet.Changed) -> None:
  128. """WLAN-Modus umschalten."""
  129. if event.radio_set.id == "rs-wifi-connect":
  130. pressed_id = event.pressed.id if event.pressed else ""
  131. connect = pressed_id == "rb-wifi-connect"
  132. self._config.wifi_connect = connect
  133. # Eingabefelder aktivieren/deaktivieren
  134. try:
  135. self.query_one("#input-wifi-connect-ssid", Input).disabled = not connect
  136. self.query_one("#input-wifi-connect-password", Input).disabled = not connect
  137. except Exception:
  138. pass
  139. def on_input_changed(self, event: Input.Changed) -> None:
  140. """Aktualisiert Konfig bei Eingabeaenderungen."""
  141. mapping = {
  142. "input-wifi-ssid": "wifi_ssid",
  143. "input-wifi-password": "wifi_password",
  144. "input-ap-ip": "ap_ip",
  145. "input-dhcp-start": "dhcp_range_start",
  146. "input-dhcp-end": "dhcp_range_end",
  147. "input-wifi-connect-ssid": "wifi_connect_ssid",
  148. "input-wifi-connect-password": "wifi_connect_password",
  149. "input-server-host": "server_host",
  150. "input-room": "room",
  151. "input-alias": "alias",
  152. }
  153. attr = mapping.get(event.input.id or "")
  154. if attr:
  155. setattr(self._config, attr, event.value)
  156. elif event.input.id == "input-wifi-channel":
  157. try:
  158. self._config.wifi_channel = int(event.value)
  159. except ValueError:
  160. pass
  161. elif event.input.id == "input-server-port":
  162. try:
  163. self._config.server_port = int(event.value)
  164. except ValueError:
  165. pass
  166. def on_checkbox_changed(self, event: Checkbox.Changed) -> None:
  167. if event.checkbox.id == "cb-wifi-enabled":
  168. self._config.wifi_enabled = event.value
  169. def validate(self) -> str | None:
  170. if self._config.mode == "server" and self._config.wifi_enabled:
  171. if not self._config.wifi_ssid.strip():
  172. return "WiFi SSID darf nicht leer sein"
  173. if len(self._config.wifi_password) < 8:
  174. return "WiFi Passwort muss mindestens 8 Zeichen haben"
  175. elif self._config.mode == "client":
  176. if not self._config.server_host.strip():
  177. return "Server-Host darf nicht leer sein"
  178. if not self._config.room.strip():
  179. return "Raum darf nicht leer sein"
  180. if not self._config.alias.strip():
  181. return "Alias darf nicht leer sein"
  182. # WLAN-Validierung (Client/Standalone)
  183. if self._config.wifi_connect:
  184. if not self._config.wifi_connect_ssid.strip():
  185. return "WLAN SSID darf nicht leer sein"
  186. if len(self._config.wifi_connect_password) < 8:
  187. return "WLAN Passwort muss mindestens 8 Zeichen haben"
  188. return None