From a7ae6c9fd4c5d15c886d7c5667ca9d410bed245d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Krac=C3=ADk?= Date: Mon, 12 Jan 2026 17:46:29 +0100 Subject: [PATCH 01/24] Fix include WiFiClient in MQTT client --- src/mqtt_utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mqtt_utils.cpp b/src/mqtt_utils.cpp index 7793962..5462198 100644 --- a/src/mqtt_utils.cpp +++ b/src/mqtt_utils.cpp @@ -16,7 +16,7 @@ * along with LoRa APRS iGate. If not, see . */ -#include +#include #include #include "configuration.h" #include "station_utils.h" From 630de55febca143f2be4d90d622d6ecca2c12540 Mon Sep 17 00:00:00 2001 From: Petr Kracik Date: Tue, 13 Jan 2026 00:02:15 +0100 Subject: [PATCH 02/24] Main include WiFiClient instead generic WiFi --- src/LoRa_APRS_iGate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LoRa_APRS_iGate.cpp b/src/LoRa_APRS_iGate.cpp index 47c1c07..f28dfb1 100644 --- a/src/LoRa_APRS_iGate.cpp +++ b/src/LoRa_APRS_iGate.cpp @@ -41,7 +41,7 @@ ___________________________________________________________________*/ #include #include #include -#include +#include #include #include "configuration.h" #include "aprs_is_utils.h" From d2c9bcb71d8f94a977c0296f3b597ddca92b3b6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Krac=C3=ADk?= Date: Mon, 12 Jan 2026 19:41:47 +0100 Subject: [PATCH 03/24] NetworkManager: Initial commit --- include/network_manager.h | 53 ++++++++++++ src/LoRa_APRS_iGate.cpp | 15 +++- src/network_manager.cpp | 176 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 241 insertions(+), 3 deletions(-) create mode 100644 include/network_manager.h create mode 100644 src/network_manager.cpp diff --git a/include/network_manager.h b/include/network_manager.h new file mode 100644 index 0000000..6d84f9b --- /dev/null +++ b/include/network_manager.h @@ -0,0 +1,53 @@ +#include +#include +#include + +/** + * Class for managing network connections + */ +class NetworkManager +{ +private: + bool _wifiAPmode = false; + bool _wifiSTAmode = false; + unsigned long _apStartup = 0; + unsigned long _apTimeout = 0; + + String _generateAPSSID(); + void _processAPTimeout(); + +public: + // Constructor + NetworkManager(); + + // Destructor + ~NetworkManager(); + + // Initialize network module + bool setup(); + void loop(); + + // WiFi methods + bool setupAP(String apName, String apPsk = ""); + bool disableAP(); + void setAPTimeout(unsigned long timeout); + bool connectWiFi(String ssid, String psk); + bool disconnectWiFi(); + String getWiFiSSID() const; + String getWiFiAPSSID() const; + IPAddress getWiFiIP() const; + IPAddress getWiFiAPIP() const; + wifi_mode_t getWiFiMode() const; + uint8_t* getWiFimacAddress(uint8_t* mac); + String getWiFimacAddress(void) const; + + // Check if any network is available + bool isConnected() const; + + // Check if specific network is connected + bool isWiFiConnected() const; + bool isEthernetConnected() const; + bool isModemConnected() const; + + bool isWifiAPActive() const; +}; diff --git a/src/LoRa_APRS_iGate.cpp b/src/LoRa_APRS_iGate.cpp index f28dfb1..4a57ef3 100644 --- a/src/LoRa_APRS_iGate.cpp +++ b/src/LoRa_APRS_iGate.cpp @@ -44,6 +44,7 @@ ___________________________________________________________________*/ #include #include #include "configuration.h" +#include "network_manager.h" #include "aprs_is_utils.h" #include "station_utils.h" #include "battery_utils.h" @@ -79,6 +80,8 @@ WiFiClient mqttClient; bool gpsInfoToggle = false; #endif +NetworkManager *networkManager; + uint8_t myWiFiAPIndex = 0; int myWiFiAPSize = Config.wifiAPs.size(); WiFi_AP *currentWiFi = &Config.wifiAPs[myWiFiAPIndex]; @@ -101,6 +104,8 @@ String firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seven void setup() { Serial.begin(115200); + networkManager = new NetworkManager(); + networkManager->setup(); POWER_Utils::setup(); Utils::setupDisplay(); LoRa_Utils::setup(); @@ -133,6 +138,7 @@ void loop() { SLEEP_Utils::startSleeping(); } else { WIFI_Utils::checkAutoAPTimeout(); + networkManager->loop(); if (isUpdatingOTA) { ElegantOTA.loop(); @@ -161,11 +167,14 @@ void loop() { #endif #ifdef HAS_A7670 + // TODO: Make this part of Network manager, and use ESP-IDF network stack instead manual AT commands if (Config.aprs_is.active && !modemLoggedToAPRSIS) A7670_Utils::APRS_IS_connect(); #else WIFI_Utils::checkWiFi(); - if (Config.aprs_is.active && (WiFi.status() == WL_CONNECTED) && !aprsIsClient.connected()) APRS_IS_Utils::connect(); - if (Config.mqtt.active && (WiFi.status() == WL_CONNECTED) && !mqttClient.connected()) MQTT_Utils::connect(); + if (networkManager->isConnected()) { + if (Config.aprs_is.active && !aprsIsClient.connected()) APRS_IS_Utils::connect(); + if (Config.mqtt.active && !mqttClient.connected()) MQTT_Utils::connect(); + } #endif NTP_Utils::update(); @@ -216,4 +225,4 @@ void loop() { Utils::checkRebootTime(); Utils::checkSleepByLowBatteryVoltage(1); } -} \ No newline at end of file +} diff --git a/src/network_manager.cpp b/src/network_manager.cpp new file mode 100644 index 0000000..27451ba --- /dev/null +++ b/src/network_manager.cpp @@ -0,0 +1,176 @@ +#include + +#include "network_manager.h" + + // Constructor +NetworkManager::NetworkManager() { } + +// Destructor +NetworkManager::~NetworkManager() { } + +// Initialize +bool NetworkManager::setup() { + Serial.println("Initializing Networking..."); + return true; +} + + +void NetworkManager::loop() { + if (_wifiAPmode) { + _processAPTimeout(); + } +} + + +// WiFi methods + +void NetworkManager::_processAPTimeout() { + if (!_wifiAPmode || _apTimeout == 0 || !_wifiSTAmode) { + return; + } + + if (millis() - _apStartup > _apTimeout) { + // Time expired, switch to client mode if successfully connected + if (isWiFiConnected()) { + Serial.println("AP timeout reached. Switching to client mode only."); + disableAP(); + } + else { + // Not connected as a client, keep AP running + Serial.println("AP timeout reached but WiFi client still not connected. Keeping AP mode active."); + _apStartup = millis(); // Reset timer + } + } +} + +bool NetworkManager::setupAP(String apName, String apPsk) { + _wifiAPmode = true; + + Serial.println("Starting AP mode: " + apName); + + // Full WiFi reset sequence + WiFi.disconnect(true); + WiFi.mode(WIFI_OFF); + delay(200); + + // Set up AP mode with optimized settings + WiFi.mode(WIFI_AP); + + bool apStarted = WiFi.softAP(apName.c_str(), apPsk.c_str()); + delay(1000); // Give AP time to fully initialize + + if (apStarted) { + Serial.println("AP setup successful"); + _apStartup = millis(); + } + else { + Serial.println("AP setup failed"); + return false; + } + + IPAddress apIP = getWiFiAPIP(); + Serial.println("AP IP assigned: " + apIP.toString()); + + return true; +} + +bool NetworkManager::disableAP() { + WiFi.mode(_wifiSTAmode ? WIFI_STA : WIFI_OFF); + _wifiAPmode = false; + + return true; +} + +void NetworkManager::setAPTimeout(unsigned long timeout) { + Serial.println("Setting AP timeout to " + String(timeout / 1000) + " sec"); + _apTimeout = timeout; +} + +bool NetworkManager::connectWiFi(String ssid, String psk) { + _wifiSTAmode = true; + + WiFi.mode(_wifiAPmode ? WIFI_AP_STA : WIFI_STA); + + Serial.println("Attempting to connect to WiFi: " + ssid); + WiFi.begin(ssid.c_str(), psk.c_str()); + + int attempts = 0; + while (!isWiFiConnected() && attempts < 20) { + delay(500); + Serial.print("."); + attempts++; + } + Serial.println(); + + if (isWiFiConnected()) { + Serial.println("WiFi connected! IP: " + WiFi.localIP().toString()); + return true; + } + else { + Serial.println("Failed to connect to WiFi after " + String(attempts) + " attempts. SSID: " + + ssid); + return false; + } +} + +bool NetworkManager::disconnectWiFi() { + WiFi.disconnect(true); + WiFi.mode(_wifiAPmode ? WIFI_AP : WIFI_OFF); + + _wifiSTAmode = false; + return true; +} + +String NetworkManager::getWiFiSSID() const { + return WiFi.SSID(); +} + +String NetworkManager::getWiFiAPSSID() const { + return WiFi.softAPSSID(); +} + +IPAddress NetworkManager::getWiFiIP() const { + return WiFi.localIP(); +} + +IPAddress NetworkManager::getWiFiAPIP() const { + return WiFi.softAPIP(); +} + +wifi_mode_t NetworkManager::getWiFiMode() const { + return WiFi.getMode(); +} + +uint8_t* NetworkManager::getWiFimacAddress(uint8_t* mac) { + return WiFi.macAddress(mac); +} + +String NetworkManager::getWiFimacAddress(void) const { + return WiFi.macAddress(); +} + +// Check if network is available +bool NetworkManager::isConnected() const { + return isWiFiConnected() || isEthernetConnected() || isModemConnected(); +} + +// Check if WiFi is connected +bool NetworkManager::isWiFiConnected() const { + return _wifiSTAmode ? WiFi.status() == WL_CONNECTED : false; +} + +bool NetworkManager::isWifiAPActive() const { + return _wifiAPmode; +} + +// Check if Ethernet is connected +bool NetworkManager::isEthernetConnected() const { + // Implement Ethernet connection check logic here + return false; +} + +// Check if Modem is connected +bool NetworkManager::isModemConnected() const { + // Implement Modem connection check logic here + return false; +} From e0c66080556fabd5a1cd8fc49907093e98cfbe1d Mon Sep 17 00:00:00 2001 From: Petr Kracik Date: Thu, 15 Jan 2026 00:03:19 +0100 Subject: [PATCH 04/24] Network manager supports setHostname --- include/network_manager.h | 5 ++++- src/network_manager.cpp | 38 +++++++++++++++++++++++--------------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/include/network_manager.h b/include/network_manager.h index 6d84f9b..a7f2ae1 100644 --- a/include/network_manager.h +++ b/include/network_manager.h @@ -13,7 +13,8 @@ private: unsigned long _apStartup = 0; unsigned long _apTimeout = 0; - String _generateAPSSID(); + String _hostName = ""; + void _processAPTimeout(); public: @@ -27,6 +28,8 @@ public: bool setup(); void loop(); + void setHostName(const String& hostName); + // WiFi methods bool setupAP(String apName, String apPsk = ""); bool disableAP(); diff --git a/src/network_manager.cpp b/src/network_manager.cpp index 27451ba..c0f4794 100644 --- a/src/network_manager.cpp +++ b/src/network_manager.cpp @@ -8,21 +8,7 @@ NetworkManager::NetworkManager() { } // Destructor NetworkManager::~NetworkManager() { } -// Initialize -bool NetworkManager::setup() { - Serial.println("Initializing Networking..."); - return true; -} - - -void NetworkManager::loop() { - if (_wifiAPmode) { - _processAPTimeout(); - } -} - - -// WiFi methods +// Private methods void NetworkManager::_processAPTimeout() { if (!_wifiAPmode || _apTimeout == 0 || !_wifiSTAmode) { @@ -43,6 +29,24 @@ void NetworkManager::_processAPTimeout() { } } +// Initialize +bool NetworkManager::setup() { + Serial.println("Initializing Networking..."); + return true; +} + +void NetworkManager::loop() { + if (_wifiAPmode) { + _processAPTimeout(); + } +} + +void NetworkManager::setHostName(const String& hostName) { + _hostName = hostName; +} + +// WiFi methods + bool NetworkManager::setupAP(String apName, String apPsk) { _wifiAPmode = true; @@ -89,6 +93,10 @@ void NetworkManager::setAPTimeout(unsigned long timeout) { bool NetworkManager::connectWiFi(String ssid, String psk) { _wifiSTAmode = true; + if (!_hostName.isEmpty()) { + WiFi.setHostname(_hostName.c_str()); + } + WiFi.mode(_wifiAPmode ? WIFI_AP_STA : WIFI_STA); Serial.println("Attempting to connect to WiFi: " + ssid); From 1ff5504956e6fdf6ec8bee242625b4ee27a77fd6 Mon Sep 17 00:00:00 2001 From: Petr Kracik Date: Thu, 5 Mar 2026 22:39:43 +0100 Subject: [PATCH 05/24] Network manager: wifi connect use LED --- src/network_manager.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/network_manager.cpp b/src/network_manager.cpp index c0f4794..933d8f2 100644 --- a/src/network_manager.cpp +++ b/src/network_manager.cpp @@ -102,10 +102,19 @@ bool NetworkManager::connectWiFi(String ssid, String psk) { Serial.println("Attempting to connect to WiFi: " + ssid); WiFi.begin(ssid.c_str(), psk.c_str()); + Serial.print("Connecting "); + int attempts = 0; - while (!isWiFiConnected() && attempts < 20) { + while (!isWiFiConnected() && attempts < 10) { delay(500); - Serial.print("."); + #ifdef INTERNAL_LED_PIN + digitalWrite(INTERNAL_LED_PIN,HIGH); + #endif + Serial.print('.'); + delay(500); + #ifdef INTERNAL_LED_PIN + digitalWrite(INTERNAL_LED_PIN,LOW); + #endif attempts++; } Serial.println(); From 1668fc14123bd095f12156b32eda2db793afb409 Mon Sep 17 00:00:00 2001 From: Petr Kracik Date: Thu, 5 Mar 2026 23:23:34 +0100 Subject: [PATCH 06/24] Network manager: AutoAP Disable --- src/network_manager.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/network_manager.cpp b/src/network_manager.cpp index 933d8f2..d40e5c8 100644 --- a/src/network_manager.cpp +++ b/src/network_manager.cpp @@ -11,21 +11,19 @@ NetworkManager::~NetworkManager() { } // Private methods void NetworkManager::_processAPTimeout() { - if (!_wifiAPmode || _apTimeout == 0 || !_wifiSTAmode) { + if (!_wifiAPmode || _apTimeout == 0) { + return; + } + + // If any station is connected, reset the timer + if (WiFi.softAPgetStationNum() > 0) { + _apStartup = millis(); return; } if (millis() - _apStartup > _apTimeout) { - // Time expired, switch to client mode if successfully connected - if (isWiFiConnected()) { - Serial.println("AP timeout reached. Switching to client mode only."); - disableAP(); - } - else { - // Not connected as a client, keep AP running - Serial.println("AP timeout reached but WiFi client still not connected. Keeping AP mode active."); - _apStartup = millis(); // Reset timer - } + Serial.println("AP timeout reached. Disabling AP mode."); + disableAP(); } } From 447c2d49379d7467b85049ec4673a26bc1732029 Mon Sep 17 00:00:00 2001 From: Petr Kracik Date: Thu, 15 Jan 2026 01:41:42 +0100 Subject: [PATCH 07/24] Network manager support more Wifi networks --- include/network_manager.h | 17 ++++- src/network_manager.cpp | 127 ++++++++++++++++++++++++++++---------- 2 files changed, 111 insertions(+), 33 deletions(-) diff --git a/include/network_manager.h b/include/network_manager.h index a7f2ae1..0d8987f 100644 --- a/include/network_manager.h +++ b/include/network_manager.h @@ -1,6 +1,7 @@ #include #include #include +#include /** * Class for managing network connections @@ -8,13 +9,22 @@ class NetworkManager { private: + class WiFiNetwork { + public: + String ssid; + String psk; + }; + bool _wifiAPmode = false; bool _wifiSTAmode = false; unsigned long _apStartup = 0; unsigned long _apTimeout = 0; String _hostName = ""; + std::vector _wifiNetworks; + int _findWiFiNetworkIndex(const String& ssid) const; + bool _connectWiFi(const WiFiNetwork& network); void _processAPTimeout(); public: @@ -34,7 +44,12 @@ public: bool setupAP(String apName, String apPsk = ""); bool disableAP(); void setAPTimeout(unsigned long timeout); - bool connectWiFi(String ssid, String psk); + void addWiFiNetwork(const String& ssid, const String& psk = ""); + void clearWiFiNetworks(); + bool hasWiFiNetworks() const; + size_t getWiFiNetworkCount() const; + bool connectWiFi(); + bool connectWiFi(const String& ssid, const String& psk = ""); bool disconnectWiFi(); String getWiFiSSID() const; String getWiFiAPSSID() const; diff --git a/src/network_manager.cpp b/src/network_manager.cpp index d40e5c8..0597c1f 100644 --- a/src/network_manager.cpp +++ b/src/network_manager.cpp @@ -10,6 +10,58 @@ NetworkManager::~NetworkManager() { } // Private methods +int NetworkManager::_findWiFiNetworkIndex(const String& ssid) const { + for (size_t i = 0; i < _wifiNetworks.size(); i++) { + if (_wifiNetworks[i].ssid == ssid) { + return static_cast(i); + } + } + return -1; +} + +bool NetworkManager::_connectWiFi(const WiFiNetwork& network) { + if (network.ssid.isEmpty()) { + return false; + } + + _wifiSTAmode = true; + + if (!_hostName.isEmpty()) { + WiFi.setHostname(_hostName.c_str()); + } + + WiFi.mode(_wifiAPmode ? WIFI_AP_STA : WIFI_STA); + + Serial.println("[NM] Attempting to connect to WiFi: " + network.ssid); + WiFi.begin(network.ssid.c_str(), network.psk.c_str()); + + Serial.print("[NM] Connecting "); + + int attempts = 0; + while (!isWiFiConnected() && attempts < 10) { + delay(500); + #ifdef INTERNAL_LED_PIN + digitalWrite(INTERNAL_LED_PIN,HIGH); + #endif + Serial.print('.'); + delay(500); + #ifdef INTERNAL_LED_PIN + digitalWrite(INTERNAL_LED_PIN,LOW); + #endif + attempts++; + } + Serial.println(); + + if (isWiFiConnected()) { + Serial.println("[NM] WiFi connected! IP: " + WiFi.localIP().toString()); + return true; + } + + Serial.println("[NM] Failed to connect to WiFi after " + String(attempts) + " attempts. SSID: " + + network.ssid); + return false; +} + void NetworkManager::_processAPTimeout() { if (!_wifiAPmode || _apTimeout == 0) { return; @@ -88,44 +140,55 @@ void NetworkManager::setAPTimeout(unsigned long timeout) { _apTimeout = timeout; } -bool NetworkManager::connectWiFi(String ssid, String psk) { - _wifiSTAmode = true; - - if (!_hostName.isEmpty()) { - WiFi.setHostname(_hostName.c_str()); +void NetworkManager::addWiFiNetwork(const String& ssid, const String& psk) { + if (ssid.isEmpty()) { + return; } - WiFi.mode(_wifiAPmode ? WIFI_AP_STA : WIFI_STA); - - Serial.println("Attempting to connect to WiFi: " + ssid); - WiFi.begin(ssid.c_str(), psk.c_str()); - - Serial.print("Connecting "); - - int attempts = 0; - while (!isWiFiConnected() && attempts < 10) { - delay(500); - #ifdef INTERNAL_LED_PIN - digitalWrite(INTERNAL_LED_PIN,HIGH); - #endif - Serial.print('.'); - delay(500); - #ifdef INTERNAL_LED_PIN - digitalWrite(INTERNAL_LED_PIN,LOW); - #endif - attempts++; + int index = _findWiFiNetworkIndex(ssid); + if (index >= 0) { + Serial.println("[NM] Updating WiFi network: " + ssid); + _wifiNetworks[static_cast(index)].psk = psk; + return; } - Serial.println(); - if (isWiFiConnected()) { - Serial.println("WiFi connected! IP: " + WiFi.localIP().toString()); - return true; - } - else { - Serial.println("Failed to connect to WiFi after " + String(attempts) + " attempts. SSID: " + - ssid); + Serial.println("[NM] Adding WiFi network: " + ssid); + WiFiNetwork network; + network.ssid = ssid; + network.psk = psk; + _wifiNetworks.push_back(network); +} + +void NetworkManager::clearWiFiNetworks() { + _wifiNetworks.clear(); +} + +bool NetworkManager::hasWiFiNetworks() const { + return !_wifiNetworks.empty(); +} + +size_t NetworkManager::getWiFiNetworkCount() const { + return _wifiNetworks.size(); +} + +bool NetworkManager::connectWiFi() { + if (_wifiNetworks.empty()) { return false; } + + for (size_t i = 0; i < _wifiNetworks.size(); i++) { + disconnectWiFi(); + if (_connectWiFi(_wifiNetworks[i])) { + return true; + } + } + + return false; +} + +bool NetworkManager::connectWiFi(const String& ssid, const String& psk) { + addWiFiNetwork(ssid, psk); + return connectWiFi(); } bool NetworkManager::disconnectWiFi() { From 801641f781af2527d9ff538e3f6e225dbb8aec36 Mon Sep 17 00:00:00 2001 From: Petr Kracik Date: Thu, 15 Jan 2026 00:23:41 +0100 Subject: [PATCH 08/24] Network manager supports basic Ethernet --- include/network_manager.h | 11 +++++ src/network_manager.cpp | 87 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 2 deletions(-) diff --git a/include/network_manager.h b/include/network_manager.h index 0d8987f..fac3964 100644 --- a/include/network_manager.h +++ b/include/network_manager.h @@ -1,6 +1,7 @@ #include #include #include +#include #include /** @@ -17,6 +18,8 @@ private: bool _wifiAPmode = false; bool _wifiSTAmode = false; + bool _ethernetMode = false; + bool _ethernetConnected = false; unsigned long _apStartup = 0; unsigned long _apTimeout = 0; @@ -26,6 +29,7 @@ private: int _findWiFiNetworkIndex(const String& ssid) const; bool _connectWiFi(const WiFiNetwork& network); void _processAPTimeout(); + void _onNetworkEvent(arduino_event_id_t event, arduino_event_info_t /*info*/); public: // Constructor @@ -59,6 +63,13 @@ public: uint8_t* getWiFimacAddress(uint8_t* mac); String getWiFimacAddress(void) const; + // Ethernet methods + bool ethernetConnect(eth_phy_type_t type, uint8_t phy_addr, uint8_t mdc, uint8_t mdio, int power, eth_clock_mode_t clock_mode, bool use_mac_from_efuse = false); + bool setEthernetIP(const String& staticIP, const String& gateway, const String& subnet, const String& dns1, const String& dns2); + bool ethernetDisconnect(); + IPAddress getEthernetIP() const; + String getEthernetMACAddress() const; + // Check if any network is available bool isConnected() const; diff --git a/src/network_manager.cpp b/src/network_manager.cpp index 0597c1f..f5b47bf 100644 --- a/src/network_manager.cpp +++ b/src/network_manager.cpp @@ -79,9 +79,44 @@ void NetworkManager::_processAPTimeout() { } } +void NetworkManager::_onNetworkEvent(arduino_event_id_t event, arduino_event_info_t /*info*/) { + switch (event) { + case ARDUINO_EVENT_ETH_START: + Serial.println("ETH Started"); + if (!_hostName.isEmpty()) { + Serial.println("ETH Setting Hostname: " + _hostName); + ETH.setHostname(_hostName.c_str()); + } + break; + case ARDUINO_EVENT_ETH_CONNECTED: + Serial.println("ETH Connected"); + break; + case ARDUINO_EVENT_ETH_GOT_IP: + Serial.println("ETH Got IP"); + _ethernetConnected = true; + break; + case ARDUINO_EVENT_ETH_DISCONNECTED: + Serial.println("ETH Disconnected"); + _ethernetConnected = false; + break; + case ARDUINO_EVENT_ETH_STOP: + Serial.println("ETH Stopped"); + _ethernetConnected = false; + break; + default: + break; + } +} + // Initialize bool NetworkManager::setup() { Serial.println("Initializing Networking..."); + + WiFi.onEvent( + [this](arduino_event_id_t event, arduino_event_info_t info) { + _onNetworkEvent(event, info); + }); + return true; } @@ -227,6 +262,55 @@ String NetworkManager::getWiFimacAddress(void) const { return WiFi.macAddress(); } +// Ethernet methods +bool NetworkManager::ethernetConnect(eth_phy_type_t type, uint8_t phy_addr, uint8_t mdc, uint8_t mdio, int power, eth_clock_mode_t clock_mode, bool use_mac_from_efuse) { + _ethernetMode = true; + Serial.println("Setting up Ethernet..."); + + #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) + // SDK 5.x (Arduino SDK 3.x) + #pragma message("Compiling ETH init: SDK 5.x (Arduino core 3.x)") + return ETH.begin(type, phy_addr, mdc, mdio, power, clock_mode, use_mac_from_efuse); + #else + // SDK 4.x (Arduino SDK 2.x) + #pragma message("Compiling ETH init: SDK 4.x (Arduino core 2.x)") + return ETH.begin(phy_addr, power, mdc, mdio, type, clock_mode, use_mac_from_efuse); + #endif +} + +bool NetworkManager::setEthernetIP(const String& staticIP, const String& gateway, const String& subnet, const String& dns1, const String& dns2) { + if (staticIP.isEmpty()) { + return false; + } + + IPAddress ip, gw, sn, d1, d2; + if (!ip.fromString(staticIP) || !gw.fromString(gateway) || !sn.fromString(subnet)) { + Serial.println("Invalid static IP configuration"); + return false; + } + + if (!dns1.isEmpty() && d1.fromString(dns1)) { + if (!dns2.isEmpty() && d2.fromString(dns2)) { + ETH.config(ip, gw, sn, d1, d2); + } else { + ETH.config(ip, gw, sn, d1); + } + } else { + ETH.config(ip, gw, sn); + } + + Serial.println("Ethernet static IP: " + staticIP); + return true; +} + +IPAddress NetworkManager::getEthernetIP() const { + return ETH.localIP(); +} + +String NetworkManager::getEthernetMACAddress() const { + return ETH.macAddress(); +} + // Check if network is available bool NetworkManager::isConnected() const { return isWiFiConnected() || isEthernetConnected() || isModemConnected(); @@ -243,8 +327,7 @@ bool NetworkManager::isWifiAPActive() const { // Check if Ethernet is connected bool NetworkManager::isEthernetConnected() const { - // Implement Ethernet connection check logic here - return false; + return _ethernetMode && _ethernetConnected && ETH.linkUp(); } // Check if Modem is connected From ca567e720d7bc50627861a98b4949e0bcb7f44e7 Mon Sep 17 00:00:00 2001 From: Petr Kracik Date: Tue, 3 Feb 2026 19:25:05 +0100 Subject: [PATCH 09/24] NetworkManager: NM log prefix --- src/network_manager.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/network_manager.cpp b/src/network_manager.cpp index f5b47bf..b94693c 100644 --- a/src/network_manager.cpp +++ b/src/network_manager.cpp @@ -74,7 +74,7 @@ void NetworkManager::_processAPTimeout() { } if (millis() - _apStartup > _apTimeout) { - Serial.println("AP timeout reached. Disabling AP mode."); + Serial.println("[NM] AP timeout reached. Disabling AP mode."); disableAP(); } } @@ -82,25 +82,25 @@ void NetworkManager::_processAPTimeout() { void NetworkManager::_onNetworkEvent(arduino_event_id_t event, arduino_event_info_t /*info*/) { switch (event) { case ARDUINO_EVENT_ETH_START: - Serial.println("ETH Started"); + Serial.println("[NM] ETH Started"); if (!_hostName.isEmpty()) { - Serial.println("ETH Setting Hostname: " + _hostName); + Serial.println("[NM] ETH Setting Hostname: " + _hostName); ETH.setHostname(_hostName.c_str()); } break; case ARDUINO_EVENT_ETH_CONNECTED: - Serial.println("ETH Connected"); + Serial.println("[NM] ETH Connected"); break; case ARDUINO_EVENT_ETH_GOT_IP: - Serial.println("ETH Got IP"); + Serial.println("[NM] ETH Got IP"); _ethernetConnected = true; break; case ARDUINO_EVENT_ETH_DISCONNECTED: - Serial.println("ETH Disconnected"); + Serial.println("[NM] ETH Disconnected"); _ethernetConnected = false; break; case ARDUINO_EVENT_ETH_STOP: - Serial.println("ETH Stopped"); + Serial.println("[NM] ETH Stopped"); _ethernetConnected = false; break; default: @@ -110,7 +110,7 @@ void NetworkManager::_onNetworkEvent(arduino_event_id_t event, arduino_event_inf // Initialize bool NetworkManager::setup() { - Serial.println("Initializing Networking..."); + Serial.println("[NM] Initializing Networking..."); WiFi.onEvent( [this](arduino_event_id_t event, arduino_event_info_t info) { @@ -135,7 +135,7 @@ void NetworkManager::setHostName(const String& hostName) { bool NetworkManager::setupAP(String apName, String apPsk) { _wifiAPmode = true; - Serial.println("Starting AP mode: " + apName); + Serial.println("[NM] Starting AP mode: " + apName); // Full WiFi reset sequence WiFi.disconnect(true); @@ -149,16 +149,16 @@ bool NetworkManager::setupAP(String apName, String apPsk) { delay(1000); // Give AP time to fully initialize if (apStarted) { - Serial.println("AP setup successful"); + Serial.println("[NM] AP setup successful"); _apStartup = millis(); } else { - Serial.println("AP setup failed"); + Serial.println("[NM] AP setup failed"); return false; } IPAddress apIP = getWiFiAPIP(); - Serial.println("AP IP assigned: " + apIP.toString()); + Serial.println("[NM] AP IP assigned: " + apIP.toString()); return true; } @@ -171,7 +171,7 @@ bool NetworkManager::disableAP() { } void NetworkManager::setAPTimeout(unsigned long timeout) { - Serial.println("Setting AP timeout to " + String(timeout / 1000) + " sec"); + Serial.println("[NM] Setting AP timeout to " + String(timeout / 1000) + " sec"); _apTimeout = timeout; } @@ -265,7 +265,7 @@ String NetworkManager::getWiFimacAddress(void) const { // Ethernet methods bool NetworkManager::ethernetConnect(eth_phy_type_t type, uint8_t phy_addr, uint8_t mdc, uint8_t mdio, int power, eth_clock_mode_t clock_mode, bool use_mac_from_efuse) { _ethernetMode = true; - Serial.println("Setting up Ethernet..."); + Serial.println("[NM] Setting up Ethernet..."); #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) // SDK 5.x (Arduino SDK 3.x) @@ -285,7 +285,7 @@ bool NetworkManager::setEthernetIP(const String& staticIP, const String& gateway IPAddress ip, gw, sn, d1, d2; if (!ip.fromString(staticIP) || !gw.fromString(gateway) || !sn.fromString(subnet)) { - Serial.println("Invalid static IP configuration"); + Serial.println("[NM] Invalid static IP configuration"); return false; } @@ -299,7 +299,7 @@ bool NetworkManager::setEthernetIP(const String& staticIP, const String& gateway ETH.config(ip, gw, sn); } - Serial.println("Ethernet static IP: " + staticIP); + Serial.println("[NM] Ethernet static IP: " + staticIP); return true; } From 1edb333b1d5e6f914dc3193755901b89fdbfecf1 Mon Sep 17 00:00:00 2001 From: Petr Kracik Date: Thu, 5 Mar 2026 23:02:30 +0100 Subject: [PATCH 10/24] WiFi utils uses networkManager --- src/wifi_utils.cpp | 107 +++++++++++++++++---------------------------- 1 file changed, 39 insertions(+), 68 deletions(-) diff --git a/src/wifi_utils.cpp b/src/wifi_utils.cpp index 2781f17..54d4dde 100644 --- a/src/wifi_utils.cpp +++ b/src/wifi_utils.cpp @@ -18,6 +18,7 @@ #include #include "configuration.h" +#include "network_manager.h" #include "board_pinout.h" #include "wifi_utils.h" #include "display.h" @@ -25,6 +26,7 @@ extern Configuration Config; +extern NetworkManager *networkManager; extern uint8_t myWiFiAPIndex; extern int myWiFiAPSize; @@ -34,7 +36,6 @@ extern uint32_t lastServerCheck; bool WiFiConnected = false; uint32_t WiFiAutoAPTime = millis(); -bool WiFiAutoAPStarted = false; uint8_t wifiCounter = 0; uint32_t lastBackupDigiTime = millis(); uint32_t lastWiFiCheck = 0; @@ -47,29 +48,27 @@ namespace WIFI_Utils { uint32_t currentTime = millis(); if (backupDigiMode) { - if (WiFi.status() != WL_CONNECTED && ((currentTime - lastBackupDigiTime) >= 15 * 60 * 1000)) { + if (!networkManager->isWiFiConnected() && ((currentTime - lastBackupDigiTime) >= 15 * 60 * 1000)) { Serial.println("*** Stopping BackUp Digi Mode ***"); backupDigiMode = false; wifiCounter = 0; - } else if (WiFi.status() == WL_CONNECTED) { + } else if (networkManager->isWiFiConnected()) { Serial.println("*** WiFi Reconnect Success (Stopping Backup Digi Mode) ***"); backupDigiMode = false; wifiCounter = 0; } } - if (!backupDigiMode && ((currentTime - lastWiFiCheck) >= 30 * 1000) && !WiFiAutoAPStarted) { + if (!backupDigiMode && ((currentTime - lastWiFiCheck) >= 30 * 1000) && !networkManager->isWifiAPActive()) { lastWiFiCheck = currentTime; - if (WiFi.status() == WL_CONNECTED) { + if (networkManager->isWiFiConnected()) { if (Config.digi.backupDigiMode && (currentTime - lastServerCheck > 30 * 1000)) { Serial.println("*** Server Connection LOST → Backup Digi Mode ***"); backupDigiMode = true; - WiFi.disconnect(); lastBackupDigiTime = currentTime; } } else { Serial.println("Reconnecting to WiFi..."); - WiFi.disconnect(); WIFI_Utils::startWiFi(); if (Config.digi.backupDigiMode) wifiCounter++; @@ -83,84 +82,57 @@ namespace WIFI_Utils { } void startAutoAP() { - WiFi.mode(WIFI_MODE_NULL); - - WiFi.mode(WIFI_AP); - WiFi.softAP(Config.callsign + "-AP", Config.wifiAutoAP.password); - + displayShow("", " Starting Auto AP", " Please connect to it " , " loading ...", 1000); + networkManager->setupAP(Config.callsign + "-AP", Config.wifiAutoAP.password); WiFiAutoAPTime = millis(); - WiFiAutoAPStarted = true; } void startWiFi() { - bool startAP = false; - if (currentWiFi->ssid == "") { - startAP = true; - } else { - uint8_t wifiCounter = 0; - String hostName = "iGATE-" + Config.callsign; - WiFi.setHostname(hostName.c_str()); - WiFi.mode(WIFI_STA); - WiFi.disconnect(); - delay(500); - unsigned long start = millis(); - displayShow("", "Connecting to WiFi:", "", currentWiFi->ssid + " ...", 0); - Serial.print("\nConnecting to WiFi '"); Serial.print(currentWiFi->ssid); Serial.print("' "); - WiFi.begin(currentWiFi->ssid.c_str(), currentWiFi->password.c_str()); - while (WiFi.status() != WL_CONNECTED && wifiCounter < myWiFiAPSize) { - delay(500); - #ifdef INTERNAL_LED_PIN - digitalWrite(INTERNAL_LED_PIN, HIGH); - #endif - Serial.print('.'); - delay(500); - #ifdef INTERNAL_LED_PIN - digitalWrite(INTERNAL_LED_PIN, LOW); - #endif - if ((millis() - start) > 10000){ - delay(1000); - if (myWiFiAPIndex >= (myWiFiAPSize - 1)) { - myWiFiAPIndex = 0; - wifiCounter++; - } else { - myWiFiAPIndex++; - } - wifiCounter++; - currentWiFi = &Config.wifiAPs[myWiFiAPIndex]; - start = millis(); - Serial.print("\nConnecting to WiFi '"); Serial.print(currentWiFi->ssid); Serial.println("' ..."); - displayShow("", "Connecting to WiFi:", "", currentWiFi->ssid + " ...", 0); - WiFi.disconnect(); - WiFi.begin(currentWiFi->ssid.c_str(), currentWiFi->password.c_str()); - } - } + if (currentWiFi->ssid.isEmpty()) { + Serial.println("WiFi SSID not set! Starting Auto AP"); + startAutoAP(); + return; } + + String hostName = "iGATE-" + Config.callsign; + WiFi.setHostname(hostName.c_str()); + + // TODO: Create generic multi-SSID support in Network Manager + while (!networkManager->isWiFiConnected()) { + displayShow("", "Connecting to WiFi:", "", currentWiFi->ssid + " ...", 0); + networkManager->disconnectWiFi(); + networkManager->connectWiFi(currentWiFi->ssid, currentWiFi->password); + + if(myWiFiAPIndex >= (myWiFiAPSize - 1)) { + break; + } + + myWiFiAPIndex++; + currentWiFi = &Config.wifiAPs[myWiFiAPIndex]; + } + #ifdef INTERNAL_LED_PIN digitalWrite(INTERNAL_LED_PIN, LOW); #endif - if (WiFi.status() == WL_CONNECTED) { + if (networkManager->isWiFiConnected()) { Serial.print("\nConnected as "); - Serial.print(WiFi.localIP()); + Serial.print(networkManager->getWiFiIP()); Serial.print(" / MAC Address: "); - Serial.println(WiFi.macAddress()); + Serial.println(networkManager->getWiFimacAddress()); displayShow("", " Connected!!", "" , " loading ...", 1000); } else { - startAP = true; - Serial.println("\nNot connected to WiFi! Starting Auto AP"); displayShow("", " WiFi Not Connected!", "" , " loading ...", 1000); - } - WiFiConnected = !startAP; - if (startAP) { - Serial.println("\nNot connected to WiFi! Starting Auto AP"); - displayShow("", " Starting Auto AP", " Please connect to it " , " loading ...", 1000); startAutoAP(); } + + //TODO: Use network manager whenever this variable is used + WiFiConnected = networkManager->isWiFiConnected(); } void checkAutoAPTimeout() { - if (WiFiAutoAPStarted && Config.wifiAutoAP.timeout > 0) { + if (networkManager->isWifiAPActive() && Config.wifiAutoAP.timeout > 0) { if (WiFi.softAPgetStationNum() > 0) { WiFiAutoAPTime = 0; } else { @@ -169,8 +141,7 @@ namespace WIFI_Utils { } else if ((millis() - WiFiAutoAPTime) > Config.wifiAutoAP.timeout * 60 * 1000) { Serial.println("Stopping auto AP"); - WiFiAutoAPStarted = false; - WiFi.softAPdisconnect(true); + networkManager->disableAP(); Serial.println("Auto AP stopped (timeout)"); } @@ -183,4 +154,4 @@ namespace WIFI_Utils { btStop(); } -} \ No newline at end of file +} From f18d16a6fb199a7112245b270925557474ab8d8c Mon Sep 17 00:00:00 2001 From: Petr Kracik Date: Mon, 12 Jan 2026 23:42:46 +0100 Subject: [PATCH 11/24] ARPS Utils uses networkManager --- src/aprs_is_utils.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/aprs_is_utils.cpp b/src/aprs_is_utils.cpp index 2dc93b9..97be61b 100644 --- a/src/aprs_is_utils.cpp +++ b/src/aprs_is_utils.cpp @@ -16,9 +16,10 @@ * along with LoRa APRS iGate. If not, see . */ -#include -#include +#include +#include #include "configuration.h" +#include "network_manager.h" #include "aprs_is_utils.h" #include "station_utils.h" #include "board_pinout.h" @@ -32,6 +33,7 @@ extern Configuration Config; +extern NetworkManager *networkManager; extern WiFiClient aprsIsClient; extern uint32_t lastScreenOn; extern String firstLine; @@ -93,7 +95,7 @@ namespace APRS_IS_Utils { void checkStatus() { String wifiState, aprsisState; - if (WiFi.status() == WL_CONNECTED) { + if (networkManager->isWiFiConnected()) { wifiState = "OK"; } else { if (backupDigiMode || Config.digi.ecoMode == 1 || Config.digi.ecoMode == 2) { @@ -408,7 +410,7 @@ namespace APRS_IS_Utils { } void firstConnection() { - if (Config.aprs_is.active && (WiFi.status() == WL_CONNECTED) && !aprsIsClient.connected()) { + if (Config.aprs_is.active && networkManager->isConnected() && !aprsIsClient.connected()) { connect(); while (!passcodeValid) { listenAPRSIS(); @@ -416,4 +418,4 @@ namespace APRS_IS_Utils { } } -} \ No newline at end of file +} From 10d1fb4ede93954ea48aba2c49d3eebafe03beaa Mon Sep 17 00:00:00 2001 From: Petr Kracik Date: Thu, 5 Mar 2026 22:24:57 +0100 Subject: [PATCH 12/24] Utils uses networkManager --- src/utils.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/utils.cpp b/src/utils.cpp index c7b023e..b0d618f 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -18,9 +18,9 @@ #include #include -#include #include "telemetry_utils.h" #include "configuration.h" +#include "network_manager.h" #include "station_utils.h" #include "battery_utils.h" #include "aprs_is_utils.h" @@ -37,6 +37,7 @@ #define DAY_MS (24UL * 60UL * 60UL * 1000UL) extern Configuration Config; +extern NetworkManager *networkManager; extern TinyGPSPlus gps; extern String versionDate; extern String firstLine; @@ -52,7 +53,6 @@ extern int rssi; extern float snr; extern int freqError; extern String distance; -extern bool WiFiConnected; extern int wxModuleType; extern bool backupDigiMode; extern bool shouldSleepLowVoltage; @@ -75,7 +75,7 @@ String secondaryBeaconPacket; namespace Utils { void processStatus() { - bool sendOverAPRSIS = Config.beacon.sendViaAPRSIS && Config.aprs_is.active && WiFi.status() == WL_CONNECTED; + bool sendOverAPRSIS = Config.beacon.sendViaAPRSIS && Config.aprs_is.active && networkManager->isConnected(); bool sendOverRF = !Config.beacon.sendViaAPRSIS && Config.beacon.sendViaRF; if (!sendOverAPRSIS && !sendOverRF) { @@ -104,12 +104,12 @@ namespace Utils { String getLocalIP() { if (Config.digi.ecoMode == 1 || Config.digi.ecoMode == 2) { return "** WiFi AP Killed **"; - } else if (!WiFiConnected) { - return "IP : 192.168.4.1"; + } else if (!networkManager->isWiFiConnected() && networkManager->isWifiAPActive()) { + return "IP : " + networkManager->getWiFiAPIP().toString(); } else if (backupDigiMode) { return "- BACKUP DIGI MODE -"; } else { - return "IP : " + String(WiFi.localIP()[0]) + "." + String(WiFi.localIP()[1]) + "." + String(WiFi.localIP()[2]) + "." + String(WiFi.localIP()[3]); + return "IP : " + networkManager->getWiFiIP().toString(); } } @@ -481,4 +481,4 @@ namespace Utils { } } -} \ No newline at end of file +} From eb4087073b626ffbe9b0bba41ffdb26e6aad0fa5 Mon Sep 17 00:00:00 2001 From: Petr Kracik Date: Tue, 13 Jan 2026 00:01:56 +0100 Subject: [PATCH 13/24] Lora uses networkManager --- src/lora_utils.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/lora_utils.cpp b/src/lora_utils.cpp index 5394944..d9653f7 100644 --- a/src/lora_utils.cpp +++ b/src/lora_utils.cpp @@ -17,8 +17,8 @@ */ #include -#include #include "configuration.h" +#include "network_manager.h" #include "aprs_is_utils.h" #include "station_utils.h" #include "board_pinout.h" @@ -29,6 +29,7 @@ extern Configuration Config; +extern NetworkManager *networkManager; extern uint32_t lastRxTime; extern bool packetIsBeacon; @@ -181,7 +182,7 @@ namespace LoRa_Utils { int state = radio.transmit("\x3c\xff\x01" + newPacket); transmitFlag = true; if (state == RADIOLIB_ERR_NONE) { - if (Config.syslog.active && WiFi.status() == WL_CONNECTED) { + if (Config.syslog.active && networkManager->isConnected()) { SYSLOG_Utils::log(3, newPacket, 0, 0.0, 0); // TX } Utils::print("---> LoRa Packet Tx : "); @@ -243,7 +244,7 @@ namespace LoRa_Utils { receivedPackets.push_back(receivedPacket); } - if (Config.syslog.active && WiFi.status() == WL_CONNECTED) { + if (Config.syslog.active && networkManager->isConnected()) { SYSLOG_Utils::log(1, packet, rssi, snr, freqError); // RX } } else { @@ -257,7 +258,7 @@ namespace LoRa_Utils { snr = radio.getSNR(); freqError = radio.getFrequencyError(); Utils::println(F("CRC error!")); - if (Config.syslog.active && WiFi.status() == WL_CONNECTED) { + if (Config.syslog.active && networkManager->isConnected()) { SYSLOG_Utils::log(0, packet, rssi, snr, freqError); // CRC } packet = ""; From 891fc906bbef6d2e6d8a17e0f4dcc19517440f0c Mon Sep 17 00:00:00 2001 From: Petr Kracik Date: Tue, 13 Jan 2026 00:08:29 +0100 Subject: [PATCH 14/24] NTP uses networkManager --- src/ntp_utils.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ntp_utils.cpp b/src/ntp_utils.cpp index b835384..bec0e80 100644 --- a/src/ntp_utils.cpp +++ b/src/ntp_utils.cpp @@ -18,14 +18,14 @@ #include #include -#include #include "configuration.h" +#include "network_manager.h" #include "ntp_utils.h" #include "time.h" extern Configuration Config; - +extern NetworkManager *networkManager; WiFiUDP ntpUDP; NTPClient* timeClient; @@ -33,7 +33,7 @@ NTPClient* timeClient; namespace NTP_Utils { void setup() { - if (WiFi.status() == WL_CONNECTED && Config.digi.ecoMode == 0 && Config.callsign != "NOCALL-10") { + if (networkManager->isConnected() && Config.digi.ecoMode == 0 && Config.callsign != "NOCALL-10") { int gmt = Config.ntp.gmtCorrection * 3600; timeClient = new NTPClient(ntpUDP, Config.ntp.server.c_str(), gmt, 15 * 60 * 1000); // Update interval 15 min timeClient->begin(); @@ -41,11 +41,11 @@ namespace NTP_Utils { } void update() { - if (WiFi.status() == WL_CONNECTED && Config.digi.ecoMode == 0 && Config.callsign != "NOCALL-10") timeClient->update(); + if (networkManager->isConnected() && Config.digi.ecoMode == 0 && Config.callsign != "NOCALL-10") timeClient->update(); } String getFormatedTime() { - if (WiFi.status() == WL_CONNECTED && Config.digi.ecoMode == 0) return timeClient->getFormattedTime(); + if (networkManager->isConnected() && Config.digi.ecoMode == 0) return timeClient->getFormattedTime(); return "DigiEcoMode Active"; } From 8a16be1bea38e0b7bac150cf49065a0aa7bd3424 Mon Sep 17 00:00:00 2001 From: Petr Kracik Date: Wed, 4 Feb 2026 14:45:47 +0100 Subject: [PATCH 15/24] NTP: Fix nullptr if network is connected after setup() --- include/ntp_utils.h | 2 +- src/ntp_utils.cpp | 24 +++++++++++++++++++----- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/include/ntp_utils.h b/include/ntp_utils.h index d016a23..59acde2 100644 --- a/include/ntp_utils.h +++ b/include/ntp_utils.h @@ -24,7 +24,7 @@ namespace NTP_Utils { - void setup(); + bool setup(); void update(); String getFormatedTime(); diff --git a/src/ntp_utils.cpp b/src/ntp_utils.cpp index bec0e80..1874501 100644 --- a/src/ntp_utils.cpp +++ b/src/ntp_utils.cpp @@ -27,26 +27,40 @@ extern Configuration Config; extern NetworkManager *networkManager; WiFiUDP ntpUDP; -NTPClient* timeClient; +NTPClient* timeClient = nullptr; namespace NTP_Utils { - void setup() { + bool setup() { if (networkManager->isConnected() && Config.digi.ecoMode == 0 && Config.callsign != "NOCALL-10") { int gmt = Config.ntp.gmtCorrection * 3600; + Serial.println("[NTP] Setting up, TZ offset: " + String(gmt) + " Server: " + Config.ntp.server); timeClient = new NTPClient(ntpUDP, Config.ntp.server.c_str(), gmt, 15 * 60 * 1000); // Update interval 15 min timeClient->begin(); + return true; } + return false; } void update() { - if (networkManager->isConnected() && Config.digi.ecoMode == 0 && Config.callsign != "NOCALL-10") timeClient->update(); + if (!networkManager->isConnected() || Config.digi.ecoMode != 0 || Config.callsign == "NOCALL-10") { + return; + } + if (timeClient == nullptr) { + if (!setup()) { + return; + } + } + + timeClient->update(); } String getFormatedTime() { - if (networkManager->isConnected() && Config.digi.ecoMode == 0) return timeClient->getFormattedTime(); + if (networkManager->isConnected() && Config.digi.ecoMode == 0 && timeClient != nullptr) { + return timeClient->getFormattedTime(); + } return "DigiEcoMode Active"; } -} \ No newline at end of file +} From e5fa6574f0eed397dd4d5a764806febd2314e54c Mon Sep 17 00:00:00 2001 From: Petr Kracik Date: Tue, 13 Jan 2026 00:09:28 +0100 Subject: [PATCH 16/24] Syslog uses networkManager --- src/syslog_utils.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/syslog_utils.cpp b/src/syslog_utils.cpp index 95d9d52..1c48fd6 100644 --- a/src/syslog_utils.cpp +++ b/src/syslog_utils.cpp @@ -17,13 +17,14 @@ */ #include -#include #include "configuration.h" +#include "network_manager.h" #include "syslog_utils.h" #include "gps_utils.h" extern Configuration Config; +extern NetworkManager *networkManager; extern String versionDate; extern String versionNumber; @@ -33,7 +34,7 @@ WiFiUDP udpClient; namespace SYSLOG_Utils { void log(const uint8_t type, const String& packet, const int rssi, const float snr, const int freqError) { - if (Config.syslog.active && WiFi.status() == WL_CONNECTED) { + if (Config.syslog.active && networkManager->isConnected()) { String syslogPacket = "<165>1 - "; syslogPacket.concat(Config.callsign); syslogPacket.concat(" CA2RXU_LoRa_iGate_"); @@ -140,7 +141,7 @@ namespace SYSLOG_Utils { } void setup() { - if (WiFi.status() == WL_CONNECTED) { + if (networkManager->isConnected()) { udpClient.begin(0); if (Config.syslog.active) Serial.println("init : Syslog Server ... done! (at " + Config.syslog.server + ")"); } From ec28dc09784d75d8d890be5978625e1d7a4cf41a Mon Sep 17 00:00:00 2001 From: Petr Kracik Date: Tue, 13 Jan 2026 00:36:53 +0100 Subject: [PATCH 17/24] Removed deprecated WiFiConnected extern --- src/wifi_utils.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/wifi_utils.cpp b/src/wifi_utils.cpp index 54d4dde..ca7efa6 100644 --- a/src/wifi_utils.cpp +++ b/src/wifi_utils.cpp @@ -34,7 +34,6 @@ extern WiFi_AP *currentWiFi; extern bool backupDigiMode; extern uint32_t lastServerCheck; -bool WiFiConnected = false; uint32_t WiFiAutoAPTime = millis(); uint8_t wifiCounter = 0; uint32_t lastBackupDigiTime = millis(); @@ -126,9 +125,6 @@ namespace WIFI_Utils { startAutoAP(); } - - //TODO: Use network manager whenever this variable is used - WiFiConnected = networkManager->isWiFiConnected(); } void checkAutoAPTimeout() { From 413318e94b7bfe94a6d9ca978116e7e4f0e43b2c Mon Sep 17 00:00:00 2001 From: Petr Kracik Date: Thu, 5 Mar 2026 23:25:04 +0100 Subject: [PATCH 18/24] Use SoftAP from network manager --- include/wifi_utils.h | 1 - src/LoRa_APRS_iGate.cpp | 2 +- src/wifi_utils.cpp | 20 -------------------- 3 files changed, 1 insertion(+), 22 deletions(-) diff --git a/include/wifi_utils.h b/include/wifi_utils.h index a7540f8..be2e035 100644 --- a/include/wifi_utils.h +++ b/include/wifi_utils.h @@ -27,7 +27,6 @@ namespace WIFI_Utils { void checkWiFi(); void startAutoAP(); void startWiFi(); - void checkAutoAPTimeout(); void setup(); } diff --git a/src/LoRa_APRS_iGate.cpp b/src/LoRa_APRS_iGate.cpp index 4a57ef3..670b1f5 100644 --- a/src/LoRa_APRS_iGate.cpp +++ b/src/LoRa_APRS_iGate.cpp @@ -106,6 +106,7 @@ void setup() { Serial.begin(115200); networkManager = new NetworkManager(); networkManager->setup(); + networkManager->setAPTimeout(Config.wifiAutoAP.timeout * 60 * 1000); // Convert minutes to milliseconds POWER_Utils::setup(); Utils::setupDisplay(); LoRa_Utils::setup(); @@ -137,7 +138,6 @@ void loop() { Utils::checkSleepByLowBatteryVoltage(1); SLEEP_Utils::startSleeping(); } else { - WIFI_Utils::checkAutoAPTimeout(); networkManager->loop(); if (isUpdatingOTA) { diff --git a/src/wifi_utils.cpp b/src/wifi_utils.cpp index ca7efa6..5fabf77 100644 --- a/src/wifi_utils.cpp +++ b/src/wifi_utils.cpp @@ -34,7 +34,6 @@ extern WiFi_AP *currentWiFi; extern bool backupDigiMode; extern uint32_t lastServerCheck; -uint32_t WiFiAutoAPTime = millis(); uint8_t wifiCounter = 0; uint32_t lastBackupDigiTime = millis(); uint32_t lastWiFiCheck = 0; @@ -83,7 +82,6 @@ namespace WIFI_Utils { void startAutoAP() { displayShow("", " Starting Auto AP", " Please connect to it " , " loading ...", 1000); networkManager->setupAP(Config.callsign + "-AP", Config.wifiAutoAP.password); - WiFiAutoAPTime = millis(); } void startWiFi() { @@ -127,24 +125,6 @@ namespace WIFI_Utils { } } - void checkAutoAPTimeout() { - if (networkManager->isWifiAPActive() && Config.wifiAutoAP.timeout > 0) { - if (WiFi.softAPgetStationNum() > 0) { - WiFiAutoAPTime = 0; - } else { - if (WiFiAutoAPTime == 0) { - WiFiAutoAPTime = millis(); - } else if ((millis() - WiFiAutoAPTime) > Config.wifiAutoAP.timeout * 60 * 1000) { - Serial.println("Stopping auto AP"); - - networkManager->disableAP(); - - Serial.println("Auto AP stopped (timeout)"); - } - } - } - } - void setup() { if (Config.digi.ecoMode == 0) startWiFi(); btStop(); From b0d441a519384aae001f05853ec484769cbaef4e Mon Sep 17 00:00:00 2001 From: Petr Kracik Date: Thu, 15 Jan 2026 00:04:07 +0100 Subject: [PATCH 19/24] Use setHostname from network manager --- src/LoRa_APRS_iGate.cpp | 1 + src/wifi_utils.cpp | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/LoRa_APRS_iGate.cpp b/src/LoRa_APRS_iGate.cpp index 670b1f5..8c72690 100644 --- a/src/LoRa_APRS_iGate.cpp +++ b/src/LoRa_APRS_iGate.cpp @@ -107,6 +107,7 @@ void setup() { networkManager = new NetworkManager(); networkManager->setup(); networkManager->setAPTimeout(Config.wifiAutoAP.timeout * 60 * 1000); // Convert minutes to milliseconds + networkManager->setHostName("iGATE-" + Config.callsign); POWER_Utils::setup(); Utils::setupDisplay(); LoRa_Utils::setup(); diff --git a/src/wifi_utils.cpp b/src/wifi_utils.cpp index 5fabf77..dd78741 100644 --- a/src/wifi_utils.cpp +++ b/src/wifi_utils.cpp @@ -91,9 +91,6 @@ namespace WIFI_Utils { return; } - String hostName = "iGATE-" + Config.callsign; - WiFi.setHostname(hostName.c_str()); - // TODO: Create generic multi-SSID support in Network Manager while (!networkManager->isWiFiConnected()) { displayShow("", "Connecting to WiFi:", "", currentWiFi->ssid + " ...", 0); From 9775c601bb2861b55b84bbfd0cffe94b15d5956d Mon Sep 17 00:00:00 2001 From: Petr Kracik Date: Thu, 5 Mar 2026 23:31:07 +0100 Subject: [PATCH 20/24] Wifi utils add multiple SSID --- src/LoRa_APRS_iGate.cpp | 4 ---- src/wifi_utils.cpp | 33 ++++++++++++++++----------------- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/src/LoRa_APRS_iGate.cpp b/src/LoRa_APRS_iGate.cpp index 8c72690..5a60d22 100644 --- a/src/LoRa_APRS_iGate.cpp +++ b/src/LoRa_APRS_iGate.cpp @@ -82,10 +82,6 @@ WiFiClient mqttClient; NetworkManager *networkManager; -uint8_t myWiFiAPIndex = 0; -int myWiFiAPSize = Config.wifiAPs.size(); -WiFi_AP *currentWiFi = &Config.wifiAPs[myWiFiAPIndex]; - bool isUpdatingOTA = false; uint32_t lastBatteryCheck = 0; diff --git a/src/wifi_utils.cpp b/src/wifi_utils.cpp index dd78741..1393e96 100644 --- a/src/wifi_utils.cpp +++ b/src/wifi_utils.cpp @@ -28,9 +28,6 @@ extern Configuration Config; extern NetworkManager *networkManager; -extern uint8_t myWiFiAPIndex; -extern int myWiFiAPSize; -extern WiFi_AP *currentWiFi; extern bool backupDigiMode; extern uint32_t lastServerCheck; @@ -85,25 +82,27 @@ namespace WIFI_Utils { } void startWiFi() { - if (currentWiFi->ssid.isEmpty()) { + bool hasNetworks = false; + + networkManager->clearWiFiNetworks(); + for (size_t i = 0; i < Config.wifiAPs.size(); i++) { + const WiFi_AP& wifiAP = Config.wifiAPs[i]; + if (wifiAP.ssid.isEmpty()) { + continue; + } + + hasNetworks = true; + networkManager->addWiFiNetwork(wifiAP.ssid, wifiAP.password); + } + + if (!hasNetworks) { Serial.println("WiFi SSID not set! Starting Auto AP"); startAutoAP(); return; } - // TODO: Create generic multi-SSID support in Network Manager - while (!networkManager->isWiFiConnected()) { - displayShow("", "Connecting to WiFi:", "", currentWiFi->ssid + " ...", 0); - networkManager->disconnectWiFi(); - networkManager->connectWiFi(currentWiFi->ssid, currentWiFi->password); - - if(myWiFiAPIndex >= (myWiFiAPSize - 1)) { - break; - } - - myWiFiAPIndex++; - currentWiFi = &Config.wifiAPs[myWiFiAPIndex]; - } + displayShow("", "Connecting to WiFi:", "", " loading ...", 0); + networkManager->connectWiFi(); #ifdef INTERNAL_LED_PIN digitalWrite(INTERNAL_LED_PIN, LOW); From d8b658df30024ae7f5dd1a3b57b8bbfd1dca6682 Mon Sep 17 00:00:00 2001 From: Petr Kracik Date: Fri, 30 Jan 2026 21:31:42 +0100 Subject: [PATCH 21/24] Prepare AutoAP enable/disable --- data_embed/index.html | 94 +++++++++++++++++++++++++---------------- data_embed/script.js | 14 ++++++ include/configuration.h | 1 + src/configuration.cpp | 6 ++- src/web_utils.cpp | 2 +- 5 files changed, 79 insertions(+), 38 deletions(-) diff --git a/data_embed/index.html b/data_embed/index.html index 611dc07..0c4ab20 100644 --- a/data_embed/index.html +++ b/data_embed/index.html @@ -1853,46 +1853,68 @@
-
- -
+
+
-
-
-
- -
- - minutesEnable Auto AP
- Set to 0 if you don't - want WiFi AP to stop. + Create WiFi AP when no network is available +
+
+
+
+
+
+
+ +
+ +
+
+
+ +
+ + minutes +
+ Set to 0 if you don't + want WiFi AP to stop. +
diff --git a/data_embed/script.js b/data_embed/script.js index e0c26fa..dab331f 100644 --- a/data_embed/script.js +++ b/data_embed/script.js @@ -237,8 +237,10 @@ function loadSettings(settings) { RebootModeTime.disabled = !RebootModeCheckbox.check; // WiFi Auto AP + document.getElementById("wifi.autoAP.enabled").checked = settings.wifi.autoAP.enabled; document.getElementById("wifi.autoAP.password").value = settings.wifi.autoAP.password; document.getElementById("wifi.autoAP.timeout").value = settings.wifi.autoAP.timeout; + toggleWiFiAutoAPFields(); // OTA document.getElementById("ota.username").value = settings.ota.username; @@ -432,6 +434,18 @@ WebadminCheckbox.addEventListener("change", function () { WebadminPassword.disabled = !this.checked; }); +// WiFi Auto AP Switches +const WiFiAutoAPCheckbox = document.querySelector('input[name="wifi.autoAP.enabled"]'); +WiFiAutoAPCheckbox.addEventListener("change", function () { + toggleWiFiAutoAPFields(); +}); + +function toggleWiFiAutoAPFields() { + const isEnabled = WiFiAutoAPCheckbox.checked; + const autoAPConfig = document.getElementById('wifi-autoap-config'); + if (autoAPConfig) autoAPConfig.style.display = isEnabled ? 'block' : 'none'; +} + document.querySelector(".new button").addEventListener("click", function () { const networksContainer = document.querySelector(".list-networks"); diff --git a/include/configuration.h b/include/configuration.h index abf5cc7..38080c3 100644 --- a/include/configuration.h +++ b/include/configuration.h @@ -32,6 +32,7 @@ public: class WiFi_Auto_AP { public: + bool enabled; // Enable Auto AP String password; int timeout; }; diff --git a/src/configuration.cpp b/src/configuration.cpp index 4ffb2a6..e50eef6 100644 --- a/src/configuration.cpp +++ b/src/configuration.cpp @@ -47,6 +47,7 @@ bool Configuration::writeFile() { data["other"]["startupDelay"] = startupDelay; + data["wifi"]["autoAP"]["enabled"] = wifiAutoAP.enabled; data["wifi"]["autoAP"]["password"] = wifiAutoAP.password; data["wifi"]["autoAP"]["timeout"] = wifiAutoAP.timeout; @@ -214,8 +215,10 @@ bool Configuration::readFile() { if (!data["other"].containsKey("startupDelay")) needsRewrite = true; startupDelay = data["other"]["startupDelay"] | 0; - if (!data["wifi"]["autoAP"].containsKey("password") || + if (!data["wifi"]["autoAP"].containsKey("enabled") || + !data["wifi"]["autoAP"].containsKey("password") || !data["wifi"]["autoAP"].containsKey("timeout")) needsRewrite = true; + wifiAutoAP.enabled = data["wifi"]["autoAP"]["enabled"] | true; wifiAutoAP.password = data["wifi"]["autoAP"]["password"] | "1234567890"; wifiAutoAP.timeout = data["wifi"]["autoAP"]["timeout"] | 10; @@ -446,6 +449,7 @@ void Configuration::setDefaultValues() { startupDelay = 0; + wifiAutoAP.enabled = true; wifiAutoAP.password = "1234567890"; wifiAutoAP.timeout = 10; diff --git a/src/web_utils.cpp b/src/web_utils.cpp index 6197b37..8eebfc2 100644 --- a/src/web_utils.cpp +++ b/src/web_utils.cpp @@ -161,7 +161,7 @@ namespace WEB_Utils { Config.callsign = getParamStringSafe("callsign", Config.callsign); Config.tacticalCallsign = getParamStringSafe("tacticalCallsign", Config.tacticalCallsign); - + Config.wifiAutoAP.enabled = request->hasParam("wifi.autoAP.enabled", true); Config.wifiAutoAP.password = getParamStringSafe("wifi.autoAP.password", Config.wifiAutoAP.password); Config.wifiAutoAP.timeout = getParamIntSafe("wifi.autoAP.timeout", Config.wifiAutoAP.timeout); From e241321abc0d2048b13a95068e0698ba46ccda4e Mon Sep 17 00:00:00 2001 From: Petr Kracik Date: Thu, 5 Mar 2026 23:36:28 +0100 Subject: [PATCH 22/24] Use AutoAP --- src/LoRa_APRS_iGate.cpp | 4 +++- src/wifi_utils.cpp | 19 +++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/LoRa_APRS_iGate.cpp b/src/LoRa_APRS_iGate.cpp index 5a60d22..14fbe23 100644 --- a/src/LoRa_APRS_iGate.cpp +++ b/src/LoRa_APRS_iGate.cpp @@ -102,7 +102,9 @@ void setup() { Serial.begin(115200); networkManager = new NetworkManager(); networkManager->setup(); - networkManager->setAPTimeout(Config.wifiAutoAP.timeout * 60 * 1000); // Convert minutes to milliseconds + if (Config.wifiAutoAP.enabled) { + networkManager->setAPTimeout(Config.wifiAutoAP.timeout * 60 * 1000); // Convert minutes to milliseconds + } networkManager->setHostName("iGATE-" + Config.callsign); POWER_Utils::setup(); Utils::setupDisplay(); diff --git a/src/wifi_utils.cpp b/src/wifi_utils.cpp index 1393e96..620f6d6 100644 --- a/src/wifi_utils.cpp +++ b/src/wifi_utils.cpp @@ -96,8 +96,11 @@ namespace WIFI_Utils { } if (!hasNetworks) { - Serial.println("WiFi SSID not set! Starting Auto AP"); - startAutoAP(); + Serial.println("WiFi SSID not set!"); + if (Config.wifiAutoAP.enabled) { + Serial.println("Starting AP fallback..."); + startAutoAP(); + } return; } @@ -114,10 +117,14 @@ namespace WIFI_Utils { Serial.println(networkManager->getWiFimacAddress()); displayShow("", " Connected!!", "" , " loading ...", 1000); } else { - Serial.println("\nNot connected to WiFi! Starting Auto AP"); - displayShow("", " WiFi Not Connected!", "" , " loading ...", 1000); - - startAutoAP(); + Serial.println("\nNot connected to WiFi!"); + if (Config.wifiAutoAP.enabled) { + Serial.println("Starting AP fallback..."); + displayShow("", " WiFi Not Connected!", "" , " loading ...", 1000); + startAutoAP(); + } else { + displayShow("", " WiFi Not Connected!", "" , " loading ...", 1000); + } } } From 8bca896e31796b90fadce6d801b2a7049f319844 Mon Sep 17 00:00:00 2001 From: Petr Kracik Date: Thu, 5 Mar 2026 23:39:41 +0100 Subject: [PATCH 23/24] Utils: Added Ethernet IP --- src/utils.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/utils.cpp b/src/utils.cpp index b0d618f..65b5292 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -104,6 +104,8 @@ namespace Utils { String getLocalIP() { if (Config.digi.ecoMode == 1 || Config.digi.ecoMode == 2) { return "** WiFi AP Killed **"; + } else if (networkManager->isEthernetConnected()) { + return "LAN: " + networkManager->getEthernetIP().toString(); } else if (!networkManager->isWiFiConnected() && networkManager->isWifiAPActive()) { return "IP : " + networkManager->getWiFiAPIP().toString(); } else if (backupDigiMode) { From 37e3a2f831d241184deb8c50f16a3b4478df077c Mon Sep 17 00:00:00 2001 From: Petr Kracik Date: Fri, 6 Mar 2026 00:02:40 +0100 Subject: [PATCH 24/24] Wifi: use hasWifiNetworks --- src/wifi_utils.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/wifi_utils.cpp b/src/wifi_utils.cpp index 620f6d6..a249676 100644 --- a/src/wifi_utils.cpp +++ b/src/wifi_utils.cpp @@ -40,6 +40,11 @@ namespace WIFI_Utils { void checkWiFi() { if (Config.digi.ecoMode != 0) return; + + if (!networkManager->hasWiFiNetworks()) { + return; + } + uint32_t currentTime = millis(); if (backupDigiMode) { @@ -82,8 +87,6 @@ namespace WIFI_Utils { } void startWiFi() { - bool hasNetworks = false; - networkManager->clearWiFiNetworks(); for (size_t i = 0; i < Config.wifiAPs.size(); i++) { const WiFi_AP& wifiAP = Config.wifiAPs[i]; @@ -91,11 +94,10 @@ namespace WIFI_Utils { continue; } - hasNetworks = true; networkManager->addWiFiNetwork(wifiAP.ssid, wifiAP.password); } - if (!hasNetworks) { + if (!networkManager->hasWiFiNetworks()) { Serial.println("WiFi SSID not set!"); if (Config.wifiAutoAP.enabled) { Serial.println("Starting AP fallback...");