fix: ignore zeroed telemetry gps coords

Fixes #4\nRefs #5\n\nref:
This commit is contained in:
Janez T
2026-02-28 14:17:52 +01:00
parent c90fd8f617
commit 8d0aa7849e
2 changed files with 142 additions and 1 deletions

View File

@@ -1,4 +1,5 @@
import 'package:flutter/foundation.dart';
import 'package:latlong2/latlong.dart';
import '../models/contact.dart';
import '../services/cayenne_lpp_parser.dart';
import '../services/contact_storage_service.dart';
@@ -330,10 +331,28 @@ class ContactsProvider with ChangeNotifier {
try {
// Parse Cayenne LPP data
final telemetry = CayenneLppParser.parse(lppData);
var telemetry = CayenneLppParser.parse(lppData);
debugPrint(' ✅ Parsed new telemetry');
debugPrint(' New telemetry timestamp: ${telemetry.timestamp}');
// Ignore placeholder GPS coordinates (0,0) so we don't overwrite a
// previously known/saved position with invalid telemetry data.
if (_isInvalidTelemetryGps(telemetry.gpsLocation)) {
debugPrint(
' ⚠️ Ignoring invalid telemetry GPS coordinates: ${telemetry.gpsLocation}',
);
telemetry = ContactTelemetry(
gpsLocation: null,
batteryPercentage: telemetry.batteryPercentage,
batteryMilliVolts: telemetry.batteryMilliVolts,
temperature: telemetry.temperature,
timestamp: telemetry.timestamp,
humidity: telemetry.humidity,
pressure: telemetry.pressure,
extraSensorData: telemetry.extraSensorData,
);
}
// Update contact with new telemetry AND last seen time
// lastAdvert is Unix timestamp in seconds
final currentTimestamp = (DateTime.now().millisecondsSinceEpoch / 1000)
@@ -359,6 +378,18 @@ class ContactsProvider with ChangeNotifier {
}
}
bool _isInvalidTelemetryGps(LatLng? location) {
if (location == null) return false;
final lat = location.latitude;
final lon = location.longitude;
if (!lat.isFinite || !lon.isFinite) return true;
// Many devices report "0000" placeholder GPS as (0.0, 0.0).
const epsilon = 1e-7;
return lat.abs() < epsilon && lon.abs() < epsilon;
}
/// Find contact by public key prefix (6 bytes)
Contact? _findContactByPrefix(Uint8List prefix) {
if (prefix.length < 6) return null;

View File

@@ -0,0 +1,110 @@
import 'dart:typed_data';
import 'package:flutter_test/flutter_test.dart';
import 'package:meshcore_sar_app/models/contact.dart';
import 'package:meshcore_sar_app/providers/contacts_provider.dart';
import 'package:meshcore_sar_app/services/cayenne_lpp_parser.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
group('ContactsProvider.updateTelemetry', () {
late ContactsProvider provider;
late Uint8List publicKey;
setUp(() {
SharedPreferences.setMockInitialValues({});
provider = ContactsProvider();
publicKey = Uint8List.fromList([
0xAA,
0xBB,
0xCC,
0xDD,
0xEE,
0xFF,
0x01,
0x02,
0x03,
0x04,
0x05,
0x06,
0x07,
0x08,
0x09,
0x0A,
0x0B,
0x0C,
0x0D,
0x0E,
0x0F,
0x10,
0x11,
0x12,
0x13,
0x14,
0x15,
0x16,
0x17,
0x18,
0x19,
0x1A,
]);
provider.addOrUpdateContact(
Contact(
publicKey: publicKey,
type: ContactType.chat,
flags: 0,
outPathLen: 0,
outPath: Uint8List(64),
advName: 'Test Contact',
lastAdvert: DateTime.now().millisecondsSinceEpoch ~/ 1000,
advLat: (46.0569 * 1e6).toInt(),
advLon: (14.5058 * 1e6).toInt(),
lastMod: DateTime.now().millisecondsSinceEpoch ~/ 1000,
),
);
});
test('ignores telemetry GPS at 0,0 and keeps advert location', () {
final lppData = CayenneLppParser.createGpsData(
latitude: 0.0,
longitude: 0.0,
);
provider.updateTelemetry(publicKey.sublist(0, 6), lppData);
final updated = provider.findContactByKey(publicKey)!;
expect(updated.telemetry, isNotNull);
expect(updated.telemetry!.gpsLocation, isNull);
expect(updated.displayLocation, isNotNull);
expect(updated.displayLocation!.latitude, closeTo(46.0569, 0.000001));
expect(updated.displayLocation!.longitude, closeTo(14.5058, 0.000001));
});
test('keeps valid telemetry GPS and uses it for display location', () {
final lppData = CayenneLppParser.createGpsData(
latitude: 45.0001,
longitude: 13.9999,
);
provider.updateTelemetry(publicKey.sublist(0, 6), lppData);
final updated = provider.findContactByKey(publicKey)!;
expect(updated.telemetry, isNotNull);
expect(updated.telemetry!.gpsLocation, isNotNull);
expect(
updated.telemetry!.gpsLocation!.latitude,
closeTo(45.0001, 0.0001),
);
expect(
updated.telemetry!.gpsLocation!.longitude,
closeTo(13.9999, 0.0001),
);
expect(updated.displayLocation, isNotNull);
expect(updated.displayLocation!.latitude, closeTo(45.0001, 0.0001));
expect(updated.displayLocation!.longitude, closeTo(13.9999, 0.0001));
});
});
}