Merge branch 'http-server' of https://github.com/iranl/nuki_hub into http-server
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#define NUKI_HUB_VERSION "9.01"
|
#define NUKI_HUB_VERSION "9.01"
|
||||||
#define NUKI_HUB_BUILD "unknownbuildnr"
|
#define NUKI_HUB_BUILD "unknownbuildnr"
|
||||||
#define NUKI_HUB_DATE "2024-08-26"
|
#define NUKI_HUB_DATE "2024-08-27"
|
||||||
|
|
||||||
#define GITHUB_LATEST_RELEASE_URL (char*)"https://github.com/technyon/nuki_hub/releases/latest"
|
#define GITHUB_LATEST_RELEASE_URL (char*)"https://github.com/technyon/nuki_hub/releases/latest"
|
||||||
#define GITHUB_OTA_MANIFEST_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/manifest.json"
|
#define GITHUB_OTA_MANIFEST_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/manifest.json"
|
||||||
|
|||||||
@@ -149,6 +149,7 @@ void WebCfgServer::initialize()
|
|||||||
_network->reconfigureDevice();
|
_network->reconfigureDevice();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
return(ESP_OK);
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
_psychicServer->on("/unpairlock", HTTP_POST, [&](PsychicRequest *request){
|
_psychicServer->on("/unpairlock", HTTP_POST, [&](PsychicRequest *request){
|
||||||
@@ -225,16 +226,38 @@ void WebCfgServer::initialize()
|
|||||||
#endif
|
#endif
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
PsychicUploadHandler *updateHandler = new PsychicUploadHandler();
|
||||||
_psychicServer->on("/uploadota", HTTP_POST,
|
updateHandler->onUpload([&](PsychicRequest *request, const String& filename, uint64_t index, uint8_t *data, size_t len, bool final)
|
||||||
[&](PsychicRequest *request) {},
|
|
||||||
[&](PsychicRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final)
|
|
||||||
{
|
{
|
||||||
if(strlen(_credUser) > 0 && strlen(_credPassword) > 0) if(!request->authenticate(_credUser, _credPassword)) return request->requestAuthentication(BASIC_AUTH, "Nuki Hub", "You must log in.");
|
if(strlen(_credUser) > 0 && strlen(_credPassword) > 0) if(!request->authenticate(_credUser, _credPassword)) return request->requestAuthentication(BASIC_AUTH, "Nuki Hub", "You must log in.");
|
||||||
return handleOtaUpload(request, filename, index, data, len, final);
|
return handleOtaUpload(request, filename, index, data, len, final);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
*/
|
|
||||||
|
updateHandler->onRequest([&](PsychicRequest *request) {
|
||||||
|
if(strlen(_credUser) > 0 && strlen(_credPassword) > 0) if(!request->authenticate(_credUser, _credPassword)) return request->requestAuthentication(BASIC_AUTH, "Nuki Hub", "You must log in.");
|
||||||
|
|
||||||
|
String result;
|
||||||
|
if (!Update.hasError())
|
||||||
|
{
|
||||||
|
Log->print("Update code or data OK Update.errorString() ");
|
||||||
|
Log->println(Update.errorString());
|
||||||
|
result = "<b style='color:green'>Update OK.</b>";
|
||||||
|
esp_err_t res = request->reply(200,"text/html",result.c_str());
|
||||||
|
restartEsp(RestartReason::OTACompleted);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = " Update.errorString() " + String(Update.errorString());
|
||||||
|
Log->print("ERROR : error ");
|
||||||
|
Log->println(result.c_str());
|
||||||
|
esp_err_t res = request->reply(500, "text/html", result.c_str());
|
||||||
|
restartEsp(RestartReason::OTAAborted);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_psychicServer->on("/uploadota", HTTP_POST, updateHandler);
|
||||||
//Update.onProgress(printProgress);
|
//Update.onProgress(printProgress);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,27 +318,27 @@ esp_err_t WebCfgServer::buildOtaHtml(PsychicRequest *request, bool debug)
|
|||||||
bool manifestSuccess = false;
|
bool manifestSuccess = false;
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
|
|
||||||
NetworkClientSecure *client = new NetworkClientSecure;
|
NetworkClientSecure *clientOTAUpdate = new NetworkClientSecure;
|
||||||
if (client) {
|
if (clientOTAUpdate) {
|
||||||
client->setCACertBundle(x509_crt_imported_bundle_bin_start, x509_crt_imported_bundle_bin_end - x509_crt_imported_bundle_bin_start);
|
clientOTAUpdate->setCACertBundle(x509_crt_imported_bundle_bin_start, x509_crt_imported_bundle_bin_end - x509_crt_imported_bundle_bin_start);
|
||||||
{
|
{
|
||||||
HTTPClient https;
|
HTTPClient httpsOTAClient;
|
||||||
https.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
httpsOTAClient.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
||||||
https.setTimeout(2500);
|
httpsOTAClient.setTimeout(2500);
|
||||||
https.useHTTP10(true);
|
httpsOTAClient.useHTTP10(true);
|
||||||
|
|
||||||
if (https.begin(*client, GITHUB_OTA_MANIFEST_URL)) {
|
if (httpsOTAClient.begin(*clientOTAUpdate, GITHUB_OTA_MANIFEST_URL)) {
|
||||||
int http_responseCode = https.GET();
|
int httpResponseCodeOTA = httpsOTAClient.GET();
|
||||||
|
|
||||||
if (http_responseCode == HTTP_CODE_OK || http_responseCode == HTTP_CODE_MOVED_PERMANENTLY)
|
if (httpResponseCodeOTA == HTTP_CODE_OK || httpResponseCodeOTA == HTTP_CODE_MOVED_PERMANENTLY)
|
||||||
{
|
{
|
||||||
DeserializationError jsonError = deserializeJson(doc, https.getStream());
|
DeserializationError jsonError = deserializeJson(doc, httpsOTAClient.getStream());
|
||||||
if (!jsonError) { manifestSuccess = true; }
|
if (!jsonError) { manifestSuccess = true; }
|
||||||
}
|
}
|
||||||
https.end();
|
httpsOTAClient.end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete client;
|
delete clientOTAUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!manifestSuccess)
|
if(!manifestSuccess)
|
||||||
@@ -469,35 +492,32 @@ void WebCfgServer::printProgress(size_t prg, size_t sz) {
|
|||||||
Log->printf("Progress: %d%%\n", (prg*100)/_otaContentLen);
|
Log->printf("Progress: %d%%\n", (prg*100)/_otaContentLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebCfgServer::handleOtaUpload(PsychicRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final)
|
esp_err_t WebCfgServer::handleOtaUpload(PsychicRequest *request, const String& filename, uint64_t index, uint8_t *data, size_t len, bool final)
|
||||||
{
|
{
|
||||||
if(!request->url().endsWith("/uploadota")) return;
|
if(!request->url().endsWith("/uploadota")) return(ESP_FAIL);
|
||||||
|
|
||||||
if(filename == "")
|
if(filename == "")
|
||||||
{
|
{
|
||||||
Log->println("Invalid file for OTA upload");
|
Log->println("Invalid file for OTA upload");
|
||||||
return;
|
return(ESP_FAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!index)
|
if (!Update.hasError()) {
|
||||||
{
|
if (!index){
|
||||||
|
Update.clearError();
|
||||||
|
|
||||||
Log->println("Starting manual OTA update");
|
Log->println("Starting manual OTA update");
|
||||||
_otaContentLen = request->contentLength();
|
_otaContentLen = request->contentLength();
|
||||||
|
|
||||||
if(_partitionType == 1 && _otaContentLen > 1600000)
|
if(_partitionType == 1 && _otaContentLen > 1600000)
|
||||||
{
|
{
|
||||||
Log->println("Uploaded OTA file too large, are you trying to upload a Nuki Hub binary instead of a Nuki Hub updater binary?");
|
Log->println("Uploaded OTA file too large, are you trying to upload a Nuki Hub binary instead of a Nuki Hub updater binary?");
|
||||||
return;
|
return(ESP_FAIL);
|
||||||
}
|
}
|
||||||
else if(_partitionType == 2 && _otaContentLen < 1600000)
|
else if(_partitionType == 2 && _otaContentLen < 1600000)
|
||||||
{
|
{
|
||||||
Log->println("Uploaded OTA file is too small, are you trying to upload a Nuki Hub updater binary instead of a Nuki Hub binary?");
|
Log->println("Uploaded OTA file is too small, are you trying to upload a Nuki Hub updater binary instead of a Nuki Hub binary?");
|
||||||
return;
|
return(ESP_FAIL);
|
||||||
}
|
|
||||||
|
|
||||||
int cmd = U_FLASH;
|
|
||||||
if (!Update.begin(UPDATE_SIZE_UNKNOWN, cmd)) {
|
|
||||||
Update.printError(Serial);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_otaStartTs = esp_timer_get_time() / 1000;
|
_otaStartTs = esp_timer_get_time() / 1000;
|
||||||
@@ -522,35 +542,58 @@ void WebCfgServer::handleOtaUpload(PsychicRequest *request, String filename, siz
|
|||||||
#endif
|
#endif
|
||||||
Log->print("handleFileUpload Name: ");
|
Log->print("handleFileUpload Name: ");
|
||||||
Log->println(filename);
|
Log->println(filename);
|
||||||
|
|
||||||
|
if (!Update.begin(UPDATE_SIZE_UNKNOWN, U_FLASH)) {
|
||||||
|
if (!Update.hasError())
|
||||||
|
{
|
||||||
|
Update.abort();
|
||||||
|
}
|
||||||
|
Log->print("ERROR : update.begin error Update.errorString() ");
|
||||||
|
Log->println(Update.errorString());
|
||||||
|
return(ESP_FAIL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_otaContentLen == 0) return;
|
if ((len) && (!Update.hasError())) {
|
||||||
|
|
||||||
if (Update.write(data, len) != len) {
|
if (Update.write(data, len) != len) {
|
||||||
Update.printError(Serial);
|
if (!Update.hasError())
|
||||||
restartEsp(RestartReason::OTAAborted);
|
{
|
||||||
|
Update.abort();
|
||||||
|
}
|
||||||
|
Log->print("ERROR : update.write error Update.errorString() ");
|
||||||
|
Log->println(Update.errorString());
|
||||||
|
return(ESP_FAIL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if ((final) && (!Update.hasError())) {
|
||||||
if (final) {
|
if (Update.end(true)) {
|
||||||
AsyncWebServerResponse *response = request->beginResponse(302, "text/plain", "Please wait while the device reboots");
|
Log->print("Update Success: ");
|
||||||
response->addHeader("Refresh", "20");
|
Log->print(index+len);
|
||||||
response->addHeader("Location", "/");
|
Log->println(" written");
|
||||||
request->send(response);
|
}
|
||||||
if (!Update.end(true)){
|
else {
|
||||||
Update.printError(Serial);
|
if (!Update.hasError())
|
||||||
restartEsp(RestartReason::OTAAborted);
|
{
|
||||||
} else {
|
Update.abort();
|
||||||
|
}
|
||||||
|
Log->print("ERROR : update end error Update.errorString() ");
|
||||||
|
Log->println(Update.errorString());
|
||||||
|
return(ESP_FAIL);
|
||||||
|
}
|
||||||
|
}
|
||||||
Log->print(F("Progress: 100%"));
|
Log->print(F("Progress: 100%"));
|
||||||
Log->println();
|
Log->println();
|
||||||
Log->print("handleFileUpload Total Size: ");
|
Log->print("handleFileUpload Total Size: ");
|
||||||
Log->println(index+len);
|
Log->println(index+len);
|
||||||
Log->println("Update complete");
|
Log->println("Update complete");
|
||||||
Log->flush();
|
Log->flush();
|
||||||
restartEsp(RestartReason::OTACompleted);
|
return(ESP_OK);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return(ESP_FAIL);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t WebCfgServer::buildConfirmHtml(PsychicRequest *request, const String &message, uint32_t redirectDelay, bool redirect)
|
esp_err_t WebCfgServer::buildConfirmHtml(PsychicRequest *request, const String &message, uint32_t redirectDelay, bool redirect)
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ private:
|
|||||||
esp_err_t sendFavicon(PsychicRequest *request);
|
esp_err_t sendFavicon(PsychicRequest *request);
|
||||||
void buildHtmlHeader(PsychicStreamResponse *response, String additionalHeader = "");
|
void buildHtmlHeader(PsychicStreamResponse *response, String additionalHeader = "");
|
||||||
void waitAndProcess(const bool blocking, const uint32_t duration);
|
void waitAndProcess(const bool blocking, const uint32_t duration);
|
||||||
void handleOtaUpload(PsychicRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final);
|
esp_err_t handleOtaUpload(PsychicRequest *request, const String& filename, uint64_t index, uint8_t *data, size_t len, bool final);
|
||||||
void printProgress(size_t prg, size_t sz);
|
void printProgress(size_t prg, size_t sz);
|
||||||
|
|
||||||
PsychicHttpServer* _psychicServer = nullptr;
|
PsychicHttpServer* _psychicServer = nullptr;
|
||||||
|
|||||||
15
src/main.cpp
15
src/main.cpp
@@ -19,10 +19,12 @@
|
|||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "PreferencesKeys.h"
|
#include "PreferencesKeys.h"
|
||||||
#include "RestartReason.h"
|
#include "RestartReason.h"
|
||||||
|
/*
|
||||||
#ifdef DEBUG_NUKIHUB
|
#ifdef DEBUG_NUKIHUB
|
||||||
#include <WString.h>
|
#include <WString.h>
|
||||||
#include <MycilaWebSerial.h>
|
#include <MycilaWebSerial.h>
|
||||||
#endif
|
#endif
|
||||||
|
*/
|
||||||
|
|
||||||
char log_print_buffer[1024];
|
char log_print_buffer[1024];
|
||||||
|
|
||||||
@@ -490,6 +492,9 @@ void setup()
|
|||||||
if(!doOta)
|
if(!doOta)
|
||||||
{
|
{
|
||||||
psychicServer = new PsychicHttpServer;
|
psychicServer = new PsychicHttpServer;
|
||||||
|
psychicServer->config.max_uri_handlers = 40;
|
||||||
|
psychicServer->config.stack_size = 8192;
|
||||||
|
psychicServer->listen(80);
|
||||||
|
|
||||||
if(forceEnableWebServer || preferences->getBool(preference_webserver_enabled, true))
|
if(forceEnableWebServer || preferences->getBool(preference_webserver_enabled, true))
|
||||||
{
|
{
|
||||||
@@ -497,18 +502,18 @@ void setup()
|
|||||||
webCfgServer->initialize();
|
webCfgServer->initialize();
|
||||||
psychicServer->onNotFound([](PsychicRequest* request) { return request->redirect("/"); });
|
psychicServer->onNotFound([](PsychicRequest* request) { return request->redirect("/"); });
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
#ifdef DEBUG_NUKIHUB
|
#ifdef DEBUG_NUKIHUB
|
||||||
else psychicServer->onNotFound([](PsychicRequest* request) { return request->redirect("/webserial"); });
|
else psychicServer->onNotFound([](PsychicRequest* request) { return request->redirect("/webserial"); });
|
||||||
|
|
||||||
if(preferences->getBool(preference_webserial_enabled, false))
|
if(preferences->getBool(preference_webserial_enabled, false))
|
||||||
{
|
{
|
||||||
//WebSerial.setAuthentication(preferences->getString(preference_cred_user), preferences->getString(preference_cred_password));
|
WebSerial.setAuthentication(preferences->getString(preference_cred_user), preferences->getString(preference_cred_password));
|
||||||
//WebSerial.begin(asyncServer);
|
WebSerial.begin(asyncServer);
|
||||||
//WebSerial.setBuffer(1024);
|
WebSerial.setBuffer(1024);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
*/
|
||||||
psychicServer->listen(80);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user