feat: align fast-GPS beacons with MeshUI firmware (16-byte format + cadence parity)

Switch the fast-GPS beacon to the firmware's canonical 16-byte wire format
(magic, key6, lat/lon microdegrees, speed km/h) — no on-wire timestamp; the
receiver stamps its own RX time. Drops compatibility with the older 19-byte app
format.

Mirror the firmware's adaptive send cadence in the app-fallback path
(LocationTrackingService): anchor + dwell motion hysteresis, EMA ground speed,
9-min stationary keepalive, fix-quality (accuracy) gate, and a post-RX hold-off
to avoid channel collisions. Parked nodes now beacon the stable anchor instead
of GPS wander.

Add the fast_gps_region config: region-scope picker in settings backed by the
firmware's fast_gps_region / fast_gps_regions custom vars.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Janez T
2026-06-24 13:17:02 +02:00
parent 3283d4ca20
commit 3c08e150ef
7 changed files with 490 additions and 113 deletions

View File

@@ -1164,6 +1164,10 @@ class ContactsProvider with ChangeNotifier {
return;
}
// The fast-GPS beacon carries no timestamp — stamp our own receive time.
final receivedAt = DateTime.now();
final receivedAtSeconds = receivedAt.millisecondsSinceEpoch ~/ 1000;
final updatedTelemetry = _mergeTelemetryForContact(
existingTelemetry: contact.telemetry,
incomingTelemetry: ContactTelemetry(
@@ -1171,9 +1175,7 @@ class ContactsProvider with ChangeNotifier {
batteryPercentage: null,
batteryMilliVolts: null,
temperature: null,
timestamp: DateTime.fromMillisecondsSinceEpoch(
packet.timestampSeconds * 1000,
),
timestamp: receivedAt,
humidity: null,
pressure: null,
extraSensorData: null,
@@ -1187,13 +1189,13 @@ class ContactsProvider with ChangeNotifier {
'contactKey=${contact.publicKeyHex} '
'lat=${packet.latitude} '
'lon=${packet.longitude} '
'ts=${packet.timestampSeconds}',
'speed=${packet.speedKmh}km/h',
);
final updatedContact = contact.copyWith(
telemetry: updatedTelemetry,
lastAdvert: packet.timestampSeconds,
lastMod: packet.timestampSeconds,
lastAdvert: receivedAtSeconds,
lastMod: receivedAtSeconds,
advLat: _coordinateToAdvertMicrodegrees(packet.latitude),
advLon: _coordinateToAdvertMicrodegrees(packet.longitude),
);