diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index f0a17392..39dcd915 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -3396,6 +3396,25 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep } return; } +#endif +#ifdef WITH_MQTT_BRIDGE + // bridge_enabled is stored with the common node preferences. Keep its + // MQTT-specific switch here rather than in the observer preferences + // handler, which must only write its own store. + if (strncmp(config, "mqtt.enabled ", 13) == 0) { + const char* value = config + 13; + if (strcmp(value, "on") != 0 && strcmp(value, "off") != 0) { + strcpy(reply, "Error: use set mqtt.enabled on|off"); + } else { + const bool enable = strcmp(value, "on") == 0; + _prefs->bridge_enabled = enable ? 1 : 0; + const bool applied = _callbacks->setMqttBridgeState(enable); + savePrefs(); + strcpy(reply, applied ? "OK" + : "Error: MQTT runtime change failed; setting saved"); + } + return; + } #endif // Observer/MQTT/WiFi/timezone/alert/SNMP commands live in CommonCLI_Observer.cpp. if (handleObserverSetCmd(sender_timestamp, config, reply)) return; diff --git a/src/helpers/CommonCLI_Observer.cpp b/src/helpers/CommonCLI_Observer.cpp index 11c2f58b..0b252909 100644 --- a/src/helpers/CommonCLI_Observer.cpp +++ b/src/helpers/CommonCLI_Observer.cpp @@ -182,20 +182,6 @@ static void formatMQTTPresetListReply(char* reply, size_t reply_size, int start) bool CommonCLI::handleObserverSetCmd(uint32_t sender_timestamp, const char* config, char* reply) { #ifdef WITH_MQTT_BRIDGE bool handled = true; - if (strncmp(config, "mqtt.enabled ", 13) == 0) { - const char* value = config + 13; - if (strcmp(value, "on") != 0 && strcmp(value, "off") != 0) { - strcpy(reply, "Error: use set mqtt.enabled on|off"); - } else { - const bool enable = strcmp(value, "on") == 0; - _prefs->bridge_enabled = enable ? 1 : 0; - const bool applied = _callbacks->setMqttBridgeState(enable); - savePrefs(); - strcpy(reply, applied ? "OK" - : "Error: MQTT runtime change failed; setting saved"); - } - return true; - } const auto restart_observer_bridge = [this]() { return mesh::cli::restartBridgeIfEnabled( _prefs->bridge_enabled != 0, diff --git a/test/test_cli_settings_contract.py b/test/test_cli_settings_contract.py index 10876bda..0fb2437f 100644 --- a/test/test_cli_settings_contract.py +++ b/test/test_cli_settings_contract.py @@ -63,6 +63,7 @@ COMMON_QUERY_EXCEPTIONS = { } OBSERVER_QUERY_EXCEPTIONS = { 'mqtt.config.valid': 'Configuration validation result', + 'mqtt.enabled': 'Stored in common NodePrefs; set mqtt.enabled is handled by CommonCLI', 'mqtt.ntp.diag': 'NTP diagnostics', 'mqtt.presets': 'List of available presets', 'mqtt.running': 'Live state; set mqtt.enabled controls intent', diff --git a/test/test_espnow_radio_lifecycle.py b/test/test_espnow_radio_lifecycle.py index 463b250e..255ff68b 100644 --- a/test/test_espnow_radio_lifecycle.py +++ b/test/test_espnow_radio_lifecycle.py @@ -120,7 +120,7 @@ class EspNowLifecycleTests(unittest.TestCase): self.assertIn('uint8_t espnow_bridge_enabled = 1;', prefs) self.assertIn('setEspNowBridgeState(enable)', common) self.assertIn('_prefs->espnow_bridge_enabled', common) - self.assertIn('setMqttBridgeState(enable)', observer) + self.assertIn('setMqttBridgeState(enable)', common) self.assertIn('isMqttBridgeRunning()', observer) for role in ('simple_repeater', 'simple_room_server'): header = (ROOT/f'examples/{role}/MyMesh.h').read_text()