Die simulierte Telemetrie war fest auf 6S verdrahtet (18.0-24.0V), obwohl das Drohnenprofil laengst eine konfigurierbare Zellenzahl hat - beim T1-Ranger-Standardprofil (4S) zeigte die Statusanzeige dadurch bis zu 18V, obwohl 16.8V (4 * 4.2V Ladeschluss) der realistische Maximalwert ist. MockFlightControllerLink nimmt jetzt batteryCellCount entgegen und skaliert den simulierten Spannungsverlauf (4.2V/Zelle voll bis 3.0V/Zelle nahezu leer) damit. telemetry_provider.dart uebergibt dafuer die Zellenzahl des aktuell aktiven Drohnenprofils (ref.read, analog zu den initialWaypoints - einmalig bei der Verbindungserzeugung, kein Reset des laufenden Akkustands bei spaeteren Profilwechseln). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
86 lines
4.8 KiB
Dart
86 lines
4.8 KiB
Dart
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 'active_drone_profile_provider.dart';
|
|
import 'connection_settings_provider.dart';
|
|
import 'current_mission_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 (ConnectionType.mock, oder solange die Einstellungen noch nicht
|
|
/// geladen sind) der Mock fuer UI-Entwicklung/Testphase ohne Hardware.
|
|
///
|
|
/// 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<FlightControllerLink>((ref) {
|
|
final connectionType = ref.watch(connectionSettingsProvider).value?.connectionType;
|
|
final FlightControllerLink link = connectionType == ConnectionType.wifi
|
|
? MspFlightControllerLink(transport: ref.watch(wifiTransportProvider))
|
|
// ref.read() statt watch() - der Mock soll nur einmal bei seiner
|
|
// Erzeugung am ersten Wegpunkt der GERADE aktuellen Mission
|
|
// verankert werden (Doku: "Mock-Daten fuer die Live-Details-Ansicht
|
|
// nutzbar machen"), nicht bei jeder spaeteren Missionsaenderung
|
|
// neu erzeugt werden (das wuerde Timer/Drift/Akkustand zuruecksetzen).
|
|
// Gleiches gilt fuer die Zellenzahl: sie bestimmt nur den simulierten
|
|
// Spannungsbereich bei der Erzeugung, ein spaeterer Profilwechsel
|
|
// waehrend einer laufenden Mock-Verbindung setzt den Akkustand nicht
|
|
// zurueck.
|
|
: MockFlightControllerLink(
|
|
initialWaypoints: ref.read(currentMissionProvider),
|
|
batteryCellCount: ref.read(activeDroneProfileProvider).batteryCellCount,
|
|
);
|
|
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<TelemetryFrame>((ref) async* {
|
|
final link = ref.watch(flightControllerLinkProvider);
|
|
if (link is MspFlightControllerLink &&
|
|
ref.watch(wifiLinkStateProvider).value != LinkState.connected) {
|
|
return;
|
|
}
|
|
await link.connect();
|
|
yield* link.subscribeTelemetry();
|
|
});
|