import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../transport/connection_type.dart'; import '../../transport/flight_controller_link.dart'; import '../../transport/link_transport.dart'; import '../../transport/mock/mock_flight_controller_link.dart'; import '../../transport/msp/msp_flight_controller_link.dart'; import 'connection_settings_provider.dart'; import 'wifi_connection_provider.dart'; /// FlightControllerLink fuer den Fly-Modus (Doku 3.1): bei WLAN als /// gewaehlter Verbindungsart ein echter MSP-Link ueber den UDP-Transport, /// sonst (Bluetooth/5G/USB, oder solange die Einstellungen noch nicht /// geladen sind) weiterhin der Mock fuer UI-Entwicklung ohne Hardware - /// Bluetooth ist auf der eingesetzten mLRS-Bruecke ohnehin nicht moeglich /// (Doku Kommunikationsschicht v2, Abschnitt 1), 5G/USB sind noch nicht /// umgesetzt. /// /// connectionType wird reaktiv beobachtet (ref.watch), nicht nur einmalig /// gelesen - beim ersten App-Start ist connectionSettingsProvider oft noch /// nicht aus der DB geladen (AsyncLoading, value == null), was ohne Watch /// dauerhaft auf den Mock-Fallback festgenagelt haette (siehe unten, "nicht /// autoDispose"): sobald die Einstellungen nachladen oder der Nutzer die /// Verbindungsart in den Settings aendert, baut dieser Provider sich korrekt /// neu auf (alter Link wird dabei via ref.onDispose sauber getrennt). Das /// ist inzwischen unkritisch haeufig, da die fruehere Sorge (Tippen im /// SSID-Praefix-Feld loest bei jedem Zeichen einen Neuaufbau aus) entfaellt, /// seit dieses Feld aus den Settings entfernt wurde (Preset "WiFi mLRS UDP"). /// /// Bewusst NICHT autoDispose (Doku: "beim Wechsel in Plan kein disconnect /// triggern, Verbindung aktiv halten") - anders als frueher trennt ein /// Wechsel zurueck in den Plan-Modus (der telemetryProvider nicht mehr /// beobachtet) die Verbindung nicht mehr automatisch. Sie bleibt bis zum /// expliziten "Disconnect" in den Settings, einer Aenderung der /// Verbindungsart oder Schliessen der App bestehen. /// [MspFlightControllerLink.connect]/[MockFlightControllerLink.connect] /// sind deshalb idempotent: jeder erneute Watch von [telemetryProvider] /// (z.B. erneuter Eintritt in den Fly-Modus) ruft `connect()` erneut auf, /// darf aber keinen zweiten MSP-Client/-Poller nebenher starten. final flightControllerLinkProvider = Provider((ref) { final connectionType = ref.watch(connectionSettingsProvider).value?.connectionType; final FlightControllerLink link = connectionType == ConnectionType.wifi ? MspFlightControllerLink(transport: ref.watch(wifiTransportProvider)) : MockFlightControllerLink(); ref.onDispose(link.disconnect); return link; }); /// Live-Telemetrie des verbundenen Flightcontrollers (Doku 3.4). Bleibt /// selbst autoDispose: nur die Frame-Weiterleitung an gerade aktive Watcher /// endet beim Verlassen, nicht die zugrundeliegende Verbindung (siehe /// [flightControllerLinkProvider]). /// /// Ruft bei WLAN/MSP bewusst NICHT einfach `link.connect()` auf, sobald /// irgendwer (z.B. FlyScreen beim Eintritt in den Fly-Modus) diesen Provider /// beobachtet (Doku: "kein connect beim Wechsel in den Fly-Modus, um das /// Debuggen auf echter Hardware zu vereinfachen") - `MspFlightControllerLink. /// connect()` wuerde sonst ueber `transport.connect()` sofort einen /// WifiNetworkSpecifier-Systemdialog ausloesen, unabhaengig vom entfernten /// Auto-Connect-Trigger in TopModeBar. Stattdessen wird erst aktiv, sobald /// die rohe WLAN-Verbindung bereits ueber den expliziten "Connect"-Knopf in /// den Settings steht - bis dahin bleibt der Stream leer (kein Frame, /// FlyScreen zeigt den Fallback-Marker auf dem ersten Wegpunkt). Fuer /// Mock/Bluetooth/5G/USB gilt diese Einschraenkung nicht, dort ist /// "verbinden" ohnehin folgenlos bzw. noch nicht umgesetzt. final telemetryProvider = StreamProvider.autoDispose((ref) async* { final link = ref.watch(flightControllerLinkProvider); if (link is MspFlightControllerLink && ref.watch(wifiLinkStateProvider).value != LinkState.connected) { return; } await link.connect(); yield* link.subscribeTelemetry(); });