mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
Refactor logging to use debugPrint for better performance in debug mode
- Updated all print statements in services and widgets to use debugPrint. - This change improves logging performance and ensures that debug messages are only shown in debug builds. - Removed unnecessary transitive dependencies from pubspec.lock. - Cleaned up pubspec.yaml by removing integration_test from dev_dependencies.
This commit is contained in:
@@ -146,7 +146,7 @@ class ConnectionProvider with ChangeNotifier {
|
||||
|
||||
void _initializeBleService() {
|
||||
_bleService.onConnectionStateChanged = (isConnected) {
|
||||
print('🔔 [Provider] Connection state callback fired: $isConnected');
|
||||
debugPrint('🔔 [Provider] Connection state callback fired: $isConnected');
|
||||
_deviceInfo = _deviceInfo.copyWith(
|
||||
connectionState: isConnected
|
||||
? ConnectionState.connected
|
||||
@@ -155,37 +155,37 @@ class ConnectionProvider with ChangeNotifier {
|
||||
: ConnectionState.disconnected),
|
||||
lastUpdate: DateTime.now(),
|
||||
);
|
||||
print(
|
||||
debugPrint(
|
||||
' Updated deviceInfo.connectionState: ${_deviceInfo.connectionState}',
|
||||
);
|
||||
print(' Updated deviceInfo.isConnected: ${_deviceInfo.isConnected}');
|
||||
print(' isReconnecting: ${_bleService.isReconnecting}');
|
||||
debugPrint(' Updated deviceInfo.isConnected: ${_deviceInfo.isConnected}');
|
||||
debugPrint(' isReconnecting: ${_bleService.isReconnecting}');
|
||||
notifyListeners();
|
||||
print(' Notified listeners');
|
||||
debugPrint(' Notified listeners');
|
||||
};
|
||||
|
||||
_bleService.onReconnectionAttempt = (attemptNumber, maxAttempts) {
|
||||
print('🔄 [Provider] Reconnection attempt $attemptNumber/$maxAttempts');
|
||||
debugPrint('🔄 [Provider] Reconnection attempt $attemptNumber/$maxAttempts');
|
||||
// Notify UI to update reconnection status display
|
||||
notifyListeners();
|
||||
};
|
||||
|
||||
_bleService.onError = (error, {int? errorCode}) {
|
||||
print('⚠️ [Provider] BLE error received: $error');
|
||||
print(' Error code: ${errorCode ?? "none"}');
|
||||
print(' Current connection state: ${_deviceInfo.connectionState}');
|
||||
debugPrint('⚠️ [Provider] BLE error received: $error');
|
||||
debugPrint(' Error code: ${errorCode ?? "none"}');
|
||||
debugPrint(' Current connection state: ${_deviceInfo.connectionState}');
|
||||
|
||||
_error = error;
|
||||
|
||||
// Only set connection state to error if we're not already connected
|
||||
// Data parsing errors after connection shouldn't disconnect us
|
||||
if (_deviceInfo.connectionState != ConnectionState.connected) {
|
||||
print(' Setting connection state to error');
|
||||
debugPrint(' Setting connection state to error');
|
||||
_deviceInfo = _deviceInfo.copyWith(
|
||||
connectionState: ConnectionState.error,
|
||||
);
|
||||
} else {
|
||||
print(
|
||||
debugPrint(
|
||||
' Keeping connection state as connected (ignoring data parsing error)',
|
||||
);
|
||||
}
|
||||
@@ -194,10 +194,10 @@ class ConnectionProvider with ChangeNotifier {
|
||||
};
|
||||
|
||||
_bleService.onContactNotFound = (contactPublicKey) async {
|
||||
print('🔧 [Provider] Contact not found error detected - initiating auto-recovery');
|
||||
debugPrint('🔧 [Provider] Contact not found error detected - initiating auto-recovery');
|
||||
|
||||
if (contactPublicKey == null) {
|
||||
print(' ⚠️ No contact public key available for recovery');
|
||||
debugPrint(' ⚠️ No contact public key available for recovery');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -206,12 +206,12 @@ class ConnectionProvider with ChangeNotifier {
|
||||
final pendingOp = _pendingSendOperations[operationId];
|
||||
|
||||
if (pendingOp == null || pendingOp.contact == null) {
|
||||
print(' ⚠️ No pending operation found for recovery: $operationId');
|
||||
debugPrint(' ⚠️ No pending operation found for recovery: $operationId');
|
||||
return;
|
||||
}
|
||||
|
||||
print(' 📋 Found pending operation for: ${pendingOp.contact!.advName}');
|
||||
print(' 📤 Step 1: Adding contact to radio...');
|
||||
debugPrint(' 📋 Found pending operation for: ${pendingOp.contact!.advName}');
|
||||
debugPrint(' 📤 Step 1: Adding contact to radio...');
|
||||
|
||||
try {
|
||||
// Step 1: Add the contact to the radio
|
||||
@@ -220,8 +220,8 @@ class ConnectionProvider with ChangeNotifier {
|
||||
// Small delay to ensure contact is added before retrying
|
||||
await Future.delayed(const Duration(milliseconds: 300));
|
||||
|
||||
print(' ✅ Contact added successfully');
|
||||
print(' 🔄 Step 2: Retrying message send...');
|
||||
debugPrint(' ✅ Contact added successfully');
|
||||
debugPrint(' 🔄 Step 2: Retrying message send...');
|
||||
|
||||
// Step 2: Retry the send operation
|
||||
await _bleService.sendTextMessage(
|
||||
@@ -230,12 +230,12 @@ class ConnectionProvider with ChangeNotifier {
|
||||
attempt: pendingOp.retryAttempt,
|
||||
);
|
||||
|
||||
print(' ✅ Auto-recovery completed - message resent');
|
||||
debugPrint(' ✅ Auto-recovery completed - message resent');
|
||||
|
||||
// Clear pending operation after successful recovery
|
||||
_pendingSendOperations.remove(operationId);
|
||||
} catch (e) {
|
||||
print(' ❌ Auto-recovery failed: $e');
|
||||
debugPrint(' ❌ Auto-recovery failed: $e');
|
||||
_error = 'Auto-recovery failed: $e';
|
||||
notifyListeners();
|
||||
|
||||
@@ -269,12 +269,12 @@ class ConnectionProvider with ChangeNotifier {
|
||||
};
|
||||
|
||||
_bleService.onBinaryResponse = (publicKeyPrefix, tag, responseData) {
|
||||
print('📥 [Provider] Binary response received');
|
||||
print(
|
||||
debugPrint('📥 [Provider] Binary response received');
|
||||
debugPrint(
|
||||
' Public key prefix: ${publicKeyPrefix.map((b) => b.toRadixString(16).padLeft(2, '0')).join(':')}',
|
||||
);
|
||||
print(' Tag: $tag');
|
||||
print(' Response data: ${responseData.length} bytes');
|
||||
debugPrint(' Tag: $tag');
|
||||
debugPrint(' Response data: ${responseData.length} bytes');
|
||||
// Mark ping as successful if this was a ping request
|
||||
// Binary responses can also be telemetry responses (newer firmware)
|
||||
_pingTracker.markPingSuccessful(publicKeyPrefix);
|
||||
@@ -282,12 +282,12 @@ class ConnectionProvider with ChangeNotifier {
|
||||
};
|
||||
|
||||
_bleService.onNoMoreMessages = () {
|
||||
print('📥 [Provider] Received NoMoreMessages signal');
|
||||
debugPrint('📥 [Provider] Received NoMoreMessages signal');
|
||||
_noMoreMessages = true;
|
||||
};
|
||||
|
||||
_bleService.onMessageWaiting = () {
|
||||
print(
|
||||
debugPrint(
|
||||
'📥 [Provider] PUSH_CODE_MSG_WAITING received - auto-fetching messages via event',
|
||||
);
|
||||
// Automatically fetch messages when push notification received
|
||||
@@ -297,11 +297,11 @@ class ConnectionProvider with ChangeNotifier {
|
||||
|
||||
_bleService
|
||||
.onLoginSuccess = (publicKeyPrefix, permissions, isAdmin, tag) async {
|
||||
print('📥 [Provider] Login successful to room');
|
||||
print(
|
||||
debugPrint('📥 [Provider] Login successful to room');
|
||||
debugPrint(
|
||||
' Public key prefix: ${publicKeyPrefix.map((b) => b.toRadixString(16).padLeft(2, '0')).join(':')}',
|
||||
);
|
||||
print(' Permissions: $permissions, Admin: $isAdmin, Tag: $tag');
|
||||
debugPrint(' Permissions: $permissions, Admin: $isAdmin, Tag: $tag');
|
||||
|
||||
// Update room login state via helper
|
||||
await _roomLoginManager.handleLoginSuccess(
|
||||
@@ -316,8 +316,8 @@ class ConnectionProvider with ChangeNotifier {
|
||||
};
|
||||
|
||||
_bleService.onLoginFail = (publicKeyPrefix) {
|
||||
print('📥 [Provider] Login failed to room');
|
||||
print(
|
||||
debugPrint('📥 [Provider] Login failed to room');
|
||||
debugPrint(
|
||||
' Public key prefix: ${publicKeyPrefix.map((b) => b.toRadixString(16).padLeft(2, '0')).join(':')}',
|
||||
);
|
||||
|
||||
@@ -329,11 +329,11 @@ class ConnectionProvider with ChangeNotifier {
|
||||
};
|
||||
|
||||
_bleService.onAdvertReceived = (publicKey) {
|
||||
print('📥 [Provider] Advert received from node');
|
||||
print(
|
||||
debugPrint('📥 [Provider] Advert received from node');
|
||||
debugPrint(
|
||||
' Public key: ${publicKey.sublist(0, 6).map((b) => b.toRadixString(16).padLeft(2, '0')).join(':')}...',
|
||||
);
|
||||
print(
|
||||
debugPrint(
|
||||
' Note: Waiting for PUSH_CODE_NEW_ADVERT (0x8A) with full contact details',
|
||||
);
|
||||
// The companion radio will automatically send PUSH_CODE_NEW_ADVERT if manual_add_contacts=0
|
||||
@@ -341,11 +341,11 @@ class ConnectionProvider with ChangeNotifier {
|
||||
};
|
||||
|
||||
_bleService.onPathUpdated = (publicKey) {
|
||||
print('📥 [Provider] Path updated for contact');
|
||||
print(
|
||||
debugPrint('📥 [Provider] Path updated for contact');
|
||||
debugPrint(
|
||||
' Public key: ${publicKey.sublist(0, 6).map((b) => b.toRadixString(16).padLeft(2, '0')).join(':')}...',
|
||||
);
|
||||
print(
|
||||
debugPrint(
|
||||
' Note: Mesh network discovered a new/better routing path to this contact',
|
||||
);
|
||||
// Forward the callback to ContactsProvider to trigger contact sync
|
||||
@@ -354,7 +354,7 @@ class ConnectionProvider with ChangeNotifier {
|
||||
|
||||
_bleService
|
||||
.onMessageSent = (expectedAckTag, suggestedTimeoutMs, isFloodMode) {
|
||||
print(
|
||||
debugPrint(
|
||||
'📥 [Provider] Message sent - ACK tag: $expectedAckTag, timeout: ${suggestedTimeoutMs}ms',
|
||||
);
|
||||
|
||||
@@ -362,7 +362,7 @@ class ConnectionProvider with ChangeNotifier {
|
||||
final messageId = _messageDeliveryTracker.popPendingMessageId();
|
||||
|
||||
if (messageId != null) {
|
||||
print(' Matched with message ID: $messageId');
|
||||
debugPrint(' Matched with message ID: $messageId');
|
||||
|
||||
// Store the ACK tag to message ID mapping for delivery confirmation
|
||||
_messageDeliveryTracker.mapAckTagToMessageId(expectedAckTag, messageId);
|
||||
@@ -370,45 +370,45 @@ class ConnectionProvider with ChangeNotifier {
|
||||
// Notify callback with message ID
|
||||
onMessageSent?.call(messageId, expectedAckTag, suggestedTimeoutMs);
|
||||
} else {
|
||||
print(
|
||||
debugPrint(
|
||||
'⚠️ [Provider] SENT response received but no pending message IDs',
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
_bleService.onMessageDelivered = (ackCode, roundTripTimeMs) {
|
||||
print(
|
||||
debugPrint(
|
||||
'📥 [Provider] Message delivered - ACK code: $ackCode, RTT: ${roundTripTimeMs}ms',
|
||||
);
|
||||
onMessageDelivered?.call(ackCode, roundTripTimeMs);
|
||||
};
|
||||
|
||||
_bleService.onMessageEchoDetected = (messageId, echoCount, snrRaw, rssiDbm) {
|
||||
print(
|
||||
debugPrint(
|
||||
'🔊 [Provider] Echo detected - Message: $messageId, Count: $echoCount',
|
||||
);
|
||||
onMessageEchoDetected?.call(messageId, echoCount, snrRaw, rssiDbm);
|
||||
};
|
||||
|
||||
_bleService.onStatusResponse = (publicKeyPrefix, statusData) {
|
||||
print('📥 [Provider] Status response received from node');
|
||||
print(
|
||||
debugPrint('📥 [Provider] Status response received from node');
|
||||
debugPrint(
|
||||
' Public key prefix: ${publicKeyPrefix.map((b) => b.toRadixString(16).padLeft(2, '0')).join(':')}',
|
||||
);
|
||||
print(' Status data: ${statusData.length} bytes');
|
||||
debugPrint(' Status data: ${statusData.length} bytes');
|
||||
// Forward the callback to whoever needs it (e.g., ContactsProvider)
|
||||
onStatusResponse?.call(publicKeyPrefix, statusData);
|
||||
};
|
||||
|
||||
_bleService.onDeviceInfoReceived = (deviceInfo) {
|
||||
print('📥 [Provider] Received DeviceInfo:');
|
||||
print(' Firmware Version: ${deviceInfo['firmwareVersion']}');
|
||||
print(' Max Contacts: ${deviceInfo['maxContacts']}');
|
||||
print(' Max Channels: ${deviceInfo['maxChannels']}');
|
||||
print(' BLE PIN: ${deviceInfo['blePin']}');
|
||||
print(' Build Date: ${deviceInfo['firmwareBuildDate']}');
|
||||
print(' Model: ${deviceInfo['manufacturerModel']}');
|
||||
print(' Version: ${deviceInfo['semanticVersion']}');
|
||||
debugPrint('📥 [Provider] Received DeviceInfo:');
|
||||
debugPrint(' Firmware Version: ${deviceInfo['firmwareVersion']}');
|
||||
debugPrint(' Max Contacts: ${deviceInfo['maxContacts']}');
|
||||
debugPrint(' Max Channels: ${deviceInfo['maxChannels']}');
|
||||
debugPrint(' BLE PIN: ${deviceInfo['blePin']}');
|
||||
debugPrint(' Build Date: ${deviceInfo['firmwareBuildDate']}');
|
||||
debugPrint(' Model: ${deviceInfo['manufacturerModel']}');
|
||||
debugPrint(' Version: ${deviceInfo['semanticVersion']}');
|
||||
|
||||
_deviceInfo = _deviceInfo.copyWith(
|
||||
firmwareVersion: deviceInfo['firmwareVersion'] as int?,
|
||||
@@ -420,21 +420,21 @@ class ConnectionProvider with ChangeNotifier {
|
||||
semanticVersion: deviceInfo['semanticVersion'] as String?,
|
||||
);
|
||||
notifyListeners();
|
||||
print('✅ [Provider] Device info updated with DeviceInfo');
|
||||
debugPrint('✅ [Provider] Device info updated with DeviceInfo');
|
||||
};
|
||||
|
||||
_bleService.onSelfInfoReceived = (selfInfo) {
|
||||
print('📥 [Provider] Received SelfInfo:');
|
||||
print(
|
||||
debugPrint('📥 [Provider] Received SelfInfo:');
|
||||
debugPrint(
|
||||
' TX Power: ${selfInfo['txPower']} / ${selfInfo['maxTxPower']} dBm',
|
||||
);
|
||||
print(
|
||||
debugPrint(
|
||||
' Radio: freq=${selfInfo['radioFreq']}, bw=${selfInfo['radioBw']}, sf=${selfInfo['radioSf']}, cr=${selfInfo['radioCr']}',
|
||||
);
|
||||
print(
|
||||
debugPrint(
|
||||
' Position: ${selfInfo['advLat'] / 1000000.0}, ${selfInfo['advLon'] / 1000000.0}',
|
||||
);
|
||||
print(' Self Name: ${selfInfo['selfName']}');
|
||||
debugPrint(' Self Name: ${selfInfo['selfName']}');
|
||||
|
||||
_deviceInfo = _deviceInfo.copyWith(
|
||||
deviceType: selfInfo['deviceType'] as int?,
|
||||
@@ -451,24 +451,24 @@ class ConnectionProvider with ChangeNotifier {
|
||||
selfName: selfInfo['selfName'] as String?,
|
||||
);
|
||||
notifyListeners();
|
||||
print('✅ [Provider] Device info updated with SelfInfo');
|
||||
debugPrint('✅ [Provider] Device info updated with SelfInfo');
|
||||
};
|
||||
|
||||
// Activity indicators
|
||||
|
||||
_bleService.onBatteryAndStorage = (millivolts, usedKb, totalKb) {
|
||||
print('📥 [Provider] Received BatteryAndStorage:');
|
||||
print(
|
||||
debugPrint('📥 [Provider] Received BatteryAndStorage:');
|
||||
debugPrint(
|
||||
' Battery: ${millivolts}mV (${(millivolts / 1000.0).toStringAsFixed(2)}V)',
|
||||
);
|
||||
if (usedKb != null) {
|
||||
print(' Storage Used: ${usedKb}KB');
|
||||
debugPrint(' Storage Used: ${usedKb}KB');
|
||||
}
|
||||
if (totalKb != null) {
|
||||
print(' Storage Total: ${totalKb}KB');
|
||||
debugPrint(' Storage Total: ${totalKb}KB');
|
||||
if (totalKb > 0 && usedKb != null) {
|
||||
final usedPercent = (usedKb / totalKb) * 100.0;
|
||||
print(' Storage Usage: ${usedPercent.toStringAsFixed(1)}%');
|
||||
debugPrint(' Storage Usage: ${usedPercent.toStringAsFixed(1)}%');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,7 +479,7 @@ class ConnectionProvider with ChangeNotifier {
|
||||
lastUpdate: DateTime.now(),
|
||||
);
|
||||
notifyListeners();
|
||||
print('✅ [Provider] Device info updated with BatteryAndStorage');
|
||||
debugPrint('✅ [Provider] Device info updated with BatteryAndStorage');
|
||||
};
|
||||
_bleService.onRxActivity = () {
|
||||
_rxActivity = true;
|
||||
@@ -516,24 +516,24 @@ class ConnectionProvider with ChangeNotifier {
|
||||
|
||||
/// Start scanning for MeshCore devices
|
||||
Future<void> startScan() async {
|
||||
print('🔍 [Provider] startScan() called');
|
||||
debugPrint('🔍 [Provider] startScan() called');
|
||||
_isScanning = true;
|
||||
_scannedDevices.clear();
|
||||
_error = null;
|
||||
notifyListeners();
|
||||
print('✅ [Provider] Scan state initialized, notifying listeners');
|
||||
debugPrint('✅ [Provider] Scan state initialized, notifying listeners');
|
||||
|
||||
try {
|
||||
await for (final scanResult in _bleService.scanForDevices(
|
||||
timeout: const Duration(seconds: 10),
|
||||
)) {
|
||||
print('📱 [Provider] Scan result received from scan stream');
|
||||
debugPrint('📱 [Provider] Scan result received from scan stream');
|
||||
final device = scanResult.device;
|
||||
final rssi = scanResult.rssi;
|
||||
|
||||
if (!_scannedDevices.any((d) => d.device.remoteId == device.remoteId)) {
|
||||
_scannedDevices.add(ScannedDevice(device: device, rssi: rssi));
|
||||
print(
|
||||
debugPrint(
|
||||
'✅ [Provider] Added device to list: ${device.platformName} (RSSI: $rssi dBm), total: ${_scannedDevices.length}',
|
||||
);
|
||||
notifyListeners();
|
||||
@@ -544,22 +544,22 @@ class ConnectionProvider with ChangeNotifier {
|
||||
);
|
||||
if (index != -1 && _scannedDevices[index].rssi != rssi) {
|
||||
_scannedDevices[index] = ScannedDevice(device: device, rssi: rssi);
|
||||
print(
|
||||
debugPrint(
|
||||
' 🔄 [Provider] Updated RSSI for ${device.platformName}: $rssi dBm',
|
||||
);
|
||||
notifyListeners();
|
||||
} else {
|
||||
print(
|
||||
debugPrint(
|
||||
' ⏭️ [Provider] Device already in list with same RSSI, skipping',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print('❌ [Provider] Scan error: $e');
|
||||
debugPrint('❌ [Provider] Scan error: $e');
|
||||
_error = 'Scan error: $e';
|
||||
} finally {
|
||||
print('🏁 [Provider] Scan completed');
|
||||
debugPrint('🏁 [Provider] Scan completed');
|
||||
_isScanning = false;
|
||||
notifyListeners();
|
||||
}
|
||||
@@ -574,7 +574,7 @@ class ConnectionProvider with ChangeNotifier {
|
||||
|
||||
/// Connect to a device
|
||||
Future<bool> connect(BluetoothDevice device) async {
|
||||
print('🔵 [Provider] connect() called for device: ${device.platformName}');
|
||||
debugPrint('🔵 [Provider] connect() called for device: ${device.platformName}');
|
||||
|
||||
_deviceInfo = _deviceInfo.copyWith(
|
||||
deviceId: device.remoteId.toString(),
|
||||
@@ -584,16 +584,16 @@ class ConnectionProvider with ChangeNotifier {
|
||||
connectionState: ConnectionState.connecting,
|
||||
);
|
||||
_error = null;
|
||||
print('✅ [Provider] Device info updated to connecting state');
|
||||
debugPrint('✅ [Provider] Device info updated to connecting state');
|
||||
notifyListeners();
|
||||
|
||||
print('🔵 [Provider] Calling BLE service connect()...');
|
||||
debugPrint('🔵 [Provider] Calling BLE service connect()...');
|
||||
final success = await _bleService.connect(device);
|
||||
|
||||
if (success) {
|
||||
print('✅ [Provider] BLE service connect() returned success');
|
||||
debugPrint('✅ [Provider] BLE service connect() returned success');
|
||||
} else {
|
||||
print('❌ [Provider] BLE service connect() returned failure');
|
||||
debugPrint('❌ [Provider] BLE service connect() returned failure');
|
||||
_deviceInfo = _deviceInfo.copyWith(
|
||||
connectionState: ConnectionState.error,
|
||||
);
|
||||
@@ -622,7 +622,7 @@ class ConnectionProvider with ChangeNotifier {
|
||||
/// Cancel ongoing reconnection attempts
|
||||
/// This is useful when the user wants to manually disconnect during reconnection
|
||||
void cancelReconnection() {
|
||||
print('🔴 [Provider] User requested cancellation of reconnection');
|
||||
debugPrint('🔴 [Provider] User requested cancellation of reconnection');
|
||||
disconnect();
|
||||
}
|
||||
|
||||
@@ -705,19 +705,19 @@ class ConnectionProvider with ChangeNotifier {
|
||||
// Log path status and retry info
|
||||
if (contact != null) {
|
||||
if (retryAttempt > 0) {
|
||||
print('🔄 [ConnectionProvider] Sending message to ${contact.advName} (retry $retryAttempt/3)');
|
||||
debugPrint('🔄 [ConnectionProvider] Sending message to ${contact.advName} (retry $retryAttempt/3)');
|
||||
} else {
|
||||
print('📤 [ConnectionProvider] Sending message to ${contact.advName}');
|
||||
debugPrint('📤 [ConnectionProvider] Sending message to ${contact.advName}');
|
||||
}
|
||||
print(' Type: ${contact.type.displayName}');
|
||||
print(' Path status: ${contact.pathDescription}');
|
||||
debugPrint(' Type: ${contact.type.displayName}');
|
||||
debugPrint(' Path status: ${contact.pathDescription}');
|
||||
if (contact.hasPath) {
|
||||
print(' ✅ Using learned path (${contact.outPathLen} bytes)');
|
||||
debugPrint(' ✅ Using learned path (${contact.outPathLen} bytes)');
|
||||
} else {
|
||||
print(' ⚠️ No path available - will use flood mode');
|
||||
debugPrint(' ⚠️ No path available - will use flood mode');
|
||||
}
|
||||
} else if (retryAttempt > 0) {
|
||||
print('🔄 [ConnectionProvider] Sending message (retry $retryAttempt/3)');
|
||||
debugPrint('🔄 [ConnectionProvider] Sending message (retry $retryAttempt/3)');
|
||||
}
|
||||
|
||||
// Track pending operation for auto-recovery (if contact not found in radio)
|
||||
@@ -730,7 +730,7 @@ class ConnectionProvider with ChangeNotifier {
|
||||
contact: contact,
|
||||
retryAttempt: retryAttempt,
|
||||
);
|
||||
print(' 📝 Tracked pending operation for auto-recovery: $operationId');
|
||||
debugPrint(' 📝 Tracked pending operation for auto-recovery: $operationId');
|
||||
}
|
||||
|
||||
// IMPORTANT: Track pending message BEFORE sending to avoid race condition
|
||||
@@ -738,7 +738,7 @@ class ConnectionProvider with ChangeNotifier {
|
||||
// the callback will fire before we add the message ID to the queue.
|
||||
if (messageId != null) {
|
||||
_messageDeliveryTracker.trackPendingMessage(messageId);
|
||||
print(' Added message ID to pending queue BEFORE sending: $messageId');
|
||||
debugPrint(' Added message ID to pending queue BEFORE sending: $messageId');
|
||||
}
|
||||
|
||||
// Send the message with retry attempt info
|
||||
@@ -796,9 +796,9 @@ class ConnectionProvider with ChangeNotifier {
|
||||
// Channel messages are ephemeral (not persisted) - mark as "sent" immediately
|
||||
// They don't have ACK/TAG mechanism like direct messages
|
||||
if (messageId != null) {
|
||||
print('✅ [ConnectionProvider] Channel message sent successfully');
|
||||
print(' Message ID: $messageId');
|
||||
print(' onMessageSent callback exists: ${onMessageSent != null}');
|
||||
debugPrint('✅ [ConnectionProvider] Channel message sent successfully');
|
||||
debugPrint(' Message ID: $messageId');
|
||||
debugPrint(' onMessageSent callback exists: ${onMessageSent != null}');
|
||||
|
||||
// Track for echo detection
|
||||
// The BLE handler will capture the packet via LOG_RX_DATA and associate it
|
||||
@@ -812,9 +812,9 @@ class ConnectionProvider with ChangeNotifier {
|
||||
|
||||
// Use a dummy ACK tag (0) and timeout (0) for channel messages
|
||||
// This will trigger the callback to mark the message as "sent"
|
||||
print(' Calling onMessageSent callback...');
|
||||
debugPrint(' Calling onMessageSent callback...');
|
||||
onMessageSent?.call(messageId, 0, 0);
|
||||
print(' onMessageSent callback completed');
|
||||
debugPrint(' onMessageSent callback completed');
|
||||
}
|
||||
} catch (e) {
|
||||
_error = 'Failed to send channel message: $e';
|
||||
@@ -902,7 +902,7 @@ class ConnectionProvider with ChangeNotifier {
|
||||
|
||||
// First attempt timed out - retry with flooding if first was direct
|
||||
if (firstAttemptDirect) {
|
||||
print(
|
||||
debugPrint(
|
||||
'⚠️ [Provider] Ping timeout on direct attempt, retrying with flooding...',
|
||||
);
|
||||
onRetryWithFlooding?.call();
|
||||
@@ -1253,8 +1253,8 @@ class ConnectionProvider with ChangeNotifier {
|
||||
|
||||
try {
|
||||
_isSyncingMessages = true;
|
||||
print('🔄 [Provider] Starting message sync loop...');
|
||||
print(' Initial _noMoreMessages state: $_noMoreMessages');
|
||||
debugPrint('🔄 [Provider] Starting message sync loop...');
|
||||
debugPrint(' Initial _noMoreMessages state: $_noMoreMessages');
|
||||
|
||||
// Keep syncing until we get NoMoreMessages response
|
||||
// The device will send ContactMsgRecv or ChannelMsgRecv responses
|
||||
@@ -1263,13 +1263,13 @@ class ConnectionProvider with ChangeNotifier {
|
||||
// Safety limit
|
||||
// Check flag BEFORE sending (not after)
|
||||
if (_noMoreMessages) {
|
||||
print(
|
||||
debugPrint(
|
||||
'✅ [Provider] Message sync complete - NoMoreMessages flag set after $count requests',
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
print(
|
||||
debugPrint(
|
||||
'📤 [Provider] Sync iteration ${i + 1}: Sending CMD_SYNC_NEXT_MESSAGE',
|
||||
);
|
||||
|
||||
@@ -1290,21 +1290,21 @@ class ConnectionProvider with ChangeNotifier {
|
||||
// Small delay to allow response to be processed
|
||||
await Future.delayed(const Duration(milliseconds: 150));
|
||||
|
||||
print(' After iteration ${i + 1}: _noMoreMessages=$_noMoreMessages');
|
||||
debugPrint(' After iteration ${i + 1}: _noMoreMessages=$_noMoreMessages');
|
||||
}
|
||||
|
||||
if (!_noMoreMessages && count >= 100) {
|
||||
print(
|
||||
debugPrint(
|
||||
'⚠️ [Provider] Message sync stopped - reached safety limit of 100 requests without NoMoreMessages',
|
||||
);
|
||||
}
|
||||
|
||||
print(
|
||||
debugPrint(
|
||||
'🏁 [Provider] Message sync finished: sent $count sync requests, _noMoreMessages=$_noMoreMessages',
|
||||
);
|
||||
return count;
|
||||
} catch (e) {
|
||||
print('❌ [Provider] Failed to sync messages: $e');
|
||||
debugPrint('❌ [Provider] Failed to sync messages: $e');
|
||||
_error = 'Failed to sync messages: $e';
|
||||
notifyListeners();
|
||||
return count;
|
||||
@@ -1321,10 +1321,10 @@ class ConnectionProvider with ChangeNotifier {
|
||||
/// Example usage:
|
||||
/// ```dart
|
||||
/// connectionProvider.onLoginSuccess = (pkPrefix, perms, isAdmin, tag) {
|
||||
/// print('Successfully logged in to room!');
|
||||
/// debugPrint('Successfully logged in to room!');
|
||||
/// };
|
||||
/// connectionProvider.onLoginFail = (pkPrefix) {
|
||||
/// print('Login failed - incorrect password');
|
||||
/// debugPrint('Login failed - incorrect password');
|
||||
/// };
|
||||
/// await connectionProvider.loginToRoom(
|
||||
/// roomPublicKey: contact.publicKey,
|
||||
@@ -1374,7 +1374,7 @@ class ConnectionProvider with ChangeNotifier {
|
||||
/// Example usage:
|
||||
/// ```dart
|
||||
/// connectionProvider.onStatusResponse = (publicKeyPrefix, statusData) {
|
||||
/// print('Status from node: ${utf8.decode(statusData)}');
|
||||
/// debugPrint('Status from node: ${utf8.decode(statusData)}');
|
||||
/// };
|
||||
/// await connectionProvider.requestStatus(repeaterContact.publicKey);
|
||||
/// ```
|
||||
|
||||
@@ -23,7 +23,7 @@ class ContactsProvider with ChangeNotifier {
|
||||
if (_isInitialized) return;
|
||||
|
||||
try {
|
||||
print('📦 [ContactsProvider] Loading persisted contacts...');
|
||||
debugPrint('📦 [ContactsProvider] Loading persisted contacts...');
|
||||
final storedContacts = await _storageService.loadContacts(
|
||||
excludePublicKey: devicePublicKey,
|
||||
);
|
||||
@@ -39,14 +39,14 @@ class ContactsProvider with ChangeNotifier {
|
||||
}
|
||||
|
||||
_isInitialized = true;
|
||||
print('✅ [ContactsProvider] Loaded ${storedContacts.length} persisted contacts');
|
||||
debugPrint('✅ [ContactsProvider] Loaded ${storedContacts.length} persisted contacts');
|
||||
|
||||
// Ensure public channel exists after loading
|
||||
_ensurePublicChannelExists();
|
||||
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
print('❌ [ContactsProvider] Error initializing: $e');
|
||||
debugPrint('❌ [ContactsProvider] Error initializing: $e');
|
||||
_isInitialized = true; // Mark as initialized even on error
|
||||
_ensurePublicChannelExists();
|
||||
}
|
||||
@@ -84,7 +84,7 @@ class ContactsProvider with ChangeNotifier {
|
||||
.toList();
|
||||
await _storageService.saveContacts(contactsToSave);
|
||||
} catch (e) {
|
||||
print('❌ [ContactsProvider] Error persisting contacts: $e');
|
||||
debugPrint('❌ [ContactsProvider] Error persisting contacts: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ class ContactsProvider with ChangeNotifier {
|
||||
void addOrUpdateContact(Contact contact, {Uint8List? devicePublicKey}) {
|
||||
// Don't add contacts that match our device's public key
|
||||
if (devicePublicKey != null && _publicKeysMatch(contact.publicKey, devicePublicKey)) {
|
||||
print('ℹ️ [ContactsProvider] Ignoring contact with device\'s own public key: ${contact.advName}');
|
||||
debugPrint('ℹ️ [ContactsProvider] Ignoring contact with device\'s own public key: ${contact.advName}');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -182,14 +182,14 @@ class ContactsProvider with ChangeNotifier {
|
||||
for (final contact in contacts) {
|
||||
// Don't add contacts that match our device's public key
|
||||
if (devicePublicKey != null && _publicKeysMatch(contact.publicKey, devicePublicKey)) {
|
||||
print('ℹ️ [ContactsProvider] Ignoring contact with device\'s own public key: ${contact.advName}');
|
||||
debugPrint('ℹ️ [ContactsProvider] Ignoring contact with device\'s own public key: ${contact.advName}');
|
||||
excluded++;
|
||||
continue;
|
||||
}
|
||||
_contacts[contact.publicKeyHex] = contact;
|
||||
}
|
||||
if (excluded > 0) {
|
||||
print('ℹ️ [ContactsProvider] Excluded $excluded contact(s) matching device public key');
|
||||
debugPrint('ℹ️ [ContactsProvider] Excluded $excluded contact(s) matching device public key');
|
||||
}
|
||||
_persistContacts();
|
||||
notifyListeners();
|
||||
@@ -197,38 +197,38 @@ class ContactsProvider with ChangeNotifier {
|
||||
|
||||
/// Update contact telemetry
|
||||
void updateTelemetry(Uint8List publicKeyPrefix, Uint8List lppData) {
|
||||
print('📊 [ContactsProvider] updateTelemetry() called');
|
||||
print(' Public key prefix (hex): ${publicKeyPrefix.map((b) => b.toRadixString(16).padLeft(2, '0')).join(':')}');
|
||||
print(' LPP data size: ${lppData.length} bytes');
|
||||
debugPrint('📊 [ContactsProvider] updateTelemetry() called');
|
||||
debugPrint(' Public key prefix (hex): ${publicKeyPrefix.map((b) => b.toRadixString(16).padLeft(2, '0')).join(':')}');
|
||||
debugPrint(' LPP data size: ${lppData.length} bytes');
|
||||
|
||||
// Find contact by public key prefix
|
||||
final contact = _findContactByPrefix(publicKeyPrefix);
|
||||
if (contact == null) {
|
||||
print(' ❌ Contact not found for this prefix');
|
||||
debugPrint(' ❌ Contact not found for this prefix');
|
||||
return;
|
||||
}
|
||||
|
||||
print(' ✅ Found contact: ${contact.advName}');
|
||||
print(' Old telemetry timestamp: ${contact.telemetry?.timestamp}');
|
||||
debugPrint(' ✅ Found contact: ${contact.advName}');
|
||||
debugPrint(' Old telemetry timestamp: ${contact.telemetry?.timestamp}');
|
||||
|
||||
try {
|
||||
// Parse Cayenne LPP data
|
||||
final telemetry = CayenneLppParser.parse(lppData);
|
||||
print(' ✅ Parsed new telemetry');
|
||||
print(' New telemetry timestamp: ${telemetry.timestamp}');
|
||||
debugPrint(' ✅ Parsed new telemetry');
|
||||
debugPrint(' New telemetry timestamp: ${telemetry.timestamp}');
|
||||
|
||||
// Update contact with new telemetry
|
||||
final updatedContact = contact.copyWith(telemetry: telemetry);
|
||||
_contacts[contact.publicKeyHex] = updatedContact;
|
||||
print(' ✅ Updated contact in map');
|
||||
debugPrint(' ✅ Updated contact in map');
|
||||
|
||||
_persistContacts();
|
||||
print(' ✅ Persisted contacts to storage');
|
||||
debugPrint(' ✅ Persisted contacts to storage');
|
||||
|
||||
notifyListeners();
|
||||
print(' ✅ Notified listeners - UI should update');
|
||||
debugPrint(' ✅ Notified listeners - UI should update');
|
||||
} catch (e) {
|
||||
print(' ❌ Failed to parse telemetry: $e');
|
||||
debugPrint(' ❌ Failed to parse telemetry: $e');
|
||||
debugPrint('Failed to parse telemetry: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ class MessagesProvider with ChangeNotifier {
|
||||
if (_isInitialized) return;
|
||||
|
||||
try {
|
||||
print('📦 [MessagesProvider] Loading persisted messages...');
|
||||
debugPrint('📦 [MessagesProvider] Loading persisted messages...');
|
||||
final storedMessages = await _storageService.loadMessages();
|
||||
|
||||
// Add stored messages with enhancement to ensure SAR detection
|
||||
@@ -108,10 +108,10 @@ class MessagesProvider with ChangeNotifier {
|
||||
}
|
||||
|
||||
_isInitialized = true;
|
||||
print('✅ [MessagesProvider] Loaded ${storedMessages.length} persisted messages');
|
||||
debugPrint('✅ [MessagesProvider] Loaded ${storedMessages.length} persisted messages');
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
print('❌ [MessagesProvider] Error initializing: $e');
|
||||
debugPrint('❌ [MessagesProvider] Error initializing: $e');
|
||||
_isInitialized = true; // Mark as initialized even on error
|
||||
}
|
||||
}
|
||||
@@ -149,9 +149,9 @@ class MessagesProvider with ChangeNotifier {
|
||||
|
||||
// Debug: Check if message is SAR
|
||||
if (message.text.startsWith('S:')) {
|
||||
print('🔍 [MessagesProvider] Processing SAR message: ${message.text}');
|
||||
print(' isSarMarker: ${finalMessage.isSarMarker}');
|
||||
print(' sarMarkerType: ${finalMessage.sarMarkerType}');
|
||||
debugPrint('🔍 [MessagesProvider] Processing SAR message: ${message.text}');
|
||||
debugPrint(' isSarMarker: ${finalMessage.isSarMarker}');
|
||||
debugPrint(' sarMarkerType: ${finalMessage.sarMarkerType}');
|
||||
}
|
||||
|
||||
// Check for duplicates before adding
|
||||
@@ -160,8 +160,8 @@ class MessagesProvider with ChangeNotifier {
|
||||
// - Multiple paths in the network
|
||||
// - Syncing messages from device queue
|
||||
if (_isDuplicate(finalMessage)) {
|
||||
print('⚠️ [MessagesProvider] Duplicate message detected, skipping: ${finalMessage.id}');
|
||||
print(' Text: ${finalMessage.text.substring(0, finalMessage.text.length > 50 ? 50 : finalMessage.text.length)}...');
|
||||
debugPrint('⚠️ [MessagesProvider] Duplicate message detected, skipping: ${finalMessage.id}');
|
||||
debugPrint(' Text: ${finalMessage.text.substring(0, finalMessage.text.length > 50 ? 50 : finalMessage.text.length)}...');
|
||||
return; // Skip duplicate
|
||||
}
|
||||
|
||||
@@ -263,7 +263,7 @@ class MessagesProvider with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
print('📥 [MessagesProvider] Added $addedCount messages, skipped $duplicateCount duplicates');
|
||||
debugPrint('📥 [MessagesProvider] Added $addedCount messages, skipped $duplicateCount duplicates');
|
||||
|
||||
// Persist to storage asynchronously
|
||||
_persistMessages();
|
||||
@@ -280,9 +280,9 @@ class MessagesProvider with ChangeNotifier {
|
||||
// Get sender name from message
|
||||
final senderName = message.senderName ?? message.senderKeyShort ?? 'Unknown';
|
||||
|
||||
print('🔔 [MessagesProvider] Triggering SAR notification for ${marker.type.displayName}');
|
||||
print(' Sender: $senderName');
|
||||
print(' Coordinates: $coords');
|
||||
debugPrint('🔔 [MessagesProvider] Triggering SAR notification for ${marker.type.displayName}');
|
||||
debugPrint(' Sender: $senderName');
|
||||
debugPrint(' Coordinates: $coords');
|
||||
|
||||
await _notificationService.showSarNotification(
|
||||
type: marker.type,
|
||||
@@ -292,7 +292,7 @@ class MessagesProvider with ChangeNotifier {
|
||||
localizations: _localizations,
|
||||
);
|
||||
} catch (e) {
|
||||
print('❌ [MessagesProvider] Error triggering SAR notification: $e');
|
||||
debugPrint('❌ [MessagesProvider] Error triggering SAR notification: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,7 +301,7 @@ class MessagesProvider with ChangeNotifier {
|
||||
try {
|
||||
await _storageService.saveMessages(_messages);
|
||||
} catch (e) {
|
||||
print('❌ [MessagesProvider] Error persisting messages: $e');
|
||||
debugPrint('❌ [MessagesProvider] Error persisting messages: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,7 +409,7 @@ class MessagesProvider with ChangeNotifier {
|
||||
_pendingSentMessages.remove(message.expectedAckTag);
|
||||
}
|
||||
|
||||
print('🗑️ [MessagesProvider] Message $messageId deleted');
|
||||
debugPrint('🗑️ [MessagesProvider] Message $messageId deleted');
|
||||
|
||||
_persistMessages();
|
||||
notifyListeners();
|
||||
@@ -495,18 +495,18 @@ class MessagesProvider with ChangeNotifier {
|
||||
|
||||
/// Add a sent message with initial status
|
||||
void addSentMessage(Message message, {Contact? contact}) {
|
||||
print('📝 [MessagesProvider] addSentMessage called');
|
||||
print(' Message ID: ${message.id}');
|
||||
print(' Message type: ${message.messageType}');
|
||||
print(' Initial status: ${message.deliveryStatus}');
|
||||
print(' Message text preview: ${message.text.substring(0, message.text.length > 30 ? 30 : message.text.length)}...');
|
||||
debugPrint('📝 [MessagesProvider] addSentMessage called');
|
||||
debugPrint(' Message ID: ${message.id}');
|
||||
debugPrint(' Message type: ${message.messageType}');
|
||||
debugPrint(' Initial status: ${message.deliveryStatus}');
|
||||
debugPrint(' Message text preview: ${message.text.substring(0, message.text.length > 30 ? 30 : message.text.length)}...');
|
||||
|
||||
// Always enhance message with SAR parser to detect SAR markers
|
||||
final enhancedMessage = SarMessageParser.enhanceMessage(message);
|
||||
|
||||
// Check for duplicates (shouldn't happen for sent messages, but be safe)
|
||||
if (_isDuplicate(enhancedMessage)) {
|
||||
print('⚠️ [MessagesProvider] Duplicate sent message detected, skipping: ${enhancedMessage.id}');
|
||||
debugPrint('⚠️ [MessagesProvider] Duplicate sent message detected, skipping: ${enhancedMessage.id}');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -516,13 +516,13 @@ class MessagesProvider with ChangeNotifier {
|
||||
isRead: true, // Sent messages are always marked as read
|
||||
);
|
||||
_messages.add(sendingMessage);
|
||||
print(' ✅ Message added to list at index ${_messages.length - 1}');
|
||||
print(' Total messages in list: ${_messages.length}');
|
||||
debugPrint(' ✅ Message added to list at index ${_messages.length - 1}');
|
||||
debugPrint(' Total messages in list: ${_messages.length}');
|
||||
|
||||
// Store contact mapping for retry logic
|
||||
if (contact != null) {
|
||||
_messageContactMap[message.id] = contact;
|
||||
print(' ✅ Stored contact mapping for retry logic');
|
||||
debugPrint(' ✅ Stored contact mapping for retry logic');
|
||||
}
|
||||
|
||||
// If it's a SAR marker message, extract and store the marker
|
||||
@@ -535,25 +535,25 @@ class MessagesProvider with ChangeNotifier {
|
||||
|
||||
_persistMessages();
|
||||
notifyListeners();
|
||||
print(' ✅ notifyListeners() called - UI should update');
|
||||
debugPrint(' ✅ notifyListeners() called - UI should update');
|
||||
}
|
||||
|
||||
/// Update message status to sent with ACK tag
|
||||
void markMessageSent(String messageId, int expectedAckTag, int suggestedTimeoutMs) {
|
||||
print('📤 [MessagesProvider] markMessageSent called');
|
||||
print(' Message ID: $messageId');
|
||||
print(' Expected ACK tag: $expectedAckTag (0x${expectedAckTag.toRadixString(16).padLeft(8, '0')})');
|
||||
print(' Timeout: ${suggestedTimeoutMs}ms');
|
||||
print(' Current pending ACKs before adding: ${_pendingSentMessages.keys.toList()}');
|
||||
debugPrint('📤 [MessagesProvider] markMessageSent called');
|
||||
debugPrint(' Message ID: $messageId');
|
||||
debugPrint(' Expected ACK tag: $expectedAckTag (0x${expectedAckTag.toRadixString(16).padLeft(8, '0')})');
|
||||
debugPrint(' Timeout: ${suggestedTimeoutMs}ms');
|
||||
debugPrint(' Current pending ACKs before adding: ${_pendingSentMessages.keys.toList()}');
|
||||
|
||||
final index = _messages.indexWhere((m) => m.id == messageId);
|
||||
print(' Message index in list: $index');
|
||||
debugPrint(' Message index in list: $index');
|
||||
|
||||
if (index != -1) {
|
||||
final message = _messages[index];
|
||||
print(' Current status: ${message.deliveryStatus}');
|
||||
print(' Message type: ${message.messageType}');
|
||||
print(' Message text preview: ${message.text.substring(0, message.text.length > 30 ? 30 : message.text.length)}...');
|
||||
debugPrint(' Current status: ${message.deliveryStatus}');
|
||||
debugPrint(' Message type: ${message.messageType}');
|
||||
debugPrint(' Message text preview: ${message.text.substring(0, message.text.length > 30 ? 30 : message.text.length)}...');
|
||||
|
||||
final updatedMessage = message.copyWith(
|
||||
deliveryStatus: MessageDeliveryStatus.sent,
|
||||
@@ -566,55 +566,55 @@ class MessagesProvider with ChangeNotifier {
|
||||
if (expectedAckTag > 0 && suggestedTimeoutMs > 0) {
|
||||
// Track by ACK tag for matching with delivery confirmation
|
||||
_pendingSentMessages[expectedAckTag] = updatedMessage;
|
||||
print(' ✅ Added to pending messages map with ACK: $expectedAckTag');
|
||||
print(' Total pending messages: ${_pendingSentMessages.length}');
|
||||
print(' Pending ACKs after adding: ${_pendingSentMessages.keys.toList()}');
|
||||
debugPrint(' ✅ Added to pending messages map with ACK: $expectedAckTag');
|
||||
debugPrint(' Total pending messages: ${_pendingSentMessages.length}');
|
||||
debugPrint(' Pending ACKs after adding: ${_pendingSentMessages.keys.toList()}');
|
||||
|
||||
// Start timeout timer
|
||||
_timeoutTimers[expectedAckTag] = Timer(
|
||||
Duration(milliseconds: suggestedTimeoutMs),
|
||||
() {
|
||||
print('⏱️ [MessagesProvider] Timeout for message $messageId (ACK $expectedAckTag)');
|
||||
debugPrint('⏱️ [MessagesProvider] Timeout for message $messageId (ACK $expectedAckTag)');
|
||||
if (_pendingSentMessages.containsKey(expectedAckTag)) {
|
||||
markMessageFailed(messageId);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
print('⏱️ [MessagesProvider] Started ${suggestedTimeoutMs}ms timeout timer for message $messageId (ACK $expectedAckTag)');
|
||||
debugPrint('⏱️ [MessagesProvider] Started ${suggestedTimeoutMs}ms timeout timer for message $messageId (ACK $expectedAckTag)');
|
||||
} else {
|
||||
print(' ℹ️ Channel message (no ACK tracking) - marked as sent immediately');
|
||||
debugPrint(' ℹ️ Channel message (no ACK tracking) - marked as sent immediately');
|
||||
}
|
||||
|
||||
print(' Calling notifyListeners() to update UI with "sent" status');
|
||||
debugPrint(' Calling notifyListeners() to update UI with "sent" status');
|
||||
|
||||
_persistMessages();
|
||||
notifyListeners();
|
||||
|
||||
print(' ✅ markMessageSent completed successfully');
|
||||
debugPrint(' ✅ markMessageSent completed successfully');
|
||||
} else {
|
||||
print('⚠️ [MessagesProvider] Message not found in list: $messageId');
|
||||
print(' Total messages in list: ${_messages.length}');
|
||||
print(' Recent messages:');
|
||||
debugPrint('⚠️ [MessagesProvider] Message not found in list: $messageId');
|
||||
debugPrint(' Total messages in list: ${_messages.length}');
|
||||
debugPrint(' Recent messages:');
|
||||
for (final m in _messages.take(5)) {
|
||||
print(' - ID: ${m.id}, Status: ${m.deliveryStatus}');
|
||||
debugPrint(' - ID: ${m.id}, Status: ${m.deliveryStatus}');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle echo detection for public channel messages
|
||||
void handleMessageEcho(String messageId, int echoCount, int snrRaw, int rssiDbm) {
|
||||
print('🔊 [MessagesProvider] handleMessageEcho called');
|
||||
print(' Message ID: $messageId');
|
||||
print(' Echo count: $echoCount');
|
||||
print(' SNR: ${(snrRaw.toSigned(8) / 4.0).toStringAsFixed(2)} dB');
|
||||
print(' RSSI: ${rssiDbm.toSigned(8)} dBm');
|
||||
debugPrint('🔊 [MessagesProvider] handleMessageEcho called');
|
||||
debugPrint(' Message ID: $messageId');
|
||||
debugPrint(' Echo count: $echoCount');
|
||||
debugPrint(' SNR: ${(snrRaw.toSigned(8) / 4.0).toStringAsFixed(2)} dB');
|
||||
debugPrint(' RSSI: ${rssiDbm.toSigned(8)} dBm');
|
||||
|
||||
// Find the message
|
||||
final index = _messages.indexWhere((m) => m.id == messageId);
|
||||
if (index != -1) {
|
||||
final message = _messages[index];
|
||||
print(' ✅ Found message: ${message.text.substring(0, message.text.length > 30 ? 30 : message.text.length)}...');
|
||||
debugPrint(' ✅ Found message: ${message.text.substring(0, message.text.length > 30 ? 30 : message.text.length)}...');
|
||||
|
||||
// Update echo count
|
||||
final updatedMessage = message.copyWith(
|
||||
@@ -623,28 +623,28 @@ class MessagesProvider with ChangeNotifier {
|
||||
);
|
||||
_messages[index] = updatedMessage;
|
||||
|
||||
print(' Updated echo count to: $echoCount');
|
||||
debugPrint(' Updated echo count to: $echoCount');
|
||||
_persistMessages();
|
||||
notifyListeners();
|
||||
print(' ✅ Echo update complete, UI notified');
|
||||
debugPrint(' ✅ Echo update complete, UI notified');
|
||||
} else {
|
||||
print(' ⚠️ Message not found in messages list');
|
||||
debugPrint(' ⚠️ Message not found in messages list');
|
||||
}
|
||||
}
|
||||
|
||||
/// Update message status to delivered with RTT
|
||||
void markMessageDelivered(int ackCode, int roundTripTimeMs) {
|
||||
print('🔍 [MessagesProvider] markMessageDelivered called with ACK: $ackCode, RTT: ${roundTripTimeMs}ms');
|
||||
print(' Current pending messages: ${_pendingSentMessages.keys.toList()}');
|
||||
print(' Total messages in list: ${_messages.length}');
|
||||
print(' Looking for ACK: $ackCode');
|
||||
debugPrint('🔍 [MessagesProvider] markMessageDelivered called with ACK: $ackCode, RTT: ${roundTripTimeMs}ms');
|
||||
debugPrint(' Current pending messages: ${_pendingSentMessages.keys.toList()}');
|
||||
debugPrint(' Total messages in list: ${_messages.length}');
|
||||
debugPrint(' Looking for ACK: $ackCode');
|
||||
|
||||
// Find message by ACK code
|
||||
final message = _pendingSentMessages[ackCode];
|
||||
if (message != null) {
|
||||
print(' ✅ Found message in pending map: ${message.id}');
|
||||
debugPrint(' ✅ Found message in pending map: ${message.id}');
|
||||
final index = _messages.indexWhere((m) => m.id == message.id);
|
||||
print(' Message index in list: $index');
|
||||
debugPrint(' Message index in list: $index');
|
||||
|
||||
if (index != -1) {
|
||||
final updatedMessage = message.copyWith(
|
||||
@@ -664,42 +664,42 @@ class MessagesProvider with ChangeNotifier {
|
||||
// Clear retry tracking on successful delivery
|
||||
_retryManager.clearRetry(message.id);
|
||||
|
||||
print('✅ [MessagesProvider] Message ${message.id} delivered in ${roundTripTimeMs}ms (ACK $ackCode)');
|
||||
print(' Updated status to: ${updatedMessage.deliveryStatus}');
|
||||
print(' Calling notifyListeners() to update UI');
|
||||
debugPrint('✅ [MessagesProvider] Message ${message.id} delivered in ${roundTripTimeMs}ms (ACK $ackCode)');
|
||||
debugPrint(' Updated status to: ${updatedMessage.deliveryStatus}');
|
||||
debugPrint(' Calling notifyListeners() to update UI');
|
||||
|
||||
_persistMessages();
|
||||
notifyListeners();
|
||||
|
||||
print(' ✅ notifyListeners() called successfully');
|
||||
debugPrint(' ✅ notifyListeners() called successfully');
|
||||
} else {
|
||||
print('⚠️ [MessagesProvider] Message not found in messages list (index=-1)');
|
||||
print(' This should never happen - message was in pending map but not in messages list');
|
||||
debugPrint('⚠️ [MessagesProvider] Message not found in messages list (index=-1)');
|
||||
debugPrint(' This should never happen - message was in pending map but not in messages list');
|
||||
}
|
||||
} else {
|
||||
print('⚠️ [MessagesProvider] No pending message found for ACK code: $ackCode');
|
||||
print(' Pending ACK codes: ${_pendingSentMessages.keys.toList()}');
|
||||
print(' This means either:');
|
||||
print(' 1. markMessageSent() was never called for this message (ACK tag not stored)');
|
||||
print(' 2. The ACK code from PUSH_CODE_SEND_CONFIRMED doesn\'t match the expected ACK tag from RESP_CODE_SENT');
|
||||
print(' 3. The message was already delivered or timed out');
|
||||
print(' Searching all messages for debugging...');
|
||||
debugPrint('⚠️ [MessagesProvider] No pending message found for ACK code: $ackCode');
|
||||
debugPrint(' Pending ACK codes: ${_pendingSentMessages.keys.toList()}');
|
||||
debugPrint(' This means either:');
|
||||
debugPrint(' 1. markMessageSent() was never called for this message (ACK tag not stored)');
|
||||
debugPrint(' 2. The ACK code from PUSH_CODE_SEND_CONFIRMED doesn\'t match the expected ACK tag from RESP_CODE_SENT');
|
||||
debugPrint(' 3. The message was already delivered or timed out');
|
||||
debugPrint(' Searching all messages for debugging...');
|
||||
|
||||
// Debug: Search for any message with this ACK tag
|
||||
final matchingMessages = _messages.where((m) => m.expectedAckTag == ackCode).toList();
|
||||
if (matchingMessages.isNotEmpty) {
|
||||
print(' ⚠️ Found ${matchingMessages.length} message(s) with matching ACK tag but NOT in pending map:');
|
||||
debugPrint(' ⚠️ Found ${matchingMessages.length} message(s) with matching ACK tag but NOT in pending map:');
|
||||
for (final m in matchingMessages) {
|
||||
print(' - Message ID: ${m.id}, Status: ${m.deliveryStatus}, ACK: ${m.expectedAckTag}');
|
||||
debugPrint(' - Message ID: ${m.id}, Status: ${m.deliveryStatus}, ACK: ${m.expectedAckTag}');
|
||||
}
|
||||
print(' This indicates the message was sent but never added to _pendingSentMessages map');
|
||||
print(' Likely cause: markMessageSent() was not called with correct message ID');
|
||||
debugPrint(' This indicates the message was sent but never added to _pendingSentMessages map');
|
||||
debugPrint(' Likely cause: markMessageSent() was not called with correct message ID');
|
||||
} else {
|
||||
print(' No messages found with ACK tag $ackCode');
|
||||
print(' Recent sent messages:');
|
||||
debugPrint(' No messages found with ACK tag $ackCode');
|
||||
debugPrint(' Recent sent messages:');
|
||||
final sentMessages = _messages.where((m) => m.isSentMessage).take(5).toList();
|
||||
for (final m in sentMessages) {
|
||||
print(' - ID: ${m.id}, Status: ${m.deliveryStatus}, ACK: ${m.expectedAckTag}');
|
||||
debugPrint(' - ID: ${m.id}, Status: ${m.deliveryStatus}, ACK: ${m.expectedAckTag}');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -709,17 +709,17 @@ class MessagesProvider with ChangeNotifier {
|
||||
void markMessageFailed(String messageId) {
|
||||
final index = _messages.indexWhere((m) => m.id == messageId);
|
||||
if (index == -1) {
|
||||
print('⚠️ [MessagesProvider] markMessageFailed: Message not found: $messageId');
|
||||
debugPrint('⚠️ [MessagesProvider] markMessageFailed: Message not found: $messageId');
|
||||
return;
|
||||
}
|
||||
|
||||
final message = _messages[index];
|
||||
final contact = _messageContactMap[messageId];
|
||||
|
||||
print('❌ [MessagesProvider] Message $messageId timeout/failed');
|
||||
print(' Retry attempt: ${message.retryAttempt}');
|
||||
print(' Contact has path: ${contact?.hasPath ?? false}');
|
||||
print(' Used flood fallback: ${message.usedFloodFallback}');
|
||||
debugPrint('❌ [MessagesProvider] Message $messageId timeout/failed');
|
||||
debugPrint(' Retry attempt: ${message.retryAttempt}');
|
||||
debugPrint(' Contact has path: ${contact?.hasPath ?? false}');
|
||||
debugPrint(' Used flood fallback: ${message.usedFloodFallback}');
|
||||
|
||||
// Decision tree for retry/flood/fail
|
||||
if (contact != null && _retryManager.canRetry(message, contact)) {
|
||||
@@ -739,8 +739,8 @@ class MessagesProvider with ChangeNotifier {
|
||||
final nextAttempt = message.retryAttempt + 1;
|
||||
final timeout = _retryManager.getTimeoutForAttempt(message.retryAttempt);
|
||||
|
||||
print('🔄 [MessagesProvider] Scheduling retry $nextAttempt/3 for message $messageId');
|
||||
print(' Timeout: ${timeout}ms');
|
||||
debugPrint('🔄 [MessagesProvider] Scheduling retry $nextAttempt/3 for message $messageId');
|
||||
debugPrint(' Timeout: ${timeout}ms');
|
||||
|
||||
// Update message with new retry attempt
|
||||
final index = _messages.indexWhere((m) => m.id == messageId);
|
||||
@@ -765,7 +765,7 @@ class MessagesProvider with ChangeNotifier {
|
||||
|
||||
// Schedule actual retry after delay
|
||||
Timer(Duration(milliseconds: timeout), () async {
|
||||
print('⏰ [MessagesProvider] Executing retry $nextAttempt for message $messageId');
|
||||
debugPrint('⏰ [MessagesProvider] Executing retry $nextAttempt for message $messageId');
|
||||
if (sendMessageCallback != null) {
|
||||
await sendMessageCallback!(
|
||||
contactPublicKey: contact.publicKey,
|
||||
@@ -775,7 +775,7 @@ class MessagesProvider with ChangeNotifier {
|
||||
retryAttempt: nextAttempt,
|
||||
);
|
||||
} else {
|
||||
print('⚠️ [MessagesProvider] sendMessageCallback not set, cannot retry');
|
||||
debugPrint('⚠️ [MessagesProvider] sendMessageCallback not set, cannot retry');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -785,7 +785,7 @@ class MessagesProvider with ChangeNotifier {
|
||||
|
||||
/// Send message with flood mode as last resort
|
||||
Future<void> _sendWithFloodMode(String messageId, Message message, Contact contact) async {
|
||||
print('🌊 [MessagesProvider] Trying flood mode for message $messageId');
|
||||
debugPrint('🌊 [MessagesProvider] Trying flood mode for message $messageId');
|
||||
|
||||
final index = _messages.indexWhere((m) => m.id == messageId);
|
||||
if (index != -1) {
|
||||
@@ -813,7 +813,7 @@ class MessagesProvider with ChangeNotifier {
|
||||
retryAttempt: 0, // Reset attempt for flood
|
||||
);
|
||||
} else {
|
||||
print('⚠️ [MessagesProvider] sendMessageCallback not set, cannot send flood');
|
||||
debugPrint('⚠️ [MessagesProvider] sendMessageCallback not set, cannot send flood');
|
||||
}
|
||||
|
||||
_persistMessages();
|
||||
@@ -822,7 +822,7 @@ class MessagesProvider with ChangeNotifier {
|
||||
|
||||
/// Mark message as permanently failed
|
||||
void _markAsPermanentlyFailed(String messageId, Message message) {
|
||||
print('❌ [MessagesProvider] Message $messageId permanently failed');
|
||||
debugPrint('❌ [MessagesProvider] Message $messageId permanently failed');
|
||||
|
||||
final index = _messages.indexWhere((m) => m.id == messageId);
|
||||
if (index != -1) {
|
||||
@@ -849,7 +849,7 @@ class MessagesProvider with ChangeNotifier {
|
||||
Future<void> resendMessage(String messageId) async {
|
||||
final index = _messages.indexWhere((m) => m.id == messageId);
|
||||
if (index == -1) {
|
||||
print('⚠️ [MessagesProvider] resendMessage: Message not found: $messageId');
|
||||
debugPrint('⚠️ [MessagesProvider] resendMessage: Message not found: $messageId');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -857,11 +857,11 @@ class MessagesProvider with ChangeNotifier {
|
||||
final contact = _messageContactMap[messageId];
|
||||
|
||||
if (contact == null) {
|
||||
print('⚠️ [MessagesProvider] Cannot resend: Contact not found for message $messageId');
|
||||
debugPrint('⚠️ [MessagesProvider] Cannot resend: Contact not found for message $messageId');
|
||||
return;
|
||||
}
|
||||
|
||||
print('🔁 [MessagesProvider] Resending message $messageId');
|
||||
debugPrint('🔁 [MessagesProvider] Resending message $messageId');
|
||||
|
||||
// Reset retry state
|
||||
_messages[index] = message.copyWith(
|
||||
@@ -886,7 +886,7 @@ class MessagesProvider with ChangeNotifier {
|
||||
retryAttempt: 0,
|
||||
);
|
||||
} else {
|
||||
print('⚠️ [MessagesProvider] sendMessageCallback not set, cannot resend');
|
||||
debugPrint('⚠️ [MessagesProvider] sendMessageCallback not set, cannot resend');
|
||||
}
|
||||
|
||||
_persistMessages();
|
||||
|
||||
Reference in New Issue
Block a user