[OTA] Enable 2 clicks OTA update / one simple MQTT command (#1485)

* [OTA] Add automatic OTA updates

This feature will enable to update the gateway with one button or a simple MQTT command.

* [CI] Enable automatic OTA for nightly development builds

And integrate the latest_version file creation into the CI

Enable to specify a particular version
and switch between dev and production builds
This commit is contained in:
Florian authored and GitHub committed 2023-02-27 12:54:30 -06:00
1 parent e83bfb0e4d
commit 454a062b3b
15 files changed
+186 -54

No files matched your search

+78 -18
View File
@@ -596,9 +596,6 @@ void connectMQTT() {
#endif
#ifdef ZgatewayIR
client.subscribe(subjectMultiGTWIR); // subject on which other OMG will publish, this OMG will store these msg and by the way don't republish them if they have been already published
#endif
#ifdef MQTT_HTTPS_FW_UPDATE
client.subscribe(subjectFWUpdate);
#endif
Log.trace(F("Subscription OK to the subjects %s" CR), topic2);
}
@@ -653,7 +650,7 @@ void callback(char* topic, byte* payload, unsigned int length) {
//launch the function to treat received data if this data concern OpenMQTTGateway
if ((strstr(topic, subjectMultiGTWKey) != NULL) ||
(strstr(topic, subjectGTWSendKey) != NULL) ||
(strstr(topic, subjectFWUpdate) != NULL))
(strstr(topic, subjectMQTTtoSYSupdate) != NULL))
receivingMQTT(topic, (char*)p);
// Free the memory
@@ -1509,6 +1506,10 @@ void loop() {
connected = true;
#if defined(ESP8266) || defined(ESP32) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__)
if (now > (timer_sys_measures + (TimeBetweenReadingSYS * 1000)) || !timer_sys_measures) {
# if defined(ESP32) && defined(MQTT_HTTPS_FW_UPDATE)
if (!timer_sys_measures) // Only check for updates at start for ESP32
checkForUpdates();
# endif
timer_sys_measures = millis();
stateMeasures();
# ifdef ZgatewayBT
@@ -1691,6 +1692,7 @@ void stateMeasures() {
SYSdata["uptime"] = uptime();
SYSdata["version"] = OMG_VERSION;
# if defined(ESP8266) || defined(ESP32)
SYSdata["env"] = ENV_NAME;
uint32_t freeMem;
freeMem = ESP.getFreeHeap();
SYSdata["freemem"] = freeMem;
@@ -1940,39 +1942,97 @@ void receivingMQTT(char* topicOri, char* datacallback) {
}
#ifdef MQTT_HTTPS_FW_UPDATE
String latestVersion;
# ifdef ESP32
# include <HTTPClient.h>
# include "zzHTTPUpdate.h"
/**
* Check on a server the latest version information to build a releaseLink
* The release link will be used when the user trigger an OTA update command
* Only available for ESP32
*/
bool checkForUpdates() {
HTTPClient http;
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
http.begin(OTA_JSON_URL, OTAserver_cert);
int httpCode = http.GET();
StaticJsonDocument<JSON_MSG_BUFFER> jsonBuffer;
JsonObject jsondata = jsonBuffer.to<JsonObject>();
if (httpCode > 0) { //Check for the returning code
String payload = http.getString();
auto error = deserializeJson(jsonBuffer, payload);
if (error) {
Log.error(F("Deserialize MQTT data failed: %s" CR), error.c_str());
}
Log.trace(F("HttpCode %d" CR), httpCode);
Log.trace(F("Payload %s" CR), payload.c_str());
} else {
Log.error(F("Error on HTTP request"));
}
http.end(); //Free the resources
if (jsondata.containsKey("latest_version")) {
jsondata["installed_version"] = OMG_VERSION;
jsondata["entity_picture"] = ENTITY_PICTURE;
latestVersion = jsondata["latest_version"].as<String>();
pub(subjectSYStoMQTT, jsondata);
Log.trace(F("Update file found on server" CR));
return true;
} else {
Log.trace(F("No update file found on server" CR));
return false;
}
}
# elif ESP8266
# include <ESP8266httpUpdate.h>
# endif
void MQTTHttpsFWUpdate(char* topicOri, JsonObject& HttpsFwUpdateData) {
if (strstr(topicOri, subjectFWUpdate) != NULL) {
if (strstr(topicOri, subjectMQTTtoSYSupdate) != NULL) {
const char* version = HttpsFwUpdateData["version"];
if (version && ((strlen(version) != strlen(OMG_VERSION)) || strcmp(version, OMG_VERSION) != 0)) {
const char* url = HttpsFwUpdateData["url"];
String systemUrl;
if (url) {
if (!strstr((url + (strlen(url) - 5)), ".bin")) {
Log.error(F("Invalid firmware extension" CR));
return;
}
# if MQTT_HTTPS_FW_UPDATE_USE_PASSWORD > 0
const char* pwd = HttpsFwUpdateData["password"];
if (pwd) {
if (strcmp(pwd, ota_pass) != 0) {
Log.error(F("Invalid OTA password" CR));
return;
}
} else {
Log.error(F("No password sent" CR));
return;
}
# endif
# ifdef ESP32
} else if (strcmp(version, "latest") == 0) {
if (!checkForUpdates())
return;
systemUrl = RELEASE_LINK + latestVersion + "/" + ENV_NAME + "-firmware.bin";
url = systemUrl.c_str();
Log.notice(F("Using system OTA url with latest version %s" CR), url);
} else if (strcmp(version, "dev") == 0) {
systemUrl = String(RELEASE_LINK_DEV) + ENV_NAME + "-firmware.bin";
url = systemUrl.c_str();
Log.notice(F("Using system OTA url with dev version %s" CR), url);
} else if (version[0] == 'v') {
systemUrl = String(RELEASE_LINK) + version + "/" + ENV_NAME + "-firmware.bin";
url = systemUrl.c_str();
Log.notice(F("Using system OTA url with defined version %s" CR), url);
# endif
} else {
Log.error(F("Invalid URL" CR));
return;
}
# if MQTT_HTTPS_FW_UPDATE_USE_PASSWORD > 0
const char* pwd = HttpsFwUpdateData["password"];
if (pwd) {
if (strcmp(pwd, ota_pass) != 0) {
Log.error(F("Invalid OTA password" CR));
return;
}
} else {
Log.error(F("No password sent" CR));
return;
}
# endif
Log.warning(F("Starting firmware update" CR));
SendReceiveIndicatorON();
ErrorIndicatorON();