device infos

This commit is contained in:
2026-08-28 15:07:30 +05:30
parent 5723d373b2
commit 69f4f3e909
84 changed files with 4337 additions and 2339 deletions

View File

@@ -9,6 +9,7 @@ import 'package:latlong2/latlong.dart' show LatLng;
import 'package:miler/helpers/miler_router.dart';
import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:miler/data/accepted_store.dart';
import 'package:geolocator/geolocator.dart';
import 'package:miler/views/helpers/constants/apiconstants.dart';
@@ -574,6 +575,29 @@ class PickupsController extends GetxController
}
}
// ── Written down, not only sent ──
//
// This figure is the only measurement of the leg that exists: the backend
// does not reliably send a distance back on `GET /miler/bookings`, and
// until now the app posted this and kept nothing, so Activity's `km
// ridden` had no row to total and printed an em dash on a day of real
// riding. Recorded against the stop so the record that gets filed carries
// it — see [kStopKmKey] and `addCompletedBookings`.
//
// Best-effort: a preferences write must never cost the rider a pickup
// that has otherwise succeeded.
if (calculatedKms > 0) {
try {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(
kStopKmKey(pickupId),
calculatedKms.toStringAsFixed(2),
);
} catch (e) {
debugPrint('[PICKED] could not record the distance: $e');
}
}
final payload = <String, dynamic>{
'pickupid': pickupId,
// Not sent to the backend — the legacy shape carries it and the mapper

View File

@@ -15,6 +15,7 @@ import 'package:miler/controllers/logcontroller.dart';
import 'package:miler/background/foreground_service.dart' as fg;
import 'package:miler/utils/kalman_filter.dart';
import 'package:miler/utils/mqtt_service.dart';
import 'package:miler/data/device_telemetry.dart';
import 'package:miler/views/helpers/constants/mqtt_constants.dart';
import 'package:battery_plus/battery_plus.dart';
import 'package:miler/controllers/connectivity_mixin.dart';
@@ -260,6 +261,14 @@ class RiderLogController extends GetxController
}
} catch (_) {}
// The handset's own state — see [DeviceTelemetry] for why this is read
// here and not published to MQTT alone. The console's Battery,
// Connection, GPS Accuracy and Location Service columns are read off the
// rider log, and until now nothing put them in it.
final telemetry = await DeviceTelemetry.read(
locationService: loc['status'],
);
final Map<String, dynamic> payload = {
// Base from server template
...baseTemplate,
@@ -288,6 +297,14 @@ class RiderLogController extends GetxController
'applocationid': applocationid ?? 0,
'userfcmtoken': userfcmtoken ?? '',
'orderid': orderId,
...telemetry.toPayload(),
// Only a measured one. A `0` here would draw on the console as a
// perfect fix rather than as no fix at all.
if ((loc['accuracy'] ?? '').isNotEmpty) 'accuracy': loc['accuracy'],
// This is the *foreground* controller — the rider has the app open.
// The background heartbeat sends true, and the difference between the
// two is what the console's App State column reports.
'is_background': false,
};
// --- MQTT LOGIC ( Lane Split ) ---
@@ -325,6 +342,10 @@ class RiderLogController extends GetxController
'heading': loc['heading'] ?? '0',
'status': riderStatus,
'orderid': orderId,
// The same reading the log above carries, so the live lane and the
// trail cannot report two different batteries a second apart.
...telemetry.toPayload(),
if ((loc['accuracy'] ?? '').isNotEmpty) 'accuracy': loc['accuracy'],
});
// Ensure rider identity fields are clean:
@@ -779,6 +800,19 @@ class RiderLogController extends GetxController
'heading': '0',
'velocity_lat': '0',
'velocity_lng': '0',
// ── Two fields the background lookup has always returned and this one
// did not ──
//
// `accuracy` is how good the fix is and `status` is whether location is
// switched on at all — the two the console draws under GPS Accuracy and
// Location Service. Absent here, the foreground heartbeat had nothing to
// send and would have had to invent a `0`, which reads as a *perfect*
// fix rather than as no fix.
//
// Empty, not zero: an unknown accuracy is dropped from the payload by
// the caller and drawn as an em dash, which is the truth.
'accuracy': '',
'status': 'unknown',
};
try {
final needsFetch =
@@ -786,7 +820,10 @@ class RiderLogController extends GetxController
if (!needsFetch) return result;
final serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) return result;
if (!serviceEnabled) {
result['status'] = 'disabled';
return result;
}
LocationPermission permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
@@ -794,8 +831,12 @@ class RiderLogController extends GetxController
}
if (permission == LocationPermission.denied ||
permission == LocationPermission.deniedForever) {
result['status'] = permission == LocationPermission.deniedForever
? 'denied_forever'
: 'denied';
return result;
}
result['status'] = 'enabled';
final Position pos = await Geolocator.getCurrentPosition(
locationSettings: const LocationSettings(
@@ -836,6 +877,8 @@ class RiderLogController extends GetxController
'heading': heading.toStringAsFixed(2),
'velocity_lat': velocityLat.toStringAsFixed(4),
'velocity_lng': velocityLng.toStringAsFixed(4),
'accuracy': pos.accuracy.toStringAsFixed(1),
'status': 'enabled',
};
} catch (_) {
return result;