Neue Zeile ganz oben mit farblich kodierten Sensor-Badges (ACC/BARO/MAG/ GPS/RNG/OF/PITOT/TEMP, aus dem sensorStatus-Bitfeld von MSP2_INAV_STATUS, zuvor schon dokumentiert aber ungenutzt), darunter ein Zeilenpaar fuer Arming-Status und die ersten 3 Temperatursensoren (neu: MSP2_INAV_ TEMPERATURES, 0x201E). Ans Ende der Liste die Steig-/Sinkrate (vario aus MSP_ALTITUDE, bislang nur die Hoehe selbst wurde daraus gelesen). - msp_commands.dart: inavTemperatures-Konstante ergaenzt; die Sensor- Status-Bits (bisher nur als Doc-Kommentar bei MSP2_INAV_STATUS notiert) zu echten Konstanten (MspSensorStatusBits) promoviert, da jetzt tatsaechlich gebraucht. - msp_telemetry_codec.dart: parseMspAltitudeVerticalSpeedMs, parseMspInavStatusSensorStatus, parseMspInavTemperaturesC ergaenzt + Unit-Tests. - TelemetryFrame: sensorStatusBits (Bitmaske, protokollneutral durchgereicht wie navMode), temperaturesC (erste 3 Sensoren, null je nicht konfiguriertem Slot), verticalSpeedMs. - msp_telemetry_poller.dart: vario kommt aus derselben MSP_ALTITUDE- Antwort wie die Hoehe (keine zusaetzliche Anfrage), sensorStatus aus derselben MSP2_INAV_STATUS-Antwort wie ARMED; MSP2_INAV_TEMPERATURES neu im 2-Hz-Statuszyklus abgefragt. - MockFlightControllerLink: synthetische Sensor-/Temperatur-/Vario-Werte (kein Pitot/Rangefinder/Opflow am T1 Ranger vorgesehen), leicht schwankend, damit die neuen Felder auch ohne Hardware sichtbar auf Werteaenderungen reagieren. - drone_status_messages_panel.dart: eigene Sensor-Status-Zeile (lokale Bit-Konstanten statt MSP-Import, analog zum bestehenden navMode-Muster in domain/telemetry/drone_status.dart, damit die UI protokollneutral bleibt), Arming+Temperaturen-Zeilenpaar, Vertical-speed-Zeile am Ende. Auf dem Pixel_10a-Emulator verifiziert: Sensor-Badges gruen/grau je nach Bitmaske, Arming/Temperaturen-Paar, Vertical speed am Listenende. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
146 lines
7.6 KiB
Dart
146 lines
7.6 KiB
Dart
/// MSP-Befehlsnummern, geprueft gegen den tatsaechlichen iNAV-9.1.0-Quellcode
|
|
/// statt aus dem Gedaechtnis uebernommen (Doku Kommunikationsschicht
|
|
/// Abschnitt 4):
|
|
/// https://github.com/iNavFlight/inav/blob/9.1.0/src/main/msp/msp_protocol.h
|
|
/// https://github.com/iNavFlight/inav/blob/9.1.0/src/main/msp/msp_protocol_v2_inav.h
|
|
///
|
|
/// `MSP_STATUS` und `MSP_ANALOG` sind laut `msp_protocol.h` seit iNAV 9.1
|
|
/// als "DEPRECATED ... use MSP2_INAV_STATUS/MSP2_INAV_ANALOG instead. Will
|
|
/// be removed in INAV 10.0" markiert - deshalb wird hier bewusst die
|
|
/// MSP2_INAV_-Variante verwendet, nicht die MSPv1-Klassiker.
|
|
abstract final class MspCommands {
|
|
/// Response: u8 fixType, u8 numSat, i32 lat(1e-7 deg), i32 lon(1e-7 deg),
|
|
/// u16 alt(m), u16 groundSpeed(cm/s), u16 groundCourse(0.1 deg), u16 hdop.
|
|
/// (`fc_msp.c`, `case MSP_RAW_GPS`)
|
|
static const int rawGps = 106;
|
|
|
|
/// Response (4 Byte): u8 reserved, u8 maxWaypoints (NAV_MAX_WAYPOINTS),
|
|
/// u8 isWaypointListValid (`posControl.waypointListValid`), u8
|
|
/// waypointCount (`getWaypointCount()`) - Grundlage der Upload-
|
|
/// Verifikation (Doku 2.2/4.5: "Upload + verifiziert"), siehe
|
|
/// msp_waypoint_codec.dart. (`fc_msp.c`, `case MSP_WP_GETINFO`)
|
|
static const int wpGetInfo = 20;
|
|
|
|
/// Request-Payload (21 Byte, siehe msp_waypoint_codec.dart
|
|
/// `encodeMspSetWaypoint`): u8 wp_no, u8 action, i32 lat(1e-7 deg),
|
|
/// i32 lon(1e-7 deg), i32 alt(cm), i16 p1, i16 p2, i16 p3, u8 flag. Nur
|
|
/// WP#1..NAV_MAX_WAYPOINTS gueltig; WP#1 setzt die Missionsliste des FC
|
|
/// zurueck (neue Mission), jede weitere WP# muss exakt die naechste sein
|
|
/// (`fc_msp.c` `case MSP_SET_WP`, `navigation.c` `setWaypoint()` - kein
|
|
/// Batch-Kommando, ein Aufruf pro Wegpunkt).
|
|
static const int setWp = 209;
|
|
|
|
/// Response: i32 estAlt(cm), i16 vario(cm/s), i32 baroAlt(cm).
|
|
/// `vario` ist `getEstimatedActualVelocity(Z)` - dieselbe Achse/dasselbe
|
|
/// Vorzeichen wie `estAlt` (`getEstimatedActualPosition(Z)`, beide aus
|
|
/// `navGetCurrentActualPositionAndVelocity()`, `navigation.c`), also
|
|
/// positiv = Steigen, negativ = Sinken.
|
|
/// (`fc_msp.c`, `case MSP_ALTITUDE`)
|
|
static const int altitude = 109;
|
|
|
|
/// Response: u8 mode, u8 state, u8 activeWpAction, u8 activeWpNumber,
|
|
/// u8 error, u16 headingHoldTarget. (`fc_msp.c`, `case MSP_NAV_STATUS`)
|
|
static const int navStatus = 121;
|
|
|
|
/// Response: u16 cycleTime, u16 i2cErrors, u16 sensorStatus,
|
|
/// u16 avgSystemLoad%, u8 (batteryProfile<<4|configProfile),
|
|
/// u32 armingFlags, 8 byte boxModeFlags, u8 mixerProfile.
|
|
/// (`fc_msp.c`, `case MSP2_INAV_STATUS`; ID aus
|
|
/// `msp_protocol_v2_inav.h`: `#define MSP2_INAV_STATUS 0x2000`)
|
|
///
|
|
/// Bit-Layout `sensorStatus` (`packSensorStatus()` in `fc_msp_box.c`) -
|
|
/// siehe [MspSensorStatusBits].
|
|
///
|
|
/// Bit-Layout `armingFlags` (`armingFlag_e` in `fc/runtime_config.h`) -
|
|
/// siehe [MspArmingFlags].
|
|
///
|
|
/// `boxModeFlags` (8 Byte = 64 Bit) ist KEIN fest verdrahtetes Bit-pro-
|
|
/// Modus-Mapping (`packBoxModeFlags()` in `fc_msp_box.c`): Bit `i` sagt
|
|
/// nur "ist der i-te Eintrag der aktuell aktiven Box-Liste gerade aktiv"
|
|
/// - welcher Modus das ist, hängt vom konkreten Firmware-Build/-Setup ab
|
|
/// (nur kompilierte/aktivierte Boxen landen in der Liste,
|
|
/// `initActiveBoxIds()`). Um ein Bit einem Modus zuzuordnen, muss der
|
|
/// Client `MSP_BOXIDS` (ID 119, `case MSP_BOXIDS: serializeBoxReply()`)
|
|
/// EINMAL beim Verbindungsaufbau abfragen: die Antwort ist ein
|
|
/// Array von `u8 permanentId` in exakt der gleichen Reihenfolge wie die
|
|
/// Bits in `boxModeFlags` - erst über diese `permanentId` lässt sich der
|
|
/// Modusname aus der festen `boxes[]`-Tabelle in `fc_msp_box.c` ablesen
|
|
/// (`permanentId` ist stabil über Firmware-Versionen, die Bit-Position
|
|
/// nicht). Für Fixed-Wing/iNAV-Missionsbetrieb relevante `permanentId`s:
|
|
/// 0 ARM, 1 ANGLE, 2 HORIZON, 10 NAV RTH, 11 NAV POSHOLD, 12 MANUAL,
|
|
/// 27 FAILSAFE, 28 NAV WP, 30 HOME RESET, 34 FLAPERON, 35 TURN ASSIST,
|
|
/// 36 NAV LAUNCH, 37 SERVO AUTOTRIM, 45 NAV COURSE HOLD, 51 PREARM,
|
|
/// 53 NAV CRUISE, 55 WP PLANNER, 56 SOARING, 59 MISSION CHANGE, 64
|
|
/// ANGLE HOLD (vollständige Tabelle: `boxes[]` in `fc_msp_box.c`, iNAV
|
|
/// 9.1.0 - noch nicht in `MspCommands` aufgenommen, da bisher ungenutzt).
|
|
static const int inavStatus = 0x2000;
|
|
|
|
/// Response (24 Byte): u8 flags, u16 batteryVoltage(0.01V),
|
|
/// u16 amperage(0.01A), u32 power, u32 mAhDrawn, u32 mWhDrawn,
|
|
/// u32 remainingCapacity, u8 batteryPercentage(0-100, bereits fertig
|
|
/// berechnet ueber `calculateBatteryPercentage()`), u16 legacyRssi
|
|
/// (0-1023, veraltete Skala - siehe stattdessen [inavLinkStats]).
|
|
/// (`fc_msp.c`, `case MSP2_INAV_ANALOG`; ID aus
|
|
/// `msp_protocol_v2_inav.h`: `#define MSP2_INAV_ANALOG 0x2002`)
|
|
static const int inavAnalog = 0x2002;
|
|
|
|
/// Response (3 Byte): u8 uplinkRssiDbm (negiert gespeichert als
|
|
/// `-rxLinkStatistics.uplinkRSSI`), u8 uplinkLinkQuality (0-100%,
|
|
/// `rxLinkStatistics.uplinkLQ` - das ist die "Receiver Link Quality"),
|
|
/// i8 uplinkSnr. (`fc_msp.c`, `case MSP2_INAV_GET_LINK_STATS`; ID aus
|
|
/// `msp_protocol_v2_inav.h`: `#define MSP2_INAV_GET_LINK_STATS 0x2103`)
|
|
static const int inavLinkStats = 0x2103;
|
|
|
|
/// Response (`MAX_TEMP_SENSORS` = 8 Slots, je i16, 0.1°C-Schritte,
|
|
/// `sensors/temperature.h`: "Temperature is returned in degC*10"):
|
|
/// ungueltiger/nicht konfigurierter Sensor liefert `-1000`
|
|
/// (`fc_msp.c`, `case MSP2_INAV_TEMPERATURES`: `sbufWriteU16(dst, valid
|
|
/// ? temperature : -1000)`, braucht `USE_TEMPERATURE_SENSOR` +
|
|
/// konfigurierte Sensoren, sonst dauerhaft `-1000` fuer alle 8 Slots).
|
|
/// ID aus `msp_protocol_v2_inav.h`:
|
|
/// `#define MSP2_INAV_TEMPERATURES 0x201E`.
|
|
static const int inavTemperatures = 0x201E;
|
|
}
|
|
|
|
/// Bits von `armingFlags` (`armingFlag_e` in `fc/runtime_config.h`, iNAV
|
|
/// 9.1.0). Nur das fuer die Telemetrie benoetigte ARMED-Bit ist hier als
|
|
/// Konstante abgebildet - der Rest der Aufzaehlung ist unten als Referenz
|
|
/// dokumentiert, falls spaeter z.B. eine "warum laesst sich nicht armen"-
|
|
/// Anzeige gebraucht wird (aktuell ungenutzt, deshalb keine eigenen
|
|
/// Konstanten dafuer):
|
|
///
|
|
/// Bit 2 `ARMED`, Bit 3 `WAS_EVER_ARMED`, Bit 4/5 Simulator-Modus
|
|
/// (HITL/SITL), danach ausschliesslich Arm-Sperrgruende
|
|
/// (`ARMING_DISABLED_*`, jeweils "warum kann/darf gerade nicht armiert
|
|
/// werden"): Bit 6 GEOZONE, 7 FAILSAFE_SYSTEM, 8 NOT_LEVEL, 9
|
|
/// SENSORS_CALIBRATING, 10 SYSTEM_OVERLOADED, 11 NAVIGATION_UNSAFE, 12
|
|
/// COMPASS_NOT_CALIBRATED, 13 ACCELEROMETER_NOT_CALIBRATED, 14 ARM_SWITCH,
|
|
/// 15 HARDWARE_FAILURE, 16 BOXFAILSAFE, 18 RC_LINK, 19 THROTTLE, 20 CLI,
|
|
/// 21 CMS_MENU, 22 OSD_MENU, 23 ROLLPITCH_NOT_CENTERED, 24 SERVO_AUTOTRIM,
|
|
/// 25 OOM, 26 INVALID_SETTING, 27 PWM_OUTPUT_ERROR, 28 NO_PREARM, 29
|
|
/// DSHOT_BEEPER, 30 LANDING_DETECTED (Bit 17 unbenutzt).
|
|
abstract final class MspArmingFlags {
|
|
static const int armed = 1 << 2;
|
|
}
|
|
|
|
/// Bits von `sensorStatus` (`packSensorStatus()` in `fc_msp_box.c`, Teil
|
|
/// der `MSP2_INAV_STATUS`-Antwort, siehe [MspCommands.inavStatus]) - Bits
|
|
/// 0-7 melden je, ob der Sensor als vorhanden/aktiviert erkannt wurde
|
|
/// (`sensors(SENSOR_*)`), unabhaengig von einer eigenen Kalibrierung/einem
|
|
/// gueltigen Messwert. Bits 8-14 unbenutzt.
|
|
abstract final class MspSensorStatusBits {
|
|
static const int acc = 1 << 0;
|
|
static const int baro = 1 << 1;
|
|
static const int mag = 1 << 2;
|
|
static const int gps = 1 << 3;
|
|
static const int rangefinder = 1 << 4;
|
|
static const int opflow = 1 << 5;
|
|
static const int pitot = 1 << 6;
|
|
static const int temp = 1 << 7;
|
|
|
|
/// `!isHardwareHealthy()` - mind. ein Sensor meldet einen Hardware-Defekt
|
|
/// (I2C-Fehler etc.), unabhaengig davon, welcher der Bits 0-7 betroffen
|
|
/// ist.
|
|
static const int hardwareFailure = 1 << 15;
|
|
}
|