Merge branch 'mega' of https://github.com/letscontrolit/ESPEasy into feature/Metrics-add-network-tx-rx-data

This commit is contained in:
Ton Huisman
2026-05-11 21:54:47 +02:00
93 changed files with 1624 additions and 655 deletions
+18 -14
View File
@@ -67,6 +67,7 @@ collection_F | Normal + plugin collection F | Stable + Collection b
collection_G | Normal + plugin collection G | Stable + Collection base + set G |
collection_H | Normal + plugin collection H | Stable + Collection base + set H |
max | All available plugins | All available |
max32 | All available plugins, 32MB Flash | All available, large file system |
energy | All plugins related to energy measurement | Stable + Energy measurement |
display A | All plugins related to displays A | Stable + Displays A |
display B | All plugins related to displays B | Stable + Displays B |
@@ -101,6 +102,10 @@ ESP32c3 | Espressif ESP32-C3 generic boards |
ESP32s3 | Espressif ESP32-S3 generic boards |
ESP32c2 | Espressif ESP32-C2 generic boards |
ESP32c6 | Espressif ESP32-C6 generic boards |
ESP32c61 | Espressif ESP32-C61 generic boards (experimental) |
ESP32c5 | Espressif ESP32-C5 generic boards (experimental) |
ESP32p4 | Espressif ESP32-P4 (Rev.1) generic boards |
ESP32p4r3 | Espressif ESP32-P4 (Rev.3/P4X) generic boards |
ESP32-wrover-kit | Espressif ESP32 wrover-kit boards |
SONOFF | Sonoff hardware specific |
other_POW | Switch with power measurement |
@@ -124,10 +129,10 @@ Flash size | Description |
16M | 16 MB with 14 MB filesystem |
4M316k | 4 MB with 316 kB filesystem |
8M1M | 8 MB with 1 MB filesystem |
16M1M | 16 MB with 1 MB filesystem |
16M8M | 16 MB with 8 MB filesystem |
32M20M | 32 MB with 20 MB filesystem |
N.B. Starting with release 2023/12/25, All ESP32 LittleFS builds use IDF 5.3, to support newer ESP32 chips like ESP32-C2 and ESP32-C6, and SPI Ethernet. Other SPIFFS based ESP32 builds will be migrated to LittleFS as SPIFFS is no longer officially available in IDF 5 and later. As a temporary solution, a specially crafted IDF 5.1 build that still includes SPIFFS, is used for the SPIFFS builds. A migration plan will be made available in 2025.
N.B. Starting with release 2023/12/25, All ESP32 LittleFS builds use IDF 5.3, to support newer ESP32 chips like ESP32-C2 and ESP32-C6, and SPI Ethernet. Other SPIFFS based ESP32 builds will be migrated to LittleFS as SPIFFS is no longer officially available in IDF 5 and later. As a temporary solution, a specially crafted IDF 5.1 build that still includes SPIFFS, is used for the SPIFFS builds. A migration plan is available, [here](https://espeasy.readthedocs.io/en/latest/Reference/Migrate_SPIFFS_to_LittleFS.html).
N.B.2 Starting with builds made after 2025/11/04, ESP32 builds will no longer have ``_LittleFS`` in the name as all ESP32 builds use LittleFS. Also the suffix ``_ETH`` has been removed since all builds will have Ethernet support, except for ESP32C2 builds.
@@ -142,7 +147,7 @@ Domoticz_MQTT | Only Domoticz controllers (MQTT) and plugins included
FHEM_HA | Only FHEM/OpenHAB/Home Assistant (MQTT) controllers and plugins included |
ETH | Ethernet support enabled (ESP32 and IDF 5.x based builds) |
OPI_PSRAM | Specific configuration to enable PSRAM detection, ESP32-S3 only |
CDC | Support USBCDC/HWCDC-serial console on ESP32-C3, ESP32-S2, ESP32-S3 and ESP32-C6 |
CDC | Support USBCDC/HWCDC-serial console on ESP32-C3, ESP32-S2, ESP32-S3, ESP32-C6, ESP32-C61 and ESP32-C5 |
noOTA/NO_OTA | Does not support OTA (Over The Air-updating of the firmware) Use [the flash page](https://td-er.nl/ESPEasy/) or ESPTool via USB Serial |
N.B. Starting ca. 2025/02/27, many ESP32 builds are *only* available with _ETH suffix, indicating that Ethernet support is enabled, to reduce the (rather high) number of builds.
@@ -150,18 +155,17 @@ N.B. Starting ca. 2025/02/27, many ESP32 builds are *only* available with _ETH s
Some example firmware names:
Firmware name | Hardware | Included plugins |
--------------------------------------------------------|-------------------------------------------------|----------------------------------|
ESPEasy_mega-20230822_normal_ESP8266_1M.bin | ESP8266/ESP8285 with 1MB flash | Stable |
ESPEasy_mega-20230822_normal_ESP8266_4M1M.bin | ESP8266 with 4MB flash | Stable |
ESPEasy_mega-20230822_collection_A_ESP8266_4M1M.bin | ESP8266 with 4MB flash | Stable + Collection base + set A |
ESPEasy_mega-20230822_normal_ESP32_4M316k_ETH.bin | ESP32 with 4MB flash | Stable |
ESPEasy_mega-20230822_collection_A_ESP32_4M316k_ETH.bin | ESP32 with 4MB flash | Stable + Collection base + set A |
ESPEasy_mega-20230822_collection_B_ESP32_4M316k_ETH.bin | ESP32 with 4MB flash | Stable + Collection base + set B |
ESPEasy_mega-20230822_max_ESP32s3_8M1M.bin | ESP32-S3 with 8MB flash, CDC-serial, Ethernet | All available plugins |
ESPEasy_mega-20230822_max_ESP32s3_8M1M_OPI_PSRAM.bin | ESP32-S3 8MB flash, PSRAM, CDC-serial, Ethernet | All available plugins |
ESPEasy_mega-20230822_max_ESP32_16M1M_ETH.bin | ESP32 with 16MB flash, SPIFFS, Ethernet | All available plugins |
ESPEasy_mega-20230822_max_ESP32_16M8M.bin | ESP32 with 16MB flash, LittleFS, Ethernet | All available plugins |
ESPEasy_mega-20260121_normal_ESP8266_1M.bin | ESP8266/ESP8285 with 1MB flash | Stable |
ESPEasy_mega-20260121_normal_ESP8266_4M1M.bin | ESP8266 with 4MB flash | Stable |
ESPEasy_mega-20260121_collection_A_ESP8266_4M1M.bin | ESP8266 with 4MB flash | Stable + Collection base + set A |
ESPEasy_mega-20260121_normal_ESP32_4M316k.bin | ESP32 with 4MB flash | Stable |
ESPEasy_mega-20260121_collection_A_ESP32_4M316k.bin | ESP32 with 4MB flash | Stable + Collection base + set A |
ESPEasy_mega-20260121_collection_B_ESP32_4M316k.bin | ESP32 with 4MB flash | Stable + Collection base + set B |
ESPEasy_mega-20260121_max_ESP32s3_8M1M.bin | ESP32-S3 with 8MB flash, CDC-serial, Ethernet | All available plugins |
ESPEasy_mega-20260121_max_ESP32s3_8M1M_OPI_PSRAM.bin | ESP32-S3 8MB flash, PSRAM, CDC-serial, Ethernet | All available plugins |
ESPEasy_mega-20260121_max_ESP32_16M8M.bin | ESP32 with 16MB flash, LittleFS, Ethernet | All available plugins |
The binary files for the different ESP32 variants (S2, C3, S3, C2, C6, Solo1, 'Classic') are available in separate archives.
The binary files for the different ESP32 variants (S2, C3, S3, C2, C6/C61, C5, P4, Solo1, 'Classic') are available in separate archives.
To see what plugins are included in which collection set, you can find that on the [ESPEasy Plugin overview page](https://espeasy.readthedocs.io/en/latest/Plugin/_Plugin.html)
+40
View File
@@ -0,0 +1,40 @@
{
"build": {
"arduino":{
"ldscript": "esp32c5_out.ld"
},
"core": "esp32",
"extra_flags": "-DARDUINO_TASMOTA -DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=1 -DUSE_USB_CDC_CONSOLE -DESP32_16M -DESP32C5 -DARDUINO_USB_CDC_ON_BOOT=0",
"f_cpu": "160000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"mcu": "esp32c5",
"variant": "esp32c5",
"partitions": "boards/partitions/esp32_partition_app4096k_spiffs8124k.csv"
},
"connectivity": [
"wifi",
"bluetooth"
],
"debug": {
"default_tool": "esp-builtin",
"onboard_tools": [
"esp-builtin"
],
"openocd_target": "esp32c5.cfg"
},
"frameworks": [
"arduino",
"espidf"
],
"name": "Espressif Generic ESP32-C5 16M Flash, ESPEasy 4096k Code/OTA 8M FS",
"upload": {
"flash_size": "16MB",
"maximum_ram_size": 327680,
"maximum_size": 16777216,
"require_upload_port": true,
"speed": 460800
},
"url": "https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32c5/esp32-c5-devkitc-1/index.html",
"vendor": "Espressif"
}
+40
View File
@@ -0,0 +1,40 @@
{
"build": {
"arduino":{
"ldscript": "esp32c5_out.ld"
},
"core": "esp32",
"extra_flags": "-DARDUINO_TASMOTA -DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=1 -DUSE_USB_CDC_CONSOLE -DESP32_32M -DESP32C5 -DARDUINO_USB_CDC_ON_BOOT=0",
"f_cpu": "160000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"mcu": "esp32c5",
"variant": "esp32c5",
"partitions": "boards/partitions/esp32_partition_app6144k_spiffs20412k.csv"
},
"connectivity": [
"wifi",
"bluetooth"
],
"debug": {
"default_tool": "esp-builtin",
"onboard_tools": [
"esp-builtin"
],
"openocd_target": "esp32c5.cfg"
},
"frameworks": [
"arduino",
"espidf"
],
"name": "Espressif Generic ESP32-C5 32M Flash, ESPEasy 6144k Code/OTA 20M FS",
"upload": {
"flash_size": "32MB",
"maximum_ram_size": 327680,
"maximum_size": 33554432,
"require_upload_port": true,
"speed": 460800
},
"url": "https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32c5/esp32-c5-devkitc-1/index.html",
"vendor": "Espressif"
}
+39
View File
@@ -0,0 +1,39 @@
{
"build": {
"core": "esp32",
"extra_flags": [
"-DARDUINO_TASMOTA -DESP32P4 -DESP32_32M -DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=1 -DUSE_USB_CDC_CONSOLE"
],
"f_cpu": "360000000L",
"f_flash": "80000000L",
"f_psram": "200000000L",
"flash_mode": "qio",
"mcu": "esp32p4",
"chip_variant": "esp32p4_es",
"variant": "esp32p4",
"partitions": "boards/partitions/esp32_partition_app6144k_spiffs20412k.csv"
},
"connectivity": [
"wifi",
"bluetooth",
"openthread",
"ethernet"
],
"debug": {
"openocd_target": "esp32p4.cfg"
},
"frameworks": [
"arduino",
"espidf"
],
"name": "Espressif ESP32-P4 Function EV Board 32M Flash, ESPEasy 6144k Code/OTA 20M FS",
"upload": {
"flash_size": "32MB",
"maximum_ram_size": 768000,
"maximum_size": 33554432,
"require_upload_port": true,
"speed": 1500000
},
"url": "https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32p4/esp32-p4-function-ev-board/index.html",
"vendor": "Espressif"
}
+39
View File
@@ -0,0 +1,39 @@
{
"build": {
"core": "esp32",
"extra_flags": [
"-DARDUINO_TASMOTA -DESP32P4R3 -DESP32_32M -DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=1 -DUSE_USB_CDC_CONSOLE"
],
"f_cpu": "400000000L",
"f_flash": "80000000L",
"f_psram": "200000000L",
"flash_mode": "qio",
"mcu": "esp32p4",
"chip_variant": "esp32p4",
"variant": "esp32p4",
"partitions": "boards/partitions/esp32_partition_app6144k_spiffs20412k.csv"
},
"connectivity": [
"wifi",
"bluetooth",
"openthread",
"ethernet"
],
"debug": {
"openocd_target": "esp32p4.cfg"
},
"frameworks": [
"arduino",
"espidf"
],
"name": "Espressif Generic ESP32-P4 rev.3 32M Flash, ESPEasy 6144k Code/OTA 20M FS",
"upload": {
"flash_size": "32MB",
"maximum_ram_size": 768000,
"maximum_size": 33554432,
"require_upload_port": true,
"speed": 1500000
},
"url": "https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32p4/esp32-p4x-function-ev-board/index.html",
"vendor": "Espressif"
}
+1 -1
View File
@@ -34,6 +34,6 @@
"require_upload_port": true,
"speed": 1500000
},
"url": "https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32p4/esp32-p4-function-ev-board/index.html",
"url": "https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32p4/esp32-p4x-function-ev-board/index.html",
"vendor": "Espressif"
}
+41
View File
@@ -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"
}
@@ -0,0 +1,7 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x600000,
app1, app, ota_1, 0x610000,0x600000,
eeprom, data, 0x99, 0xC10000,0x1000,
spiffs, data, spiffs, 0xC11000,0x13EF000,
1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 0x5000
3 otadata data ota 0xe000 0x2000
4 app0 app ota_0 0x10000 0x600000
5 app1 app ota_1 0x610000 0x600000
6 eeprom data 0x99 0xC10000 0x1000
7 spiffs data spiffs 0xC11000 0x13EF000
+2 -2
View File
@@ -66,10 +66,10 @@ ESP32 now has a number of builds:
- custom_ESP32_4M316k Build template using either the plugin set defined in ``Custom.h`` or ``tools/pio/pre_custom_esp32.py``
- test_ESP32_4M316k Build using the "testing" set of plugins for ESP32
- test_ESP32-wrover-kit_4M316k A build for ESP32 including build flags for the official WRover test kit.
- max_ESP32_16M1M A build for ESP32 with larger flash size including all plugins.
- max_ESP32_16M8M A build for ESP32 with larger flash size including all plugins.
ESP32 also supports Ethernet.
Ethernet support is included in similar builds as mentioned before, only ending with "_ETH" in the file name.
Ethernet support is included in nearly all ESP32 builds, only ESP32-C2 doesn't have support for Ethernet.
+28 -24
View File
@@ -10,9 +10,14 @@ ESPEasy Project Directories
Below a list of the most important directories and files used in this project.
* ``.pio/`` Working dir for PlatformIO (Ignored by Git)
* ``build_output/`` The output directory where all built files are collected.
* ``dist/`` Files also includd in the nightly builds (e.g. blank flash files and ESPEasy flasher)
* ``.github/`` Buildscripts used by the Github Actions build and release CI jobs.
* ``.pio/`` Working dir for pioarduino (Ignored by Git)
* ``.platformio/`` Working dir for pioarduino (Ignored by Git)
* ``.platformio/penv/`` Directory to store the used Python Virtual Environment.
* ``boards/`` Used board definitions.
* ``boards/partitions/`` Used partition layout in ESP32 builds.
* ``build_output/`` The output directory where all built files are collected. (Ignored by Git)
* ``dist/`` Files also includd in the nightly builds (e.g. blank flash files and Espressif flash download tool)
* ``docs/`` Documentation tree using Sphinx to build the documents.
* ``hooks/`` Used for the continous integration process, used by Travis CI.
* ``include/`` PlatformIO's suggested folder for .h files (not yet used)
@@ -20,16 +25,14 @@ Below a list of the most important directories and files used in this project.
* ``misc/`` Additional files needed for some use cases, like specialized a firmware for some boards or decoder files for the TTN project.
* ``patches/`` Patches we apply during build for core libraries.
* ``src/`` The source code of ESPeasy
* ``src/ESPEasy/`` Parts of ESPeasy use C++ namespaces, and are placed in this directory, matching the namespace structure.
* ``static/`` Static files we use in ESPEasy, like CSS/JS/ICO files.
* ``test/`` Test scripts to be used in the continous integration process.
* ``tools/`` Tools to help build ESPeasy.
* ``tools/pio/pre_custom_esp32.py`` Python helper script for building custom ESP32 binary.
* ``tools/pio/pre_custom_esp8266.py`` Python helper script for building custom ESP8266 binary.
* ``venv/`` Directory to store the used Python Virtual Environment. (Ignored by Git)
* ``platformio.ini`` Configuration file for PlatformIO to define various build setups.
* ``uncrustify.cfg`` Configuration file for Uncrustify, to format source code using some uniform formatting rules.
* ``tools/pio/pre_custom_esp*.py`` Python helper scripts for building custom ESP binaries.
* ``platformio.ini`` Configuration file for pioarduino to define various build setups.
* ``requirements.txt`` List of used Python libraries and their version (result of ``pip freeze`` with Virtual env active)
* ``boards/partitions/esp32_partition_app1810k_spiffs316k.csv`` Used partition layout in ESP32 4M builds.
* ``uncrustify.cfg`` Configuration file for Uncrustify, to format source code using some uniform formatting rules.
ESPEasy src dir
@@ -107,14 +110,17 @@ There is also a number of special builds:
ESP Chip Type
-------------
* ``ESP8266`` Most likely option.
* ``ESP8266`` Deprecated for new projects, as support from Espressif has been stopped, even though new chips are still being produced.
* ``ESP8285`` Supported in ``ESP8266`` builds. Used in some Sonoff modules. This chip has embedded flash, so no extra flash chip.
* ``ESP32`` Allows for more memory and more GPIO pins.
* ``ESP32-S2`` Newer version of ESP32. Has even more GPIO pins, but some specific features of ESP32 were removed.
* ``ESP32-S3`` Newer version of ESP32 and ESP32-S2. Has even more GPIO pins, some specific features of ESP32 were removed, and some design choices of ESP32-S2 are reverted and implemented differently.
* ``ESP32-C2`` Preliminary supported. Cheaper variant of ESP32-C3, and also an ESP8266 replacement. Available as pin-compatible module for ESP8266. Single core, and max 120 MHz clock speed.
* ``ESP32-C2`` Cheaper variant of ESP32-C3, and also an ESP8266 replacement. Available as pin-compatible module for ESP8266. Single core, and max 120 MHz clock speed.
* ``ESP32-C3`` Intended as a replacement for ESP8266, using ESP32 technology, though single-core and with limited clock speed (160 MHz, some models 120 MHz).
* ``ESP32-C6`` Preliminary supported. Will allow connectivity with IEEE 802.15.4 (Thread/Zigbee) wireless protocol.
* ``ESP32-C6`` Will allow connectivity with IEEE 802.15.4 (Thread/Zigbee) wireless protocol.
* ``ESP32-C61`` Preliminary supported. Will allow connectivity with IEEE 802.15.4 (Thread/Zigbee) wireless protocol.
* ``ESP32-C5`` Will allow connectivity with WiFi 2.4GHz and 5GHz support.
* ``ESP32-P4`` High-end dual-core MCU, with many GPIO pins and support for camera, display, RMII Ethernet and many other protocols. No on-chip WiFi support. Often has an additional ESP32-C6 with ESP-HostedMCU to provide wireless support via an SDIO connection.
Memory Size and Partitioning
----------------------------
@@ -123,12 +129,12 @@ Memory Size and Partitioning
* ``2M`` 2 MB flash modules (e.g. Shelly1/WROOM02)
* ``4M`` 4 MB flash modules (e.g. NodeMCU/ESP32)
* ``16M`` 16 MB flash modules (e.g. Wemos D1 mini pro) (has 14 MB LittleFS filesystem, as SPIFFS is unstable > 2 MB)
* ``4M1M`` 4 MB flash modules with 1 MB filesystem (usually SPIFFS)
* ``4M2M`` 4 MB flash modules with 2 MB filesystem (usually SPIFFS)
* ``4M316k`` 4 MB flash modules using 1.8 MB sketch size, with 316 kB filesystem (usually SPIFFS) (for ESP32)
* ``8M1M`` 8 MB flash modules using 3.5MB sketch size, with 1 MB filesystem (LittleFS) (ESP32 only a.t.m.)
* ``16M1M`` 16 MB flash modules using 4MB sketch size, with 1 MB filesystem (usually SPIFFS) (ESP32 only a.t.m.)
* ``16M8M`` 16 MB flash modules using 4MB sketch size, with 8 MB filesystem (LittleFS) (ESP32 only a.t.m.)
* ``4M1M`` 4 MB flash modules with 1 MB filesystem (SPIFFS)
* ``4M2M`` 4 MB flash modules with 2 MB filesystem (SPIFFS)
* ``4M316k`` 4 MB flash modules using 1.8 MB sketch size, with 316 kB filesystem (LittleFS) (for ESP32)
* ``8M1M`` 8 MB flash modules using 3.5MB sketch size, with 1 MB filesystem (LittleFS) (ESP32 only)
* ``16M8M`` 16 MB flash modules using 4MB sketch size, with 8 MB filesystem (LittleFS) (ESP32 only)
* ``32M20M`` 32 MB flash modules using 6MB sketch size, with 20 MB filesystem (LittleFS) (ESP32 only)
Optional build options
----------------------
@@ -143,7 +149,7 @@ Optional build options
* ``OPI`` Flash via OPI protocol support (ESP32 only)
* ``QIO`` Flash via QIO protocol support (ESP32 only)
* ``CDC`` CDC Serial (built-in USB) support (ESP32 only)
* ``ETH`` Ethernet interface enabled (ESP32 only)
* ``ETH`` Ethernet interface enabled (ESP32 only, no longer used, as all ESP32, except for ESP32-C2, have support for Ethernet included)
Please note that the performance of 14MB SPIFFS (16M flash ESP8266 modules) is really slow.
@@ -183,17 +189,15 @@ This also means we still need to update the 2-step updater to support .bin.gz fi
ESP32 builds
------------
There are several builds for ESP32:
There are several builds for ESP32, this is just a selection:
* ``normal_ESP32_4M316k`` Build using the "stable" set of plugins for ESP32
* ``normal_ESP32_4M316k_ETH`` Build using the "stable" set of plugins for ESP32, with support for an on-board Ethernet controller
* ``normal_ESP32_4M316k`` Build using the "stable" set of plugins for ESP32, with support for an on-board Ethernet controller
* ``custom_ESP32_4M316k`` Build template using either the plugin set defined in ``Custom.h`` or ``tools/pio/pre_custom_esp32.py``
* ``collection_A_ESP32_4M316k`` Build using the "Collection" set "A" of plugins for ESP32
* ``collection_B_ESP32_4M316k`` Build using the "Collection" set "B" of plugins for ESP32
* ``collection_C_ESP32_4M316k`` Build using the "Collection" set "C" of plugins for ESP32
* ``collection_D_ESP32_4M316k`` Build using the "Collection" set "D" of plugins for ESP32
* ``collection_A_ESP32-wrover-kit_4M316k`` A build for ESP32 including build flags for the official WRover test kit.
* ``max_ESP32_16M8M_LittleFS`` Build using all available plugins and controllers for ESP32 with 16 MB flash (some lolin_d32_pro boards)
* ``max_ESP32_16M8M`` Build using all available plugins and controllers for ESP32 with 16 MB flash (like lolin_d32_pro boards)
Since ESP32 does have its flash partitioned in several blocks, we have 2 bin files of each ESP32 build, f.e.:
@@ -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();
}
}
+3 -2
View File
@@ -31,10 +31,11 @@ void DIRECT_pinWrite(IO_REG_TYPE pin, bool pinstate)
digitalWrite(pin, pinstate);
return;
}
# endif // ifdef ARDUINO_ARCH_ESP8266
if (pinstate) { DIRECT_WRITE_HIGH(reg, PIN_TO_BITMASK(pin)); }
else { DIRECT_WRITE_LOW(reg, PIN_TO_BITMASK(pin)); }
#else
directWrite(pin, pinstate ? 1u : 0u);
# endif // ifdef ARDUINO_ARCH_ESP8266
}
void DIRECT_PINMODE_OUTPUT(IO_REG_TYPE pin)
+21 -116
View File
@@ -134,147 +134,52 @@ void DIRECT_PINMODE_INPUT_ISR(IO_REG_TYPE pin);
int32_t DIRECT_measureWaitForPinState_ISR(IO_REG_TYPE gpio_pin_rx, uint32_t start_usec, int32_t timeout_usec, bool newState);
#elif defined(ARDUINO_ARCH_ESP32)
#if ESP_IDF_VERSION_MAJOR < 5
#include <esp32-hal-gpio.h>
#include <driver/rtc_io.h>
#else
#include <soc/gpio_struct.h>
#include <driver/rtc_io.h>
#include <esp_idf_version.h>
#include <soc/soc_caps.h>
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0)
#include <driver/gpio.h>
#endif
#endif
#include <hal/gpio_ll.h>
#define PIN_TO_BASEREG(pin) (0)
#define PIN_TO_BITMASK(pin) (pin)
#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
static inline __attribute__((always_inline))
IO_REG_TYPE directRead(IO_REG_TYPE pin)
__attribute__((always_inline))
static inline IO_REG_TYPE directRead(IO_REG_TYPE pin)
{
#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C5
return (GPIO.in.val >> pin) & 0x1;
#elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C61 || CONFIG_IDF_TARGET_ESP32P4
if ( pin < 32 )
return (GPIO.in.val >> pin) & 0x1;
else if ( pin < SOC_GPIO_PIN_COUNT )
return (GPIO.in1.val >> (pin - 32)) & 0x1;
#else // plain ESP32
if ( pin < 32 )
return (GPIO.in >> pin) & 0x1;
else if ( pin < SOC_GPIO_PIN_COUNT )
return (GPIO.in1.val >> (pin - 32)) & 0x1;
#endif
return 0;
return gpio_ll_get_level(&GPIO, pin);
}
static inline __attribute__((always_inline))
void directWriteLow(IO_REG_TYPE pin)
__attribute__((always_inline))
static inline void directWrite(IO_REG_TYPE pin, IO_REG_TYPE level)
{
#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C5
GPIO.out_w1tc.val = ((uint32_t)1 << pin);
#elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C61 || CONFIG_IDF_TARGET_ESP32P4
if ( pin < 32 )
GPIO.out_w1tc.val = ((uint32_t)1 << pin);
else if ( pin < SOC_GPIO_PIN_COUNT )
GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32));
#else // plain ESP32
if ( pin < 32 )
GPIO.out_w1tc = ((uint32_t)1 << pin);
else if ( pin < SOC_GPIO_PIN_COUNT )
GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32));
#endif
gpio_ll_set_level(&GPIO, pin, level);
}
static inline __attribute__((always_inline))
void directWriteHigh(IO_REG_TYPE pin)
__attribute__((always_inline))
static inline void directWriteLow(IO_REG_TYPE pin)
{
#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C5
GPIO.out_w1ts.val = ((uint32_t)1 << pin);
#elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C61 || CONFIG_IDF_TARGET_ESP32P4
if ( pin < 32 )
GPIO.out_w1ts.val = ((uint32_t)1 << pin);
else if ( pin < SOC_GPIO_PIN_COUNT )
GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32));
#else // plain ESP32
if ( pin < 32 )
GPIO.out_w1ts = ((uint32_t)1 << pin);
else if ( pin < SOC_GPIO_PIN_COUNT )
GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32));
#endif
gpio_ll_set_level(&GPIO, pin, 0u);
}
static inline __attribute__((always_inline))
void directModeInput(IO_REG_TYPE pin)
__attribute__((always_inline))
static inline void directWriteHigh(IO_REG_TYPE pin)
{
#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C5
GPIO.enable_w1tc.val = ((uint32_t)1 << (pin));
#else
if ( GPIO_IS_VALID_GPIO(pin) )
{
#if ESP_IDF_VERSION_MAJOR < 4 // IDF 3.x ESP32/PICO-D4
uint32_t rtc_reg(rtc_gpio_desc[pin].reg);
if ( rtc_reg ) // RTC pins PULL settings
{
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux);
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown);
}
#endif
// Input
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C61 || CONFIG_IDF_TARGET_ESP32P4
if ( pin < 32 )
GPIO.enable_w1tc.val = ((uint32_t)1 << pin);
else
GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32));
#else
if ( pin < 32 )
GPIO.enable_w1tc = ((uint32_t)1 << pin);
else
GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32));
#endif
}
#endif
gpio_ll_set_level(&GPIO, pin, 1u);
}
static inline __attribute__((always_inline))
void directModeOutput(IO_REG_TYPE pin)
__attribute__((always_inline))
static inline void directModeInput(IO_REG_TYPE pin)
{
#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C5
GPIO.enable_w1ts.val = ((uint32_t)1 << (pin));
#else
if ( GPIO_IS_VALID_GPIO(pin) && pin <= 33 ) // pins above 33 can be only inputs
{
#if ESP_IDF_VERSION_MAJOR < 4 // IDF 3.x ESP32/PICO-D4
uint32_t rtc_reg(rtc_gpio_desc[pin].reg);
gpio_ll_output_disable(&GPIO, pin);
}
if ( rtc_reg ) // RTC pins PULL settings
{
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux);
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown);
}
#endif
// Output
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C61 || CONFIG_IDF_TARGET_ESP32P4
if ( pin < 32 )
GPIO.enable_w1ts.val = ((uint32_t)1 << pin);
else // already validated to pins <= 33
GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32));
#else
if ( pin < 32 )
GPIO.enable_w1ts = ((uint32_t)1 << pin);
else // already validated to pins <= 33
GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32));
#endif
}
#endif
__attribute__((always_inline))
static inline void directModeOutput(IO_REG_TYPE pin)
{
gpio_ll_output_enable(&GPIO, pin);
}
#define DIRECT_READ(base, pin) directRead(pin)
+5 -2
View File
@@ -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
+27
View File
@@ -14,6 +14,15 @@ lib_ignore = ${esp32_base_idf5_5.lib_ignore}
board = esp32c5cdc
[env:custom_ESP32c5_4M316k]
extends = esp32c5_common_LittleFS
build_flags = ${esp32c5_common_LittleFS.build_flags}
-DPLUGIN_BUILD_CUSTOM
extra_scripts = ${esp32c5_common_LittleFS.extra_scripts}
pre:tools/pio/pre_custom_esp32.py
[env:max_ESP32c5_8M1M]
extends = esp32c5_common_LittleFS
board = esp32c5cdc-8M
@@ -26,4 +35,22 @@ build_flags = ${esp32c5_common_LittleFS.build_flags}
-D P116_EXTRA_ST7789=1
extra_scripts = ${esp32c5_common_LittleFS.extra_scripts}
[env:max_ESP32c5_16M8M]
extends = esp32c5_common_LittleFS
board = esp32c5cdc-16M
build_flags = ${esp32c5_common_LittleFS.build_flags}
-DFEATURE_ETHERNET=1
-DFEATURE_ARDUINO_OTA=1
-DPLUGIN_BUILD_MAX_ESP32
-DPLUGIN_BUILD_IR_EXTENDED
-D ST7789_EXTRA_INIT=1
-D P116_EXTRA_ST7789=1
extra_scripts = ${esp32c5_common_LittleFS.extra_scripts}
[env:max32_ESP32c5_32M20M]
extends = env:max_ESP32c5_16M8M
board = esp32c5cdc-32M
build_flags = ${env:max_ESP32c5_16M8M.build_flags}
-DPLUGIN_BUILD_MAX32_ESP32
+6
View File
@@ -27,4 +27,10 @@ build_flags = ${esp32p4_common_LittleFS.build_flags}
-D P116_EXTRA_ST7789=1
extra_scripts = ${esp32p4_common_LittleFS.extra_scripts}
[env:max32_ESP32p4_32M20M]
extends = env:max_ESP32p4_16M8M
board = esp32p4_ev-32M
build_flags = ${env:max_ESP32p4_16M8M.build_flags}
-DPLUGIN_BUILD_MAX32_ESP32
+6
View File
@@ -11,4 +11,10 @@ board = esp32p4r3
extends = env:max_ESP32p4_16M8M
board = esp32p4r3
[env:max32_ESP32p4r3_32M20M]
extends = env:max_ESP32p4_16M8M
board = esp32p4r3-32M
build_flags = ${env:max_ESP32p4r3_16M8M.build_flags}
-DPLUGIN_BUILD_MAX32_ESP32
+11
View File
@@ -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
View File
@@ -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) {
+2 -2
View File
@@ -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
+5 -1
View File
@@ -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();
+29 -4
View File
@@ -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;
+3 -3
View File
@@ -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;
}
+9 -4
View File
@@ -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,
+5 -11
View File
@@ -57,17 +57,11 @@ bool NWPlugin_001(NWPlugin::Function function, EventStruct *event, String& strin
{
case NWPlugin::Function::NWPLUGIN_DRIVER_ADD:
{
NetworkDriverStruct& nw = getNetworkDriverStruct(networkDriverIndex_t::toNetworkDriverIndex(event->idx));
nw.onlySingleInstance = true;
nw.alwaysPresent = true;
# ifdef ESP32P4
nw.enabledOnFactoryReset = false;
// ESPEasy::net::wifi::GetHostedMCUFwVersion() > 0x00020600;
# else // ifdef ESP32P4
NetworkDriverStruct& nw = getNetworkDriverStruct(networkDriverIndex_t::toNetworkDriverIndex(event->idx));
nw.onlySingleInstance = true;
nw.alwaysPresent = true;
nw.enabledOnFactoryReset = true;
# endif // ifdef ESP32P4
nw.fixedNetworkIndex = NWPLUGIN_ID_001 - 1; // Start counting at 0
nw.fixedNetworkIndex = NWPLUGIN_ID_001 - 1; // Start counting at 0
break;
}
@@ -488,7 +482,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;
+73 -47
View File
@@ -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>
@@ -39,6 +39,10 @@ extern "C" {
# endif // ifdef ESP32
# ifdef BOARD_HAS_SDIO_ESP_HOSTED
# define MIN_REQUIRED_ESP_HOSTED_FW 0x00020600
# endif
namespace ESPEasy {
namespace net {
namespace wifi {
@@ -101,6 +105,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 +190,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 +260,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 +345,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 +356,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;
}
@@ -345,6 +382,12 @@ bool write_WiFi_Hosted_MCU_info(KeyValueWriter*writer)
} else {
writer->write({ F("ESP-Host Fw Version"), GetHostedFwVersion(EspHostTypes::ESP_HOST) });
writer->write({ F("ESP-Hosted-MCU Fw Version"), GetHostedFwVersion(EspHostTypes::ESP_HOSTED) });
if (GetHostedMCUFwVersion() < MIN_REQUIRED_ESP_HOSTED_FW) {
writer->writeNote(F("ESP-Hosted-MCU firmware is too old, run <tt>wifiotahostedmcu</tt> via ESPEasy console"));
} else if (hostedHasUpdate()) {
writer->writeNote(F("ESP-Hosted-MCU firmware update available, run <tt>wifiotahostedmcu</tt> via ESPEasy console"));
}
writer->write({ F("ESP-Hosted-MCU Chip"), GetHostedMCU() });
writer->write({
F("MAC"),
@@ -471,37 +514,20 @@ bool wifiAPmodeActivelyUsed()
// AP not active or soon to be disabled in processDisableAPmode()
return false;
}
#ifdef BOARD_HAS_SDIO_ESP_HOSTED
if (GetHostedMCUFwVersion() < MIN_REQUIRED_ESP_HOSTED_FW) {
// Hosted fw is too old, function below is not yet implemented
// When calling that function the ESP32-P4 will crash.
return false;
}
#endif
return SOFTAP_STATION_COUNT != 0;
// FIXME TD-er: is effectively checking for AP active enough or must really check for connected clients to prevent automatic wifi
// 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
// ********************************************************************************
+6 -2
View File
@@ -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); }
+1
View File
@@ -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)
+16 -1
View File
@@ -206,11 +206,21 @@ String Command_Wifi_OTA_hosted_mcu(
return return_command_failed_flashstr();
}
const String url = hostedGetUpdateURL();
uint32_t major, minor, patch;
hostedGetHostVersion(&major, &minor, &patch);
// https://pioarduino.github.io/esp-hosted-mcu-firmware/v2.12.7/network_adapter_esp32c6.bin
const String url = strformat(
F("https://pioarduino.github.io/esp-hosted-mcu-firmware/v%u.%u.%u/network_adapter_%s.bin"),
major, minor, patch,
CONFIG_ESP_HOSTED_IDF_SLAVE_TARGET);
// Step 4: Begin the update process - display update URL
addLog(LOG_LEVEL_INFO, concat(F("Updating esp-hosted co-processor from "), url));
processLogs();
/*
// Step 5: Create a secure network client for HTTPS communication
BearSSL::WiFiClientSecure_light secureClient(4096, 4096);
@@ -264,6 +274,7 @@ String Command_Wifi_OTA_hosted_mcu(
// Step 11: Initialize the ESP-Hosted update process
addLog(LOG_LEVEL_INFO, F("Beginning update process..."));
processLogs();
// FIXME TD-er: Block actual update to see how far we get with making connection
// goto finish_ota;
@@ -343,6 +354,7 @@ String Command_Wifi_OTA_hosted_mcu(
// Small delay to prevent overwhelming the system
delay(1);
}
processLogs(true);
// Step 15: Clean up allocated buffer
free(buff);
@@ -352,6 +364,7 @@ String Command_Wifi_OTA_hosted_mcu(
} else {
addLog(LOG_LEVEL_ERROR, strformat(F("ERROR: HTTP request failed with code %d!"), httpCode));
}
processLogs(true);
// Step 16: Close HTTP connection
https.end();
@@ -361,6 +374,8 @@ finish_ota:
// Step 17: Clean up network client
// delete client;
processLogs(true);
if (updateSuccess) { return return_command_success_flashstr(); }
return return_command_failed_flashstr();
}
+5
View File
@@ -8,6 +8,11 @@
#endif
#if defined(PLUGIN_BUILD_MAX32_ESP32) && !defined(PLUGIN_BUILD_MAX_ESP32)
#define PLUGIN_BUILD_MAX_ESP32
#endif
/*
#################################################
This is the place where plugins are registered
+11
View File
@@ -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; }
+5
View File
@@ -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);
+2 -1
View File
@@ -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
+6 -2
View File
@@ -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
-14
View File
@@ -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;
}
-2
View File
@@ -47,8 +47,6 @@ private:
void endPort();
int availableForWrite();
uint32_t _baudrate = 115200u;
EspEasy_Console_Port _mainSerial;
+10 -4
View File
@@ -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;
+15
View File
@@ -219,6 +219,7 @@ void addLog(uint8_t logLevel, const __FlashStringHelper *str)
}
#endif // ifdef ESP32
Logging.addLogEntry(LogEntry_t(logLevel, str));
processLogs();
}
void addLog(uint8_t logLevel, const char *line) {
@@ -233,6 +234,7 @@ void addLog(uint8_t logLevel, const char *line) {
}
#endif // ifdef ESP32
Logging.addLogEntry(LogEntry_t(logLevel, line));
processLogs();
}
void addLog(uint8_t logLevel, String&& str) { addToLogMove(logLevel, std::move(str)); }
@@ -250,6 +252,7 @@ void addLog(uint8_t logLevel, const String& str)
}
#endif // ifdef ESP32
Logging.addLogEntry(LogEntry_t(logLevel, str));
processLogs();
}
void addToLogMove(uint8_t logLevel, String&& str)
@@ -265,4 +268,16 @@ void addToLogMove(uint8_t logLevel, String&& str)
}
#endif // ifdef ESP32
Logging.addLogEntry(LogEntry_t(logLevel, std::move(str)));
processLogs();
}
void processLogs(bool serialOnly)
{
process_serialWriteBuffer();
Logging.loop(serialOnly);
#if FEATURE_SYSLOG
if (!serialOnly) {
syslogWriter.process();
}
#endif
}
+4
View File
@@ -47,3 +47,7 @@ void addLog(uint8_t logLevel,
void addToLogMove(uint8_t logLevel,
String&& str);
void processLogs(bool serialOnly = false);
@@ -28,6 +28,7 @@
* run background tasks
\*********************************************************************************************/
bool runningBackgroundTasks = false;
void backgroundtasks()
{
// checkRAM(F("backgroundtasks"));
@@ -74,11 +75,8 @@ void backgroundtasks()
}
*/
process_serialWriteBuffer();
#if FEATURE_SYSLOG
syslogWriter.process();
#endif
Logging.loop();
processLogs();
if (!UseRTOSMultitasking) {
serial();
+8 -7
View File
@@ -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"));
}
+2 -2
View File
@@ -140,8 +140,8 @@ uint32_t getFlashRealSizeInBytes() {
if (res == 0) {
#if defined(ESP32)
#ifdef ESP32P4
// TODO TD-er: Implement
res = 1 << 24;
const int32_t flash_cap_MB = getEmbeddedFlashSize();
res = flash_cap_MB << 20;
#else
res = (1 << ((getFlashChipId() >> 16) & 0xFF));
#endif
+2 -1
View File
@@ -118,7 +118,8 @@ size_t LogStreamWriter::write_part(String& str, Print& stream, size_t nrBytesTo
const size_t bytesLeft = str.length() - _readpos;
bytesWritten = stream.write(&str[_readpos], bytesLeft);
_readpos += bytesWritten;
} else {
}
if (_readpos >= str.length()) {
// Clear str
str.clear();
_readpos = 0;
+4 -2
View File
@@ -52,7 +52,7 @@ void LogHelper::addLogEntry(LogEntry_t&& logEntry)
_logBuffer.add(std::move(logEntry));
loop();
loop(false);
}
bool LogHelper::getNext(LogDestination logDestination, uint32_t& timestamp, String& message, uint8_t& loglevel)
@@ -65,9 +65,10 @@ uint32_t LogHelper::getNrMessages(LogDestination logDestination) const
return _logBuffer.getNrMessages(logDestination);
}
void LogHelper::loop()
void LogHelper::loop(bool serialOnly)
{
#if FEATURE_SD
if (!serialOnly) {
String message;
uint32_t timestamp{};
uint8_t loglevel{};
@@ -76,6 +77,7 @@ void LogHelper::loop()
{
addToSDLog(loglevel, message);
}
}
#endif
_logBuffer.clearExpiredEntries();
}
+1 -1
View File
@@ -21,7 +21,7 @@ public:
uint32_t getNrMessages(LogDestination logDestination) const;
void loop();
void loop(bool serialOnly);
bool logActiveRead(LogDestination logDestination);
+12 -1
View File
@@ -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
View File
@@ -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
+21 -3
View File
@@ -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) {
+2
View File
@@ -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);
+2 -1
View File
@@ -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);
+18 -6
View File
@@ -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);
}
+187 -60
View File
@@ -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
+40 -25
View File
@@ -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;
+2 -1
View File
@@ -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
+66 -7
View File
@@ -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)
+8
View File
@@ -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));
}
}
}
+47 -17
View File
@@ -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
// ********************************************************************************
+8
View File
@@ -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
// ********************************************************************************
+2 -2
View File
@@ -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; }
}
+4 -1
View File
@@ -25,10 +25,13 @@ def get_max_bin_size(env_name, file_suffix):
if "_8M1M" in env_name:
# ESP32 with 3520k of sketch space.
max_bin_size = 3604480
if "_ESP32_" in env_name or "_ESP32c3_" in env_name or "_ESP32c5_" in env_name or "_ESP32c6_" in env_name or "_ESP32p4_" in env_name or "_ESP32p4r3_" in env_name or "_ESP32s2_" in env_name or "_ESP32s3_" in env_name:
if "_ESP32_" in env_name or "_ESP32c3_" in env_name or "_ESP32c5_" in env_name or "_ESP32c6_" in env_name or "_ESP32c61_" in env_name or "_ESP32p4_" in env_name or "_ESP32p4r3_" in env_name or "_ESP32s2_" in env_name or "_ESP32s3_" in env_name:
if "_16M8M" in env_name or "_16M2M" in env_name or "_16M1M" in env_name:
# ESP32 with 4096k of sketch space.
max_bin_size = 4194304
if "_32M20M" in env_name:
# ESP32 with 6144k of sketch space.
max_bin_size = 6291456
if "factory" in file_suffix:
# Factory bin files include a part which is not overwritten via OTA
max_bin_size = max_bin_size + 65536
+59 -70
View File
@@ -28,7 +28,7 @@ def create_display_text(description, version, families):
esp32_split.append('S2')
if 'ESP32-S31' in families:
esp32_split.append('S31')
elif 'ESP32-S3' in families:
if 'ESP32-S3' in families:
esp32_split.append('S3')
if 'ESP32-C2' in families:
esp32_split.append('C2')
@@ -38,7 +38,7 @@ def create_display_text(description, version, families):
esp32_split.append('C5')
if 'ESP32-C61' in families:
esp32_split.append('C61')
elif 'ESP32-C6' in families:
if 'ESP32-C6' in families:
esp32_split.append('C6')
if 'ESP32-H2' in families:
esp32_split.append('H2')
@@ -46,12 +46,13 @@ def create_display_text(description, version, families):
esp32_split.append('H21')
if 'ESP32-P4R3' in families:
esp32_split.append('P4R3')
elif 'ESP32-P4' in families:
if 'ESP32-P4' in families:
esp32_split.append('P4')
if len(esp32_split) > 0:
fam_split.append('ESP32-' + '/'.join(esp32_split))
res = list(set(esp32_split)) # Make list unique
res.sort(key=str.lower)
fam_split.append('ESP32-' + '/'.join(res))
fam_str = ','.join(fam_split)
@@ -59,11 +60,11 @@ def create_display_text(description, version, families):
def parse_filename(file, version, variant, file_suffix):
#print("{} : {} {} {}".format(file, version, variant, file_suffix))
# print("{} : {} {} {}".format(file, version, variant, file_suffix))
chipFamily = 'NotSet'
chipVariant = ''
manifest_suff = ''
chip_family = 'NotSet'
chip_variant = ''
manifest_suffix = ''
add_improv = True
main_group = 'Misc' # e.g. "4M Flash" or "Device Specific"
@@ -71,6 +72,7 @@ def parse_filename(file, version, variant, file_suffix):
description = 'NotSet'
sub_group = 'NotSet'
flash_size = 'NotSet'
flash_size_mb = 0 # For separating different "MAX" builds
build_flags = ''
@@ -78,53 +80,59 @@ def parse_filename(file, version, variant, file_suffix):
if ".factory.bin" in file_suffix:
if 'ESP32' in variant:
manifest_suff = '.manifest.json'
manifest_suffix = '.manifest.json'
if 'ESP32s2' in variant:
chipFamily = 'ESP32-S2'
chip_family = 'ESP32-S2'
elif 'ESP32s31' in variant:
chipFamily = 'ESP32-S31'
chip_family = 'ESP32-S31'
elif 'ESP32s3' in variant:
chipFamily = 'ESP32-S3'
chip_family = 'ESP32-S3'
elif 'ESP32c2' in variant:
chipFamily = 'ESP32-C2'
chip_family = 'ESP32-C2'
elif 'ESP32c3' in variant:
chipFamily = 'ESP32-C3'
chip_family = 'ESP32-C3'
elif 'ESP32c5' in variant:
chipFamily = 'ESP32-C5'
chip_family = 'ESP32-C5'
elif 'ESP32c61' in variant:
chipFamily = 'ESP32-C61'
chip_family = 'ESP32-C61'
elif 'ESP32c6' in variant:
chipFamily = 'ESP32-C6'
chip_family = 'ESP32-C6'
elif 'ESP32h21' in variant:
chipFamily = 'ESP32-H21'
chip_family = 'ESP32-H21'
elif 'ESP32h2' in variant:
chipFamily = 'ESP32-H2'
chip_family = 'ESP32-H2'
elif 'ESP32p4' in variant:
chipFamily = 'ESP32-P4'
chip_family = 'ESP32-P4'
if 'rev300' in variant or 'r3' in variant:
chipVariant = 'rev300'
chip_variant = 'rev300'
else:
chipVariant = 'rev0'
chip_variant = 'rev0'
else:
chipFamily = 'ESP32'
chip_family = 'ESP32'
if '_4M316k' in variant:
flash_size = '4M'
main_group = '4M Flash'
elif '_8M1M' in variant:
flash_size = '8M1M'
main_group = '8M Flash'
flash_size_mb = 8
main_group = '8M/16M/32M Flash MAX Builds'
elif '_16M1M' in variant:
flash_size = '16M1M'
main_group = '16M Flash'
elif '_16M8M' in variant:
flash_size = '16M8M'
main_group = '16M Flash'
flash_size_mb = 16
main_group = '8M/16M/32M Flash MAX Builds'
elif '_32M20M' in variant:
flash_size = '32M20M'
flash_size_mb = 32
main_group = '8M/16M/32M Flash MAX Builds'
else:
if ".bin" in file_suffix and ".gz" not in file_suffix and 'ESP32' not in variant:
chipFamily = 'ESP8266'
manifest_suff = '.manifest.json'
chip_family = 'ESP8266'
manifest_suffix = '.manifest.json'
add_improv = False
if '_4M1M' in variant:
@@ -140,8 +148,7 @@ def parse_filename(file, version, variant, file_suffix):
flash_size = '1M'
main_group = '1M Flash'
if 'NotSet' not in chipFamily:
if 'NotSet' not in chip_family:
for special in ['minimal_', 'core', '_302_', 'Domoticz', 'FHEM', 'hard_', 'beta', 'alt_wifi', 'OTA']:
if special in variant:
sub_group = variant
@@ -160,7 +167,7 @@ def parse_filename(file, version, variant, file_suffix):
group = 'NeoPixel'
elif 'normal_' in variant:
group = 'Normal'
elif 'max_' in variant:
elif 'max_' in variant or 'max32_' in variant or 'max8_' in variant:
group = 'MAX'
elif 'custom_' in variant:
group = 'Custom'
@@ -172,14 +179,14 @@ def parse_filename(file, version, variant, file_suffix):
if '_4M1M' in variant:
main_group = '4M Flash Collection Builds'
if 'NotSet' not in group:
sub_group_spit = group.split('_')
# Add some flags to differentiate the groups
# but also use this to sort the items per main group.
specials = []
specials.append(flash_size)
if 'MAX' not in group:
specials.append(flash_size)
if '_PSRAM' in variant:
specials.append('PSRAM')
if 'LittleFS' in variant and 'ESP32' not in variant:
@@ -193,7 +200,6 @@ def parse_filename(file, version, variant, file_suffix):
if 'solo1' in variant:
specials.append('Solo1')
for sp in specials:
sub_group_spit.append(sp)
@@ -229,58 +235,43 @@ def parse_filename(file, version, variant, file_suffix):
main_group = '4M Flash ESP32-solo1'
if ".factory.bin" in file_suffix or 'ESP32' not in file:
#print('{:10s}: {:34s}\t{:10s} {} / {}'.format(state, sub_group, chipFamily, version, file))
# print('{:10s}: {:34s}\t{:10s} {} / {}'.format(state, sub_group, chipFamily, version, file))
print('{:10s}: {:34s}\t{:10s} {} / {}'.format(state, description, chipFamily, version, file))
print('{:10s}: {:34s}\t{:10s} {} / {}'.format(state, description, chip_family, version, file))
if main_group not in manifest_binfiles:
manifest_binfiles[main_group] = {}
builds = dict([('chipFamily', chip_family)])
if flash_size_mb > 0:
builds['flashSizeMB'] = flash_size_mb
if add_improv:
builds['improv'] = True
if chip_variant:
builds['chipVariant'] = chip_variant
builds['parts'] = [dict([('path', file), ('offset', 0)])]
if sub_group not in manifest_binfiles[main_group]:
manifest = {}
manifest['name'] = description
families = []
families.append(chipFamily)
manifest['displaytext'] = description
manifest['families'] = families
manifest['families'] = [chip_family]
manifest['version'] = version
manifest['new_install_prompt_erase'] = True
manifest['build_flags'] = build_flags
parts = dict([('path', file), ('offset', 0)])
if not chipVariant:
if add_improv:
builds = dict([('chipFamily', chipFamily), ('improv', True), ('parts', [parts])])
else:
builds = dict([('chipFamily', chipFamily), ('parts', [parts])])
else:
if add_improv:
builds = dict([('chipFamily', chipFamily), ('chipVariant', chipVariant), ('improv', False), ('parts', [parts])])
else:
builds = dict([('chipFamily', chipFamily), ('chipVariant', chipVariant), ('parts', [parts])])
manifest['builds'] = [builds]
manifest_binfiles[main_group][sub_group] = manifest
else:
parts = dict([('path', file), ('offset', 0)])
if not chipVariant:
if add_improv:
builds = dict([('chipFamily', chipFamily), ('improv', True), ('parts', [parts])])
else:
builds = dict([('chipFamily', chipFamily), ('parts', [parts])])
else:
if add_improv:
builds = dict([('chipFamily', chipFamily), ('chipVariant', chipVariant), ('improv', True), ('parts', [parts])])
else:
builds = dict([('chipFamily', chipFamily), ('chipVariant', chipVariant), ('parts', [parts])])
manifest_binfiles[main_group][sub_group]['builds'].append(builds)
manifest_binfiles[main_group][sub_group]['families'].append(chipFamily)
manifest_binfiles[main_group][sub_group]['families'].append(chip_family)
display_string = create_display_text(description, version, manifest_binfiles[main_group][sub_group]['families'])
manifest_binfiles[main_group][sub_group]['displaytext'] = display_string
if 'ESP8266' in main_group:
manifest_binfiles[main_group][sub_group]['manifestfilename'] = '{}_ESP8266{}'.format(sub_group, manifest_suff)
manifest_binfiles[main_group][sub_group]['manifestfilename'] = '{}_ESP8266{}'.format(sub_group, manifest_suffix)
else:
manifest_binfiles[main_group][sub_group]['manifestfilename'] = '{}{}'.format(sub_group, manifest_suff)
manifest_binfiles[main_group][sub_group]['manifestfilename'] = '{}{}'.format(sub_group, manifest_suffix)
@@ -312,11 +303,10 @@ def generate_manifest_files(bin_folder, output_prefix):
# the main grouping in the combo box on the web flasher page
main_group_list = [
'8M/16M/32M Flash MAX Builds',
'4M Flash',
'4M Flash ESP32-solo1',
'4M Flash Collection Builds',
'8M Flash',
'16M Flash',
'2M Flash',
'1M Flash',
'Device Specific',
@@ -324,7 +314,6 @@ def generate_manifest_files(bin_folder, output_prefix):
'Custom Misc',
'Misc']
for main_group in main_group_list:
if main_group in manifest_binfiles:
html_options_group = []
@@ -389,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.0.0/dist/web/install-button.js?module"\n',
' src="https://unpkg.com/tasmota-esp-web-tools@12.2.2/dist/web/install-button.js?module"\n',
' ></script>\n',
' </head>\n',
' <body>\n',
@@ -409,7 +398,7 @@ def generate_manifest_files(bin_folder, output_prefix):
lines_tail = [
' </select>\n',
' </div>\n',
' <esp-web-install-button></esp-web-install-button>\n',
' <esp-web-install-button baud-rate="460800"></esp-web-install-button>\n',
' <br>\n',
' <br>\n',