mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-27 19:57:38 +00:00
Merge branch 'mega' of https://github.com/letscontrolit/ESPEasy into bugfix/Fixes-for-release-may-2026
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino":{
|
||||
"ldscript": "esp32s2_out.ld",
|
||||
"memory_type": "dio_qspi"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": "-DARDUINO_TASMOTA -DBOARD_HAS_PSRAM -DESP32_8M -DESP32S2 -DCONFIG_IDF_TARGET_ESP32S2=1 -DUSE_USB_CDC_CONSOLE -DARDUINO_USB_CDC_ON_BOOT=1 -DCONFIG_TINYUSB_CDC_ENABLED=1",
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "dio",
|
||||
"mcu": "esp32s2",
|
||||
"variant": "esp32s2",
|
||||
"filesystem": "littlefs",
|
||||
"partitions": "boards/partitions/esp32_partition_app3520k_spiffs1088k.csv"
|
||||
},
|
||||
"connectivity": [
|
||||
"wifi"
|
||||
],
|
||||
"debug": {
|
||||
"openocd_target": "esp32s2.cfg"
|
||||
},
|
||||
"frameworks": [
|
||||
"espidf",
|
||||
"arduino"
|
||||
],
|
||||
"name": "Espressif Generic ESP32-S2 USB CDC 8M Flash ESPEasy 3520k Code/OTA 1088k FS",
|
||||
"upload": {
|
||||
"flash_size": "8MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 4194304,
|
||||
"before_reset": "usb_reset",
|
||||
"after_reset": "hard_reset",
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 460800
|
||||
},
|
||||
"url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-saola-1-v1.2.html",
|
||||
"vendor": "Espressif"
|
||||
}
|
||||
@@ -10,7 +10,12 @@
|
||||
|
||||
Port_ESPEasySerial_HardwareSerial_t::Port_ESPEasySerial_HardwareSerial_t() {}
|
||||
|
||||
Port_ESPEasySerial_HardwareSerial_t::~Port_ESPEasySerial_HardwareSerial_t() {}
|
||||
Port_ESPEasySerial_HardwareSerial_t::~Port_ESPEasySerial_HardwareSerial_t() {
|
||||
if (_serial != nullptr) {
|
||||
_serial->flush();
|
||||
_serial->end();
|
||||
}
|
||||
}
|
||||
|
||||
void Port_ESPEasySerial_HardwareSerial_t::resetConfig(const ESPEasySerialConfig& config)
|
||||
{
|
||||
@@ -153,7 +158,7 @@ void Port_ESPEasySerial_HardwareSerial_t::begin(unsigned long baud)
|
||||
}
|
||||
|
||||
if (_config.txBuffSize > 256) {
|
||||
_config.txBuffSize = _serial->setRxBufferSize(_config.txBuffSize);
|
||||
_config.txBuffSize = _serial->setTxBufferSize(_config.txBuffSize);
|
||||
}
|
||||
|
||||
_serial->begin(baud, _config.config, _config.receivePin, _config.transmitPin, _config.inverse_logic);
|
||||
|
||||
@@ -128,6 +128,7 @@ Port_ESPEasySerial_USBCDC_t::Port_ESPEasySerial_USBCDC_t(const ESPEasySerialConf
|
||||
Port_ESPEasySerial_USBCDC_t::~Port_ESPEasySerial_USBCDC_t()
|
||||
{
|
||||
if (_serial != nullptr) {
|
||||
_serial->flush();
|
||||
_serial->end();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,8 +187,11 @@ extra_scripts = ${esp82xx_common.extra_scripts}
|
||||
;platform = https://github.com/Jason2866/platform-espressif32.git#IDF6
|
||||
;platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2403-0020-6.0/framework-arduinoespressif32-release_v6.0-1a97ddaa.tar.xz
|
||||
|
||||
platform = https://github.com/Jason2866/platform-espressif32.git#Arduino/IDF55_gcc152
|
||||
platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1204-1214-5.5/framework-arduinoespressif32-release_v5.5-f2a3fa2b.tar.xz
|
||||
;platform = https://github.com/Jason2866/platform-espressif32.git#Arduino/IDF55_gcc152
|
||||
;platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2904-2115-5.5/framework-arduinoespressif32-release_v5.5-f2a3fa2b.tar.xz
|
||||
|
||||
platform = https://github.com/tasmota/platform-espressif32/releases/download/2026.04.50/platform-espressif32.zip
|
||||
platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/0405-1702-5.5/framework-arduinoespressif32-release_v5.5-f2a3fa2b.tar.xz
|
||||
|
||||
custom_remove_include = true
|
||||
|
||||
|
||||
@@ -148,3 +148,14 @@ board = esp32s2cdc
|
||||
build_flags = ${esp32s2_common_LittleFS.build_flags}
|
||||
-D PLUGIN_CLIMATE_B_COLLECTION
|
||||
|
||||
|
||||
[env:max_ESP32s2_8M1M]
|
||||
extends = esp32s2_common_LittleFS
|
||||
board = esp32s2cdc_8M
|
||||
build_flags = ${esp32s2_common_LittleFS.build_flags}
|
||||
-DFEATURE_ARDUINO_OTA=1
|
||||
-DPLUGIN_BUILD_MAX_ESP32
|
||||
-DPLUGIN_BUILD_IR_EXTENDED
|
||||
-D ST7789_EXTRA_INIT=1
|
||||
-D P116_EXTRA_ST7789=1
|
||||
extra_scripts = ${esp32s2_common_LittleFS.extra_scripts}
|
||||
|
||||
+20
-20
@@ -328,26 +328,26 @@ lib_ignore = ${normal_beta_2ndheap.lib_ignore}
|
||||
|
||||
; NORMAL: 16M version --- LittleFS --------------
|
||||
; LittleFS is determined by using "LittleFS" in the pio env name
|
||||
[env:normal_beta_ESP8266_16M_LittleFS]
|
||||
extends = esp8266_16M
|
||||
platform = ${normal_beta.platform}
|
||||
platform_packages = ${normal_beta.platform_packages}
|
||||
build_flags = ${normal_beta.build_flags}
|
||||
${esp8266_16M.build_flags}
|
||||
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22y
|
||||
lib_ignore = ESP32_ping
|
||||
ESP32WebServer
|
||||
ESP32HTTPUpdateServer
|
||||
ServoESP32
|
||||
${no_ir.lib_ignore}
|
||||
TinyWireM
|
||||
ESP8266SdFat
|
||||
SD(esp8266)
|
||||
SD
|
||||
SDFS
|
||||
ArduinoOTA
|
||||
ESP8266mDNS
|
||||
I2C AXP192 Power management
|
||||
;[env:normal_beta_ESP8266_16M_LittleFS]
|
||||
;extends = esp8266_16M
|
||||
;platform = ${normal_beta.platform}
|
||||
;platform_packages = ${normal_beta.platform_packages}
|
||||
;build_flags = ${normal_beta.build_flags}
|
||||
; ${esp8266_16M.build_flags}
|
||||
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22y
|
||||
;lib_ignore = ESP32_ping
|
||||
; ESP32WebServer
|
||||
; ESP32HTTPUpdateServer
|
||||
; ServoESP32
|
||||
; ${no_ir.lib_ignore}
|
||||
; TinyWireM
|
||||
; ESP8266SdFat
|
||||
; SD(esp8266)
|
||||
; SD
|
||||
; SDFS
|
||||
; ArduinoOTA
|
||||
; ESP8266mDNS
|
||||
; I2C AXP192 Power management
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "../../../src/DataStructs/ESPEasy_EventStruct.h"
|
||||
#include "../../../src/Helpers/StringConverter.h"
|
||||
#include "../../../src/Helpers/Misc.h"
|
||||
#include "../../../src/Helpers/Networking.h"
|
||||
#if FEATURE_STORE_NETWORK_INTERFACE_SETTINGS
|
||||
# include "../../../src/Helpers/_ESPEasy_key_value_store.h"
|
||||
#include "../_NWPlugin_Helper.h"
|
||||
@@ -65,6 +67,15 @@ bool NWPluginData_base::isDefaultRoute() const {
|
||||
|
||||
#endif
|
||||
|
||||
bool NWPluginData_base::getStaticIPAddresses(IPAddress & ip, IPAddress & gateway, IPAddress & subnetmask, IPAddress & dns ) const
|
||||
{
|
||||
getStaticIPAddress(IPAddressType::IP, ip);
|
||||
getStaticIPAddress(IPAddressType::Gateway, gateway);
|
||||
getStaticIPAddress(IPAddressType::Subnetmask, subnetmask);
|
||||
getStaticIPAddress(IPAddressType::DNS, dns);
|
||||
|
||||
return IPAddressSet(ip) && IPAddressSet(gateway) && IPAddressSet(subnetmask);
|
||||
}
|
||||
|
||||
bool NWPluginData_base::hasPluginStats() const {
|
||||
#if FEATURE_NETWORK_STATS
|
||||
@@ -333,7 +344,7 @@ bool NWPluginData_base::handle_priority_route_changed()
|
||||
for (size_t i = 0; i < NR_ELEMENTS(cache->_dns_cache); ++i) {
|
||||
auto tmp = _netif->dnsIP(i);
|
||||
|
||||
if ((cache->_dns_cache[i] != INADDR_NONE) && (cache->_dns_cache[i] != tmp)) {
|
||||
if (valid_DNS_address(cache->_dns_cache[i]) && (cache->_dns_cache[i] != tmp)) {
|
||||
addLog(LOG_LEVEL_INFO, strformat(
|
||||
F("%s: Restore cached DNS server %d from %s to %s"),
|
||||
_netif->desc(),
|
||||
@@ -409,7 +420,7 @@ bool NWPluginData_base::_restore_DNS_cache()
|
||||
for (size_t i = 0; i < NR_ELEMENTS(cache->_dns_cache); ++i) {
|
||||
auto tmp = _netif->dnsIP(i);
|
||||
|
||||
if ((cache->_dns_cache[i] != INADDR_NONE) && (cache->_dns_cache[i] != tmp)) {
|
||||
if (valid_DNS_address(cache->_dns_cache[i]) && (cache->_dns_cache[i] != tmp)) {
|
||||
addLog(LOG_LEVEL_INFO, strformat(
|
||||
F("NW%03%d: Restore cached DNS server %d from %s to %s"),
|
||||
_nw_data_pluginID,
|
||||
|
||||
@@ -33,6 +33,13 @@ struct NWPluginData_base {
|
||||
#endif // ifdef ESP32
|
||||
);
|
||||
|
||||
enum class IPAddressType {
|
||||
IP,
|
||||
Gateway,
|
||||
Subnetmask,
|
||||
DNS
|
||||
};
|
||||
|
||||
virtual ~NWPluginData_base();
|
||||
|
||||
virtual bool init(EventStruct *event) = 0;
|
||||
@@ -110,6 +117,10 @@ struct NWPluginData_base {
|
||||
|
||||
virtual NWPluginData_static_runtime* getNWPluginData_static_runtime() = 0;
|
||||
|
||||
virtual bool getStaticIPAddress(IPAddressType addressType, IPAddress & ip) const = 0;
|
||||
|
||||
bool getStaticIPAddresses(IPAddress & ip, IPAddress & gateway, IPAddress & subnetmask, IPAddress & dns ) const;
|
||||
|
||||
|
||||
#if FEATURE_NETWORK_STATS
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "../../../src/Globals/EventQueue.h"
|
||||
#include "../../../src/Globals/Settings.h"
|
||||
|
||||
#include "../../../src/Helpers/Networking.h"
|
||||
#include "../../../src/Helpers/NetworkStatusLED.h"
|
||||
#include "../../../src/Helpers/StringConverter.h"
|
||||
|
||||
@@ -98,12 +99,12 @@ bool NWPluginData_static_runtime::getTrafficCount(TX_RX_traffic_count& traffic)
|
||||
|
||||
void NWPluginData_static_runtime::clear(networkIndex_t networkIndex)
|
||||
{
|
||||
_connectedStats.clear();
|
||||
_gotIPStats.clear();
|
||||
_connectedStats.reset();
|
||||
_gotIPStats.reset();
|
||||
#if FEATURE_USE_IPV6
|
||||
_gotIP6Stats.clear();
|
||||
_gotIP6Stats.reset();
|
||||
#endif
|
||||
_operationalStats.clear();
|
||||
_operationalStats.reset();
|
||||
#if FEATURE_NETWORK_TRAFFIC_COUNT
|
||||
|
||||
if (_netif) {
|
||||
@@ -125,7 +126,7 @@ void NWPluginData_static_runtime::clear(networkIndex_t networkIndex)
|
||||
|
||||
_connectionFailures = 0;
|
||||
|
||||
// FIXME TD-er: Should also clear dns cache?
|
||||
// FIXME TD-er: Should also clear dns cache and/or static IP?
|
||||
}
|
||||
|
||||
void NWPluginData_static_runtime::processEvent_and_clear()
|
||||
@@ -171,7 +172,7 @@ void NWPluginData_static_runtime::processEvents()
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO) && _netif) {
|
||||
auto ip = _netif->localIP();
|
||||
|
||||
if (ip != INADDR_NONE) {
|
||||
if (IPAddressSet(ip)) {
|
||||
addLog(LOG_LEVEL_INFO, strformat(
|
||||
F("%s: Got IP: %s/%d GW: %s"),
|
||||
_eventInterfaceName.c_str(),
|
||||
@@ -267,17 +268,17 @@ void NWPluginData_static_runtime::processEvents()
|
||||
{
|
||||
if (_operationalStats.isOn()) {
|
||||
if (_isAP) {
|
||||
eventQueue.add(F("WiFi#APmodeConnected"));
|
||||
eventQueue.addDeDup(F("WiFi#APmodeConnected"));
|
||||
}
|
||||
else {
|
||||
eventQueue.add(concat(_eventInterfaceName, F("#Connected")));
|
||||
eventQueue.addDeDup(concat(_eventInterfaceName, F("#Connected")));
|
||||
}
|
||||
} else if (_operationalStats.isOff()) {
|
||||
if (_isAP) {
|
||||
eventQueue.add(F("WiFi#APmodeDisconnected"));
|
||||
eventQueue.addDeDup(F("WiFi#APmodeDisconnected"));
|
||||
}
|
||||
else {
|
||||
eventQueue.add(concat(_eventInterfaceName, F("#Disconnected")));
|
||||
eventQueue.addDeDup(concat(_eventInterfaceName, F("#Disconnected")));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -287,22 +288,31 @@ void NWPluginData_static_runtime::processEvents()
|
||||
if (_startStopStats.changedSinceLastCheck_and_clear() && Settings.UseRules) {
|
||||
if (_startStopStats.isOn()) {
|
||||
if (_isAP) {
|
||||
eventQueue.add(F("WiFi#APmodeEnabled"));
|
||||
eventQueue.addDeDup(F("WiFi#APmodeEnabled"));
|
||||
}
|
||||
else {
|
||||
eventQueue.add(concat(_eventInterfaceName, F("#Enabled")));
|
||||
eventQueue.addDeDup(concat(_eventInterfaceName, F("#Enabled")));
|
||||
}
|
||||
} else if (_startStopStats.isOff()) {
|
||||
if (_isAP) {
|
||||
eventQueue.add(F("WiFi#APmodeDisabled"));
|
||||
eventQueue.addDeDup(F("WiFi#APmodeDisabled"));
|
||||
}
|
||||
else {
|
||||
eventQueue.add(concat(_eventInterfaceName, F("#Disabled")));
|
||||
eventQueue.addDeDup(concat(_eventInterfaceName, F("#Disabled")));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NWPluginData_static_runtime::setStaticIP(const IPAddress & ip, const IPAddress & gateway, const IPAddress & subnetmask, const IPAddress & dns)
|
||||
{
|
||||
_useStaticIP = IPAddressSet(ip) && IPAddressSet(gateway) && IPAddressSet(subnetmask);
|
||||
_ip = ip;
|
||||
_gateway = gateway;
|
||||
_sn = subnetmask;
|
||||
_dns = dns;
|
||||
}
|
||||
|
||||
String NWPluginData_static_runtime::statusToString() const
|
||||
{
|
||||
String log;
|
||||
@@ -313,6 +323,7 @@ String NWPluginData_static_runtime::statusToString() const
|
||||
|
||||
if (hasIP()) {
|
||||
log += F("IP ");
|
||||
if (_useStaticIP) log += F("(static) ");
|
||||
}
|
||||
|
||||
if (operational()) {
|
||||
|
||||
@@ -127,6 +127,8 @@ struct NWPluginData_static_runtime {
|
||||
|
||||
void processEvents();
|
||||
|
||||
void setStaticIP(const IPAddress & ip, const IPAddress & gateway, const IPAddress & subnetmask, const IPAddress & dns);
|
||||
|
||||
// =============================================
|
||||
// OnOffTimers for keeping track of:
|
||||
// - start/stop of interface
|
||||
@@ -157,6 +159,9 @@ struct NWPluginData_static_runtime {
|
||||
bool _enableIPv6{}; // Cached enableIPv6 flag as it is being used from callbacks
|
||||
#endif
|
||||
|
||||
IPAddress _ip, _gateway, _sn, _dns;
|
||||
bool _useStaticIP{}; // Added to make sure we don't have to re-check IP from a callback
|
||||
|
||||
private:
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
# include "../ESPEasyNetwork.h"
|
||||
|
||||
# include "../../../src/Helpers/StringConverter.h"
|
||||
# include "../../../src/Helpers/Networking.h"
|
||||
# include "../../../src/Globals/Settings.h"
|
||||
|
||||
# include "../Globals/NetworkState.h"
|
||||
@@ -95,6 +96,16 @@ void NWPluginData_static_runtime::mark_start()
|
||||
|
||||
if (!_netif) { return; }
|
||||
|
||||
if (_useStaticIP) {
|
||||
_netif->config(
|
||||
_ip,
|
||||
_gateway,
|
||||
_sn,
|
||||
_dns);
|
||||
} else {
|
||||
_netif->config((uint32_t)0, (uint32_t)0, (uint32_t)0);
|
||||
}
|
||||
|
||||
const String hostname = strformat(
|
||||
F("%s-%s"),
|
||||
NetworkCreateRFCCompliantHostname().c_str(),
|
||||
@@ -147,11 +158,10 @@ void NWPluginData_static_runtime::mark_got_IP()
|
||||
|
||||
for (size_t i = 0; i < NR_ELEMENTS(_dns_cache); ++i) {
|
||||
auto tmp = _netif->dnsIP(i);
|
||||
|
||||
_dns_cache[i] = tmp; // Also set the 'empty' ones so we won't set left-over DNS server from when another interface was active.
|
||||
# if NW_PLUGIN_LOG_EVENTS
|
||||
|
||||
if ((tmp != INADDR_NONE) && loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
if (valid_DNS_address(tmp) && loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
addLog(LOG_LEVEL_INFO, strformat(
|
||||
F("%s: DNS Cache %d set to %s"),
|
||||
_eventInterfaceName.c_str(),
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
# include "../ESPEasyNetwork.h"
|
||||
# include "../../../src/Helpers/StringConverter.h"
|
||||
# include "../wifi/ESPEasyWifi.h"
|
||||
|
||||
namespace ESPEasy {
|
||||
namespace net {
|
||||
@@ -71,9 +72,23 @@ void NWPluginData_static_runtime::mark_lost_IP()
|
||||
|
||||
void NWPluginData_static_runtime::mark_begin_establish_connection()
|
||||
{
|
||||
_establishConnectStats.forceSet(true);
|
||||
_connectedStats.setOff();
|
||||
_operationalStats.setOff();
|
||||
|
||||
if (!_isAP) {
|
||||
ESPEasy::net::wifi::setUseStaticIP(_useStaticIP);
|
||||
if (_useStaticIP) {
|
||||
WiFi.config(
|
||||
_ip,
|
||||
_gateway,
|
||||
_sn,
|
||||
_dns);
|
||||
} else {
|
||||
WiFi.config((uint32_t)0, (uint32_t)0, (uint32_t)0);
|
||||
}
|
||||
}
|
||||
|
||||
_establishConnectStats.forceSet(true);
|
||||
WiFi.hostname(NetworkCreateRFCCompliantHostname().c_str());
|
||||
}
|
||||
|
||||
@@ -81,6 +96,10 @@ void NWPluginData_static_runtime::mark_connected()
|
||||
{
|
||||
_establishConnectStats.setOff();
|
||||
_connectedStats.setOn();
|
||||
if (_useStaticIP) {
|
||||
// Since we won't get an event stating we got an IP, we need to trigger it here
|
||||
mark_got_IP();
|
||||
}
|
||||
}
|
||||
|
||||
void NWPluginData_static_runtime::log_connected()
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "../../../src/Helpers/StringConverter.h"
|
||||
#include "../../../src/Helpers/StringGenerator_WiFi.h"
|
||||
|
||||
#include "../wifi/ESPEasyWifi.h"
|
||||
|
||||
#if defined(ESP8266)
|
||||
# include <ESP8266WiFi.h>
|
||||
#endif // if defined(ESP8266)
|
||||
@@ -73,15 +75,9 @@ WiFi_AP_Candidate::WiFi_AP_Candidate(uint8_t index_c, const String& ssid_c) :
|
||||
{
|
||||
_allBits = 0u;
|
||||
|
||||
const size_t ssid_length = ssid_c.length();
|
||||
|
||||
if ((ssid_length == 0) || equals(ssid_c, F("ssid"))) {
|
||||
return;
|
||||
if (validWiFiSSID(ssid_c)) {
|
||||
ssid = ssid_c;
|
||||
}
|
||||
|
||||
if (ssid_length > 32) { return; }
|
||||
|
||||
ssid = ssid_c;
|
||||
}
|
||||
|
||||
WiFi_AP_Candidate::WiFi_AP_Candidate(uint8_t networkItem) : index(0) {
|
||||
|
||||
@@ -79,14 +79,14 @@ String makeRFCCompliantName(const String& name, const char replaceChar, const ch
|
||||
return hostname;
|
||||
}
|
||||
|
||||
void CheckRunningServices() {
|
||||
void CheckRunningServices(bool force) {
|
||||
// First try to get the time, since that may be used in logs
|
||||
if (Settings.UseNTP() && (node_time.getTimeSource() > timeSource_t::NTP_time_source)) {
|
||||
node_time.lastNTPSyncTime_ms = 0;
|
||||
node_time.initTime();
|
||||
}
|
||||
#if FEATURE_ESPEASY_P2P
|
||||
updateUDPport(true);
|
||||
updateUDPport(force);
|
||||
#endif
|
||||
|
||||
#if FEATURE_WIFI
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "../../ESPEasy_common.h"
|
||||
|
||||
#include "../net/DataStructs/MAC_address.h"
|
||||
#include "../net/DataTypes/NetworkIndex.h"
|
||||
|
||||
#include <IPAddress.h>
|
||||
|
||||
@@ -23,6 +24,9 @@ namespace net {
|
||||
|
||||
void setNetworkMedium(NetworkMedium_t medium);
|
||||
|
||||
|
||||
ESPEasy::net::networkIndex_t getNetworkIndex_defaultNetwork();
|
||||
|
||||
// void NetworkConnectRelaxed();
|
||||
bool NetworkConnected(bool force = false);
|
||||
IPAddress NetworkLocalIP();
|
||||
@@ -63,7 +67,7 @@ MAC_address WifiSoftAPmacAddress();
|
||||
MAC_address WifiSTAmacAddress();
|
||||
#endif // if FEATURE_WIFI
|
||||
|
||||
void CheckRunningServices();
|
||||
void CheckRunningServices(bool force = false);
|
||||
|
||||
#if FEATURE_ETHERNET
|
||||
bool EthFullDuplex();
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
|
||||
#include "../net/ESPEasyNetwork.h"
|
||||
|
||||
#include "../../ESPEasy/net/Globals/NetworkState.h"
|
||||
#include "../net/Globals/NetworkState.h"
|
||||
#include "../net/eth/ESPEasyEth.h"
|
||||
#include "../net/Globals/NWPlugins.h"
|
||||
#include "../../src/ESPEasyCore/ESPEasy_Log.h"
|
||||
#include "../../src/Helpers/NetworkStatusLED.h"
|
||||
#include "../../src/Helpers/StringConverter.h"
|
||||
#include "../net/eth/ESPEasyEth.h"
|
||||
#include "../net/Globals/NWPlugins.h"
|
||||
#include "../../src/Globals/Settings.h"
|
||||
|
||||
|
||||
#include <NetworkManager.h>
|
||||
|
||||
@@ -116,13 +118,35 @@ NetworkInterface* getDefaultNonAP_interface()
|
||||
return network_if;
|
||||
}
|
||||
|
||||
ESPEasy::net::networkIndex_t getNetworkIndex_defaultNetwork()
|
||||
{
|
||||
auto network_if = getDefaultNonAP_interface();
|
||||
if (network_if == nullptr) {
|
||||
return ESPEasy::net::INVALID_NETWORK_INDEX;
|
||||
}
|
||||
for (ESPEasy::net::networkIndex_t x = 0; x < NETWORK_MAX; ++x) {
|
||||
if (Settings.getNetworkEnabled(x)) {
|
||||
struct EventStruct TempEvent;
|
||||
TempEvent.NetworkIndex = x;
|
||||
String str;
|
||||
|
||||
if (ESPEasy::net::NWPluginCall(NWPlugin::Function::NWPLUGIN_GET_INTERFACE, &TempEvent, str))
|
||||
{
|
||||
if (TempEvent.networkInterface->netif() == network_if->netif()) {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ESPEasy::net::INVALID_NETWORK_INDEX;
|
||||
}
|
||||
|
||||
bool NetworkConnected(bool force) {
|
||||
static bool last_result = false;
|
||||
static uint32_t last_check_millis = 0;
|
||||
|
||||
if (force || (timePassedSince(last_check_millis) > 50) || (last_check_millis == 0)) {
|
||||
last_check_millis = millis();
|
||||
last_result = Network.isOnline();
|
||||
|
||||
// FIXME TD-er: This is checking for NonAP interfaces, however we also have
|
||||
// ESPEasy::net::NWPluginCall(NWPlugin::Function::NWPLUGIN_WEBSERVER_SHOULD_RUN);
|
||||
@@ -136,6 +160,7 @@ bool NetworkConnected(bool force) {
|
||||
// - Webserver
|
||||
|
||||
processNetworkEvents();
|
||||
last_result = Network.isOnline();
|
||||
}
|
||||
return last_result;
|
||||
}
|
||||
|
||||
@@ -56,6 +56,12 @@ void setNetworkMedium(NetworkMedium_t new_medium) {
|
||||
// ESPEasy::net::wifi::WiFiConnectRelaxed();
|
||||
// }
|
||||
|
||||
ESPEasy::net::networkIndex_t getNetworkIndex_defaultNetwork()
|
||||
{
|
||||
if (NetworkConnected()) return NETWORK_INDEX_WIFI_STA;
|
||||
return ESPEasy::net::INVALID_NETWORK_INDEX;
|
||||
}
|
||||
|
||||
bool NetworkConnected(bool force) {
|
||||
static bool last_result = false;
|
||||
static uint32_t last_check_millis = 0;
|
||||
|
||||
@@ -181,7 +181,7 @@ bool NWPluginCall(NWPlugin::Function Function, EventStruct *event, String& str)
|
||||
}
|
||||
|
||||
if (Function == NWPlugin::Function::NWPLUGIN_PRIORITY_ROUTE_CHANGED) {
|
||||
CheckRunningServices();
|
||||
CheckRunningServices(success);
|
||||
}
|
||||
|
||||
return success;
|
||||
@@ -493,7 +493,7 @@ bool NWPluginCall(NWPlugin::Function Function, EventStruct *event, String& str)
|
||||
}
|
||||
#endif // ifdef ESP32
|
||||
}
|
||||
#ifdef ESP32
|
||||
//#ifdef ESP32
|
||||
|
||||
if (Function == NWPlugin::Function::NWPLUGIN_EXIT) {
|
||||
// Cache.clearNetworkSettings(networkIndex);
|
||||
@@ -505,7 +505,7 @@ bool NWPluginCall(NWPlugin::Function Function, EventStruct *event, String& str)
|
||||
}
|
||||
clearNWPluginData(event->NetworkIndex);
|
||||
}
|
||||
#endif // ifdef ESP32
|
||||
//#endif // ifdef ESP32
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "../../../src/DataStructs/TimingStats.h"
|
||||
#include "../../../src/DataTypes/ESPEasy_plugin_functions.h"
|
||||
#include "../../../src/Globals/Settings.h"
|
||||
#include "../../../src/Globals/ESPEasy_Scheduler.h"
|
||||
//#include "../../../src/Helpers/Misc.h"
|
||||
#include "../../../src/Helpers/StringConverter.h"
|
||||
#include "../Globals/NWPlugins.h"
|
||||
@@ -2130,20 +2131,24 @@ bool do_NWPluginCall(networkDriverIndex_t networkDriverIndex, NWPlugin::
|
||||
addLog(LOG_LEVEL_ERROR, strformat(F("Network %d was already initialized"), event->NetworkIndex + 1));
|
||||
return false;
|
||||
}
|
||||
bitSet(networkIndex_initialized, event->NetworkIndex);
|
||||
} else if (Function == NWPlugin::Function::NWPLUGIN_EXIT) {
|
||||
if (!bitRead(networkIndex_initialized, event->NetworkIndex)) {
|
||||
// FIXME TD-er: What to do here? Was not (yet) initialized
|
||||
// addLog(LOG_LEVEL_ERROR, strformat(F("Network %d was not (yet) initialized"), event->NetworkIndex + 1));
|
||||
return false;
|
||||
}
|
||||
bitClear(networkIndex_initialized, event->NetworkIndex);
|
||||
}
|
||||
|
||||
|
||||
START_TIMER;
|
||||
NWPlugin_ptr_t nwplugin_call = (NWPlugin_ptr_t)pgm_read_ptr(NWPlugin_ptr + networkDriverIndex.value);
|
||||
const bool res = nwplugin_call(Function, event, string);
|
||||
if (res && Function == NWPlugin::Function::NWPLUGIN_INIT) {
|
||||
bitSet(networkIndex_initialized, event->NetworkIndex);
|
||||
} else if (Function == NWPlugin::Function::NWPLUGIN_EXIT) {
|
||||
bitClear(networkIndex_initialized, event->NetworkIndex);
|
||||
}
|
||||
|
||||
STOP_TIMER_NETWORK(networkDriverIndex, Function);
|
||||
return res;
|
||||
}
|
||||
@@ -2200,10 +2205,10 @@ void NWPlugin_Exit_Init(networkIndex_t networkIndex)
|
||||
String dummy;
|
||||
|
||||
// May need to call init later, so make sure exit is called first
|
||||
NWPluginCall(NWPlugin::Function::NWPLUGIN_EXIT, &TempEvent, dummy);
|
||||
Scheduler.setNetworkExitTimer(0, networkIndex);
|
||||
|
||||
if (Settings.getNetworkEnabled(networkIndex)) {
|
||||
NWPluginCall(NWPlugin::Function::NWPLUGIN_INIT, &TempEvent, dummy);
|
||||
Scheduler.setNetworkInitTimer(0, networkIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
# include "../../../src/DataTypes/ESPEasy_plugin_functions.h"
|
||||
# include "../../../src/WebServer/HTML_wrappers.h"
|
||||
# include "../../../src/WebServer/Markup.h"
|
||||
# include "../../../src/Globals/Settings.h"
|
||||
# include "../../../src/Helpers/Networking.h"
|
||||
|
||||
# include "../wifi/ESPEasyWifi.h"
|
||||
|
||||
@@ -42,9 +44,9 @@ void NW001_data_struct_WiFi_STA::webform_load(EventStruct *event)
|
||||
|
||||
}
|
||||
|
||||
void NW001_data_struct_WiFi_STA::webform_save(EventStruct *event) {}
|
||||
void NW001_data_struct_WiFi_STA::webform_save(EventStruct *event) {}
|
||||
|
||||
bool NW001_data_struct_WiFi_STA::webform_getPort(KeyValueWriter *writer) { return true; }
|
||||
bool NW001_data_struct_WiFi_STA::webform_getPort(KeyValueWriter *writer) { return true; }
|
||||
|
||||
bool NW001_data_struct_WiFi_STA::init(EventStruct *event)
|
||||
{
|
||||
@@ -95,6 +97,16 @@ bool NW001_data_struct_WiFi_STA::init(EventStruct *event)
|
||||
// ESPEasy::net::wifi::setWifiMode(WIFI_OFF);
|
||||
*/
|
||||
|
||||
{
|
||||
auto runtime_data = getNWPluginData_static_runtime();
|
||||
if (runtime_data) {
|
||||
IPAddress ip, gateway, sn, dns;
|
||||
getStaticIPAddresses(ip, gateway, sn, dns);
|
||||
runtime_data->setStaticIP(ip, gateway, sn, dns);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ESPEasy::net::wifi::initWiFi();
|
||||
return true;
|
||||
}
|
||||
@@ -108,6 +120,30 @@ NWPluginData_static_runtime * NW001_data_struct_WiFi_STA::getNWPluginData_static
|
||||
return _WiFiEventHandler.getNWPluginData_static_runtime();
|
||||
}
|
||||
|
||||
bool NW001_data_struct_WiFi_STA::getStaticIPAddress(IPAddressType addressType, IPAddress& ip) const
|
||||
{
|
||||
IPAddress res;
|
||||
|
||||
switch (addressType)
|
||||
{
|
||||
case IPAddressType::IP:
|
||||
res = IPAddress(Settings.IP);
|
||||
break;
|
||||
case IPAddressType::Gateway:
|
||||
res = IPAddress(Settings.Gateway);
|
||||
break;
|
||||
case IPAddressType::Subnetmask:
|
||||
res = IPAddress(Settings.Subnet);
|
||||
break;
|
||||
case IPAddressType::DNS:
|
||||
res = IPAddress(Settings.DNS);
|
||||
break;
|
||||
}
|
||||
ip = res;
|
||||
|
||||
return IPAddressSet(ip);
|
||||
}
|
||||
|
||||
const __FlashStringHelper * NW001_data_struct_WiFi_STA::getWiFi_encryptionType() const
|
||||
{
|
||||
return _WiFiEventHandler.getWiFi_encryptionType();
|
||||
|
||||
@@ -41,6 +41,7 @@ struct NW001_data_struct_WiFi_STA : public NWPluginData_base {
|
||||
# endif // if FEATURE_NETWORK_STATS
|
||||
|
||||
NWPluginData_static_runtime* getNWPluginData_static_runtime() override;
|
||||
bool getStaticIPAddress(IPAddressType addressType, IPAddress & ip) const override;
|
||||
const __FlashStringHelper* getWiFi_encryptionType() const;
|
||||
|
||||
WiFiDisconnectReason getWiFi_disconnectReason() const;
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
#ifdef USES_NW002
|
||||
|
||||
# ifdef ESP32
|
||||
# include "../../../src/Globals/Settings.h"
|
||||
#endif
|
||||
# include "../../../src/Globals/Settings.h"
|
||||
# endif
|
||||
|
||||
# include "../wifi/ESPEasyWifi.h"
|
||||
|
||||
# include "../../../src/Helpers/Networking.h"
|
||||
|
||||
# ifdef ESP32
|
||||
# include <esp_wifi.h>
|
||||
# include <esp_wifi_ap_get_sta_list.h>
|
||||
@@ -89,6 +91,15 @@ bool NW002_data_struct_WiFi_AP::webform_getPort(KeyValueWriter *writer) { return
|
||||
|
||||
bool NW002_data_struct_WiFi_AP::init(EventStruct *event)
|
||||
{
|
||||
{
|
||||
auto runtime_data = getNWPluginData_static_runtime();
|
||||
if (runtime_data) {
|
||||
IPAddress ip, gateway, sn, dns;
|
||||
getStaticIPAddresses(ip, gateway, sn, dns);
|
||||
runtime_data->setStaticIP(ip, gateway, sn, dns);
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef ESP32
|
||||
nw002_enable_NAPT = Settings.WiFi_AP_enable_NAPT();
|
||||
# endif
|
||||
@@ -97,13 +108,13 @@ bool NW002_data_struct_WiFi_AP::init(EventStruct *event)
|
||||
# ifdef ESP32
|
||||
NW002_update_NAPT();
|
||||
# endif
|
||||
# if FEATURE_MDNS
|
||||
# ifdef ESP8266
|
||||
# if FEATURE_MDNS
|
||||
# ifdef ESP8266
|
||||
|
||||
// notifyAPChange() is not present in the ESP32 MDNSResponder
|
||||
MDNS.notifyAPChange();
|
||||
# endif // ifdef ESP8266
|
||||
# endif // if FEATURE_MDNS
|
||||
# endif // ifdef ESP8266
|
||||
# endif // if FEATURE_MDNS
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -132,6 +143,32 @@ NWPluginData_static_runtime * NW002_data_struct_WiFi_AP::getNWPluginData_static_
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool NW002_data_struct_WiFi_AP::getStaticIPAddress(IPAddressType addressType, IPAddress& ip) const
|
||||
{
|
||||
// TODO TD-er: Implement for AP
|
||||
/*
|
||||
IPAddress res;
|
||||
|
||||
switch (addressType)
|
||||
{
|
||||
case IPAddressType::IP: res = IPAddress(Settings.IP);
|
||||
break;
|
||||
case IPAddressType::Gateway: res = IPAddress(Settings.Gateway);
|
||||
break;
|
||||
case IPAddressType::Subnetmask: res = IPAddress(Settings.Subnet);
|
||||
break;
|
||||
case IPAddressType::DNS: res = IPAddress(Settings.DNS);
|
||||
break;
|
||||
}
|
||||
|
||||
if (IPAddressSet(res)) {
|
||||
ip = res;
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
# ifdef ESP32
|
||||
|
||||
bool NW002_data_struct_WiFi_AP::handle_priority_route_changed() { return NW002_update_NAPT(); }
|
||||
|
||||
@@ -35,6 +35,8 @@ struct NW002_data_struct_WiFi_AP : public NWPluginData_base {
|
||||
|
||||
NWPluginData_static_runtime* getNWPluginData_static_runtime() override;
|
||||
|
||||
bool getStaticIPAddress(IPAddressType addressType, IPAddress & ip) const override;
|
||||
|
||||
private:
|
||||
|
||||
# ifdef ESP32
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
# include "../../../src/Globals/Settings.h"
|
||||
|
||||
# include "../../../src/Helpers/Hardware_GPIO.h"
|
||||
# include "../../../src/Helpers/Networking.h"
|
||||
# include "../../../src/Helpers/StringConverter.h"
|
||||
|
||||
# include "../../../src/WebServer/Markup.h"
|
||||
@@ -55,16 +56,16 @@ const __FlashStringHelper * NW003_data_struct_ETH_RMII::getLabelString(uint32_t
|
||||
case NW003_KEY_ETH_PIN_POWER: return displayString ? F("Ethernet Power pin") : F("pwr");
|
||||
case NW003_KEY_CLOCK_MODE: return displayString ? F("Ethernet Clock") : F("clock");
|
||||
case NW003_KEY_IP:
|
||||
storageType = KVS_StorageType::Enum::string_type;
|
||||
storageType = KVS_StorageType::Enum::ip_type;
|
||||
return F("IP");
|
||||
case NW003_KEY_GW:
|
||||
storageType = KVS_StorageType::Enum::string_type;
|
||||
storageType = KVS_StorageType::Enum::ip_type;
|
||||
return displayString ? F("Gateway") : F("gw");
|
||||
case NW003_KEY_SN:
|
||||
storageType = KVS_StorageType::Enum::string_type;
|
||||
storageType = KVS_StorageType::Enum::ip_type;
|
||||
return displayString ? F("Subnetmask") : F("sn");
|
||||
case NW003_KEY_DNS:
|
||||
storageType = KVS_StorageType::Enum::string_type;
|
||||
storageType = KVS_StorageType::Enum::ip_type;
|
||||
return F("DNS");
|
||||
}
|
||||
return F("");
|
||||
@@ -144,7 +145,18 @@ void NW003_data_struct_ETH_RMII::loadDefaults(ESPEasy_key_value_store *kvs,
|
||||
kvs->setValue(NW003_KEY_ETH_PIN_POWER, static_cast<int8_t>(Settings.ETH_Pin_power_rst));
|
||||
kvs->setValue(NW003_KEY_CLOCK_MODE, static_cast<int8_t>(Settings.ETH_Clock_Mode));
|
||||
|
||||
// TODO TD-er: Copy IP info
|
||||
const IPAddress ip = Settings.ETH_IP;
|
||||
const IPAddress gw = Settings.ETH_Gateway;
|
||||
const IPAddress subnet = Settings.ETH_Subnet;
|
||||
const IPAddress dns = Settings.ETH_DNS;
|
||||
|
||||
// TODO TD-er: Must clear the previous ETH IP settings, once converted
|
||||
|
||||
kvs->setValue(NW003_KEY_IP, ip);
|
||||
kvs->setValue(NW003_KEY_GW, gw);
|
||||
kvs->setValue(NW003_KEY_SN, subnet);
|
||||
kvs->setValue(NW003_KEY_DNS, dns);
|
||||
|
||||
|
||||
store_nwpluginTaskData_KVS(kvs, networkIndex, nwPluginID);
|
||||
}
|
||||
@@ -176,12 +188,18 @@ void NW003_data_struct_ETH_RMII::webform_load(EventStruct *event)
|
||||
NW003_data_struct_ETH_RMII::loadDefaults(_kvs, event->NetworkIndex, nwpluginID_t(3));
|
||||
|
||||
addFormSubHeader(F("Ethernet IP Settings"));
|
||||
{
|
||||
const int keys[] = {
|
||||
NW003_KEY_IP,
|
||||
NW003_KEY_GW,
|
||||
NW003_KEY_SN,
|
||||
NW003_KEY_DNS
|
||||
};
|
||||
|
||||
addFormIPBox(F("ESP Ethernet IP"), F("espethip"), Settings.ETH_IP);
|
||||
addFormIPBox(F("ESP Ethernet Gateway"), F("espethgateway"), Settings.ETH_Gateway);
|
||||
addFormIPBox(F("ESP Ethernet Subnetmask"), F("espethsubnet"), Settings.ETH_Subnet);
|
||||
addFormIPBox(F("ESP Ethernet DNS"), F("espethdns"), Settings.ETH_DNS);
|
||||
addFormNote(F("Leave empty for DHCP"));
|
||||
for (uint32_t i = 0; i < NR_ELEMENTS(keys); ++i) {
|
||||
showWebformItem(*_kvs, NW003_makeWebFormItemParams(keys[i]));
|
||||
}
|
||||
}
|
||||
|
||||
addFormSubHeader(F("Ethernet"));
|
||||
|
||||
@@ -276,19 +294,21 @@ void NW003_data_struct_ETH_RMII::webform_load(EventStruct *event)
|
||||
// toString(EthClockMode_t::Default),
|
||||
toString(EthClockMode_t::Ext_crystal),
|
||||
toString(EthClockMode_t::Int_50MHz)
|
||||
// , toString(EthClockMode_t::Ext_crystal_GPIO_32)
|
||||
// , toString(EthClockMode_t::Int_50MHz_GPIO_32)
|
||||
// , toString(EthClockMode_t::Ext_crystal_GPIO_44)
|
||||
// , toString(EthClockMode_t::Int_50MHz_GPIO_44)
|
||||
|
||||
// , toString(EthClockMode_t::Ext_crystal_GPIO_32)
|
||||
// , toString(EthClockMode_t::Int_50MHz_GPIO_32)
|
||||
// , toString(EthClockMode_t::Ext_crystal_GPIO_44)
|
||||
// , toString(EthClockMode_t::Int_50MHz_GPIO_44)
|
||||
};
|
||||
const int indices[] = {
|
||||
// static_cast<int>(EthClockMode_t::Default),
|
||||
static_cast<int>(EthClockMode_t::Ext_crystal),
|
||||
static_cast<int>(EthClockMode_t::Int_50MHz)
|
||||
// ,static_cast<int>(EthClockMode_t::Ext_crystal_GPIO_32)
|
||||
// ,static_cast<int>(EthClockMode_t::Int_50MHz_GPIO_32)
|
||||
// ,static_cast<int>(EthClockMode_t::Ext_crystal_GPIO_44)
|
||||
// ,static_cast<int>(EthClockMode_t::Int_50MHz_GPIO_44)
|
||||
|
||||
// ,static_cast<int>(EthClockMode_t::Ext_crystal_GPIO_32)
|
||||
// ,static_cast<int>(EthClockMode_t::Int_50MHz_GPIO_32)
|
||||
// ,static_cast<int>(EthClockMode_t::Ext_crystal_GPIO_44)
|
||||
// ,static_cast<int>(EthClockMode_t::Int_50MHz_GPIO_44)
|
||||
};
|
||||
# endif // if CONFIG_IDF_TARGET_ESP32P4
|
||||
const FormSelectorOptions selector(
|
||||
@@ -298,10 +318,10 @@ void NW003_data_struct_ETH_RMII::webform_load(EventStruct *event)
|
||||
auto params = NW003_makeWebFormItemParams(NW003_KEY_CLOCK_MODE);
|
||||
# if CONFIG_IDF_TARGET_ESP32
|
||||
params._defaultIntValue = static_cast<int>(EthClockMode_t::Ext_crystal_osc);
|
||||
#endif
|
||||
# endif
|
||||
# if CONFIG_IDF_TARGET_ESP32P4
|
||||
params._defaultIntValue = static_cast<int>(EthClockMode_t::Ext_crystal);
|
||||
#endif
|
||||
# endif
|
||||
|
||||
showFormSelector(*_kvs, selector, params);
|
||||
|
||||
@@ -327,6 +347,15 @@ bool NW003_data_struct_ETH_RMII::webform_getPort(KeyValueWriter *writer) { retur
|
||||
bool NW003_data_struct_ETH_RMII::init(EventStruct *event)
|
||||
{
|
||||
_load();
|
||||
{
|
||||
auto runtime_data = getNWPluginData_static_runtime();
|
||||
if (runtime_data) {
|
||||
IPAddress ip, gateway, sn, dns;
|
||||
getStaticIPAddresses(ip, gateway, sn, dns);
|
||||
runtime_data->setStaticIP(ip, gateway, sn, dns);
|
||||
}
|
||||
}
|
||||
|
||||
ETHConnectRelaxed();
|
||||
|
||||
return true;
|
||||
@@ -338,6 +367,36 @@ NWPluginData_static_runtime * NW003_data_struct_ETH_RMII::getNWPluginData_static
|
||||
return ESPEasy::net::eth::ETH_NWPluginData_static_runtime::getNWPluginData_static_runtime(_networkIndex);
|
||||
}
|
||||
|
||||
bool NW003_data_struct_ETH_RMII::getStaticIPAddress(IPAddressType addressType, IPAddress& ip) const
|
||||
{
|
||||
ip = IPAddress();
|
||||
|
||||
if (!_kvs) { return false; }
|
||||
uint32_t key = NW003_MAX_KEY;
|
||||
|
||||
switch (addressType)
|
||||
{
|
||||
case IPAddressType::IP:
|
||||
key = NW003_KEY_IP;
|
||||
break;
|
||||
case IPAddressType::Gateway:
|
||||
key = NW003_KEY_GW;
|
||||
break;
|
||||
case IPAddressType::Subnetmask:
|
||||
key = NW003_KEY_SN;
|
||||
break;
|
||||
case IPAddressType::DNS:
|
||||
key = NW003_KEY_DNS;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((key == NW003_MAX_KEY) || !_kvs->getValue(key, ip)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return IPAddressSet(ip);
|
||||
}
|
||||
|
||||
bool NW003_data_struct_ETH_RMII::write_Eth_HW_Address(KeyValueWriter *writer)
|
||||
{
|
||||
if (writer == nullptr) { return false; }
|
||||
@@ -447,6 +506,7 @@ void NW003_data_struct_ETH_RMII::ethPower(bool enable)
|
||||
|
||||
if (!enable) {
|
||||
const EthClockMode_t ETH_ClockMode = static_cast<EthClockMode_t>(_kvs->getValueAsInt(NW003_KEY_CLOCK_MODE));
|
||||
|
||||
if (isExternalCrystal(ETH_ClockMode)) {
|
||||
delay(600); // Give some time to discharge any capacitors
|
||||
// Delay is needed to make sure no clock signal remains present which may cause the ESP to boot into flash mode.
|
||||
@@ -503,7 +563,7 @@ bool NW003_data_struct_ETH_RMII::ETHConnectRelaxed() {
|
||||
if (!(data && iface)) { return false; }
|
||||
|
||||
if (data->started() && data->connected()) {
|
||||
if (EthLinkUp()) return true;
|
||||
if (EthLinkUp()) { return true; }
|
||||
data->mark_connect_failed();
|
||||
return false;
|
||||
}
|
||||
@@ -541,6 +601,18 @@ bool NW003_data_struct_ETH_RMII::ETHConnectRelaxed() {
|
||||
# ifndef ESP32P4
|
||||
ethResetGPIOpins();
|
||||
# endif
|
||||
|
||||
IPAddress ip, gateway, sn, dns;
|
||||
if (getStaticIPAddresses(ip, gateway, sn, dns)) {
|
||||
addLog(LOG_LEVEL_INFO, strformat(
|
||||
F("ETH: static IP: %s, GW: %s, SN: %s, DNS:%s"),
|
||||
ip.toString().c_str(),
|
||||
gateway.toString().c_str(),
|
||||
sn.toString().c_str(),
|
||||
dns.toString().c_str()));
|
||||
iface->config(ip, gateway, sn, dns);
|
||||
}
|
||||
|
||||
success = iface->begin(
|
||||
to_ESP_phy_type(phyType),
|
||||
phy_addr,
|
||||
@@ -548,7 +620,8 @@ bool NW003_data_struct_ETH_RMII::ETHConnectRelaxed() {
|
||||
mdioPin,
|
||||
powerPin,
|
||||
(eth_clock_mode_t)ETH_ClockMode);
|
||||
// TODO TD-er: When we can set the clock GPIO pin on ESP32-P4, this should also be matched to the Espressif eth_clock_mode_t enum.
|
||||
|
||||
// TODO TD-er: When we can set the clock GPIO pin on ESP32-P4, this should also be matched to the Espressif eth_clock_mode_t enum.
|
||||
}
|
||||
|
||||
if (success) {
|
||||
|
||||
@@ -39,6 +39,8 @@ struct NW003_data_struct_ETH_RMII : public NWPluginData_base {
|
||||
|
||||
NWPluginData_static_runtime* getNWPluginData_static_runtime() override;
|
||||
|
||||
bool getStaticIPAddress(IPAddressType addressType, IPAddress & ip) const override;
|
||||
|
||||
bool write_Eth_HW_Address(KeyValueWriter *writer);
|
||||
|
||||
bool write_Eth_port(KeyValueWriter *writer);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
# include "../../../src/Helpers/Hardware_GPIO.h"
|
||||
# include "../../../src/Helpers/Hardware_SPI.h"
|
||||
# include "../../../src/Helpers/Networking.h"
|
||||
# include "../../../src/Helpers/SPI_Helper.h"
|
||||
# include "../../../src/Helpers/StringConverter.h"
|
||||
|
||||
@@ -53,16 +54,16 @@ const __FlashStringHelper * NW004_data_struct_ETH_SPI::getLabelString(uint32_t k
|
||||
case NW004_KEY_ETH_PIN_RST: return displayString ? F("Ethernet RST pin") : F("RST");
|
||||
case NW004_KEY_SPI_BUS: return displayString ? F("SPI Bus") : F("ethspibus");
|
||||
case NW004_KEY_IP:
|
||||
storageType = KVS_StorageType::Enum::string_type;
|
||||
storageType = KVS_StorageType::Enum::ip_type;
|
||||
return F("IP");
|
||||
case NW004_KEY_GW:
|
||||
storageType = KVS_StorageType::Enum::string_type;
|
||||
storageType = KVS_StorageType::Enum::ip_type;
|
||||
return displayString ? F("Gateway") : F("gw");
|
||||
case NW004_KEY_SN:
|
||||
storageType = KVS_StorageType::Enum::string_type;
|
||||
storageType = KVS_StorageType::Enum::ip_type;
|
||||
return displayString ? F("Subnetmask") : F("sn");
|
||||
case NW004_KEY_DNS:
|
||||
storageType = KVS_StorageType::Enum::string_type;
|
||||
storageType = KVS_StorageType::Enum::ip_type;
|
||||
return F("DNS");
|
||||
}
|
||||
return F("");
|
||||
@@ -141,7 +142,17 @@ void NW004_data_struct_ETH_SPI::loadDefaults(ESPEasy_key_value_store *kvs,
|
||||
kvs->setValue(NW004_KEY_ETH_PIN_IRQ, static_cast<int8_t>(Settings.ETH_Pin_mdio_irq));
|
||||
kvs->setValue(NW004_KEY_ETH_PIN_RST, static_cast<int8_t>(Settings.ETH_Pin_power_rst));
|
||||
|
||||
// TODO TD-er: Copy IP info
|
||||
const IPAddress ip = Settings.ETH_IP;
|
||||
const IPAddress gw = Settings.ETH_Gateway;
|
||||
const IPAddress subnet = Settings.ETH_Subnet;
|
||||
const IPAddress dns = Settings.ETH_DNS;
|
||||
|
||||
// TODO TD-er: Must clear the previous ETH IP settings, once converted
|
||||
|
||||
kvs->setValue(NW004_KEY_IP, ip);
|
||||
kvs->setValue(NW004_KEY_GW, gw);
|
||||
kvs->setValue(NW004_KEY_SN, subnet);
|
||||
kvs->setValue(NW004_KEY_DNS, dns);
|
||||
|
||||
store_nwpluginTaskData_KVS(kvs, networkIndex, nwPluginID);
|
||||
}
|
||||
@@ -157,8 +168,6 @@ void NW004_data_struct_ETH_SPI::loadDefaults(ESPEasy_key_value_store *kvs,
|
||||
kvs->setValue(NW004_KEY_ETH_PIN_IRQ, static_cast<int8_t>(DEFAULT_ETH_PIN_MDIO));
|
||||
kvs->setValue(NW004_KEY_ETH_PIN_RST, static_cast<int8_t>(DEFAULT_ETH_PIN_POWER));
|
||||
|
||||
// TODO TD-er: Copy IP info
|
||||
|
||||
store_nwpluginTaskData_KVS(kvs, networkIndex, nwPluginID);
|
||||
}
|
||||
# endif // if defined(DEFAULT_ETH_PHY_TYPE) && defined(DEFAULT_ETH_CLOCK_MODE) && defined(DEFAULT_ETH_PHY_ADDR) &&
|
||||
@@ -171,11 +180,18 @@ void NW004_data_struct_ETH_SPI::webform_load(EventStruct *event)
|
||||
_load();
|
||||
NW004_data_struct_ETH_SPI::loadDefaults(_kvs, event->NetworkIndex, nwpluginID_t(4));
|
||||
addFormSubHeader(F("Ethernet IP Settings"));
|
||||
{
|
||||
const int keys[] = {
|
||||
NW004_KEY_IP,
|
||||
NW004_KEY_GW,
|
||||
NW004_KEY_SN,
|
||||
NW004_KEY_DNS
|
||||
};
|
||||
|
||||
addFormIPBox(F("ESP Ethernet IP"), F("espethip"), Settings.ETH_IP);
|
||||
addFormIPBox(F("ESP Ethernet Gateway"), F("espethgateway"), Settings.ETH_Gateway);
|
||||
addFormIPBox(F("ESP Ethernet Subnetmask"), F("espethsubnet"), Settings.ETH_Subnet);
|
||||
addFormIPBox(F("ESP Ethernet DNS"), F("espethdns"), Settings.ETH_DNS);
|
||||
for (uint32_t i = 0; i < NR_ELEMENTS(keys); ++i) {
|
||||
showWebformItem(*_kvs, NW004_makeWebFormItemParams(keys[i]));
|
||||
}
|
||||
}
|
||||
addFormNote(F("Leave empty for DHCP"));
|
||||
|
||||
addFormSubHeader(F("Ethernet"));
|
||||
@@ -277,6 +293,15 @@ bool NW004_data_struct_ETH_SPI::webform_getPort(KeyValueWriter *writer) { return
|
||||
bool NW004_data_struct_ETH_SPI::init(EventStruct *event)
|
||||
{
|
||||
_load();
|
||||
{
|
||||
auto runtime_data = getNWPluginData_static_runtime();
|
||||
if (runtime_data) {
|
||||
IPAddress ip, gateway, sn, dns;
|
||||
getStaticIPAddresses(ip, gateway, sn, dns);
|
||||
runtime_data->setStaticIP(ip, gateway, sn, dns);
|
||||
}
|
||||
}
|
||||
|
||||
ETHConnectRelaxed();
|
||||
|
||||
return true;
|
||||
@@ -288,6 +313,37 @@ NWPluginData_static_runtime * NW004_data_struct_ETH_SPI::getNWPluginData_static_
|
||||
return ESPEasy::net::eth::ETH_NWPluginData_static_runtime::getNWPluginData_static_runtime(_networkIndex);
|
||||
}
|
||||
|
||||
bool NW004_data_struct_ETH_SPI::getStaticIPAddress(IPAddressType addressType, IPAddress& ip) const
|
||||
{
|
||||
ip = IPAddress();
|
||||
|
||||
if (!_kvs) { return false; }
|
||||
uint32_t key = NW004_MAX_KEY;
|
||||
|
||||
switch (addressType)
|
||||
{
|
||||
case IPAddressType::IP:
|
||||
key = NW004_KEY_IP;
|
||||
break;
|
||||
case IPAddressType::Gateway:
|
||||
key = NW004_KEY_GW;
|
||||
break;
|
||||
case IPAddressType::Subnetmask:
|
||||
key = NW004_KEY_SN;
|
||||
break;
|
||||
case IPAddressType::DNS:
|
||||
key = NW004_KEY_DNS;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((key == NW004_MAX_KEY) || !_kvs->getValue(key, ip)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return IPAddressSet(ip);
|
||||
|
||||
}
|
||||
|
||||
bool NW004_data_struct_ETH_SPI::write_Eth_HW_Address(KeyValueWriter *writer)
|
||||
{
|
||||
if (writer == nullptr) { return false; }
|
||||
@@ -448,6 +504,12 @@ bool NW004_data_struct_ETH_SPI::ETHConnectRelaxed() {
|
||||
// else
|
||||
if (spi_instance)
|
||||
{
|
||||
IPAddress ip, gateway, sn, dns;
|
||||
|
||||
if (getStaticIPAddresses(ip, gateway, sn, dns)) {
|
||||
iface->config(ip, gateway, sn, dns);
|
||||
}
|
||||
|
||||
// TODO TD-er: Do we need to include the CLK, MISO, MOSI pins in the call or do we need to start the SPI bus first?
|
||||
# if ETH_SPI_SUPPORTS_CUSTOM
|
||||
success = iface->begin(
|
||||
|
||||
@@ -40,6 +40,8 @@ struct NW004_data_struct_ETH_SPI : public NWPluginData_base {
|
||||
|
||||
NWPluginData_static_runtime* getNWPluginData_static_runtime() override;
|
||||
|
||||
bool getStaticIPAddress(IPAddressType addressType, IPAddress & ip) const override;
|
||||
|
||||
bool write_Eth_HW_Address(KeyValueWriter *writer);
|
||||
bool write_Eth_port(KeyValueWriter *writer);
|
||||
|
||||
|
||||
@@ -926,12 +926,12 @@ bool NW005_data_struct_PPP_modem::init(EventStruct *event)
|
||||
}
|
||||
{
|
||||
String apn;
|
||||
_kvs->getValue(NW005_KEY_APN, apn);
|
||||
_kvs->getValue(NW005_KEY_APN, apn, KVS_StorageType::Enum::string_type);
|
||||
NW_PLUGIN_INTERFACE.setApn(apn.c_str());
|
||||
}
|
||||
{
|
||||
String pin;
|
||||
_kvs->getValue(NW005_KEY_SIM_PIN, pin);
|
||||
_kvs->getValue(NW005_KEY_SIM_PIN, pin, KVS_StorageType::Enum::string_type);
|
||||
|
||||
if (pin.length() >= 4) {
|
||||
NW_PLUGIN_INTERFACE.setPin(pin.c_str());
|
||||
@@ -1108,6 +1108,12 @@ bool NW005_data_struct_PPP_modem::record_stats()
|
||||
|
||||
NWPluginData_static_runtime * NW005_data_struct_PPP_modem::getNWPluginData_static_runtime() { return &stats_and_cache; }
|
||||
|
||||
bool NW005_data_struct_PPP_modem::getStaticIPAddress(IPAddressType addressType, IPAddress & ip) const
|
||||
{
|
||||
// No static IP for PPP modem
|
||||
return false;
|
||||
}
|
||||
|
||||
void NW005_data_struct_PPP_modem::onEvent(arduino_event_id_t event, arduino_event_info_t info) {
|
||||
// TODO TD-er: Must store flags from events in static (or global) object to act on it later.
|
||||
switch (event)
|
||||
|
||||
@@ -80,6 +80,8 @@ static int32_t getNextKey_noCredentials(int32_t key);
|
||||
|
||||
NWPluginData_static_runtime* getNWPluginData_static_runtime() override;
|
||||
|
||||
bool getStaticIPAddress(IPAddressType addressType, IPAddress & ip) const override;
|
||||
|
||||
private:
|
||||
|
||||
static void onEvent(arduino_event_id_t event,
|
||||
|
||||
@@ -491,7 +491,7 @@ bool NWPlugin_001(NWPlugin::Function function, EventStruct *event, String& strin
|
||||
|
||||
addFormNumericBox(LabelType::WIFI_NR_RECONNECT_ATTEMPTS, 0, 255);
|
||||
{
|
||||
LabelType::Enum labels[]{
|
||||
LabelType::Enum labels[]{
|
||||
LabelType::RESTART_WIFI_LOST_CONN
|
||||
, LabelType::WIFI_USE_LAST_CONN_FROM_RTC
|
||||
# ifndef ESP32
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
# include "../../../src/DataTypes/ESPEasyTimeSource.h"
|
||||
# include "../../../src/ESPEasyCore/ESPEasy_Log.h"
|
||||
# include "../../../src/Helpers/Networking.h"
|
||||
# include "../../../src/Helpers/StringConverter.h"
|
||||
# include "../../../src/Helpers/StringGenerator_WiFi.h"
|
||||
# include "../DataStructs/NWPluginData_static_runtime.h"
|
||||
@@ -65,7 +66,7 @@ bool ESPEasyWiFi_STA_EventHandler::restore_dns_from_cac
|
||||
for (size_t i = 0; i < NR_ELEMENTS(stats_and_cache._dns_cache); ++i) {
|
||||
auto tmp = WiFi.STA.dnsIP(i);
|
||||
|
||||
if ((stats_and_cache._dns_cache[i] != INADDR_NONE) && (stats_and_cache._dns_cache[i] != tmp)) {
|
||||
if (valid_DNS_address(stats_and_cache._dns_cache[i]) && (stats_and_cache._dns_cache[i] != tmp)) {
|
||||
addLog(LOG_LEVEL_INFO, strformat(
|
||||
F("WiFi STA: Restore cached DNS server %d from %s to %s"),
|
||||
i,
|
||||
|
||||
@@ -86,7 +86,7 @@ void ESPEasyWiFi_STA_EventHandler::onDisconnect(const WiFiEventStationModeDiscon
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
// See https://github.com/esp8266/Arduino/issues/5912
|
||||
WiFi.persistent(false);
|
||||
WiFi.disconnect(false);
|
||||
WiFi.disconnect(true);
|
||||
delay(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ void ESPEasyWiFi_t::begin() {
|
||||
setState(WiFiState_e::IdleWaiting, 100);
|
||||
} else {
|
||||
if (WiFi_AP_Candidates.hasScanned()) {
|
||||
// Has no candidates, but scan was performed.
|
||||
if (shouldStartAP_fallback()) {
|
||||
setState(WiFiState_e::AP_only, WIFI_STATE_MACHINE_AP_ONLY_TIMEOUT);
|
||||
}
|
||||
@@ -153,7 +154,12 @@ void ESPEasyWiFi_t::loop()
|
||||
// && !WiFiEventData.warnedNoValidWiFiSettings
|
||||
)
|
||||
{
|
||||
addLog(LOG_LEVEL_ERROR, F("WIFI : No valid wifi settings"));
|
||||
// Check for whether No Valid WiFi settings was already logged
|
||||
static uint32_t lastTimeLoggedNoWiFiCredentials = 0;
|
||||
if (timePassedSince(lastTimeLoggedNoWiFiCredentials) > 5000) {
|
||||
addLog(LOG_LEVEL_ERROR, F("WIFI : No valid wifi settings"));
|
||||
lastTimeLoggedNoWiFiCredentials = millis();
|
||||
}
|
||||
|
||||
// WiFiEventData.warnedNoValidWiFiSettings = true;
|
||||
}
|
||||
@@ -299,7 +305,7 @@ void ESPEasyWiFi_t::loop()
|
||||
/*
|
||||
if (Settings.UseRules)
|
||||
{
|
||||
eventQueue.add(F("WiFi#Disconnected"));
|
||||
eventQueue.addDeDup(F("WiFi#Disconnected"));
|
||||
}
|
||||
statusLED(false);
|
||||
*/
|
||||
@@ -330,7 +336,7 @@ void ESPEasyWiFi_t::disconnect() { doWiFiDisconnect(); }
|
||||
|
||||
void ESPEasyWiFi_t::setState(WiFiState_e newState, uint32_t timeout) {
|
||||
if (newState == _state) { return; }
|
||||
# ifndef BUILD_NO_DEBUG
|
||||
//# ifndef BUILD_NO_DEBUG
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
addLog(
|
||||
@@ -339,7 +345,7 @@ void ESPEasyWiFi_t::setState(WiFiState_e newState, uint32_t timeout) {
|
||||
concat(F(" to: "), toString(newState)) +
|
||||
concat(F(" timeout: "), timeout));
|
||||
}
|
||||
# endif // ifndef BUILD_NO_DEBUG
|
||||
//# endif // ifndef BUILD_NO_DEBUG
|
||||
|
||||
if ((_state == WiFiState_e::AP_only) ||
|
||||
(_state == WiFiState_e::AP_Fallback)) {
|
||||
@@ -355,7 +361,7 @@ void ESPEasyWiFi_t::setState(WiFiState_e newState, uint32_t timeout) {
|
||||
wifi_STA_data->mark_disconnected();
|
||||
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
WiFi.disconnect();
|
||||
WiFi.disconnect(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -461,7 +467,7 @@ void ESPEasyWiFi_t::setState(WiFiState_e newState, uint32_t timeout) {
|
||||
/*
|
||||
if (Settings.UseRules)
|
||||
{
|
||||
eventQueue.add(F("WiFi#Connected"));
|
||||
eventQueue.addDeDup(F("WiFi#Connected"));
|
||||
}
|
||||
statusLED(true);
|
||||
*/
|
||||
@@ -469,6 +475,12 @@ void ESPEasyWiFi_t::setState(WiFiState_e newState, uint32_t timeout) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
auto wifi_STA_data = getWiFi_STA_NWPluginData_static_runtime();
|
||||
|
||||
if (wifi_STA_data) {
|
||||
wifi_STA_data->processEvents();
|
||||
}
|
||||
}
|
||||
|
||||
void ESPEasyWiFi_t::checkConnectProgress() {}
|
||||
@@ -536,7 +548,6 @@ bool ESPEasyWiFi_t::connectSTA()
|
||||
// WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
|
||||
# endif // if defined(ESP32)
|
||||
doSetConnectionSpeed();
|
||||
setupStaticIPconfig();
|
||||
|
||||
// Start the process of connecting or starting AP
|
||||
if (!WiFi_AP_Candidates.getNext(true))
|
||||
@@ -655,6 +666,16 @@ bool ESPEasyWiFi_t::shouldStartAP_fallback() const
|
||||
(_connect_attempt > Settings.ConnectFailRetryCount);
|
||||
}
|
||||
|
||||
bool ESPEasyWiFi_t::shouldRedirectTo_setup() const
|
||||
{
|
||||
if (!Settings.ApCaptivePortal()) return false;
|
||||
if (Settings.StartAPfallback_NoCredentials() && !SecuritySettings.hasWiFiCredentials()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !Settings.DoNotStartAPfallback_ConnectFail();
|
||||
}
|
||||
|
||||
} // namespace wifi
|
||||
} // namespace net
|
||||
} // namespace ESPEasy
|
||||
|
||||
@@ -100,6 +100,8 @@ public:
|
||||
|
||||
bool shouldStartAP_fallback() const;
|
||||
|
||||
bool shouldRedirectTo_setup() const;
|
||||
|
||||
private:
|
||||
|
||||
// WiFi_AP_Candidate _active_sta;
|
||||
|
||||
@@ -11,15 +11,15 @@
|
||||
# include "../../../src/Helpers/ESPEasy_time_calc.h"
|
||||
# include "../../../src/Helpers/StringConverter.h"
|
||||
|
||||
#if FEATURE_TASKVALUE_UNIT_OF_MEASURE
|
||||
# include "../../../src/Helpers/ESPEasy_UnitOfMeasure.h"
|
||||
#endif
|
||||
# if FEATURE_TASKVALUE_UNIT_OF_MEASURE
|
||||
# include "../../../src/Helpers/ESPEasy_UnitOfMeasure.h"
|
||||
# endif
|
||||
|
||||
#ifdef ESP8266
|
||||
# ifndef BUILD_NO_DEBUG
|
||||
#include "../../../src/Helpers/StringGenerator_WiFi.h"
|
||||
#endif
|
||||
#endif
|
||||
# ifdef ESP8266
|
||||
# ifndef BUILD_NO_DEBUG
|
||||
# include "../../../src/Helpers/StringGenerator_WiFi.h"
|
||||
# endif
|
||||
# endif // ifdef ESP8266
|
||||
|
||||
# ifdef ESP32
|
||||
# include <WiFiGeneric.h>
|
||||
@@ -101,6 +101,34 @@ namespace wifi {
|
||||
- Connection stable (connected for > 5 minutes)
|
||||
|
||||
*/
|
||||
bool validWiFiSSID(const String& ssid) {
|
||||
// Can be any char upto 32 characters not being a null-char.
|
||||
// Some implementations, like Cisco, suggest some invalid characters:
|
||||
// - '+'
|
||||
// - ']'
|
||||
// - '/'
|
||||
// - '*'
|
||||
// - TAB
|
||||
// - Trailing spaces
|
||||
// And the first character cannot contain:
|
||||
// - '!'
|
||||
// - '#'
|
||||
// - ';'
|
||||
// Source: https://community.cisco.com/t5/networking-knowledge-base/characteristics-of-ssids/ta-p/3131765
|
||||
//
|
||||
// However this seems to be Cisco specific and not a limitation of the standard
|
||||
if (ssid.length() > 32) { return false; }
|
||||
|
||||
// "ssid" is an internal ESPEasy limitation, to signal an 'unset' value.
|
||||
return !ssid.isEmpty() && !ssid.equalsIgnoreCase(F("ssid"));
|
||||
}
|
||||
|
||||
bool validWiFiCredentials(const String& ssid, const String& pass) {
|
||||
if (!validWiFiSSID(ssid)) { return false; }
|
||||
const auto pass_length = pass.length();
|
||||
return (pass_length >= 8 && pass_length <= 63)
|
||||
|| pass_length == 0; // Empty password is possible
|
||||
}
|
||||
|
||||
// ********************************************************************************
|
||||
// Check WiFi connected status
|
||||
@@ -158,16 +186,19 @@ void resetWiFi() {
|
||||
*/
|
||||
}
|
||||
|
||||
void initWiFi() { ESPEasyWiFi.setup(); }
|
||||
void initWiFi() { ESPEasyWiFi.setup(); }
|
||||
|
||||
void exitWiFi() { ESPEasyWiFi.disable(); }
|
||||
|
||||
void loopWiFi() { ESPEasyWiFi.loop(); }
|
||||
|
||||
bool shouldStartAP_fallback() {
|
||||
return ESPEasyWiFi.shouldStartAP_fallback();
|
||||
void exitWiFi() {
|
||||
ESPEasyWiFi.disable();
|
||||
WiFi_AP_Candidates.force_reload();
|
||||
}
|
||||
|
||||
void loopWiFi() { ESPEasyWiFi.loop(); }
|
||||
|
||||
bool shouldStartAP_fallback() { return ESPEasyWiFi.shouldStartAP_fallback(); }
|
||||
|
||||
bool shouldRedirectTo_setup() { return ESPEasyWiFi.shouldRedirectTo_setup(); }
|
||||
|
||||
# ifdef BOARD_HAS_SDIO_ESP_HOSTED
|
||||
|
||||
// ********************************************************************************
|
||||
@@ -225,13 +256,14 @@ String GetHostedFwVersion(EspHostTypes hostType)
|
||||
String GetHostedMCU()
|
||||
{
|
||||
// Function is not yet implemented in Arduino Core so emulate it here
|
||||
#if defined(CONFIG_ESP_HOSTED_CP_TARGET_ESP32C6) && CONFIG_ESP_HOSTED_CP_TARGET_ESP32C6==1
|
||||
# if defined(CONFIG_ESP_HOSTED_CP_TARGET_ESP32C6) && CONFIG_ESP_HOSTED_CP_TARGET_ESP32C6 == 1
|
||||
return String("ESP32-C6");
|
||||
#else
|
||||
# else
|
||||
|
||||
if (equals(F(CONFIG_ESP_HOSTED_IDF_SLAVE_TARGET), F("esp32c6"))) {
|
||||
return String("ESP32-C6");
|
||||
}
|
||||
#endif
|
||||
# endif // if defined(CONFIG_ESP_HOSTED_CP_TARGET_ESP32C6) && CONFIG_ESP_HOSTED_CP_TARGET_ESP32C6 == 1
|
||||
return String("Unknown");
|
||||
}
|
||||
|
||||
@@ -309,9 +341,9 @@ bool write_WiFi_Hosted_MCU_pins(KeyValueWriter*writer)
|
||||
writer->write(kv);
|
||||
} else {
|
||||
KeyValueStruct freq(F("SDIO Freq"), psdio_config->clock_freq_khz / 1000);
|
||||
#if FEATURE_TASKVALUE_UNIT_OF_MEASURE
|
||||
# if FEATURE_TASKVALUE_UNIT_OF_MEASURE
|
||||
freq.setUnit(UOM_MHz);
|
||||
#endif
|
||||
# endif
|
||||
writer->write(freq);
|
||||
writer->write({ F("SDIO D0"), psdio_config->pin_d0.pin });
|
||||
writer->write({ F("SDIO D1"), psdio_config->pin_d1.pin });
|
||||
@@ -320,9 +352,10 @@ bool write_WiFi_Hosted_MCU_pins(KeyValueWriter*writer)
|
||||
writer->write({ F("SDIO CLK"), psdio_config->pin_clk.pin });
|
||||
writer->write({ F("SDIO CMD"), psdio_config->pin_cmd.pin });
|
||||
writer->write({ F("SDIO RST"), psdio_config->pin_reset.pin });
|
||||
|
||||
// Hide TX/RX queue size for now as it is unclear what these mean
|
||||
//writer->write({ F("SDIO TX queue"), psdio_config->tx_queue_size });
|
||||
//writer->write({ F("SDIO RX queue"), psdio_config->rx_queue_size });
|
||||
// writer->write({ F("SDIO TX queue"), psdio_config->tx_queue_size });
|
||||
// writer->write({ F("SDIO RX queue"), psdio_config->rx_queue_size });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -477,31 +510,6 @@ bool wifiAPmodeActivelyUsed()
|
||||
// reconnect?
|
||||
}
|
||||
|
||||
void setupStaticIPconfig() {
|
||||
setUseStaticIP(WiFiUseStaticIP());
|
||||
|
||||
if (!WiFiUseStaticIP()) { return; }
|
||||
const IPAddress ip(Settings.IP);
|
||||
const IPAddress gw(Settings.Gateway);
|
||||
const IPAddress subnet(Settings.Subnet);
|
||||
const IPAddress dns(Settings.DNS);
|
||||
|
||||
// WiFiEventData.dns0_cache = dns;
|
||||
|
||||
WiFi.config(ip, gw, subnet, dns);
|
||||
# ifndef BUILD_NO_DEBUG
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
addLogMove(LOG_LEVEL_INFO, strformat(
|
||||
F("IP : Static IP : %s GW: %s SN: %s DNS: %s"),
|
||||
formatIP(ip).c_str(),
|
||||
formatIP(gw).c_str(),
|
||||
formatIP(subnet).c_str(),
|
||||
getValue(LabelType::DNS).c_str()));
|
||||
}
|
||||
# endif // ifndef BUILD_NO_DEBUG
|
||||
}
|
||||
|
||||
// ********************************************************************************
|
||||
// Formatting WiFi related strings
|
||||
// ********************************************************************************
|
||||
|
||||
@@ -36,10 +36,14 @@ namespace wifi {
|
||||
# else
|
||||
# define WIFI_CONNECTION_CONSIDERED_STABLE 60000 // in milliSeconds
|
||||
# endif // if FEATURE_CUSTOM_PROVISIONING
|
||||
# define WIFI_ALLOW_AP_AFTERBOOT_PERIOD 5 // in minutes
|
||||
//# define WIFI_ALLOW_AP_AFTERBOOT_PERIOD 5 // in minutes
|
||||
# define WIFI_SCAN_INTERVAL_AP_USED 125000 // in milliSeconds
|
||||
# define WIFI_SCAN_INTERVAL_MINIMAL 60000 // in milliSeconds
|
||||
|
||||
bool validWiFiSSID(const String& ssid);
|
||||
|
||||
bool validWiFiCredentials(const String& ssid, const String& pass);
|
||||
|
||||
|
||||
bool WiFiConnected();
|
||||
|
||||
@@ -52,6 +56,7 @@ void exitWiFi();
|
||||
void loopWiFi();
|
||||
|
||||
bool shouldStartAP_fallback();
|
||||
bool shouldRedirectTo_setup();
|
||||
|
||||
# ifdef BOARD_HAS_SDIO_ESP_HOSTED
|
||||
|
||||
@@ -108,7 +113,6 @@ bool setAPinternal(bool enable); // FIXME TD-er: Move to ESPEasyWifi_abstract
|
||||
void setUseStaticIP(bool enabled);
|
||||
bool WiFiUseStaticIP();
|
||||
bool wifiAPmodeActivelyUsed();
|
||||
void setupStaticIPconfig();
|
||||
String formatScanResult(int i,
|
||||
const String& separator);
|
||||
String formatScanResult(int i,
|
||||
|
||||
@@ -167,7 +167,15 @@ bool doSetAPinternal(bool enable)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Settings.ApCaptivePortal()) {
|
||||
if (ESPEasy::net::wifi::shouldRedirectTo_setup()) {
|
||||
# if FEATURE_DNS_SERVER
|
||||
|
||||
if (dnsServerActive) {
|
||||
dnsServerActive = false;
|
||||
dnsServer.stop();
|
||||
}
|
||||
# endif // if FEATURE_DNS_SERVER
|
||||
|
||||
# ifdef ESP32
|
||||
# if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 2)
|
||||
|
||||
|
||||
@@ -47,7 +47,13 @@ bool WiFi_pre_STA_setup()
|
||||
void doWiFiDisconnect() {
|
||||
uint8_t retry = 3;
|
||||
|
||||
while (!WiFi.disconnect(Settings.WiFiRestart_connection_lost()) && retry) {
|
||||
#ifdef BOARD_HAS_SDIO_ESP_HOSTED
|
||||
bool wifioff = true;
|
||||
#else
|
||||
bool wifioff = Settings.WiFiRestart_connection_lost();
|
||||
#endif
|
||||
|
||||
while (!WiFi.disconnect(wifioff) && retry) {
|
||||
--retry;
|
||||
delay(100);
|
||||
}
|
||||
@@ -207,7 +213,7 @@ bool doSetWifiMode(WiFiMode_t new_mode)
|
||||
const bool new_mode_AP_enabled = doWifiIsAP(new_mode);
|
||||
|
||||
if (doWifiIsAP(cur_mode) && !new_mode_AP_enabled) {
|
||||
eventQueue.add(F("WiFi#APmodeDisabled"));
|
||||
eventQueue.addDeDup(F("WiFi#APmodeDisabled"));
|
||||
}
|
||||
|
||||
if (doWifiIsAP(cur_mode) != new_mode_AP_enabled) {
|
||||
|
||||
@@ -42,13 +42,16 @@ bool WiFi_pre_STA_setup() {
|
||||
void doWiFiDisconnect() {
|
||||
// Only call disconnect when STA is active
|
||||
if (doWifiIsSTA(WiFi.getMode())) {
|
||||
wifi_station_disconnect();
|
||||
WiFi.disconnect(true);
|
||||
// wifi_station_disconnect();
|
||||
}
|
||||
/*
|
||||
station_config conf{};
|
||||
memset(&conf, 0, sizeof(conf));
|
||||
ETS_UART_INTR_DISABLE();
|
||||
wifi_station_set_config_current(&conf);
|
||||
ETS_UART_INTR_ENABLE();
|
||||
*/
|
||||
}
|
||||
|
||||
bool doWifiIsAP(WiFiMode_t wifimode) { return (wifimode == WIFI_AP) || (wifimode == WIFI_AP_STA); }
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "../Globals/Settings.h"
|
||||
|
||||
#include "../Helpers/DeepSleep.h"
|
||||
#include "../Helpers/ESPEasy_Storage.h"
|
||||
#include "../Helpers/Misc.h"
|
||||
|
||||
const __FlashStringHelper * Command_System_NoSleep(struct EventStruct *event, const char* Line)
|
||||
|
||||
@@ -33,6 +33,17 @@ void EventQueueStruct::add(const __FlashStringHelper *event, bool deduplicate)
|
||||
add(str, deduplicate);
|
||||
}
|
||||
|
||||
void EventQueueStruct::addDeDup(const String& event)
|
||||
{
|
||||
add(event, true);
|
||||
}
|
||||
|
||||
void EventQueueStruct::addDeDup(const __FlashStringHelper *event)
|
||||
{
|
||||
add(event, true);
|
||||
}
|
||||
|
||||
|
||||
void EventQueueStruct::addMove(String&& event, bool deduplicate)
|
||||
{
|
||||
if (!event.length()) { return; }
|
||||
|
||||
@@ -17,6 +17,11 @@ struct EventQueueStruct {
|
||||
void add(const __FlashStringHelper *event,
|
||||
bool deduplicate = false);
|
||||
|
||||
void addDeDup(const String& event);
|
||||
|
||||
void addDeDup(const __FlashStringHelper *event);
|
||||
|
||||
|
||||
void addMove(String&& event,
|
||||
bool deduplicate = false);
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "../Globals/Settings.h"
|
||||
#include "../Helpers/ESPEasy_time_calc.h"
|
||||
#include "../Helpers/Misc.h"
|
||||
#include "../Helpers/Networking.h"
|
||||
#include "../Helpers/StringConverter.h"
|
||||
#include "../Helpers/StringGenerator_System.h"
|
||||
|
||||
@@ -503,7 +504,7 @@ void NodesHandler::updateThisNode() {
|
||||
thisNode.distance = _distance;
|
||||
|
||||
#if FEATURE_USE_IPV6
|
||||
thisNode.hasIPv4 = thisNode.IP() != INADDR_NONE;
|
||||
thisNode.hasIPv4 = IPAddressSet(thisNode.IP()) && thisNode.IP().type() == IPv4;
|
||||
thisNode.hasIPv6_mac_based_link_local = ESPEasy::net::is_IPv6_link_local_from_MAC(thisNode.sta_mac);
|
||||
thisNode.hasIPv6_mac_based_link_global = ESPEasy::net::is_IPv6_global_from_MAC(thisNode.sta_mac);
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#include "../Globals/SecuritySettings.h"
|
||||
|
||||
#include "../../ESPEasy/net/wifi/ESPEasyWifi.h"
|
||||
|
||||
|
||||
SecurityStruct::SecurityStruct() {
|
||||
ZERO_FILL(WifiSSID);
|
||||
@@ -90,10 +92,12 @@ bool SecurityStruct::hasWiFiCredentials() const {
|
||||
}
|
||||
|
||||
bool SecurityStruct::hasWiFiCredentials(SecurityStruct::WiFiCredentialsSlot slot) const {
|
||||
|
||||
|
||||
if (slot == SecurityStruct::WiFiCredentialsSlot::first)
|
||||
return (WifiSSID[0] != 0 && !String(WifiSSID).equalsIgnoreCase(F("ssid")));
|
||||
return ESPEasy::net::wifi::validWiFiSSID(WifiSSID);
|
||||
if (slot == SecurityStruct::WiFiCredentialsSlot::second)
|
||||
return (WifiSSID2[0] != 0 && !String(WifiSSID2).equalsIgnoreCase(F("ssid")));
|
||||
return ESPEasy::net::wifi::validWiFiSSID(WifiSSID2);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#if FEATURE_STORE_CREDENTIALS_SEPARATE_FILE
|
||||
|
||||
# include "../../ESPEasy/net/wifi/ESPEasyWifi.h"
|
||||
|
||||
int SecurityStruct_deviceSpecific::maxLength(KeyType keyType)
|
||||
{
|
||||
switch (keyType)
|
||||
@@ -75,19 +77,83 @@ bool SecurityStruct_deviceSpecific::hasWiFiCredentials() const
|
||||
{
|
||||
for (uint8_t i = 0; i < MAX_EXTRA_WIFI_CREDENTIALS_SEPARATE_FILE; ++i)
|
||||
{
|
||||
if (hasWiFiCredentials(i)) return true;
|
||||
if (hasWiFiCredentials(i)) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SecurityStruct_deviceSpecific::hasWiFiCredentials(uint8_t index) const
|
||||
{
|
||||
if (index >= MAX_EXTRA_WIFI_CREDENTIALS_SEPARATE_FILE) { return false; }
|
||||
String ssid, pass;
|
||||
|
||||
if (!_kvs.getValue(createKey(KeyType::WiFi_SSID, index), ssid, KVS_StorageType::Enum::string_type) ||
|
||||
!_kvs.getValue(createKey(KeyType::WiFi_Password, index), pass, KVS_StorageType::Enum::string_type)) {
|
||||
return false;
|
||||
}
|
||||
return ESPEasy::net::wifi::validWiFiCredentials(ssid, pass);
|
||||
}
|
||||
|
||||
bool SecurityStruct_deviceSpecific::getWiFiCredentials(uint8_t index,
|
||||
String& ssid,
|
||||
String& passwd) const
|
||||
{
|
||||
return
|
||||
(index < MAX_EXTRA_WIFI_CREDENTIALS_SEPARATE_FILE) &&
|
||||
_kvs.hasKey(KVS_StorageType::Enum::string_type,
|
||||
createKey(KeyType::WiFi_SSID, index)) &&
|
||||
_kvs.hasKey(KVS_StorageType::Enum::string_type,
|
||||
createKey(KeyType::WiFi_Password, index));
|
||||
index < MAX_EXTRA_WIFI_CREDENTIALS_SEPARATE_FILE &&
|
||||
getCredentials(KeyType::WiFi_SSID, KeyType::WiFi_Password, index, ssid, passwd);
|
||||
}
|
||||
|
||||
void SecurityStruct_deviceSpecific::setWiFiCredentials(
|
||||
uint8_t index,
|
||||
const String& ssid,
|
||||
const String& passwd)
|
||||
{
|
||||
if (index < MAX_EXTRA_WIFI_CREDENTIALS_SEPARATE_FILE)
|
||||
{
|
||||
if (ESPEasy::net::wifi::validWiFiCredentials(ssid, passwd)) {
|
||||
setCredentials(
|
||||
KeyType::WiFi_SSID,
|
||||
KeyType::WiFi_Password,
|
||||
index,
|
||||
ssid,
|
||||
passwd);
|
||||
}
|
||||
else {
|
||||
_kvs.clearKey(
|
||||
KVS_StorageType::Enum::string_type,
|
||||
createKey(KeyType::WiFi_SSID, index));
|
||||
_kvs.clearKey(
|
||||
KVS_StorageType::Enum::string_type,
|
||||
createKey(KeyType::WiFi_Password, index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SecurityStruct_deviceSpecific::getControllerCredentials(uint8_t index,
|
||||
String& user,
|
||||
String& passwd) const
|
||||
{
|
||||
return
|
||||
(index < CONTROLLER_MAX) && getCredentials(
|
||||
KeyType::Controller_User,
|
||||
KeyType::Controller_Password,
|
||||
index,
|
||||
user,
|
||||
passwd);
|
||||
}
|
||||
|
||||
void SecurityStruct_deviceSpecific::setControllerCredentials(uint8_t index,
|
||||
const String& user,
|
||||
const String& passwd)
|
||||
{
|
||||
if (index < CONTROLLER_MAX) {
|
||||
setCredentials(
|
||||
KeyType::Controller_User,
|
||||
KeyType::Controller_Password,
|
||||
index,
|
||||
user,
|
||||
passwd);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -103,12 +169,12 @@ bool SecurityStruct_deviceSpecific::hasWiFiCredentials(uint8_t index) const
|
||||
bool SecurityStruct_deviceSpecific::getValue(
|
||||
KeyType keytype, uint8_t index, String& value) const
|
||||
{
|
||||
return _kvs.getValue(createKey(keytype, index), value);
|
||||
return _kvs.getValue(createKey(keytype, index), value, KVS_StorageType::Enum::string_type);
|
||||
}
|
||||
|
||||
void SecurityStruct_deviceSpecific::setValue(KeyType keytype, uint8_t index, const String& value)
|
||||
{
|
||||
_kvs.setValue(createKey(keytype, index), value);
|
||||
_kvs.setValue(createKey(keytype, index), value, KVS_StorageType::Enum::string_type);
|
||||
}
|
||||
|
||||
uint32_t SecurityStruct_deviceSpecific::createKey(KeyType keytype, uint16_t index)
|
||||
@@ -123,8 +189,8 @@ bool SecurityStruct_deviceSpecific::getCredentials(KeyType keytype_key,
|
||||
String& secret) const
|
||||
{
|
||||
return
|
||||
_kvs.getValue(createKey(keytype_key, index), key) &&
|
||||
_kvs.getValue(createKey(keytype_secret, index), secret);
|
||||
_kvs.getValue(createKey(keytype_key, index), key, KVS_StorageType::Enum::string_type) &&
|
||||
_kvs.getValue(createKey(keytype_secret, index), secret, KVS_StorageType::Enum::string_type);
|
||||
}
|
||||
|
||||
void SecurityStruct_deviceSpecific::setCredentials(KeyType keytype_key,
|
||||
@@ -133,8 +199,8 @@ void SecurityStruct_deviceSpecific::setCredentials(KeyType keytype_key,
|
||||
const String& key,
|
||||
const String& secret)
|
||||
{
|
||||
_kvs.setValue(createKey(keytype_key, index), key);
|
||||
_kvs.setValue(createKey(keytype_secret, index), secret);
|
||||
_kvs.setValue(createKey(keytype_key, index), key, KVS_StorageType::Enum::string_type);
|
||||
_kvs.setValue(createKey(keytype_secret, index), secret, KVS_StorageType::Enum::string_type);
|
||||
}
|
||||
|
||||
#endif // if FEATURE_STORE_CREDENTIALS_SEPARATE_FILE
|
||||
|
||||
@@ -53,63 +53,29 @@ public:
|
||||
|
||||
// Move all set WiFi credentials to free up first entry
|
||||
// Typically used for setup page.
|
||||
// void freeUpFirstWiFiCredentials(uint8_t index = 0);
|
||||
// void freeUpFirstWiFiCredentials(uint8_t index = 0);
|
||||
|
||||
bool getWiFiCredentials(uint8_t index,
|
||||
String& ssid,
|
||||
String& passwd) const
|
||||
{
|
||||
return
|
||||
index < MAX_EXTRA_WIFI_CREDENTIALS_SEPARATE_FILE &&
|
||||
getCredentials(KeyType::WiFi_SSID, KeyType::WiFi_Password, index, ssid, passwd);
|
||||
}
|
||||
String& passwd) const;
|
||||
|
||||
void setWiFiCredentials(
|
||||
uint8_t index,
|
||||
const String& ssid,
|
||||
const String& passwd)
|
||||
{
|
||||
if (index < MAX_EXTRA_WIFI_CREDENTIALS_SEPARATE_FILE)
|
||||
{
|
||||
setCredentials(
|
||||
KeyType::WiFi_SSID,
|
||||
KeyType::WiFi_Password,
|
||||
index,
|
||||
ssid,
|
||||
passwd);
|
||||
}
|
||||
}
|
||||
const String& passwd);
|
||||
|
||||
bool getControllerCredentials(uint8_t index,
|
||||
String& user,
|
||||
String& passwd) const
|
||||
{
|
||||
return
|
||||
(index < CONTROLLER_MAX) && getCredentials(
|
||||
KeyType::Controller_User,
|
||||
KeyType::Controller_Password,
|
||||
index,
|
||||
user,
|
||||
passwd);
|
||||
}
|
||||
String& passwd) const;
|
||||
|
||||
void setControllerCredentials(uint8_t index,
|
||||
const String& user,
|
||||
const String& passwd)
|
||||
{
|
||||
if (index < CONTROLLER_MAX) {
|
||||
setCredentials(
|
||||
KeyType::Controller_User,
|
||||
KeyType::Controller_Password,
|
||||
index,
|
||||
user,
|
||||
passwd);
|
||||
}
|
||||
}
|
||||
const String& passwd);
|
||||
|
||||
bool getValue(KeyType keytype,
|
||||
uint8_t index,
|
||||
String& value) const;
|
||||
|
||||
void setValue(KeyType keytype,
|
||||
uint8_t index,
|
||||
const String& value);
|
||||
|
||||
@@ -29,6 +29,7 @@ size_t KVS_StorageType::getStorageSizePerType(KVS_StorageType::Enum storageType)
|
||||
{
|
||||
case KVS_StorageType::Enum::not_set: break;
|
||||
case KVS_StorageType::Enum::string_type: break;
|
||||
case KVS_StorageType::Enum::ip_type: break;
|
||||
case KVS_StorageType::Enum::int8_type: return 4 + 1;
|
||||
case KVS_StorageType::Enum::uint8_type: return 4 + 1;
|
||||
case KVS_StorageType::Enum::int16_type: return 4 + 2;
|
||||
|
||||
@@ -23,6 +23,7 @@ public:
|
||||
float_type = 10,
|
||||
double_type = 11,
|
||||
bool_type = 12,
|
||||
ip_type = 13,
|
||||
|
||||
MAX_Type, // Leave this one after the generic type and before 'special' types
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#ifdef ESP32
|
||||
|
||||
# include "../Helpers/StringConverter.h"
|
||||
# include "../Helpers/Networking.h"
|
||||
|
||||
# include <esp_netif.h>
|
||||
|
||||
@@ -154,7 +155,7 @@ bool NWPlugin::get_subnet(NWPlugin::IP_type ip_type, NetworkInterface*networkInt
|
||||
if (!networkInterface) { return false; }
|
||||
IPAddress ip = get_IP_address(ip_type, networkInterface);
|
||||
|
||||
if (ip == INADDR_NONE) { return false; }
|
||||
if (!IPAddressSet(ip)) { return false; }
|
||||
|
||||
# if CONFIG_LWIP_IPV6
|
||||
|
||||
|
||||
@@ -127,8 +127,6 @@ void EspEasy_Console_t::reInit()
|
||||
|
||||
if (!mustHaveFallback) {
|
||||
if (_fallbackSerial._serial != nullptr) {
|
||||
_fallbackSerial._serial->flush();
|
||||
_fallbackSerial._serial->end();
|
||||
delete _fallbackSerial._serial;
|
||||
_fallbackSerial._serial = nullptr;
|
||||
somethingChanged = true;
|
||||
@@ -142,8 +140,6 @@ void EspEasy_Console_t::reInit()
|
||||
(_console_serial_txpin != Settings.console_serial_txpin) ||
|
||||
!mustHaveSerial) {
|
||||
if (_mainSerial._serial != nullptr) {
|
||||
_mainSerial._serial->flush();
|
||||
_mainSerial._serial->end();
|
||||
delete _mainSerial._serial;
|
||||
_mainSerial._serial = nullptr;
|
||||
somethingChanged = true;
|
||||
@@ -444,13 +440,3 @@ void EspEasy_Console_t::endPort()
|
||||
#endif // if USES_ESPEASY_CONSOLE_FALLBACK_PORT
|
||||
delay(10);
|
||||
}
|
||||
|
||||
int EspEasy_Console_t::availableForWrite()
|
||||
{
|
||||
auto serial = getPort();
|
||||
|
||||
if (serial != nullptr) {
|
||||
return serial->availableForWrite();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -47,8 +47,6 @@ private:
|
||||
|
||||
void endPort();
|
||||
|
||||
int availableForWrite();
|
||||
|
||||
uint32_t _baudrate = 115200u;
|
||||
EspEasy_Console_Port _mainSerial;
|
||||
|
||||
|
||||
@@ -148,6 +148,10 @@ bool EspEasy_Console_Port::process_serialWriteBuffer()
|
||||
|
||||
bool EspEasy_Console_Port::process_consoleInput(uint8_t SerialInByte)
|
||||
{
|
||||
if (!InputBuffer_Serial) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isprint(SerialInByte))
|
||||
{
|
||||
if (SerialInByteCounter < CONSOLE_INPUT_BUFFER_SIZE) { // add char to string if it still fits
|
||||
@@ -163,14 +167,16 @@ bool EspEasy_Console_Port::process_consoleInput(uint8_t SerialInByte)
|
||||
{
|
||||
// Ignore empty command
|
||||
if (SerialInByteCounter != 0) {
|
||||
InputBuffer_Serial[SerialInByteCounter] = 0; // serial data completed
|
||||
if (SerialInByteCounter < CONSOLE_INPUT_BUFFER_SIZE) {
|
||||
InputBuffer_Serial[SerialInByteCounter] = 0; // serial data completed
|
||||
|
||||
String cmd(InputBuffer_Serial);
|
||||
String cmd(InputBuffer_Serial);
|
||||
#if !FEATURE_COLORIZE_CONSOLE_LOGS
|
||||
Logging.consolePrintln(concat('>', cmd));
|
||||
Logging.consolePrintln(concat('>', cmd));
|
||||
#endif
|
||||
|
||||
ExecuteCommand_all({ EventValueSource::Enum::VALUE_SOURCE_SERIAL, std::move(cmd) }, true);
|
||||
ExecuteCommand_all({ EventValueSource::Enum::VALUE_SOURCE_SERIAL, std::move(cmd) }, true);
|
||||
}
|
||||
SerialInByteCounter = 0;
|
||||
InputBuffer_Serial[0] = 0; // serial data processed, clear buffer
|
||||
return true;
|
||||
|
||||
@@ -582,7 +582,9 @@ void fileSystemCheck()
|
||||
#ifndef BUILD_NO_RAM_TRACKER
|
||||
checkRAM(F("fileSystemCheck"));
|
||||
#endif // ifndef BUILD_NO_RAM_TRACKER
|
||||
# ifndef BUILD_NO_DEBUG
|
||||
addLog(LOG_LEVEL_INFO, F("FS : Mounting..."));
|
||||
#endif
|
||||
#if defined(ESP32) && defined(USE_LITTLEFS)
|
||||
|
||||
if ((getPartionCount(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS) != 0)
|
||||
@@ -593,7 +595,7 @@ void fileSystemCheck()
|
||||
#endif // if defined(ESP32) && defined(USE_LITTLEFS)
|
||||
{
|
||||
clearAllCaches();
|
||||
|
||||
# ifndef BUILD_NO_DEBUG
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
addLogMove(LOG_LEVEL_INFO, strformat(
|
||||
F("FS : "
|
||||
@@ -605,6 +607,7 @@ void fileSystemCheck()
|
||||
" mount successful, used %u bytes of %u"),
|
||||
SpiffsUsedBytes(), SpiffsTotalBytes()));
|
||||
}
|
||||
# endif
|
||||
|
||||
// Run garbage collection before any file is open.
|
||||
uint8_t retries = 3;
|
||||
@@ -711,7 +714,7 @@ bool Erase_WiFi_Calibration() {
|
||||
ESPEasy::net::wifi::setWifiMode(WIFI_OFF);
|
||||
if (!ESP.eraseConfig())
|
||||
return false;
|
||||
#ifndef LIMIT_BUILD_SIZE
|
||||
# ifndef BUILD_NO_DEBUG
|
||||
addLog(LOG_LEVEL_INFO, F("WiFi : Erased WiFi calibration data"));
|
||||
#endif
|
||||
#endif
|
||||
@@ -991,7 +994,7 @@ void afterloadSettings() {
|
||||
#ifdef ESP32
|
||||
// FIXME TD-er: Must also update hostname on other interfaces for ESP32
|
||||
#endif
|
||||
ESPEasy::net::CheckRunningServices(); // To update changes in hostname.
|
||||
ESPEasy::net::CheckRunningServices(true); // To update changes in hostname.
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
@@ -1064,8 +1067,6 @@ String LoadSettings()
|
||||
SecuritySettings_deviceSpecific.load();
|
||||
#endif
|
||||
|
||||
|
||||
// setupStaticIPconfig();
|
||||
// FIXME TD-er: Must check if static/dynamic IP was changed and trigger a reconnect? Or is a reboot better when changing those settings?
|
||||
afterloadSettings();
|
||||
SecuritySettings.validate();
|
||||
@@ -1446,7 +1447,7 @@ String SaveTaskSettings(taskIndex_t TaskIndex)
|
||||
reinterpret_cast<const uint8_t *>(&ExtraTaskSettings),
|
||||
sizeof(struct ExtraTaskSettingsStruct));
|
||||
|
||||
#ifndef LIMIT_BUILD_SIZE
|
||||
#ifndef BUILD_NO_DEBUG
|
||||
if (err.isEmpty()) {
|
||||
err = checkTaskSettings(TaskIndex);
|
||||
}
|
||||
@@ -1455,7 +1456,7 @@ String SaveTaskSettings(taskIndex_t TaskIndex)
|
||||
// FIXME TD-er: Is this still needed as it is also cleared on PLUGIN_INIT and PLUGIN_EXIT?
|
||||
UserVar.clear_computed(ExtraTaskSettings.TaskIndex);
|
||||
}
|
||||
#ifndef LIMIT_BUILD_SIZE
|
||||
#ifndef BUILD_NO_DEBUG
|
||||
else {
|
||||
addLog(LOG_LEVEL_INFO, F("Skip saving task settings, not changed"));
|
||||
}
|
||||
|
||||
@@ -9,6 +9,12 @@ void LongTermOnOffTimer::clear()
|
||||
resetCount();
|
||||
}
|
||||
|
||||
void LongTermOnOffTimer::reset()
|
||||
{
|
||||
clear();
|
||||
_changedSinceLastCheck = false;
|
||||
}
|
||||
|
||||
bool LongTermOnOffTimer::setOn()
|
||||
{
|
||||
if (isOn()) { return false; }
|
||||
@@ -43,7 +49,12 @@ bool LongTermOnOffTimer::set(bool onState)
|
||||
|
||||
bool LongTermOnOffTimer::forceSet(bool onState)
|
||||
{
|
||||
set(!onState);
|
||||
/*
|
||||
// TODO TD-er: Should we also change the timestamp?
|
||||
if (onState) _onTimer.setNow();
|
||||
else _offTimer.setNow();
|
||||
*/
|
||||
_changedSinceLastCheck = true;
|
||||
return set(onState);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,14 @@ class LongTermOnOffTimer
|
||||
{
|
||||
public:
|
||||
|
||||
// Clear all timers and counts
|
||||
// _changedSinceLastCheck will be set when values were set before calling clear()
|
||||
void clear();
|
||||
|
||||
// Reset to default
|
||||
// _changedSinceLastCheck is also set to false
|
||||
void reset();
|
||||
|
||||
void resetCount() { _changeToOffCount = 0; _changeToOnCount = 0; }
|
||||
|
||||
// Return true when state changed
|
||||
|
||||
@@ -167,7 +167,7 @@ void updateUDPport(bool force)
|
||||
// Or we may need to look into AsyncUDP as that allows to send to specific interfaces.
|
||||
const bool connected = ESPEasy::net::NWPluginCall(NWPlugin::Function::NWPLUGIN_WEBSERVER_SHOULD_RUN);
|
||||
//const bool connected = ESPEasy::net::NetworkConnected();
|
||||
if (!connected || lastUsedUDPPort != 0) {
|
||||
if (!connected || (Settings.UDPPort != lastUsedUDPPort)) {
|
||||
if (lastUsedUDPPort != 0) {
|
||||
portUDP.stop();
|
||||
lastUsedUDPPort = 0;
|
||||
@@ -180,7 +180,7 @@ void updateUDPport(bool force)
|
||||
}
|
||||
}
|
||||
|
||||
if (Settings.UDPPort != 0) {
|
||||
if ((Settings.UDPPort != lastUsedUDPPort) && Settings.UDPPort != 0) {
|
||||
if (portUDP.begin(Settings.UDPPort) == 0) {
|
||||
#ifndef BUILD_NO_DEBUG
|
||||
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
|
||||
@@ -1124,6 +1124,24 @@ void scrubDNS() {
|
||||
*/
|
||||
}
|
||||
|
||||
#ifdef ESP32
|
||||
bool IPAddressSet(const IPAddress& ip)
|
||||
{
|
||||
return !(ip == INADDR_NONE
|
||||
# if CONFIG_LWIP_IPV6
|
||||
|| ip == IN6ADDR_ANY
|
||||
# endif
|
||||
);
|
||||
}
|
||||
#endif
|
||||
#ifdef ESP8266
|
||||
bool IPAddressSet(const IPAddress& ip)
|
||||
{
|
||||
return !(ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool valid_DNS_address(const IPAddress& dns) {
|
||||
return /*dns.v4() != (uint32_t)0x00000000 && */
|
||||
dns != IPAddress((uint32_t)0xFD000000) &&
|
||||
@@ -1133,7 +1151,7 @@ bool valid_DNS_address(const IPAddress& dns) {
|
||||
// Global IPv6 prefixes currently start with 2xxx::
|
||||
(dns[0] & 0xF0) != 0x20 &&
|
||||
#endif // ifdef ESP32
|
||||
dns != INADDR_NONE;
|
||||
IPAddressSet(dns);
|
||||
}
|
||||
|
||||
bool setDNS(int index, const IPAddress& dns) {
|
||||
|
||||
@@ -196,6 +196,8 @@ bool connectClient(WiFiClient& client, IPAddress ip, uint16_t port, uint32_t tim
|
||||
|
||||
void scrubDNS();
|
||||
|
||||
bool IPAddressSet(const IPAddress& ip);
|
||||
|
||||
bool valid_DNS_address(const IPAddress& dns);
|
||||
|
||||
bool setDNS(int index, const IPAddress& dns);
|
||||
|
||||
@@ -43,7 +43,8 @@ void ESPEasy_Scheduler::setNetworkTimer(unsigned long msecFromNow
|
||||
{
|
||||
if (!validNetworkIndex(networkIndex)) { return; }
|
||||
|
||||
if (!Settings.getNetworkEnabled(networkIndex)) { return; }
|
||||
if (function != NWPlugin::Function::NWPLUGIN_EXIT &&
|
||||
!Settings.getNetworkEnabled(networkIndex)) { return; }
|
||||
|
||||
const NWPluginTimerID timerID(networkIndex, Par1, function);
|
||||
|
||||
|
||||
@@ -407,7 +407,7 @@ KeyValueStruct getKeyValue(LabelType::Enum label, bool extendedValue)
|
||||
}
|
||||
case LabelType::ENABLE_SERIAL_PORT_CONSOLE:
|
||||
{
|
||||
return KeyValueStruct(F("Enable Serial Port Console"), !!Settings.UseSerial);
|
||||
return KeyValueStruct(F("Enable Serial Port Console"), !!Settings.UseSerial); // Cast to bool to make sure it is shown as a checkmark
|
||||
}
|
||||
case LabelType::CONSOLE_SERIAL_PORT:
|
||||
{
|
||||
@@ -416,7 +416,7 @@ KeyValueStruct getKeyValue(LabelType::Enum label, bool extendedValue)
|
||||
#if USES_ESPEASY_CONSOLE_FALLBACK_PORT
|
||||
case LabelType::CONSOLE_FALLBACK_TO_SERIAL0:
|
||||
{
|
||||
return KeyValueStruct(F("Fallback to Serial 0"), Settings.console_serial0_fallback);
|
||||
return KeyValueStruct(F("Fallback to Serial 0"), !!Settings.console_serial0_fallback); // Cast to bool to make sure it is shown as a checkmark
|
||||
}
|
||||
case LabelType::CONSOLE_FALLBACK_PORT:
|
||||
{
|
||||
@@ -752,7 +752,10 @@ KeyValueStruct getKeyValue(LabelType::Enum label, bool extendedValue)
|
||||
}
|
||||
case LabelType::RESTART_WIFI_LOST_CONN:
|
||||
{
|
||||
#ifndef BOARD_HAS_SDIO_ESP_HOSTED
|
||||
// Disable option for ESP-hosted WiFi as this always needs to restart when forcing disconnect.
|
||||
return KeyValueStruct(F("Restart WiFi Lost Conn"), Settings.WiFiRestart_connection_lost());
|
||||
#endif
|
||||
}
|
||||
case LabelType::FORCE_WIFI_NOSLEEP:
|
||||
{
|
||||
@@ -1041,10 +1044,19 @@ KeyValueStruct getKeyValue(LabelType::Enum label, bool extendedValue)
|
||||
uint32_t maxSketchSize;
|
||||
bool use2step;
|
||||
OTA_possible(maxSketchSize, use2step);
|
||||
str += strformat(
|
||||
F("%d [kB] (%d kB not used)"),
|
||||
(getSketchSize() >> 10),
|
||||
(maxSketchSize - getSketchSize()) >> 10);
|
||||
const uint32_t sketchsize_kB = getSketchSize() >> 10;
|
||||
maxSketchSize >>= 10;
|
||||
|
||||
if (maxSketchSize >= sketchsize_kB)
|
||||
str += strformat(
|
||||
F("%d [kB] (%d kB not used)"),
|
||||
sketchsize_kB,
|
||||
(maxSketchSize - sketchsize_kB));
|
||||
else
|
||||
str += strformat(
|
||||
F("%d [kB]"),
|
||||
sketchsize_kB);
|
||||
|
||||
} else {
|
||||
str = (getSketchSize() >> 10);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# include "../Helpers/KeyValueWriter.h"
|
||||
# include "../Helpers/StringConverter.h"
|
||||
# include "../Helpers/StringConverter_Numerical.h"
|
||||
|
||||
# include "../Helpers/Networking.h"
|
||||
|
||||
bool ESPEasy_key_value_store::isEmpty() const
|
||||
{
|
||||
@@ -138,7 +138,7 @@ bool ESPEasy_key_value_store::load(
|
||||
sizePerType = KVS_StorageType::getStorageSizePerType(storageType);
|
||||
key = KVS_StorageType::getKey_from_combined_key(combined_key.getUint32());
|
||||
|
||||
if ((sizePerType < 4) && (storageType != KVS_StorageType::Enum::string_type)) {
|
||||
if ((sizePerType < 4) && ((storageType != KVS_StorageType::Enum::string_type) && (storageType != KVS_StorageType::Enum::ip_type))) {
|
||||
// Should not happen as those should not be stored in the file
|
||||
_state = State::ErrorOnLoad;
|
||||
# ifndef BUILD_NO_DEBUG
|
||||
@@ -165,6 +165,7 @@ bool ESPEasy_key_value_store::load(
|
||||
}
|
||||
|
||||
case KVS_StorageType::Enum::string_type:
|
||||
case KVS_StorageType::Enum::ip_type:
|
||||
{
|
||||
if (bytesLeftPartialString == 0) {
|
||||
// Found new string type
|
||||
@@ -211,7 +212,7 @@ bool ESPEasy_key_value_store::load(
|
||||
}
|
||||
|
||||
if ((bytesLeftPartialString == 0) && (partialString.length() > 0)) {
|
||||
setValue(key, std::move(partialString));
|
||||
setValue(key, std::move(partialString), storageType);
|
||||
partialString.clear();
|
||||
|
||||
// ++bufPos; // Skip over nul-termination char
|
||||
@@ -427,10 +428,10 @@ bool ESPEasy_key_value_store::store(
|
||||
|
||||
} else if (it_4byte != _4byte_data.end()) {
|
||||
// Write 4-byte data
|
||||
uint32_t combined_key = it_4byte->first;
|
||||
uint32_t combined_key = it_4byte->first;
|
||||
KVS_StorageType::Enum storageType = KVS_StorageType::get_StorageType_from_combined_key(combined_key);
|
||||
const uint32_t key = KVS_StorageType::getKey_from_combined_key(combined_key);
|
||||
const size_t sizePerType = KVS_StorageType::getStorageSizePerType(storageType);
|
||||
const uint32_t key = KVS_StorageType::getKey_from_combined_key(combined_key);
|
||||
const size_t sizePerType = KVS_StorageType::getStorageSizePerType(storageType);
|
||||
|
||||
if (sizePerType >= 4) {
|
||||
if ((buffer.size() - bufPos) < sizePerType) {
|
||||
@@ -552,7 +553,7 @@ bool ESPEasy_key_value_store::hasKey(KVS_StorageType::Enum storageType, uint32_t
|
||||
|
||||
const uint32_t combined_key = KVS_StorageType::combine_StorageType_and_key(storageType, key);
|
||||
|
||||
if (storageType == KVS_StorageType::Enum::string_type)
|
||||
if ((storageType == KVS_StorageType::Enum::string_type) || (storageType == KVS_StorageType::Enum::ip_type))
|
||||
{
|
||||
return _string_data.find(combined_key) != _string_data.end();
|
||||
}
|
||||
@@ -569,6 +570,46 @@ bool ESPEasy_key_value_store::hasKey(KVS_StorageType::Enum storageType, uint32_t
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ESPEasy_key_value_store::clearKey(KVS_StorageType::Enum storageType, uint32_t key)
|
||||
{
|
||||
if (!hasKey(storageType, key)) { return false; }
|
||||
|
||||
const uint32_t combined_key = KVS_StorageType::combine_StorageType_and_key(storageType, key);
|
||||
|
||||
if ((storageType == KVS_StorageType::Enum::string_type) || (storageType == KVS_StorageType::Enum::ip_type))
|
||||
{
|
||||
auto it = _string_data.find(combined_key);
|
||||
|
||||
if (it != _string_data.end()) {
|
||||
_state = State::Changed;
|
||||
_string_data.erase(it);
|
||||
updateHasStorageType(storageType);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
const size_t size = KVS_StorageType::getStorageSizePerType(storageType);
|
||||
|
||||
if (size == 12)
|
||||
{
|
||||
auto it = _8byte_data.find(combined_key);
|
||||
|
||||
if (it != _8byte_data.end()) {
|
||||
_state = State::Changed;
|
||||
_8byte_data.erase(it);
|
||||
updateHasStorageType(storageType);
|
||||
}
|
||||
} else if (size >= 4) {
|
||||
auto it = _4byte_data.find(combined_key);
|
||||
|
||||
if (it != _4byte_data.end()) {
|
||||
_state = State::Changed;
|
||||
_4byte_data.erase(it);
|
||||
updateHasStorageType(storageType);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
KVS_StorageType::Enum ESPEasy_key_value_store::getStorageType(uint32_t key) const
|
||||
{
|
||||
uint32_t cached_bitmap = _storage_type_present_cache;
|
||||
@@ -586,21 +627,26 @@ KVS_StorageType::Enum ESPEasy_key_value_store::getStorageType(uint32_t key) cons
|
||||
}
|
||||
return KVS_StorageType::Enum::not_set;
|
||||
}
|
||||
#define KVS_STRINGPAIR_SEPARATOR ((char)1)
|
||||
|
||||
# define KVS_STRINGPAIR_SEPARATOR ((char)1)
|
||||
|
||||
bool ESPEasy_key_value_store::getValue(uint32_t key, StringPair& stringPair) const
|
||||
{
|
||||
String str;
|
||||
if (!getValue(key, str)) {
|
||||
|
||||
if (!getValue(key, str, KVS_StorageType::Enum::string_type)) {
|
||||
return false;
|
||||
}
|
||||
const int separatorPos = str.indexOf(KVS_STRINGPAIR_SEPARATOR);
|
||||
if (separatorPos < 0) return false;
|
||||
stringPair.first = str.substring(0, separatorPos);
|
||||
|
||||
if (separatorPos < 0) { return false; }
|
||||
stringPair.first = str.substring(0, separatorPos);
|
||||
stringPair.second = str.substring(separatorPos + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ESPEasy_key_value_store::setValue(uint32_t key, const StringPair& stringPair)
|
||||
void ESPEasy_key_value_store::setValue(
|
||||
uint32_t key, const StringPair& stringPair)
|
||||
{
|
||||
String str;
|
||||
str.reserve(stringPair.first.length() + 1 + stringPair.second.length());
|
||||
@@ -609,12 +655,14 @@ void ESPEasy_key_value_store::setValue(uint32_t key, const StringPair& stringPai
|
||||
str += stringPair.second;
|
||||
setValue(key, str);
|
||||
}
|
||||
#undef KVS_STRINGPAIR_SEPARATOR
|
||||
|
||||
bool ESPEasy_key_value_store::getValue(uint32_t key, String& value) const
|
||||
# undef KVS_STRINGPAIR_SEPARATOR
|
||||
|
||||
bool ESPEasy_key_value_store::getValue(
|
||||
uint32_t key, String& value, KVS_StorageType::Enum storageType) const
|
||||
{
|
||||
const uint32_t combined_key = KVS_StorageType::combine_StorageType_and_key(
|
||||
KVS_StorageType::Enum::string_type,
|
||||
storageType,
|
||||
key);
|
||||
|
||||
auto it = _string_data.find(combined_key);
|
||||
@@ -624,15 +672,20 @@ bool ESPEasy_key_value_store::getValue(uint32_t key, String& value) const
|
||||
return true;
|
||||
}
|
||||
|
||||
void ESPEasy_key_value_store::setValue(uint32_t key, const String& value) { setValue(key, String(value)); }
|
||||
void ESPEasy_key_value_store::setValue(
|
||||
uint32_t key, const String& value,
|
||||
KVS_StorageType::Enum storageType) { setValue(key, String(value), storageType); }
|
||||
|
||||
void ESPEasy_key_value_store::setValue(uint32_t key,
|
||||
const __FlashStringHelper*value) { setValue(key, String(value)); }
|
||||
void ESPEasy_key_value_store::setValue(
|
||||
uint32_t key,
|
||||
const __FlashStringHelper*value,
|
||||
KVS_StorageType::Enum storageType) { setValue(key, String(value), storageType); }
|
||||
|
||||
void ESPEasy_key_value_store::setValue(uint32_t key, String&& value)
|
||||
void ESPEasy_key_value_store::setValue(
|
||||
uint32_t key, String&& value, KVS_StorageType::Enum storageType)
|
||||
{
|
||||
const uint32_t combined_key = KVS_StorageType::combine_StorageType_and_key(
|
||||
KVS_StorageType::Enum::string_type,
|
||||
storageType,
|
||||
key);
|
||||
auto it = _string_data.find(combined_key);
|
||||
|
||||
@@ -646,12 +699,26 @@ void ESPEasy_key_value_store::setValue(uint32_t key, String&& value)
|
||||
_state = State::Changed;
|
||||
}
|
||||
}
|
||||
setHasStorageType(KVS_StorageType::Enum::string_type);
|
||||
setHasStorageType(storageType);
|
||||
}
|
||||
|
||||
bool ESPEasy_key_value_store::getValue(uint32_t key, IPAddress& value) const
|
||||
{
|
||||
String ip_str;
|
||||
|
||||
if (!getValue(key, ip_str, KVS_StorageType::Enum::ip_type)) { return false; }
|
||||
return value.fromString(ip_str);
|
||||
}
|
||||
|
||||
void ESPEasy_key_value_store::setValue(uint32_t key, const IPAddress& value)
|
||||
{
|
||||
if (IPAddressSet(value)) { setValue(key, value.toString(), KVS_StorageType::Enum::ip_type); }
|
||||
else { clearKey(KVS_StorageType::Enum::ip_type, key); }
|
||||
}
|
||||
|
||||
ESPEasy_key_value_store::map_4byte_data::const_iterator ESPEasy_key_value_store::get4byteIterator(
|
||||
KVS_StorageType::Enum storageType,
|
||||
uint32_t key) const
|
||||
uint32_t key) const
|
||||
{
|
||||
if (!hasStorageType(storageType)) { return _4byte_data.end(); }
|
||||
const uint32_t combined_key = KVS_StorageType::combine_StorageType_and_key(storageType, key);
|
||||
@@ -660,37 +727,37 @@ ESPEasy_key_value_store::map_4byte_data::const_iterator ESPEasy_key_value_store:
|
||||
|
||||
ESPEasy_key_value_store::map_8byte_data::const_iterator ESPEasy_key_value_store::get8byteIterator(
|
||||
KVS_StorageType::Enum storageType,
|
||||
uint32_t key) const
|
||||
uint32_t key) const
|
||||
{
|
||||
if (!hasStorageType(storageType)) { return _8byte_data.end(); }
|
||||
const uint32_t combined_key = KVS_StorageType::combine_StorageType_and_key(storageType, key);
|
||||
return _8byte_data.find(combined_key);
|
||||
}
|
||||
|
||||
# define GET_4BYTE_TYPE(T, GF) \
|
||||
# define GET_4BYTE_TYPE(T, GF) \
|
||||
auto it = get4byteIterator(KVS_StorageType::Enum::T, key); \
|
||||
if (it == _4byte_data.end()) return false; \
|
||||
value = it->second.GF(); \
|
||||
return true; \
|
||||
if (it == _4byte_data.end()) return false; \
|
||||
value = it->second.GF(); \
|
||||
return true; \
|
||||
|
||||
# define GET_8BYTE_TYPE(T, GF) \
|
||||
# define GET_8BYTE_TYPE(T, GF) \
|
||||
auto it = get8byteIterator(KVS_StorageType::Enum::T, key); \
|
||||
if (it == _8byte_data.end()) return false; \
|
||||
value = it->second.GF(); \
|
||||
return true; \
|
||||
if (it == _8byte_data.end()) return false; \
|
||||
value = it->second.GF(); \
|
||||
return true; \
|
||||
|
||||
|
||||
# define SET_4BYTE_TYPE(T, SF) \
|
||||
const uint32_t combined_key = KVS_StorageType::combine_StorageType_and_key( \
|
||||
KVS_StorageType::Enum::T, key); \
|
||||
if (_4byte_data[combined_key].SF(value)) _state = State::Changed; \
|
||||
# define SET_4BYTE_TYPE(T, SF) \
|
||||
const uint32_t combined_key = KVS_StorageType::combine_StorageType_and_key( \
|
||||
KVS_StorageType::Enum::T, key); \
|
||||
if (_4byte_data[combined_key].SF(value)) _state = State::Changed; \
|
||||
setHasStorageType(KVS_StorageType::Enum::T);
|
||||
|
||||
|
||||
# define SET_8BYTE_TYPE(T, SF) \
|
||||
const uint32_t combined_key = KVS_StorageType::combine_StorageType_and_key( \
|
||||
KVS_StorageType::Enum::T, key); \
|
||||
if (_8byte_data[combined_key].SF(value)) _state = State::Changed; \
|
||||
# define SET_8BYTE_TYPE(T, SF) \
|
||||
const uint32_t combined_key = KVS_StorageType::combine_StorageType_and_key( \
|
||||
KVS_StorageType::Enum::T, key); \
|
||||
if (_8byte_data[combined_key].SF(value)) _state = State::Changed; \
|
||||
setHasStorageType(KVS_StorageType::Enum::T);
|
||||
|
||||
bool ESPEasy_key_value_store::getValue(uint32_t key, int8_t& value) const
|
||||
@@ -788,7 +855,8 @@ bool ESPEasy_key_value_store::getValueAsString(const KVS_StorageType::Enum& stor
|
||||
switch (storageType)
|
||||
{
|
||||
case KVS_StorageType::Enum::string_type:
|
||||
return getValue(key, value);
|
||||
case KVS_StorageType::Enum::ip_type:
|
||||
return getValue(key, value, storageType);
|
||||
|
||||
case KVS_StorageType::Enum::bool_type:
|
||||
case KVS_StorageType::Enum::int8_type:
|
||||
@@ -856,15 +924,15 @@ bool ESPEasy_key_value_store::getValueAsString(uint32_t key, String& value) cons
|
||||
return getValueAsString(getStorageType(key), key, value);
|
||||
}
|
||||
|
||||
# define GET_TYPE_AS_INT64(T, CT) \
|
||||
# define GET_TYPE_AS_INT64(T, CT) \
|
||||
case KVS_StorageType::Enum::T: \
|
||||
{ \
|
||||
CT v{}; \
|
||||
if (getValue(key, v)) { \
|
||||
value = v; \
|
||||
return true; \
|
||||
} \
|
||||
break; \
|
||||
{ \
|
||||
CT v{}; \
|
||||
if (getValue(key, v)) { \
|
||||
value = v; \
|
||||
return true; \
|
||||
} \
|
||||
break; \
|
||||
}
|
||||
|
||||
bool ESPEasy_key_value_store::getValueAsInt(
|
||||
@@ -920,12 +988,12 @@ int64_t ESPEasy_key_value_store::getValueAsInt(uint32_t key) const
|
||||
return getValueAsInt_or_default(key, 0);
|
||||
}
|
||||
|
||||
# define GET_4BYTE_INT_TYPE_FROM_STRING(T, CT) \
|
||||
case KVS_StorageType::Enum::T: \
|
||||
{ \
|
||||
CT v(value.toInt()); \
|
||||
setValue(key, v); \
|
||||
break; \
|
||||
# define GET_4BYTE_INT_TYPE_FROM_STRING(T, CT) \
|
||||
case KVS_StorageType::Enum::T: \
|
||||
{ \
|
||||
CT v(value.toInt()); \
|
||||
setValue(key, v); \
|
||||
break; \
|
||||
}
|
||||
|
||||
void ESPEasy_key_value_store::setValue(const KVS_StorageType::Enum& storageType, uint32_t key, const String& value)
|
||||
@@ -933,8 +1001,15 @@ void ESPEasy_key_value_store::setValue(const KVS_StorageType::Enum& storageType,
|
||||
switch (storageType)
|
||||
{
|
||||
case KVS_StorageType::Enum::string_type:
|
||||
setValue(key, value);
|
||||
setValue(key, value, storageType);
|
||||
break;
|
||||
case KVS_StorageType::Enum::ip_type:
|
||||
{
|
||||
IPAddress ip;
|
||||
ip.fromString(value);
|
||||
setValue(key, ip);
|
||||
break;
|
||||
}
|
||||
GET_4BYTE_INT_TYPE_FROM_STRING(int8_type, int8_t)
|
||||
GET_4BYTE_INT_TYPE_FROM_STRING(uint8_type, uint8_t)
|
||||
GET_4BYTE_INT_TYPE_FROM_STRING(int16_type, int16_t)
|
||||
@@ -972,7 +1047,7 @@ void ESPEasy_key_value_store::setValue(const KVS_StorageType::Enum& storageType,
|
||||
}
|
||||
|
||||
bool ESPEasy_key_value_store::getValue(
|
||||
KVS_StorageType::Enum & storageType,
|
||||
KVS_StorageType::Enum & storageType,
|
||||
uint32_t key,
|
||||
ESPEasy_key_value_store_4byte_data_t& value) const
|
||||
{
|
||||
@@ -984,7 +1059,7 @@ bool ESPEasy_key_value_store::getValue(
|
||||
}
|
||||
|
||||
void ESPEasy_key_value_store::setValue(
|
||||
KVS_StorageType::Enum & storageType,
|
||||
KVS_StorageType::Enum & storageType,
|
||||
uint32_t key,
|
||||
const ESPEasy_key_value_store_4byte_data_t& value)
|
||||
{
|
||||
@@ -1002,7 +1077,7 @@ void ESPEasy_key_value_store::setValue(
|
||||
}
|
||||
|
||||
bool ESPEasy_key_value_store::getValue(
|
||||
KVS_StorageType::Enum & storageType,
|
||||
KVS_StorageType::Enum & storageType,
|
||||
uint32_t key,
|
||||
ESPEasy_key_value_store_8byte_data_t& value) const
|
||||
{
|
||||
@@ -1014,7 +1089,7 @@ bool ESPEasy_key_value_store::getValue(
|
||||
}
|
||||
|
||||
void ESPEasy_key_value_store::setValue(
|
||||
KVS_StorageType::Enum & storageType,
|
||||
KVS_StorageType::Enum & storageType,
|
||||
uint32_t key,
|
||||
const ESPEasy_key_value_store_8byte_data_t& value)
|
||||
{
|
||||
@@ -1065,6 +1140,59 @@ void ESPEasy_key_value_store::setHasStorageType(KVS_StorageType::Enum storageTyp
|
||||
// TODO TD-er: Whenever this is called, there has been a change, so invalidate checksum
|
||||
}
|
||||
|
||||
void ESPEasy_key_value_store::updateHasStorageType(KVS_StorageType::Enum storageType)
|
||||
{
|
||||
if ((storageType == KVS_StorageType::Enum::bool_true) ||
|
||||
(storageType == KVS_StorageType::Enum::bool_false)) {
|
||||
storageType = KVS_StorageType::Enum::bool_type;
|
||||
}
|
||||
const uint32_t bitnr = static_cast<uint32_t>(storageType);
|
||||
constexpr uint32_t max_bitnr = static_cast<uint32_t>(KVS_StorageType::Enum::MAX_Type);
|
||||
|
||||
if (bitnr >= max_bitnr) { return; }
|
||||
|
||||
const uint32_t old_cache = _storage_type_present_cache;
|
||||
bitClear(_storage_type_present_cache, bitnr);
|
||||
|
||||
if ((storageType == KVS_StorageType::Enum::string_type) || (storageType == KVS_StorageType::Enum::ip_type))
|
||||
{
|
||||
bool done = false;
|
||||
|
||||
for (auto it = _string_data.begin(); !done && it != _string_data.end(); ++it) {
|
||||
if (storageType == KVS_StorageType::get_StorageType_from_combined_key(it->first)) {
|
||||
bitSet(_storage_type_present_cache, bitnr);
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const size_t size = KVS_StorageType::getStorageSizePerType(storageType);
|
||||
|
||||
if (size == 12) {
|
||||
bool done = false;
|
||||
|
||||
for (auto it = _8byte_data.begin(); !done && it != _8byte_data.end(); ++it) {
|
||||
if (storageType == KVS_StorageType::get_StorageType_from_combined_key(it->first)) {
|
||||
bitSet(_storage_type_present_cache, bitnr);
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bool done = false;
|
||||
|
||||
for (auto it = _4byte_data.begin(); !done && it != _4byte_data.end(); ++it) {
|
||||
if (storageType == KVS_StorageType::get_StorageType_from_combined_key(it->first)) {
|
||||
bitSet(_storage_type_present_cache, bitnr);
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (old_cache != _storage_type_present_cache) {
|
||||
_state = State::Changed;
|
||||
}
|
||||
}
|
||||
|
||||
void ESPEasy_key_value_store::dump() const
|
||||
{
|
||||
addLog(LOG_LEVEL_INFO, strformat(F("KVS: Payload Storage size : %d"), getPayloadStorageSize()));
|
||||
@@ -1144,5 +1272,4 @@ void ESPEasy_key_value_store::dump() const
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // if FEATURE_ESPEASY_KEY_VALUE_STORE
|
||||
|
||||
@@ -43,17 +43,17 @@ public:
|
||||
|
||||
};
|
||||
|
||||
State getState() const { return _state; }
|
||||
State getState() const { return _state; }
|
||||
|
||||
bool isEmpty() const;
|
||||
bool isEmpty() const;
|
||||
|
||||
void clear();
|
||||
void clear();
|
||||
|
||||
|
||||
bool load(SettingsType::Enum settingsType,
|
||||
int index,
|
||||
uint32_t offset_in_block,
|
||||
uint16_t id_to_match);
|
||||
bool load(SettingsType::Enum settingsType,
|
||||
int index,
|
||||
uint32_t offset_in_block,
|
||||
uint16_t id_to_match);
|
||||
bool store(SettingsType::Enum settingsType,
|
||||
int index,
|
||||
uint32_t offset_in_block,
|
||||
@@ -64,7 +64,10 @@ public:
|
||||
|
||||
// Check to see if there is a key stored with given storage type
|
||||
bool hasKey(KVS_StorageType::Enum storageType,
|
||||
uint32_t key) const;
|
||||
uint32_t key) const;
|
||||
|
||||
bool clearKey(KVS_StorageType::Enum storageType,
|
||||
uint32_t key);
|
||||
|
||||
// Try to find a key and get its storage type or 'not_set' if the key is not present
|
||||
KVS_StorageType::Enum getStorageType(uint32_t key) const;
|
||||
@@ -81,14 +84,24 @@ public:
|
||||
void setValue(uint32_t key,
|
||||
const StringPair& stringPair);
|
||||
|
||||
bool getValue(uint32_t key,
|
||||
String & value) const;
|
||||
void setValue(uint32_t key,
|
||||
const String& value);
|
||||
bool getValue(uint32_t key,
|
||||
String & value,
|
||||
KVS_StorageType::Enum storageType) const;
|
||||
void setValue(uint32_t key,
|
||||
const String & value,
|
||||
KVS_StorageType::Enum storageType);
|
||||
void setValue(uint32_t key,
|
||||
const __FlashStringHelper*value);
|
||||
void setValue(uint32_t key,
|
||||
String&& value);
|
||||
const __FlashStringHelper*value,
|
||||
KVS_StorageType::Enum storageType);
|
||||
void setValue(uint32_t key,
|
||||
String && value,
|
||||
KVS_StorageType::Enum storageType);
|
||||
|
||||
bool getValue(uint32_t key,
|
||||
IPAddress& value) const;
|
||||
void setValue(uint32_t key,
|
||||
const IPAddress& value);
|
||||
|
||||
|
||||
bool getValue(uint32_t key,
|
||||
int8_t & value) const;
|
||||
@@ -149,8 +162,8 @@ public:
|
||||
// Generic get function for any given storageType/key and represent its value as a string.
|
||||
// Return false when storageType/key is not present.
|
||||
bool getValueAsString(const KVS_StorageType::Enum& storageType,
|
||||
uint32_t key,
|
||||
String & value) const;
|
||||
uint32_t key,
|
||||
String & value) const;
|
||||
|
||||
bool getValueAsString(uint32_t key,
|
||||
String & value) const;
|
||||
@@ -166,8 +179,8 @@ public:
|
||||
// Given value is a string representation of that storage type.
|
||||
// TODO TD-er: Implement
|
||||
void setValue(const KVS_StorageType::Enum& storageType,
|
||||
uint32_t key,
|
||||
const String & value);
|
||||
uint32_t key,
|
||||
const String & value);
|
||||
|
||||
String getLastError() const { return _lastError; }
|
||||
|
||||
@@ -175,19 +188,19 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
bool getValue(KVS_StorageType::Enum & storageType,
|
||||
bool getValue(KVS_StorageType::Enum & storageType,
|
||||
uint32_t key,
|
||||
ESPEasy_key_value_store_4byte_data_t& value) const;
|
||||
|
||||
void setValue(KVS_StorageType::Enum & storageType,
|
||||
void setValue(KVS_StorageType::Enum & storageType,
|
||||
uint32_t key,
|
||||
const ESPEasy_key_value_store_4byte_data_t& value);
|
||||
|
||||
bool getValue(KVS_StorageType::Enum & storageType,
|
||||
bool getValue(KVS_StorageType::Enum & storageType,
|
||||
uint32_t key,
|
||||
ESPEasy_key_value_store_8byte_data_t& value) const;
|
||||
|
||||
void setValue(KVS_StorageType::Enum & storageType,
|
||||
void setValue(KVS_StorageType::Enum & storageType,
|
||||
uint32_t key,
|
||||
const ESPEasy_key_value_store_8byte_data_t& value);
|
||||
|
||||
@@ -198,15 +211,17 @@ private:
|
||||
// Update cache to indicate we have at least one of the given storage type
|
||||
void setHasStorageType(KVS_StorageType::Enum storageType);
|
||||
|
||||
void updateHasStorageType(KVS_StorageType::Enum storageType);
|
||||
|
||||
typedef std::map<uint32_t, ESPEasy_key_value_store_4byte_data_t> map_4byte_data;
|
||||
typedef std::map<uint32_t, ESPEasy_key_value_store_8byte_data_t> map_8byte_data;
|
||||
|
||||
map_4byte_data::const_iterator get4byteIterator(
|
||||
KVS_StorageType::Enum storageType,
|
||||
uint32_t key) const;
|
||||
uint32_t key) const;
|
||||
map_8byte_data::const_iterator get8byteIterator(
|
||||
KVS_StorageType::Enum storageType,
|
||||
uint32_t key) const;
|
||||
uint32_t key) const;
|
||||
|
||||
String _lastError;
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ void handleNotFound() {
|
||||
if (captivePortal()) { // If captive portal redirect instead of displaying the error page.
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
// if Wifi setup, launch setup wizard if AP_DONT_FORCE_SETUP is not set.
|
||||
if (//WiFiEventData.wifiSetup &&
|
||||
Settings.ApCaptivePortal())
|
||||
@@ -35,6 +35,7 @@ void handleNotFound() {
|
||||
web_server.send_P(200, (PGM_P)F("text/html"), (PGM_P)F("<meta HTTP-EQUIV='REFRESH' content='0; url=/setup'>"));
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
#ifdef WEBSERVER_RULES
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
|
||||
#include "../Helpers/ESPEasy_Storage.h"
|
||||
#include "../Helpers/Hardware_device_info.h"
|
||||
#include "../Helpers/Networking.h"
|
||||
#include "../Helpers/OTA.h"
|
||||
#include "../Helpers/StringConverter.h"
|
||||
|
||||
@@ -126,6 +127,7 @@ void sendHeadandTail_stdtemplate(bool Tail, bool rebooting) {
|
||||
sendHeadandTail(F("TmplStd"), Tail, rebooting);
|
||||
|
||||
if (!Tail) {
|
||||
// TODO TD-er: Must check clientConnectedToAP()?
|
||||
if (!clientIPinSubnetDefaultNetwork() && ESPEasy::net::wifi::wifiAPmodeActivelyUsed()) {
|
||||
addHtmlError(F("Warning: Connected via AP"));
|
||||
}
|
||||
@@ -169,14 +171,16 @@ void sendHeadandTail_stdtemplate(bool Tail, bool rebooting) {
|
||||
}
|
||||
|
||||
bool captivePortal() {
|
||||
if (!Settings.ApCaptivePortal()) return false;
|
||||
const IPAddress client_localIP = web_server.client().localIP();
|
||||
const bool fromAP = client_localIP == apIP;
|
||||
const bool hasWiFiCredentials = SecuritySettings.hasWiFiCredentials();
|
||||
// We only need to check if a client connected here via AP
|
||||
// as currently we don't have any interface which allows forwarding
|
||||
// packets and thus acting as a gateway for others.
|
||||
if (!Settings.ApCaptivePortal() || !clientConnectedToAP()) return false;
|
||||
|
||||
#ifndef BUILD_NO_DEBUG
|
||||
addLog(LOG_LEVEL_DEBUG, concat(F("CaptivePortal: hostHeader: "), web_server.hostHeader()));
|
||||
#endif
|
||||
if (hasWiFiCredentials || !fromAP) {
|
||||
if (!ESPEasy::net::NetworkConnected())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -185,10 +189,11 @@ bool captivePortal() {
|
||||
&& !getValue(LabelType::M_DNS).equalsIgnoreCase(web_server.hostHeader())
|
||||
#endif
|
||||
) {
|
||||
const IPAddress client_localIP = web_server.client().localIP();
|
||||
String redirectURL = concat(F("http://"), formatIP(client_localIP));
|
||||
#ifdef WEBSERVER_SETUP
|
||||
|
||||
if (fromAP && !hasWiFiCredentials) {
|
||||
if (ESPEasy::net::wifi::shouldRedirectTo_setup()) {
|
||||
redirectURL += F("/setup");
|
||||
}
|
||||
#endif // ifdef WEBSERVER_SETUP
|
||||
@@ -201,6 +206,60 @@ bool captivePortal() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool clientConnectedToAP()
|
||||
{
|
||||
const IPAddress client_localIP = web_server.client().localIP();
|
||||
return IPAddressSet(client_localIP) && client_localIP == apIP;
|
||||
}
|
||||
|
||||
ESPEasy::net::networkIndex_t getNetworkIndex_ClientConnectsTo()
|
||||
{
|
||||
const IPAddress client_localIP = web_server.client().localIP();
|
||||
if (!IPAddressSet(client_localIP))
|
||||
return ESPEasy::net::INVALID_NETWORK_INDEX;
|
||||
if (client_localIP == apIP) {
|
||||
// Easy to check as this is a global variable
|
||||
return NETWORK_INDEX_WIFI_AP;
|
||||
}
|
||||
#ifdef ESP8266
|
||||
if (client_localIP == WiFi.localIP()) {
|
||||
return NETWORK_INDEX_WIFI_STA;
|
||||
}
|
||||
#endif
|
||||
#ifdef ESP32
|
||||
for (ESPEasy::net::networkIndex_t x = 0; x < NETWORK_MAX; ++x) {
|
||||
if (Settings.getNetworkEnabled(x)) {
|
||||
struct EventStruct TempEvent;
|
||||
TempEvent.NetworkIndex = x;
|
||||
String str;
|
||||
|
||||
if (ESPEasy::net::NWPluginCall(NWPlugin::Function::NWPLUGIN_GET_INTERFACE, &TempEvent, str))
|
||||
{
|
||||
const NWPlugin::IP_type ip_types[] = {
|
||||
NWPlugin::IP_type::inet,
|
||||
# if CONFIG_LWIP_IPV6
|
||||
NWPlugin::IP_type::ipv6_unknown,
|
||||
NWPlugin::IP_type::ipv6_global,
|
||||
NWPlugin::IP_type::ipv6_link_local,
|
||||
NWPlugin::IP_type::ipv6_site_local,
|
||||
NWPlugin::IP_type::ipv6_unique_local,
|
||||
NWPlugin::IP_type::ipv4_mapped_ipv6,
|
||||
# endif // if CONFIG_LWIP_IPV6
|
||||
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < NR_ELEMENTS(ip_types); ++i) {
|
||||
const IPAddress ip(NWPlugin::get_IP_address(ip_types[i], TempEvent.networkInterface));
|
||||
if (client_localIP == ip) return x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
return ESPEasy::net::INVALID_NETWORK_INDEX;
|
||||
}
|
||||
|
||||
// ********************************************************************************
|
||||
// Web Interface init
|
||||
// ********************************************************************************
|
||||
@@ -447,7 +506,7 @@ void setWebserverRunning(bool state) {
|
||||
#endif
|
||||
}
|
||||
webserverRunning = state;
|
||||
ESPEasy::net::CheckRunningServices(); // Uses webserverRunning state.
|
||||
ESPEasy::net::CheckRunningServices(true); // Uses webserverRunning state.
|
||||
}
|
||||
|
||||
void getWebPageTemplateDefault(const String& tmplName, WebTemplateParser& parser)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "../DataTypes/SettingsType.h"
|
||||
#include "../WebServer/WebTemplateParser.h"
|
||||
#include "../../ESPEasy/net/DataTypes/NetworkIndex.h"
|
||||
|
||||
|
||||
// Uncrustify must not be used on macros, so turn it off.
|
||||
@@ -33,6 +34,13 @@ void WebServerInit();
|
||||
// ********************************************************************************
|
||||
bool captivePortal();
|
||||
|
||||
bool clientConnectedToAP();
|
||||
|
||||
// Determine which network interface is being used by the client to access this ESPEasy node
|
||||
ESPEasy::net::networkIndex_t getNetworkIndex_ClientConnectsTo();
|
||||
|
||||
|
||||
|
||||
void setWebserverRunning(bool state);
|
||||
|
||||
void getWebPageTemplateDefault(const String& tmplName,
|
||||
|
||||
@@ -6,21 +6,21 @@
|
||||
# include "../WebServer/Markup_Forms.h"
|
||||
|
||||
WebFormItemParams::WebFormItemParams(
|
||||
const String & label,
|
||||
const String & id,
|
||||
const String & label,
|
||||
const String & id,
|
||||
KVS_StorageType::Enum storageType,
|
||||
uint32_t key)
|
||||
uint32_t key)
|
||||
: _label(label), _id(id), _storageType(storageType), _key(key) {}
|
||||
|
||||
WebFormItemParams::WebFormItemParams(
|
||||
const __FlashStringHelper *label,
|
||||
const __FlashStringHelper *id,
|
||||
KVS_StorageType::Enum storageType,
|
||||
uint32_t key)
|
||||
const __FlashStringHelper *label,
|
||||
const __FlashStringHelper *id,
|
||||
KVS_StorageType::Enum storageType,
|
||||
uint32_t key)
|
||||
: _label(label), _id(id), _storageType(storageType), _key(key) {}
|
||||
|
||||
# define CORRECT_RANGE(T, CT) \
|
||||
case KVS_StorageType::Enum::T: \
|
||||
case KVS_StorageType::Enum::T: \
|
||||
if (_max > std::numeric_limits<CT>::max()) _max = std::numeric_limits<CT>::max(); \
|
||||
if (_min < std::numeric_limits<CT>::min()) _min = std::numeric_limits<CT>::min(); \
|
||||
break;
|
||||
@@ -29,15 +29,15 @@ void WebFormItemParams::checkRanges()
|
||||
{
|
||||
switch (_storageType)
|
||||
{
|
||||
CORRECT_RANGE(int8_type, int8_t)
|
||||
CORRECT_RANGE(uint8_type, uint8_t)
|
||||
CORRECT_RANGE(int16_type, int16_t)
|
||||
CORRECT_RANGE(uint16_type, uint16_t)
|
||||
CORRECT_RANGE(int32_type, int32_t)
|
||||
CORRECT_RANGE(uint32_type, uint32_t)
|
||||
CORRECT_RANGE(float_type, float)
|
||||
CORRECT_RANGE(uint64_type, uint64_t)
|
||||
CORRECT_RANGE(int64_type, int64_t)
|
||||
CORRECT_RANGE(int8_type, int8_t)
|
||||
CORRECT_RANGE(uint8_type, uint8_t)
|
||||
CORRECT_RANGE(int16_type, int16_t)
|
||||
CORRECT_RANGE(uint16_type, uint16_t)
|
||||
CORRECT_RANGE(int32_type, int32_t)
|
||||
CORRECT_RANGE(uint32_type, uint32_t)
|
||||
CORRECT_RANGE(float_type, float)
|
||||
CORRECT_RANGE(uint64_type, uint64_t)
|
||||
CORRECT_RANGE(int64_type, int64_t)
|
||||
|
||||
// CORRECT_RANGE(double_type, double)
|
||||
default: break;
|
||||
@@ -52,6 +52,21 @@ bool showWebformItem(const ESPEasy_key_value_store& store,
|
||||
|
||||
switch (params._storageType)
|
||||
{
|
||||
case KVS_StorageType::Enum::ip_type:
|
||||
{
|
||||
IPAddress value;
|
||||
|
||||
if (!store.getValue(params._key, value) && !params._defaultStringValue.isEmpty())
|
||||
{
|
||||
value.fromString(params._defaultStringValue);
|
||||
}
|
||||
addFormIPBox(
|
||||
params._label,
|
||||
id,
|
||||
value);
|
||||
return true;
|
||||
}
|
||||
|
||||
case KVS_StorageType::Enum::string_type:
|
||||
{
|
||||
String value;
|
||||
@@ -175,15 +190,15 @@ void showFormSelector(const ESPEasy_key_value_store& store,
|
||||
selector.addFormSelector(params._label, params._id, value);
|
||||
}
|
||||
|
||||
void storeWebformItem(ESPEasy_key_value_store & store,
|
||||
uint32_t key,
|
||||
KVS_StorageType::Enum storageType,
|
||||
const __FlashStringHelper *id) { storeWebformItem(store, key, storageType, String(id)); }
|
||||
void storeWebformItem(ESPEasy_key_value_store & store,
|
||||
uint32_t key,
|
||||
KVS_StorageType::Enum storageType,
|
||||
const __FlashStringHelper *id) { storeWebformItem(store, key, storageType, String(id)); }
|
||||
|
||||
void storeWebformItem(ESPEasy_key_value_store & store,
|
||||
uint32_t key,
|
||||
KVS_StorageType::Enum storageType,
|
||||
const String & id)
|
||||
void storeWebformItem(ESPEasy_key_value_store& store,
|
||||
uint32_t key,
|
||||
KVS_StorageType::Enum storageType,
|
||||
const String & id)
|
||||
{
|
||||
String _id = id.isEmpty() ? concat(F("KVS_ID_"), key) : id;
|
||||
|
||||
@@ -193,7 +208,13 @@ void storeWebformItem(ESPEasy_key_value_store & store,
|
||||
}
|
||||
|
||||
if (hasArg(_id)) {
|
||||
store.setValue(storageType, key, webArg(_id));
|
||||
if (storageType == KVS_StorageType::Enum::ip_type) {
|
||||
IPAddress ip;
|
||||
ip.fromString(webArg(_id));
|
||||
store.setValue(key, ip);
|
||||
} else {
|
||||
store.setValue(storageType, key, webArg(_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "../Helpers/Hardware_GPIO.h"
|
||||
#include "../Helpers/Hardware_device_info.h"
|
||||
#include "../Helpers/Networking.h"
|
||||
#include "../Helpers/Numerical.h"
|
||||
#include "../Helpers/StringConverter.h"
|
||||
#include "../Helpers/StringGenerator_GPIO.h"
|
||||
@@ -380,35 +381,64 @@ bool getFormPassword(const String& id, String& password)
|
||||
return !equals(password, F(MARKUP_FORMS_PASSWORD_MASK_ASTERISKS));
|
||||
}
|
||||
|
||||
// ********************************************************************************
|
||||
// Add a IP Box form
|
||||
// ********************************************************************************
|
||||
void addFormIPBox(const __FlashStringHelper *label,
|
||||
const __FlashStringHelper *id,
|
||||
const uint8_t ip[4])
|
||||
{
|
||||
addFormIPBox(String(label), String(id), ip);
|
||||
}
|
||||
|
||||
void addFormTextBox(const String& label, const String& id, const String& value)
|
||||
{
|
||||
addRowLabel_tr_id(label, id);
|
||||
|
||||
addHtml(strformat(
|
||||
F("<input class='wide' type='text' name='%s' id='%s' value='%s'>"),
|
||||
id.c_str(),
|
||||
id.c_str(),
|
||||
value.c_str()
|
||||
));
|
||||
F("<input class='wide' type='text' name='%s' id='%s' value='%s'>"),
|
||||
id.c_str(),
|
||||
id.c_str(),
|
||||
value.c_str()
|
||||
));
|
||||
}
|
||||
|
||||
void addFormIPBox(const String& label, const String& id, const uint8_t ip[4])
|
||||
// ********************************************************************************
|
||||
// Add a IP Box form
|
||||
// ********************************************************************************
|
||||
void addFormIPBox(const __FlashStringHelper *label,
|
||||
const __FlashStringHelper *id,
|
||||
const uint8_t ip[4]) { addFormIPBox(String(label), String(id), IPAddress(ip)); }
|
||||
|
||||
void addFormIPBox(const String& label, const String& id, const uint8_t ip[4]) { addFormIPBox(label, id, IPAddress(ip)); }
|
||||
|
||||
void addFormIPBox(const __FlashStringHelper *label,
|
||||
const __FlashStringHelper *id,
|
||||
const IPAddress & ip) { addFormIPBox(String(label), String(id), ip); }
|
||||
|
||||
void addFormIPBox(const String & label,
|
||||
const String & id,
|
||||
const IPAddress& ip)
|
||||
{
|
||||
const bool empty_IP = (ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0);
|
||||
const bool empty_IP = !IPAddressSet(ip);
|
||||
|
||||
addFormTextBox(label, id, (empty_IP) ? EMPTY_STRING : formatIP(ip));
|
||||
|
||||
/*
|
||||
// TODO TD-er: Option to validate IP in HTML
|
||||
//
|
||||
// IP input HTML validation from:
|
||||
// Source - https://stackoverflow.com/a/54796814
|
||||
// Posted by ptay, modified by community. See post 'Timeline' for change history
|
||||
// Retrieved 2026-04-30, License - CC BY-SA 4.0
|
||||
//
|
||||
// <input type="text" minlength="7" maxlength="15" size="15" pattern="^(?>(\d|[1-9]\d{2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?1)$">
|
||||
|
||||
const String value = (empty_IP) ? EMPTY_STRING : formatIP(ip);
|
||||
addRowLabel_tr_id(label, id);
|
||||
|
||||
// Validation only for IPv4 address
|
||||
addHtml(strformat(
|
||||
F("<input class='wide' type='text' minlength='7' maxlength='15' size='15'
|
||||
pattern='^(?>(\\d|[1-9]\\d{2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?1)$' name='%s' id='%s' value='%s'>"),
|
||||
id.c_str(),
|
||||
id.c_str(),
|
||||
value.c_str()
|
||||
));
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
// ********************************************************************************
|
||||
// Add a MAC Box form
|
||||
// ********************************************************************************
|
||||
|
||||
@@ -233,6 +233,14 @@ void addFormIPBox(const String& label,
|
||||
const String& id,
|
||||
const uint8_t ip[4]);
|
||||
|
||||
void addFormIPBox(const __FlashStringHelper *label,
|
||||
const __FlashStringHelper *id,
|
||||
const IPAddress& ip);
|
||||
|
||||
void addFormIPBox(const String& label,
|
||||
const String& id,
|
||||
const IPAddress& ip);
|
||||
|
||||
// ********************************************************************************
|
||||
// Add a MAC address Box form
|
||||
// ********************************************************************************
|
||||
|
||||
@@ -64,7 +64,7 @@ void handle_root() {
|
||||
if (captivePortal()) { // If captive portal redirect instead of displaying the page.
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
// if Wifi setup, launch setup wizard if AP_FORCE_SETUP is set.
|
||||
if (!ESPEasy::net::NetworkConnected() &&
|
||||
Settings.ApCaptivePortal())
|
||||
@@ -72,7 +72,7 @@ void handle_root() {
|
||||
web_server.send_P(200, (PGM_P)F("text/html"), (PGM_P)F("<meta HTTP-EQUIV='REFRESH' content='0; url=/setup'>"));
|
||||
return;
|
||||
}
|
||||
|
||||
*/
|
||||
if (!MAIN_PAGE_SHOW_BASIC_INFO_NOT_LOGGED_IN) {
|
||||
if (!isLoggedIn()) { return; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user