diff --git a/README.md b/README.md index c14d9bc4..85cc049f 100644 --- a/README.md +++ b/README.md @@ -343,6 +343,39 @@ Both of the above options will not backup pairing data, so you will have to manu To import settings copy and paste the contents of the JSON file that is created by any of the above export options and select "Import". After importing the device will reboot. +### Advanced Configuration + +The advanced configuration menu is not reachable from the main menu of the web configurator by default.
+You can reach the menu directly by browsing to http://NUKIHUBIP/?get=advanced or enable showing it in the main menu by browsing to http://NUKIHUBIP/?get=debugon once (http://NUKIHUBIP/?get=debugoff to disable). + +Note that the following options can break NukiHub and cause bootloops that will require you to erase your ESP and reflash following the instructions for first-time flashing. + +- Disable Network if not connected within 60s: Enable to allow NukiHub to function without a network connection (for example when only using NukiHub with GPIO) +- Enable Bootloop prevention: Enable to reset the following stack size and max entry settings to default if NukiHub detects a bootloop. +- Char buffer size (min 4096, max 65536): Set the character buffer size, needs to be enlarged to support large amounts of auth/keypad/timecontrol/authorization entries. Default 4096. +- Task size Network (min 12288, max 65536): Set the Network task stack size, needs to be enlarged to support large amounts of auth/keypad/timecontrol/authorization entries. Default 12288. +- Task size Nuki (min 8192, max 65536): Set the Nuki task stack size. Default 8192. +- Max auth log entries (min 1, max 100): The maximum amount of log entries that will be requested from the lock/opener, default 5. +- Max keypad entries (min 1, max 200): The maximum amount of keypad codes that will be requested from the lock/opener, default 10. +- Max timecontrol entries (min 1, max 100): The maximum amount of timecontrol entries that will be requested from the lock/opener, default 10. +- Max authorization entries (min 1, max 100): The maximum amount of authorization entries that will be requested from the lock/opener, default 10. +- Show Pairing secrets on Info page: Enable to show the pairing secrets on the info page. Will be disabled on reboot. +- Manually set lock pairing data: Enable to save the pairing data fields and manually set pairing info for the lock. +- Manually set opener pairing data: Enable to save the pairing data fields and manually set pairing info for the opener. +- Custom URL to update Nuki Hub updater: Set to a HTTPS address to update to a custom NukiHub updater binary on next boot of the NukiHub partition. +- Custom URL to update Nuki Hub: Set to a HTTPS address to update to a custom NukiHub binary on next boot of the NukiHub updater partition. +- Force Lock ID to current ID: Enable to force the current Lock ID, irrespective of the config received from the lock. +- Force Lock Keypad connected: Enable to force NukiHub to function as if a keypad was connected, irrespective of the config received from the lock. +- Force Lock Doorsensor connected: Enable to force NukiHub to function as if a doorsensor was connected, irrespective of the config received from the lock. +- Force Opener ID to current ID: Enable to force the current Opener ID, irrespective of the config received from the opener. +- Force Opener Keypad: Enable to force NukiHub to function as if a keypad was connected, irrespective of the config received from the opener. +- Enable Nuki connect debug logging: Enable to log debug information regarding Nuki BLE connection to MQTT and/or Serial. +- Enable Nuki communication debug logging: Enable to log debug information regarding Nuki BLE communication to MQTT and/or Serial. +- Enable Nuki readable data debug logging: Enable to log human readable debug information regarding Nuki BLE to MQTT and/or Serial. +- Enable Nuki hex data debug logging: Enable to log hex debug information regarding Nuki BLE to MQTT and/or Serial. +- Enable Nuki command debug logging: Enable to log debug information regarding Nuki BLE commands to MQTT and/or Serial. +- Pubish free heap over MQTT: Enable to publish free heap to MQTT. + ## Exposed MQTT Topics ### Lock diff --git a/src/Config.h b/src/Config.h index 85ffa72a..ec1e067d 100644 --- a/src/Config.h +++ b/src/Config.h @@ -120,8 +120,6 @@ #ifndef NUKI_HUB_UPDATER #define MQTT_QOS_LEVEL 1 -#define MQTT_CLEAN_SESSIONS false -#define MQTT_KEEP_ALIVE 60 #define GPIO_DEBOUNCE_TIME 200 #define CHAR_BUFFER_SIZE 4096 #define NUKI_TASK_SIZE 8192 diff --git a/src/NukiNetwork.cpp b/src/NukiNetwork.cpp index c28d44e9..8cbc306a 100644 --- a/src/NukiNetwork.cpp +++ b/src/NukiNetwork.cpp @@ -306,8 +306,8 @@ void NukiNetwork::initialize() Log->println(_mqttPort); _device->mqttSetClientId(_hostnameArr); - _device->mqttSetCleanSession(MQTT_CLEAN_SESSIONS); - _device->mqttSetKeepAlive(MQTT_KEEP_ALIVE); + _device->mqttSetCleanSession(false); + _device->mqttSetKeepAlive(60); char gpioPath[250]; bool rebGpio = rebuildGpio(); diff --git a/src/WebCfgServer.cpp b/src/WebCfgServer.cpp index f7efb19d..840c5b14 100644 --- a/src/WebCfgServer.cpp +++ b/src/WebCfgServer.cpp @@ -124,11 +124,6 @@ void WebCfgServer::initialize() #ifndef CONFIG_IDF_TARGET_ESP32H2 _psychicServer->on("/ssidlist", HTTP_GET, [&](PsychicRequest *request, PsychicResponse* resp) { - if(strlen(_credUser) > 0 && strlen(_credPassword) > 0 && !request->authenticate(_credUser, _credPassword)) - { - return request->requestAuthentication(auth_type, "Nuki Hub", "You must log in."); - } - return buildSSIDListHtml(request, resp); }); _psychicServer->on("/savewifi", HTTP_POST, [&](PsychicRequest *request, PsychicResponse* resp) @@ -186,11 +181,6 @@ void WebCfgServer::initialize() { _psychicServer->on("/get", HTTP_GET, [&](PsychicRequest *request, PsychicResponse* resp) { - if(strlen(_credUser) > 0 && strlen(_credPassword) > 0 && !request->authenticate(_credUser, _credPassword)) - { - return request->requestAuthentication(auth_type, "Nuki Hub", "You must log in."); - } - String value = ""; if(request->hasParam("page")) { @@ -200,6 +190,14 @@ void WebCfgServer::initialize() value = p->value(); } } + + if (value != "status") + { + if(strlen(_credUser) > 0 && strlen(_credPassword) > 0 && !request->authenticate(_credUser, _credPassword)) + { + return request->requestAuthentication(auth_type, "Nuki Hub", "You must log in."); + } + } if (value == "reboot") { @@ -251,7 +249,18 @@ void WebCfgServer::initialize() } else if (value == "status") { - return buildStatusHtml(request, resp); + if(request->hasParam("token")) + { + const PsychicWebParameter* p2 = request->getParam("token"); + if(p2->value().toInt() == _randomInt) + { + return buildStatusHtml(request, resp); + } + } + resp->setCode(200); + resp->setContentType("text/html"); + resp->setContent(""); + return resp->send(); } else if (value == "acclvl") { @@ -2398,7 +2407,7 @@ bool WebCfgServer::processArgs(PsychicRequest *request, PsychicResponse* resp, S } else if(key == "TSKNTWK") { - if(value.toInt() > 12287 && value.toInt() < 32769) + if(value.toInt() > 12287 && value.toInt() < 65537) { if(_preferences->getInt(preference_task_size_network, NETWORK_TASK_SIZE) != value.toInt()) { @@ -2411,7 +2420,7 @@ bool WebCfgServer::processArgs(PsychicRequest *request, PsychicResponse* resp, S } else if(key == "TSKNUKI") { - if(value.toInt() > 8191 && value.toInt() < 32769) + if(value.toInt() > 8191 && value.toInt() < 65537) { if(_preferences->getInt(preference_task_size_nuki, NUKI_TASK_SIZE) != value.toInt()) { @@ -2424,7 +2433,7 @@ bool WebCfgServer::processArgs(PsychicRequest *request, PsychicResponse* resp, S } else if(key == "ALMAX") { - if(value.toInt() > 0 && value.toInt() < 51) + if(value.toInt() > 0 && value.toInt() < 101) { if(_preferences->getInt(preference_authlog_max_entries, MAX_AUTHLOG) != value.toInt()) { @@ -2437,7 +2446,7 @@ bool WebCfgServer::processArgs(PsychicRequest *request, PsychicResponse* resp, S } else if(key == "KPMAX") { - if(value.toInt() > 0 && value.toInt() < 101) + if(value.toInt() > 0 && value.toInt() < 201) { if(_preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD) != value.toInt()) { @@ -2450,7 +2459,7 @@ bool WebCfgServer::processArgs(PsychicRequest *request, PsychicResponse* resp, S } else if(key == "TCMAX") { - if(value.toInt() > 0 && value.toInt() < 51) + if(value.toInt() > 0 && value.toInt() < 101) { if(_preferences->getInt(preference_timecontrol_max_entries, MAX_TIMECONTROL) != value.toInt()) { @@ -2463,7 +2472,7 @@ bool WebCfgServer::processArgs(PsychicRequest *request, PsychicResponse* resp, S } else if(key == "AUTHMAX") { - if(value.toInt() > 0 && value.toInt() < 51) + if(value.toInt() > 0 && value.toInt() < 101) { if(_preferences->getInt(preference_auth_max_entries, MAX_AUTH) != value.toInt()) { @@ -2476,7 +2485,7 @@ bool WebCfgServer::processArgs(PsychicRequest *request, PsychicResponse* resp, S } else if(key == "BUFFSIZE") { - if(value.toInt() > 4095 && value.toInt() < 32769) + if(value.toInt() > 4095 && value.toInt() < 65537) { if(_preferences->getInt(preference_buffer_size, CHAR_BUFFER_SIZE) != value.toInt()) { @@ -2566,7 +2575,7 @@ bool WebCfgServer::processArgs(PsychicRequest *request, PsychicResponse* resp, S Log->println(key); configChanged = true; } - } + } else if(key == "DBGREAD") { if(_preferences->getBool(preference_debug_readable_data, false) != (value == "1")) @@ -3904,7 +3913,8 @@ esp_err_t WebCfgServer::buildCustomNetworkConfigHtml(PsychicRequest *request, Ps esp_err_t WebCfgServer::buildHtml(PsychicRequest *request, PsychicResponse* resp) { - String header = ""; + _randomInt = random(0xFFFFFFFF); + String header = (String)""; PsychicStreamResponse response(resp, "text/html"); response.beginSend(); buildHtmlHeader(&response, header); @@ -4396,15 +4406,15 @@ esp_err_t WebCfgServer::buildAdvancedConfigHtml(PsychicRequest *request, Psychic printCheckBox(&response, "DISNTWNOCON", "Disable Network if not connected within 60s", _preferences->getBool(preference_disable_network_not_connected, false), ""); //printCheckBox(&response, "WEBLOG", "Enable WebSerial logging", _preferences->getBool(preference_webserial_enabled), ""); printCheckBox(&response, "BTLPRST", "Enable Bootloop prevention (Try to reset these settings to default on bootloop)", true, ""); - printInputField(&response, "BUFFSIZE", "Char buffer size (min 4096, max 32768)", _preferences->getInt(preference_buffer_size, CHAR_BUFFER_SIZE), 6, ""); + printInputField(&response, "BUFFSIZE", "Char buffer size (min 4096, max 65536)", _preferences->getInt(preference_buffer_size, CHAR_BUFFER_SIZE), 6, ""); response.print("Advised minimum char buffer size based on current settings"); - printInputField(&response, "TSKNTWK", "Task size Network (min 12288, max 32768)", _preferences->getInt(preference_task_size_network, NETWORK_TASK_SIZE), 6, ""); + printInputField(&response, "TSKNTWK", "Task size Network (min 12288, max 65536)", _preferences->getInt(preference_task_size_network, NETWORK_TASK_SIZE), 6, ""); response.print("Advised minimum network task size based on current settings"); - 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, "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\""); - printInputField(&response, "AUTHMAX", "Max authorization entries (min 1, max 50)", _preferences->getInt(preference_auth_max_entries, MAX_AUTH), 3, "id=\"inputmaxauth\""); + printInputField(&response, "TSKNUKI", "Task size Nuki (min 8192, max 65536)", _preferences->getInt(preference_task_size_nuki, NUKI_TASK_SIZE), 6, ""); + printInputField(&response, "ALMAX", "Max auth log entries (min 1, max 100)", _preferences->getInt(preference_authlog_max_entries, MAX_AUTHLOG), 3, "id=\"inputmaxauthlog\""); + printInputField(&response, "KPMAX", "Max keypad entries (min 1, max 200)", _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD), 3, "id=\"inputmaxkeypad\""); + printInputField(&response, "TCMAX", "Max timecontrol entries (min 1, max 100)", _preferences->getInt(preference_timecontrol_max_entries, MAX_TIMECONTROL), 3, "id=\"inputmaxtimecontrol\""); + printInputField(&response, "AUTHMAX", "Max authorization entries (min 1, max 100)", _preferences->getInt(preference_auth_max_entries, MAX_AUTH), 3, "id=\"inputmaxauth\""); printCheckBox(&response, "SHOWSECRETS", "Show Pairing secrets on Info page", _preferences->getBool(preference_show_secrets), ""); if(_preferences->getBool(preference_lock_enabled, true)) { @@ -4424,11 +4434,6 @@ esp_err_t WebCfgServer::buildAdvancedConfigHtml(PsychicRequest *request, Psychic printInputField(&response, "OTAUPD", "Custom URL to update Nuki Hub updater", "", 255, ""); printInputField(&response, "OTAMAIN", "Custom URL to update Nuki Hub", "", 255, ""); - std::vector> optionsForce; - optionsForce.push_back(std::make_pair("0", "Do not force")); - optionsForce.push_back(std::make_pair("1", "Force unavailable")); - optionsForce.push_back(std::make_pair("2", "Force available")); - if(_nuki != nullptr) { char uidString[20]; @@ -4456,7 +4461,7 @@ esp_err_t WebCfgServer::buildAdvancedConfigHtml(PsychicRequest *request, Psychic response.print("
"); response.print(""); - response.print(""); + response.print(""); return response.endSend(); } @@ -4467,7 +4472,6 @@ esp_err_t WebCfgServer::buildStatusHtml(PsychicRequest *request, PsychicResponse bool mqttDone = false; bool lockDone = false; bool openerDone = false; - bool latestDone = false; json["stop"] = 0; @@ -4545,14 +4549,9 @@ esp_err_t WebCfgServer::buildStatusHtml(PsychicRequest *request, PsychicResponse if(_preferences->getBool(preference_check_updates)) { json["latestFirmware"] = _preferences->getString(preference_latest_version); - latestDone = true; - } - else - { - latestDone = true; } - if(mqttDone && lockDone && openerDone && latestDone) + if(mqttDone && lockDone && openerDone) { json["stop"] = 1; } @@ -4803,7 +4802,7 @@ esp_err_t WebCfgServer::buildNukiConfigHtml(PsychicRequest *request, PsychicResp printInputField(&response, "TXPWR", "BLE transmit power in dB (minimum -12, maximum 9)", _preferences->getInt(preference_ble_tx_power, 9), 10, ""); printCheckBox(&response, "UPTIME", "Update Nuki Hub and Lock/Opener time using NTP", _preferences->getBool(preference_update_time, false), ""); printInputField(&response, "TIMESRV", "NTP server", _preferences->getString(preference_time_server, "pool.ntp.org").c_str(), 255, ""); - + response.print(""); response.print("
"); response.print(""); diff --git a/src/WebCfgServer.h b/src/WebCfgServer.h index 0865d815..67ed731b 100644 --- a/src/WebCfgServer.h +++ b/src/WebCfgServer.h @@ -128,5 +128,6 @@ class WebCfgServer bool _allowRestartToPortal = false; uint8_t _partitionType = 0; size_t _otaContentLen = 0; + uint32_t _randomInt = 0; String _hostname; };