Food: single-source tracking, mode exclusivity, in-app navigation
This commit is contained in:
@@ -13,6 +13,7 @@ import 'package:siro_driver/constant/box_name.dart';
|
||||
import 'package:siro_driver/constant/links.dart';
|
||||
import 'package:siro_driver/controller/car_platform_bridge.dart';
|
||||
import 'package:siro_driver/controller/functions/crud.dart';
|
||||
import 'package:siro_driver/controller/functions/location_controller.dart';
|
||||
import 'package:siro_driver/controller/functions/tts.dart';
|
||||
import 'package:siro_driver/controller/home/navigation/decode_polyline_isolate.dart';
|
||||
import 'package:siro_driver/env/env.dart';
|
||||
@@ -39,9 +40,6 @@ class RouteData {
|
||||
|
||||
class NavigationController extends GetxController
|
||||
with GetSingleTickerProviderStateMixin {
|
||||
static const Duration _recordInterval = Duration(seconds: 4);
|
||||
static const Duration _uploadInterval = Duration(minutes: 2);
|
||||
static const double _minMoveToRecord = 10.0;
|
||||
static const double _minMoveToProcess = 2.0;
|
||||
static const double _offRouteThresholdM = 25.0;
|
||||
static const int _offRouteTriggerSeconds = 6;
|
||||
@@ -164,11 +162,6 @@ class NavigationController extends GetxController
|
||||
DateTime? _offRouteStartTime;
|
||||
bool _autoRecalcInProgress = false;
|
||||
|
||||
final List<Map<String, dynamic>> _trackBuffer = [];
|
||||
Timer? _recordTimer;
|
||||
Timer? _uploadBatchTimer;
|
||||
LatLng? _lastBufferedLocation;
|
||||
DateTime? _lastBufferedTime;
|
||||
LatLng? _lastDistanceLocation;
|
||||
|
||||
List<RouteData> routes = [];
|
||||
@@ -364,13 +357,11 @@ class NavigationController extends GetxController
|
||||
@override
|
||||
void onClose() {
|
||||
_locationStreamSubscription?.cancel();
|
||||
_recordTimer?.cancel();
|
||||
_uploadBatchTimer?.cancel();
|
||||
_debounce?.cancel();
|
||||
_animController?.dispose();
|
||||
mapController = null;
|
||||
placeDestinationController.dispose();
|
||||
_flushBufferToServer();
|
||||
_flushTracksViaCentral();
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
@@ -475,7 +466,6 @@ class NavigationController extends GetxController
|
||||
if (isStyleLoaded) animateCameraToPosition(myLocation!);
|
||||
// Start the Location Stream for real-time updates
|
||||
_startLocationStream();
|
||||
_startBatchTimers();
|
||||
} catch (e) {
|
||||
Log.print("DEBUG: Error getting initial location: $e");
|
||||
}
|
||||
@@ -616,63 +606,16 @@ class NavigationController extends GetxController
|
||||
}
|
||||
}
|
||||
|
||||
void _startBatchTimers() {
|
||||
_recordTimer?.cancel();
|
||||
_uploadBatchTimer?.cancel();
|
||||
_recordTimer = Timer.periodic(_recordInterval, (_) => _recordToBuffer());
|
||||
_uploadBatchTimer =
|
||||
Timer.periodic(_uploadInterval, (_) => _flushBufferToServer());
|
||||
}
|
||||
// رفع مسار القيادة (add_batch) مركزيّ في LocationController وحده.
|
||||
// كان الملّاح يحتفظ بذاكرة ومؤقّتات رفع خاصة به ويُرسل إلى نفس الواجهة
|
||||
// ونفس الخادم، فيُكتب مسار السائق الواحد مرتين ما دامت شاشة الملاحة
|
||||
// مفتوحة — ولأن add_batch.php يراكم زمن العمل اليومي من نفس الجدول،
|
||||
// كان ذلك يضاعف ساعات العمل المحسوبة. مصدر الموقع واحد فالرفع واحد.
|
||||
|
||||
void _recordToBuffer() {
|
||||
if (myLocation == null ||
|
||||
(myLocation!.latitude == 0 && myLocation!.longitude == 0)) {
|
||||
return;
|
||||
}
|
||||
final now = DateTime.now();
|
||||
final distFromLast = _lastBufferedLocation == null
|
||||
? 999.0
|
||||
: Geolocator.distanceBetween(
|
||||
_lastBufferedLocation!.latitude,
|
||||
_lastBufferedLocation!.longitude,
|
||||
myLocation!.latitude,
|
||||
myLocation!.longitude);
|
||||
final bool moved = distFromLast > _minMoveToRecord && currentSpeed > 0.5;
|
||||
final bool timeForced = _lastBufferedTime == null ||
|
||||
now.difference(_lastBufferedTime!).inSeconds >= 60;
|
||||
if (!moved && !timeForced) return;
|
||||
|
||||
_lastBufferedLocation = myLocation;
|
||||
_lastBufferedTime = now;
|
||||
|
||||
_trackBuffer.add({
|
||||
'lat': double.parse(myLocation!.latitude.toStringAsFixed(6)),
|
||||
'lng': double.parse(myLocation!.longitude.toStringAsFixed(6)),
|
||||
'spd': double.parse(currentSpeed.toStringAsFixed(1)),
|
||||
'head': _smoothedHeading.toStringAsFixed(0),
|
||||
'dist': double.parse(totalDistance.toStringAsFixed(1)),
|
||||
'ts': now.toIso8601String(),
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _flushBufferToServer() async {
|
||||
if (_trackBuffer.isEmpty) return;
|
||||
final batch = List<Map<String, dynamic>>.from(_trackBuffer);
|
||||
_trackBuffer.clear();
|
||||
final String passengerId = (box.read(BoxName.passengerID) ?? '').toString();
|
||||
|
||||
try {
|
||||
await CRUD().post(
|
||||
link: '${AppLink.locationServerSide}/add_batch.php',
|
||||
payload: {
|
||||
'driver_id': passengerId,
|
||||
'batch_data': jsonEncode(batch),
|
||||
'session_dist': totalDistance.toStringAsFixed(1),
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
_trackBuffer.insertAll(0, batch);
|
||||
}
|
||||
// الرفع مركزيّ في LocationController — نطلب منه دفع ما تراكم فقط
|
||||
void _flushTracksViaCentral() {
|
||||
if (!Get.isRegistered<LocationController>()) return;
|
||||
Get.find<LocationController>().flushTrackBufferNow();
|
||||
}
|
||||
|
||||
Future<void> _updateCarMarker() async {
|
||||
@@ -1179,7 +1122,7 @@ class NavigationController extends GetxController
|
||||
isNavigating = false;
|
||||
routes = [];
|
||||
CarPlatformBridge.stopNavigation();
|
||||
await _flushBufferToServer();
|
||||
_flushTracksViaCentral();
|
||||
}
|
||||
routeSteps = [];
|
||||
_fullRouteCoordinates = [];
|
||||
@@ -1277,7 +1220,7 @@ class NavigationController extends GetxController
|
||||
Get.find<TextToSpeechController>().speakText(currentInstruction);
|
||||
}
|
||||
CarPlatformBridge.stopNavigation();
|
||||
_flushBufferToServer();
|
||||
_flushTracksViaCentral();
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user