diff --git a/lib/gps_service.dart b/lib/gps_service.dart index e5961ad..e818c8d 100644 --- a/lib/gps_service.dart +++ b/lib/gps_service.dart @@ -10,7 +10,6 @@ class GpsService { locationSettings: const LocationSettings( accuracy: LocationAccuracy.bestForNavigation, distanceFilter: 0, - timeLimit: Duration(seconds: 2), // Short timeout for ongoing updates after initial fix ), ); } @@ -44,4 +43,4 @@ class GpsService { final cachedHeading = getCachedHeading(heading); return '${cachedHeading.round()} ${getCompassDirection(heading)}'; // don't add that degree symbol, this is cooler } -} \ No newline at end of file +} diff --git a/lib/services/gps_data_manager.dart b/lib/services/gps_data_manager.dart index f53d88f..6a82947 100644 --- a/lib/services/gps_data_manager.dart +++ b/lib/services/gps_data_manager.dart @@ -58,6 +58,9 @@ class GpsDataManager { isHeadingValid: false, ); + static const Duration _staleDataThreshold = Duration(seconds: 4); + Timer? _staleDataTimer; + // Public stream for UI components to subscribe to Stream get dataStream => _dataController.stream; @@ -154,30 +157,36 @@ class GpsDataManager { void _onPositionUpdate(Position position) { print('[GpsDataManager] 📡 Raw GPS update: speed=${position.speed.toStringAsFixed(2)} m/s, heading=${position.heading.toStringAsFixed(1)}°'); - - // For now, simple pass-through processing - // TODO: Add intelligent caching logic here later - - final speed = position.speed; - final heading = position.heading; - + + _scheduleStaleDataTimer(); + + final rawSpeed = position.speed; + final bool speedValid = rawSpeed.isFinite && rawSpeed >= 0; + final double speed = speedValid ? rawSpeed : 0.0; + + final rawHeading = position.heading; + final bool headingValid = rawHeading.isFinite && rawHeading >= 0 && rawHeading < 360; + final double heading = headingValid ? rawHeading : _currentData.heading; + // Basic display logic - TEMPORARILY show all speeds for indoor testing // TODO: Re-enable low-speed logic later: (speed < 1.0 && (heading < 0.0 || heading >= 360.0)) ? '--' : ... final displaySpeed = speed.toStringAsFixed(1); - - final displayHeading = GpsService.formatHeading(heading); - + + final displayHeading = headingValid + ? GpsService.formatHeading(heading) + : _currentData.displayHeading; + print('[GpsDataManager] 🔄 Processed: displaySpeed="$displaySpeed", displayHeading="$displayHeading"'); - + final processedData = ProcessedGpsData( speed: speed, heading: heading, displaySpeed: displaySpeed, displayHeading: displayHeading, - isSpeedValid: speed >= 0, - isHeadingValid: heading >= 0 && heading < 360, + isSpeedValid: speedValid, + isHeadingValid: headingValid, ); - + _updateData(processedData); } @@ -194,6 +203,34 @@ class GpsDataManager { } } + void _scheduleStaleDataTimer() { + _staleDataTimer?.cancel(); + _staleDataTimer = Timer(_staleDataThreshold, _handleStaleDataTimeout); + } + + void _handleStaleDataTimeout() { + // Avoid overriding explicit GPS error states or repeated stale notifications + final displayText = _currentData.displaySpeed; + if (displayText == '--' || displayText.startsWith('GPS') || displayText == 'NO PERM') { + return; + } + + final headingStillValid = _currentData.isHeadingValid && _currentData.heading >= 0 && _currentData.heading < 360; + final displayHeading = headingStillValid ? _currentData.displayHeading : '--'; + + print('[GpsDataManager] ⏱️ No GPS updates within ${_staleDataThreshold.inSeconds}s - marking data as stale'); + + final staleData = _currentData.copyWith( + displaySpeed: '--', + displayHeading: displayHeading, + isSpeedValid: false, + isHeadingValid: headingStillValid, + ); + + _staleDataTimer = null; + _updateData(staleData); + } + void _updateData(ProcessedGpsData newData) { print('[GpsDataManager] 📤 Broadcasting data: ${newData.displaySpeed} ${newData.displayHeading}'); _currentData = newData; @@ -217,8 +254,10 @@ class GpsDataManager { _gpsSubscription = null; } print('[GpsDataManager] 🛑 Closing data controller...'); + _staleDataTimer?.cancel(); + _staleDataTimer = null; _dataController.close(); _isInitialized = false; print('[GpsDataManager] 🛑 GPS manager disposed'); } -} \ No newline at end of file +}