Track rögzítés javítása, távolság limit idő alapú módosítása, Fix #9 @30m

This commit is contained in:
2026-07-11 18:28:01 +02:00
parent fc31acb80f
commit d2605b00da
2 changed files with 80 additions and 23 deletions
@@ -329,17 +329,35 @@ class TrackingController extends GetxController {
pos.latitude, pos.latitude,
pos.longitude, pos.longitude,
); );
// Szűrés: ugrásszerű változás (pl. GPS lock elvesztése) ignorálása
if (segmentDist > 100) { // Szűrés: valóban LEHETETLEN ugrás kiszűrése (pl. GPS lock-
// vesztés utáni téves fix) — az ELTELT IDŐT is figyelembe véve.
// A korábbi, sima 100 m-es távolság-küszöb gyorsabb haladásnál
// (pl. földúton autóval) egy rövid, teljesen normál jel-
// kimaradás után érkező, VALÓS pontokat is kiszűrt, mert
// néhány másodperc alatt egy autó simán megtesz 100+ métert.
final elapsedSec =
point.timestamp.difference(_lastPoint!.timestamp).inMilliseconds /
1000.0;
final impliedSpeedMs =
elapsedSec > 0 ? segmentDist / elapsedSec : double.infinity;
// ~50 m/s = 180 km/h — terepen, földúton ennél gyorsabban senki
// nem halad, tehát ami ennél nagyobb sebességet implikálna, az
// GPS-hiba, nem valódi mozgás.
const maxPlausibleSpeedMs = 50.0;
if (impliedSpeedMs > maxPlausibleSpeedMs) {
AppLogger.w( AppLogger.w(
'_onPosition', '_onPosition',
'GPS ugrás kiszűrve: ${segmentDist.toStringAsFixed(0)}m ' 'GPS ugrás kiszűrve: ${segmentDist.toStringAsFixed(0)}m / '
'(pts: ${livePoints.length})'); '${elapsedSec.toStringAsFixed(1)}s '
_lastPoint = point; // reset — következő pont ettől mér '(${(impliedSpeedMs * 3.6).toStringAsFixed(0)} km/h, '
'pts: ${livePoints.length})');
_lastPoint = point;
return; return;
} }
} }
_accumulatedDistance += segmentDist; _accumulatedDistance += segmentDist;
sessionDistance.value = _accumulatedDistance; sessionDistance.value = _accumulatedDistance;
+44 -5
View File
@@ -20,6 +20,12 @@ class PhoneGpsSource implements LocationSource {
/// Minimális elmozdulás méterben új pont előtt. /// Minimális elmozdulás méterben új pont előtt.
final double distanceFilter; final double distanceFilter;
/// Egymást követő sikertelen újraindítási kísérletek száma — véd a
/// végtelen, szoros hiba-ciklus ellen, ha valami tartósan elromlott.
int _retryCount = 0;
static const _maxRetries = 5;
Timer? _retryTimer;
PhoneGpsSource({ PhoneGpsSource({
this.intervalMs = 1000, this.intervalMs = 1000,
this.distanceFilter = 1.0, this.distanceFilter = 1.0,
@@ -59,15 +65,17 @@ class PhoneGpsSource implements LocationSource {
// notification biztosítja a jogszerű háttér-használatot. // notification biztosítja a jogszerű háttér-használatot.
foregroundNotificationConfig: const ForegroundNotificationConfig( foregroundNotificationConfig: const ForegroundNotificationConfig(
notificationText: 'Track rögzítése folyamatban', notificationText: 'Track rögzítése folyamatban',
notificationTitle: 'Terepi Segéd Nyomvonal', notificationTitle: 'Terepi Segéd - Nyomvonal',
enableWakeLock: true, enableWakeLock: true,
), ),
); );
await _positionSub?.cancel();
_positionSub = Geolocator.getPositionStream( _positionSub = Geolocator.getPositionStream(
locationSettings: settings, locationSettings: settings,
).listen( ).listen((Position pos) {
(Position pos) { _retryCount = 0;
_controller?.add(SourcePosition( _controller?.add(SourcePosition(
latitude: pos.latitude, latitude: pos.latitude,
longitude: pos.longitude, longitude: pos.longitude,
@@ -80,12 +88,43 @@ class PhoneGpsSource implements LocationSource {
source: displayName, source: displayName,
)); ));
}, },
onError: (e) => _controller?.addError(e), onError: (e) => _handleStreamError,
); onDone: () =>
_handleStreamError(Exception('A GPS-stream váratlanul lezárult.')));
}
/// A Geolocator stream NEM öngyógyuló: ha egyszer hibát dob (terepen,
/// zötykölődő telefonnal ez elő szokott fordulni), magától többé NEM
/// küld pozíciót. Ezért itt — a korábbi "csak továbbadjuk és feladjuk"
/// helyett — manuálisan újraindítjuk a mögöttes streamet. Végleges,
/// nem-helyreállítható hibáknál (jogosultság/szolgáltatás kikapcsolva)
/// viszont TOVÁBBADJUK, hogy a TrackingController korrekten leállítsa
/// a rögzítést, ahogy eddig is.
void _handleStreamError(Object e) {
if (e is LocationServiceDisabledException ||
e is PermissionDeniedException) {
_controller?.addError(e);
return;
}
_retryCount++;
if (_retryCount > _maxRetries) {
// Tartósan hibás állapot — ezt már valóban jelezni kell.
_controller?.addError(e);
return;
}
// Rövid várakozás, majd friss stream indítása. A _controller
// (amit a TrackingController figyel) változatlan marad — onnan
// nézve ez csak egy pillanatnyi szünet a pozíciókban, nem egy
// végleges leállás.
_retryTimer?.cancel();
_retryTimer = Timer(const Duration(seconds: 1), _startListening);
} }
@override @override
Future<void> dispose() async { Future<void> dispose() async {
_retryTimer?.cancel();
await _positionSub?.cancel(); await _positionSub?.cancel();
await _controller?.close(); await _controller?.close();
_controller = null; _controller = null;