233 lines
7.8 KiB
Dart
Executable File
233 lines
7.8 KiB
Dart
Executable File
import 'dart:async';
|
|
import 'dart:math';
|
|
|
|
import 'package:get/get.dart';
|
|
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
|
import 'package:location/location.dart';
|
|
import 'package:sefer_driver/constant/table_names.dart';
|
|
|
|
import '../../constant/box_name.dart';
|
|
import '../../constant/links.dart';
|
|
import '../../main.dart';
|
|
import '../../print.dart';
|
|
import '../home/captin/home_captain_controller.dart';
|
|
import '../home/payment/captain_wallet_controller.dart';
|
|
import 'battery_status.dart';
|
|
import 'crud.dart';
|
|
import 'encrypt_decrypt.dart';
|
|
|
|
class LocationController extends GetxController {
|
|
LocationData? _currentLocation;
|
|
late Location location = Location();
|
|
bool isLoading = false;
|
|
late double heading = 0;
|
|
late double previousTime = 0;
|
|
late double latitude;
|
|
late double totalDistance = 0;
|
|
late double longitude;
|
|
late DateTime time;
|
|
late double speed = 0;
|
|
bool isActive = false;
|
|
late LatLng myLocation = LatLng(0, 0);
|
|
String totalPoints = '0';
|
|
LocationData? get currentLocation => _currentLocation;
|
|
Timer? _locationTimer;
|
|
|
|
LatLng? _lastSavedPosition;
|
|
|
|
@override
|
|
void onInit() async {
|
|
super.onInit();
|
|
location = Location();
|
|
await location.changeSettings(
|
|
accuracy: LocationAccuracy.high, interval: 5000, distanceFilter: 0);
|
|
await location.enableBackgroundMode(enable: true);
|
|
await getLocation();
|
|
await startLocationUpdates();
|
|
|
|
totalPoints = Get.put(CaptainWalletController()).totalPoints.toString();
|
|
isActive = Get.put(HomeCaptainController()).isActive;
|
|
}
|
|
|
|
String getLocationArea(double latitude, double longitude) {
|
|
final locations = box.read(BoxName.locationName) ?? [];
|
|
for (final location in locations) {
|
|
final locationData = location as Map<String, dynamic>;
|
|
final minLatitude =
|
|
double.tryParse(locationData['min_latitude'].toString()) ?? 0.0;
|
|
final maxLatitude =
|
|
double.tryParse(locationData['max_latitude'].toString()) ?? 0.0;
|
|
final minLongitude =
|
|
double.tryParse(locationData['min_longitude'].toString()) ?? 0.0;
|
|
final maxLongitude =
|
|
double.tryParse(locationData['max_longitude'].toString()) ?? 0.0;
|
|
|
|
if (latitude >= minLatitude &&
|
|
latitude <= maxLatitude &&
|
|
longitude >= minLongitude &&
|
|
longitude <= maxLongitude) {
|
|
box.write(BoxName.serverChosen, (locationData['server_link']));
|
|
return locationData['name'];
|
|
}
|
|
}
|
|
|
|
box.write(BoxName.serverChosen, AppLink.seferCairoServer);
|
|
return 'Cairo';
|
|
}
|
|
|
|
int _insertCounter = 0;
|
|
double? _lastSpeed;
|
|
DateTime? _lastSpeedTime;
|
|
|
|
Future<void> startLocationUpdates() async {
|
|
if (box.read(BoxName.driverID) != null) {
|
|
_locationTimer =
|
|
Timer.periodic(const Duration(seconds: 5), (timer) async {
|
|
try {
|
|
await BatteryNotifier.checkBatteryAndNotify();
|
|
totalPoints =
|
|
Get.find<CaptainWalletController>().totalPoints.toString();
|
|
isActive = Get.find<HomeCaptainController>().isActive;
|
|
|
|
if (isActive && double.parse(totalPoints) > -300) {
|
|
await getLocation();
|
|
if (myLocation.latitude == 0 && myLocation.longitude == 0) return;
|
|
|
|
String area =
|
|
getLocationArea(myLocation.latitude, myLocation.longitude);
|
|
|
|
final payload = {
|
|
'driver_id': box.read(BoxName.driverID).toString(),
|
|
'latitude': myLocation.latitude.toString(),
|
|
'longitude': myLocation.longitude.toString(),
|
|
'heading': heading.toString(),
|
|
'speed': (speed * 3.6).toStringAsFixed(1),
|
|
'distance': totalDistance.toStringAsFixed(2),
|
|
'status': box.read(BoxName.statusDriverLocation) ?? 'off',
|
|
};
|
|
|
|
// ✅ تحديث للسيرفر
|
|
await CRUD().post(
|
|
link:
|
|
box.read(BoxName.serverChosen) + '/ride/location/update.php',
|
|
payload: payload,
|
|
);
|
|
|
|
// ✅ تخزين في SQLite فقط إذا الرحلة On + تحرك أكثر من 10 متر
|
|
if ((box.read(BoxName.statusDriverLocation) ?? 'off') == 'on') {
|
|
if (_lastSavedPosition == null ||
|
|
_calculateDistanceInMeters(_lastSavedPosition!, myLocation) >=
|
|
10) {
|
|
double currentSpeed = speed; // m/s
|
|
double? acceleration = _calculateAcceleration(currentSpeed);
|
|
|
|
await sql.insertData({
|
|
'driver_id': box.read(BoxName.driverID).toString(),
|
|
'latitude': myLocation.latitude,
|
|
'longitude': myLocation.longitude,
|
|
'acceleration': acceleration ?? 0.0,
|
|
'created_at': DateTime.now().toIso8601String(),
|
|
'updated_at': DateTime.now().toIso8601String(),
|
|
}, TableName.behavior);
|
|
|
|
_lastSavedPosition = myLocation;
|
|
}
|
|
}
|
|
|
|
// ✅ إدخال للسيرفر كل دقيقة
|
|
_insertCounter++;
|
|
// Log.print('_insertCounter: ${_insertCounter}');
|
|
if (_insertCounter == 12) {
|
|
_insertCounter = 0;
|
|
await CRUD().post(
|
|
link: box.read(BoxName.serverChosen) + '/ride/location/add.php',
|
|
payload: payload,
|
|
);
|
|
}
|
|
|
|
// ✅ تحديث الكاميرا
|
|
Get.find<HomeCaptainController>()
|
|
.mapHomeCaptainController
|
|
?.animateCamera(
|
|
CameraUpdate.newLatLng(
|
|
LatLng(
|
|
myLocation.latitude,
|
|
myLocation.longitude,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
} catch (e) {
|
|
print('Location update error: $e');
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
void stopLocationUpdates() {
|
|
_locationTimer?.cancel();
|
|
}
|
|
|
|
Future<void> getLocation() async {
|
|
bool serviceEnabled = await location.serviceEnabled();
|
|
if (!serviceEnabled) {
|
|
serviceEnabled = await location.requestService();
|
|
if (!serviceEnabled) return;
|
|
}
|
|
|
|
PermissionStatus permissionGranted = await location.hasPermission();
|
|
if (permissionGranted == PermissionStatus.denied) {
|
|
permissionGranted = await location.requestPermission();
|
|
if (permissionGranted != PermissionStatus.granted) return;
|
|
}
|
|
|
|
Future.delayed(Duration(milliseconds: 500), () async {
|
|
try {
|
|
LocationData _locationData = await location.getLocation();
|
|
if (_locationData.latitude != null && _locationData.longitude != null) {
|
|
myLocation =
|
|
LatLng(_locationData.latitude!, _locationData.longitude!);
|
|
} else {
|
|
myLocation = LatLng(0, 0);
|
|
}
|
|
|
|
speed = _locationData.speed ?? 0;
|
|
heading = _locationData.heading ?? 0;
|
|
|
|
update();
|
|
} catch (e) {
|
|
print("Error getting location: $e");
|
|
}
|
|
});
|
|
}
|
|
|
|
double _calculateDistanceInMeters(LatLng start, LatLng end) {
|
|
const p = 0.017453292519943295;
|
|
final a = 0.5 -
|
|
cos((end.latitude - start.latitude) * p) / 2 +
|
|
cos(start.latitude * p) *
|
|
cos(end.latitude * p) *
|
|
(1 - cos((end.longitude - start.longitude) * p)) /
|
|
2;
|
|
return 12742 * 1000 * asin(sqrt(a)); // meters
|
|
}
|
|
|
|
double? _calculateAcceleration(double currentSpeed) {
|
|
final now = DateTime.now();
|
|
if (_lastSpeed != null && _lastSpeedTime != null) {
|
|
final deltaTime =
|
|
now.difference(_lastSpeedTime!).inMilliseconds / 1000.0; // seconds
|
|
if (deltaTime > 0) {
|
|
final acceleration = (currentSpeed - _lastSpeed!) / deltaTime;
|
|
_lastSpeed = currentSpeed;
|
|
_lastSpeedTime = now;
|
|
return double.parse(acceleration.toStringAsFixed(2));
|
|
}
|
|
}
|
|
|
|
_lastSpeed = currentSpeed;
|
|
_lastSpeedTime = now;
|
|
return null;
|
|
}
|
|
}
|