# Build & Flash the Firmware with PlatformIO ## Prerequisites * 🔴 **Python 3.7 is the minimum supported version!** * 🔴 PlatformIO installer might not always use the system Python! ### Installing git `git` is used to manage our library dependencies * https://git-scm.com/downloads ### Installing PlatformIO Refer to the latest platformio-core documentation and follow the instructions for your platform * https://docs.platformio.org/en/latest/core/installation.html By default, PlatformIO does not add `pio` / `platformio` command to the system PATH variable ([but, it is a recommended option for Windows installations](https://docs.platformio.org/en/latest/faq.html#faq-install-python)) * https://docs.platformio.org/en/latest/core/installation.html#piocore-install-shell-commands Otherwise, it is possible to use [Python's venv](https://docs.python.org/3/library/venv.html) 'activate' / 'activate.bat' / 'activate.ps1' scripts (depends on the platform) to allow the use of `python` and `pio` commands in the shell * https://docs.python.org/3/library/venv.html#creating-virtual-environments Common location of the platformio installation is `~/.platformio/penv/Scripts/` ## Building For example, to build a binary for Sonoff Basic: ```bash $ pio run -e itead-sonoff-basic ``` The resulting `.bin` file can be found at `.pio/build/itead-sonoff-basic/firmware.bin` Or, using special generic environment: ```bash $ env ESPURNA_FLAGS="-DITEAD_SONOFF_BASIC" pio run -e esp8266-1m-base ``` (including any other flags / environment variables, depending on the board you are working with) For Window's cmd.exe, syntax is a bit different: ```cmd > cmd /V /C "set ESPURNA_FLAGS=-DITEAD_SONOFF_BASIC && pio run -e esp8266-1m-base" ``` ## Flash your board > **Notice** This describes serial upload, [see OTA page for information about wireless upload](OTA) and [PlatformIO documentation](https://docs.platformio.org/en/latest/platforms/espressif8266.html#over-the-air-ota-update) Wire your board (check the [Hardware page](Hardware)) and flash the firmware (with ```upload```): ```bash $ env ESPURNA_FLAGS="-DITEAD_SONOFF_BASIC" pio run -e esp8266-1m-base -t upload ``` ### macOS Big Sur PlatformIO's compatibility issues are fixed since espressif8266 version 2.6.3: ``` platform = platformio/espressif8266 @ >=2.6.3 ``` As an alternative, it is possible to override an older version of the tool-esptoolpy: ``` platform_packages = platformio/tool-esptoolpy @ ~1.30000.0 ``` Or, install [esptool>=3.0](https://pypi.org/project/esptool/) via `pip` and manually call the updated version. For more information, see https://github.com/espressif/esptool/issues/540 ## Libraries PlatformIO will take care of the library dependencies. The first time you run the build process it will fetch and install all the libraries required by ESPurna in the specified versions. For the most up-to-date list, please see [`code/platformio.ini`](https://github.com/xoseperez/espurna/blob/dev/code/platformio.ini) lib_deps = ... in the `[common]` section. Core libraries: * Benoit Blanchon's [ArduinoJson](https://github.com/bblanchon/ArduinoJson) * Marvin Roger's [AsyncMqttClient](https://github.com/marvinroger/async-mqtt-client) [[1]](#footnote1) * Hristo Gochkov's [ESPAsyncTCP](https://github.com/me-no-dev/ESPAsyncTCP) * Hristo Gochkov's [ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer) * Xose Pérez's [EEPROM Rotate](https://github.com/xoseperez/eeprom_rotate/) Optional libraries, depending on specific ...\_SUPPORT flags: * Joël Gähwiler's [Arduino MQTT](https://github.com/256dpi/arduino-mqtt) [[1]](#footnote1) * Nick O'Leary's [PubSubClient](https://github.com/knolleary/pubsubclient) [[1]](#footnote1) * Pascal Kurtansky's [Brzo I2C](https://github.com/pasko-zh/brzo_i2c) [[2]](#footnote2) * Xose Pérez's [HLW8012](https://bitbucket.org/xoseperez/hlw8012.git) [[3]](#footnote3) * Xose Pérez's [my92xx](https://github.com/xoseperez/my92xx) [[4]](#footnote4) * Xose Pérez's [NoFUSS](https://bitbucket.org/xoseperez/nofuss.git) * Paul Vint's, Xose Pérez's (et al.) [fauxmo ESP](https://github.com/vintlabs/fauxmoESP) * David Conran's, Mark Szabo (et al.) [IrRemoteES8266](hhttps://github.com/crankyoldgit/IRremoteESP8266) * Paul Stoffregen (et al.) [OneWire](https://github.com/PaulStoffregen/OneWire) * Mariusz Kacki's [PMS](https://github.com/fu-hsi/PMS) [[4]](#footnote1) * Randy Simons' [RemoteSwitch](https://github.com/jccprj/RemoteSwitch-arduino-library) * Maxim Prokhorov's fork of Xose Pérez's [RPNLib](https://github.com/mcspr/rpnlib) [[5]](#footnote5) * [@1technophile](https://github.com/1technophile) fork of Suat Özgür's [RCSwitch](https://github.com/1technophile/rc-switch) [[6]](#footnote6) Button management, WiFi control and settings storage inspired by: * Xose Pérez's [DebounceEvent](https://bitbucket.org/xoseperez/debounceevent.git) * Xose Pérez's [JustWifi](https://github.com/xoseperez/justwifi.git) * The PatternAgents (et al.) [Embedis](https://github.com/thingSoC/embedis) At last, legacy libraries for Core 2.3.0 (deprecated, only matters when building using `platform = espressif8266@1.5.0`): * German Martin's [NtpCLientLib](https://github.com/gmag11/NtpClient) * Fork of Michael Maregolis & Paul Stoffregen's [Time](https://github.com/xoseperez/Time) * Peter Lerup's [ESPSoftwareSerial, pinned to the version 3.4.1](https://github.com/plerup/espsoftwareserial/tree/3.4.1) ## Customize build settings ### platformio.ini format Please refer to the official PlatformIO documentation for `platformio.ini`: https://docs.platformio.org/en/latest/projectconf/ ESPurna's platformio.ini has the following structure: - `code/espurna/` is set as source code root directory - `code/platformio_override.ini` can be used to override existing or create new sections. - `[common]` sections is used to set some variables that later will be used as `${common.variable}` - `[env]` section implicitly provides keys for every environment, so we don't have to repeat ourselves - `[env:...-base]` specifies framework (arduino, only available option), board (upload settings, variant build flags), ldscript (memory regions, flash constants and flash size), platform (PlatformIO build system version) and platform_packages (in case we need to change build tools versions) - `[env:named]` extends from the `-base` environment and sets `build_src_flags` with our project-specific flags. Common way to specify hardware is to have `#if defined(HARDWARE_FLAG)` (see `code/espurna/config/hardware.h') and add `-DHARDWARE_FLAG` when you need to enable multiple `#define` options. It is important to note that in case of repeating keys: ```ini [env:example] extends = esp8266-1m-base build_src_flags = -DMY_CUSTOM_HARDWARE -DUSE_CUSTOM_H [env:override] extends = env:example build_src_flags = -DANOTHER_HARDWARE ``` When building `env:override`, `-DUSE_CUSTOM_H` will not be added to the compiler build flags. To append to the existing variable you would need to explicitly specify the key that you want it to use. For example: ```ini [env:example] extends = esp8266-1m-base build_src_flags = -DMY_CUSTOM_HARDWARE -DUSE_CUSTOM_H [env:override] extends = esp8266-1m-base build_src_flags = ${env:example.build_src_flags} -DSOME_OTHER_FLAG=1 ``` ### build_flags and build_src_flags - `build_src_flags` is used only by our project's files - `build_flags` sets command line options for project's files, Core and libraries For example, our `[env]` sections contains the following flags: ```ini build_flags = -g -w -DNO_GLOBAL_EEPROM -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH ``` Where: - `-g` add debug information into the resulting `.elf` file - `-w` suppresses build warnings for libraries and Core - `-DNO_GLOBAL_EEPROM` is a compatibility flag that disables Core built-in EEPROM library which conflicts with the EEPROM_Rotate. (**WARNING** removing it will cause build to fail with recent Core versions, unless you also change `board_build.ldscript` to the value that will use the .ld file from the Core, see [tools/sdk/ld](https://github.com/esp8266/Arduino/tree/master/tools/sdk/ld)) - `-DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH` sets lwipv2 variant to 1460 MSS option, see https://docs.platformio.org/en/latest/platforms/espressif8266.html#lwip-variant and / or https://github.com/esp8266/Arduino/blob/9845deb2832bb28bf355d5ff652eb7908977b443/tools/platformio-build.py#L199-L244 for the upstream configuration options. Any environment that wants to modify build flags needs to explicitly specify the existing build_flags variable as `build_flags = ${common.build_flags} -DLIBRARY_CUSTOM_FLAG=12345 -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221`. ### Custom environment If you want to modify the stock configuration but you don't want to touch the repo files you can create a brand new environment in the `code/platformio_override.ini`: ```ini [env:my-environment] extends = esp8266-1m-base build_src_flags = -DITEAD_SONOFF_BASIC -DDHT_SUPPORT=1 ``` ### custom.h Add `-DUSE_CUSTOM_H` to `build_src_flags` and create `code/espurna/config/custom.h`. For example: ```cpp #define WEB_EMBEDDED 0 #define NTP_SERVER "it.pool.ntp.org" #define MQTT_TOPIC "my/topic" #define DOMOTICZ_ENABLED 1 #define ALEXA_SUPPORT 0 ``` (see `code/espurna/config/general.h` and `code/espurna/config/sensor.h` for available flags) It is also possible to add flag through command line by setting OS environment variables `PLATFORMIO_BUILD_SRC_FLAGS` and `PLATFORMIO_BUILD_FLAGS`, for `build_src_flags` and `build_flags` respectively: ```sh export PLATFORMIO_BUILD_SRC_FLAGS="-DUSE_CUSTOM_H" ``` We also provide a `ESPURNA_FLAGS` OS environment variable that is used by the [OTA](OTA#using-generic-environments): ```sh export ESPURNA_FLAGS="-DUSE_CUSTOM_H" ``` `ESPURNA_FLAGS` is interchangeable with the `PLATFORMIO_BUILD_SRC_FLAGS` and both will append flags into the existing `build_src_flags` contents. ### Advanced options #### `-DDISABLE_POSTMORTEM_STACKDUMP` (`build_flags` / `build_src_flags` option) Used to disable serial print of postmortem stack dump after a board crashes. This functionality is part of the Arduino Core, so we build a dummy file with an empty printf function and replace the reference to printf in the resulting .o file. Kind of a hack, this should probably be configured in the Core itself. But, we need to write a patch for that. #### `ESPURNA_BUILD_SINGLE_SOURCE` (OS environment variable) Combine every .cpp into a single file to significantly speed up compilation process when parallel build cannot be used. This will also result in a reduced .bin size (~7KB smaller). ATM this option is only used in CI to build release and test .bin files #### `ESPURNA_BUILD_DESTINATION` and `ESPURNA_BUILD_NAME` (OS environment variables) Specify where to store files copied with `pio run -e $env -t build-and-copy` and how to name them #### `ESPURNA_BUILD_FULL_VERSION` and `ESPURNA_BUILD_VERSION`, `ESPURNA_BUILD_REVISION`, `ESPURNA_BUILD_VERSION_SUFFIX` (OS environment variables) Configures version string, both for the resulting .bin name and string inside of the app. Ver By default, version string looks like this: `1.15.0-dev.git73e3bdac`. It can be completely changed, or just some parts of it - `ESPURNA_BUILD_FULL_VERSION` replaces the full string; `{FULL_VERSION}` - `ESPURNA_BUILD_VERSION` replaces the leftmost part; `{VERSION}-git73e3bdac` - `ESPURNA_BUILD_REVISION` replaces the hash string at the end; `1.15.0-dev.git{REVISION}` (since we use git by default) - `ESPURNA_BUILD_VERSION_SUFFIX` adds an extra (semantic version compatible) string at the end; `1.15.0-dev.git73e3bdac+{SUFFIX}` #### `ESPURNA_FLAGS`, `ESPURNA_IP`, `ESPURNA_AUTH`, `ESPURNA_BOARD` (OS environment variables) - `ESPURNA_IP` flags upload type as OTA (when using `-t upload`) and adds `--ip=$ESPURNA_IP` to the espota.py arguments list - `ESPURNA_AUTH` adds `--auth=$ESPURNA_AUTH` to the espota.py arguments list (depends on `ESPURNA_IP`) - `ESPURNA_FLAGS` supports adding `-D...` to the project build flags (or, modify `build_src_flags` for the same result. however, `ESPURNA_FLAGS` could be used to short-circuit PlatformIO configuration change detection which will prevent rebuilding everything when flags change) - (legacy) `ESPURNA_BOARD` updates build flags with `-D$ESPURNA_BOARD`. This was used previously as a platformio.ini substitution, but is no longer used and will be removed in the future. --- 1 See [MQTT configuration](MQTT)
2 See [I2C configuration](I2C)
3 See [Sensors configuration](Sensors)
4 See [Lights configuration](Lights)
5 See [RPN Rules configuration](RPN-Rules)
6 See [RFBridge configuration](RFBRIDGE)