mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
Preserve contact telemetry data
This commit is contained in:
@@ -283,62 +283,16 @@ class ContactsProvider with ChangeNotifier {
|
||||
}
|
||||
|
||||
// Check if this is a new contact
|
||||
final isNewContact = !_contacts.containsKey(contact.publicKeyHex);
|
||||
final existingContact = _contacts[contact.publicKeyHex];
|
||||
final isNewContact = existingContact == null;
|
||||
debugPrint(
|
||||
' isNew: $isNewContact, total contacts before: ${_contacts.length}',
|
||||
);
|
||||
|
||||
Contact updatedContact;
|
||||
if (isNewContact) {
|
||||
// New contact - add initial location to history if available
|
||||
updatedContact = contact.copyWith(isNew: true);
|
||||
if (contact.advertLocation != null) {
|
||||
final timestamp = DateTime.fromMillisecondsSinceEpoch(
|
||||
contact.lastAdvert * 1000,
|
||||
);
|
||||
updatedContact = updatedContact.addAdvertLocation(
|
||||
contact.advertLocation!,
|
||||
timestamp,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Existing contact - preserve history and isNew status
|
||||
final existingContact = _contacts[contact.publicKeyHex]!;
|
||||
final mergedTelemetry = _mergeTelemetryForContact(
|
||||
existingTelemetry: existingContact.telemetry,
|
||||
incomingTelemetry: contact.telemetry,
|
||||
);
|
||||
final incomingAdvertLocation = contact.advertLocation;
|
||||
final existingAdvertLocation = existingContact.advertLocation;
|
||||
|
||||
// Start with existing contact
|
||||
updatedContact = contact.copyWith(
|
||||
isNew: existingContact.isNew,
|
||||
advertHistory: existingContact.advertHistory,
|
||||
telemetry: mergedTelemetry,
|
||||
advLat: incomingAdvertLocation != null
|
||||
? contact.advLat
|
||||
: existingAdvertLocation != null
|
||||
? existingContact.advLat
|
||||
: contact.advLat,
|
||||
advLon: incomingAdvertLocation != null
|
||||
? contact.advLon
|
||||
: existingAdvertLocation != null
|
||||
? existingContact.advLon
|
||||
: contact.advLon,
|
||||
);
|
||||
|
||||
// Add new location to history if location has changed
|
||||
if (contact.advertLocation != null) {
|
||||
final timestamp = DateTime.fromMillisecondsSinceEpoch(
|
||||
contact.lastAdvert * 1000,
|
||||
);
|
||||
updatedContact = updatedContact.addAdvertLocation(
|
||||
contact.advertLocation!,
|
||||
timestamp,
|
||||
);
|
||||
}
|
||||
}
|
||||
final updatedContact = _mergeIncomingContact(
|
||||
incomingContact: contact,
|
||||
existingContact: existingContact,
|
||||
);
|
||||
|
||||
_contacts[contact.publicKeyHex] = updatedContact;
|
||||
_pendingAdverts.remove(contact.publicKeyHex);
|
||||
@@ -364,7 +318,11 @@ class ContactsProvider with ChangeNotifier {
|
||||
excluded++;
|
||||
continue;
|
||||
}
|
||||
_contacts[contact.publicKeyHex] = contact;
|
||||
final existingContact = _contacts[contact.publicKeyHex];
|
||||
_contacts[contact.publicKeyHex] = _mergeIncomingContact(
|
||||
incomingContact: contact,
|
||||
existingContact: existingContact,
|
||||
);
|
||||
_pendingAdverts.remove(contact.publicKeyHex);
|
||||
}
|
||||
if (excluded > 0) {
|
||||
@@ -376,6 +334,60 @@ class ContactsProvider with ChangeNotifier {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Contact _mergeIncomingContact({
|
||||
required Contact incomingContact,
|
||||
Contact? existingContact,
|
||||
}) {
|
||||
if (existingContact == null) {
|
||||
var newContact = incomingContact.copyWith(isNew: true);
|
||||
if (incomingContact.advertLocation != null) {
|
||||
final timestamp = DateTime.fromMillisecondsSinceEpoch(
|
||||
incomingContact.lastAdvert * 1000,
|
||||
);
|
||||
newContact = newContact.addAdvertLocation(
|
||||
incomingContact.advertLocation!,
|
||||
timestamp,
|
||||
);
|
||||
}
|
||||
return newContact;
|
||||
}
|
||||
|
||||
final mergedTelemetry = _mergeTelemetryForContact(
|
||||
existingTelemetry: existingContact.telemetry,
|
||||
incomingTelemetry: incomingContact.telemetry,
|
||||
);
|
||||
final incomingAdvertLocation = incomingContact.advertLocation;
|
||||
final existingAdvertLocation = existingContact.advertLocation;
|
||||
|
||||
var updatedContact = incomingContact.copyWith(
|
||||
isNew: existingContact.isNew,
|
||||
advertHistory: existingContact.advertHistory,
|
||||
telemetry: mergedTelemetry,
|
||||
advLat: incomingAdvertLocation != null
|
||||
? incomingContact.advLat
|
||||
: existingAdvertLocation != null
|
||||
? existingContact.advLat
|
||||
: incomingContact.advLat,
|
||||
advLon: incomingAdvertLocation != null
|
||||
? incomingContact.advLon
|
||||
: existingAdvertLocation != null
|
||||
? existingContact.advLon
|
||||
: incomingContact.advLon,
|
||||
);
|
||||
|
||||
if (incomingAdvertLocation != null) {
|
||||
final timestamp = DateTime.fromMillisecondsSinceEpoch(
|
||||
incomingContact.lastAdvert * 1000,
|
||||
);
|
||||
updatedContact = updatedContact.addAdvertLocation(
|
||||
incomingAdvertLocation,
|
||||
timestamp,
|
||||
);
|
||||
}
|
||||
|
||||
return updatedContact;
|
||||
}
|
||||
|
||||
/// Update contact telemetry
|
||||
void updateTelemetry(Uint8List publicKeyPrefix, Uint8List lppData) {
|
||||
debugPrint('📊 [ContactsProvider] updateTelemetry() called');
|
||||
@@ -541,6 +553,8 @@ class ContactsProvider with ChangeNotifier {
|
||||
return existingTelemetry;
|
||||
}
|
||||
|
||||
// Telemetry packets and contact refreshes are often sparse. Preserve the
|
||||
// last known reading for any field that is omitted in the incoming update.
|
||||
final incomingGps = _getValidGpsOrNull(incomingTelemetry.gpsLocation);
|
||||
final previousGps = _getValidGpsOrNull(existingTelemetry?.gpsLocation);
|
||||
final mergedExtraSensorData = <String, dynamic>{
|
||||
|
||||
@@ -220,35 +220,48 @@ class SensorsProvider with ChangeNotifier {
|
||||
|
||||
try {
|
||||
for (final key in _watchedSensorKeys) {
|
||||
Contact? contact;
|
||||
for (final entry in contactsProvider.contacts) {
|
||||
if (entry.publicKeyHex == key) {
|
||||
contact = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (contact == null) {
|
||||
_refreshStates[key] = SensorRefreshState.unavailable;
|
||||
notifyListeners();
|
||||
continue;
|
||||
}
|
||||
|
||||
_refreshStates[key] = SensorRefreshState.refreshing;
|
||||
notifyListeners();
|
||||
|
||||
final result = await connectionProvider.smartPing(
|
||||
contactPublicKey: contact.publicKey,
|
||||
hasPath: contact.hasPath,
|
||||
await refreshSensor(
|
||||
publicKeyHex: key,
|
||||
contactsProvider: contactsProvider,
|
||||
connectionProvider: connectionProvider,
|
||||
);
|
||||
|
||||
_refreshStates[key] = result.success
|
||||
? SensorRefreshState.success
|
||||
: SensorRefreshState.timeout;
|
||||
notifyListeners();
|
||||
}
|
||||
} finally {
|
||||
_isRefreshingAll = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> refreshSensor({
|
||||
required String publicKeyHex,
|
||||
required ContactsProvider contactsProvider,
|
||||
required ConnectionProvider connectionProvider,
|
||||
}) async {
|
||||
Contact? contact;
|
||||
for (final entry in contactsProvider.contacts) {
|
||||
if (entry.publicKeyHex == publicKeyHex) {
|
||||
contact = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (contact == null) {
|
||||
_refreshStates[publicKeyHex] = SensorRefreshState.unavailable;
|
||||
notifyListeners();
|
||||
return;
|
||||
}
|
||||
|
||||
_refreshStates[publicKeyHex] = SensorRefreshState.refreshing;
|
||||
notifyListeners();
|
||||
|
||||
final result = await connectionProvider.smartPing(
|
||||
contactPublicKey: contact.publicKey,
|
||||
hasPath: contact.hasPath,
|
||||
);
|
||||
|
||||
_refreshStates[publicKeyHex] = result.success
|
||||
? SensorRefreshState.success
|
||||
: SensorRefreshState.timeout;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user