mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 08:20:36 +00:00
feat: Implement optimized contact fetching by public key to enhance performance
This commit is contained in:
@@ -236,11 +236,12 @@ class AppProvider with ChangeNotifier {
|
|||||||
// When a contact's routing path is updated in the mesh network
|
// When a contact's routing path is updated in the mesh network
|
||||||
connectionProvider.onPathUpdated = (publicKey) {
|
connectionProvider.onPathUpdated = (publicKey) {
|
||||||
debugPrint('🔄 [AppProvider] Path updated for contact: ${publicKey.sublist(0, 6).map((b) => b.toRadixString(16).padLeft(2, '0')).join(':')}...');
|
debugPrint('🔄 [AppProvider] Path updated for contact: ${publicKey.sublist(0, 6).map((b) => b.toRadixString(16).padLeft(2, '0')).join(':')}...');
|
||||||
// Trigger a contact sync to get the updated path information
|
// Trigger a single contact fetch to get the updated path information
|
||||||
|
// This is much more efficient than fetching all contacts
|
||||||
// This happens asynchronously to avoid blocking the event handler
|
// This happens asynchronously to avoid blocking the event handler
|
||||||
Future.delayed(const Duration(milliseconds: 100), () {
|
Future.delayed(const Duration(milliseconds: 100), () {
|
||||||
if (connectionProvider.deviceInfo.isConnected) {
|
if (connectionProvider.deviceInfo.isConnected) {
|
||||||
connectionProvider.getContacts();
|
connectionProvider.getContact(publicKey);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -252,11 +253,12 @@ class AppProvider with ChangeNotifier {
|
|||||||
// Check if this is an existing contact that might have updated location
|
// Check if this is an existing contact that might have updated location
|
||||||
final contact = contactsProvider.findContactByKey(publicKey);
|
final contact = contactsProvider.findContactByKey(publicKey);
|
||||||
if (contact != null) {
|
if (contact != null) {
|
||||||
debugPrint(' Existing contact "${contact.advName}" - triggering contact sync for updates');
|
debugPrint(' Existing contact "${contact.advName}" - fetching updated contact info (optimized)');
|
||||||
// Trigger a contact sync to get the updated contact information
|
// Trigger a single contact fetch to get the updated contact information
|
||||||
|
// This is much more efficient than fetching all contacts
|
||||||
Future.delayed(const Duration(milliseconds: 100), () {
|
Future.delayed(const Duration(milliseconds: 100), () {
|
||||||
if (connectionProvider.deviceInfo.isConnected) {
|
if (connectionProvider.deviceInfo.isConnected) {
|
||||||
connectionProvider.getContacts();
|
connectionProvider.getContact(publicKey);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -686,6 +686,30 @@ class ConnectionProvider with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a single contact by public key from device
|
||||||
|
///
|
||||||
|
/// This is more efficient than getContacts() when you only need to refresh
|
||||||
|
/// one specific contact (e.g., after receiving an advertisement or path update).
|
||||||
|
///
|
||||||
|
/// The contact will be delivered via the onContactReceived callback.
|
||||||
|
Future<void> getContact(Uint8List publicKey) async {
|
||||||
|
if (!_bleService.isConnected) {
|
||||||
|
_error = 'Not connected to device';
|
||||||
|
notifyListeners();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await _bleService.getContactByKey(publicKey);
|
||||||
|
} catch (e) {
|
||||||
|
_error = 'Failed to get contact: $e';
|
||||||
|
debugPrint('⚠️ [Provider] Failed to get contact by key, falling back to full contact sync');
|
||||||
|
// Fallback to full contact sync if command not supported
|
||||||
|
await _bleService.getContacts();
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Sync all channels from device
|
/// Sync all channels from device
|
||||||
Future<void> syncChannels({int? maxChannels}) async {
|
Future<void> syncChannels({int? maxChannels}) async {
|
||||||
if (!_bleService.isConnected) {
|
if (!_bleService.isConnected) {
|
||||||
|
|||||||
@@ -311,6 +311,20 @@ class MeshCoreBleService {
|
|||||||
await _commandSender.writeData(FrameBuilder.buildGetContacts());
|
await _commandSender.writeData(FrameBuilder.buildGetContacts());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a single contact by public key from device
|
||||||
|
///
|
||||||
|
/// This is more efficient than getContacts() when you only need to refresh
|
||||||
|
/// one specific contact (e.g., after receiving an advertisement).
|
||||||
|
///
|
||||||
|
/// The contact will be delivered via the onContactReceived callback.
|
||||||
|
Future<void> getContactByKey(Uint8List publicKey) async {
|
||||||
|
debugPrint('🔍 [BLE] Requesting single contact by key:');
|
||||||
|
debugPrint(
|
||||||
|
' Public key prefix: ${publicKey.sublist(0, 6).map((b) => b.toRadixString(16).padLeft(2, '0')).join(':')}...',
|
||||||
|
);
|
||||||
|
await _commandSender.writeData(FrameBuilder.buildGetContactByKey(publicKey));
|
||||||
|
}
|
||||||
|
|
||||||
/// Manually add or update a contact on the companion radio
|
/// Manually add or update a contact on the companion radio
|
||||||
Future<void> addOrUpdateContact(Contact contact) async {
|
Future<void> addOrUpdateContact(Contact contact) async {
|
||||||
debugPrint('📝 [BLE] Adding/updating contact on companion radio:');
|
debugPrint('📝 [BLE] Adding/updating contact on companion radio:');
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ class MeshCoreConstants {
|
|||||||
static const int cmdSendRawData = 25;
|
static const int cmdSendRawData = 25;
|
||||||
static const int cmdSendLogin = 26;
|
static const int cmdSendLogin = 26;
|
||||||
static const int cmdSendStatusReq = 27;
|
static const int cmdSendStatusReq = 27;
|
||||||
|
static const int cmdGetContactByKey = 30;
|
||||||
static const int cmdGetChannel = 31;
|
static const int cmdGetChannel = 31;
|
||||||
static const int cmdSetChannel = 32;
|
static const int cmdSetChannel = 32;
|
||||||
static const int cmdSignStart = 33;
|
static const int cmdSignStart = 33;
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ class MeshCoreOpcodeNames {
|
|||||||
return 'SEND_LOGIN';
|
return 'SEND_LOGIN';
|
||||||
case MeshCoreConstants.cmdSendStatusReq:
|
case MeshCoreConstants.cmdSendStatusReq:
|
||||||
return 'SEND_STATUS_REQ';
|
return 'SEND_STATUS_REQ';
|
||||||
|
case MeshCoreConstants.cmdGetContactByKey:
|
||||||
|
return 'GET_CONTACT_BY_KEY';
|
||||||
case MeshCoreConstants.cmdGetChannel:
|
case MeshCoreConstants.cmdGetChannel:
|
||||||
return 'GET_CHANNEL';
|
return 'GET_CHANNEL';
|
||||||
case MeshCoreConstants.cmdSetChannel:
|
case MeshCoreConstants.cmdSetChannel:
|
||||||
|
|||||||
@@ -31,6 +31,14 @@ class FrameBuilder {
|
|||||||
return writer.toBytes();
|
return writer.toBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Build GetContactByKey command - retrieves a single contact by public key
|
||||||
|
static Uint8List buildGetContactByKey(Uint8List publicKey) {
|
||||||
|
final writer = BufferWriter();
|
||||||
|
writer.writeByte(MeshCoreConstants.cmdGetContactByKey); // 0x1E (30)
|
||||||
|
writer.writeBytes(publicKey); // 32 bytes
|
||||||
|
return writer.toBytes();
|
||||||
|
}
|
||||||
|
|
||||||
/// Build AddUpdateContact command
|
/// Build AddUpdateContact command
|
||||||
static Uint8List buildAddUpdateContact(Contact contact) {
|
static Uint8List buildAddUpdateContact(Contact contact) {
|
||||||
final writer = BufferWriter();
|
final writer = BufferWriter();
|
||||||
|
|||||||
Reference in New Issue
Block a user