import 'dart:typed_data'; import 'msp_commands.dart'; /// GPS-Rohwerte aus `MSP_RAW_GPS` (Doku Kommunikationsschicht Abschnitt 4). class MspGpsReading { const MspGpsReading({ required this.fixType, required this.numSat, required this.lat, required this.lon, required this.speedMs, }); /// 0 = kein Fix (`fc_msp.c`: `gpsSol.fixType`). final int fixType; final int numSat; final double lat; final double lon; final double speedMs; bool get hasFix => fixType != 0; } /// Parst die `MSP_RAW_GPS`-Antwort (Byte-Layout siehe [MspCommands.rawGps]). MspGpsReading parseMspRawGps(Uint8List payload) { final data = ByteData.sublistView(payload); return MspGpsReading( fixType: data.getUint8(0), numSat: data.getUint8(1), lat: data.getInt32(2, Endian.little) / 1e7, lon: data.getInt32(6, Endian.little) / 1e7, speedMs: data.getUint16(12, Endian.little) / 100.0, ); } /// Parst die `MSP_ALTITUDE`-Antwort und liefert die geschaetzte Hoehe in /// Metern (siehe [MspCommands.altitude]). double parseMspAltitudeMeters(Uint8List payload) { final data = ByteData.sublistView(payload); return data.getInt32(0, Endian.little) / 100.0; } /// Parst die `MSP2_INAV_STATUS`-Antwort und liefert, ob der ARMED-Bit in /// `armingFlags` gesetzt ist (siehe [MspCommands.inavStatus]). bool parseMspInavStatusArmed(Uint8List payload) { final data = ByteData.sublistView(payload); // Offset 9 = cycleTime(2) + i2cErrors(2) + sensorStatus(2) + avgLoad(2) // + Profil-Byte(1), siehe fc_msp.c/MSP2_INAV_STATUS. final armingFlags = data.getUint32(9, Endian.little); return (armingFlags & MspArmingFlags.armed) != 0; } /// Parst die `MSP_NAV_STATUS`-Antwort und liefert den aktiven /// Wegpunktindex, oder null, wenn keine Mission aktiv ist (`activeWpNumber /// == 0`, siehe [MspCommands.navStatus]). int? parseMspNavStatusActiveWaypoint(Uint8List payload) { final activeWpNumber = payload[3]; return activeWpNumber == 0 ? null : activeWpNumber; }