@@ -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"
|
||||
|
||||
@@ -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<char*> _bytePrefs =
|
||||
{
|
||||
|
||||
@@ -592,6 +592,7 @@ esp_err_t WebCfgServer::buildWifiConnectHtml(PsychicRequest *request)
|
||||
response.print("<table>");
|
||||
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("</table>");
|
||||
response.print("<h3>IP Address assignment</h3>");
|
||||
response.print("<table>");
|
||||
@@ -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("</table>");
|
||||
response.print("<h3>IP Address assignment</h3>");
|
||||
response.print("<table>");
|
||||
@@ -3581,7 +3600,7 @@ esp_err_t WebCfgServer::buildAdvancedConfigHtml(PsychicRequest *request)
|
||||
response.print(_preferences->getBool(preference_enable_bootloop_reset, false) ? "Enabled" : "Disabled");
|
||||
response.print("</td></tr>");
|
||||
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("<tr><td>Advised minimum char buffer size based on current settings</td><td id=\"mincharbuffer\"></td>");
|
||||
@@ -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);
|
||||
|
||||
68
src/main.cpp
68
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();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "WifiDevice.h"
|
||||
#include "esp_wifi.h"
|
||||
#include <WiFi.h>
|
||||
#include <ESPmDNS.h>
|
||||
#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;
|
||||
|
||||
Reference in New Issue
Block a user