From 65d0998278517f7564a6dbbe3b78a72267fe6b2b Mon Sep 17 00:00:00 2001 From: Florian Date: Mon, 10 Aug 2026 06:33:13 -0500 Subject: [PATCH] [OTA] Resolve the offered version per build environment (#2350) checkForUpdates() reads an optional "envs" map from the update manifest and, when it holds an entry for this build's ENV_NAME, offers that version instead of the global latest_version. Boards with no entry are unaffected. This lets the OTA server hold a specific product at an older release while the rest of the fleet advances, with no per-board build flags. The resolved value is republished as latest_version so the Home Assistant update entity compares against it, and the map itself is dropped from the retained state topic to keep it small. Backward compatible both ways: old firmware ignores "envs", and a manifest without "envs" behaves exactly as before. OTA_JSON_URL is also guarded with #ifndef so a build environment can point the update check at another OTA server. It was defined unconditionally, so a -D build flag could not retarget it (the header definition always won). This is needed to exercise the check against a test manifest, and is useful for self-hosted OTA servers. No behaviour change without an override. Co-authored-by: Claude Opus 5 --- main/User_config.h | 10 ++++++---- main/main.cpp | 21 +++++++++++++++++++-- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/main/User_config.h b/main/User_config.h index 4a2af04..bdd7792 100644 --- a/main/User_config.h +++ b/main/User_config.h @@ -251,10 +251,12 @@ # ifndef MQTT_HTTPS_FW_UPDATE_USE_PASSWORD # define MQTT_HTTPS_FW_UPDATE_USE_PASSWORD 1 // Set this to 0 if not using TLS connection to MQTT broker to prevent clear text passwords being sent. # endif -# if DEVELOPMENTOTA -# define OTA_JSON_URL "https://ota.openmqttgateway.com/binaries/dev/latest_version_dev.json" //OTA url used to discover new versions of the firmware from development nightly builds -# else -# define OTA_JSON_URL "https://ota.openmqttgateway.com/binaries/latest_version.json" //OTA url used to discover new versions of the firmware +# ifndef OTA_JSON_URL // may be overridden by a build flag to use another OTA server +# if DEVELOPMENTOTA +# define OTA_JSON_URL "https://ota.openmqttgateway.com/binaries/dev/latest_version_dev.json" //OTA url used to discover new versions of the firmware from development nightly builds +# else +# define OTA_JSON_URL "https://ota.openmqttgateway.com/binaries/latest_version.json" //OTA url used to discover new versions of the firmware +# endif # endif # define ENTITY_PICTURE "https://github.com/1technophile/OpenMQTTGateway/raw/development/docs/img/Openmqttgateway_logo_mini_margins.png" # define RELEASE_LINK_DEV "https://ota.openmqttgateway.com/binaries/dev/" diff --git a/main/main.cpp b/main/main.cpp index b200f3c..e997dae 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -3224,12 +3224,29 @@ bool checkForUpdates() { jsondata["entity_picture"] = ENTITY_PICTURE; if (!jsondata.containsKey("release_summary")) jsondata["release_summary"] = ""; - latestVersion = jsondata["latest_version"].as(); + // Per-environment version pinning: if the manifest carries an "envs" map with + // an entry for this build's ENV_NAME, that entry caps the version offered to + // this board; boards without an entry fall back to the global latest_version. + // This lets the OTA server hold e.g. theengs-plug at an older release while the + // rest of the fleet advances, with no board-specific firmware build flags. + // The "envs" map is expected to list only pinned exceptions so the manifest + // stays within JSON_MSG_BUFFER (1024 B on ESP32). + JsonVariant envVersion = jsondata["envs"][ENV_NAME]; + if (!envVersion.isNull()) { + latestVersion = envVersion.as(); + } else { + latestVersion = jsondata["latest_version"].as(); + } + // Publish the resolved value as latest_version so the Home Assistant update + // entity compares against the (possibly pinned) version, and drop the map so + // it is not carried in the retained state topic. + jsondata["latest_version"] = latestVersion; + jsondata.remove("envs"); jsondata["origin"] = subjectRLStoMQTT; jsondata["retain"] = true; enqueueJsonObject(jsondata); - THEENGS_LOG_TRACE(F("Update file found on server" CR)); + THEENGS_LOG_TRACE(F("Update file found on server, offering version %s" CR), latestVersion.c_str()); return true; } else { THEENGS_LOG_TRACE(F("No update file found on server" CR));