mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-09-11 09:04:53 +00:00
Merge branch 'mega' into feature/P157-plugin-14-segment-display
This commit is contained in:
@@ -94,3 +94,5 @@ sdkconfig.*
|
||||
src/Custom_.h
|
||||
|
||||
compile_commands.json
|
||||
|
||||
*.Identifier
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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(); }
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user