Added buildGetCustomVarsFrame

And added update to refreshDeviceInfo and _requestDeviceInfo.
Added parsing of Custom Vars
This commit is contained in:
Winston Lowe 2026-01-19 16:55:39 -08:00
parent 714aecd7e6
commit 2becbb342c
2 changed files with 41 additions and 0 deletions

View file

@ -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<String, String>? _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<String, String>? 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<String, String> _parseKeyValueString(String input) {
final result = <String, String>{};
// 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;

View file

@ -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