Merge branch 'mega' into feature/P157-plugin-14-segment-display

This commit is contained in:
TD-er
2026-06-12 15:12:13 +02:00
committed by GitHub
32 changed files with 358 additions and 185 deletions
+2
View File
@@ -94,3 +94,5 @@ sdkconfig.*
src/Custom_.h
compile_commands.json
*.Identifier
+3 -1
View File
@@ -666,6 +666,8 @@ Sources:
* `Espressif Product Selector <https://products.espressif.com/#/product-comparison>`_
* `Espressif ESP32-xx modules overview <https://www.espressif.com/en/products/modules>`_
* `Espressif Product overview SoCs <https://www.espressif.com/en/products/socs>`_
* `Espressif Arduino Libraries: Supported Features and Peripherals <https://docs.espressif.com/projects/arduino-esp32/en/latest/libraries.html>`_
Datasheets
==========
@@ -1004,4 +1006,4 @@ ESP32-P4 rev3.x
New revision of the ESP32-P4, which is incompatible with the initial P4.
.. note:: Not yet supported (as of March 2026)
.. note:: Not yet supported (as of March 2026)
+1 -1
View File
@@ -83,7 +83,7 @@ Optional, but highly recommended:
* C/C++ DevTools (by Microsoft)
* Bookmarks (by Alessandro Fragnani)
* GitLens - Git supercharged (by Gitkraken)
* Todo Tree (by Gruntfuggly)
* TODO Highlight (by Wayou Liu)
* All Autocomplete (by Atishay Jain)
* Excel Viewer (by GrapeCity)
* Esbonio - An extension for editing sphinx projects (by Swyddfa)
+2 -1
View File
@@ -191,7 +191,8 @@ extra_scripts = ${esp82xx_common.extra_scripts}
;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/Jason2866/platform-espressif32.git#Arduino/IDF55_gcc152
platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/1905-1208-5.5/framework-arduinoespressif32-release_v5.5-f3cdb9d0.tar.xz
platform_packages =
;platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/2805-1324-5.5/framework-arduinoespressif32-release_v5.5-f3cdb9d0.tar.xz
custom_remove_include = true
@@ -15,8 +15,9 @@
#if FEATURE_MDNS
//#include "../../../src/Helpers/MDNS_Helper.h"
#endif
// #include "../../../src/Helpers/MDNS_Helper.h"
#endif // if FEATURE_MDNS
namespace ESPEasy {
@@ -103,7 +104,9 @@ void NWPluginData_static_runtime::clear(networkIndex_t networkIndex)
_gotIPStats.reset();
#if FEATURE_USE_IPV6
_gotIP6Stats.reset();
#endif
// TODO TD-er: Must also clear _gotIP6Events
#endif // if FEATURE_USE_IPV6
_operationalStats.reset();
#if FEATURE_NETWORK_TRAFFIC_COUNT
@@ -121,12 +124,20 @@ void NWPluginData_static_runtime::clear(networkIndex_t networkIndex)
_eventInterfaceName = _netif->desc();
_eventInterfaceName.toUpperCase();
}
_enableIPv6 = Settings.EnableIPv6() && Settings.getNetworkEnabled_IPv6(_networkIndex);
}
_routePrio = Settings.getRoutePrio_for_network(_networkIndex);
_dns_cache[0] = INADDR_NONE;
_dns_cache[1] = INADDR_NONE;
#endif // ifdef ESP32
_connectionFailures = 0;
// FIXME TD-er: Should also clear dns cache and/or static IP?
_ip = INADDR_NONE;
_gateway = INADDR_NONE;
_sn = INADDR_NONE;
_dns = INADDR_NONE;
}
void NWPluginData_static_runtime::processEvent_and_clear()
@@ -197,8 +208,9 @@ void NWPluginData_static_runtime::processEvents()
# endif // ifndef BUILD_NO_DEBUG
#endif // ifdef ESP8266
#if FEATURE_MDNS
// update_mDNS();
#endif
// update_mDNS();
#endif // if FEATURE_MDNS
}
#if FEATURE_USE_IPV6
@@ -225,9 +237,10 @@ void NWPluginData_static_runtime::processEvents()
}
}
}
#if FEATURE_MDNS
// update_mDNS();
#endif
# if FEATURE_MDNS
// update_mDNS();
# endif // if FEATURE_MDNS
}
#endif // if FEATURE_USE_IPV6
@@ -304,13 +317,21 @@ void NWPluginData_static_runtime::processEvents()
}
}
void NWPluginData_static_runtime::setStaticIP(const IPAddress & ip, const IPAddress & gateway, const IPAddress & subnetmask, const IPAddress & dns)
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;
_ip = ip;
_gateway = gateway;
_sn = subnetmask;
_dns = dns;
#ifdef ESP32
if (_useStaticIP) {
_dns_cache[0] = dns;
_dns_cache[1] = INADDR_NONE;
}
#endif // ifdef ESP32
}
String NWPluginData_static_runtime::statusToString() const
@@ -323,7 +344,8 @@ String NWPluginData_static_runtime::statusToString() const
if (hasIP()) {
log += F("IP ");
if (_useStaticIP) log += F("(static) ");
if (_useStaticIP) { log += F("(static) "); }
}
if (operational()) {
@@ -96,14 +96,18 @@ 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);
// AP IP and DHCP server are configured via softAPConfig().
// Calling config(0,0,0) on the AP netif enables DHCP client and breaks AP DHCP.
if (!_isAP) {
if (_useStaticIP) {
_netif->config(
_ip,
_gateway,
_sn,
_dns);
} else {
_netif->config((uint32_t)0, (uint32_t)0, (uint32_t)0);
}
}
const String hostname = strformat(
@@ -237,9 +241,7 @@ void NWPluginData_static_runtime::mark_begin_establish_connection()
_enableIPv6 = false;
}
# endif // if FEATURE_USE_IPV6
# ifdef ESP32
_routePrio = Settings.getRoutePrio_for_network(_networkIndex);
# endif
}
void NWPluginData_static_runtime::mark_connected()
+6 -14
View File
@@ -77,24 +77,16 @@ IPAddress NetworkLocalIP() { return WiFi.localIP(); }
IPAddress NetworkID()
{
const IPAddress subnet = NetworkSubnetMask();
IPAddress networkID = ESPEasy::net::NetworkLocalIP();
for (uint8_t i = 0; i < 4; ++i) {
networkID[i] &= subnet[i];
}
return networkID;
return NWPlugin::getNetworkID(
ESPEasy::net::NetworkLocalIP(),
NetworkSubnetMask());
}
IPAddress NetworkBroadcast()
{
const IPAddress subnet = NetworkSubnetMask();
IPAddress broadcast = ESPEasy::net::NetworkLocalIP();
for (uint8_t i = 0; i < 4; ++i) {
broadcast[i] |= ~subnet[i];
}
return broadcast;
return NWPlugin::getNetworkBroadcast(
ESPEasy::net::NetworkLocalIP(),
NetworkSubnetMask());
}
IPAddress NetworkSubnetMask() { return WiFi.subnetMask(); }
+47 -22
View File
@@ -4,24 +4,24 @@
#include "../../../src/DataStructs/TimingStats.h"
#include "../../../src/DataTypes/ESPEasy_plugin_functions.h"
#ifdef ESP32
#include "../../../src/Globals/SecuritySettings.h"
# include "../../../src/Globals/SecuritySettings.h"
#endif
#include "../../../src/Globals/Settings.h"
#include "../Helpers/_NWPlugin_init.h"
#ifdef ESP32
#include "../Helpers/NWAccessControl.h"
# include "../Helpers/NWAccessControl.h"
#endif
#include "../../../src/Globals/ESPEasy_Scheduler.h"
#include "../../../src/Helpers/Networking.h"
#include "../_NWPlugin_Helper.h"
#ifdef ESP8266
#include "../wifi/ESPEasyWifi.h"
# include "../wifi/ESPEasyWifi.h"
#endif
#include "../ESPEasyNetwork.h"
namespace ESPEasy {
namespace net {
@@ -324,11 +324,11 @@ bool NWPluginCall(NWPlugin::Function Function, EventStruct *event, String& str)
// calls to specific network which need to be enabled before calling
case NWPlugin::Function::NWPLUGIN_INIT:
// case NWPlugin::Function::NWPLUGIN_CONNECT_SUCCESS:
// case NWPlugin::Function::NWPLUGIN_CONNECT_FAIL:
// case NWPlugin::Function::NWPLUGIN_CONNECT_SUCCESS:
// case NWPlugin::Function::NWPLUGIN_CONNECT_FAIL:
case NWPlugin::Function::NWPLUGIN_WEBFORM_SHOW_ACTIVE:
case NWPlugin::Function::NWPLUGIN_WEBFORM_SHOW_CONNECTED:
// case NWPlugin::Function::NWPLUGIN_WEBFORM_SHOW_EXTENDED:
// case NWPlugin::Function::NWPLUGIN_WEBFORM_SHOW_EXTENDED:
case NWPlugin::Function::NWPLUGIN_WEBFORM_SHOW_HW_ADDRESS:
case NWPlugin::Function::NWPLUGIN_WEBFORM_SHOW_IP:
#ifdef ESP32
@@ -356,7 +356,7 @@ bool NWPluginCall(NWPlugin::Function Function, EventStruct *event, String& str)
case NWPlugin::Function::NWPLUGIN_WEBFORM_LOAD:
case NWPlugin::Function::NWPLUGIN_WEBFORM_SAVE:
// case NWPlugin::Function::NWPLUGIN_DRIVER_TEMPLATE:
// case NWPlugin::Function::NWPLUGIN_DRIVER_TEMPLATE:
{
const networkIndex_t networkIndex = event->NetworkIndex;
bool success = false;
@@ -468,20 +468,43 @@ bool NWPluginCall(NWPlugin::Function Function, EventStruct *event, String& str)
case NWPlugin::Function::NWPLUGIN_CLIENT_IP_WEB_ACCESS_ALLOWED:
{
IPAddress client_ip;
client_ip.fromString(str);
if (!Settings.getNetworkInterfaceSubnetBlockClientIP(event->NetworkIndex)) {
IPAddress client_ip;
client_ip.fromString(str);
if ((SecuritySettings.IPblockLevel == LOCAL_SUBNET_ALLOWED) &&
!Settings.getNetworkInterfaceSubnetBlockClientIP(event->NetworkIndex)) {
success = NWPlugin::IP_in_subnet(client_ip, event->networkInterface);
} else if (SecuritySettings.IPblockLevel == ONLY_IP_RANGE_ALLOWED) {
const IPAddress low(SecuritySettings.AllowedIPrangeLow);
const IPAddress high(SecuritySettings.AllowedIPrangeHigh);
success = NWPlugin::ipInRange(client_ip, low, high) &&
NWPlugin::IP_in_subnet(low, event->networkInterface) &&
NWPlugin::IP_in_subnet(high, event->networkInterface);
} else {
success = true;
if (SecuritySettings.IPblockLevel == LOCAL_SUBNET_ALLOWED) {
success = NWPlugin::IP_in_subnet(client_ip, event->networkInterface);
const NWPlugin::IP_type ip_type = NWPlugin::get_IP_type(client_ip);
IPAddress networkID;
IPAddress broadcast;
if (NWPlugin::get_subnet(ip_type, event->networkInterface, networkID, broadcast)) {
# if FEATURE_USE_IPV6
const bool includeZone = ip_type == NWPlugin::IP_type::ipv6_link_local;
event->String1 = formatIP(networkID, includeZone);
event->String2 = formatIP(broadcast, includeZone);
# else // if FEATURE_USE_IPV6
event->String1 = formatIP(networkID);
event->String2 = formatIP(broadcast);
# endif // if FEATURE_USE_IPV6
}
} else if (SecuritySettings.IPblockLevel == ONLY_IP_RANGE_ALLOWED) {
const IPAddress low(SecuritySettings.AllowedIPrangeLow);
const IPAddress high(SecuritySettings.AllowedIPrangeHigh);
if (IPAddressSet(low) || IPAddressSet(high))
{
// Use || as for example 0.0.0.0 ... 123.0.0.0 might also be a possible range.
// Though I have no idea for what practical use case...
success = NWPlugin::ipInRange(client_ip, low, high);
event->String1 = formatIP(low);
event->String2 = formatIP(high);
}
}
}
break;
}
@@ -493,7 +516,8 @@ 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 +529,8 @@ bool NWPluginCall(NWPlugin::Function Function, EventStruct *event, String& str)
}
clearNWPluginData(event->NetworkIndex);
}
//#endif // ifdef ESP32
// #endif // ifdef ESP32
}
return success;
}
+22 -34
View File
@@ -30,43 +30,31 @@ bool ipInAllowedSubnet(const IPAddress& ip)
}
String describeAllowedIPrange() {
String reply;
switch (SecuritySettings.IPblockLevel)
{
case ALL_ALLOWED:
reply += F("All Allowed");
break;
default:
{
IPAddress low, high;
getIPallowedRange(low, high);
reply += formatIP(low);
reply += F(" - ");
reply += formatIP(high);
}
}
return reply;
return describeAllowedIPrange(ESPEasy::net::NetworkLocalIP());
}
bool getIPallowedRange(IPAddress& low, IPAddress& high)
{
switch (SecuritySettings.IPblockLevel)
{
case LOCAL_SUBNET_ALLOWED:
low = NetworkID();
high = NetworkBroadcast();
return true;
case ONLY_IP_RANGE_ALLOWED:
low = IPAddress(SecuritySettings.AllowedIPrangeLow);
high = IPAddress(SecuritySettings.AllowedIPrangeHigh);
break;
default:
low = IPAddress(0, 0, 0, 0);
high = IPAddress(255, 255, 255, 255);
return false;
String describeAllowedIPrange(const IPAddress& ip) {
if (SecuritySettings.IPblockLevel == ALL_ALLOWED) {
return F("All Allowed");
}
return true;
String allowedRange;
String ip_str = ip.toString();
for (networkIndex_t x = 0; x < NETWORK_MAX; x++) {
EventStruct tempEvent;
tempEvent.NetworkIndex = x;
if (NWPluginCall(NWPlugin::Function::NWPLUGIN_CLIENT_IP_WEB_ACCESS_ALLOWED, &tempEvent, ip_str)) {
if (!tempEvent.String1.isEmpty() && !tempEvent.String2.isEmpty()) {
if (!allowedRange.isEmpty()) { allowedRange += F(", "); }
allowedRange += tempEvent.String1;
allowedRange += F(" - ");
allowedRange += tempEvent.String2;
}
}
}
return allowedRange;
}
} // namespace net
+1 -2
View File
@@ -15,8 +15,7 @@ namespace net {
bool ipInAllowedSubnet(const IPAddress& ip);
String describeAllowedIPrange();
bool getIPallowedRange(IPAddress& low, IPAddress& high);
String describeAllowedIPrange(const IPAddress& ip);
} // namespace net
@@ -101,6 +101,7 @@ bool NW001_data_struct_WiFi_STA::init(EventStruct *event)
auto runtime_data = getNWPluginData_static_runtime();
if (runtime_data) {
runtime_data->clear(event->NetworkIndex);
IPAddress ip, gateway, sn, dns;
getStaticIPAddresses(ip, gateway, sn, dns);
runtime_data->setStaticIP(ip, gateway, sn, dns);
@@ -2,12 +2,10 @@
#ifdef USES_NW002
# ifdef ESP32
# include "../../../src/Globals/Settings.h"
# endif
# include "../wifi/ESPEasyWifi.h"
# include "../Globals/NetworkState.h"
# include "../../../src/Globals/Settings.h"
# include "../../../src/Helpers/Networking.h"
# ifdef ESP32
@@ -95,6 +93,7 @@ bool NW002_data_struct_WiFi_AP::init(EventStruct *event)
auto runtime_data = getNWPluginData_static_runtime();
if (runtime_data) {
runtime_data->clear(event->NetworkIndex);
IPAddress ip, gateway, sn, dns;
getStaticIPAddresses(ip, gateway, sn, dns);
runtime_data->setStaticIP(ip, gateway, sn, dns);
@@ -105,8 +104,13 @@ bool NW002_data_struct_WiFi_AP::init(EventStruct *event)
nw002_enable_NAPT = Settings.WiFi_AP_enable_NAPT();
# endif
ESPEasy::net::wifi::setAPinternal(true);
if (!ESPEasy::net::wifi::setAPinternal(true)) {
return false;
}
# ifdef ESP32
if (NW_PLUGIN_INTERFACE.hasIP()) {
stats_and_cache.mark_got_IP();
}
NW002_update_NAPT();
# endif
# if FEATURE_MDNS
@@ -146,28 +150,25 @@ NWPluginData_static_runtime * NW002_data_struct_WiFi_AP::getNWPluginData_static_
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;
switch (addressType)
{
case IPAddressType::IP:
ip = apIP;
return true;
}
*/
case IPAddressType::Gateway:
ip = apIP;
return true;
case IPAddressType::Subnetmask:
ip = IPAddress(DEFAULT_AP_SUBNET);
return true;
case IPAddressType::DNS:
if (Settings.ApCaptivePortal()) {
ip = apIP;
} else {
ip = IPAddress(DEFAULT_AP_DNS);
}
return true;
}
return false;
}
@@ -264,6 +265,10 @@ void NW002_data_struct_WiFi_AP::onEvent(arduino_event_id_t event,
{
case ARDUINO_EVENT_WIFI_AP_START:
stats_and_cache.mark_start();
if (NW_PLUGIN_INTERFACE.hasIP()) {
stats_and_cache.mark_got_IP();
}
break;
case ARDUINO_EVENT_WIFI_AP_STOP:
stats_and_cache.mark_stop();
@@ -283,6 +288,10 @@ void NW002_data_struct_WiFi_AP::onEvent(arduino_event_id_t event,
break;
case ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED:
addLog(LOG_LEVEL_INFO, F("AP_STAIPASSIGNED"));
if (!stats_and_cache.hasIP() && NW_PLUGIN_INTERFACE.hasIP()) {
stats_and_cache.mark_got_IP();
}
break;
case ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED:
addLog(LOG_LEVEL_INFO, F("AP_PROBEREQRECVED"));
@@ -350,6 +350,7 @@ bool NW003_data_struct_ETH_RMII::init(EventStruct *event)
{
auto runtime_data = getNWPluginData_static_runtime();
if (runtime_data) {
runtime_data->clear(event->NetworkIndex);
IPAddress ip, gateway, sn, dns;
getStaticIPAddresses(ip, gateway, sn, dns);
runtime_data->setStaticIP(ip, gateway, sn, dns);
@@ -293,9 +293,10 @@ 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) {
runtime_data->clear(event->NetworkIndex);
IPAddress ip, gateway, sn, dns;
getStaticIPAddresses(ip, gateway, sn, dns);
runtime_data->setStaticIP(ip, gateway, sn, dns);
@@ -980,6 +980,8 @@ bool NW005_data_struct_PPP_modem::init(EventStruct *event)
_modem_task_data.initializing = false;
_modem_task_data.dtrPin = _kvs->getValueAsInt_or_default(NW005_KEY_PIN_DTR, -1);
stats_and_cache.clear(event->NetworkIndex);
stats_and_cache.mark_begin_establish_connection();
xTaskCreatePinnedToCore(
+20 -11
View File
@@ -13,6 +13,7 @@
# include "../../src/DataStructs/ESPEasy_EventStruct.h"
# include "../../src/Globals/SecuritySettings.h"
# include "../../src/Globals/Settings.h"
# include "../../src/Helpers/Networking.h"
# include "../../src/Helpers/StringConverter.h"
# include "../../src/Helpers/StringGenerator_WiFi.h"
# include "../../src/WebServer/ESPEasy_WebServer.h"
@@ -27,6 +28,7 @@
# include "../net/ESPEasyNetwork.h"
# endif
# if FEATURE_TASKVALUE_UNIT_OF_MEASURE
# include "../../src/Helpers/ESPEasy_UnitOfMeasure.h"
# endif
@@ -295,18 +297,25 @@ bool NWPlugin_001(NWPlugin::Function function, EventStruct *event, String& strin
case NWPlugin::Function::NWPLUGIN_CLIENT_IP_WEB_ACCESS_ALLOWED:
{
IPAddress client_ip;
client_ip.fromString(string);
if ((SecuritySettings.IPblockLevel == LOCAL_SUBNET_ALLOWED) &&
!Settings.getNetworkInterfaceSubnetBlockClientIP(event->NetworkIndex)) {
success = NWPlugin::ipInRange(client_ip, NetworkID(), NetworkBroadcast());
} else if (SecuritySettings.IPblockLevel == ONLY_IP_RANGE_ALLOWED) {
const IPAddress low(SecuritySettings.AllowedIPrangeLow);
const IPAddress high(SecuritySettings.AllowedIPrangeHigh);
success = NWPlugin::ipInRange(client_ip, low, high);
} else {
if (!Settings.getNetworkInterfaceSubnetBlockClientIP(event->NetworkIndex)) {
IPAddress client_ip;
client_ip.fromString(string);
success = true;
if (SecuritySettings.IPblockLevel != ALL_ALLOWED) {
IPAddress low, high;
if (SecuritySettings.IPblockLevel == LOCAL_SUBNET_ALLOWED) {
low = NetworkID();
high = NetworkBroadcast();
} else if (SecuritySettings.IPblockLevel == ONLY_IP_RANGE_ALLOWED) {
low = IPAddress(SecuritySettings.AllowedIPrangeLow);
high = IPAddress(SecuritySettings.AllowedIPrangeHigh);
}
if (IPAddressSet(low) || IPAddressSet(high)) {
success = NWPlugin::ipInRange(client_ip, low, high);
event->String1 = formatIP(low);
event->String2 = formatIP(high);
}
}
}
break;
}
+2 -9
View File
@@ -219,6 +219,7 @@ bool NWPlugin_002(NWPlugin::Function function, EventStruct *event, String& strin
}
break;
}
# endif // ifdef ESP8266
case NWPlugin::Function::NWPLUGIN_CLIENT_IP_WEB_ACCESS_ALLOWED:
{
@@ -229,18 +230,10 @@ bool NWPlugin_002(NWPlugin::Function function, EventStruct *event, String& strin
// FIXME TD-er: Do we allow to set the subnetmask for AP to anything else?
const IPAddress subnet(255, 255, 255, 0);
const IPAddress localIP = WiFi.softAPIP();
bool success = true;
for (uint8_t i = 0; success && i < 4; ++i) {
if ((localIP[i] & subnet[i]) != (client_ip[i] & subnet[i])) {
success = false;
}
}
success = NWPlugin::IP_in_subnet(WiFi.softAPIP(), client_ip, subnet);
}
break;
}
# endif // ifdef ESP8266
case NWPlugin::Function::NWPLUGIN_WEBFORM_SAVE:
{
@@ -82,6 +82,13 @@ bool doSetAPinternal(bool enable)
String softAPSSID = NetworkCreateRFCCompliantHostname();
String pwd = SecuritySettings.WifiAPKey;
IPAddress subnet(DEFAULT_AP_SUBNET);
// AP mode (and AP netif on ESP32) must be enabled before softAPConfig,
// otherwise DHCP server setup fails when STA is active but not connected.
if (!doSetAP(true)) {
return false;
}
# ifdef ESP32
IPAddress dhcp_lease_start = (uint32_t)0;
@@ -138,10 +145,6 @@ bool doSetAPinternal(bool enable)
channel = WiFi.channel();
}
#ifdef ESP32
doSetAP(true);
#endif
if (WiFi.softAP(softAPSSID.c_str(), pwd.c_str(), channel)) {
auto data = getWiFi_AP_NWPluginData_static_runtime();
@@ -204,6 +207,7 @@ bool doSetAPinternal(bool enable)
# endif // if FEATURE_DNS_SERVER
# endif // ifdef ESP32
}
return true;
} else {
# if FEATURE_DNS_SERVER
@@ -218,7 +222,7 @@ bool doSetAPinternal(bool enable)
doSetAP(false);
}
return false;
return true;
}
void doSetConnectionSpeed() {
+71 -11
View File
@@ -185,21 +185,22 @@ bool NWPlugin::get_subnet(NWPlugin::IP_type ip_type, NetworkInterface*networkInt
broadcast = networkInterface->broadcastIP();
return true;
}
#endif
#endif // ifdef ESP32
bool NWPlugin::ipLessEqual(const IPAddress& ip, const IPAddress& high)
{
// FIXME TD-er: Must check whether both are of same type and check full range IPv6
int nrOctets = 4;
# if FEATURE_USE_IPV6
#if FEATURE_USE_IPV6
if (ip.type() != high.type()) { return false; }
if (ip.type() == IPv6) {
nrOctets = 16;
}
# endif // if FEATURE_USE_IPV6
#endif // if FEATURE_USE_IPV6
for (int i = 0; i < nrOctets; ++i) {
if (ip[i] != high[i]) {
@@ -211,11 +212,69 @@ bool NWPlugin::ipLessEqual(const IPAddress& ip, const IPAddress& high)
return true;
}
bool NWPlugin::ipInRange(const IPAddress& ip, const IPAddress& low, const IPAddress& high) {
return ipLessEqual(low, ip) && ipLessEqual(ip, high);
bool NWPlugin::ipInRange(const IPAddress& ip, const IPAddress& low, const IPAddress& high) {
return ipLessEqual(low, ip) && ipLessEqual(ip, high);
}
bool NWPlugin::IP_in_subnet(const IPAddress& localIP,
const IPAddress& client_ip,
const IPAddress& subnet)
{
#if FEATURE_USE_IPV6
if ((localIP.type() != client_ip.type()) ||
(localIP.type() != subnet.type())) { return false; }
#endif // if FEATURE_USE_IPV6
return ipInRange(
client_ip,
getNetworkID(localIP, subnet),
getNetworkBroadcast(localIP, subnet));
}
IPAddress NWPlugin::getNetworkID(const IPAddress& localIP, const IPAddress& subnet)
{
IPAddress networkID = localIP;
int nrOctets = 4;
#if FEATURE_USE_IPV6
if (localIP.type() != subnet.type()) { return IPAddress(); }
if (localIP.type() == IPv6) {
nrOctets = 16;
}
#endif // if FEATURE_USE_IPV6
for (uint8_t i = 0; i < nrOctets; ++i) {
networkID[i] &= subnet[i];
}
return networkID;
}
IPAddress NWPlugin::getNetworkBroadcast(const IPAddress& localIP, const IPAddress& subnet)
{
IPAddress broadcast = localIP;
int nrOctets = 4;
#if FEATURE_USE_IPV6
if (localIP.type() != subnet.type()) { return IPAddress(); }
if (localIP.type() == IPv6) {
nrOctets = 16;
}
#endif // if FEATURE_USE_IPV6
for (uint8_t i = 0; i < nrOctets; ++i) {
broadcast[i] |= ~subnet[i];
}
return broadcast;
}
#ifdef ESP32
bool NWPlugin::IP_in_subnet(const IPAddress & ip,
NetworkInterface *networkInterface)
{
@@ -223,17 +282,18 @@ bool NWPlugin::IP_in_subnet(const IPAddress & ip,
IPAddress networkID;
IPAddress broadcast;
if (!get_subnet(ip_type, networkInterface, networkID, broadcast)) {
return false;
if (!get_subnet(ip_type, networkInterface, networkID, broadcast)) {
return false;
}
#if FEATURE_USE_IPV6
# if FEATURE_USE_IPV6
if (ip_type == NWPlugin::IP_type::ipv6_link_local) {
// Must match zone, or else it will always match.
return (ip.zone() == networkID.zone());
if (ip.zone() != networkID.zone()) return false;
}
#endif
# endif // if FEATURE_USE_IPV6
return ipLessEqual(networkID, ip) && ipLessEqual(ip, broadcast);
return ipInRange(ip, networkID, broadcast);
}
NWPlugin::IP_type NWPlugin::get_IP_type(const IPAddress& ip)
@@ -255,6 +255,14 @@ public:
const IPAddress& low,
const IPAddress& high);
static bool IP_in_subnet(const IPAddress& localIP,
const IPAddress& client_ip,
const IPAddress& subnet);
static IPAddress getNetworkID(const IPAddress& localIP, const IPAddress& subnet);
static IPAddress getNetworkBroadcast(const IPAddress& localIP, const IPAddress& subnet);
#ifdef ESP32
static bool IP_in_subnet(const IPAddress & ip,
NetworkInterface *networkInterface);
+1 -1
View File
@@ -212,7 +212,7 @@ int SettingsType::getFileSize(Enum settingsType) {
return max_file_pos;
}
#ifndef BUILD_NO_DEBUG
#if FEATURE_CHART_STORAGE_LAYOUT && !defined(BUILD_NO_DEBUG)
unsigned int SettingsType::getSVGcolor(Enum settingsType) {
switch (settingsType) {
case Enum::BasicSettings_Type:
+1 -1
View File
@@ -54,7 +54,7 @@ public:
static int getMaxFilePos(Enum settingsType);
static int getFileSize(Enum settingsType);
#ifndef BUILD_NO_DEBUG
#if FEATURE_CHART_STORAGE_LAYOUT && !defined(BUILD_NO_DEBUG)
static unsigned int getSVGcolor(Enum settingsType);
#endif
+10
View File
@@ -273,6 +273,16 @@ void addToLogMove(uint8_t logLevel, String&& str)
void processLogs(bool serialOnly)
{
#ifdef ESP32
if (xPortInIsrContext()) {
// When called from an ISR, you should not send out logs.
// Allocating memory from within an ISR is a big no-no.
// Also long-time blocking like sending logs (especially to a syslog server)
// is also really not a good idea from an ISR call.
return;
}
#endif // ifdef ESP32
process_serialWriteBuffer();
Logging.loop(serialOnly);
#if FEATURE_SYSLOG
+2 -1
View File
@@ -615,7 +615,7 @@ void logMemUsageAfter(const __FlashStringHelper *function, int value) {
// The recorded used memory is not an exact value, as background (or interrupt) tasks may also allocate or free heap memory.
static int last_freemem = ESP.getFreeHeap();
const int freemem_end = ESP.getFreeHeap();
#ifndef BUILD_NO_DEBUG
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
String log;
@@ -639,6 +639,7 @@ void logMemUsageAfter(const __FlashStringHelper *function, int value) {
addLogMove(LOG_LEVEL_DEBUG, log);
}
}
#endif
last_freemem = freemem_end;
}
+6 -1
View File
@@ -411,7 +411,12 @@ void updateMQTTclient_connected() {
const bool actual_MQTTclient_connected = ESPEasy::net::NetworkConnected(true) && MQTTclient.connected();
if (MQTTclient_connected != actual_MQTTclient_connected) {
MQTTclient_connected = actual_MQTTclient_connected;
if (!actual_MQTTclient_connected) mqtt.stop(); // Make sure PubSubClient isn't trying to do a graceful disconnect
if (!actual_MQTTclient_connected) {
// Make sure PubSubClient isn't trying to do a graceful disconnect
// FIXME TD-er: This seems to cause a crash on ESP32-xx, though no idea how to fix.
// See also: https://github.com/espressif/arduino-esp32/issues/12517
mqtt.stop();
}
MQTTclient_connected_stats.set(actual_MQTTclient_connected);
if (!MQTTclient_connected) {
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
+3 -13
View File
@@ -33,30 +33,20 @@ bool clientIPallowed()
// return true;
#endif
const IPAddress remoteIP = web_server.client().remoteIP();
if (remoteIP == IPAddress(0, 0, 0, 0)
#if ESP_IDF_VERSION_MAJOR>=5
|| remoteIP.type() == IPv6
#else
|| !remoteIP.isV4()
#endif
) {
if (!IPAddressSet(remoteIP))
{
// FIXME TD-er: Must see what's going on here, why the client doesn't send remote IP for some reason
return true;
}
if (ESPEasy::net::ipInAllowedSubnet(remoteIP)) {
return true;
}
if ( ESPEasy::net::wifi::WifiIsAP(WiFi.getMode())) {
// @TD-er Fixme: Should match subnet of SoftAP.
return true;
}
String response = concat(F("IP blocked: "), formatIP(remoteIP));
web_server.send(403, F("text/html"), response);
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
response += F(" Allowed: ");
response += ESPEasy::net::describeAllowedIPrange();
response += ESPEasy::net::describeAllowedIPrange(remoteIP);
addLogMove(LOG_LEVEL_ERROR, response);
}
return false;
+1 -1
View File
@@ -1091,7 +1091,7 @@ void getWiFi_RSSI_icon(int rssi, int width_pixels)
addHtml(F("</svg>\n"));
}
#if FEATURE_CHART_STORAGE_LAYOUT
#if FEATURE_CHART_STORAGE_LAYOUT && !defined(BUILD_NO_DEBUG)
void getConfig_dat_file_layout() {
const int shiftY = 2;
float yOffset = shiftY;
+1 -1
View File
@@ -193,7 +193,7 @@ void write_SVG_image_header(int width,
void getWiFi_RSSI_icon(int rssi,
int width_pixels);
#if FEATURE_CHART_STORAGE_LAYOUT
#if FEATURE_CHART_STORAGE_LAYOUT && !defined(BUILD_NO_DEBUG)
void getConfig_dat_file_layout();
void getStorageTableSVG(SettingsType::Enum settingsType);
+2
View File
@@ -5,6 +5,8 @@
#ifdef WEBSERVER_METRICS
#include "../../ESPEasy/net/ESPEasyNetwork.h"
# if FEATURE_NETWORK_STATS
# ifdef ESP8266
# define MAX_NR_NETWORKS_IN_TABLE 2
+1 -1
View File
@@ -668,7 +668,7 @@ void handle_sysinfo_Storage() {
}
# endif // ifndef LIMIT_BUILD_SIZE
# if FEATURE_CHART_STORAGE_LAYOUT
#if FEATURE_CHART_STORAGE_LAYOUT && !defined(BUILD_NO_DEBUG)
if (showSettingsFileLayout) {
addTableSeparator(F("Settings Files"), 2, 3);
+45 -1
View File
@@ -18,6 +18,11 @@
# include "../Helpers/SystemVariables.h"
#if defined(ESP32) && (!defined(LIMIT_BUILD_SIZE) || FEATURE_STRING_VARIABLES)
#define FEATURE_CUSTOM_STRING_SORT 1
#else
#define FEATURE_CUSTOM_STRING_SORT 0
#endif
// ********************************************************************************
// Web Interface sysvars showing all system vars and their value.
// ********************************************************************************
@@ -52,6 +57,19 @@ void handle_sysvars() {
html_table_header(F("URL encoded"), F("RTDReference/SystemVariable.html"), 0);
addTableSeparator(F("Custom Variables"), 3, 3);
#if FEATURE_CUSTOM_STRING_SORT
auto numAlphaSort = [](const String& a, const String& b) {
const int32_t ai = a.toInt();
const int32_t bi = b.toInt();
if (!ai && !bi) { return !!(a < b); } // a..z , need to cast to bool for ESP8266
if (!ai) { return false; } // Alphanum after num
return ai < bi; // Numerical order
};
std::vector<String> customStringSort;
# endif // FEATURE_CUSTOM_STRING_SORT
if (customFloatVar.empty()) {
html_TR_TD();
@@ -59,14 +77,33 @@ void handle_sysvars() {
html_TD();
html_TD();
} else {
#if FEATURE_CUSTOM_STRING_SORT
for (auto it = customFloatVar.begin(); it != customFloatVar.end(); ++it) {
customStringSort.push_back(it->first);
}
std::sort(customStringSort.begin(), customStringSort.end(), numAlphaSort);
for (auto& it : customStringSort) {
NumericalType detectedType;
bool isv_ = true;
if (getNumerical(it, NumericalType::HexadecimalUInt, detectedType).length() > 0) {
isv_ = detectedType != NumericalType::Integer;
}
addSysVar_html(strformat(F("%%%s%s%%"), FsP(isv_ ? F("v_") : F("v")), it.c_str()), false);
}
# else // FEATURE_CUSTOM_STRING_SORT
for (auto it = customFloatVar.begin(); it != customFloatVar.end(); ++it) {
NumericalType detectedType;
bool isv_ = true;
if (getNumerical(it->first, NumericalType::HexadecimalUInt, detectedType).length() > 0) {
isv_ = detectedType != NumericalType::Integer;
}
addSysVar_html(strformat(F("%%%s%s%%"), FsP(isv_ ? F("v_") : F("v")), it->first.c_str()), false);
}
# endif // FEATURE_CUSTOM_STRING_SORT
}
# if FEATURE_STRING_VARIABLES
@@ -78,8 +115,15 @@ void handle_sysvars() {
html_TD();
html_TD();
} else {
customStringSort.clear();
for (auto it = customStringVar.begin(); it != customStringVar.end(); ++it) {
addSysVar_html(strformat(F("[str#%s]"), it->first.c_str()), false);
customStringSort.push_back(it->first);
}
std::sort(customStringSort.begin(), customStringSort.end(), numAlphaSort);
for (auto& it : customStringSort) {
addSysVar_html(strformat(F("[str#%s]"), it.c_str()), false);
}
}
# endif // if FEATURE_STRING_VARIABLES
+1 -1
View File
@@ -378,7 +378,7 @@ def generate_manifest_files(bin_folder, output_prefix):
' </style>\n',
' <script\n',
' type="module"\n',
' src="https://unpkg.com/tasmota-esp-web-tools@12.2.2/dist/web/install-button.js?module"\n',
' src="https://unpkg.com/tasmota-esp-web-tools@12.2.4/dist/web/install-button.js?module"\n',
' ></script>\n',
' </head>\n',
' <body>\n',