mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
Retain rx path for adverts
This commit is contained in:
@@ -10,8 +10,15 @@ import '../utils/key_comparison.dart';
|
||||
class PendingAdvert {
|
||||
final Uint8List publicKey;
|
||||
final DateTime receivedAt;
|
||||
final int? signedEncodedPathLen;
|
||||
final Uint8List? paddedPathBytes;
|
||||
|
||||
const PendingAdvert({required this.publicKey, required this.receivedAt});
|
||||
const PendingAdvert({
|
||||
required this.publicKey,
|
||||
required this.receivedAt,
|
||||
this.signedEncodedPathLen,
|
||||
this.paddedPathBytes,
|
||||
});
|
||||
|
||||
String get publicKeyHex =>
|
||||
publicKey.map((b) => b.toRadixString(16).padLeft(2, '0')).join('');
|
||||
@@ -21,14 +28,31 @@ class PendingAdvert {
|
||||
return prefix.map((b) => b.toRadixString(16).padLeft(2, '0')).join(':');
|
||||
}
|
||||
|
||||
PendingAdvert copyWith({Uint8List? publicKey, DateTime? receivedAt}) {
|
||||
PendingAdvert copyWith({
|
||||
Uint8List? publicKey,
|
||||
DateTime? receivedAt,
|
||||
int? signedEncodedPathLen,
|
||||
Uint8List? paddedPathBytes,
|
||||
}) {
|
||||
return PendingAdvert(
|
||||
publicKey: publicKey ?? this.publicKey,
|
||||
receivedAt: receivedAt ?? this.receivedAt,
|
||||
signedEncodedPathLen: signedEncodedPathLen ?? this.signedEncodedPathLen,
|
||||
paddedPathBytes: paddedPathBytes ?? this.paddedPathBytes,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _RetainedRoute {
|
||||
final int signedEncodedPathLen;
|
||||
final Uint8List paddedPathBytes;
|
||||
|
||||
const _RetainedRoute({
|
||||
required this.signedEncodedPathLen,
|
||||
required this.paddedPathBytes,
|
||||
});
|
||||
}
|
||||
|
||||
/// Contacts Provider - manages contact list and telemetry
|
||||
class ContactsProvider with ChangeNotifier {
|
||||
final Map<String, Contact> _contacts = {};
|
||||
@@ -338,8 +362,19 @@ class ContactsProvider with ChangeNotifier {
|
||||
required Contact incomingContact,
|
||||
Contact? existingContact,
|
||||
}) {
|
||||
final retainedRoute = _retainedRouteForContact(
|
||||
keyHex: incomingContact.publicKeyHex,
|
||||
incomingContact: incomingContact,
|
||||
existingContact: existingContact,
|
||||
);
|
||||
|
||||
if (existingContact == null) {
|
||||
var newContact = incomingContact.copyWith(isNew: true);
|
||||
var newContact = incomingContact.copyWith(
|
||||
isNew: true,
|
||||
outPathLen:
|
||||
retainedRoute?.signedEncodedPathLen ?? incomingContact.outPathLen,
|
||||
outPath: retainedRoute?.paddedPathBytes ?? incomingContact.outPath,
|
||||
);
|
||||
if (incomingContact.advertLocation != null) {
|
||||
final timestamp = DateTime.fromMillisecondsSinceEpoch(
|
||||
incomingContact.lastAdvert * 1000,
|
||||
@@ -363,6 +398,9 @@ class ContactsProvider with ChangeNotifier {
|
||||
isNew: existingContact.isNew,
|
||||
advertHistory: existingContact.advertHistory,
|
||||
telemetry: mergedTelemetry,
|
||||
outPathLen:
|
||||
retainedRoute?.signedEncodedPathLen ?? incomingContact.outPathLen,
|
||||
outPath: retainedRoute?.paddedPathBytes ?? incomingContact.outPath,
|
||||
advLat: incomingAdvertLocation != null
|
||||
? incomingContact.advLat
|
||||
: existingAdvertLocation != null
|
||||
@@ -388,6 +426,37 @@ class ContactsProvider with ChangeNotifier {
|
||||
return updatedContact;
|
||||
}
|
||||
|
||||
_RetainedRoute? _retainedRouteForContact({
|
||||
required String keyHex,
|
||||
required Contact incomingContact,
|
||||
required Contact? existingContact,
|
||||
}) {
|
||||
if (incomingContact.routeHasPath) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final pendingAdvert = _pendingAdverts[keyHex];
|
||||
final pendingPathBytes = pendingAdvert?.paddedPathBytes;
|
||||
final pendingPathLen = pendingAdvert?.signedEncodedPathLen;
|
||||
if (pendingPathLen != null &&
|
||||
pendingPathBytes != null &&
|
||||
pendingPathBytes.isNotEmpty) {
|
||||
return _RetainedRoute(
|
||||
signedEncodedPathLen: pendingPathLen,
|
||||
paddedPathBytes: Uint8List.fromList(pendingPathBytes),
|
||||
);
|
||||
}
|
||||
|
||||
if (existingContact != null && existingContact.routeHasPath) {
|
||||
return _RetainedRoute(
|
||||
signedEncodedPathLen: existingContact.outPathLen,
|
||||
paddedPathBytes: Uint8List.fromList(existingContact.outPath),
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Update contact telemetry
|
||||
void updateTelemetry(Uint8List publicKeyPrefix, Uint8List lppData) {
|
||||
debugPrint('📊 [ContactsProvider] updateTelemetry() called');
|
||||
@@ -660,6 +729,46 @@ class ContactsProvider with ChangeNotifier {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void retainReceivedRoute(
|
||||
Uint8List publicKey, {
|
||||
required int signedEncodedPathLen,
|
||||
required Uint8List paddedPathBytes,
|
||||
Uint8List? devicePublicKey,
|
||||
}) {
|
||||
if (devicePublicKey != null && publicKey.matches(devicePublicKey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final keyHex = publicKey
|
||||
.map((b) => b.toRadixString(16).padLeft(2, '0'))
|
||||
.join('');
|
||||
final contact = _contacts[keyHex];
|
||||
if (contact != null) {
|
||||
_contacts[keyHex] = contact.copyWith(
|
||||
outPathLen: signedEncodedPathLen,
|
||||
outPath: Uint8List.fromList(paddedPathBytes),
|
||||
);
|
||||
_persistContacts();
|
||||
notifyListeners();
|
||||
return;
|
||||
}
|
||||
|
||||
final now = DateTime.now();
|
||||
final existing = _pendingAdverts[keyHex];
|
||||
_pendingAdverts[keyHex] =
|
||||
(existing ??
|
||||
PendingAdvert(
|
||||
publicKey: Uint8List.fromList(publicKey),
|
||||
receivedAt: now,
|
||||
))
|
||||
.copyWith(
|
||||
receivedAt: now,
|
||||
signedEncodedPathLen: signedEncodedPathLen,
|
||||
paddedPathBytes: Uint8List.fromList(paddedPathBytes),
|
||||
);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void resetContactRouteLocal(Uint8List publicKey) {
|
||||
final contact = findContactByKey(publicKey);
|
||||
if (contact == null) {
|
||||
|
||||
Reference in New Issue
Block a user