/// 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 (1 Byte): u8 wp_no. Response (21 Byte): 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 (`fc_msp.c`, `mspFcWaypointOutCommand()`, `case /// MSP_WP`). Kein Batch-Kommando - ein Request pro Wegpunktnummer, analog /// zu [setWp]. `wp_no` kennt laut `navigation.c` `getWaypoint()` zwei /// Sonderwerte neben echten Missions-Wegpunktnummern: 0 = Homepoint /// (`GPS_home.lat/lon/alt`, nur gueltig wenn `STATE(GPS_FIX_HOME)` - /// sonst liefert der FC (0,0,0) statt eines Fehlers, siehe /// msp_waypoint_codec.dart `parseMspHomePoint`), 255 = aktuelle /// Ist-Position. Der Homepoint selbst wird vom FC NICHT beim ersten /// GPS-Fix eingefroren, sondern folgt der Drohne kontinuierlich, solange /// sie disarmed ist und noch nie armed war (`updateHomePosition()`) - /// gesperrt wird er erst beim ersten Armen (iNAV-Default /// `reset_home_type = FIRST_ARM`, `settings.yaml`). static const int getWp = 118; /// 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; }