import 'package:nmea/nmea.dart'; import 'package:terepi_seged/models/satellite_info.dart'; /// GSA — GNSS DOP és aktív műholdak /// /// Formátum: /// $GNGSA,A,3,01,02,03,04,05,06,07,08,09,10,11,12,2.1,1.2,1.7*XX /// │ │ └─────────── 12 db PRN ────────┘ │ │ │ /// │ └── Fix típus: 1=nincs, 2=2D, 3=3D │ │ └─ VDOP /// └──── Mód: M=kézi, A=auto │ └───── HDOP /// └───────── PDOP /// /// NMEA 4.1+: opcionális rendszer azonosító (fields[18]) /// Minden rendszerhez érkezik egy-egy GSA mondat. class Gngsa extends TalkerSentence { static const String id = 'GNGSA'; Gngsa({required super.raw}); @override bool get valid => super.valid && fields.length >= 18; /// Módválasztás: 'M' = kézi, 'A' = automatikus String get selectionMode => fields[1]; /// Fix típus: 1 = nincs, 2 = 2D, 3 = 3D int get fixType => int.tryParse(fields[2]) ?? 1; /// Fixben használt műholdak PRN számai (max 12, üres mezők kihagyva) List get activeSatellitePrns { final prns = []; for (int i = 3; i <= 14; i++) { if (i >= fields.length) break; final prn = int.tryParse(fields[i]); if (prn != null && prn > 0) prns.add(prn); } return prns; } /// PDOP — 3D pozíció pontossági szorzó double get pdop => _parseDouble(fields[15]); /// HDOP — vízszintes pontossági szorzó double get hdop => _parseDouble(fields[16]); /// VDOP — függőleges pontossági szorzó /// Az utolsó mező checksum előtti részét veszi double get vdop { if (fields.length <= 17) return 0.0; return _parseDouble(fields[17].split('*').first); } /// GDOP számítása: √(PDOP² + TDOP²) /// Közelítés TDOP nélkül: GDOP ≈ PDOP * 1.1 double get gdopApprox => pdop * 1.1; /// Talker azonosító — rendszer meghatározásához /// GP=GPS, GL=GLONASS, GA=Galileo, GB/BD=BeiDou, GN=vegyes String get talkerId => raw.length >= 3 ? raw.substring(1, 3) : 'GN'; /// Rendszer neve a talker alapján String get systemName => switch (talkerId) { 'GP' => 'GPS', 'GL' => 'GLONASS', 'GA' => 'Galileo', 'GB' || 'BD' => 'BeiDou', 'GN' => 'Mixed', _ => 'Unknown', }; int? get systemId { if (fields.length <= 18) return null; final rawSys = fields[18].split('*').first.trim(); if (rawSys.isEmpty) return null; return int.tryParse(rawSys); } GnssConstellation get constellation { switch (systemId) { case 1: return GnssConstellation.gps; case 2: return GnssConstellation.glonass; case 3: return GnssConstellation.galileo; case 4: return GnssConstellation.beidou; case 5: return GnssConstellation.qzss; default: return SatelliteInfo.constellationFromTalker(talkerId); } } String get constellationKey => constellation.name; List get activeSatelliteKeys => activeSatellitePrns.map((prn) => '$constellationKey:$prn').toList(); int get usedSatelliteCount => activeSatellitePrns.length; double _parseDouble(String? s) { if (s == null || s.isEmpty) return 0.0; return double.tryParse(s) ?? 0.0; } }