feat: Enhance MeshCoreConnector with storage metrics and improve error handling

- Added storageUsedKb and storageTotalKb properties to MeshCoreConnector.
- Updated battery and storage frame parsing with improved error handling.
- Refactored log RX data handling to use BufferReader for better readability and error management.
- Enhanced message parsing in ChannelMessage and Message classes to utilize BufferReader.
- Introduced new text type for signed messages in meshcore_protocol.dart.
- Updated BLE debug log screen to use BufferReader for payload parsing.
- Refactored message retry service to handle ACK hashes as integers instead of Uint8List.
- Improved message storage serialization and deserialization to accommodate new expectedAckHash type.
- Added wasPulled property to Contact model for better state management.
This commit is contained in:
Winston Lowe
2026-03-21 13:01:02 -07:00
parent 1392c2d00f
commit dbefb0b5f4
11 changed files with 382 additions and 340 deletions
+13
View File
@@ -245,6 +245,19 @@ class BleDebugLogService extends ChangeNotifier {
}
}
// Helper to read uint32 little-endian
int readUint32LE(Uint8List data, int offset) {
return data[offset] |
(data[offset + 1] << 8) |
(data[offset + 2] << 16) |
(data[offset + 3] << 24);
}
// // Helper to read uint16 little-endian
int readUint16LE(Uint8List data, int offset) {
return data[offset] | (data[offset + 1] << 8);
}
String _frameDetail(int code, Uint8List frame) {
switch (code) {
case respCodeSent:
+12 -18
View File
@@ -11,7 +11,7 @@ import 'app_debug_log_service.dart';
class _AckHistoryEntry {
final String messageId;
final List<Uint8List> ackHashes;
final List<int> ackHashes;
final DateTime timestamp;
_AckHistoryEntry({
@@ -77,7 +77,7 @@ class MessageRetryService extends ChangeNotifier {
final Map<String, Contact> _pendingContacts = {};
final Map<String, List<PathSelection>> _attemptPathHistory = {};
final Map<String, AckHashMapping> _ackHashToMessageId = {};
final Map<String, List<Uint8List>> _expectedAckHashes = {};
final Map<String, List<int>> _expectedAckHashes = {};
final List<_AckHistoryEntry> _ackHistory = [];
final Map<String, List<String>> _sendQueue = {};
final Set<String> _activeMessages = {};
@@ -341,13 +341,11 @@ class MessageRetryService extends ChangeNotifier {
config.sendMessage(contact, message.text, attempt, timestampSeconds);
}
bool updateMessageFromSent(Uint8List ackHash, int timeoutMs) {
bool updateMessageFromSent(int ackHash, int timeoutMs) {
final config = _config;
if (config == null) return false;
final ackHashHex = ackHash
.map((b) => b.toRadixString(16).padLeft(2, '0'))
.join();
final ackHashHex = ackHash.toRadixString(16).padLeft(8, '0');
// Try hash-based matching (fixes LoRa message drops causing mismatches)
String? messageId = _expectedHashToMessageId.remove(ackHashHex);
@@ -389,10 +387,8 @@ class MessageRetryService extends ChangeNotifier {
// Add this ACK hash to the list of expected ACKs for this message (for history)
_expectedAckHashes[messageId] ??= [];
if (!_expectedAckHashes[messageId]!.any(
(hash) => listEquals(hash, ackHash),
)) {
_expectedAckHashes[messageId]!.add(Uint8List.fromList(ackHash));
if (!_expectedAckHashes[messageId]!.any((hash) => hash == ackHash)) {
_expectedAckHashes[messageId]!.add(ackHash);
}
// Calculate timeout: prefer ML prediction, then device-provided, then physics fallback
@@ -559,10 +555,10 @@ class MessageRetryService extends ChangeNotifier {
}
}
bool _checkAckHistory(Uint8List ackHash) {
bool _checkAckHistory(int ackHash) {
for (final entry in _ackHistory) {
for (final expectedHash in entry.ackHashes) {
if (listEquals(expectedHash, ackHash)) {
if (expectedHash == ackHash) {
return true;
}
}
@@ -570,13 +566,11 @@ class MessageRetryService extends ChangeNotifier {
return false;
}
void handleAckReceived(Uint8List ackHash, int tripTimeMs) {
void handleAckReceived(int ackHash, int tripTimeMs) {
final config = _config;
String? matchedMessageId;
int? matchedAttemptIndex;
final ackHashHex = ackHash
.map((b) => b.toRadixString(16).padLeft(2, '0'))
.join();
final ackHashHex = ackHash.toRadixString(16).padLeft(8, '0');
// Clean up old ACK hash mappings (older than 15 minutes)
final cutoffTime = DateTime.now().subtract(const Duration(minutes: 15));
@@ -606,7 +600,7 @@ class MessageRetryService extends ChangeNotifier {
final expectedHashes = entry.value;
for (final expectedHash in expectedHashes) {
if (listEquals(expectedHash, ackHash)) {
if (expectedHash == ackHash) {
matchedMessageId = messageId;
matchedAttemptIndex = expectedHashes.indexOf(expectedHash);
break;
@@ -689,7 +683,7 @@ class MessageRetryService extends ChangeNotifier {
for (var entry in _pendingMessages.entries) {
final message = entry.value;
if (message.expectedAckHash != null &&
listEquals(message.expectedAckHash, ackHash)) {
message.expectedAckHash == ackHash) {
final contact = _pendingContacts[entry.key];
return contact?.publicKeyHex;
}