; PlatformIO Project Configuration File for EMS-ESP ; ; override any settings with your own local ones in pio_local.ini (see example pio_local.ini_example) ; The firmware is renamed following this convention, and placed in the build/firmware folder: ; EMS-ESP32---[+ if PSRAM onboard].bin ; For example: EMS-ESP-3_7_0-dev_31-esp32-16MB+.bin ; ; boards can be found in https://github.com/pioarduino/platform-espressif32/tree/main/boards [platformio] ; build all supported targets. Use pio_local.ini to override and build specific targets. default_envs = s_4M, s_16M, s_16M_P, s3_16M_P description = EMS-ESP Firmware for the ESP32 src_dir = src lib_dir = lib boards_dir = boards ; build_cache_dir = .pio/build_cache extra_configs = factory_settings.ini pio_local.ini [common] core_build_flags = -std=c++17 -std=gnu++17 -O3 -flto=auto -Wno-type-limits -Wall -Wextra -Wno-unused-parameter -Wno-unused-variable -Wno-format core_unbuild_flags = -std=gnu++11 -fno-lto my_build_flags = build_flags = ${common.core_build_flags} ${factory_settings.build_flags} ${common.my_build_flags} -I./src/core -D ARDUINO_ARCH_ESP32 -D ONEWIRE_CRC16=0 -D CONFIG_UART_ISR_IN_IRAM ; AsyncTCP -D CONFIG_ASYNC_TCP_MAX_ACK_TIME=5000 ; default -D CONFIG_ASYNC_TCP_PRIORITY=10 ; default -D CONFIG_ASYNC_TCP_QUEUE_SIZE=64 ; default -D CONFIG_ASYNC_TCP_RUNNING_CORE=1 ; force async_tcp task to be on same core as Arduino app (default is any core) -D CONFIG_ASYNC_TCP_STACK_SIZE=6144 ; default is 16KB/8192*2 ; ESPAsyncWebServer ; -D WS_MAX_QUEUED_MESSAGES=0 ; not used, default 8 ; -D SSE_MAX_QUEUED_MESSAGES=1 ; for log messages, default 32 -D EMSESP_SCHEDULER_RUNNING_CORE=1 -D EMSESP_SCHEDULER_STACKSIZE=8192 ; 8KB -D EMSESP_MQTT_RUNNING_CORE=1 ; default 1 ; -D EMSESP_MQTT_STACKSIZE=5120 ; default -D EMSESP_UART_RUNNING_CORE=1 ; default any core ; -D EMSESP_UART_STACKSIZE=2560 ; default unbuild_flags = ${common.core_unbuild_flags} ; 16MB Flash variants [espressif32_base_16M] framework = arduino board_build.partitions = partitions/esp32_partition_16M.csv board_upload.flash_size = 16MB board_build.app_partition_name = app0 platform = espressif32@6.12.0 ; Arduino Core 2.0.17 / IDF 4.4.7 ; 32MB Flash variants [espressif32_base_32M] framework = arduino board_build.partitions = partitions/esp32_partition_32M.csv board_upload.flash_size = 32MB board_build.app_partition_name = app0 platform = espressif32@6.12.0 ; Arduino Core 2.0.17 / IDF 4.4.7 ; use Tasmota's library for 4MB Flash variants. ; Removes libs (like mbedtsl, so no WiFi_secure.h) to increase available heap [espressif32_base_T_4M] framework = arduino board_build.partitions = partitions/esp32_partition_4M.csv board_upload.flash_size = 4MB board_build.app_partition_name = app0 platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.06.00/platform-espressif32.zip ; Arduino Core 2.0.18 with IPv6 support, based on IDF 4.4.8 ; Tasmota Arduino Core 3.1.3.250302 based on IDF 5.3.2.250228 ; platform = https://github.com/tasmota/platform-espressif32/releases/download/2025.03.30/platform-espressif32.zip ; use Tasmota's library for 16MB Flash variants. ; Removes libs (like mbedtsl, so no WiFi_secure.h) to increase available heap [espressif32_base_T_16M] framework = arduino board_build.partitions = partitions/esp32_partition_16M.csv board_upload.flash_size = 16MB board_build.app_partition_name = app0 platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.06.00/platform-espressif32.zip ; Arduino Core 2.0.18 with IPv6 support, based on IDF 4.4.8 ; Tasmota Arduino Core 3.1.3.250302 based on IDF 5.3.2.250228 ; platform = https://github.com/tasmota/platform-espressif32/releases/download/2025.03.30/platform-espressif32.zip [env] build_flags = ${common.build_flags} build_unflags = ${common.unbuild_flags} extra_scripts = post:scripts/rename_fw.py ; renames the firmware .bin file monitor_speed = 115200 monitor_filters = direct build_type = release board_build.filesystem = littlefs lib_deps = bblanchon/ArduinoJson @ 7.4.2 ESP32Async/AsyncTCP @ 3.4.9 ESP32Async/ESPAsyncWebServer @ 3.9.2 https://github.com/emsesp/EMS-ESP-Modules.git @ 1.0.8 ; builds the web interface only, not the firmware [env:build_webUI] platform = native targets = build extra_scripts = pre:scripts/build_interface.py ; Exclude all source files so the C code doesn't build build_src_filter = -<*> ; ; Builds for different board types ; We use Tasmota for boards without PSRAM as this framework has mbedtls removed to save memory. ; If you're building for a single target environment, we recommend creating a pio_local.ini (see example file) ; [env:s_4M] ; 4MB ESP32 - no SSL, no PSRAM - like a BBQKees older S32 and E32 models - uses Tasmota extends = espressif32_base_T_4M board = s_4M [env:s_16M] ; 16MB ESP32 - no PSRAM - like a BBQKees later S32 V2 models - uses Tasmota extends = espressif32_base_T_16M board = s_16M [env:s_16M_P] ; 16MB ESP32 - with PSRAM - like a BBQKees E32V2 extends = espressif32_base_16M board = s_16M_P [env:s3_16M_P] ; 16MB ESP32-S3 - with PSRAM - like a BBQKees S3 extends = espressif32_base_16M board = s3_16M_P [env:s3_32M_P] ; 16MB ESP32-S3 - with PSRAM and 32MB flash extends = espressif32_base_32M board = s3_32M_P [env:s2_4M_P] ; based on lolin_s2_mini 4MB with 2MB PSRAM - uses Tasmota extends = espressif32_base_T_4M board = s2_4M_P [env:c3_mini_4M] ; based on lolin_c3_mini 4MB, no PSRAM - uses Tasmota extends = espressif32_base_T_4M board = c3_mini_4M ; lolin C3 mini v1 needs special wifi initialization ; https://www.wemos.cc/en/latest/c3/c3_mini_1_0_0.html#about-wifi [env:c3_miniv1_4M] extends = espressif32_base_T_4M board = c3_mini_4M build_flags = ${common.build_flags} -DBOARD_C3_MINI_V1 ; XIAO ESP32C - 512KB SRAM & 4MB Flash - https://wiki.seeedstudio.com/xiao_esp32c6_getting_started/ [env:c6] framework = arduino board_build.partitions = partitions/esp32_partition_4M.csv board_upload.flash_size = 4MB board_build.app_partition_name = app0 platform = https://github.com/pioarduino/platform-espressif32/releases/download/54.03.21-2/platform-espressif32.zip ; Arduino Release v3.2.1 based on ESP-IDF v5.4.2 ; platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.30-2/platform-espressif32.zip ; Arduino Release v3.3.0 based on ESP-IDF v5.5.0 board = seeed_xiao_esp32c6 build_flags = ${common.build_flags} -DBOARD_C6 ; foundation for building and testing natively, standalone without an ESP32. [env:native] platform = native build_type = debug build_flags = build_src_flags = -DEMSESP_STANDALONE -DEMSESP_TEST -DARDUINOJSON_ENABLE_ARDUINO_STRING=1 -std=gnu++17 -Og -ggdb -Wall -Wextra -Wno-unused-parameter -Wno-sign-compare -Wno-missing-braces -I./src/core -I./lib_standalone -I./lib/uuid-common/src -I./lib/uuid-console/src -I./lib/uuid-log/src -I./lib/semver -I./lib/PButton -I./lib/espMqttClient/src -I./lib/espMqttClient/src/Transport build_src_filter = +<../src> +<../lib> +<../lib_standalone> -<../src/ESP32React> -<../lib/uuid-telnet> -<../lib/uuid-syslog> -<../lib/eModbus> -<../lib/OneWire> lib_ldf_mode = off lib_deps = ; unit tests ; The test code is in ./test/test_api.cpp and the test_api.h file is created by the native-test-create environment. ; to run use `platformio run -e native-test -t exec`. All tests should PASS. ; tip: use https://jsondiff.com/ to compare the expected and actual responses. [env:native-test] platform = native test_build_src = true build_flags = build_type = debug build_src_flags = -DEMSESP_STANDALONE -DEMSESP_TEST -DEMSESP_UNITY -DARDUINOJSON_ENABLE_ARDUINO_STRING=1 -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.7.3-dev.0\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\" -std=gnu++17 -Og -ggdb -Wall -Wextra -Wno-unused-parameter -Wno-sign-compare -Wno-missing-braces -Wno-vla-cxx-extension -Wno-tautological-constant-out-of-range-compare -I./src/core -I./lib_standalone -I./lib/uuid-common/src -I./lib/uuid-console/src -I./lib/uuid-log/src -I./lib/semver -I./lib/PButton -I./lib/espMqttClient/src -I./lib/espMqttClient/src/Transport -I./test/api -I./test build_src_filter = +<../src> +<../test> +<../lib> +<../lib_standalone> -<../src/ESP32React> -<../lib/uuid-telnet> -<../lib/uuid-syslog> -<../lib/eModbus> -<../lib/OneWire> lib_ldf_mode = off lib_deps = Unity test_testing_command = ${platformio.build_dir}/${this.__env__}/program ; builds the test cases and creates the test_api.h file ; run with `pio run -e native-test-create -t exec` and capture the output between "START - CUT HERE" and "END - CUT HERE" and paste it into the test_api.h file [env:native-test-create] extends = env:native-test build_flags = -DEMSESP_UNITY_CREATE ; ; Building and testing locally on OS, which we call "standalone" without an ESP32. ; See https://docs.platformio.org/en/latest/platforms/native.html ; ; It will generate an executable which when run will show the EMS-ESP Console where you can run tests using the `test` command. ; ; See https://docs.platformio.org/en/latest/core/installation/shell-commands.html#piocore-install-shell-commands ; ; to build and run directly on linux: pio run -e standalone -t exec ; ; to build and run on Windows, it needs winsock for the console input so: ; - For the first time, install Msys2 (https://www.msys2.org/) and the GCC compiler with `run pacman -S mingw-w64-ucrt-x86_64-gcc` ; - Then, build with `pio run -e standalone` to create the program.exe file ; - run by calling the executable from the Mysys shell e.g. `C:/msys64/msys2_shell.cmd -defterm -here -no-start -ucrt64 -c /.pio/build/native/program.exe` ; - or use with Windows Terminal https://www.msys2.org/docs/terminals/ ; [env:standalone] extends = env:native build_flags = -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.7.3-dev.0\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\" ; Modbus ; Creating the modbus registers is a multi-step process. Before it was in a shell script called generate_csv_and_headers.sh ; but now moved to pio so everything is in python and cross-platform. The logic is as follows: ; 1. create a dummy modbus_entity_parameters.hpp file so the first pass compiles ; 2. compile the EMS-ESPcode with the EMSESP_MODBUS flag set ; 3. run the entity_dump test command and generate the dump_entities.csv file ; 4. use the dump_entities.csv file with update_modbus_registers.py script to generate the modbus_entity_parameters.hpp file ; 5. clean up everything and start again with the EMSESP_STANDALONE flag set ; 6. run the entity_dump test command again to create the real dump_entities.csv file ; 7. create the Modbus-Entity-Registers.md file ; 8. create the dump_telegrams.csv file ; ; To run this in pio use the steps ; pio run -e build_modbus -t clean -t build ; pio run -e build_standalone -t clean -t build # builds the modbus_entity_parameters.hpp header file # pio run -e build_modbus -t clean -t build [env:build_modbus] extends = env:native targets = build extra_scripts = pre:scripts/build_modbus_entity_parameters_pre.py post:scripts/build_run_test.py build_flags = -DEMSESP_MODBUS custom_test_command = entity_dump custom_output_file = dump_entities.csv custom_post_script = scripts/build_modbus_entity_parameters_post.py ; builds the real dump_entities.csv and dump_telegrams.csv files, and also the Modbus-Entity-Registers.md file ; to be run after build_modbus with: pio run -e build_standalone -t clean -t build [env:build_standalone] extends = env:native targets = build extra_scripts = post:scripts/build_run_test.py build_flags = -DEMSESP_STANDALONE custom_test_command = entity_dump custom_output_file = dump_entities.csv custom_post_script = scripts/build_standalone_post.py