mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-07-12 03:27:06 +10:00
fix double entry due to mixed 1byte and 2byte paths
This commit is contained in:
@@ -49,14 +49,16 @@ import 'meshcore_protocol.dart';
|
|||||||
|
|
||||||
class DirectRepeater {
|
class DirectRepeater {
|
||||||
static const int maxAgeMinutes = 30; // Max age for direct repeater info
|
static const int maxAgeMinutes = 30; // Max age for direct repeater info
|
||||||
final List<int> pubkeyPrefix;
|
List<int> pubkeyPrefix;
|
||||||
final int pathHashWidth;
|
int pathHashWidth;
|
||||||
|
String? contactKeyHex;
|
||||||
double snr;
|
double snr;
|
||||||
DateTime lastUpdated;
|
DateTime lastUpdated;
|
||||||
|
|
||||||
DirectRepeater({
|
DirectRepeater({
|
||||||
required List<int> pubkeyPrefix,
|
required List<int> pubkeyPrefix,
|
||||||
required this.pathHashWidth,
|
required this.pathHashWidth,
|
||||||
|
this.contactKeyHex,
|
||||||
required this.snr,
|
required this.snr,
|
||||||
DateTime? lastUpdated,
|
DateTime? lastUpdated,
|
||||||
}) : pubkeyPrefix = List.unmodifiable(pubkeyPrefix),
|
}) : pubkeyPrefix = List.unmodifiable(pubkeyPrefix),
|
||||||
@@ -79,8 +81,21 @@ class DirectRepeater {
|
|||||||
return listEquals(pubkeyPrefix, pathBytes.sublist(0, width));
|
return listEquals(pubkeyPrefix, pathBytes.sublist(0, width));
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(double newSNR) {
|
void update(
|
||||||
|
double newSNR, {
|
||||||
|
List<int>? pubkeyPrefix,
|
||||||
|
int? pathHashWidth,
|
||||||
|
String? contactKeyHex,
|
||||||
|
}) {
|
||||||
snr = newSNR;
|
snr = newSNR;
|
||||||
|
if (pubkeyPrefix != null &&
|
||||||
|
pubkeyPrefix.length >= this.pubkeyPrefix.length) {
|
||||||
|
this.pubkeyPrefix = List.unmodifiable(pubkeyPrefix);
|
||||||
|
}
|
||||||
|
if (pathHashWidth != null && pathHashWidth >= this.pathHashWidth) {
|
||||||
|
this.pathHashWidth = pathHashWidth;
|
||||||
|
}
|
||||||
|
this.contactKeyHex ??= contactKeyHex;
|
||||||
lastUpdated = DateTime.now();
|
lastUpdated = DateTime.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6239,6 +6254,25 @@ class MeshCoreConnector extends ChangeNotifier {
|
|||||||
0,
|
0,
|
||||||
math.min(hashWidth, contact.publicKey.length),
|
math.min(hashWidth, contact.publicKey.length),
|
||||||
);
|
);
|
||||||
|
final contactKeyHex = _resolveDirectRepeaterContactKeyHex(
|
||||||
|
contact,
|
||||||
|
pubkeyPrefix,
|
||||||
|
path.isEmpty,
|
||||||
|
);
|
||||||
|
final knownRepeaters = contactKeyHex == null
|
||||||
|
? _directRepeaters
|
||||||
|
.where(
|
||||||
|
(r) =>
|
||||||
|
r.contactKeyHex != null &&
|
||||||
|
_contactKeyMatchesPrefix(r.contactKeyHex!, pubkeyPrefix),
|
||||||
|
)
|
||||||
|
.toList()
|
||||||
|
: const <DirectRepeater>[];
|
||||||
|
final knownRepeater = knownRepeaters.length == 1
|
||||||
|
? knownRepeaters.first
|
||||||
|
: null;
|
||||||
|
final effectiveContactKeyHex =
|
||||||
|
contactKeyHex ?? knownRepeater?.contactKeyHex;
|
||||||
|
|
||||||
_directRepeaters.removeWhere((r) => r.isStale());
|
_directRepeaters.removeWhere((r) => r.isStale());
|
||||||
|
|
||||||
@@ -6249,9 +6283,25 @@ class MeshCoreConnector extends ChangeNotifier {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final isTracked = _directRepeaters.where(
|
final isTracked = _directRepeaters.where((r) {
|
||||||
(r) => r.pathHashWidth == hashWidth && r.matchesPrefix(pubkeyPrefix),
|
if (knownRepeater != null) {
|
||||||
);
|
return identical(r, knownRepeater);
|
||||||
|
}
|
||||||
|
if (effectiveContactKeyHex != null) {
|
||||||
|
return r.contactKeyHex == effectiveContactKeyHex ||
|
||||||
|
(r.contactKeyHex == null &&
|
||||||
|
_contactKeyMatchesPrefix(
|
||||||
|
effectiveContactKeyHex,
|
||||||
|
r.pubkeyPrefix,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if (r.contactKeyHex == null &&
|
||||||
|
r.pathHashWidth == hashWidth &&
|
||||||
|
r.matchesPrefix(pubkeyPrefix)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}).toList();
|
||||||
|
|
||||||
final sortedRepeaters = List<DirectRepeater>.from(_directRepeaters)
|
final sortedRepeaters = List<DirectRepeater>.from(_directRepeaters)
|
||||||
..sort((a, b) => b.snr.compareTo(a.snr));
|
..sort((a, b) => b.snr.compareTo(a.snr));
|
||||||
@@ -6267,12 +6317,30 @@ class MeshCoreConnector extends ChangeNotifier {
|
|||||||
|
|
||||||
if (isTracked.isNotEmpty) {
|
if (isTracked.isNotEmpty) {
|
||||||
final repeater = isTracked.first;
|
final repeater = isTracked.first;
|
||||||
repeater.update(snr);
|
repeater.update(
|
||||||
|
snr,
|
||||||
|
pubkeyPrefix: pubkeyPrefix,
|
||||||
|
pathHashWidth: hashWidth,
|
||||||
|
contactKeyHex: effectiveContactKeyHex,
|
||||||
|
);
|
||||||
|
if (effectiveContactKeyHex != null) {
|
||||||
|
_directRepeaters.removeWhere(
|
||||||
|
(r) =>
|
||||||
|
!identical(r, repeater) &&
|
||||||
|
(r.contactKeyHex == effectiveContactKeyHex ||
|
||||||
|
(r.contactKeyHex == null &&
|
||||||
|
_contactKeyMatchesPrefix(
|
||||||
|
effectiveContactKeyHex,
|
||||||
|
r.pubkeyPrefix,
|
||||||
|
))),
|
||||||
|
);
|
||||||
|
}
|
||||||
} else if (_directRepeaters.length < 5) {
|
} else if (_directRepeaters.length < 5) {
|
||||||
_directRepeaters.add(
|
_directRepeaters.add(
|
||||||
DirectRepeater(
|
DirectRepeater(
|
||||||
pubkeyPrefix: pubkeyPrefix,
|
pubkeyPrefix: pubkeyPrefix,
|
||||||
pathHashWidth: hashWidth,
|
pathHashWidth: hashWidth,
|
||||||
|
contactKeyHex: effectiveContactKeyHex,
|
||||||
snr: snr,
|
snr: snr,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -6280,6 +6348,37 @@ class MeshCoreConnector extends ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String? _resolveDirectRepeaterContactKeyHex(
|
||||||
|
Contact contact,
|
||||||
|
List<int> pubkeyPrefix,
|
||||||
|
bool pathIsEmpty,
|
||||||
|
) {
|
||||||
|
if (pathIsEmpty &&
|
||||||
|
(contact.type == advTypeRepeater || contact.type == advTypeRoom)) {
|
||||||
|
return contact.publicKeyHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
final prefixMatches = allContacts
|
||||||
|
.where(
|
||||||
|
(c) =>
|
||||||
|
(c.type == advTypeRepeater || c.type == advTypeRoom) &&
|
||||||
|
_contactKeyMatchesPrefix(c.publicKeyHex, pubkeyPrefix),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
if (prefixMatches.length == 1) {
|
||||||
|
return prefixMatches.first.publicKeyHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _contactKeyMatchesPrefix(String contactKeyHex, List<int> pubkeyPrefix) {
|
||||||
|
final prefixHex = pubkeyPrefix
|
||||||
|
.map((b) => b.toRadixString(16).padLeft(2, '0'))
|
||||||
|
.join();
|
||||||
|
return contactKeyHex.startsWith(prefixHex);
|
||||||
|
}
|
||||||
|
|
||||||
void _handleAutoAddConfig(Uint8List frame) {
|
void _handleAutoAddConfig(Uint8List frame) {
|
||||||
final reader = BufferReader(frame);
|
final reader = BufferReader(frame);
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -12,9 +12,18 @@ import 'signal_ui.dart';
|
|||||||
Contact? _getRepeaterPrefixMatchNearLocation(
|
Contact? _getRepeaterPrefixMatchNearLocation(
|
||||||
List<Contact> contacts,
|
List<Contact> contacts,
|
||||||
List<int> pubkeyPrefix, {
|
List<int> pubkeyPrefix, {
|
||||||
|
String? contactKeyHex,
|
||||||
LatLng? searchPoint,
|
LatLng? searchPoint,
|
||||||
bool preferFavorites = false,
|
bool preferFavorites = false,
|
||||||
}) {
|
}) {
|
||||||
|
if (contactKeyHex != null) {
|
||||||
|
for (final c in contacts) {
|
||||||
|
if (c.publicKeyHex == contactKeyHex) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final candidates = contacts
|
final candidates = contacts
|
||||||
.where(
|
.where(
|
||||||
(c) =>
|
(c) =>
|
||||||
@@ -242,6 +251,7 @@ class _SNRIndicatorState extends State<SNRIndicator> {
|
|||||||
final contact = _getRepeaterPrefixMatchNearLocation(
|
final contact = _getRepeaterPrefixMatchNearLocation(
|
||||||
allContacts,
|
allContacts,
|
||||||
repeater.pubkeyPrefix,
|
repeater.pubkeyPrefix,
|
||||||
|
contactKeyHex: repeater.contactKeyHex,
|
||||||
searchPoint: selfPoint,
|
searchPoint: selfPoint,
|
||||||
preferFavorites: true,
|
preferFavorites: true,
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user