Refactor message handling and enhance BLE connection management

- Cleaned up message formatting in MessagesTab for better readability.
- Improved SAR message parsing to include optional inline messages.
- Updated BLE connection manager to monitor RSSI values and added callback for RSSI updates.
- Adjusted drawing message parser to remove sender name from JSON and extract it from packet metadata.
- Enhanced drawing toolbar to reflect changes in message creation without sender name.
- Ensured consistent error handling and logging across BLE operations.
This commit is contained in:
Janez T
2025-10-16 13:32:58 +02:00
parent 5a096c048e
commit 23c439a92e
28 changed files with 957 additions and 4730 deletions

View File

@@ -6,6 +6,7 @@ import '../meshcore_constants.dart';
typedef OnConnectionStateCallback = void Function(bool isConnected);
typedef OnErrorCallback = void Function(String error);
typedef OnReconnectionAttemptCallback = void Function(int attemptNumber, int maxAttempts);
typedef OnRssiUpdateCallback = void Function(int rssi);
/// Manages BLE connection lifecycle with automatic reconnection
class BleConnectionManager {
@@ -21,6 +22,10 @@ class BleConnectionManager {
Timer? _reconnectionTimer;
StreamSubscription<BluetoothConnectionState>? _connectionStateSubscription;
// RSSI monitoring
Timer? _rssiTimer;
int? _lastRssi;
// SAR-optimized reconnection: ~15 minutes total
// Pattern: Fast retries first (for temporary issues), then slower retries (for extended disconnections)
static const int _maxReconnectionAttempts = 30;
@@ -38,6 +43,7 @@ class BleConnectionManager {
OnConnectionStateCallback? onConnectionStateChanged;
OnErrorCallback? onError;
OnReconnectionAttemptCallback? onReconnectionAttempt;
OnRssiUpdateCallback? onRssiUpdate;
// Getters
bool get isConnected => _isConnected;
@@ -49,7 +55,7 @@ class BleConnectionManager {
BluetoothCharacteristic? get txCharacteristic => _txCharacteristic;
/// Scan for MeshCore devices
Stream<BluetoothDevice> scanForDevices({Duration timeout = const Duration(seconds: 10)}) async* {
Stream<ScanResult> scanForDevices({Duration timeout = const Duration(seconds: 10)}) async* {
try {
print('🔍 [BLE] Starting scan for MeshCore devices...');
print(' Service UUID: ${MeshCoreConstants.bleServiceUuid}');
@@ -73,7 +79,7 @@ class BleConnectionManager {
.contains(Guid(MeshCoreConstants.bleServiceUuid))) {
deviceCount++;
print(' ✅ MeshCore device found! Total: $deviceCount');
yield result.device;
yield result;
} else {
print(' ❌ Not a MeshCore device (service UUID mismatch)');
}
@@ -170,6 +176,9 @@ class BleConnectionManager {
// Monitor connection state for automatic reconnection
_setupConnectionMonitoring();
// Start RSSI monitoring
_startRssiMonitoring();
print('✅✅✅ [BLE] Connection completed successfully!');
return true;
} catch (e) {
@@ -189,6 +198,7 @@ class BleConnectionManager {
// Disable reconnection before disconnecting
_reconnectionEnabled = false;
_cancelReconnection();
_stopRssiMonitoring();
await _device?.disconnect();
_isConnected = false;
@@ -317,10 +327,40 @@ class BleConnectionManager {
_reconnectionEnabled = true;
}
/// Start monitoring RSSI in the background
void _startRssiMonitoring() {
print('📡 [BLE] Starting RSSI monitoring (every 5 seconds)');
_stopRssiMonitoring(); // Cancel any existing timer
_rssiTimer = Timer.periodic(const Duration(seconds: 5), (timer) async {
if (_device != null && _isConnected) {
try {
final rssi = await _device!.readRssi();
if (_lastRssi != rssi) {
_lastRssi = rssi;
print('📡 [BLE] RSSI updated: $rssi dBm');
onRssiUpdate?.call(rssi);
}
} catch (e) {
print('⚠️ [BLE] Failed to read RSSI: $e');
}
}
});
}
/// Stop RSSI monitoring
void _stopRssiMonitoring() {
_rssiTimer?.cancel();
_rssiTimer = null;
_lastRssi = null;
print('📡 [BLE] RSSI monitoring stopped');
}
/// Dispose resources
void dispose() {
print('🔴 [BLE] Disposing BLE connection manager');
_cancelReconnection();
_stopRssiMonitoring();
_device = null;
_rxCharacteristic = null;
_txCharacteristic = null;

View File

@@ -31,6 +31,7 @@ typedef OnBatteryAndStorageCallback = void Function(int millivolts, int? usedKb,
typedef OnErrorCallback = void Function(String error);
typedef OnConnectionStateCallback = void Function(bool isConnected);
typedef OnReconnectionAttemptCallback = void Function(int attemptNumber, int maxAttempts);
typedef OnRssiUpdateCallback = void Function(int rssi);
/// MeshCore BLE Service - coordinates BLE communication components
class MeshCoreBleService {
@@ -42,6 +43,7 @@ class MeshCoreBleService {
// Event callbacks
OnConnectionStateCallback? onConnectionStateChanged;
OnReconnectionAttemptCallback? onReconnectionAttempt;
OnRssiUpdateCallback? onRssiUpdate;
OnContactCallback? onContactReceived;
OnContactsCompleteCallback? onContactsComplete;
OnMessageCallback? onMessageReceived;
@@ -83,6 +85,9 @@ class MeshCoreBleService {
print('🔄 [Service] Reconnection attempt $attemptNumber/$maxAttempts');
onReconnectionAttempt?.call(attemptNumber, maxAttempts);
};
_connectionManager.onRssiUpdate = (rssi) {
onRssiUpdate?.call(rssi);
};
// Command sender callbacks
_commandSender.onError = (error) {
@@ -167,7 +172,7 @@ class MeshCoreBleService {
}
/// Scan for MeshCore devices
Stream<BluetoothDevice> scanForDevices({Duration timeout = const Duration(seconds: 10)}) {
Stream<ScanResult> scanForDevices({Duration timeout = const Duration(seconds: 10)}) {
return _connectionManager.scanForDevices(timeout: timeout);
}