226 lines
6.1 KiB
Dart
226 lines
6.1 KiB
Dart
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';
|
||
}
|
||
}
|
||
}
|