Merge pull request #585 from iranl/psychichttp2
PsychicHTTP v2-dev branch, add HTTPS server (PSRAM only), add HTTP Digest Authentication
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
#define NUKI_HUB_VERSION "9.07"
|
||||
#define NUKI_HUB_VERSION_INT (uint32_t)907
|
||||
#define NUKI_HUB_BUILD "unknownbuildnr"
|
||||
#define NUKI_HUB_DATE "2024-12-30"
|
||||
#define NUKI_HUB_DATE "2024-12-31"
|
||||
|
||||
#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"
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
#define preference_debug_hex_data (char*)"dbgHexData"
|
||||
#define preference_debug_command (char*)"dbgCommand"
|
||||
#define preference_connect_mode (char*)"nukiConnMode"
|
||||
#define preference_http_auth_type (char*)"httpdAuthType"
|
||||
|
||||
// CHANGE DOES NOT REQUIRE REBOOT TO TAKE EFFECT
|
||||
#define preference_find_best_rssi (char*)"nwbestrssi"
|
||||
@@ -222,8 +223,9 @@ inline void initPreferences(Preferences* preferences)
|
||||
preferences->putBool(preference_debug_hex_data, false);
|
||||
preferences->putBool(preference_debug_command, false);
|
||||
preferences->putBool(preference_connect_mode, true);
|
||||
|
||||
preferences->putBool(preference_http_auth_type, false);
|
||||
preferences->putBool(preference_retain_gpio, false);
|
||||
|
||||
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32H2
|
||||
WiFi.begin();
|
||||
@@ -370,7 +372,7 @@ private:
|
||||
preference_opener_continuous_mode, preference_lock_max_keypad_code_count, preference_opener_max_keypad_code_count,
|
||||
preference_lock_max_timecontrol_entry_count, preference_opener_max_timecontrol_entry_count, preference_enable_bootloop_reset, preference_mqtt_ca, preference_mqtt_crt,
|
||||
preference_mqtt_key, preference_mqtt_hass_discovery, preference_mqtt_hass_cu_url, preference_buffer_size, preference_ip_dhcp_enabled, preference_ip_address,
|
||||
preference_ip_subnet, preference_ip_gateway, preference_ip_dns_server, preference_network_hardware,
|
||||
preference_ip_subnet, preference_ip_gateway, preference_ip_dns_server, preference_network_hardware, preference_http_auth_type,
|
||||
preference_rssi_publish_interval, preference_hostname, preference_network_timeout, preference_restart_on_disconnect,
|
||||
preference_restart_ble_beacon_lost, preference_query_interval_lockstate, preference_timecontrol_topic_per_entry, preference_keypad_topic_per_entry,
|
||||
preference_query_interval_configuration, preference_query_interval_battery, preference_query_interval_keypad, preference_keypad_control_enabled,
|
||||
@@ -402,7 +404,7 @@ private:
|
||||
preference_publish_authdata, preference_publish_debug_info, preference_official_hybrid_enabled, preference_mqtt_hass_enabled, preference_retain_gpio,
|
||||
preference_official_hybrid_actions, preference_official_hybrid_retry, preference_conf_info_enabled, preference_disable_non_json, preference_update_from_mqtt,
|
||||
preference_auth_control_enabled, preference_auth_topic_per_entry, preference_auth_info_enabled, preference_webserial_enabled, preference_hass_device_discovery,
|
||||
preference_ntw_reconfigure, preference_keypad_check_code_enabled, preference_disable_network_not_connected, preference_find_best_rssi,
|
||||
preference_ntw_reconfigure, preference_keypad_check_code_enabled, preference_disable_network_not_connected, preference_find_best_rssi, preference_http_auth_type,
|
||||
preference_debug_connect, preference_debug_communication, preference_debug_readable_data, preference_debug_hex_data, preference_debug_command, preference_connect_mode,
|
||||
preference_lock_force_id, preference_lock_force_doorsensor, preference_lock_force_keypad, preference_opener_force_id, preference_opener_force_keypad
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -48,29 +48,30 @@ public:
|
||||
|
||||
private:
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
esp_err_t sendSettings(PsychicRequest *request);
|
||||
bool processArgs(PsychicRequest *request, String& message);
|
||||
bool processImport(PsychicRequest *request, String& message);
|
||||
void processGpioArgs(PsychicRequest *request);
|
||||
esp_err_t buildHtml(PsychicRequest *request);
|
||||
esp_err_t buildAccLvlHtml(PsychicRequest *request);
|
||||
esp_err_t buildCredHtml(PsychicRequest *request);
|
||||
esp_err_t buildImportExportHtml(PsychicRequest *request);
|
||||
esp_err_t buildNetworkConfigHtml(PsychicRequest *request);
|
||||
esp_err_t buildMqttConfigHtml(PsychicRequest *request);
|
||||
esp_err_t buildMqttSSLConfigHtml(PsychicRequest *request, int type=0);
|
||||
esp_err_t buildStatusHtml(PsychicRequest *request);
|
||||
esp_err_t buildAdvancedConfigHtml(PsychicRequest *request);
|
||||
esp_err_t buildNukiConfigHtml(PsychicRequest *request);
|
||||
esp_err_t buildGpioConfigHtml(PsychicRequest *request);
|
||||
esp_err_t sendSettings(PsychicRequest *request, PsychicResponse* resp);
|
||||
bool processArgs(PsychicRequest *request, PsychicResponse* resp, String& message);
|
||||
bool processImport(PsychicRequest *request, PsychicResponse* resp, String& message);
|
||||
void processGpioArgs(PsychicRequest *request, PsychicResponse* resp);
|
||||
esp_err_t buildHtml(PsychicRequest *request, PsychicResponse* resp);
|
||||
esp_err_t buildAccLvlHtml(PsychicRequest *request, PsychicResponse* resp);
|
||||
esp_err_t buildCredHtml(PsychicRequest *request, PsychicResponse* resp);
|
||||
esp_err_t buildImportExportHtml(PsychicRequest *request, PsychicResponse* resp);
|
||||
esp_err_t buildNetworkConfigHtml(PsychicRequest *request, PsychicResponse* resp);
|
||||
esp_err_t buildMqttConfigHtml(PsychicRequest *request, PsychicResponse* resp);
|
||||
esp_err_t buildMqttSSLConfigHtml(PsychicRequest *request, PsychicResponse* resp, int type=0);
|
||||
esp_err_t buildHttpSSLConfigHtml(PsychicRequest *request, PsychicResponse* resp, int type=0);
|
||||
esp_err_t buildStatusHtml(PsychicRequest *request, PsychicResponse* resp);
|
||||
esp_err_t buildAdvancedConfigHtml(PsychicRequest *request, PsychicResponse* resp);
|
||||
esp_err_t buildNukiConfigHtml(PsychicRequest *request, PsychicResponse* resp);
|
||||
esp_err_t buildGpioConfigHtml(PsychicRequest *request, PsychicResponse* resp);
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32H2
|
||||
esp_err_t buildConfigureWifiHtml(PsychicRequest *request);
|
||||
esp_err_t buildConfigureWifiHtml(PsychicRequest *request, PsychicResponse* resp);
|
||||
#endif
|
||||
esp_err_t buildInfoHtml(PsychicRequest *request);
|
||||
esp_err_t buildCustomNetworkConfigHtml(PsychicRequest *request);
|
||||
esp_err_t processUnpair(PsychicRequest *request, bool opener);
|
||||
esp_err_t processUpdate(PsychicRequest *request);
|
||||
esp_err_t processFactoryReset(PsychicRequest *request);
|
||||
esp_err_t buildInfoHtml(PsychicRequest *request, PsychicResponse* resp);
|
||||
esp_err_t buildCustomNetworkConfigHtml(PsychicRequest *request, PsychicResponse* resp);
|
||||
esp_err_t processUnpair(PsychicRequest *request, PsychicResponse* resp, bool opener);
|
||||
esp_err_t processUpdate(PsychicRequest *request, PsychicResponse* resp);
|
||||
esp_err_t processFactoryReset(PsychicRequest *request, PsychicResponse* resp);
|
||||
void printTextarea(PsychicStreamResponse *response, const char *token, const char *description, const char *value, const size_t& maxLength, const bool& enabled = true, const bool& showLengthRestriction = false);
|
||||
void printDropDown(PsychicStreamResponse *response, const char *token, const char *description, const String preselectedValue, std::vector<std::pair<String, String>> options, const String className);
|
||||
void buildNavigationMenuEntry(PsychicStreamResponse *response, const char *title, const char *targetPath, const char* warningMessage = "");
|
||||
@@ -94,30 +95,30 @@ private:
|
||||
bool _brokerConfigured = false;
|
||||
bool _rebootRequired = false;
|
||||
#endif
|
||||
|
||||
|
||||
std::vector<String> _ssidList;
|
||||
std::vector<int> _rssiList;
|
||||
String generateConfirmCode();
|
||||
String _confirmCode = "----";
|
||||
|
||||
esp_err_t buildSSIDListHtml(PsychicRequest *request);
|
||||
esp_err_t buildConfirmHtml(PsychicRequest *request, const String &message, uint32_t redirectDelay = 5, bool redirect = false, String redirectTo = "/");
|
||||
esp_err_t buildOtaHtml(PsychicRequest *request, bool debug = false);
|
||||
esp_err_t sendCss(PsychicRequest *request);
|
||||
esp_err_t sendFavicon(PsychicRequest *request);
|
||||
|
||||
esp_err_t buildSSIDListHtml(PsychicRequest *request, PsychicResponse* resp);
|
||||
esp_err_t buildConfirmHtml(PsychicRequest *request, PsychicResponse* resp, const String &message, uint32_t redirectDelay = 5, bool redirect = false, String redirectTo = "/");
|
||||
esp_err_t buildOtaHtml(PsychicRequest *request, PsychicResponse* resp, bool debug = false);
|
||||
esp_err_t sendCss(PsychicRequest *request, PsychicResponse* resp);
|
||||
esp_err_t sendFavicon(PsychicRequest *request, PsychicResponse* resp);
|
||||
void createSsidList();
|
||||
void buildHtmlHeader(PsychicStreamResponse *response, String additionalHeader = "");
|
||||
void waitAndProcess(const bool blocking, const uint32_t duration);
|
||||
esp_err_t handleOtaUpload(PsychicRequest *request, const String& filename, uint64_t index, uint8_t *data, size_t len, bool final);
|
||||
void printCheckBox(PsychicStreamResponse *response, const char* token, const char* description, const bool value, const char* htmlClass);
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32H2
|
||||
esp_err_t buildWifiConnectHtml(PsychicRequest *request);
|
||||
bool processWiFi(PsychicRequest *request, String& message);
|
||||
|
||||
esp_err_t buildWifiConnectHtml(PsychicRequest *request, PsychicResponse* resp);
|
||||
bool processWiFi(PsychicRequest *request, PsychicResponse* resp, String& message);
|
||||
|
||||
#endif
|
||||
void printInputField(PsychicStreamResponse *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(PsychicStreamResponse *response, const char* token, const char* description, const int value, size_t maxLength, const char* args);
|
||||
|
||||
|
||||
PsychicHttpServer* _psychicServer = nullptr;
|
||||
NukiNetwork* _network = nullptr;
|
||||
Preferences* _preferences = nullptr;
|
||||
|
||||
186
src/main.cpp
186
src/main.cpp
@@ -10,6 +10,11 @@
|
||||
#include "esp32-hal-log.h"
|
||||
#include "hal/wdt_hal.h"
|
||||
#include "esp_chip_info.h"
|
||||
#ifdef CONFIG_SOC_SPIRAM_SUPPORTED
|
||||
#include "esp_psram.h"
|
||||
#include "FS.h"
|
||||
#include "SPIFFS.h"
|
||||
#endif
|
||||
|
||||
#ifndef NUKI_HUB_UPDATER
|
||||
#include "NukiWrapper.h"
|
||||
@@ -65,8 +70,10 @@ int64_t restartTs = 10 * 60 * 1000;
|
||||
#endif
|
||||
|
||||
PsychicHttpServer* psychicServer = nullptr;
|
||||
PsychicHttpsServer* psychicSSLServer = nullptr;
|
||||
NukiNetwork* network = nullptr;
|
||||
WebCfgServer* webCfgServer = nullptr;
|
||||
WebCfgServer* webCfgServerSSL = nullptr;
|
||||
Preferences* preferences = nullptr;
|
||||
|
||||
RTC_NOINIT_ATTR int espRunning;
|
||||
@@ -80,6 +87,7 @@ RTC_NOINIT_ATTR bool disableNetwork;
|
||||
RTC_NOINIT_ATTR bool wifiFallback;
|
||||
RTC_NOINIT_ATTR bool ethCriticalFailure;
|
||||
|
||||
bool doOta = false;
|
||||
bool restartReason_isValid;
|
||||
RestartReason currentRestartReason = RestartReason::NotApplicable;
|
||||
|
||||
@@ -132,7 +140,7 @@ void setReroute()
|
||||
esp_log_level_set("httpd_parse", ESP_LOG_ERROR);
|
||||
esp_log_level_set("httpd_txrx", ESP_LOG_ERROR);
|
||||
esp_log_level_set("httpd_uri", ESP_LOG_ERROR);
|
||||
esp_log_level_set("event", ESP_LOG_ERROR);
|
||||
esp_log_level_set("event", ESP_LOG_ERROR);
|
||||
esp_log_level_set("psychic", ESP_LOG_ERROR);
|
||||
esp_log_level_set("ARDUINO", ESP_LOG_DEBUG);
|
||||
esp_log_level_set("nvs", ESP_LOG_ERROR);
|
||||
@@ -494,7 +502,6 @@ void setup()
|
||||
preferences = new Preferences();
|
||||
preferences->begin("nukihub", false);
|
||||
initPreferences(preferences);
|
||||
bool doOta = false;
|
||||
uint8_t partitionType = checkPartition();
|
||||
|
||||
initializeRestartReason();
|
||||
@@ -539,16 +546,84 @@ void setup()
|
||||
|
||||
if(!doOta)
|
||||
{
|
||||
psychicServer = new PsychicHttpServer;
|
||||
psychicServer->config.max_uri_handlers = 10;
|
||||
psychicServer->config.stack_size = HTTPD_TASK_SIZE;
|
||||
psychicServer->listen(80);
|
||||
webCfgServer = new WebCfgServer(network, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi, partitionType, psychicServer);
|
||||
webCfgServer->initialize();
|
||||
psychicServer->onNotFound([](PsychicRequest* request)
|
||||
#ifdef CONFIG_SOC_SPIRAM_SUPPORTED
|
||||
bool failed = false;
|
||||
|
||||
if (esp_psram_get_size() <= 0) {
|
||||
Log->println("Not running on PSRAM enabled device");
|
||||
failed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return request->redirect("/");
|
||||
});
|
||||
if (!SPIFFS.begin(true)) {
|
||||
Log->println("SPIFFS Mount Failed");
|
||||
failed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
File file = SPIFFS.open("/http_ssl.crt");
|
||||
if (!file || file.isDirectory()) {
|
||||
failed = true;
|
||||
Log->println("http_ssl.crt not found");
|
||||
}
|
||||
else
|
||||
{
|
||||
char cert[4400] = {0};
|
||||
|
||||
Log->println("Reading http_ssl.crt");
|
||||
uint32_t i = 0;
|
||||
while(file.available()){
|
||||
cert[i] = file.read();
|
||||
i++;
|
||||
}
|
||||
file.close();
|
||||
|
||||
File file2 = SPIFFS.open("/http_ssl.key");
|
||||
if (!file2 || file2.isDirectory()) {
|
||||
failed = true;
|
||||
Log->println("http_ssl.key not found");
|
||||
}
|
||||
else
|
||||
{
|
||||
char key[2200] = {0};
|
||||
|
||||
Log->println("Reading http_ssl.key");
|
||||
i = 0;
|
||||
while(file2.available()){
|
||||
key[i] = file2.read();
|
||||
i++;
|
||||
}
|
||||
file2.close();
|
||||
|
||||
psychicSSLServer = new PsychicHttpsServer;
|
||||
psychicSSLServer->ssl_config.httpd.max_open_sockets = 8;
|
||||
psychicSSLServer->setCertificate(cert, key);
|
||||
psychicSSLServer->config.stack_size = HTTPD_TASK_SIZE;
|
||||
webCfgServerSSL = new WebCfgServer(network, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi, partitionType, psychicSSLServer);
|
||||
webCfgServerSSL->initialize();
|
||||
psychicSSLServer->onNotFound([](PsychicRequest* request, PsychicResponse* response) {
|
||||
return response->redirect("/");
|
||||
});
|
||||
psychicSSLServer->begin();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (failed)
|
||||
{
|
||||
#endif
|
||||
psychicServer = new PsychicHttpServer;
|
||||
psychicServer->config.stack_size = HTTPD_TASK_SIZE;
|
||||
webCfgServer = new WebCfgServer(network, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi, partitionType, psychicServer);
|
||||
webCfgServer->initialize();
|
||||
psychicServer->onNotFound([](PsychicRequest* request, PsychicResponse* response) {
|
||||
return response->redirect("/");
|
||||
});
|
||||
psychicServer->begin();
|
||||
#ifdef CONFIG_SOC_SPIRAM_SUPPORTED
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
if(preferences->getBool(preference_enable_bootloop_reset, false))
|
||||
@@ -635,19 +710,86 @@ void setup()
|
||||
|
||||
if(!doOta && !disableNetwork && (forceEnableWebServer || preferences->getBool(preference_webserver_enabled, true) || preferences->getBool(preference_webserial_enabled, false)))
|
||||
{
|
||||
psychicServer = new PsychicHttpServer;
|
||||
psychicServer->config.max_uri_handlers = 10;
|
||||
psychicServer->config.stack_size = HTTPD_TASK_SIZE;
|
||||
psychicServer->listen(80);
|
||||
|
||||
if(forceEnableWebServer || preferences->getBool(preference_webserver_enabled, true))
|
||||
{
|
||||
webCfgServer = new WebCfgServer(nuki, nukiOpener, network, gpio, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi, partitionType, psychicServer);
|
||||
webCfgServer->initialize();
|
||||
psychicServer->onNotFound([](PsychicRequest* request)
|
||||
#ifdef CONFIG_SOC_SPIRAM_SUPPORTED
|
||||
bool failed = false;
|
||||
|
||||
if (esp_psram_get_size() <= 0) {
|
||||
Log->println("Not running on PSRAM enabled device");
|
||||
failed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return request->redirect("/");
|
||||
});
|
||||
if (!SPIFFS.begin(true)) {
|
||||
Log->println("SPIFFS Mount Failed");
|
||||
failed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
File file = SPIFFS.open("/http_ssl.crt");
|
||||
if (!file || file.isDirectory()) {
|
||||
failed = true;
|
||||
Log->println("http_ssl.crt not found");
|
||||
}
|
||||
else
|
||||
{
|
||||
char cert[4400] = {0};
|
||||
|
||||
Log->println("Reading http_ssl.crt");
|
||||
uint32_t i = 0;
|
||||
while(file.available()){
|
||||
cert[i] = file.read();
|
||||
i++;
|
||||
}
|
||||
file.close();
|
||||
|
||||
File file2 = SPIFFS.open("/http_ssl.key");
|
||||
if (!file2 || file2.isDirectory()) {
|
||||
failed = true;
|
||||
Log->println("http_ssl.key not found");
|
||||
}
|
||||
else
|
||||
{
|
||||
char key[2200] = {0};
|
||||
|
||||
Log->println("Reading http_ssl.key");
|
||||
i = 0;
|
||||
while(file2.available()){
|
||||
key[i] = file2.read();
|
||||
i++;
|
||||
}
|
||||
file2.close();
|
||||
|
||||
psychicSSLServer = new PsychicHttpsServer;
|
||||
psychicSSLServer->ssl_config.httpd.max_open_sockets = 8;
|
||||
psychicSSLServer->setCertificate(cert, key);
|
||||
psychicSSLServer->config.stack_size = HTTPD_TASK_SIZE;
|
||||
webCfgServerSSL = new WebCfgServer(nuki, nukiOpener, network, gpio, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi, partitionType, psychicSSLServer);
|
||||
webCfgServerSSL->initialize();
|
||||
psychicSSLServer->onNotFound([](PsychicRequest* request, PsychicResponse* response) {
|
||||
return response->redirect("/");
|
||||
});
|
||||
psychicSSLServer->begin();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (failed)
|
||||
{
|
||||
#endif
|
||||
psychicServer = new PsychicHttpServer;
|
||||
psychicServer->config.stack_size = HTTPD_TASK_SIZE;
|
||||
webCfgServer = new WebCfgServer(nuki, nukiOpener, network, gpio, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi, partitionType, psychicServer);
|
||||
webCfgServer->initialize();
|
||||
psychicServer->onNotFound([](PsychicRequest* request, PsychicResponse* response) {
|
||||
return response->redirect("/");
|
||||
});
|
||||
psychicServer->begin();
|
||||
#ifdef CONFIG_SOC_SPIRAM_SUPPORTED
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
#ifdef DEBUG_NUKIHUB
|
||||
@@ -656,7 +798,7 @@ void setup()
|
||||
if(preferences->getBool(preference_webserial_enabled, false))
|
||||
{
|
||||
WebSerial.setAuthentication(preferences->getString(preference_cred_user), preferences->getString(preference_cred_password));
|
||||
WebSerial.begin(asyncServer);
|
||||
WebSerial.begin(psychicServer);
|
||||
WebSerial.setBuffer(1024);
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user