import 'dart:math' as math; enum GnssConstellation { gps, glonass, galileo, beidou, qzss, sbas, navic, mixed, unknown, } // ─── SatelliteInfo modell ────────────────────────────────────────────────── /// Egyetlen látható műhold adatai — a skyplot és az SNR diagram alapja. class SatelliteInfo { /// Műhold PRN/SVID azonosítója final int prn; /// Eleváció fokban (0–90°, 90 = zenit) final int elevation; /// Azimut fokban (0–359°, 0/360 = É, 90 = K) final int azimuth; /// Jelerősség dB-Hz-ben (0–99, 0 = nem tracking) final int snr; /// A műhold konstellációja final GnssConstellation constellation; // Opcionális: NMEA signal ID (pl. L1/L2/E1/...) final int? signalId; const SatelliteInfo( {required this.prn, required this.elevation, required this.azimuth, required this.snr, required this.constellation, this.signalId}); String get system => switch (constellation) { GnssConstellation.gps => 'GPS', GnssConstellation.glonass => 'GLONASS', GnssConstellation.galileo => 'Galileo', GnssConstellation.beidou => 'BeiDou', GnssConstellation.qzss => 'QZSS', GnssConstellation.sbas => 'SBAS', GnssConstellation.navic => 'NavIC', GnssConstellation.mixed => 'Mixed', GnssConstellation.unknown => 'Unknown', }; /// Egyedi kulcs ugyanazon konstellacio azonos muholdjahoz String get satelliteKey => '${constellation.name}:$prn'; /// Egyedi kulcs ugyanazon signal streamhez String get signalKey => '${constellation.name}:$prn:${signalId ?? -1}'; /// Human-readable sav/frekvencia becsles signalId alapjan String get bandLabel => _bandLabel(constellation, signalId); // ── Minősítési segédek ──────────────────────────────────────────── /// Erős jel — fixben megbízhatóan részt vesz bool get isStrong => snr >= 40; /// Jelszint alapjan varhatoan hasznalhato jel. /// A valodi "used in fix" allapotot a GSA mondatok alapjan allapitsuk meg. bool get hasUsableSignal => snr >= 30; /// Gyenge de látható jel bool get isWeak => snr > 0 && snr < 30; /// Egyáltalán látható-e (snr > 0) bool get isVisible => snr > 0; // ── Polár koordináta számítás a skyplot CustomPainter-hez ──────── /// Normalizált sugár (0.0 = zenit, 1.0 = horizont) double get polarRadius => 1.0 - (elevation / 90.0); /// Szög radiánban a polár koordinátához /// (azimut → matematikai szög: É=felső, K=jobb) double get polarAngleRad => (azimuth - 90) * math.pi / 180.0; /// Polár koordináta pixel pozíciójának kiszámítása /// [center] a kör középpontja, [radius] a horizont kör sugara ({double dx, double dy}) toOffset( double centerX, double centerY, double radius) { return ( dx: centerX + radius * polarRadius * math.cos(polarAngleRad), dy: centerY + radius * polarRadius * math.sin(polarAngleRad), ); } @override String toString() { final signal = signalId == null ? '-' : signalId.toString(); return 'SatelliteInfo($system PRN$prn elev=$elevation az=$azimuth snr=$snr signal=$signal band=$bandLabel)'; } static GnssConstellation constellationFromTalker(String talkerId) { switch (talkerId) { case 'GP': return GnssConstellation.gps; case 'GL': return GnssConstellation.glonass; case 'GA': return GnssConstellation.galileo; case 'GB': case 'BD': return GnssConstellation.beidou; case 'GQ': case 'QZ': return GnssConstellation.qzss; case 'GI': case 'IN': return GnssConstellation.navic; case 'GN': return GnssConstellation.mixed; default: return GnssConstellation.unknown; } } static String _bandLabel(GnssConstellation constellation, int? signalId) { if (signalId == null) return 'Unknown'; switch (constellation) { case GnssConstellation.gps: switch (signalId) { case 1: return 'L1 C/A'; case 5: return 'L2C'; case 6: return 'L5'; default: return 'GPS sig $signalId'; } case GnssConstellation.glonass: switch (signalId) { case 1: return 'G1'; case 3: return 'G2'; default: return 'GLO sig $signalId'; } case GnssConstellation.galileo: switch (signalId) { case 1: return 'E1'; case 6: return 'E5a'; case 7: return 'E5b'; case 8: return 'E5 AltBOC'; default: return 'GAL sig $signalId'; } case GnssConstellation.beidou: switch (signalId) { case 1: return 'B1I'; case 3: return 'B2I'; case 5: return 'B1C'; case 7: return 'B2a'; default: return 'BDS sig $signalId'; } case GnssConstellation.qzss: switch (signalId) { case 1: return 'L1 C/A'; case 4: return 'L1S'; case 5: return 'L2C'; case 6: return 'L5'; default: return 'QZSS sig $signalId'; } case GnssConstellation.sbas: switch (signalId) { case 1: return 'L1'; case 6: return 'L5'; default: return 'SBAS sig $signalId'; } case GnssConstellation.navic: switch (signalId) { case 1: return 'L5'; case 2: return 'S'; default: return 'NavIC sig $signalId'; } case GnssConstellation.mixed: return 'Mixed sig $signalId'; case GnssConstellation.unknown: return 'Unknown'; } } }