From 0141cdb17daedec074753f3c46de823f287ad1fe Mon Sep 17 00:00:00 2001 From: Constantin Leue <77660791+Consti3D@users.noreply.github.com> Date: Thu, 6 Aug 2026 22:38:11 +0200 Subject: [PATCH] Add flight mode and GPS fix type to drone status menu MSP_RAW_GPS already reports a fixType byte (0=no fix, 1=2D, 2=3D) but only a collapsed hasFix bool was surfaced past the parser. Thread fixType through TelemetryFrame and show it as a color-coded field in the status grid, alongside the already-parsed but previously unshown flight mode string. Arming/Temperatures/Flight mode is now a 3-column row, and GPS fix type/GPS satellites/GPS precision (HDOP) another. --- app/lib/transport/flight_controller_link.dart | 8 + .../mock/mock_flight_controller_link.dart | 1 + .../transport/msp/msp_telemetry_poller.dart | 1 + .../widgets/drone_status_messages_panel.dart | 168 +++++++++++------- app/test/domain/system_message_test.dart | 1 + .../system_message_log_provider_test.dart | 1 + 6 files changed, 112 insertions(+), 68 deletions(-) diff --git a/app/lib/transport/flight_controller_link.dart b/app/lib/transport/flight_controller_link.dart index 247b945..65d68f3 100644 --- a/app/lib/transport/flight_controller_link.dart +++ b/app/lib/transport/flight_controller_link.dart @@ -29,6 +29,7 @@ class TelemetryFrame { required this.lat, required this.lon, required this.hasFix, + required this.fixType, required this.numSat, required this.altitudeM, required this.gpsAltitudeM, @@ -54,6 +55,13 @@ class TelemetryFrame { final double lat; final double lon; final bool hasFix; + + /// Roher `gpsFixType_e`-Wert aus `MSP_RAW_GPS` (`MspGpsReading.fixType` in + /// msp_telemetry_codec.dart): 0 = kein Fix, 1 = 2D, 2 = 3D. [hasFix] ist + /// bereits daraus abgeleitet (`fixType != 0`) - dieses Feld existiert nur + /// fuer die 2D/3D-Unterscheidung selbst (Doku: "GPS Fixtyp im Drone Status + /// Menue anzeigen"). + final int fixType; final int numSat; /// Barometrisch/GPS-fusionierte Hoehe relativ zum Referenzpunkt der diff --git a/app/lib/transport/mock/mock_flight_controller_link.dart b/app/lib/transport/mock/mock_flight_controller_link.dart index a792c8c..9e72019 100644 --- a/app/lib/transport/mock/mock_flight_controller_link.dart +++ b/app/lib/transport/mock/mock_flight_controller_link.dart @@ -102,6 +102,7 @@ class MockFlightControllerLink implements FlightControllerLink { lat: lat, lon: lon, hasFix: true, + fixType: 2, numSat: 12, altitudeM: 120, // Leicht abweichend von altitudeM statt identisch (Doku: rohe diff --git a/app/lib/transport/msp/msp_telemetry_poller.dart b/app/lib/transport/msp/msp_telemetry_poller.dart index 79ef0db..47e5aff 100644 --- a/app/lib/transport/msp/msp_telemetry_poller.dart +++ b/app/lib/transport/msp/msp_telemetry_poller.dart @@ -137,6 +137,7 @@ class MspTelemetryPoller { lat: gps.lat, lon: gps.lon, hasFix: gps.hasFix, + fixType: gps.fixType, numSat: gps.numSat, altitudeM: altitudeM, gpsAltitudeM: gps.altitudeM, diff --git a/app/lib/ui/widgets/drone_status_messages_panel.dart b/app/lib/ui/widgets/drone_status_messages_panel.dart index 13b0141..237570f 100644 --- a/app/lib/ui/widgets/drone_status_messages_panel.dart +++ b/app/lib/ui/widgets/drone_status_messages_panel.dart @@ -144,84 +144,97 @@ class _DroneStatusMessagesPanelState extends ConsumerState _statusGrid(List tiles) { - final rows = []; - for (var i = 0; i < tiles.length; i += 2) { - final hasPair = i + 1 < tiles.length; - // Kein CrossAxisAlignment.stretch: diese Row sitzt direkt als - // ListView-Kind, das seinen Kindern unbegrenzte Hoehe gibt (0<=h<= - // Infinity) - stretch verlangt aber eine endliche Hoehe, um die Kacheln - // darauf zu strecken, und wirft sonst "BoxConstraints forces an - // infinite height" (fuehrte zum komplett schwarzen Status-Tab). Default - // (center) reicht, da beide Kacheln einer Zeile ohnehin fast gleich - // hohen Inhalt haben. - rows.add(Row( - children: [ - Expanded(child: tiles[i]), - if (hasPair) ...[ - const SizedBox(width: 8), - Expanded(child: tiles[i + 1]), + /// Ordnet die Statuszeilen in explizit vorgegebenen Gruppen an (Doku: "2 + /// felder pro zeile im drone status menue erlauben um platz effizienter zu + /// nutzen", inzwischen mit einzelnen 3er-Zeilen wie Arming/Temperatures/ + /// Flight mode) - anders als eine reine Zweier-Paarbildung braucht das + /// gemischte 2er/3er-Layout eine explizite Gruppierung pro Zeile statt + /// automatischem Chunking. + List _statusRows(List> rows) { + return [ + for (final tiles in rows) + Row( + children: [ + for (var i = 0; i < tiles.length; i++) ...[ + if (i > 0) const SizedBox(width: 8), + Expanded(child: tiles[i]), + ], ], - ], - )); - } - return rows; + ), + ]; } static const _signalColors = { @@ -359,6 +372,25 @@ class _DroneStatusMessagesPanelState extends ConsumerState 'No fix', + 1 => '2D fix', + 2 => '3D fix', + final other => 'Unknown ($other)', + }; + } + + SignalLevel _fixTypeLevel(int fixType) { + if (fixType >= 2) return SignalLevel.green; + if (fixType == 1) return SignalLevel.yellow; + return SignalLevel.red; + } + String _formatTemperatures(TelemetryFrame? frame) { if (frame == null) return '—'; return frame.temperaturesC.map((t) => t == null ? '—' : '${t.round()}°').join(' / '); diff --git a/app/test/domain/system_message_test.dart b/app/test/domain/system_message_test.dart index a1ce588..928a0a3 100644 --- a/app/test/domain/system_message_test.dart +++ b/app/test/domain/system_message_test.dart @@ -13,6 +13,7 @@ TelemetryFrame _frame({ lat: 52.5, lon: 13.4, hasFix: hasFix, + fixType: hasFix ? 2 : 0, numSat: numSat, altitudeM: 100, gpsAltitudeM: 100, diff --git a/app/test/ui/providers/system_message_log_provider_test.dart b/app/test/ui/providers/system_message_log_provider_test.dart index aa72b4b..841917d 100644 --- a/app/test/ui/providers/system_message_log_provider_test.dart +++ b/app/test/ui/providers/system_message_log_provider_test.dart @@ -14,6 +14,7 @@ TelemetryFrame _frame({bool hasFix = true, int numSat = 10}) => TelemetryFrame( lat: 52.5, lon: 13.4, hasFix: hasFix, + fixType: hasFix ? 2 : 0, numSat: numSat, altitudeM: 100, gpsAltitudeM: 100,