/// Ampelfarbe fuer die Verbindungs- und Positionsqualitaets-Icons in der /// Drohnen-Status-Pille (Doku: "icon mit Farbcodierung (gruen/gelb/rot)"). enum SignalLevel { green, yellow, red } /// Zustand der Drohne fuer das Papierflieger-Icon in der Drohnen-Status- /// Pille (Doku: "drone state: papierflieger icon mit farbcodierung ... mit /// text wie (idle, ready, armed, waypoint, error)"). [disconnected] deckt /// den Fall ab, dass der Telemetrie-Strom selbst gerade fehlerhaft ist /// (Doku: "Statuspille ... muss eine rote Drohne, eine rote /// Verbindungsqualität und den Status text in rot disconnected anzeigen"), /// im Unterschied zu den anderen Zustaenden, die aus (ggf. eingefrorenen, /// siehe computeDroneStatus) Telemetriewerten abgeleitet werden. enum DroneState { idle, ready, armed, waypoint, disconnected, error } /// Kombiniertes Ergebnis aus [computeDroneStatus] - die drei Elemente der /// Fly-Modus-Drohnen-Pille (Doku: "connection quality", "position quality", /// "drone state"). class DroneStatus { const DroneStatus({ required this.connectionQuality, required this.positionQuality, required this.state, }); final SignalLevel connectionQuality; final SignalLevel positionQuality; final DroneState state; } /// Verbindungsqualitaet aus Empfaenger-Linkqualitaet (LQ%) und /// Signal-Rausch-Verhaeltnis (SNR, dB) - LQ ist der primaere Massstab (die /// 70%-Schwelle entspricht iNAVs eigenem OSD-Alarm-Default /// `osd_link_quality_alarm`, `fc/settings.yaml`), SNR stuft zusaetzlich von /// gruen auf gelb herab, wenn das Rauschen trotz noch guter LQ bereits das /// Signal ueberdeckt (SNR < 0 dB). SignalLevel _connectionQuality({required int linkQuality, required int snrDb}) { if (linkQuality < 50) return SignalLevel.red; if (linkQuality < 70 || snrDb < 0) return SignalLevel.yellow; return SignalLevel.green; } /// Positionsqualitaet aus Satellitenanzahl und HDOP - gaengige GNSS- /// Faustregel (>=8 Sat. und HDOP <2.0 = gut, >=6 Sat. und HDOP <5.0 = /// brauchbar, sonst schlecht/kein Fix). SignalLevel _positionQuality({ required bool hasFix, required int numSat, required double hdop, }) { if (!hasFix) return SignalLevel.red; if (numSat >= 8 && hdop < 2.0) return SignalLevel.green; if (numSat >= 6 && hdop < 5.0) return SignalLevel.yellow; return SignalLevel.red; } /// Zustand aus Armed-Status, GPS-Fix und dem rohen Navigationsmodus /// (`MW_GPS_MODE_*`, siehe TelemetryFrame.navMode) - [connected] hat /// Vorrang vor allem anderen (kein Telemetrie-Strom heisst, keiner der /// anderen Werte ist aktuell), danach Emergency (15), "waypoint" nur /// solange tatsaechlich armed und im Waypoint-Missionsmodus (3) navigiert /// wird, "ready" markiert lediglich einen vorhandenen GPS-Fix im /// disarmed-Zustand (kein zusaetzlicher Qualitaets-Gate durch /// Positionsqualitaet - Nutzerentscheidung). DroneState _droneState({ required bool connected, required bool armed, required bool hasFix, required int navMode, }) { const navModeEmergency = 15; const navModeWaypointMission = 3; if (!connected) return DroneState.disconnected; if (navMode == navModeEmergency) return DroneState.error; if (armed && navMode == navModeWaypointMission) return DroneState.waypoint; if (armed) return DroneState.armed; if (hasFix) return DroneState.ready; return DroneState.idle; } /// Reine Ableitung aus einem [TelemetryFrame] (siehe transport/ /// flight_controller_link.dart) - kein MSP-/Protokollwissen, nur die /// bereits normalisierten Felder. /// /// [connected] spiegelt, ob der Telemetrie-Strom gerade tatsaechlich Daten /// liefert (z.B. `!telemetryProvider.hasError`, siehe fly_screen.dart) - /// getrennt von den einzelnen Telemetriewerten, weil diese bei einem /// Verbindungsverlust bewusst auf ihrem letzten Stand "einfrieren" (Doku: /// "im Drone Detail Menü ist es okay, dass die Daten einfrieren"), die /// Statuspille aber trotzdem ehrlich "disconnected" anzeigen soll statt /// den zuletzt bekannten (ggf. laengst veralteten) Zustand fortzuschreiben. DroneStatus computeDroneStatus({ required bool connected, required bool armed, required bool hasFix, required int numSat, required double hdop, required int linkQuality, required int snrDb, required int navMode, }) { return DroneStatus( connectionQuality: connected ? _connectionQuality(linkQuality: linkQuality, snrDb: snrDb) : SignalLevel.red, positionQuality: _positionQuality(hasFix: hasFix, numSat: numSat, hdop: hdop), state: _droneState(connected: connected, armed: armed, hasFix: hasFix, navMode: navMode), ); }