WebConfigurator fixes

This commit is contained in:
iranl
2024-08-17 23:22:16 +02:00
parent 83ddd91589
commit 1ca0cb2e72
4 changed files with 121 additions and 41 deletions

View File

@@ -7,8 +7,12 @@
#include "RestartReason.h"
#include <ArduinoJson.h>
#include <ctype.h>
#include <HTTPClient.h>
#include <NetworkClientSecure.h>
extern bool forceEnableWebServer;
extern const uint8_t x509_crt_imported_bundle_bin_start[] asm("_binary_x509_crt_bundle_start");
extern const uint8_t x509_crt_imported_bundle_bin_end[] asm("_binary_x509_crt_bundle_end");
NukiNetworkLock::NukiNetworkLock(NukiNetwork* network, Preferences* preferences, char* buffer, size_t bufferSize)
: _network(network),
@@ -204,30 +208,102 @@ void NukiNetworkLock::onMqttDataReceived(const char* topic, byte* payload, const
else if(comparePrefixedPath(topic, mqtt_topic_update) && strcmp(value, "1") == 0 && _preferences->getBool(preference_update_from_mqtt, false))
{
Log->println(F("Update requested via MQTT."));
String currentVersion = NUKI_HUB_VERSION;
bool otaManifestSuccess = false;
JsonDocument doc;
if(atof(_preferences->getString(preference_latest_version).c_str()) >= atof(currentVersion.c_str()))
{
_preferences->putString(preference_ota_updater_url, GITHUB_LATEST_UPDATER_BINARY_URL);
_preferences->putString(preference_ota_main_url, GITHUB_LATEST_RELEASE_BINARY_URL);
NetworkClientSecure *client = new NetworkClientSecure;
if (client) {
client->setCACertBundle(x509_crt_imported_bundle_bin_start, x509_crt_imported_bundle_bin_end - x509_crt_imported_bundle_bin_start);
{
HTTPClient https;
https.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
https.useHTTP10(true);
if (https.begin(*client, GITHUB_OTA_MANIFEST_URL)) {
int httpResponseCode = https.GET();
if (httpResponseCode == HTTP_CODE_OK || httpResponseCode == HTTP_CODE_MOVED_PERMANENTLY)
{
DeserializationError jsonError = deserializeJson(doc, https.getStream());
if (!jsonError) { otaManifestSuccess = true; }
}
}
https.end();
}
delete client;
}
else if(currentVersion.indexOf("beta") > 0)
if (otaManifestSuccess)
{
_preferences->putString(preference_ota_updater_url, GITHUB_BETA_RELEASE_BINARY_URL);
_preferences->putString(preference_ota_main_url, GITHUB_BETA_UPDATER_BINARY_URL);
}
else if(currentVersion.indexOf("master") > 0)
{
_preferences->putString(preference_ota_updater_url, GITHUB_MASTER_RELEASE_BINARY_URL);
_preferences->putString(preference_ota_main_url, GITHUB_MASTER_UPDATER_BINARY_URL);
String currentVersion = NUKI_HUB_VERSION;
if(atof(doc["release"]["version"]) >= atof(currentVersion.c_str()))
{
if(strcmp(NUKI_HUB_VERSION, doc["release"]["fullversion"].as<const char*>()) == 0 && strcmp(NUKI_HUB_BUILD, doc["release"]["build"].as<const char*>()) == 0 && strcmp(NUKI_HUB_DATE, doc["release"]["time"].as<const char*>()) == 0)
{
Log->println(F("Nuki Hub is already on the latest release version, OTA update aborted."));
}
else
{
_preferences->putString(preference_ota_updater_url, GITHUB_LATEST_UPDATER_BINARY_URL);
_preferences->putString(preference_ota_main_url, GITHUB_LATEST_RELEASE_BINARY_URL);
Log->println(F("Updating to latest release version."));
delay(200);
restartEsp(RestartReason::OTAReboot);
}
}
else if(currentVersion.indexOf("beta") > 0)
{
if(strcmp(NUKI_HUB_VERSION, doc["beta"]["fullversion"].as<const char*>()) == 0 && strcmp(NUKI_HUB_BUILD, doc["beta"]["build"].as<const char*>()) == 0 && strcmp(NUKI_HUB_DATE, doc["beta"]["time"].as<const char*>()) == 0)
{
Log->println(F("Nuki Hub is already on the latest beta version, OTA update aborted."));
}
else
{
_preferences->putString(preference_ota_updater_url, GITHUB_BETA_RELEASE_BINARY_URL);
_preferences->putString(preference_ota_main_url, GITHUB_BETA_UPDATER_BINARY_URL);
Log->println(F("Updating to latest beta version."));
delay(200);
restartEsp(RestartReason::OTAReboot);
}
}
else if(currentVersion.indexOf("master") > 0)
{
if(strcmp(NUKI_HUB_VERSION, doc["master"]["fullversion"].as<const char*>()) == 0 && strcmp(NUKI_HUB_BUILD, doc["master"]["build"].as<const char*>()) == 0 && strcmp(NUKI_HUB_DATE, doc["master"]["time"].as<const char*>()) == 0)
{
Log->println(F("Nuki Hub is already on the latest development version, OTA update aborted."));
}
else
{
_preferences->putString(preference_ota_updater_url, GITHUB_MASTER_RELEASE_BINARY_URL);
_preferences->putString(preference_ota_main_url, GITHUB_MASTER_UPDATER_BINARY_URL);
Log->println(F("Updating to latest developmemt version."));
delay(200);
restartEsp(RestartReason::OTAReboot);
}
}
else
{
if(strcmp(NUKI_HUB_VERSION, doc["release"]["fullversion"].as<const char*>()) == 0 && strcmp(NUKI_HUB_BUILD, doc["release"]["build"].as<const char*>()) == 0 && strcmp(NUKI_HUB_DATE, doc["release"]["time"].as<const char*>()) == 0)
{
Log->println(F("Nuki Hub is already on the latest release version, OTA update aborted."));
}
else
{
_preferences->putString(preference_ota_updater_url, GITHUB_LATEST_UPDATER_BINARY_URL);
_preferences->putString(preference_ota_main_url, GITHUB_LATEST_RELEASE_BINARY_URL);
Log->println(F("Updating to latest release version."));
delay(200);
restartEsp(RestartReason::OTAReboot);
}
}
}
else
{
_preferences->putString(preference_ota_updater_url, GITHUB_LATEST_UPDATER_BINARY_URL);
_preferences->putString(preference_ota_main_url, GITHUB_LATEST_RELEASE_BINARY_URL);
Log->println(F("Failed to retrieve OTA manifest, OTA update aborted."));
}
delay(200);
restartEsp(RestartReason::OTAReboot);
}
else if(comparePrefixedPath(topic, mqtt_topic_webserver_action))
{

View File

@@ -2906,7 +2906,10 @@ void NukiOpenerWrapper::readConfig()
char resultStr[20];
NukiOpener::cmdResultToString(result, resultStr);
Log->print(F("Opener config result: "));
Log->println(resultStr);
Log->print(resultStr);
Log->print("(");
Log->print(result);
Log->println(")");
postponeBleWatchdog();
}

View File

@@ -283,9 +283,9 @@ void WebCfgServer::buildOtaHtml(AsyncWebServerRequest *request, bool debug)
#else
String build_type = "debug";
#endif
response->print("<form onsubmit=\"if(document.getElementById('currentver').value == document.getElementById('latestver').value && '" + release_type + "' == '" + build_type + "') { alert('You are already on this version, build and build type'); return false; } else { return confirm('Do you really want to update to the latest release?'); } \" action=\"/autoupdate\" method=\"get\" style=\"float: left; margin-right: 10px\"><input type=\"hidden\" name=\"release\" value=\"1\" /><input type=\"hidden\" name=\"" + release_type + "\" value=\"1\" /><input type=\"hidden\" name=\"token\" value=\"" + _confirmCode + "\" /><br><input type=\"submit\" style=\"background: green\" value=\"Update to latest release\"></form>");
response->print("<form onsubmit=\"if(document.getElementById('currentver').value == document.getElementById('betaver').value && '" + release_type + "' == '" + build_type + "') { alert('You are already on this version, build and build type'); return false; } else { return confirm('Do you really want to update to the latest beta? This version could contain breaking bugs and necessitate downgrading to the latest release version using USB/Serial'); }\" action=\"/autoupdate\" method=\"get\" style=\"float: left; margin-right: 10px\"><input type=\"hidden\" name=\"beta\" value=\"1\" /><input type=\"hidden\" name=\"" + release_type + "\" value=\"1\" /><input type=\"hidden\" name=\"token\" value=\"" + _confirmCode + "\" /><br><input type=\"submit\" style=\"color: black; background: yellow\" value=\"Update to latest beta\"></form>");
response->print("<form onsubmit=\"if(document.getElementById('currentver').value == document.getElementById('devver').value && '" + release_type + "' == '" + build_type + "') { alert('You are already on this version, build and build type'); return false; } else { return confirm('Do you really want to update to the latest development version? This version could contain breaking bugs and necessitate downgrading to the latest release version using USB/Serial'); }\" action=\"/autoupdate\" method=\"get\" style=\"float: left; margin-right: 10px\"><input type=\"hidden\" name=\"master\" value=\"1\" /><input type=\"hidden\" name=\"" + release_type + "\" value=\"1\" /><input type=\"hidden\" name=\"token\" value=\"" + _confirmCode + "\" /><br><input type=\"submit\" style=\"background: red\" value=\"Update to latest development version\"></form>");
response->print("<form onsubmit=\"if(document.getElementById('currentver').innerHTML == document.getElementById('latestver').innerHTML && '" + release_type + "' == '" + build_type + "') { alert('You are already on this version, build and build type'); return false; } else { return confirm('Do you really want to update to the latest release?'); } \" action=\"/autoupdate\" method=\"get\" style=\"float: left; margin-right: 10px\"><input type=\"hidden\" name=\"release\" value=\"1\" /><input type=\"hidden\" name=\"" + release_type + "\" value=\"1\" /><input type=\"hidden\" name=\"token\" value=\"" + _confirmCode + "\" /><br><input type=\"submit\" style=\"background: green\" value=\"Update to latest release\"></form>");
response->print("<form onsubmit=\"if(document.getElementById('currentver').innerHTML == document.getElementById('betaver').innerHTML && '" + release_type + "' == '" + build_type + "') { alert('You are already on this version, build and build type'); return false; } else { return confirm('Do you really want to update to the latest beta? This version could contain breaking bugs and necessitate downgrading to the latest release version using USB/Serial'); }\" action=\"/autoupdate\" method=\"get\" style=\"float: left; margin-right: 10px\"><input type=\"hidden\" name=\"beta\" value=\"1\" /><input type=\"hidden\" name=\"" + release_type + "\" value=\"1\" /><input type=\"hidden\" name=\"token\" value=\"" + _confirmCode + "\" /><br><input type=\"submit\" style=\"color: black; background: yellow\" value=\"Update to latest beta\"></form>");
response->print("<form onsubmit=\"if(document.getElementById('currentver').innerHTML == document.getElementById('devver').innerHTML && '" + release_type + "' == '" + build_type + "') { alert('You are already on this version, build and build type'); return false; } else { return confirm('Do you really want to update to the latest development version? This version could contain breaking bugs and necessitate downgrading to the latest release version using USB/Serial'); }\" action=\"/autoupdate\" method=\"get\" style=\"float: left; margin-right: 10px\"><input type=\"hidden\" name=\"master\" value=\"1\" /><input type=\"hidden\" name=\"" + release_type + "\" value=\"1\" /><input type=\"hidden\" name=\"token\" value=\"" + _confirmCode + "\" /><br><input type=\"submit\" style=\"background: red\" value=\"Update to latest development version\"></form>");
response->print("<div style=\"clear: both\"></div><br>");
response->print("<b>Current version: </b><span id=\"currentver\">");
@@ -358,6 +358,16 @@ void WebCfgServer::buildOtaHtml(AsyncWebServerRequest *request, bool debug)
response->print(")</span>, ");
response->print(doc["master"]["time"].as<const char*>());
response->print("<br>");
String currentVersion = NUKI_HUB_VERSION;
const char* latestVersion;
if(atof(doc["release"]["version"]) >= atof(currentVersion.c_str())) latestVersion = doc["release"]["fullversion"];
else if(currentVersion.indexOf("beta") > 0) latestVersion = doc["beta"]["fullversion"];
else if(currentVersion.indexOf("master") > 0) latestVersion = doc["master"]["fullversion"];
else latestVersion = doc["release"]["fullversion"];
if(strcmp(latestVersion, _preferences->getString(preference_latest_version).c_str()) != 0) _preferences->putString(preference_latest_version, latestVersion);
}
#endif
response->print("<br></div>");
@@ -2746,9 +2756,9 @@ void WebCfgServer::buildAdvancedConfigHtml(AsyncWebServerRequest *request)
printInputField(response, "TSKNTWK", "Task size Network (min 12288, max 32768)", _preferences->getInt(preference_task_size_network, NETWORK_TASK_SIZE), 6, "");
response->print("<tr><td>Advised minimum network task size based on current settings</td><td id=\"minnetworktask\"></td>");
printInputField(response, "TSKNUKI", "Task size Nuki (min 8192, max 32768)", _preferences->getInt(preference_task_size_nuki, NUKI_TASK_SIZE), 6, "");
printInputField(response, "ALMAX", "Max auth log entries (min 1, max 50)", _preferences->getInt(preference_authlog_max_entries, MAX_AUTHLOG), 3, "inputmaxauthlog");
printInputField(response, "KPMAX", "Max keypad entries (min 1, max 100)", _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD), 3, "inputmaxkeypad");
printInputField(response, "TCMAX", "Max timecontrol entries (min 1, max 50)", _preferences->getInt(preference_timecontrol_max_entries, MAX_TIMECONTROL), 3, "inputmaxtimecontrol");
printInputField(response, "ALMAX", "Max auth log entries (min 1, max 50)", _preferences->getInt(preference_authlog_max_entries, MAX_AUTHLOG), 3, "id=\"inputmaxauthlog\"");
printInputField(response, "KPMAX", "Max keypad entries (min 1, max 100)", _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD), 3, "id=\"inputmaxkeypad\"");
printInputField(response, "TCMAX", "Max timecontrol entries (min 1, max 50)", _preferences->getInt(preference_timecontrol_max_entries, MAX_TIMECONTROL), 3, "id=\"inputmaxtimecontrol\"");
printCheckBox(response, "SHOWSECRETS", "Show Pairing secrets on Info page (for 120s after next boot)", _preferences->getBool(preference_show_secrets), "");
if(_preferences->getBool(preference_lock_enabled, true))
{
@@ -3875,7 +3885,7 @@ void WebCfgServer::printInputField(AsyncResponseStream *response,
const char *description,
const char *value,
const size_t& maxLength,
const char *id,
const char *args,
const bool& isPassword,
const bool& showLengthRestriction)
{
@@ -3896,19 +3906,10 @@ void WebCfgServer::printInputField(AsyncResponseStream *response,
response->print("</td><td>");
response->print("<input type=");
response->print(isPassword ? "\"password\"" : "\"text\"");
if(strcmp(id, "") != 0)
if(strcmp(args, "") != 0)
{
if(strncmp(id, "class=", 6) != 0)
{
response->print(" ");
response->print(id);
}
else
{
response->print(" id=\"");
response->print(id);
response->print("\"");
}
response->print(" ");
response->print(args);
}
if(strcmp(value, "") != 0)
{
@@ -3928,11 +3929,11 @@ void WebCfgServer::printInputField(AsyncResponseStream *response,
const char *description,
const int value,
size_t maxLength,
const char *id)
const char *args)
{
char valueStr[20];
itoa(value, valueStr, 10);
printInputField(response, token, description, valueStr, maxLength, id);
printInputField(response, token, description, valueStr, maxLength, args);
}
void WebCfgServer::printCheckBox(AsyncResponseStream *response, const char *token, const char *description, const bool value, const char *htmlClass)

View File

@@ -68,8 +68,8 @@ private:
void processUnpair(AsyncWebServerRequest *request, bool opener);
void processUpdate(AsyncWebServerRequest *request);
void processFactoryReset(AsyncWebServerRequest *request);
void printInputField(AsyncResponseStream *response, const char* token, const char* description, const char* value, const size_t& maxLength, const char* id, const bool& isPassword = false, const bool& showLengthRestriction = false);
void printInputField(AsyncResponseStream *response, const char* token, const char* description, const int value, size_t maxLength, const char* id);
void printInputField(AsyncResponseStream *response, const char* token, const char* description, const char* value, const size_t& maxLength, const char* args, const bool& isPassword = false, const bool& showLengthRestriction = false);
void printInputField(AsyncResponseStream *response, const char* token, const char* description, const int value, size_t maxLength, const char* args);
void printCheckBox(AsyncResponseStream *response, const char* token, const char* description, const bool value, const char* htmlClass);
void printCheckBox(String &partString, const char* token, const char* description, const bool value, const char* htmlClass);
void printTextarea(AsyncResponseStream *response, const char *token, const char *description, const char *value, const size_t& maxLength, const bool& enabled = true, const bool& showLengthRestriction = false);