Skip to content

Commit

Permalink
Trigger firmware update via MQTT.
Browse files Browse the repository at this point in the history
If enabled in user_config.h this will trigger the OMG to update it's firmware from the link
provided in the MQTT message.

Example message:
{\"version\":\"test\",\"url\":\"https://github.com/1technophile/OpenMQTTGateway/releases/download/v0.9.6/esp32dev-ble-cont-firmware.bin\"}

If the firmware version in the message is not the same as the current OMG version the device will self update using the link in the url of the message.

This is still a work in progress but is currently functional as-is for what it is.
  • Loading branch information
h2zero committed May 21, 2021
1 parent 4706d75 commit 21df632
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 2 deletions.
18 changes: 17 additions & 1 deletion main/User_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,24 @@ const byte subnet[] = {255, 255, 255, 0};

#if defined(ESP8266) || defined(ESP32) // for nodemcu, weemos and esp8266
//# define ESPWifiManualSetup true //uncomment you don't want to use wifimanager for your credential settings on ESP
//# define MQTT_HTTPS_FW_UPDATE //uncomment to enable updating via mqtt message.
#else // for arduino boards
const byte ip[] = {192, 168, 1, 99};
const byte mac[] = {0xDE, 0xED, 0xBA, 0xFE, 0x54, 0x95}; //W5100 ethernet shield mac adress
#endif

#ifdef MQTT_HTTPS_FW_UPDATE
//If used, this should be set to the root CA certificate of the server hosting the firmware.
// The certificate must be in PEM ascii format
const char* https_fw_server_cert = CERT_ATTRIBUTE = R"EOF("
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
")EOF";

# define NTP_SERVER "pool.ntp.org"
#endif

//#define ESP32_ETHERNET=true // Uncomment to use Ethernet module on OLIMEX ESP32 Ethernet gateway

#if defined(ESPWifiManualSetup) // for nodemcu, weemos and esp8266
Expand Down Expand Up @@ -163,7 +176,9 @@ const char* certificate CERT_ATTRIBUTE = R"EOF("
")EOF";

// specify a NTP server here or else the NTP server from DHCP is used
# ifndef NTP_SERVER
//# define NTP_SERVER "pool.ntp.org"
# endif
# else
# error "only ESP8266 and ESP32 support SECURE_CONNECTION with TLS"
# endif
Expand Down Expand Up @@ -336,6 +351,7 @@ int lowpowermode = DEFAULT_LOW_POWER_MODE;
#define subjectMQTTtoX "/commands/#"
#define subjectMultiGTWKey "toMQTT"
#define subjectGTWSendKey "MQTTto"
#define subjectFWUpdate "firmware_update"

// key used for launching commands to the gateway
#define restartCmd "restart"
Expand Down Expand Up @@ -381,4 +397,4 @@ int lowpowermode = DEFAULT_LOW_POWER_MODE;
# define LOG_LEVEL LOG_LEVEL_NOTICE
#endif

#endif
#endif
70 changes: 69 additions & 1 deletion main/main.ino
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,9 @@ 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);
}
Expand Down Expand Up @@ -539,8 +542,11 @@ void callback(char* topic, byte* payload, unsigned int length) {
// Conversion to a printable string
p[length] = '\0';
//launch the function to treat received data if this data concern OpenMQTTGateway
if ((strstr(topic, subjectMultiGTWKey) != NULL) || (strstr(topic, subjectGTWSendKey) != NULL))
if ((strstr(topic, subjectMultiGTWKey) != NULL) ||
(strstr(topic, subjectGTWSendKey) != NULL) ||
(strstr(topic, subjectFWUpdate) != NULL))
receivingMQTT(topic, (char*)p);

// Free the memory
free(p);
}
Expand Down Expand Up @@ -1576,6 +1582,9 @@ void receivingMQTT(char* topicOri, char* datacallback) {
# ifdef ZgatewayRS232
MQTTtoRS232(topicOri, jsondata);
# endif
# ifdef MQTT_HTTPS_FW_UPDATE
MQTTHttpsFWUpdate(topicOri, jsondata);
# endif
#endif
digitalWrite(LED_SEND, LED_SEND_ON);

Expand Down Expand Up @@ -1613,6 +1622,65 @@ void receivingMQTT(char* topicOri, char* datacallback) {
}
}

#ifdef MQTT_HTTPS_FW_UPDATE
# include <WiFiClientSecure.h>
# ifdef ESP32
# include <HTTPUpdate.h>
# elif ESP8266
# include <ESP8266httpUpdate.h>
# endif
void MQTTHttpsFWUpdate(char* topicOri, JsonObject& HttpsFwUpdateData) {
if (strstr(topicOri, subjectFWUpdate) != NULL) {
if (strcmp(HttpsFwUpdateData["version"], OMG_VERSION) != 0) {
const char* url = HttpsFwUpdateData["url"];
if (!strstr((url + strlen(url - 5)), ".bin")) {
Log.error(F("Invalid firmware extension" CR));
return;
}

Log.warning(F("Starting firmware update" CR));
WiFiClientSecure update_client;
# ifdef ESP32
# ifndef NTP_SERVER
update_client.setInsecure();
# else
if (strlen(https_fw_server_cert) < 200) {
Log.error(F("Invalid certificate - using insecure" CR));
update_client.setInsecure();
} else {
update_client.setCACert(https_fw_server_cert);
}
# endif
update_client.setTimeout(12);
/****** For Future use, does not work with current releases of arduino core ******/
// httpUpdate.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
t_httpUpdate_return ret = httpUpdate.update(update_client, url);
# elif ESP8266
update_client.setInsecure();
update_client.setTimeout(12000);
/****** For Future use, does not work with current releases of arduino core ******/
// ESPhttpUpdate.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
t_httpUpdate_return ret = ESPhttpUpdate.update(update_client, url);
# endif

switch (ret) {
case HTTP_UPDATE_FAILED:
Log.error(F("HTTP_UPDATE_FAILED Error (%d): %s\n" CR), httpUpdate.getLastError(), httpUpdate.getLastErrorString().c_str());
break;

case HTTP_UPDATE_NO_UPDATES:
Log.notice(F("HTTP_UPDATE_NO_UPDATES" CR));
break;

case HTTP_UPDATE_OK:
Log.notice(F("HTTP_UPDATE_OK" CR));
break;
}
}
}
}
#endif

void MQTTtoSYS(char* topicOri, JsonObject& SYSdata) { // json object decoding
if (cmpToMainTopic(topicOri, subjectMQTTtoSYSset)) {
Log.trace(F("MQTTtoSYS json" CR));
Expand Down

0 comments on commit 21df632

Please sign in to comment.