diff --git a/src/Config.h b/src/Config.h index 8592bd0..7beec7d 100644 --- a/src/Config.h +++ b/src/Config.h @@ -4,7 +4,7 @@ #define NUKI_HUB_VERSION "9.02" #define NUKI_HUB_BUILD "unknownbuildnr" -#define NUKI_HUB_DATE "2024-11-11" +#define NUKI_HUB_DATE "2024-11-15" #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" diff --git a/src/PreferencesKeys.h b/src/PreferencesKeys.h index 7272158..212c888 100644 --- a/src/PreferencesKeys.h +++ b/src/PreferencesKeys.h @@ -61,6 +61,7 @@ #define preference_disable_network_not_connected (char*)"disNtwNoCon" // CHANGE DOES NOT REQUIRE REBOOT TO TAKE EFFECT +#define preference_find_best_rssi (char*)"nwbestrssi" #define preference_ntw_reconfigure (char*)"ntwRECONF" #define preference_auth_max_entries (char*)"authmaxentry" #define preference_auth_info_enabled (char*)"authInfoEna" @@ -188,6 +189,7 @@ inline void initPreferences(Preferences* preferences) preferences->putBool(preference_ip_dhcp_enabled, true); preferences->putBool(preference_enable_bootloop_reset, false); preferences->putBool(preference_show_secrets, false); + preferences->putBool(preference_find_best_rssi, true); preferences->putBool(preference_conf_info_enabled, true); preferences->putBool(preference_keypad_info_enabled, false); @@ -355,7 +357,7 @@ private: preference_cred_password, preference_disable_non_json, preference_publish_authdata, preference_publish_debug_info, preference_official_hybrid_enabled, preference_query_interval_hybrid_lockstate, preference_official_hybrid_actions, preference_official_hybrid_retry, preference_task_size_network, preference_task_size_nuki, preference_authlog_max_entries, preference_keypad_max_entries, preference_timecontrol_max_entries, - preference_update_from_mqtt, preference_show_secrets, preference_ble_tx_power, preference_webserial_enabled, + preference_update_from_mqtt, preference_show_secrets, preference_ble_tx_power, preference_webserial_enabled, preference_find_best_rssi, preference_network_custom_mdc, preference_network_custom_clk, preference_network_custom_phy, preference_network_custom_addr, preference_network_custom_irq, preference_network_custom_rst, preference_network_custom_cs, preference_network_custom_sck, preference_network_custom_miso, preference_network_custom_mosi, preference_network_custom_pwr, preference_network_custom_mdio, preference_ntw_reconfigure, preference_lock_max_auth_entry_count, preference_opener_max_auth_entry_count, @@ -376,7 +378,7 @@ private: preference_publish_authdata, preference_publish_debug_info, preference_official_hybrid_enabled, preference_mqtt_hass_enabled, 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_ntw_reconfigure, preference_keypad_check_code_enabled, preference_disable_network_not_connected, preference_find_best_rssi }; std::vector _bytePrefs = { diff --git a/src/WebCfgServer.cpp b/src/WebCfgServer.cpp index c9065b5..9d26003 100644 --- a/src/WebCfgServer.cpp +++ b/src/WebCfgServer.cpp @@ -592,6 +592,7 @@ esp_err_t WebCfgServer::buildWifiConnectHtml(PsychicRequest *request) response.print(""); printInputField(&response, "WIFISSID", "SSID", "", 32, "id=\"inputssid\"", false, true); printInputField(&response, "WIFIPASS", "Secret key", "", 63, "id=\"inputpass\"", false, true); + printCheckBox(&response, "FINDBESTRSSI", "Find AP with best signal (disable for hidden SSID)", _preferences->getBool(preference_find_best_rssi, true), ""); response.print("
"); response.print("

IP Address assignment

