fix(mqtt): align legacy CLI with slot prefs and restore isConfigValid

Map mqtt.server/port/username/password to slot 3 (index 2) and analyzer
toggles to slot presets. Add MQTTBridge::isConfigValid matching bridge
startup rules.

Made-with: Cursor
This commit is contained in:
agessaman committed 2026-04-21 21:44:03 -07:00
1 parent d6712c69c8
commit ac2662c573
3 files changed
+53 -12

No files matched your search

+37 -12
View File
@@ -1389,33 +1389,58 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
sprintf(reply, "unknown config: %s", config);
}
} else if (memcmp(config, "mqtt.server ", 12) == 0) {
StrHelper::strncpy(_prefs->mqtt_server, &config[12], sizeof(_prefs->mqtt_server));
// Legacy single-broker CLI → slot 3 (index 2), same layout as old prefs migration.
const int legacy_slot = 2;
StrHelper::strncpy(_prefs->mqtt_slot_host[legacy_slot], &config[12], sizeof(_prefs->mqtt_slot_host[legacy_slot]));
StrHelper::strncpy(_prefs->mqtt_slot_preset[legacy_slot], MQTT_PRESET_CUSTOM, sizeof(_prefs->mqtt_slot_preset[legacy_slot]));
savePrefs();
_callbacks->restartBridgeSlot(legacy_slot);
strcpy(reply, "OK");
} else if (memcmp(config, "mqtt.port ", 10) == 0) {
const int legacy_slot = 2;
int port = atoi(&config[10]);
if (port > 0 && port <= 65535) {
_prefs->mqtt_port = port;
_prefs->mqtt_slot_port[legacy_slot] = (uint16_t)port;
StrHelper::strncpy(_prefs->mqtt_slot_preset[legacy_slot], MQTT_PRESET_CUSTOM, sizeof(_prefs->mqtt_slot_preset[legacy_slot]));
savePrefs();
_callbacks->restartBridgeSlot(legacy_slot);
strcpy(reply, "OK");
} else {
strcpy(reply, "Error: port must be between 1 and 65535");
}
} else if (memcmp(config, "mqtt.username ", 14) == 0) {
StrHelper::strncpy(_prefs->mqtt_username, &config[14], sizeof(_prefs->mqtt_username));
const int legacy_slot = 2;
StrHelper::strncpy(_prefs->mqtt_slot_username[legacy_slot], &config[14], sizeof(_prefs->mqtt_slot_username[legacy_slot]));
StrHelper::strncpy(_prefs->mqtt_slot_preset[legacy_slot], MQTT_PRESET_CUSTOM, sizeof(_prefs->mqtt_slot_preset[legacy_slot]));
savePrefs();
_callbacks->restartBridgeSlot(legacy_slot);
strcpy(reply, "OK");
} else if (memcmp(config, "mqtt.password ", 14) == 0) {
StrHelper::strncpy(_prefs->mqtt_password, &config[14], sizeof(_prefs->mqtt_password));
const int legacy_slot = 2;
StrHelper::strncpy(_prefs->mqtt_slot_password[legacy_slot], &config[14], sizeof(_prefs->mqtt_slot_password[legacy_slot]));
StrHelper::strncpy(_prefs->mqtt_slot_preset[legacy_slot], MQTT_PRESET_CUSTOM, sizeof(_prefs->mqtt_slot_preset[legacy_slot]));
savePrefs();
_callbacks->restartBridgeSlot(legacy_slot);
strcpy(reply, "OK");
} else if (memcmp(config, "mqtt.analyzer.us ", 17) == 0) {
_prefs->mqtt_analyzer_us_enabled = memcmp(&config[17], "on", 2) == 0;
const int slot = 0;
if (memcmp(&config[17], "on", 2) == 0) {
StrHelper::strncpy(_prefs->mqtt_slot_preset[slot], "analyzer-us", sizeof(_prefs->mqtt_slot_preset[slot]));
} else {
StrHelper::strncpy(_prefs->mqtt_slot_preset[slot], MQTT_PRESET_NONE, sizeof(_prefs->mqtt_slot_preset[slot]));
}
savePrefs();
_callbacks->restartBridgeSlot(slot);
strcpy(reply, "OK");
} else if (memcmp(config, "mqtt.analyzer.eu ", 17) == 0) {
_prefs->mqtt_analyzer_eu_enabled = memcmp(&config[17], "on", 2) == 0;
const int slot = 1;
if (memcmp(&config[17], "on", 2) == 0) {
StrHelper::strncpy(_prefs->mqtt_slot_preset[slot], "analyzer-eu", sizeof(_prefs->mqtt_slot_preset[slot]));
} else {
StrHelper::strncpy(_prefs->mqtt_slot_preset[slot], MQTT_PRESET_NONE, sizeof(_prefs->mqtt_slot_preset[slot]));
}
savePrefs();
_callbacks->restartBridgeSlot(slot);
strcpy(reply, "OK");
} else if (memcmp(config, "mqtt.owner ", 11) == 0) {
const char* owner_key = &config[11];
@@ -1636,13 +1661,13 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep
sprintf(reply, "??: %s", config);
}
} else if (memcmp(config, "mqtt.server", 11) == 0) {
sprintf(reply, "> %s", _prefs->mqtt_server);
sprintf(reply, "> %s", _prefs->mqtt_slot_host[2]);
} else if (memcmp(config, "mqtt.port", 9) == 0) {
sprintf(reply, "> %d", _prefs->mqtt_port);
sprintf(reply, "> %d", (int)_prefs->mqtt_slot_port[2]);
} else if (memcmp(config, "mqtt.username", 13) == 0) {
sprintf(reply, "> %s", _prefs->mqtt_username);
sprintf(reply, "> %s", _prefs->mqtt_slot_username[2]);
} else if (memcmp(config, "mqtt.password", 13) == 0) {
sprintf(reply, "> %s", _prefs->mqtt_password);
sprintf(reply, "> %s", _prefs->mqtt_slot_password[2]);
} else if (memcmp(config, "wifi.ssid", 9) == 0) {
sprintf(reply, "> %s", _prefs->wifi_ssid);
} else if (memcmp(config, "wifi.pwd", 8) == 0) {
@@ -1709,9 +1734,9 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep
} else if (memcmp(config, "timezone.offset", 15) == 0) {
sprintf(reply, "> %d", _prefs->timezone_offset);
} else if (memcmp(config, "mqtt.analyzer.us", 17) == 0) {
sprintf(reply, "> %s", _prefs->mqtt_analyzer_us_enabled ? "on" : "off");
sprintf(reply, "> %s", strcmp(_prefs->mqtt_slot_preset[0], "analyzer-us") == 0 ? "on" : "off");
} else if (memcmp(config, "mqtt.analyzer.eu", 17) == 0) {
sprintf(reply, "> %s", _prefs->mqtt_analyzer_eu_enabled ? "on" : "off");
sprintf(reply, "> %s", strcmp(_prefs->mqtt_slot_preset[1], "analyzer-eu") == 0 ? "on" : "off");
} else if (sender_timestamp == 0 && memcmp(config, "mqtt.owner", 10) == 0) {
if (_prefs->mqtt_owner_public_key[0] != '\0') {
sprintf(reply, "> %s", _prefs->mqtt_owner_public_key);
+14
View File
@@ -51,6 +51,20 @@ static bool isWiFiConfigValid(const NodePrefs* prefs) {
#ifdef WITH_MQTT_BRIDGE
bool MQTTBridge::isConfigValid(const NodePrefs* prefs) {
if (!prefs || !isWiFiConfigValid(prefs)) return false;
for (int i = 0; i < RUNTIME_MQTT_SLOTS; i++) {
const char* preset_name = prefs->mqtt_slot_preset[i];
if (preset_name[0] == '\0' || strcmp(preset_name, MQTT_PRESET_NONE) == 0) continue;
if (strcmp(preset_name, MQTT_PRESET_CUSTOM) == 0) {
if (prefs->mqtt_slot_host[i][0] != '\0' && prefs->mqtt_slot_port[i] != 0) return true;
} else if (findMQTTPreset(preset_name) != nullptr) {
return true;
}
}
return false;
}
// Optional embedded CA bundle symbols produced by board_build.embed_files.
// Weak linkage keeps non-bundle builds linkable and allows runtime fallback.
extern const uint8_t rootca_crt_bundle_start[] asm("_binary_src_certs_x509_crt_bundle_bin_start") __attribute__((weak));
+2
View File
@@ -379,6 +379,8 @@ public:
static unsigned long getWifiConnectedAtMillis();
static void formatMqttStatusReply(char* buf, size_t bufsize, const NodePrefs* prefs);
/** True when WiFi is set and at least one MQTT slot can run (preset + custom host if needed). */
static bool isConfigValid(const NodePrefs* prefs);
static void formatSlotDiagReply(char* buf, size_t bufsize, int slot_index);
static uint8_t getLastWifiDisconnectReason();
static unsigned long getLastWifiDisconnectTime();