mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
feat: Enhance message sending feedback and improve reconnection logic with optimized delays
This commit is contained in:
@@ -522,10 +522,19 @@ class ConnectionProvider with ChangeNotifier {
|
|||||||
// Channel messages are ephemeral (not persisted) - mark as "sent" immediately
|
// Channel messages are ephemeral (not persisted) - mark as "sent" immediately
|
||||||
// They don't have ACK/TAG mechanism like direct messages
|
// They don't have ACK/TAG mechanism like direct messages
|
||||||
if (messageId != null) {
|
if (messageId != null) {
|
||||||
print('✅ [Provider] Channel message sent successfully - marking as sent: $messageId');
|
print('✅ [ConnectionProvider] Channel message sent successfully');
|
||||||
|
print(' Message ID: $messageId');
|
||||||
|
print(' onMessageSent callback exists: ${onMessageSent != null}');
|
||||||
|
|
||||||
|
// Small delay to ensure the message is in the MessagesProvider list
|
||||||
|
// before we try to mark it as sent
|
||||||
|
await Future.delayed(const Duration(milliseconds: 50));
|
||||||
|
|
||||||
// Use a dummy ACK tag (0) and timeout (0) for channel messages
|
// Use a dummy ACK tag (0) and timeout (0) for channel messages
|
||||||
// This will trigger the callback to mark the message as "sent"
|
// This will trigger the callback to mark the message as "sent"
|
||||||
|
print(' Calling onMessageSent callback...');
|
||||||
onMessageSent?.call(messageId, 0, 0);
|
onMessageSent?.call(messageId, 0, 0);
|
||||||
|
print(' onMessageSent callback completed');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
_error = 'Failed to send channel message: $e';
|
_error = 'Failed to send channel message: $e';
|
||||||
|
|||||||
@@ -334,6 +334,12 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
|
|
||||||
/// Add a sent message with initial status
|
/// Add a sent message with initial status
|
||||||
void addSentMessage(Message message) {
|
void addSentMessage(Message message) {
|
||||||
|
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)}...');
|
||||||
|
|
||||||
// Always enhance message with SAR parser to detect SAR markers
|
// Always enhance message with SAR parser to detect SAR markers
|
||||||
final enhancedMessage = SarMessageParser.enhanceMessage(message);
|
final enhancedMessage = SarMessageParser.enhanceMessage(message);
|
||||||
|
|
||||||
@@ -348,6 +354,8 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
deliveryStatus: MessageDeliveryStatus.sending,
|
deliveryStatus: MessageDeliveryStatus.sending,
|
||||||
);
|
);
|
||||||
_messages.add(sendingMessage);
|
_messages.add(sendingMessage);
|
||||||
|
print(' ✅ Message added to list at index ${_messages.length - 1}');
|
||||||
|
print(' Total messages in list: ${_messages.length}');
|
||||||
|
|
||||||
// If it's a SAR marker message, extract and store the marker
|
// If it's a SAR marker message, extract and store the marker
|
||||||
if (sendingMessage.isSarMarker) {
|
if (sendingMessage.isSarMarker) {
|
||||||
@@ -359,6 +367,7 @@ class MessagesProvider with ChangeNotifier {
|
|||||||
|
|
||||||
_persistMessages();
|
_persistMessages();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
print(' ✅ notifyListeners() called - UI should update');
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update message status to sent with ACK tag
|
/// Update message status to sent with ACK tag
|
||||||
|
|||||||
@@ -20,8 +20,19 @@ class BleConnectionManager {
|
|||||||
int _reconnectionAttempt = 0;
|
int _reconnectionAttempt = 0;
|
||||||
Timer? _reconnectionTimer;
|
Timer? _reconnectionTimer;
|
||||||
StreamSubscription<BluetoothConnectionState>? _connectionStateSubscription;
|
StreamSubscription<BluetoothConnectionState>? _connectionStateSubscription;
|
||||||
static const int _maxReconnectionAttempts = 5;
|
|
||||||
static const List<int> _reconnectionDelaysMs = [1000, 2000, 3000, 5000, 10000]; // Exponential backoff
|
// SAR-optimized reconnection: ~15 minutes total
|
||||||
|
// Pattern: Fast retries first (for temporary issues), then slower retries (for extended disconnections)
|
||||||
|
static const int _maxReconnectionAttempts = 30;
|
||||||
|
static const List<int> _reconnectionDelaysMs = [
|
||||||
|
2000, // 2s - immediate retry
|
||||||
|
3000, // 3s - quick retry
|
||||||
|
5000, // 5s - fast retry
|
||||||
|
10000, // 10s - moderate retry
|
||||||
|
15000, // 15s - longer retry
|
||||||
|
30000, // 30s - extended retry
|
||||||
|
30000, // 30s - keep trying every 30s after this
|
||||||
|
]; // Total: ~15 minutes of reconnection attempts
|
||||||
|
|
||||||
// Callbacks
|
// Callbacks
|
||||||
OnConnectionStateCallback? onConnectionStateChanged;
|
OnConnectionStateCallback? onConnectionStateChanged;
|
||||||
@@ -234,17 +245,17 @@ class BleConnectionManager {
|
|||||||
onReconnectionAttempt?.call(_reconnectionAttempt, _maxReconnectionAttempts);
|
onReconnectionAttempt?.call(_reconnectionAttempt, _maxReconnectionAttempts);
|
||||||
|
|
||||||
if (_reconnectionAttempt > _maxReconnectionAttempts) {
|
if (_reconnectionAttempt > _maxReconnectionAttempts) {
|
||||||
print('❌ [BLE] Max reconnection attempts reached. Giving up.');
|
print('❌ [BLE] Max reconnection attempts reached after ~15 minutes. Giving up.');
|
||||||
_isReconnecting = false;
|
_isReconnecting = false;
|
||||||
onError?.call('Connection lost. Max reconnection attempts ($_maxReconnectionAttempts) reached.');
|
onError?.call('Connection lost. Unable to reconnect after 15 minutes ($_maxReconnectionAttempts attempts).');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate delay with exponential backoff
|
// Calculate delay with exponential backoff (uses last delay for attempts beyond array length)
|
||||||
final delayIndex = (_reconnectionAttempt - 1).clamp(0, _reconnectionDelaysMs.length - 1);
|
final delayIndex = (_reconnectionAttempt - 1).clamp(0, _reconnectionDelaysMs.length - 1);
|
||||||
final delayMs = _reconnectionDelaysMs[delayIndex];
|
final delayMs = _reconnectionDelaysMs[delayIndex];
|
||||||
|
|
||||||
print('🔄 [BLE] Waiting ${delayMs}ms before reconnection attempt $_reconnectionAttempt...');
|
print('🔄 [BLE] Waiting ${(delayMs / 1000).toStringAsFixed(0)}s before reconnection attempt $_reconnectionAttempt...');
|
||||||
|
|
||||||
// Wait before attempting reconnection
|
// Wait before attempting reconnection
|
||||||
_reconnectionTimer = Timer(Duration(milliseconds: delayMs), () async {
|
_reconnectionTimer = Timer(Duration(milliseconds: delayMs), () async {
|
||||||
@@ -272,7 +283,7 @@ class BleConnectionManager {
|
|||||||
if (_reconnectionAttempt < _maxReconnectionAttempts) {
|
if (_reconnectionAttempt < _maxReconnectionAttempts) {
|
||||||
_attemptReconnection();
|
_attemptReconnection();
|
||||||
} else {
|
} else {
|
||||||
onError?.call('Connection lost. Unable to reconnect after $_maxReconnectionAttempts attempts.');
|
onError?.call('Connection lost. Unable to reconnect after 15 minutes ($_maxReconnectionAttempts attempts).');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -283,7 +294,7 @@ class BleConnectionManager {
|
|||||||
if (_reconnectionAttempt < _maxReconnectionAttempts) {
|
if (_reconnectionAttempt < _maxReconnectionAttempts) {
|
||||||
_attemptReconnection();
|
_attemptReconnection();
|
||||||
} else {
|
} else {
|
||||||
onError?.call('Connection lost. Unable to reconnect: $e');
|
onError?.call('Connection lost. Unable to reconnect after 15 minutes: $e');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user