/* * EMS-ESP - https://github.com/emsesp/EMS-ESP * Copyright 2020-2025 emsesp.org * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef EMSESP_NETWORK_H_ #define EMSESP_NETWORK_H_ #ifndef EMSESP_STANDALONE #include #include #include #include #include #include #endif #include #include #include namespace emsesp { #define NETWORK_RECONNECTION_DELAY_SHORT 5000 // 5 seconds #ifndef EMSESP_DEBUG #define NETWORK_RECONNECTION_DELAY_LONG 60000 // 1 minute #else #define NETWORK_RECONNECTION_DELAY_LONG 10000 // 10 seconds - for debugging #endif #define MAX_NETWORK_RECONNECTION_ATTEMPTS 3 // maximum number of network reconnection attempts before going to AP fallback #define DNS_PORT 53 // dns server port for captive portal // copied from Tasmota #if CONFIG_IDF_TARGET_ESP32S2 #define MAX_TX_PWR_DBM_11b 195 #define MAX_TX_PWR_DBM_54g 150 #define MAX_TX_PWR_DBM_n 130 #define WIFI_SENSITIVITY_11b -880 #define WIFI_SENSITIVITY_54g -750 #define WIFI_SENSITIVITY_n -720 #elif CONFIG_IDF_TARGET_ESP32S3 #define MAX_TX_PWR_DBM_11b 210 #define MAX_TX_PWR_DBM_54g 190 #define MAX_TX_PWR_DBM_n 185 #define WIFI_SENSITIVITY_11b -880 #define WIFI_SENSITIVITY_54g -760 #define WIFI_SENSITIVITY_n -720 #elif CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 #define MAX_TX_PWR_DBM_11b 210 #define MAX_TX_PWR_DBM_54g 190 #define MAX_TX_PWR_DBM_n 185 #define WIFI_SENSITIVITY_11b -880 #define WIFI_SENSITIVITY_54g -760 #define WIFI_SENSITIVITY_n -730 #else #define MAX_TX_PWR_DBM_11b 195 #define MAX_TX_PWR_DBM_54g 160 #define MAX_TX_PWR_DBM_n 140 #define WIFI_SENSITIVITY_11b -880 #define WIFI_SENSITIVITY_54g -750 #define WIFI_SENSITIVITY_n -700 #endif // which physical interface we are currently using for the active network connection. // Mapped from the esp-netif description string returned by esp_netif_get_desc(): "sta" -> WIFI, // "ap" -> AP, "eth"/"eth1"/"eth2"/... enum class NetIface : uint8_t { NONE = 0, // 0 WIFI, // 1 ETHERNET, // 2 AP, // 3 }; enum class NetPhase : uint8_t { ETHERNET = 0, WIFI = 1, AP = 2, }; class Network { public: void begin(); void loop(); uint32_t network_ip() const { return network_ip_; } NetIface network_iface() const { return network_iface_; } bool ethernet_connected() const { return network_iface_ == NetIface::ETHERNET && network_ip_ != 0; } bool wifi_connected() const { return network_iface_ == NetIface::WIFI && network_ip_ != 0; } bool ap_connected() const { return network_iface_ == NetIface::AP && network_ip_ != 0; } bool network_connected() const { return ethernet_connected() || wifi_connected(); // don't include AP here } bool has_ipv6() const { return has_ipv6_ && (network_iface_ == NetIface::WIFI || network_iface_ == NetIface::ETHERNET); } uint16_t getNetworkReconnects() { return reconnect_count_; } std::string getLocalIP() const; std::string getMacAddress() const; uint8_t getStationNum() const; void reconnect(); // map a netif description string (from esp_netif_get_desc) to a NetIface static NetIface iface_from_desc(const char * desc) { if (!desc) { return NetIface::NONE; } if (strcmp(desc, "sta") == 0) { return NetIface::WIFI; } if (strcmp(desc, "ap") == 0) { return NetIface::AP; } // any "eth*" (eth, eth0, eth1, ...) is treated as Ethernet if (strncmp(desc, "eth", 3) == 0) { return NetIface::ETHERNET; } return NetIface::NONE; } static const char * network_iface_to_string(NetIface iface) { switch (iface) { case NetIface::WIFI: return "WiFi"; case NetIface::ETHERNET: return "Ethernet"; case NetIface::AP: return "AP"; case NetIface::NONE: default: return "None"; } return "unknown"; } private: static uuid::log::Logger logger_; void findNetworks(); void checkConnection(); void startmDNS() const; bool formatBSSID(const String & bssid, uint8_t (&mac)[6]); void startAP(); void startWIFI(); void startEthernet(); void setWiFiPower(uint8_t tx_power); const char * disconnectReason(uint8_t code); void stopAP(); NetPhase initialPhase() const; #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-private-field" #endif unsigned long lastConnectionAttempt_ = 0; uint16_t reconnect_count_ = 0; // number of network reconnects uint32_t network_ip_ = 0; NetIface network_iface_ = NetIface::NONE; bool has_ipv6_ = false; bool juststopped_ = false; volatile uint8_t last_disconnect_reason_ = 0; uint16_t connect_retry_ = 0; // number of network re-connection attempts volatile bool wifi_connect_pending_ = false; volatile bool ethernet_connect_pending_ = false; NetPhase phase_ = NetPhase::ETHERNET; bool wifi_events_registered_ = false; // ensure WiFi.onEvent() handlers are registered only once across begin()/reconnect() cycles bool wifi_ever_connected_ = false; // set true once we've successfully obtained an IP // Network and AP settings bool enableMDNS_; bool staticIPConfig_; IPAddress localIP_; IPAddress gatewayIP_; IPAddress subnetMask_; IPAddress dnsIP1_; IPAddress dnsIP2_; String hostname_; String ssid_; String password_; bool bandwidth20_; bool nosleep_; uint8_t tx_power_; String bssid_; uint8_t phy_type_; int8_t eth_power_; uint8_t eth_phy_addr_; uint8_t eth_clock_mode_; // AP settings uint8_t ap_provisionMode_; String ap_ssid_; String ap_password_; uint8_t ap_channel_; bool ap_ssid_hidden_; uint8_t ap_max_clients_; IPAddress ap_localIP_; IPAddress ap_gatewayIP_; IPAddress ap_subnetMask_; #if defined(__clang__) #pragma clang diagnostic pop #endif // for the captive portal in AP mode #ifndef EMSESP_STANDALONE DNSServer * ap_dnsServer_ = nullptr; #endif }; } // namespace emsesp #endif