web_flutter_tank_appwrite_app/lib/controllers/geolocation_controller.dart
2025-10-22 08:43:20 +02:00

282 lines
8.3 KiB
Dart

import 'package:get/get.dart';
import 'package:geolocator/geolocator.dart';
import '../../services/geolocation.dart';
import '../models/ptv_logistic_model.dart';
import '../services/ptv_api_simple.dart';
/// GetX Controller für Geolocation Funktionalität
class GeolocationController extends GetxController {
// Reactive Variablen
final _currentPosition = Rxn<Position>();
final _statusText = 'Noch keine Position ermittelt'.obs;
final _isTracking = false.obs;
final _isLoading = false.obs;
final _ptvModel = Rxn<PTVModel>();
// Getter für reactive Variablen
Position? get currentPosition => _currentPosition.value;
String get statusText => _statusText.value;
bool get isTracking => _isTracking.value;
bool get isLoading => _isLoading.value;
PTVModel? get ptvModel => _ptvModel.value;
@override
void onClose() {
// Cleanup beim Schließen des Controllers
stopTracking();
super.onClose();
}
/// Holt die aktuelle Position einmalig
Future<void> getCurrentPosition() async {
try {
_isLoading.value = true;
_statusText.value = 'Position wird ermittelt...';
Position? position = await GeolocationService.getCurrentPosition();
if (position != null) {
_currentPosition.value = position;
_statusText.value = GeolocationService.positionToString(position);
var resultData = await PtvApiServiceSimple.getLocationsByPosition(
latitude: position.latitude,
longitude: position.longitude,
);
if(resultData != null) {
_ptvModel.value = PTVModel.fromJson(resultData);
} else {
_ptvModel.value = null;
}
// Erfolgs-Snackbar anzeigen
Get.snackbar(
'Position ermittelt',
'Aktuelle Position wurde erfolgreich abgerufen',
snackPosition: SnackPosition.BOTTOM,
);
} else {
_statusText.value = 'Position konnte nicht ermittelt werden';
// Fehler-Snackbar anzeigen
Get.snackbar(
'Fehler',
'Position konnte nicht ermittelt werden',
snackPosition: SnackPosition.BOTTOM,
);
}
} catch (e) {
_statusText.value = 'Fehler beim Abrufen der Position: $e';
Get.snackbar(
'Fehler',
'Unerwarteter Fehler: $e',
snackPosition: SnackPosition.BOTTOM,
);
} finally {
_isLoading.value = false;
}
}
/// Startet kontinuierliches Position Tracking
Future<void> startTracking() async {
if (_isTracking.value) return;
try {
_isLoading.value = true;
_statusText.value = 'Tracking wird gestartet...';
bool success = await GeolocationService.startPositionStream(
onPositionChanged: (Position position) {
_currentPosition.value = position;
_statusText.value = GeolocationService.positionToString(position);
},
onError: (String error) {
_statusText.value = 'Tracking Fehler: $error';
_isTracking.value = false;
Get.snackbar(
'Tracking Fehler',
error,
snackPosition: SnackPosition.BOTTOM,
);
},
accuracy: LocationAccuracy.high,
distanceFilter: 5, // Updates alle 5 Meter
);
if (success) {
_isTracking.value = true;
_statusText.value = 'Tracking aktiv - Warten auf erste Position...';
Get.snackbar(
'Tracking gestartet',
'Position wird kontinuierlich überwacht',
snackPosition: SnackPosition.BOTTOM,
);
} else {
_statusText.value = 'Tracking konnte nicht gestartet werden';
Get.snackbar(
'Fehler',
'Tracking konnte nicht gestartet werden',
snackPosition: SnackPosition.BOTTOM,
);
}
} catch (e) {
_statusText.value = 'Fehler beim Starten des Trackings: $e';
Get.snackbar(
'Fehler',
'Tracking-Fehler: $e',
snackPosition: SnackPosition.BOTTOM,
);
} finally {
_isLoading.value = false;
}
}
/// Stoppt das Position Tracking
Future<void> stopTracking() async {
if (!_isTracking.value) return;
try {
await GeolocationService.stopPositionStream();
_isTracking.value = false;
_statusText.value = 'Tracking gestoppt';
Get.snackbar(
'Tracking gestoppt',
'Position wird nicht mehr überwacht',
snackPosition: SnackPosition.BOTTOM,
);
} catch (e) {
Get.snackbar(
'Fehler',
'Fehler beim Stoppen des Trackings: $e',
snackPosition: SnackPosition.BOTTOM,
);
}
}
/// Togglet das Tracking (Start/Stop)
Future<void> toggleTracking() async {
if (_isTracking.value) {
await stopTracking();
} else {
await startTracking();
}
}
/// Prüft Permission Status
Future<void> checkPermissions() async {
try {
_isLoading.value = true;
_statusText.value = 'Berechtigungen werden geprüft...';
LocationPermission permission = await GeolocationService.checkPermission();
bool serviceEnabled = await GeolocationService.isLocationServiceEnabled();
_statusText.value = 'Service aktiv: $serviceEnabled\n'
'Berechtigung: ${LocationPermissionHelper.getPermissionStatusText(permission)}';
// Detaillierte Information in Snackbar
String permissionStatus = LocationPermissionHelper.getPermissionStatusText(permission);
Get.snackbar(
'Berechtigungs-Status',
'Location Service: ${serviceEnabled ? "Aktiv" : "Inaktiv"}\n$permissionStatus',
snackPosition: SnackPosition.BOTTOM,
duration: const Duration(seconds: 4),
);
} catch (e) {
_statusText.value = 'Fehler beim Prüfen der Berechtigungen: $e';
Get.snackbar(
'Fehler',
'Berechtigungen konnten nicht geprüft werden: $e',
snackPosition: SnackPosition.BOTTOM,
);
} finally {
_isLoading.value = false;
}
}
/// Öffnet die Location Einstellungen
Future<void> openLocationSettings() async {
try {
bool opened = await GeolocationService.openLocationSettings();
if (opened) {
Get.snackbar(
'Einstellungen geöffnet',
'Location-Einstellungen wurden geöffnet',
snackPosition: SnackPosition.BOTTOM,
);
} else {
Get.snackbar(
'Fehler',
'Location-Einstellungen konnten nicht geöffnet werden',
snackPosition: SnackPosition.BOTTOM,
);
}
} catch (e) {
Get.snackbar(
'Fehler',
'Fehler beim Öffnen der Location-Einstellungen: $e',
snackPosition: SnackPosition.BOTTOM,
);
}
}
/// Öffnet die App Einstellungen
Future<void> openAppSettings() async {
try {
bool opened = await GeolocationService.openAppSettings();
if (opened) {
Get.snackbar(
'Einstellungen geöffnet',
'App-Einstellungen wurden geöffnet',
snackPosition: SnackPosition.BOTTOM,
);
} else {
Get.snackbar(
'Fehler',
'App-Einstellungen konnten nicht geöffnet werden',
snackPosition: SnackPosition.BOTTOM,
);
}
} catch (e) {
Get.snackbar(
'Fehler',
'Fehler beim Öffnen der App-Einstellungen: $e',
snackPosition: SnackPosition.BOTTOM,
);
}
}
/// Formatiert die aktuelle Position als lesbaren String
String get formattedPosition {
if (_currentPosition.value == null) return 'Keine Position verfügbar';
return GeolocationService.positionToString(_currentPosition.value!);
}
/// Prüft ob eine Position verfügbar ist
bool get hasPosition => _currentPosition.value != null;
/// Holt die Genauigkeit der aktuellen Position
double get currentAccuracy => _currentPosition.value?.accuracy ?? 0.0;
/// Holt die Geschwindigkeit der aktuellen Position in km/h
double get currentSpeedKmh {
if (_currentPosition.value?.speed == null) return 0.0;
return (_currentPosition.value!.speed * 3.6); // m/s zu km/h
}
/// Resettet alle Werte auf ihre Anfangszustände
void reset() {
stopTracking();
_currentPosition.value = null;
_statusText.value = 'Noch keine Position ermittelt';
_isTracking.value = false;
_isLoading.value = false;
}
}