OTA and Debug improvements (#445)

* Use esp_crt_bundle for HTTPS requests

* Remove Solo1 support

* Improve Nuki device config read functions

* Webserial

* OTA Improvements

* WebCfg fixes

* Debug improvements
This commit is contained in:
iranl
2024-08-11 11:20:51 +02:00
committed by GitHub
parent 9d55c2173d
commit 063fbab6b2
11 changed files with 317 additions and 108 deletions

View File

@@ -48,8 +48,9 @@ WebCfgServer::WebCfgServer(NukiNetwork* network, EthServer* ethServer, Preferenc
memcpy(&_credPassword, pass, str.length());
}
#ifndef NUKI_HUB_UPDATER
_confirmCode = generateConfirmCode();
#ifndef NUKI_HUB_UPDATER
_pinsConfigured = true;
if(_nuki != nullptr && !_nuki->isPinSet())
@@ -312,6 +313,14 @@ void WebCfgServer::initialize()
buildOtaHtml(response, _server.arg("errored") != "");
_server.send(200, "text/html", response);
});
_server.on("/otadebug", [&]() {
if (_hasCredentials && !_server.authenticate(_credUser, _credPassword)) {
return _server.requestAuthentication();
}
String response = "";
buildOtaHtml(response, _server.arg("errored") != "", true);
_server.send(200, "text/html", response);
});
_server.on("/reboottoota", [&]() {
if (_hasCredentials && !_server.authenticate(_credUser, _credPassword)) {
return _server.requestAuthentication();
@@ -327,29 +336,12 @@ void WebCfgServer::initialize()
if (_hasCredentials && !_server.authenticate(_credUser, _credPassword)) {
return _server.requestAuthentication();
}
String response = "";
String key = _server.argName(0);
if(key == "beta")
{
buildConfirmHtml(response, "Rebooting to update Nuki Hub and Nuki Hub updater<br/>Updating to latest BETA version", 2);
_preferences->putString(preference_ota_updater_url, GITHUB_BETA_UPDATER_BINARY_URL);
_preferences->putString(preference_ota_main_url, GITHUB_BETA_RELEASE_BINARY_URL);
}
else if(key == "master")
{
buildConfirmHtml(response, "Rebooting to update Nuki Hub and Nuki Hub updater<br/>Updating to latest development version", 2);
_preferences->putString(preference_ota_updater_url, GITHUB_MASTER_UPDATER_BINARY_URL);
_preferences->putString(preference_ota_main_url, GITHUB_MASTER_RELEASE_BINARY_URL);
}
else
{
buildConfirmHtml(response, "Rebooting to update Nuki Hub and Nuki Hub updater<br/>Updating to latest RELEASE version", 2);
_preferences->putString(preference_ota_updater_url, GITHUB_LATEST_UPDATER_BINARY_URL);
_preferences->putString(preference_ota_main_url, GITHUB_LATEST_RELEASE_BINARY_URL);
}
_server.send(200, "text/html", response);
waitAndProcess(true, 1000);
restartEsp(RestartReason::OTAReboot);
#ifndef NUKI_HUB_UPDATER
processUpdate();
#else
_server.sendHeader("Location", "/");
_server.send(302, "text/plain", "");
#endif
});
_server.on("/uploadota", HTTP_POST, [&]() {
if (_hasCredentials && !_server.authenticate(_credUser, _credPassword)) {
@@ -401,7 +393,7 @@ void WebCfgServer::update()
_server.handleClient();
}
void WebCfgServer::buildOtaHtml(String &response, bool errored)
void WebCfgServer::buildOtaHtml(String &response, bool errored, bool debug)
{
buildHtmlHeader(response);
@@ -421,20 +413,34 @@ void WebCfgServer::buildOtaHtml(String &response, bool errored)
response.concat("<div id=\"autoupdform\"><h4>Update Nuki Hub</h4>");
response.concat("Click on the button to reboot and automatically update Nuki Hub and the Nuki Hub updater to the latest versions from GitHub");
response.concat("<div style=\"clear: both\"></div>");
response.concat("<form onsubmit=\"return confirm('Do you really want to update to the latest release?');\" action=\"/autoupdate\" method=\"get\" style=\"float: left; margin-right: 10px\"><br><input type=\"submit\" style=\"background: green\" value=\"Update to latest release\"></form>");
response.concat("<form onsubmit=\"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\" /><br><input type=\"submit\" style=\"color: black; background: yellow\" value=\"Update to latest beta\"></form>");
response.concat("<form onsubmit=\"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\" /><br><input type=\"submit\" style=\"background: red\" value=\"Update to latest development version\"></form>");
String release_type;
if(debug) release_type = "debug";
else release_type = "release";
#ifndef DEBUG_NUKIHUB
String build_type = "release";
#else
String build_type = "debug";
#endif
response.concat("<form onsubmit=\"if(document.getElementById('currentver') == document.getElementById('latestver') && \"" + 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.concat("<form onsubmit=\"if(document.getElementById('currentver') == document.getElementById('betaver') && \"" + 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.concat("<form onsubmit=\"if(document.getElementById('currentver') == document.getElementById('devver') && \"" + 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.concat("<div style=\"clear: both\"></div><br>");
response.concat("<b>Current version: </b>");
response.concat("<b>Current version: </b><span id=\"currentver\">");
response.concat(NUKI_HUB_VERSION);
response.concat(" (");
response.concat(NUKI_HUB_BUILD);
response.concat("), ");
response.concat(")</span>, ");
response.concat(NUKI_HUB_DATE);
response.concat("<br>");
#ifndef NUKI_HUB_UPDATER
bool manifestSuccess = false;
NetworkClientSecure *client = new NetworkClientSecure;
if (client) {
client->setDefaultCACertBundle();
@@ -454,28 +460,34 @@ void WebCfgServer::buildOtaHtml(String &response, bool errored)
if (!jsonError)
{
response.concat("<b>Latest release version: </b>");
manifestSuccess = true;
response.concat("<b>Latest release version: </b><span id=\"latestver\">");
response.concat(doc["release"]["fullversion"].as<const char*>());
response.concat(" (");
response.concat(doc["release"]["build"].as<const char*>());
response.concat("), ");
response.concat(")</span>, ");
response.concat(doc["release"]["time"].as<const char*>());
response.concat("<br>");
response.concat("<b>Latest beta version: </b>");
response.concat(doc["beta"]["fullversion"].as<const char*>());
response.concat("<b>Latest beta version: </b><span id=\"betaver\">");
if(doc["beta"]["fullversion"] != "No beta available")
{
response.concat(doc["beta"]["fullversion"].as<const char*>());
response.concat(" (");
response.concat(doc["beta"]["build"].as<const char*>());
response.concat("), ");
response.concat(")</span>, ");
response.concat(doc["beta"]["time"].as<const char*>());
}
else
{
response.concat(doc["beta"]["fullversion"].as<const char*>());
response.concat("</span>");
}
response.concat("<br>");
response.concat("<b>Latest development version: </b>");
response.concat("<b>Latest development version: </b><span id=\"devver\">");
response.concat(doc["master"]["fullversion"].as<const char*>());
response.concat(" (");
response.concat(doc["master"]["build"].as<const char*>());
response.concat("), ");
response.concat(")</span>, ");
response.concat(doc["master"]["time"].as<const char*>());
response.concat("<br>");
}
@@ -485,6 +497,11 @@ void WebCfgServer::buildOtaHtml(String &response, bool errored)
}
delete client;
}
if(!manifestSuccess)
{
response.concat("<span id=\"currentver\" style=\"display: none;\">currentver</span><span id=\"latestver\" style=\"display: none;\">latestver</span><span id=\"devver\" style=\"display: none;\">devver</span><span id=\"betaver\" style=\"display: none;\">betaver</span>");
}
#endif
response.concat("<br></div>");
@@ -665,11 +682,20 @@ void WebCfgServer::handleOtaUpload()
}
}
void WebCfgServer::buildConfirmHtml(String &response, const String &message, uint32_t redirectDelay)
void WebCfgServer::buildConfirmHtml(String &response, const String &message, uint32_t redirectDelay, bool redirect)
{
String delay(redirectDelay);
String header = "<meta http-equiv=\"Refresh\" content=\"" + delay + "; url=/\" />";
String header;
if(!redirect)
{
String delay(redirectDelay);
header = "<meta http-equiv=\"Refresh\" content=\"" + delay + "; url=/\" />";
}
else
{
String delay(redirectDelay * 1000);
header = "<script type=\"text/JavaScript\">function Redirect() { window.location.href = \"/\"; } setTimeout(function() { Redirect(); }, " + delay + "); </script>";
}
buildHtmlHeader(response, header);
response.concat(message);
response.concat("</body></html>");
@@ -688,6 +714,12 @@ void WebCfgServer::sendFavicon()
_server.send(200, "image/png", (const char*)favicon_32x32, sizeof(favicon_32x32));
}
String WebCfgServer::generateConfirmCode()
{
int code = random(1000,9999);
return String(code);
}
#ifndef NUKI_HUB_UPDATER
void WebCfgServer::sendSettings()
{
@@ -2976,6 +3008,72 @@ void WebCfgServer::processUnpair(bool opener)
restartEsp(RestartReason::DeviceUnpaired);
}
void WebCfgServer::processUpdate()
{
String response = "";
String key = _server.argName(0);
String key2 = _server.argName(1);
String key3 = _server.argName(2);
String value3 = _server.arg(2);
String key4 = _server.argName(3);
if(key3 != "token" || value3 != _confirmCode)
{
buildConfirmHtml(response, "Confirm code is invalid.", 3, true);
_server.send(200, "text/html", response);
return;
}
if(key == "beta")
{
if(key2 == "debug")
{
buildConfirmHtml(response, "Rebooting to update Nuki Hub and Nuki Hub updater<br/>Updating to latest DEBUG BETA version", 2, true);
_preferences->putString(preference_ota_updater_url, GITHUB_BETA_UPDATER_BINARY_URL_DBG);
_preferences->putString(preference_ota_main_url, GITHUB_BETA_RELEASE_BINARY_URL_DBG);
}
else
{
buildConfirmHtml(response, "Rebooting to update Nuki Hub and Nuki Hub updater<br/>Updating to latest BETA version", 2, true);
_preferences->putString(preference_ota_updater_url, GITHUB_BETA_UPDATER_BINARY_URL);
_preferences->putString(preference_ota_main_url, GITHUB_BETA_RELEASE_BINARY_URL);
}
}
else if(key == "master")
{
if(key2 == "debug")
{
buildConfirmHtml(response, "Rebooting to update Nuki Hub and Nuki Hub updater<br/>Updating to latest DEBUG DEVELOPMENT version", 2, true);
_preferences->putString(preference_ota_updater_url, GITHUB_MASTER_UPDATER_BINARY_URL_DBG);
_preferences->putString(preference_ota_main_url, GITHUB_MASTER_RELEASE_BINARY_URL_DBG);
}
else
{
buildConfirmHtml(response, "Rebooting to update Nuki Hub and Nuki Hub updater<br/>Updating to latest DEVELOPMENT version", 2, true);
_preferences->putString(preference_ota_updater_url, GITHUB_MASTER_UPDATER_BINARY_URL);
_preferences->putString(preference_ota_main_url, GITHUB_MASTER_RELEASE_BINARY_URL);
}
}
else
{
if(key2 == "debug")
{
buildConfirmHtml(response, "Rebooting to update Nuki Hub and Nuki Hub updater<br/>Updating to latest DEBUG RELEASE version", 2, true);
_preferences->putString(preference_ota_updater_url, GITHUB_LATEST_UPDATER_BINARY_URL_DBG);
_preferences->putString(preference_ota_main_url, GITHUB_LATEST_UPDATER_BINARY_URL_DBG);
}
else
{
buildConfirmHtml(response, "Rebooting to update Nuki Hub and Nuki Hub updater<br/>Updating to latest RELEASE version", 2, true);
_preferences->putString(preference_ota_updater_url, GITHUB_LATEST_UPDATER_BINARY_URL);
_preferences->putString(preference_ota_main_url, GITHUB_LATEST_RELEASE_BINARY_URL);
}
}
_server.send(200, "text/html", response);
waitAndProcess(true, 1000);
restartEsp(RestartReason::OTAReboot);
}
void WebCfgServer::processFactoryReset()
{
bool resetWifi = false;
@@ -3238,13 +3336,6 @@ void WebCfgServer::printParameter(String& response, const char *description, con
}
String WebCfgServer::generateConfirmCode()
{
int code = random(1000,9999);
return String(code);
}
const std::vector<std::pair<String, String>> WebCfgServer::getNetworkDetectionOptions() const
{
std::vector<std::pair<String, String>> options;