GnssService javítás, refraktálás
This commit is contained in:
parent
24a6b7d513
commit
20a8078f3c
@ -129,6 +129,7 @@ class MapSurveyController extends GetxController {
|
|||||||
|
|
||||||
// ── Telefon GPS fallback ──────────────────────────────────────────
|
// ── Telefon GPS fallback ──────────────────────────────────────────
|
||||||
StreamSubscription<Position>? _phoneLocationSub;
|
StreamSubscription<Position>? _phoneLocationSub;
|
||||||
|
StreamSubscription<void>? _gnssUpdateSub;
|
||||||
|
|
||||||
// ── UI controllerek ───────────────────────────────────────────────
|
// ── UI controllerek ───────────────────────────────────────────────
|
||||||
final pointIdController = TextEditingController();
|
final pointIdController = TextEditingController();
|
||||||
@ -161,7 +162,9 @@ class MapSurveyController extends GetxController {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// ── GnssService pozíció változás → EOV, marker, NTRIP GGA ────
|
// ── GnssService pozíció változás → EOV, marker, NTRIP GGA ────
|
||||||
ever(_gnss.gpsQuality, (_) => _onGnssUpdate());
|
_gnssUpdateSub = _gnss.onDataUpdated.listen((_) {
|
||||||
|
_onGnssUpdate();
|
||||||
|
});
|
||||||
|
|
||||||
// ── Supabase realtime ─────────────────────────────────────────
|
// ── Supabase realtime ─────────────────────────────────────────
|
||||||
_supaChannel = Supabase.instance.client
|
_supaChannel = Supabase.instance.client
|
||||||
@ -194,6 +197,7 @@ class MapSurveyController extends GetxController {
|
|||||||
super.onClose();
|
super.onClose();
|
||||||
|
|
||||||
_phoneLocationSub?.cancel();
|
_phoneLocationSub?.cancel();
|
||||||
|
_gnssUpdateSub?.cancel();
|
||||||
await _supaChannel?.unsubscribe();
|
await _supaChannel?.unsubscribe();
|
||||||
|
|
||||||
pointIdController.dispose();
|
pointIdController.dispose();
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import 'dart:typed_data';
|
|||||||
|
|
||||||
import 'package:geolocator/geolocator.dart';
|
import 'package:geolocator/geolocator.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:googleapis/privateca/v1.dart';
|
||||||
import 'package:nmea/nmea.dart';
|
import 'package:nmea/nmea.dart';
|
||||||
import 'package:terepi_seged/services/gnss/gnss_device_service.dart';
|
import 'package:terepi_seged/services/gnss/gnss_device_service.dart';
|
||||||
import 'package:terepi_seged/services/gnss/phone_gps_connection.dart';
|
import 'package:terepi_seged/services/gnss/phone_gps_connection.dart';
|
||||||
@ -45,6 +46,9 @@ class GnssService extends GetxService {
|
|||||||
// ── RMC adatok (dátum/idő) ────────────────────────────────────────
|
// ── RMC adatok (dátum/idő) ────────────────────────────────────────
|
||||||
final gpsDateTime = DateTime(2000).obs;
|
final gpsDateTime = DateTime(2000).obs;
|
||||||
|
|
||||||
|
Timer? _reconnectTimer;
|
||||||
|
bool _isClosing = false;
|
||||||
|
|
||||||
// Segédmező: van-e érvényes adat
|
// Segédmező: van-e érvényes adat
|
||||||
bool get hasValidData => gpsQuality.value > 0;
|
bool get hasValidData => gpsQuality.value > 0;
|
||||||
|
|
||||||
@ -54,11 +58,16 @@ class GnssService extends GetxService {
|
|||||||
StreamSubscription? _stateSub;
|
StreamSubscription? _stateSub;
|
||||||
StreamSubscription<Position>? _positionSub;
|
StreamSubscription<Position>? _positionSub;
|
||||||
|
|
||||||
|
final _updateController = StreamController<void>.broadcast();
|
||||||
|
Stream<void> get onDataUpdated => _updateController.stream;
|
||||||
|
|
||||||
String _utcTime = '';
|
String _utcTime = '';
|
||||||
String _utcDate = '';
|
String _utcDate = '';
|
||||||
|
|
||||||
bool _intentionalDisconnection = false;
|
bool _intentionalDisconnection = false;
|
||||||
|
|
||||||
|
String _digitsOnly(String value) => value.replaceAll(RegExp(r'[^0-9]'), '');
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
@ -106,14 +115,17 @@ class GnssService extends GetxService {
|
|||||||
break;
|
break;
|
||||||
case GnssConnectionType.btSerial:
|
case GnssConnectionType.btSerial:
|
||||||
await connectBtSerial(device.address);
|
await connectBtSerial(device.address);
|
||||||
|
break;
|
||||||
case GnssConnectionType.ble:
|
case GnssConnectionType.ble:
|
||||||
await connectBle(device.address);
|
await connectBle(device.address);
|
||||||
|
break;
|
||||||
case GnssConnectionType.phoneGps:
|
case GnssConnectionType.phoneGps:
|
||||||
await _disconnect();
|
await _disconnect();
|
||||||
_connection = PhoneGpsConnection();
|
_connection = PhoneGpsConnection();
|
||||||
//connectionState.value = GnssConnectionState.disconnected;
|
//connectionState.value = GnssConnectionState.disconnected;
|
||||||
activeConnectionType.value = GnssConnectionType.phoneGps;
|
activeConnectionType.value = GnssConnectionType.phoneGps;
|
||||||
await _doConnect('iternal');
|
await _doConnect('iternal');
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,9 +139,13 @@ class GnssService extends GetxService {
|
|||||||
Future<void> _doConnect(String address) async {
|
Future<void> _doConnect(String address) async {
|
||||||
_stateSub = _connection!.connectionState.listen((s) {
|
_stateSub = _connection!.connectionState.listen((s) {
|
||||||
connectionState.value = s;
|
connectionState.value = s;
|
||||||
if (s == GnssConnectionState.disconnected &&
|
if (s == GnssConnectionState.connected) {
|
||||||
_intentionalDisconnection == false) {
|
_reconnectTimer?.cancel();
|
||||||
Future.delayed(const Duration(seconds: 3), () => reconnect());
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s == GnssConnectionState.disconnected) {
|
||||||
|
_scheduleReconnect();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -141,6 +157,8 @@ class GnssService extends GetxService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _parseDirectPosition(Position pos) {
|
void _parseDirectPosition(Position pos) {
|
||||||
|
if (_isClosing) return;
|
||||||
|
|
||||||
latitude.value = pos.latitude;
|
latitude.value = pos.latitude;
|
||||||
longitude.value = pos.longitude;
|
longitude.value = pos.longitude;
|
||||||
altitude.value = pos.altitude;
|
altitude.value = pos.altitude;
|
||||||
@ -151,17 +169,22 @@ class GnssService extends GetxService {
|
|||||||
// A Geolocator a pontosságot (accuracy) méterben adja vissza
|
// A Geolocator a pontosságot (accuracy) méterben adja vissza
|
||||||
latitudeError.value = pos.accuracy;
|
latitudeError.value = pos.accuracy;
|
||||||
longitudeError.value = pos.accuracy;
|
longitudeError.value = pos.accuracy;
|
||||||
altitudeError.value = pos.altitudeAccuracy ?? 0.0;
|
altitudeError.value = pos.altitudeAccuracy;
|
||||||
|
|
||||||
// Az RMC (idő) adatait is beállítjuk a telefon idejéből
|
// Az RMC (idő) adatait is beállítjuk a telefon idejéből
|
||||||
gpsDateTime.value = pos.timestamp;
|
gpsDateTime.value = pos.timestamp;
|
||||||
|
|
||||||
|
_emitUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _disconnect() async {
|
Future<void> _disconnect() async {
|
||||||
_intentionalDisconnection = true;
|
_intentionalDisconnection = true;
|
||||||
|
_reconnectTimer?.cancel();
|
||||||
|
|
||||||
await _nmeaSub?.cancel();
|
await _nmeaSub?.cancel();
|
||||||
await _positionSub?.cancel();
|
await _positionSub?.cancel();
|
||||||
await _stateSub?.cancel();
|
await _stateSub?.cancel();
|
||||||
|
|
||||||
await _connection?.disconnect();
|
await _connection?.disconnect();
|
||||||
_connection?.dispose();
|
_connection?.dispose();
|
||||||
_connection = null;
|
_connection = null;
|
||||||
@ -180,11 +203,15 @@ class GnssService extends GetxService {
|
|||||||
// ── NMEA parsing ──────────────────────────────────────────────────
|
// ── NMEA parsing ──────────────────────────────────────────────────
|
||||||
|
|
||||||
void _parseNmea(String line) {
|
void _parseNmea(String line) {
|
||||||
if (line.startsWith('\$GNGGA') || line.startsWith('\$GPGGA')) {
|
if (_isClosing || line.length < 6 || !line.startsWith(r'$')) return;
|
||||||
|
|
||||||
|
final sentenceType = line.substring(3, 6);
|
||||||
|
|
||||||
|
if (sentenceType == 'GGA') {
|
||||||
_parseGga(line);
|
_parseGga(line);
|
||||||
} else if (line.startsWith('\$GNGST') && hasValidData) {
|
} else if (sentenceType == 'GST' && hasValidData) {
|
||||||
_parseGst(line);
|
_parseGst(line);
|
||||||
} else if (line.startsWith('\$GNRMC') && hasValidData) {
|
} else if (sentenceType == 'RMC' && hasValidData) {
|
||||||
_parseRmc(line);
|
_parseRmc(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -205,7 +232,11 @@ class GnssService extends GetxService {
|
|||||||
hdop.value = s.hdop;
|
hdop.value = s.hdop;
|
||||||
lastGgaLine.value = line;
|
lastGgaLine.value = line;
|
||||||
_utcTime = s.utcOfPositionFix;
|
_utcTime = s.utcOfPositionFix;
|
||||||
} catch (_) {}
|
|
||||||
|
_emitUpdate();
|
||||||
|
} catch (e) {
|
||||||
|
print('GGA parsing error: $e');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _parseGst(String line) {
|
void _parseGst(String line) {
|
||||||
@ -215,30 +246,45 @@ class GnssService extends GetxService {
|
|||||||
latitudeError.value = s.latitudeError;
|
latitudeError.value = s.latitudeError;
|
||||||
longitudeError.value = s.longitudeError;
|
longitudeError.value = s.longitudeError;
|
||||||
altitudeError.value = s.heightError;
|
altitudeError.value = s.heightError;
|
||||||
} catch (_) {}
|
} catch (e) {
|
||||||
|
print('GST parse error: $e');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _parseRmc(String line) {
|
void _parseRmc(String line) {
|
||||||
try {
|
try {
|
||||||
final s = _decoder.decode(line);
|
final s = _decoder.decode(line);
|
||||||
if (s == null || !s.valid || s is! Gnrmc) return;
|
if (s == null || !s.valid || s is! Gnrmc) return;
|
||||||
|
|
||||||
_utcDate = s.date;
|
_utcDate = s.date;
|
||||||
if (_utcDate.length >= 6 && _utcTime.length >= 6) {
|
final date = _digitsOnly(_utcDate);
|
||||||
gpsDateTime.value = DateTime(
|
final time = _digitsOnly(s.utcOfPositionFix);
|
||||||
2000 + int.parse('${_utcDate[4]}${_utcDate[5]}'),
|
|
||||||
int.parse('${_utcDate[2]}${_utcDate[3]}'),
|
if (date.length >= 6 && time.length >= 6) {
|
||||||
int.parse('${_utcDate[0]}${_utcDate[1]}'),
|
gpsDateTime.value = DateTime.utc(
|
||||||
int.parse('${_utcTime[0]}${_utcTime[1]}'),
|
2000 + int.parse(date.substring(4, 6)),
|
||||||
int.parse('${_utcTime[2]}${_utcTime[3]}'),
|
int.parse(date.substring(2, 4)),
|
||||||
int.parse('${_utcTime[4]}${_utcTime[5]}'),
|
int.parse(date.substring(0, 2)),
|
||||||
|
int.parse(time.substring(0, 2)),
|
||||||
|
int.parse(time.substring(2, 4)),
|
||||||
|
int.parse(time.substring(4, 6)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (_) {}
|
} catch (e) {
|
||||||
|
print('RMC parse error: $e');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onClose() {
|
void onClose() async {
|
||||||
_disconnect();
|
_isClosing = true;
|
||||||
|
|
||||||
|
await _disconnect();
|
||||||
|
|
||||||
|
if (!_updateController.isClosed) {
|
||||||
|
_updateController.close();
|
||||||
|
}
|
||||||
|
|
||||||
super.onClose();
|
super.onClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,4 +319,19 @@ class GnssService extends GetxService {
|
|||||||
print('Nem sikerült lekérni a kezdőpozíciót: $e');
|
print('Nem sikerült lekérni a kezdőpozíciót: $e');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _emitUpdate() {
|
||||||
|
if (_isClosing || _updateController.isClosed) return;
|
||||||
|
_updateController.add(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _scheduleReconnect() {
|
||||||
|
if (_intentionalDisconnection || _isClosing) return;
|
||||||
|
if (_reconnectTimer?.isActive ?? false) return;
|
||||||
|
|
||||||
|
_reconnectTimer = Timer(const Duration(seconds: 3), () {
|
||||||
|
if (_intentionalDisconnection || _isClosing) return;
|
||||||
|
unawaited(reconnect());
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import 'dart:math';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:terepi_seged/pages/map_survey/presentations/controllers/map_survey_controller.dart';
|
||||||
import 'package:terepi_seged/services/ntrip_service.dart';
|
import 'package:terepi_seged/services/ntrip_service.dart';
|
||||||
|
|
||||||
import '../services/gnss/gnss_service.dart';
|
import '../services/gnss/gnss_service.dart';
|
||||||
@ -35,7 +36,7 @@ class CoordinatePanel extends StatelessWidget {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/// Gyors factory — MapSurveyController mezőiből.
|
/// Gyors factory — MapSurveyController mezőiből.
|
||||||
factory CoordinatePanel.fromController(dynamic ctrl) {
|
factory CoordinatePanel.fromController(MapSurveyController ctrl) {
|
||||||
final y = RxDouble(0.0);
|
final y = RxDouble(0.0);
|
||||||
final x = RxDouble(0.0);
|
final x = RxDouble(0.0);
|
||||||
// Figyeli az eov változást és frissíti Y/X-et
|
// Figyeli az eov változást és frissíti Y/X-et
|
||||||
@ -45,7 +46,7 @@ class CoordinatePanel extends StatelessWidget {
|
|||||||
});
|
});
|
||||||
return CoordinatePanel(
|
return CoordinatePanel(
|
||||||
eovY: y,
|
eovY: y,
|
||||||
eovX: x,
|
eovX: ctrl.eov.value.X.obs,
|
||||||
horError: ctrl.gpsLatitudeError as RxDouble,
|
horError: ctrl.gpsLatitudeError as RxDouble,
|
||||||
vertError: ctrl.gpsAltitudeError as RxDouble,
|
vertError: ctrl.gpsAltitudeError as RxDouble,
|
||||||
altitudeMsl: ctrl.gpsAltitude as RxDouble,
|
altitudeMsl: ctrl.gpsAltitude as RxDouble,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user