diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5480c70ff9..911a28e5e3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -167,7 +167,6 @@ jobs: find . -name '*ESP32solo1*' -print | zip -@ ../../ESPEasy_ESP32solo1.zip find . -name '*ESP32_*' -print | zip -@ ../../ESPEasy_ESP32.zip cd ../.. - mv artifacts/Distribution/ESPEasy_dist* . cp ESPEasy_dist.zip ESPEasy_mega_${{ steps.date.outputs.builddate }}_ESP82xx_binaries.zip zip -d ESPEasy_mega_${{ steps.date.outputs.builddate }}_ESP82xx_binaries.zip "bin/blank_8MB.bin" mv ESPEasy_dist.zip ESPEasy_mega_${{ steps.date.outputs.builddate }}_ESP32_binaries.zip diff --git a/README.md b/README.md index 5479149996..54602e24c5 100644 --- a/README.md +++ b/README.md @@ -140,7 +140,7 @@ ESPEasy_mega-20230822_max_ESP32s3_8M1M_LittleFS_OPI_PSRAM_CDC.bin | ESP32-S3 8MB ESPEasy_mega-20230822_max_ESP32_16M1M.bin | ESP32 with 16MB flash | All available plugins | ESPEasy_mega-20230822_max_ESP32_16M8M_LittleFS.bin | ESP32 with 16MB flash | All available plugins | -NB: Since 2023-05-10 the binary files for the different ESP32 variants (S2, C3, S3, 'Classic') are available in separate archives. +The binary files for the different ESP32 variants (S2, C3, S3, C2, C6, '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) diff --git a/boards/esp32c6cdc-16M.json b/boards/esp32c6cdc-16M.json new file mode 100644 index 0000000000..efa16120c3 --- /dev/null +++ b/boards/esp32c6cdc-16M.json @@ -0,0 +1,40 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32c6_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_TASMOTA -DARDUINO_USB_MODE=1 -DUSE_USB_CDC_CONSOLE -DESP32_16M -DESP32C6 -DARDUINO_USB_CDC_ON_BOOT=1", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32c6", + "variant": "esp32c6", + "partitions": "boards/partitions/esp32_partition_app4096k_spiffs8124k.csv" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": [ + "esp-builtin" + ], + "openocd_target": "esp32c6.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif Generic ESP32-C6 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/esp32c6/esp32-c6-devkitc-1/index.html", + "vendor": "Espressif" + } diff --git a/boards/esp32c6cdc-8M.json b/boards/esp32c6cdc-8M.json new file mode 100644 index 0000000000..9bfc4e34c0 --- /dev/null +++ b/boards/esp32c6cdc-8M.json @@ -0,0 +1,40 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32c6_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_TASMOTA -DARDUINO_USB_MODE=1 -DUSE_USB_CDC_CONSOLE -DESP32_8M -DESP32C6 -DARDUINO_USB_CDC_ON_BOOT=1", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32c6", + "variant": "esp32c6", + "partitions": "boards/partitions/esp32_partition_app3520k_spiffs1088k.csv" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": [ + "esp-builtin" + ], + "openocd_target": "esp32c6.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif Generic ESP32-C6 >= 8M Flash, ESPEasy 3520k Code/OTA 1088k FS", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32c6/esp32-c6-devkitc-1/index.html", + "vendor": "Espressif" + } diff --git a/docs/source/ESPEasy/ESPchips.rst b/docs/source/ESPEasy/ESPchips.rst index 4b0754c137..f821ea9b2a 100644 --- a/docs/source/ESPEasy/ESPchips.rst +++ b/docs/source/ESPEasy/ESPchips.rst @@ -10,8 +10,8 @@ ESPEasy does support a number of variants of the processors manufactured by Espr * **ESP32-S2** Has more GPIO pins than the ESP32, but only 1 CPU core. Initial support in ESPEasy added since 2021-09-19. * **ESP32-S3** Support added: 2023-05-03 * **ESP32-C3 / ESP8685** Support added: 2023-05-03 -* **ESP32-C2 / ESP8684** Not yet supported -* **ESP32-C6** Not yet supported +* **ESP32-C2 / ESP8684** Support added: 2023-11-10 +* **ESP32-C6** Support added: 2023-11-10 * **ESP32-H2** Not yet supported @@ -83,7 +83,7 @@ ESPEasy does support a number of variants of the processors manufactured by Espr - 2022 - 2021 - 2021 - * - Status (2023/05) + * - Status (2024/03) - NRND - Mass Production (solo1: NRND) - NRND @@ -91,7 +91,7 @@ ESPEasy does support a number of variants of the processors manufactured by Espr - Mass Production - Mass Production - Mass Production - - Sample + - Mass Production * - Wi-Fi - IEEE 802.11 b/g/n; 2.4 GHz; HT20; up to 72 Mbps - IEEE 802.11 b/g/n; 2.4 GHz; HT20/40; up to 150 Mbps @@ -328,12 +328,12 @@ ESPEasy does support a number of variants of the processors manufactured by Espr - 0 * - Ethernet - 0 - - 1 (RMII) - - 0 - - 0 - - 0 - - 0 - - 0 + - 1 (RMII and SPI) + - 1 (SPI) + - 1 (SPI) + - 1 (SPI) + - 1 (SPI) + - 1 (SPI) - 0 * - TWAI (CAN) - 0 @@ -683,7 +683,7 @@ ESP32-C2/ESP8684 Added: 2023/11/10 -The ESP32-C2 is only available with embedded flash and can only be found labelled as "ESP8684". +The ESP32-C2 is only available with embedded flash and can also be found labeled as "ESP8684". It looks like it is aimed to be used in single purpose devices, due to its low GPIO count and only requiring a bare minimum of external parts. @@ -700,9 +700,9 @@ Added: 2023/11/10 The ESP32-C6 seems to be aimed at being used as a gateway for the new Thread protocol and Wi-Fi. -It is the more powerful version of the ESP32-H2 and also includes not only the traditional 2.4 GHz Wi-Fi, but also the new Wi-Fi6 standard on 2.4 GHz. +It is the more powerful version of the ESP32-H2 and also includes not only the traditional 2.4 GHz Wi-Fi, but also the new Wi-Fi6 standard on 2.4 GHz and IEEE 802.15.4 (Zigbee/Thread). Zigbee/Thread not yet supported by ESPEasy (March 2024). -.. note:: Labelled as "unstable" by the Arduino team (as of Nov 2023), preliminary support in ESPEasy +.. note:: Labeled as "unstable" by the Arduino team (as of Nov 2023), preliminary support in ESPEasy ESP32-H2 ======== diff --git a/docs/source/Participate/ProjectStructure.rst b/docs/source/Participate/ProjectStructure.rst index b25676a9cb..8e7b61199c 100644 --- a/docs/source/Participate/ProjectStructure.rst +++ b/docs/source/Participate/ProjectStructure.rst @@ -29,7 +29,7 @@ Below a list of the most important directories and files used in this project. * ``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. * ``requirements.txt`` List of used Python libraries and their version (result of ``pip freeze`` with Virtual env active) -* ``esp32_partition_app1810k_spiffs316k.csv`` Used partition layout in ESP32 builds. +* ``boards/partitions/esp32_partition_app1810k_spiffs316k.csv`` Used partition layout in ESP32 4M builds. ESPEasy src dir @@ -90,11 +90,11 @@ The filename is quite descriptive: Build Type ---------- -Build type can be: (differ in included plugins) +Build type can be: (differences in included plugins) -* normal => Only Stable plugins and controllers -* test => Stable + Testing (split into multiple sets, A/B/C/D) -* max => All available plugins +* normal => Only Stable plugins and controllers +* collection => Stable + Collection (split into multiple sets, A/B/C/D/E/F/G) +* max => All available plugins and features There is also a number of special builds: @@ -111,8 +111,10 @@ ESP Chip Type * ``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`` Not yet available. -* ``ESP32-C3`` Support will be added soon. +* ``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-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. Memory Size and Partitioning ---------------------------- @@ -124,23 +126,27 @@ Memory Size and Partitioning * ``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.) -* ``16M2M`` 16 MB flash modules using 4MB sketch size, with 2 MB filesystem (LittleFS) (ESP32 only a.t.m.) * ``16M8M`` 16 MB flash modules using 4MB sketch size, with 8 MB filesystem (LittleFS) (ESP32 only a.t.m.) Optional build options ---------------------- -* ``LittleFS`` Use LittleFS instead of SPIFFS filesystem (SPIFFS is unstable > 2 MB) +* ``LittleFS`` Use LittleFS instead of SPIFFS filesystem (SPIFFS is unstable \> 2 MB and no longer available from IDF 5.x) * ``VCC`` Analog input configured to measure VCC voltage * ``OTA`` Arduino OTA (Over The Air) update feature enabled * ``Domoticz`` Only Domoticz controllers (HTTP+MQTT) and plugins included * ``FHEM_HA`` Only FHEM/OpenHAB/Home Assistant (MQTT) controllers and plugins included * ``lolin_d32_pro`` Specific Lolin hardware options enabled +* ``PSRAM`` Additional PSRAM support (ESP32 only) +* ``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) -Please note that the performance of 14MB SPIFFS (16M flash modules) is really slow. +Please note that the performance of 14MB SPIFFS (16M flash ESP8266 modules) is really slow. All file access takes a lot longer and since the settings are also read from flash, the entire node will perform slower. See `Arduino issue - SPIFFS file access slow on 16/14M flash config `_ @@ -150,7 +156,7 @@ Special memory partitioning: * ``2M256`` 2 MB flash modules (e.g. Shelly1/WROOM02) with 256k SPIFFS (only core 2.5.0 or newer) * ``4M316k`` For ESP32 with 4MB flash, sketch size is set to 1.8 MByte (default: 1.4 MByte) -* ``4M1M`` 4MB flash, 1 MB SPIFFS. Default layout for 4MB flash. +* ``4M1M`` 4MB flash, 1 MB SPIFFS. Default layout for ESP8266 4MB flash. * ``4M2M`` 4MB flash, 2 MB SPIFFS. Introduced in October 2019. Only possible with core 2.5.2 or newer. .. warning:: @@ -165,7 +171,7 @@ Difference between .bin and .bin.gz Starting on esp8266/Arduino core 2.7.0, it is possible to flash images that have been compressed using GZip. -Please note that this only can be used on installs already running a very recent build. +Please note that this only can be used on installs already running a recent build. This also means we still need to update the 2-step updater to support .bin.gz files. @@ -182,17 +188,17 @@ There are several builds for ESP32: * ``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 * ``custom_ESP32_4M316k`` Build template using either the plugin set defined in ``Custom.h`` or ``tools/pio/pre_custom_esp32.py`` -* ``test_A_ESP32_4M316k`` Build using the "testing" set "A" of plugins for ESP32 -* ``test_B_ESP32_4M316k`` Build using the "testing" set "B" of plugins for ESP32 -* ``test_C_ESP32_4M316k`` Build using the "testing" set "C" of plugins for ESP32 -* ``test_D_ESP32_4M316k`` Build using the "testing" set "D" of plugins for ESP32 -* ``test_A_ESP32-wrover-kit_4M316k`` A build for ESP32 including build flags for the official WRover test kit. +* ``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) Since ESP32 does have its flash partitioned in several blocks, we have 2 bin files of each ESP32 build, f.e.: -* ``test_D_ESP32_4M316k.bin`` Use for OTA upgrades. -* ``test_D_ESP32_4M316k.factory.bin`` Use on clean nodes as initial inistall. +* ``collection_D_ESP32_4M316k.bin`` Use for OTA upgrades. +* ``collection_D_ESP32_4M316k.factory.bin`` Use on clean nodes as initial inistall. The binary with ``.factory`` in the name must be flashed on a new node, via the serial interface of the board. This flash must be started at address 0. @@ -208,7 +214,8 @@ To help recover from a bad flash, there are also blank images included. * ``blank_1MB.bin`` * ``blank_2MB.bin`` * ``blank_4MB.bin`` +* ``blank_8MB.bin`` * ``blank_16MB.bin`` When the wrong image is flashed, or the module behaves unstable, or is in a reboot loop, -flash these images first and then the right image for the module. +flash these images first to clear out any remaining or hidden settings (Arduino framework...) and then the right image for the module. diff --git a/docs/source/Plugin/P087.rst b/docs/source/Plugin/P087.rst index 721a197527..4582df69d8 100644 --- a/docs/source/Plugin/P087.rst +++ b/docs/source/Plugin/P087.rst @@ -48,7 +48,7 @@ This section only shows settings when the plugin is configured and enabled. .. image:: P087_FilteringConfiguration.png -* **RegEx**: Specify a regular expression to apply to the received data before it is accepted as acceptable data. +* **RegEx**: Specify a regular expression to apply to the received data before it is accepted as acceptable data. This regular expression is based on the Lua script language, and is documented here: http://www.lua.org/manual/5.2/manual.html#6.4.1 * **Nr Chars use in RegEx**: Limit the length of the data to be checked using the **RegEx** regular expression filter. When set to 0 all data is checked. @@ -109,6 +109,13 @@ Commands available .. include:: P087_commands.repl +Get Config Values +^^^^^^^^^^^^^^^^^ + +Get Config Values retrieves values or settings from the sensor or plugin, and can be used in Rules, Display plugins, Formula's etc. The square brackets **are** part of the variable. Replace ```` by the **Name** of the task. + +.. include:: P087_config_values.repl + Change log ---------- @@ -116,6 +123,8 @@ Change log .. versionchanged:: 2.0 ... + |added| 2024-02-25 Add support for ``serialproxy_test`` command and retrieving the separate groups from parsed regex. + |added| 2023-03-22 Add support for writing any binary data out via the serial port. |added| 2020-02-22 diff --git a/docs/source/Plugin/P087_commands.repl b/docs/source/Plugin/P087_commands.repl index 60effc0a9c..ca2b9f1c8d 100644 --- a/docs/source/Plugin/P087_commands.repl +++ b/docs/source/Plugin/P087_commands.repl @@ -26,3 +26,12 @@ ``'0xXXxx XX,xx-XX:xx'``: A sequence of hexadecimal values (range: 0x00..0xFF), that *can* be separated by a space, comma, dash, colon, semicolon or period, or are just entered adjecent. Only the first 2 characters should be ``0x`` or ``0X``, the rest is interpreted as hex bytes, and appended to the data to send. Quotes are only required if space or comma separators are used. Using this command, either from rules, via http or mqtt, the text that is provided as content is completely sent to the serial port. No extra data is added, other than any (system) variables that are included, being replaced. " + " + ``serialproxy_test,'[,...]'`` + + ````: Some text to be processed as if it was received via the serial port. + "," + This command is intended for testing the regular expression and filtering. + + The sentence provided with this command is handed over for processing as if it was received via the serial port, so it will be processed and filtered, and an event will be generated if it's matched. + " diff --git a/docs/source/Plugin/P087_config_values.repl b/docs/source/Plugin/P087_config_values.repl new file mode 100644 index 0000000000..b386e5d20a --- /dev/null +++ b/docs/source/Plugin/P087_config_values.repl @@ -0,0 +1,70 @@ +.. csv-table:: + :header: "Config value", "Information" + :widths: 20, 30 + + " + ``[#group,]`` + "," + Get the contents from groupnr after processing received data. + + NB: The regular expression parsen uses 0-based group numbers (where most other regex parsers use 1-based group numbers!) + " + " + ``[#next,]`` + "," + Get the value of the next group that holds ````. + + Example: + + Regular expression: ``((node)=(%d+);?)((weight)=(%d+);?)((temp%d?)=(%-?%d+);?)((rssi)=(%-?%d+);?)`` + + Received data: ``node=1;weight=40;temp1=20;rssi=-30`` + + This will result in these groups: + + .. list-table:: + :widths: 20, 50, 200 + :header-rows: 1 + + * - Group + - Data + - + * - 0 + - node=1 + - + * - 1 + - node + - + * - 2 + - 1 + - + * - 3 + - weight=40 + - + * - 4 + - weight + - + * - 5 + - 40 + - + * - 6 + - temp1=20 + - + * - 7 + - temp1 + - + * - 8 + - 20 + - + * - 9 + - rssi=-30 + - + * - 10 + - rssi + - + * - 11 + - -30 + - + + Requesting ``[SerialProxy#next,weight]`` will return the value ``40``. + " diff --git a/platformio_esp32_envs.ini b/platformio_esp32_envs.ini index cb558c0f08..6c24456eab 100644 --- a/platformio_esp32_envs.ini +++ b/platformio_esp32_envs.ini @@ -333,9 +333,9 @@ build_flags = ${esp32_custom_base_LittleFS.build_flags} [env:custom_IR_ESP32_4M316k_ETH] extends = env:custom_IR_ESP32_4M316k -build_flags = ${env:custom_ESP32_4M316k.build_flags} +build_flags = ${env:custom_IR_ESP32_4M316k.build_flags} -DFEATURE_ETHERNET=1 -extra_scripts = ${env:custom_ESP32_4M316k.extra_scripts} +extra_scripts = ${env:custom_IR_ESP32_4M316k.extra_scripts} [env:custom_IR_ESP32_16M8M_LittleFS_ETH] extends = esp32_common_LittleFS @@ -349,7 +349,7 @@ lib_ignore = ${esp32_always.lib_ignore} ESP32_ping ${esp32_common_LittleFS.lib_ignore} extra_scripts = ${esp32_common.extra_scripts} - pre:tools/pio/pre_custom_esp32.py + pre:tools/pio/pre_custom_esp32_IR.py pre:tools/pio/ir_build_check.py [env:normal_ESP32_4M316k_ETH] diff --git a/platformio_esp32c3_envs.ini b/platformio_esp32c3_envs.ini index 36983a99c1..abffc558e6 100644 --- a/platformio_esp32c3_envs.ini +++ b/platformio_esp32c3_envs.ini @@ -44,7 +44,7 @@ build_flags = ${esp32c3_common.build_flags} lib_ignore = ${esp32_always.lib_ignore} ESP32_ping extra_scripts = ${esp32c3_common.extra_scripts} - pre:tools/pio/pre_custom_esp32.py + pre:tools/pio/pre_custom_esp32_IR.py pre:tools/pio/ir_build_check.py [env:custom_ESP32c3_4M316k_LittleFS_CDC] diff --git a/platformio_esp32c6_envs.ini b/platformio_esp32c6_envs.ini index 4d07f4a115..2889771b92 100644 --- a/platformio_esp32c6_envs.ini +++ b/platformio_esp32c6_envs.ini @@ -11,9 +11,6 @@ build_unflags = ${esp32_base_idf5.build_unflags} -fexceptions board_build.filesystem = littlefs lib_ignore = ${esp32_base_idf5.lib_ignore} - NeoPixelBus - NeoPixelBus_wrapper - Adafruit NeoMatrix via NeoPixelBus board = esp32c6cdc @@ -29,3 +26,27 @@ extra_scripts = ${esp32c6_common_LittleFS.extra_scripts} extends = esp32c6_common_LittleFS lib_ignore = ${esp32c6_common_LittleFS.lib_ignore} ${no_ir.lib_ignore} + + +[env:max_ESP32c6_8M1M_LittleFS_CDC_ETH] +extends = esp32c6_common_LittleFS +board = esp32c6cdc-8M +build_flags = ${esp32c6_common_LittleFS.build_flags} + -DFEATURE_ETHERNET=1 + -DFEATURE_ARDUINO_OTA=1 + -DPLUGIN_BUILD_MAX_ESP32 + -DPLUGIN_BUILD_IR_EXTENDED +extra_scripts = ${esp32c6_common_LittleFS.extra_scripts} + + +[env:max_ESP32c6_16M8M_LittleFS_CDC_ETH] +extends = esp32c6_common_LittleFS +board = esp32c6cdc-16M +build_flags = ${esp32c6_common_LittleFS.build_flags} + -DFEATURE_ETHERNET=1 + -DFEATURE_ARDUINO_OTA=1 + -DPLUGIN_BUILD_MAX_ESP32 + -DPLUGIN_BUILD_IR_EXTENDED +extra_scripts = ${esp32c6_common_LittleFS.extra_scripts} + + diff --git a/platformio_esp32s2_envs.ini b/platformio_esp32s2_envs.ini index 20fdaf4689..d97fd66415 100644 --- a/platformio_esp32s2_envs.ini +++ b/platformio_esp32s2_envs.ini @@ -62,7 +62,7 @@ build_flags = ${esp32s2_common.build_flags} lib_ignore = ${esp32_always.lib_ignore} ESP32_ping extra_scripts = ${esp32s2_common.extra_scripts} - pre:tools/pio/pre_custom_esp32.py + pre:tools/pio/pre_custom_esp32_IR.py pre:tools/pio/ir_build_check.py diff --git a/platformio_esp32s3_envs.ini b/platformio_esp32s3_envs.ini index a771e96ce1..284b717885 100644 --- a/platformio_esp32s3_envs.ini +++ b/platformio_esp32s3_envs.ini @@ -49,7 +49,7 @@ build_flags = ${esp32s3_common.build_flags} lib_ignore = ${esp32_always.lib_ignore} ESP32_ping extra_scripts = ${esp32s3_common.extra_scripts} - pre:tools/pio/pre_custom_esp32.py + pre:tools/pio/pre_custom_esp32_IR.py pre:tools/pio/ir_build_check.py diff --git a/src/Custom-sample.h b/src/Custom-sample.h index fb806bb7d9..50a2a44b4a 100644 --- a/src/Custom-sample.h +++ b/src/Custom-sample.h @@ -272,7 +272,6 @@ -#define FEATURE_SSDP 1 /* ####################################################################################################### diff --git a/src/_P087_SerialProxy.ino b/src/_P087_SerialProxy.ino index 0fb2a02987..d816b7b854 100644 --- a/src/_P087_SerialProxy.ino +++ b/src/_P087_SerialProxy.ino @@ -11,6 +11,12 @@ /** * Changelog: + * 2024-02-27 tonhuisman: Always process the regular expression like 'Global Match' to enable retrieving the available values + * 2024-02-26 tonhuisman: Apply log-string and other code optimizations + * 2024-02-25 tonhuisman: Add command serialproxy_test, to test as if serial data was received + * Add Get Config Value support for retrieving the last regex-parsed data: + * - By group: [#group,] (groupnr is 0-base!) + * - By name: [#next,] if the is found, the next group-data is returned * 2023-03-25 tonhuisman: Change serialproxy_writemix to handle 0x00 also, by implementing parseHexTextData() * 2023-03-22 tonhuisman: Add command serialproxy_writemix to handle mixed hex characters and text to send * using parseHexTextString() @@ -144,7 +150,7 @@ boolean Plugin_087(uint8_t function, struct EventStruct *event, String& string) { addFormNumericBox(F("Baudrate"), P087_BAUDRATE_LABEL, P087_BAUDRATE, 300, 115200); addUnit(F("baud")); - uint8_t serialConfChoice = serialHelper_convertOldSerialConfig(P087_SERIAL_CONFIG); + const uint8_t serialConfChoice = serialHelper_convertOldSerialConfig(P087_SERIAL_CONFIG); serialHelper_serialconfig_webformLoad(event, serialConfChoice); break; } @@ -168,7 +174,7 @@ boolean Plugin_087(uint8_t function, struct EventStruct *event, String& string) static_cast(getPluginTaskData(event->TaskIndex)); if (nullptr != P087_data) { - for (uint8_t varNr = 0; varNr < P87_Nlines; varNr++) + for (uint8_t varNr = 0; varNr < P87_Nlines; ++varNr) { P087_data->setLine(varNr, webArg(getPluginCustomArgName(varNr))); } @@ -225,14 +231,13 @@ boolean Plugin_087(uint8_t function, struct EventStruct *event, String& string) if ((nullptr != P087_data) && P087_data->getSentence(event->String2)) { if (Plugin_087_match_all(event->TaskIndex, event->String2)) { // sendData(event); -# ifndef BUILD_NO_DEBUG + # ifndef BUILD_NO_DEBUG addLog(LOG_LEVEL_DEBUG, event->String2); -# endif // ifndef BUILD_NO_DEBUG + # endif // ifndef BUILD_NO_DEBUG success = true; } } - if ((nullptr != P087_data)) {} break; } @@ -240,26 +245,49 @@ boolean Plugin_087(uint8_t function, struct EventStruct *event, String& string) P087_data_struct *P087_data = static_cast(getPluginTaskData(event->TaskIndex)); - if ((nullptr != P087_data)) { - String cmd = parseString(string, 1); + if (nullptr != P087_data) { + const String cmd = parseString(string, 1); if (equals(cmd, F("serialproxy_write"))) { - String param1 = parseStringKeepCase(string, 2, ',', false); // Don't trim off white-space - parseSystemVariables(param1, false); // FIXME tonhuisman: Doesn't seem to be needed? + String param1 = parseStringKeepCaseNoTrim(string, 2); // Don't trim off white-space + parseSystemVariables(param1, false); // FIXME tonhuisman: Doesn't seem to be needed? P087_data->sendString(param1); - addLogMove(LOG_LEVEL_INFO, param1); // FIXME tonhuisman: Should we always want to write to the log? + addLogMove(LOG_LEVEL_INFO, param1); // FIXME tonhuisman: Should we always want to write to the log? success = true; } else if (equals(cmd, F("serialproxy_writemix"))) { std::vector param1 = parseHexTextData(string); - if (param1.size()) + + if (param1.size()) { P087_data->sendData(¶m1[0], param1.size()); + } + success = true; + } else + if (equals(cmd, F("serialproxy_test"))) { // Test-parse data as if received via serial + const String param1 = parseStringKeepCaseNoTrim(string, 2); + + if (!param1.isEmpty()) { + P087_data->setLastSentence(param1); + Scheduler.schedule_task_device_timer(event->TaskIndex, millis() + 10); + delay(0); // Processing a full sentence may take a while, run some background tasks. + } success = true; } } break; } + + case PLUGIN_GET_CONFIG_VALUE: + { + P087_data_struct *P087_data = + static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P087_data) { + success = P087_data->plugin_get_config_value(event, string); + } + break; + } } return success; } @@ -279,7 +307,7 @@ bool Plugin_087_match_all(taskIndex_t taskIndex, String& received) return true; } - bool res = P087_data->matchRegexp(received); + const bool res = P087_data->matchRegexp(received); if (P087_data->invertMatch()) { addLog(LOG_LEVEL_INFO, F("Serial Proxy: invert filter")); @@ -292,7 +320,7 @@ String Plugin_087_valuename(uint8_t value_nr, bool displayString) { switch (value_nr) { case P087_QUERY_VALUE: return displayString ? F("Value") : F("v"); } - return ""; + return EMPTY_STRING; } void P087_html_show_matchForms(struct EventStruct *event) { @@ -342,7 +370,7 @@ void P087_html_show_matchForms(struct EventStruct *event) { for (uint8_t varNr = P087_FIRST_FILTER_POS; varNr < P87_Nlines; ++varNr) { - String id = getPluginCustomArgName(varNr); + const String id = getPluginCustomArgName(varNr); switch (varNr % 3) { case 0: @@ -350,10 +378,7 @@ void P087_html_show_matchForms(struct EventStruct *event) { // Label + first parameter filter = P087_data->getFilter(lineNr, capture, comparator); ++lineNr; - String label; - label = F("Capture Filter "); - label += String(lineNr); - addRowLabel_tr_id(label, id); + addRowLabel_tr_id(concat(F("Capture Filter "), lineNr), id); addNumericBox(id, capture, -1, P87_MAX_CAPTURE_INDEX); break; @@ -364,7 +389,7 @@ void P087_html_show_matchForms(struct EventStruct *event) { const __FlashStringHelper *options[2]; options[P087_Filter_Comp::Equal] = F("=="); options[P087_Filter_Comp::NotEqual] = F("!="); - int optionValues[2] = { P087_Filter_Comp::Equal, P087_Filter_Comp::NotEqual }; + const int optionValues[2] = { P087_Filter_Comp::Equal, P087_Filter_Comp::NotEqual }; addSelector(id, 2, options, optionValues, nullptr, static_cast(comparator), false, true, F("")); break; } @@ -395,13 +420,9 @@ void P087_html_show_stats(struct EventStruct *event) { { addRowLabel(F("Sentences (pass/fail)")); - String chksumStats; uint32_t success, error, length_last; P087_data->getSentencesReceived(success, error, length_last); - chksumStats = success; - chksumStats += '/'; - chksumStats += error; - addHtml(chksumStats); + addHtml(strformat(F("%d/%d"), success, error)); addRowLabel(F("Length Last Sentence")); addHtmlInt(length_last); } diff --git a/src/src/CustomBuild/define_plugin_sets.h b/src/src/CustomBuild/define_plugin_sets.h index 5091c64f4a..1a3a6dbc55 100644 --- a/src/src/CustomBuild/define_plugin_sets.h +++ b/src/src/CustomBuild/define_plugin_sets.h @@ -3251,8 +3251,8 @@ To create/register a plugin, you have to : # endif #endif -// Incompatible plugins with ESP32-C2/C6 -#if defined(ESP32C2) || defined(ESP32C6) +// Incompatible plugins with ESP32-C2 // (C6 seems to work as intended) +#if defined(ESP32C2) // || defined(ESP32C6) #define DISABLE_NEOPIXEL_PLUGINS 1 #endif diff --git a/src/src/PluginStructs/P087_data_struct.cpp b/src/src/PluginStructs/P087_data_struct.cpp index fad12222c2..76228036ce 100644 --- a/src/src/PluginStructs/P087_data_struct.cpp +++ b/src/src/PluginStructs/P087_data_struct.cpp @@ -13,17 +13,13 @@ P087_data_struct::~P087_data_struct() { - if (easySerial != nullptr) { - delete easySerial; - easySerial = nullptr; - } + delete easySerial; + easySerial = nullptr; } void P087_data_struct::reset() { - if (easySerial != nullptr) { - delete easySerial; - easySerial = nullptr; - } + delete easySerial; + easySerial = nullptr; } bool P087_data_struct::init(ESPEasySerialPort port, const int16_t serial_rx, const int16_t serial_tx, unsigned long baudrate, @@ -62,10 +58,7 @@ void P087_data_struct::post_init() { // Index is negative when not used. if ((index >= 0) && (index < P87_MAX_CAPTURE_INDEX) && (_lines[i * 3 + P087_FIRST_FILTER_POS + 2].length() > 0)) { # ifndef BUILD_NO_DEBUG - log += ' '; - log += String(i); - log += ':'; - log += String(index); + log += strformat(F(" %d:%d"), i, index); # endif // ifndef BUILD_NO_DEBUG capture_index[i] = index; capture_index_used[index] = true; @@ -86,9 +79,7 @@ void P087_data_struct::sendString(const String& data) { easySerial->write(data.c_str()); if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log = F("Proxy: Sending: "); - log += data; - addLogMove(LOG_LEVEL_INFO, log); + addLogMove(LOG_LEVEL_INFO, concat(F("Proxy: Sending: "), data)); } } } @@ -99,10 +90,7 @@ void P087_data_struct::sendData(uint8_t *data, size_t size) { easySerial->write(data, size); if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log = F("Proxy: Sending "); - log += size; - log += F(" bytes."); - addLogMove(LOG_LEVEL_INFO, log); + addLogMove(LOG_LEVEL_INFO, strformat(F("Proxy: Sending %d bytes."), size)); } } } @@ -134,7 +122,7 @@ bool P087_data_struct::loop() { for (size_t i = 0; i < length && valid; ++i) { if ((sentence_part[i] > 127) || (sentence_part[i] < 32)) { - sentence_part = String(); + sentence_part = EMPTY_STRING; ++sentences_received_error; valid = false; } @@ -143,7 +131,7 @@ bool P087_data_struct::loop() { if (valid) { fullSentenceReceived = true; last_sentence = sentence_part; - sentence_part = String(); + sentence_part = EMPTY_STRING; } break; } @@ -173,7 +161,7 @@ bool P087_data_struct::getSentence(String& string) { if (string.isEmpty()) { return false; } - last_sentence = String(); + last_sentence = EMPTY_STRING; return true; } @@ -241,10 +229,10 @@ String P087_data_struct::getFilter(uint8_t lineNr, uint8_t& capture, P087_Filter { uint8_t varNr = lineNr * 3 + P087_FIRST_FILTER_POS; - if ((varNr + 3) > P87_Nlines) { return ""; } + if ((varNr + 3) > P87_Nlines) { return EMPTY_STRING; } capture = _lines[varNr++].toInt(); - comparator = _lines[varNr++] == "1" ? P087_Filter_Comp::NotEqual : P087_Filter_Comp::Equal; + comparator = equals(_lines[varNr++], '1') ? P087_Filter_Comp::NotEqual : P087_Filter_Comp::Equal; return _lines[varNr]; } @@ -295,7 +283,7 @@ bool P087_data_struct::matchRegexp(String& received) const { } - uint32_t regexp_match_length = getRegExpMatchLength(); + const uint32_t regexp_match_length = getRegExpMatchLength(); if ((regexp_match_length > 0) && (strlength > regexp_match_length)) { strlength = regexp_match_length; @@ -307,9 +295,10 @@ bool P087_data_struct::matchRegexp(String& received) const { bool match_result = false; + capture_vector.clear(); + ms.GlobalMatch(getRegEx().c_str(), match_callback); // To allow the matched values be retrieved also when not using Global Match option + if (globalMatch()) { - capture_vector.clear(); - ms.GlobalMatch(_lines[P087_REGEX_POS].c_str(), match_callback); const uint8_t vectorlength = capture_vector.size(); for (uint8_t i = 0; i < vectorlength; ++i) { @@ -320,13 +309,10 @@ bool P087_data_struct::matchRegexp(String& received) const { if ((capture_index[n] == capture_vector[i].first) && !(_lines[lines_index].isEmpty())) { String log; log.reserve(32); - log = F("P087: Index: "); - log += capture_vector[i].first; - log += F(" Found "); - log += capture_vector[i].second; + log = strformat(F("P087: Index: %d Found %s"), capture_vector[i].first, capture_vector[i].second.c_str()); // Found a Capture Filter with this capture index. - if (capture_vector[i].second == _lines[lines_index]) { + if (capture_vector[i].second.equals(_lines[lines_index])) { log += F(" Matches"); // Found a match. Now check if it is supposed to be one or not. @@ -342,10 +328,11 @@ bool P087_data_struct::matchRegexp(String& received) const { log += F(" No Match"); if (capture_index_must_not_match[n]) { - log += F(" (!=) "); + log += F(" (!=)"); } else { - log += F(" (==) "); + log += F(" (==)"); } + log += ' '; log += _lines[lines_index]; } addLogMove(LOG_LEVEL_INFO, log); @@ -353,19 +340,16 @@ bool P087_data_struct::matchRegexp(String& received) const { } } } - capture_vector.clear(); + + // capture_vector.clear(); // KEEP so we can use plugin_get_config_value to retrieve the values } else { - char result = ms.Match(_lines[P087_REGEX_POS].c_str()); + char result = ms.Match(getRegEx().c_str()); if (result == REGEXP_MATCHED) { # ifndef BUILD_NO_DEBUG if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { - String log = F("Match at: "); - log += ms.MatchStart; - log += F(" Match Length: "); - log += ms.MatchLength; - addLogMove(LOG_LEVEL_DEBUG, log); + addLogMove(LOG_LEVEL_DEBUG, strformat(F("Match at: %d Match Length: %d"), ms.MatchStart, ms.MatchLength)); } # endif // ifndef BUILD_NO_DEBUG match_result = true; @@ -391,4 +375,62 @@ bool P087_data_struct::max_length_reached() const { return sentence_part.length() >= max_length; } +void P087_data_struct::setLastSentence(String string) { + last_sentence = string; +} + +bool P087_data_struct::plugin_get_config_value(struct EventStruct *event, + String & string) { + bool success = false; + const uint8_t vectorlength = capture_vector.size(); + const String cmd = parseString(string, 1); + + # ifndef BUILD_NO_DEBUG + addLog(LOG_LEVEL_DEBUG, concat(F("P087: Before GetConfig: "), string)); + # endif // ifndef BUILD_NO_DEBUG + + if (equals(cmd, F("group"))) { + int32_t par2; + + if (validIntFromString(parseString(string, 2), par2) && + (par2 >= 0)) { + for (uint8_t i = 0; i < vectorlength && !success; ++i) { // Stop when we find the requested group + # ifndef BUILD_NO_DEBUG + addLog(LOG_LEVEL_DEBUG, strformat(F("P087: get group: %d = %s"), + capture_vector[i].first, + capture_vector[i].second.c_str())); + # endif // ifndef BUILD_NO_DEBUG + + if (par2 == capture_vector[i].first) { + string = capture_vector[i].second; + success = true; + } + } + } + } else + if (equals(cmd, F("next"))) { // Get next group value after matching name + const String name_ = parseString(string, 2); + + for (uint8_t i = 0; i < (vectorlength - 1) && !success; ++i) { // Stop when we find the requested name + // Loops until 1 BEFORE the end of the vector! + # ifndef BUILD_NO_DEBUG + addLog(LOG_LEVEL_DEBUG, strformat(F("P087: get next: %d = %s => %s"), + capture_vector[i].first, + capture_vector[i].second.c_str(), + capture_vector[i + 1].second.c_str())); + # endif // ifndef BUILD_NO_DEBUG + + if (name_.equalsIgnoreCase(capture_vector[i].second)) { + string = capture_vector[i + 1].second; // Take NEXT value + success = true; + } + } + } // else... + # ifndef BUILD_NO_DEBUG + addLog(LOG_LEVEL_DEBUG, concat(F("P087: After GetConfig: "), string)); + # endif // ifndef BUILD_NO_DEBUG + + return success; +} + #endif // USES_P087 diff --git a/src/src/PluginStructs/P087_data_struct.h b/src/src/PluginStructs/P087_data_struct.h index a96eeed129..031e88a52b 100644 --- a/src/src/PluginStructs/P087_data_struct.h +++ b/src/src/PluginStructs/P087_data_struct.h @@ -67,6 +67,7 @@ struct P087_data_struct : public PluginTaskData_base { // Get the received sentence // @retval true when the string is not empty. bool getSentence(String& string); + void setLastSentence(String string); void getSentencesReceived(uint32_t& succes, uint32_t& error, @@ -110,6 +111,10 @@ struct P087_data_struct : public PluginTaskData_base { // Made public so we don't have to copy the values when loading/saving. String _lines[P87_Nlines]; + // Plugin handler functions: + bool plugin_get_config_value(struct EventStruct *event, + String & string); + private: bool max_length_reached() const; diff --git a/tools/pio/copy_files.py b/tools/pio/copy_files.py index 82fc546914..755c271ebf 100644 --- a/tools/pio/copy_files.py +++ b/tools/pio/copy_files.py @@ -21,11 +21,11 @@ def get_max_bin_size(env_name, file_suffix): if "4M316k" in env_name or "_ESP32_4M2M" in env_name: # ESP32 with 1800k of sketch space. max_bin_size = 1900544 - if "_ESP32_" in env_name or "_ESP32s2_" in env_name or "_ESP32s3_" in env_name: + if "_ESP32_" in env_name or "_ESP32c6_" in env_name or "_ESP32s2_" in env_name or "_ESP32s3_" in env_name: 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 "_ESP32s2_" in env_name or "_ESP32s3_" in env_name: + if "_ESP32_" in env_name or "_ESP32c3_" in env_name or "_ESP32c6_" 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