"); response.print(""); @@ -675,6 +676,13 @@ bool WebCfgServer::processWiFi(PsychicRequest *request, String& message) _preferences->putString(preference_ip_dns_server, value); } } + else if(key == "FINDBESTRSSI") + { + if(_preferences->getBool(preference_find_best_rssi, false) != (value == "1")) + { + _preferences->putBool(preference_find_best_rssi, (value == "1")); + } + } } ssid.trim(); @@ -1813,6 +1821,16 @@ bool WebCfgServer::processArgs(PsychicRequest *request, String& message) //configChanged = true; } } + else if(key == "FINDBESTRSSI") + { + if(_preferences->getBool(preference_find_best_rssi, false) != (value == "1")) + { + _preferences->putBool(preference_find_best_rssi, (value == "1")); + Log->print(F("Setting changed: ")); + Log->println(key); + //configChanged = true; + } + } else if(key == "RSTDISC") { if(_preferences->getBool(preference_restart_on_disconnect, false) != (value == "1")) @@ -3508,6 +3526,7 @@ esp_err_t WebCfgServer::buildNetworkConfigHtml(PsychicRequest *request) #endif printCheckBox(&response, "RSTDISC", "Restart on disconnect", _preferences->getBool(preference_restart_on_disconnect), ""); printCheckBox(&response, "CHECKUPDATE", "Check for Firmware Updates every 24h", _preferences->getBool(preference_check_updates), ""); + printCheckBox(&response, "FINDBESTRSSI", "Find WiFi AP with strongest signal", _preferences->getBool(preference_find_best_rssi, false), ""); response.print("
"); response.print("

IP Address assignment

