From 2becbb342cbd80daf7d8f5750b9d19ec2c952e89 Mon Sep 17 00:00:00 2001 From: Winston Lowe Date: Mon, 19 Jan 2026 16:55:39 -0800 Subject: [PATCH] Added buildGetCustomVarsFrame And added update to refreshDeviceInfo and _requestDeviceInfo. Added parsing of Custom Vars --- lib/connector/meshcore_connector.dart | 34 +++++++++++++++++++++++++++ lib/connector/meshcore_protocol.dart | 7 ++++++ 2 files changed, 41 insertions(+) diff --git a/lib/connector/meshcore_connector.dart b/lib/connector/meshcore_connector.dart index 96fb229..15614b5 100644 --- a/lib/connector/meshcore_connector.dart +++ b/lib/connector/meshcore_connector.dart @@ -110,6 +110,7 @@ class MeshCoreConnector extends ChangeNotifier { int _queueSyncRetries = 0; static const int _maxQueueSyncRetries = 3; static const int _queueSyncTimeoutMs = 5000; // 5 second timeout + Map? _currentCustomVars; // Channel syncing state (sequential pattern) bool _isSyncingChannels = false; @@ -196,6 +197,7 @@ class MeshCoreConnector extends ChangeNotifier { int? get currentBwHz => _currentBwHz; int? get currentSf => _currentSf; int? get currentCr => _currentCr; + Map? get currentCustomVars => _currentCustomVars; int? get batteryMillivolts => _batteryMillivolts; int get maxContacts => _maxContacts; int get maxChannels => _maxChannels; @@ -952,6 +954,7 @@ class MeshCoreConnector extends ChangeNotifier { await sendFrame(buildAppStartFrame()); await requestBatteryStatus(force: true); await sendFrame(buildGetRadioSettingsFrame()); + await sendFrame(buildGetCustomVarsFrame()); _scheduleSelfInfoRetry(); } @@ -959,6 +962,7 @@ class MeshCoreConnector extends ChangeNotifier { _awaitingSelfInfo = true; await sendFrame(buildDeviceQueryFrame()); await sendFrame(buildAppStartFrame()); + await sendFrame(buildGetCustomVarsFrame()); await requestBatteryStatus(); _scheduleSelfInfoRetry(); @@ -1696,6 +1700,8 @@ class MeshCoreConnector extends ChangeNotifier { case respCodeBattAndStorage: _handleBatteryAndStorage(frame); break; + case respCodeCustomVars: + _handleCustomVars(frame); default: debugPrint('Unknown frame code: $code'); } @@ -3107,6 +3113,34 @@ class MeshCoreConnector extends ChangeNotifier { _scheduleReconnect(); } + Map _parseKeyValueString(String input) { + final result = {}; + + // Split on commas first – empty entries are ignored. + for (final pair in input.split(',')) { + final trimmedPair = pair.trim(); + if (trimmedPair.isEmpty) continue; + + // Each pair must contain exactly one ':'. + final separatorIndex = trimmedPair.indexOf(':'); + if (separatorIndex == -1) continue; // malformed, skip + + final key = trimmedPair.substring(0, separatorIndex).trim(); + final value = trimmedPair.substring(separatorIndex + 1).trim(); + + if (key.isNotEmpty) { + result[key] = value; + } + } + + return result; + } + + void _handleCustomVars(Uint8List frame) { + final buf = BufferReader(frame.sublist(1)); + _currentCustomVars = _parseKeyValueString(buf.readString()); + } + void _setState(MeshCoreConnectionState newState) { if (_state != newState) { _state = newState; diff --git a/lib/connector/meshcore_protocol.dart b/lib/connector/meshcore_protocol.dart index 21c4392..8469d61 100644 --- a/lib/connector/meshcore_protocol.dart +++ b/lib/connector/meshcore_protocol.dart @@ -129,6 +129,7 @@ const int cmdGetChannel = 31; const int cmdSetChannel = 32; const int cmdGetRadioSettings = 57; const int cmdGetTelemetryReq = 39; +const int cmdGetCustomVar = 40; const int cmdSetCustomVar = 41; const int cmdSendBinaryReq = 50; @@ -164,6 +165,7 @@ const int respCodeContactMsgRecvV3 = 16; const int respCodeChannelMsgRecvV3 = 17; const int respCodeChannelInfo = 18; const int respCodeRadioSettings = 25; +const int respCodeCustomVars = 21; // Push codes (async from device) const int pushCodeAdvert = 0x80; @@ -603,6 +605,11 @@ Uint8List buildGetRadioSettingsFrame() { return Uint8List.fromList([cmdGetRadioSettings]); } +//Build CMD_GET_CUSTOM_VARS frame +Uint8List buildGetCustomVarsFrame() { + return Uint8List.fromList([cmdGetCustomVar]); +} + // Calculate LoRa airtime for a packet // Based on Semtech SX127x datasheet formula // Returns airtime in milliseconds