From bb5366300a9f9d2361a36094acdeba847c27a95e Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Fri, 29 Nov 2019 03:42:53 -0300 Subject: [PATCH 01/50] Don't allow blank issues --- .github/ISSUE_TEMPLATE/config.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..9c78f2c84 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Tasmota Docs + url: https://tasmota.github.io/docs/#/ + about: All the information related to Tasmota + - name: Tasmota Support Chat + url: https://discord.gg/Ks2Kzd4 + about: Chat for feedback, questions and troubleshooting. From 38d64634abd3d4bee327bd42d8b441f230bd048b Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Fri, 29 Nov 2019 03:46:57 -0300 Subject: [PATCH 02/50] Update Bug Report to Problem Report As sometimes a bug is reported as a troubleshooting and also a troubleshooting issue is reported as a bug, and as both templates are nearly the same, it is better to have just one problem template. --- .github/ISSUE_TEMPLATE/Bug_report.md | 37 ++++++++++++++-------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index 373d518cb..847958093 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -1,31 +1,32 @@ --- -name: Bug report +name: Problem report about: Create a report to help us improve --- -> **GUIDE** -> -> This BUG issue template is meant to REPORT Tasmota software BUGS ONLY> -> -> Please DO NOT OPEN AN ISSUE: -> - If your Tasmota version is not the latest from the development branch, please update your device before submitting your issue. Your problem might already be solved. The latest precompiled binaries of Tasmota can be downloaded from http://thehackbox.org/tasmota/ -> - If you have a issue when flashing was done via Tuya Convert -> - If your issue is a flashing issue, please address it to the [Tasmota Support Chat](https://discord.gg/Ks2Kzd4) -> - If your issue is compilation problem, please address it to the [Tasmota Support Chat](https://discord.gg/Ks2Kzd4) -> - If your issue has been addressed before (i.e., duplicated issue), please ask in the original issue -> - If your issue is a Wi-Fi problem or MQTT problem, please try the steps provided in the [FAQ](https://github.com/arendst/Tasmota/wiki/FAQ) and troubleshooting wiki articles -> -> Please take a few minutes to complete the requested information below. Our ability to provide assistance is greatly hampered without it. The details requested potentially affect which options to pursue. The small amount of time you spend completing the template will also help the volunteers providing the assistance to you to reduce the time required to help you. + + +### PROBLEM DESCRIPTION +_A clear and concise description of what the problem is._ ### REQUESTED INFORMATION _Make sure your have performed every step and checked the applicable boxes before submitting your issue. Thank you!_ -**FAILURE TO COMPLETE THE REQUESTED INFORMATION WILL RESULT IN YOUR ISSUE BEING CLOSED** - - [ ] Read the [Contributing Guide and Policy](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md) and [the Code of Conduct](https://github.com/arendst/Tasmota/blob/development/CODE_OF_CONDUCT.md) - [ ] Searched the problem in [issues](https://github.com/arendst/Tasmota/issues) - [ ] Searched the problem in the [wiki](https://github.com/arendst/Tasmota/wiki/Troubleshooting) From a2a3e1ad7b2043d3189f12174933e7b9bc335736 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Fri, 29 Nov 2019 03:47:36 -0300 Subject: [PATCH 03/50] Update Feature_request.md --- .github/ISSUE_TEMPLATE/Feature_request.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md index 5aa100e01..43fd36e7c 100644 --- a/.github/ISSUE_TEMPLATE/Feature_request.md +++ b/.github/ISSUE_TEMPLATE/Feature_request.md @@ -3,7 +3,12 @@ name: Feature request about: Suggest an idea for this project --- -> Please take a few minutes to complete the requested information below. Our ability to provide assistance is greatly hampered without it. The details requested potentially affect which options to pursue. The small amount of time you spend completing the template will also help the volunteers providing the assistance to you to reduce the time required to help you. + **Have you looked for this feature in other issues and in the wiki?** From 278e913709aa2c52d0acd7c218e6aa5611c738f3 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Fri, 29 Nov 2019 03:48:35 -0300 Subject: [PATCH 04/50] Merging Troubleshooting and Bug reports into one --- .github/ISSUE_TEMPLATE/Custom.md | 67 -------------------------------- 1 file changed, 67 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/Custom.md diff --git a/.github/ISSUE_TEMPLATE/Custom.md b/.github/ISSUE_TEMPLATE/Custom.md deleted file mode 100644 index 3b30c5f18..000000000 --- a/.github/ISSUE_TEMPLATE/Custom.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -name: Troubleshooting -about: Users Troubleshooting Help ---- - -> **GUIDE** -> -> This troubleshooting issue template is meant to help Tasmota users with difficult problems. It is aimed to be opened if using the wiki and the support chat could not solve the issue. The Github Issue tracker is NOT a general discussion forum! -> -> Please DO NOT OPEN AN ISSUE: -> - If you have general questions or you need help on Tasmota usage, go to the [Tasmota Support Chat](https://discord.gg/Ks2Kzd4) -> - If your Tasmota version is not the latest from the development branch, please update your device before submitting your issue. Your problem might already be solved. The latest precompiled binaries of Tasmota can be downloaded from http://thehackbox.org/tasmota/ -> - If your issue is about a new device, please use the Tasmota [Template](../wiki/Templates) feature. -> - If your issue is a flashing issue, please address it to the [Tasmota Support Chat](https://discord.gg/Ks2Kzd4) -> - If your issue is compilation problem, please address it to the [Tasmota Support Chat](https://discord.gg/Ks2Kzd4) -> - If your issue has been addressed before (i.e., duplicated issue), please ask in the original issue -> - If your issue is a Wi-Fi problem or MQTT problem, please try the steps provided in the [FAQ](https://github.com/arendst/Tasmota/wiki/FAQ) and troubleshooting wiki articles -> -> Please take a few minutes to complete the requested information below. Our ability to provide assistance is greatly hampered without it. The details requested potentially affect which options to pursue. The small amount of time you spend completing the template will also help the volunteers providing the assistance to you to reduce the time required to help you. - -### ISSUE DESCRIPTION - TROUBLESHOOTING -_A clear description of what the issue is and be as extensive as possible_ - - -### REQUESTED INFORMATION -_Make sure these boxes are checked before submitting your issue. Thank you_ - -**FAILURE TO COMPLETE THE REQUESTED INFORMATION WILL RESULT IN YOUR ISSUE BEING CLOSED** - -- [ ] Read the [Contributing Guide and Policy](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md) and [the Code of Conduct](https://github.com/arendst/Tasmota/blob/development/CODE_OF_CONDUCT.md) -- [ ] Searched the problem in issues (https://github.com/arendst/Tasmota/issues) -- [ ] Searched the problem in the wiki (https://github.com/arendst/Tasmota/wiki/Troubleshooting) -- [ ] Searched the problem in the forum (https://groups.google.com/d/forum/sonoffusers) -- [ ] Searched the problem in the chat (https://discord.gg/Ks2Kzd4) -- [ ] Device used (e.g., Sonoff Basic): _____ -- [ ] Tasmota binary firmware version number used: _____ - - [ ] Pre-compiled - - [ ] Self-compiled - - [ ] IDE / Compiler used: _____ -- [ ] Flashing tools used: _____ -- [ ] Provide the output of this command: ``Backlog Template; Module; GPIO``: - ``` - Configuration output here: - - - ``` -- [ ] If using rules, provide the output of this command: ``Backlog Rule1; Rule2; Rule3``: - ``` - Rules output here: - - - ``` -- [ ] Provide the output of this command: ``Status 0``: - ``` - STATUS 0 output here: - - - ``` -- [ ] Provide the output of the Console log output when you experience your issue; if applicable: - _(Please use_ ``weblog 4`` _for more debug information)_ - ``` - Console output here: - - - ``` - -**(Please, remember to close the issue when the problem has been addressed)** From b9dfa51225658b0abef41cce388bb786fbcf8c24 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Fri, 29 Nov 2019 03:50:28 -0300 Subject: [PATCH 05/50] Add code of conduct Bot --- .github/config.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/config.yml diff --git a/.github/config.yml b/.github/config.yml new file mode 100644 index 000000000..6ef38dd6b --- /dev/null +++ b/.github/config.yml @@ -0,0 +1,11 @@ +# Configuration for sentiment-bot - https://github.com/behaviorbot/sentiment-bot + +# *Required* toxicity threshold between 0 and .99 with the higher numbers being the most toxic +# Anything higher than this threshold will be marked as toxic and commented on +sentimentBotToxicityThreshold: .7 + +# *Required* Comment to reply with +sentimentBotReplyComment: > + Please be sure to review the code of conduct and be respectful of other users. + +# Note: the bot will only work if your repository has a Code of Conduct From 5bb42670948a51d85693ee775069eec08014a2ae Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Fri, 29 Nov 2019 03:52:13 -0300 Subject: [PATCH 06/50] Add issue-close Bot This Bot auto-closes new issues without template --- .github/issue-close-app.yml | 54 +++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 .github/issue-close-app.yml diff --git a/.github/issue-close-app.yml b/.github/issue-close-app.yml new file mode 100644 index 000000000..0fcb996ab --- /dev/null +++ b/.github/issue-close-app.yml @@ -0,0 +1,54 @@ +# CLOSE ISSUE BOT +# --------------- +# A bot which helps you to close issues that don't include some specific contents. +# See how to use it in https://github.com/offu/close-issue-app. + +# Comment that will be sent if an issue is judged to be closed. +comment: >- + This issue has been automatically closed because the issue template is missing or incomplete. + + Filling the template is required so standard questions don't need to be asked again each time. + Our ability to provide assistance is greatly hampered if few minutes are not taken to complete the issue template + with the requested information. The details requested potentially affect which options to pursue. The small amount + of time you spend completing the template will also help the volunteers providing the assistance to you, to reduce + the time required to help you. + + Please, could you be so kind on completing the [issue template](https://github.com/arendst/Tasmota/issues/new/choose) in order to have more information so as to properly help you? + + Thank you for taking the time to report, hopefully it can be resolved soon. + + [Support Information](https://github.com/arendst/Sonoff-Tasmota/blob/development/SUPPORT.md) + + [Wiki](https://tasmota.github.io/docs/#/) for more information. + + [Chat](https://discord.gg/Ks2Kzd4) for more user experience. + + [Community](https://groups.google.com/d/forum/sonoffusers) for forum. + + [Code of Conduct](https://github.com/arendst/Sonoff-Tasmota/blob/development/CODE_OF_CONDUCT.md) + + [Contributing Guideline and Policy](https://github.com/arendst/Sonoff-Tasmota/blob/development/CONTRIBUTING.md) + +issueConfigs: +# There can be several configs for different kind of issues. +- content: +# template 1: bug report + - "PROBLEM DESCRIPTION" + - "REQUESTED INFORMATION" + - "TO REPRODUCE" + - "EXPECTED BEHAVIOUR" +- content: +# template 2: feature request + - "Have you looked for this feature in other issues and in the wiki" + - "Describe the solution you'd like" + +# Optional configuration: +# +# whether the keywords are case-insensitive +# default value is false, which means keywords are case-sensitive +caseInsensitive: true +# the label that will be added when the bot close an issue +# The bot will only add a label if this property is set. +label: "template missing/incomplete" +# The issue is judged to be legal if it includes all keywords from any of these two configs. +# Or it will be closed by the app. From 0640838be7eac6b2868bae10215dedf1021caaf1 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Fri, 29 Nov 2019 04:43:25 -0300 Subject: [PATCH 07/50] Updated README Now thehackbox.org is providing binaries from dev branch in all supported languages. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ed884afea..8d5a1e696 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ See [tasmota/CHANGELOG.md](tasmota/CHANGELOG.md) for detailed change information Unless your Tasmota powered device exhibits a problem or you need to make use of a feature that is not available in the Tasmota version currently installed on your device, leave your device alone - it works so don't make unnecessary changes! If the release version (i.e., the master branch) exhibits unexpected behaviour for your device and configuration, you should upgrade to the latest development version instead to see if your problem is resolved as some bugs in previous releases or development builds may already have been resolved. -The Tasmota development codebase is checked every 1-2 hours for changes. If new commits have been merged and they compile successfuly, new binary files for every variant (excluding non-English languages) will be posted at http://thehackbox.org/tasmota/ (this web address can be used for OTA updates too). The last compiled commit number is also indicated on the same page. It is important to note that these binaries are based on the current development codebase. These commits are tested as much as is possible and are typically quite stable. However, it is infeasible to test on the hundreds of different types of devices with all the available configuration options permitted. +The Tasmota development codebase is checked every 1-2 hours for changes. If new commits have been merged and they compile successfuly, new binary files for every variant will be posted at http://thehackbox.org/tasmota/ (this web address can be used for OTA updates too). The last compiled commit number is also indicated on the same page. It is important to note that these binaries are based on the current development codebase. These commits are tested as much as is possible and are typically quite stable. However, it is infeasible to test on the hundreds of different types of devices with all the available configuration options permitted. Note that there is a chance, as with any upgrade, that the device may not function as expected. You must always account for the possibility that you may need to flash the device via the serial programming interface if the OTA upgrade fails. Even with the master release, you should always attempt to test the device or a similar prototype before upgrading a device which is in production or is hard to reach. And, as always, make a backup of the device configuration before beginning any firmware update. From 70c89f62cc4fb2c6690ed189e737dd1ed73e87e2 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 29 Nov 2019 11:09:29 +0100 Subject: [PATCH 08/50] Update platformio_override_sample.ini --- platformio_override_sample.ini | 206 +++++++++++++++++++++++++++++++-- 1 file changed, 196 insertions(+), 10 deletions(-) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index bd4ed2a13..c0313577e 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -1,11 +1,14 @@ -; PlatformIO Project Configuration Override File +; *** Example PlatformIO Project Configuration Override File *** +; *** Changes done here overrides settings in platformio.ini *** +; +; **************************************************************** +; *** to activate rename this fie to platformio_override.ini *** +; **************************************************************** ; -; Build options: build flags, source filter, extra scripting -; Upload options: custom port, speed and extra flags -; Library options: dependencies, extra library storages -; -; Please visit documentation for the other options and examples +; Please visit documentation for the options and examples ; http://docs.platformio.org/en/stable/projectconf.html +; + [platformio] @@ -24,14 +27,197 @@ default_envs = [common] -; *** Use settings from file user_config_override.h +platform = ${core_active.platform} build_flags = ${core_active.build_flags} +; *** Use settings from file user_config_override.h -DUSE_CONFIG_OVERRIDE +; *** Optional Firmware configurations +; -DFIRMWARE_MINIMAL +; -DFIRMWARE_SENSORS +; -DFIRMWARE_BASIC +; -DFIRMWARE_KNX_NO_EMULATION +; -DFIRMWARE_DISPLAYS +; -DFIRMWARE_IR +; -DFIRMWARE_IR_CUSTOM + +; *** Optional Debug messages +; -DDEBUG_TASMOTA_CORE +; -DDEBUG_TASMOTA_DRIVER +; -DDEBUG_TASMOTA_SENSOR + +; set CPU frequency to 80MHz (default) or 160MHz +;board_build.f_cpu = 160000000L + ; *** Upload Serial reset method for Wemos and NodeMCU upload_port = COM5 -[core_active] +extra_scripts = ${scripts_defaults.extra_scripts} + pio/obj-dump.py -platform = ${core_2_6_2.platform} -build_flags = ${core_2_6_2.build_flags} +; *** Upload file to OTA server using SCP +;upload_port = user@host:/path +;extra_scripts = ${scripts_defaults.extra_scripts} +; pio/strip-floats.py, pio/sftp-uploader.py + +; *** Upload file to OTA server in folder api/arduino using HTTP +;upload_port = domus1:80/api/upload-arduino.php +;extra_scripts = ${scripts_defaults.extra_scripts} +; pio/strip-floats.py, pio/http-uploader.py + +[core_active] +; Select one core set for platform and build_flags +platform = ${core_2_6_1.platform} +build_flags = ${core_2_6_1.build_flags} +;platform = ${core_2_6_2.platform} +;build_flags = ${core_2_6_2.build_flags} +;platform = ${core_stage.platform} +;build_flags = ${core_stage.build_flags} + + +[core_2_6_1] +; *** Esp8266 core for Arduino version 2.6.1 +platform = espressif8266@2.3.0 +build_flags = ${esp82xx_defaults.build_flags} + -Wl,-Teagle.flash.1m.ld + -DBEARSSL_SSL_BASIC +; NONOSDK221 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 +; NONOSDK22x_190313 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 +; NONOSDK22x_190703 = 2.2.2-dev(38a443e) (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 +; NONOSDK22x_191024 = 2.2.2-dev(5ab15d1) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 +; NONOSDK22x_191105 = 2.2.2-dev(bb83b9b) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 +; NONOSDK3V0 (known issues) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 +; lwIP 1.4 +; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH +; lwIP 2 - Low Memory +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY +; lwIP 2 - Higher Bandwidth +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH +; lwIP 2 - Higher Bandwidth Low Memory no Features +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH +; lwIP 2 - Higher Bandwidth no Features (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH +; lwIP 2 - Higher Bandwidth IPv6 (use ONLY if you need IPv6, experimental!) +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_HIGHER_BANDWIDTH +; VTABLES in Flash (Tasmota default) + -DVTABLES_IN_FLASH +; VTABLES in Heap +; -DVTABLES_IN_DRAM +; VTABLES in IRAM +; -DVTABLES_IN_IRAM +; enable one option set -> No exception recommended +; No exception code in firmware + -fno-exceptions + -lstdc++ +; Exception code in firmware /needs much space! 90k +; -fexceptions +; -lstdc++-exc + +[core_2_6_2] +; *** Esp8266 core for Arduino version 2.6.2 +platform = espressif8266@2.3.1 +build_flags = ${esp82xx_defaults.build_flags} + -Wl,-Teagle.flash.1m.ld + -DBEARSSL_SSL_BASIC +; NONOSDK221 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 +; NONOSDK22x_190313 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 +; NONOSDK22x_190703 = 2.2.2-dev(38a443e) (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 +; NONOSDK22x_191024 = 2.2.2-dev(5ab15d1) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 +; NONOSDK22x_191105 = 2.2.2-dev(bb83b9b) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 +; NONOSDK3V0 (known issues) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 +; lwIP 1.4 +; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH +; lwIP 2 - Low Memory +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY +; lwIP 2 - Higher Bandwidth +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH +; lwIP 2 - Higher Bandwidth Low Memory no Features +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH +; lwIP 2 - Higher Bandwidth no Features (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH +; lwIP 2 - Higher Bandwidth IPv6 (use ONLY if you need IPv6, experimental!) +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_HIGHER_BANDWIDTH +; VTABLES in Flash (Tasmota default) + -DVTABLES_IN_FLASH +; VTABLES in Heap +; -DVTABLES_IN_DRAM +; VTABLES in IRAM +; -DVTABLES_IN_IRAM +; enable one option set -> No exception recommended +; No exception code in firmware + -fno-exceptions + -lstdc++ +; Exception code in firmware /needs much space! 90k +; -fexceptions +; -lstdc++-exc + +[core_stage] +; *** Esp8266 core for Arduino version latest beta +platform = https://github.com/platformio/platform-espressif8266.git#feature/stage +build_flags = ${esp82xx_defaults.build_flags} + -Wl,-Teagle.flash.1m.ld + -DBEARSSL_SSL_BASIC +; NONOSDK221 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 +; NONOSDK22x_190313 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 +; NONOSDK22x_190703 (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 +; NONOSDK22x_191024 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 +; NONOSDK22x_191105 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 +; NONOSDK3V0 (known issues) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 +; lwIP 1.4 +; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH +; lwIP 2 - Low Memory +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY +; lwIP 2 - Higher Bandwidth +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH +; lwIP 2 - Higher Bandwidth Low Memory no Features +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH +; lwIP 2 - Higher Bandwidth no Features (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH +; VTABLES in Flash (Tasmota default) + -DVTABLES_IN_FLASH +; VTABLES in Heap +; -DVTABLES_IN_DRAM +; VTABLES in IRAM +; -DVTABLES_IN_IRAM +; enable one option set -> No exception recommended +; No exception code in firmware + -fno-exceptions + -lstdc++ +; Exception code in firmware /needs much space! 90k +; -fexceptions +; -lstdc++-exc + + +; *** Debug version used for PlatformIO Home Project Inspection +[env:tasmota-debug] +platform = ${common.platform} +framework = ${common.framework} +board = ${common.board} +board_build.flash_mode = ${common.board_build.flash_mode} +board_build.f_cpu = ${common.board_build.f_cpu} +build_type = debug +build_unflags = ${common.build_unflags} +build_flags = ${common.build_flags} +monitor_speed = ${common.monitor_speed} +upload_port = ${common.upload_port} +upload_resetmethod = ${common.upload_resetmethod} +upload_speed = ${common.upload_speed} +extra_scripts = ${common.extra_scripts} From 2539d67839bec53c770ec3143993fc80a70edf45 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 29 Nov 2019 11:14:26 +0100 Subject: [PATCH 09/50] Add files via upload --- platformio.ini | 190 +++++-------------------------------------------- 1 file changed, 19 insertions(+), 171 deletions(-) diff --git a/platformio.ini b/platformio.ini index cdce62e9d..838354a84 100755 --- a/platformio.ini +++ b/platformio.ini @@ -45,6 +45,11 @@ default_envs = ; tasmota-TR ; tasmota-TW ; tasmota-UK +; +; *** alternatively can be done in file: platformio_override.ini +; *** See example: platformio_override_sample.ini +; ********************************************************************* + [common] framework = arduino @@ -57,192 +62,51 @@ build_flags = ${core_active.build_flags} ; ********************************************************************* ; *** Uncomment, by deleting ";" in line below, to use custom settings from file user_config_override.h ; -DUSE_CONFIG_OVERRIDE +; +; *** alternatively can be done in: platformio_override.ini +; *** See example: platformio_override_sample.ini ; ********************************************************************* -; *** Optional Debug messages -; -DDEBUG_TASMOTA_CORE -; -DDEBUG_TASMOTA_DRIVER -; -DDEBUG_TASMOTA_SENSOR - -; *** Optional Firmware configurations -; -DFIRMWARE_MINIMAL -; -DFIRMWARE_SENSORS -; -DFIRMWARE_BASIC -; -DFIRMWARE_KNX_NO_EMULATION -; -DFIRMWARE_DISPLAYS -; -DFIRMWARE_IR -; -DFIRMWARE_IR_CUSTOM - ; *** Fix espressif8266@1.7.0 induced undesired all warnings build_unflags = -Wall -; set CPU frequency to 80MHz (default) or 160MHz board_build.f_cpu = 80000000L -;board_build.f_cpu = 160000000L - monitor_speed = 115200 upload_speed = 115200 -upload_resetmethod = nodemcu - ; *** Upload Serial reset method for Wemos and NodeMCU +upload_resetmethod = nodemcu upload_port = COM5 +extra_scripts = ${scripts_defaults.extra_scripts} + +[scripts_defaults] extra_scripts = pio/strip-floats.py pio/name-firmware.py -; pio/obj-dump.py - -; *** Upload file to OTA server using SCP -;upload_port = user@host:/path -;extra_scripts = pio/strip-floats.py, pio/sftp-uploader.py - -; *** Upload file to OTA server in folder api/arduino using HTTP -;upload_port = domus1:80/api/upload-arduino.php -;extra_scripts = pio/strip-floats.py, pio/http-uploader.py - -[core_active] -; Select one core set for platform and build_flags -platform = ${core_2_6_1.platform} -build_flags = ${core_2_6_1.build_flags} -;platform = ${core_2_6_2.platform} -;build_flags = ${core_2_6_2.build_flags} -;platform = ${core_stage.platform} -;build_flags = ${core_stage.build_flags} - -; ********************************************************************* [esp82xx_defaults] build_flags = -D NDEBUG -mtarget-align -Wl,-Map,firmware.map +[core_active] +platform = ${core_2_6_1.platform} +build_flags = ${core_2_6_1.build_flags} + [core_2_6_1] ; *** Esp8266 core for Arduino version 2.6.1 platform = espressif8266@2.3.0 build_flags = ${esp82xx_defaults.build_flags} -Wl,-Teagle.flash.1m.ld -DBEARSSL_SSL_BASIC -; NONOSDK221 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 -; NONOSDK22x_190313 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 -; NONOSDK22x_190703 = 2.2.2-dev(38a443e) (Tasmota default) +; NONOSDK22x_190703 = 2.2.2-dev(38a443e) -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 -; NONOSDK22x_191024 = 2.2.2-dev(5ab15d1) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 -; NONOSDK22x_191105 = 2.2.2-dev(bb83b9b) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 -; NONOSDK3V0 (known issues) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 -; lwIP 1.4 -; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH -; lwIP 2 - Low Memory -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY -; lwIP 2 - Higher Bandwidth -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH -; lwIP 2 - Higher Bandwidth Low Memory no Features -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH -; lwIP 2 - Higher Bandwidth no Features (Tasmota default) +; lwIP 2 - Higher Bandwidth no Features -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH -; lwIP 2 - Higher Bandwidth IPv6 (use ONLY if you need IPv6, experimental!) -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_HIGHER_BANDWIDTH -; VTABLES in Flash (Tasmota default) +; VTABLES in Flash -DVTABLES_IN_FLASH -; VTABLES in Heap -; -DVTABLES_IN_DRAM -; VTABLES in IRAM -; -DVTABLES_IN_IRAM -; enable one option set -> No exception recommended ; No exception code in firmware -fno-exceptions -lstdc++ -; Exception code in firmware /needs much space! 90k -; -fexceptions -; -lstdc++-exc -[core_2_6_2] -; *** Esp8266 core for Arduino version 2.6.2 -platform = espressif8266@2.3.1 -build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Teagle.flash.1m.ld - -DBEARSSL_SSL_BASIC -; NONOSDK221 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 -; NONOSDK22x_190313 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 -; NONOSDK22x_190703 = 2.2.2-dev(38a443e) (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 -; NONOSDK22x_191024 = 2.2.2-dev(5ab15d1) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 -; NONOSDK22x_191105 = 2.2.2-dev(bb83b9b) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 -; NONOSDK3V0 (known issues) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 -; lwIP 1.4 -; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH -; lwIP 2 - Low Memory -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY -; lwIP 2 - Higher Bandwidth -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH -; lwIP 2 - Higher Bandwidth Low Memory no Features -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH -; lwIP 2 - Higher Bandwidth no Features (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH -; lwIP 2 - Higher Bandwidth IPv6 (use ONLY if you need IPv6, experimental!) -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_HIGHER_BANDWIDTH -; VTABLES in Flash (Tasmota default) - -DVTABLES_IN_FLASH -; VTABLES in Heap -; -DVTABLES_IN_DRAM -; VTABLES in IRAM -; -DVTABLES_IN_IRAM -; enable one option set -> No exception recommended -; No exception code in firmware - -fno-exceptions - -lstdc++ -; Exception code in firmware /needs much space! 90k -; -fexceptions -; -lstdc++-exc - -[core_stage] -; *** Esp8266 core for Arduino version latest beta -platform = https://github.com/platformio/platform-espressif8266.git#feature/stage -build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Teagle.flash.1m.ld - -DBEARSSL_SSL_BASIC -; NONOSDK221 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 -; NONOSDK22x_190313 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 -; NONOSDK22x_190703 (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 -; NONOSDK22x_191024 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 -; NONOSDK22x_191105 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 -; NONOSDK3V0 (known issues) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 -; lwIP 1.4 -; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH -; lwIP 2 - Low Memory -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY -; lwIP 2 - Higher Bandwidth -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH -; lwIP 2 - Higher Bandwidth Low Memory no Features -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH -; lwIP 2 - Higher Bandwidth no Features (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH -; VTABLES in Flash (Tasmota default) - -DVTABLES_IN_FLASH -; VTABLES in Heap -; -DVTABLES_IN_DRAM -; VTABLES in IRAM -; -DVTABLES_IN_IRAM -; enable one option set -> No exception recommended -; No exception code in firmware - -fno-exceptions - -lstdc++ -; Exception code in firmware /needs much space! 90k -; -fexceptions -; -lstdc++-exc [env:tasmota] platform = ${common.platform} @@ -258,22 +122,6 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = ${common.upload_speed} extra_scripts = ${common.extra_scripts} -; *** Debug version used for PlatformIO Home Project Inspection -[env:tasmota-debug] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_type = debug -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - [env:tasmota-minimal] platform = ${common.platform} framework = ${common.framework} From 616b07cc01cabc9addcbb3421690d0684a16d9bb Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 29 Nov 2019 12:45:10 +0100 Subject: [PATCH 10/50] delete --- platformio_override_sample.ini | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index c0313577e..f75e64544 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -6,9 +6,7 @@ ; **************************************************************** ; ; Please visit documentation for the options and examples -; http://docs.platformio.org/en/stable/projectconf.html -; - +; http://docs.platformio.org/en/stable/projectconf.htm [platformio] From f890014d8fad458d12a6a7e3e48d76bc96780976 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 29 Nov 2019 12:45:51 +0100 Subject: [PATCH 11/50] Delete platformio_override_sample.ini --- platformio_override_sample.ini | 221 --------------------------------- 1 file changed, 221 deletions(-) delete mode 100644 platformio_override_sample.ini diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini deleted file mode 100644 index f75e64544..000000000 --- a/platformio_override_sample.ini +++ /dev/null @@ -1,221 +0,0 @@ -; *** Example PlatformIO Project Configuration Override File *** -; *** Changes done here overrides settings in platformio.ini *** -; -; **************************************************************** -; *** to activate rename this fie to platformio_override.ini *** -; **************************************************************** -; -; Please visit documentation for the options and examples -; http://docs.platformio.org/en/stable/projectconf.htm - -[platformio] - -; *** Build/upload environment -default_envs = -; *** Uncomment the line(s) below to select version(s) - tasmota -; tasmota-debug -; tasmota-ircustom ; alternative to 'tasmota' with full IR protocols activated, you will need to disable some features to keep code not too big -; tasmota-minimal -; tasmota-basic -; tasmota-knx -; tasmota-sensors -; tasmota-display -; tasmota-ir - - -[common] -platform = ${core_active.platform} -build_flags = ${core_active.build_flags} -; *** Use settings from file user_config_override.h - -DUSE_CONFIG_OVERRIDE - -; *** Optional Firmware configurations -; -DFIRMWARE_MINIMAL -; -DFIRMWARE_SENSORS -; -DFIRMWARE_BASIC -; -DFIRMWARE_KNX_NO_EMULATION -; -DFIRMWARE_DISPLAYS -; -DFIRMWARE_IR -; -DFIRMWARE_IR_CUSTOM - -; *** Optional Debug messages -; -DDEBUG_TASMOTA_CORE -; -DDEBUG_TASMOTA_DRIVER -; -DDEBUG_TASMOTA_SENSOR - -; set CPU frequency to 80MHz (default) or 160MHz -;board_build.f_cpu = 160000000L - -; *** Upload Serial reset method for Wemos and NodeMCU -upload_port = COM5 - -extra_scripts = ${scripts_defaults.extra_scripts} - pio/obj-dump.py - -; *** Upload file to OTA server using SCP -;upload_port = user@host:/path -;extra_scripts = ${scripts_defaults.extra_scripts} -; pio/strip-floats.py, pio/sftp-uploader.py - -; *** Upload file to OTA server in folder api/arduino using HTTP -;upload_port = domus1:80/api/upload-arduino.php -;extra_scripts = ${scripts_defaults.extra_scripts} -; pio/strip-floats.py, pio/http-uploader.py - -[core_active] -; Select one core set for platform and build_flags -platform = ${core_2_6_1.platform} -build_flags = ${core_2_6_1.build_flags} -;platform = ${core_2_6_2.platform} -;build_flags = ${core_2_6_2.build_flags} -;platform = ${core_stage.platform} -;build_flags = ${core_stage.build_flags} - - -[core_2_6_1] -; *** Esp8266 core for Arduino version 2.6.1 -platform = espressif8266@2.3.0 -build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Teagle.flash.1m.ld - -DBEARSSL_SSL_BASIC -; NONOSDK221 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 -; NONOSDK22x_190313 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 -; NONOSDK22x_190703 = 2.2.2-dev(38a443e) (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 -; NONOSDK22x_191024 = 2.2.2-dev(5ab15d1) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 -; NONOSDK22x_191105 = 2.2.2-dev(bb83b9b) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 -; NONOSDK3V0 (known issues) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 -; lwIP 1.4 -; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH -; lwIP 2 - Low Memory -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY -; lwIP 2 - Higher Bandwidth -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH -; lwIP 2 - Higher Bandwidth Low Memory no Features -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH -; lwIP 2 - Higher Bandwidth no Features (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH -; lwIP 2 - Higher Bandwidth IPv6 (use ONLY if you need IPv6, experimental!) -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_HIGHER_BANDWIDTH -; VTABLES in Flash (Tasmota default) - -DVTABLES_IN_FLASH -; VTABLES in Heap -; -DVTABLES_IN_DRAM -; VTABLES in IRAM -; -DVTABLES_IN_IRAM -; enable one option set -> No exception recommended -; No exception code in firmware - -fno-exceptions - -lstdc++ -; Exception code in firmware /needs much space! 90k -; -fexceptions -; -lstdc++-exc - -[core_2_6_2] -; *** Esp8266 core for Arduino version 2.6.2 -platform = espressif8266@2.3.1 -build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Teagle.flash.1m.ld - -DBEARSSL_SSL_BASIC -; NONOSDK221 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 -; NONOSDK22x_190313 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 -; NONOSDK22x_190703 = 2.2.2-dev(38a443e) (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 -; NONOSDK22x_191024 = 2.2.2-dev(5ab15d1) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 -; NONOSDK22x_191105 = 2.2.2-dev(bb83b9b) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 -; NONOSDK3V0 (known issues) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 -; lwIP 1.4 -; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH -; lwIP 2 - Low Memory -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY -; lwIP 2 - Higher Bandwidth -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH -; lwIP 2 - Higher Bandwidth Low Memory no Features -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH -; lwIP 2 - Higher Bandwidth no Features (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH -; lwIP 2 - Higher Bandwidth IPv6 (use ONLY if you need IPv6, experimental!) -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_HIGHER_BANDWIDTH -; VTABLES in Flash (Tasmota default) - -DVTABLES_IN_FLASH -; VTABLES in Heap -; -DVTABLES_IN_DRAM -; VTABLES in IRAM -; -DVTABLES_IN_IRAM -; enable one option set -> No exception recommended -; No exception code in firmware - -fno-exceptions - -lstdc++ -; Exception code in firmware /needs much space! 90k -; -fexceptions -; -lstdc++-exc - -[core_stage] -; *** Esp8266 core for Arduino version latest beta -platform = https://github.com/platformio/platform-espressif8266.git#feature/stage -build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Teagle.flash.1m.ld - -DBEARSSL_SSL_BASIC -; NONOSDK221 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 -; NONOSDK22x_190313 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 -; NONOSDK22x_190703 (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 -; NONOSDK22x_191024 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 -; NONOSDK22x_191105 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 -; NONOSDK3V0 (known issues) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 -; lwIP 1.4 -; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH -; lwIP 2 - Low Memory -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY -; lwIP 2 - Higher Bandwidth -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH -; lwIP 2 - Higher Bandwidth Low Memory no Features -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH -; lwIP 2 - Higher Bandwidth no Features (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH -; VTABLES in Flash (Tasmota default) - -DVTABLES_IN_FLASH -; VTABLES in Heap -; -DVTABLES_IN_DRAM -; VTABLES in IRAM -; -DVTABLES_IN_IRAM -; enable one option set -> No exception recommended -; No exception code in firmware - -fno-exceptions - -lstdc++ -; Exception code in firmware /needs much space! 90k -; -fexceptions -; -lstdc++-exc - - -; *** Debug version used for PlatformIO Home Project Inspection -[env:tasmota-debug] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_type = debug -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} From 6f57c30c92e1692bada599cb81bb0dd04d918da0 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 29 Nov 2019 12:46:16 +0100 Subject: [PATCH 12/50] Add files via upload --- platformio.ini | 418 +------------------------------------------------ 1 file changed, 6 insertions(+), 412 deletions(-) diff --git a/platformio.ini b/platformio.ini index 838354a84..5db6b8ed0 100755 --- a/platformio.ini +++ b/platformio.ini @@ -11,7 +11,8 @@ src_dir = tasmota build_dir = .pioenvs build_cache_dir = .cache -extra_configs = platformio_override.ini +extra_configs = pio/tasmota_env.ini + pio/platformio_override.ini ; *** Build/upload environment default_envs = @@ -46,8 +47,8 @@ default_envs = ; tasmota-TW ; tasmota-UK ; -; *** alternatively can be done in file: platformio_override.ini -; *** See example: platformio_override_sample.ini +; *** alternatively can be done in: pio/platformio_override.ini +; *** See example: platformio_override_sample.ini in folder pio ; ********************************************************************* @@ -63,8 +64,8 @@ build_flags = ${core_active.build_flags} ; *** Uncomment, by deleting ";" in line below, to use custom settings from file user_config_override.h ; -DUSE_CONFIG_OVERRIDE ; -; *** alternatively can be done in: platformio_override.ini -; *** See example: platformio_override_sample.ini +; *** alternatively can be done in: pio/platformio_override.ini +; *** See example: platformio_override_sample.ini in folder pio ; ********************************************************************* ; *** Fix espressif8266@1.7.0 induced undesired all warnings @@ -106,410 +107,3 @@ build_flags = ${esp82xx_defaults.build_flags} ; No exception code in firmware -fno-exceptions -lstdc++ - - -[env:tasmota] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-minimal] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DFIRMWARE_MINIMAL -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-basic] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DFIRMWARE_BASIC -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-knx] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DFIRMWARE_KNX_NO_EMULATION -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-sensors] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DFIRMWARE_SENSORS -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-display] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DFIRMWARE_DISPLAYS -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-ir] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DUSE_IR_REMOTE_FULL -DFIRMWARE_IR -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-ircustom] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DUSE_IR_REMOTE_FULL -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-BG] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=bg-BG -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-BR] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=pt-BR -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-CN] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=zh-CN -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-CZ] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=cs-CZ -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-DE] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=de-DE -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-ES] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=es-ES -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-FR] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=fr-FR -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-GR] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=el-GR -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-HE] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=he-HE -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-HU] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=hu-HU -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-IT] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=it-IT -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-KO] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=ko-KO -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-NL] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=nl-NL -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-PL] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=pl-PL -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-PT] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=pt-PT -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-RU] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=ru-RU -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-SE] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=sv-SE -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-SK] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=sk-SK -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-TR] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=tr-TR -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-TW] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=zh-TW -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota-UK] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=uk-UK -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} From c3d59e920474dbe97bdb233a0ba42c3739213f8a Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 29 Nov 2019 12:46:59 +0100 Subject: [PATCH 13/50] Add files via upload --- pio/platformio_override_sample.ini | 211 +++++++++++++++++++++++++++++ pio/tasmota_env.ini | 99 ++++++++++++++ 2 files changed, 310 insertions(+) create mode 100644 pio/platformio_override_sample.ini create mode 100644 pio/tasmota_env.ini diff --git a/pio/platformio_override_sample.ini b/pio/platformio_override_sample.ini new file mode 100644 index 000000000..d94903d0e --- /dev/null +++ b/pio/platformio_override_sample.ini @@ -0,0 +1,211 @@ +; *** Example PlatformIO Project Configuration Override File *** +; *** Changes done here overrides settings in platformio.ini *** +; +; **************************************************************** +; *** to activate rename this fie to platformio_override.ini *** +; **************************************************************** +; +; Please visit documentation for the options and examples +; http://docs.platformio.org/en/stable/projectconf.html +; + + +[platformio] + +; *** Build/upload environment +default_envs = +; *** Uncomment the line(s) below to select version(s) + tasmota +; tasmota-debug +; tasmota-ircustom ; alternative to 'tasmota' with full IR protocols activated, you will need to disable some features to keep code not too big +; tasmota-minimal +; tasmota-basic +; tasmota-knx +; tasmota-sensors +; tasmota-display +; tasmota-ir + + +[common] +platform = ${core_active.platform} +build_flags = ${core_active.build_flags} +; *** Use settings from file user_config_override.h + -DUSE_CONFIG_OVERRIDE + +; *** Optional Firmware configurations +; -DFIRMWARE_MINIMAL +; -DFIRMWARE_SENSORS +; -DFIRMWARE_BASIC +; -DFIRMWARE_KNX_NO_EMULATION +; -DFIRMWARE_DISPLAYS +; -DFIRMWARE_IR +; -DFIRMWARE_IR_CUSTOM + +; *** Optional Debug messages +; -DDEBUG_TASMOTA_CORE +; -DDEBUG_TASMOTA_DRIVER +; -DDEBUG_TASMOTA_SENSOR + +; set CPU frequency to 80MHz (default) or 160MHz +;board_build.f_cpu = 160000000L + +; *** Upload Serial reset method for Wemos and NodeMCU +upload_port = COM5 + +extra_scripts = ${scripts_defaults.extra_scripts} + pio/obj-dump.py + +; *** Upload file to OTA server using SCP +;upload_port = user@host:/path +;extra_scripts = ${scripts_defaults.extra_scripts} +; pio/strip-floats.py, pio/sftp-uploader.py + +; *** Upload file to OTA server in folder api/arduino using HTTP +;upload_port = domus1:80/api/upload-arduino.php +;extra_scripts = ${scripts_defaults.extra_scripts} +; pio/strip-floats.py, pio/http-uploader.py + +[core_active] +; Select one core set for platform and build_flags +platform = ${core_2_6_1.platform} +build_flags = ${core_2_6_1.build_flags} +;platform = ${core_2_6_2.platform} +;build_flags = ${core_2_6_2.build_flags} +;platform = ${core_stage.platform} +;build_flags = ${core_stage.build_flags} + + +[core_2_6_1] +; *** Esp8266 core for Arduino version 2.6.1 +platform = espressif8266@2.3.0 +build_flags = ${esp82xx_defaults.build_flags} + -Wl,-Teagle.flash.1m.ld + -DBEARSSL_SSL_BASIC +; NONOSDK221 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 +; NONOSDK22x_190313 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 +; NONOSDK22x_190703 = 2.2.2-dev(38a443e) (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 +; NONOSDK22x_191024 = 2.2.2-dev(5ab15d1) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 +; NONOSDK22x_191105 = 2.2.2-dev(bb83b9b) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 +; NONOSDK3V0 (known issues) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 +; lwIP 1.4 +; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH +; lwIP 2 - Low Memory +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY +; lwIP 2 - Higher Bandwidth +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH +; lwIP 2 - Higher Bandwidth Low Memory no Features +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH +; lwIP 2 - Higher Bandwidth no Features (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH +; lwIP 2 - Higher Bandwidth IPv6 (use ONLY if you need IPv6, experimental!) +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_HIGHER_BANDWIDTH +; VTABLES in Flash (Tasmota default) + -DVTABLES_IN_FLASH +; VTABLES in Heap +; -DVTABLES_IN_DRAM +; VTABLES in IRAM +; -DVTABLES_IN_IRAM +; enable one option set -> No exception recommended +; No exception code in firmware + -fno-exceptions + -lstdc++ +; Exception code in firmware /needs much space! 90k +; -fexceptions +; -lstdc++-exc + +[core_2_6_2] +; *** Esp8266 core for Arduino version 2.6.2 +platform = espressif8266@2.3.1 +build_flags = ${esp82xx_defaults.build_flags} + -Wl,-Teagle.flash.1m.ld + -DBEARSSL_SSL_BASIC +; NONOSDK221 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 +; NONOSDK22x_190313 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 +; NONOSDK22x_190703 = 2.2.2-dev(38a443e) (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 +; NONOSDK22x_191024 = 2.2.2-dev(5ab15d1) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 +; NONOSDK22x_191105 = 2.2.2-dev(bb83b9b) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 +; NONOSDK3V0 (known issues) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 +; lwIP 1.4 +; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH +; lwIP 2 - Low Memory +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY +; lwIP 2 - Higher Bandwidth +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH +; lwIP 2 - Higher Bandwidth Low Memory no Features +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH +; lwIP 2 - Higher Bandwidth no Features (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH +; lwIP 2 - Higher Bandwidth IPv6 (use ONLY if you need IPv6, experimental!) +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_HIGHER_BANDWIDTH +; VTABLES in Flash (Tasmota default) + -DVTABLES_IN_FLASH +; VTABLES in Heap +; -DVTABLES_IN_DRAM +; VTABLES in IRAM +; -DVTABLES_IN_IRAM +; enable one option set -> No exception recommended +; No exception code in firmware + -fno-exceptions + -lstdc++ +; Exception code in firmware /needs much space! 90k +; -fexceptions +; -lstdc++-exc + +[core_stage] +; *** Esp8266 core for Arduino version latest beta +platform = https://github.com/platformio/platform-espressif8266.git#feature/stage +build_flags = ${esp82xx_defaults.build_flags} + -Wl,-Teagle.flash.1m.ld + -DBEARSSL_SSL_BASIC +; NONOSDK221 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 +; NONOSDK22x_190313 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 +; NONOSDK22x_190703 (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 +; NONOSDK22x_191024 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 +; NONOSDK22x_191105 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 +; NONOSDK3V0 (known issues) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 +; lwIP 1.4 +; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH +; lwIP 2 - Low Memory +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY +; lwIP 2 - Higher Bandwidth +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH +; lwIP 2 - Higher Bandwidth Low Memory no Features +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH +; lwIP 2 - Higher Bandwidth no Features (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH +; VTABLES in Flash (Tasmota default) + -DVTABLES_IN_FLASH +; VTABLES in Heap +; -DVTABLES_IN_DRAM +; VTABLES in IRAM +; -DVTABLES_IN_IRAM +; enable one option set -> No exception recommended +; No exception code in firmware + -fno-exceptions + -lstdc++ +; Exception code in firmware /needs much space! 90k +; -fexceptions +; -lstdc++-exc + + +; *** Debug version used for PlatformIO Home Project Inspection +[env:tasmota-debug] +build_type = debug diff --git a/pio/tasmota_env.ini b/pio/tasmota_env.ini new file mode 100644 index 000000000..46e71d7af --- /dev/null +++ b/pio/tasmota_env.ini @@ -0,0 +1,99 @@ +[env] +platform = ${common.platform} +framework = ${common.framework} +board = ${common.board} +board_build.flash_mode = ${common.board_build.flash_mode} +board_build.f_cpu = ${common.board_build.f_cpu} +build_unflags = ${common.build_unflags} +build_flags = ${common.build_flags} +monitor_speed = ${common.monitor_speed} +upload_port = ${common.upload_port} +upload_resetmethod = ${common.upload_resetmethod} +upload_speed = ${common.upload_speed} +extra_scripts = ${common.extra_scripts} + +[env:tasmota] + +[env:tasmota-minimal] +build_flags = ${common.build_flags} -DFIRMWARE_MINIMAL + +[env:tasmota-basic] +build_flags = ${common.build_flags} -DFIRMWARE_BASIC + +[env:tasmota-knx] +build_flags = ${common.build_flags} -DFIRMWARE_KNX_NO_EMULATION + +[env:tasmota-sensors] +build_flags = ${common.build_flags} -DFIRMWARE_SENSORS + +[env:tasmota-display] +build_flags = ${common.build_flags} -DFIRMWARE_DISPLAYS + +[env:tasmota-ir] +build_flags = ${common.build_flags} -DUSE_IR_REMOTE_FULL -DFIRMWARE_IR + +[env:tasmota-ircustom] +build_flags = ${common.build_flags} -DUSE_IR_REMOTE_FULL + +[env:tasmota-BG] +build_flags = ${common.build_flags} -DMY_LANGUAGE=bg-BG + +[env:tasmota-BR] +build_flags = ${common.build_flags} -DMY_LANGUAGE=pt-BR + +[env:tasmota-CN] +build_flags = ${common.build_flags} -DMY_LANGUAGE=zh-CN + +[env:tasmota-CZ] +build_flags = ${common.build_flags} -DMY_LANGUAGE=cs-CZ + +[env:tasmota-DE] +build_flags = ${common.build_flags} -DMY_LANGUAGE=de-DE + +[env:tasmota-ES] +build_flags = ${common.build_flags} -DMY_LANGUAGE=es-ES + +[env:tasmota-FR] +build_flags = ${common.build_flags} -DMY_LANGUAGE=fr-FR + +[env:tasmota-GR] +build_flags = ${common.build_flags} -DMY_LANGUAGE=el-GR + +[env:tasmota-HE] +build_flags = ${common.build_flags} -DMY_LANGUAGE=he-HE + +[env:tasmota-HU] +build_flags = ${common.build_flags} -DMY_LANGUAGE=hu-HU + +[env:tasmota-IT] +build_flags = ${common.build_flags} -DMY_LANGUAGE=it-IT + +[env:tasmota-KO] +build_flags = ${common.build_flags} -DMY_LANGUAGE=ko-KO + +[env:tasmota-NL] +build_flags = ${common.build_flags} -DMY_LANGUAGE=nl-NL + +[env:tasmota-PL] +build_flags = ${common.build_flags} -DMY_LANGUAGE=pl-PL + +[env:tasmota-PT] +build_flags = ${common.build_flags} -DMY_LANGUAGE=pt-PT + +[env:tasmota-RU] +build_flags = ${common.build_flags} -DMY_LANGUAGE=ru-RU + +[env:tasmota-SE] +build_flags = ${common.build_flags} -DMY_LANGUAGE=sv-SE + +[env:tasmota-SK] +build_flags = ${common.build_flags} -DMY_LANGUAGE=sk-SK + +[env:tasmota-TR] +build_flags = ${common.build_flags} -DMY_LANGUAGE=tr-TR + +[env:tasmota-TW] +build_flags = ${common.build_flags} -DMY_LANGUAGE=zh-TW + +[env:tasmota-UK] +build_flags = ${common.build_flags} -DMY_LANGUAGE=uk-UK From ac065867d3c5bd992405190cb9cac9a41df652f7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 29 Nov 2019 13:11:35 +0100 Subject: [PATCH 14/50] Add command ``SetOption77 0/1`` Add command ``SetOption77 0/1`` to keep power on when slider is far left --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + tasmota/settings.h | 2 +- tasmota/xdrv_01_webserver.ino | 2 +- tools/decode-status.py | 3 ++- 5 files changed, 6 insertions(+), 3 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index afb4c18ee..a46f2bd46 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -155,6 +155,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add command ``SetOption74 0/1`` to enable DS18x20 internal pull-up and remove define DS18B20_INTERNAL_PULLUP (#6795) - Add command ``SetOption75 0/1`` to switch between grouptopic (0) using fulltopic replacing %topic% or (1) is cmnd/\ (#6779) - Add command ``SetOption76 0/1`` to enable incrementing bootcount when deepsleep is enabled (#6930) +- Add command ``SetOption77 0/1`` to keep power on when slider is far left - Add command ``I2cDriver`` for I2C driver runtime control using document I2CDEVICES.md - Add command ``TempOffset -12.6 .. 12.6`` to set global temperature sensor offset (#6958) - Add command ``WebColor19`` to control color of Module and Name (#6811) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 5c7202aae..2ab00d9ba 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -8,6 +8,7 @@ - Change update lib IRremoteESP8266 updated to v2.7.1, -2.7k flash and -1.5k RAM for Tasmota-IR - Fix auto--power on/off when setting channel to non-zero or zero value, when SetOption68 1 - Fix postpone saving settings to flash until Fade is complete, avoids pause in Fade +- Add command ``SetOption77 0/1`` to keep power on when slider is far left ### 7.0.0.5 20191118 diff --git a/tasmota/settings.h b/tasmota/settings.h index 876e0bde5..554711cad 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -90,7 +90,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t ds18x20_internal_pullup : 1; // bit 24 (v7.0.0.1) - SetOption74 - Enable internal pullup for single DS18x20 sensor uint32_t grouptopic_mode : 1; // bit 25 (v7.0.0.1) - SetOption75 - GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1) uint32_t bootcount_update : 1; // bit 26 (v7.0.0.4) - SetOption76 - Enable incrementing bootcount when deepsleep is enabled - uint32_t spare27 : 1; + uint32_t slider_dimmer_stay_on : 1; // bit 27 (v7.0.0.6) - SetOption77 - Do not power off if slider moved to far left uint32_t spare28 : 1; uint32_t spare29 : 1; uint32_t shutter_mode : 1; // bit 30 (v6.6.0.14) - SetOption80 - Enable shutter support diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index e5d8aecfe..42630b8ba 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1065,7 +1065,7 @@ void HandleRoot(void) "c", // c - Unique HTML id "#000", "#fff", // Black to White 4, // sl4 - Unique range HTML id - Used as source for Saturation begin color - 0, 100, // Range 0 to 100% + Settings.flag3.slider_dimmer_stay_on, 100, // Range 0/1 to 100% Settings.light_dimmer, 'd', 0); // d0 - Value id is related to lc("d0", value) and WebGetArg("d0", tmp, sizeof(tmp)); } else { // Settings.flag3.pwm_multi_channels - SetOption68 1 - Enable multi-channels PWM instead of Color PWM diff --git a/tools/decode-status.py b/tools/decode-status.py index 5b5c3df98..be79cf921 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -129,7 +129,8 @@ a_setoption = [[ "Enable HTTP CORS", "Enable internal pullup for single DS18x20 sensor", "GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1)", - "","", + "Enable incrementing bootcount when deepsleep is enabled", + "Do not power off if slider moved to far left", "","", "Enable shutter support", "Invert PCF8574 ports" From 100ac8a75e7a87c5c971071b91a6f5ee30444b75 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 29 Nov 2019 14:40:11 +0100 Subject: [PATCH 15/50] Move ENVs back in platformio.ini... since the idea to have 3 files for setting up was not liked at all. --- platformio.ini | 103 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 5db6b8ed0..a1c604735 100755 --- a/platformio.ini +++ b/platformio.ini @@ -11,8 +11,7 @@ src_dir = tasmota build_dir = .pioenvs build_cache_dir = .cache -extra_configs = pio/tasmota_env.ini - pio/platformio_override.ini +extra_configs = pio/platformio_override.ini ; *** Build/upload environment default_envs = @@ -107,3 +106,103 @@ build_flags = ${esp82xx_defaults.build_flags} ; No exception code in firmware -fno-exceptions -lstdc++ + +[env] +platform = ${common.platform} +framework = ${common.framework} +board = ${common.board} +board_build.flash_mode = ${common.board_build.flash_mode} +board_build.f_cpu = ${common.board_build.f_cpu} +build_unflags = ${common.build_unflags} +build_flags = ${common.build_flags} +monitor_speed = ${common.monitor_speed} +upload_port = ${common.upload_port} +upload_resetmethod = ${common.upload_resetmethod} +upload_speed = ${common.upload_speed} +extra_scripts = ${common.extra_scripts} + +[env:tasmota] + +[env:tasmota-minimal] +build_flags = ${common.build_flags} -DFIRMWARE_MINIMAL + +[env:tasmota-basic] +build_flags = ${common.build_flags} -DFIRMWARE_BASIC + +[env:tasmota-knx] +build_flags = ${common.build_flags} -DFIRMWARE_KNX_NO_EMULATION + +[env:tasmota-sensors] +build_flags = ${common.build_flags} -DFIRMWARE_SENSORS + +[env:tasmota-display] +build_flags = ${common.build_flags} -DFIRMWARE_DISPLAYS + +[env:tasmota-ir] +build_flags = ${common.build_flags} -DUSE_IR_REMOTE_FULL -DFIRMWARE_IR + +[env:tasmota-ircustom] +build_flags = ${common.build_flags} -DUSE_IR_REMOTE_FULL + +[env:tasmota-BG] +build_flags = ${common.build_flags} -DMY_LANGUAGE=bg-BG + +[env:tasmota-BR] +build_flags = ${common.build_flags} -DMY_LANGUAGE=pt-BR + +[env:tasmota-CN] +build_flags = ${common.build_flags} -DMY_LANGUAGE=zh-CN + +[env:tasmota-CZ] +build_flags = ${common.build_flags} -DMY_LANGUAGE=cs-CZ + +[env:tasmota-DE] +build_flags = ${common.build_flags} -DMY_LANGUAGE=de-DE + +[env:tasmota-ES] +build_flags = ${common.build_flags} -DMY_LANGUAGE=es-ES + +[env:tasmota-FR] +build_flags = ${common.build_flags} -DMY_LANGUAGE=fr-FR + +[env:tasmota-GR] +build_flags = ${common.build_flags} -DMY_LANGUAGE=el-GR + +[env:tasmota-HE] +build_flags = ${common.build_flags} -DMY_LANGUAGE=he-HE + +[env:tasmota-HU] +build_flags = ${common.build_flags} -DMY_LANGUAGE=hu-HU + +[env:tasmota-IT] +build_flags = ${common.build_flags} -DMY_LANGUAGE=it-IT + +[env:tasmota-KO] +build_flags = ${common.build_flags} -DMY_LANGUAGE=ko-KO + +[env:tasmota-NL] +build_flags = ${common.build_flags} -DMY_LANGUAGE=nl-NL + +[env:tasmota-PL] +build_flags = ${common.build_flags} -DMY_LANGUAGE=pl-PL + +[env:tasmota-PT] +build_flags = ${common.build_flags} -DMY_LANGUAGE=pt-PT + +[env:tasmota-RU] +build_flags = ${common.build_flags} -DMY_LANGUAGE=ru-RU + +[env:tasmota-SE] +build_flags = ${common.build_flags} -DMY_LANGUAGE=sv-SE + +[env:tasmota-SK] +build_flags = ${common.build_flags} -DMY_LANGUAGE=sk-SK + +[env:tasmota-TR] +build_flags = ${common.build_flags} -DMY_LANGUAGE=tr-TR + +[env:tasmota-TW] +build_flags = ${common.build_flags} -DMY_LANGUAGE=zh-TW + +[env:tasmota-UK] +build_flags = ${common.build_flags} -DMY_LANGUAGE=uk-UK From b92a3c9764c645160981f6f157be3174630c63ee Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 29 Nov 2019 14:40:42 +0100 Subject: [PATCH 16/50] Delete tasmota_env.ini --- pio/tasmota_env.ini | 99 --------------------------------------------- 1 file changed, 99 deletions(-) delete mode 100644 pio/tasmota_env.ini diff --git a/pio/tasmota_env.ini b/pio/tasmota_env.ini deleted file mode 100644 index 46e71d7af..000000000 --- a/pio/tasmota_env.ini +++ /dev/null @@ -1,99 +0,0 @@ -[env] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota] - -[env:tasmota-minimal] -build_flags = ${common.build_flags} -DFIRMWARE_MINIMAL - -[env:tasmota-basic] -build_flags = ${common.build_flags} -DFIRMWARE_BASIC - -[env:tasmota-knx] -build_flags = ${common.build_flags} -DFIRMWARE_KNX_NO_EMULATION - -[env:tasmota-sensors] -build_flags = ${common.build_flags} -DFIRMWARE_SENSORS - -[env:tasmota-display] -build_flags = ${common.build_flags} -DFIRMWARE_DISPLAYS - -[env:tasmota-ir] -build_flags = ${common.build_flags} -DUSE_IR_REMOTE_FULL -DFIRMWARE_IR - -[env:tasmota-ircustom] -build_flags = ${common.build_flags} -DUSE_IR_REMOTE_FULL - -[env:tasmota-BG] -build_flags = ${common.build_flags} -DMY_LANGUAGE=bg-BG - -[env:tasmota-BR] -build_flags = ${common.build_flags} -DMY_LANGUAGE=pt-BR - -[env:tasmota-CN] -build_flags = ${common.build_flags} -DMY_LANGUAGE=zh-CN - -[env:tasmota-CZ] -build_flags = ${common.build_flags} -DMY_LANGUAGE=cs-CZ - -[env:tasmota-DE] -build_flags = ${common.build_flags} -DMY_LANGUAGE=de-DE - -[env:tasmota-ES] -build_flags = ${common.build_flags} -DMY_LANGUAGE=es-ES - -[env:tasmota-FR] -build_flags = ${common.build_flags} -DMY_LANGUAGE=fr-FR - -[env:tasmota-GR] -build_flags = ${common.build_flags} -DMY_LANGUAGE=el-GR - -[env:tasmota-HE] -build_flags = ${common.build_flags} -DMY_LANGUAGE=he-HE - -[env:tasmota-HU] -build_flags = ${common.build_flags} -DMY_LANGUAGE=hu-HU - -[env:tasmota-IT] -build_flags = ${common.build_flags} -DMY_LANGUAGE=it-IT - -[env:tasmota-KO] -build_flags = ${common.build_flags} -DMY_LANGUAGE=ko-KO - -[env:tasmota-NL] -build_flags = ${common.build_flags} -DMY_LANGUAGE=nl-NL - -[env:tasmota-PL] -build_flags = ${common.build_flags} -DMY_LANGUAGE=pl-PL - -[env:tasmota-PT] -build_flags = ${common.build_flags} -DMY_LANGUAGE=pt-PT - -[env:tasmota-RU] -build_flags = ${common.build_flags} -DMY_LANGUAGE=ru-RU - -[env:tasmota-SE] -build_flags = ${common.build_flags} -DMY_LANGUAGE=sv-SE - -[env:tasmota-SK] -build_flags = ${common.build_flags} -DMY_LANGUAGE=sk-SK - -[env:tasmota-TR] -build_flags = ${common.build_flags} -DMY_LANGUAGE=tr-TR - -[env:tasmota-TW] -build_flags = ${common.build_flags} -DMY_LANGUAGE=zh-TW - -[env:tasmota-UK] -build_flags = ${common.build_flags} -DMY_LANGUAGE=uk-UK From 3ab7d8306108e39ec0f27aad09400bcb3dd63f29 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 29 Nov 2019 14:52:17 +0100 Subject: [PATCH 17/50] Add files via upload --- platformio_override.ini | 277 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 platformio_override.ini diff --git a/platformio_override.ini b/platformio_override.ini new file mode 100644 index 000000000..ca6f80845 --- /dev/null +++ b/platformio_override.ini @@ -0,0 +1,277 @@ +[platformio] + +; *** Build/upload environment +default_envs = +; *** Uncomment the line(s) below to select version(s) + tasmota +; tasmota-debug +; tasmota-ircustom ; alternative to 'tasmota' with full IR protocols activated, you will need to disable some features to keep code not too big +; tasmota-minimal +; tasmota-basic +; tasmota-knx +; tasmota-sensors +; tasmota-display +; tasmota-ir + + +[common] +platform = ${core_active.platform} +platform_packages = ${core_active.platform_packages} +build_flags = ${core_active.build_flags} + + -DUSE_CONFIG_OVERRIDE + +; *** Optional Firmware configurations +; -DFIRMWARE_MINIMAL +; -DFIRMWARE_SENSORS +; -DFIRMWARE_BASIC +; -DFIRMWARE_KNX_NO_EMULATION +; -DFIRMWARE_DISPLAYS +; -DFIRMWARE_IR +; -DFIRMWARE_IR_CUSTOM + +; *** Optional Debug messages +; -DDEBUG_TASMOTA_CORE +; -DDEBUG_TASMOTA_DRIVER +; -DDEBUG_TASMOTA_SENSOR + +; set CPU frequency to 80MHz (default) or 160MHz +;board_build.f_cpu = 160000000L + +; *** Upload Serial reset method for Wemos and NodeMCU +upload_port = COM5 + +extra_scripts = ${scripts_defaults.extra_scripts} +; pio/obj-dump.py + +; *** Upload file to OTA server using SCP +;upload_port = user@host:/path +;extra_scripts = ${scripts_defaults.extra_scripts} +; pio/strip-floats.py, pio/sftp-uploader.py + +; *** Upload file to OTA server in folder api/arduino using HTTP +;upload_port = domus1:80/api/upload-arduino.php +;extra_scripts = ${scripts_defaults.extra_scripts} +; pio/strip-floats.py, pio/http-uploader.py + +[core_active] +; Select one core set for platform and build_flags + +;platform = ${core_2_3_0.platform} +;build_flags = ${core_2_3_0.build_flags} + +;platform = ${core_2_4_2.platform} +;build_flags = ${core_2_4_2.build_flags} + +platform = ${core_2_6_1.platform} +build_flags = ${core_2_6_1.build_flags} + +;platform = ${core_2_6_2.platform} +;build_flags = ${core_2_6_2.build_flags} + +;platform = ${core_stage.platform} +;build_flags = ${core_stage.build_flags} +;platform_packages = ${core_stage.platform_packages} + +;platform = ${core_cstage.platform} +;build_flags = ${core_cstage.build_flags} + + + +[core_2_3_0] +; *** Esp8266 core for Arduino version 2.3.0 +platform = espressif8266@~1.5.0 +build_flags = ${esp82xx_defaults.build_flags} + -Wl,-Tesp8266.flash.1m0.ld + +[core_2_4_2] +; *** Esp8266 core for Arduino version 2.4.2 +platform = espressif8266@~1.8.0 +build_flags = ${esp82xx_defaults.build_flags} + -Wl,-Teagle.flash.1m0.ld + -lstdc++ -lsupc++ +; link with an memory optimized version of lib_bearssl + -Llib_bearssl -lbearssl +; lwIP 1.4 +; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH +; lwIP 2 - Low Memory +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY +; lwIP 2 - Higher Bandwidth (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH + -DVTABLES_IN_FLASH + +[core_2_6_1] +; *** Esp8266 core for Arduino version 2.6.1 +;platform = https://github.com/Jason2866/platform-espressif8266.git#new_gcc +platform = espressif8266@2.3.0 +build_flags = ${esp82xx_defaults.build_flags} + -Wl,-Teagle.flash.1m.ld + -DBEARSSL_SSL_BASIC +; NONOSDK221 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 +; NONOSDK22x_190313 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 +; NONOSDK22x_190703 (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 +; NONOSDK22x_191024 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 +; NONOSDK22x_191105 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 +; NONOSDK3V0 (known issues) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 +; lwIP 1.4 +; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH +; lwIP 2 - Low Memory +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY +; lwIP 2 - Higher Bandwidth +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH +; lwIP 2 - Higher Bandwidth Low Memory no Features +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH +; lwIP 2 - Higher Bandwidth no Features (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH +; VTABLES in Flash (Tasmota default) + -DVTABLES_IN_FLASH +; VTABLES in Heap +; -DVTABLES_IN_DRAM +; VTABLES in IRAM +; -DVTABLES_IN_IRAM +; enable one option set -> No exception recommended +; No exception code in firmware + -fno-exceptions + -lstdc++ +; Exception code in firmware /needs much space! 90k +; -fexceptions +; -lstdc++-exc + +[core_2_6_2] +; *** Esp8266 core for Arduino version 2.6.2 +platform = espressif8266@2.3.1 +build_flags = ${esp82xx_defaults.build_flags} + -Wl,-Teagle.flash.1m.ld + -DBEARSSL_SSL_BASIC +; NONOSDK221 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 +; NONOSDK22x_190313 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 +; NONOSDK22x_190703 (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 +; NONOSDK22x_191024 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 +; NONOSDK22x_191105 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 +; NONOSDK3V0 (known issues) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 +; lwIP 1.4 +; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH +; lwIP 2 - Low Memory +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY +; lwIP 2 - Higher Bandwidth +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH +; lwIP 2 - Higher Bandwidth Low Memory no Features +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH +; lwIP 2 - Higher Bandwidth no Features (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH +; VTABLES in Flash (Tasmota default) + -DVTABLES_IN_FLASH +; VTABLES in Heap +; -DVTABLES_IN_DRAM +; VTABLES in IRAM +; -DVTABLES_IN_IRAM +; enable one option set -> No exception recommended +; No exception code in firmware + -fno-exceptions + -lstdc++ +; Exception code in firmware /needs much space! 90k +; -fexceptions +; -lstdc++-exc + +[core_stage] +; *** Esp8266 core for Arduino version latest beta +platform = espressif8266 +platform_packages = + framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git +build_flags = ${esp82xx_defaults.build_flags} + -Wl,-Teagle.flash.1m.ld + -DBEARSSL_SSL_BASIC +; NONOSDK221 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 +; NONOSDK22x_190313 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 +; NONOSDK22x_190703 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 +; NONOSDK22x_191024 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 +; NONOSDK22x_191105 + -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 +; NONOSDK3V0 (known issues) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 +; lwIP 1.4 +; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH +; lwIP 2 - Low Memory +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY +; lwIP 2 - Higher Bandwidth +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH +; lwIP 2 - Higher Bandwidth Low Memory no Features +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH +; lwIP 2 - Higher Bandwidth no Features (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH +; VTABLES in Flash (Tasmota default) + -DVTABLES_IN_FLASH +; VTABLES in Heap +; -DVTABLES_IN_DRAM +; VTABLES in IRAM +; -DVTABLES_IN_IRAM +; enable one option set -> No exception recommended +; No exception code in firmware + -fno-exceptions + -lstdc++ +; Exception code in firmware /needs much space! 90k +; -fexceptions +; -lstdc++-exc + +[core_cstage] +; *** Arduino Esp8266 -> Wstring optimization +platform = https://github.com/Jason2866/platform-espressif8266.git#feature/stage +build_flags = ${esp82xx_defaults.build_flags} + -Wl,-Tesp8266.flash.1m.ld + -DBEARSSL_SSL_BASIC +; NONOSDK221 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 +; NONOSDK22x_190313 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 +; NONOSDK22x_190703 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 +; NONOSDK22x_191024 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 +; NONOSDK22x_191105 + -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 +; NONOSDK3V0 (known issues) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 +; lwIP 1.4 +; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH +; lwIP 2 - Low Memory +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY +; lwIP 2 - Higher Bandwidth +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH +; lwIP 2 - Higher Bandwidth Low Memory no Features +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH +; lwIP 2 - Higher Bandwidth no Features + -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH +; VTABLES in Flash (default) + -DVTABLES_IN_FLASH +; VTABLES in Heap +; -DVTABLES_IN_DRAM +; VTABLES in IRAM +; -DVTABLES_IN_IRAM +; enable one option set -> No exception recommended +; No exception code in firmware + -fno-exceptions + -lstdc++ +; Exception code in firmware /needs much space! 90k +; -fexceptions +; -lstdc++-exc + + +; *** Debug version used for PlatformIO Home Project Inspection +[env:tasmota-debug] +build_type = debug From 9de4ba1801269b164a985eccc31beb0c485f0c7e Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 29 Nov 2019 14:52:42 +0100 Subject: [PATCH 18/50] Update platformio.ini --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index a1c604735..e6b31968c 100755 --- a/platformio.ini +++ b/platformio.ini @@ -11,7 +11,7 @@ src_dir = tasmota build_dir = .pioenvs build_cache_dir = .cache -extra_configs = pio/platformio_override.ini +extra_configs = platformio_override.ini ; *** Build/upload environment default_envs = From 54ce44cc5e428db88df7e56804532f1bd24d2582 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 29 Nov 2019 14:57:11 +0100 Subject: [PATCH 19/50] Update platformio.ini --- platformio.ini | 103 +------------------------------------------------ 1 file changed, 2 insertions(+), 101 deletions(-) diff --git a/platformio.ini b/platformio.ini index e6b31968c..554c0d1eb 100755 --- a/platformio.ini +++ b/platformio.ini @@ -11,7 +11,8 @@ src_dir = tasmota build_dir = .pioenvs build_cache_dir = .cache -extra_configs = platformio_override.ini +extra_configs = platformio_tasmota_env.ini + platformio_override.ini ; *** Build/upload environment default_envs = @@ -106,103 +107,3 @@ build_flags = ${esp82xx_defaults.build_flags} ; No exception code in firmware -fno-exceptions -lstdc++ - -[env] -platform = ${common.platform} -framework = ${common.framework} -board = ${common.board} -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_cpu = ${common.board_build.f_cpu} -build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = ${common.upload_speed} -extra_scripts = ${common.extra_scripts} - -[env:tasmota] - -[env:tasmota-minimal] -build_flags = ${common.build_flags} -DFIRMWARE_MINIMAL - -[env:tasmota-basic] -build_flags = ${common.build_flags} -DFIRMWARE_BASIC - -[env:tasmota-knx] -build_flags = ${common.build_flags} -DFIRMWARE_KNX_NO_EMULATION - -[env:tasmota-sensors] -build_flags = ${common.build_flags} -DFIRMWARE_SENSORS - -[env:tasmota-display] -build_flags = ${common.build_flags} -DFIRMWARE_DISPLAYS - -[env:tasmota-ir] -build_flags = ${common.build_flags} -DUSE_IR_REMOTE_FULL -DFIRMWARE_IR - -[env:tasmota-ircustom] -build_flags = ${common.build_flags} -DUSE_IR_REMOTE_FULL - -[env:tasmota-BG] -build_flags = ${common.build_flags} -DMY_LANGUAGE=bg-BG - -[env:tasmota-BR] -build_flags = ${common.build_flags} -DMY_LANGUAGE=pt-BR - -[env:tasmota-CN] -build_flags = ${common.build_flags} -DMY_LANGUAGE=zh-CN - -[env:tasmota-CZ] -build_flags = ${common.build_flags} -DMY_LANGUAGE=cs-CZ - -[env:tasmota-DE] -build_flags = ${common.build_flags} -DMY_LANGUAGE=de-DE - -[env:tasmota-ES] -build_flags = ${common.build_flags} -DMY_LANGUAGE=es-ES - -[env:tasmota-FR] -build_flags = ${common.build_flags} -DMY_LANGUAGE=fr-FR - -[env:tasmota-GR] -build_flags = ${common.build_flags} -DMY_LANGUAGE=el-GR - -[env:tasmota-HE] -build_flags = ${common.build_flags} -DMY_LANGUAGE=he-HE - -[env:tasmota-HU] -build_flags = ${common.build_flags} -DMY_LANGUAGE=hu-HU - -[env:tasmota-IT] -build_flags = ${common.build_flags} -DMY_LANGUAGE=it-IT - -[env:tasmota-KO] -build_flags = ${common.build_flags} -DMY_LANGUAGE=ko-KO - -[env:tasmota-NL] -build_flags = ${common.build_flags} -DMY_LANGUAGE=nl-NL - -[env:tasmota-PL] -build_flags = ${common.build_flags} -DMY_LANGUAGE=pl-PL - -[env:tasmota-PT] -build_flags = ${common.build_flags} -DMY_LANGUAGE=pt-PT - -[env:tasmota-RU] -build_flags = ${common.build_flags} -DMY_LANGUAGE=ru-RU - -[env:tasmota-SE] -build_flags = ${common.build_flags} -DMY_LANGUAGE=sv-SE - -[env:tasmota-SK] -build_flags = ${common.build_flags} -DMY_LANGUAGE=sk-SK - -[env:tasmota-TR] -build_flags = ${common.build_flags} -DMY_LANGUAGE=tr-TR - -[env:tasmota-TW] -build_flags = ${common.build_flags} -DMY_LANGUAGE=zh-TW - -[env:tasmota-UK] -build_flags = ${common.build_flags} -DMY_LANGUAGE=uk-UK From 52f5bebd413827d0bf2c25f1e7f1f90e4213f767 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 29 Nov 2019 14:57:30 +0100 Subject: [PATCH 20/50] Add files via upload --- platformio_tasmota_env.ini | 99 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 platformio_tasmota_env.ini diff --git a/platformio_tasmota_env.ini b/platformio_tasmota_env.ini new file mode 100644 index 000000000..46e71d7af --- /dev/null +++ b/platformio_tasmota_env.ini @@ -0,0 +1,99 @@ +[env] +platform = ${common.platform} +framework = ${common.framework} +board = ${common.board} +board_build.flash_mode = ${common.board_build.flash_mode} +board_build.f_cpu = ${common.board_build.f_cpu} +build_unflags = ${common.build_unflags} +build_flags = ${common.build_flags} +monitor_speed = ${common.monitor_speed} +upload_port = ${common.upload_port} +upload_resetmethod = ${common.upload_resetmethod} +upload_speed = ${common.upload_speed} +extra_scripts = ${common.extra_scripts} + +[env:tasmota] + +[env:tasmota-minimal] +build_flags = ${common.build_flags} -DFIRMWARE_MINIMAL + +[env:tasmota-basic] +build_flags = ${common.build_flags} -DFIRMWARE_BASIC + +[env:tasmota-knx] +build_flags = ${common.build_flags} -DFIRMWARE_KNX_NO_EMULATION + +[env:tasmota-sensors] +build_flags = ${common.build_flags} -DFIRMWARE_SENSORS + +[env:tasmota-display] +build_flags = ${common.build_flags} -DFIRMWARE_DISPLAYS + +[env:tasmota-ir] +build_flags = ${common.build_flags} -DUSE_IR_REMOTE_FULL -DFIRMWARE_IR + +[env:tasmota-ircustom] +build_flags = ${common.build_flags} -DUSE_IR_REMOTE_FULL + +[env:tasmota-BG] +build_flags = ${common.build_flags} -DMY_LANGUAGE=bg-BG + +[env:tasmota-BR] +build_flags = ${common.build_flags} -DMY_LANGUAGE=pt-BR + +[env:tasmota-CN] +build_flags = ${common.build_flags} -DMY_LANGUAGE=zh-CN + +[env:tasmota-CZ] +build_flags = ${common.build_flags} -DMY_LANGUAGE=cs-CZ + +[env:tasmota-DE] +build_flags = ${common.build_flags} -DMY_LANGUAGE=de-DE + +[env:tasmota-ES] +build_flags = ${common.build_flags} -DMY_LANGUAGE=es-ES + +[env:tasmota-FR] +build_flags = ${common.build_flags} -DMY_LANGUAGE=fr-FR + +[env:tasmota-GR] +build_flags = ${common.build_flags} -DMY_LANGUAGE=el-GR + +[env:tasmota-HE] +build_flags = ${common.build_flags} -DMY_LANGUAGE=he-HE + +[env:tasmota-HU] +build_flags = ${common.build_flags} -DMY_LANGUAGE=hu-HU + +[env:tasmota-IT] +build_flags = ${common.build_flags} -DMY_LANGUAGE=it-IT + +[env:tasmota-KO] +build_flags = ${common.build_flags} -DMY_LANGUAGE=ko-KO + +[env:tasmota-NL] +build_flags = ${common.build_flags} -DMY_LANGUAGE=nl-NL + +[env:tasmota-PL] +build_flags = ${common.build_flags} -DMY_LANGUAGE=pl-PL + +[env:tasmota-PT] +build_flags = ${common.build_flags} -DMY_LANGUAGE=pt-PT + +[env:tasmota-RU] +build_flags = ${common.build_flags} -DMY_LANGUAGE=ru-RU + +[env:tasmota-SE] +build_flags = ${common.build_flags} -DMY_LANGUAGE=sv-SE + +[env:tasmota-SK] +build_flags = ${common.build_flags} -DMY_LANGUAGE=sk-SK + +[env:tasmota-TR] +build_flags = ${common.build_flags} -DMY_LANGUAGE=tr-TR + +[env:tasmota-TW] +build_flags = ${common.build_flags} -DMY_LANGUAGE=zh-TW + +[env:tasmota-UK] +build_flags = ${common.build_flags} -DMY_LANGUAGE=uk-UK From 2fff09ddc9b8cf532ae2e1b8ea78d42c5fa0f570 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 29 Nov 2019 14:58:43 +0100 Subject: [PATCH 21/50] Delete platformio_override_sample.ini --- pio/platformio_override_sample.ini | 211 ----------------------------- 1 file changed, 211 deletions(-) delete mode 100644 pio/platformio_override_sample.ini diff --git a/pio/platformio_override_sample.ini b/pio/platformio_override_sample.ini deleted file mode 100644 index d94903d0e..000000000 --- a/pio/platformio_override_sample.ini +++ /dev/null @@ -1,211 +0,0 @@ -; *** Example PlatformIO Project Configuration Override File *** -; *** Changes done here overrides settings in platformio.ini *** -; -; **************************************************************** -; *** to activate rename this fie to platformio_override.ini *** -; **************************************************************** -; -; Please visit documentation for the options and examples -; http://docs.platformio.org/en/stable/projectconf.html -; - - -[platformio] - -; *** Build/upload environment -default_envs = -; *** Uncomment the line(s) below to select version(s) - tasmota -; tasmota-debug -; tasmota-ircustom ; alternative to 'tasmota' with full IR protocols activated, you will need to disable some features to keep code not too big -; tasmota-minimal -; tasmota-basic -; tasmota-knx -; tasmota-sensors -; tasmota-display -; tasmota-ir - - -[common] -platform = ${core_active.platform} -build_flags = ${core_active.build_flags} -; *** Use settings from file user_config_override.h - -DUSE_CONFIG_OVERRIDE - -; *** Optional Firmware configurations -; -DFIRMWARE_MINIMAL -; -DFIRMWARE_SENSORS -; -DFIRMWARE_BASIC -; -DFIRMWARE_KNX_NO_EMULATION -; -DFIRMWARE_DISPLAYS -; -DFIRMWARE_IR -; -DFIRMWARE_IR_CUSTOM - -; *** Optional Debug messages -; -DDEBUG_TASMOTA_CORE -; -DDEBUG_TASMOTA_DRIVER -; -DDEBUG_TASMOTA_SENSOR - -; set CPU frequency to 80MHz (default) or 160MHz -;board_build.f_cpu = 160000000L - -; *** Upload Serial reset method for Wemos and NodeMCU -upload_port = COM5 - -extra_scripts = ${scripts_defaults.extra_scripts} - pio/obj-dump.py - -; *** Upload file to OTA server using SCP -;upload_port = user@host:/path -;extra_scripts = ${scripts_defaults.extra_scripts} -; pio/strip-floats.py, pio/sftp-uploader.py - -; *** Upload file to OTA server in folder api/arduino using HTTP -;upload_port = domus1:80/api/upload-arduino.php -;extra_scripts = ${scripts_defaults.extra_scripts} -; pio/strip-floats.py, pio/http-uploader.py - -[core_active] -; Select one core set for platform and build_flags -platform = ${core_2_6_1.platform} -build_flags = ${core_2_6_1.build_flags} -;platform = ${core_2_6_2.platform} -;build_flags = ${core_2_6_2.build_flags} -;platform = ${core_stage.platform} -;build_flags = ${core_stage.build_flags} - - -[core_2_6_1] -; *** Esp8266 core for Arduino version 2.6.1 -platform = espressif8266@2.3.0 -build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Teagle.flash.1m.ld - -DBEARSSL_SSL_BASIC -; NONOSDK221 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 -; NONOSDK22x_190313 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 -; NONOSDK22x_190703 = 2.2.2-dev(38a443e) (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 -; NONOSDK22x_191024 = 2.2.2-dev(5ab15d1) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 -; NONOSDK22x_191105 = 2.2.2-dev(bb83b9b) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 -; NONOSDK3V0 (known issues) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 -; lwIP 1.4 -; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH -; lwIP 2 - Low Memory -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY -; lwIP 2 - Higher Bandwidth -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH -; lwIP 2 - Higher Bandwidth Low Memory no Features -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH -; lwIP 2 - Higher Bandwidth no Features (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH -; lwIP 2 - Higher Bandwidth IPv6 (use ONLY if you need IPv6, experimental!) -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_HIGHER_BANDWIDTH -; VTABLES in Flash (Tasmota default) - -DVTABLES_IN_FLASH -; VTABLES in Heap -; -DVTABLES_IN_DRAM -; VTABLES in IRAM -; -DVTABLES_IN_IRAM -; enable one option set -> No exception recommended -; No exception code in firmware - -fno-exceptions - -lstdc++ -; Exception code in firmware /needs much space! 90k -; -fexceptions -; -lstdc++-exc - -[core_2_6_2] -; *** Esp8266 core for Arduino version 2.6.2 -platform = espressif8266@2.3.1 -build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Teagle.flash.1m.ld - -DBEARSSL_SSL_BASIC -; NONOSDK221 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 -; NONOSDK22x_190313 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 -; NONOSDK22x_190703 = 2.2.2-dev(38a443e) (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 -; NONOSDK22x_191024 = 2.2.2-dev(5ab15d1) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 -; NONOSDK22x_191105 = 2.2.2-dev(bb83b9b) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 -; NONOSDK3V0 (known issues) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 -; lwIP 1.4 -; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH -; lwIP 2 - Low Memory -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY -; lwIP 2 - Higher Bandwidth -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH -; lwIP 2 - Higher Bandwidth Low Memory no Features -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH -; lwIP 2 - Higher Bandwidth no Features (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH -; lwIP 2 - Higher Bandwidth IPv6 (use ONLY if you need IPv6, experimental!) -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_HIGHER_BANDWIDTH -; VTABLES in Flash (Tasmota default) - -DVTABLES_IN_FLASH -; VTABLES in Heap -; -DVTABLES_IN_DRAM -; VTABLES in IRAM -; -DVTABLES_IN_IRAM -; enable one option set -> No exception recommended -; No exception code in firmware - -fno-exceptions - -lstdc++ -; Exception code in firmware /needs much space! 90k -; -fexceptions -; -lstdc++-exc - -[core_stage] -; *** Esp8266 core for Arduino version latest beta -platform = https://github.com/platformio/platform-espressif8266.git#feature/stage -build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Teagle.flash.1m.ld - -DBEARSSL_SSL_BASIC -; NONOSDK221 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 -; NONOSDK22x_190313 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 -; NONOSDK22x_190703 (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 -; NONOSDK22x_191024 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 -; NONOSDK22x_191105 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 -; NONOSDK3V0 (known issues) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 -; lwIP 1.4 -; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH -; lwIP 2 - Low Memory -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY -; lwIP 2 - Higher Bandwidth -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH -; lwIP 2 - Higher Bandwidth Low Memory no Features -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH -; lwIP 2 - Higher Bandwidth no Features (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH -; VTABLES in Flash (Tasmota default) - -DVTABLES_IN_FLASH -; VTABLES in Heap -; -DVTABLES_IN_DRAM -; VTABLES in IRAM -; -DVTABLES_IN_IRAM -; enable one option set -> No exception recommended -; No exception code in firmware - -fno-exceptions - -lstdc++ -; Exception code in firmware /needs much space! 90k -; -fexceptions -; -lstdc++-exc - - -; *** Debug version used for PlatformIO Home Project Inspection -[env:tasmota-debug] -build_type = debug From 9805a840d7a56b6a61b0f3413c3da0c890cbd385 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 29 Nov 2019 14:59:03 +0100 Subject: [PATCH 22/50] Add files via upload --- platformio_override_sample.ini | 211 +++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 platformio_override_sample.ini diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini new file mode 100644 index 000000000..d94903d0e --- /dev/null +++ b/platformio_override_sample.ini @@ -0,0 +1,211 @@ +; *** Example PlatformIO Project Configuration Override File *** +; *** Changes done here overrides settings in platformio.ini *** +; +; **************************************************************** +; *** to activate rename this fie to platformio_override.ini *** +; **************************************************************** +; +; Please visit documentation for the options and examples +; http://docs.platformio.org/en/stable/projectconf.html +; + + +[platformio] + +; *** Build/upload environment +default_envs = +; *** Uncomment the line(s) below to select version(s) + tasmota +; tasmota-debug +; tasmota-ircustom ; alternative to 'tasmota' with full IR protocols activated, you will need to disable some features to keep code not too big +; tasmota-minimal +; tasmota-basic +; tasmota-knx +; tasmota-sensors +; tasmota-display +; tasmota-ir + + +[common] +platform = ${core_active.platform} +build_flags = ${core_active.build_flags} +; *** Use settings from file user_config_override.h + -DUSE_CONFIG_OVERRIDE + +; *** Optional Firmware configurations +; -DFIRMWARE_MINIMAL +; -DFIRMWARE_SENSORS +; -DFIRMWARE_BASIC +; -DFIRMWARE_KNX_NO_EMULATION +; -DFIRMWARE_DISPLAYS +; -DFIRMWARE_IR +; -DFIRMWARE_IR_CUSTOM + +; *** Optional Debug messages +; -DDEBUG_TASMOTA_CORE +; -DDEBUG_TASMOTA_DRIVER +; -DDEBUG_TASMOTA_SENSOR + +; set CPU frequency to 80MHz (default) or 160MHz +;board_build.f_cpu = 160000000L + +; *** Upload Serial reset method for Wemos and NodeMCU +upload_port = COM5 + +extra_scripts = ${scripts_defaults.extra_scripts} + pio/obj-dump.py + +; *** Upload file to OTA server using SCP +;upload_port = user@host:/path +;extra_scripts = ${scripts_defaults.extra_scripts} +; pio/strip-floats.py, pio/sftp-uploader.py + +; *** Upload file to OTA server in folder api/arduino using HTTP +;upload_port = domus1:80/api/upload-arduino.php +;extra_scripts = ${scripts_defaults.extra_scripts} +; pio/strip-floats.py, pio/http-uploader.py + +[core_active] +; Select one core set for platform and build_flags +platform = ${core_2_6_1.platform} +build_flags = ${core_2_6_1.build_flags} +;platform = ${core_2_6_2.platform} +;build_flags = ${core_2_6_2.build_flags} +;platform = ${core_stage.platform} +;build_flags = ${core_stage.build_flags} + + +[core_2_6_1] +; *** Esp8266 core for Arduino version 2.6.1 +platform = espressif8266@2.3.0 +build_flags = ${esp82xx_defaults.build_flags} + -Wl,-Teagle.flash.1m.ld + -DBEARSSL_SSL_BASIC +; NONOSDK221 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 +; NONOSDK22x_190313 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 +; NONOSDK22x_190703 = 2.2.2-dev(38a443e) (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 +; NONOSDK22x_191024 = 2.2.2-dev(5ab15d1) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 +; NONOSDK22x_191105 = 2.2.2-dev(bb83b9b) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 +; NONOSDK3V0 (known issues) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 +; lwIP 1.4 +; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH +; lwIP 2 - Low Memory +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY +; lwIP 2 - Higher Bandwidth +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH +; lwIP 2 - Higher Bandwidth Low Memory no Features +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH +; lwIP 2 - Higher Bandwidth no Features (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH +; lwIP 2 - Higher Bandwidth IPv6 (use ONLY if you need IPv6, experimental!) +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_HIGHER_BANDWIDTH +; VTABLES in Flash (Tasmota default) + -DVTABLES_IN_FLASH +; VTABLES in Heap +; -DVTABLES_IN_DRAM +; VTABLES in IRAM +; -DVTABLES_IN_IRAM +; enable one option set -> No exception recommended +; No exception code in firmware + -fno-exceptions + -lstdc++ +; Exception code in firmware /needs much space! 90k +; -fexceptions +; -lstdc++-exc + +[core_2_6_2] +; *** Esp8266 core for Arduino version 2.6.2 +platform = espressif8266@2.3.1 +build_flags = ${esp82xx_defaults.build_flags} + -Wl,-Teagle.flash.1m.ld + -DBEARSSL_SSL_BASIC +; NONOSDK221 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 +; NONOSDK22x_190313 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 +; NONOSDK22x_190703 = 2.2.2-dev(38a443e) (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 +; NONOSDK22x_191024 = 2.2.2-dev(5ab15d1) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 +; NONOSDK22x_191105 = 2.2.2-dev(bb83b9b) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 +; NONOSDK3V0 (known issues) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 +; lwIP 1.4 +; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH +; lwIP 2 - Low Memory +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY +; lwIP 2 - Higher Bandwidth +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH +; lwIP 2 - Higher Bandwidth Low Memory no Features +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH +; lwIP 2 - Higher Bandwidth no Features (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH +; lwIP 2 - Higher Bandwidth IPv6 (use ONLY if you need IPv6, experimental!) +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_HIGHER_BANDWIDTH +; VTABLES in Flash (Tasmota default) + -DVTABLES_IN_FLASH +; VTABLES in Heap +; -DVTABLES_IN_DRAM +; VTABLES in IRAM +; -DVTABLES_IN_IRAM +; enable one option set -> No exception recommended +; No exception code in firmware + -fno-exceptions + -lstdc++ +; Exception code in firmware /needs much space! 90k +; -fexceptions +; -lstdc++-exc + +[core_stage] +; *** Esp8266 core for Arduino version latest beta +platform = https://github.com/platformio/platform-espressif8266.git#feature/stage +build_flags = ${esp82xx_defaults.build_flags} + -Wl,-Teagle.flash.1m.ld + -DBEARSSL_SSL_BASIC +; NONOSDK221 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 +; NONOSDK22x_190313 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 +; NONOSDK22x_190703 (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 +; NONOSDK22x_191024 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 +; NONOSDK22x_191105 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 +; NONOSDK3V0 (known issues) +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 +; lwIP 1.4 +; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH +; lwIP 2 - Low Memory +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY +; lwIP 2 - Higher Bandwidth +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH +; lwIP 2 - Higher Bandwidth Low Memory no Features +; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH +; lwIP 2 - Higher Bandwidth no Features (Tasmota default) + -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH +; VTABLES in Flash (Tasmota default) + -DVTABLES_IN_FLASH +; VTABLES in Heap +; -DVTABLES_IN_DRAM +; VTABLES in IRAM +; -DVTABLES_IN_IRAM +; enable one option set -> No exception recommended +; No exception code in firmware + -fno-exceptions + -lstdc++ +; Exception code in firmware /needs much space! 90k +; -fexceptions +; -lstdc++-exc + + +; *** Debug version used for PlatformIO Home Project Inspection +[env:tasmota-debug] +build_type = debug From 2f18f0732f488ad6d3aaff648dc70209587b3b27 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 29 Nov 2019 14:59:57 +0100 Subject: [PATCH 23/50] Update platformio.ini --- platformio.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platformio.ini b/platformio.ini index 554c0d1eb..70d7373f3 100755 --- a/platformio.ini +++ b/platformio.ini @@ -48,7 +48,7 @@ default_envs = ; tasmota-UK ; ; *** alternatively can be done in: pio/platformio_override.ini -; *** See example: platformio_override_sample.ini in folder pio +; *** See example: platformio_override_sample.ini ; ********************************************************************* @@ -64,8 +64,8 @@ build_flags = ${core_active.build_flags} ; *** Uncomment, by deleting ";" in line below, to use custom settings from file user_config_override.h ; -DUSE_CONFIG_OVERRIDE ; -; *** alternatively can be done in: pio/platformio_override.ini -; *** See example: platformio_override_sample.ini in folder pio +; *** alternatively can be done in: platformio_override.ini +; *** See example: platformio_override_sample.ini ; ********************************************************************* ; *** Fix espressif8266@1.7.0 induced undesired all warnings From b6f74f86d6fb81eb42a8581fb9685c9e233f5c5b Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 29 Nov 2019 15:02:05 +0100 Subject: [PATCH 24/50] Delete platformio_override.ini --- platformio_override.ini | 277 ---------------------------------------- 1 file changed, 277 deletions(-) delete mode 100644 platformio_override.ini diff --git a/platformio_override.ini b/platformio_override.ini deleted file mode 100644 index ca6f80845..000000000 --- a/platformio_override.ini +++ /dev/null @@ -1,277 +0,0 @@ -[platformio] - -; *** Build/upload environment -default_envs = -; *** Uncomment the line(s) below to select version(s) - tasmota -; tasmota-debug -; tasmota-ircustom ; alternative to 'tasmota' with full IR protocols activated, you will need to disable some features to keep code not too big -; tasmota-minimal -; tasmota-basic -; tasmota-knx -; tasmota-sensors -; tasmota-display -; tasmota-ir - - -[common] -platform = ${core_active.platform} -platform_packages = ${core_active.platform_packages} -build_flags = ${core_active.build_flags} - - -DUSE_CONFIG_OVERRIDE - -; *** Optional Firmware configurations -; -DFIRMWARE_MINIMAL -; -DFIRMWARE_SENSORS -; -DFIRMWARE_BASIC -; -DFIRMWARE_KNX_NO_EMULATION -; -DFIRMWARE_DISPLAYS -; -DFIRMWARE_IR -; -DFIRMWARE_IR_CUSTOM - -; *** Optional Debug messages -; -DDEBUG_TASMOTA_CORE -; -DDEBUG_TASMOTA_DRIVER -; -DDEBUG_TASMOTA_SENSOR - -; set CPU frequency to 80MHz (default) or 160MHz -;board_build.f_cpu = 160000000L - -; *** Upload Serial reset method for Wemos and NodeMCU -upload_port = COM5 - -extra_scripts = ${scripts_defaults.extra_scripts} -; pio/obj-dump.py - -; *** Upload file to OTA server using SCP -;upload_port = user@host:/path -;extra_scripts = ${scripts_defaults.extra_scripts} -; pio/strip-floats.py, pio/sftp-uploader.py - -; *** Upload file to OTA server in folder api/arduino using HTTP -;upload_port = domus1:80/api/upload-arduino.php -;extra_scripts = ${scripts_defaults.extra_scripts} -; pio/strip-floats.py, pio/http-uploader.py - -[core_active] -; Select one core set for platform and build_flags - -;platform = ${core_2_3_0.platform} -;build_flags = ${core_2_3_0.build_flags} - -;platform = ${core_2_4_2.platform} -;build_flags = ${core_2_4_2.build_flags} - -platform = ${core_2_6_1.platform} -build_flags = ${core_2_6_1.build_flags} - -;platform = ${core_2_6_2.platform} -;build_flags = ${core_2_6_2.build_flags} - -;platform = ${core_stage.platform} -;build_flags = ${core_stage.build_flags} -;platform_packages = ${core_stage.platform_packages} - -;platform = ${core_cstage.platform} -;build_flags = ${core_cstage.build_flags} - - - -[core_2_3_0] -; *** Esp8266 core for Arduino version 2.3.0 -platform = espressif8266@~1.5.0 -build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Tesp8266.flash.1m0.ld - -[core_2_4_2] -; *** Esp8266 core for Arduino version 2.4.2 -platform = espressif8266@~1.8.0 -build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Teagle.flash.1m0.ld - -lstdc++ -lsupc++ -; link with an memory optimized version of lib_bearssl - -Llib_bearssl -lbearssl -; lwIP 1.4 -; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH -; lwIP 2 - Low Memory -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY -; lwIP 2 - Higher Bandwidth (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH - -DVTABLES_IN_FLASH - -[core_2_6_1] -; *** Esp8266 core for Arduino version 2.6.1 -;platform = https://github.com/Jason2866/platform-espressif8266.git#new_gcc -platform = espressif8266@2.3.0 -build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Teagle.flash.1m.ld - -DBEARSSL_SSL_BASIC -; NONOSDK221 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 -; NONOSDK22x_190313 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 -; NONOSDK22x_190703 (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 -; NONOSDK22x_191024 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 -; NONOSDK22x_191105 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 -; NONOSDK3V0 (known issues) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 -; lwIP 1.4 -; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH -; lwIP 2 - Low Memory -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY -; lwIP 2 - Higher Bandwidth -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH -; lwIP 2 - Higher Bandwidth Low Memory no Features -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH -; lwIP 2 - Higher Bandwidth no Features (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH -; VTABLES in Flash (Tasmota default) - -DVTABLES_IN_FLASH -; VTABLES in Heap -; -DVTABLES_IN_DRAM -; VTABLES in IRAM -; -DVTABLES_IN_IRAM -; enable one option set -> No exception recommended -; No exception code in firmware - -fno-exceptions - -lstdc++ -; Exception code in firmware /needs much space! 90k -; -fexceptions -; -lstdc++-exc - -[core_2_6_2] -; *** Esp8266 core for Arduino version 2.6.2 -platform = espressif8266@2.3.1 -build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Teagle.flash.1m.ld - -DBEARSSL_SSL_BASIC -; NONOSDK221 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 -; NONOSDK22x_190313 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 -; NONOSDK22x_190703 (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 -; NONOSDK22x_191024 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 -; NONOSDK22x_191105 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 -; NONOSDK3V0 (known issues) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 -; lwIP 1.4 -; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH -; lwIP 2 - Low Memory -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY -; lwIP 2 - Higher Bandwidth -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH -; lwIP 2 - Higher Bandwidth Low Memory no Features -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH -; lwIP 2 - Higher Bandwidth no Features (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH -; VTABLES in Flash (Tasmota default) - -DVTABLES_IN_FLASH -; VTABLES in Heap -; -DVTABLES_IN_DRAM -; VTABLES in IRAM -; -DVTABLES_IN_IRAM -; enable one option set -> No exception recommended -; No exception code in firmware - -fno-exceptions - -lstdc++ -; Exception code in firmware /needs much space! 90k -; -fexceptions -; -lstdc++-exc - -[core_stage] -; *** Esp8266 core for Arduino version latest beta -platform = espressif8266 -platform_packages = - framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git -build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Teagle.flash.1m.ld - -DBEARSSL_SSL_BASIC -; NONOSDK221 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 -; NONOSDK22x_190313 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 -; NONOSDK22x_190703 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 -; NONOSDK22x_191024 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 -; NONOSDK22x_191105 - -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 -; NONOSDK3V0 (known issues) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 -; lwIP 1.4 -; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH -; lwIP 2 - Low Memory -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY -; lwIP 2 - Higher Bandwidth -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH -; lwIP 2 - Higher Bandwidth Low Memory no Features -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH -; lwIP 2 - Higher Bandwidth no Features (Tasmota default) - -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH -; VTABLES in Flash (Tasmota default) - -DVTABLES_IN_FLASH -; VTABLES in Heap -; -DVTABLES_IN_DRAM -; VTABLES in IRAM -; -DVTABLES_IN_IRAM -; enable one option set -> No exception recommended -; No exception code in firmware - -fno-exceptions - -lstdc++ -; Exception code in firmware /needs much space! 90k -; -fexceptions -; -lstdc++-exc - -[core_cstage] -; *** Arduino Esp8266 -> Wstring optimization -platform = https://github.com/Jason2866/platform-espressif8266.git#feature/stage -build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Tesp8266.flash.1m.ld - -DBEARSSL_SSL_BASIC -; NONOSDK221 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 -; NONOSDK22x_190313 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313 -; NONOSDK22x_190703 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703 -; NONOSDK22x_191024 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 -; NONOSDK22x_191105 - -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 -; NONOSDK3V0 (known issues) -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 -; lwIP 1.4 -; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH -; lwIP 2 - Low Memory -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY -; lwIP 2 - Higher Bandwidth -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH -; lwIP 2 - Higher Bandwidth Low Memory no Features -; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH -; lwIP 2 - Higher Bandwidth no Features - -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH -; VTABLES in Flash (default) - -DVTABLES_IN_FLASH -; VTABLES in Heap -; -DVTABLES_IN_DRAM -; VTABLES in IRAM -; -DVTABLES_IN_IRAM -; enable one option set -> No exception recommended -; No exception code in firmware - -fno-exceptions - -lstdc++ -; Exception code in firmware /needs much space! 90k -; -fexceptions -; -lstdc++-exc - - -; *** Debug version used for PlatformIO Home Project Inspection -[env:tasmota-debug] -build_type = debug From 02e938fc185337222c8c56273929afe13e105474 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 29 Nov 2019 15:22:28 +0100 Subject: [PATCH 25/50] Prep for release 7.1 --- README.md | 25 +++++++++++++++++++++---- SUPPORT.md | 24 ------------------------ platformio_override_sample.ini | 20 ++++++++++---------- tasmota/CHANGELOG.md | 9 +++++++-- tasmota/tasmota_version.h | 2 +- 5 files changed, 39 insertions(+), 41 deletions(-) delete mode 100644 SUPPORT.md diff --git a/README.md b/README.md index 8d5a1e696..c0b26ce70 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ In addition to the [release webpage](https://github.com/arendst/Tasmota/releases ## Development -[![Dev Version](https://img.shields.io/badge/development%20version-v7.0.0.x-blue.svg)](https://github.com/arendst/Tasmota) +[![Dev Version](https://img.shields.io/badge/development%20version-v7.1.0.x-blue.svg)](https://github.com/arendst/Tasmota) [![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://thehackbox.org/tasmota/) [![Build Status](https://img.shields.io/travis/arendst/Tasmota.svg)](https://travis-ci.org/arendst/Tasmota) @@ -74,9 +74,26 @@ See [wiki migration path](https://tasmota.github.io/docs/#/Upgrading?id=migratio For a database of supported devices see [Tasmota Device Templates Repository](https://blakadder.github.io/templates) -See [Wiki](https://tasmota.github.io/docs) for use instructions and how-to's. -See [Community](https://groups.google.com/d/forum/sonoffusers) for forum. -Visit [Discord Chat](https://discord.gg/Ks2Kzd4) for discussions and troubleshooting. +If you're looking for support on **Tasmota** there are some options available: + +### Documentation: + +* [Documentation Site](https://tasmota.github.io/docs): For information on how to flash Tasmota, configure, use and expand it +* [FAQ and Troubleshooting](https://tasmota.github.io/docs/#/help/): For information on common problems and solutions. +* [Commands Information](https://tasmota.github.io/docs/#/Commands): For information on all the commands supported by Tasmota. + +### Support's Community: + +* [Tasmota Forum](https://groups.google.com/d/forum/sonoffusers): For usage and discussions. +* [Tasmota Support Chat](https://discord.gg/Ks2Kzd4): For support, troubleshooting and general questions. You have better chances to get fast answers from members of the Tasmota Community. +* [Search in Issues](https://github.com/arendst/Tasmota/issues): You might find an answer to your question by searching current or closed issues. + +### Developers' Community: + +* [Bug Report](https://github.com/arendst/Tasmota/issues/new?template=Bug_report.md): For reporting Bugs of Tasmota Software. +* [Feature Request](https://github.com/arendst/Tasmota/issues/new?template=Feature_request.md): For requesting features/functions to Tasmota Software. +* [Troubleshooting](https://github.com/arendst/Tasmota/issues/new?template=Custom.md): As a last resort, you can open new *Troubleshooting* issue on GitHub if the solution could not be found using the other channels. Just remember: the more info you provide the more chances you'll have to get an accurate answer. +* [Issue a question](https://github.com/arendst/Tasmota/issues/new/choose): As a last resort, you can open a new *Question* issue on GitHub if the answer could not be found using the other channels. Just remember: the more info you provide the more chances you'll have to get an accurate answer. ## Contribute diff --git a/SUPPORT.md b/SUPPORT.md deleted file mode 100644 index d26baa615..000000000 --- a/SUPPORT.md +++ /dev/null @@ -1,24 +0,0 @@ - - -# Support - -If you're looking for support on **Tasmota** there are some options available: - -## Documentation: - -* [Documentation Site](https://tasmota.github.io/docs): For information on how to flash Tasmota, configure, use and expand it -* [FAQ and Troubleshooting](https://tasmota.github.io/docs/#/help/): For information on common problems and solutions. -* [Commands Information](https://tasmota.github.io/docs/#/Commands): For information on all the commands supported by Tasmota. - -## Support's Community: - -* [Tasmota Forum](https://groups.google.com/d/forum/sonoffusers): For usage and discussions. -* [Tasmota Support Chat](https://discord.gg/Ks2Kzd4): For support, troubleshooting and general questions. You have better chances to get fast answers from members of the Tasmota Community. -* [Search in Issues](https://github.com/arendst/Tasmota/issues): You might find an answer to your question by searching current or closed issues. - -## Developers' Community: - -* [Bug Report](https://github.com/arendst/Tasmota/issues/new?template=Bug_report.md): For reporting Bugs of Tasmota Software. -* [Feature Request](https://github.com/arendst/Tasmota/issues/new?template=Feature_request.md): For requesting features/functions to Tasmota Software. -* [Troubleshooting](https://github.com/arendst/Tasmota/issues/new?template=Custom.md): As a last resort, you can open new *Troubleshooting* issue on GitHub if the solution could not be found using the other channels. Just remember: the more info you provide the more chances you'll have to get an accurate answer. -* [Issue a question](https://github.com/arendst/Tasmota/issues/new/choose): As a last resort, you can open a new *Question* issue on GitHub if the answer could not be found using the other channels. Just remember: the more info you provide the more chances you'll have to get an accurate answer. diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index d94903d0e..9827447dd 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -1,9 +1,9 @@ -; *** Example PlatformIO Project Configuration Override File *** -; *** Changes done here overrides settings in platformio.ini *** -; -; **************************************************************** -; *** to activate rename this fie to platformio_override.ini *** -; **************************************************************** +; *** Example PlatformIO Project Configuration Override File *** +; *** Changes done here override settings in platformio.ini *** +; +; ***************************************************************** +; *** to activate rename this file to platformio_override.ini *** +; ***************************************************************** ; ; Please visit documentation for the options and examples ; http://docs.platformio.org/en/stable/projectconf.html @@ -13,7 +13,7 @@ [platformio] ; *** Build/upload environment -default_envs = +default_envs = ; *** Uncomment the line(s) below to select version(s) tasmota ; tasmota-debug @@ -29,7 +29,7 @@ default_envs = [common] platform = ${core_active.platform} build_flags = ${core_active.build_flags} -; *** Use settings from file user_config_override.h +; *** Use settings from file user_config_override.h -DUSE_CONFIG_OVERRIDE ; *** Optional Firmware configurations @@ -57,7 +57,7 @@ extra_scripts = ${scripts_defaults.extra_scripts} ; *** Upload file to OTA server using SCP ;upload_port = user@host:/path -;extra_scripts = ${scripts_defaults.extra_scripts} +;extra_scripts = ${scripts_defaults.extra_scripts} ; pio/strip-floats.py, pio/sftp-uploader.py ; *** Upload file to OTA server in folder api/arduino using HTTP @@ -178,7 +178,7 @@ build_flags = ${esp82xx_defaults.build_flags} ; NONOSDK22x_191024 ; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024 ; NONOSDK22x_191105 -; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 +; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105 ; NONOSDK3V0 (known issues) ; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3 ; lwIP 1.4 diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 2ab00d9ba..259095dc3 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,5 +1,12 @@ ## Unreleased (development) + +## Released + +### 7.1.0 20191129 + +- Release + ### 7.0.0.6 20191122 - Add colorpicker to WebUI by Christian Staars (#6984) @@ -65,8 +72,6 @@ - Add support for Tuya battery powered devices (#6735) - Change repository name from Sonoff-Tasmota to Tasmota and all code references from Sonoff to Tasmota -## Released - ### 6.7.1 20191026 - Release diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index 4e674bf6c..bb71cb5f2 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x07000006; +const uint32_t VERSION = 0x07010000; #endif // _TASMOTA_VERSION_H_ From 3d28f347d5a392ab1de5cb88e117ce5de2a1c369 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 29 Nov 2019 16:15:12 +0100 Subject: [PATCH 26/50] Update platformio.ini --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 70d7373f3..d47eadafb 100755 --- a/platformio.ini +++ b/platformio.ini @@ -47,7 +47,7 @@ default_envs = ; tasmota-TW ; tasmota-UK ; -; *** alternatively can be done in: pio/platformio_override.ini +; *** alternatively can be done in: platformio_override.ini ; *** See example: platformio_override_sample.ini ; ********************************************************************* From 36fa0e9517080f7c44b5273cb5b5502d3a356e7d Mon Sep 17 00:00:00 2001 From: andrethomas Date: Fri, 29 Nov 2019 21:20:33 +0200 Subject: [PATCH 27/50] TasmotaSlave: Bugfix for Tele & add support for Commands --- tasmota/xdrv_31_tasmota_slave.ino | 34 +++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/tasmota/xdrv_31_tasmota_slave.ino b/tasmota/xdrv_31_tasmota_slave.ino index daa5586b8..2f5369a12 100644 --- a/tasmota/xdrv_31_tasmota_slave.ino +++ b/tasmota/xdrv_31_tasmota_slave.ino @@ -47,6 +47,7 @@ #define CMND_FUNC_EVERY_100_MSECOND 0x04 #define CMND_SLAVE_SEND 0x05 #define CMND_PUBLISH_TELE 0x06 +#define CMND_EXECUTE_CMND 0x07 #define PARAM_DATA_START 0xFE #define PARAM_DATA_END 0xFF @@ -142,6 +143,7 @@ struct TSLAVE { bool flashing = false; bool SerialEnabled = false; uint8_t waitstate = 0; // We use this so that features detection does not slow down other stuff on startup + bool unsupported = false; } TSlave; typedef union { @@ -461,9 +463,14 @@ void TasmotaSlave_Init(void) TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer)); uint8_t len = TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer)); memcpy(&TSlaveSettings, &buffer, sizeof(TSlaveSettings)); - if (20191101 == TSlaveSettings.features_version) { + if (20191129 == TSlaveSettings.features_version) { TSlave.type = true; AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Version %u"), TSlaveSettings.features_version); + } else { + if ((!TSlave.unsupported) && (TSlaveSettings.features_version > 0)) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Version %u not supported!"), TSlaveSettings.features_version); + TSlave.unsupported = true; + } } } } @@ -506,8 +513,9 @@ void (* const TasmotaSlaveCommand[])(void) PROGMEM = { void CmndTasmotaSlaveReset(void) { TasmotaSlave_Reset(); - TSlave.type = false; // Force redetection - TSlave.waitstate = 7; // give it at least 3 seconds to restart from bootloader + TSlave.type = false; // Force redetection + TSlave.waitstate = 7; // give it at least 3 seconds to restart from bootloader + TSlave.unsupported = false; // Reset unsupported flag ResponseCmndDone(); } @@ -536,21 +544,25 @@ void TasmotaSlave_ProcessIn(void) } TasmotaSlave_Serial->read(); // read trailing byte of command memcpy(&TSlaveCommand, &buffer, sizeof(TSlaveCommand)); + char inbuf[TSlaveCommand.parameter+1]; + TasmotaSlave_waitForSerialData(TSlaveCommand.parameter, 50); + TasmotaSlave_Serial->read(); // Read leading byte + for (uint8_t idx = 0; idx < TSlaveCommand.parameter; idx++) { + inbuf[idx] = TasmotaSlave_Serial->read(); + } + TasmotaSlave_Serial->read(); // Read trailing byte + inbuf[TSlaveCommand.parameter] = '\0'; + if (CMND_PUBLISH_TELE == TSlaveCommand.command) { // We need to publish stat/ with incoming stream as content - char inbuf[sizeof(TSlaveCommand.parameter)+1]; - TasmotaSlave_waitForSerialData(TSlaveCommand.parameter, 50); - TasmotaSlave_Serial->read(); // Read leading byte - for (uint8_t idx = 0; idx < TSlaveCommand.parameter; idx++) { - inbuf[idx] = TasmotaSlave_Serial->read(); - } - TasmotaSlave_Serial->read(); // Read trailing byte - inbuf[TSlaveCommand.parameter] = '\0'; Response_P(PSTR("{\"TasmotaSlave\":")); ResponseAppend_P("%s", inbuf); ResponseJsonEnd(); MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); XdrvRulesProcess(); } + if (CMND_EXECUTE_CMND == TSlaveCommand.command) { // We need to execute the incoming command + ExecuteCommand(inbuf, SRC_IGNORE); + } break; default: break; From bffe8f0c8d6e83655636d4a8f07599cff9f2c1be Mon Sep 17 00:00:00 2001 From: Andre Thomas <470015+andrethomas@users.noreply.github.com> Date: Fri, 29 Nov 2019 21:24:13 +0200 Subject: [PATCH 28/50] Update CHANGELOG.md --- tasmota/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 259095dc3..56f3c146e 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,5 +1,7 @@ ## Unreleased (development) +- TasmotaSlave bugfix for buffer overrun on Tele +- TasmotaSlave add support for executing commands on Tasmota ## Released From 459b45bb27663637fa509b9fbe74495fded0de75 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <39969427+ascillato2@users.noreply.github.com> Date: Fri, 29 Nov 2019 20:18:26 -0300 Subject: [PATCH 29/50] Fix grammar in Bot Message --- .github/issue-close-app.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/issue-close-app.yml b/.github/issue-close-app.yml index 0fcb996ab..8e981441b 100644 --- a/.github/issue-close-app.yml +++ b/.github/issue-close-app.yml @@ -10,7 +10,7 @@ comment: >- Filling the template is required so standard questions don't need to be asked again each time. Our ability to provide assistance is greatly hampered if few minutes are not taken to complete the issue template with the requested information. The details requested potentially affect which options to pursue. The small amount - of time you spend completing the template will also help the volunteers providing the assistance to you, to reduce + of time you will spend completing the template will also help the volunteers, providing assistance to you, to reduce the time required to help you. Please, could you be so kind on completing the [issue template](https://github.com/arendst/Tasmota/issues/new/choose) in order to have more information so as to properly help you? From 09f91044658cc46ee4e31357173745d01b555e26 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 30 Nov 2019 15:36:15 +0100 Subject: [PATCH 30/50] Bump version 7.1.0.1 --- tasmota/CHANGELOG.md | 1 + tasmota/tasmota_version.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 259095dc3..2810f3373 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,5 +1,6 @@ ## Unreleased (development) +### 7.1.0.1 20191130 ## Released diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index bb71cb5f2..7484f5bc9 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x07010000; +const uint32_t VERSION = 0x07010001; #endif // _TASMOTA_VERSION_H_ From 5524075b04e28548e71254ae01205a58d02ecaac Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 30 Nov 2019 16:05:09 +0100 Subject: [PATCH 31/50] Fix slider for devices without RGB Fix slider for devices with one or two channels like only white or white/yellow --- tasmota/CHANGELOG.md | 2 ++ tasmota/xdrv_01_webserver.ino | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 2810f3373..235471a07 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -2,6 +2,8 @@ ### 7.1.0.1 20191130 +- Fix slider for devices with one or two channels like only white or white/yellow + ## Released ### 7.1.0 20191129 diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 42630b8ba..48e2cd26a 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -154,9 +154,11 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM = const char HTTP_SCRIPT_ROOT_PART2[] PROGMEM = "function lc(v,i,p){" - "if(v=='h'||v=='d'){" // Hue or Brightness changed so change Saturation colors too - "var sl=eb('sl4').value;" - "eb('s').style.background='linear-gradient(to right,rgb('+sl+'%%,'+sl+'%%,'+sl+'%%),hsl('+eb('sl2').value+',100%%,50%%))';" + "if(eb('s')){" // Check if Saturation is in DOM otherwise javascript fails on la() + "if(v=='h'||v=='d'){" // Hue or Brightness changed so change Saturation colors too + "var sl=eb('sl4').value;" + "eb('s').style.background='linear-gradient(to right,rgb('+sl+'%%,'+sl+'%%,'+sl+'%%),hsl('+eb('sl2').value+',100%%,50%%))';" + "}" "}" "la('&'+v+i+'='+p);" "}" From 8cf2d15ed1c09645cc1c33fca9a6376ed4b635f0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 30 Nov 2019 17:53:49 +0100 Subject: [PATCH 32/50] Fix light scheme 4 speed Fix light scheme 4 speed (#7072) --- tasmota/CHANGELOG.md | 1 + tasmota/xdrv_04_light.ino | 30 +++++++++++------------------- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index c5aa2355d..e9949c4f5 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -4,6 +4,7 @@ - Fix slider for devices with one or two channels like only white or white/yellow - Fix TasmotaSlave buffer overrun on Tele +- Fix light scheme 4 speed (#7072) - Add support for TasmotaSlave executing commands on Tasmota ## Released diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 695815d71..b50d8e4df 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -242,6 +242,7 @@ struct LIGHT { uint8_t color_remap[LST_MAX]; uint8_t wheel = 0; + uint8_t random = 0; uint8_t subtype = 0; // LST_ subtype uint8_t device = 0; uint8_t old_power = 1; @@ -1541,28 +1542,19 @@ void LightCycleColor(int8_t direction) if (Light.strip_timer_counter % (Settings.light_speed * 2)) { return; } - Light.wheel += direction; + + if (0 == direction) { + if (Light.random == Light.wheel) { + Light.random = random(255); + } + Light.wheel += (Light.random < Light.wheel) ? -1 : 1; + } else { + Light.wheel += direction; + } LightWheel(Light.wheel); memcpy(Light.new_color, Light.entry_color, sizeof(Light.new_color)); } -void LightRandomColor(void) -{ - bool update = false; - for (uint32_t i = 0; i < LST_RGB; i++) { - if (Light.new_color[i] != Light.current_color[i]) { - update = true; - } - } - if (!update) { - Light.wheel = random(255); - LightWheel(Light.wheel); - memcpy(Light.current_color, Light.entry_color, sizeof(Light.current_color)); - } - - memcpy(Light.new_color, Light.current_color, sizeof(Light.new_color)); -} - void LightSetPower(void) { // Light.power = XdrvMailbox.index; @@ -1652,7 +1644,7 @@ void LightAnimate(void) LightCycleColor(-1); break; case LS_RANDOM: - LightRandomColor(); + LightCycleColor(0); break; default: XlgtCall(FUNC_SET_SCHEME); From 9b62d1084dcedaf6173e42ca3595cb6b6dc313ad Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 1 Dec 2019 12:56:05 +0100 Subject: [PATCH 33/50] Bump version 7.1.1 --- MODULES.md | 80 ++++++++++++++++++++++++ README.md | 2 +- RELEASENOTES.md | 126 +++----------------------------------- tasmota/CHANGELOG.md | 8 ++- tasmota/tasmota_version.h | 2 +- 5 files changed, 95 insertions(+), 123 deletions(-) create mode 100644 MODULES.md diff --git a/MODULES.md b/MODULES.md new file mode 100644 index 000000000..bb02bfe73 --- /dev/null +++ b/MODULES.md @@ -0,0 +1,80 @@ +## Supported Modules + +The following hardware modules are supported. + +Module | Description +------------------|----------------------- +01 Sonoff Basic | Sonoff Basic Wifi Smart Switch +02 Sonoff RF | Sonoff RF Wifi Smart Switch with RF (434MHz) receiver +03 Sonoff SV | Sonoff SV Safe Voltage Wifi Smart Switch +04 Sonoff TH | Sonoff TH10/TH16 Wifi Smart Switch with Sensor connection +05 Sonoff Dual | Sonoff Dual Wifi Smart Switch +06 Sonoff Pow | Sonoff Pow Wifi Smart Switch with Energy Monitoring +07 Sonoff 4CH | Sonoff 4CH 4-gang Wifi Smart Switch +08 Sonoff S2X | Sonoff S20/S26 Wifi Smart Socket +09 Slampher | Sonoff Slampher Wifi Smart Light Bulb Socket with RF (434MHz) receiver +10 Sonoff Touch | Sonoff Touch Wifi Light Switch +11 Sonoff LED | Sonoff Led Wifi Led Pack (Retired) +12 1 Channel | 1 Channel Inching/Self Locking Wifi Switch 5V/12V +13 4 Channel | 4 Channel Inching/Self Locking Wifi Switch (Retired) +14 Motor C/AC | Motor Clockwise/Antoclockwise Wifi Switch (Retired) +15 ElectroDragon | Electrodragon Wifi IoT Board +16 EXS Relay(s) | Electronic Experience Store 1 or 2-gang Wifi Module +17 WiOn | WiOn Wifi Smart Socket +18 Generic | Any ESP8266/ESP8285 device like WeMos and NodeMCU +19 Sonoff Dev | Sonoff Dev Wifi Development Board +20 H801 | H801 Wifi RGBWW Led Controller +21 Sonoff SC | Sonoff SC Wifi Environmental Monitor +22 Sonoff BN-SZ | Sonoff BN-SZ01 Wifi Ceiling Led (Retired) +23 Sonoff 4CH Pro | Sonoff 4CH Pro 4-gang Wifi Smart Switch +24 Huafan SS | HuaFan Wifi Smart Socket +25 Sonoff Bridge | Sonoff RF (434MHz) transceive to Wifi Bridge +26 Sonoff B1 | Sonoff B1 Wifi RGBWW Led Bulb +27 AiLight | Ai-Thinker RGBW Led Bulb +28 Sonoff T1 1CH | Sonoff T1 1-gang Wifi Light Switch +29 Sonoff T1 2CH | Sonoff T1 2-gang Wifi Light Switch +30 Sonoff T1 3CH | Sonoff T1 3-gang Wifi Light Switch +31 Supla Espablo | 2-gang Wifi Module +32 Witty Cloud | Witty Cloud ESP8266 Wifi Development Board +33 Yunshan Relay | ESP8266 Wifi Network Relay Module +34 MagicHome | MagicHome, Flux-light and some Arilux LC10 RGB(W) Led Controller +35 Luani HVIO | Luani ESP8266 Wifi I/O Module +36 KMC 70011 | KMC Wifi Smart Socket with Energy Monitoring +37 Arilux LC01 | Arilux AL-LC01 RGB Led Controller +38 Arilux LC11 | Arilux AL-LC11 RGBWW Led Controller +39 Sonoff Dual R2 | Sonoff Dual R2 Wifi Smart Switch +40 Arilux LC06 | Arilux AL-LC06 RGB(WW) Led Controller +41 Sonoff S31 | Sonoff S31 Wifi Smart Socket with Energy Monitoring +42 Zengge WF017 | Zengge WF017 Wifi RGB(W) Led Controller +43 Sonoff Pow R2 | Sonoff Pow R2 Wifi Smart Switch with Energy Monitoring +44 Sonoff iFan02 | Sonoff iFan02 Wifi Smart Ceiling Fan with Light +45 BlitzWolf SHP | BlitzWolf BW-SHP2, BW-SHP6, HomeCube SP1, Gosund SP111, Teckin SP22 Wifi Smart Switch with Energy Monitoring +46 Shelly 1 | Shelly 1 Open Source Wifi Relay Module +47 Shelly 2 | Shelly 2 Wifi 2-gang Relay Module with Energy Monitoring +48 Xiaomi Philips | Xiaomi Philips Wifi WW Led Bulb +49 Neo Coolcam | Neo Coolcam Wifi Smart Socket +50 ESP Switch | ESP Switch 4-gang Wifi Switch with Leds +51 OBI Socket | OBI Wifi Smart Socket +52 Teckin | Teckin SP22 Wifi Smart Switch with Energy Monitoring +53 AplicWDP303075 | Aplic WDP 303075 CSL Wifi Smart Switch with Energy Monitoring +54 Tuya Dimmer | MIUO (and other Tuya based) Wifi Dimmer for Incandescent Lights and Led +55 Gosund SP1 v23 | Gosund SP1 v2.3 Wifi Smart Switch with Energy Monitoring +56 ARMTR Dimmer | ARMtronix Wifi dimmer for Incandescent Lights and Led +57 SK03 Outdoor | SK03 Outdoor Wifi Smart Switch with Energy Monitoring +58 PS-16-DZ | PS-16-DZ Wifi dimmer for Incandescent Lights and Led +59 Teckin US | Teckin SP20 and ZooZee SA102 Wifi Smart Switch with Energy Monitoring +60 Manzoku strip | Manzoku Wifi Smart Power Strip with four Relays +61 OBI Socket 2 | OBI 2 Wifi Smart Socket +62 YTF IR Bridge | YTF Infra Red Wifi Bridge +63 Digoo DG-SP202 | Digoo DG-SP202 Dual Wifi Smart Switch with Energy Monitoring +64 KA10 | Smanergy KA10 Wifi Smart Wall Switch with Energy Monitoring +65 Luminea ZX2820 | Luminea ZX2820 Wifi Smart Switch with Energy Monitoring +66 Mi Desk Lamp | Mi Desk Lamp with rotary switch and Wifi +67 SP10 | Tuya SP10 Wifi Smart Switch with Energy Monitoring +68 WAGA CHCZ02MB | WAGA life CHCZ02MB Wifi Smart Switch with Energy Monitoring +69 SYF05 | Sunyesmart SYF05 RGBWW Wifi Led Bulb +70 Sonoff L1 | Sonoff L1 light strip +71 Sonoff iFan03 | Sonoff iFan03 Wifi Smart Ceiling Fan with Light +72 EXS Dimmer | EXS Wifi Dimmer v4 + +Over 600 additional devices are supported using [templates](TEMPLATES.md). diff --git a/README.md b/README.md index c0b26ce70..cd99f948a 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ In addition to the [release webpage](https://github.com/arendst/Tasmota/releases ## Development -[![Dev Version](https://img.shields.io/badge/development%20version-v7.1.0.x-blue.svg)](https://github.com/arendst/Tasmota) +[![Dev Version](https://img.shields.io/badge/development%20version-v7.1.1.x-blue.svg)](https://github.com/arendst/Tasmota) [![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://thehackbox.org/tasmota/) [![Build Status](https://img.shields.io/travis/arendst/Tasmota.svg)](https://travis-ci.org/arendst/Tasmota) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index a46f2bd46..1ea030e6a 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -28,87 +28,6 @@ To save resources when TLS is enabled mDNS needs to be disabled. In addition to For initial configuration this release supports Webserver based **WifiManager** or **Serial** based command interface only. Support for **WPS** and **SmartConfig** has been removed. -## Supported Modules - -The following hardware modules are supported. - -Module | Description -------------------|----------------------- -01 Sonoff Basic | Sonoff Basic Wifi Smart Switch -02 Sonoff RF | Sonoff RF Wifi Smart Switch with RF (434MHz) receiver -03 Sonoff SV | Sonoff SV Safe Voltage Wifi Smart Switch -04 Sonoff TH | Sonoff TH10/TH16 Wifi Smart Switch with Sensor connection -05 Sonoff Dual | Sonoff Dual Wifi Smart Switch -06 Sonoff Pow | Sonoff Pow Wifi Smart Switch with Energy Monitoring -07 Sonoff 4CH | Sonoff 4CH 4-gang Wifi Smart Switch -08 Sonoff S2X | Sonoff S20/S26 Wifi Smart Socket -09 Slampher | Sonoff Slampher Wifi Smart Light Bulb Socket with RF (434MHz) receiver -10 Sonoff Touch | Sonoff Touch Wifi Light Switch -11 Sonoff LED | Sonoff Led Wifi Led Pack (Retired) -12 1 Channel | 1 Channel Inching/Self Locking Wifi Switch 5V/12V -13 4 Channel | 4 Channel Inching/Self Locking Wifi Switch (Retired) -14 Motor C/AC | Motor Clockwise/Antoclockwise Wifi Switch (Retired) -15 ElectroDragon | Electrodragon Wifi IoT Board -16 EXS Relay(s) | Electronic Experience Store 1 or 2-gang Wifi Module -17 WiOn | WiOn Wifi Smart Socket -18 Generic | Any ESP8266/ESP8285 device like WeMos and NodeMCU -19 Sonoff Dev | Sonoff Dev Wifi Development Board -20 H801 | H801 Wifi RGBWW Led Controller -21 Sonoff SC | Sonoff SC Wifi Environmental Monitor -22 Sonoff BN-SZ | Sonoff BN-SZ01 Wifi Ceiling Led (Retired) -23 Sonoff 4CH Pro | Sonoff 4CH Pro 4-gang Wifi Smart Switch -24 Huafan SS | HuaFan Wifi Smart Socket -25 Sonoff Bridge | Sonoff RF (434MHz) transceive to Wifi Bridge -26 Sonoff B1 | Sonoff B1 Wifi RGBWW Led Bulb -27 AiLight | Ai-Thinker RGBW Led Bulb -28 Sonoff T1 1CH | Sonoff T1 1-gang Wifi Light Switch -29 Sonoff T1 2CH | Sonoff T1 2-gang Wifi Light Switch -30 Sonoff T1 3CH | Sonoff T1 3-gang Wifi Light Switch -31 Supla Espablo | 2-gang Wifi Module -32 Witty Cloud | Witty Cloud ESP8266 Wifi Development Board -33 Yunshan Relay | ESP8266 Wifi Network Relay Module -34 MagicHome | MagicHome, Flux-light and some Arilux LC10 RGB(W) Led Controller -35 Luani HVIO | Luani ESP8266 Wifi I/O Module -36 KMC 70011 | KMC Wifi Smart Socket with Energy Monitoring -37 Arilux LC01 | Arilux AL-LC01 RGB Led Controller -38 Arilux LC11 | Arilux AL-LC11 RGBWW Led Controller -39 Sonoff Dual R2 | Sonoff Dual R2 Wifi Smart Switch -40 Arilux LC06 | Arilux AL-LC06 RGB(WW) Led Controller -41 Sonoff S31 | Sonoff S31 Wifi Smart Socket with Energy Monitoring -42 Zengge WF017 | Zengge WF017 Wifi RGB(W) Led Controller -43 Sonoff Pow R2 | Sonoff Pow R2 Wifi Smart Switch with Energy Monitoring -44 Sonoff iFan02 | Sonoff iFan02 Wifi Smart Ceiling Fan with Light -45 BlitzWolf SHP | BlitzWolf BW-SHP2, BW-SHP6, HomeCube SP1, Gosund SP111, Teckin SP22 Wifi Smart Switch with Energy Monitoring -46 Shelly 1 | Shelly 1 Open Source Wifi Relay Module -47 Shelly 2 | Shelly 2 Wifi 2-gang Relay Module with Energy Monitoring -48 Xiaomi Philips | Xiaomi Philips Wifi WW Led Bulb -49 Neo Coolcam | Neo Coolcam Wifi Smart Socket -50 ESP Switch | ESP Switch 4-gang Wifi Switch with Leds -51 OBI Socket | OBI Wifi Smart Socket -52 Teckin | Teckin SP22 Wifi Smart Switch with Energy Monitoring -53 AplicWDP303075 | Aplic WDP 303075 CSL Wifi Smart Switch with Energy Monitoring -54 Tuya Dimmer | MIUO (and other Tuya based) Wifi Dimmer for Incandescent Lights and Led -55 Gosund SP1 v23 | Gosund SP1 v2.3 Wifi Smart Switch with Energy Monitoring -56 ARMTR Dimmer | ARMtronix Wifi dimmer for Incandescent Lights and Led -57 SK03 Outdoor | SK03 Outdoor Wifi Smart Switch with Energy Monitoring -58 PS-16-DZ | PS-16-DZ Wifi dimmer for Incandescent Lights and Led -59 Teckin US | Teckin SP20 and ZooZee SA102 Wifi Smart Switch with Energy Monitoring -60 Manzoku strip | Manzoku Wifi Smart Power Strip with four Relays -61 OBI Socket 2 | OBI 2 Wifi Smart Socket -62 YTF IR Bridge | YTF Infra Red Wifi Bridge -63 Digoo DG-SP202 | Digoo DG-SP202 Dual Wifi Smart Switch with Energy Monitoring -64 KA10 | Smanergy KA10 Wifi Smart Wall Switch with Energy Monitoring -65 Luminea ZX2820 | Luminea ZX2820 Wifi Smart Switch with Energy Monitoring -66 Mi Desk Lamp | Mi Desk Lamp with rotary switch and Wifi -67 SP10 | Tuya SP10 Wifi Smart Switch with Energy Monitoring -68 WAGA CHCZ02MB | WAGA life CHCZ02MB Wifi Smart Switch with Energy Monitoring -69 SYF05 | Sunyesmart SYF05 RGBWW Wifi Led Bulb -70 Sonoff L1 | Sonoff L1 light strip -71 Sonoff iFan03 | Sonoff iFan03 Wifi Smart Ceiling Fan with Light -72 EXS Dimmer | EXS Wifi Dimmer v4 - -Over 500 additional devices are supported using [templates](TEMPLATES.md). - ## Provided Binary Downloads The following binary downloads have been compiled with ESP8266/Arduino library core version **2.6.1**. @@ -122,46 +41,15 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - **tasmota-display.bin** = The Display version without Energy Monitoring but adds display support. - **tasmota-minimal.bin** = The Minimal version allows intermediate OTA uploads to support larger versions and does NOT change any persistent parameter. This version **should NOT be used for initial installation**. +[List](MODULES.md) of embedded modules. + [Complete list](BUILDS.md) of available feature and sensors. ## Changelog -### Version 7.1.0 Betty +### Version 7.1.1 Betty -- Remove update support for versions before 6.0 -- Remove driver xsns_12_ads1115_i2cdev replaced by xsns_12_ads1115 -- Remove most IR protocols from non dedicated IR firmware except NEC, RC5 and RC6 -- Change repository name from Sonoff-Tasmota to Tasmota and all code references from Sonoff to Tasmota -- Change documentation from wiki to [documentation repository](https://tasmota.github.io/docs/) by @Blakadder -- Change default GUI to dark theme -- Change ArduinoSlave to TasmotaSlave -- Change IRremoteESP8266 library to v2.7.1 -- Change supported PCF8574 I2C address range to 0x20 - 0x26 allowing other I2C devices with address 0x27 to be used at the same time -- Change supported PCF8574A I2C address range to 0x39 - 0x3F allowing other I2C devices with address 0x38 to be used at the same time -- Change supported MCP230xx I2C address range to 0x20 - 0x26 allowing other I2C devices with address 0x27 to be used at the same time -- Change Reset erase end address from as seen by SDK (getFlashChipSize) to full flash size (getFlashChipRealSize) -- Change new Fade system much smoother, Speed now up to 40 (#6942, #3714) -- Fix better control of RGB/White when ``SetOption37`` >128, added ``Dimmer1`` and ``Dimmer2`` commands (#6714) -- Fix random crash caused by UPNP flood -- Fix check deepsleep for valid values in Settings (#6961) -- Fix Wifi instability when light is on, due to ``Sleep 0`` (#6961, #6608) -- Fix auto-power on/off when setting channel to non-zero or zero value, when ``SetOption68 1`` -- Fix postpone saving settings to flash until Fade is complete, avoids pause in Fade -- Add support for Tuya battery powered devices (#6735) -- Add support for Honeywell I2C HIH series Humidity and Temperetaure sensor (#6808) -- Add support for Honeywell HPMA115S0 particle concentration sensor by David Hunt (#6843) -- Add support for I2C sensor TLS2591 Light Intensity sensor (#6873) -- Add command ``SetOption73 0/1`` to re-enable HTTP Cross-Origin Resource Sharing (CORS) now default disabled (#6767) -- Add command ``SetOption74 0/1`` to enable DS18x20 internal pull-up and remove define DS18B20_INTERNAL_PULLUP (#6795) -- Add command ``SetOption75 0/1`` to switch between grouptopic (0) using fulltopic replacing %topic% or (1) is cmnd/\ (#6779) -- Add command ``SetOption76 0/1`` to enable incrementing bootcount when deepsleep is enabled (#6930) -- Add command ``SetOption77 0/1`` to keep power on when slider is far left -- Add command ``I2cDriver`` for I2C driver runtime control using document I2CDEVICES.md -- Add command ``TempOffset -12.6 .. 12.6`` to set global temperature sensor offset (#6958) -- Add command ``WebColor19`` to control color of Module and Name (#6811) -- Add command ``WifiPower 0 .. 20.5`` to set Wifi Output Power which will be default set to 17dBm -- Add frequency to ADE7953 energy monitor as used in Shelly 2.5 by ljakob (#6778) -- Add hide Alexa objects with friendlyname starting with '$' (#6722, #6762) -- Add Zigbee command support, considered as v1.0 for full Zigbee support -- Add hardware detection to be overruled with ``SetOption51`` (#6969) -- Add Colorpicker to WebUI by Christian Staars (#6984) +- Fix slider for devices with one or two channels like only white or white/yellow +- Fix TasmotaSlave buffer overrun on Tele +- Fix light scheme 4 speed (#7072) +- Add support for TasmotaSlave executing commands on Tasmota diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index e9949c4f5..112df96ba 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,5 +1,11 @@ ## Unreleased (development) +## Released + +### 7.1.1 20191201 + +- Maintenance Release + ### 7.1.0.1 20191130 - Fix slider for devices with one or two channels like only white or white/yellow @@ -7,8 +13,6 @@ - Fix light scheme 4 speed (#7072) - Add support for TasmotaSlave executing commands on Tasmota -## Released - ### 7.1.0 20191129 - Release diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index 7484f5bc9..eac271bd0 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x07010001; +const uint32_t VERSION = 0x07010100; #endif // _TASMOTA_VERSION_H_ From 302f0f6fdaf77129c210d57b76f66854d2f24215 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 1 Dec 2019 13:22:23 +0100 Subject: [PATCH 34/50] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cd99f948a..7b101df63 100644 --- a/README.md +++ b/README.md @@ -76,19 +76,19 @@ For a database of supported devices see [Tasmota Device Templates Repository](ht If you're looking for support on **Tasmota** there are some options available: -### Documentation: +### Documentation * [Documentation Site](https://tasmota.github.io/docs): For information on how to flash Tasmota, configure, use and expand it * [FAQ and Troubleshooting](https://tasmota.github.io/docs/#/help/): For information on common problems and solutions. * [Commands Information](https://tasmota.github.io/docs/#/Commands): For information on all the commands supported by Tasmota. -### Support's Community: +### Support's Community * [Tasmota Forum](https://groups.google.com/d/forum/sonoffusers): For usage and discussions. * [Tasmota Support Chat](https://discord.gg/Ks2Kzd4): For support, troubleshooting and general questions. You have better chances to get fast answers from members of the Tasmota Community. * [Search in Issues](https://github.com/arendst/Tasmota/issues): You might find an answer to your question by searching current or closed issues. -### Developers' Community: +### Developers' Community * [Bug Report](https://github.com/arendst/Tasmota/issues/new?template=Bug_report.md): For reporting Bugs of Tasmota Software. * [Feature Request](https://github.com/arendst/Tasmota/issues/new?template=Feature_request.md): For requesting features/functions to Tasmota Software. From bea001968f98026f58368506a057f1370157b5a7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 1 Dec 2019 13:38:24 +0100 Subject: [PATCH 35/50] Bump version 7.1.1.1 --- tasmota/CHANGELOG.md | 4 ++++ tasmota/tasmota_version.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 112df96ba..14bdeba9a 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,5 +1,9 @@ ## Unreleased (development) +### 7.1.1.1 20191201 + +- Version bump + ## Released ### 7.1.1 20191201 diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index eac271bd0..54e4c165f 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x07010100; +const uint32_t VERSION = 0x07010101; #endif // _TASMOTA_VERSION_H_ From d9e20497da04607b34bc7b348f3ef40894ce206e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 1 Dec 2019 18:19:17 +0100 Subject: [PATCH 36/50] Change light color schemes 2, 3 and 4 Change light color schemes 2, 3 and 4 from color wheel to Hue driven --- tasmota/CHANGELOG.md | 2 +- tasmota/xdrv_04_light.ino | 42 ++++++++++----------------------------- 2 files changed, 11 insertions(+), 33 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 14bdeba9a..6ce18c917 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -2,7 +2,7 @@ ### 7.1.1.1 20191201 -- Version bump +- Change light color schemes 2, 3 and 4 from color wheel to Hue driven ## Released diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index b50d8e4df..8b6b96bbd 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -241,8 +241,8 @@ struct LIGHT { uint8_t last_color[LST_MAX]; uint8_t color_remap[LST_MAX]; - uint8_t wheel = 0; - uint8_t random = 0; + uint16_t wheel = 0; + uint16_t random = 0; uint8_t subtype = 0; // LST_ subtype uint8_t device = 0; uint8_t old_power = 1; @@ -1510,33 +1510,6 @@ void LightPreparePower(power_t channels = 0xFFFFFFFF) { // 1 = only RGB, 2 = LightState(0); } -void LightWheel(uint8_t wheel_pos) -{ - wheel_pos = 255 - wheel_pos; - if (wheel_pos < 85) { - Light.entry_color[0] = 255 - wheel_pos * 3; - Light.entry_color[1] = 0; - Light.entry_color[2] = wheel_pos * 3; - } else if (wheel_pos < 170) { - wheel_pos -= 85; - Light.entry_color[0] = 0; - Light.entry_color[1] = wheel_pos * 3; - Light.entry_color[2] = 255 - wheel_pos * 3; - } else { - wheel_pos -= 170; - Light.entry_color[0] = wheel_pos * 3; - Light.entry_color[1] = 255 - wheel_pos * 3; - Light.entry_color[2] = 0; - } - Light.entry_color[3] = 0; - Light.entry_color[4] = 0; - float dimmer = 100 / (float)Settings.light_dimmer; - for (uint32_t i = 0; i < LST_RGB; i++) { - float temp = (float)Light.entry_color[i] / dimmer + 0.5f; - Light.entry_color[i] = (uint8_t)temp; - } -} - void LightCycleColor(int8_t direction) { if (Light.strip_timer_counter % (Settings.light_speed * 2)) { @@ -1545,14 +1518,19 @@ void LightCycleColor(int8_t direction) if (0 == direction) { if (Light.random == Light.wheel) { - Light.random = random(255); + Light.random = random(358) +1; // Random Hue } Light.wheel += (Light.random < Light.wheel) ? -1 : 1; } else { Light.wheel += direction; } - LightWheel(Light.wheel); - memcpy(Light.new_color, Light.entry_color, sizeof(Light.new_color)); + if (Light.wheel > 359) { Light.wheel = 1; } // Loop Hue colors + if (Light.wheel < 1) { Light.wheel = 359; } // Loop Hue colors + + uint8_t sat; + light_state.getHSB(nullptr, &sat, nullptr); // Allow user control over Saturation + light_state.setHS(Light.wheel, sat); + light_controller.calcLevels(Light.new_color); } void LightSetPower(void) From 3b662ee88e88a90e9bf43f94dae869e77ab835d3 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sun, 1 Dec 2019 19:00:52 +0100 Subject: [PATCH 37/50] Fix Zigbee uses Hardware Serial if GPIO 1/3 or GPIO 13/15 and SerialLog 0 (#7071) --- tasmota/CHANGELOG.md | 1 + tasmota/xdrv_23_zigbee_9_impl.ino | 23 ++++------------------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 6ce18c917..9fa9a880b 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,6 +3,7 @@ ### 7.1.1.1 20191201 - Change light color schemes 2, 3 and 4 from color wheel to Hue driven +- Fix Zigbee uses Hardware Serial if GPIO 1/3 or GPIO 13/15 and SerialLog 0 (#7071) ## Released diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index 1cd3955ce..cb08eeaee 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -25,16 +25,8 @@ const uint32_t ZIGBEE_BUFFER_SIZE = 256; // Max ZNP frame is SOF+LEN+CMD1+CMD2+ const uint8_t ZIGBEE_SOF = 0xFE; const uint8_t ZIGBEE_SOF_ALT = 0xFF; -//#define Z_USE_SOFTWARE_SERIAL - -#ifdef Z_USE_SOFTWARE_SERIAL -#include -SoftwareSerial *ZigbeeSerial = nullptr; -#else #include TasmotaSerial *ZigbeeSerial = nullptr; -#endif - const char kZigbeeCommands[] PROGMEM = "|" D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" @@ -185,9 +177,7 @@ void ZigbeeInput(void) char hex_char[(zigbee_buffer->len() * 2) + 2]; ToHex_P((unsigned char*)zigbee_buffer->getBuffer(), zigbee_buffer->len(), hex_char, sizeof(hex_char)); -#ifndef Z_USE_SOFTWARE_SERIAL AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "Bytes follow_read_metric = %0d"), ZigbeeSerial->getLoopReadMetric()); -#endif // buffer received, now check integrity if (zigbee_buffer->len() != zigbee_frame_len) { // Len is not correct, log and reject frame @@ -224,21 +214,16 @@ void ZigbeeInit(void) zigbee.active = false; if ((pin[GPIO_ZIGBEE_RX] < 99) && (pin[GPIO_ZIGBEE_TX] < 99)) { AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("Zigbee: GPIOs Rx:%d Tx:%d"), pin[GPIO_ZIGBEE_RX], pin[GPIO_ZIGBEE_TX]); -#ifdef Z_USE_SOFTWARE_SERIAL - ZigbeeSerial = new SoftwareSerial(); - ZigbeeSerial->begin(115200, pin[GPIO_ZIGBEE_RX], pin[GPIO_ZIGBEE_TX], SWSERIAL_8N1, false, 256); // ZNP is 115200, RTS/CTS (ignored), 8N1 - ZigbeeSerial->enableIntTx(false); - zigbee_buffer = new SBuffer(ZIGBEE_BUFFER_SIZE); -#else - ZigbeeSerial = new TasmotaSerial(pin[GPIO_ZIGBEE_RX], pin[GPIO_ZIGBEE_TX], 0, 0, 256); // set a receive buffer of 256 bytes + // if seriallog_level is 0, we allow GPIO 13/15 to switch to Hardware Serial + ZigbeeSerial = new TasmotaSerial(pin[GPIO_ZIGBEE_RX], pin[GPIO_ZIGBEE_TX], seriallog_level ? 1 : 2, 0, 256); // set a receive buffer of 256 bytes ZigbeeSerial->begin(115200); if (ZigbeeSerial->hardwareSerial()) { ClaimSerial(); - zigbee_buffer = new PreAllocatedSBuffer(sizeof(serial_in_buffer), serial_in_buffer); + uint32_t aligned_buffer = ((uint32_t)serial_in_buffer + 3) & ~3; + zigbee_buffer = new PreAllocatedSBuffer(sizeof(serial_in_buffer) - 3, (char*) aligned_buffer); } else { zigbee_buffer = new SBuffer(ZIGBEE_BUFFER_SIZE); } -#endif zigbee.active = true; zigbee.init_phase = true; // start the state machine zigbee.state_machine = true; // start the state machine From 1692241b25148af2cf616ceb33e2ba1fa5b56cd4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 1 Dec 2019 19:03:53 +0100 Subject: [PATCH 38/50] Fix lost functionality of GPIO9 and GPIO10 - Remove inconsistent hardware detection introduced in version 7.0.0.5 - Fix lost functionality of GPIO9 and GPIO10 on some devices (#7080) --- tasmota/CHANGELOG.md | 2 ++ tasmota/support.ino | 28 +--------------------------- tasmota/support_command.ino | 5 ++--- 3 files changed, 5 insertions(+), 30 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 6ce18c917..309ea6e63 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -2,6 +2,8 @@ ### 7.1.1.1 20191201 +- Remove inconsistent hardware detection introduced in version 7.0.0.5 +- Fix lost functionality of GPIO9 and GPIO10 on some devices (#7080) - Change light color schemes 2, 3 and 4 from color wheel to Hue driven ## Released diff --git a/tasmota/support.ino b/tasmota/support.ino index 55c01b71d..1e639494b 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -521,32 +521,6 @@ char* GetPowerDevice(char* dest, uint32_t idx, size_t size) return GetPowerDevice(dest, idx, size, 0); } -bool IsEsp8285(void) -{ - // esptool.py get_efuses - uint32_t efuse1 = *(uint32_t*)(0x3FF00050); - uint32_t efuse2 = *(uint32_t*)(0x3FF00054); -// uint32_t efuse3 = *(uint32_t*)(0x3FF00058); -// uint32_t efuse4 = *(uint32_t*)(0x3FF0005C); - - bool is_8285 = ( (efuse1 & (1 << 4)) || (efuse2 & (1 << 16)) ); - if (is_8285 && (ESP.getFlashChipRealSize() > 1048576)) { - is_8285 = false; // ESP8285 can only have 1M flash - } - return is_8285; -} - -String GetDeviceHardware(void) -{ - char buff[10]; - if (IsEsp8285()) { - strcpy_P(buff, PSTR("ESP8285")); - } else { - strcpy_P(buff, PSTR("ESP8266EX")); - } - return String(buff); -} - float ConvertTemp(float c) { float result = c; @@ -1039,7 +1013,7 @@ uint8_t ValidPin(uint32_t pin, uint32_t gpio) if (FlashPin(pin)) { result = GPIO_NONE; // Disable flash pins GPIO6, GPIO7, GPIO8 and GPIO11 } - if (!IsEsp8285() && !Settings.flag3.user_esp8285_enable) { // SetOption51 - Enable ESP8285 user GPIO's + if ((WEMOS == Settings.module) && !Settings.flag3.user_esp8285_enable) { // SetOption51 - Enable ESP8285 user GPIO's if ((pin == 9) || (pin == 10)) { result = GPIO_NONE; // Disable possible flash GPIO9 and GPIO10 } diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index fe8640045..e5c19c0e0 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -376,10 +376,9 @@ void CmndStatus(void) if ((0 == payload) || (2 == payload)) { Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS2_FIRMWARE "\":{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\",\"" - D_JSON_BOOTVERSION "\":%d,\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"," - "\"Hardware\":\"%s\"}}"), + D_JSON_BOOTVERSION "\":%d,\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"}}"), my_version, my_image, GetBuildDateAndTime().c_str(), - ESP.getBootVersion(), ESP.getSdkVersion(), GetDeviceHardware().c_str()); + ESP.getBootVersion(), ESP.getSdkVersion()); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "2")); } From 1a476ab9b55f58a9ca8f7c0922ce3e6a85c66d70 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 1 Dec 2019 19:09:57 +0100 Subject: [PATCH 39/50] Update release notes --- RELEASENOTES.md | 10 +++++----- tasmota/CHANGELOG.md | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 1ea030e6a..cc067d531 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -47,9 +47,9 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 7.1.1 Betty +### Version 7.1.1.1 Betty -- Fix slider for devices with one or two channels like only white or white/yellow -- Fix TasmotaSlave buffer overrun on Tele -- Fix light scheme 4 speed (#7072) -- Add support for TasmotaSlave executing commands on Tasmota +- Remove inconsistent hardware detection introduced in version 7.0.0.5 +- Fix lost functionality of GPIO9 and GPIO10 on some devices (#7080) +- Fix Zigbee uses Hardware Serial if GPIO 1/3 or GPIO 13/15 and SerialLog 0 (#7071) +- Change light color schemes 2, 3 and 4 from color wheel to Hue driven diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 59d07df72..4e798c754 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -4,8 +4,8 @@ - Remove inconsistent hardware detection introduced in version 7.0.0.5 - Fix lost functionality of GPIO9 and GPIO10 on some devices (#7080) -- Change light color schemes 2, 3 and 4 from color wheel to Hue driven - Fix Zigbee uses Hardware Serial if GPIO 1/3 or GPIO 13/15 and SerialLog 0 (#7071) +- Change light color schemes 2, 3 and 4 from color wheel to Hue driven ## Released From 6475e15b1c1ec9dfd444479897462a1c51b5dbed Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Sun, 1 Dec 2019 15:18:24 -0300 Subject: [PATCH 40/50] Delete faulty Portisch Firmware As reported in #7064 this version hungs when using rfraw. Using previous one works fine. --- .../fw_efm8bb1/RF-Bridge-EFM8BB1-20191006.hex | 491 ------------------ 1 file changed, 491 deletions(-) delete mode 100644 tools/fw_efm8bb1/RF-Bridge-EFM8BB1-20191006.hex diff --git a/tools/fw_efm8bb1/RF-Bridge-EFM8BB1-20191006.hex b/tools/fw_efm8bb1/RF-Bridge-EFM8BB1-20191006.hex deleted file mode 100644 index c8cb43003..000000000 --- a/tools/fw_efm8bb1/RF-Bridge-EFM8BB1-20191006.hex +++ /dev/null @@ -1,491 +0,0 @@ -:020000040000FA -:100000000210D8A2029290A2029280AD40AC3F7F33 -:100010000A7E0012002E12001DA202B322E59120DA -:10002000E2FB220210487597A5222202141B8E4182 -:100030008F428C438D4412163112188EE54424BF32 -:100040009000E8F0E54334FF9000E7F09000E3E52E -:1000500041F0A3E542F043910422220211671219F4 -:100060002253D87853DAFE1218F3E4900087F02276 -:10007000D2DE2202146E1217C0C290C296C280E471 -:10008000FBFD7F101218DA12053174A4F0D2AF1202 -:10009000170AD2969000ECE004F070069000EBE0B6 -:1000A00004F09000EBE0B427E9A3E0B410E4C296BA -:1000B0001200263003091216B18E228F2380067596 -:1000C0002201752300E5237004E522640170469047 -:1000D00000DEE0700612170B0202959000EBE4754B -:1000E000F001120807FED3E5F09410EE94274002C9 -:1000F000D296D39000ECE094309000EBE0947550F1 -:1001000003020295E4F0A3F09000DEF0900099F075 -:10011000C29602029512170A9000DEE014602A14BB -:1001200070030202591470030202171470030202D2 -:100130003024046003020295E52364AA60030202EE -:10014000959000DE04F0020295E523900099F0906E -:1001500000DE7402F0E52312092F0201A0017FA145 -:10016000018BA501A9A601BDA701C6A801DDA901B2 -:10017000CCB001D5B1019DC00295FF0000020C1268 -:10018000051EE490008AF07FA1806512054E900064 -:10019000EA7408F0E4F52575240902029512054E6B -:1001A000E4F52575240202029590008A7401F07F1F -:1001B000A61215A690007974A6F0020295120531D8 -:1001C00074A4F00202959000EA7408F09000DE74C6 -:1001D00003F00202957FB112056202029512051E1C -:1001E00090008AE09000E9F090008A7401F07FA905 -:1001F0001205627D307C757F017E00121797020226 -:100200009512056B900079EFF0E48005E490009979 -:10021000F09000DEF0807EE4F525E523F524E5246A -:10022000D39400402C12005E9000DE7404F08065D0 -:1002300074032525F582E43400F583E523F00525D4 -:10024000E525B52402800AE525C39470404775244E -:10025000709000DE7402F0803CE5236455703690A7 -:1002600000DEF0C203900099E02460601B24FC6073 -:100270001224FE600E14600B24F760101460042436 -:100280001070127FA0121875D2038009900004E04C -:10029000049000EAF0900099E012092F02BEA10339 -:1002A00033A40377A50333A60447A802BEA9047CA0 -:1002B000B004E5B1041EC00442FF000000B090008D -:1002C00086E030E73F7DC87C0012053F900099E052 -:1002D0002457600E2408701F12056B7FA31215ECC3 -:1002E00080159000E9E090008AF0900079E0FF121C -:1002F00015A67FAB12057CE4900086F043DA01D2AC -:10030000030200B01218EB50207DE87C0312053F79 -:10031000900099E02457600C240860030200B07F2D -:10032000A20204D77FAA0204D71205744003020078 -:10033000B0802E900086E030E71F900099E0245AAC -:10034000600F240260030204F17FA41215EC020482 -:10035000F17FA612057C0204F1120574400302002D -:10036000B01216E7C006C0071216F69200D007D0EA -:10037000061209810200B09000DEE060030200B0C6 -:100380001217127003020411240560030200B01258 -:100390000558900005E0FFA3E090008BCFF0A3EF9D -:1003A000F0900007E0FFA3E090008DCFF0A3EFF006 -:1003B000900003E0FFA3E090008FCFF0A3EFF07B6D -:1003C000017A00798B901A0EE493FC740193FD90EE -:1003D0001A10E493F52E1217028E2FF530901A138F -:1003E000E493F5311217028E32F533901A16E49326 -:1003F000F5341217028E35F536901A19E493F53755 -:10040000A3E493F538753900753A09120EBC020061 -:10041000B09000EAE07063C2807FA00204D7900031 -:10042000DEE060030200B0900003E0FCA3E0FD7F8B -:10043000017E00121797D29612001DC2967FA0026D -:1004400004D77F030204D79000DEE060030200B00F -:100450001217126019240560030200B012055890AB -:100460000003E0FF7C007D041213570200B09000EF -:10047000EAE07006C2807FA0805D80619000DEE0CF -:1004800060030200B01217126043240560030200EB -:10049000B09000EAE014F012005E7E007F05C00616 -:1004A000C007900003E0FB25E0FFE433FE74052F56 -:1004B000F58274003EAD82FCEB25E0FFE52424FECE -:1004C000C39FFBD007D006120FA70200B09000EA2E -:1004D000E0700AC2807FA01218680200B0E49000A9 -:1004E00087F00200B0900086E030E7107FB1121173 -:1004F000ECE4900086F043DA010200B07E007FED6C -:1005000012151040030200B01216E7C006C0071211 -:1005100016F69200D007D006120D160200B07D32FA -:100520007C007F017E00121797D29612001DC296A2 -:1005300022E490008AF07FA41215A6900079227F11 -:10054000017E00121797D29612001DC29622120049 -:100550005E9000DE7404F0229000EAE014F01200D5 -:100560005E221215A6900079EFF022900079E0FF4C -:100570001215A6227E007FED12151022900086E053 -:10058000547FFD12155B228F29E4F536EF25E02517 -:10059000E02468F8E6701EEF25E025E02469F8768F -:1005A000087E007F707D007B017A00790312095577 -:1005B000E490007AF0AB2CAA2DA92EC001120B6793 -:1005C0002466F9E7540F120CA3120B86D001121403 -:1005D000C1503D120B672466F9E7540FFF120CA3BC -:1005E000120C90300101B34031EF700A900077E5B2 -:1005F0002AF0A3E52BF0120B67120CAF2401FFEFDA -:10060000FEEC54F04EFEEDFF120B67120C9A800ABE -:10061000120B672466F874F056F6AB2CAA2DA92E9F -:10062000C001120B67120CBB120BD1120CC7120BBC -:1006300086D0011214C15052120B67120CBB120B60 -:10064000D1FF120CC75408FE120C92300101B340C6 -:1006500043EF700A900088E52AF0A3E52BF0120B17 -:1006600067120BC22401FFE433FEEFC4F8540FC835 -:1006700068FFEEC454F048FEED540FFDEC4EFEED65 -:100680004FFF120B67120C9A800A120B672467F84F -:10069000740F56F6120B67120CAFFB700F120BCAD9 -:1006A000700A120B4D2469F8E4F6C322120B67247A -:1006B00068F8E53514667003753601C3E531953683 -:1006C0006B7020D290120B672466F874F056F674A3 -:1006D0000F0856120B662468F806120B672469F897 -:1006E00016804C120B67120BC2FFC3E53495366FB0 -:1006F000703DD290120B672466F8EC54F0FEED5476 -:100700000FA60608120B662468F806120B67246908 -:10071000F816120B67120BD8E0FF120B672469F86A -:10072000E6FE7401A806088002C333D8FC4FF0121D -:100730000B672469F8E67017120B67120BD8120CBE -:100740004CFF12182DEFF0120B672469F87608128F -:100750000B672468F8E6C3953540311218E350055D -:10076000E4900085F0120C4960181218F37D207C8B -:10077000037F017E0012176E120CD3A3E529F0440B -:1007800080F0120B4D2469F8E4F6D322C322BB019A -:100790000689828A83F0225002F722BBFE01F322EF -:1007A000EF8DF0A4A8F0CF8CF0A428CE8DF0A42E6D -:1007B000FE22BC000BBE0029EF8DF084FFADF022BD -:1007C000E4CCF875F008EF2FFFEE33FEEC33FCEECF -:1007D0009DEC984005FCEE9DFE0FD5F0E9E4CEFDC2 -:1007E00022EDF8F5F0EE8420D21CFEADF075F00895 -:1007F000EF2FFFED33FD4007985006D5F0F222C3EE -:1008000098FD0FD5F0EA22C5F0F8A3E028F0C5F076 -:10081000F8E582158270021583E038F022BB0110E2 -:10082000E58229F582E5833AF583E0F5F0A3E0223D -:100830005009E92582F886F008E622BBFE0AE92580 -:1008400082F8E2F5F008E222E5832AF583E993F5E0 -:10085000F0A3E9932275F008758200EF2FFFEE33C5 -:10086000FECD33CDCC33CCC58233C5829BED9AEC23 -:1008700099E58298400CF582EE9BFEED9AFDEC998D -:10088000FC0FD5F0D6E4CEFBE4CDFAE4CCF9A88297 -:1008900022B800C1B90059BA002DEC8BF084CFCE3C -:1008A000CDFCE5F0CBF97818EF2FFFEE33FEED33FA -:1008B000FDEC33FCEB33FB10D703994004EB99FBC1 -:1008C0000FD8E5E4F9FA227818EF2FFFEE33FEEDAA -:1008D00033FDEC33FCC933C910D7059BE99A4007B7 -:1008E000EC9BFCE99AF90FD8E0E4C9FAE4CCFB22CE -:1008F00075F010EF2FFFEE33FEED33FDCC33CCC897 -:1009000033C810D7079BEC9AE899400AED9BFDECA1 -:100910009AFCE899F80FD5F0DAE4CDFBE4CCFAE4E0 -:10092000C8F922A42582F582E5F03583F58322D02B -:1009300083D082F8E4937012740193700DA3A39393 -:10094000F8740193F5828883E4737402936860EF0E -:10095000A3A3A380DFEF4E6012EF60010EEDBB0199 -:100960000B89828A83F0A3DFFCDEFA2289F050072C -:10097000F709DFFCA9F022BBFEFCF309DFFCA9F0BC -:10098000228E268F27E4F528C3E5279464E5269474 -:10099000005017E4F528E528120B922469F8E4F6D4 -:1009A0000528E528B40FEFC2902290008AE0147069 -:1009B00003020A6F046003020B4C7866E6C4540F0E -:1009C000F97065D3E5279494E52694115003020B42 -:1009D0004C300003020B4CE9120C32E6540FFC08B9 -:1009E000E6FDEC4E18F6ED08F618120C29EC540F43 -:1009F0004E18F6ED08F6900001E526F0A3E527F085 -:100A0000AE26FF7C007D1F1207B290008BEEF0A394 -:100A1000EFF07C007D031207A0A3EEF0A3EFF0A39C -:100A2000E526F0A3E527F0227866E6C4540F6402B9 -:100A30006003020B4C120CEB752C01752D00752E0A -:100A40008B901BD793FE7401938E2FF530901BD99A -:100A5000E493F531A3120BBB8E32F533901BDCE42B -:100A600093F534901BE0E493F535E4FF020587E449 -:100A7000F528120BA8120D0CFFE528120C54F9EF03 -:100A8000C399506EE528120C16F5828C832FF582DF -:100A9000E43583F583E493FF120C90300001B350EA -:100AA00003020B40E528C454F024D1F582E4341B42 -:100AB000120C20F5828C83EF540775F00212092383 -:100AC000120C22FDAF27AE261214CBE528501925B3 -:100AD000E025E02466F8120C29EC540F4EFEEDFFE1 -:100AE000120BA8120C9A8058120B922469F8E4F6A3 -:100AF000804E120BA8120D0C697045120CEBE52804 -:100B0000120BAFAA06752CFF8A2DF52EE528120CC4 -:100B1000F6120BB98E2FF530E528120C63F531E58E -:100B200028120D01120BB98E32F533E528120C7222 -:100B3000F534E528120C81F535AF28120587400CF5 -:100B40000528E528C3940F5003020A7222C290E5DB -:100B50002925E025E02466F8E4F608F6E52925E0F5 -:100B600025E02468F8E4F6E52925E025E022F58370 -:100B7000E493FF5408FE131313541F24FF9202AB97 -:100B800029AA2AA92BEF540775F002A4F58285F053 -:100B9000832225E025E02466F8E4F608F6E528251A -:100BA000E025E02468F8E4F6E52825E025E022C405 -:100BB00054F024D1F582E4341BF583E493FE7401F0 -:100BC00093222466F8E6FC08E6FDECC4F854F0C86D -:100BD000EDC4540F48540F222468F8E6141313137D -:100BE000541F2403F582E43400F58322E529252BE4 -:100BF000F582E43528F583E022A200E433C43333E0 -:100C00003354804526FFE527900074CFF0A3EFF022 -:100C1000E490007BF022C454F024D4F582E4341B29 -:100C2000F583E493FC74019322E6FC08E6FDECC432 -:100C3000540F2401FFEFC454F0FE22E52E25E024DA -:100C40008BF582E43400F58322900085E0FF90006C -:100C50007AE06F22C454F024D6F582E4341BF58385 -:100C6000E49322C454F024D9F582E4341BF583E4E0 -:100C70009322C454F024DCF582E4341BF583E4931E -:100C800022C454F024E0F582E4341BF583E493227B -:100C90005408131313541F24FF222466F8A60608D1 -:100CA000A607222530F582E4352FF583E49322242C -:100CB00066F8E6FC08E6FDEC540F222466F9E7C46A -:100CC000F854F0C809E7222533F582E43532F5837C -:100CD000E4932290007AE0900085F053DAFE22251A -:100CE000E0247DF582E43400F58322A200920185A0 -:100CF000262A85272B22C454F024D7F582E4341BFE -:100D000022C454F024DAF582E4341B222466F8E687 -:100D1000FEEEC4540F228E268F27C3E5279464E588 -:100D20002694005003020EAA900087E024FE60255E -:100D3000147003020DB724036003020EAFC290AF1C -:100D400027AE2612185A4003020EAF120BF990007C -:100D5000877402F022120EB0503090007BE09404B1 -:100D60004021D290E4900000F0900073F0C2049013 -:100D7000007CF090007AF0900003F09000877403FC -:100D8000F08025E4900087F0801E900074E0547F8E -:100D9000FEA3E0FFD3E5279FE5269E4005120BF951 -:100DA000800690007BE004F090007BE0C394E0506C -:100DB00003020EAF020EAA90007CE004F090007BCC -:100DC000E0FFA3E0D39F4003020E587B007A007936 -:100DD00028AF27AE261212DF4022900000E0FF125B -:100DE0000C3DE526F0A3E527F08F28900000E004F5 -:100DF000F0E0D394074005E4900087F030041DA292 -:100E000000E433C43333335480FFE528C454F04F37 -:100E1000FF900073E0120BE2EFF08039900073E076 -:100E2000FF120BE2E0FEA200E43333333354F84503 -:100E300028FDEE4DF074032F120BE4120C4CFF1240 -:100E4000182DEFF0900073E004F0E0D394704005AB -:100E5000E4900087F0B20422120EB0504D1218E355 -:100E60005005E4900085F0120C49603A1218F37DA9 -:100E7000207C037F017E0012176E120CD3900003BA -:100E8000E0FD900074E05480FF900000E0C454F056 -:100E90004FFFED4F900003F0900074E0547FF0900E -:100EA0000086E04480F0C2908000E4900087F02249 -:100EB000A2009201AF27AE26121744228B298A2A5C -:100EC000892B8C2C8D2DE4F53D753E80F53BE53B63 -:100ED000C3952E5010E52D253BF582E4352C120FDD -:100EE0006C053B80E9E4F53BE53BC395385057E59D -:100EF0003A253DF582E43539F583E0553E7019F524 -:100F00003CE53CC39531502DE530253CF582E43578 -:100F10002F120F6C053C80E9E4F53CE53CC39534A9 -:100F20005013E533253CF582E43532120B6E120F77 -:100F30009B053C80E6E53EC313F53E7005053D7517 -:100F40003E80053B80A2E4F53BE53BC3953750135B -:100F5000E536253BF582E43535120B6E120F9B0505 -:100F60003B80E6C2909000877405F022F583E493FD -:100F7000FF5408FE131313541F24FF9202AB29AA37 -:100F80002AA92BEF540775F002A4F58285F083128D -:100F9000081DF54085F03F1200032212081DF540A0 -:100FA00085F03F120003228E268F278C288D298BF7 -:100FB0002AD200C201852982852883E05488D394EF -:100FC000004003D38001C39201E4F52BE52BC395C8 -:100FD0002A505930010D120BECC413131354012481 -:100FE000FF8002A2009202852782852683C083C0EB -:100FF00082120BECFFC45407D082D083121035301C -:10100000010C120BECFF131313541F138002A200E8 -:101010009202852782852683C083C082120BEC54FE -:1010200007D082D083121035052B80A0C29090008B -:10103000877405F02275F002120923E0F53FA3E062 -:10104000F540120003920022C0E0C0F0C083C082CD -:10105000C0D075D000C000C001C002C003C004C031 -:1010600005C006C007E5985403F545F45298E545D8 -:1010700030E01712192B9000DD121739EFF09000B5 -:10108000DDE004F0E0B44002E4F0E54530E12E900C -:1010900000E0E0D39400401A9000DCE02446F8E63B -:1010A000FF1219289000DCE004F09000E0E014F05A -:1010B0008002D2059000DCE0B42002E4F0D007D03A -:1010C00006D005D004D003D002D001D000D0D0D0BB -:1010D00082D083D0F0D0E03212005A787FE4F6D884 -:1010E000FD7581A1021122020076E493A3F8E49336 -:1010F000A34003F68001F208DFF48029E493A3F80B -:101100005407240CC8C333C4540F4420C88340047C -:10111000F456800146F6DFE4800B0102040810203B -:101120004080901266E47E019360BCA3FF543F3080 -:10113000E509541FFEE493A360010ECF54C025E0DF -:1011400060A840B8E493A3FAE493A3F8E493A3C897 -:10115000C582C8CAC583CAF0A3C8C582C8CAC58328 -:10116000CADFE9DEE780BEC0E0C0F0C083C082C055 -:10117000D075D000C000C001C002C003C004C005CB -:10118000C006C007E5D85487F521F452D8E5F730FA -:10119000E508E5F730E60312193253F7DFE52130B1 -:1011A000E708E5D930E003121931E52130E008E520 -:1011B000DA30E003121675E52130E108E5DB30E0B6 -:1011C00003121933E52130E208E5DC30E00312199F -:1011D00034D007D006D005D004D003D002D001D03F -:1011E00000D0D0D082D083D0F0D0E032AE07E4F58A -:1011F0002612180A900000E004FF12181112125F64 -:10120000900000E0FFE526C39F501412172BE05416 -:101210007FFF12181112172B121725052680E19057 -:101220000074E0547FFF12181190007412172512F9 -:10123000125FE4F526900073E0FFE526C39F501788 -:10124000740325261217190526E526541F70E61289 -:10125000192512191E80DE7F551218110219251248 -:10126000192512191E224200E500004200E100008B -:101270004200E700004200E30000C1834100860015 -:101280004100870041008A004100790042000100CE -:101290000042008800004200770000C10441007352 -:1012A000004100850041007A004100000048007DB7 -:1012B0000000000000000000410076004100DD0059 -:1012C0004100DF004100DB004100DC004100E000A4 -:1012D0004100DA00C1054100DE0041009900008EA6 -:1012E000298F2A8B2B8A2C892DE4F52E900000E083 -:1012F000FFE52EC39F505EE52AAE297803CEC313C7 -:10130000CE13D8F9FDAC06E52AAE297802CEC31378 -:10131000CE13D8F92DFFEE3CAB07FA120C3BE0FEE2 -:10132000A3E0FFC39BEE9A50028004AE02AF03AA73 -:1013300006AB07120C3BE0FCA3E0FDAF2AAE29127E -:1013400017E7500DAB2BAA2CA92DE52E12078ED333 -:1013500022052E8097C3228F268C278D28EF120B13 -:10136000AFAA06F97BFFEF120C16FDEF120C54F535 -:101370002EEF120CF6120BB98E2FF530EF120C6314 -:10138000F531EF120D01120BB98E32F533EF120C5D -:1013900072F534EFC454F024DDF582E4341B120BF3 -:1013A000B98E35F536EFC454F024DFF582E4341BF2 -:1013B000F583E493F537EF120C81F53885273985ED -:1013C000283A020EBC900076E0FDC4540F2401FBC5 -:1013D000E433FAED540FF96B7001EA603DE97010E7 -:1013E000E0C4540F2401FDE433FCED64044C602A96 -:1013F000900076E0C4540FFD540F120CDFEEF0A302 -:10140000EFF0ED04C454F049900076F0E0FFC454CE -:101410000FC394044004EF540FF022C0E0C083C017 -:1014200082C0D075D000C004C005C006C00753C834 -:101430007F9000E5E0FEA3E0FF4E700353C8FB90F1 -:1014400000E112166A50099000E5E4F0A3F0800D67 -:10145000C39000E6E09DF09000E5E09CF0D007D05E -:1014600006D005D004D0D0D082D083D0E032C0E006 -:10147000C083C082C0D075D000C004C005C006C003 -:101480000753917F9000E7E0FEA3E0FF4E70035307 -:1014900091FB9000E312166A50099000E7E4F0A374 -:1014A000F0800DC39000E8E09DF09000E7E09CF034 -:1014B000D007D006D005D004D0D0D082D083D0E0E1 -:1014C0003212081DFDACF0AF2BAE2A8F828E83AF97 -:1014D00005AE041218A6AB07AA06D3EB94F4EA945F -:1014E0000140067E017FF48004AE02AF03AA06AB82 -:1014F00007C3EB9464EA940050067E007F64800486 -:10150000AE02AF03AA06AB07AF82AE831217E72283 -:10151000AD07AC06ABDA900076E0FEC4540FFFEEE8 -:10152000540FFEB50702C32253DAFE900076E0FAAC -:10153000EE120CDFE0FFA3E08D828C83CFF0A3EFEF -:10154000F0EA54F0FF900076E0044FF0540FC3949B -:10155000044004E054F0F08BDAD322AE05AD07E48A -:10156000FCFB7FAA121811AF05121811EEC454F03B -:1015700024A6F582E4341DF583E493FFECC39F5069 -:101580000774082CFC0B80F4EB04FF12180CE4FC2D -:10159000ECC39B500974032C1217190C80F27F5571 -:1015A0001218110219258F26900079E0F5277E0088 -:1015B0007F3C7D007B007A0079661209557F0B1213 -:1015C000192E43DA011200707D0A7C007F017E0033 -:1015D00012179712001DE4900087F0900086F0909B -:1015E0000099E526F0900079F0AF2722AE07E4FDE0 -:1015F000F52612180A900001E0FF12181190000160 -:10160000121725900077E0FF12181190007712173B -:1016100025900088E0FF1218119000881217257499 -:10162000032D1217190DBD03F67F5512181102195B -:1016300025AB07AA06E4F9F87F407E427D0FFC1235 -:101640000891A804A905AA06AB077F207ED77D755F -:101650007C01120891C3E49FFFE49EFE22AB07AA1F -:1016600006E4F9F87FE87E03FD22E0FCA3E0FDC379 -:10167000EF9DEE9C22AFFBAEFC7C007D0A1207A022 -:10168000AD07AC06AFD953D9BFE4F5FAF5F98FD958 -:10169000C3EC948050157F002093027F01EFC43388 -:1016A000333354804CFEEDFF0213C5E4900076F016 -:1016B000229000DDE0FF9000DBE0B507057E017FB2 -:1016C00000229000DB121739E0FD7C009000DBE087 -:1016D00004F0E0B44002E4F09000DAE0FEEE4204F0 -:1016E000E4F0AE04AF05229000EDE0FCA3E0FDECD9 -:1016F000547FFEAF0522EC5480C41313135401240D -:10170000FF22A3E493FE74019322E49000EBF0A384 -:10171000F022900087E024FB22F582E43400F58378 -:10172000E0FF021811A3E0FF021811E52625E024CE -:101730008BF582E43400F58322E0249AF582E434C8 -:1017400000F58322AD07AC06900074E0FAA3E0FB3D -:10175000EA5480C413131354017005300102C322EC -:10176000AF05AE04EA547FFCAD031214CB228E37D2 -:101770008F388C398D3A12165D12163E12188290EF -:1017800000E5E539F0A3E53AF09000E1E537F0A394 -:10179000E538F043C804228E288F298C2A8D2B121D -:1017A000165D12163E12188E9000E7E52AF0A3E5AA -:1017B0002BF09000E3E528F0A3E529F04391042203 -:1017C00012002A1218FA1219011218B2121916125E -:1017D00018441218D01218BC1218C612189A1219EE -:1017E0000812191A02190FC3ED9BF582EC9AF583C2 -:1017F000C3E5829FE5839E500FED2BFDEC3AFCC3C1 -:10180000EF9DEE9C50028001C3227FAA121811AFF7 -:1018100006C2059000DFE0B42002E4F09000DFE0B3 -:101820002446F8A607E004F0A3E004F0227E1DE4BD -:10183000FDEF30E70625E06EFF8004EF25E0FF0DA9 -:10184000BD08EE22AF885388AF758CA0758DCBEFA5 -:101850005440FEEF54104E428822C3EF942CEE9475 -:10186000014003D38001C322121875D2039000797E -:10187000E0FF0215A6AE0712180A7F5512181102D2 -:101880001925AD07AC06ECF5CBAF058FCA22AD0725 -:10189000AC06ECF593AF058F9222C2DE75D90575C3 -:1018A000F9FF75960122EF7802CEC313CE13D8F953 -:1018B000FF2275E34075E10175E20122E5915404D0 -:1018C0005391FB429122758E547589224388502290 -:1018D000E5C8540453C8FB42C82253984FEB4F4D00 -:1018E000F59822E5C8C320E201D322E591C320E2A6 -:1018F00001D32253C8FB53C87F2275A41175D4CFDE -:101900002275A54175D5772253F77F75DA30227598 -:10191000E69075A8B022E4F5A9224398102230057C -:10192000FD22C2DE22D299228F9922AF99228F8C7A -:101930002222222222015E041A2A620802080109D8 -:1019400000019004B00BB81C520A03080109000101 -:10195000C20384286E020800090108014A02762A9F -:101960004E020800090108028A1E82071C0F8C081B -:101970000108020803016802D012C005DC0A03084E -:10198000010900024E05DC01AE348A0A0308010990 -:1019900000012C0A00008C047E27F60801080308C9 -:1019A0000208020803080401040A9A051428A00882 -:1019B000010800080208020800080301720438192F -:1019C00082020801080009029407D00FA02328080A -:1019D00003080108020801061802D000D208010A13 -:1019E0000109020A0101D603FC0BFE0208010800EE -:1019F00009019002D0132E010A00090108023007E4 -:101A0000760F322274030801080208193503193BC6 -:101A100002193D02193F020000001819410419493A -:101A200002194B02194D0200000018194F031955F5 -:101A30000219570219590200000018195B031961B5 -:101A4000021963021965020000000C196704196F7E -:101A50000219710219730200000028197504197D1A -:101A600002197F0219810200000028198304198BD2 -:101A700002198D02198F0200000018199105199B97 -:101A800002199D0419A10419A5022019A70419AF70 -:101A90000219B10419B50419B9022019BB0319C1FF -:101AA0000219C30219C5020000001119C70419CF99 -:101AB0000219D10219D30219D5022419D70319DD4D -:101AC0000219DF0219E10219E3022819E50319EBF3 -:101AD0000219ED0219EF020000001419F10319F7C1 -:101AE0000219F90219FB020000002719FD041A056A -:101AF000021A07021A090200000024015E041A2AD1 -:101B000062080208010900019004B00BB81C520AD7 -:101B1000030801090001C20384286E0208000901BC -:101B200008014A02762A4E020800090108028A1EAC -:101B300082071C0F8C080108020803016802D012FA -:101B4000C005DC0A0308010900024E05DC01AE34C1 -:101B50008A0A0308010900012C0A00008C047E2770 -:101B6000F608010803080208020803080401040A31 -:101B70009A051428A00801080008020802080008B5 -:101B8000030172043819820208010800090294074F -:101B9000D00FA02328080308010802080106180234 -:101BA000D000D208010A0109020A0101D603FC0B88 -:101BB000FE020801080009019002D0132E010A005C -:101BC000090108023007760F322274030801080267 -:101BD000081AFB031B01021B03021B050200000085 -:101BE000181B07041B0F021B11021B13020000002D -:101BF000181B15031B1B021B1D021B1F02000000EC -:101C0000181B21031B27021B29021B2B02000000AB -:101C10000C1B2D041B35021B37021B390200000070 -:101C2000281B3B041B43021B45021B47020000000C -:101C3000281B49041B51021B53021B5502000000C4 -:101C4000181B57051B61021B63041B67041B6B02F7 -:101C5000201B6D041B75021B77041B7B041B7F027A -:101C6000201B81031B87021B89021B8B02000000C3 -:101C7000111B8D041B95021B97021B99021B9B02D3 -:101C8000241B9D031BA3021BA5021BA7021BA90269 -:101C9000281BAB031BB1021BB3021BB502000000E3 -:101CA000141BB7031BBD021BBF021BC102000000B7 -:101CB000271BC3041BCB021BCD021BCF020000005D -:101CC00024015E041A2A6208020801090001900436 -:101CD000B00BB81C520A030801090001C203842892 -:101CE0006E020800090108014A02762A4E02080025 -:101CF000090108028A1E82071C0F8C0801080208CD -:101D000003016802D012C005DC0A030801090002C1 -:101D10004E05DC01AE348A0A0308010900012C0AD1 -:101D200000008C047E27F608010803080208020858 -:101D300003080401040A9A051428A00801080008F1 -:101D4000020802080008030172043819820208011F -:101D5000080009029407D00FA023280803080108EF -:101D6000020801061802D000D208010A0109020A7D -:101D70000101D603FC0BFE020801080009019002D4 -:101D8000D0132E010A00090108023007760F322213 -:101D9000740308010802081CC1031CC7021CC90205 -:101DA0001CCB02000000181CCD041CD5021CD7025D -:101DB0001CD902000000181CDB031CE1021CE3021A -:101DC0001CE502000000181CE7031CED021CEF02DA -:101DD0001CF1020000000C1CF3041CFB021CFD02A1 -:101DE0001CFF02000000281D01041D09021D0B023A -:101DF0001D0D02000000281D0F041D17021D1902F1 -:101E00001D1B02000000181D1D051D27021D2904B1 -:101E10001D2D041D3102201D33041D3B021D3D04F8 -:101E20001D41041D4502201D47031D4D021D4F028B -:101E30001D5102000000111D53041D5B021D5D02B7 -:101E40001D5F021D6102241D63031D69021D6B02DB -:101E50001D6D021D6F02281D71031D77021D790281 -:101E60001D7B02000000141D7D031D83021D8502E1 -:101E70001D8702000000271D89041D91021D930289 -:071E80001D95020000002483 -:00000001FF From e150717e95f68cfe02050015639f8d46bf10f8e5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 2 Dec 2019 10:31:33 +0100 Subject: [PATCH 41/50] Restore hardware detection --- RELEASENOTES.md | 1 - tasmota/CHANGELOG.md | 1 - tasmota/support.ino | 35 ++++++++++++++++++++++++++++++----- tasmota/support_command.ino | 5 +++-- tasmota/tasmota.ino | 2 ++ 5 files changed, 35 insertions(+), 9 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index cc067d531..8bc11b7ab 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -49,7 +49,6 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ### Version 7.1.1.1 Betty -- Remove inconsistent hardware detection introduced in version 7.0.0.5 - Fix lost functionality of GPIO9 and GPIO10 on some devices (#7080) - Fix Zigbee uses Hardware Serial if GPIO 1/3 or GPIO 13/15 and SerialLog 0 (#7071) - Change light color schemes 2, 3 and 4 from color wheel to Hue driven diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 4e798c754..c639e5392 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -2,7 +2,6 @@ ### 7.1.1.1 20191201 -- Remove inconsistent hardware detection introduced in version 7.0.0.5 - Fix lost functionality of GPIO9 and GPIO10 on some devices (#7080) - Fix Zigbee uses Hardware Serial if GPIO 1/3 or GPIO 13/15 and SerialLog 0 (#7071) - Change light color schemes 2, 3 and 4 from color wheel to Hue driven diff --git a/tasmota/support.ino b/tasmota/support.ino index 1e639494b..8ce7f2840 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -521,6 +521,31 @@ char* GetPowerDevice(char* dest, uint32_t idx, size_t size) return GetPowerDevice(dest, idx, size, 0); } +void GetEspHardwareType(void) +{ + // esptool.py get_efuses + uint32_t efuse1 = *(uint32_t*)(0x3FF00050); + uint32_t efuse2 = *(uint32_t*)(0x3FF00054); +// uint32_t efuse3 = *(uint32_t*)(0x3FF00058); +// uint32_t efuse4 = *(uint32_t*)(0x3FF0005C); + + is_8285 = ( (efuse1 & (1 << 4)) || (efuse2 & (1 << 16)) ); + if (is_8285 && (ESP.getFlashChipRealSize() > 1048576)) { + is_8285 = false; // ESP8285 can only have 1M flash + } +} + +String GetDeviceHardware(void) +{ + char buff[10]; + if (is_8285) { + strcpy_P(buff, PSTR("ESP8285")); + } else { + strcpy_P(buff, PSTR("ESP8266EX")); + } + return String(buff); +} + float ConvertTemp(float c) { float result = c; @@ -1008,18 +1033,18 @@ bool FlashPin(uint32_t pin) uint8_t ValidPin(uint32_t pin, uint32_t gpio) { - uint8_t result = gpio; - if (FlashPin(pin)) { - result = GPIO_NONE; // Disable flash pins GPIO6, GPIO7, GPIO8 and GPIO11 + return GPIO_NONE; // Disable flash pins GPIO6, GPIO7, GPIO8 and GPIO11 } + +// if (!is_8285 && !Settings.flag3.user_esp8285_enable) { // SetOption51 - Enable ESP8285 user GPIO's if ((WEMOS == Settings.module) && !Settings.flag3.user_esp8285_enable) { // SetOption51 - Enable ESP8285 user GPIO's if ((pin == 9) || (pin == 10)) { - result = GPIO_NONE; // Disable possible flash GPIO9 and GPIO10 + return GPIO_NONE; // Disable possible flash GPIO9 and GPIO10 } } - return result; + return gpio; } bool ValidGPIO(uint32_t pin, uint32_t gpio) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index e5c19c0e0..fe8640045 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -376,9 +376,10 @@ void CmndStatus(void) if ((0 == payload) || (2 == payload)) { Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS2_FIRMWARE "\":{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\",\"" - D_JSON_BOOTVERSION "\":%d,\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"}}"), + D_JSON_BOOTVERSION "\":%d,\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"," + "\"Hardware\":\"%s\"}}"), my_version, my_image, GetBuildDateAndTime().c_str(), - ESP.getBootVersion(), ESP.getSdkVersion()); + ESP.getBootVersion(), ESP.getSdkVersion(), GetDeviceHardware().c_str()); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "2")); } diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 64a1125c6..b7b4523e0 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -157,6 +157,7 @@ bool spi_flg = false; // SPI configured bool soft_spi_flg = false; // Software SPI configured bool ntp_force_sync = false; // Force NTP sync bool ntp_synced_message = false; // NTP synced message flag +bool is_8285 = false; // Hardware device ESP8266EX (0) or ESP8285 (1) myio my_module; // Active copy of Module GPIOs (17 x 8 bits) gpio_flag my_module_flag; // Active copy of Template GPIO flags StateBitfield global_state; // Global states (currently Wifi and Mqtt) (8 bits) @@ -1591,6 +1592,7 @@ void setup(void) snprintf_P(my_hostname, sizeof(my_hostname)-1, Settings.hostname); } + GetEspHardwareType(); GpioInit(); SetSerialBaudrate(baudrate); From 70673b8c748ad7442362345c6ee286bbf9daa0de Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 2 Dec 2019 10:44:27 +0100 Subject: [PATCH 42/50] Add support_tasmota --- tasmota/support_tasmota.ino | 1339 +++++++++++++++++++++++++++++++++++ tasmota/tasmota.ino | 1326 +--------------------------------- 2 files changed, 1344 insertions(+), 1321 deletions(-) create mode 100644 tasmota/support_tasmota.ino diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino new file mode 100644 index 000000000..e7099affd --- /dev/null +++ b/tasmota/support_tasmota.ino @@ -0,0 +1,1339 @@ +/* + support_tasmota.ino - Core support for Tasmota + + Copyright (C) 2019 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +const char kSleepMode[] PROGMEM = "Dynamic|Normal"; +const char kPrefixes[] PROGMEM = D_CMND "|" D_STAT "|" D_TELE; + +char* Format(char* output, const char* input, int size) +{ + char *token; + uint32_t digits = 0; + + if (strstr(input, "%") != nullptr) { + strlcpy(output, input, size); + token = strtok(output, "%"); + if (strstr(input, "%") == input) { + output[0] = '\0'; + } else { + token = strtok(nullptr, ""); + } + if (token != nullptr) { + digits = atoi(token); + if (digits) { + char tmp[size]; + if (strchr(token, 'd')) { + snprintf_P(tmp, size, PSTR("%s%c0%dd"), output, '%', digits); + snprintf_P(output, size, tmp, ESP.getChipId() & 0x1fff); // %04d - short chip ID in dec, like in hostname + } else { + snprintf_P(tmp, size, PSTR("%s%c0%dX"), output, '%', digits); + snprintf_P(output, size, tmp, ESP.getChipId()); // %06X - full chip ID in hex + } + } else { + if (strchr(token, 'd')) { + snprintf_P(output, size, PSTR("%s%d"), output, ESP.getChipId()); // %d - full chip ID in dec + digits = 8; + } + } + } + } + if (!digits) { + strlcpy(output, input, size); + } + return output; +} + +char* GetOtaUrl(char *otaurl, size_t otaurl_size) +{ + if (strstr(Settings.ota_url, "%04d") != nullptr) { // OTA url contains placeholder for chip ID + snprintf(otaurl, otaurl_size, Settings.ota_url, ESP.getChipId() & 0x1fff); + } + else if (strstr(Settings.ota_url, "%d") != nullptr) { // OTA url contains placeholder for chip ID + snprintf_P(otaurl, otaurl_size, Settings.ota_url, ESP.getChipId()); + } + else { + strlcpy(otaurl, Settings.ota_url, otaurl_size); + } + return otaurl; +} + +char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopic) +{ + /* prefix 0 = Cmnd + prefix 1 = Stat + prefix 2 = Tele + prefix 4 = Cmnd fallback + prefix 5 = Stat fallback + prefix 6 = Tele fallback + prefix 8 = Cmnd topic + prefix 9 = Stat topic + prefix 10 = Tele topic + */ + char romram[CMDSZ]; + String fulltopic; + + snprintf_P(romram, sizeof(romram), subtopic); + if (fallback_topic_flag || (prefix > 3)) { + bool fallback = (prefix < 8); + prefix &= 3; + char stemp[11]; + fulltopic = GetTextIndexed(stemp, sizeof(stemp), prefix, kPrefixes); + fulltopic += F("/"); + if (fallback) { + fulltopic += mqtt_client; + fulltopic += F("_fb"); // cmnd/_fb + } else { + fulltopic += topic; // cmnd/ + } + } else { + fulltopic = Settings.mqtt_fulltopic; + if ((0 == prefix) && (-1 == fulltopic.indexOf(FPSTR(MQTT_TOKEN_PREFIX)))) { + fulltopic += F("/"); + fulltopic += FPSTR(MQTT_TOKEN_PREFIX); // Need prefix for commands to handle mqtt topic loops + } + for (uint32_t i = 0; i < 3; i++) { + if ('\0' == Settings.mqtt_prefix[i][0]) { + GetTextIndexed(Settings.mqtt_prefix[i], sizeof(Settings.mqtt_prefix[i]), i, kPrefixes); + } + } + fulltopic.replace(FPSTR(MQTT_TOKEN_PREFIX), Settings.mqtt_prefix[prefix]); + fulltopic.replace(FPSTR(MQTT_TOKEN_TOPIC), topic); + fulltopic.replace(F("%hostname%"), my_hostname); + String token_id = WiFi.macAddress(); + token_id.replace(":", ""); + fulltopic.replace(F("%id%"), token_id); + } + fulltopic.replace(F("#"), ""); + fulltopic.replace(F("//"), "/"); + if (!fulltopic.endsWith("/")) { + fulltopic += "/"; + } + snprintf_P(stopic, TOPSZ, PSTR("%s%s"), fulltopic.c_str(), romram); + return stopic; +} + +char* GetGroupTopic_P(char *stopic, const char* subtopic) +{ + // SetOption75 0: %prefix%/nothing/%topic% = cmnd/nothing//# + // SetOption75 1: cmnd/ + return GetTopic_P(stopic, (Settings.flag3.grouptopic_mode) ? CMND +8 : CMND, Settings.mqtt_grptopic, subtopic); // SetOption75 - GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1) +} + +char* GetFallbackTopic_P(char *stopic, const char* subtopic) +{ + return GetTopic_P(stopic, CMND +4, nullptr, subtopic); +} + +char* GetStateText(uint32_t state) +{ + if (state > 3) { + state = 1; + } + return Settings.state_text[state]; +} + +/********************************************************************************************/ + +void SetLatchingRelay(power_t lpower, uint32_t state) +{ + // power xx00 - toggle REL1 (Off) and REL3 (Off) - device 1 Off, device 2 Off + // power xx01 - toggle REL2 (On) and REL3 (Off) - device 1 On, device 2 Off + // power xx10 - toggle REL1 (Off) and REL4 (On) - device 1 Off, device 2 On + // power xx11 - toggle REL2 (On) and REL4 (On) - device 1 On, device 2 On + + if (state && !latching_relay_pulse) { // Set latching relay to power if previous pulse has finished + latching_power = lpower; + latching_relay_pulse = 2; // max 200mS (initiated by stateloop()) + } + + for (uint32_t i = 0; i < devices_present; i++) { + uint32_t port = (i << 1) + ((latching_power >> i) &1); + if (pin[GPIO_REL1 +port] < 99) { + digitalWrite(pin[GPIO_REL1 +port], bitRead(rel_inverted, port) ? !state : state); + } + } +} + +void SetDevicePower(power_t rpower, uint32_t source) +{ + ShowSource(source); + last_source = source; + + if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { // All on and stay on + power = (1 << devices_present) -1; + rpower = power; + } + + if (Settings.flag.interlock) { // Allow only one or no relay set - CMND_INTERLOCK - Enable/disable interlock + for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { + power_t mask = 1; + uint32_t count = 0; + for (uint32_t j = 0; j < devices_present; j++) { + if ((Settings.interlock[i] & mask) && (rpower & mask)) { + count++; + } + mask <<= 1; + } + if (count > 1) { + mask = ~Settings.interlock[i]; // Turn interlocked group off as there would be multiple relays on + power &= mask; + rpower &= mask; + } + } + } + + if (rpower) { // Any power set + last_power = rpower; + } + + XdrvMailbox.index = rpower; + XdrvCall(FUNC_SET_POWER); // Signal power state + + XdrvMailbox.index = rpower; + XdrvMailbox.payload = source; + if (XdrvCall(FUNC_SET_DEVICE_POWER)) { // Set power state and stop if serviced + // Serviced + } + else if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { + Serial.write(0xA0); + Serial.write(0x04); + Serial.write(rpower &0xFF); + Serial.write(0xA1); + Serial.write('\n'); + Serial.flush(); + } + else if (EXS_RELAY == my_module_type) { + SetLatchingRelay(rpower, 1); + } + else { + for (uint32_t i = 0; i < devices_present; i++) { + power_t state = rpower &1; + if ((i < MAX_RELAYS) && (pin[GPIO_REL1 +i] < 99)) { + digitalWrite(pin[GPIO_REL1 +i], bitRead(rel_inverted, i) ? !state : state); + } + rpower >>= 1; + } + } +} + +void RestorePower(bool publish_power, uint32_t source) +{ + if (power != last_power) { + SetDevicePower(last_power, source); + if (publish_power) { + MqttPublishAllPowerState(); + } + } +} + +void SetAllPower(uint32_t state, uint32_t source) +{ +// state 0 = POWER_OFF = Relay Off +// state 1 = POWER_ON = Relay On (turn off after Settings.pulse_timer * 100 mSec if enabled) +// state 2 = POWER_TOGGLE = Toggle relay +// state 8 = POWER_OFF_NO_STATE = Relay Off and no publishPowerState +// state 9 = POWER_ON_NO_STATE = Relay On and no publishPowerState +// state 10 = POWER_TOGGLE_NO_STATE = Toggle relay and no publishPowerState +// state 16 = POWER_SHOW_STATE = Show power state + + bool publish_power = true; + if ((state >= POWER_OFF_NO_STATE) && (state <= POWER_TOGGLE_NO_STATE)) { + state &= 3; // POWER_OFF, POWER_ON or POWER_TOGGLE + publish_power = false; + } + if ((state >= POWER_OFF) && (state <= POWER_TOGGLE)) { + power_t all_on = (1 << devices_present) -1; + switch (state) { + case POWER_OFF: + power = 0; + break; + case POWER_ON: + power = all_on; + break; + case POWER_TOGGLE: + power ^= all_on; // Complement current state + } + SetDevicePower(power, source); + } + if (publish_power) { + MqttPublishAllPowerState(); + } +} + +void SetLedPowerIdx(uint32_t led, uint32_t state) +{ + if ((99 == pin[GPIO_LEDLNK]) && (0 == led)) { // Legacy - LED1 is link led only if LED2 is present + if (pin[GPIO_LED2] < 99) { + led = 1; + } + } + if (pin[GPIO_LED1 + led] < 99) { + uint32_t mask = 1 << led; + if (state) { + state = 1; + led_power |= mask; + } else { + led_power &= (0xFF ^ mask); + } + digitalWrite(pin[GPIO_LED1 + led], bitRead(led_inverted, led) ? !state : state); + } +} + +void SetLedPower(uint32_t state) +{ + if (99 == pin[GPIO_LEDLNK]) { // Legacy - Only use LED1 and/or LED2 + SetLedPowerIdx(0, state); + } else { + power_t mask = 1; + for (uint32_t i = 0; i < leds_present; i++) { // Map leds to power + bool tstate = (power & mask); + SetLedPowerIdx(i, tstate); + mask <<= 1; + } + } +} + +void SetLedPowerAll(uint32_t state) +{ + for (uint32_t i = 0; i < leds_present; i++) { + SetLedPowerIdx(i, state); + } +} + +void SetLedLink(uint32_t state) +{ + uint32_t led_pin = pin[GPIO_LEDLNK]; + uint32_t led_inv = ledlnk_inverted; + if (99 == led_pin) { // Legacy - LED1 is status + led_pin = pin[GPIO_LED1]; + led_inv = bitRead(led_inverted, 0); + } + if (led_pin < 99) { + if (state) { state = 1; } + digitalWrite(led_pin, (led_inv) ? !state : state); + } +} + +void SetPulseTimer(uint32_t index, uint32_t time) +{ + pulse_timer[index] = (time > 111) ? millis() + (1000 * (time - 100)) : (time > 0) ? millis() + (100 * time) : 0L; +} + +uint32_t GetPulseTimer(uint32_t index) +{ + long time = TimePassedSince(pulse_timer[index]); + if (time < 0) { + time *= -1; + return (time > 11100) ? (time / 1000) + 100 : (time > 0) ? time / 100 : 0; + } + return 0; +} + +/********************************************************************************************/ + +bool SendKey(uint32_t key, uint32_t device, uint32_t state) +{ +// key 0 = KEY_BUTTON = button_topic +// key 1 = KEY_SWITCH = switch_topic +// state 0 = POWER_OFF = off +// state 1 = POWER_ON = on +// state 2 = POWER_TOGGLE = toggle +// state 3 = POWER_HOLD = hold +// state 9 = CLEAR_RETAIN = clear retain flag + + char stopic[TOPSZ]; + char scommand[CMDSZ]; + char key_topic[sizeof(Settings.button_topic)]; + bool result = false; + + char *tmp = (key) ? Settings.switch_topic : Settings.button_topic; + Format(key_topic, tmp, sizeof(key_topic)); + if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) { // SetOption3 - Enable MQTT + if (!key && (device > devices_present)) { + device = 1; // Only allow number of buttons up to number of devices + } + GetTopic_P(stopic, CMND, key_topic, + GetPowerDevice(scommand, device, sizeof(scommand), (key + Settings.flag.device_index_enable))); // cmnd/switchtopic/POWERx - SetOption26 - Switch between POWER or POWER1 + if (CLEAR_RETAIN == state) { + mqtt_data[0] = '\0'; + } else { + if ((Settings.flag3.button_switch_force_local || // SetOption61 - Force local operation when button/switch topic is set + !strcmp(mqtt_topic, key_topic) || + !strcmp(Settings.mqtt_grptopic, key_topic)) && + (POWER_TOGGLE == state)) { + state = ~(power >> (device -1)) &1; // POWER_OFF or POWER_ON + } + snprintf_P(mqtt_data, sizeof(mqtt_data), GetStateText(state)); + } +#ifdef USE_DOMOTICZ + if (!(DomoticzSendKey(key, device, state, strlen(mqtt_data)))) { +#endif // USE_DOMOTICZ + MqttPublishDirect(stopic, ((key) ? Settings.flag.mqtt_switch_retain // CMND_SWITCHRETAIN + : Settings.flag.mqtt_button_retain) && // CMND_BUTTONRETAIN + (state != POWER_HOLD || !Settings.flag3.no_hold_retain)); // SetOption62 - Don't use retain flag on HOLD messages +#ifdef USE_DOMOTICZ + } +#endif // USE_DOMOTICZ + result = !Settings.flag3.button_switch_force_local; // SetOption61 - Force local operation when button/switch topic is set + } else { + Response_P(PSTR("{\"%s%d\":{\"State\":%d}}"), (key) ? "Switch" : "Button", device, state); + result = XdrvRulesProcess(); + } + int32_t payload_save = XdrvMailbox.payload; + XdrvMailbox.payload = key << 16 | state << 8 | device; + XdrvCall(FUNC_ANY_KEY); + XdrvMailbox.payload = payload_save; + return result; +} + +void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source) +{ +// device = Relay number 1 and up +// state 0 = POWER_OFF = Relay Off +// state 1 = POWER_ON = Relay On (turn off after Settings.pulse_timer * 100 mSec if enabled) +// state 2 = POWER_TOGGLE = Toggle relay +// state 3 = POWER_BLINK = Blink relay +// state 4 = POWER_BLINK_STOP = Stop blinking relay +// state 8 = POWER_OFF_NO_STATE = Relay Off and no publishPowerState +// state 9 = POWER_ON_NO_STATE = Relay On and no publishPowerState +// state 10 = POWER_TOGGLE_NO_STATE = Toggle relay and no publishPowerState +// state 16 = POWER_SHOW_STATE = Show power state + +// ShowSource(source); + +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan()) { + blink_mask &= 1; // No blinking on the fan relays + Settings.flag.interlock = 0; // No interlock mode as it is already done by the microcontroller - CMND_INTERLOCK - Enable/disable interlock + Settings.pulse_timer[1] = 0; // No pulsetimers on the fan relays + Settings.pulse_timer[2] = 0; + Settings.pulse_timer[3] = 0; + } +#endif // USE_SONOFF_IFAN + + bool publish_power = true; + if ((state >= POWER_OFF_NO_STATE) && (state <= POWER_TOGGLE_NO_STATE)) { + state &= 3; // POWER_OFF, POWER_ON or POWER_TOGGLE + publish_power = false; + } + + if ((device < 1) || (device > devices_present)) { + device = 1; + } + active_device = device; + + if (device <= MAX_PULSETIMERS) { + SetPulseTimer(device -1, 0); + } + power_t mask = 1 << (device -1); // Device to control + if (state <= POWER_TOGGLE) { + if ((blink_mask & mask)) { + blink_mask &= (POWER_MASK ^ mask); // Clear device mask + MqttPublishPowerBlinkState(device); + } + + if (Settings.flag.interlock && // CMND_INTERLOCK - Enable/disable interlock + !interlock_mutex && + ((POWER_ON == state) || ((POWER_TOGGLE == state) && !(power & mask))) + ) { + interlock_mutex = true; // Clear all but masked relay in interlock group if new set requested + for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { + if (Settings.interlock[i] & mask) { // Find interlock group + for (uint32_t j = 0; j < devices_present; j++) { + power_t imask = 1 << j; + if ((Settings.interlock[i] & imask) && (power & imask) && (mask != imask)) { + ExecuteCommandPower(j +1, POWER_OFF, SRC_IGNORE); + delay(50); // Add some delay to make sure never have more than one relay on + } + } + break; // An interlocked relay is only present in one group so quit + } + } + interlock_mutex = false; + } + + switch (state) { + case POWER_OFF: { + power &= (POWER_MASK ^ mask); + break; } + case POWER_ON: + power |= mask; + break; + case POWER_TOGGLE: + power ^= mask; + } + SetDevicePower(power, source); +#ifdef USE_DOMOTICZ + DomoticzUpdatePowerState(device); +#endif // USE_DOMOTICZ +#ifdef USE_KNX + KnxUpdatePowerState(device, power); +#endif // USE_KNX + if (publish_power && Settings.flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT + MqttPublishTeleState(); + } + if (device <= MAX_PULSETIMERS) { // Restart PulseTime if powered On + SetPulseTimer(device -1, (((POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? ~power : power) & mask) ? Settings.pulse_timer[device -1] : 0); + } + } + else if (POWER_BLINK == state) { + if (!(blink_mask & mask)) { + blink_powersave = (blink_powersave & (POWER_MASK ^ mask)) | (power & mask); // Save state + blink_power = (power >> (device -1))&1; // Prep to Toggle + } + blink_timer = millis() + 100; + blink_counter = ((!Settings.blinkcount) ? 64000 : (Settings.blinkcount *2)) +1; + blink_mask |= mask; // Set device mask + MqttPublishPowerBlinkState(device); + return; + } + else if (POWER_BLINK_STOP == state) { + bool flag = (blink_mask & mask); + blink_mask &= (POWER_MASK ^ mask); // Clear device mask + MqttPublishPowerBlinkState(device); + if (flag) { + ExecuteCommandPower(device, (blink_powersave >> (device -1))&1, SRC_IGNORE); // Restore state + } + return; + } + if (publish_power) { + MqttPublishPowerState(device); + } +} + +void StopAllPowerBlink(void) +{ + power_t mask; + + for (uint32_t i = 1; i <= devices_present; i++) { + mask = 1 << (i -1); + if (blink_mask & mask) { + blink_mask &= (POWER_MASK ^ mask); // Clear device mask + MqttPublishPowerBlinkState(i); + ExecuteCommandPower(i, (blink_powersave >> (i -1))&1, SRC_IGNORE); // Restore state + } + } +} + +void MqttShowPWMState(void) +{ + ResponseAppend_P(PSTR("\"" D_CMND_PWM "\":{")); + bool first = true; + for (uint32_t i = 0; i < MAX_PWMS; i++) { + if (pin[GPIO_PWM1 + i] < 99) { + ResponseAppend_P(PSTR("%s\"" D_CMND_PWM "%d\":%d"), first ? "" : ",", i+1, Settings.pwm_value[i]); + first = false; + } + } + ResponseJsonEnd(); +} + +void MqttShowState(void) +{ + char stemp1[33]; + + ResponseAppendTime(); + ResponseAppend_P(PSTR(",\"" D_JSON_UPTIME "\":\"%s\",\"UptimeSec\":%u"), GetUptime().c_str(), UpTime()); + +#ifdef USE_ADC_VCC + dtostrfd((double)ESP.getVcc()/1000, 3, stemp1); + ResponseAppend_P(PSTR(",\"" D_JSON_VCC "\":%s"), stemp1); +#endif + + ResponseAppend_P(PSTR(",\"" D_JSON_HEAPSIZE "\":%d,\"SleepMode\":\"%s\",\"Sleep\":%u,\"LoadAvg\":%u,\"MqttCount\":%u"), + ESP.getFreeHeap()/1024, GetTextIndexed(stemp1, sizeof(stemp1), Settings.flag3.sleep_normal, kSleepMode), // SetOption60 - Enable normal sleep instead of dynamic sleep + sleep, loop_load_avg, MqttConnectCount()); + + for (uint32_t i = 1; i <= devices_present; i++) { +#ifdef USE_LIGHT + if ((LightDevice()) && (i >= LightDevice())) { + if (i == LightDevice()) { LightState(1); } // call it only once + } else { +#endif + ResponseAppend_P(PSTR(",\"%s\":\"%s\""), GetPowerDevice(stemp1, i, sizeof(stemp1), Settings.flag.device_index_enable), // SetOption26 - Switch between POWER or POWER1 + GetStateText(bitRead(power, i-1))); +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan()) { + ResponseAppend_P(PSTR(",\"" D_CMND_FANSPEED "\":%d"), GetFanspeed()); + break; + } +#endif // USE_SONOFF_IFAN +#ifdef USE_LIGHT + } +#endif + } + + if (pwm_present) { + ResponseAppend_P(PSTR(",")); + MqttShowPWMState(); + } + + ResponseAppend_P(PSTR(",\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}}"), + Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI()), WifiLinkCount(), WifiDowntime().c_str()); +} + +void MqttPublishTeleState(void) +{ + mqtt_data[0] = '\0'; + MqttShowState(); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); +#ifdef USE_SCRIPT + RulesTeleperiod(); // Allow rule based HA messages +#endif // USE_SCRIPT +} + +bool MqttShowSensor(void) +{ + ResponseAppendTime(); + + int json_data_start = strlen(mqtt_data); + for (uint32_t i = 0; i < MAX_SWITCHES; i++) { +#ifdef USE_TM1638 + if ((pin[GPIO_SWT1 +i] < 99) || ((pin[GPIO_TM16CLK] < 99) && (pin[GPIO_TM16DIO] < 99) && (pin[GPIO_TM16STB] < 99))) { +#else + if (pin[GPIO_SWT1 +i] < 99) { +#endif // USE_TM1638 + bool swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i])); + ResponseAppend_P(PSTR(",\"" D_JSON_SWITCH "%d\":\"%s\""), i +1, GetStateText(swm ^ SwitchLastState(i))); + } + } + XsnsCall(FUNC_JSON_APPEND); + XdrvCall(FUNC_JSON_APPEND); + + bool json_data_available = (strlen(mqtt_data) - json_data_start); + if (strstr_P(mqtt_data, PSTR(D_JSON_PRESSURE)) != nullptr) { + ResponseAppend_P(PSTR(",\"" D_JSON_PRESSURE_UNIT "\":\"%s\""), PressureUnit().c_str()); + } + if (strstr_P(mqtt_data, PSTR(D_JSON_TEMPERATURE)) != nullptr) { + ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE_UNIT "\":\"%c\""), TempUnit()); + } + ResponseJsonEnd(); + + if (json_data_available) { XdrvCall(FUNC_SHOW_SENSOR); } + return json_data_available; +} + +void MqttPublishSensor(void) +{ + mqtt_data[0] = '\0'; + if (MqttShowSensor()) { + MqttPublishTeleSensor(); + } +} + +/********************************************************************************************/ + +void PerformEverySecond(void) +{ + uptime++; + + if (ntp_synced_message) { + // Moved here to fix syslog UDP exception 9 during RtcSecond + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NTP: Drift %d, (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), + DriftTime(), GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); + ntp_synced_message = false; + } + + if (POWER_CYCLE_TIME == uptime) { + UpdateQuickPowerCycle(false); + } + + if (BOOT_LOOP_TIME == uptime) { + RtcRebootReset(); + +#ifdef USE_DEEPSLEEP + if (!(DeepSleepEnabled() && !Settings.flag3.bootcount_update)) { +#endif + Settings.bootcount++; // Moved to here to stop flash writes during start-up + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BOOT_COUNT " %d"), Settings.bootcount); +#ifdef USE_DEEPSLEEP + } +#endif + } + + if (seriallog_timer) { + seriallog_timer--; + if (!seriallog_timer) { + if (seriallog_level) { + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SERIAL_LOGGING_DISABLED)); + } + seriallog_level = 0; + } + } + + if (syslog_timer) { // Restore syslog level + syslog_timer--; + if (!syslog_timer) { + syslog_level = Settings.syslog_level; + if (Settings.syslog_level) { + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SYSLOG_LOGGING_REENABLED)); // Might trigger disable again (on purpose) + } + } + } + + ResetGlobalValues(); + + if (Settings.tele_period) { + if (tele_period >= 9999) { + if (!global_state.wifi_down) { + tele_period = 0; // Allow teleperiod once wifi is connected + } + } else { + tele_period++; + if (tele_period >= Settings.tele_period) { + tele_period = 0; + + MqttPublishTeleState(); + + mqtt_data[0] = '\0'; + if (MqttShowSensor()) { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); // CMND_SENSORRETAIN +#if defined(USE_RULES) || defined(USE_SCRIPT) + RulesTeleperiod(); // Allow rule based HA messages +#endif // USE_RULES + } + + XdrvCall(FUNC_AFTER_TELEPERIOD); + } + } + } +} + +/*********************************************************************************************\ + * State loops +\*********************************************************************************************/ +/*-------------------------------------------------------------------------------------------*\ + * Every 0.1 second +\*-------------------------------------------------------------------------------------------*/ + +void Every100mSeconds(void) +{ + // As the max amount of sleep = 250 mSec this loop will shift in time... + power_t power_now; + + if (latching_relay_pulse) { + latching_relay_pulse--; + if (!latching_relay_pulse) SetLatchingRelay(0, 0); + } + + for (uint32_t i = 0; i < MAX_PULSETIMERS; i++) { + if (pulse_timer[i] != 0L) { // Timer active? + if (TimeReached(pulse_timer[i])) { // Timer finished? + pulse_timer[i] = 0L; // Turn off this timer + ExecuteCommandPower(i +1, (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? POWER_ON : POWER_OFF, SRC_PULSETIMER); + } + } + } + + if (blink_mask) { + if (TimeReached(blink_timer)) { + SetNextTimeInterval(blink_timer, 100 * Settings.blinktime); + blink_counter--; + if (!blink_counter) { + StopAllPowerBlink(); + } else { + blink_power ^= 1; + power_now = (power & (POWER_MASK ^ blink_mask)) | ((blink_power) ? blink_mask : 0); + SetDevicePower(power_now, SRC_IGNORE); + } + } + } +} + +/*-------------------------------------------------------------------------------------------*\ + * Every 0.25 second +\*-------------------------------------------------------------------------------------------*/ + +void Every250mSeconds(void) +{ +// As the max amount of sleep = 250 mSec this loop should always be taken... + + uint32_t blinkinterval = 1; + + state_250mS++; + state_250mS &= 0x3; + + if (mqtt_cmnd_publish) mqtt_cmnd_publish--; // Clean up + + if (!Settings.flag.global_state) { // Problem blinkyblinky enabled - SetOption31 - Control link led blinking + if (global_state.data) { // Any problem + if (global_state.mqtt_down) { blinkinterval = 7; } // MQTT problem so blink every 2 seconds (slowest) + if (global_state.wifi_down) { blinkinterval = 3; } // Wifi problem so blink every second (slow) + blinks = 201; // Allow only a single blink in case the problem is solved + } + } + if (blinks || restart_flag || ota_state_flag) { + if (restart_flag || ota_state_flag) { // Overrule blinks and keep led lit + blinkstate = true; // Stay lit + } else { + blinkspeed--; + if (!blinkspeed) { + blinkspeed = blinkinterval; // Set interval to 0.2 (default), 1 or 2 seconds + blinkstate ^= 1; // Blink + } + } + if ((!(Settings.ledstate &0x08)) && ((Settings.ledstate &0x06) || (blinks > 200) || (blinkstate))) { + SetLedLink(blinkstate); // Set led on or off + } + if (!blinkstate) { + blinks--; + if (200 == blinks) blinks = 0; // Disable blink + } + } + if (Settings.ledstate &1 && (pin[GPIO_LEDLNK] < 99 || !(blinks || restart_flag || ota_state_flag)) ) { + bool tstate = power & Settings.ledmask; + if ((SONOFF_TOUCH == my_module_type) || (SONOFF_T11 == my_module_type) || (SONOFF_T12 == my_module_type) || (SONOFF_T13 == my_module_type)) { + tstate = (!power) ? 1 : 0; // As requested invert signal for Touch devices to find them in the dark + } + SetLedPower(tstate); + } + +/*-------------------------------------------------------------------------------------------*\ + * Every second at 0.25 second interval +\*-------------------------------------------------------------------------------------------*/ + + switch (state_250mS) { + case 0: // Every x.0 second + if (ota_state_flag && BACKLOG_EMPTY) { + ota_state_flag--; + if (2 == ota_state_flag) { + ota_url = Settings.ota_url; + RtcSettings.ota_loader = 0; // Try requested image first + ota_retry_counter = OTA_ATTEMPTS; + ESPhttpUpdate.rebootOnUpdate(false); + SettingsSave(1); // Free flash for OTA update + } + if (ota_state_flag <= 0) { +#ifdef USE_WEBSERVER + if (Settings.webserver) StopWebserver(); +#endif // USE_WEBSERVER +#ifdef USE_ARILUX_RF + AriluxRfDisable(); // Prevent restart exception on Arilux Interrupt routine +#endif // USE_ARILUX_RF + ota_state_flag = 92; + ota_result = 0; + ota_retry_counter--; + if (ota_retry_counter) { + strlcpy(mqtt_data, GetOtaUrl(log_data, sizeof(log_data)), sizeof(mqtt_data)); +#ifndef FIRMWARE_MINIMAL + if (RtcSettings.ota_loader) { + char *bch = strrchr(mqtt_data, '/'); // Only consider filename after last backslash prevent change of urls having "-" in it + char *pch = strrchr((bch != nullptr) ? bch : mqtt_data, '-'); // Change from filename-DE.bin into filename-minimal.bin + char *ech = strrchr((bch != nullptr) ? bch : mqtt_data, '.'); // Change from filename.bin into filename-minimal.bin + if (!pch) { pch = ech; } + if (pch) { + mqtt_data[pch - mqtt_data] = '\0'; + char *ech = strrchr(Settings.ota_url, '.'); // Change from filename.bin into filename-minimal.bin + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s-" D_JSON_MINIMAL "%s"), mqtt_data, ech); // Minimal filename must be filename-minimal + } + } +#endif // FIRMWARE_MINIMAL + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "%s"), mqtt_data); +#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) + ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(mqtt_data)); +#else + // If using core stage or 2.5.0+ the syntax has changed + WiFiClient OTAclient; + ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(OTAclient, mqtt_data)); +#endif + if (!ota_result) { +#ifndef FIRMWARE_MINIMAL + int ota_error = ESPhttpUpdate.getLastError(); + DEBUG_CORE_LOG(PSTR("OTA: Error %d"), ota_error); + if ((HTTP_UE_TOO_LESS_SPACE == ota_error) || (HTTP_UE_BIN_FOR_WRONG_FLASH == ota_error)) { + RtcSettings.ota_loader = 1; // Try minimal image next + } +#endif // FIRMWARE_MINIMAL + ota_state_flag = 2; // Upgrade failed - retry + } + } + } + if (90 == ota_state_flag) { // Allow MQTT to reconnect + ota_state_flag = 0; + if (ota_result) { +// SetFlashModeDout(); // Force DOUT for both ESP8266 and ESP8285 + Response_P(PSTR(D_JSON_SUCCESSFUL ". " D_JSON_RESTARTING)); + } else { + Response_P(PSTR(D_JSON_FAILED " %s"), ESPhttpUpdate.getLastErrorString().c_str()); + } + restart_flag = 2; // Restart anyway to keep memory clean webserver + MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_UPGRADE)); + } + } + break; + case 1: // Every x.25 second + if (MidnightNow()) { + XsnsCall(FUNC_SAVE_AT_MIDNIGHT); + } + if (save_data_counter && BACKLOG_EMPTY) { + save_data_counter--; + if (save_data_counter <= 0) { + if (Settings.flag.save_state) { // SetOption0 - Save power state and use after restart + power_t mask = POWER_MASK; + for (uint32_t i = 0; i < MAX_PULSETIMERS; i++) { + if ((Settings.pulse_timer[i] > 0) && (Settings.pulse_timer[i] < 30)) { // 3 seconds + mask &= ~(1 << i); + } + } + if (!((Settings.power &mask) == (power &mask))) { + Settings.power = power; + } + } else { + Settings.power = 0; + } + SettingsSave(0); + save_data_counter = Settings.save_data; + } + } + if (restart_flag && BACKLOG_EMPTY) { + if ((214 == restart_flag) || (215 == restart_flag) || (216 == restart_flag)) { + char storage_wifi[sizeof(Settings.sta_ssid) + + sizeof(Settings.sta_pwd)]; + char storage_mqtt[sizeof(Settings.mqtt_host) + + sizeof(Settings.mqtt_port) + + sizeof(Settings.mqtt_client) + + sizeof(Settings.mqtt_user) + + sizeof(Settings.mqtt_pwd) + + sizeof(Settings.mqtt_topic)]; + memcpy(storage_wifi, Settings.sta_ssid, sizeof(storage_wifi)); // Backup current SSIDs and Passwords + if (216 == restart_flag) { + memcpy(storage_mqtt, Settings.mqtt_host, sizeof(storage_mqtt)); // Backup mqtt host, port, client, username and password + } + if ((215 == restart_flag) || (216 == restart_flag)) { + SettingsErase(0); // Erase all flash from program end to end of physical flash + } + SettingsDefault(); + memcpy(Settings.sta_ssid, storage_wifi, sizeof(storage_wifi)); // Restore current SSIDs and Passwords + if (216 == restart_flag) { + memcpy(Settings.mqtt_host, storage_mqtt, sizeof(storage_mqtt)); // Restore the mqtt host, port, client, username and password + strlcpy(Settings.mqtt_client, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client)); // Set client to default + } + restart_flag = 2; + } + else if (213 == restart_flag) { + SettingsSdkErase(); // Erase flash SDK parameters + restart_flag = 2; + } + else if (212 == restart_flag) { + SettingsErase(0); // Erase all flash from program end to end of physical flash + restart_flag = 211; + } + if (211 == restart_flag) { + SettingsDefault(); + restart_flag = 2; + } + if (2 == restart_flag) { + SettingsSaveAll(); + } + restart_flag--; + if (restart_flag <= 0) { + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); + EspRestart(); + } + } + break; + case 2: // Every x.5 second + WifiCheck(wifi_state_flag); + wifi_state_flag = WIFI_RESTART; + break; + case 3: // Every x.75 second + if (!global_state.wifi_down) { MqttCheck(); } + break; + } +} + +#ifdef USE_ARDUINO_OTA +/*********************************************************************************************\ + * Allow updating via the Arduino OTA-protocol. + * + * - Once started disables current wifi clients and udp + * - Perform restart when done to re-init wifi clients +\*********************************************************************************************/ + +bool arduino_ota_triggered = false; +uint16_t arduino_ota_progress_dot_count = 0; + +void ArduinoOTAInit(void) +{ + ArduinoOTA.setPort(8266); + ArduinoOTA.setHostname(my_hostname); + if (Settings.web_password[0] !=0) { ArduinoOTA.setPassword(Settings.web_password); } + + ArduinoOTA.onStart([]() + { + SettingsSave(1); // Free flash for OTA update +#ifdef USE_WEBSERVER + if (Settings.webserver) { StopWebserver(); } +#endif // USE_WEBSERVER +#ifdef USE_ARILUX_RF + AriluxRfDisable(); // Prevent restart exception on Arilux Interrupt routine +#endif // USE_ARILUX_RF + if (Settings.flag.mqtt_enabled) { + MqttDisconnect(); // SetOption3 - Enable MQTT + } + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_UPLOAD_STARTED)); + arduino_ota_triggered = true; + arduino_ota_progress_dot_count = 0; + delay(100); // Allow time for message xfer + }); + + ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) + { + if ((LOG_LEVEL_DEBUG <= seriallog_level)) { + arduino_ota_progress_dot_count++; + Serial.printf("."); + if (!(arduino_ota_progress_dot_count % 80)) { Serial.println(); } + } + }); + + ArduinoOTA.onError([](ota_error_t error) + { + /* + From ArduinoOTA.h: + typedef enum { OTA_AUTH_ERROR, OTA_BEGIN_ERROR, OTA_CONNECT_ERROR, OTA_RECEIVE_ERROR, OTA_END_ERROR } ota_error_t; + */ + char error_str[100]; + + if ((LOG_LEVEL_DEBUG <= seriallog_level) && arduino_ota_progress_dot_count) { Serial.println(); } + switch (error) { + case OTA_BEGIN_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_2), sizeof(error_str)); break; + case OTA_RECEIVE_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_5), sizeof(error_str)); break; + case OTA_END_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_7), sizeof(error_str)); break; + default: + snprintf_P(error_str, sizeof(error_str), PSTR(D_UPLOAD_ERROR_CODE " %d"), error); + } + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA %s. " D_RESTARTING), error_str); + EspRestart(); + }); + + ArduinoOTA.onEnd([]() + { + if ((LOG_LEVEL_DEBUG <= seriallog_level)) { Serial.println(); } + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_SUCCESSFUL ". " D_RESTARTING)); + EspRestart(); + }); + + ArduinoOTA.begin(); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_ENABLED " " D_PORT " 8266")); +} +#endif // USE_ARDUINO_OTA + +/********************************************************************************************/ + +void SerialInput(void) +{ + while (Serial.available()) { +// yield(); + delay(0); + serial_in_byte = Serial.read(); + +/*-------------------------------------------------------------------------------------------*\ + * Sonoff dual and ch4 19200 baud serial interface +\*-------------------------------------------------------------------------------------------*/ + if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { + serial_in_byte = ButtonSerial(serial_in_byte); + } + +/*-------------------------------------------------------------------------------------------*/ + + if (XdrvCall(FUNC_SERIAL)) { + serial_in_byte_counter = 0; + Serial.flush(); + return; + } + +/*-------------------------------------------------------------------------------------------*/ + + if (serial_in_byte > 127 && !Settings.flag.mqtt_serial_raw) { // Discard binary data above 127 if no raw reception allowed - CMND_SERIALSEND3 + serial_in_byte_counter = 0; + Serial.flush(); + return; + } + if (!Settings.flag.mqtt_serial) { // SerialSend active - CMND_SERIALSEND and CMND_SERIALLOG + if (isprint(serial_in_byte)) { // Any char between 32 and 127 + if (serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { // Add char to string if it still fits + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + } else { + serial_in_byte_counter = 0; + } + } + } else { + if (serial_in_byte || Settings.flag.mqtt_serial_raw) { // Any char between 1 and 127 or any char (0 - 255) - CMND_SERIALSEND3 + if ((serial_in_byte_counter < INPUT_BUFFER_SIZE -1) && // Add char to string if it still fits and ... + ((isprint(serial_in_byte) && (128 == Settings.serial_delimiter)) || // Any char between 32 and 127 + ((serial_in_byte != Settings.serial_delimiter) && (128 != Settings.serial_delimiter)) || // Any char between 1 and 127 and not being delimiter + Settings.flag.mqtt_serial_raw)) { // Any char between 0 and 255 - CMND_SERIALSEND3 + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + serial_polling_window = millis(); + } else { + serial_polling_window = 0; // Reception done - send mqtt + break; + } + } + } + +#ifdef USE_SONOFF_SC +/*-------------------------------------------------------------------------------------------*\ + * Sonoff SC 19200 baud serial interface +\*-------------------------------------------------------------------------------------------*/ + if (SONOFF_SC == my_module_type) { + if (serial_in_byte == '\x1B') { // Sonoff SC status from ATMEGA328P + serial_in_buffer[serial_in_byte_counter] = 0; // Serial data completed + SonoffScSerialInput(serial_in_buffer); + serial_in_byte_counter = 0; + Serial.flush(); + return; + } + } else +#endif // USE_SONOFF_SC +/*-------------------------------------------------------------------------------------------*/ + + if (!Settings.flag.mqtt_serial && (serial_in_byte == '\n')) { // CMND_SERIALSEND and CMND_SERIALLOG + serial_in_buffer[serial_in_byte_counter] = 0; // Serial data completed + seriallog_level = (Settings.seriallog_level < LOG_LEVEL_INFO) ? (uint8_t)LOG_LEVEL_INFO : Settings.seriallog_level; + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "%s"), serial_in_buffer); + ExecuteCommand(serial_in_buffer, SRC_SERIAL); + serial_in_byte_counter = 0; + serial_polling_window = 0; + Serial.flush(); + return; + } + } + + if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) { // CMND_SERIALSEND and CMND_SERIALLOG + serial_in_buffer[serial_in_byte_counter] = 0; // Serial data completed + char hex_char[(serial_in_byte_counter * 2) + 2]; + Response_P(PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), + (Settings.flag.mqtt_serial_raw) ? ToHex_P((unsigned char*)serial_in_buffer, serial_in_byte_counter, hex_char, sizeof(hex_char)) : serial_in_buffer); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED)); + XdrvRulesProcess(); + serial_in_byte_counter = 0; + } +} + +/********************************************************************************************/ + +void GpioInit(void) +{ + uint32_t mpin; + + if (!ValidModule(Settings.module)) { + uint32_t module = MODULE; + if (!ValidModule(MODULE)) { module = SONOFF_BASIC; } + Settings.module = module; + Settings.last_module = module; + } + SetModuleType(); + + if (Settings.module != Settings.last_module) { + baudrate = APP_BAUDRATE; + } + + for (uint32_t i = 0; i < sizeof(Settings.user_template.gp); i++) { + if ((Settings.user_template.gp.io[i] >= GPIO_SENSOR_END) && (Settings.user_template.gp.io[i] < GPIO_USER)) { + Settings.user_template.gp.io[i] = GPIO_USER; // Fix not supported sensor ids in template + } + } + + myio def_gp; + ModuleGpios(&def_gp); + for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { + if ((Settings.my_gp.io[i] >= GPIO_SENSOR_END) && (Settings.my_gp.io[i] < GPIO_USER)) { + Settings.my_gp.io[i] = GPIO_NONE; // Fix not supported sensor ids in module + } + else if (Settings.my_gp.io[i] > GPIO_NONE) { + my_module.io[i] = Settings.my_gp.io[i]; // Set User selected Module sensors + } + if ((def_gp.io[i] > GPIO_NONE) && (def_gp.io[i] < GPIO_USER)) { + my_module.io[i] = def_gp.io[i]; // Force Template override + } + } + if ((Settings.my_adc0 >= ADC0_END) && (Settings.my_adc0 < ADC0_USER)) { + Settings.my_adc0 = ADC0_NONE; // Fix not supported sensor ids in module + } + else if (Settings.my_adc0 > ADC0_NONE) { + my_adc0 = Settings.my_adc0; // Set User selected Module sensors + } + my_module_flag = ModuleFlag(); + uint32_t template_adc0 = my_module_flag.data &15; + if ((template_adc0 > ADC0_NONE) && (template_adc0 < ADC0_USER)) { + my_adc0 = template_adc0; // Force Template override + } + + for (uint32_t i = 0; i < GPIO_MAX; i++) { + pin[i] = 99; + } + for (uint32_t i = 0; i < sizeof(my_module.io); i++) { + mpin = ValidPin(i, my_module.io[i]); + + DEBUG_CORE_LOG(PSTR("INI: gpio pin %d, mpin %d"), i, mpin); + + if (mpin) { + XdrvMailbox.index = mpin; + XdrvMailbox.payload = i; + + if ((mpin >= GPIO_SWT1_NP) && (mpin < (GPIO_SWT1_NP + MAX_SWITCHES))) { + SwitchPullupFlag(mpin - GPIO_SWT1_NP); + mpin -= (GPIO_SWT1_NP - GPIO_SWT1); + } + else if ((mpin >= GPIO_KEY1_NP) && (mpin < (GPIO_KEY1_NP + MAX_KEYS))) { + ButtonPullupFlag(mpin - GPIO_KEY1_NP); // 0 .. 3 + mpin -= (GPIO_KEY1_NP - GPIO_KEY1); + } + else if ((mpin >= GPIO_KEY1_INV) && (mpin < (GPIO_KEY1_INV + MAX_KEYS))) { + ButtonInvertFlag(mpin - GPIO_KEY1_INV); // 0 .. 3 + mpin -= (GPIO_KEY1_INV - GPIO_KEY1); + } + else if ((mpin >= GPIO_KEY1_INV_NP) && (mpin < (GPIO_KEY1_INV_NP + MAX_KEYS))) { + ButtonPullupFlag(mpin - GPIO_KEY1_INV_NP); // 0 .. 3 + ButtonInvertFlag(mpin - GPIO_KEY1_INV_NP); // 0 .. 3 + mpin -= (GPIO_KEY1_INV_NP - GPIO_KEY1); + } + else if ((mpin >= GPIO_REL1_INV) && (mpin < (GPIO_REL1_INV + MAX_RELAYS))) { + bitSet(rel_inverted, mpin - GPIO_REL1_INV); + mpin -= (GPIO_REL1_INV - GPIO_REL1); + } + else if ((mpin >= GPIO_LED1_INV) && (mpin < (GPIO_LED1_INV + MAX_LEDS))) { + bitSet(led_inverted, mpin - GPIO_LED1_INV); + mpin -= (GPIO_LED1_INV - GPIO_LED1); + } + else if (mpin == GPIO_LEDLNK_INV) { + ledlnk_inverted = 1; + mpin -= (GPIO_LEDLNK_INV - GPIO_LEDLNK); + } + else if ((mpin >= GPIO_PWM1_INV) && (mpin < (GPIO_PWM1_INV + MAX_PWMS))) { + bitSet(pwm_inverted, mpin - GPIO_PWM1_INV); + mpin -= (GPIO_PWM1_INV - GPIO_PWM1); + } + else if (XdrvCall(FUNC_PIN_STATE)) { + mpin = XdrvMailbox.index; + } + else if (XsnsCall(FUNC_PIN_STATE)) { + mpin = XdrvMailbox.index; + }; + } + if (mpin) pin[mpin] = i; + } + + if ((2 == pin[GPIO_TXD]) || (H801 == my_module_type)) { Serial.set_tx(2); } + + analogWriteRange(Settings.pwm_range); // Default is 1023 (Arduino.h) + analogWriteFreq(Settings.pwm_frequency); // Default is 1000 (core_esp8266_wiring_pwm.c) + +#ifdef USE_SPI + spi_flg = ((((pin[GPIO_SPI_CS] < 99) && (pin[GPIO_SPI_CS] > 14)) || (pin[GPIO_SPI_CS] < 12)) || (((pin[GPIO_SPI_DC] < 99) && (pin[GPIO_SPI_DC] > 14)) || (pin[GPIO_SPI_DC] < 12))); + if (spi_flg) { + for (uint32_t i = 0; i < GPIO_MAX; i++) { + if ((pin[i] >= 12) && (pin[i] <=14)) pin[i] = 99; + } + my_module.io[12] = GPIO_SPI_MISO; + pin[GPIO_SPI_MISO] = 12; + my_module.io[13] = GPIO_SPI_MOSI; + pin[GPIO_SPI_MOSI] = 13; + my_module.io[14] = GPIO_SPI_CLK; + pin[GPIO_SPI_CLK] = 14; + } + soft_spi_flg = ((pin[GPIO_SSPI_CS] < 99) && (pin[GPIO_SSPI_SCLK] < 99) && ((pin[GPIO_SSPI_MOSI] < 99) || (pin[GPIO_SSPI_MOSI] < 99))); +#endif // USE_SPI + +#ifdef USE_I2C + i2c_flg = ((pin[GPIO_I2C_SCL] < 99) && (pin[GPIO_I2C_SDA] < 99)); + if (i2c_flg) { + Wire.begin(pin[GPIO_I2C_SDA], pin[GPIO_I2C_SCL]); + } +#endif // USE_I2C + + devices_present = 0; + light_type = LT_BASIC; // Use basic PWM control if SetOption15 = 0 + if (XdrvCall(FUNC_MODULE_INIT)) { + // Serviced + } + else if (YTF_IR_BRIDGE == my_module_type) { + ClaimSerial(); // Stop serial loopback mode +// devices_present = 1; + } + else if (SONOFF_DUAL == my_module_type) { + Settings.flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG + devices_present = 2; + baudrate = 19200; + } + else if (CH4 == my_module_type) { + Settings.flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG + devices_present = 4; + baudrate = 19200; + } +#ifdef USE_SONOFF_SC + else if (SONOFF_SC == my_module_type) { + Settings.flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG + devices_present = 0; + baudrate = 19200; + } +#endif // USE_SONOFF_SC + + if (!light_type) { + for (uint32_t i = 0; i < MAX_PWMS; i++) { // Basic PWM control only + if (pin[GPIO_PWM1 +i] < 99) { + pwm_present = true; + pinMode(pin[GPIO_PWM1 +i], OUTPUT); + analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - Settings.pwm_value[i] : Settings.pwm_value[i]); + } + } + } + for (uint32_t i = 0; i < MAX_RELAYS; i++) { + if (pin[GPIO_REL1 +i] < 99) { + pinMode(pin[GPIO_REL1 +i], OUTPUT); + devices_present++; + if (EXS_RELAY == my_module_type) { + digitalWrite(pin[GPIO_REL1 +i], bitRead(rel_inverted, i) ? 1 : 0); + if (i &1) { devices_present--; } + } + } + } + + for (uint32_t i = 0; i < MAX_LEDS; i++) { + if (pin[GPIO_LED1 +i] < 99) { +#ifdef USE_ARILUX_RF + if ((3 == i) && (leds_present < 2) && (99 == pin[GPIO_ARIRFSEL])) { + pin[GPIO_ARIRFSEL] = pin[GPIO_LED4]; // Legacy support where LED4 was Arilux RF enable + pin[GPIO_LED4] = 99; + } else { +#endif + pinMode(pin[GPIO_LED1 +i], OUTPUT); + leds_present++; + digitalWrite(pin[GPIO_LED1 +i], bitRead(led_inverted, i)); +#ifdef USE_ARILUX_RF + } +#endif + } + } + if (pin[GPIO_LEDLNK] < 99) { + pinMode(pin[GPIO_LEDLNK], OUTPUT); + digitalWrite(pin[GPIO_LEDLNK], ledlnk_inverted); + } + + ButtonInit(); + SwitchInit(); +#ifdef ROTARY_V1 + RotaryInit(); +#endif + + SetLedPower(Settings.ledstate &8); + SetLedLink(Settings.ledstate &8); + + XdrvCall(FUNC_PRE_INIT); +} diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index b7b4523e0..e10dfdb63 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -37,7 +37,6 @@ #include "i18n.h" // Language support configured by my_user_config.h #include "tasmota_template.h" // Hardware configuration - #ifdef ARDUINO_ESP8266_RELEASE_2_4_0 #include "lwip/init.h" #if LWIP_VERSION_MAJOR != 1 @@ -69,11 +68,12 @@ // Structs #include "settings.h" -const char kSleepMode[] PROGMEM = "Dynamic|Normal"; -const char kPrefixes[] PROGMEM = D_CMND "|" D_STAT "|" D_TELE; const char kCodeImage[] PROGMEM = "tasmota|minimal|sensors|knx|basic|display|ir"; -// Global variables +/*********************************************************************************************\ + * Global variables +\*********************************************************************************************/ + SerialConfig serial_config = SERIAL_8N1; // Serial interface configuration 8 data bits, No parity, 1 stop bit WiFiUDP PortUdp; // UDP Syslog and Alexa @@ -181,1325 +181,9 @@ char web_log[WEB_LOG_SIZE] = {'\0'}; // Web log buffer #define BACKLOG_EMPTY (backlog_pointer == backlog_index) #endif -/********************************************************************************************/ - -char* Format(char* output, const char* input, int size) -{ - char *token; - uint32_t digits = 0; - - if (strstr(input, "%") != nullptr) { - strlcpy(output, input, size); - token = strtok(output, "%"); - if (strstr(input, "%") == input) { - output[0] = '\0'; - } else { - token = strtok(nullptr, ""); - } - if (token != nullptr) { - digits = atoi(token); - if (digits) { - char tmp[size]; - if (strchr(token, 'd')) { - snprintf_P(tmp, size, PSTR("%s%c0%dd"), output, '%', digits); - snprintf_P(output, size, tmp, ESP.getChipId() & 0x1fff); // %04d - short chip ID in dec, like in hostname - } else { - snprintf_P(tmp, size, PSTR("%s%c0%dX"), output, '%', digits); - snprintf_P(output, size, tmp, ESP.getChipId()); // %06X - full chip ID in hex - } - } else { - if (strchr(token, 'd')) { - snprintf_P(output, size, PSTR("%s%d"), output, ESP.getChipId()); // %d - full chip ID in dec - digits = 8; - } - } - } - } - if (!digits) { - strlcpy(output, input, size); - } - return output; -} - -char* GetOtaUrl(char *otaurl, size_t otaurl_size) -{ - if (strstr(Settings.ota_url, "%04d") != nullptr) { // OTA url contains placeholder for chip ID - snprintf(otaurl, otaurl_size, Settings.ota_url, ESP.getChipId() & 0x1fff); - } - else if (strstr(Settings.ota_url, "%d") != nullptr) { // OTA url contains placeholder for chip ID - snprintf_P(otaurl, otaurl_size, Settings.ota_url, ESP.getChipId()); - } - else { - strlcpy(otaurl, Settings.ota_url, otaurl_size); - } - return otaurl; -} - -char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopic) -{ - /* prefix 0 = Cmnd - prefix 1 = Stat - prefix 2 = Tele - prefix 4 = Cmnd fallback - prefix 5 = Stat fallback - prefix 6 = Tele fallback - prefix 8 = Cmnd topic - prefix 9 = Stat topic - prefix 10 = Tele topic - */ - char romram[CMDSZ]; - String fulltopic; - - snprintf_P(romram, sizeof(romram), subtopic); - if (fallback_topic_flag || (prefix > 3)) { - bool fallback = (prefix < 8); - prefix &= 3; - char stemp[11]; - fulltopic = GetTextIndexed(stemp, sizeof(stemp), prefix, kPrefixes); - fulltopic += F("/"); - if (fallback) { - fulltopic += mqtt_client; - fulltopic += F("_fb"); // cmnd/_fb - } else { - fulltopic += topic; // cmnd/ - } - } else { - fulltopic = Settings.mqtt_fulltopic; - if ((0 == prefix) && (-1 == fulltopic.indexOf(FPSTR(MQTT_TOKEN_PREFIX)))) { - fulltopic += F("/"); - fulltopic += FPSTR(MQTT_TOKEN_PREFIX); // Need prefix for commands to handle mqtt topic loops - } - for (uint32_t i = 0; i < 3; i++) { - if ('\0' == Settings.mqtt_prefix[i][0]) { - GetTextIndexed(Settings.mqtt_prefix[i], sizeof(Settings.mqtt_prefix[i]), i, kPrefixes); - } - } - fulltopic.replace(FPSTR(MQTT_TOKEN_PREFIX), Settings.mqtt_prefix[prefix]); - fulltopic.replace(FPSTR(MQTT_TOKEN_TOPIC), topic); - fulltopic.replace(F("%hostname%"), my_hostname); - String token_id = WiFi.macAddress(); - token_id.replace(":", ""); - fulltopic.replace(F("%id%"), token_id); - } - fulltopic.replace(F("#"), ""); - fulltopic.replace(F("//"), "/"); - if (!fulltopic.endsWith("/")) { - fulltopic += "/"; - } - snprintf_P(stopic, TOPSZ, PSTR("%s%s"), fulltopic.c_str(), romram); - return stopic; -} - -char* GetGroupTopic_P(char *stopic, const char* subtopic) -{ - // SetOption75 0: %prefix%/nothing/%topic% = cmnd/nothing//# - // SetOption75 1: cmnd/ - return GetTopic_P(stopic, (Settings.flag3.grouptopic_mode) ? CMND +8 : CMND, Settings.mqtt_grptopic, subtopic); // SetOption75 - GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1) -} - -char* GetFallbackTopic_P(char *stopic, const char* subtopic) -{ - return GetTopic_P(stopic, CMND +4, nullptr, subtopic); -} - -char* GetStateText(uint32_t state) -{ - if (state > 3) { - state = 1; - } - return Settings.state_text[state]; -} - -/********************************************************************************************/ - -void SetLatchingRelay(power_t lpower, uint32_t state) -{ - // power xx00 - toggle REL1 (Off) and REL3 (Off) - device 1 Off, device 2 Off - // power xx01 - toggle REL2 (On) and REL3 (Off) - device 1 On, device 2 Off - // power xx10 - toggle REL1 (Off) and REL4 (On) - device 1 Off, device 2 On - // power xx11 - toggle REL2 (On) and REL4 (On) - device 1 On, device 2 On - - if (state && !latching_relay_pulse) { // Set latching relay to power if previous pulse has finished - latching_power = lpower; - latching_relay_pulse = 2; // max 200mS (initiated by stateloop()) - } - - for (uint32_t i = 0; i < devices_present; i++) { - uint32_t port = (i << 1) + ((latching_power >> i) &1); - if (pin[GPIO_REL1 +port] < 99) { - digitalWrite(pin[GPIO_REL1 +port], bitRead(rel_inverted, port) ? !state : state); - } - } -} - -void SetDevicePower(power_t rpower, uint32_t source) -{ - ShowSource(source); - last_source = source; - - if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { // All on and stay on - power = (1 << devices_present) -1; - rpower = power; - } - - if (Settings.flag.interlock) { // Allow only one or no relay set - CMND_INTERLOCK - Enable/disable interlock - for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { - power_t mask = 1; - uint32_t count = 0; - for (uint32_t j = 0; j < devices_present; j++) { - if ((Settings.interlock[i] & mask) && (rpower & mask)) { - count++; - } - mask <<= 1; - } - if (count > 1) { - mask = ~Settings.interlock[i]; // Turn interlocked group off as there would be multiple relays on - power &= mask; - rpower &= mask; - } - } - } - - if (rpower) { // Any power set - last_power = rpower; - } - - XdrvMailbox.index = rpower; - XdrvCall(FUNC_SET_POWER); // Signal power state - - XdrvMailbox.index = rpower; - XdrvMailbox.payload = source; - if (XdrvCall(FUNC_SET_DEVICE_POWER)) { // Set power state and stop if serviced - // Serviced - } - else if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { - Serial.write(0xA0); - Serial.write(0x04); - Serial.write(rpower &0xFF); - Serial.write(0xA1); - Serial.write('\n'); - Serial.flush(); - } - else if (EXS_RELAY == my_module_type) { - SetLatchingRelay(rpower, 1); - } - else { - for (uint32_t i = 0; i < devices_present; i++) { - power_t state = rpower &1; - if ((i < MAX_RELAYS) && (pin[GPIO_REL1 +i] < 99)) { - digitalWrite(pin[GPIO_REL1 +i], bitRead(rel_inverted, i) ? !state : state); - } - rpower >>= 1; - } - } -} - -void RestorePower(bool publish_power, uint32_t source) -{ - if (power != last_power) { - SetDevicePower(last_power, source); - if (publish_power) { - MqttPublishAllPowerState(); - } - } -} - -void SetAllPower(uint32_t state, uint32_t source) -{ -// state 0 = POWER_OFF = Relay Off -// state 1 = POWER_ON = Relay On (turn off after Settings.pulse_timer * 100 mSec if enabled) -// state 2 = POWER_TOGGLE = Toggle relay -// state 8 = POWER_OFF_NO_STATE = Relay Off and no publishPowerState -// state 9 = POWER_ON_NO_STATE = Relay On and no publishPowerState -// state 10 = POWER_TOGGLE_NO_STATE = Toggle relay and no publishPowerState -// state 16 = POWER_SHOW_STATE = Show power state - - bool publish_power = true; - if ((state >= POWER_OFF_NO_STATE) && (state <= POWER_TOGGLE_NO_STATE)) { - state &= 3; // POWER_OFF, POWER_ON or POWER_TOGGLE - publish_power = false; - } - if ((state >= POWER_OFF) && (state <= POWER_TOGGLE)) { - power_t all_on = (1 << devices_present) -1; - switch (state) { - case POWER_OFF: - power = 0; - break; - case POWER_ON: - power = all_on; - break; - case POWER_TOGGLE: - power ^= all_on; // Complement current state - } - SetDevicePower(power, source); - } - if (publish_power) { - MqttPublishAllPowerState(); - } -} - -void SetLedPowerIdx(uint32_t led, uint32_t state) -{ - if ((99 == pin[GPIO_LEDLNK]) && (0 == led)) { // Legacy - LED1 is link led only if LED2 is present - if (pin[GPIO_LED2] < 99) { - led = 1; - } - } - if (pin[GPIO_LED1 + led] < 99) { - uint32_t mask = 1 << led; - if (state) { - state = 1; - led_power |= mask; - } else { - led_power &= (0xFF ^ mask); - } - digitalWrite(pin[GPIO_LED1 + led], bitRead(led_inverted, led) ? !state : state); - } -} - -void SetLedPower(uint32_t state) -{ - if (99 == pin[GPIO_LEDLNK]) { // Legacy - Only use LED1 and/or LED2 - SetLedPowerIdx(0, state); - } else { - power_t mask = 1; - for (uint32_t i = 0; i < leds_present; i++) { // Map leds to power - bool tstate = (power & mask); - SetLedPowerIdx(i, tstate); - mask <<= 1; - } - } -} - -void SetLedPowerAll(uint32_t state) -{ - for (uint32_t i = 0; i < leds_present; i++) { - SetLedPowerIdx(i, state); - } -} - -void SetLedLink(uint32_t state) -{ - uint32_t led_pin = pin[GPIO_LEDLNK]; - uint32_t led_inv = ledlnk_inverted; - if (99 == led_pin) { // Legacy - LED1 is status - led_pin = pin[GPIO_LED1]; - led_inv = bitRead(led_inverted, 0); - } - if (led_pin < 99) { - if (state) { state = 1; } - digitalWrite(led_pin, (led_inv) ? !state : state); - } -} - -void SetPulseTimer(uint32_t index, uint32_t time) -{ - pulse_timer[index] = (time > 111) ? millis() + (1000 * (time - 100)) : (time > 0) ? millis() + (100 * time) : 0L; -} - -uint32_t GetPulseTimer(uint32_t index) -{ - long time = TimePassedSince(pulse_timer[index]); - if (time < 0) { - time *= -1; - return (time > 11100) ? (time / 1000) + 100 : (time > 0) ? time / 100 : 0; - } - return 0; -} - -/********************************************************************************************/ - -bool SendKey(uint32_t key, uint32_t device, uint32_t state) -{ -// key 0 = KEY_BUTTON = button_topic -// key 1 = KEY_SWITCH = switch_topic -// state 0 = POWER_OFF = off -// state 1 = POWER_ON = on -// state 2 = POWER_TOGGLE = toggle -// state 3 = POWER_HOLD = hold -// state 9 = CLEAR_RETAIN = clear retain flag - - char stopic[TOPSZ]; - char scommand[CMDSZ]; - char key_topic[sizeof(Settings.button_topic)]; - bool result = false; - - char *tmp = (key) ? Settings.switch_topic : Settings.button_topic; - Format(key_topic, tmp, sizeof(key_topic)); - if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) { // SetOption3 - Enable MQTT - if (!key && (device > devices_present)) { - device = 1; // Only allow number of buttons up to number of devices - } - GetTopic_P(stopic, CMND, key_topic, - GetPowerDevice(scommand, device, sizeof(scommand), (key + Settings.flag.device_index_enable))); // cmnd/switchtopic/POWERx - SetOption26 - Switch between POWER or POWER1 - if (CLEAR_RETAIN == state) { - mqtt_data[0] = '\0'; - } else { - if ((Settings.flag3.button_switch_force_local || // SetOption61 - Force local operation when button/switch topic is set - !strcmp(mqtt_topic, key_topic) || - !strcmp(Settings.mqtt_grptopic, key_topic)) && - (POWER_TOGGLE == state)) { - state = ~(power >> (device -1)) &1; // POWER_OFF or POWER_ON - } - snprintf_P(mqtt_data, sizeof(mqtt_data), GetStateText(state)); - } -#ifdef USE_DOMOTICZ - if (!(DomoticzSendKey(key, device, state, strlen(mqtt_data)))) { -#endif // USE_DOMOTICZ - MqttPublishDirect(stopic, ((key) ? Settings.flag.mqtt_switch_retain // CMND_SWITCHRETAIN - : Settings.flag.mqtt_button_retain) && // CMND_BUTTONRETAIN - (state != POWER_HOLD || !Settings.flag3.no_hold_retain)); // SetOption62 - Don't use retain flag on HOLD messages -#ifdef USE_DOMOTICZ - } -#endif // USE_DOMOTICZ - result = !Settings.flag3.button_switch_force_local; // SetOption61 - Force local operation when button/switch topic is set - } else { - Response_P(PSTR("{\"%s%d\":{\"State\":%d}}"), (key) ? "Switch" : "Button", device, state); - result = XdrvRulesProcess(); - } - int32_t payload_save = XdrvMailbox.payload; - XdrvMailbox.payload = key << 16 | state << 8 | device; - XdrvCall(FUNC_ANY_KEY); - XdrvMailbox.payload = payload_save; - return result; -} - -void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source) -{ -// device = Relay number 1 and up -// state 0 = POWER_OFF = Relay Off -// state 1 = POWER_ON = Relay On (turn off after Settings.pulse_timer * 100 mSec if enabled) -// state 2 = POWER_TOGGLE = Toggle relay -// state 3 = POWER_BLINK = Blink relay -// state 4 = POWER_BLINK_STOP = Stop blinking relay -// state 8 = POWER_OFF_NO_STATE = Relay Off and no publishPowerState -// state 9 = POWER_ON_NO_STATE = Relay On and no publishPowerState -// state 10 = POWER_TOGGLE_NO_STATE = Toggle relay and no publishPowerState -// state 16 = POWER_SHOW_STATE = Show power state - -// ShowSource(source); - -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { - blink_mask &= 1; // No blinking on the fan relays - Settings.flag.interlock = 0; // No interlock mode as it is already done by the microcontroller - CMND_INTERLOCK - Enable/disable interlock - Settings.pulse_timer[1] = 0; // No pulsetimers on the fan relays - Settings.pulse_timer[2] = 0; - Settings.pulse_timer[3] = 0; - } -#endif // USE_SONOFF_IFAN - - bool publish_power = true; - if ((state >= POWER_OFF_NO_STATE) && (state <= POWER_TOGGLE_NO_STATE)) { - state &= 3; // POWER_OFF, POWER_ON or POWER_TOGGLE - publish_power = false; - } - - if ((device < 1) || (device > devices_present)) { - device = 1; - } - active_device = device; - - if (device <= MAX_PULSETIMERS) { - SetPulseTimer(device -1, 0); - } - power_t mask = 1 << (device -1); // Device to control - if (state <= POWER_TOGGLE) { - if ((blink_mask & mask)) { - blink_mask &= (POWER_MASK ^ mask); // Clear device mask - MqttPublishPowerBlinkState(device); - } - - if (Settings.flag.interlock && // CMND_INTERLOCK - Enable/disable interlock - !interlock_mutex && - ((POWER_ON == state) || ((POWER_TOGGLE == state) && !(power & mask))) - ) { - interlock_mutex = true; // Clear all but masked relay in interlock group if new set requested - for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { - if (Settings.interlock[i] & mask) { // Find interlock group - for (uint32_t j = 0; j < devices_present; j++) { - power_t imask = 1 << j; - if ((Settings.interlock[i] & imask) && (power & imask) && (mask != imask)) { - ExecuteCommandPower(j +1, POWER_OFF, SRC_IGNORE); - delay(50); // Add some delay to make sure never have more than one relay on - } - } - break; // An interlocked relay is only present in one group so quit - } - } - interlock_mutex = false; - } - - switch (state) { - case POWER_OFF: { - power &= (POWER_MASK ^ mask); - break; } - case POWER_ON: - power |= mask; - break; - case POWER_TOGGLE: - power ^= mask; - } - SetDevicePower(power, source); -#ifdef USE_DOMOTICZ - DomoticzUpdatePowerState(device); -#endif // USE_DOMOTICZ -#ifdef USE_KNX - KnxUpdatePowerState(device, power); -#endif // USE_KNX - if (publish_power && Settings.flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT - MqttPublishTeleState(); - } - if (device <= MAX_PULSETIMERS) { // Restart PulseTime if powered On - SetPulseTimer(device -1, (((POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? ~power : power) & mask) ? Settings.pulse_timer[device -1] : 0); - } - } - else if (POWER_BLINK == state) { - if (!(blink_mask & mask)) { - blink_powersave = (blink_powersave & (POWER_MASK ^ mask)) | (power & mask); // Save state - blink_power = (power >> (device -1))&1; // Prep to Toggle - } - blink_timer = millis() + 100; - blink_counter = ((!Settings.blinkcount) ? 64000 : (Settings.blinkcount *2)) +1; - blink_mask |= mask; // Set device mask - MqttPublishPowerBlinkState(device); - return; - } - else if (POWER_BLINK_STOP == state) { - bool flag = (blink_mask & mask); - blink_mask &= (POWER_MASK ^ mask); // Clear device mask - MqttPublishPowerBlinkState(device); - if (flag) { - ExecuteCommandPower(device, (blink_powersave >> (device -1))&1, SRC_IGNORE); // Restore state - } - return; - } - if (publish_power) { - MqttPublishPowerState(device); - } -} - -void StopAllPowerBlink(void) -{ - power_t mask; - - for (uint32_t i = 1; i <= devices_present; i++) { - mask = 1 << (i -1); - if (blink_mask & mask) { - blink_mask &= (POWER_MASK ^ mask); // Clear device mask - MqttPublishPowerBlinkState(i); - ExecuteCommandPower(i, (blink_powersave >> (i -1))&1, SRC_IGNORE); // Restore state - } - } -} - -void MqttShowPWMState(void) -{ - ResponseAppend_P(PSTR("\"" D_CMND_PWM "\":{")); - bool first = true; - for (uint32_t i = 0; i < MAX_PWMS; i++) { - if (pin[GPIO_PWM1 + i] < 99) { - ResponseAppend_P(PSTR("%s\"" D_CMND_PWM "%d\":%d"), first ? "" : ",", i+1, Settings.pwm_value[i]); - first = false; - } - } - ResponseJsonEnd(); -} - -void MqttShowState(void) -{ - char stemp1[33]; - - ResponseAppendTime(); - ResponseAppend_P(PSTR(",\"" D_JSON_UPTIME "\":\"%s\",\"UptimeSec\":%u"), GetUptime().c_str(), UpTime()); - -#ifdef USE_ADC_VCC - dtostrfd((double)ESP.getVcc()/1000, 3, stemp1); - ResponseAppend_P(PSTR(",\"" D_JSON_VCC "\":%s"), stemp1); -#endif - - ResponseAppend_P(PSTR(",\"" D_JSON_HEAPSIZE "\":%d,\"SleepMode\":\"%s\",\"Sleep\":%u,\"LoadAvg\":%u,\"MqttCount\":%u"), - ESP.getFreeHeap()/1024, GetTextIndexed(stemp1, sizeof(stemp1), Settings.flag3.sleep_normal, kSleepMode), // SetOption60 - Enable normal sleep instead of dynamic sleep - sleep, loop_load_avg, MqttConnectCount()); - - for (uint32_t i = 1; i <= devices_present; i++) { -#ifdef USE_LIGHT - if ((LightDevice()) && (i >= LightDevice())) { - if (i == LightDevice()) { LightState(1); } // call it only once - } else { -#endif - ResponseAppend_P(PSTR(",\"%s\":\"%s\""), GetPowerDevice(stemp1, i, sizeof(stemp1), Settings.flag.device_index_enable), // SetOption26 - Switch between POWER or POWER1 - GetStateText(bitRead(power, i-1))); -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { - ResponseAppend_P(PSTR(",\"" D_CMND_FANSPEED "\":%d"), GetFanspeed()); - break; - } -#endif // USE_SONOFF_IFAN -#ifdef USE_LIGHT - } -#endif - } - - if (pwm_present) { - ResponseAppend_P(PSTR(",")); - MqttShowPWMState(); - } - - ResponseAppend_P(PSTR(",\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}}"), - Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI()), WifiLinkCount(), WifiDowntime().c_str()); -} - -void MqttPublishTeleState(void) -{ - mqtt_data[0] = '\0'; - MqttShowState(); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); -#ifdef USE_SCRIPT - RulesTeleperiod(); // Allow rule based HA messages -#endif // USE_SCRIPT -} - -bool MqttShowSensor(void) -{ - ResponseAppendTime(); - - int json_data_start = strlen(mqtt_data); - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { -#ifdef USE_TM1638 - if ((pin[GPIO_SWT1 +i] < 99) || ((pin[GPIO_TM16CLK] < 99) && (pin[GPIO_TM16DIO] < 99) && (pin[GPIO_TM16STB] < 99))) { -#else - if (pin[GPIO_SWT1 +i] < 99) { -#endif // USE_TM1638 - bool swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i])); - ResponseAppend_P(PSTR(",\"" D_JSON_SWITCH "%d\":\"%s\""), i +1, GetStateText(swm ^ SwitchLastState(i))); - } - } - XsnsCall(FUNC_JSON_APPEND); - XdrvCall(FUNC_JSON_APPEND); - - bool json_data_available = (strlen(mqtt_data) - json_data_start); - if (strstr_P(mqtt_data, PSTR(D_JSON_PRESSURE)) != nullptr) { - ResponseAppend_P(PSTR(",\"" D_JSON_PRESSURE_UNIT "\":\"%s\""), PressureUnit().c_str()); - } - if (strstr_P(mqtt_data, PSTR(D_JSON_TEMPERATURE)) != nullptr) { - ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE_UNIT "\":\"%c\""), TempUnit()); - } - ResponseJsonEnd(); - - if (json_data_available) { XdrvCall(FUNC_SHOW_SENSOR); } - return json_data_available; -} - -void MqttPublishSensor(void) -{ - mqtt_data[0] = '\0'; - if (MqttShowSensor()) { - MqttPublishTeleSensor(); - } -} - -/********************************************************************************************/ - -void PerformEverySecond(void) -{ - uptime++; - - if (ntp_synced_message) { - // Moved here to fix syslog UDP exception 9 during RtcSecond - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NTP: Drift %d, (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), - DriftTime(), GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); - ntp_synced_message = false; - } - - if (POWER_CYCLE_TIME == uptime) { - UpdateQuickPowerCycle(false); - } - - if (BOOT_LOOP_TIME == uptime) { - RtcRebootReset(); - -#ifdef USE_DEEPSLEEP - if (!(DeepSleepEnabled() && !Settings.flag3.bootcount_update)) { -#endif - Settings.bootcount++; // Moved to here to stop flash writes during start-up - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BOOT_COUNT " %d"), Settings.bootcount); -#ifdef USE_DEEPSLEEP - } -#endif - } - - if (seriallog_timer) { - seriallog_timer--; - if (!seriallog_timer) { - if (seriallog_level) { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SERIAL_LOGGING_DISABLED)); - } - seriallog_level = 0; - } - } - - if (syslog_timer) { // Restore syslog level - syslog_timer--; - if (!syslog_timer) { - syslog_level = Settings.syslog_level; - if (Settings.syslog_level) { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SYSLOG_LOGGING_REENABLED)); // Might trigger disable again (on purpose) - } - } - } - - ResetGlobalValues(); - - if (Settings.tele_period) { - if (tele_period >= 9999) { - if (!global_state.wifi_down) { - tele_period = 0; // Allow teleperiod once wifi is connected - } - } else { - tele_period++; - if (tele_period >= Settings.tele_period) { - tele_period = 0; - - MqttPublishTeleState(); - - mqtt_data[0] = '\0'; - if (MqttShowSensor()) { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); // CMND_SENSORRETAIN -#if defined(USE_RULES) || defined(USE_SCRIPT) - RulesTeleperiod(); // Allow rule based HA messages -#endif // USE_RULES - } - - XdrvCall(FUNC_AFTER_TELEPERIOD); - } - } - } -} - /*********************************************************************************************\ - * State loops + * Main \*********************************************************************************************/ -/*-------------------------------------------------------------------------------------------*\ - * Every 0.1 second -\*-------------------------------------------------------------------------------------------*/ - -void Every100mSeconds(void) -{ - // As the max amount of sleep = 250 mSec this loop will shift in time... - power_t power_now; - - if (latching_relay_pulse) { - latching_relay_pulse--; - if (!latching_relay_pulse) SetLatchingRelay(0, 0); - } - - for (uint32_t i = 0; i < MAX_PULSETIMERS; i++) { - if (pulse_timer[i] != 0L) { // Timer active? - if (TimeReached(pulse_timer[i])) { // Timer finished? - pulse_timer[i] = 0L; // Turn off this timer - ExecuteCommandPower(i +1, (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? POWER_ON : POWER_OFF, SRC_PULSETIMER); - } - } - } - - if (blink_mask) { - if (TimeReached(blink_timer)) { - SetNextTimeInterval(blink_timer, 100 * Settings.blinktime); - blink_counter--; - if (!blink_counter) { - StopAllPowerBlink(); - } else { - blink_power ^= 1; - power_now = (power & (POWER_MASK ^ blink_mask)) | ((blink_power) ? blink_mask : 0); - SetDevicePower(power_now, SRC_IGNORE); - } - } - } -} - -/*-------------------------------------------------------------------------------------------*\ - * Every 0.25 second -\*-------------------------------------------------------------------------------------------*/ - -void Every250mSeconds(void) -{ -// As the max amount of sleep = 250 mSec this loop should always be taken... - - uint32_t blinkinterval = 1; - - state_250mS++; - state_250mS &= 0x3; - - if (mqtt_cmnd_publish) mqtt_cmnd_publish--; // Clean up - - if (!Settings.flag.global_state) { // Problem blinkyblinky enabled - SetOption31 - Control link led blinking - if (global_state.data) { // Any problem - if (global_state.mqtt_down) { blinkinterval = 7; } // MQTT problem so blink every 2 seconds (slowest) - if (global_state.wifi_down) { blinkinterval = 3; } // Wifi problem so blink every second (slow) - blinks = 201; // Allow only a single blink in case the problem is solved - } - } - if (blinks || restart_flag || ota_state_flag) { - if (restart_flag || ota_state_flag) { // Overrule blinks and keep led lit - blinkstate = true; // Stay lit - } else { - blinkspeed--; - if (!blinkspeed) { - blinkspeed = blinkinterval; // Set interval to 0.2 (default), 1 or 2 seconds - blinkstate ^= 1; // Blink - } - } - if ((!(Settings.ledstate &0x08)) && ((Settings.ledstate &0x06) || (blinks > 200) || (blinkstate))) { - SetLedLink(blinkstate); // Set led on or off - } - if (!blinkstate) { - blinks--; - if (200 == blinks) blinks = 0; // Disable blink - } - } - if (Settings.ledstate &1 && (pin[GPIO_LEDLNK] < 99 || !(blinks || restart_flag || ota_state_flag)) ) { - bool tstate = power & Settings.ledmask; - if ((SONOFF_TOUCH == my_module_type) || (SONOFF_T11 == my_module_type) || (SONOFF_T12 == my_module_type) || (SONOFF_T13 == my_module_type)) { - tstate = (!power) ? 1 : 0; // As requested invert signal for Touch devices to find them in the dark - } - SetLedPower(tstate); - } - -/*-------------------------------------------------------------------------------------------*\ - * Every second at 0.25 second interval -\*-------------------------------------------------------------------------------------------*/ - - switch (state_250mS) { - case 0: // Every x.0 second - if (ota_state_flag && BACKLOG_EMPTY) { - ota_state_flag--; - if (2 == ota_state_flag) { - ota_url = Settings.ota_url; - RtcSettings.ota_loader = 0; // Try requested image first - ota_retry_counter = OTA_ATTEMPTS; - ESPhttpUpdate.rebootOnUpdate(false); - SettingsSave(1); // Free flash for OTA update - } - if (ota_state_flag <= 0) { -#ifdef USE_WEBSERVER - if (Settings.webserver) StopWebserver(); -#endif // USE_WEBSERVER -#ifdef USE_ARILUX_RF - AriluxRfDisable(); // Prevent restart exception on Arilux Interrupt routine -#endif // USE_ARILUX_RF - ota_state_flag = 92; - ota_result = 0; - ota_retry_counter--; - if (ota_retry_counter) { - strlcpy(mqtt_data, GetOtaUrl(log_data, sizeof(log_data)), sizeof(mqtt_data)); -#ifndef FIRMWARE_MINIMAL - if (RtcSettings.ota_loader) { - char *bch = strrchr(mqtt_data, '/'); // Only consider filename after last backslash prevent change of urls having "-" in it - char *pch = strrchr((bch != nullptr) ? bch : mqtt_data, '-'); // Change from filename-DE.bin into filename-minimal.bin - char *ech = strrchr((bch != nullptr) ? bch : mqtt_data, '.'); // Change from filename.bin into filename-minimal.bin - if (!pch) { pch = ech; } - if (pch) { - mqtt_data[pch - mqtt_data] = '\0'; - char *ech = strrchr(Settings.ota_url, '.'); // Change from filename.bin into filename-minimal.bin - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s-" D_JSON_MINIMAL "%s"), mqtt_data, ech); // Minimal filename must be filename-minimal - } - } -#endif // FIRMWARE_MINIMAL - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "%s"), mqtt_data); -#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) - ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(mqtt_data)); -#else - // If using core stage or 2.5.0+ the syntax has changed - WiFiClient OTAclient; - ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(OTAclient, mqtt_data)); -#endif - if (!ota_result) { -#ifndef FIRMWARE_MINIMAL - int ota_error = ESPhttpUpdate.getLastError(); - DEBUG_CORE_LOG(PSTR("OTA: Error %d"), ota_error); - if ((HTTP_UE_TOO_LESS_SPACE == ota_error) || (HTTP_UE_BIN_FOR_WRONG_FLASH == ota_error)) { - RtcSettings.ota_loader = 1; // Try minimal image next - } -#endif // FIRMWARE_MINIMAL - ota_state_flag = 2; // Upgrade failed - retry - } - } - } - if (90 == ota_state_flag) { // Allow MQTT to reconnect - ota_state_flag = 0; - if (ota_result) { -// SetFlashModeDout(); // Force DOUT for both ESP8266 and ESP8285 - Response_P(PSTR(D_JSON_SUCCESSFUL ". " D_JSON_RESTARTING)); - } else { - Response_P(PSTR(D_JSON_FAILED " %s"), ESPhttpUpdate.getLastErrorString().c_str()); - } - restart_flag = 2; // Restart anyway to keep memory clean webserver - MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_UPGRADE)); - } - } - break; - case 1: // Every x.25 second - if (MidnightNow()) { - XsnsCall(FUNC_SAVE_AT_MIDNIGHT); - } - if (save_data_counter && BACKLOG_EMPTY) { - save_data_counter--; - if (save_data_counter <= 0) { - if (Settings.flag.save_state) { // SetOption0 - Save power state and use after restart - power_t mask = POWER_MASK; - for (uint32_t i = 0; i < MAX_PULSETIMERS; i++) { - if ((Settings.pulse_timer[i] > 0) && (Settings.pulse_timer[i] < 30)) { // 3 seconds - mask &= ~(1 << i); - } - } - if (!((Settings.power &mask) == (power &mask))) { - Settings.power = power; - } - } else { - Settings.power = 0; - } - SettingsSave(0); - save_data_counter = Settings.save_data; - } - } - if (restart_flag && BACKLOG_EMPTY) { - if ((214 == restart_flag) || (215 == restart_flag) || (216 == restart_flag)) { - char storage_wifi[sizeof(Settings.sta_ssid) + - sizeof(Settings.sta_pwd)]; - char storage_mqtt[sizeof(Settings.mqtt_host) + - sizeof(Settings.mqtt_port) + - sizeof(Settings.mqtt_client) + - sizeof(Settings.mqtt_user) + - sizeof(Settings.mqtt_pwd) + - sizeof(Settings.mqtt_topic)]; - memcpy(storage_wifi, Settings.sta_ssid, sizeof(storage_wifi)); // Backup current SSIDs and Passwords - if (216 == restart_flag) { - memcpy(storage_mqtt, Settings.mqtt_host, sizeof(storage_mqtt)); // Backup mqtt host, port, client, username and password - } - if ((215 == restart_flag) || (216 == restart_flag)) { - SettingsErase(0); // Erase all flash from program end to end of physical flash - } - SettingsDefault(); - memcpy(Settings.sta_ssid, storage_wifi, sizeof(storage_wifi)); // Restore current SSIDs and Passwords - if (216 == restart_flag) { - memcpy(Settings.mqtt_host, storage_mqtt, sizeof(storage_mqtt)); // Restore the mqtt host, port, client, username and password - strlcpy(Settings.mqtt_client, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client)); // Set client to default - } - restart_flag = 2; - } - else if (213 == restart_flag) { - SettingsSdkErase(); // Erase flash SDK parameters - restart_flag = 2; - } - else if (212 == restart_flag) { - SettingsErase(0); // Erase all flash from program end to end of physical flash - restart_flag = 211; - } - if (211 == restart_flag) { - SettingsDefault(); - restart_flag = 2; - } - if (2 == restart_flag) { - SettingsSaveAll(); - } - restart_flag--; - if (restart_flag <= 0) { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); - EspRestart(); - } - } - break; - case 2: // Every x.5 second - WifiCheck(wifi_state_flag); - wifi_state_flag = WIFI_RESTART; - break; - case 3: // Every x.75 second - if (!global_state.wifi_down) { MqttCheck(); } - break; - } -} - -#ifdef USE_ARDUINO_OTA -/*********************************************************************************************\ - * Allow updating via the Arduino OTA-protocol. - * - * - Once started disables current wifi clients and udp - * - Perform restart when done to re-init wifi clients -\*********************************************************************************************/ - -bool arduino_ota_triggered = false; -uint16_t arduino_ota_progress_dot_count = 0; - -void ArduinoOTAInit(void) -{ - ArduinoOTA.setPort(8266); - ArduinoOTA.setHostname(my_hostname); - if (Settings.web_password[0] !=0) { ArduinoOTA.setPassword(Settings.web_password); } - - ArduinoOTA.onStart([]() - { - SettingsSave(1); // Free flash for OTA update -#ifdef USE_WEBSERVER - if (Settings.webserver) { StopWebserver(); } -#endif // USE_WEBSERVER -#ifdef USE_ARILUX_RF - AriluxRfDisable(); // Prevent restart exception on Arilux Interrupt routine -#endif // USE_ARILUX_RF - if (Settings.flag.mqtt_enabled) { - MqttDisconnect(); // SetOption3 - Enable MQTT - } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_UPLOAD_STARTED)); - arduino_ota_triggered = true; - arduino_ota_progress_dot_count = 0; - delay(100); // Allow time for message xfer - }); - - ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) - { - if ((LOG_LEVEL_DEBUG <= seriallog_level)) { - arduino_ota_progress_dot_count++; - Serial.printf("."); - if (!(arduino_ota_progress_dot_count % 80)) { Serial.println(); } - } - }); - - ArduinoOTA.onError([](ota_error_t error) - { - /* - From ArduinoOTA.h: - typedef enum { OTA_AUTH_ERROR, OTA_BEGIN_ERROR, OTA_CONNECT_ERROR, OTA_RECEIVE_ERROR, OTA_END_ERROR } ota_error_t; - */ - char error_str[100]; - - if ((LOG_LEVEL_DEBUG <= seriallog_level) && arduino_ota_progress_dot_count) { Serial.println(); } - switch (error) { - case OTA_BEGIN_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_2), sizeof(error_str)); break; - case OTA_RECEIVE_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_5), sizeof(error_str)); break; - case OTA_END_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_7), sizeof(error_str)); break; - default: - snprintf_P(error_str, sizeof(error_str), PSTR(D_UPLOAD_ERROR_CODE " %d"), error); - } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA %s. " D_RESTARTING), error_str); - EspRestart(); - }); - - ArduinoOTA.onEnd([]() - { - if ((LOG_LEVEL_DEBUG <= seriallog_level)) { Serial.println(); } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_SUCCESSFUL ". " D_RESTARTING)); - EspRestart(); - }); - - ArduinoOTA.begin(); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_ENABLED " " D_PORT " 8266")); -} -#endif // USE_ARDUINO_OTA - -/********************************************************************************************/ - -void SerialInput(void) -{ - while (Serial.available()) { -// yield(); - delay(0); - serial_in_byte = Serial.read(); - -/*-------------------------------------------------------------------------------------------*\ - * Sonoff dual and ch4 19200 baud serial interface -\*-------------------------------------------------------------------------------------------*/ - if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { - serial_in_byte = ButtonSerial(serial_in_byte); - } - -/*-------------------------------------------------------------------------------------------*/ - - if (XdrvCall(FUNC_SERIAL)) { - serial_in_byte_counter = 0; - Serial.flush(); - return; - } - -/*-------------------------------------------------------------------------------------------*/ - - if (serial_in_byte > 127 && !Settings.flag.mqtt_serial_raw) { // Discard binary data above 127 if no raw reception allowed - CMND_SERIALSEND3 - serial_in_byte_counter = 0; - Serial.flush(); - return; - } - if (!Settings.flag.mqtt_serial) { // SerialSend active - CMND_SERIALSEND and CMND_SERIALLOG - if (isprint(serial_in_byte)) { // Any char between 32 and 127 - if (serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { // Add char to string if it still fits - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - } else { - serial_in_byte_counter = 0; - } - } - } else { - if (serial_in_byte || Settings.flag.mqtt_serial_raw) { // Any char between 1 and 127 or any char (0 - 255) - CMND_SERIALSEND3 - if ((serial_in_byte_counter < INPUT_BUFFER_SIZE -1) && // Add char to string if it still fits and ... - ((isprint(serial_in_byte) && (128 == Settings.serial_delimiter)) || // Any char between 32 and 127 - ((serial_in_byte != Settings.serial_delimiter) && (128 != Settings.serial_delimiter)) || // Any char between 1 and 127 and not being delimiter - Settings.flag.mqtt_serial_raw)) { // Any char between 0 and 255 - CMND_SERIALSEND3 - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - serial_polling_window = millis(); - } else { - serial_polling_window = 0; // Reception done - send mqtt - break; - } - } - } - -#ifdef USE_SONOFF_SC -/*-------------------------------------------------------------------------------------------*\ - * Sonoff SC 19200 baud serial interface -\*-------------------------------------------------------------------------------------------*/ - if (SONOFF_SC == my_module_type) { - if (serial_in_byte == '\x1B') { // Sonoff SC status from ATMEGA328P - serial_in_buffer[serial_in_byte_counter] = 0; // Serial data completed - SonoffScSerialInput(serial_in_buffer); - serial_in_byte_counter = 0; - Serial.flush(); - return; - } - } else -#endif // USE_SONOFF_SC -/*-------------------------------------------------------------------------------------------*/ - - if (!Settings.flag.mqtt_serial && (serial_in_byte == '\n')) { // CMND_SERIALSEND and CMND_SERIALLOG - serial_in_buffer[serial_in_byte_counter] = 0; // Serial data completed - seriallog_level = (Settings.seriallog_level < LOG_LEVEL_INFO) ? (uint8_t)LOG_LEVEL_INFO : Settings.seriallog_level; - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "%s"), serial_in_buffer); - ExecuteCommand(serial_in_buffer, SRC_SERIAL); - serial_in_byte_counter = 0; - serial_polling_window = 0; - Serial.flush(); - return; - } - } - - if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) { // CMND_SERIALSEND and CMND_SERIALLOG - serial_in_buffer[serial_in_byte_counter] = 0; // Serial data completed - char hex_char[(serial_in_byte_counter * 2) + 2]; - Response_P(PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), - (Settings.flag.mqtt_serial_raw) ? ToHex_P((unsigned char*)serial_in_buffer, serial_in_byte_counter, hex_char, sizeof(hex_char)) : serial_in_buffer); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED)); - XdrvRulesProcess(); - serial_in_byte_counter = 0; - } -} - -/********************************************************************************************/ - -void GpioInit(void) -{ - uint32_t mpin; - - if (!ValidModule(Settings.module)) { - uint32_t module = MODULE; - if (!ValidModule(MODULE)) { module = SONOFF_BASIC; } - Settings.module = module; - Settings.last_module = module; - } - SetModuleType(); - - if (Settings.module != Settings.last_module) { - baudrate = APP_BAUDRATE; - } - - for (uint32_t i = 0; i < sizeof(Settings.user_template.gp); i++) { - if ((Settings.user_template.gp.io[i] >= GPIO_SENSOR_END) && (Settings.user_template.gp.io[i] < GPIO_USER)) { - Settings.user_template.gp.io[i] = GPIO_USER; // Fix not supported sensor ids in template - } - } - - myio def_gp; - ModuleGpios(&def_gp); - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - if ((Settings.my_gp.io[i] >= GPIO_SENSOR_END) && (Settings.my_gp.io[i] < GPIO_USER)) { - Settings.my_gp.io[i] = GPIO_NONE; // Fix not supported sensor ids in module - } - else if (Settings.my_gp.io[i] > GPIO_NONE) { - my_module.io[i] = Settings.my_gp.io[i]; // Set User selected Module sensors - } - if ((def_gp.io[i] > GPIO_NONE) && (def_gp.io[i] < GPIO_USER)) { - my_module.io[i] = def_gp.io[i]; // Force Template override - } - } - if ((Settings.my_adc0 >= ADC0_END) && (Settings.my_adc0 < ADC0_USER)) { - Settings.my_adc0 = ADC0_NONE; // Fix not supported sensor ids in module - } - else if (Settings.my_adc0 > ADC0_NONE) { - my_adc0 = Settings.my_adc0; // Set User selected Module sensors - } - my_module_flag = ModuleFlag(); - uint32_t template_adc0 = my_module_flag.data &15; - if ((template_adc0 > ADC0_NONE) && (template_adc0 < ADC0_USER)) { - my_adc0 = template_adc0; // Force Template override - } - - for (uint32_t i = 0; i < GPIO_MAX; i++) { - pin[i] = 99; - } - for (uint32_t i = 0; i < sizeof(my_module.io); i++) { - mpin = ValidPin(i, my_module.io[i]); - - DEBUG_CORE_LOG(PSTR("INI: gpio pin %d, mpin %d"), i, mpin); - - if (mpin) { - XdrvMailbox.index = mpin; - XdrvMailbox.payload = i; - - if ((mpin >= GPIO_SWT1_NP) && (mpin < (GPIO_SWT1_NP + MAX_SWITCHES))) { - SwitchPullupFlag(mpin - GPIO_SWT1_NP); - mpin -= (GPIO_SWT1_NP - GPIO_SWT1); - } - else if ((mpin >= GPIO_KEY1_NP) && (mpin < (GPIO_KEY1_NP + MAX_KEYS))) { - ButtonPullupFlag(mpin - GPIO_KEY1_NP); // 0 .. 3 - mpin -= (GPIO_KEY1_NP - GPIO_KEY1); - } - else if ((mpin >= GPIO_KEY1_INV) && (mpin < (GPIO_KEY1_INV + MAX_KEYS))) { - ButtonInvertFlag(mpin - GPIO_KEY1_INV); // 0 .. 3 - mpin -= (GPIO_KEY1_INV - GPIO_KEY1); - } - else if ((mpin >= GPIO_KEY1_INV_NP) && (mpin < (GPIO_KEY1_INV_NP + MAX_KEYS))) { - ButtonPullupFlag(mpin - GPIO_KEY1_INV_NP); // 0 .. 3 - ButtonInvertFlag(mpin - GPIO_KEY1_INV_NP); // 0 .. 3 - mpin -= (GPIO_KEY1_INV_NP - GPIO_KEY1); - } - else if ((mpin >= GPIO_REL1_INV) && (mpin < (GPIO_REL1_INV + MAX_RELAYS))) { - bitSet(rel_inverted, mpin - GPIO_REL1_INV); - mpin -= (GPIO_REL1_INV - GPIO_REL1); - } - else if ((mpin >= GPIO_LED1_INV) && (mpin < (GPIO_LED1_INV + MAX_LEDS))) { - bitSet(led_inverted, mpin - GPIO_LED1_INV); - mpin -= (GPIO_LED1_INV - GPIO_LED1); - } - else if (mpin == GPIO_LEDLNK_INV) { - ledlnk_inverted = 1; - mpin -= (GPIO_LEDLNK_INV - GPIO_LEDLNK); - } - else if ((mpin >= GPIO_PWM1_INV) && (mpin < (GPIO_PWM1_INV + MAX_PWMS))) { - bitSet(pwm_inverted, mpin - GPIO_PWM1_INV); - mpin -= (GPIO_PWM1_INV - GPIO_PWM1); - } - else if (XdrvCall(FUNC_PIN_STATE)) { - mpin = XdrvMailbox.index; - } - else if (XsnsCall(FUNC_PIN_STATE)) { - mpin = XdrvMailbox.index; - }; - } - if (mpin) pin[mpin] = i; - } - - if ((2 == pin[GPIO_TXD]) || (H801 == my_module_type)) { Serial.set_tx(2); } - - analogWriteRange(Settings.pwm_range); // Default is 1023 (Arduino.h) - analogWriteFreq(Settings.pwm_frequency); // Default is 1000 (core_esp8266_wiring_pwm.c) - -#ifdef USE_SPI - spi_flg = ((((pin[GPIO_SPI_CS] < 99) && (pin[GPIO_SPI_CS] > 14)) || (pin[GPIO_SPI_CS] < 12)) || (((pin[GPIO_SPI_DC] < 99) && (pin[GPIO_SPI_DC] > 14)) || (pin[GPIO_SPI_DC] < 12))); - if (spi_flg) { - for (uint32_t i = 0; i < GPIO_MAX; i++) { - if ((pin[i] >= 12) && (pin[i] <=14)) pin[i] = 99; - } - my_module.io[12] = GPIO_SPI_MISO; - pin[GPIO_SPI_MISO] = 12; - my_module.io[13] = GPIO_SPI_MOSI; - pin[GPIO_SPI_MOSI] = 13; - my_module.io[14] = GPIO_SPI_CLK; - pin[GPIO_SPI_CLK] = 14; - } - soft_spi_flg = ((pin[GPIO_SSPI_CS] < 99) && (pin[GPIO_SSPI_SCLK] < 99) && ((pin[GPIO_SSPI_MOSI] < 99) || (pin[GPIO_SSPI_MOSI] < 99))); -#endif // USE_SPI - -#ifdef USE_I2C - i2c_flg = ((pin[GPIO_I2C_SCL] < 99) && (pin[GPIO_I2C_SDA] < 99)); - if (i2c_flg) { - Wire.begin(pin[GPIO_I2C_SDA], pin[GPIO_I2C_SCL]); - } -#endif // USE_I2C - - devices_present = 0; - light_type = LT_BASIC; // Use basic PWM control if SetOption15 = 0 - if (XdrvCall(FUNC_MODULE_INIT)) { - // Serviced - } - else if (YTF_IR_BRIDGE == my_module_type) { - ClaimSerial(); // Stop serial loopback mode -// devices_present = 1; - } - else if (SONOFF_DUAL == my_module_type) { - Settings.flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG - devices_present = 2; - baudrate = 19200; - } - else if (CH4 == my_module_type) { - Settings.flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG - devices_present = 4; - baudrate = 19200; - } -#ifdef USE_SONOFF_SC - else if (SONOFF_SC == my_module_type) { - Settings.flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG - devices_present = 0; - baudrate = 19200; - } -#endif // USE_SONOFF_SC - - if (!light_type) { - for (uint32_t i = 0; i < MAX_PWMS; i++) { // Basic PWM control only - if (pin[GPIO_PWM1 +i] < 99) { - pwm_present = true; - pinMode(pin[GPIO_PWM1 +i], OUTPUT); - analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - Settings.pwm_value[i] : Settings.pwm_value[i]); - } - } - } - for (uint32_t i = 0; i < MAX_RELAYS; i++) { - if (pin[GPIO_REL1 +i] < 99) { - pinMode(pin[GPIO_REL1 +i], OUTPUT); - devices_present++; - if (EXS_RELAY == my_module_type) { - digitalWrite(pin[GPIO_REL1 +i], bitRead(rel_inverted, i) ? 1 : 0); - if (i &1) { devices_present--; } - } - } - } - - for (uint32_t i = 0; i < MAX_LEDS; i++) { - if (pin[GPIO_LED1 +i] < 99) { -#ifdef USE_ARILUX_RF - if ((3 == i) && (leds_present < 2) && (99 == pin[GPIO_ARIRFSEL])) { - pin[GPIO_ARIRFSEL] = pin[GPIO_LED4]; // Legacy support where LED4 was Arilux RF enable - pin[GPIO_LED4] = 99; - } else { -#endif - pinMode(pin[GPIO_LED1 +i], OUTPUT); - leds_present++; - digitalWrite(pin[GPIO_LED1 +i], bitRead(led_inverted, i)); -#ifdef USE_ARILUX_RF - } -#endif - } - } - if (pin[GPIO_LEDLNK] < 99) { - pinMode(pin[GPIO_LEDLNK], OUTPUT); - digitalWrite(pin[GPIO_LEDLNK], ledlnk_inverted); - } - - ButtonInit(); - SwitchInit(); -#ifdef ROTARY_V1 - RotaryInit(); -#endif - - SetLedPower(Settings.ledstate &8); - SetLedLink(Settings.ledstate &8); - - XdrvCall(FUNC_PRE_INIT); -} void setup(void) { From 07807fc7999807a50f03fffb2701394ca3b1b616 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 2 Dec 2019 11:10:04 +0100 Subject: [PATCH 43/50] Update RELEASENOTES.md --- RELEASENOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 8bc11b7ab..51d078352 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -47,7 +47,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 7.1.1.1 Betty +### Version 7.1.2 Betty - Fix lost functionality of GPIO9 and GPIO10 on some devices (#7080) - Fix Zigbee uses Hardware Serial if GPIO 1/3 or GPIO 13/15 and SerialLog 0 (#7071) From 8c3295034d72cb2906932184d4d14dfb1d7b2e04 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 2 Dec 2019 11:56:40 +0100 Subject: [PATCH 44/50] Update support_wifi.ino --- tasmota/support_wifi.ino | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index c920c8a63..49faa0663 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -118,8 +118,10 @@ void WifiSetMode(WiFiMode_t wifi_mode) delay(100); } - if (!WiFi.mode(wifi_mode)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI "Cannot set Mode")); + uint32_t retry = 2; + while (!WiFi.mode(wifi_mode) && retry--) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR("Retry set Mode...")); + delay(100); } if (wifi_mode == WIFI_OFF) { From eb1785c559fb2031ce922b52b7347790d638d3fa Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 2 Dec 2019 14:51:28 +0100 Subject: [PATCH 45/50] Tune light schemes 2, 3 and 4 --- tasmota/xdrv_04_light.ino | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 8b6b96bbd..0ef3f1ea9 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -241,8 +241,8 @@ struct LIGHT { uint8_t last_color[LST_MAX]; uint8_t color_remap[LST_MAX]; - uint16_t wheel = 0; - uint16_t random = 0; + uint8_t wheel = 0; + uint8_t random = 0; uint8_t subtype = 0; // LST_ subtype uint8_t device = 0; uint8_t old_power = 1; @@ -1518,18 +1518,18 @@ void LightCycleColor(int8_t direction) if (0 == direction) { if (Light.random == Light.wheel) { - Light.random = random(358) +1; // Random Hue + Light.random = random(255); } - Light.wheel += (Light.random < Light.wheel) ? -1 : 1; - } else { - Light.wheel += direction; + direction = (Light.random < Light.wheel) ? -1 : 1; } - if (Light.wheel > 359) { Light.wheel = 1; } // Loop Hue colors - if (Light.wheel < 1) { Light.wheel = 359; } // Loop Hue colors + Light.wheel += direction; + uint16_t hue = changeUIntScale(Light.wheel, 0, 255, 0, 359); // Scale to hue to keep amount of steps low (max 255 instead of 359) + +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: random %d, wheel %d, hue %d"), Light.random, Light.wheel, hue); uint8_t sat; light_state.getHSB(nullptr, &sat, nullptr); // Allow user control over Saturation - light_state.setHS(Light.wheel, sat); + light_state.setHS(hue, sat); light_controller.calcLevels(Light.new_color); } From 0b59cc6ea123b59b5ca96d66f62b8a298cfb7628 Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Mon, 2 Dec 2019 15:15:04 +0100 Subject: [PATCH 46/50] decode-config moved to https://github.com/tasmota/decode-config --- tools/decode-config.md | 408 +---- tools/decode-config.py | 3322 ---------------------------------------- 2 files changed, 2 insertions(+), 3728 deletions(-) delete mode 100755 tools/decode-config.py diff --git a/tools/decode-config.md b/tools/decode-config.md index 4097638fa..10019a23f 100644 --- a/tools/decode-config.md +++ b/tools/decode-config.md @@ -1,407 +1,3 @@ -# decode-config.py -_decode-config.py_ is able to backup and restore Tasmota configuration. +A tool to backup and restore the configuration of [Tasmota](http://tasmota.com/)-devices. -In comparison with the Tasmota build-in "Backup/Restore Configuration" function _decode-config.py_ -* uses human readable and editable [JSON](http://www.json.org/)-format for backup/restore, -* can restore previously backup and changed [JSON](http://www.json.org/)-format files, -* is able to create Tasmota compatible command list with related config parameter - -Comparing backup files created by *decode-config.py* and *.dmp files created by Tasmota "Backup/Restore Configuration": - -|   | decode-config.py
*.json file | Tasmota
*.dmp file | -|-------------------------|:-------------------------------:|:-----------------------------------:| -| Encrypted | No | Yes | -| Readable | Yes | No | -| Simply editable | Yes | No | -| Simply batch processing | Yes | No | - -_decode-config.py_ is compatible with Tasmota version from v5.10.0 up to now. - -# Content -* [Prerequisite](decode-config.md#prerequisite) -* [File Types](decode-config.md#file-types) - * [.dmp File Format](decode-config.md#-dmp-format) - * [.json File Format](decode-config.md#-json-format) - * [.bin File Format](decode-config.md#-bin-format) - * [File extensions](decode-config.md#file-extensions) -* [Usage](decode-config.md#usage) - * [Basics](decode-config.md#basics) - * [Save backup file](decode-config.md#save-backup-file) - * [Restore backup file](decode-config.md#restore-backup-file) - * [Output to screen](decode-config.md#output-to-screen) - * [JSON output](decode-config.md#json-output) - * [Tasmota command output](decode-config.md#tasmota-command-output) - * [Filter data](decode-config.md#filter-data) - * [Configuration file](decode-config.md#configuration-file) - * [More program arguments](decode-config.md#more-program-arguments) - * [Examples](decode-config.md#examples) - * [Config file](decode-config.md#config-file) - * [Using Tasmota binary configuration files](decode-config.md#using-tasmota-binary-configuration-files) - * [Use batch processing](decode-config.md#use-batch-processing) - * [Notes](decode-config.md#notes) - -## Prerequisite -* This program is written in [Python](https://en.wikipedia.org/wiki/Python_(programming_language)) so you need to install a working python environment for your operating system. - -### Linux -``` -sudo apt-get install python python-pip libcurl4-openssl-dev libssl-dev -``` -``` -pip install pycurl configargparse -``` - -### Windows 10 - -Install [Python 2.7](https://www.python.org/download/releases/2.7/) then install dependencies. For PyCurl you need to [download pycurl‑7.43.0.3‑cp27‑cp27m‑win_amd64.whl](https://www.lfd.uci.edu/~gohlke/pythonlibs/#pycurl) for Windows 10 64bit. -``` -pip install pycurl-7.43.0.3-cp27-cp27m-win_amd64.whl -// run the command from the folder where you downloaded the file - -pip install configargparse -``` - -* [Tasmota](https://github.com/arendst/Tasmota) [Firmware](https://github.com/arendst/Tasmota/releases) with Web-Server enabled: - * To backup or restore configurations from or to a Tasmota device you need a firmare with enabled web-server in admin mode (command [WebServer 2](https://tasmota.github.io/docs/#/Commands#wifi)). This is the Tasmota default. - * If using your own compiled firmware be aware to enable the web-server (`#define USE_WEBSERVER` and `#define WEB_SERVER 2`). - -## File Types -_decode-config.py_ can handle the following backup file types: -### .dmp Format -Configuration data as used by Tasmota "Backup/Restore Configuration" web interface. -This format is binary and encrypted. -### .json Format -Configuration data in [JSON](http://www.json.org/)-format. -This format is decrypted, human readable and editable and can also be used for the `--restore-file` parameter. -This file will be created by _decode-config.py_ using the `--backup-file` with `--backup-type json` parameter, this is the default. -### .bin Format -Configuration data in binary format. -This format is binary decryptet, editable (e.g. using a hex editor) and can also be used for `--restore-file` command. -It will be created by _decode-config.py_ using `--backup-file` with `--backup-type bin`. -Note: -The .bin file contains the same information as the original .dmp file from Tasmota "Backup/Restore Configuration" but it is decrpted and 4 byte longer than an original (it is a prefix header at the beginning). .bin file data starting at address 4 contains the same as the **struct SYSCFG** from Tasmota [settings.h](https://github.com/arendst/Tasmota/blob/master/tasmota/settings.h) in decrypted format. - -#### File extensions -You don't need to append exensions for your file name as _decode-config.py_ uses auto extension as default. The extension will be choose based on file contents and `--backup-type` parameter. -If you do not want using auto extensions use the `--no-extension` parameter. - -## Usage -After download don't forget to set the executable flag under linux with `chmod +x decode-config.py` or call the program using `python decode-config.py...`. - -### Basics -At least pass a source where you want to read the configuration data from using `-f ` or `-d `: - -The source can be either -* a Tasmota device hostname or IP using the `-d ` parameter -* a Tasmota `*.dmp` configuration file using `-f ` parameter - -Example: - - decode-config.py -d tasmota-4281 - -will output a human readable configuration in [JSON](http://www.json.org/)-format: - - { - "altitude": 112, - "baudrate": 115200, - "blinkcount": 10, - "blinktime": 10, - ... - "ws_width": [ - 1, - 3, - 5 - ] - } - - -### Save backup file -To save the output as backup file use `--backup-file `, you can use placeholder for Version, Friendlyname and Hostname: - - decode-config.py -d tasmota-4281 --backup-file Config_@f_@v - -If you have setup a WebPassword within Tasmota, use - - decode-config.py -d tasmota-4281 -p --backup-file Config_@f_@v - -will create a file like `Config_Tasmota_6.4.0.json` (the part `Tasmota` and `6.4.0` will choosen related to your device configuration). Because the default backup file format is JSON, you can read and change it with any raw text editor. - -### Restore backup file -Reading back a saved (and possible changed) backup file use the `--restore-file ` parameter. This will read the (changed) configuration data from this file and send it back to the source device or filename. - -To restore the previously save backup file `Config_Tasmota_6.2.1.json` to device `tasmota-4281` use: - - decode-config.py -d tasmota-4281 --restore-file Config_Tasmota_6.2.1.json - -with password set by WebPassword: - - decode-config.py -d tasmota-4281 -p --restore-file Config_Tasmota_6.2.1.json - -### Output to screen -To force screen output use the `--output` parameter. - -Output to screen is default enabled when calling the program with a source parameter (-f or -d) but without any backup or restore parameter. - -#### JSON output -The default output format is [JSON](decode-config.md#-json-format). You can force JSON output using the `--output-format json` parameter. - -Example: - - decode-config.py -d tasmota-4281 -c my.conf -x Wifi --output-format json - - { - ... - "hostname": "%s-%04d", - "ip_address": [ - "0.0.0.0", - "192.168.12.1", - "255.255.255.0", - "192.168.12.1" - ], - "ntp_server": [ - "ntp.localnet.home", - "ntp2.localnet.home", - "192.168.12.1" - ], - "sta_active": 0, - "sta_config": 5, - "sta_pwd": [ - "myWlAnPaszxwo!z", - "myWlAnPaszxwo!z2" - ], - "sta_ssid": [ - "wlan.1", - "my-wlan" - ], - "web_password": "myPaszxwo!z", - "webserver": 2 - ... - } - -Note: JSON output always contains all configuration data like the backup file except you are using `--group` arg. - - -#### Tasmota command output -_decode-config.py_ is able to translate the configuration data to (most all) Tasmota commands. To output your configuration as Tasmota commands use `--output-format cmnd` or `--output-format command`. - -Example: - - decode-config.py -d tasmota-4281 -c my.conf -g Wifi --output-format cmnd - - # Wifi: - AP 0 - Hostname %s-%04d - IPAddress1 0.0.0.0 - IPAddress2 192.168.12.1 - IPAddress3 255.255.255.0 - IPAddress4 192.168.12.1 - NtpServer1 ntp.localnet.home - NtpServer2 ntp2.localnet.home - NtpServer3 192.168.12.1 - Password1 myWlAnPaszxwo!z - Password2 myWlAnPaszxwo!z2 - SSId1 wlan.1 - SSId2 wlan.1 - WebPassword myPaszxwo!z - WebServer 2 - WifiConfig 5 - -Note: A few very specific module commands like MPC230xx, KNX and some Display commands are not supported. These are still available by JSON output. - -### Filter data -The huge number of Tasmota configuration data can be overstrained and confusing, so the most of the configuration data are grouped into categories. - -With _decode-config.py_ the following categories are available: `Display`, `Domoticz`, `Internal`, `KNX`, `Led`, `Logging`, `MCP230xx`, `MQTT`, `Main`, `Management`, `Pow`, `Sensor`, `Serial`, `SetOption`, `RF`, `System`, `Timers`, `Wifi` - -These are similary to the categories on [https://tasmota.github.io/docs/#/Commands](Tasmota Command Wiki). - -To filter outputs to a subset of groups use the `-g` or `--group` arg concatenating the grooup you want, e. g. - - decode-config.py -d tasmota-4281 -c my.conf --output-format cmnd --group Main MQTT Management Wifi - - -### Configuration file -Each argument that start with `--` (eg. `--file`) can also be set in a config file (specified via -c). Config file syntax allows: key=value, flag=true, stuff=[a,b,c] (for details, see syntax at [https://pypi.org/project/ConfigArgParse](https://pypi.org/project/ConfigArgParse/)). - -If an argument is specified in more than one place, then commandline values override config file values which override defaults. This is usefull if you always use the same argument or a basic set of arguments. - -The http authentication credentials `--username` and `--password` is predestinated to store it in a file instead using it on your command line as argument: - -e.g. my.conf: - - [source] - username = admin - password = myPaszxwo!z - -To make a backup file from example above you can now pass the config file instead using the password on command line: - - decode-config.py -d tasmota-4281 -c my.conf --backup-file Config_@f_@v - - - -### More program arguments -For better reading each short written arg (minus sign `-`) has a corresponding long version (two minus signs `--`), eg. `--device` for `-d` or `--file` for `-f` (note: not even all `--` arg has a corresponding `-` one). - -A short list of possible program args is displayed using `-h` or `--help`. - -For advanced help use `-H` or `--full-help`: - - usage: decode-config.py [-f ] [-d ] [-P ] - [-u ] [-p ] [-i ] - [-o ] [-t json|bin|dmp] [-E] [-e] [-F] - [--json-indent ] [--json-compact] - [--json-hide-pw] [--json-show-pw] - [--cmnd-indent ] [--cmnd-groups] - [--cmnd-nogroups] [--cmnd-sort] [--cmnd-unsort] - [-c ] [-S] [-T json|cmnd|command] - [-g {Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rf,Rules,Sensor,Serial,Setoption,Shutter,System,Timer,Wifi} [{Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rf,Rules,Sensor,Serial,Setoption,Shutter,System,Timer,Wifi} ...]] - [--ignore-warnings] [-h] [-H] [-v] [-V] - - Backup/Restore Tasmota configuration data. Args that start with '--' - (eg. -f) can also be set in a config file (specified via -c). Config file - syntax allows: key=value, flag=true, stuff=[a,b,c] (for details, see syntax at - https://goo.gl/R74nmi). If an arg is specified in more than one place, then - commandline values override config file values which override defaults. - - Source: - Read/Write Tasmota configuration from/to - - -f, --file, --tasmota-file - file to retrieve/write Tasmota configuration from/to - (default: None)' - -d, --device, --host - hostname or IP address to retrieve/send Tasmota - configuration from/to (default: None) - -P, --port TCP/IP port number to use for the host connection - (default: 80) - -u, --username - host HTTP access username (default: admin) - -p, --password - host HTTP access password (default: None) - - Backup/Restore: - Backup & restore specification - - -i, --restore-file - file to restore configuration from (default: None). - Replacements: @v=firmware version from config, - @f=device friendly name from config, @h=device - hostname from config, @H=device hostname from device - (-d arg only) - -o, --backup-file - file to backup configuration to (default: None). - Replacements: @v=firmware version from config, - @f=device friendly name from config, @h=device - hostname from config, @H=device hostname from device - (-d arg only) - -t, --backup-type json|bin|dmp - backup filetype (default: 'json') - -E, --extension append filetype extension for -i and -o filename - (default) - -e, --no-extension do not append filetype extension, use -i and -o - filename as passed - -F, --force-restore force restore even configuration is identical - - JSON output: - JSON format specification - - --json-indent - pretty-printed JSON output using indent level - (default: 'None'). -1 disables indent. - --json-compact compact JSON output by eliminate whitespace - --json-hide-pw hide passwords - --json-show-pw, --json-unhide-pw - unhide passwords (default) - - Tasmota command output: - Tasmota command output format specification - - --cmnd-indent - Tasmota command grouping indent level (default: '2'). - 0 disables indent - --cmnd-groups group Tasmota commands (default) - --cmnd-nogroups leave Tasmota commands ungrouped - --cmnd-sort sort Tasmota commands (default) - --cmnd-unsort leave Tasmota commands unsorted - - Common: - Optional arguments - - -c, --config - program config file - can be used to set default - command args (default: None) - -S, --output display output regardsless of backup/restore usage - (default do not output on backup or restore usage) - -T, --output-format json|cmnd|command - display output format (default: 'json') - -g, --group {Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rf,Rules,Sensor,Serial,Setoption,Shutter,System,Timer,Wifi} - limit data processing to command groups (default no - filter) - --ignore-warnings do not exit on warnings. Not recommended, used by your - own responsibility! - - Info: - Extra information - - -h, --help show usage help message and exit - -H, --full-help show full help message and exit - -v, --verbose produce more output about what the program does - -V, --version show program's version number and exit - - Either argument -d or -f must be given. - -### Program parameter notes - -_decode-config.py_ - - -### Examples -The most of the examples are for linux command line. Under Windows call the program using `python decode-config.py ...`. - -#### Config file -Note: The example contains .ini style sections `[...]`. Sections are always treated as comment and serves as clarity only. -For further details of config file syntax see [https://pypi.org/project/ConfigArgParse](https://pypi.org/project/ConfigArgParse/). - -*my.conf* - - [Source] - username = admin - password = myPaszxwo!z - - [JSON] - json-indent 2 - -#### Using Tasmota binary configuration files - -1. Restore a Tasmota configuration file - - `decode-config.py -c my.conf -d tasmota --restore-file Config_Tasmota_6.2.1.dmp` - -2. Backup device using Tasmota configuration compatible format - - a) use file extension to choice the file format - - `decode-config.py -c my.conf -d tasmota --backup-file Config_@f_@v.dmp` - - b) use args to choice the file format - - `decode-config.py -c my.conf -d tasmota --backup-type dmp --backup-file Config_@f_@v` - -#### Use batch processing - - for device in tasmota1 tasmota2 tasmota3; do ./decode-config.py -c my.conf -d $device -o Config_@f_@v - -or under windows - - for device in (tasmota1 tasmota2 tasmota3) do python decode-config.py -c my.conf -d %device -o Config_@f_@v - -will produce JSON configuration files for host tasmota1, tasmota2 and tasmota3 using friendly name and Tasmota firmware version for backup filenames. - -## Notes -Some general notes: -* Filename replacement macros **@h** and **@H**: - * **@h** -The **@h** replacement macro uses the hostname configured with the Tasomta Wifi `Hostname ` command (defaults to `%s-%04d`). It will not use the network hostname of your device because this is not available when working with files only (e.g. `--file ` as source). -To prevent having a useless % in your filename, **@h** will not replaced by configuration data hostname if this contains '%' characters. - * **@H** -If you want to use the network hostname within your filename, use the **@H** replacement macro instead - but be aware this will only replaced if you are using a network device as source (`-d`, `--device`, `--host`); it will not work when using a file as source (`-f`, `--file`) +## decode-config has moved to [https://github.com/tasmota/decode-config](https://github.com/tasmota/decode-config) diff --git a/tools/decode-config.py b/tools/decode-config.py deleted file mode 100755 index f15c696ae..000000000 --- a/tools/decode-config.py +++ /dev/null @@ -1,3322 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -from __future__ import print_function -from past.builtins import long -VER = '2.4.0039' - -""" - decode-config.py - Backup/Restore Tasmota configuration data - - Copyright (C) 2019 Norbert Richter - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - -Requirements: - - Python 2.x: - pip install json requests urllib2 configargparse - - -Instructions: - Execute command with option -d to retrieve config data from a host - or use -f to read a configuration file saved using Tasmota Web-UI - - For further information read 'decode-config.md' - - For help execute command with argument -h (or -H for advanced help) - - -Usage: decode-config.py [-f ] [-d ] [-P ] - [-u ] [-p ] [-i ] - [-o ] [-t json|bin|dmp] [-E] [-e] [-F] - [--json-indent ] [--json-compact] - [--json-hide-pw] [--json-show-pw] - [--cmnd-indent ] [--cmnd-groups] - [--cmnd-nogroups] [--cmnd-sort] [--cmnd-unsort] - [-c ] [-S] [-T json|cmnd|command] - [-g {Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rules,Sensor,Serial,Setoption,Shutter,Rf,System,Timer,Wifi} [{Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rules,Sensor,Serial,Setoption,Shutter,Rf,System,Timer,Wifi} ...]] - [--ignore-warnings] [-h] [-H] [-v] [-V] - - Backup/Restore Tasmota configuration data. Args that start with '--' - (eg. -f) can also be set in a config file (specified via -c). Config file - syntax allows: key=value, flag=true, stuff=[a,b,c] (for details, see syntax at - https://goo.gl/R74nmi). If an arg is specified in more than one place, then - commandline values override config file values which override defaults. - - Source: - Read/Write Tasmota configuration from/to - - -f, --file, --tasmota-file - file to retrieve/write Tasmota configuration from/to - (default: None)' - -d, --device, --host - hostname or IP address to retrieve/send Tasmota - configuration from/to (default: None) - -P, --port TCP/IP port number to use for the host connection - (default: 80) - -u, --username - host HTTP access username (default: admin) - -p, --password - host HTTP access password (default: None) - - Backup/Restore: - Backup & restore specification - - -i, --restore-file - file to restore configuration from (default: None). - Replacements: @v=firmware version from config, - @f=device friendly name from config, @h=device - hostname from config, @H=device hostname from device - (-d arg only) - -o, --backup-file - file to backup configuration to (default: None). - Replacements: @v=firmware version from config, - @f=device friendly name from config, @h=device - hostname from config, @H=device hostname from device - (-d arg only) - -t, --backup-type json|bin|dmp - backup filetype (default: 'json') - -E, --extension append filetype extension for -i and -o filename - (default) - -e, --no-extension do not append filetype extension, use -i and -o - filename as passed - -F, --force-restore force restore even configuration is identical - - JSON output: - JSON format specification - - --json-indent - pretty-printed JSON output using indent level - (default: 'None'). -1 disables indent. - --json-compact compact JSON output by eliminate whitespace - --json-hide-pw hide passwords - --json-show-pw, --json-unhide-pw - unhide passwords (default) - - Tasmota command output: - Tasmota command output format specification - - --cmnd-indent - Tasmota command grouping indent level (default: '2'). - 0 disables indent - --cmnd-groups group Tasmota commands (default) - --cmnd-nogroups leave Tasmota commands ungrouped - --cmnd-sort sort Tasmota commands (default) - --cmnd-unsort leave Tasmota commands unsorted - - Common: - Optional arguments - - -c, --config - program config file - can be used to set default - command args (default: None) - -S, --output display output regardsless of backup/restore usage - (default do not output on backup or restore usage) - -T, --output-format json|cmnd|command - display output format (default: 'json') - -g, --group {Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rules,Sensor,Serial,Setoption,Shutter,Rf,System,Timer,Wifi} - limit data processing to command groups (default no - filter) - --ignore-warnings do not exit on warnings. Not recommended, used by your - own responsibility! - - Info: - Extra information - - -h, --help show usage help message and exit - -H, --full-help show full help message and exit - -v, --verbose produce more output about what the program does - -V, --version show program's version number and exit - - Either argument -d or -f must be given. - - -Returns: - 0: successful - 1: restore skipped - 2: program argument error - 3: file not found - 4: data size mismatch - 5: data CRC error - 6: unsupported configuration version - 7: configuration file read error - 8: JSON file decoding error - 9: Restore file data error - 10: Device data download error - 11: Device data upload error - 20: python module missing - 21: Internal error - >21: python library exit code - 4xx, 5xx: HTTP errors - -""" - -class ExitCode: - OK = 0 - RESTORE_SKIPPED = 1 - ARGUMENT_ERROR = 2 - FILE_NOT_FOUND = 3 - DATA_SIZE_MISMATCH = 4 - DATA_CRC_ERROR = 5 - UNSUPPORTED_VERSION = 6 - FILE_READ_ERROR = 7 - JSON_READ_ERROR = 8 - RESTORE_DATA_ERROR = 9 - DOWNLOAD_CONFIG_ERROR = 10 - UPLOAD_CONFIG_ERROR = 11 - MODULE_NOT_FOUND = 20 - INTERNAL_ERROR = 21 - -# ====================================================================== -# imports -# ====================================================================== -import os.path -import io -import sys, platform -def ModuleImportError(module): - er = str(module) - print('{}, try "pip install {}"'.format(er,er.split(' ')[len(er.split(' '))-1]), file=sys.stderr) - sys.exit(ExitCode.MODULE_NOT_FOUND) -try: - from datetime import datetime - import time - import copy - import struct - import socket - import re - import math - import inspect - import json - import configargparse - import requests - if sys.version_info.major==2: - import urllib2 - else: - import urllib -except ImportError as e: - ModuleImportError(e) - -# ====================================================================== -# globals -# ====================================================================== -PROG='{} v{} by Norbert Richter '.format(os.path.basename(sys.argv[0]),VER) - -CONFIG_FILE_XOR = 0x5A -BINARYFILE_MAGIC = 0x63576223 -STR_ENCODING = 'utf8' -HIDDEN_PASSWORD = '********' -INTERNAL = 'Internal' - -DEFAULTS = { - 'source': - { - 'device': None, - 'port': 80, - 'username': 'admin', - 'password': None, - 'tasmotafile': None, - }, - 'backup': - { - 'restorefile': None, - 'backupfile': None, - 'backupfileformat': 'json', - 'extension': True, - 'forcerestore': False, - }, - 'jsonformat': - { - 'jsonindent': None, - 'jsoncompact': False, - 'jsonsort': True, - 'jsonhidepw': False, - }, - 'cmndformat': - { - 'cmndindent': 2, - 'cmndgroup': True, - 'cmndsort': True, - }, - 'common': - { - 'output': False, - 'outputformat': 'json', - 'configfile': None, - 'ignorewarning':False, - 'filter': None, - }, -} -args = {} -exitcode = 0 - - -# ====================================================================== -# Settings mapping -# ====================================================================== -""" -Settings dictionary describes the config file fields definition: - - = { : } - - : "string" - a python valid dictionary key (string) - - : ( , , [,] ) - a tuple containing the following items: - - : | - data type & format definition - : - defines the use of data at - format is defined in 'struct module format string' - see - https://docs.python.org/3.8/library/struct.html#format-strings - : - A dictionary describes a (sub)setting dictonary - and can recursively define another - - : | (, , ) - address definition - : - The address (starting from 0) within binary config data. - : - number of bits used (positive integer) - : - bit shift : - >= 0: shift the result right - < 0: shift the result left - - : | (, [,cmd]) - data definition - : None | | [] | [ ,...] - None: - Single value, not an array - : - [] - Defines a one-dimensional array of size - [ ,...] - Defines a one- or multi-dimensional array - : - value validation function - : (, ) - Tasmota command definition - : - command group string - : | (,...) - convert data into Tasmota command function - - : | (, ) - read/write converter - : None | - Will be used in Bin2Mapping to convert values read - from the binary data object into mapping dictionary - None - None indicates not read conversion - - to convert value from binary object to JSON. - : None | False | - Will be used in Mapping2Bin to convert values read - from mapping dictionary before write to binary - data object - None - None indicates not write conversion - False - False indicates the value is readonly and will - not be written into the binary object. - - to convert value from JSON back to binary object - - Common definitions - - : | | None - function to be called or string to evaluate: - : - A function name will be called with one or two parameter: - The value to be processed - (optional) the current array index (1,n) - - A string will be evaluate as is. The following - placeholder can be used to replace it by runtime values: - '$': - will be replaced by the mapping name value - '#': - will be replace by array index (if any) - '@': - can be used as reference to other mapping values - see definition below for examples - - : 'string' | "string" - characters enclosed in ' or " - - : integer - numbers in the range -2147483648 through 2147483647 - : unsigned integer - numbers in the range 0 through 4294967295 - -""" -# ---------------------------------------------------------------------- -# Settings helper -# ---------------------------------------------------------------------- -def passwordread(value): - return HIDDEN_PASSWORD if args.jsonhidepw else value -def passwordwrite(value): - return None if value == HIDDEN_PASSWORD else value -def bitsRead(x, n=0, c=1): - """ - Reads bit(s) of a number - - @param x: - the number from which to read - - @param n: - which bit position to read - - @param c: - how many bits to read (1 if omitted) - - @return: - the bit value(s) - """ - if isinstance(x,str): - x = int(x, 0) - if isinstance(x,str): - n = int(n, 0) - - if n >= 0: - x >>= n - else: - x <<= abs(n) - if c>0: - x &= (1<, , [,] - 'cfg_holder': ('0 and bitsRead($,0,11)>(12*60) else "",time=time.strftime("%H:%M",time.gmtime((bitsRead($,0,11) if bitsRead($,29,2)==0 else bitsRead($,0,11) if bitsRead($,0,11)<=(12*60) else bitsRead($,0,11)-(12*60))*60)),window=bitsRead($,11,4),repeat=bitsRead($,15),days="{:07b}".format(bitsRead($,16,7))[::-1],device=bitsRead($,23,4)+1,power=bitsRead($,27,2) )')), ('"0x{:08x}".format($)', False) ), - 'time': (' 0 and type_ is not None else '', - sstatus=status if status is not None and status > 0 else '', - scolon=': ' if type_ is not None or line is not None else '', - smgs=msg, - slineno=' (@{:04d})'.format(line) if line is not None else '') - , file=sys.stderr) - - -def exit(status=0, msg="end", type_=LogType.ERROR, src=None, doexit=True, line=None): - """ - Called when the program should be exit - - @param status: - the exit status program returns to callert - @param msg: - the msg logged before exit - @param type_: - msg type: 'INFO', 'WARNING' or 'ERROR' - @param doexit: - True to exit program, otherwise return - """ - - if src is not None: - msg = '{} ({})'.format(src, msg) - message(msg, type_=type_ if status!=ExitCode.OK else LogType.INFO, status=status, line=line) - exitcode = status - if doexit: - sys.exit(exitcode) - - -def debug(args): - """ - Get debug level - - @param args: - configargparse.parse_args() result - - @return: - debug level - """ - return 0 if args.debug is None else args.debug - - -def instance(type_): - """ - Creates Python2/3 compatible isinstance test type(s) - - @param args: - Python3 instance type - - @return: - Python2/3 compatible isinstance type(s) - """ - newtype = type_ - if sys.version_info.major==2: - if type_==str: - newtype = (str,unicode) - elif isinstance(type_, tuple) and str in type_: - newtype = newtype + (unicode,) - return newtype - - -def ShortHelp(doexit=True): - """ - Show short help (usage) only - ued by own -h handling - - @param doexit: - sys.exit with OK if True - """ - print(parser.description) - print - parser.print_usage() - print - print("For advanced help use '{prog} -H' or '{prog} --full-help'".format(prog=os.path.basename(sys.argv[0]))) - if doexit: - sys.exit(ExitCode.OK) - - -class CustomHelpFormatter(configargparse.HelpFormatter): - """ - Class for customizing the help output - """ - - def _format_action_invocation(self, action): - """ - Reformat multiple metavar output - -d , --device , --host - to single output - -d, --device, --host - """ - - orgstr = configargparse.HelpFormatter._format_action_invocation(self, action) - if orgstr and orgstr[0] != '-': # only optional arguments - return orgstr - res = getattr(action, '_formatted_action_invocation', None) - if res: - return res - - options = orgstr.split(', ') - if len(options) <= 1: - action._formatted_action_invocation = orgstr - return orgstr - - return_list = [] - for option in options: - meta = "" - arg = option.split(' ') - if len(arg) > 1: - meta = arg[1] - return_list.append(arg[0]) - if len(meta) > 0 and len(return_list) > 0: - return_list[len(return_list)-1] += " "+meta - action._formatted_action_invocation = ', '.join(return_list) - return action._formatted_action_invocation - - -# ====================================================================== -# Tasmota config data handling -# ====================================================================== -def GetTemplateSizes(): - """ - Get all possible template sizes as list - - @return: - template sizes as list [] - """ - sizes = [] - for cfg in Settings: - sizes.append(cfg[1]) - # return unique sizes only (remove duplicates) - return list(set(sizes)) - - -def GetTemplateSetting(decode_cfg): - """ - Search for version, size and settings to be used depending on given binary config data - - @param decode_cfg: - binary config data (decrypted) - - @return: - version, size, settings to use; None if version is invalid - """ - version = 0x0 - size = setting = None - version = GetField(decode_cfg, 'version', Setting_6_2_1['version'], raw=True) - # search setting definition top-down - for cfg in sorted(Settings, key=lambda s: s[0], reverse=True): - if version >= cfg[0]: - size = cfg[1] - setting = cfg[2] - break - - return version, size, setting - - -def GetGroupList(setting): - """ - Get all avilable group definition from setting - - @return: - configargparse.parse_args() result - """ - groups = set() - - for name in setting: - dev = setting[name] - format_, group = GetFieldDef(dev, fields="format_, group") - if group is not None and len(group) > 0: - groups.add(group.title()) - if isinstance(format_, dict): - subgroups = GetGroupList(format_) - if subgroups is not None and len(subgroups) > 0: - for group in subgroups: - groups.add(group.title()) - - groups=list(groups) - groups.sort() - return groups - - -class FileType: - FILE_NOT_FOUND = None - DMP = 'dmp' - JSON = 'json' - BIN = 'bin' - UNKNOWN = 'unknown' - INCOMPLETE_JSON = 'incomplete json' - INVALID_JSON = 'invalid json' - INVALID_BIN = 'invalid bin' - -def GetFileType(filename): - """ - Get the FileType class member of a given filename - - @param filename: - filename of the file to analyse - - @return: - FileType class member - """ - filetype = FileType.UNKNOWN - - # try filename - try: - isfile = os.path.isfile(filename) - try: - with open(filename, "r") as f: - try: - # try reading as json - inputjson = json.load(f) - if 'header' in inputjson: - filetype = FileType.JSON - else: - filetype = FileType.INCOMPLETE_JSON - except ValueError: - filetype = FileType.INVALID_JSON - # not a valid json, get filesize and compare it with all possible sizes - try: - size = os.path.getsize(filename) - except: - filetype = FileType.UNKNOWN - sizes = GetTemplateSizes() - - # size is one of a dmp file size - if size in sizes: - filetype = FileType.DMP - elif (size - ((len(hex(BINARYFILE_MAGIC))-2)/2)) in sizes: - # check if the binary file has the magic header - with open(filename, "rb") as inputfile: - inputbin = inputfile.read() - if struct.unpack_from('>24) & 0xff) - minor = ((version>>16) & 0xff) - release = ((version>> 8) & 0xff) - subrelease = (version & 0xff) - if major >= 6: - if subrelease > 0: - subreleasestr = str(subrelease) - else: - subreleasestr = '' - else: - if subrelease > 0: - subreleasestr = str(chr(subrelease+ord('a')-1)) - else: - subreleasestr = '' - return "{:d}.{:d}.{:d}{}{}".format( major, minor, release, '.' if (major >= 6 and subreleasestr != '') else '', subreleasestr) - - -def MakeFilename(filename, filetype, configmapping): - """ - Replace variables within a filename - - @param filename: - original filename possible containing replacements: - @v: - Tasmota version from config data - @f: - friendlyname from config data - @h: - hostname from config data - @H: - hostname from device (-d arg only) - @param filetype: - FileType.x object - creates extension if not None - @param configmapping: - binary config data (decrypted) - - @return: - New filename with replacements - """ - config_version = config_friendlyname = config_hostname = device_hostname = '' - - if 'version' in configmapping: - config_version = GetVersionStr( int(str(configmapping['version']), 0) ) - if 'friendlyname' in configmapping: - config_friendlyname = re.sub('[^0-9a-zA-Z]','_', configmapping['friendlyname'][0]) - if 'hostname' in configmapping: - if configmapping['hostname'].find('%') < 0: - config_hostname = re.sub('[^0-9a-zA-Z]','_', configmapping['hostname']) - if filename.find('@H') >= 0 and args.device is not None: - device_hostname = GetTasmotaHostname(args.device, args.port, username=args.username, password=args.password) - if device_hostname is None: - device_hostname = '' - - dirname = basename = ext = '' - - # split file parts - dirname = os.path.normpath(os.path.dirname(filename)) - basename = os.path.basename(filename) - name, ext = os.path.splitext(basename) - - # make a valid filename - try: - name = name.decode('unicode-escape').translate(dict((ord(char), None) for char in '\/*?:"<>|')) - except: - pass - name = str(name.replace(' ','_')) - - # append extension based on filetype if not given - if len(ext) and ext[0]=='.': - ext = ext[1:] - if filetype is not None and args.extension and (len(ext)<2 or all(c.isdigit() for c in ext)): - ext = filetype.lower() - - # join filename + extension - if len(ext): - name_ext = name+'.'+ext - else: - name_ext = name - - # join path and filename - try: - filename = os.path.join(dirname, name_ext) - except: - pass - - filename = filename.replace('@v', config_version) - filename = filename.replace('@f', config_friendlyname ) - filename = filename.replace('@h', config_hostname ) - filename = filename.replace('@H', device_hostname ) - - return filename - - -def MakeUrl(host, port=80, location=''): - """ - Create a Tasmota host url - - @param host: - hostname or IP of Tasmota host - @param port: - port number to use for http connection - @param location: - http url location - - @return: - Tasmota http url - """ - return "http://{shost}{sdelimiter}{sport}/{slocation}".format(\ - shost=host, - sdelimiter=':' if port != 80 else '', - sport=port if port != 80 else '', - slocation=location ) - - -def LoadTasmotaConfig(filename): - """ - Load config from Tasmota file - - @param filename: - filename to load - - @return: - binary config data (encrypted) or None on error - """ - - encode_cfg = None - - # read config from a file - if not os.path.isfile(filename): # check file exists - exit(ExitCode.FILE_NOT_FOUND, "File '{}' not found".format(filename),line=inspect.getlineno(inspect.currentframe())) - try: - with open(filename, "rb") as tasmotafile: - encode_cfg = tasmotafile.read() - except Exception as e: - exit(e.args[0], "'{}' {}".format(filename, e[1]),line=inspect.getlineno(inspect.currentframe())) - - return encode_cfg - - -def TasmotaGet(cmnd, host, port, username=DEFAULTS['source']['username'], password=None, contenttype = None): - """ - Tasmota http request - - @param host: - hostname or IP of Tasmota device - @param port: - http port of Tasmota device - @param username: - optional username for Tasmota web login - @param password - optional password for Tasmota web login - - @return: - binary config data (encrypted) or None on error - """ - - # read config direct from device via http - url = MakeUrl(host, port, cmnd) - auth = None - if username is not None and password is not None: - auth = (username, password) - res = requests.get(url, auth=auth) - - if not res.ok: - exit(res.status_code, "Error on http GET request for {} - {}".format(url,res.reason), line=inspect.getlineno(inspect.currentframe())) - - if contenttype is not None and res.headers['Content-Type']!=contenttype: - exit(ExitCode.DOWNLOAD_CONFIG_ERROR, "Device did not response properly, may be Tasmota webserver admin mode is disabled (WebServer 2)",line=inspect.getlineno(inspect.currentframe())) - - return res.status_code, res.content - - -def GetTasmotaHostname(host, port, username=DEFAULTS['source']['username'], password=None): - """ - Get Tasmota hostname from device - - @param host: - hostname or IP of Tasmota device - @param port: - http port of Tasmota device - @param username: - optional username for Tasmota web login - @param password - optional password for Tasmota web login - - @return: - Tasmota real hostname or None on error - """ - hostname = None - - loginstr = "" - if password is not None: - loginstr = "user={}&password={}&".format(urllib2.quote(username), urllib2.quote(password)) - # get hostname - responsecode, body = TasmotaGet("cm?{}cmnd=status%205".format(loginstr), host, port, username=username, password=password) - if body is not None: - jsonbody = json.loads(body) - if "StatusNET" in jsonbody and "Hostname" in jsonbody["StatusNET"]: - hostname = jsonbody["StatusNET"]["Hostname"] - if args.verbose: - message("Hostname for '{}' retrieved: '{}'".format(host, hostname), type_=LogType.INFO) - - return hostname - - -def PullTasmotaConfig(host, port, username=DEFAULTS['source']['username'], password=None): - """ - Pull config from Tasmota device - - @param host: - hostname or IP of Tasmota device - @param port: - http port of Tasmota device - @param username: - optional username for Tasmota web login - @param password - optional password for Tasmota web login - - @return: - binary config data (encrypted) or None on error - """ - responsecode, body = TasmotaGet('dl', host, port, username, password, contenttype='application/octet-stream') - - return body - - -def PushTasmotaConfig(encode_cfg, host, port, username=DEFAULTS['source']['username'], password=None): - """ - Upload binary data to a Tasmota host using http - - @param encode_cfg: - encrypted binary data or filename containing Tasmota encrypted binary config - @param host: - hostname or IP of Tasmota device - @param port: - http port of Tasmota device - @param username: - optional username for Tasmota web login - @param password - optional password for Tasmota web login - - @return - errorcode, errorstring - errorcode=0 if success, otherwise http response or exception code - """ - if isinstance(encode_cfg, (bytes,bytearray)): - encode_cfg = str(encode_cfg) - - # get restore config page first to set internal Tasmota vars - responsecode, body = TasmotaGet('rs?', host, port, username, password, contenttype='text/html') - if body is None: - return responsecode, "ERROR" - - # ~ # post data - url = MakeUrl(host, port, "u2") - auth = None - if username is not None and password is not None: - auth = (username, password) - files = {'u2':('{sprog}_v{sver}.dmp'.format(sprog=os.path.basename(sys.argv[0]), sver=VER), encode_cfg)} - res = requests.post(url, auth=auth, files=files) - - if not res.ok: - exit(res.status_code, "Error on http POST request for {} - {}".format(url,res.reason), line=inspect.getlineno(inspect.currentframe())) - - if res.headers['Content-Type']!='text/html': - exit(ExitCode.DOWNLOAD_CONFIG_ERROR, "Device did not response properly, may be Tasmota webserver admin mode is disabled (WebServer 2)",line=inspect.getlineno(inspect.currentframe())) - - body = res.content - - findUpload = body.find("Upload") - if findUpload < 0: - return ExitCode.UPLOAD_CONFIG_ERROR, "Device did not response properly with upload result page" - - body = body[findUpload:] - findSuccessful = body.find("Successful") - if findSuccessful < 0: - errmatch = re.search("(\S*)

(.*)
", body) - reason = "Unknown error" - if errmatch and len(errmatch.groups()) > 1: - reason = errmatch.group(2) - return ExitCode.UPLOAD_CONFIG_ERROR, reason - - return 0, 'OK' - - -def DecryptEncrypt(obj): - """ - Decrpt/Encrypt binary config data - - @param obj: - binary config data - - @return: - decrypted configuration (if obj contains encrypted data) - """ - if isinstance(obj, (bytes,bytearray)): - obj = str(obj) - dobj = obj[0:2] - for i in range(2, len(obj)): - dobj += chr( (ord(obj[i]) ^ (CONFIG_FILE_XOR +i)) & 0xff ) - return dobj - - -def GetSettingsCrc(dobj): - """ - Return binary config data calclulated crc - - @param dobj: - decrypted binary config data - - @return: - 2 byte unsigned integer crc value - - """ - if isinstance(dobj, (bytes,bytearray)): - dobj = str(dobj) - version, size, setting = GetTemplateSetting(dobj) - if version < 0x06060007 or version > 0x0606000A: - size = 3584 - crc = 0 - for i in range(0, size): - if not i in [14,15]: # Skip crc - byte = ord(dobj[i]) - crc += byte * (i+1) - - return crc & 0xffff - - -def GetSettingsCrc32(dobj): - """ - Return binary config data calclulated crc32 - - @param dobj: - decrypted binary config data - - @return: - 4 byte unsigned integer crc value - - """ - if isinstance(dobj, (bytes,bytearray)): - dobj = str(dobj) - crc = 0 - for i in range(0, len(dobj)-4): - crc ^= ord(dobj[i]) - for j in range(0, 8): - crc = (crc >> 1) ^ (-int(crc & 1) & 0xEDB88320); - - return ~crc & 0xffffffff - - -def GetFieldDef(fielddef, fields="format_, addrdef, baseaddr, bits, bitshift, datadef, arraydef, validate, cmd, group, tasmotacmnd, converter, readconverter, writeconverter"): - - """ - Get field definition items - - @param fielddef: - field format - see "Settings dictionary" above - @param fields: - comma separated string list of values to be returned - possible values see fields default - - @return: - set of values defined in - """ - format_ = addrdef = baseaddr = datadef = arraydef = validate = cmd = group = tasmotacmnd = converter = readconverter = writeconverter = None - bits = bitshift = 0 - - # calling with nothing is wrong - if fielddef is None: - print(' is None', file=sys.stderr) - raise SyntaxError(' error') - - # get top level items - if len(fielddef) == 3: - # converter not present - format_, addrdef, datadef = fielddef - elif len(fielddef) == 4: - # converter present - format_, addrdef, datadef, converter = fielddef - else: - print('wrong {} length ({}) in setting'.format(fielddef, len(fielddef)), file=sys.stderr) - raise SyntaxError(' error') - - # ignore calls with 'root' setting - if isinstance(format_, instance(dict)) and baseaddr is None and datadef is None: - return eval(fields) - - if not isinstance(format_, instance((str,dict))): - print('wrong {} type {} in {}'.format(format_, type(format_), fielddef), file=sys.stderr) - raise SyntaxError(' error') - - # extract addrdef items - baseaddr = addrdef - if isinstance(baseaddr, instance((list,tuple))): - if len(baseaddr) == 3: - # baseaddr bit definition - baseaddr, bits, bitshift = baseaddr - if not isinstance(bits, instance(int)): - print(' must be defined as integer in {}'.format(bits, fielddef), file=sys.stderr) - raise SyntaxError(' error') - if not isinstance(bitshift, instance(int)): - print(' must be defined as integer in {}'.format(bitshift, fielddef), file=sys.stderr) - raise SyntaxError(' error') - else: - print('wrong {} length ({}) in {}'.format(addrdef, len(addrdef), fielddef), file=sys.stderr) - raise SyntaxError(' error') - if not isinstance(baseaddr, instance(int)): - print(' must be defined as integer in {}'.format(baseaddr, fielddef), file=sys.stderr) - raise SyntaxError(' error') - - # extract datadef items - arraydef = datadef - if isinstance(datadef, instance((tuple))): - if len(datadef) == 2: - # datadef has a validator - arraydef, validate = datadef - elif len(datadef) == 3: - # datadef has a validator and cmd set - arraydef, validate, cmd = datadef - # cmd must be a tuple with 2 objects - if isinstance(cmd, instance((tuple))) and len(cmd) == 2: - group, tasmotacmnd = cmd - if group is not None and not isinstance(group, instance(str)): - print('wrong {} in {}'.format(group, fielddef), file=sys.stderr) - raise SyntaxError(' error') - if tasmotacmnd is isinstance(tasmotacmnd, instance(tuple)): - tasmotacmnds = tasmotacmnd - for tasmotacmnd in tasmotacmnds: - if tasmotacmnd is not None and not callable(tasmotacmnd) and not isinstance(tasmotacmnd, instance(str)): - print('wrong {} in {}'.format(tasmotacmnd, fielddef), file=sys.stderr) - raise SyntaxError(' error') - else: - if tasmotacmnd is not None and not callable(tasmotacmnd) and not isinstance(tasmotacmnd, instance(str)): - print('wrong {} in {}'.format(tasmotacmnd, fielddef), file=sys.stderr) - raise SyntaxError(' error') - else: - print('wrong {} length ({}) in {}'.format(cmd, len(cmd), fielddef), file=sys.stderr) - raise SyntaxError(' error') - else: - print('wrong {} length ({}) in {}'.format(datadef, len(datadef), fielddef), file=sys.stderr) - raise SyntaxError(' error') - - if validate is not None and (not isinstance(validate, instance(str)) and not callable(validate)): - print('wrong {} type {} in {}'.format(validate, type(validate), fielddef), file=sys.stderr) - raise SyntaxError(' error') - - # convert single int into one-dimensional list - if isinstance(arraydef, instance(int)): - arraydef = [arraydef] - - if arraydef is not None and not isinstance(arraydef, instance((list))): - print('wrong {} type {} in {}'.format(arraydef, type(arraydef), fielddef), file=sys.stderr) - raise SyntaxError(' error') - - # get read/write converter items - readconverter = converter - if isinstance(converter, instance((tuple))): - if len(converter) == 2: - # converter has read/write converter - readconverter, writeconverter = converter - if readconverter is not None and not isinstance(readconverter, instance(str)) and not callable(readconverter): - print('wrong {} type {} in {}'.format(readconverter, type(readconverter), fielddef), file=sys.stderr) - raise SyntaxError(' error') - if writeconverter is not None and (not isinstance(writeconverter, instance((bool,str))) and not callable(writeconverter)): - print('wrong {} type {} in {}'.format(writeconverter, type(writeconverter), fielddef), file=sys.stderr) - raise SyntaxError(' error') - else: - print('wrong {} length ({}) in {}'.format(converter, len(converter), fielddef), file=sys.stderr) - raise SyntaxError(' error') - - - return eval(fields) - - -def ReadWriteConverter(value, fielddef, read=True, raw=False): - """ - Convert field value based on field desc - - @param value: - original value - @param fielddef - field definition - see "Settings dictionary" above - @param read - use read conversion if True, otherwise use write conversion - @param raw - return raw values (True) or converted values (False) - - @return: - (un)converted value - """ - converter, readconverter, writeconverter = GetFieldDef(fielddef, fields='converter, readconverter, writeconverter') - - # call password functions even if raw value should be processed - if read and callable(readconverter) and readconverter == passwordread: - raw = False - if not read and callable(writeconverter) and writeconverter == passwordwrite: - raw = False - - if not raw and converter is not None: - conv = readconverter if read else writeconverter - try: - if isinstance(conv, instance(str)): # evaluate strings - return eval(conv.replace('$','value')) - elif callable(conv): # use as format function - return conv(value) - except Exception as e: - exit(e.args[0], e.args[1], type_=LogType.WARNING, line=inspect.getlineno(inspect.currentframe())) - - return value - - -def CmndConverter(valuemapping, value, idx, fielddef): - """ - Convert field value into Tasmota command if available - - @param valuemapping: - data mapping - @param value: - original value - @param fielddef - field definition - see "Settings dictionary" above - - @return: - converted value, list of values or None if unable to convert - """ - converter, readconverter, writeconverter, group, tasmotacmnd = GetFieldDef(fielddef, fields='converter, readconverter, writeconverter, group, tasmotacmnd') - - result = None - - if (callable(readconverter) and readconverter == passwordread) or (callable(writeconverter) and writeconverter == passwordwrite): - if value == HIDDEN_PASSWORD: - return None - else: - result = value - - if tasmotacmnd is not None and (callable(tasmotacmnd) or len(tasmotacmnd) > 0): - if idx is not None: - idx += 1 - if isinstance(tasmotacmnd, instance(str)): # evaluate strings - if idx is not None: - evalstr = tasmotacmnd.replace('$','value').replace('#','idx').replace('@','valuemapping') - else: - evalstr = tasmotacmnd.replace('$','value').replace('@','valuemapping') - result = eval(evalstr) - - elif callable(tasmotacmnd): # use as format function - if idx is not None: - result = tasmotacmnd(value, idx) - else: - result = tasmotacmnd(value) - - return result - - -def ValidateValue(value, fielddef): - """ - Validate a value if validator is defined in fielddef - - @param value: - original value - @param fielddef - field definition - see "Settings dictionary" above - - @return: - True if value is valid, False if invalid - """ - validate = GetFieldDef(fielddef, fields='validate') - - if value == 0: - # can not complete all validate condition - # some Tasmota values are not allowed to be 0 on input - # even though these values are set to 0 on Tasmota initial. - # so we can't validate 0 values - return True; - - valid = True - try: - if isinstance(validate, instance(str)): # evaluate strings - valid = eval(validate.replace('$','value')) - elif callable(validate): # use as format function - valid = validate(value) - except: - valid = False - - return valid - - -def GetFormatCount(format_): - """ - Get format prefix count - - @param format_: - format specifier - - @return: - prefix count or 1 if not specified - """ - - if isinstance(format_, instance(str)): - match = re.search("\s*(\d+)", format_) - if match: - return int(match.group(0)) - - return 1 - - -def GetFormatType(format_): - """ - Get format type and bitsize without prefix - - @param format_: - format specifier - - @return: - (format_, 0) or (format without prefix, bitsize) - """ - - formattype = format_ - bitsize = 0 - if isinstance(format_, instance(str)): - match = re.search("\s*(\D+)", format_) - if match: - formattype = match.group(0) - bitsize = struct.calcsize(formattype) * 8 - return formattype, bitsize - - -def GetFieldMinMax(fielddef): - """ - Get minimum, maximum of field based on field format definition - - @param fielddef: - field format - see "Settings dictionary" above - - @return: - min, max - """ - minmax = {'c': (0, 0xff), - '?': (0, 1), - 'b': (~0x7f, 0x7f), - 'B': (0, 0xff), - 'h': (~0x7fff, 0x7fff), - 'H': (0, 0xffff), - 'i': (~0x7fffffff, 0x7fffffff), - 'I': (0, 0xffffffff), - 'l': (~0x7fffffff, 0x7fffffff), - 'L': (0, 0xffffffff), - 'q': (~0x7fffffffffffffff, 0x7fffffffffffffff), - 'Q': (0, 0x7fffffffffffffff), - 'f': (sys.float_info.min, sys.float_info.max), - 'd': (sys.float_info.min, sys.float_info.max), - } - format_ = GetFieldDef(fielddef, fields='format_') - min_ = 0 - max_ = 0 - - if format_[-1:] in minmax: - min_, max_ = minmax[format_[-1:]] - max_ *= GetFormatCount(format_) - elif format_[-1:] in ['s','p']: - # s and p may have a prefix as length - max_ = GetFormatCount(format_) - - return min_,max_ - - -def GetFieldLength(fielddef): - """ - Get length of a field in bytes based on field format definition - - @param fielddef: - field format - see "Settings dictionary" above - - @return: - length of field in bytes - """ - - length=0 - format_, addrdef, arraydef = GetFieldDef(fielddef, fields='format_, addrdef, arraydef') - - # contains a integer list - if isinstance(arraydef, instance(list)) and len(arraydef) > 0: - # arraydef contains a list - # calc size recursive by sum of all elements - for i in range(0, arraydef[0]): - subfielddef = GetSubfieldDef(fielddef) - if len(arraydef) > 1: - length += GetFieldLength( (format_, addrdef, subfielddef) ) - # single array - else: - length += GetFieldLength( (format_, addrdef, None) ) - - elif isinstance(format_, instance(dict)): - # -> iterate through format - addr = None - setting = format_ - for name in setting: - baseaddr, bits, bitshift = GetFieldDef(setting[name], fields='baseaddr, bits, bitshift') - _len = GetFieldLength(setting[name]) - if addr != baseaddr: - addr = baseaddr - length += _len - - # a simple value - elif isinstance(format_, instance(str)): - length = struct.calcsize(format_) - - return length - - -def GetSubfieldDef(fielddef): - """ - Get subfield definition from a given field definition - - @param fielddef: - see Settings desc above - - @return: - subfield definition - """ - - format_, addrdef, datadef, arraydef, validate, cmd, converter = GetFieldDef(fielddef, fields='format_, addrdef, datadef, arraydef, validate, cmd, converter') - - # create new arraydef - if len(arraydef) > 1: - arraydef = arraydef[1:] - else: - arraydef = None - - # create new datadef - if isinstance(datadef, instance(tuple)): - if cmd is not None: - datadef = (arraydef, validate, cmd) - else: - datadef = (arraydef, validate) - else: - datadef = arraydef - - # set new field def - subfielddef = None - if converter is not None: - subfielddef = (format_, addrdef, datadef, converter) - else: - subfielddef = (format_, addrdef, datadef) - - return subfielddef - - -def IsFilterGroup(group): - """ - Check if group is valid on filter - - @param grooup: - group name to check - - @return: - True if group is in filter, otherwise False - """ - - if args.filter is not None: - if group is None: - return False - if group == '*': - return True - if group.title() != INTERNAL.title() and group.title() not in (groupname.title() for groupname in args.filter): - return False - return True - - -def GetFieldValue(fielddef, dobj, addr): - """ - Get single field value from definition - - @param fielddef: - see Settings desc - @param dobj: - decrypted binary config data - @param addr - addr within dobj - - @return: - value read from dobj - """ - - format_, bits, bitshift = GetFieldDef(fielddef, fields='format_, bits, bitshift') - - value_ = 0 - unpackedvalue = struct.unpack_from(format_, dobj, addr) - singletype, bitsize = GetFormatType(format_) - - if not format_[-1:].lower() in ['s','p']: - for val in unpackedvalue: - value_ <<= bitsize - value_ = value_ + val - value_ = bitsRead(value_, bitshift, bits) - else: - value_ = unpackedvalue[0] - s = str(value_).split('\0')[0] # use left string until \0 - value_ = unicode(s, errors='ignore') # remove character > 127 - - return value_ - - -def SetFieldValue(fielddef, dobj, addr, value): - """ - Set single field value from definition - - @param fielddef: - see Settings desc - @param dobj: - decrypted binary config data - @param addr - addr within dobj - @param value - new value - - @return: - new decrypted binary config data - """ - - format_, bits, bitshift = GetFieldDef(fielddef, fields='format_, bits, bitshift') - formatcnt = GetFormatCount(format_) - singletype, bitsize = GetFormatType(format_) - if debug(args) >= 2: - print("SetFieldValue(): fielddef {}, addr 0x{:04x} value {} formatcnt {} singletype {} bitsize {} ".format(fielddef,addr,value,formatcnt,singletype,bitsize), file=sys.stderr) - if not format_[-1:].lower() in ['s','p']: - addr += (bitsize / 8) * formatcnt - for _ in range(0, formatcnt): - addr -= (bitsize / 8) - maxunsigned = ((2**bitsize) - 1) - maxsigned = ((2**bitsize)>>1)-1 - val = value & maxunsigned - if isinstance(value,instance(int)) and value < 0 and val > maxsigned: - val = ((maxunsigned+1)-val) * (-1) - if debug(args) >= 3: - print("SetFieldValue(): Single type - fielddef {}, addr 0x{:04x} value {} singletype {} bitsize {}".format(fielddef,addr,val,singletype,bitsize), file=sys.stderr) - try: - struct.pack_into(singletype, dobj, addr, val) - except struct.error as e: - exit(ExitCode.RESTORE_DATA_ERROR, - "Single type {} [fielddef={}, addr=0x{:04x}, value={}] - skipped!".format(e,fielddef,addr,val), - type_=LogType.WARNING, - doexit=not args.ignorewarning, - line=inspect.getlineno(inspect.currentframe())) - value >>= bitsize - else: - if debug(args) >= 3: - print("SetFieldValue(): String type - fielddef {}, addr 0x{:04x} value {} format_ {}".format(fielddef,addr,value,format_), file=sys.stderr) - try: - struct.pack_into(format_, dobj, addr, value) - except struct.error as e: - exit(ExitCode.RESTORE_DATA_ERROR, - "String type {} [fielddef={}, addr=0x{:04x}, value={}} - skipped!".format(e,fielddef,addr,value), - type_=LogType.WARNING, - doexit=not args.ignorewarning, - line=inspect.getlineno(inspect.currentframe())) - - return dobj - - -def GetField(dobj, fieldname, fielddef, raw=False, addroffset=0): - """ - Get field value from definition - - @param dobj: - decrypted binary config data - @param fieldname: - name of the field - @param fielddef: - see Settings desc above - @param raw - return raw values (True) or converted values (False) - @param addroffset - use offset for baseaddr (used for recursive calls) - - @return: - field mapping - """ - - if isinstance(dobj, instance((bytes,bytearray))): - dobj = str(dobj) - - valuemapping = None - - # get field definition - format_, baseaddr, bits, bitshift, arraydef, group, tasmotacmnd = GetFieldDef(fielddef, fields='format_, baseaddr, bits, bitshift, arraydef, group, tasmotacmnd') - - # filter groups - if not IsFilterGroup(group): - return valuemapping - - # contains a integer list - if isinstance(arraydef, instance(list)) and len(arraydef) > 0: - valuemapping = [] - offset = 0 - for i in range(0, arraydef[0]): - subfielddef = GetSubfieldDef(fielddef) - length = GetFieldLength(subfielddef) - if length != 0: - value = GetField(dobj, fieldname, subfielddef, raw=raw, addroffset=addroffset+offset) - valuemapping.append(value) - offset += length - - # contains a dict - elif isinstance(format_, instance(dict)): - mapping_value = {} - # -> iterate through format - for name in format_: - value = None - value = GetField(dobj, name, format_[name], raw=raw, addroffset=addroffset) - if value is not None: - mapping_value[name] = value - # copy complete returned mapping - valuemapping = copy.deepcopy(mapping_value) - - # a simple value - elif isinstance(format_, instance((str, bool, int, float, long))): - if GetFieldLength(fielddef) != 0: - valuemapping = ReadWriteConverter(GetFieldValue(fielddef, dobj, baseaddr+addroffset), fielddef, read=True, raw=raw) - - else: - exit(ExitCode.INTERNAL_ERROR, "Wrong mapping format definition: '{}'".format(format_), type_=LogType.WARNING, doexit=not args.ignorewarning, line=inspect.getlineno(inspect.currentframe())) - - return valuemapping - - -def SetField(dobj, fieldname, fielddef, restore, addroffset=0, filename=""): - """ - Get field value from definition - - @param dobj: - decrypted binary config data - @param fieldname: - name of the field - @param fielddef: - see Settings desc above - @param restore - restore mapping with the new value(s) - @param addroffset - use offset for baseaddr (used for recursive calls) - @param filename - related filename (for messages only) - - @return: - new decrypted binary config data - """ - format_, baseaddr, bits, bitshift, arraydef, group, writeconverter = GetFieldDef(fielddef, fields='format_, baseaddr, bits, bitshift, arraydef, group, writeconverter') - # cast unicode - fieldname = str(fieldname) - - # filter groups - if not IsFilterGroup(group): - return dobj - - # do not write readonly values - if writeconverter is False: - if debug(args) >= 2: - print("SetField(): Readonly '{}' using '{}'/{}{} @{} skipped".format(fieldname, format_, arraydef, bits, hex(baseaddr+addroffset)), file=sys.stderr) - return dobj - - # contains a list - if isinstance(arraydef, instance(list)) and len(arraydef) > 0: - offset = 0 - if len(restore) > arraydef[0]: - exit(ExitCode.RESTORE_DATA_ERROR, "file '{sfile}', array '{sname}[{selem}]' exceeds max number of elements [{smax}]".format(sfile=filename, sname=fieldname, selem=len(restore), smax=arraydef[0]), type_=LogType.WARNING, doexit=not args.ignorewarning, line=inspect.getlineno(inspect.currentframe())) - for i in range(0, arraydef[0]): - subfielddef = GetSubfieldDef(fielddef) - length = GetFieldLength(subfielddef) - if length != 0: - if i >= len(restore): # restore data list may be shorter than definition - break - subrestore = restore[i] - dobj = SetField(dobj, fieldname, subfielddef, subrestore, addroffset=addroffset+offset, filename=filename) - offset += length - - # contains a dict - elif isinstance(format_, instance(dict)): - for name in format_: # -> iterate through format - if name in restore: - dobj = SetField(dobj, name, format_[name], restore[name], addroffset=addroffset, filename=filename) - - # a simple value - elif isinstance(format_, instance((str, bool, int, float, long))): - valid = True - err = "" - errformat = "" - - min_, max_ = GetFieldMinMax(fielddef) - value = _value = None - skip = False - - # simple char value - if format_[-1:] in ['c']: - try: - value = ReadWriteConverter(restore.encode(STR_ENCODING)[0], fielddef, read=False) - except Exception as e: - exit(e.args[0], e.args[1], type_=LogType.WARNING, line=inspect.getlineno(inspect.currentframe())) - valid = False - - # bool - elif format_[-1:] in ['?']: - try: - value = ReadWriteConverter(bool(restore), fielddef, read=False) - except Exception as e: - exit(e.args[0], e.args[1], type_=LogType.WARNING, line=inspect.getlineno(inspect.currentframe())) - valid = False - - # integer - elif format_[-1:] in ['b','B','h','H','i','I','l','L','q','Q','P']: - value = ReadWriteConverter(restore, fielddef, read=False) - if isinstance(value, instance(str)): - value = int(value, 0) - else: - value = int(value) - # bits - if bits != 0: - bitvalue = value - value = struct.unpack_from(format_, dobj, baseaddr+addroffset)[0] - # validate restore value - valid = ValidateValue(bitvalue, fielddef) - if not valid: - err = "valid bit range exceeding" - value = bitvalue - else: - mask = (1< mask: - min_ = 0 - max_ = mask - _value = bitvalue - valid = False - else: - if bitshift >= 0: - bitvalue <<= bitshift - mask <<= bitshift - else: - bitvalue >>= abs(bitshift) - mask >>= abs(bitshift) - v=value - value &= (0xffffffff ^ mask) - value |= bitvalue - - # full size values - else: - # validate restore function - valid = ValidateValue(value, fielddef) - if not valid: - err = "valid range exceeding" - _value = value - - # float - elif format_[-1:] in ['f','d']: - try: - value = ReadWriteConverter(float(restore), fielddef, read=False) - except: - valid = False - - # string - elif format_[-1:] in ['s','p']: - value = ReadWriteConverter(restore.encode(STR_ENCODING), fielddef, read=False) - err = "string length exceeding" - if value is not None: - max_ -= 1 - valid = min_ <= len(value) <= max_ - else: - skip = True - valid = True - - if value is None and not skip: - # None is an invalid value - valid = False - - if valid is None and not skip: - # validate against object type size - valid = min_ <= value <= max_ - if not valid: - err = "type range exceeding" - errformat = " [{smin},{smax}]" - - if _value is None: - # copy value before possible change below - _value = value - - if isinstance(_value, instance(str)): - _value = "'{}'".format(_value) - - if valid: - if not skip: - if debug(args) >= 2: - sbits = " {} bits shift {}".format(bits, bitshift) if bits else "" - strvalue = "{} [{}]".format(_value, hex(value)) if isinstance(_value, instance(int)) else _value - print("SetField(): Set '{}' using '{}'/{}{} @{} to {}".format(fieldname, format_, arraydef, sbits, hex(baseaddr+addroffset), strvalue), file=sys.stderr) - if fieldname != 'cfg_crc' and fieldname != '_': - prevvalue = GetFieldValue(fielddef, dobj, baseaddr+addroffset) - dobj = SetFieldValue(fielddef, dobj, baseaddr+addroffset, value) - curvalue = GetFieldValue(fielddef, dobj, baseaddr+addroffset) - if prevvalue != curvalue and args.verbose: - message("Value for '{}' changed from {} to {}".format(fieldname, prevvalue, curvalue), type_=LogType.INFO) - else: - if debug(args) >= 2: - print("SetField(): Special field '{}' using '{}'/{}{} @{} skipped".format(fieldname, format_, arraydef, bits, hex(baseaddr+addroffset)), file=sys.stderr) - else: - sformat = "file '{sfile}' - {{'{sname}': {svalue}}} ({serror})"+errformat - exit(ExitCode.RESTORE_DATA_ERROR, sformat.format(sfile=filename, sname=fieldname, serror=err, svalue=_value, smin=min_, smax=max_), type_=LogType.WARNING, doexit=not args.ignorewarning) - - return dobj - - -def SetCmnd(cmnds, fieldname, fielddef, valuemapping, mappedvalue, addroffset=0, idx=None): - """ - Get field value from definition - - @param cmnds: - Tasmota command mapping: { 'group': ['cmnd' <,'cmnd'...>] ... } - @param fieldname: - name of the field - @param fielddef: - see Settings desc above - @param valuemapping: - data mapping - @param mappedvalue - mappedvalue mapping with the new value(s) - @param addroffset - use offset for baseaddr (used for recursive calls) - @param idx - optional array index - - @return: - new Tasmota command mapping - """ - format_, baseaddr, bits, bitshift, arraydef, group, tasmotacmnd, writeconverter = GetFieldDef(fielddef, fields='format_, baseaddr, bits, bitshift, arraydef, group, tasmotacmnd, writeconverter') - - # cast unicode - fieldname = str(fieldname) - - # filter groups - if not IsFilterGroup(group): - return cmnds - - # contains a list - if isinstance(arraydef, instance(list)) and len(arraydef) > 0: - offset = 0 - if len(mappedvalue) > arraydef[0]: - exit(ExitCode.RESTORE_DATA_ERROR, "array '{sname}[{selem}]' exceeds max number of elements [{smax}]".format(sname=fieldname, selem=len(mappedvalue), smax=arraydef[0]), type_=LogType.WARNING, doexit=not args.ignorewarning, line=inspect.getlineno(inspect.currentframe())) - for i in range(0, arraydef[0]): - subfielddef = GetSubfieldDef(fielddef) - length = GetFieldLength(subfielddef) - if length != 0: - if i >= len(mappedvalue): # mappedvalue data list may be shorter than definition - break - subrestore = mappedvalue[i] - cmnds = SetCmnd(cmnds, fieldname, subfielddef, valuemapping, subrestore, addroffset=addroffset+offset, idx=i) - offset += length - - # contains a dict - elif isinstance(format_, instance(dict)): - for name in format_: # -> iterate through format - if name in mappedvalue: - cmnds = SetCmnd(cmnds, name, format_[name], valuemapping, mappedvalue[name], addroffset=addroffset, idx=idx) - - # a simple value - elif isinstance(format_, instance((str, bool, int, float, long))): - if group is not None: - group = group.title(); - if isinstance(tasmotacmnd, instance(tuple)): - tasmotacmnds = tasmotacmnd - for tasmotacmnd in tasmotacmnds: - cmnd = CmndConverter(valuemapping, mappedvalue, idx, fielddef) - if group is not None and cmnd is not None: - if group not in cmnds: - cmnds[group] = [] - if isinstance(cmnd, instance(list)): - for c in cmnd: - cmnds[group].append(c) - else: - cmnds[group].append(cmnd) - else: - cmnd = CmndConverter(valuemapping, mappedvalue, idx, fielddef) - if group is not None and cmnd is not None: - if group not in cmnds: - cmnds[group] = [] - if isinstance(cmnd, instance(list)): - for c in cmnd: - cmnds[group].append(c) - else: - cmnds[group].append(cmnd) - - return cmnds - - -def Bin2Mapping(decode_cfg): - """ - Decodes binary data stream into pyhton mappings dict - - @param decode_cfg: - binary config data (decrypted) - - @return: - valuemapping data as mapping dictionary - """ - if isinstance(decode_cfg, instance((bytes,bytearray))): - decode_cfg = str(decode_cfg) - - # get binary header and template to use - version, size, setting = GetTemplateSetting(decode_cfg) - - # if we did not found a mathching setting - if setting is None: - exit(ExitCode.UNSUPPORTED_VERSION, "Tasmota configuration version {} not supported".format(version),line=inspect.getlineno(inspect.currentframe())) - - if 'version' in setting: - cfg_version = GetField(decode_cfg, 'version', setting['version'], raw=True) - - # check size if exists - if 'cfg_size' in setting: - cfg_size = GetField(decode_cfg, 'cfg_size', setting['cfg_size'], raw=True) - # read size should be same as definied in setting - if cfg_size > size: - # may be processed - exit(ExitCode.DATA_SIZE_MISMATCH, "Number of bytes read does ot match - read {}, expected {} byte".format(cfg_size, size), type_=LogType.ERROR,line=inspect.getlineno(inspect.currentframe())) - elif cfg_size < size: - # less number of bytes can not be processed - exit(ExitCode.DATA_SIZE_MISMATCH, "Number of bytes read to small to process - read {}, expected {} byte".format(cfg_size, size), type_=LogType.ERROR,line=inspect.getlineno(inspect.currentframe())) - - # check crc if exists - if 'cfg_crc' in setting: - cfg_crc = GetField(decode_cfg, 'cfg_crc', setting['cfg_crc'], raw=True) - else: - cfg_crc = GetSettingsCrc(decode_cfg) - if 'cfg_crc32' in setting: - cfg_crc32 = GetField(decode_cfg, 'cfg_crc32', setting['cfg_crc32'], raw=True) - else: - cfg_crc32 = GetSettingsCrc32(decode_cfg) - if version < 0x0606000B: - if cfg_crc != GetSettingsCrc(decode_cfg): - exit(ExitCode.DATA_CRC_ERROR, 'Data CRC error, read 0x{:4x} should be 0x{:4x}'.format(cfg_crc, GetSettingsCrc(decode_cfg)), type_=LogType.WARNING, doexit=not args.ignorewarning,line=inspect.getlineno(inspect.currentframe())) - else: - if cfg_crc32 != GetSettingsCrc32(decode_cfg): - exit(ExitCode.DATA_CRC_ERROR, 'Data CRC32 error, read 0x{:8x} should be 0x{:8x}'.format(cfg_crc32, GetSettingsCrc32(decode_cfg)), type_=LogType.WARNING, doexit=not args.ignorewarning,line=inspect.getlineno(inspect.currentframe())) - - # get valuemapping - valuemapping = GetField(decode_cfg, None, (setting,0,(None, None, (INTERNAL, None)))) - - # add header info - timestamp = datetime.now() - valuemapping['header'] = { 'timestamp':timestamp.strftime("%Y-%m-%d %H:%M:%S"), - 'format': { - 'jsonindent': args.jsonindent, - 'jsoncompact': args.jsoncompact, - 'jsonsort': args.jsonsort, - 'jsonhidepw': args.jsonhidepw, - }, - 'template': { - 'version': hex(version), - 'crc': hex(cfg_crc), - }, - 'data': { - 'crc': hex(GetSettingsCrc(decode_cfg)), - 'size': len(decode_cfg), - }, - 'script': { - 'name': os.path.basename(__file__), - 'version': VER, - }, - 'os': (platform.machine(), platform.system(), platform.release(), platform.version(), platform.platform()), - 'python': platform.python_version(), - } - if 'cfg_crc' in setting: - valuemapping['header']['template'].update({'size': cfg_size}) - if 'cfg_crc32' in setting: - valuemapping['header']['template'].update({'crc32': hex(cfg_crc32)}) - valuemapping['header']['data'].update({'crc32': hex(GetSettingsCrc32(decode_cfg))}) - if 'version' in setting: - valuemapping['header']['data'].update({'version': hex(cfg_version)}) - - return valuemapping - - -def Mapping2Bin(decode_cfg, jsonconfig, filename=""): - """ - Encodes into binary data stream - - @param decode_cfg: - binary config data (decrypted) - @param jsonconfig: - restore data mapping - @param filename: - name of the restore file (for error output only) - - @return: - changed binary config data (decrypted) or None on error - """ - if isinstance(decode_cfg, instance(str)): - decode_cfg = bytearray(decode_cfg) - - - # get binary header data to use the correct version template from device - version, size, setting = GetTemplateSetting(decode_cfg) - - # make empty binarray array - _buffer = bytearray() - # add data - _buffer.extend(decode_cfg) - - if setting is not None: - # iterate through restore data mapping - for name in jsonconfig: - # key must exist in both dict - if name in setting: - SetField(_buffer, name, setting[name], jsonconfig[name], addroffset=0, filename=filename) - else: - if name != 'header': - exit(ExitCode.RESTORE_DATA_ERROR, "Restore file '{}' contains obsolete name '{}', skipped".format(filename, name), type_=LogType.WARNING, doexit=not args.ignorewarning) - - if 'cfg_crc' in setting: - crc = GetSettingsCrc(_buffer) - struct.pack_into(setting['cfg_crc'][0], _buffer, setting['cfg_crc'][1], crc) - if 'cfg_crc32' in setting: - crc32 = GetSettingsCrc32(_buffer) - struct.pack_into(setting['cfg_crc32'][0], _buffer, setting['cfg_crc32'][1], crc32) - return _buffer - - else: - exit(ExitCode.UNSUPPORTED_VERSION,"File '{}', Tasmota configuration version 0x{:x} not supported".format(filename, version), type_=LogType.WARNING, doexit=not args.ignorewarning) - - return None - - -def Mapping2Cmnd(decode_cfg, valuemapping, filename=""): - """ - Encodes mapping data into Tasmota command mapping - - @param decode_cfg: - binary config data (decrypted) - @param valuemapping: - data mapping - @param filename: - name of the restore file (for error output only) - - @return: - Tasmota command mapping {group: [cmnd <,cmnd <,...>>]} - """ - if isinstance(decode_cfg, instance(str)): - decode_cfg = bytearray(decode_cfg) - - # get binary header data to use the correct version template from device - version, size, setting = GetTemplateSetting(decode_cfg) - - cmnds = {} - - if setting is not None: - # iterate through restore data mapping - for name in valuemapping: - # key must exist in both dict - if name in setting: - cmnds = SetCmnd(cmnds, name, setting[name], valuemapping, valuemapping[name], addroffset=0) - else: - if name != 'header': - exit(ExitCode.RESTORE_DATA_ERROR, "Restore file '{}' contains obsolete name '{}', skipped".format(filename, name), type_=LogType.WARNING, doexit=not args.ignorewarning) - - return cmnds - - else: - exit(ExitCode.UNSUPPORTED_VERSION,"File '{}', Tasmota configuration version 0x{:x} not supported".format(filename, version), type_=LogType.WARNING, doexit=not args.ignorewarning) - - return None - - -def Backup(backupfile, backupfileformat, encode_cfg, decode_cfg, configmapping): - """ - Create backup file - - @param backupfile: - Raw backup filename from program args - @param backupfileformat: - Backup file format - @param encode_cfg: - binary config data (encrypted) - @param decode_cfg: - binary config data (decrypted) - @param configmapping: - config data mapppings - """ - - name, ext = os.path.splitext(backupfile) - if ext.lower() == '.'+FileType.BIN.lower(): - backupfileformat = FileType.BIN - elif ext.lower() == '.'+FileType.DMP.lower(): - backupfileformat = FileType.DMP - elif ext.lower() == '.'+FileType.JSON.lower(): - backupfileformat = FileType.JSON - - fileformat = "" - # Tasmota format - if backupfileformat.lower() == FileType.DMP.lower(): - fileformat = "Tasmota" - backup_filename = MakeFilename(backupfile, FileType.DMP, configmapping) - if args.verbose: - message("Writing backup file '{}' ({} format)".format(backup_filename, fileformat), type_=LogType.INFO) - try: - with open(backup_filename, "wb") as backupfp: - backupfp.write(encode_cfg) - except Exception as e: - exit(e.args[0], "'{}' {}".format(backup_filename, e[1]),line=inspect.getlineno(inspect.currentframe())) - - # binary format - elif backupfileformat.lower() == FileType.BIN.lower(): - fileformat = "binary" - backup_filename = MakeFilename(backupfile, FileType.BIN, configmapping) - if args.verbose: - message("Writing backup file '{}' ({} format)".format(backup_filename, fileformat), type_=LogType.INFO) - try: - with open(backup_filename, "wb") as backupfp: - backupfp.write(struct.pack('>]} - """ - def OutputTasmotaSubCmnds(cmnds): - if args.cmndsort: - for cmnd in sorted(cmnds, key = lambda cmnd:[int(c) if c.isdigit() else c for c in re.split('(\d+)', cmnd)]): - print("{}{}".format(" "*args.cmndindent, cmnd)) - else: - for cmnd in cmnds: - print("{}{}".format(" "*args.cmndindent, cmnd)) - - groups = GetGroupList(Settings[0][2]) - - if args.cmndgroup: - for group in groups: - if group.title() in (groupname.title() for groupname in tasmotacmnds): - cmnds = tasmotacmnds[group] - print - print("# {}:".format(group)) - OutputTasmotaSubCmnds(cmnds) - - else: - cmnds = [] - for group in groups: - if group.title() in (groupname.title() for groupname in tasmotacmnds): - cmnds.extend(tasmotacmnds[group]) - OutputTasmotaSubCmnds(cmnds) - -def ParseArgs(): - """ - Program argument parser - - @return: - configargparse.parse_args() result - """ - global parser - parser = configargparse.ArgumentParser(description='Backup/Restore Tasmota configuration data.', - epilog='Either argument -d or -f must be given.', - add_help=False, - formatter_class=lambda prog: CustomHelpFormatter(prog)) - - source = parser.add_argument_group('Source', 'Read/Write Tasmota configuration from/to') - source.add_argument('-f', '--file', '--tasmota-file', - metavar='', - dest='tasmotafile', - default=DEFAULTS['source']['tasmotafile'], - help="file to retrieve/write Tasmota configuration from/to (default: {})'".format(DEFAULTS['source']['tasmotafile'])) - source.add_argument('-d', '--device', '--host', - metavar='', - dest='device', - default=DEFAULTS['source']['device'], - help="hostname or IP address to retrieve/send Tasmota configuration from/to (default: {})".format(DEFAULTS['source']['device']) ) - source.add_argument('-P', '--port', - metavar='', - dest='port', - default=DEFAULTS['source']['port'], - help="TCP/IP port number to use for the host connection (default: {})".format(DEFAULTS['source']['port']) ) - source.add_argument('-u', '--username', - metavar='', - dest='username', - default=DEFAULTS['source']['username'], - help="host HTTP access username (default: {})".format(DEFAULTS['source']['username'])) - source.add_argument('-p', '--password', - metavar='', - dest='password', - default=DEFAULTS['source']['password'], - help="host HTTP access password (default: {})".format(DEFAULTS['source']['password'])) - - backup = parser.add_argument_group('Backup/Restore', 'Backup & restore specification') - backup.add_argument('-i', '--restore-file', - metavar='', - dest='restorefile', - default=DEFAULTS['backup']['backupfile'], - help="file to restore configuration from (default: {}). Replacements: @v=firmware version from config, @f=device friendly name from config, @h=device hostname from config, @H=device hostname from device (-d arg only)".format(DEFAULTS['backup']['restorefile'])) - backup.add_argument('-o', '--backup-file', - metavar='', - dest='backupfile', - default=DEFAULTS['backup']['backupfile'], - help="file to backup configuration to (default: {}). Replacements: @v=firmware version from config, @f=device friendly name from config, @h=device hostname from config, @H=device hostname from device (-d arg only)".format(DEFAULTS['backup']['backupfile'])) - backup_file_formats = ['json', 'bin', 'dmp'] - backup.add_argument('-t', '--backup-type', - metavar='|'.join(backup_file_formats), - dest='backupfileformat', - choices=backup_file_formats, - default=DEFAULTS['backup']['backupfileformat'], - help="backup filetype (default: '{}')".format(DEFAULTS['backup']['backupfileformat']) ) - backup.add_argument('-E', '--extension', - dest='extension', - action='store_true', - default=DEFAULTS['backup']['extension'], - help="append filetype extension for -i and -o filename{}".format(' (default)' if DEFAULTS['backup']['extension'] else '') ) - backup.add_argument('-e', '--no-extension', - dest='extension', - action='store_false', - default=DEFAULTS['backup']['extension'], - help="do not append filetype extension, use -i and -o filename as passed{}".format(' (default)' if not DEFAULTS['backup']['extension'] else '') ) - backup.add_argument('-F', '--force-restore', - dest='forcerestore', - action='store_true', - default=DEFAULTS['backup']['forcerestore'], - help="force restore even configuration is identical{}".format(' (default)' if DEFAULTS['backup']['forcerestore'] else '') ) - - jsonformat = parser.add_argument_group('JSON output', 'JSON format specification') - jsonformat.add_argument('--json-indent', - metavar='', - dest='jsonindent', - type=int, - default=DEFAULTS['jsonformat']['jsonindent'], - help="pretty-printed JSON output using indent level (default: '{}'). -1 disables indent.".format(DEFAULTS['jsonformat']['jsonindent']) ) - jsonformat.add_argument('--json-compact', - dest='jsoncompact', - action='store_true', - default=DEFAULTS['jsonformat']['jsoncompact'], - help="compact JSON output by eliminate whitespace{}".format(' (default)' if DEFAULTS['jsonformat']['jsoncompact'] else '') ) - - jsonformat.add_argument('--json-sort', - dest='jsonsort', - action='store_true', - default=DEFAULTS['jsonformat']['jsonsort'], - help=configargparse.SUPPRESS) #"sort json keywords{}".format(' (default)' if DEFAULTS['jsonformat']['jsonsort'] else '') ) - jsonformat.add_argument('--json-unsort', - dest='jsonsort', - action='store_false', - default=DEFAULTS['jsonformat']['jsonsort'], - help=configargparse.SUPPRESS) #"do not sort json keywords{}".format(' (default)' if not DEFAULTS['jsonformat']['jsonsort'] else '') ) - - jsonformat.add_argument('--json-hide-pw', - dest='jsonhidepw', - action='store_true', - default=DEFAULTS['jsonformat']['jsonhidepw'], - help="hide passwords{}".format(' (default)' if DEFAULTS['jsonformat']['jsonhidepw'] else '') ) - jsonformat.add_argument('--json-show-pw', '--json-unhide-pw', - dest='jsonhidepw', - action='store_false', - default=DEFAULTS['jsonformat']['jsonhidepw'], - help="unhide passwords{}".format(' (default)' if not DEFAULTS['jsonformat']['jsonhidepw'] else '') ) - - cmndformat = parser.add_argument_group('Tasmota command output', 'Tasmota command output format specification') - cmndformat.add_argument('--cmnd-indent', - metavar='', - dest='cmndindent', - type=int, - default=DEFAULTS['cmndformat']['cmndindent'], - help="Tasmota command grouping indent level (default: '{}'). 0 disables indent".format(DEFAULTS['cmndformat']['cmndindent']) ) - cmndformat.add_argument('--cmnd-groups', - dest='cmndgroup', - action='store_true', - default=DEFAULTS['cmndformat']['cmndgroup'], - help="group Tasmota commands{}".format(' (default)' if DEFAULTS['cmndformat']['cmndgroup'] else '') ) - cmndformat.add_argument('--cmnd-nogroups', - dest='cmndgroup', - action='store_false', - default=DEFAULTS['cmndformat']['cmndgroup'], - help="leave Tasmota commands ungrouped{}".format(' (default)' if not DEFAULTS['cmndformat']['cmndgroup'] else '') ) - cmndformat.add_argument('--cmnd-sort', - dest='cmndsort', - action='store_true', - default=DEFAULTS['cmndformat']['cmndsort'], - help="sort Tasmota commands{}".format(' (default)' if DEFAULTS['cmndformat']['cmndsort'] else '') ) - cmndformat.add_argument('--cmnd-unsort', - dest='cmndsort', - action='store_false', - default=DEFAULTS['cmndformat']['cmndsort'], - help="leave Tasmota commands unsorted{}".format(' (default)' if not DEFAULTS['cmndformat']['cmndsort'] else '') ) - - common = parser.add_argument_group('Common', 'Optional arguments') - common.add_argument('-c', '--config', - metavar='', - dest='configfile', - default=DEFAULTS['common']['configfile'], - is_config_file=True, - help="program config file - can be used to set default command args (default: {})".format(DEFAULTS['common']['configfile']) ) - - common.add_argument('-S', '--output', - dest='output', - action='store_true', - default=DEFAULTS['common']['output'], - help="display output regardsless of backup/restore usage{}".format(" (default)" if DEFAULTS['common']['output'] else " (default do not output on backup or restore usage)") ) - output_formats = ['json', 'cmnd','command'] - common.add_argument('-T', '--output-format', - metavar='|'.join(output_formats), - dest='outputformat', - choices=output_formats, - default=DEFAULTS['common']['outputformat'], - help="display output format (default: '{}')".format(DEFAULTS['common']['outputformat']) ) - groups = GetGroupList(Settings[0][2]) - if '*' in groups: - groups.remove('*') - common.add_argument('-g', '--group', - dest='filter', - choices=groups, - nargs='+', - type=lambda s : s.title(), - default=DEFAULTS['common']['filter'], - help="limit data processing to command groups (default {})".format("no filter" if DEFAULTS['common']['filter'] == None else DEFAULTS['common']['filter']) ) - common.add_argument('--ignore-warnings', - dest='ignorewarning', - action='store_true', - default=DEFAULTS['common']['ignorewarning'], - help="do not exit on warnings{}. Not recommended, used by your own responsibility!".format(' (default)' if DEFAULTS['common']['ignorewarning'] else '') ) - - - info = parser.add_argument_group('Info','Extra information') - info.add_argument('-D', '--debug', - dest='debug', - action='count', - help=configargparse.SUPPRESS) - info.add_argument('-h', '--help', - dest='shorthelp', - action='store_true', - help='show usage help message and exit') - info.add_argument("-H", "--full-help", - action="help", - help="show full help message and exit") - info.add_argument('-v', '--verbose', - dest='verbose', - action='store_true', - help='produce more output about what the program does') - info.add_argument('-V', '--version', - action='version', - version=PROG) - - args = parser.parse_args() - - if debug(args) >= 1: - print(parser.format_values(), file=sys.stderr) - print("Settings:", file=sys.stderr) - for k in args.__dict__: - print(" "+str(k), "= ",eval('args.{}'.format(k)), file=sys.stderr) - return args - - -if __name__ == "__main__": - args = ParseArgs() - if args.shorthelp: - ShortHelp() - - # check source args - if args.device is not None and args.tasmotafile is not None: - exit(ExitCode.ARGUMENT_ERROR, "Unable to select source, do not use -d and -f together",line=inspect.getlineno(inspect.currentframe())) - - # default no configuration available - encode_cfg = None - - # pull config from Tasmota device - if args.tasmotafile is not None: - if args.verbose: - message("Load data from file '{}'".format(args.tasmotafile), type_=LogType.INFO) - encode_cfg = LoadTasmotaConfig(args.tasmotafile) - - # load config from Tasmota file - if args.device is not None: - if args.verbose: - message("Load data from device '{}'".format(args.device), type_=LogType.INFO) - encode_cfg = PullTasmotaConfig(args.device, args.port, username=args.username, password=args.password) - - if encode_cfg is None: - # no config source given - ShortHelp(False) - print - print(parser.epilog) - sys.exit(ExitCode.OK) - - if len(encode_cfg) == 0: - exit(ExitCode.FILE_READ_ERROR, "Unable to read configuration data from {} '{}'".format('device' if args.device is not None else 'file', \ - args.device if args.device is not None else args.tasmotafile) \ - ,line=inspect.getlineno(inspect.currentframe()) ) - # decrypt Tasmota config - decode_cfg = DecryptEncrypt(encode_cfg) - - # decode into mappings dictionary - configmapping = Bin2Mapping(decode_cfg) - if args.verbose and 'version' in configmapping: - message("{} '{}' is using Tasmota {}".format('File' if args.tasmotafile is not None else 'Device', - args.tasmotafile if args.tasmotafile is not None else args.device, - GetVersionStr(configmapping['version'])), - type_=LogType.INFO) - - # backup to file - if args.backupfile is not None: - Backup(args.backupfile, args.backupfileformat, encode_cfg, decode_cfg, configmapping) - - # restore from file - if args.restorefile is not None: - Restore(args.restorefile, args.backupfileformat, encode_cfg, decode_cfg, configmapping) - - # json screen output - if (args.backupfile is None and args.restorefile is None) or args.output: - if args.outputformat == 'json': - print(json.dumps(configmapping, sort_keys=args.jsonsort, indent=None if args.jsonindent<0 else args.jsonindent, separators=(',', ':') if args.jsoncompact else (', ', ': ') )) - - if args.outputformat == 'cmnd' or args.outputformat == 'command': - tasmotacmnds = Mapping2Cmnd(decode_cfg, configmapping) - OutputTasmotaCmnds(tasmotacmnds) - - sys.exit(exitcode) From 4441f212d5164d510ee9594399b36a2e1b60dc95 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Mon, 2 Dec 2019 13:03:43 -0300 Subject: [PATCH 47/50] Add rule trigger tele-switch1#state --- tasmota/support_tasmota.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index e7099affd..84e31d4b0 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -609,7 +609,7 @@ bool MqttShowSensor(void) if (pin[GPIO_SWT1 +i] < 99) { #endif // USE_TM1638 bool swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i])); - ResponseAppend_P(PSTR(",\"" D_JSON_SWITCH "%d\":\"%s\""), i +1, GetStateText(swm ^ SwitchLastState(i))); + ResponseAppend_P(PSTR(",\"" D_JSON_SWITCH "%d\":{\"STATE\":\"%s\"}"), i +1, GetStateText(swm ^ SwitchLastState(i))); } } XsnsCall(FUNC_JSON_APPEND); From 621204e57f736c1c672c81cd197229e88e955f05 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 2 Dec 2019 18:54:08 +0100 Subject: [PATCH 48/50] Fix WS2812 power control (#7090) --- tasmota/CHANGELOG.md | 1 + tasmota/xdrv_04_light.ino | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index c639e5392..1706dbbb3 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -4,6 +4,7 @@ - Fix lost functionality of GPIO9 and GPIO10 on some devices (#7080) - Fix Zigbee uses Hardware Serial if GPIO 1/3 or GPIO 13/15 and SerialLog 0 (#7071) +- Fix WS2812 power control (#7090) - Change light color schemes 2, 3 and 4 from color wheel to Hue driven ## Released diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 0ef3f1ea9..7f1e66fc6 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -1571,6 +1571,7 @@ void LightAnimate(void) { uint8_t cur_col[LST_MAX]; uint16_t light_still_on = 0; + bool power_off = false; Light.strip_timer_counter++; if (!Light.power) { // All channels powered off @@ -1578,6 +1579,9 @@ void LightAnimate(void) if (!Light.fade_running) { sleep = Settings.sleep; } + if (Settings.light_scheme >= LS_MAX) { + power_off = true; + } } else { if (Settings.sleep > PWM_MAX_SLEEP) { sleep = PWM_MAX_SLEEP; // set a maxumum value of 50 milliseconds to ensure that animations are smooth @@ -1629,7 +1633,7 @@ void LightAnimate(void) } } - if (Settings.light_scheme < LS_MAX) { // exclude WS281X Neopixel + if ((Settings.light_scheme < LS_MAX) || power_off) { // exclude WS281X Neopixel schemes // Apply power modifiers to Light.new_color LightApplyPower(Light.new_color, Light.power); @@ -1714,7 +1718,7 @@ void LightAnimate(void) cur_col_10bits[i] = orig_col_10bits[Light.color_remap[i]]; } - if (!Settings.light_fade) { // no fade + if (!Settings.light_fade || power_off) { // no fade // record the current value for a future Fade memcpy(Light.fade_start_8, cur_col, sizeof(Light.fade_start_8)); memcpy(Light.fade_start_10, cur_col_10bits, sizeof(Light.fade_start_10)); From 461d18b3f9966888ce7c780f34786ff70d07331f Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Mon, 2 Dec 2019 15:04:38 -0300 Subject: [PATCH 49/50] Add new tele- rule triggers --- tasmota/support_tasmota.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 84e31d4b0..2f54cec7d 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -565,7 +565,7 @@ void MqttShowState(void) if (i == LightDevice()) { LightState(1); } // call it only once } else { #endif - ResponseAppend_P(PSTR(",\"%s\":\"%s\""), GetPowerDevice(stemp1, i, sizeof(stemp1), Settings.flag.device_index_enable), // SetOption26 - Switch between POWER or POWER1 + ResponseAppend_P(PSTR(",\"%s\":{\"STATE\":\"%s\"}"), GetPowerDevice(stemp1, i, sizeof(stemp1), Settings.flag.device_index_enable), // SetOption26 - Switch between POWER or POWER1 GetStateText(bitRead(power, i-1))); #ifdef USE_SONOFF_IFAN if (IsModuleIfan()) { @@ -592,7 +592,7 @@ void MqttPublishTeleState(void) mqtt_data[0] = '\0'; MqttShowState(); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); -#ifdef USE_SCRIPT +#if defined(USE_RULES) || defined(USE_SCRIPT) RulesTeleperiod(); // Allow rule based HA messages #endif // USE_SCRIPT } From 0b3f84c36e01db3f95ebb26404a2155910cc1aed Mon Sep 17 00:00:00 2001 From: stefanbode Date: Mon, 2 Dec 2019 21:44:05 +0100 Subject: [PATCH 50/50] Added #7006 request for support of stepper motors --- tasmota/xdrv_27_shutter.ino | 84 ++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 34 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 3c3039dda..b397ac732 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -76,10 +76,10 @@ struct SHUTTER { uint16_t open_time[MAX_SHUTTERS]; // duration to open the shutter uint16_t close_time[MAX_SHUTTERS]; // duration to close the shutter uint16_t close_velocity[MAX_SHUTTERS]; // in relation to open velocity. higher value = faster - uint16_t operations[MAX_SHUTTERS]; int8_t direction[MAX_SHUTTERS]; // 1 == UP , 0 == stop; -1 == down uint8_t mode = 0; // operation mode definition. see enum type above SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE uint8_t motordelay[MAX_SHUTTERS]; // initial motorstarttime in 0.05sec. + uint16_t pwm_frequency; } Shutter; void ShutterRtc50mS(void) @@ -237,45 +237,32 @@ void ShutterUpdatePosition(void) { char scommand[CMDSZ]; char stopic[TOPSZ]; + char stemp2[10]; for (uint32_t i = 0; i < shutters_present; i++) { if (Shutter.direction[i] != 0) { //char stemp1[20]; + + if (pin[GPIO_PWM1]+i < 99 && Shutter.pwm_frequency != 1000) { + Shutter.pwm_frequency += 100; + Shutter.pwm_frequency = (Shutter.pwm_frequency > 1000 ? 1000 : Shutter.pwm_frequency); + analogWriteFreq(Shutter.pwm_frequency); + analogWrite(pin[GPIO_PWM1]+i, 50); + } + Shutter.real_position[i] = Shutter.start_position[i] + ( (Shutter.time[i] - Shutter.motordelay[i]) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); // avoid real position leaving the boundaries. - Shutter.real_position[i] = Shutter.real_position[i] < 0 ? 0 : (Shutter.real_position[i] > Shutter.open_max[i] ? Shutter.open_max[i] : Shutter.real_position[i]) ; + if (Shutter.real_position[i] < 0 || Shutter.real_position[i] > Shutter.open_max[i]) { + dtostrfd((float)Shutter.time[i] / 20, 1, stemp2); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: ShutterTEMP %d: Real Pos. %d, Stoppos: %ld, direction %d, rtcshutter: %s [s]"), i, Shutter.real_position[i], Settings.shutter_position[i], Shutter.direction[i], stemp2); - // Add additional runtime, if shutter did not reach the endstop for some time. - if (Shutter.target_position[i] == Shutter.real_position[i] && Shutter.target_position[i] == 0) { - // for every operation add 5x50ms = 250ms to stop position - //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Adding additional runtime")); - Shutter.real_position[i] += 500 * Shutter.operations[i] ; - Shutter.operations[i] = 0; + Shutter.real_position[i] = Shutter.real_position[i] < 0 ? 0 : (Shutter.real_position[i] > Shutter.open_max[i] ? Shutter.open_max[i] : Shutter.real_position[i]) ; } + if (Shutter.real_position[i] * Shutter.direction[i] >= Shutter.target_position[i] * Shutter.direction[i] ) { // calculate relay number responsible for current movement. //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Stop Condition detected: real: %d, Target: %d, direction: %d"),Shutter.real_position[i], Shutter.target_position[i],Shutter.direction[i]); uint8_t cur_relay = Settings.shutter_startrelay[i] + (Shutter.direction[i] == 1 ? 0 : 1) ; - char stemp2[10]; - - Settings.shutter_position[i] = ShutterRealToPercentPosition(Shutter.real_position[i], i); - //Settings.shutter_position[i] = Settings.shuttercoeff[2][i] * 5 > Shutter.real_position[i] ? (Shutter.real_position[i] * 10 / Settings.shuttercoeff[2][i] + 4)/10 : ((Shutter.real_position[i]-Settings.shuttercoeff[0,i]) *10 / Settings.shuttercoeff[1][i] +4) / 10; - - if (0 < Settings.shutter_position[i] && Settings.shutter_position[i] < 100) { - Shutter.operations[i]++; - } else { - Shutter.operations[i] = 0; - } - - dtostrfd((float)Shutter.time[i] / 20, 1, stemp2); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Real Pos. %d, Stoppos: %ld, relay: %d, direction %d, pulsetimer: %d, rtcshutter: %s [s], operationtime %d"), i, Shutter.real_position[i], Settings.shutter_position[i], cur_relay -1, Shutter.direction[i], Settings.pulse_timer[cur_relay -1], stemp2, Shutter.operations[i]); - Shutter.start_position[i] = Shutter.real_position[i]; - - // sending MQTT result to broker - snprintf_P(scommand, sizeof(scommand),PSTR(D_SHUTTER "%d"), i+1); - GetTopic_P(stopic, STAT, mqtt_topic, scommand); - Response_P("%d", Settings.shutter_invert[i] ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]); - MqttPublish(stopic, Settings.flag.mqtt_power_retain); // CMND_POWERRETAIN switch (Shutter.mode) { case SHT_PULSE_OPEN__PULSE_CLOSE: @@ -288,8 +275,21 @@ void ShutterUpdatePosition(void) break; case SHT_OFF_ON__OPEN_CLOSE: // This is a failsafe configuration. Relay1 ON/OFF Relay2 -1/1 direction + if (pin[GPIO_PWM1 ]+i < 99) { + Shutter.pwm_frequency = 0; + //slow down for acurate position + analogWriteFreq(500); + analogWrite(pin[GPIO_PWM1]+i, 50); + analogWriteFreq(0); + while (RtcSettings.pulse_counter[i] < (Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]/2) { + delay(1); + } + analogWrite(pin[GPIO_PWM1]+i, 0); + Shutter.real_position[i] = RtcSettings.pulse_counter[i]*Shutter.direction[i]*2+Shutter.start_position[i]; + } if ((1 << (Settings.shutter_startrelay[i]-1)) & power) { ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); + ExecuteCommandPower(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER); } break; case SHT_OFF_OPEN__OFF_CLOSE: @@ -300,6 +300,18 @@ void ShutterUpdatePosition(void) } break; } + Settings.shutter_position[i] = ShutterRealToPercentPosition(Shutter.real_position[i], i); + + dtostrfd((float)Shutter.time[i] / 20, 1, stemp2); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Real Pos. %d, Stoppos: %ld, relay: %d, direction %d, pulsetimer: %d, rtcshutter: %s [s]"), i, Shutter.real_position[i], Settings.shutter_position[i], cur_relay -1, Shutter.direction[i], Settings.pulse_timer[cur_relay -1], stemp2); + Shutter.start_position[i] = Shutter.real_position[i]; + + // sending MQTT result to broker + snprintf_P(scommand, sizeof(scommand),PSTR(D_SHUTTER "%d"), i+1); + GetTopic_P(stopic, STAT, mqtt_topic, scommand); + Response_P("%d", Settings.shutter_invert[i] ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]); + MqttPublish(stopic, Settings.flag.mqtt_power_retain); // CMND_POWERRETAIN + Shutter.direction[i] = 0; uint8_t position = Settings.shutter_invert[i] ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]; Response_P(PSTR("{")); @@ -326,6 +338,12 @@ void ShutterStartInit(uint8_t index, uint8_t direction, int32_t target_pos) Shutter.target_position[index] = target_pos; Shutter.start_position[index] = Shutter.real_position[index]; Shutter.time[index] = 0; + if (pin[GPIO_PWM1]+index < 99) { + Shutter.pwm_frequency = 0; + analogWriteFreq(Shutter.pwm_frequency); + analogWrite(pin[GPIO_PWM1]+index, 0); + RtcSettings.pulse_counter[index] = 0; + } //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter: %d from %d to %d in directin %d"), index, Shutter.start_position[index], Shutter.target_position[index], Shutter.direction[index]); } @@ -426,7 +444,6 @@ void ShutterSetPosition(uint8_t device, uint8_t position) void CmndShutterOpen(void) { XdrvMailbox.payload = 100; - XdrvMailbox.data_len = 3; last_source = SRC_WEBGUI; CmndShutterPosition(); } @@ -434,7 +451,7 @@ void CmndShutterOpen(void) void CmndShutterClose(void) { XdrvMailbox.payload = 0; - XdrvMailbox.data_len = 1; + XdrvMailbox.data_len = 0; last_source = SRC_WEBGUI; CmndShutterPosition(); } @@ -445,7 +462,7 @@ void CmndShutterStop(void) uint32_t index = XdrvMailbox.index -1; if (Shutter.direction[index] != 0) { - //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving shutter %d: direction: %d"), XdrvMailbox.index, Shutter.direction[index]); + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving shutter %d: direction: %d"), XdrvMailbox.index, Shutter.direction[index]); int32_t temp_realpos = Shutter.start_position[index] + ( (Shutter.time[index]+10) * (Shutter.direction[index] > 0 ? 100 : -Shutter.close_velocity[index])); XdrvMailbox.payload = ShutterRealToPercentPosition(temp_realpos, index); @@ -472,7 +489,7 @@ void CmndShutterPosition(void) if (!strcmp(XdrvMailbox.data,"STOP")) { CmndShutterStop(); } return; } - + int8_t target_pos_percent = XdrvMailbox.payload < 0 ? 0 : (XdrvMailbox.payload > 100 ? 100 : XdrvMailbox.payload); // webgui still send also on inverted shutter the native position. target_pos_percent = Settings.shutter_invert[index] && SRC_WEBGUI != last_source ? 100 - target_pos_percent : target_pos_percent; @@ -497,7 +514,6 @@ void CmndShutterPosition(void) } if (Shutter.direction[index] != new_shutterdirection ) { ShutterStartInit(index, new_shutterdirection, Shutter.target_position[index]); - Shutter.operations[index]++; if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE) { ExecuteCommandPower(Settings.shutter_startrelay[index], 0, SRC_SHUTTER); //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Delay5 5s, xdrv %d"), XdrvMailbox.payload); @@ -556,7 +572,7 @@ void CmndShutterMotorDelay(void) ShutterInit(); } char time_chr[10]; - dtostrfd((float)(Settings.shutter_motordelay[XdrvMailbox.index -1]) / 20, 1, time_chr); + dtostrfd((float)(Settings.shutter_motordelay[XdrvMailbox.index -1]) / 20, 2, time_chr); ResponseCmndIdxChar(time_chr); } }