From ea541e182a20ee89c977f02e375e0ba77d2caae0 Mon Sep 17 00:00:00 2001 From: Elektr0Vodka <211697683+Elektr0Vodka@users.noreply.github.com> Date: Mon, 14 Sep 2026 04:29:28 +0200 Subject: [PATCH] feat(ota): add 'ota branch [stable|dev|default]' command (cherry picked from commit 240804999edb284fd276489e6898ccad8a19a8e7) --- src/helpers/CommonCLI_Observer.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/helpers/CommonCLI_Observer.cpp b/src/helpers/CommonCLI_Observer.cpp index c6d44f49..e4d71182 100644 --- a/src/helpers/CommonCLI_Observer.cpp +++ b/src/helpers/CommonCLI_Observer.cpp @@ -1130,6 +1130,35 @@ bool CommonCLI::handleObserverCommand(uint32_t sender_timestamp, char* command, } #else strcpy(reply, "ERR: online OTA not supported on this build"); +#endif + return true; + } else if (memcmp(command, "ota branch", 10) == 0) { + // Switch (or report) the OTA release channel this device pulls from. The + // selection is persisted (NodePrefs::ota_channel) and resolved to a baked-in + // base URL by ota_resolve_base(); it changes only WHERE updates are fetched, + // never the running image's reported version. Reachable from any admin path, + // same as `ota update`. +#if defined(WITH_MQTT_BRIDGE) && defined(OTA_MANIFEST_BASE) + const char* arg = command + 10; + while (*arg == ' ') arg++; + if (*arg == 0) { + snprintf(reply, 160, "channel: %s (%s), base %s", + ota_channel_name(_prefs->ota_channel), + _prefs->ota_channel == OTA_CH_NATIVE ? "native" : "override", + ota_resolve_base(_prefs->ota_channel)); + } else { + uint8_t ch; + if (!ota_parse_channel(arg, &ch)) { + strcpy(reply, "ERR: usage ota branch [stable|dev|default]"); + } else { + _prefs->ota_channel = ch; + savePrefs(); + snprintf(reply, 160, "channel set to %s, base %s", + ota_channel_name(ch), ota_resolve_base(ch)); + } + } +#else + strcpy(reply, "ERR: online OTA not supported on this build"); #endif return true; } else if (memcmp(command, "start webconfig", 15) == 0 && (command[15] == 0 || command[15] == ' ')) {