From 8936fc6007f2cd83139ceb71109935fdd72ef802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Fri, 18 Sep 2026 10:54:51 +0200 Subject: [PATCH] fix(mqtt): count the regional roots as the default root topic --- src/mqtt/MQTT.cpp | 13 +++++++------ test/test_mqtt/MQTT.cpp | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index 2a267c52a..8e7d344d9 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -247,11 +247,6 @@ bool isDefaultServer(const String &host) return host.length() == 0 || host == default_mqtt_address; } -bool isDefaultRootTopic(const String &root) -{ - return root.length() == 0 || root == default_mqtt_root; -} - // "msh/" is what the default broker's convention produces; any other suffix is the user's own. bool isRegionRootTopic(const char *root) { @@ -264,6 +259,12 @@ bool isRegionRootTopic(const char *root) return false; } +// The regional roots count as default: they are what a region change writes on the default broker. +bool isDefaultRootTopic(const String &root) +{ + return root.length() == 0 || root == default_mqtt_root || isRegionRootTopic(root.c_str()); +} + struct PubSubConfig { explicit PubSubConfig(const meshtastic_ModuleConfig_MQTTConfig &config) { @@ -385,7 +386,7 @@ bool MQTT::applyRegionRootTopic(const char *regionName) (void)parsedPort; if (!isDefaultServer(host)) return false; - if (!isDefaultRootTopic(moduleConfig.mqtt.root) && !isRegionRootTopic(moduleConfig.mqtt.root)) + if (!isDefaultRootTopic(moduleConfig.mqtt.root)) return false; // the user picked their own root snprintf(moduleConfig.mqtt.root, sizeof(moduleConfig.mqtt.root), "%s/%s", default_mqtt_root, regionName); return true; diff --git a/test/test_mqtt/MQTT.cpp b/test/test_mqtt/MQTT.cpp index e0867e9f9..afe46ff2c 100644 --- a/test/test_mqtt/MQTT.cpp +++ b/test/test_mqtt/MQTT.cpp @@ -1427,6 +1427,20 @@ void test_applyRegionRootTopic_rewritesDefaultBrokerRootsOnly(void) TEST_ASSERT_EQUAL_STRING("msh/US", moduleConfig.mqtt.root); } +// USERPREFS_EVENT_MODE gates the public broker on isUsingDefaultRootTopic() (Channels::anyMqttEnabled()). +// A "msh/" root is what a region change writes on the default broker, so it has to keep counting as +// the default root; otherwise an event build silently loses that guard the first time the region changes. +void test_regionRootTopic_countsAsTheDefaultRoot(void) +{ + strcpy(moduleConfig.mqtt.root, "msh/EU_868"); + MQTTUnitTest::restart(); + TEST_ASSERT_TRUE(mqtt->isUsingDefaultRootTopic()); + + strcpy(moduleConfig.mqtt.root, "msh/home"); + MQTTUnitTest::restart(); + TEST_ASSERT_FALSE(mqtt->isUsingDefaultRootTopic()); +} + // Empty configuration is valid. void test_configEmptyIsValid(void) { @@ -1624,6 +1638,7 @@ void setup() RUN_TEST(test_customMqttRoot); RUN_TEST(test_rootChange_rebuildsTopics); RUN_TEST(test_applyRegionRootTopic_rewritesDefaultBrokerRootsOnly); + RUN_TEST(test_regionRootTopic_countsAsTheDefaultRoot); RUN_TEST(test_configEmptyIsValid); RUN_TEST(test_configEnabledEmptyIsValid); RUN_TEST(test_configWithDefaultServer);