From 2358245c0404cc134712f251323bacebda9ea54a Mon Sep 17 00:00:00 2001 From: Jared Dohrman Date: Thu, 9 Jul 2026 17:10:04 +1000 Subject: [PATCH] fix(prefs): realign NodePrefs to upstream byte offsets Keep upstream's persisted layout verbatim (rx_boosted_gain 290 .. cad_enabled 294) and append the EastMesh-only fields after it, rather than interleaving fan_mode/fan_timeout_secs into upstream's range. Minimises CommonCLI.cpp conflicts on every upstream sync. EastMesh fields now occupy 295..524: fan_mode, fan_timeout_secs, and bridge_peer_*. Existing prefs files written by prior EastMesh firmware will be misread from offset 292 onward and need reconfiguring. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/helpers/CommonCLI.cpp | 60 +++++++++++++++++---------------------- src/helpers/CommonCLI.h | 3 +- 2 files changed, 28 insertions(+), 35 deletions(-) diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index 6499d2e6..0ab1bef7 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -88,38 +88,29 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) { file.read((uint8_t *)&_prefs->discovery_mod_timestamp, sizeof(_prefs->discovery_mod_timestamp)); // 162 file.read((uint8_t *)&_prefs->adc_multiplier, sizeof(_prefs->adc_multiplier)); // 166 file.read((uint8_t *)_prefs->owner_info, sizeof(_prefs->owner_info)); // 170 - if (file.available() >= (int)sizeof(_prefs->rx_boosted_gain)) { - file.read((uint8_t *)&_prefs->rx_boosted_gain, sizeof(_prefs->rx_boosted_gain)); // 290 - } - if (file.available() >= (int)sizeof(_prefs->flood_max_unscoped)) { - file.read((uint8_t *)&_prefs->flood_max_unscoped, sizeof(_prefs->flood_max_unscoped)); // 291 - } + file.read((uint8_t *)&_prefs->rx_boosted_gain, sizeof(_prefs->rx_boosted_gain)); // 290 + file.read((uint8_t *)&_prefs->flood_max_unscoped, sizeof(_prefs->flood_max_unscoped)); // 291 + file.read((uint8_t *)&_prefs->flood_max_advert, sizeof(_prefs->flood_max_advert)); // 292 + file.read((uint8_t *)&_prefs->radio_fem_rxgain, sizeof(_prefs->radio_fem_rxgain)); // 293 + file.read((uint8_t *)&_prefs->cad_enabled, sizeof(_prefs->cad_enabled)); // 294 + // upstream layout ends at 295; EastMesh-only fields are appended below if (file.available() >= (int)sizeof(_prefs->fan_mode)) { - file.read((uint8_t *)&_prefs->fan_mode, sizeof(_prefs->fan_mode)); // 292 + file.read((uint8_t *)&_prefs->fan_mode, sizeof(_prefs->fan_mode)); // 295 } if (file.available() >= (int)sizeof(_prefs->fan_timeout_secs)) { - file.read((uint8_t *)&_prefs->fan_timeout_secs, sizeof(_prefs->fan_timeout_secs)); // 293 - } - if (file.available() >= (int)sizeof(_prefs->flood_max_advert)) { - file.read((uint8_t *)&_prefs->flood_max_advert, sizeof(_prefs->flood_max_advert)); // 295 + file.read((uint8_t *)&_prefs->fan_timeout_secs, sizeof(_prefs->fan_timeout_secs)); // 296 } if (file.available() >= (int)sizeof(_prefs->bridge_peer_host)) { - file.read((uint8_t *)&_prefs->bridge_peer_host, sizeof(_prefs->bridge_peer_host)); // 296 + file.read((uint8_t *)&_prefs->bridge_peer_host, sizeof(_prefs->bridge_peer_host)); // 298 } if (file.available() >= (int)sizeof(_prefs->bridge_peer_port)) { - file.read((uint8_t *)&_prefs->bridge_peer_port, sizeof(_prefs->bridge_peer_port)); // 360 + file.read((uint8_t *)&_prefs->bridge_peer_port, sizeof(_prefs->bridge_peer_port)); // 362 } if (file.available() >= (int)sizeof(_prefs->bridge_peer_username)) { - file.read((uint8_t *)&_prefs->bridge_peer_username, sizeof(_prefs->bridge_peer_username)); // 362 + file.read((uint8_t *)&_prefs->bridge_peer_username, sizeof(_prefs->bridge_peer_username)); // 364 } if (file.available() >= (int)sizeof(_prefs->bridge_peer_password)) { - file.read((uint8_t *)&_prefs->bridge_peer_password, sizeof(_prefs->bridge_peer_password)); // 427 - } - if (file.available() >= (int)sizeof(_prefs->radio_fem_rxgain)) { - file.read((uint8_t *)&_prefs->radio_fem_rxgain, sizeof(_prefs->radio_fem_rxgain)); // 523 - } - if (file.available() >= (int)sizeof(_prefs->cad_enabled)) { - file.read((uint8_t *)&_prefs->cad_enabled, sizeof(_prefs->cad_enabled)); // 524 + file.read((uint8_t *)&_prefs->bridge_peer_password, sizeof(_prefs->bridge_peer_password)); // 429 } // next: 525 @@ -151,10 +142,10 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) { // sanitise settings _prefs->rx_boosted_gain = constrain(_prefs->rx_boosted_gain, 0, 1); // boolean - _prefs->fan_mode = constrain(_prefs->fan_mode, 0, 2); - _prefs->fan_timeout_secs = constrain(_prefs->fan_timeout_secs, 0, 600); _prefs->radio_fem_rxgain = constrain(_prefs->radio_fem_rxgain, 0, 1); // boolean _prefs->cad_enabled = constrain(_prefs->cad_enabled, 0, 1); // boolean + _prefs->fan_mode = constrain(_prefs->fan_mode, 0, 2); + _prefs->fan_timeout_secs = constrain(_prefs->fan_timeout_secs, 0, 600); file.close(); } @@ -215,17 +206,18 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) { file.write((uint8_t *)&_prefs->discovery_mod_timestamp, sizeof(_prefs->discovery_mod_timestamp)); // 162 file.write((uint8_t *)&_prefs->adc_multiplier, sizeof(_prefs->adc_multiplier)); // 166 file.write((uint8_t *)_prefs->owner_info, sizeof(_prefs->owner_info)); // 170 - file.write((uint8_t *)&_prefs->rx_boosted_gain, sizeof(_prefs->rx_boosted_gain)); // 290 - file.write((uint8_t *)&_prefs->flood_max_unscoped, sizeof(_prefs->flood_max_unscoped)); // 291 - file.write((uint8_t *)&_prefs->fan_mode, sizeof(_prefs->fan_mode)); // 292 - file.write((uint8_t *)&_prefs->fan_timeout_secs, sizeof(_prefs->fan_timeout_secs)); // 293 - file.write((uint8_t *)&_prefs->flood_max_advert, sizeof(_prefs->flood_max_advert)); // 295 - file.write((uint8_t *)&_prefs->bridge_peer_host, sizeof(_prefs->bridge_peer_host)); // 296 - file.write((uint8_t *)&_prefs->bridge_peer_port, sizeof(_prefs->bridge_peer_port)); // 360 - file.write((uint8_t *)&_prefs->bridge_peer_username, sizeof(_prefs->bridge_peer_username)); // 362 - file.write((uint8_t *)&_prefs->bridge_peer_password, sizeof(_prefs->bridge_peer_password)); // 427 - file.write((uint8_t *)&_prefs->radio_fem_rxgain, sizeof(_prefs->radio_fem_rxgain)); // 523 - file.write((uint8_t *)&_prefs->cad_enabled, sizeof(_prefs->cad_enabled)); // 524 + file.write((uint8_t *)&_prefs->rx_boosted_gain, sizeof(_prefs->rx_boosted_gain)); // 290 + file.write((uint8_t *)&_prefs->flood_max_unscoped, sizeof(_prefs->flood_max_unscoped)); // 291 + file.write((uint8_t *)&_prefs->flood_max_advert, sizeof(_prefs->flood_max_advert)); // 292 + file.write((uint8_t *)&_prefs->radio_fem_rxgain, sizeof(_prefs->radio_fem_rxgain)); // 293 + file.write((uint8_t *)&_prefs->cad_enabled, sizeof(_prefs->cad_enabled)); // 294 + // upstream layout ends at 295; EastMesh-only fields are appended below + file.write((uint8_t *)&_prefs->fan_mode, sizeof(_prefs->fan_mode)); // 295 + file.write((uint8_t *)&_prefs->fan_timeout_secs, sizeof(_prefs->fan_timeout_secs)); // 296 + file.write((uint8_t *)&_prefs->bridge_peer_host, sizeof(_prefs->bridge_peer_host)); // 298 + file.write((uint8_t *)&_prefs->bridge_peer_port, sizeof(_prefs->bridge_peer_port)); // 362 + file.write((uint8_t *)&_prefs->bridge_peer_username, sizeof(_prefs->bridge_peer_username)); // 364 + file.write((uint8_t *)&_prefs->bridge_peer_password, sizeof(_prefs->bridge_peer_password)); // 429 // next: 525 file.close(); diff --git a/src/helpers/CommonCLI.h b/src/helpers/CommonCLI.h index d5e00ece..52a2653f 100644 --- a/src/helpers/CommonCLI.h +++ b/src/helpers/CommonCLI.h @@ -64,13 +64,14 @@ struct NodePrefs { // persisted to file uint8_t radio_fem_rxgain; // LoRa FEM RX gain setting uint8_t path_hash_mode; // which path mode to use when sending uint8_t loop_detect; + uint8_t cad_enabled; // hardware Channel Activity Detection before TX (boolean) + // EastMesh-only fields, appended after the upstream layout uint8_t fan_mode; uint16_t fan_timeout_secs; char bridge_peer_host[64]; // peer MQTT broker host (MQTT bridge only) uint16_t bridge_peer_port; // peer MQTT broker port (MQTT bridge only, default 1883) char bridge_peer_username[65]; // peer MQTT broker username (MQTT bridge only) char bridge_peer_password[96]; // peer MQTT broker password (MQTT bridge only) - uint8_t cad_enabled; // hardware Channel Activity Detection before TX (boolean) }; class CommonCLICallbacks {