"); response.print(""); @@ -3581,7 +3600,7 @@ esp_err_t WebCfgServer::buildAdvancedConfigHtml(PsychicRequest *request) response.print(_preferences->getBool(preference_enable_bootloop_reset, false) ? "Enabled" : "Disabled"); response.print(""); 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, "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, ""); response.print(""); @@ -4063,8 +4082,10 @@ esp_err_t WebCfgServer::buildInfoHtml(PsychicRequest *request) if(esp_psram_get_size() > 0) { response.print("\nPSRAM Available: Yes"); - response.print("\nFree PSRAM: "); - response.print((esp_get_free_heap_size() - ESP.getFreeHeap())); + response.print("\nFree usable PSRAM: "); + response.print(ESP.getFreePsram()); + response.print("\nTotal usable PSRAM: "); + response.print(ESP.getPsramSize()); response.print("\nTotal PSRAM: "); response.print(esp_psram_get_size()); response.print("\nTotal free heap: "); @@ -4165,6 +4186,9 @@ esp_err_t WebCfgServer::buildInfoHtml(PsychicRequest *request) { response.print(_preferences->getInt(preference_rssi_publish_interval, 60)); } + + response.print("\nFind WiFi AP with strongest signal: "); + response.print(_preferences->getBool(preference_find_best_rssi, false) ? "Yes" : "No"); } #endif response.print("\nRestart ESP32 on network disconnect enabled: "); @@ -4644,7 +4668,7 @@ esp_err_t WebCfgServer::processUnpair(PsychicRequest *request, bool opener) { _nukiOpener->unpair(); } - + _network->disableHASS(); waitAndProcess(false, 1000); restartEsp(RestartReason::DeviceUnpaired); diff --git a/src/main.cpp b/src/main.cpp index 0a86511..2ddbb41 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -56,7 +56,7 @@ int64_t restartTs = (pow(2,64) - (5 * 1000 * 60000)) / 1000; #include "../../src/NukiNetwork.h" #include "../../src/EspMillis.h" -int64_t restartTs = 10 * 1000 * 60000; +int64_t restartTs = 10 * 60 * 1000; #endif @@ -129,6 +129,28 @@ void setReroute() } #endif +uint8_t checkPartition() +{ + const esp_partition_t* running_partition = esp_ota_get_running_partition(); + Log->print(F("Partition size: ")); + Log->println(running_partition->size); + Log->print(F("Partition subtype: ")); + Log->println(running_partition->subtype); + + if(running_partition->size == 1966080) + { + return 0; //OLD PARTITION TABLE + } + else if(running_partition->subtype == ESP_PARTITION_SUBTYPE_APP_OTA_0) + { + return 1; //NEW PARTITION TABLE, RUNNING MAIN APP + } + else + { + return 2; //NEW PARTITION TABLE, RUNNING UPDATER APP + } +} + void networkTask(void *pvParameters) { int64_t networkLoopTs = 0; @@ -151,7 +173,7 @@ void networkTask(void *pvParameters) network->update(); bool connected = network->isConnected(); - + #ifdef DEBUG_NUKIHUB if(connected && reroute) { @@ -180,6 +202,17 @@ void networkTask(void *pvParameters) networkLoopTs = espMillis(); } + if(espMillis() > restartTs) + { + uint8_t partitionType = checkPartition(); + + if(partitionType!=1) + { + esp_ota_set_boot_partition(esp_ota_get_next_update_partition(NULL)); + } + + restartEsp(RestartReason::RestartTimer); + } esp_task_wdt_reset(); } } @@ -275,28 +308,6 @@ void bootloopDetection() } #endif -uint8_t checkPartition() -{ - const esp_partition_t* running_partition = esp_ota_get_running_partition(); - Log->print(F("Partition size: ")); - Log->println(running_partition->size); - Log->print(F("Partition subtype: ")); - Log->println(running_partition->subtype); - - if(running_partition->size == 1966080) - { - return 0; //OLD PARTITION TABLE - } - else if(running_partition->subtype == ESP_PARTITION_SUBTYPE_APP_OTA_0) - { - return 1; //NEW PARTITION TABLE, RUNNING MAIN APP - } - else - { - return 2; //NEW PARTITION TABLE, RUNNING UPDATER APP - } -} - esp_err_t _http_event_handler(esp_http_client_event_t *evt) { switch (evt->event_id) @@ -344,6 +355,13 @@ void otaTask(void *pvParameter) updateUrl = preferences->getString(preference_ota_main_url); preferences->putString(preference_ota_main_url, ""); } + + while(!network->isConnected()) + { + Log->println("OTA waiting for network"); + vTaskDelay(5000 / portTICK_PERIOD_MS); + } + Log->println("Starting OTA task"); esp_http_client_config_t config = { @@ -581,7 +599,7 @@ void setup() { networkOpener->initialize(); } - + nukiOpener = new NukiOpenerWrapper("NukiHub", deviceIdOpener, bleScanner, networkOpener, gpio, preferences); nukiOpener->initialize(); } diff --git a/src/networkDevices/WifiDevice.cpp b/src/networkDevices/WifiDevice.cpp index 0109e7f..3481645 100644 --- a/src/networkDevices/WifiDevice.cpp +++ b/src/networkDevices/WifiDevice.cpp @@ -1,6 +1,7 @@ #include "WifiDevice.h" #include "esp_wifi.h" #include +#include #include "../PreferencesKeys.h" #include "../Logger.h" #include "../RestartReason.h" @@ -62,7 +63,7 @@ void WifiDevice::initialize() String(F(" and channel: ")) + String(WiFi.channel(i))); } - if (_connectOnScanDone && _foundNetworks > 0) + if ((_connectOnScanDone && _foundNetworks > 0) || _preferences->getBool(preference_find_best_rssi, false)) { connect(); } @@ -199,6 +200,10 @@ void WifiDevice::openAP() WiFi.softAPsetHostname(_hostname.c_str()); WiFi.softAP("NukiHub", "NukiHubESP32"); _startAP = false; + + if(MDNS.begin(_hostname.c_str())){ + MDNS.addService("http", "tcp", 80); + } } } @@ -212,107 +217,104 @@ bool WifiDevice::connect() delay(500); int bestConnection = -1; - for (int i = 0; i < _foundNetworks; i++) + + if(_preferences->getBool(preference_find_best_rssi, false)) { - if (ssid == WiFi.SSID(i)) + for (int i = 0; i < _foundNetworks; i++) { - Log->println(String(F("Saved SSID ")) + ssid + String(F(" found with RSSI: ")) + - String(WiFi.RSSI(i)) + String(F("(")) + - String(constrain((100.0 + WiFi.RSSI(i)) * 2, 0, 100)) + - String(F(" %) and BSSID: ")) + WiFi.BSSIDstr(i) + - String(F(" and channel: ")) + String(WiFi.channel(i))); - if (bestConnection == -1) + if (ssid == WiFi.SSID(i)) { - bestConnection = i; - } - else - { - if (WiFi.RSSI(i) > WiFi.RSSI(bestConnection)) + Log->println(String(F("Saved SSID ")) + ssid + String(F(" found with RSSI: ")) + + String(WiFi.RSSI(i)) + String(F("(")) + + String(constrain((100.0 + WiFi.RSSI(i)) * 2, 0, 100)) + + String(F(" %) and BSSID: ")) + WiFi.BSSIDstr(i) + + String(F(" and channel: ")) + String(WiFi.channel(i))); + if (bestConnection == -1) { bestConnection = i; } + else + { + if (WiFi.RSSI(i) > WiFi.RSSI(bestConnection)) + { + bestConnection = i; + } + } } } + + if (bestConnection == -1) + { + Log->print("No network found with SSID: "); + Log->println(ssid); + } + else + { + Log->println(String(F("Trying to connect to SSID ")) + ssid + String(F(" found with RSSI: ")) + + String(WiFi.RSSI(bestConnection)) + String(F("(")) + + String(constrain((100.0 + WiFi.RSSI(bestConnection)) * 2, 0, 100)) + + String(F(" %) and BSSID: ")) + WiFi.BSSIDstr(bestConnection) + + String(F(" and channel: ")) + String(WiFi.channel(bestConnection))); + } } - if (bestConnection == -1) + _connecting = true; + esp_wifi_scan_stop(); + + if(!_ipConfiguration->dhcpEnabled()) { - Log->print("No network found with SSID: "); - Log->println(ssid); - if(_preferences->getBool(preference_restart_on_disconnect, false) && (espMillis() > 60000)) - { - restartEsp(RestartReason::RestartOnDisconnectWatchdog); - } + WiFi.config(_ipConfiguration->ipAddress(), _ipConfiguration->dnsServer(), _ipConfiguration->defaultGateway(), _ipConfiguration->subnet()); + } + + WiFi.begin(ssid, pass); + auto status = WiFi.waitForConnectResult(10000); + + switch (status) + { + case WL_CONNECTED: + Log->println("WiFi connected"); + break; + case WL_NO_SSID_AVAIL: + Log->println("WiFi SSID not available"); + break; + case WL_CONNECT_FAILED: + Log->println("WiFi connection failed"); + break; + case WL_IDLE_STATUS: + Log->println("WiFi changing status"); + break; + case WL_DISCONNECTED: + Log->println("WiFi disconnected"); + break; + default: + Log->println("WiFi timeout"); + break; + } + + if (status != WL_CONNECTED) + { + Log->println("Retrying"); _connectOnScanDone = true; _openAP = false; scan(false, true); + _connecting = false; return false; } else { - _connecting = true; - esp_wifi_scan_stop(); - Log->println(String(F("Trying to connect to SSID ")) + ssid + String(F(" found with RSSI: ")) + - String(WiFi.RSSI(bestConnection)) + String(F("(")) + - String(constrain((100.0 + WiFi.RSSI(bestConnection)) * 2, 0, 100)) + - String(F(" %) and BSSID: ")) + WiFi.BSSIDstr(bestConnection) + - String(F(" and channel: ")) + String(WiFi.channel(bestConnection))); - - - if(!_ipConfiguration->dhcpEnabled()) + if(!_preferences->getBool(preference_wifi_converted, false)) { - WiFi.config(_ipConfiguration->ipAddress(), _ipConfiguration->dnsServer(), _ipConfiguration->defaultGateway(), _ipConfiguration->subnet()); + _preferences->putBool(preference_wifi_converted, true); } + _connecting = false; + return true; + } - WiFi.begin(ssid, pass); - auto status = WiFi.waitForConnectResult(10000); - - switch (status) - { - case WL_CONNECTED: - Log->println("WiFi connected"); - break; - case WL_NO_SSID_AVAIL: - Log->println("WiFi SSID not available"); - break; - case WL_CONNECT_FAILED: - Log->println("WiFi connection failed"); - break; - case WL_IDLE_STATUS: - Log->println("WiFi changing status"); - break; - case WL_DISCONNECTED: - Log->println("WiFi disconnected"); - break; - default: - Log->println("WiFi timeout"); - break; - } - - if (status != WL_CONNECTED) - { - if(_preferences->getBool(preference_restart_on_disconnect, false) && (espMillis() > 60000)) - { - restartEsp(RestartReason::RestartOnDisconnectWatchdog); - _connecting = false; - return false; - } - Log->println("Retrying"); - _connectOnScanDone = true; - _openAP = false; - scan(false, true); - _connecting = false; - return false; - } - else - { - if(!_preferences->getBool(preference_wifi_converted, false)) - { - _preferences->putBool(preference_wifi_converted, true); - } - _connecting = false; - return true; - } + if(_preferences->getBool(preference_restart_on_disconnect, false) && (espMillis() > 60000)) + { + restartEsp(RestartReason::RestartOnDisconnectWatchdog); + _connecting = false; + return false; } return false;
Advised minimum char buffer size based on current settings