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; +}