Új nmea mondatok: gsa, gsv, műhold info osztály
This commit is contained in:
parent
3d4c937b71
commit
9347e22843
74
lib/gnss_sentences/gngsa.dart
Normal file
74
lib/gnss_sentences/gngsa.dart
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import 'package:nmea/nmea.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<int> get activeSatellitePrns {
|
||||||
|
final prns = <int>[];
|
||||||
|
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',
|
||||||
|
};
|
||||||
|
|
||||||
|
double _parseDouble(String? s) {
|
||||||
|
if (s == null || s.isEmpty) return 0.0;
|
||||||
|
return double.tryParse(s) ?? 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
92
lib/gnss_sentences/gngsv.dart
Normal file
92
lib/gnss_sentences/gngsv.dart
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
// ─── GSV mondatelemző ──────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
import 'package:nmea/nmea.dart';
|
||||||
|
import 'package:terepi_seged/models/satellite_info.dart';
|
||||||
|
|
||||||
|
/// GSV — GNSS Satellites in View
|
||||||
|
///
|
||||||
|
/// Formátum (max 4 műhold/mondat):
|
||||||
|
/// $GPGSV,3,1,11,01,70,042,45,03,55,218,48,07,22,085,35,10,35,315,40*73
|
||||||
|
/// │ │ │ │ │ │ │
|
||||||
|
/// │ │ │ PRN El Az SNR (×4 max)
|
||||||
|
/// │ │ └── összes látható műhold száma
|
||||||
|
/// │ └───── ezen mondat sorszáma (1-től)
|
||||||
|
/// └─────── összes GSV mondat ebben a ciklusban
|
||||||
|
///
|
||||||
|
/// Több mondat alkotja az epochot:
|
||||||
|
/// GPGSV (GPS) + GLGSV (GLONASS) + GAGSV (Galileo) + GBGSV (BeiDou)
|
||||||
|
class Gngsv extends TalkerSentence {
|
||||||
|
static const String id = 'GNGSV';
|
||||||
|
|
||||||
|
Gngsv({required super.raw});
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get valid =>
|
||||||
|
super.valid && fields.length >= 8; // min: típus + 3 fejléc + 1×4 műhold
|
||||||
|
|
||||||
|
// ── Fejléc mezők ─────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/// Összes GSV mondat ezen rendszerhez ebben az epochban
|
||||||
|
int get totalMessages => int.tryParse(fields[1]) ?? 1;
|
||||||
|
|
||||||
|
/// Ezen mondat sorszáma (1-től indul)
|
||||||
|
int get messageNumber => int.tryParse(fields[2]) ?? 1;
|
||||||
|
|
||||||
|
/// Összes látható műhold száma (az epochban, nem csak ebben a mondatban)
|
||||||
|
int get totalSatellitesInView => int.tryParse(fields[3]) ?? 0;
|
||||||
|
|
||||||
|
/// Ez az utolsó mondat az adott rendszer GSV sorozatában?
|
||||||
|
bool get isLastMessage => messageNumber == totalMessages;
|
||||||
|
|
||||||
|
// ── Műholdak ebben a mondatban ───────────────────────────────────
|
||||||
|
|
||||||
|
/// A mondatban szereplő műholdak listája (max 4)
|
||||||
|
List<SatelliteInfo> get satellites {
|
||||||
|
final sats = <SatelliteInfo>[];
|
||||||
|
final system = systemName;
|
||||||
|
|
||||||
|
// Minden műhold 4 mezőt foglal: PRN, eleváció, azimut, SNR
|
||||||
|
// fields[4]-től kezdődnek, fields[0] = mondattípus
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
final base = 4 + i * 4;
|
||||||
|
|
||||||
|
// Ellenőrzés: van-e elég mező
|
||||||
|
if (base + 3 >= fields.length) break;
|
||||||
|
|
||||||
|
final prn = int.tryParse(fields[base] ?? '');
|
||||||
|
final elev = int.tryParse(fields[base + 1] ?? '') ?? 0;
|
||||||
|
final az = int.tryParse(fields[base + 2] ?? '') ?? 0;
|
||||||
|
|
||||||
|
// SNR az utolsó mezőben checksum lehet (*XX)
|
||||||
|
final snrRaw = (fields[base + 3] ?? '').split('*').first;
|
||||||
|
final snr = int.tryParse(snrRaw) ?? 0;
|
||||||
|
|
||||||
|
if (prn != null && prn > 0) {
|
||||||
|
sats.add(SatelliteInfo(
|
||||||
|
prn: prn,
|
||||||
|
elevation: elev,
|
||||||
|
azimuth: az,
|
||||||
|
snr: snr,
|
||||||
|
system: system,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sats;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Rendszer azonosítás ───────────────────────────────────────────
|
||||||
|
|
||||||
|
/// Talker azonosító a nyers mondatból
|
||||||
|
String get talkerId => raw.length >= 3 ? raw.substring(1, 3) : 'GN';
|
||||||
|
|
||||||
|
/// Rendszer neve a talker azonosítóból
|
||||||
|
String get systemName => switch (talkerId) {
|
||||||
|
'GP' => 'GPS',
|
||||||
|
'GL' => 'GLONASS',
|
||||||
|
'GA' => 'Galileo',
|
||||||
|
'GB' || 'BD' => 'BeiDou',
|
||||||
|
'GN' => 'Mixed',
|
||||||
|
_ => 'Unknown',
|
||||||
|
};
|
||||||
|
}
|
||||||
66
lib/models/satellite_info.dart
Normal file
66
lib/models/satellite_info.dart
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import 'dart:math' as math;
|
||||||
|
|
||||||
|
// ─── 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;
|
||||||
|
|
||||||
|
/// Rendszer neve: GPS, GLONASS, Galileo, BeiDou, Mixed
|
||||||
|
final String system;
|
||||||
|
|
||||||
|
const SatelliteInfo({
|
||||||
|
required this.prn,
|
||||||
|
required this.elevation,
|
||||||
|
required this.azimuth,
|
||||||
|
required this.snr,
|
||||||
|
required this.system,
|
||||||
|
});
|
||||||
|
|
||||||
|
// ── Minősítési segédek ────────────────────────────────────────────
|
||||||
|
|
||||||
|
/// Erős jel — fixben megbízhatóan részt vesz
|
||||||
|
bool get isStrong => snr >= 40;
|
||||||
|
|
||||||
|
/// Használható jel — fixben részt vesz
|
||||||
|
bool get isUsed => 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() =>
|
||||||
|
'SatelliteInfo($system PRN$prn elev=$elevation° az=$azimuth° snr=$snr)';
|
||||||
|
}
|
||||||
@ -26,6 +26,10 @@ class MapSurveyView extends GetView<MapSurveyController> {
|
|||||||
onZoomIn: controller.mapZoomIn,
|
onZoomIn: controller.mapZoomIn,
|
||||||
onZoomOut: controller.mapZoomOut,
|
onZoomOut: controller.mapZoomOut,
|
||||||
onCenterOnGps: controller.isMapMoveToCenter,
|
onCenterOnGps: controller.isMapMoveToCenter,
|
||||||
|
layers: [
|
||||||
|
Obx(() =>
|
||||||
|
MarkerLayer(markers: controller.currentLocationMarker.toList()))
|
||||||
|
],
|
||||||
),
|
),
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 8,
|
top: 8,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user