MotorSignal-App/lib/services/location_service.dart

68 lines
2.2 KiB
Dart

import 'dart:async';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:geolocator/geolocator.dart';
import 'package:permission_handler/permission_handler.dart';
final locationServiceProvider = Provider<LocationService>((ref) {
return LocationService();
});
final locationStreamProvider = StreamProvider<Position>((ref) {
final service = ref.watch(locationServiceProvider);
return service.getFilteredPositionStream();
});
class LocationService {
Position? _lastValidPosition;
// Filtering thresholds
static const double _maxAcceptableAccuracy = 20.0; // meters
static const double _maxRealisticSpeed = 100.0; // roughly 223 MPH in m/s
static const double _maxAcceleration = 20.0; // m/s^2 (unrealistic jump)
Future<bool> requestPermissions() async {
final status = await Permission.locationWhenInUse.request();
if (status.isGranted) {
// Optional: request background if needed later
return true;
}
return false;
}
Stream<Position> getFilteredPositionStream() {
final LocationSettings locationSettings = AndroidSettings(
accuracy: LocationAccuracy.bestForNavigation,
distanceFilter: 0,
intervalDuration: const Duration(milliseconds: 200), // 5Hz updates
// (Optional) foregroundNotificationConfig if we implement background tracking
);
return Geolocator.getPositionStream(locationSettings: locationSettings)
.where(_isValidPosition);
}
bool _isValidPosition(Position position) {
if (position.accuracy > _maxAcceptableAccuracy) {
return false; // Reject extremely poor accuracy
}
if (position.speed > _maxRealisticSpeed) {
return false; // Reject impossible speeds
}
if (_lastValidPosition != null) {
// Avoid division by zero and ensure positive time diff
final timeDiff = (position.timestamp.difference(_lastValidPosition!.timestamp)).inMilliseconds / 1000.0;
if (timeDiff > 0) {
final accel = (position.speed - _lastValidPosition!.speed).abs() / timeDiff;
if (accel > _maxAcceleration) {
return false; // Reject impossible acceleration spikes
}
}
}
_lastValidPosition = position;
return true;
}
}