mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
fix: ignore zeroed telemetry gps coords
Fixes #4\nRefs #5\n\nref:
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:latlong2/latlong.dart';
|
||||||
import '../models/contact.dart';
|
import '../models/contact.dart';
|
||||||
import '../services/cayenne_lpp_parser.dart';
|
import '../services/cayenne_lpp_parser.dart';
|
||||||
import '../services/contact_storage_service.dart';
|
import '../services/contact_storage_service.dart';
|
||||||
@@ -330,10 +331,28 @@ class ContactsProvider with ChangeNotifier {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Parse Cayenne LPP data
|
// Parse Cayenne LPP data
|
||||||
final telemetry = CayenneLppParser.parse(lppData);
|
var telemetry = CayenneLppParser.parse(lppData);
|
||||||
debugPrint(' ✅ Parsed new telemetry');
|
debugPrint(' ✅ Parsed new telemetry');
|
||||||
debugPrint(' New telemetry timestamp: ${telemetry.timestamp}');
|
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
|
// Update contact with new telemetry AND last seen time
|
||||||
// lastAdvert is Unix timestamp in seconds
|
// lastAdvert is Unix timestamp in seconds
|
||||||
final currentTimestamp = (DateTime.now().millisecondsSinceEpoch / 1000)
|
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)
|
/// Find contact by public key prefix (6 bytes)
|
||||||
Contact? _findContactByPrefix(Uint8List prefix) {
|
Contact? _findContactByPrefix(Uint8List prefix) {
|
||||||
if (prefix.length < 6) return null;
|
if (prefix.length < 6) return null;
|
||||||
|
|||||||
110
test/providers/contacts_provider_test.dart
Normal file
110
test/providers/contacts_provider_test.dart
Normal 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));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user