diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 1cb3f42cd..e542181b9 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -3,7 +3,7 @@ **Related issue (if applicable):** fixes # ## Checklist: - - [ ] The pull request is done against the latest dev branch + - [ ] The pull request is done against the latest development branch - [ ] Only relevant files were touched - [ ] Only one feature/fix was added per PR and the code change compiles without warnings - [ ] The code change is tested and works on Tasmota core ESP8266 V.2.7.4.9 diff --git a/.github/workflows/CI_github.yml b/.github/workflows/CI_github.yml index b8844bb5c..74cd0573a 100644 --- a/.github/workflows/CI_github.yml +++ b/.github/workflows/CI_github.yml @@ -1,6 +1,6 @@ name: Tasmota CI -on: +on: pull_request: jobs: @@ -16,7 +16,7 @@ jobs: pip install -U platformio platformio upgrade --dev platformio update - - name: Run PlatformIO + - name: Run PlatformIO run: platformio run -e tasmota - uses: actions/upload-artifact@v2 with: @@ -79,7 +79,7 @@ jobs: with: name: firmware path: ./build_output/firmware - + tasmota-sensors: runs-on: ubuntu-latest steps: @@ -156,6 +156,25 @@ jobs: name: firmware path: ./build_output/firmware + tasmota-AF: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Set up Python + uses: actions/setup-python@v1 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -U platformio + platformio upgrade --dev + platformio update + - name: Run PlatformIO + run: platformio run -e tasmota-AF + - uses: actions/upload-artifact@v2 + with: + name: firmware + path: ./build_output/firmware + tasmota-BG: runs-on: ubuntu-latest steps: @@ -174,7 +193,7 @@ jobs: with: name: firmware path: ./build_output/firmware - + tasmota-BR: runs-on: ubuntu-latest steps: @@ -250,7 +269,7 @@ jobs: with: name: firmware path: ./build_output/firmware - + tasmota-ES: runs-on: ubuntu-latest steps: @@ -269,7 +288,7 @@ jobs: with: name: firmware path: ./build_output/firmware - + tasmota-FR: runs-on: ubuntu-latest steps: @@ -326,7 +345,7 @@ jobs: with: name: firmware path: ./build_output/firmware - + tasmota-HU: runs-on: ubuntu-latest steps: @@ -402,7 +421,7 @@ jobs: with: name: firmware path: ./build_output/firmware - + tasmota-PL: runs-on: ubuntu-latest steps: @@ -478,7 +497,7 @@ jobs: with: name: firmware path: ./build_output/firmware - + tasmota-SE: runs-on: ubuntu-latest steps: @@ -554,7 +573,7 @@ jobs: with: name: firmware path: ./build_output/firmware - + tasmota-UK: runs-on: ubuntu-latest steps: diff --git a/.github/workflows/CI_github_ESP32.yml b/.github/workflows/CI_github_ESP32.yml index aca4ddb15..ecf8bf561 100644 --- a/.github/workflows/CI_github_ESP32.yml +++ b/.github/workflows/CI_github_ESP32.yml @@ -23,7 +23,7 @@ jobs: with: name: firmware path: ./build_output/firmware - + tasmota32-webcam: runs-on: ubuntu-latest steps: @@ -44,6 +44,26 @@ jobs: name: firmware path: ./build_output/firmware + tasmota32-odroidgo: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Set up Python + uses: actions/setup-python@v1 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -U platformio + platformio upgrade --dev + platformio update + - name: Run PlatformIO + run: | + platformio run -e tasmota32-odroidgo + - uses: actions/upload-artifact@v2 + with: + name: firmware + path: ./build_output/firmware + tasmota32-minimal: runs-on: ubuntu-latest steps: @@ -103,7 +123,7 @@ jobs: with: name: firmware path: ./build_output/firmware - + tasmota32-sensors: runs-on: ubuntu-latest steps: @@ -164,6 +184,26 @@ jobs: name: firmware path: ./build_output/firmware + tasmota32-AF: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Set up Python + uses: actions/setup-python@v1 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -U platformio + platformio upgrade --dev + platformio update + - name: Run PlatformIO + run: | + platformio run -e tasmota32-AF + - uses: actions/upload-artifact@v2 + with: + name: firmware + path: ./build_output/firmware + tasmota32-BG: runs-on: ubuntu-latest steps: @@ -183,7 +223,7 @@ jobs: with: name: firmware path: ./build_output/firmware - + tasmota32-BR: runs-on: ubuntu-latest steps: @@ -263,7 +303,7 @@ jobs: with: name: firmware path: ./build_output/firmware - + tasmota32-ES: runs-on: ubuntu-latest steps: @@ -343,7 +383,7 @@ jobs: with: name: firmware path: ./build_output/firmware - + tasmota32-HU: runs-on: ubuntu-latest steps: @@ -423,7 +463,7 @@ jobs: with: name: firmware path: ./build_output/firmware - + tasmota32-PL: runs-on: ubuntu-latest steps: @@ -503,7 +543,7 @@ jobs: with: name: firmware path: ./build_output/firmware - + tasmota32-SE: runs-on: ubuntu-latest steps: @@ -583,7 +623,7 @@ jobs: with: name: firmware path: ./build_output/firmware - + tasmota32-UK: runs-on: ubuntu-latest steps: diff --git a/.github/workflows/Tasmota_build.yml b/.github/workflows/Tasmota_build.yml index b0044da28..9e8f61219 100644 --- a/.github/workflows/Tasmota_build.yml +++ b/.github/workflows/Tasmota_build.yml @@ -230,6 +230,30 @@ jobs: name: firmware path: ./build_output/firmware + + tasmota-AF: + needs: tasmota_pull + runs-on: ubuntu-latest + continue-on-error: true + steps: + - uses: actions/checkout@v1 + - name: Set up Python + uses: actions/setup-python@v1 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -U platformio + platformio upgrade --dev + platformio update + - name: Run PlatformIO + run: | + platformio run -e tasmota-AF + - uses: actions/upload-artifact@v2 + with: + name: firmware + path: ./build_output/firmware + + tasmota-BG: needs: tasmota_pull runs-on: ubuntu-latest @@ -851,6 +875,29 @@ jobs: path: ./build_output/firmware + tasmota32-odroidgo: + needs: tasmota_pull + runs-on: ubuntu-latest + continue-on-error: true + steps: + - uses: actions/checkout@v1 + - name: Set up Python + uses: actions/setup-python@v1 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -U platformio + platformio upgrade --dev + platformio update + - name: Run PlatformIO + run: | + platformio run -e tasmota32-odroidgo + - uses: actions/upload-artifact@v2 + with: + name: firmware + path: ./build_output/firmware + + tasmota32-knx: needs: tasmota_pull runs-on: ubuntu-latest @@ -966,6 +1013,29 @@ jobs: path: ./build_output/firmware + tasmota32-AF: + needs: tasmota_pull + runs-on: ubuntu-latest + continue-on-error: true + steps: + - uses: actions/checkout@v1 + - name: Set up Python + uses: actions/setup-python@v1 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -U platformio + platformio upgrade --dev + platformio update + - name: Run PlatformIO + run: | + platformio run -e tasmota32-AF + - uses: actions/upload-artifact@v2 + with: + name: firmware + path: ./build_output/firmware + + tasmota32-BG: needs: tasmota_pull runs-on: ubuntu-latest @@ -1513,6 +1583,7 @@ jobs: mkdir -p ./firmware/tasmota/languages mkdir -p ./firmware/tasmota32/languages mkdir -p ./firmware/tasmota32/ESP32_needed_files/ + mkdir -p ./firmware/tasmota32/Odroid_go_needed_files/ [ ! -f ./mv_firmware/tasmota.* ] || mv ./mv_firmware/tasmota.* ./firmware/tasmota/ [ ! -f ./mv_firmware/tasmota-sensors.* ] || mv ./mv_firmware/tasmota-sensors.* ./firmware/tasmota/ [ ! -f ./mv_firmware/tasmota-minimal.* ] || mv ./mv_firmware/tasmota-minimal.* ./firmware/tasmota/ @@ -1528,12 +1599,14 @@ jobs: [ ! -f ./mv_firmware/tasmota32-ir*.* ] || mv ./mv_firmware/tasmota32-ir*.* ./firmware/tasmota32/ [ ! -f ./mv_firmware/tasmota32-display.* ] || mv ./mv_firmware/tasmota32-display.* ./firmware/tasmota32/ [ ! -f ./mv_firmware/tasmota32-web*.* ] || mv ./mv_firmware/tasmota32-web*.* ./firmware/tasmota32/ + [ ! -f ./mv_firmware/tasmota32-odroidgo.* ] || mv ./mv_firmware/tasmota32-odroidgo.* ./firmware/tasmota32/ [ ! -f ./mv_firmware/tasmota32-knx.* ] || mv ./mv_firmware/tasmota32-knx.* ./firmware/tasmota32/ [ ! -f ./mv_firmware/tasmota32* ] || mv ./mv_firmware/tasmota32* ./firmware/tasmota32/languages/ [ ! -f ./mv_firmware/* ] || mv ./mv_firmware/* ./firmware/tasmota/languages/ rm ./firmware/tasmota32/*.gz rm ./firmware/tasmota32/languages/*.gz [ ! -f ./tools/Esptool/ESP32/*.* ] || mv ./tools/Esptool/ESP32/*.* ./firmware/tasmota32/ESP32_needed_files/ + [ ! -f ./tools/Esptool/Odroid_go/*.* ] || mv ./tools/Esptool/Odroid_go/*.* ./firmware/tasmota32/Odroid_go_needed_files/ [ ! -f ./FIRMWARE.md ] || mv -f ./FIRMWARE.md ./README.md - name: Commit files # transfer the new binaries back into the repository run: | diff --git a/.github/workflows/Tasmota_build_master.yml b/.github/workflows/Tasmota_build_master.yml index 244bfe8ce..8c00d25e3 100644 --- a/.github/workflows/Tasmota_build_master.yml +++ b/.github/workflows/Tasmota_build_master.yml @@ -230,6 +230,30 @@ jobs: name: firmware path: ./build_output/firmware + + tasmota-AF: + needs: tasmota_pull + runs-on: ubuntu-latest + continue-on-error: true + steps: + - uses: actions/checkout@v1 + - name: Set up Python + uses: actions/setup-python@v1 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -U platformio + platformio upgrade --dev + platformio update + - name: Run PlatformIO + run: | + platformio run -e tasmota-AF + - uses: actions/upload-artifact@v2 + with: + name: firmware + path: ./build_output/firmware + + tasmota-BG: needs: tasmota_pull runs-on: ubuntu-latest @@ -851,6 +875,29 @@ jobs: path: ./build_output/firmware + tasmota32-odroidgo: + needs: tasmota_pull + runs-on: ubuntu-latest + continue-on-error: true + steps: + - uses: actions/checkout@v1 + - name: Set up Python + uses: actions/setup-python@v1 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -U platformio + platformio upgrade --dev + platformio update + - name: Run PlatformIO + run: | + platformio run -e tasmota32-odroidgo + - uses: actions/upload-artifact@v2 + with: + name: firmware + path: ./build_output/firmware + + tasmota32-knx: needs: tasmota_pull runs-on: ubuntu-latest @@ -966,6 +1013,29 @@ jobs: path: ./build_output/firmware + tasmota32-AF: + needs: tasmota_pull + runs-on: ubuntu-latest + continue-on-error: true + steps: + - uses: actions/checkout@v1 + - name: Set up Python + uses: actions/setup-python@v1 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -U platformio + platformio upgrade --dev + platformio update + - name: Run PlatformIO + run: | + platformio run -e tasmota32-AF + - uses: actions/upload-artifact@v2 + with: + name: firmware + path: ./build_output/firmware + + tasmota32-BG: needs: tasmota_pull runs-on: ubuntu-latest @@ -1513,6 +1583,7 @@ jobs: mkdir -p ./firmware/tasmota/languages mkdir -p ./firmware/tasmota32/languages mkdir -p ./firmware/tasmota32/ESP32_needed_files/ + mkdir -p ./firmware/tasmota32/Odroid_go_needed_files/ [ ! -f ./mv_firmware/tasmota.* ] || mv ./mv_firmware/tasmota.* ./firmware/tasmota/ [ ! -f ./mv_firmware/tasmota-sensors.* ] || mv ./mv_firmware/tasmota-sensors.* ./firmware/tasmota/ [ ! -f ./mv_firmware/tasmota-minimal.* ] || mv ./mv_firmware/tasmota-minimal.* ./firmware/tasmota/ @@ -1520,7 +1591,7 @@ jobs: [ ! -f ./mv_firmware/tasmota-ir*.* ] || mv ./mv_firmware/tasmota-ir*.* ./firmware/tasmota/ [ ! -f ./mv_firmware/tasmota-display.* ] || mv ./mv_firmware/tasmota-display.* ./firmware/tasmota/ [ ! -f ./mv_firmware/tasmota-knx.* ] || mv ./mv_firmware/tasmota-knx.* ./firmware/tasmota/ - [ ! -f ./mv_firmware/tasmota-zbbridge.* ] || mv ./mv_firmware/tasmota-zbbridge.* ./firmware/tasmota/ + [ ! -f ./mv_firmware/tasmota-zbbridge.* ] || mv ./mv_firmware/tasmota-zbbridge.* ./firmware/tasmota/ [ ! -f ./mv_firmware/tasmota32.* ] || mv ./mv_firmware/tasmota32.* ./firmware/tasmota32/ [ ! -f ./mv_firmware/tasmota32-sensors.* ] || mv ./mv_firmware/tasmota32-sensors.* ./firmware/tasmota32/ [ ! -f ./mv_firmware/tasmota32-minimal.* ] || mv ./mv_firmware/tasmota32-minimal.* ./firmware/tasmota32/ @@ -1528,12 +1599,14 @@ jobs: [ ! -f ./mv_firmware/tasmota32-ir*.* ] || mv ./mv_firmware/tasmota32-ir*.* ./firmware/tasmota32/ [ ! -f ./mv_firmware/tasmota32-display.* ] || mv ./mv_firmware/tasmota32-display.* ./firmware/tasmota32/ [ ! -f ./mv_firmware/tasmota32-web*.* ] || mv ./mv_firmware/tasmota32-web*.* ./firmware/tasmota32/ + [ ! -f ./mv_firmware/tasmota32-odroidgo.* ] || mv ./mv_firmware/tasmota32-odroidgo.* ./firmware/tasmota32/ [ ! -f ./mv_firmware/tasmota32-knx.* ] || mv ./mv_firmware/tasmota32-knx.* ./firmware/tasmota32/ [ ! -f ./mv_firmware/tasmota32* ] || mv ./mv_firmware/tasmota32* ./firmware/tasmota32/languages/ [ ! -f ./mv_firmware/* ] || mv ./mv_firmware/* ./firmware/tasmota/languages/ rm ./firmware/tasmota32/*.gz rm ./firmware/tasmota32/languages/*.gz [ ! -f ./tools/Esptool/ESP32/*.* ] || mv ./tools/Esptool/ESP32/*.* ./firmware/tasmota32/ESP32_needed_files/ + [ ! -f ./tools/Esptool/Odroid_go/*.* ] || mv ./tools/Esptool/Odroid_go/*.* ./firmware/tasmota32/Odroid_go_needed_files/ [ ! -f ./FIRMWARE.md ] || mv -f ./RELEASENOTES.md ./README.md - name: Commit files # transfer the new binaries back into the repository run: | diff --git a/BUILDS.md b/BUILDS.md index ed11aae2c..34d386c62 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -201,15 +201,17 @@ | USE_DISPLAY_ILI9341 | - | - | - | - | - | - | x | | USE_DISPLAY_EPAPER_29 | - | - | - | - | - | - | x | | USE_DISPLAY_EPAPER_42 | - | - | - | - | - | - | x | -| USE_DISPLAY_ILI9488 | - | - | - | - | - | - | - | -| USE_DISPLAY_SSD1351 | - | - | - | - | - | - | - | -| USE_DISPLAY_RA8876 | - | - | - | - | - | - | - | +| USE_DISPLAY_ILI9488 | - | - | - | - | - | - | x | +| USE_DISPLAY_SSD1351 | - | - | - | - | - | - | x | +| USE_DISPLAY_RA8876 | - | - | - | - | - | - | x | +| USE_DISPLAY_ST7789 | - | - | - | - | - | - | x | ## Additional Features and Sensors on ESP32 | Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | webcam | Remarks |-----------------------|---------|-------|--------|-----|---------|----|---------|--------|-------- -| USE_MI_ESP32 | - | - | - | - | - | - | - | - | +| USE_MI_ESP32 | - | - | X | - | X | - | - | - | See SetOption115 +| USE_IBEACON_ESP32 | - | - | - | - | - | - | - | - | | USE_WEBCAM | - | - | - | - | - | - | - | x | | USE_ETHERNET | - | - | - | - | - | - | - | - | | USE_I2S_AUDIO | - | - | - | - | - | - | - | - | diff --git a/CHANGELOG.md b/CHANGELOG.md index 458019d7b..5bb01ac2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,16 +3,43 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - Development -## [9.2.0.1] +## [9.2.0.2] +### Added +- Basic support for ESP32 Odroid Go 16MB binary tasmota32-odroidgo.bin (#8630) +- Command ``CTRange`` to specify the visible CT range the bulb is capable of (#10311) +- Command ``VirtualCT`` to simulate or fine tune CT bulbs with 3,4,5 channels (#10311) +- Disable `USE_LIGHT`` light support for ZBBridge (saves 17.6kb) + +### Breaking Changed +- Replaced MFRC522 13.56MHz rfid card reader GPIO selection from ``SPI CS`` by ``RC522 CS`` +- Replaced NRF24L01 GPIO selection from ``SPI CS`` by ``NRF24 CS`` and ``SPI DC`` by ``NRF24 DC`` +- Replaced ILI9341 GPIO selection from ``SPI CS`` by ``ILI9341 CS`` and ``SPI DC`` by ``ILI9341 DC`` +- Replaced ST7789 GPIO selection from ``SPI CS`` by ``ST7789 CS`` and ``SPI DC`` by ``ST7789 DC`` +- Replaced ILI9488 GPIO selection from ``SPI CS`` by ``ILI9488_CS`` +- Replaced EPaper29 GPIO selection from ``SPI CS`` by ``EPaper29 CS`` +- Replaced EPaper42 GPIO selection from ``SPI CS`` by ``EPaper42 CS`` +- Replaced SSD1351 GPIO selection from ``SPI CS`` by ``SSD1351 CS`` +- Replaced RA8876 GPIO selection from ``SPI CS`` by ``RA8876 CS`` + +### Changed +- Maximum chars in AddLog_P logging reduced from 700 to 128 (LOGSZ) to enhance stability + +## [9.2.0.1] 20201229 ### Added - Milliseconds to console output (#10152) - Support for P9813 RGB Led MOSFET controller (#10104) - Support for GPIO option selection - Gpio ``Option_a1`` enabling PWM2 high impedance if powered off as used by Wyze bulbs (#10196) - Support for FTC532 8-button touch controller by Peter Franck (#10222) +- Support character `#` to be replaced by `space`-character in command ``Publish`` topic (#10258) +- BSSID and Signal Strength Indicator to GUI wifi scan result (#10253) +- Support for Afrikaans language translations by Christiaan Heerze +- Support for IR inverted leds using ``#define IR_SEND_INVERTED true`` (#10301) +- Support for disabling 38kHz IR modulation using ``#define IR_SEND_USE_MODULATION false`` (#10301) +- Support for SPI display driver for ST7789 TFT by Gerhard Mutz (#9037) ### Changed -- Logging from fixed global memory buffer to stack buffer freeing 700 bytes RAM +- Logging from heap to stack freeing 700 bytes RAM ### Fixed - Redesign syslog and mqttlog using log buffer (#10164) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 34c3c2b98..8a2d4afc5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -47,13 +47,13 @@ The process is straight-forward. - Fork the Tasmota Repository [git repository](https://github.com/arendst/Tasmota). - Write/Change the code in your Fork for a new feature, bug fix, new sensor, optimization, etc. - Ensure tests work. - - Create a Pull Request against the [**dev**](https://github.com/arendst/Tasmota/tree/dev) branch of Tasmota. + - Create a Pull Request against the [**development**](https://github.com/arendst/Tasmota/tree/development) branch of Tasmota. -1. All pull requests must be done against the dev branch. +1. All pull requests must be done against the development branch. 2. Only relevant files should be touched (Also beware if your editor has auto-formatting feature enabled). 3. Only one feature/fix should be added per PR. 4. If adding a new functionality (new hardware, new library support) not related to an existing component move it to it's own modules (.ino file). -5. PRs that don't compile (fail in CI Tests) or cause coding errors will not be merged. Please fix the issue. Same goes for PRs that are raised against older commit in dev - you might need to rebase and resolve conflicts. +5. PRs that don't compile (fail in CI Tests) or cause coding errors will not be merged. Please fix the issue. Same goes for PRs that are raised against older commit in development - you might need to rebase and resolve conflicts. 6. All pull requests should undergo peer review by at least one contributor other than the creator, excepts for the owner. 7. All pull requests should consider updates to the documentation. 8. Pull requests that address an outstanding issue, particularly an issue deemed to be severe, should be given priority. diff --git a/RELEASENOTES.md b/RELEASENOTES.md index e9cb5b4d5..539323f9d 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -56,16 +56,36 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota [Complete list](BUILDS.md) of available feature and sensors. -## Changelog v9.2.0.1 +## Changelog v9.2.0.2 ### Added +- Command ``CTRange`` to specify the visible CT range the bulb is capable of [#10311](https://github.com/arendst/Tasmota/issues/10311) +- Command ``VirtualCT`` to simulate or fine tune CT bulbs with 3,4,5 channels [#10311](https://github.com/arendst/Tasmota/issues/10311) - Milliseconds to console output [#10152](https://github.com/arendst/Tasmota/issues/10152) +- Gpio ``Option_a1`` enabling PWM2 high impedance if powered off as used by Wyze bulbs [#10196](https://github.com/arendst/Tasmota/issues/10196) +- BSSID and Signal Strength Indicator to GUI wifi scan result [#10253](https://github.com/arendst/Tasmota/issues/10253) - Support for P9813 RGB Led MOSFET controller [#10104](https://github.com/arendst/Tasmota/issues/10104) - Support for GPIO option selection -- Gpio ``Option_a1`` enabling PWM2 high impedance if powered off as used by Wyze bulbs [#10196](https://github.com/arendst/Tasmota/issues/10196) - Support for FTC532 8-button touch controller by Peter Franck [#10222](https://github.com/arendst/Tasmota/issues/10222) +- Support character `#` to be replaced by `space`-character in command ``Publish`` topic [#10258](https://github.com/arendst/Tasmota/issues/10258) +- Support for Afrikaans language translations by Christiaan Heerze +- Support for IR inverted leds using ``#define IR_SEND_INVERTED true`` [#10301](https://github.com/arendst/Tasmota/issues/10301) +- Support for disabling 38kHz IR modulation using ``#define IR_SEND_USE_MODULATION false`` [#10301](https://github.com/arendst/Tasmota/issues/10301) +- Support for SPI display driver for ST7789 TFT by Gerhard Mutz [#9037](https://github.com/arendst/Tasmota/issues/9037) +- Basic support for ESP32 Odroid Go 16MB binary tasmota32-odroidgo.bin [#8630](https://github.com/arendst/Tasmota/issues/8630) + +### Breaking Changed +- Replaced MFRC522 13.56MHz rfid card reader GPIO selection from ``SPI CS`` by ``RC522 CS`` +- Replaced NRF24L01 GPIO selection from ``SPI CS`` by ``NRF24 CS`` and ``SPI DC`` by ``NRF24 DC`` +- Replaced ILI9341 GPIO selection from ``SPI CS`` by ``ILI9341 CS`` and ``SPI DC`` by ``ILI9341 DC`` +- Replaced ST7789 GPIO selection from ``SPI CS`` by ``ST7789 CS`` and ``SPI DC`` by ``ST7789 DC`` +- Replaced ILI9488 GPIO selection from ``SPI CS`` by ``ILI9488_CS`` +- Replaced EPaper29 GPIO selection from ``SPI CS`` by ``EPaper29 CS`` +- Replaced EPaper42 GPIO selection from ``SPI CS`` by ``EPaper42 CS`` +- Replaced SSD1351 GPIO selection from ``SPI CS`` by ``SSD1351 CS`` +- Replaced RA8876 GPIO selection from ``SPI CS`` by ``RA8876 CS`` ### Changed -- Logging from fixed global memory buffer to stack buffer freeing 700 bytes RAM +- Logging from heap to stack freeing 700 bytes RAM ### Fixed - Redesign syslog and mqttlog using log buffer [#10164](https://github.com/arendst/Tasmota/issues/10164) diff --git a/lib/default/TasmotaSerial-3.1.0/src/TasmotaSerial.cpp b/lib/default/TasmotaSerial-3.1.0/src/TasmotaSerial.cpp index d7ac0866e..1d0445351 100644 --- a/lib/default/TasmotaSerial-3.1.0/src/TasmotaSerial.cpp +++ b/lib/default/TasmotaSerial-3.1.0/src/TasmotaSerial.cpp @@ -1,7 +1,7 @@ /* TasmotaSerial.cpp - Implementation of software serial with hardware serial fallback for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 Theo Arends This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/default/TasmotaSerial-3.1.0/src/TasmotaSerial.h b/lib/default/TasmotaSerial-3.1.0/src/TasmotaSerial.h index bc5161d65..2a97741e3 100644 --- a/lib/default/TasmotaSerial-3.1.0/src/TasmotaSerial.h +++ b/lib/default/TasmotaSerial-3.1.0/src/TasmotaSerial.h @@ -1,7 +1,7 @@ /* TasmotaSerial.h - Implementation of software serial with hardware serial fallback for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 Theo Arends This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/default/UdpListener/src/UdpListener.h b/lib/default/UdpListener/src/UdpListener.h index b4f5af93b..57bce0dae 100644 --- a/lib/default/UdpListener/src/UdpListener.h +++ b/lib/default/UdpListener/src/UdpListener.h @@ -1,7 +1,7 @@ /* UdpListener.h - webserver for Tasmota - Copyright (C) 2020 Theo Arends & Stephan Hadinger + Copyright (C) 2021 Theo Arends & Stephan Hadinger 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 diff --git a/lib/default/Unishox-1.0-shadinger/src/UnishoxStrings.cpp b/lib/default/Unishox-1.0-shadinger/src/UnishoxStrings.cpp index 223399e2f..22b8cbcc3 100644 --- a/lib/default/Unishox-1.0-shadinger/src/UnishoxStrings.cpp +++ b/lib/default/Unishox-1.0-shadinger/src/UnishoxStrings.cpp @@ -1,7 +1,7 @@ /* UnishoxStrings.c - support library for compressed strings in Flash - Copyright (C) 2020 Theo Arends and Stephan Hadinger + Copyright (C) 2021 Theo Arends and Stephan Hadinger 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 diff --git a/lib/default/Unishox-1.0-shadinger/src/UnishoxStrings.h b/lib/default/Unishox-1.0-shadinger/src/UnishoxStrings.h index 12de778d4..3ded62ffe 100644 --- a/lib/default/Unishox-1.0-shadinger/src/UnishoxStrings.h +++ b/lib/default/Unishox-1.0-shadinger/src/UnishoxStrings.h @@ -1,7 +1,7 @@ /* UnishoxStrings.c - support library for compressed strings in Flash - Copyright (C) 2020 Theo Arends and Stephan Hadinger + Copyright (C) 2021 Theo Arends and Stephan Hadinger 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 @@ -28,18 +28,18 @@ /*******************************************************************************************/ /* * UnishoxStrings compressed literal strings - * + * * To be typically used for web UI to have multiple strings like JS, CSS, HTML * compressed in a single list of small strings. This is where Unishox shines. - * + * * Strings before compression are separated with NULL chars, which makes them ready to use * once you know the offset in the global array. - * + * * The list of string is marked by an empty stings, i.e. two consecutive NULL chars - * + * * To distinguish from uncompressed templates, and to indicate the global size * the compressed array is prefixed with NULL and the uncompressed size * 16 bytes. - * + * * Compressed format: * - Byte 00 : \00 - if non-null, then it is not compressed * - Byte 01 : - uncompressed size is * 16 bytes (always rounded up) @@ -54,22 +54,22 @@ * This class is initialzed with either a PMEM uncompressed list of strings * or a PMEM unishox-compressed list of strings; in this case RAM is allocated * to hold the uncompressed data, until the class gets out of scope. - * + * * To encode, use https://tasmota.hadinger.fr/util * and use the "Compress strings template with unishox" * past the C code for the strings, and copy/paste the result * (don't foget to rename the variable). - * + * * Input: * Each string must be terminated with an explicit NULL char "\0". The list is hence * terminated with a double-NULL. - * + * * Each string is then indexed as its byte offset in the whole template. * The offsets are computed at the same time as the compressed version. * You need to use the online compressor even if you don't use the comrpessed version. - * + * * Indexes are marked as C++ comments starting with "//=" - * + * * Example input: * con * // start of strings diff --git a/lib/default/jsmn-shadinger-1.0/src/JsonGenerator.cpp b/lib/default/jsmn-shadinger-1.0/src/JsonGenerator.cpp index 0bdd77768..b823c58d9 100644 --- a/lib/default/jsmn-shadinger-1.0/src/JsonGenerator.cpp +++ b/lib/default/jsmn-shadinger-1.0/src/JsonGenerator.cpp @@ -1,7 +1,7 @@ /* JsonGenerator.cpp - lightweight JSON parser - Copyright (C) 2020 Stephan Hadinger + Copyright (C) 2021 Stephan Hadinger 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 diff --git a/lib/default/jsmn-shadinger-1.0/src/JsonGenerator.h b/lib/default/jsmn-shadinger-1.0/src/JsonGenerator.h index 589c60167..2f27b846b 100644 --- a/lib/default/jsmn-shadinger-1.0/src/JsonGenerator.h +++ b/lib/default/jsmn-shadinger-1.0/src/JsonGenerator.h @@ -1,7 +1,7 @@ /* JsonGenerator.h - lightweight JSON generator - Copyright (C) 2020 Stephan Hadinger + Copyright (C) 2021 Stephan Hadinger 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 diff --git a/lib/default/jsmn-shadinger-1.0/src/JsonParser.cpp b/lib/default/jsmn-shadinger-1.0/src/JsonParser.cpp index 050505d07..73703d6ed 100644 --- a/lib/default/jsmn-shadinger-1.0/src/JsonParser.cpp +++ b/lib/default/jsmn-shadinger-1.0/src/JsonParser.cpp @@ -1,7 +1,7 @@ /* JsonParser.cpp - lightweight JSON parser - Copyright (C) 2020 Stephan Hadinger + Copyright (C) 2021 Stephan Hadinger 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 diff --git a/lib/default/jsmn-shadinger-1.0/src/JsonParser.h b/lib/default/jsmn-shadinger-1.0/src/JsonParser.h index 85d401407..a31f28c91 100644 --- a/lib/default/jsmn-shadinger-1.0/src/JsonParser.h +++ b/lib/default/jsmn-shadinger-1.0/src/JsonParser.h @@ -1,7 +1,7 @@ /* JsonParser.h - lightweight JSON parser - Copyright (C) 2020 Stephan Hadinger + Copyright (C) 2021 Stephan Hadinger 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 @@ -228,7 +228,7 @@ public: // destructor ~JsonParser(); - + // set the current buffer for attribute access (i.e. set the global) void setCurrent(void) { k_current_json_buffer = _json; } diff --git a/lib/lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.cpp b/lib/lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.cpp index 057001779..b1a8c48f8 100644 --- a/lib/lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.cpp +++ b/lib/lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.cpp @@ -1,7 +1,7 @@ /* TasmotaModbus.cpp - Basic modbus wrapper for TasmotaSerial for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 Theo Arends This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.h b/lib/lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.h index 4a5fbc7a8..22d4e12f3 100644 --- a/lib/lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.h +++ b/lib/lib_basic/TasmotaModbus-1.2.0/src/TasmotaModbus.h @@ -1,7 +1,7 @@ /* TasmotaModbus.h - Basic modbus wrapper for TasmotaSerial for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 Theo Arends This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/lib/lib_display/Arduino_ST7789-gemu-1.0/Arduino_ST7789.cpp b/lib/lib_display/Arduino_ST7789-gemu-1.0/Arduino_ST7789.cpp index f45b33095..74837242b 100644 --- a/lib/lib_display/Arduino_ST7789-gemu-1.0/Arduino_ST7789.cpp +++ b/lib/lib_display/Arduino_ST7789-gemu-1.0/Arduino_ST7789.cpp @@ -27,7 +27,7 @@ uint16_t Arduino_ST7789::GetColorFromIndex(uint8_t index) { } static const uint8_t PROGMEM - cmd_240x240[] = { // Initialization commands for 7789 screens + init_cmd[] = { // Initialization commands for 7789 screens 10, // 9 commands in list: ST7789_SWRESET, ST_CMD_DELAY, // 1: Software reset, no args, w/delay 150, // 150 ms delay @@ -38,14 +38,6 @@ static const uint8_t PROGMEM 10, // 10 ms delay ST7789_MADCTL , 1, // 4: Memory access ctrl (directions), 1 arg: 0x00, // Row addr/col addr, bottom to top refresh - ST7789_CASET , 4, // 5: Column addr set, 4 args, no delay: - 0x00, ST7789_240x240_XSTART, // XSTART = 0 - (ST7789_TFTWIDTH+ST7789_240x240_XSTART) >> 8, - (ST7789_TFTWIDTH+ST7789_240x240_XSTART) & 0xFF, // XEND = 240 - ST7789_RASET , 4, // 6: Row addr set, 4 args, no delay: - 0x00, ST7789_240x240_YSTART, // YSTART = 0 - (ST7789_TFTHEIGHT+ST7789_240x240_YSTART) >> 8, - (ST7789_TFTHEIGHT+ST7789_240x240_YSTART) & 0xFF, // YEND = 240 ST7789_INVON , ST_CMD_DELAY, // 7: Inversion ON 10, ST7789_NORON , ST_CMD_DELAY, // 8: Normal display on, no args, w/delay @@ -75,7 +67,7 @@ inline uint16_t swapcolor(uint16_t x) { // Constructor when using software SPI. All output pins are configurable. Arduino_ST7789::Arduino_ST7789(int8_t dc, int8_t rst, int8_t sid, int8_t sclk, int8_t cs, int8_t bp) - : Renderer(ST7789_TFTWIDTH, ST7789_TFTHEIGHT) + : Renderer(_width, _height) { _cs = cs; _dc = dc; @@ -91,7 +83,7 @@ Arduino_ST7789::Arduino_ST7789(int8_t dc, int8_t rst, int8_t sid, int8_t sclk, i // Constructor when using hardware SPI. Faster, but must use SPI pins // specific to each board type (e.g. 11,13 for Uno, 51,52 for Mega, etc.) Arduino_ST7789::Arduino_ST7789(int8_t dc, int8_t rst, int8_t cs, int8_t bp) - : Renderer(ST7789_TFTWIDTH, ST7789_TFTHEIGHT) { + : Renderer(_width, _height) { _cs = cs; _dc = dc; _rst = rst; @@ -335,29 +327,59 @@ void Arduino_ST7789::setRotation(uint8_t m) { case 0: writedata(ST7789_MADCTL_MX | ST7789_MADCTL_MY | ST7789_MADCTL_RGB); - _xstart = _colstart; - // _ystart = _rowstart; - _ystart = 80; + _xstart = 0; + _ystart = 0; + if (_width==240 && _height==240) { + _xstart = ST7789_240x240_XSTART_R0; + _ystart = ST7789_240x240_YSTART_R0; + } + if (_width==135 && _height==240) { + _xstart = ST7789_135x240_XSTART_R0; + _ystart = ST7789_135x240_YSTART_R0; + } break; case 1: writedata(ST7789_MADCTL_MY | ST7789_MADCTL_MV | ST7789_MADCTL_RGB); - _ystart = _colstart; - // _xstart = _rowstart; - _xstart = 80; + _ystart = 0; + _xstart = 0; + if (_width==240 && _height==240) { + _xstart = ST7789_240x240_XSTART_R1; + _ystart = ST7789_240x240_YSTART_R1; + } + if (_width==240 && _height==135) { + _xstart = ST7789_135x240_XSTART_R1; + _ystart = ST7789_135x240_YSTART_R1; + } break; case 2: writedata(ST7789_MADCTL_RGB); - _xstart = _colstart; - _ystart = _rowstart; + _xstart = 0; + _ystart = 0; + if (_width==240 && _height==240) { + _xstart = ST7789_240x240_XSTART_R2; + _ystart = ST7789_240x240_YSTART_R2; + } + if (_width==135 && _height==240) { + _xstart = ST7789_135x240_XSTART_R2; + _ystart = ST7789_135x240_YSTART_R2; + } break; case 3: writedata(ST7789_MADCTL_MX | ST7789_MADCTL_MV | ST7789_MADCTL_RGB); - _ystart = _colstart; - _xstart = _rowstart; + _xstart = 0; + _ystart = 0; + if (_width==240 && _height==240) { + _xstart = ST7789_240x240_XSTART_R3; + _ystart = ST7789_240x240_YSTART_R3; + } + if (_width==240 && _height==135) { + _xstart = ST7789_135x240_XSTART_R3; + _ystart = ST7789_135x240_YSTART_R3; + } break; } } @@ -533,12 +555,10 @@ inline void Arduino_ST7789::DC_LOW(void) { void Arduino_ST7789::init(uint16_t width, uint16_t height) { commonInit(NULL); - _colstart = ST7789_240x240_XSTART; - _rowstart = ST7789_240x240_YSTART; _height = height; _width = width; - displayInit(cmd_240x240); + displayInit(init_cmd); setRotation(2); diff --git a/lib/lib_display/Arduino_ST7789-gemu-1.0/Arduino_ST7789.h b/lib/lib_display/Arduino_ST7789-gemu-1.0/Arduino_ST7789.h index 2d97346e7..3dfaa03a8 100644 --- a/lib/lib_display/Arduino_ST7789-gemu-1.0/Arduino_ST7789.h +++ b/lib/lib_display/Arduino_ST7789-gemu-1.0/Arduino_ST7789.h @@ -39,11 +39,23 @@ //#define SPI_HAS_TRANSACTION // already defined in SPI.h -#define ST7789_TFTWIDTH 240 -#define ST7789_TFTHEIGHT 240 +#define ST7789_240x240_XSTART_R0 0 +#define ST7789_240x240_YSTART_R0 80 +#define ST7789_240x240_XSTART_R1 80 +#define ST7789_240x240_YSTART_R1 0 +#define ST7789_240x240_XSTART_R2 0 +#define ST7789_240x240_YSTART_R2 0 +#define ST7789_240x240_XSTART_R3 0 +#define ST7789_240x240_YSTART_R3 0 -#define ST7789_240x240_XSTART 0 -#define ST7789_240x240_YSTART 0 +#define ST7789_135x240_XSTART_R0 53 +#define ST7789_135x240_YSTART_R0 40 +#define ST7789_135x240_XSTART_R1 40 +#define ST7789_135x240_YSTART_R1 52 +#define ST7789_135x240_XSTART_R2 52 +#define ST7789_135x240_YSTART_R2 40 +#define ST7789_135x240_XSTART_R3 40 +#define ST7789_135x240_YSTART_R3 53 #define ST_CMD_DELAY 0x80 // special signifier for command lists diff --git a/lib/lib_i2c/FT5206_Library/.gitignore b/lib/lib_display/FT5206_Library/.gitignore similarity index 100% rename from lib/lib_i2c/FT5206_Library/.gitignore rename to lib/lib_display/FT5206_Library/.gitignore diff --git a/lib/lib_i2c/FT5206_Library/LICENSE b/lib/lib_display/FT5206_Library/LICENSE similarity index 100% rename from lib/lib_i2c/FT5206_Library/LICENSE rename to lib/lib_display/FT5206_Library/LICENSE diff --git a/lib/lib_i2c/FT5206_Library/README.md b/lib/lib_display/FT5206_Library/README.md similarity index 100% rename from lib/lib_i2c/FT5206_Library/README.md rename to lib/lib_display/FT5206_Library/README.md diff --git a/lib/lib_i2c/FT5206_Library/keywords.txt b/lib/lib_display/FT5206_Library/keywords.txt similarity index 100% rename from lib/lib_i2c/FT5206_Library/keywords.txt rename to lib/lib_display/FT5206_Library/keywords.txt diff --git a/lib/lib_i2c/FT5206_Library/library.properties b/lib/lib_display/FT5206_Library/library.properties similarity index 100% rename from lib/lib_i2c/FT5206_Library/library.properties rename to lib/lib_display/FT5206_Library/library.properties diff --git a/lib/lib_i2c/FT5206_Library/src/FT5206.cpp b/lib/lib_display/FT5206_Library/src/FT5206.cpp similarity index 100% rename from lib/lib_i2c/FT5206_Library/src/FT5206.cpp rename to lib/lib_display/FT5206_Library/src/FT5206.cpp diff --git a/lib/lib_i2c/FT5206_Library/src/FT5206.h b/lib/lib_display/FT5206_Library/src/FT5206.h similarity index 100% rename from lib/lib_i2c/FT5206_Library/src/FT5206.h rename to lib/lib_display/FT5206_Library/src/FT5206.h diff --git a/lib/libesp32/CORE2_Library/BM8563_RTC.cpp b/lib/libesp32/CORE2_Library/BM8563_RTC.cpp index 986ccf897..f17262d29 100755 --- a/lib/libesp32/CORE2_Library/BM8563_RTC.cpp +++ b/lib/libesp32/CORE2_Library/BM8563_RTC.cpp @@ -268,8 +268,8 @@ int BM8563_RTC::SetAlarmIRQ(const RTC_TimeTypeDef &RTC_TimeStruct) out_buf[1] = ByteToBcd2(RTC_TimeStruct.Hours) & 0x3f; } - out_buf[2] = 0x00; - out_buf[3] = 0x00; + //out_buf[2] = 0x00; + //out_buf[3] = 0x00; uint8_t reg_value = ReadReg(0x01); diff --git a/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP32Wifi.cpp b/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP32Wifi.cpp index a72d95cb6..0e26883ba 100644 --- a/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP32Wifi.cpp +++ b/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP32Wifi.cpp @@ -1,7 +1,7 @@ /* WiFi compat with ESP32 - Copyright (C) 2020 Theo Arends / Jörg Schüler-Maroldt + Copyright (C) 2021 Theo Arends / Jörg Schüler-Maroldt 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 diff --git a/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP8266WiFi.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP8266WiFi.h index df9f54273..9649f49f5 100644 --- a/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP8266WiFi.h +++ b/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP8266WiFi.h @@ -1,7 +1,7 @@ /* WiFi compat with ESP32 - Copyright (C) 2020 Theo Arends / Jörg Schüler-Maroldt + Copyright (C) 2021 Theo Arends / Jörg Schüler-Maroldt 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 diff --git a/platformio.ini b/platformio.ini index 6c0f401df..d7d6caa45 100644 --- a/platformio.ini +++ b/platformio.ini @@ -21,6 +21,7 @@ default_envs = ; tasmota-display ; tasmota-zbbridge ; tasmota-ir +; tasmota-AF ; tasmota-BG ; tasmota-BR ; tasmota-CN diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index 3f76397af..eaaf59729 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -36,6 +36,7 @@ default_envs = ; tasmota32-ir ; tasmota32-ircustom ; tasmota32solo1 +; tasmota32-odroidgo [common] diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index c3aa37f2f..430fcc344 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -8,6 +8,7 @@ default_envs = ${build_envs.default_envs} ; *** Uncomment by deleting ";" in the line(s) below to select version(s) ; tasmota32 ; tasmota32-webcam +; tasmota32-odroidgo ; tasmota32-minimal ; tasmota32-lite ; tasmota32-knx @@ -15,6 +16,7 @@ default_envs = ${build_envs.default_envs} ; tasmota32-display ; tasmota32-ir ; tasmota32-ircustom +; tasmota32-AF ; tasmota32-BG ; tasmota32-BR ; tasmota32-CN diff --git a/platformio_tasmota_env.ini b/platformio_tasmota_env.ini index 428fac8ce..f24794b68 100644 --- a/platformio_tasmota_env.ini +++ b/platformio_tasmota_env.ini @@ -67,6 +67,9 @@ build_flags = ${common.build_flags} -DFIRMWARE_ZBBRIDGE board_build.f_cpu = 160000000L lib_extra_dirs = lib/lib_ssl +[env:tasmota-AF] +build_flags = ${common.build_flags} -DMY_LANGUAGE=af_AF + [env:tasmota-BG] build_flags = ${common.build_flags} -DMY_LANGUAGE=bg_BG diff --git a/platformio_tasmota_env32.ini b/platformio_tasmota_env32.ini index 4fd87373c..1d64e6650 100644 --- a/platformio_tasmota_env32.ini +++ b/platformio_tasmota_env32.ini @@ -36,6 +36,14 @@ board_build.f_cpu = 240000000L build_flags = ${common32.build_flags} -DFIRMWARE_WEBCAM lib_extra_dirs = lib/libesp32, lib/lib_basic +[env:tasmota32-odroidgo] +extends = env:tasmota32 +board = odroid_esp32 +board_build.f_cpu = 240000000L +board_build.partitions = esp32_partition_app1984k_ffat12M.csv +build_flags = ${common32.build_flags} -DBOARD_HAS_PSRAM=true -DFIRMWARE_ODROID_GO +lib_extra_dirs = lib/libesp32, lib/lib_basic, lib/lib_i2c, lib/lib_rf, lib/lib_div, lib/lib_ssl, lib/lib_display + [env:tasmota32-minimal] extends = env:tasmota32 build_flags = ${common32.build_flags} -DFIRMWARE_MINIMAL @@ -70,6 +78,10 @@ lib_extra_dirs = lib/libesp32, lib/lib_basic extends = env:tasmota32 build_flags = ${common32.build_flags} ${irremoteesp_full.build_flags} -DFIRMWARE_IR_CUSTOM +[env:tasmota32-AF] +extends = env:tasmota32 +build_flags = ${common32.build_flags} -DMY_LANGUAGE=af_AF + [env:tasmota32-BG] extends = env:tasmota32 build_flags = ${common32.build_flags} -DMY_LANGUAGE=bg_BG diff --git a/tasmota/StackThunk_light.cpp b/tasmota/StackThunk_light.cpp index 1e5fd445a..aea7ae438 100644 --- a/tasmota/StackThunk_light.cpp +++ b/tasmota/StackThunk_light.cpp @@ -7,7 +7,7 @@ between a secondary, user-allocated stack on the heap and the real stack. - Copyright (c) 2017 Earle F. Philhower, III. All rights reserved. + Copyright (C) 2021 Earle F. Philhower, III. All rights reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public diff --git a/tasmota/StackThunk_light.h b/tasmota/StackThunk_light.h index 164417000..9fa562655 100644 --- a/tasmota/StackThunk_light.h +++ b/tasmota/StackThunk_light.h @@ -7,7 +7,7 @@ between a secondary, user-allocated stack on the heap and the real stack. - Copyright (c) 2017 Earle F. Philhower, III. All rights reserved. + Copyright (C) 2021 Earle F. Philhower, III. All rights reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public diff --git a/tasmota/WiFiClientSecureLightBearSSL.cpp b/tasmota/WiFiClientSecureLightBearSSL.cpp index d7b53cf25..f91d96cfc 100755 --- a/tasmota/WiFiClientSecureLightBearSSL.cpp +++ b/tasmota/WiFiClientSecureLightBearSSL.cpp @@ -3,7 +3,7 @@ - Mostly compatible with Arduino WiFi shield library and standard WiFiClient/ServerSecure (except for certificate handling). - Copyright (c) 2018 Earle F. Philhower, III + Copyright (C) 2021 Earle F. Philhower, III This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -57,8 +57,8 @@ extern "C" { #include "coredecls.h" #define LOG_HEAP_SIZE(a) _Log_heap_size(a) void _Log_heap_size(const char *msg) { - register uint32_t *sp asm("a1"); - int freestack = 4 * (sp - g_pcont->stack); + register uint32_t *sp asm("a1"); + int freestack = 4 * (sp - g_pcont->stack); Serial.printf("%s %d, Fragmentation=%d, Thunkstack=%d, Free stack=%d, FreeContStack=%d\n", msg, ESP.getFreeHeap(), ESP.getHeapFragmentation(), stack_thunk_light_get_max_usage(), freestack, ESP.getFreeContStack()); @@ -98,60 +98,60 @@ make_stack_thunk_light(br_ssl_engine_sendrec_buf); // unless the Thunk was initialized. Thanks to AES128 GCM, we can keep // symetric processing on the stack void min_br_ssl_engine_recvapp_ack(br_ssl_engine_context *cc, size_t len) { - if (stack_thunk_light_get_refcnt()) { - return thunk_light_br_ssl_engine_recvapp_ack(cc, len); - } else { - return br_ssl_engine_recvapp_ack(cc, len); - } + if (stack_thunk_light_get_refcnt()) { + return thunk_light_br_ssl_engine_recvapp_ack(cc, len); + } else { + return br_ssl_engine_recvapp_ack(cc, len); + } } unsigned char *min_br_ssl_engine_recvapp_buf(const br_ssl_engine_context *cc, size_t *len) { - if (stack_thunk_light_get_refcnt()) { - return thunk_light_br_ssl_engine_recvapp_buf(cc, len); - } else { - return br_ssl_engine_recvapp_buf(cc, len); - } + if (stack_thunk_light_get_refcnt()) { + return thunk_light_br_ssl_engine_recvapp_buf(cc, len); + } else { + return br_ssl_engine_recvapp_buf(cc, len); + } } void min_br_ssl_engine_recvrec_ack(br_ssl_engine_context *cc, size_t len) { - if (stack_thunk_light_get_refcnt()) { - return thunk_light_br_ssl_engine_recvrec_ack(cc, len); - } else { - return br_ssl_engine_recvrec_ack(cc, len); - } + if (stack_thunk_light_get_refcnt()) { + return thunk_light_br_ssl_engine_recvrec_ack(cc, len); + } else { + return br_ssl_engine_recvrec_ack(cc, len); + } } unsigned char *min_br_ssl_engine_recvrec_buf(const br_ssl_engine_context *cc, size_t *len) { - if (stack_thunk_light_get_refcnt()) { - return thunk_light_br_ssl_engine_recvrec_buf(cc, len); - } else { - return br_ssl_engine_recvrec_buf(cc, len); - } + if (stack_thunk_light_get_refcnt()) { + return thunk_light_br_ssl_engine_recvrec_buf(cc, len); + } else { + return br_ssl_engine_recvrec_buf(cc, len); + } } void min_br_ssl_engine_sendapp_ack(br_ssl_engine_context *cc, size_t len) { - if (stack_thunk_light_get_refcnt()) { - return thunk_light_br_ssl_engine_sendapp_ack(cc, len); - } else { - return br_ssl_engine_sendapp_ack(cc, len); - } + if (stack_thunk_light_get_refcnt()) { + return thunk_light_br_ssl_engine_sendapp_ack(cc, len); + } else { + return br_ssl_engine_sendapp_ack(cc, len); + } } unsigned char *min_br_ssl_engine_sendapp_buf(const br_ssl_engine_context *cc, size_t *len) { - if (stack_thunk_light_get_refcnt()) { - return thunk_light_br_ssl_engine_sendapp_buf(cc, len); - } else { - return br_ssl_engine_sendapp_buf(cc, len); - } + if (stack_thunk_light_get_refcnt()) { + return thunk_light_br_ssl_engine_sendapp_buf(cc, len); + } else { + return br_ssl_engine_sendapp_buf(cc, len); + } } void min_br_ssl_engine_sendrec_ack(br_ssl_engine_context *cc, size_t len) { - if (stack_thunk_light_get_refcnt()) { - return thunk_light_br_ssl_engine_sendrec_ack(cc, len); - } else { - return br_ssl_engine_sendrec_ack(cc, len); - } + if (stack_thunk_light_get_refcnt()) { + return thunk_light_br_ssl_engine_sendrec_ack(cc, len); + } else { + return br_ssl_engine_sendrec_ack(cc, len); + } } unsigned char *min_br_ssl_engine_sendrec_buf(const br_ssl_engine_context *cc, size_t *len) { - if (stack_thunk_light_get_refcnt()) { - return thunk_light_br_ssl_engine_sendrec_buf(cc, len); - } else { - return br_ssl_engine_sendrec_buf(cc, len); - } + if (stack_thunk_light_get_refcnt()) { + return thunk_light_br_ssl_engine_sendrec_buf(cc, len); + } else { + return br_ssl_engine_sendrec_buf(cc, len); + } } // Use min_ instead of original thunk_ @@ -176,7 +176,7 @@ namespace BearSSL { void WiFiClientSecure_light::_clear() { // TLS handshake may take more than the 5 second default timeout - _timeout = 10000; // 10 seconds max, it should never go over 6 seconds + _timeout = 10000; // 10 seconds max, it should never go over 6 seconds _sc = nullptr; _ctx_present = false; @@ -185,17 +185,17 @@ void WiFiClientSecure_light::_clear() { _iobuf_out = nullptr; setBufferSizes(1024, 1024); // reasonable minimum _handshake_done = false; - _last_error = 0; + _last_error = 0; _recvapp_buf = nullptr; _recvapp_len = 0; - _fingerprint_any = true; // by default accept all fingerprints - _fingerprint1 = nullptr; - _fingerprint2 = nullptr; - _chain_P = nullptr; - _sk_ec_P = nullptr; - _ta_P = nullptr; + _fingerprint_any = true; // by default accept all fingerprints + _fingerprint1 = nullptr; + _fingerprint2 = nullptr; + _chain_P = nullptr; + _sk_ec_P = nullptr; + _ta_P = nullptr; _ta_size = 0; - _max_thunkstack_use = 0; + _max_thunkstack_use = 0; } // Constructor @@ -221,24 +221,24 @@ WiFiClientSecure_light::~WiFiClientSecure_light() { void WiFiClientSecure_light::allocateBuffers(void) { // We prefer to allocate all buffers at start, rather than lazy allocation and deallocation // in the long run it avoids heap fragmentation and improves stability - LOG_HEAP_SIZE("allocateBuffers before"); + LOG_HEAP_SIZE("allocateBuffers before"); _sc = std::make_shared(); - LOG_HEAP_SIZE("allocateBuffers ClientContext"); + LOG_HEAP_SIZE("allocateBuffers ClientContext"); _iobuf_in = std::shared_ptr(new unsigned char[_iobuf_in_size], std::default_delete()); _iobuf_out = std::shared_ptr(new unsigned char[_iobuf_out_size], std::default_delete()); - LOG_HEAP_SIZE("allocateBuffers after"); + LOG_HEAP_SIZE("allocateBuffers after"); } void WiFiClientSecure_light::setClientECCert(const br_x509_certificate *cert, const br_ec_private_key *sk, - unsigned allowed_usages, unsigned cert_issuer_key_type) { - _chain_P = cert; - _sk_ec_P = sk; + unsigned allowed_usages, unsigned cert_issuer_key_type) { + _chain_P = cert; + _sk_ec_P = sk; _allowed_usages = allowed_usages; _cert_issuer_key_type = cert_issuer_key_type; } void WiFiClientSecure_light::setTrustAnchor(const br_x509_trust_anchor *ta, size_t ta_size) { - _ta_P = ta; + _ta_P = ta; _ta_size = ta_size; } @@ -271,9 +271,9 @@ bool WiFiClientSecure_light::flush(unsigned int maxWaitMs) { int WiFiClientSecure_light::connect(IPAddress ip, uint16_t port) { DEBUG_BSSL("connect(%s,%d)", ip.toString().c_str(), port); - clearLastError(); + clearLastError(); if (!WiFiClient::connect(ip, port)) { - setLastError(ERR_TCP_CONNECT); + setLastError(ERR_TCP_CONNECT); return 0; } return _connectSSL(nullptr); @@ -282,19 +282,19 @@ int WiFiClientSecure_light::connect(IPAddress ip, uint16_t port) { int WiFiClientSecure_light::connect(const char* name, uint16_t port) { DEBUG_BSSL("connect(%s,%d)\n", name, port); IPAddress remote_addr; - clearLastError(); + clearLastError(); if (!WiFi.hostByName(name, remote_addr)) { DEBUG_BSSL("connect: Name loopup failure\n"); - setLastError(ERR_CANT_RESOLVE_IP); + setLastError(ERR_CANT_RESOLVE_IP); return 0; } DEBUG_BSSL("connect(%s,%d)\n", remote_addr.toString().c_str(), port); if (!WiFiClient::connect(remote_addr, port)) { DEBUG_BSSL("connect: Unable to connect TCP socket\n"); - _last_error = ERR_TCP_CONNECT; + _last_error = ERR_TCP_CONNECT; return 0; } - LOG_HEAP_SIZE("Before calling _connectSSL"); + LOG_HEAP_SIZE("Before calling _connectSSL"); return _connectSSL(name); } @@ -355,7 +355,7 @@ size_t WiFiClientSecure_light::_write(const uint8_t *buf, size_t size, bool pmem } } while (size); - LOG_HEAP_SIZE("_write"); + LOG_HEAP_SIZE("_write"); return sent_bytes; } @@ -399,7 +399,7 @@ int WiFiClientSecure_light::read(uint8_t *buf, size_t size) { int avail = available(); bool conn = connected(); if (!avail && conn) { - return 0; // We're still connected, but nothing to read + return 0; // We're still connected, but nothing to read } if (!avail && !conn) { DEBUG_BSSL("read: Not connected, none left available\n"); @@ -434,7 +434,7 @@ int WiFiClientSecure_light::read() { int WiFiClientSecure_light::available() { if (_recvapp_buf) { - return _recvapp_len; // Anything from last call? + return _recvapp_len; // Anything from last call? } _recvapp_buf = nullptr; _recvapp_len = 0; @@ -443,7 +443,7 @@ int WiFiClientSecure_light::available() { } int st = br_ssl_engine_current_state(_eng); if (st == BR_SSL_CLOSED) { - return 0; // Nothing leftover, SSL is closed + return 0; // Nothing leftover, SSL is closed } if (st & BR_SSL_RECVAPP) { _recvapp_buf = br_ssl_engine_recvapp_buf(_eng, &_recvapp_len); @@ -620,24 +620,24 @@ static uint8_t htoi (unsigned char c) extern "C" { - // see https://stackoverflow.com/questions/6357031/how-do-you-convert-a-byte-array-to-a-hexadecimal-string-in-c - void tohex(unsigned char * in, size_t insz, char * out, size_t outsz) { - unsigned char * pin = in; - static const char * hex = "0123456789ABCDEF"; - char * pout = out; - for(; pin < in+insz; pout +=3, pin++){ - pout[0] = hex[(*pin>>4) & 0xF]; - pout[1] = hex[ *pin & 0xF]; - pout[2] = ':'; - if (pout + 3 - out > outsz){ - /* Better to truncate output string than overflow buffer */ - /* it would be still better to either return a status */ - /* or ensure the target buffer is large enough and it never happen */ - break; - } - } - pout[-1] = 0; - } + // see https://stackoverflow.com/questions/6357031/how-do-you-convert-a-byte-array-to-a-hexadecimal-string-in-c + void tohex(unsigned char * in, size_t insz, char * out, size_t outsz) { + unsigned char * pin = in; + static const char * hex = "0123456789ABCDEF"; + char * pout = out; + for(; pin < in+insz; pout +=3, pin++){ + pout[0] = hex[(*pin>>4) & 0xF]; + pout[1] = hex[ *pin & 0xF]; + pout[2] = ':'; + if (pout + 3 - out > outsz){ + /* Better to truncate output string than overflow buffer */ + /* it would be still better to either return a status */ + /* or ensure the target buffer is large enough and it never happen */ + break; + } + } + pout[-1] = 0; + } // BearSSL doesn't define a true insecure decoder, so we make one ourselves @@ -648,12 +648,12 @@ extern "C" { // Private x509 decoder state struct br_x509_pubkeyfingerprint_context { const br_x509_class *vtable; - bool done_cert; // did we parse the first cert already? - bool fingerprint_all; - uint8_t *pubkey_recv_fingerprint; + bool done_cert; // did we parse the first cert already? + bool fingerprint_all; + uint8_t *pubkey_recv_fingerprint; const uint8_t *fingerprint1; const uint8_t *fingerprint2; - unsigned usages; // pubkey usage + unsigned usages; // pubkey usage br_x509_decoder_context ctx; // defined in BearSSL }; @@ -662,15 +662,15 @@ extern "C" { br_x509_pubkeyfingerprint_context *xc = (br_x509_pubkeyfingerprint_context *)ctx; // Don't process anything but the first certificate in the chain if (!xc->done_cert) { - br_x509_decoder_init(&xc->ctx, nullptr, nullptr, nullptr, nullptr); - } - (void)server_name; // ignore server name + br_x509_decoder_init(&xc->ctx, nullptr, nullptr, nullptr, nullptr); + } + (void)server_name; // ignore server name } // Callback for each certificate present in the chain (but only operates // on the first one by design). static void pubkeyfingerprint_start_cert(const br_x509_class **ctx, uint32_t length) { - (void) ctx; // do nothing + (void) ctx; // do nothing (void) length; } @@ -686,7 +686,7 @@ extern "C" { // Callback on individual cert end. static void pubkeyfingerprint_end_cert(const br_x509_class **ctx) { br_x509_pubkeyfingerprint_context *xc = (br_x509_pubkeyfingerprint_context *)ctx; - xc->done_cert = true; // first cert already processed + xc->done_cert = true; // first cert already processed } // **** Start patch Castellucci @@ -743,18 +743,18 @@ extern "C" { pubkeyfingerprint_pubkey_fingerprint(&sha1_context, xc->ctx.pkey.key.rsa); br_sha1_out(&sha1_context, xc->pubkey_recv_fingerprint); // copy to fingerprint - if (!xc->fingerprint_all) { - if (0 == memcmp_P(xc->pubkey_recv_fingerprint, xc->fingerprint1, 20)) { - return 0; - } - if (0 == memcmp_P(xc->pubkey_recv_fingerprint, xc->fingerprint2, 20)) { - return 0; - } - return 1; // no match, error - } else { - // Default (no validation at all) or no errors in prior checks = success. - return 0; - } + if (!xc->fingerprint_all) { + if (0 == memcmp_P(xc->pubkey_recv_fingerprint, xc->fingerprint1, 20)) { + return 0; + } + if (0 == memcmp_P(xc->pubkey_recv_fingerprint, xc->fingerprint2, 20)) { + return 0; + } + return 1; // no match, error + } else { + // Default (no validation at all) or no errors in prior checks = success. + return 0; + } */ // set fingerprint status byte to zero // FIXME: find a better way to pass this information @@ -796,7 +796,7 @@ extern "C" { xc->pubkey_recv_fingerprint[20] |= 2; // mark for update } if (!xc->pubkey_recv_fingerprint[20]) { - return 1; // not marked for update because no match, error + return 1; // not marked for update because no match, error } // the old fingerprint format matched, recompute new one for update @@ -822,9 +822,9 @@ extern "C" { // Set up the x509 insecure data structures for BearSSL core to use. void br_x509_pubkeyfingerprint_init(br_x509_pubkeyfingerprint_context *ctx, - const uint8_t *fingerprint1, const uint8_t *fingerprint2, - uint8_t *recv_fingerprint, - bool fingerprint_all) { + const uint8_t *fingerprint1, const uint8_t *fingerprint2, + uint8_t *recv_fingerprint, + bool fingerprint_all) { static const br_x509_class br_x509_pubkeyfingerprint_vtable PROGMEM = { sizeof(br_x509_pubkeyfingerprint_context), pubkeyfingerprint_start_chain, @@ -838,26 +838,26 @@ extern "C" { memset(ctx, 0, sizeof * ctx); ctx->vtable = &br_x509_pubkeyfingerprint_vtable; ctx->done_cert = false; - ctx->fingerprint1 = fingerprint1; - ctx->fingerprint2 = fingerprint2; - ctx->pubkey_recv_fingerprint = recv_fingerprint; - ctx->fingerprint_all = fingerprint_all; + ctx->fingerprint1 = fingerprint1; + ctx->fingerprint2 = fingerprint2; + ctx->pubkey_recv_fingerprint = recv_fingerprint; + ctx->fingerprint_all = fingerprint_all; } - // We limit to a single cipher to reduce footprint + // We limit to a single cipher to reduce footprint // we reference it, don't put in PROGMEM static const uint16_t suites[] = { #ifdef USE_MQTT_TLS_FORCE_EC_CIPHER - BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 #else - BR_TLS_RSA_WITH_AES_128_GCM_SHA256 + BR_TLS_RSA_WITH_AES_128_GCM_SHA256 #endif }; // Default initializion for our SSL clients static void br_ssl_client_base_init(br_ssl_client_context *cc) { br_ssl_client_zero(cc); - // forbid SSL renegociation, as we free the Private Key after handshake + // forbid SSL renegotiation, as we free the Private Key after handshake br_ssl_engine_add_flags(&cc->eng, BR_OPT_NO_RENEGOTIATION); br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12); @@ -869,14 +869,14 @@ extern "C" { br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable); br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); - // AES CTR/GCM small version, not contstant time (we don't really care here as there is no TPM anyways) - br_ssl_engine_set_gcm(&cc->eng, &br_sslrec_in_gcm_vtable, &br_sslrec_out_gcm_vtable); - br_ssl_engine_set_aes_ctr(&cc->eng, &br_aes_small_ctr_vtable); - br_ssl_engine_set_ghash(&cc->eng, &br_ghash_ctmul32); + // AES CTR/GCM small version, not contstant time (we don't really care here as there is no TPM anyways) + br_ssl_engine_set_gcm(&cc->eng, &br_sslrec_in_gcm_vtable, &br_sslrec_out_gcm_vtable); + br_ssl_engine_set_aes_ctr(&cc->eng, &br_aes_small_ctr_vtable); + br_ssl_engine_set_ghash(&cc->eng, &br_ghash_ctmul32); #ifdef USE_MQTT_TLS_FORCE_EC_CIPHER - // we support only P256 EC curve for AWS IoT, no EC curve for Letsencrypt unless forced - br_ssl_engine_set_ec(&cc->eng, &br_ec_p256_m15); // TODO + // we support only P256 EC curve for AWS IoT, no EC curve for Letsencrypt unless forced + br_ssl_engine_set_ec(&cc->eng, &br_ec_p256_m15); // TODO #endif static const char * alpn_mqtt = "mqtt"; br_ssl_engine_set_protocol_names(&cc->eng, &alpn_mqtt, 1); @@ -886,110 +886,110 @@ extern "C" { // Called by connect() to do the actual SSL setup and handshake. // Returns if the SSL handshake succeeded. bool WiFiClientSecure_light::_connectSSL(const char* hostName) { - // Validation context, either full CA validation or checking only fingerprints + // Validation context, either full CA validation or checking only fingerprints #ifdef USE_MQTT_TLS_CA_CERT - br_x509_minimal_context *x509_minimal; + br_x509_minimal_context *x509_minimal; #else br_x509_pubkeyfingerprint_context *x509_insecure; #endif - LOG_HEAP_SIZE("_connectSSL.start"); + LOG_HEAP_SIZE("_connectSSL.start"); - do { // used to exit on Out of Memory error and keep all cleanup code at the same place - // ============================================================ - // allocate Thunk stack, move to alternate stack and initialize - stack_thunk_light_add_ref(); - LOG_HEAP_SIZE("Thunk allocated"); - DEBUG_BSSL("_connectSSL: start connection\n"); - _freeSSL(); - clearLastError(); - if (!stack_thunk_light_get_stack_bot()) break; + do { // used to exit on Out of Memory error and keep all cleanup code at the same place + // ============================================================ + // allocate Thunk stack, move to alternate stack and initialize + stack_thunk_light_add_ref(); + LOG_HEAP_SIZE("Thunk allocated"); + DEBUG_BSSL("_connectSSL: start connection\n"); + _freeSSL(); + clearLastError(); + if (!stack_thunk_light_get_stack_bot()) break; - _ctx_present = true; - _eng = &_sc->eng; // Allocation/deallocation taken care of by the _sc shared_ptr + _ctx_present = true; + _eng = &_sc->eng; // Allocation/deallocation taken care of by the _sc shared_ptr - br_ssl_client_base_init(_sc.get()); + br_ssl_client_base_init(_sc.get()); - // ============================================================ - // Allocatte and initialize Decoder Context - LOG_HEAP_SIZE("_connectSSL before DecoderContext allocation"); - // Only failure possible in the installation is OOM - #ifdef USE_MQTT_TLS_CA_CERT - x509_minimal = (br_x509_minimal_context*) malloc(sizeof(br_x509_minimal_context)); - if (!x509_minimal) break; - br_x509_minimal_init(x509_minimal, &br_sha256_vtable, _ta_P, _ta_size); - br_x509_minimal_set_rsa(x509_minimal, br_ssl_engine_get_rsavrfy(_eng)); - br_x509_minimal_set_hash(x509_minimal, br_sha256_ID, &br_sha256_vtable); - br_ssl_engine_set_x509(_eng, &x509_minimal->vtable); + // ============================================================ + // Allocatte and initialize Decoder Context + LOG_HEAP_SIZE("_connectSSL before DecoderContext allocation"); + // Only failure possible in the installation is OOM + #ifdef USE_MQTT_TLS_CA_CERT + x509_minimal = (br_x509_minimal_context*) malloc(sizeof(br_x509_minimal_context)); + if (!x509_minimal) break; + br_x509_minimal_init(x509_minimal, &br_sha256_vtable, _ta_P, _ta_size); + br_x509_minimal_set_rsa(x509_minimal, br_ssl_engine_get_rsavrfy(_eng)); + br_x509_minimal_set_hash(x509_minimal, br_sha256_ID, &br_sha256_vtable); + br_ssl_engine_set_x509(_eng, &x509_minimal->vtable); uint32_t now = UtcTime(); uint32_t cfg_time = CfgTime(); if (cfg_time > now) { now = cfg_time; } br_x509_minimal_set_time(x509_minimal, now / 86400 + 719528, now % 86400); - #else - x509_insecure = (br_x509_pubkeyfingerprint_context*) malloc(sizeof(br_x509_pubkeyfingerprint_context)); - //x509_insecure = std::unique_ptr(new br_x509_pubkeyfingerprint_context); - if (!x509_insecure) break; - br_x509_pubkeyfingerprint_init(x509_insecure, _fingerprint1, _fingerprint2, _recv_fingerprint, _fingerprint_any); - br_ssl_engine_set_x509(_eng, &x509_insecure->vtable); - #endif - LOG_HEAP_SIZE("_connectSSL after DecoderContext allocation"); + #else + x509_insecure = (br_x509_pubkeyfingerprint_context*) malloc(sizeof(br_x509_pubkeyfingerprint_context)); + //x509_insecure = std::unique_ptr(new br_x509_pubkeyfingerprint_context); + if (!x509_insecure) break; + br_x509_pubkeyfingerprint_init(x509_insecure, _fingerprint1, _fingerprint2, _recv_fingerprint, _fingerprint_any); + br_ssl_engine_set_x509(_eng, &x509_insecure->vtable); + #endif + LOG_HEAP_SIZE("_connectSSL after DecoderContext allocation"); - // ============================================================ - // Set send/receive buffers - br_ssl_engine_set_buffers_bidi(_eng, _iobuf_in.get(), _iobuf_in_size, _iobuf_out.get(), _iobuf_out_size); + // ============================================================ + // Set send/receive buffers + br_ssl_engine_set_buffers_bidi(_eng, _iobuf_in.get(), _iobuf_in_size, _iobuf_out.get(), _iobuf_out_size); - // ============================================================ - // allocate Private key if needed, only if USE_MQTT_AWS_IOT - LOG_HEAP_SIZE("_connectSSL before PrivKey allocation"); - #ifdef USE_MQTT_AWS_IOT - // ============================================================ - // Set the EC Private Key, only USE_MQTT_AWS_IOT - // limited to P256 curve - br_ssl_client_set_single_ec(_sc.get(), _chain_P, 1, - _sk_ec_P, _allowed_usages, - _cert_issuer_key_type, &br_ec_p256_m15, br_ecdsa_sign_asn1_get_default()); - #endif // USE_MQTT_AWS_IOT + // ============================================================ + // allocate Private key if needed, only if USE_MQTT_AWS_IOT + LOG_HEAP_SIZE("_connectSSL before PrivKey allocation"); + #ifdef USE_MQTT_AWS_IOT + // ============================================================ + // Set the EC Private Key, only USE_MQTT_AWS_IOT + // limited to P256 curve + br_ssl_client_set_single_ec(_sc.get(), _chain_P, 1, + _sk_ec_P, _allowed_usages, + _cert_issuer_key_type, &br_ec_p256_m15, br_ecdsa_sign_asn1_get_default()); + #endif // USE_MQTT_AWS_IOT - // ============================================================ - // Start TLS connection, ALL - if (!br_ssl_client_reset(_sc.get(), hostName, 0)) break; + // ============================================================ + // Start TLS connection, ALL + if (!br_ssl_client_reset(_sc.get(), hostName, 0)) break; - auto ret = _wait_for_handshake(); - #ifdef DEBUG_ESP_SSL - if (!ret) { - DEBUG_BSSL("Couldn't connect. Error = %d\n", getLastError()); - } else { - DEBUG_BSSL("Connected! MFLNStatus = %d\n", getMFLNStatus()); - } - #endif - LOG_HEAP_SIZE("_connectSSL.end"); - _max_thunkstack_use = stack_thunk_light_get_max_usage(); - stack_thunk_light_del_ref(); - //stack_thunk_light_repaint(); - LOG_HEAP_SIZE("_connectSSL.end, freeing StackThunk"); + auto ret = _wait_for_handshake(); + #ifdef DEBUG_ESP_SSL + if (!ret) { + DEBUG_BSSL("Couldn't connect. Error = %d\n", getLastError()); + } else { + DEBUG_BSSL("Connected! MFLNStatus = %d\n", getMFLNStatus()); + } + #endif + LOG_HEAP_SIZE("_connectSSL.end"); + _max_thunkstack_use = stack_thunk_light_get_max_usage(); + stack_thunk_light_del_ref(); + //stack_thunk_light_repaint(); + LOG_HEAP_SIZE("_connectSSL.end, freeing StackThunk"); - #ifdef USE_MQTT_TLS_CA_CERT - free(x509_minimal); - #else - free(x509_insecure); - #endif - LOG_HEAP_SIZE("_connectSSL after release of Priv Key"); - return ret; - } while (0); + #ifdef USE_MQTT_TLS_CA_CERT + free(x509_minimal); + #else + free(x509_insecure); + #endif + LOG_HEAP_SIZE("_connectSSL after release of Priv Key"); + return ret; + } while (0); - // ============================================================ - // if we arrived here, this means we had an OOM error, cleaning up - setLastError(ERR_OOM); - DEBUG_BSSL("_connectSSL: Out of memory\n"); - stack_thunk_light_del_ref(); + // ============================================================ + // if we arrived here, this means we had an OOM error, cleaning up + setLastError(ERR_OOM); + DEBUG_BSSL("_connectSSL: Out of memory\n"); + stack_thunk_light_del_ref(); #ifdef USE_MQTT_TLS_CA_CERT - free(x509_minimal); + free(x509_minimal); #else - free(x509_insecure); + free(x509_insecure); #endif - LOG_HEAP_SIZE("_connectSSL clean_on_error"); - return false; + LOG_HEAP_SIZE("_connectSSL clean_on_error"); + return false; } }; diff --git a/tasmota/WiFiClientSecureLightBearSSL.h b/tasmota/WiFiClientSecureLightBearSSL.h index ed6ced416..f480a9d42 100755 --- a/tasmota/WiFiClientSecureLightBearSSL.h +++ b/tasmota/WiFiClientSecureLightBearSSL.h @@ -3,7 +3,7 @@ - Mostly compatible with Arduino WiFi shield library and standard WiFiClient/ServerSecure (except for certificate handling). - Copyright (c) 2018 Earle F. Philhower, III + Copyright (C) 2021 Earle F. Philhower, III This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public diff --git a/tasmota/html_compressed/HTTP_HEADER1_ES6.h b/tasmota/html_compressed/HTTP_HEADER1_ES6.h new file mode 100644 index 000000000..d95dc2499 --- /dev/null +++ b/tasmota/html_compressed/HTTP_HEADER1_ES6.h @@ -0,0 +1,22 @@ +///////////////////////////////////////////////////////////////////// +// compressed by tools/unishox/compress-html-uncompressed.py +///////////////////////////////////////////////////////////////////// + +const size_t HTTP_HEADER1_SIZE = 371; +const char HTTP_HEADER1_COMPRESSED[] PROGMEM = "\x3D\x0F\xE1\x10\x98\x1D\x19\x0C\x64\x85\x50\xD0\x8F\xC3\xD0\x55\x0D\x09\x05\x7C" + "\x3C\x7C\x3D\x87\xD7\x8F\x62\x0C\x2B\xF7\x8F\x87\xB0\xF6\x1F\x87\xA0\xA7\x62\x1F" + "\x87\xA0\xD7\x56\x83\x15\x7F\xF3\xA3\xE1\xF6\x2E\x8C\x1D\x67\x3E\x7D\x90\x21\x52" + "\xEB\x1A\xCF\x87\xB0\xCF\x58\xF8\xCC\xFD\x1E\xC4\x1E\x75\x3E\xA3\xE1\xEC\x1F\xD1" + "\x28\x51\xF0\x46\x67\xA1\xB3\xAC\x7F\x44\xA1\x47\x56\xF6\xD6\xD8\x47\x5F\x83\xB0" + "\x99\xF0\xE4\x3A\x88\x5F\x9F\xCE\xBF\x07\x61\x58\xE0\x99\xF3\xB0\xF6\x1D\x87\xE1" + "\xE9\x5B\x41\x33\xF0\xFA\xF2\x3A\xD1\xF5\xE3\xD0\xEC\x04\x19\x67\xA7\x83\xFE\x8C" + "\xA3\xF0\xCE\xFE\x8D\x87\xCE\x16\x10\x47\x50\x54\x75\x56\x1D\x54\x30\xEA\x18\x19" + "\xF0\xFB\x3E\xCF\x0C\x71\xF3\xC7\xC3\xF0\x4C\x0C\x58\xD7\xD4\x74\x1E\x74\x4C\x26" + "\x35\xF5\x10\xE3\x22\xD1\x0E\xEF\x8E\xF1\xE0\xD5\xE0\x48\xBA\x6A\x16\xFE\x64\x5E" + "\x61\x30\xEB\x3E\x77\x7C\x77\x8F\x1E\x18\x7C\xD3\xE1\xF8\xC7\x1D\xDD\x3B\xC7\x4A" + "\x32\x18\xCF\x87\x74\x11\xA4\x1F\x0F\x87\xDD\x33\x65\x1F\x67\x68\xFB\x19\x7E\xF0" + "\xFE\x7C\x43\xEC\xF3\x04\x19\xC7\x78\xF0\x3E\x11\xF0\xC1\xF0\xFC\x1F\xDE\x13\x07" + "\xCE\x96\x20\x84\xCC\xDF\x51\x05\xBE\xA7\xCF\xE7\x74\xFB\x0B\x2C\x43\xEC\xEA\x30" + "\x77\x8F\x06"; + +#define HTTP_HEADER1 Decompress(HTTP_HEADER1_COMPRESSED,HTTP_HEADER1_SIZE).c_str() \ No newline at end of file diff --git a/tasmota/html_compressed/HTTP_HEADER1_NOES6.h b/tasmota/html_compressed/HTTP_HEADER1_NOES6.h new file mode 100644 index 000000000..fae966b15 --- /dev/null +++ b/tasmota/html_compressed/HTTP_HEADER1_NOES6.h @@ -0,0 +1,22 @@ +///////////////////////////////////////////////////////////////////// +// compressed by tools/unishox/compress-html-uncompressed.py +///////////////////////////////////////////////////////////////////// + +const size_t HTTP_HEADER1_SIZE = 425; +const char HTTP_HEADER1_COMPRESSED[] PROGMEM = "\x3D\x0F\xE1\x10\x98\x1D\x19\x0C\x64\x85\x50\xD0\x8F\xC3\xD0\x55\x0D\x09\x05\x7C" + "\x3C\x7C\x3D\x87\xD7\x8F\x62\x0C\x2B\xF7\x8F\x87\xB0\xF6\x1F\x87\xA0\xA7\x62\x1F" + "\x87\xA0\xD7\x56\x83\x15\x7F\xF3\xA3\xE1\xF6\x2E\x8C\x1D\x67\x3E\x7D\x90\x21\x52" + "\xEB\x1A\xCF\x87\xB0\xCF\x58\xF8\xCC\xFD\x1E\xC4\x1E\x75\x3E\xA3\xE1\xEC\x1F\xD1" + "\x28\x51\xF0\x46\x67\xA1\xB3\xAC\x7F\x44\xA1\x47\x56\xF6\xD6\xD8\x47\x5F\x83\xB0" + "\x99\xF0\xE4\x3A\x88\x5F\x9F\xCE\xBF\x07\x61\x58\xE0\x99\xF3\xB0\xF6\x1D\x87\xE1" + "\xE9\x5B\x41\x33\xF0\xFA\xF2\x3A\xD1\xF5\xE3\xD0\xEC\x04\x19\x67\xA7\x83\xFE\x8C" + "\xA3\xF0\xCE\xFE\x8D\x87\xCE\x16\x10\x47\x50\x54\x75\x56\x1D\x54\x30\xEA\x18\x19" + "\xF0\xFB\x3E\xCF\x06\x05\xF0\x75\xB9\xC9\x8E\x3B\xBE\x3B\xC7\xB7\xEE\x85\xFF\x90" + "\x98\x18\xB1\xAF\xA8\xE8\x3C\xE8\x98\x4C\x6B\xEA\x21\xC6\x45\xA2\x1D\xDF\x1D\xE3" + "\xC1\xEE\x04\x4C\x38\xD5\xE0\x4F\xC3\x8D\x42\xDF\xCC\x8B\xCC\x26\x1D\x67\xC1\x27" + "\x0D\xF0\xC3\xBB\xA7\x78\xF6\xB1\xC7\x77\x4E\xF1\xD2\x8C\x86\x33\xE1\xDD\x04\x69" + "\x07\xC3\xE1\xF7\x4C\xD9\x47\xD9\xDA\x3E\xC6\x5F\xBC\x3F\x9F\x10\xFB\x3C\xC1\x06" + "\x70\x23\xE3\xE3\xE1\x1D\xD3\x07\x78\xF6\x8F\xEF\x09\x83\xE7\x4B\x10\x42\x66\x6F" + "\xA8\x82\xDF\x53\xE7\xF3\xBA\x7D\x85\x96\x21\xF6\x75\x18\x3B\xC7\x83\xDC"; + +#define HTTP_HEADER1 Decompress(HTTP_HEADER1_COMPRESSED,HTTP_HEADER1_SIZE).c_str() \ No newline at end of file diff --git a/tasmota/html_compressed/HTTP_HEAD_LAST_SCRIPT.h b/tasmota/html_compressed/HTTP_HEAD_LAST_SCRIPT.h new file mode 100644 index 000000000..feaa2ee1e --- /dev/null +++ b/tasmota/html_compressed/HTTP_HEAD_LAST_SCRIPT.h @@ -0,0 +1,16 @@ +///////////////////////////////////////////////////////////////////// +// compressed by tools/unishox/compress-html-uncompressed.py +///////////////////////////////////////////////////////////////////// + +const size_t HTTP_HEAD_LAST_SCRIPT_SIZE = 226; +const char HTTP_HEAD_LAST_SCRIPT_COMPRESSED[] PROGMEM = "\x30\x2F\x83\xAD\xCE\x46\xB1\x0E\xE9\xDE\x3D\xA6\x77\xF5\x47\xC3\x8C\xEA\x2D\x3E" + "\x09\x81\x8B\x1A\xFA\x8E\x86\xA1\x6F\xE6\x45\xE6\x13\x0E\xB3\xE5\x61\x04\x77\x4F" + "\xBD\xE1\x82\xE8\xEA\x1C\x2E\xAB\x38\xEA\xA6\x6C\xAB\xFB\xB3\xAB\xCC\x26\x1D\x1F" + "\x67\x78\xF0\x3E\x2B\x42\x67\x77\x4E\x81\x3E\x1E\xA1\x47\xE1\xF2\x8E\xF1\xED\xD3" + "\x07\x77\x4F\x7A\x8F\x7C\xEF\x1E\xDD\x3D\xEA\x3D\xF3\xDE\x3E\xFA\xC6\xB3\xEC\xF7" + "\xCF\x87\x77\x4F\x7A\x8F\x7C\xE8\x2A\x2B\xFC\x57\x55\xFD\x1C\x2E\x99\xDD\x3E\xF4" + "\x43\xEC\xEF\x1F\xA3\xF4\x77\x4F\xE0\x27\x57\xEB\x1A\xCF\xB3\xBC\x77\x8E\xF1\xDA" + "\x04\x1C\x87\x44\x3E\xCF\x7C\xF3\x04\x7C\xB0\xF0\x7B\xA8\xED\x9D\xB3\xC1\xEE\x3D" + "\xC3\xE1\x1D\xD3\x58\x87\x78\xF0\x7A\x1D\x9E\x0F\xFA\x32\x8F\xC3"; + +#define HTTP_HEAD_LAST_SCRIPT Decompress(HTTP_HEAD_LAST_SCRIPT_COMPRESSED,HTTP_HEAD_LAST_SCRIPT_SIZE).c_str() \ No newline at end of file diff --git a/tasmota/html_compressed/HTTP_HEAD_STYLE1.h b/tasmota/html_compressed/HTTP_HEAD_STYLE1.h new file mode 100644 index 000000000..52440cd82 --- /dev/null +++ b/tasmota/html_compressed/HTTP_HEAD_STYLE1.h @@ -0,0 +1,24 @@ +///////////////////////////////////////////////////////////////////// +// compressed by tools/unishox/compress-html-uncompressed.py +///////////////////////////////////////////////////////////////////// + +const size_t HTTP_HEAD_STYLE1_SIZE = 591; +const char HTTP_HEAD_STYLE1_COMPRESSED[] PROGMEM = "\x3D\x3D\x46\x41\x33\xF0\x4D\x33\x3A\x8C\x6B\x08\x4F\x3A\x3A\xB7\x86\x0B\xA3\xAB" + "\xCC\x26\x1D\x1E\xD1\x96\x20\x9B\xC3\xC7\x99\xCD\x21\x86\xC3\xC1\x8C\xEA\x3A\xFD" + "\xA6\xD6\x79\x9C\x84\xC6\x9E\x0F\x70\x21\xE1\xA7\xB4\x75\x86\x68\x3D\xFC\x17\xC2" + "\x1E\x67\x91\xF4\x71\xF1\x1B\x0F\x07\xB8\x61\xED\x1B\x7F\x1E\xDE\x3C\xCE\x33\xA6" + "\x93\x1A\x8E\x33\xC1\xEE\x2D\xE1\x82\xE8\xF6\x8F\xE8\x94\x28\xF3\x39\x1B\x3E\x8F" + "\xA3\xC1\x0E\xC3\x61\xD7\xED\x36\xEF\x0F\x1E\x63\xB3\xE2\x3F\x9D\x63\xB0\xD8\x78" + "\x3A\xC7\xD8\xE3\x4D\xA3\xAC\x14\xAD\x0D\xC3\x68\x29\x57\x04\xCD\x84\x3C\x0B\x3E" + "\x08\x7B\x6E\xF0\xC1\x74\x7B\xD4\x64\x31\x9F\x03\x14\xC3\x34\x1D\x86\xC3\xDF\x04" + "\x1E\x11\x41\x06\x8F\xEC\x4D\xC3\xDF\x04\x3D\xF1\x8D\x3C\x02\x0F\x03\x87\x5F\xF4" + "\x78\x55\x1E\x67\x38\x86\x1B\x0F\x06\x6F\xF5\xA1\xD8\x47\x5D\x85\xA3\xDC\x79\x9D" + "\x67\x21\x0C\x04\x9C\xCF\xF7\xC3\xCC\x10\xF1\xE3\x89\x1F\x47\xD1\xE0\xF7\x10\x21" + "\x71\x3E\x09\x1C\x28\x82\xC7\x2A\x01\x54\xCD\x95\x7F\x76\x7B\x7E\xFD\xA6\xD6\x79" + "\x82\x1E\xA0\x78\x04\x2C\xC8\xE7\xCF\xA3\xE8\xF0\x42\x9E\x8F\x0A\xA3\xCC\xE5\xCF" + "\x90\xC3\x61\xE0\x11\xF8\xFA\xC3\x37\xF3\x01\x60\xF9\xE7\x62\xEB\x01\x6B\x45\x1D" + "\x82\x19\x1E\xDA\x66\xCA\x04\x2E\x0A\x83\x7D\x4F\xE0\x83\xC9\xE9\x8B\x1B\xA1\x19" + "\x1E\x66\x6F\xE2\x5F\x59\xD5\xEB\xEF\x1D\x7E\x7F\xD3\x2A\x01\x9B\x98\x1E\xEA\x10" + "\x11\x39\x7D\x38\xC8\x61\xB0\xF0\x7B\x8D"; + +#define HTTP_HEAD_STYLE1 Decompress(HTTP_HEAD_STYLE1_COMPRESSED,HTTP_HEAD_STYLE1_SIZE).c_str() \ No newline at end of file diff --git a/tasmota/html_compressed/HTTP_HEAD_STYLE2.h b/tasmota/html_compressed/HTTP_HEAD_STYLE2.h new file mode 100644 index 000000000..4c1da5898 --- /dev/null +++ b/tasmota/html_compressed/HTTP_HEAD_STYLE2.h @@ -0,0 +1,20 @@ +///////////////////////////////////////////////////////////////////// +// compressed by tools/unishox/compress-html-uncompressed.py +///////////////////////////////////////////////////////////////////// + +const size_t HTTP_HEAD_STYLE2_SIZE = 478; +const char HTTP_HEAD_STYLE2_COMPRESSED[] PROGMEM = "\x1C\x2E\xAB\x38\xF6\x8E\xCF\x88\xFE\x79\x9C\x67\x82\x04\x18\xA7\x5F\xEC\x4D\x17" + "\xE3\xCC\xE3\x3A\x59\x7D\x8D\x3C\x0E\xB0\xCD\x07\xBF\x82\xF8\x43\xCC\xF2\x3E\x8E" + "\x3E\x23\x61\xE0\x3C\x0B\x3E\x08\x52\x02\xDE\x67\x58\xA7\xA3\xC2\xA8\xF3\x39\x47" + "\x4C\x2F\xB1\xA7\x83\x19\xD4\x75\xFB\x4D\xAC\xF3\x39\x0E\x94\x5F\x63\x4F\x03\xFA" + "\x25\x0A\x3C\xCE\x46\xCF\xA3\xE8\xF0\x75\x90\xFB\x1C\x69\xB4\x75\xD7\xEF\xBD\xB5" + "\xB9\xC7\x58\x82\xFF\x75\xB9\xC7\x99\xC6\x74\xC2\xF1\xE0\x15\x2A\x2B\x86\x2F\xFE" + "\xCF\x9E\x63\x33\x7A\x9F\xCF\x07\xB8\x10\x78\x18\x3C\xC5\x61\x9B\xF9\xED\x04\xCE" + "\x2A\x01\x0F\x71\xD0\x77\xD8\x80\xA7\x50\x15\xB1\x21\xEF\xF0\x29\xD4\x05\x4C\x4A" + "\xCF\x68\x23\xF0\xDF\x4C\xD9\x47\x58\x8C\x3C\x04\x2E\x06\xBB\x39\x9E\x0F\x71\xD0" + "\x61\xED\x30\x16\x5D\x1E\x61\x33\x14\x08\x38\x05\x85\xA3\xDC\x08\x33\x0F\x71\xD0" + "\xD4\x08\x56\xFF\xA3\xC2\x81\x22\xE0\x20\xCD\x3D\xC7\x4F\x82\x17\x20\x60\x8D\xC7" + "\xD3\x1A\x78\x19\x62\x09\xBC\x3C\x79\x9C\xA2\x18\x6C\x3C\x0D\xBF\x8F\x6F\x1E\x67" + "\x38\x86\x1B\x11\xCA\x21\x86\xC3\xC1\xEE"; + +#define HTTP_HEAD_STYLE2 Decompress(HTTP_HEAD_STYLE2_COMPRESSED,HTTP_HEAD_STYLE2_SIZE).c_str() \ No newline at end of file diff --git a/tasmota/html_compressed/HTTP_HEAD_STYLE_ZIGBEE.h b/tasmota/html_compressed/HTTP_HEAD_STYLE_ZIGBEE.h new file mode 100644 index 000000000..29269d0d0 --- /dev/null +++ b/tasmota/html_compressed/HTTP_HEAD_STYLE_ZIGBEE.h @@ -0,0 +1,19 @@ +///////////////////////////////////////////////////////////////////// +// compressed by tools/unishox/compress-html-uncompressed.py +///////////////////////////////////////////////////////////////////// + +const size_t HTTP_HEAD_STYLE_ZIGBEE_SIZE = 363; +const char HTTP_HEAD_STYLE_ZIGBEE_COMPRESSED[] PROGMEM = "\x3A\x0E\xA3\xDA\x3B\x0D\x87\x5F\xB4\xDB\xBC\x3C\x79\x8E\xCF\x88\xFE\x75\x8E\xC3" + "\x61\xE0\x66\x7B\x6B\x73\x8F\x3F\xB0\xAE\xB4\xCD\x9E\x04\xDF\x0C\x0A\xCC\x8F\x3D" + "\xE0\xB7\x99\xD6\x38\x2C\x0C\xD0\xF0\x3F\xA2\x50\xA3\xCC\xE5\x32\x18\x6C\x3C\x0A" + "\x7A\x3C\x2A\x2B\x8F\x33\x92\x88\x61\xB0\xF0\x08\x39\x29\xE6\x72\x88\x61\xB1\x7B" + "\x02\xD1\x01\x0A\x69\xD7\xFB\x13\x45\xF8\xF3\x39\x64\x30\xD8\x78\x1B\x7F\x1E\xDE" + "\x3A\xC2\x66\x28\xF3\x3A\xCE\x59\x0C\x36\x1E\xE3\xA0\xEA\x3C\xCF\x3B\x31\x4F\xE7" + "\x51\xD0\x75\x1E\x67\x98\xE6\x63\x3E\xCF\x68\x79\xD4\xFA\x8F\x33\xD8\x7B\x01\x13" + "\x5E\x04\x1D\x5C\x16\xB8\x14\xB1\xDE\xC0\x85\xD3\x04\x3D\xD0\xE7\x10\xC3\x61\xE0" + "\x75\x86\x68\x3D\xFC\x17\xC2\x1E\x61\x8B\xFF\xDF\x51\x07\x81\x67\xCF\x15\x83\x0F" + "\x33\x90\x81\x0F\x5F\x04\x2D\x53\xFA\x3C\x2A\x2B\x8F\x33\xAC\xE6\x10\x22\x70\x54" + "\x08\xFC\x0C\x82\x0F\x0A\x67\x30\x81\x23\x81\x23\xDA\x08\x34\x4C\xEF\xE7\x74\xEB" + "\x3A\xC7\x04\x75\x1C\x98\x43\x0D\x87\x78\xF0\x13\x31\x47\x99\xC8\x43\x0D\x87\xB8"; + +#define HTTP_HEAD_STYLE_ZIGBEE Decompress(HTTP_HEAD_STYLE_ZIGBEE_COMPRESSED,HTTP_HEAD_STYLE_ZIGBEE_SIZE).c_str() \ No newline at end of file diff --git a/tasmota/html_compressed/HTTP_SCRIPT_CONSOL.h b/tasmota/html_compressed/HTTP_SCRIPT_CONSOL.h new file mode 100644 index 000000000..ba7f0677d --- /dev/null +++ b/tasmota/html_compressed/HTTP_SCRIPT_CONSOL.h @@ -0,0 +1,40 @@ +///////////////////////////////////////////////////////////////////// +// compressed by tools/unishox/compress-html-uncompressed.py +///////////////////////////////////////////////////////////////////// + +const size_t HTTP_SCRIPT_CONSOL_SIZE = 911; +const char HTTP_SCRIPT_CONSOL_COMPRESSED[] PROGMEM = "\x33\xBF\xAF\x71\xF0\xE3\x3A\x8B\x44\x3E\x1C\x67\x51\x18\xA3\xC1\x81\x7C\x1D\x6E" + "\x72\x08\xEE\x8C\x3B\xC7\xB4\xCE\xFE\x83\x3A\xB0\xF8\x7D\x9F\x67\x80\xC2\x77\xF2" + "\xAD\x1A\xF0\x5D\x1D\xD0\xA8\xEF\x02\x4C\xD3\x14\x77\x8F\x14\x7C\x63\x8E\xE9\xF7" + "\x47\x21\xF6\x77\x8F\x05\xA6\x0E\xE8\xC3\xE1\xF0\xE4\x3B\xC7\xB4\x83\x3E\x31\xC7" + "\x74\xFB\x0C\xE4\x3E\xCE\xF1\xE0\xB0\xF8\x7D\x9F\xA0\xCE\x43\xE1\xF6\x76\xC9\xF0" + "\x78\x23\x21\x65\xF2\xD2\x0F\x06\x8C\xCE\x7D\x47\x74\x33\xA1\x9D\x84\x2D\x9D\xE3" + "\xC0\x21\x45\x3E\x1F\x67\xD9\xE2\x8E\x9E\x0F\xF8\x10\x45\x58\x30\xF8\x71\x11\xBD" + "\x2A\x01\xF1\xEE\x3E\x02\x35\x13\xC1\xEE\xD3\x07\x74\x11\xA6\x1F\x87\xCF\x71\xDE" + "\x3D\xBA\x60\xEE\x9B\x0F\xE1\xF3\x85\x84\x11\xDE\x3D\xA6\xC3\xA5\x8E\xCF\xD1\xDD" + "\x3B\xC7\x83\xDC\x6C\x3E\x73\x1F\x44\x6C\x21\xA4\x11\x0A\xAA\x18\x5F\x66\xA1\x6F" + "\xD4\x77\x4E\xF1\xE0\xD8\x74\xCE\xFB\xB1\x0C\xBD\x57\x4C\x31\x57\xC3\xCC\xF8\x08" + "\x7C\x2F\x9D\xD0\x41\xCA\x8E\x9F\x76\x21\x91\x7A\xAE\x99\xF0\xF8\x73\x0F\xD1\xFA" + "\x23\x61\xD3\xD5\x74\x2F\xC7\xC3\xE1\xCA\x6C\x81\x07\x87\xF3\x69\xD4\x21\xE0\x43" + "\xE1\xB0\xE9\xF7\xE1\x99\xDE\x65\x4C\xD9\x47\x4F\x0C\x0B\x68\xEE\x9D\x87\xB8\xE4" + "\x3B\x0E\xF1\xE0\xB4\x43\xE0\x87\x4F\x0A\xD3\x14\x77\x4E\xF1\xE3\x4C\x1D\xD0\x44" + "\x92\x7C\x3E\x1C\x67\x78\xF6\x95\x02\x2F\x0A\x27\xB8\xDA\x09\x38\x29\xB4\xE8\x13" + "\xE1\xEA\x14\x7E\x02\x2E\x06\x76\xCF\x86\xD3\xC1\xEE\x05\xCE\x1E\x41\x33\x8F\xA0" + "\xA8\xF9\xE7\x40\x89\xC8\xE9\xD4\x7D\x08\x77\x8F\x07\xB8\xF7\x1E\x0D\x87\x4C\x18" + "\xF8\xEE\x9F\x64\x3C\x4C\xA8\xFB\x3A\x8F\xB0\xFC\x76\x83\x39\x47\xC3\xEC\xED\x96" + "\x88\x76\xF0\xEA\xAF\x8B\x67\x78\xF0\x6C\x3A\x79\xF0\x87\x74\xEF\x1E\x0C\x02\x56" + "\x3A\x72\x9B\x6C\xEF\x1E\x0F\x71\x7D\xD0\xBF\xF2\x31\x61\x79\x9E\x0F\x70\xF8\x47" + "\x74\x23\xBC\x78\x33\xBF\xA1\x41\x9F\x0F\x78\xF7\xCE\xA0\xF8\xF8\x71\x90\x22\xF3" + "\x62\x28\xEE\x9D\xE3\xDA\x08\x7C\xB6\x9D\x2C\x41\x09\x99\xBE\xA2\x0B\x7D\x4F\x9F" + "\xCE\xE9\xF6\x68\xCC\x84\xC1\xFE\x3E\xCE\xA0\x44\xE3\x7D\x82\x0F\x17\xA3\x81\x13" + "\x9A\x33\xA8\x33\xE3\x3A\x1A\x33\x22\x0F\x04\x67\x8D\x30\x77\x4E\x5F\xCF\x87\xC2" + "\x0C\xFF\x1F\xE3\x98\xCF\x87\xC2\x0C\xEF\x1E\xD1\xC7\x4B\x17\x58\x1E\x0D\x18\x13" + "\xA6\x7C\x3E\xF0\xC1\x83\xEC\xF0\x7B\x8E\x5F\xCF\x87\xC2\x0C\xED\x1D\xD3\xB6\x76" + "\xC3\xE3\xF0\x50\x60\x85\xC5\x71\xFA\x3F\x47\x74\x3E\x3E\x02\x24\xB3\xBC\x75\x0E" + "\x04\x2E\x38\x85\x06\x7B\xC1\xF1\xD6\x72\x1E\xF9\xFE\x3F\xC7\xD9\xF6\x77\x8F\x3C" + "\x67\xC3\xE1\x06\x76\x8E\xE9\xC6\x7E\x1D\x67\x59\x07\xC0\x83\x88\x1C\x64\x0A\x78" + "\x41\xC9\x67\xC3\xE1\x06\x7E\x8F\xD1\xDD\x04\x4C\xC4\xFC\x39\x11\xFA\x3F\x44\x28" + "\x33\xA0\xCC\x18\x77\x4E\xF1\xD4\x28\x33\xA0\xBE\x04\x1E\x4E\x01\x0B\x1C\x3B\xC7" + "\x50\x7C\x7C\x38\xCE\xF1\xEE\x3B\xC7\x83\xDC\x43\xE1\x1D\xD1\x47\x78\xF0"; + +#define HTTP_SCRIPT_CONSOL Decompress(HTTP_SCRIPT_CONSOL_COMPRESSED,HTTP_SCRIPT_CONSOL_SIZE).c_str() \ No newline at end of file diff --git a/tasmota/html_compressed/HTTP_SCRIPT_MODULE_TEMPLATE.h b/tasmota/html_compressed/HTTP_SCRIPT_MODULE_TEMPLATE.h new file mode 100644 index 000000000..e7f059b0b --- /dev/null +++ b/tasmota/html_compressed/HTTP_SCRIPT_MODULE_TEMPLATE.h @@ -0,0 +1,30 @@ +///////////////////////////////////////////////////////////////////// +// compressed by tools/unishox/compress-html-uncompressed.py +///////////////////////////////////////////////////////////////////// + +const size_t HTTP_SCRIPT_MODULE_TEMPLATE_SIZE = 602; +const char HTTP_SCRIPT_MODULE_TEMPLATE_COMPRESSED[] PROGMEM = "\x33\xBF\xAC\xF1\xD4\x2B\xC7\x83\x02\xF8\x3A\xDC\xE4\x1B\x3B\xBA\x75\x1A\x8E\xF1" + "\xED\x33\xBF\xAC\x3E\x09\x81\x8B\x1A\xFA\x8E\x81\xFD\xDD\x32\x61\x31\xAF\xA8\xEE" + "\x9F\x78\x32\xB7\x38\xFB\x3B\xC7\x8C\x3A\x53\x36\x51\x07\x9D\x4F\xA8\xF9\xA7\x83" + "\x51\xD2\xC6\x0C\x7C\x21\x06\x2B\x42\x10\xEE\xE1\xDE\x3C\x1E\xE0\x44\xCD\xB2\x8E" + "\xE8\xF1\xD5\xE0\x41\xCD\xAC\xF9\xE3\xF4\x71\x91\xB0\xC1\x86\x71\x9D\x44\x38\xF8" + "\x71\x9D\x44\x19\xD4\x30\xEA\x08\xEA\xA3\xE1\xAB\xC7\x74\xFB\x3C\x85\x1F\x67\x6C" + "\x78\xEF\x1D\x42\xCF\x9E\x3F\x47\x19\x1B\x0E\x37\x08\xC1\xE0\x23\xE5\x1D\x01\x07" + "\x4D\xF1\xD0\x27\xC3\xD4\x28\xF0\x63\x3E\x77\x74\xF8\x11\xE3\x4F\x1A\x75\x9D\x67" + "\x78\xF6\x8C\x04\x5B\xC7\xBD\xA7\x59\xC8\x7B\xE7\x42\x19\x7F\x7D\x45\xD8\x23\x3C" + "\x0C\x3A\x7D\x8D\xC3\x36\x08\x3B\x70\x24\xE0\x87\x78\xF0\x7B\x82\x3E\x0A\x04\xAC" + "\xC8\xE3\x3C\x16\x9E\x81\x1E\x34\xED\x9D\xB3\xBC\x7B\x43\x3E\x0A\xF1\xEF\x69\xEF" + "\x82\x17\x2A\x01\xE7\x8D\x30\x77\x6C\xF8\x7C\x0C\xEF\x1E\xD1\xC0\x89\x50\xE3\x70" + "\x8C\x1E\x07\x7D\xD9\xA1\xE0\xF7\x1E\xEF\x1F\x87\xE1\xF0\xE6\x90\x21\x64\x47\x21" + "\xE0\xB4\xF4\x3E\x0E\x04\x2C\x8D\x9D\xD3\xBB\xA7\xA1\xC8\xCE\xF1\xDA\x3B\xA7\xD9" + "\xDC\x3E\xCE\xD9\x69\xDE\x3C\xF4\xEA\xA3\xBC\x78\x3D\xCC\x71\xDD\x3E\xC5\x1F\x67" + "\x6C\x78\xEF\x1D\x0C\xEC\x21\x6C\xF8\x2C\xED\x9C\x87\x82\xA3\xA7\xA8\xC8\x26\x74" + "\x33\xDF\x68\xED\x0B\x68\xC8\xF8\x77\x47\x1F\x87\x19\xDE\x3B\x47\xD9\xF6\x79\x9F" + "\x64\x2B\x44\x11\xF1\xF6\x08\xDC\x58\xF8\xD0\xEE\xF8\xEA\x1E\x04\x3E\x42\xF3\xC7" + "\x4F\xB1\x81\x58\x6C\xEE\x9D\x87\xB8\xE5\x1D\x84\x3C\x75\x1E\xC3\xD0\x10\x78\x4B" + "\x40\x83\x9E\x9F\x67\xB0\xEF\x02\x35\xD3\x96\x76\x10\xF1\xD4\x7B\x0F\x43\xB0\x10" + "\x6F\x1F\x87\xB0\xEF\x1E\x18\xE3\xBA\x7D\x8F\x1F\x67\x6C\x78\xEF\x1D\x37\xB9\xFC" + "\x85\x15\x10\xD2\x08\xF9\x80\x8D\x48\x10\x72\x13\xBA\x3C\x7A\x1C\x48\xEF\x1D\xA2" + "\x04\x3E\x47\x4F\x3F\x1E\x34\xC0\x20\xD0\x3D\xA0\x85\xC9\xF9\xE0\xF7\x1E\xE3"; + +#define HTTP_SCRIPT_MODULE_TEMPLATE Decompress(HTTP_SCRIPT_MODULE_TEMPLATE_COMPRESSED,HTTP_SCRIPT_MODULE_TEMPLATE_SIZE).c_str() \ No newline at end of file diff --git a/tasmota/html_compressed/HTTP_SCRIPT_ROOT_NO_WEB_DISPLAY.h b/tasmota/html_compressed/HTTP_SCRIPT_ROOT_NO_WEB_DISPLAY.h new file mode 100644 index 000000000..862ecf0f6 --- /dev/null +++ b/tasmota/html_compressed/HTTP_SCRIPT_ROOT_NO_WEB_DISPLAY.h @@ -0,0 +1,27 @@ +///////////////////////////////////////////////////////////////////// +// compressed by tools/unishox/compress-html-uncompressed.py +///////////////////////////////////////////////////////////////////// + +const size_t HTTP_SCRIPT_ROOT_SIZE = 572; +const char HTTP_SCRIPT_ROOT_COMPRESSED[] PROGMEM = "\x33\xBF\xA3\x14\x78\x30\x2F\x83\xAD\xCE\x41\x59\xDD\x18\x77\x8F\x6D\x9F\x06\x1F" + "\xE3\xFC\x7D\x9F\x67\x80\xC2\x77\xF2\xAD\x1A\xF0\x5D\x1D\xD3\x14\x77\x81\x26\x68" + "\x54\x77\x8F\x1A\x60\xEE\x9B\x0F\xE1\xF3\x85\x84\x11\xDE\x3D\xA6\xC3\xA5\x8E\xCF" + "\xD1\xDD\x3B\xC7\xB8\xD8\x7C\xE6\x3E\x88\xD8\x43\x48\x22\x15\x54\x30\xBE\xCD\x42" + "\xDF\xA8\xEE\x9D\xE3\xC1\xB0\xE9\x9D\xF7\x62\x19\x7A\xAE\x98\x62\xAF\x87\x99\xF0" + "\x10\xF5\x73\xBA\x77\x8F\x6E\x98\x3B\xA6\xC3\xA7\xDD\x88\x64\x5E\xAB\xA6\x7C\x3E" + "\x1C\xC3\xF4\x7E\x88\xD8\x74\xF5\x5D\x0B\xF1\xF0\xF8\x72\x9B\x3B\xC7\xB4\x8C\xEF" + "\xEB\xC7\xC3\x61\xD3\xEF\xC3\x33\xBC\xCA\x99\xB2\x8E\x9F\x63\x02\xB0\xD9\xDD\x3B" + "\x0F\x6D\x1E\xE3\xB0\x78\xEA\x3D\x87\xA5\x58\xE0\x9A\xF5\x19\x04\xCF\x87\xD8\xFE" + "\x89\x42\x8F\x33\x91\xB3\xE8\xFA\x3E\xCF\xC3\xD8\x77\x88\x11\xB0\xAF\x02\x16\x15" + "\xF3\xF0\xF4\xA1\x40\x93\x5C\x68\x20\xD7\x3B\x28\x51\xF8\x7A\x50\x80\x93\x93\x9C" + "\xA6\x43\x0D\x87\x81\xF1\x5B\x4C\xEB\xF0\xCB\x0D\x9E\x7D\x83\xFF\xB1\x80\x95\x9C" + "\xB0\x43\xC7\x84\x3F\x0F\x43\xB2\xBE\x09\x36\x43\x3D\xC7\x60\xF1\xD4\x7B\x0F\xA3" + "\xE8\xFB\x3F\x0F\x41\x34\xCC\x10\xF3\xBA\x66\xCA\x3A\xEC\x2D\x1E\xE3\xCC\x37\xD4" + "\xFE\x78\x31\x9D\x47\x58\xFB\xD1\xE1\x54\x79\x9E\xC3\xBC\x78\x63\x8E\xE9\xF6\x11" + "\xC8\x7D\x9D\xE3\xA1\x6F\x73\xF9\x0A\x2A\x2B\x21\xA4\x11\xF3\xC0\xBD\xC8\x08\x54" + "\x7C\xF3\xA0\x44\x9D\x67\x51\xF4\x21\xDE\x3C\x1E\xE3\xDC\x78\x36\x1D\x30\x63\xE3" + "\xBA\x7D\x90\xF1\x32\xA3\xEC\xEA\x3E\xCE\x87\x68\x69\xF0\xE4\x3E\xCE\xD9\x59\xD5" + "\x5F\x16\xCE\xF1\xE0\xD8\x74\xF3\xE1\x0E\xE9\xDE\x3C\x18\x04\xBC\x68\xE5\x36\xD9" + "\xDE\x3C\x1E\xE3"; + +#define HTTP_SCRIPT_ROOT Decompress(HTTP_SCRIPT_ROOT_COMPRESSED,HTTP_SCRIPT_ROOT_SIZE).c_str() \ No newline at end of file diff --git a/tasmota/html_compressed/HTTP_SCRIPT_ROOT_PART2.h b/tasmota/html_compressed/HTTP_SCRIPT_ROOT_PART2.h new file mode 100644 index 000000000..17af45427 --- /dev/null +++ b/tasmota/html_compressed/HTTP_SCRIPT_ROOT_PART2.h @@ -0,0 +1,17 @@ +///////////////////////////////////////////////////////////////////// +// compressed by tools/unishox/compress-html-uncompressed.py +///////////////////////////////////////////////////////////////////// + +const size_t HTTP_SCRIPT_ROOT_PART2_SIZE = 222; +const char HTTP_SCRIPT_ROOT_PART2_COMPRESSED[] PROGMEM = "\x30\x2F\x83\xAD\xCE\x41\x06\x77\x4C\xCE\xAD\x3A\x86\x1D\xE3\xDB\xA6\x0E\xEB\x1C" + "\x77\x4F\xBF\x1F\x67\x78\xEF\x1E\xDD\x30\x77\x4C\xCF\x87\xC3\xEC\x51\xF6\x7F\x8F" + "\xF1\x99\xF0\xF8\x7D\x88\x7D\x9D\xE3\xDA\x67\x7F\x5E\x08\xF8\xC7\x1D\xD3\xEF\xC1" + "\x1C\xC3\xEC\xEF\x1D\x08\xCE\xC2\x16\xCF\x2A\x01\x85\x87\x9D\x3D\x46\x41\x33\xA0" + "\xEB\x0C\xD0\x7B\xF8\x2F\x84\x3E\x1F\x61\x6F\x3B\xF9\xD6\x3D\xFB\x13\x5F\x51\xDD" + "\xAC\x5F\xD1\xE1\x54\x75\x7C\x78\x71\xDD\x3E\xCE\xDF\x82\x3B\x67\xD9\xF4\x7D\x1D" + "\x40\x89\x14\x10\xE2\x9D\xE3\xA8\x57\x82\x3B\xA7\xD9\xDB\x04\x1D\x14\xE5\x10\x21" + "\xE8\xA7\x6C\xFB\x3A\x8E\x46\xCF\xA3\xE8\xEA\xD6\x7D\x1F\x47\x78\xEF\x1F\x67\x83" + "\xDC\x7B\x88\x2B\x3B\xA7\xD9\xFA\x3E\xCE\xD9\x99\xDB\xD3\xB6\x7D\x9F\x0F\xB3\xB6" + "\x30\xEF\x1E\x0F\x70\xF8\x47\x74\x2B\x3B\xC7\x83"; + +#define HTTP_SCRIPT_ROOT_PART2 Decompress(HTTP_SCRIPT_ROOT_PART2_COMPRESSED,HTTP_SCRIPT_ROOT_PART2_SIZE).c_str() \ No newline at end of file diff --git a/tasmota/html_compressed/HTTP_SCRIPT_ROOT_WEB_DISPLAY.h b/tasmota/html_compressed/HTTP_SCRIPT_ROOT_WEB_DISPLAY.h new file mode 100644 index 000000000..d211338a1 --- /dev/null +++ b/tasmota/html_compressed/HTTP_SCRIPT_ROOT_WEB_DISPLAY.h @@ -0,0 +1,32 @@ +///////////////////////////////////////////////////////////////////// +// compressed by tools/unishox/compress-html-uncompressed.py +///////////////////////////////////////////////////////////////////// + +const size_t HTTP_SCRIPT_ROOT_SIZE = 844; +const char HTTP_SCRIPT_ROOT_COMPRESSED[] PROGMEM = "\x33\xBF\xAF\x98\xF0\xA3\xE1\xC8\x75\x11\x8A\x3C\x18\x17\xC1\xD6\xE7\x20\xAC\xEE" + "\x8C\x3B\xC7\xB6\xCF\x83\x0F\xF1\xFE\x3E\xCF\xB3\xC0\x61\x3B\xF9\x56\x8D\x78\x2E" + "\x8E\xE9\x8A\x3B\xC0\x93\x34\x2A\x2B\x3B\xC7\x8D\x30\x77\x4D\x87\xF0\xF9\xC2\xC2" + "\x08\xEF\x1E\xD3\x61\xD2\xC7\x67\xE8\xEE\x9D\xE3\xC1\xEE\x36\x1F\x39\x8F\xA2\x36" + "\x10\xD2\x08\x85\x55\x0C\x2F\xB3\x50\xB7\xEA\x3B\xA7\x78\xF0\x6C\x3A\x67\x7D\xD8" + "\x86\x5E\xAB\xA6\x18\xAB\xE1\xE6\x7C\x04\x3D\x60\xEE\x9D\xE3\xDB\xA6\x0E\xE9\xB0" + "\xE9\xF7\x62\x19\x17\xAA\xE9\x9F\x0F\x87\x30\xFD\x1F\xA2\x36\x1D\x3D\x57\x42\xFC" + "\x7C\x3E\x1C\xA6\xCE\xF1\xED\x23\x3B\xFA\xF1\xF0\xD8\x74\xFB\xF0\xCC\xEF\x32\xA6" + "\x6C\xA3\xA7\xD8\xC0\xAC\x36\x77\x4E\xC3\xDB\x47\xB8\xEC\x1E\x3A\x8F\x61\xE9\x56" + "\x38\x26\xBD\x46\x41\x33\xE1\xF6\x3F\xA2\x50\xA3\xCC\xE4\x6C\xFA\x3E\x8F\xB3\xF0" + "\xF6\x1D\xE2\x04\x6C\x2B\xC0\x85\x85\x7C\xFC\x3D\x28\x50\x24\xD7\x1A\x08\x35\xCE" + "\xCA\x14\x7E\x1E\x94\x20\x24\xE4\xE7\x29\x90\xC3\x61\xE0\x7C\x56\xD3\x3A\xFC\x32" + "\xC3\x67\x9F\x60\xFF\xEC\x60\x25\x67\x2C\x10\xF1\xE1\x0F\xC3\xD0\xEC\xAF\x82\x4D" + "\x90\xCF\x71\xD8\x3C\x75\x1E\xC3\xE8\xFA\x3E\xCF\xC3\xD0\x4D\x33\x04\x3C\xEE\x99" + "\xB2\x8E\xBB\x0B\x47\xB8\xF3\x0D\xF5\x3F\x9E\x0C\x67\x51\xD6\x3E\xF4\x78\x55\x1E" + "\x67\xB0\xEF\x1E\x18\xE3\xBA\x7D\x84\x72\x1F\x67\x78\xE8\x5B\xDC\xFE\x42\x8A\x88" + "\x69\x04\x7C\xF0\x30\x1E\x40\xBE\x63\xC2\x8E\xF1\xED\x0A\x8F\x9E\x74\x08\x95\xEC" + "\xEA\x3E\x84\x3B\xC7\x83\xDC\x7B\x8F\x70\x22\xDE\x36\x1D\x30\x63\xE3\xBA\x7D\x90" + "\xF1\x32\xA3\xEC\xEA\x3E\xCE\x87\x68\x69\xF0\xE4\x3E\xCE\xD9\x59\xD5\x5F\x16\xCE" + "\xF1\xE0\xD8\x74\xF3\xE1\x0E\xE9\xDE\x3C\x18\x04\xBC\x90\xE5\x36\xD9\xDE\x3C\x1E" + "\xE3\xDC\x40\x89\xCD\x37\x99\x9D\x9D\xD1\x97\xF3\xAB\x4C\xEF\xE7\x78\xF6\x85\x67" + "\x74\xFB\x3F\x5E\x33\x3E\x1F\x67\x6F\x4C\xEF\xE7\x6C\xFB\x3F\x67\xD9\xDB\x19\x7F" + "\x3B\xC7\x80\x46\xC3\x74\x12\x30\xD0\x41\xE7\xE4\xF0\x0A\x78\xA7\xCC\x78\x51\xF0" + "\xE3\x20\x46\xC6\xC6\x7C\xEE\x98\x3B\xC7\xB7\x4C\x1D\xD3\x07\x78\xF6\x82\x67\x0B" + "\xA0\x99\xC3\xF8\x28\x70\xCA\x08\x5A\x79\xEE\x61\x79\x82\xF6\x40\x08\x7A\xF9\xEE"; + +#define HTTP_SCRIPT_ROOT Decompress(HTTP_SCRIPT_ROOT_COMPRESSED,HTTP_SCRIPT_ROOT_SIZE).c_str() \ No newline at end of file diff --git a/tasmota/html_compressed/HTTP_SCRIPT_TEMPLATE.h b/tasmota/html_compressed/HTTP_SCRIPT_TEMPLATE.h new file mode 100644 index 000000000..36ac7939d --- /dev/null +++ b/tasmota/html_compressed/HTTP_SCRIPT_TEMPLATE.h @@ -0,0 +1,20 @@ +///////////////////////////////////////////////////////////////////// +// compressed by tools/unishox/compress-html-uncompressed.py +///////////////////////////////////////////////////////////////////// + +const size_t HTTP_SCRIPT_TEMPLATE_SIZE = 303; +const char HTTP_SCRIPT_TEMPLATE_COMPRESSED[] PROGMEM = "\x30\x2F\x83\xAD\xCE\x41\x08\x77\x45\x9D\x46\x0E\xF1\xED\x33\xBF\xA3\x61\xF3\x98" + "\xFA\x23\x61\x0D\x20\x88\x55\x50\xC2\xFB\x35\x0B\x7E\xA3\xBA\x77\x8F\x06\xC3\xA6" + "\x77\xDD\x88\x65\xEA\xBA\x61\x8A\xBE\x1E\x67\xC0\x43\xC7\x4E\xE9\xDE\x3D\xBA\x60" + "\xEE\xD0\xAD\xF1\xD3\xEE\xC4\x32\x2F\x55\xD3\x3E\x1F\x0E\x61\xFA\x3F\x45\x42\xB7" + "\xC7\x4F\x55\xD0\xBF\x1F\x0F\x87\x29\xB3\xBC\x7B\x48\x10\x70\x43\xBC\x78\x3D\xC7" + "\xB8\xF0\x6C\x3A\x60\xC7\xC7\x74\xFB\x21\xE2\x65\x47\xD9\xD4\x2C\xEA\xAF\x8B\x67" + "\x78\xF0\x6C\x3A\x79\xF0\x87\x74\xEF\x1E\x0F\x71\x9D\xFD\x06\x78\x04\x4E\x2A\x01" + "\x4D\x87\x21\xDD\x21\xC0\x83\xBF\xE9\xD4\x6B\x3A\x87\x8E\xA3\x43\xAB\x0F\x18\x7C" + "\x1C\x74\xFB\xF0\xCC\xEF\x32\xA6\x6C\xA3\xA7\x86\x05\xB4\x77\x4E\xC3\xDC\x72\x1D" + "\x87\x78\xF0\x46\x87\xCC\x3A\x78\x56\x98\xA3\xBA\x77\x8F\x1A\x60\xEE\xB1\xC7\x74" + "\xFB\xF1\xC8\x7D\x9D\xE3\xA1\x19\xD8\x42\xD9\xF0\xF8\x7D\x9F\x67\x78\xF6\x82\x55" + "\x03\x43\xC1\xEE\x1E\x04\x5C\x44\x10\xB2\x93\xEC\xEA\x3E\xCE\xF1\xE3\x3C\x7C\x3D" + "\x86"; + +#define HTTP_SCRIPT_TEMPLATE Decompress(HTTP_SCRIPT_TEMPLATE_COMPRESSED,HTTP_SCRIPT_TEMPLATE_SIZE).c_str() \ No newline at end of file diff --git a/tasmota/html_uncompressed/HTTP_HEADER1_ES6.h b/tasmota/html_uncompressed/HTTP_HEADER1_ES6.h new file mode 100644 index 000000000..d89b93352 --- /dev/null +++ b/tasmota/html_uncompressed/HTTP_HEADER1_ES6.h @@ -0,0 +1,16 @@ +const char HTTP_HEADER1[] PROGMEM = + "" + "" + "" + "" + "%s - %s" + + ""; diff --git a/tasmota/html_uncompressed/HTTP_HEAD_STYLE1.h b/tasmota/html_uncompressed/HTTP_HEAD_STYLE1.h new file mode 100644 index 000000000..3ec441914 --- /dev/null +++ b/tasmota/html_uncompressed/HTTP_HEAD_STYLE1.h @@ -0,0 +1,12 @@ +const char HTTP_HEAD_STYLE1[] PROGMEM = + "" @@ -1142,11 +691,7 @@ void WSContentStart_P(const char* title, bool auth) WSContentBegin(200, CT_HTML); if (title != nullptr) { -#ifdef USE_UNISHOX_COMPRESSION WSContentSend_P(HTTP_HEADER1, D_HTML_LANGUAGE, SettingsText(SET_DEVICENAME), title); -#else - WSContentSend_P(HTTP_HEADER1, SettingsText(SET_DEVICENAME), title); -#endif //USE_UNISHOX_COMPRESSION } } @@ -1402,7 +947,7 @@ void HandleRoot(void) char scolor[8]; snprintf_P(scolor, sizeof(scolor), PSTR("#%02X%02X%02X"), dcolor, dcolor, dcolor); // Saturation start color from Black to White uint8_t red, green, blue; - LightHsToRgb(hue, 255, &red, &green, &blue); + HsToRgb(hue, 255, &red, &green, &blue); snprintf_P(stemp, sizeof(stemp), PSTR("#%02X%02X%02X"), red, green, blue); // Saturation end color WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // Saturation @@ -2084,7 +1629,11 @@ void HandleWifiConfiguration(void) WSContentStart_P(PSTR(D_CONFIGURE_WIFI), !WifiIsInManagerMode()); WSContentSend_P(HTTP_SCRIPT_WIFI); +#ifdef USE_ENHANCED_GUI_WIFI_SCAN + WSContentSendStyle_P(HTTP_HEAD_STYLE_SSI, WebColor(COL_TEXT)); +#else WSContentSendStyle(); +#endif // USE_ENHANCED_GUI_WIFI_SCAN if (HTTP_MANAGER_RESET_ONLY != Web.state) { if (Webserver->hasArg("scan")) { @@ -2105,6 +1654,7 @@ void HandleWifiConfiguration(void) indices[i] = i; } + // RSSI SORT for (uint32_t i = 0; i < n; i++) { for (uint32_t j = i + 1; j < n; j++) { @@ -2114,6 +1664,47 @@ void HandleWifiConfiguration(void) } } +#ifdef USE_ENHANCED_GUI_WIFI_SCAN + //display networks in page + for (uint32_t i = 0; i < n; i++) { + if (indices[i] < n) { + int32_t rssi = WiFi.RSSI(indices[i]); + String ssid = WiFi.SSID(indices[i]); + DEBUG_CORE_LOG(PSTR(D_LOG_WIFI D_SSID " %s, " D_BSSID " %s, " D_CHANNEL " %d, " D_RSSI " %d"), + ssid.c_str(), WiFi.BSSIDstr(indices[i]).c_str(), WiFi.channel(indices[i]), rssi); + + // Print SSID + WSContentSend_P(PSTR("
%s
"), HtmlEscape(ssid).c_str()); + + String nextSSID = ""; + // Handle all APs with the same SSID + for (uint32_t j = 0; j < n; j++) { + if ((indices[j] < n) && ((nextSSID = WiFi.SSID(indices[j])) == ssid)) { + // Update RSSI / quality + rssi = WiFi.RSSI(indices[j]); + uint32_t rssi_as_quality = WifiGetRssiAsQuality(rssi); + uint32_t num_bars = changeUIntScale(rssi_as_quality, 0, 100, 0, 4); + + // Print item + WSContentSend_P(PSTR("
%s(%d)
"), + rssi, rssi_as_quality, + WiFi.BSSIDstr(indices[j]).c_str(), + WiFi.channel(indices[j]) + ); + // Print signal strength indicator + for (uint32_t k = 0; k < 4; ++k) { + WSContentSend_P(PSTR(""), k, (num_bars < k) ? PSTR(" o30") : PSTR("")); + } + WSContentSend_P(PSTR("
")); + + indices[j] = n; + } + delay(0); + } + WSContentSend_P(PSTR("
")); + } + } +#else // No USE_ENHANCED_GUI_WIFI_SCAN // remove duplicates ( must be RSSI sorted ) String cssid; for (uint32_t i = 0; i < n; i++) { @@ -2135,6 +1726,7 @@ void HandleWifiConfiguration(void) DEBUG_CORE_LOG(PSTR(D_LOG_WIFI D_SSID " %s, " D_BSSID " %s, " D_CHANNEL " %d, " D_RSSI " %d"), WiFi.SSID(indices[i]).c_str(), WiFi.BSSIDstr(indices[i]).c_str(), WiFi.channel(indices[i]), rssi); int quality = WifiGetRssiAsQuality(rssi); +/* int auth = WiFi.encryptionType(indices[i]); char encryption[20]; WSContentSend_P(PSTR("
%s (%d) %s %d%% (%d dBm)
"), @@ -2143,9 +1735,17 @@ void HandleWifiConfiguration(void) GetTextIndexed(encryption, sizeof(encryption), auth +1, kEncryptionType), quality, rssi ); - delay(0); +*/ + WSContentSend_P(PSTR("
%s (%d) %d%% (%d dBm)
"), + HtmlEscape(WiFi.SSID(indices[i])).c_str(), + WiFi.channel(indices[i]), + quality, rssi + ); + delay(0); } +#endif // USE_ENHANCED_GUI_WIFI_SCAN + WSContentSend_P(PSTR("
")); } } else { @@ -2327,7 +1927,7 @@ void OtherSaveSettings(void) char tmp[300]; // Needs to hold complete ESP32 template of minimal 230 chars char webindex[5]; char friendlyname[TOPSZ]; - char message[LOGSZ]; + char message[MAX_LOGSZ]; WebGetArg("dn", tmp, sizeof(tmp)); SettingsUpdateText(SET_DEVICENAME, (!strlen(tmp)) ? "" : (!strcmp(tmp,"1")) ? SettingsText(SET_FRIENDLYNAME1) : tmp); @@ -3401,7 +3001,9 @@ void CmndWebColor(void) } } else { +#ifndef FIRMWARE_MINIMAL // if tasmota-minimal, read only and don't parse JSON JsonWebColor(XdrvMailbox.data); +#endif // FIRMWARE_MINIMAL } } Response_P(PSTR("{\"" D_CMND_WEBCOLOR "\":[")); diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 5baba474f..d34b98b57 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -1,7 +1,7 @@ /* xdrv_02_mqtt.ino - mqtt support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 @@ -106,8 +106,7 @@ bool is_fingerprint_mono_value(uint8_t finger[20], uint8_t value) { } #endif // USE_MQTT_TLS -void MakeValidMqtt(uint32_t option, char* str) -{ +void MakeValidMqtt(uint32_t option, char* str) { // option 0 = replace by underscore // option 1 = delete character uint32_t i = 0; @@ -147,8 +146,7 @@ void MakeValidMqtt(uint32_t option, char* str) PubSubClient MqttClient; -void MqttInit(void) -{ +void MqttInit(void) { #ifdef USE_MQTT_TLS if ((8883 == Settings.mqtt_port) || (8884 == Settings.mqtt_port)) { // Turn on TLS for port 8883 (TLS) and 8884 (TLS, client certificate) @@ -187,30 +185,25 @@ void MqttInit(void) #endif // USE_MQTT_TLS } -bool MqttIsConnected(void) -{ +bool MqttIsConnected(void) { return MqttClient.connected(); } -void MqttDisconnect(void) -{ +void MqttDisconnect(void) { MqttClient.disconnect(); } -void MqttSubscribeLib(const char *topic) -{ +void MqttSubscribeLib(const char *topic) { MqttClient.subscribe(topic); MqttClient.loop(); // Solve LmacRxBlk:1 messages } -void MqttUnsubscribeLib(const char *topic) -{ +void MqttUnsubscribeLib(const char *topic) { MqttClient.unsubscribe(topic); MqttClient.loop(); // Solve LmacRxBlk:1 messages } -bool MqttPublishLib(const char* topic, bool retained) -{ +bool MqttPublishLib(const char* topic, bool retained) { // If Prefix1 equals Prefix2 disable next MQTT subscription to prevent loop if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2))) { char *str = strstr(topic, SettingsText(SET_MQTTPREFIX1)); @@ -225,14 +218,15 @@ bool MqttPublishLib(const char* topic, bool retained) return result; } +#ifdef DEBUG_TASMOTA_CORE void MqttDumpData(char* topic, char* data, uint32_t data_len) { char dump_data[data_len +1]; memcpy(dump_data, data, sizeof(dump_data)); // Make another copy for removing optional control characters - AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_MQTT D_DATA_SIZE " %d, \"%s %s\""), data_len, topic, RemoveControlCharacter(dump_data)); + DEBUG_CORE_LOG(PSTR(D_LOG_MQTT "Size %d, \"%s %s\""), data_len, topic, RemoveControlCharacter(dump_data)); } +#endif -void MqttDataHandler(char* mqtt_topic, uint8_t* mqtt_data, unsigned int data_len) -{ +void MqttDataHandler(char* mqtt_topic, uint8_t* mqtt_data, unsigned int data_len) { #ifdef USE_DEBUG_DRIVER ShowFreeMem(PSTR("MqttDataHandler")); #endif @@ -256,9 +250,9 @@ void MqttDataHandler(char* mqtt_topic, uint8_t* mqtt_data, unsigned int data_len char data[data_len +1]; memcpy(data, mqtt_data, sizeof(data)); -// AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_MQTT D_DATA_SIZE " %d, \"%s %s\""), data_len, topic, data); -// if (LOG_LEVEL_DEBUG_MORE <= TasmotaGlobal.seriallog_level) { Serial.println(data); } +#ifdef DEBUG_TASMOTA_CORE MqttDumpData(topic, data, data_len); // Use a function to save stack space used by dump_data +#endif // MQTT pre-processing XdrvMailbox.index = strlen(topic); @@ -274,19 +268,16 @@ void MqttDataHandler(char* mqtt_topic, uint8_t* mqtt_data, unsigned int data_len /*********************************************************************************************/ -void MqttRetryCounter(uint8_t value) -{ +void MqttRetryCounter(uint8_t value) { Mqtt.retry_counter = value; } -void MqttSubscribe(const char *topic) -{ +void MqttSubscribe(const char *topic) { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT D_SUBSCRIBE_TO " %s"), topic); MqttSubscribeLib(topic); } -void MqttUnsubscribe(const char *topic) -{ +void MqttUnsubscribe(const char *topic) { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT D_UNSUBSCRIBE_FROM " %s"), topic); MqttUnsubscribeLib(topic); } @@ -307,8 +298,7 @@ void MqttPublishLoggingAsync(bool refresh) { } } -void MqttPublish(const char* topic, bool retained) -{ +void MqttPublish(const char* topic, bool retained) { #ifdef USE_DEBUG_DRIVER ShowFreeMem(PSTR("MqttPublish")); #endif @@ -331,7 +321,7 @@ void MqttPublish(const char* topic, bool retained) } } - char log_data[LOGSZ]; + char log_data[MAX_LOGSZ]; snprintf_P(log_data, sizeof(log_data), PSTR("%s%s = %s"), slog_type, (Settings.flag.mqtt_enabled) ? topic : strrchr(topic,'/')+1, TasmotaGlobal.mqtt_data); // SetOption3 - Enable MQTT if (strlen(log_data) >= (sizeof(log_data) - strlen(sretained) -1)) { log_data[sizeof(log_data) - strlen(sretained) -5] = '\0'; @@ -345,13 +335,11 @@ void MqttPublish(const char* topic, bool retained) } } -void MqttPublish(const char* topic) -{ +void MqttPublish(const char* topic) { MqttPublish(topic, false); } -void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retained) -{ +void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retained) { /* prefix 0 = cmnd using subtopic * prefix 1 = stat using subtopic * prefix 2 = tele using subtopic @@ -399,29 +387,24 @@ void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retain #endif // USE_MQTT_AWS_IOT } -void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic) -{ +void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic) { MqttPublishPrefixTopic_P(prefix, subtopic, false); } -void MqttPublishPrefixTopicRulesProcess_P(uint32_t prefix, const char* subtopic, bool retained) -{ +void MqttPublishPrefixTopicRulesProcess_P(uint32_t prefix, const char* subtopic, bool retained) { MqttPublishPrefixTopic_P(prefix, subtopic, retained); XdrvRulesProcess(); } -void MqttPublishPrefixTopicRulesProcess_P(uint32_t prefix, const char* subtopic) -{ +void MqttPublishPrefixTopicRulesProcess_P(uint32_t prefix, const char* subtopic) { MqttPublishPrefixTopicRulesProcess_P(prefix, subtopic, false); } -void MqttPublishTeleSensor(void) -{ +void MqttPublishTeleSensor(void) { MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); // CMND_SENSORRETAIN } -void MqttPublishPowerState(uint32_t device) -{ +void MqttPublishPowerState(uint32_t device) { char stopic[TOPSZ]; char scommand[33]; @@ -455,8 +438,7 @@ void MqttPublishPowerState(uint32_t device) #endif // USE_SONOFF_IFAN } -void MqttPublishAllPowerState(void) -{ +void MqttPublishAllPowerState(void) { for (uint32_t i = 1; i <= TasmotaGlobal.devices_present; i++) { MqttPublishPowerState(i); #ifdef USE_SONOFF_IFAN @@ -465,8 +447,7 @@ void MqttPublishAllPowerState(void) } } -void MqttPublishPowerBlinkState(uint32_t device) -{ +void MqttPublishPowerBlinkState(uint32_t device) { char scommand[33]; if ((device < 1) || (device > TasmotaGlobal.devices_present)) { @@ -480,13 +461,11 @@ void MqttPublishPowerBlinkState(uint32_t device) /*********************************************************************************************/ -uint16_t MqttConnectCount(void) -{ +uint16_t MqttConnectCount(void) { return Mqtt.connect_count; } -void MqttDisconnected(int state) -{ +void MqttDisconnected(int state) { Mqtt.connected = false; Mqtt.retry_counter = Settings.mqtt_retry * Mqtt.retry_counter_delay; @@ -500,8 +479,7 @@ void MqttDisconnected(int state) TasmotaGlobal.rules_flag.mqtt_disconnected = 1; } -void MqttConnected(void) -{ +void MqttConnected(void) { char stopic[TOPSZ]; if (Mqtt.allowed) { @@ -582,8 +560,7 @@ void MqttConnected(void) } } -void MqttReconnect(void) -{ +void MqttReconnect(void) { char stopic[TOPSZ]; Mqtt.allowed = Settings.flag.mqtt_enabled; // SetOption3 - Enable MQTT @@ -708,37 +685,6 @@ void MqttReconnect(void) AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "MFLN not supported by TLS server")); } #ifndef USE_MQTT_TLS_CA_CERT // don't bother with fingerprints if using CA validation -// **** Start patch Castellucci -/* - // create a printable version of the fingerprint received - char buf_fingerprint[64]; - ToHex_P((unsigned char *)tlsClient->getRecvPubKeyFingerprint(), 20, buf_fingerprint, sizeof(buf_fingerprint), ' '); - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT "Server fingerprint: %s"), buf_fingerprint); - - if (learn_fingerprint1 || learn_fingerprint2) { - // we potentially need to learn the fingerprint just seen - bool fingerprint_matched = false; - const uint8_t *recv_fingerprint = tlsClient->getRecvPubKeyFingerprint(); - if (0 == memcmp(recv_fingerprint, Settings.mqtt_fingerprint[0], 20)) { - fingerprint_matched = true; - } - if (0 == memcmp(recv_fingerprint, Settings.mqtt_fingerprint[1], 20)) { - fingerprint_matched = true; - } - if (!fingerprint_matched) { - // we had no match, so we need to change all fingerprints ready to learn - if (learn_fingerprint1) { - memcpy(Settings.mqtt_fingerprint[0], recv_fingerprint, 20); - } - if (learn_fingerprint2) { - memcpy(Settings.mqtt_fingerprint[1], recv_fingerprint, 20); - } - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "Fingerprint learned: %s"), buf_fingerprint); - - SettingsSaveAll(); // save settings - } - } -*/ const uint8_t *recv_fingerprint = tlsClient->getRecvPubKeyFingerprint(); // create a printable version of the fingerprint received char buf_fingerprint[64]; @@ -766,7 +712,6 @@ void MqttReconnect(void) SettingsSaveAll(); // save settings } - // **** End patch Castellucci #endif // !USE_MQTT_TLS_CA_CERT } #endif // USE_MQTT_TLS @@ -781,8 +726,7 @@ void MqttReconnect(void) } } -void MqttCheck(void) -{ +void MqttCheck(void) { if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT if (!MqttIsConnected()) { TasmotaGlobal.global_state.mqtt_down = 1; @@ -802,8 +746,7 @@ void MqttCheck(void) } } -bool KeyTopicActive(uint32_t key) -{ +bool KeyTopicActive(uint32_t key) { // key = 0 - Button topic // key = 1 - Switch topic key &= 1; @@ -817,8 +760,7 @@ bool KeyTopicActive(uint32_t key) \*********************************************************************************************/ #if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) -void CmndMqttFingerprint(void) -{ +void CmndMqttFingerprint(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { char fingerprint[60]; if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(fingerprint))) { @@ -838,8 +780,7 @@ void CmndMqttFingerprint(void) } #endif -void CmndMqttUser(void) -{ +void CmndMqttUser(void) { if (XdrvMailbox.data_len > 0) { SettingsUpdateText(SET_MQTT_USER, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_USER : XdrvMailbox.data); TasmotaGlobal.restart_flag = 2; @@ -847,8 +788,7 @@ void CmndMqttUser(void) ResponseCmndChar(SettingsText(SET_MQTT_USER)); } -void CmndMqttPassword(void) -{ +void CmndMqttPassword(void) { if (XdrvMailbox.data_len > 0) { SettingsUpdateText(SET_MQTT_PWD, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_PASS : XdrvMailbox.data); ResponseCmndChar(SettingsText(SET_MQTT_PWD)); @@ -858,16 +798,14 @@ void CmndMqttPassword(void) } } -void CmndMqttlog(void) -{ +void CmndMqttlog(void) { if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) { Settings.mqttlog_level = XdrvMailbox.payload; } ResponseCmndNumber(Settings.mqttlog_level); } -void CmndMqttHost(void) -{ +void CmndMqttHost(void) { if (XdrvMailbox.data_len > 0) { SettingsUpdateText(SET_MQTT_HOST, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_HOST : XdrvMailbox.data); TasmotaGlobal.restart_flag = 2; @@ -875,8 +813,7 @@ void CmndMqttHost(void) ResponseCmndChar(SettingsText(SET_MQTT_HOST)); } -void CmndMqttPort(void) -{ +void CmndMqttPort(void) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 65536)) { Settings.mqtt_port = (1 == XdrvMailbox.payload) ? MQTT_PORT : XdrvMailbox.payload; TasmotaGlobal.restart_flag = 2; @@ -884,8 +821,7 @@ void CmndMqttPort(void) ResponseCmndNumber(Settings.mqtt_port); } -void CmndMqttRetry(void) -{ +void CmndMqttRetry(void) { if ((XdrvMailbox.payload >= MQTT_RETRY_SECS) && (XdrvMailbox.payload < 32001)) { Settings.mqtt_retry = XdrvMailbox.payload; Mqtt.retry_counter = Settings.mqtt_retry; @@ -893,8 +829,7 @@ void CmndMqttRetry(void) ResponseCmndNumber(Settings.mqtt_retry); } -void CmndStateText(void) -{ +void CmndStateText(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_STATE_TEXT)) { if (!XdrvMailbox.usridx) { ResponseCmndAll(SET_STATE_TXT1, MAX_STATE_TEXT); @@ -910,8 +845,7 @@ void CmndStateText(void) } } -void CmndMqttClient(void) -{ +void CmndMqttClient(void) { if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { SettingsUpdateText(SET_MQTT_CLIENT, (SC_DEFAULT == Shortcut()) ? MQTT_CLIENT_ID : XdrvMailbox.data); TasmotaGlobal.restart_flag = 2; @@ -919,8 +853,7 @@ void CmndMqttClient(void) ResponseCmndChar(SettingsText(SET_MQTT_CLIENT)); } -void CmndFullTopic(void) -{ +void CmndFullTopic(void) { if (XdrvMailbox.data_len > 0) { MakeValidMqtt(1, XdrvMailbox.data); if (!strcmp(XdrvMailbox.data, TasmotaGlobal.mqtt_client)) { SetShortcutDefault(); } @@ -936,8 +869,7 @@ void CmndFullTopic(void) ResponseCmndChar(SettingsText(SET_MQTT_FULLTOPIC)); } -void CmndPrefix(void) -{ +void CmndPrefix(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_MQTT_PREFIXES)) { if (!XdrvMailbox.usridx) { ResponseCmndAll(SET_MQTTPREFIX1, MAX_MQTT_PREFIXES); @@ -953,14 +885,16 @@ void CmndPrefix(void) } } -void CmndPublish(void) -{ +void CmndPublish(void) { + // Allow wildcard character "#" as space replacement in topic (#10258) + // publish cmnd/theo#arends/power 2 ==> publish cmnd/theo arends/power 2 if (XdrvMailbox.data_len > 0) { char *payload_part; char *mqtt_part = strtok_r(XdrvMailbox.data, " ", &payload_part); if (mqtt_part) { char stemp1[TOPSZ]; strlcpy(stemp1, mqtt_part, sizeof(stemp1)); + ReplaceChar(stemp1, '#', ' '); if ((payload_part != nullptr) && strlen(payload_part)) { strlcpy(TasmotaGlobal.mqtt_data, payload_part, sizeof(TasmotaGlobal.mqtt_data)); } else { @@ -973,8 +907,7 @@ void CmndPublish(void) } } -void CmndGroupTopic(void) -{ +void CmndGroupTopic(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_GROUP_TOPICS)) { if (XdrvMailbox.data_len > 0) { uint32_t settings_text_index = (1 == XdrvMailbox.index) ? SET_MQTT_GRP_TOPIC : SET_MQTT_GRP_TOPIC2 + XdrvMailbox.index - 2; @@ -1023,8 +956,7 @@ void CmndGroupTopic(void) } } -void CmndTopic(void) -{ +void CmndTopic(void) { if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { MakeValidMqtt(0, XdrvMailbox.data); if (!strcmp(XdrvMailbox.data, TasmotaGlobal.mqtt_client)) { SetShortcutDefault(); } @@ -1040,8 +972,7 @@ void CmndTopic(void) ResponseCmndChar(SettingsText(SET_MQTT_TOPIC)); } -void CmndButtonTopic(void) -{ +void CmndButtonTopic(void) { if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { MakeValidMqtt(0, XdrvMailbox.data); if (!strcmp(XdrvMailbox.data, TasmotaGlobal.mqtt_client)) { SetShortcutDefault(); } @@ -1055,8 +986,7 @@ void CmndButtonTopic(void) ResponseCmndChar(SettingsText(SET_MQTT_BUTTON_TOPIC)); } -void CmndSwitchTopic(void) -{ +void CmndSwitchTopic(void) { if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { MakeValidMqtt(0, XdrvMailbox.data); if (!strcmp(XdrvMailbox.data, TasmotaGlobal.mqtt_client)) { SetShortcutDefault(); } @@ -1070,8 +1000,7 @@ void CmndSwitchTopic(void) ResponseCmndChar(SettingsText(SET_MQTT_SWITCH_TOPIC)); } -void CmndButtonRetain(void) -{ +void CmndButtonRetain(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { if (!XdrvMailbox.payload) { for (uint32_t i = 1; i <= MAX_KEYS; i++) { @@ -1083,8 +1012,7 @@ void CmndButtonRetain(void) ResponseCmndStateText(Settings.flag.mqtt_button_retain); // CMND_BUTTONRETAIN } -void CmndSwitchRetain(void) -{ +void CmndSwitchRetain(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { if (!XdrvMailbox.payload) { for (uint32_t i = 1; i <= MAX_SWITCHES; i++) { @@ -1096,8 +1024,7 @@ void CmndSwitchRetain(void) ResponseCmndStateText(Settings.flag.mqtt_switch_retain); // CMND_SWITCHRETAIN } -void CmndPowerRetain(void) -{ +void CmndPowerRetain(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { if (!XdrvMailbox.payload) { char stemp1[TOPSZ]; @@ -1116,8 +1043,7 @@ void CmndPowerRetain(void) ResponseCmndStateText(Settings.flag.mqtt_power_retain); // CMND_POWERRETAIN } -void CmndSensorRetain(void) -{ +void CmndSensorRetain(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { if (!XdrvMailbox.payload) { ResponseClear(); diff --git a/tasmota/xdrv_03_energy.ino b/tasmota/xdrv_03_energy.ino index 18c57b371..e7b52b9ab 100644 --- a/tasmota/xdrv_03_energy.ino +++ b/tasmota/xdrv_03_energy.ino @@ -1,7 +1,7 @@ /* xdrv_03_energy.ino - Energy sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 2cd84f780..90d94ffb7 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -1,7 +1,7 @@ /* xdrv_04_light.ino - PWM, WS2812 and sonoff led support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 @@ -132,6 +132,10 @@ const char kLightCommands[] PROGMEM = "|" // No prefix D_CMND_COLOR "|" D_CMND_COLORTEMPERATURE "|" D_CMND_DIMMER "|" D_CMND_DIMMER_RANGE "|" D_CMND_DIMMER_STEP "|" D_CMND_LEDTABLE "|" D_CMND_FADE "|" D_CMND_RGBWWTABLE "|" D_CMND_SCHEME "|" D_CMND_SPEED "|" D_CMND_WAKEUP "|" D_CMND_WAKEUPDURATION "|" D_CMND_WHITE "|" D_CMND_CHANNEL "|" D_CMND_HSBCOLOR + "|" D_CMND_CTRANGE +#ifdef USE_LIGHT_VIRTUAL_CT + "|" D_CMND_VIRTUALCT +#endif // USE_LIGHT_VIRTUAL_CT #ifdef USE_LIGHT_PALETTE "|" D_CMND_PALETTE #endif // USE_LIGHT_PALETTE @@ -144,6 +148,10 @@ void (* const LightCommand[])(void) PROGMEM = { &CmndColor, &CmndColorTemperature, &CmndDimmer, &CmndDimmerRange, &CmndDimmerStep, &CmndLedTable, &CmndFade, &CmndRgbwwTable, &CmndScheme, &CmndSpeed, &CmndWakeup, &CmndWakeupDuration, &CmndWhite, &CmndChannel, &CmndHsbColor, + &CmndCTRange, +#ifdef USE_LIGHT_VIRTUAL_CT + &CmndVirtualCT, +#endif // USE_LIGHT_VIRTUAL_CT #ifdef USE_LIGHT_PALETTE &CmndPalette, #endif // USE_LIGHT_PALETTE @@ -181,83 +189,12 @@ const uint16_t CT_MAX = 500; // 2000K // Ranges used for Alexa const uint16_t CT_MIN_ALEXA = 200; // also 5000K const uint16_t CT_MAX_ALEXA = 380; // also 2600K - -// New version of Gamma correction compute -// Instead of a table, we do a multi-linear approximation, which is close enough -// At low levels, the slope is a bit higher than actual gamma, to make changes smoother -// Internal resolution is 10 bits. - -typedef struct gamma_table_t { - uint16_t to_src; - uint16_t to_gamma; -} gamma_table_t; - -const gamma_table_t gamma_table[] = { // don't put in PROGMEM for performance reasons - { 1, 1 }, - { 4, 1 }, - { 209, 13 }, - { 312, 41 }, - { 457, 106 }, - { 626, 261 }, - { 762, 450 }, - { 895, 703 }, - { 1023, 1023 }, - { 0xFFFF, 0xFFFF } // fail-safe if out of range -}; - -// simplified Gamma table for Fade, cheating a little at low brightness -const gamma_table_t gamma_table_fast[] = { - { 384, 192 }, - { 768, 576 }, - { 1023, 1023 }, - { 0xFFFF, 0xFFFF } // fail-safe if out of range -}; - -// For reference, below are the computed gamma tables, via ledGamma() -// for 8 bits output: -// 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -// 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, -// 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, -// 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, -// 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, -// 11, 12, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 17, 18, -// 18, 19, 19, 20, 20, 21, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, -// 25, 26, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 36, 37, 38, -// 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, 51, 52, 53, -// 54, 55, 56, 57, 58, 59, 60, 61, 61, 62, 63, 64, 65, 67, 68, 69, -// 71, 72, 73, 75, 76, 78, 79, 80, 82, 83, 85, 86, 87, 89, 90, 91, -// 93, 94, 95, 97, 98,100,101,102,104,105,107,108,109,111,112,114, -// 116,118,120,122,124,125,127,129,131,133,135,137,139,141,143,144, -// 146,148,150,152,154,156,158,160,162,164,166,168,170,171,173,175, -// 178,180,183,185,188,190,193,195,198,200,203,205,208,210,213,215, -// 218,220,223,225,228,230,233,235,238,240,243,245,248,250,253,255 -// -// and for 10 bits output: -// 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, -// 5, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, -// 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, -// 12, 12, 13, 13, 13, 14, 15, 16, 17, 18, 20, 21, 22, 23, 24, 25, -// 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, -// 45, 47, 49, 50, 52, 54, 56, 58, 59, 61, 63, 65, 67, 68, 70, 72, -// 74, 76, 77, 79, 81, 83, 84, 86, 88, 90, 92, 93, 95, 97, 99, 101, -// 102, 104, 106, 110, 113, 117, 121, 124, 128, 132, 135, 139, 143, 146, 150, 154, -// 158, 162, 166, 169, 173, 177, 180, 184, 188, 191, 195, 199, 202, 206, 210, 213, -// 217, 221, 224, 228, 232, 235, 239, 243, 246, 250, 254, 257, 261, 267, 272, 278, -// 283, 289, 294, 300, 305, 311, 317, 322, 328, 333, 339, 344, 350, 356, 361, 367, -// 372, 378, 383, 389, 394, 400, 406, 411, 417, 422, 428, 433, 439, 444, 450, 458, -// 465, 473, 480, 488, 496, 503, 511, 518, 526, 534, 541, 549, 557, 564, 572, 579, -// 587, 595, 602, 610, 617, 627, 635, 642, 650, 657, 665, 673, 680, 688, 695, 703, -// 713, 723, 733, 743, 753, 763, 773, 783, 793, 803, 813, 823, 833, 843, 853, 863, -// 873, 883, 893, 903, 913, 923, 933, 943, 953, 963, 973, 983, 993,1003,1013,1023 -// -// Output for Dimmer 0..100 values -// 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9, -// 10, 10, 11, 12, 12, 13, 15, 17, 21, 23, 26, 28, 31, 34, 37, -// 40, 43, 49, 52, 58, 61, 67, 70, 76, 79, 84, 90, 93, 99,102, -// 110,117,128,135,146,158,166,177,184,195,202,213,221,232,239, -// 250,261,272,289,300,317,328,344,356,372,389,400,417,428,444, -// 458,480,496,518,534,557,579,595,617,635,657,673,695,713,743, -// 773,793,823,843,873,893,923,943,973,993,1023 +// Virtual CT default values +typedef uint8_t vct_pivot_t[LST_MAX]; +const size_t CT_PIVOTS = LIGHT_VIRTUAL_CT_POINTS; +const vct_pivot_t CT_PIVOTS_RGB PROGMEM = { 255, 255, 255, 0, 0 }; +const vct_pivot_t CT_PIVOTS_CWW PROGMEM = { 0, 0, 0, 255, 0 }; +const vct_pivot_t CT_PIVOTS_WWW PROGMEM = { 0, 0, 0, 0, 255 }; struct LIGHT { uint32_t strip_timer_counter = 0; // Bars and Gradient @@ -308,6 +245,12 @@ struct LIGHT { uint16_t pwm_min = 0; // minimum value for PWM, from DimmerRange, 0..1023 uint16_t pwm_max = 1023; // maxumum value for PWM, from DimmerRange, 0..1023 + + // Virtual CT + uint16_t vct_ct[CT_PIVOTS]; // CT value for each segment +#ifdef USE_LIGHT_VIRTUAL_CT + vct_pivot_t vct_color[CT_PIVOTS]; // array of 3 colors each with 5 values +#endif } Light; power_t LightPower(void) @@ -378,13 +321,6 @@ class LightStateClass { uint8_t _briCT = 255; uint8_t _color_mode = LCM_RGB; // RGB by default - // the CT range below represents the rendered range, - // This is due to Alexa whose CT range is 199..383 - // Hence setting Min=200 and Max=380 makes Alexa use the full range - // Please note that you can still set CT to 153..500, but any - // value below _ct_min_range or above _ct_max_range not change the CT - uint16_t _ct_min_range = CT_MIN; // the minimum CT rendered range - uint16_t _ct_max_range = CT_MAX; // the maximum CT rendered range public: LightStateClass() { @@ -535,22 +471,7 @@ class LightStateClass { inline uint16_t getCT() const { return _ct; // 153..500, or CT_MIN..CT_MAX - } - - // get the CT value within the range into a 10 bits 0..1023 value - uint16_t getCT10bits() const { - return changeUIntScale(_ct, _ct_min_range, _ct_max_range, 0, 1023); - } - - inline void setCTRange(uint16_t ct_min_range, uint16_t ct_max_range) { - _ct_min_range = ct_min_range; - _ct_max_range = ct_max_range; - } - - inline void getCTRange(uint16_t *ct_min_range, uint16_t *ct_max_range) const { - if (ct_min_range) { *ct_min_range = _ct_min_range; } - if (ct_max_range) { *ct_max_range = _ct_max_range; } - } + } // get current color in XY format void getXY(float *x, float *y) { @@ -603,7 +524,7 @@ class LightStateClass { setColorMode(LCM_RGB); // try deactivating CT mode, setColorMode() will check which is legal } else { ct = (ct < CT_MIN ? CT_MIN : (ct > CT_MAX ? CT_MAX : ct)); - _ww = changeUIntScale(ct, _ct_min_range, _ct_max_range, 0, 255); + _ww = changeUIntScale(ct, Light.vct_ct[0], Light.vct_ct[CT_PIVOTS-1], 0, 255); _wc = 255 - _ww; _ct = ct; addCTMode(); @@ -730,13 +651,6 @@ class LightStateClass { _r, _g, _b, _wc, _ww); #endif } - - // new version of RGB to HSB with only integer calculation - static void RgbToHsb(uint8_t r, uint8_t g, uint8_t b, uint16_t *r_hue, uint8_t *r_sat, uint8_t *r_bri); - static void HsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b); - static void RgbToXy(uint8_t i_r, uint8_t i_g, uint8_t i_b, float *r_x, float *r_y); - static void XyToRgb(float x, float y, uint8_t *rr, uint8_t *rg, uint8_t *rb); - }; @@ -744,167 +658,6 @@ class LightStateClass { * LightStateClass implementation \*********************************************************************************************/ -// new version with only integer computing -// brightness is not needed, it is controlled via Dimmer -void LightStateClass::RgbToHsb(uint8_t ir, uint8_t ig, uint8_t ib, uint16_t *r_hue, uint8_t *r_sat, uint8_t *r_bri) { - uint32_t r = ir; - uint32_t g = ig; - uint32_t b = ib; - uint32_t max = (r > g && r > b) ? r : (g > b) ? g : b; // 0..255 - uint32_t min = (r < g && r < b) ? r : (g < b) ? g : b; // 0..255 - uint32_t d = max - min; // 0..255 - - uint16_t hue = 0; // hue value in degrees ranges from 0 to 359 - uint8_t sat = 0; // 0..255 - uint8_t bri = max; // 0..255 - - if (d != 0) { - sat = changeUIntScale(d, 0, max, 0, 255); - if (r == max) { - hue = (g > b) ? changeUIntScale(g-b,0,d,0,60) : 360 - changeUIntScale(b-g,0,d,0,60); - } else if (g == max) { - hue = (b > r) ? 120 + changeUIntScale(b-r,0,d,0,60) : 120 - changeUIntScale(r-b,0,d,0,60); - } else { - hue = (r > g) ? 240 + changeUIntScale(r-g,0,d,0,60) : 240 - changeUIntScale(g-r,0,d,0,60); - } - hue = hue % 360; // 0..359 - } - - if (r_hue) *r_hue = hue; - if (r_sat) *r_sat = sat; - if (r_bri) *r_bri = bri; - //AddLog_P(LOG_LEVEL_DEBUG_MORE, "RgbToHsb rgb (%d %d %d) hsb (%d %d %d)", r, g, b, hue, sat, bri); -} - -void LightStateClass::HsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b) { - uint32_t r = 255; // default to white - uint32_t g = 255; - uint32_t b = 255; - // we take brightness at 100%, brightness should be set separately - hue = hue % 360; // normalize to 0..359 - - if (sat > 0) { - uint32_t i = hue / 60; // quadrant 0..5 - uint32_t f = hue % 60; // 0..59 - uint32_t q = 255 - changeUIntScale(f, 0, 60, 0, sat); // 0..59 - uint32_t p = 255 - sat; - uint32_t t = 255 - changeUIntScale(60 - f, 0, 60, 0, sat); - - switch (i) { - case 0: - //r = 255; - g = t; - b = p; - break; - case 1: - r = q; - //g = 255; - b = p; - break; - case 2: - r = p; - //g = 255; - b = t; - break; - case 3: - r = p; - g = q; - //b = 255; - break; - case 4: - r = t; - g = p; - //b = 255; - break; - default: - //r = 255; - g = p; - b = q; - break; - } - } - if (r_r) *r_r = r; - if (r_g) *r_g = g; - if (r_b) *r_b = b; -} - -#define POW FastPrecisePowf - -// -// Matrix 3x3 multiplied to a 3 vector, result in a 3 vector -// -void mat3x3(const float *mat33, const float *vec3, float *res3) { - for (uint32_t i = 0; i < 3; i++) { - const float * v = vec3; - *res3 = 0.0f; - for (uint32_t j = 0; j < 3; j++) { - *res3 += *mat33++ * *v++; - } - res3++; - } -} - -void LightStateClass::RgbToXy(uint8_t i_r, uint8_t i_g, uint8_t i_b, float *r_x, float *r_y) { - float x = 0.31271f; // default medium white - float y = 0.32902f; - - if (i_r + i_b + i_g > 0) { - float rgb[3] = { (float)i_r, (float)i_g, (float)i_b }; - // https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d - // Gamma correction - for (uint32_t i = 0; i < 3; i++) { - rgb[i] = rgb[i] / 255.0f; - rgb[i] = (rgb[i] > 0.04045f) ? POW((rgb[i] + 0.055f) / (1.0f + 0.055f), 2.4f) : (rgb[i] / 12.92f); - } - - // conversion to X, Y, Z - // Y is also the Luminance - float XYZ[3]; - static const float XYZ_factors[] = { 0.649926f, 0.103455f, 0.197109f, - 0.234327f, 0.743075f, 0.022598f, - 0.000000f, 0.053077f, 1.035763f }; - mat3x3(XYZ_factors, rgb, XYZ); - - float XYZ_sum = XYZ[0] + XYZ[1] + XYZ[2]; - x = XYZ[0] / XYZ_sum; - y = XYZ[1] / XYZ_sum; - // we keep the raw gamut, one nice thing could be to convert to a narrower gamut - } - if (r_x) *r_x = x; - if (r_y) *r_y = y; -} - -void LightStateClass::XyToRgb(float x, float y, uint8_t *rr, uint8_t *rg, uint8_t *rb) -{ - float XYZ[3], rgb[3]; - x = (x > 0.99f ? 0.99f : (x < 0.01f ? 0.01f : x)); - y = (y > 0.99f ? 0.99f : (y < 0.01f ? 0.01f : y)); - float z = 1.0f - x - y; - XYZ[0] = x / y; - XYZ[1] = 1.0f; - XYZ[2] = z / y; - - static const float rgb_factors[] = { 3.2406f, -1.5372f, -0.4986f, - -0.9689f, 1.8758f, 0.0415f, - 0.0557f, -0.2040f, 1.0570f }; - mat3x3(rgb_factors, XYZ, rgb); - float max = (rgb[0] > rgb[1] && rgb[0] > rgb[2]) ? rgb[0] : (rgb[1] > rgb[2]) ? rgb[1] : rgb[2]; - - for (uint32_t i = 0; i < 3; i++) { - rgb[i] = rgb[i] / max; // normalize to max == 1.0 - rgb[i] = (rgb[i] <= 0.0031308f) ? 12.92f * rgb[i] : 1.055f * POW(rgb[i], (1.0f / 2.4f)) - 0.055f; // gamma - } - - int32_t irgb[3]; - for (uint32_t i = 0; i < 3; i++) { - irgb[i] = rgb[i] * 255.0f + 0.5f; - } - - if (rr) { *rr = (irgb[0] > 255 ? 255: (irgb[0] < 0 ? 0 : irgb[0])); } - if (rg) { *rg = (irgb[1] > 255 ? 255: (irgb[1] < 0 ? 0 : irgb[1])); } - if (rb) { *rb = (irgb[2] > 255 ? 255: (irgb[2] < 0 ? 0 : irgb[2])); } -} - class LightControllerClass { private: LightStateClass *_state; @@ -932,15 +685,6 @@ public: return prev; } - void setAlexaCTRange(bool alexa_ct_range) { - // depending on SetOption82, full or limited CT range - if (alexa_ct_range) { - _state->setCTRange(CT_MIN_ALEXA, CT_MAX_ALEXA); // 200..380 - } else { - _state->setCTRange(CT_MIN, CT_MAX); // 153..500 - } - } - inline bool isCTRGBLinked() { return _ct_rgb_linked; } @@ -1179,63 +923,65 @@ LightStateClass light_state = LightStateClass(); LightControllerClass light_controller = LightControllerClass(light_state); /*********************************************************************************************\ - * Change scales from 8 bits to 10 bits and vice versa + * CT (White Color Temperature) \*********************************************************************************************/ -// 8 to 10 to 8 is guaranteed to give the same result -uint16_t change8to10(uint8_t v) { - return changeUIntScale(v, 0, 255, 0, 1023); -} -// change from 10 bits to 8 bits, but any non-zero input will be non-zero -uint8_t change10to8(uint16_t v) { - return (0 == v) ? 0 : changeUIntScale(v, 4, 1023, 1, 255); -} +// +// Ensure that invariants for Virtual CT are good: +// - CT_MIN <= ct[0] <= ct[1] <= ct[2] <= CT_MAX -/*********************************************************************************************\ - * Gamma correction -\*********************************************************************************************/ -// Calculate the gamma corrected value for LEDS -uint16_t ledGamma_internal(uint16_t v, const struct gamma_table_t *gt_ptr) { - uint16_t from_src = 0; - uint16_t from_gamma = 0; - - for (const gamma_table_t *gt = gt_ptr; ; gt++) { - uint16_t to_src = gt->to_src; - uint16_t to_gamma = gt->to_gamma; - if (v <= to_src) { - return changeUIntScale(v, from_src, to_src, from_gamma, to_gamma); - } - from_src = to_src; - from_gamma = to_gamma; +#ifdef USE_LIGHT_VIRTUAL_CT +void checkVirtualCT(void) { + if (Light.vct_ct[0] < CT_MIN) { Light.vct_ct[0] = CT_MIN; } + if (Light.vct_ct[CT_PIVOTS-1] > CT_MAX) { Light.vct_ct[CT_PIVOTS-1] = CT_MAX; } + for (uint32_t i = 0; i < CT_PIVOTS-1; i++) { + if (Light.vct_ct[i+1] < Light.vct_ct[i]) { Light.vct_ct[i+1] = Light.vct_ct[i]; } } } -// Calculate the reverse gamma value for LEDS -uint16_t ledGammaReverse_internal(uint16_t vg, const struct gamma_table_t *gt_ptr) { - uint16_t from_src = 0; - uint16_t from_gamma = 0; +#endif // USE_LIGHT_VIRTUAL_CT - for (const gamma_table_t *gt = gt_ptr; ; gt++) { - uint16_t to_src = gt->to_src; - uint16_t to_gamma = gt->to_gamma; - if (vg <= to_gamma) { - return changeUIntScale(vg, from_gamma, to_gamma, from_src, to_src); +#ifdef USE_LIGHT_VIRTUAL_CT +// Init default values for virtual CT, depending on the number of channels +void initCTRange(uint32_t channels) { + if (channels == 4) { + if (Settings.flag4.virtual_ct_cw) { // Hardware White is Cold White + memcpy_P(Light.vct_color[0], CT_PIVOTS_CWW, sizeof(Light.vct_color[0])); // Cold white + memcpy_P(Light.vct_color[1], CT_PIVOTS_RGB, sizeof(Light.vct_color[1])); // Warm white + } else { // Hardware White is Warm White + memcpy_P(Light.vct_color[0], CT_PIVOTS_RGB, sizeof(Light.vct_color[0])); // Cold white + memcpy_P(Light.vct_color[1], CT_PIVOTS_CWW, sizeof(Light.vct_color[1])); // Warm white } - from_src = to_src; - from_gamma = to_gamma; + } else if (channels == 5) { + memcpy_P(Light.vct_color[0], CT_PIVOTS_CWW, sizeof(Light.vct_color[0])); // Cold white + memcpy_P(Light.vct_color[1], CT_PIVOTS_WWW, sizeof(Light.vct_color[1])); // Warm white + } else { + memcpy_P(Light.vct_color[0], CT_PIVOTS_RGB, sizeof(Light.vct_color[0])); // Cold white + memcpy_P(Light.vct_color[1], CT_PIVOTS_RGB, sizeof(Light.vct_color[1])); // Warm white + } + for (uint32_t i = 1; i < CT_PIVOTS-1; i++) { + memcpy_P(Light.vct_color[i+1], Light.vct_color[i], sizeof(Light.vct_color[0])); // Copy slot 1 into slot 2 (slot 2 in unused) + } + checkVirtualCT(); +} +#endif // USE_LIGHT_VIRTUAL_CT + +void getCTRange(uint16_t * min_ct, uint16_t * max_ct) { + if (min_ct != nullptr) { *min_ct = Light.vct_ct[0]; } + if (max_ct != nullptr) { *max_ct = Light.vct_ct[CT_PIVOTS-1]; } +} + +void setCTRange(uint16_t ct_min, uint16_t ct_max) { + Light.vct_ct[0] = ct_min; + for (uint32_t i = 1; i < CT_PIVOTS; i++) { + Light.vct_ct[i] = ct_max; // all slots above [1] are not used } } -// 10 bits in, 10 bits out -uint16_t ledGamma10_10(uint16_t v) { - return ledGamma_internal(v, gamma_table); -} -// 10 bits resolution, 8 bits in -uint16_t ledGamma10(uint8_t v) { - return ledGamma10_10(change8to10(v)); -} - -// Legacy function -uint8_t ledGamma(uint8_t v) { - return change10to8(ledGamma10(v)); +void setAlexaCTRange(void) { // depending on SetOption82, full or limited CT range + if (Settings.flag4.alexa_ct_range) { + setCTRange(CT_MIN_ALEXA, CT_MAX_ALEXA); + } else { + setCTRange(CT_MIN, CT_MAX); + } } /********************************************************************************************/ @@ -1299,9 +1045,14 @@ bool LightModuleInit(void) } else if ((Settings.param[P_RGB_REMAP] & 128) && (LST_RGBW <= pwm_channels)) { // SetOption37 // if RGBW or RGBCW, and SetOption37 >= 128, we manage RGB and W separately, hence adding a device TasmotaGlobal.devices_present++; - } else if ((Settings.flag4.virtual_ct) && (LST_RGBW == pwm_channels)) { - Light.virtual_ct = true; // enabled - TasmotaGlobal.light_type++; // create an additional virtual 5th channel + } else { +#ifdef USE_LIGHT_VIRTUAL_CT + initCTRange(pwm_channels); + if ((Settings.flag4.virtual_ct) && (LST_RGB <= pwm_channels)) { + Light.virtual_ct = true; // enabled + TasmotaGlobal.light_type += 5 - pwm_channels; // pretend it is a 5 channels bulb + } +#endif // USE_LIGHT_VIRTUAL_CT } return (TasmotaGlobal.light_type > LT_BASIC); @@ -1367,7 +1118,7 @@ void LightInit(void) light_controller.setSubType(Light.subtype); light_controller.loadSettings(); - light_controller.setAlexaCTRange(Settings.flag4.alexa_ct_range); + setAlexaCTRange(); light_controller.calcLevels(); // calculate the initial values (#8058) if (LST_SINGLE == Light.subtype) { @@ -1457,10 +1208,6 @@ void LightGetXY(float *X, float *Y) { light_state.getXY(X, Y); } -void LightHsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b) { - light_state.HsToRgb(hue, sat, r_r, r_g, r_b); -} - // If SetOption68 is set, get the brightness for a specific device uint8_t LightGetBri(uint8_t device) { uint8_t bri = 254; // default value if relay @@ -1859,7 +1606,6 @@ void LightAnimate(void) bool power_off = false; // make sure we update CT range in case SetOption82 was changed - light_controller.setAlexaCTRange(Settings.flag4.alexa_ct_range); Light.strip_timer_counter++; // set sleep parameter: either settings, @@ -1966,7 +1712,6 @@ void LightAnimate(void) uint16_t cur_col_10[LST_MAX]; // 10 bits resolution Light.update = false; - bool rgbwwtable_applied = false; // did we already applied RGBWWTable (ex: in white_blend_mode or virtual_ct) // first set 8 and 10 bits channels for (uint32_t i = 0; i < LST_MAX; i++) { @@ -1975,58 +1720,19 @@ void LightAnimate(void) cur_col_10[i] = change8to10(Light.new_color[i]); } + bool rgbwwtable_applied_white = false; // did we already applied RGBWWTable to white channels (ex: in white_blend_mode or virtual_ct) if (Light.pwm_multi_channels) { calcGammaMultiChannels(cur_col_10); } else { - calcGammaBulbs(cur_col_10); - - // Now see if we need to mix RGB and True White - // Valid only for LST_RGBW, LST_RGBCW, rgbwwTable[4] is zero, and white is zero (see doc) - if ((LST_RGBW <= Light.subtype) && (Settings.flag4.white_blend_mode) && (0 == cur_col_10[3]+cur_col_10[4])) { - uint32_t min_rgb_10 = min3(cur_col_10[0], cur_col_10[1], cur_col_10[2]); - for (uint32_t i=0; i<3; i++) { - // substract white and adjust according to rgbwwTable - uint32_t adjust10 = change8to10(Settings.rgbwwTable[i]); - cur_col_10[i] = changeUIntScale(cur_col_10[i] - min_rgb_10, 0, 1023, 0, adjust10); - } - - // compute the adjusted white levels for 10 and 8 bits - uint32_t adjust_w_10 = changeUIntScale(Settings.rgbwwTable[3], 0, 255, 0, 1023); - uint32_t white_10 = changeUIntScale(min_rgb_10, 0, 1023, 0, adjust_w_10); // set white power down corrected with rgbwwTable[3] - if (LST_RGBW == Light.subtype) { - // we simply set the white channel - cur_col_10[3] = white_10; - } else { // LST_RGBCW - // we distribute white between cold and warm according to CT value - uint32_t ct = light_state.getCT10bits(); - cur_col_10[4] = changeUIntScale(ct, 0, 1023, 0, white_10); - cur_col_10[3] = white_10 - cur_col_10[4]; - } - rgbwwtable_applied = true; - } else if ((Light.virtual_ct) && (0 == cur_col_10[0]+cur_col_10[1]+cur_col_10[2])) { - // virtual_ct is on and we don't have any RGB set - uint16_t sw_white = Settings.flag4.virtual_ct_cw ? cur_col_10[4] : cur_col_10[3]; // white power for virtual RGB - uint16_t hw_white = Settings.flag4.virtual_ct_cw ? cur_col_10[3] : cur_col_10[4]; // white for hardware LED - uint32_t adjust_sw = change8to10(Settings.flag4.virtual_ct_cw ? Settings.rgbwwTable[4] : Settings.rgbwwTable[3]); - uint32_t adjust_hw = change8to10(Settings.flag4.virtual_ct_cw ? Settings.rgbwwTable[3] : Settings.rgbwwTable[4]); - // set the target channels. Note: Gamma correction was arleady applied - cur_col_10[3] = changeUIntScale(hw_white, 0, 1023, 0, adjust_hw); - cur_col_10[4] = 0; // we don't actually have a 5the channel - sw_white = changeUIntScale(sw_white, 0, 1023, 0, adjust_sw); // pre-adjust virtual channel - for (uint32_t i=0; i<3; i++) { - uint32_t adjust = change8to10(Settings.rgbwwTable[i]); - cur_col_10[i] = changeUIntScale(sw_white, 0, 1023, 0, adjust); - } - rgbwwtable_applied = true; - } + // AddLog_P(LOG_LEVEL_INFO, PSTR(">>> calcGammaBulbs In %03X,%03X,%03X,%03X,%03X"), cur_col_10[0], cur_col_10[1], cur_col_10[2], cur_col_10[3], cur_col_10[4]); + rgbwwtable_applied_white = calcGammaBulbs(cur_col_10); // true means that one PWM channel is used for CT + // AddLog_P(LOG_LEVEL_INFO, PSTR(">>> calcGammaBulbs Out %03X,%03X,%03X,%03X,%03X"), cur_col_10[0], cur_col_10[1], cur_col_10[2], cur_col_10[3], cur_col_10[4]); } // Apply RGBWWTable only if not Settings.flag4.white_blend_mode - if (!rgbwwtable_applied) { - for (uint32_t i = 0; i 1023) ? 1023 : white_bri10; // max 1023 - -#ifdef ESP8266 - if ((PHILIPS == TasmotaGlobal.module_type) || (Settings.flag4.pwm_ct_mode)) { // channel 1 is the color tone, mapped to cold channel (0..255) - // Xiaomi Philips bulbs follow a different scheme: - cur_col_10[cw1] = light_state.getCT10bits(); - // channel 0=intensity, channel1=temperature - if (Settings.light_correction) { // gamma correction - cur_col_10[cw0] = ledGamma10_10(white_bri10_1023); // 10 bits gamma correction - } else { - cur_col_10[cw0] = white_bri10_1023; // no gamma, extend to 10 bits - } - } else -#endif // ESP8266 - if (Settings.light_correction) { - // if sum of both channels is > 255, then channels are probably uncorrelated - if (white_bri10 <= 1031) { // take a margin of 8 above 1023 to account for rounding errors - // we calculate the gamma corrected sum of CW + WW - uint16_t white_bri_gamma10 = ledGamma10_10(white_bri10_1023); - // then we split the total energy among the cold and warm leds - cur_col_10[cw0] = changeUIntScale(cur_col_10[cw0], 0, white_bri10_1023, 0, white_bri_gamma10); - cur_col_10[cw1] = changeUIntScale(cur_col_10[cw1], 0, white_bri10_1023, 0, white_bri_gamma10); - } else { - cur_col_10[cw0] = ledGamma10_10(cur_col_10[cw0]); - cur_col_10[cw1] = ledGamma10_10(cur_col_10[cw1]); - } - } - } +// +// Compute the Gamma correction for CW/WW +// Can be used for 2-channels (channels 0,1) or 5 channels (channels 3,4) +// +// It is implicitly called by calcGammaBulb5Channels() +// +// In: +// - 2 channels CW/WW in 10 bits format (0..1023) +// Out: +// - 2 channels CW/WW in 10 bits format, with Gamma corretion (if enabled), replaced in place +// - white_bri10: global brightness of white channel, split over CW/WW (basically the sum of CW+WW, but it's easier to compute on this basis) +// - white_free_cw: signals that CW/WW are free mode, and not linked via CT. This is used when channels are manually set on a channel per channel basis. CT is ignored +// +void calcGammaBulbCW(uint16_t cw10[2], uint16_t *white_bri10_out, bool *white_free_cw_out) { + uint16_t white_bri10 = cw10[0] + cw10[1]; // cumulated brightness + bool white_free_cw = (white_bri10 > 1031); // take a margin of 8 above 1023 to account for rounding errors + white_bri10 = (white_bri10 > 1023) ? 1023 : white_bri10; // max 1023 if (Settings.light_correction) { - // then apply gamma correction to RGB channels - if (LST_RGB <= Light.subtype) { - for (uint32_t i = 0; i < 3; i++) { - cur_col_10[i] = ledGamma10_10(cur_col_10[i]); - } - } - // If RGBW or Single channel, also adjust White channel - if ((LST_SINGLE == Light.subtype) || (LST_RGBW == Light.subtype)) { - cur_col_10[Light.subtype - 1] = ledGamma10_10(cur_col_10[Light.subtype - 1]); + if (white_free_cw) { + cw10[0] = ledGamma10_10(cw10[0]); + cw10[1] = ledGamma10_10(cw10[1]); + } else { + uint16_t white_bri10_gamma = ledGamma10_10(white_bri10); // gamma corrected white + // now distributed among both channels + cw10[0] = changeUIntScale(cw10[0], 0, white_bri10, 0, white_bri10_gamma); + cw10[1] = changeUIntScale(cw10[1], 0, white_bri10, 0, white_bri10_gamma); + // now use white_bri10_gamma as a reference + white_bri10 = white_bri10_gamma; } } + if (white_bri10_out != nullptr) { *white_bri10_out = white_bri10; } + if (white_free_cw_out != nullptr) { *white_free_cw_out = white_free_cw; } +} + +// +// Calculate the gamma correction for all 5 channels RGBCW +// Computation is valid for 1,3,4,5 channels +// 2-channels bulbs must be handled separately +// +// In: +// - 5 channels RGBCW in 10 bits format (0..1023) +// Out: +// - 5 channels RGBCW in 10 bits format, with Gamma corretion (if enabled), replaced in place +// - white_bri10: global brightness of white channel, split over CW/WW (basically the sum of CW+WW, but it's easier to compute on this basis) +// - white_free_cw: signals that CW/WW are free mode, and not linked via CT. This is used when channels are manually set on a channel per channel basis. CT is ignored +// +void calcGammaBulb5Channels(uint16_t col10[LST_MAX], uint16_t *white_bri10_out, bool *white_free_cw) { + for (uint32_t i = 0; i < 3; i++) { + if (Settings.light_correction) { + col10[i] = ledGamma10_10(col10[i]); + } + } + calcGammaBulbCW(&col10[3], white_bri10_out, white_free_cw); +} + +// sale but converts from 8 bits to 10 bits first +void calcGammaBulb5Channels_8(uint8_t in8[LST_MAX], uint16_t col10[LST_MAX]) { + for (uint32_t i = 0; i < LST_MAX; i++) { + col10[i] = change8to10(in8[i]); + } + calcGammaBulb5Channels(col10, nullptr, nullptr); +} + +bool calcGammaBulbs(uint16_t cur_col_10[5]) { + bool rgbwwtable_applied_white = false; + bool pwm_ct = false; + bool white_free_cw = false; // true if White channels are uncorrelated. Happens when CW+WW>255, i.e. manually setting white channels to exceed to total power of a single channel (may harm the power supply) + // Various values needed for accurate White calculation + // CT value streteched to 0..1023 (from within CT range, so not necessarily from 153 to 500). 0=Cold, 1023=Warm + uint16_t ct = light_state.getCT(); + uint16_t ct_10 = changeUIntScale(ct, Light.vct_ct[0], Light.vct_ct[CT_PIVOTS-1], 0, 1023); + + uint16_t white_bri10 = 0; // White total brightness normalized to 0..1023 + // uint32_t cw1 = Light.subtype - 1; // address for the ColorTone PWM + uint32_t cw0 = Light.subtype - 2; // address for the White Brightness PWM + + // calc basic gamma correction for all types + if ((LST_SINGLE == Light.subtype) || (LST_RGB <= Light.subtype)) { + calcGammaBulb5Channels(cur_col_10, &white_bri10, &white_free_cw); + } else if (LST_COLDWARM == Light.subtype) { + calcGammaBulbCW(cur_col_10, &white_bri10, &white_free_cw); + } + + // Now we know ct_10 and white_bri10 (gamma corrected if needed) + +#ifdef ESP8266 + if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { + if ((PHILIPS == TasmotaGlobal.module_type) || (Settings.flag4.pwm_ct_mode)) { // channel 1 is the color tone, mapped to cold channel (0..255) + pwm_ct = true; + // Xiaomi Philips bulbs follow a different scheme: + // channel 0=intensity, channel1=temperature + cur_col_10[cw0] = white_bri10; + cur_col_10[cw0+1] = ct_10; + return false; // avoid any interference + } + } +#endif // ESP8266 + + // Now see if we need to mix RGB and White + // Valid only for LST_RGBW, LST_RGBCW, SetOption105 1, and white is zero (see doc) + if ((LST_RGBW <= Light.subtype) && (Settings.flag4.white_blend_mode) && (0 == cur_col_10[3]+cur_col_10[4])) { + uint32_t min_rgb_10 = min3(cur_col_10[0], cur_col_10[1], cur_col_10[2]); + cur_col_10[0] -= min_rgb_10; + cur_col_10[1] -= min_rgb_10; + cur_col_10[2] -= min_rgb_10; + + // Add to white level + uint32_t adjust_w_10 = change8to10(Settings.rgbwwTable[3]); // take the correction factor, bought back to 10 bits + white_bri10 += changeUIntScale(min_rgb_10, 0, 1023, 0, adjust_w_10); // set white power down corrected with rgbwwTable[3] + white_bri10 = (white_bri10 > 1023) ? 1023 : white_bri10; // max 1023 + rgbwwtable_applied_white = true; + } + +#ifdef USE_LIGHT_VIRTUAL_CT + // compute virtual CT, which is suppsed to be compatible with white_blend_mode + if (Light.virtual_ct && (!white_free_cw) && (LST_RGBW <= Light.subtype)) { // any light with a white channel + vct_pivot_t *pivot = &Light.vct_color[0]; + uint16_t *from_ct = &Light.vct_ct[0]; + + for (uint32_t i = 1; i < CT_PIVOTS-1; i++) { + if (ct > Light.vct_ct[i]) { // if above mid-point, take range [1]..[2] instead of [0]..[1] + pivot++; + from_ct++; + } + } + uint16_t from10[LST_MAX]; + uint16_t to10[LST_MAX]; + calcGammaBulb5Channels_8(*pivot, from10); + calcGammaBulb5Channels_8(*(pivot+1), to10); + + vct_pivot_t *pivot1 = pivot + 1; + // AddLog_P(LOG_LEVEL_INFO, PSTR("+++ from_ct %d, to_ct %d [%03X,%03X,%03X,%03X,%03X] - [%03X,%03X,%03X,%03X,%03X]"), + // *from_ct, *(from_ct+1), (*pivot)[0], (*pivot)[1], (*pivot)[2], (*pivot)[3], (*pivot)[4], + // (*pivot1)[0], (*pivot1)[1], (*pivot1)[2], (*pivot1)[3], (*pivot1)[4]); + // AddLog_P(LOG_LEVEL_INFO, PSTR("+++ from10 [%03X,%03X,%03X,%03X,%03X] - to 10 [%03X,%03X,%03X,%03X,%03X]"), + // from10[0],from10[0],from10[0],from10[0],from10[4], + // to10[0],to10[0],to10[0],to10[0],to10[4]); + + // set both CW/WW to zero since their previous value don't count anymore + cur_col_10[3] = 0; + cur_col_10[4] = 0; + + // Add the interpolated point to each component + for (uint32_t i = 0; i < LST_MAX; i++) { + cur_col_10[i] += changeUIntScale(changeUIntScale(ct, *from_ct, *(from_ct+1), from10[i], to10[i]), 0, 1023, 0, white_bri10); + if (cur_col_10[i] > 1023) { cur_col_10[i] = 1023; } + } + } else +#endif // USE_LIGHT_VIRTUAL_CT + // compute the actual levels for CW/WW + // We know ct_10 and white_bri_10 (which may be Gamma corrected) + // cur_col_10[cw0] and cur_col_10[cw1] were unmodified up to now + if (LST_RGBW == Light.subtype) { + cur_col_10[3] = white_bri10; // simple case, we set the White level to the required brightness + } else if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { + // if sum of both channels is > 255, then channels are probably uncorrelated + if (!white_free_cw) { + // then we split the total energy among the cold and warm leds + cur_col_10[cw0+1] = changeUIntScale(ct_10, 0, 1023, 0, white_bri10); + cur_col_10[cw0] = white_bri10 - cur_col_10[cw0+1]; + } + } + return rgbwwtable_applied_white; } #ifdef USE_DEVICE_GROUPS @@ -3045,6 +2865,83 @@ void CmndWakeupDuration(void) ResponseCmndNumber(Settings.light_wakeup); } +void CmndCTRange(void) +{ + // Format is "CTRange ctmin,ctmax" + // Ex: + // CTRange 153,500 + // CTRange + // CTRange 200,350 + char *p; + strtok_r(XdrvMailbox.data, ",", &p); + if (p != nullptr) { + int32_t ct_min = strtol(XdrvMailbox.data, nullptr, 0); + int32_t ct_max = strtol(p, nullptr, 0); + if ( (ct_min >= CT_MIN) && (ct_min <= CT_MAX) && + (ct_max >= CT_MIN) && (ct_max <= CT_MAX) && + (ct_min <= ct_max) + ) { + setCTRange(ct_min, ct_max); + } else { + return; // error + } + } + Response_P(PSTR("{\"%s\":\"%d,%d\"}"), XdrvMailbox.command, Light.vct_ct[0], Light.vct_ct[CT_PIVOTS-1]); +} + +#ifdef USE_LIGHT_VIRTUAL_CT +void CmndVirtualCT(void) +{ + if (!Settings.flag4.virtual_ct) { + ResponseCmndChar_P(PSTR("You need to enable `SetOption106 1`")); + return; + } + if (XdrvMailbox.data[0] == ('{')) { + // parse JSON + JsonParser parser(XdrvMailbox.data); + JsonParserObject root = parser.getRootObject(); + if (!root) { return; } + + uint32_t idx = 0; + for (auto key : root) { + if (idx >= CT_PIVOTS) { ResponseCmndChar_P(PSTR("Too many points")); return; } + + int32_t ct_val = strtol(key.getStr(), nullptr, 0); + if ((ct_val < CT_MIN) || (ct_val > CT_MAX)) { ResponseCmndChar_P(PSTR("CT out of range")); return; } + char * color = (char*) key.getValue().getStr(); + // call color parser + Light.vct_ct[idx] = ct_val; + if (LightColorEntry(color, strlen(color))) { + memcpy(&Light.vct_color[idx], Light.entry_color, sizeof(Light.vct_color[idx])); + } + idx++; + } + for (uint32_t i = idx-1; i < CT_PIVOTS-1; i++) { + Light.vct_ct[i+1] = Light.vct_ct[i]; + memcpy(&Light.vct_color[i+1], &Light.vct_color[i], sizeof(Light.vct_color[0])); + } + } + checkVirtualCT(); + + Response_P(PSTR("{\"%s\":{"), XdrvMailbox.command); + uint32_t pivot_len = CT_PIVOTS; + vct_pivot_t * pivot = &Light.vct_color[0]; + if (Light.vct_ct[1] >= Light.vct_ct[2]) { pivot_len = 2; } // only 2 points are valid + + bool end = false; + for (uint32_t i = 0; (i < CT_PIVOTS) && !end; i++) { + if ((i >= CT_PIVOTS-1) || (Light.vct_ct[i] >= Light.vct_ct[i+1])) { + end = true; + } + ResponseAppend_P(PSTR("\"%d\":\"%02X%02X%02X%02X%02X\"%c"), Light.vct_ct[i], + (*pivot)[0], (*pivot)[1], (*pivot)[2], (*pivot)[3], (*pivot)[4], + end ? '}' : ','); + pivot++; + } + ResponseJsonEnd(); +} +#endif // USE_LIGHT_VIRTUAL_CT + #ifdef USE_LIGHT_PALETTE void CmndPalette(void) { diff --git a/tasmota/xdrv_04_light_utils.ino b/tasmota/xdrv_04_light_utils.ino new file mode 100644 index 000000000..8ab379d62 --- /dev/null +++ b/tasmota/xdrv_04_light_utils.ino @@ -0,0 +1,335 @@ +/* + xdrv_04_light_utils.ino - Converter functions for lights + + Copyright (C) 2020 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 . +*/ + +// This file is compiled even if `USE_LIGHT` is not defined and provides +// general purpose converter fucntions + + +// New version of Gamma correction compute +// Instead of a table, we do a multi-linear approximation, which is close enough +// At low levels, the slope is a bit higher than actual gamma, to make changes smoother +// Internal resolution is 10 bits. + +typedef struct gamma_table_t { + uint16_t to_src; + uint16_t to_gamma; +} gamma_table_t; + +const gamma_table_t gamma_table[] = { // don't put in PROGMEM for performance reasons + { 1, 1 }, + { 4, 1 }, + { 209, 13 }, + { 312, 41 }, + { 457, 106 }, + { 626, 261 }, + { 762, 450 }, + { 895, 703 }, + { 1023, 1023 }, + { 0xFFFF, 0xFFFF } // fail-safe if out of range +}; + +// simplified Gamma table for Fade, cheating a little at low brightness +const gamma_table_t gamma_table_fast[] = { + { 384, 192 }, + { 768, 576 }, + { 1023, 1023 }, + { 0xFFFF, 0xFFFF } // fail-safe if out of range +}; + +// For reference, below are the computed gamma tables, via ledGamma() +// for 8 bits output: +// 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, +// 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, +// 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, +// 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, +// 11, 12, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 17, 18, +// 18, 19, 19, 20, 20, 21, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, +// 25, 26, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 36, 37, 38, +// 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, 51, 52, 53, +// 54, 55, 56, 57, 58, 59, 60, 61, 61, 62, 63, 64, 65, 67, 68, 69, +// 71, 72, 73, 75, 76, 78, 79, 80, 82, 83, 85, 86, 87, 89, 90, 91, +// 93, 94, 95, 97, 98,100,101,102,104,105,107,108,109,111,112,114, +// 116,118,120,122,124,125,127,129,131,133,135,137,139,141,143,144, +// 146,148,150,152,154,156,158,160,162,164,166,168,170,171,173,175, +// 178,180,183,185,188,190,193,195,198,200,203,205,208,210,213,215, +// 218,220,223,225,228,230,233,235,238,240,243,245,248,250,253,255 +// +// and for 10 bits output: +// 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, +// 5, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, +// 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, +// 12, 12, 13, 13, 13, 14, 15, 16, 17, 18, 20, 21, 22, 23, 24, 25, +// 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, +// 45, 47, 49, 50, 52, 54, 56, 58, 59, 61, 63, 65, 67, 68, 70, 72, +// 74, 76, 77, 79, 81, 83, 84, 86, 88, 90, 92, 93, 95, 97, 99, 101, +// 102, 104, 106, 110, 113, 117, 121, 124, 128, 132, 135, 139, 143, 146, 150, 154, +// 158, 162, 166, 169, 173, 177, 180, 184, 188, 191, 195, 199, 202, 206, 210, 213, +// 217, 221, 224, 228, 232, 235, 239, 243, 246, 250, 254, 257, 261, 267, 272, 278, +// 283, 289, 294, 300, 305, 311, 317, 322, 328, 333, 339, 344, 350, 356, 361, 367, +// 372, 378, 383, 389, 394, 400, 406, 411, 417, 422, 428, 433, 439, 444, 450, 458, +// 465, 473, 480, 488, 496, 503, 511, 518, 526, 534, 541, 549, 557, 564, 572, 579, +// 587, 595, 602, 610, 617, 627, 635, 642, 650, 657, 665, 673, 680, 688, 695, 703, +// 713, 723, 733, 743, 753, 763, 773, 783, 793, 803, 813, 823, 833, 843, 853, 863, +// 873, 883, 893, 903, 913, 923, 933, 943, 953, 963, 973, 983, 993,1003,1013,1023 +// +// Output for Dimmer 0..100 values +// 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9, +// 10, 10, 11, 12, 12, 13, 15, 17, 21, 23, 26, 28, 31, 34, 37, +// 40, 43, 49, 52, 58, 61, 67, 70, 76, 79, 84, 90, 93, 99,102, +// 110,117,128,135,146,158,166,177,184,195,202,213,221,232,239, +// 250,261,272,289,300,317,328,344,356,372,389,400,417,428,444, +// 458,480,496,518,534,557,579,595,617,635,657,673,695,713,743, +// 773,793,823,843,873,893,923,943,973,993,1023 + + +/*********************************************************************************************\ + * Color converters +\*********************************************************************************************/ + +// new version with only integer computing +// brightness is not needed, it is controlled via Dimmer +void RgbToHsb(uint8_t ir, uint8_t ig, uint8_t ib, uint16_t *r_hue, uint8_t *r_sat, uint8_t *r_bri) { + uint32_t r = ir; + uint32_t g = ig; + uint32_t b = ib; + uint32_t max = (r > g && r > b) ? r : (g > b) ? g : b; // 0..255 + uint32_t min = (r < g && r < b) ? r : (g < b) ? g : b; // 0..255 + uint32_t d = max - min; // 0..255 + + uint16_t hue = 0; // hue value in degrees ranges from 0 to 359 + uint8_t sat = 0; // 0..255 + uint8_t bri = max; // 0..255 + + if (d != 0) { + sat = changeUIntScale(d, 0, max, 0, 255); + if (r == max) { + hue = (g > b) ? changeUIntScale(g-b,0,d,0,60) : 360 - changeUIntScale(b-g,0,d,0,60); + } else if (g == max) { + hue = (b > r) ? 120 + changeUIntScale(b-r,0,d,0,60) : 120 - changeUIntScale(r-b,0,d,0,60); + } else { + hue = (r > g) ? 240 + changeUIntScale(r-g,0,d,0,60) : 240 - changeUIntScale(g-r,0,d,0,60); + } + hue = hue % 360; // 0..359 + } + + if (r_hue) *r_hue = hue; + if (r_sat) *r_sat = sat; + if (r_bri) *r_bri = bri; + //AddLog_P(LOG_LEVEL_DEBUG_MORE, "RgbToHsb rgb (%d %d %d) hsb (%d %d %d)", r, g, b, hue, sat, bri); +} + +void HsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b) { + uint32_t r = 255; // default to white + uint32_t g = 255; + uint32_t b = 255; + // we take brightness at 100%, brightness should be set separately + hue = hue % 360; // normalize to 0..359 + + if (sat > 0) { + uint32_t i = hue / 60; // quadrant 0..5 + uint32_t f = hue % 60; // 0..59 + uint32_t q = 255 - changeUIntScale(f, 0, 60, 0, sat); // 0..59 + uint32_t p = 255 - sat; + uint32_t t = 255 - changeUIntScale(60 - f, 0, 60, 0, sat); + + switch (i) { + case 0: + //r = 255; + g = t; + b = p; + break; + case 1: + r = q; + //g = 255; + b = p; + break; + case 2: + r = p; + //g = 255; + b = t; + break; + case 3: + r = p; + g = q; + //b = 255; + break; + case 4: + r = t; + g = p; + //b = 255; + break; + default: + //r = 255; + g = p; + b = q; + break; + } + } + if (r_r) *r_r = r; + if (r_g) *r_g = g; + if (r_b) *r_b = b; +} + +#define POW FastPrecisePowf + +// +// Matrix 3x3 multiplied to a 3 vector, result in a 3 vector +// +void mat3x3(const float *mat33, const float *vec3, float *res3) { + for (uint32_t i = 0; i < 3; i++) { + const float * v = vec3; + *res3 = 0.0f; + for (uint32_t j = 0; j < 3; j++) { + *res3 += *mat33++ * *v++; + } + res3++; + } +} + +void RgbToXy(uint8_t i_r, uint8_t i_g, uint8_t i_b, float *r_x, float *r_y) { + float x = 0.31271f; // default medium white + float y = 0.32902f; + + if (i_r + i_b + i_g > 0) { + float rgb[3] = { (float)i_r, (float)i_g, (float)i_b }; + // https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d + // Gamma correction + for (uint32_t i = 0; i < 3; i++) { + rgb[i] = rgb[i] / 255.0f; + rgb[i] = (rgb[i] > 0.04045f) ? POW((rgb[i] + 0.055f) / (1.0f + 0.055f), 2.4f) : (rgb[i] / 12.92f); + } + + // conversion to X, Y, Z + // Y is also the Luminance + float XYZ[3]; + static const float XYZ_factors[] = { 0.649926f, 0.103455f, 0.197109f, + 0.234327f, 0.743075f, 0.022598f, + 0.000000f, 0.053077f, 1.035763f }; + mat3x3(XYZ_factors, rgb, XYZ); + + float XYZ_sum = XYZ[0] + XYZ[1] + XYZ[2]; + x = XYZ[0] / XYZ_sum; + y = XYZ[1] / XYZ_sum; + // we keep the raw gamut, one nice thing could be to convert to a narrower gamut + } + if (r_x) *r_x = x; + if (r_y) *r_y = y; +} + +void XyToRgb(float x, float y, uint8_t *rr, uint8_t *rg, uint8_t *rb) +{ + float XYZ[3], rgb[3]; + x = (x > 0.99f ? 0.99f : (x < 0.01f ? 0.01f : x)); + y = (y > 0.99f ? 0.99f : (y < 0.01f ? 0.01f : y)); + float z = 1.0f - x - y; + XYZ[0] = x / y; + XYZ[1] = 1.0f; + XYZ[2] = z / y; + + static const float rgb_factors[] = { 3.2406f, -1.5372f, -0.4986f, + -0.9689f, 1.8758f, 0.0415f, + 0.0557f, -0.2040f, 1.0570f }; + mat3x3(rgb_factors, XYZ, rgb); + float max = (rgb[0] > rgb[1] && rgb[0] > rgb[2]) ? rgb[0] : (rgb[1] > rgb[2]) ? rgb[1] : rgb[2]; + + for (uint32_t i = 0; i < 3; i++) { + rgb[i] = rgb[i] / max; // normalize to max == 1.0 + rgb[i] = (rgb[i] <= 0.0031308f) ? 12.92f * rgb[i] : 1.055f * POW(rgb[i], (1.0f / 2.4f)) - 0.055f; // gamma + } + + int32_t irgb[3]; + for (uint32_t i = 0; i < 3; i++) { + irgb[i] = rgb[i] * 255.0f + 0.5f; + } + + if (rr) { *rr = (irgb[0] > 255 ? 255: (irgb[0] < 0 ? 0 : irgb[0])); } + if (rg) { *rg = (irgb[1] > 255 ? 255: (irgb[1] < 0 ? 0 : irgb[1])); } + if (rb) { *rb = (irgb[2] > 255 ? 255: (irgb[2] < 0 ? 0 : irgb[2])); } +} + +/*********************************************************************************************\ + * Change scales from 8 bits to 10 bits and vice versa +\*********************************************************************************************/ +// 8 to 10 to 8 is guaranteed to give the same result +uint16_t change8to10(uint8_t v) { + return changeUIntScale(v, 0, 255, 0, 1023); +} +// change from 10 bits to 8 bits, but any non-zero input will be non-zero +uint8_t change10to8(uint16_t v) { + return (0 == v) ? 0 : changeUIntScale(v, 4, 1023, 1, 255); +} + +/*********************************************************************************************\ + * Gamma correction +\*********************************************************************************************/ +// Calculate the gamma corrected value for LEDS +uint16_t ledGamma_internal(uint16_t v, const struct gamma_table_t *gt_ptr) { + uint16_t from_src = 0; + uint16_t from_gamma = 0; + + for (const gamma_table_t *gt = gt_ptr; ; gt++) { + uint16_t to_src = gt->to_src; + uint16_t to_gamma = gt->to_gamma; + if (v <= to_src) { + return changeUIntScale(v, from_src, to_src, from_gamma, to_gamma); + } + from_src = to_src; + from_gamma = to_gamma; + } +} +// Calculate the reverse gamma value for LEDS +uint16_t ledGammaReverse_internal(uint16_t vg, const struct gamma_table_t *gt_ptr) { + uint16_t from_src = 0; + uint16_t from_gamma = 0; + + for (const gamma_table_t *gt = gt_ptr; ; gt++) { + uint16_t to_src = gt->to_src; + uint16_t to_gamma = gt->to_gamma; + if (vg <= to_gamma) { + return changeUIntScale(vg, from_gamma, to_gamma, from_src, to_src); + } + from_src = to_src; + from_gamma = to_gamma; + } +} + +// 10 bits in, 10 bits out +uint16_t ledGamma10_10(uint16_t v) { + return ledGamma_internal(v, gamma_table); +} + +// 10 bits resolution, 8 bits in +uint16_t ledGamma10(uint8_t v) { + return ledGamma10_10(change8to10(v)); +} + +// Legacy function +uint8_t ledGamma(uint8_t v) { + return change10to8(ledGamma10(v)); +} + +// Fast versions for Fading +uint16_t ledGammaFast(uint16_t v) { + return ledGamma_internal(v, gamma_table_fast); +} + +uint16_t leddGammaReverseFast(uint16_t vg) { + return ledGammaReverse_internal(vg, gamma_table_fast); +} \ No newline at end of file diff --git a/tasmota/xdrv_05_irremote.ino b/tasmota/xdrv_05_irremote.ino index 6e3bad365..44304c550 100644 --- a/tasmota/xdrv_05_irremote.ino +++ b/tasmota/xdrv_05_irremote.ino @@ -1,7 +1,7 @@ /* xdrv_05_irremote.ino - infra red support for Tasmota - Copyright (C) 2020 Heiko Krupp, Lazar Obradovic and Theo Arends + Copyright (C) 2021 Heiko Krupp, Lazar Obradovic and 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 @@ -62,6 +62,12 @@ def ir_expand(ir_compact): #include #include +// Receiving IR while sending at the same time (i.e. receiving your own signal) was dsiabled in #10041 +// At the demand of @pilaGit, you can `#define IR_RCV_WHILE_SENDING 1` to bring back this behavior +#ifndef IR_RCV_WHILE_SENDING +#define IR_RCV_WHILE_SENDING 0 +#endif + enum IrErrors { IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND, IE_PROTO_UNSUPPORTED }; const char kIrRemoteCommands[] PROGMEM = "|" D_CMND_IRSEND ; @@ -122,7 +128,7 @@ IRsend *irsend = nullptr; void IrSendInit(void) { - irsend = new IRsend(Pin(GPIO_IRSEND)); // an IR led is at GPIO_IRSEND + irsend = new IRsend(Pin(GPIO_IRSEND), IR_SEND_INVERTED, IR_SEND_USE_MODULATION); // an IR led is at GPIO_IRSEND irsend->begin(); } @@ -291,7 +297,7 @@ uint32_t IrRemoteCmndIrSendJson(void) protocol_text, protocol, bits, ulltoa(data, dvalue, 10), Uint64toHex(data, hvalue, bits), repeat, protocol_code); #ifdef USE_IR_RECEIVE - if (irrecv != nullptr) { irrecv->disableIRIn(); } + if (!IR_RCV_WHILE_SENDING && (irrecv != nullptr)) { irrecv->disableIRIn(); } #endif // USE_IR_RECEIVE switch (protocol_code) { // Equals IRremoteESP8266.h enum decode_type_t @@ -309,12 +315,12 @@ uint32_t IrRemoteCmndIrSendJson(void) #endif default: #ifdef USE_IR_RECEIVE - if (irrecv != nullptr) { irrecv->enableIRIn(); } + if (!IR_RCV_WHILE_SENDING && (irrecv != nullptr)) { irrecv->enableIRIn(); } #endif // USE_IR_RECEIVE return IE_PROTO_UNSUPPORTED; } #ifdef USE_IR_RECEIVE - if (irrecv != nullptr) { irrecv->enableIRIn(); } + if (!IR_RCV_WHILE_SENDING && (irrecv != nullptr)) { irrecv->enableIRIn(); } #endif // USE_IR_RECEIVE return IE_NO_ERROR; diff --git a/tasmota/xdrv_05_irremote_full.ino b/tasmota/xdrv_05_irremote_full.ino index ce75d09db..bed0e8199 100644 --- a/tasmota/xdrv_05_irremote_full.ino +++ b/tasmota/xdrv_05_irremote_full.ino @@ -1,7 +1,7 @@ /* xdrv_05_irremote_full.ino - complete integration of IRremoteESP8266 for Tasmota - Copyright (C) 2020 Heiko Krupp, Lazar Obradovic, Theo Arends, Stephan Hadinger + Copyright (C) 2021 Heiko Krupp, Lazar Obradovic, Theo Arends, Stephan Hadinger 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 @@ -65,6 +65,12 @@ def ir_expand(ir_compact): #include #include +// Receiving IR while sending at the same time (i.e. receiving your own signal) was dsiabled in #10041 +// At the demand of @pilaGit, you can `#define IR_RCV_WHILE_SENDING 1` to bring back this behavior +#ifndef IR_RCV_WHILE_SENDING +#define IR_RCV_WHILE_SENDING 0 +#endif + enum IrErrors { IE_RESPONSE_PROVIDED, IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND, IE_SYNTAX_IRHVAC, IE_UNSUPPORTED_HVAC, IE_UNSUPPORTED_PROTOCOL, IE_MEMORY }; @@ -130,7 +136,7 @@ StateModes strToStateMode(class JsonParserToken token, StateModes def); // decla void IrSendInit(void) { - irsend = new IRsend(Pin(GPIO_IRSEND)); // an IR led is at GPIO_IRSEND + irsend = new IRsend(Pin(GPIO_IRSEND), IR_SEND_INVERTED, IR_SEND_USE_MODULATION); // an IR led is at GPIO_IRSEND irsend->begin(); } @@ -462,16 +468,16 @@ uint32_t IrRemoteCmndIrHvacJson(void) state.sleep = root.getInt(PSTR(D_JSON_IRHVAC_SLEEP), state.sleep); //if (json[D_JSON_IRHVAC_CLOCK]) { state.clock = json[D_JSON_IRHVAC_CLOCK]; } // not sure it's useful to support 'clock' - if (irrecv != nullptr) { irrecv->disableIRIn(); } + if (!IR_RCV_WHILE_SENDING && (irrecv != nullptr)) { irrecv->disableIRIn(); } if (stateMode == StateModes::SEND_ONLY || stateMode == StateModes::SEND_STORE) { - IRac ac(Pin(GPIO_IRSEND)); + IRac ac(Pin(GPIO_IRSEND), IR_SEND_INVERTED, IR_SEND_USE_MODULATION); bool success = ac.sendAc(state, irhvac_stateful && irac_prev_state.protocol == state.protocol ? &irac_prev_state : nullptr); if (!success) { return IE_SYNTAX_IRHVAC; } } if (stateMode == StateModes::STORE_ONLY || stateMode == StateModes::SEND_STORE) { // store state in memory irac_prev_state = state; } - if (irrecv != nullptr) { irrecv->enableIRIn(); } + if (!IR_RCV_WHILE_SENDING && (irrecv != nullptr)) { irrecv->enableIRIn(); } Response_P(PSTR("{\"" D_CMND_IRHVAC "\":%s}"), sendACJsonState(state).c_str()); return IE_RESPONSE_PROVIDED; @@ -529,9 +535,9 @@ uint32_t IrRemoteCmndIrSendJson(void) // AddLog_P(LOG_LEVEL_DEBUG, PSTR("IRS: protocol %d, bits %d, data 0x%s (%s), repeat %d"), // protocol, bits, ulltoa(data, dvalue, 10), Uint64toHex(data, hvalue, bits), repeat); - if (irrecv != nullptr) { irrecv->disableIRIn(); } + if (!IR_RCV_WHILE_SENDING && (irrecv != nullptr)) { irrecv->disableIRIn(); } bool success = irsend->send(protocol, data, bits, repeat); - if (irrecv != nullptr) { irrecv->enableIRIn(); } + if (!IR_RCV_WHILE_SENDING && (irrecv != nullptr)) { irrecv->enableIRIn(); } if (!success) { ResponseCmndChar(D_JSON_PROTOCOL_NOT_SUPPORTED); @@ -554,11 +560,11 @@ uint32_t IrRemoteSendGC(char ** pp, uint32_t count, uint32_t repeat) { GC[i] = strtol(strtok_r(nullptr, ",", pp), nullptr, 0); if (!GC[i]) { return IE_INVALID_RAWDATA; } } - if (irrecv != nullptr) { irrecv->disableIRIn(); } + if (!IR_RCV_WHILE_SENDING && (irrecv != nullptr)) { irrecv->disableIRIn(); } for (uint32_t r = 0; r <= repeat; r++) { irsend->sendGC(GC, count+1); } - if (irrecv != nullptr) { irrecv->enableIRIn(); } + if (!IR_RCV_WHILE_SENDING && (irrecv != nullptr)) { irrecv->enableIRIn(); } return IE_NO_ERROR; } @@ -609,7 +615,7 @@ uint32_t IrRemoteSendRawFormatted(char ** pp, uint32_t count, uint32_t repeat) { raw_array[i++] = mark; // Mark } } - if (irrecv != nullptr) { irrecv->disableIRIn(); } + if (!IR_RCV_WHILE_SENDING && (irrecv != nullptr)) { irrecv->disableIRIn(); } for (uint32_t r = 0; r <= repeat; r++) { // AddLog_P(LOG_LEVEL_DEBUG, PSTR("sendRaw count=%d, space=%d, mark=%d, freq=%d"), count, space, mark, freq); irsend->sendRaw(raw_array, i, freq); @@ -617,7 +623,7 @@ uint32_t IrRemoteSendRawFormatted(char ** pp, uint32_t count, uint32_t repeat) { irsend->space(40000); // since we don't know the inter-message gap, place an arbitrary 40ms gap } } - if (irrecv != nullptr) { irrecv->enableIRIn(); } + if (!IR_RCV_WHILE_SENDING && (irrecv != nullptr)) { irrecv->enableIRIn(); } } else if (6 == count) { // NEC Protocol // IRsend raw,0,8620,4260,544,411,1496,010101101000111011001110000000001100110000000001100000000000000010001100 uint16_t raw_array[strlen(*pp)*2+3]; // Header + bits + end @@ -636,7 +642,7 @@ uint32_t IrRemoteSendRawFormatted(char ** pp, uint32_t count, uint32_t repeat) { } } raw_array[i++] = parm[2]; // Trailing mark - if (irrecv != nullptr) { irrecv->disableIRIn(); } + if (!IR_RCV_WHILE_SENDING && (irrecv != nullptr)) { irrecv->disableIRIn(); } for (uint32_t r = 0; r <= repeat; r++) { // AddLog_P(LOG_LEVEL_DEBUG, PSTR("sendRaw %d %d %d %d %d %d"), raw_array[0], raw_array[1], raw_array[2], raw_array[3], raw_array[4], raw_array[5]); irsend->sendRaw(raw_array, i, freq); @@ -644,7 +650,7 @@ uint32_t IrRemoteSendRawFormatted(char ** pp, uint32_t count, uint32_t repeat) { irsend->space(inter_message); // since we don't know the inter-message gap, place an arbitrary 40ms gap } } - if (irrecv != nullptr) { irrecv->enableIRIn(); } + if (!IR_RCV_WHILE_SENDING && (irrecv != nullptr)) { irrecv->enableIRIn(); } } else { return IE_INVALID_RAWDATA; } // Invalid number of parameters return IE_NO_ERROR; @@ -713,11 +719,11 @@ uint32_t IrRemoteSendRawStandard(char ** pp, uint16_t freq, uint32_t count, uint // AddLog_P(LOG_LEVEL_DEBUG, PSTR("Arr %d %d %d %d %d %d %d %d"), arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7]); if (0 == count) { return IE_INVALID_RAWDATA; } - if (irrecv != nullptr) { irrecv->disableIRIn(); } + if (!IR_RCV_WHILE_SENDING && (irrecv != nullptr)) { irrecv->disableIRIn(); } for (uint32_t r = 0; r <= repeat; r++) { irsend->sendRaw(arr, count, freq); } - if (irrecv != nullptr) { irrecv->enableIRIn(); } + if (!IR_RCV_WHILE_SENDING && (irrecv != nullptr)) { irrecv->enableIRIn(); } if (nullptr != arr) { free(arr); diff --git a/tasmota/xdrv_06_snfbridge.ino b/tasmota/xdrv_06_snfbridge.ino index 735913ed4..bb77d64c2 100644 --- a/tasmota/xdrv_06_snfbridge.ino +++ b/tasmota/xdrv_06_snfbridge.ino @@ -1,7 +1,7 @@ /* xdrv_06_snfbridge.ino - sonoff RF bridge 433 support for Tasmota - Copyright (C) 2020 Theo Arends and Erik Andrén Zachrisson (fw update) + Copyright (C) 2021 Theo Arends and Erik Andrén Zachrisson (fw update) 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 diff --git a/tasmota/xdrv_07_domoticz.ino b/tasmota/xdrv_07_domoticz.ino index e43ed1ce4..82b769963 100644 --- a/tasmota/xdrv_07_domoticz.ino +++ b/tasmota/xdrv_07_domoticz.ino @@ -1,7 +1,7 @@ /* xdrv_07_domoticz.ino - domoticz support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xdrv_08_serial_bridge.ino b/tasmota/xdrv_08_serial_bridge.ino index 01e1cc5f0..eda328719 100644 --- a/tasmota/xdrv_08_serial_bridge.ino +++ b/tasmota/xdrv_08_serial_bridge.ino @@ -1,7 +1,7 @@ /* xdrv_08_serial_bridge.ino - serial bridge support for Tasmota - Copyright (C) 2020 Theo Arends and Dániel Zoltán Tolnai + Copyright (C) 2021 Theo Arends and Dániel Zoltán Tolnai 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 diff --git a/tasmota/xdrv_09_timers.ino b/tasmota/xdrv_09_timers.ino index 543da7d25..c40045a31 100644 --- a/tasmota/xdrv_09_timers.ino +++ b/tasmota/xdrv_09_timers.ino @@ -1,7 +1,7 @@ /* xdrv_09_timers.ino - timer support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 @@ -880,7 +880,7 @@ void HandleTimerConfiguration(void) void TimerSaveSettings(void) { char tmp[MAX_TIMERS *12]; // Need space for MAX_TIMERS x 10 digit numbers separated by a comma - char message[LOGSZ]; + char message[32 + (MAX_TIMERS *11)]; // MQT: Timers 0,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000 Timer timer; Settings.flag3.timers_enable = Webserver->hasArg("e0"); // CMND_TIMERS diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino index 9a91c9a38..8d8fefc13 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/xdrv_10_rules.ino @@ -1,7 +1,7 @@ /* xdrv_10_rules.ino - rule support for Tasmota - Copyright (C) 2020 ESP Easy Group and Theo Arends + Copyright (C) 2021 ESP Easy Group and 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 diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index c43f47826..44c4e2b21 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -1,7 +1,7 @@ /* xdrv_10_scripter.ino - script support for Tasmota - Copyright (C) 2020 Gerhard Mutz and Theo Arends + Copyright (C) 2021 Gerhard Mutz and 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 @@ -499,6 +499,17 @@ uint8_t fast_script=0; uint8_t glob_script=0; uint32_t script_lastmillis; +void Script_AddLog_P(uint32_t loglevel, PGM_P formatP, ...) { + char log_data[128]; + + va_list arg; + va_start(arg, formatP); + vsnprintf_P(log_data, sizeof(log_data), formatP, arg); + va_end(arg); + + AddLogData(loglevel, log_data); +} + void flt2char(float num, char *nbuff) { dtostrfd(num, glob_script_mem.script_dprec, nbuff); } @@ -578,7 +589,9 @@ float *Get_MFAddr(uint8_t index, uint16_t *len, uint16_t *ipos); int16_t Init_Scripter(void) { char *script; + int16_t err = 0; script = glob_script_mem.script_ram; + if (!*script) return -999; // scan lines for >DEF uint16_t lines = 0; @@ -586,15 +599,56 @@ char *script; uint16_t svars = 0; uint16_t vars = 0; char *lp = script; - char vnames[MAXVARS*10]; - char *vnames_p = vnames; + uint16_t imemsize = (MAXVARS*10) + 4; + uint8_t *imemptr = (uint8_t*)calloc(imemsize, 1); + if (!imemptr) { + return -7; + } + + //ClaimSerial(); + //SetSerialBaudrate(115200); + //Serial.printf("size %d\n",imemsize); + //Serial.printf("stack %d\n",GetStack()); // 2848 + // 2896 + //char vnames[MAXVARS*10]; + char *vnames = (char*)imemptr; + char *vnp[MAXVARS]; + float fvalues[MAXVARS]; + struct T_INDEX vtypes[MAXVARS]; + +/* + uint32_t imemp = (uint32_t)imemptr; + imemp += (MAXVARS*10); + imemp = (imemp & 0xfffc) + 4; + Serial.printf(">1 %x\n",imemp); + char *vnp[MAXVARS]; + + //char **vnp = (char**)imemp; + imemp += (sizeof(char*)*MAXVARS); + imemp = (imemp & 0xfffc) + 4; + Serial.printf(">2 %x\n",imemp); + + float fvalues[MAXVARS]; + //float *fvalues = (float*)imemp; + imemp += (sizeof(float*)*MAXVARS); + imemp = (imemp & 0xfffc) + 4; + Serial.printf(">3 %x\n",imemp); + + struct T_INDEX vtypes[MAXVARS]; + //struct T_INDEX *vtypes = (struct T_INDEX*)imemp; +*/ + + char *vnames_p = vnames; char **vnp_p = vnp; + char strings[MAXSVARS*SCRIPT_MAXSSIZE]; + char *snp[MAXSVARS]; + struct M_FILT mfilt[MAXFILT]; char *strings_p = strings; - char *snp[MAXSVARS]; + char **snp_p = snp; uint8_t numperm = 0; uint8_t numflt = 0; @@ -603,10 +657,6 @@ char *script; glob_script_mem.max_ssize = SCRIPT_SVARSIZE; glob_script_mem.scriptptr = 0; - if (!*script) return -999; - - float fvalues[MAXVARS]; - struct T_INDEX vtypes[MAXVARS]; char init = 0; while (1) { // check line @@ -674,6 +724,7 @@ char *script; vtypes[vars].index = numflt; numflt++; if (numflt>MAXFILT) { + if (imemptr) free(imemptr); return -6; } } else { @@ -699,6 +750,7 @@ char *script; if (!vtypes[vars].bits.is_filter) vtypes[vars].index = nvars; nvars++; if (nvars>MAXNVARS) { + if (imemptr) free(imemptr); return -1; } if (vtypes[vars].bits.is_filter) { @@ -731,11 +783,13 @@ char *script; vtypes[vars].index = svars; svars++; if (svars>MAXSVARS) { + if (imemptr) free(imemptr); return -2; } } vars++; if (vars>MAXVARS) { + if (imemptr) free(imemptr); return -3; } } @@ -786,6 +840,7 @@ char *script; uint8_t *script_mem; script_mem = (uint8_t*)calloc(script_mem_size, 1); if (!script_mem) { + if (imemptr) free(imemptr); return -4; } glob_script_mem.script_mem = script_mem; @@ -841,7 +896,6 @@ char *script; //memcpy(script_mem,strings,size); script_mem += size; - // now must recalc memory offsets uint16_t index = 0; #ifdef SCRIPT_LARGE_VNBUFF @@ -864,11 +918,13 @@ char *script; index++; if (index > MAXVNSIZ) { free(glob_script_mem.script_mem); + if (imemptr) free(imemptr); return -5; } } + // variables usage info - AddLog_P(LOG_LEVEL_INFO, PSTR("Script: nv=%d, tv=%d, vns=%d, ram=%d"), nvars, svars, index, glob_script_mem.script_mem_size); + Script_AddLog_P(LOG_LEVEL_INFO, PSTR("Script: nv=%d, tv=%d, vns=%d, ram=%d"), nvars, svars, index, glob_script_mem.script_mem_size); // copy string variables char *cp1 = glob_script_mem.glob_snp; @@ -940,7 +996,6 @@ char *script; } } - #ifdef USE_SCRIPT_FATFS if (!glob_script_mem.script_sd_found) { @@ -985,8 +1040,10 @@ char *script; } #endif //USE_SCRIPT_GLOBVARS - return 0; - + if (imemptr) { + free(imemptr); + } + return err; } #ifdef USE_SCRIPT_FATFS @@ -1072,10 +1129,10 @@ void Script_Init_UDP() { if (glob_script_mem.udp_flags.udp_connected) return; if (Script_PortUdp.beginMulticast(WiFi.localIP(), IPAddress(239,255,255,250), SCRIPT_UDP_PORT)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP "SCRIPT UDP started")); + Script_AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP "SCRIPT UDP started")); glob_script_mem.udp_flags.udp_connected = 1; } else { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP "SCRIPT UDP failed")); + Script_AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP "SCRIPT UDP failed")); glob_script_mem.udp_flags.udp_connected = 0; } } @@ -1089,7 +1146,7 @@ void Script_PollUdp(void) { int32_t len = Script_PortUdp.read(packet_buffer, SCRIPT_UDP_BUFFER_SIZE - 1); packet_buffer[len] = 0; script_udp_remote_ip = Script_PortUdp.remoteIP(); - AddLog_P(LOG_LEVEL_DEBUG, PSTR("UDP: Packet %s - %d - %s"), packet_buffer, len, script_udp_remote_ip.toString().c_str()); + Script_AddLog_P(LOG_LEVEL_DEBUG, PSTR("UDP: Packet %s - %d - %s"), packet_buffer, len, script_udp_remote_ip.toString().c_str()); char *lp=packet_buffer; if (!strncmp(lp,"=>", 2)) { lp += 2; @@ -1108,10 +1165,10 @@ void Script_PollUdp(void) { uint32_t index; uint32_t res = match_vars(vnam, &fp, &sp, &index); if (res == NUM_RES) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("num var found - %s - %d - %d"), vnam, res, index); + Script_AddLog_P(LOG_LEVEL_DEBUG, PSTR("num var found - %s - %d - %d"), vnam, res, index); *fp=CharToFloat(cp + 1); } else if (res == STR_RES) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("string var found - %s - %d - %d"), vnam, res, index); + Script_AddLog_P(LOG_LEVEL_DEBUG, PSTR("string var found - %s - %d - %d"), vnam, res, index); strlcpy(sp, cp + 1, SCRIPT_MAXSSIZE); } else { // error var not found @@ -1145,10 +1202,10 @@ void script_udp_sendvar(char *vname,float *fp,char *sp) { char flstr[16]; dtostrfd(*fp, 8, flstr); strcat(sbuf, flstr); - AddLog_P(LOG_LEVEL_DEBUG, PSTR("num var updated - %s"), sbuf); + Script_AddLog_P(LOG_LEVEL_DEBUG, PSTR("num var updated - %s"), sbuf); } else { strcat(sbuf, sp); - AddLog_P(LOG_LEVEL_DEBUG, PSTR("string var updated - %s"), sbuf); + Script_AddLog_P(LOG_LEVEL_DEBUG, PSTR("string var updated - %s"), sbuf); } Script_PortUdp.beginPacket(IPAddress(239, 255, 255, 250), SCRIPT_UDP_PORT); // Udp.print(String("RET UC: ") + String(recv_Packet)); @@ -1251,7 +1308,7 @@ float Get_MFVal(uint8_t index, int16_t bind) { if (bind<0) { return maxind; } - if (bind<1 || bind>maxind) bind = maxind; + if (bind < 1 || bind > maxind ) bind = 1; return mflp->rbuff[bind - 1]; } mp += sizeof(struct M_FILT) + ((mflp->numvals & AND_FILT_MASK) - 1) * sizeof(float); @@ -1266,10 +1323,12 @@ void Set_MFVal(uint8_t index, uint16_t bind, float val) { if (count==index) { uint16_t maxind = mflp->numvals & AND_FILT_MASK; if (!bind) { + if (val < 0 || val >= maxind) val = 0; mflp->index = val; } else { - if (bind<1 || bind>maxind) bind = maxind; - mflp->rbuff[bind-1] = val; + if (bind >= 1 && bind <= maxind) { + mflp->rbuff[bind-1] = val; + } } return; } @@ -2051,7 +2110,7 @@ chknext: if (!glob_script_mem.file_flags[cnt].is_open) { if (mode==0) { #ifdef DEBUG_FS - AddLog_P(LOG_LEVEL_INFO, PSTR("open file for read %d"), cnt); + Script_AddLog_P(LOG_LEVEL_INFO, PSTR("open file for read %d"), cnt); #endif glob_script_mem.files[cnt] = fsp->open(str, FILE_READ); if (glob_script_mem.files[cnt].isDirectory()) { @@ -2065,12 +2124,12 @@ chknext: if (mode==1) { glob_script_mem.files[cnt] = fsp->open(str,FILE_WRITE); #ifdef DEBUG_FS - AddLog_P(LOG_LEVEL_INFO, PSTR("open file for write %d"), cnt); + Script_AddLog_P(LOG_LEVEL_INFO, PSTR("open file for write %d"), cnt); #endif } else { glob_script_mem.files[cnt] = fsp->open(str,FILE_APPEND); #ifdef DEBUG_FS - AddLog_P(LOG_LEVEL_INFO, PSTR("open file for append %d"), cnt); + Script_AddLog_P(LOG_LEVEL_INFO, PSTR("open file for append %d"), cnt); #endif } } @@ -2078,7 +2137,7 @@ chknext: fvar = cnt; glob_script_mem.file_flags[cnt].is_open = 1; } else { - AddLog_P(LOG_LEVEL_INFO, PSTR("file open failed")); + Script_AddLog_P(LOG_LEVEL_INFO, PSTR("file open failed")); } break; } @@ -2093,7 +2152,7 @@ chknext: uint8_t ind = fvar; if (ind>=SFS_MAX) ind = SFS_MAX - 1; #ifdef DEBUG_FS - AddLog_P(LOG_LEVEL_INFO, PSTR("closing file %d"), ind); + Script_AddLog_P(LOG_LEVEL_INFO, PSTR("closing file %d"), ind); #endif glob_script_mem.files[ind].close(); glob_script_mem.file_flags[ind].is_open = 0; @@ -2229,7 +2288,7 @@ chknext: } else { fvar = 0; } - //AddLog_P(LOG_LEVEL_INFO, PSTR("picture save: %d"), len); + //Script_AddLog_P(LOG_LEVEL_INFO, PSTR("picture save: %d"), len); } else { fvar = 0; } @@ -2407,6 +2466,10 @@ chknext: #endif goto exit; } + if (!strncmp(vname, "frnm", 4)) { + if (sp) strlcpy(sp, SettingsText(SET_FRIENDLYNAME1), glob_script_mem.max_ssize); + goto strexit; + } break; case 'g': if (!strncmp(vname, "gtmp", 4)) { @@ -2783,6 +2846,17 @@ chknext: len++; goto exit; } +#if defined(ESP32) && (defined(USE_M5STACK_CORE2)) + if (!strncmp(vname, "rec(", 4)) { + char str[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp + 4, OPER_EQU, str, 0); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0); + fvar = i2s_record(str, fvar); + len++; + goto exit; + } +#endif break; case 's': if (!strncmp(vname, "secs", 4)) { @@ -3607,7 +3681,7 @@ void Replace_Cmd_Vars(char *srcbuf, uint32_t srcsize, char *dstbuf, uint32_t dst void toLog(const char *str) { if (!str) return; - AddLog_P(LOG_LEVEL_INFO, str); + Script_AddLog_P(LOG_LEVEL_INFO, str); } @@ -3622,7 +3696,7 @@ void toLogN(const char *cp, uint8_t len) { void toLogEOL(const char *s1,const char *str) { if (!str) return; uint8_t index = 0; - char log_data[LOGSZ]; + char log_data[MAX_LOGSZ]; char *cp = log_data; strcpy(cp, s1); cp += strlen(s1); @@ -3800,8 +3874,9 @@ void esp32_beep(int32_t freq ,uint32_t len) { uint8_t pwmpin[5]; void esp_pwm(int32_t value, uint32 freq, uint32_t channel) { - if (channel < 1 || channel > 3) channel = 1; + #ifdef ESP32 + if (channel < 1 || channel > 8) channel = 1; channel+=7; if (value < 0) { if (value <= -64) value = 0; @@ -3817,6 +3892,7 @@ void esp_pwm(int32_t value, uint32 freq, uint32_t channel) { } #else // esp8266 default to range 0-1023 + if (channel < 1 || channel > 5) channel = 1; channel-=1; if (value < 0) { if (value <= -64) value = 0; @@ -4313,7 +4389,7 @@ int16_t Run_script_sub(const char *type, int8_t tlen, JsonParserObject *jo) { } cmd[count] = *lp++; } - //AddLog_P(LOG_LEVEL_INFO, tmp); + //Script_AddLog_P(LOG_LEVEL_INFO, tmp); // replace vars in cmd char *tmp = cmdmem + SCRIPT_CMDMEM / 2; Replace_Cmd_Vars(cmd, 0, tmp, SCRIPT_CMDMEM / 2); @@ -4325,7 +4401,7 @@ int16_t Run_script_sub(const char *type, int8_t tlen, JsonParserObject *jo) { } else { if (!sflag) { tasm_cmd_activ = 1; - AddLog_P(glob_script_mem.script_loglevel&0x7f, PSTR("Script: performs \"%s\""), tmp); + Script_AddLog_P(glob_script_mem.script_loglevel&0x7f, PSTR("Script: performs \"%s\""), tmp); } else if (sflag==2) { // allow recursive call } else { @@ -4848,13 +4924,13 @@ uint8_t sc_state; // upload script and start immediately void script_upload_start(void) { - //AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: file upload execute")); + //Script_AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: file upload execute")); HTTPUpload& upload = Webserver->upload(); if (upload.status == UPLOAD_FILE_START) { - //AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload start")); + //Script_AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload start")); script_ex_ptr = (uint8_t*)glob_script_mem.script_ram; - //AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload file %s, %d"),upload.filename.c_str(),upload.totalSize); + //Script_AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload file %s, %d"),upload.filename.c_str(),upload.totalSize); if (strcmp(upload.filename.c_str(), "execute_script")) { Web.upload_error = 1; @@ -4872,7 +4948,7 @@ void script_upload_start(void) { bitWrite(Settings.rule_enabled, 0, 0); } else if(upload.status == UPLOAD_FILE_WRITE) { - //AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload write")); + //Script_AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload write")); uint32_t csiz = upload.currentSize; uint32_t tsiz = glob_script_mem.script_size - 1; if (uplsizeupload(); if (upload.status == UPLOAD_FILE_START) { char npath[48]; @@ -5084,7 +5160,7 @@ void script_upload(void) { } else if(upload.status == UPLOAD_FILE_END) { if (upload_file) upload_file.close(); if (Web.upload_error) { - AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload error")); + Script_AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload error")); } } else { Web.upload_error=1; @@ -5097,13 +5173,13 @@ uint8_t DownloadFile(char *file) { WiFiClient download_Client; if (!fsp->exists(file)) { - AddLog_P(LOG_LEVEL_INFO,PSTR("file not found")); + Script_AddLog_P(LOG_LEVEL_INFO,PSTR("file not found")); return 0; } download_file = fsp->open(file, FILE_READ); if (!download_file) { - AddLog_P(LOG_LEVEL_INFO,PSTR("could not open file")); + Script_AddLog_P(LOG_LEVEL_INFO,PSTR("could not open file")); return 0; } @@ -5170,7 +5246,7 @@ void HandleScriptConfiguration(void) { if (!HttpCheckPriviledgedAccess()) { return; } - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_SCRIPT)); + Script_AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_SCRIPT)); #ifdef USE_SCRIPT_FATFS if (Webserver->hasArg("d1")) { @@ -5301,7 +5377,7 @@ void ScriptSaveSettings(void) { strlcpy(glob_script_mem.script_ram, str.c_str(), glob_script_mem.script_size); if (glob_script_mem.script_ram[0]!='>' && glob_script_mem.script_ram[1]!='D') { - AddLog_P(LOG_LEVEL_INFO, PSTR("script error: must start with >D")); + Script_AddLog_P(LOG_LEVEL_INFO, PSTR("script error: must start with >D")); bitWrite(Settings.rule_enabled, 0, 0); } @@ -5314,14 +5390,14 @@ void ScriptSaveSettings(void) { // uint32_t script_compress(char *dest, uint32_t size) { - //AddLog_P(LOG_LEVEL_INFO,PSTR("in string: %s len = %d"),glob_script_mem.script_ram,strlen(glob_script_mem.script_ram)); + //Script_AddLog_P(LOG_LEVEL_INFO,PSTR("in string: %s len = %d"),glob_script_mem.script_ram,strlen(glob_script_mem.script_ram)); uint32_t len_compressed = SCRIPT_COMPRESS(glob_script_mem.script_ram, strlen(glob_script_mem.script_ram), dest, size); if (len_compressed > 0) { dest[len_compressed] = 0; - AddLog_P(LOG_LEVEL_INFO,PSTR("script compressed to %d bytes = %d %%"),len_compressed,len_compressed * 100 / strlen(glob_script_mem.script_ram)); + Script_AddLog_P(LOG_LEVEL_INFO,PSTR("script compressed to %d bytes = %d %%"),len_compressed,len_compressed * 100 / strlen(glob_script_mem.script_ram)); return 0; } else { - AddLog_P(LOG_LEVEL_INFO, PSTR("script compress error: %d"), len_compressed); + Script_AddLog_P(LOG_LEVEL_INFO, PSTR("script compress error: %d"), len_compressed); return 1; } } @@ -5348,7 +5424,7 @@ void SaveScriptEnd(void) { int16_t res = Init_Scripter(); if (res) { - AddLog_P(LOG_LEVEL_INFO, PSTR("script init error: %d"), res); + Script_AddLog_P(LOG_LEVEL_INFO, PSTR("script init error: %d"), res); return; } @@ -5674,7 +5750,7 @@ void Script_Check_Hue(String *response) { } *response += String(EncodeLightId(hue_devs + TasmotaGlobal.devices_present + 1))+"\":"; Script_HueStatus(response, hue_devs); - //AddLog_P(LOG_LEVEL_INFO, PSTR("Hue: %s - %d "),response->c_str(), hue_devs); + //Script_AddLog_P(LOG_LEVEL_INFO, PSTR("Hue: %s - %d "),response->c_str(), hue_devs); } hue_devs++; @@ -5689,10 +5765,10 @@ void Script_Check_Hue(String *response) { } #if 0 if (response) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("Hue: %d"), hue_devs); + Script_AddLog_P(LOG_LEVEL_DEBUG, PSTR("Hue: %d"), hue_devs); toLog(">>>>"); toLog(response->c_str()); - toLog(response->c_str()+LOGSZ); + toLog(response->c_str()+MAX_LOGSZ); } #endif } @@ -5772,8 +5848,8 @@ void Script_Handle_Hue(String *path) { String x_str = tok_x.getStr(); String y_str = tok_y.getStr(); uint8_t rr,gg,bb; - LightStateClass::XyToRgb(x, y, &rr, &gg, &bb); - LightStateClass::RgbToHsb(rr, gg, bb, &hue, &sat, nullptr); + XyToRgb(x, y, &rr, &gg, &bb); + RgbToHsb(rr, gg, bb, &hue, &sat, nullptr); if (resp) { response += ","; } response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); response.replace("{id", String(device)); @@ -5834,7 +5910,7 @@ void Script_Handle_Hue(String *path) { } else { response = FPSTR(sHUE_ERROR_JSON); } - AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str()); + Script_AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str()); WSSend(code, CT_JSON, response); if (resp) { Run_Scripter(">E", 2, 0); @@ -5848,7 +5924,7 @@ bool Script_SubCmd(void) { if (!bitRead(Settings.rule_enabled, 0)) return false; if (tasm_cmd_activ) return false; - //AddLog_P(LOG_LEVEL_INFO,PSTR(">> %s, %s, %d, %d "),XdrvMailbox.topic, XdrvMailbox.data, XdrvMailbox.payload, XdrvMailbox.index); + //Script_AddLog_P(LOG_LEVEL_INFO,PSTR(">> %s, %s, %d, %d "),XdrvMailbox.topic, XdrvMailbox.data, XdrvMailbox.payload, XdrvMailbox.index); char command[CMDSZ]; strlcpy(command, XdrvMailbox.topic, CMDSZ); @@ -5876,7 +5952,7 @@ bool Script_SubCmd(void) { } //toLog(cmdbuff); uint32_t res = Run_Scripter(cmdbuff, tlen + 1, 0); - //AddLog_P(LOG_LEVEL_INFO,">>%d",res); + //Script_AddLog_P(LOG_LEVEL_INFO,">>%d",res); if (res) { return false; } @@ -6007,10 +6083,87 @@ void dateTime(uint16_t* date, uint16_t* time) { #endif //USE_SCRIPT_FATFS -//#define DEBUG_MQTT_EVENT + #ifdef SUPPORT_MQTT_EVENT +//#define DEBUG_MQTT_EVENT + +uint32_t JsonParsePath(JsonParserObject *jobj, const char *spath, char delim, float *nres, char *sres, uint32_t slen) { + uint32_t res = 0; + const char *cp = spath; +#ifdef DEBUG_MQTT_EVENT +// Script_AddLog_P(LOG_LEVEL_INFO, PSTR("Script: parsing json key: %s from json: %s"), cp, jpath); +#endif + JsonParserObject obj = *jobj; + JsonParserObject lastobj = obj; + char selem[32]; + uint8_t aindex = 0; + String value = ""; + while (1) { + // read next element + for (uint32_t sp=0; sp%s=%d\n"), event_item.Event.c_str(), ep); - } else { - snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=\"%s\"\n"), event_item.Event.c_str(), value.c_str()); - } + if (!strncmp(lkey.c_str(), "Epoch", 5)) { + uint32_t ep = atoi(value.c_str()) - (uint32_t)EPOCH_OFFSET; + snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=%d\n"), event_item.Event.c_str(), ep); + } else { + snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=\"%s\"\n"), event_item.Event.c_str(), value.c_str()); + } #ifdef DEBUG_MQTT_EVENT - AddLog_P(LOG_LEVEL_INFO, PSTR("Script: setting script var %s"), sbuffer); + Script_AddLog_P(LOG_LEVEL_INFO, PSTR("Script: setting script var %s"), sbuffer); #endif - //toLog(sbuffer); - execute_script(sbuffer); + //toLog(sbuffer); + execute_script(sbuffer); + } } } } @@ -6202,7 +6308,7 @@ String ScriptSubscribe(const char *data, int data_len) } } } - //AddLog_P(LOG_LEVEL_DEBUG, PSTR("Script: Subscribe command with parameters: %s, %s, %s."), event_name.c_str(), topic.c_str(), key.c_str()); + //Script_AddLog_P(LOG_LEVEL_DEBUG, PSTR("Script: Subscribe command with parameters: %s, %s, %s."), event_name.c_str(), topic.c_str(), key.c_str()); //event_name.toUpperCase(); if (event_name.length() > 0 && topic.length() > 0) { //Search all subscriptions @@ -6223,7 +6329,7 @@ String ScriptSubscribe(const char *data, int data_len) topic.concat("/#"); } } - // AddLog_P(LOG_LEVEL_DEBUG, PSTR("Script: New topic: %s."), topic.c_str()); + // Script_AddLog_P(LOG_LEVEL_DEBUG, PSTR("Script: New topic: %s."), topic.c_str()); //MQTT Subscribe subscription_item.Event = event_name; subscription_item.Topic = topic.substring(0, topic.length() - 2); //Remove "/#" so easy to match @@ -6492,7 +6598,7 @@ void ScriptFullWebpage(void) { WSContentBegin(200, CT_HTML); ScriptWebShow('w'); WSContentEnd(); - Serial.printf("fwp update sv %s\n",stmp.c_str() ); + //Serial.printf("fwp update sv %s\n",stmp.c_str() ); return; //goto redraw; // } else { // Serial.printf("fwp update %s\n",stmp.c_str() ); @@ -6500,7 +6606,7 @@ void ScriptFullWebpage(void) { return; } else { - Serial.printf("fwp other %s\n",stmp.c_str() ); + //Serial.printf("fwp other %s\n",stmp.c_str() ); } WSContentBegin(200, CT_HTML); @@ -6528,7 +6634,7 @@ void Script_Check_HTML_Setvars(void) { if (Webserver->hasArg("sv")) { String stmp = Webserver->arg("sv"); - Serial.printf("fwp has arg dv %s\n", stmp.c_str()); + //Serial.printf("fwp has arg dv %s\n", stmp.c_str()); char cmdbuf[64]; memset(cmdbuf, 0, sizeof(cmdbuf)); char *cp = cmdbuf; @@ -7174,7 +7280,8 @@ exgc: char *cp = &label[3]; //todflg=atoi(&label[3]); todflg = strtol(cp, &cp, 10); - if (todflg>=entries) todflg = entries - 1; + if (todflg >= entries) todflg = entries - 1; + if (todflg < 0) todflg = 0; if (*cp=='/') { cp++; divflg = strtol(cp, &cp, 10); @@ -7593,7 +7700,7 @@ bool Xdrv10(uint8_t function) if (len_decompressed>0) glob_script_mem.script_ram[len_decompressed] = 0; // indicates scripter use compression bitWrite(Settings.rule_once, 6, 1); - //AddLog_P(LOG_LEVEL_INFO, PSTR("decompressed script len %d"),len_decompressed); + //Script_AddLog_P(LOG_LEVEL_INFO, PSTR("decompressed script len %d"),len_decompressed); #else // USE_SCRIPT_COMPRESSION // indicates scripter does not use compression bitWrite(Settings.rule_once, 6, 0); @@ -7675,7 +7782,8 @@ bool Xdrv10(uint8_t function) #endif // ESP #endif // USE_SCRIPT_FATFS>=0 - AddLog_P(LOG_LEVEL_INFO,PSTR("FATFS mount OK!")); + Script_AddLog_P(LOG_LEVEL_INFO,PSTR("FATFS mount OK!")); + //fsp->dateTimeCallback(dateTime); glob_script_mem.script_sd_found = 1; char *script; @@ -7696,7 +7804,7 @@ bool Xdrv10(uint8_t function) glob_script_mem.flags = 1; } else { - AddLog_P(LOG_LEVEL_INFO,PSTR("FATFS mount failed!")); + Script_AddLog_P(LOG_LEVEL_INFO,PSTR("FATFS mount failed!")); glob_script_mem.script_sd_found = 0; } #endif // USE_SCRIPT_FATFS diff --git a/tasmota/xdrv_11_knx.ino b/tasmota/xdrv_11_knx.ino index 6aaf73715..0a8442e3b 100644 --- a/tasmota/xdrv_11_knx.ino +++ b/tasmota/xdrv_11_knx.ino @@ -1,7 +1,7 @@ /* xdrv_11_knx.ino - KNX IP Protocol support for Tasmota - Copyright (C) 2020 Adrian Scillato (https://github.com/ascillato) + Copyright (C) 2021 Adrian Scillato (https://github.com/ascillato) 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 @@ -590,7 +590,7 @@ void KNX_CB_Action(message_t const &msg, void *arg) else if ((chan->type >= KNX_SLOT1) && (chan->type <= KNX_SLOT5)) // KNX RX SLOTs (write command) { if (!toggle_inhibit) { - char command[35]; //4294967295.00 13chars + 17 + char command[35]; //4294967295.00 13chars + 17 if (msg.data_len == 1) { // Command received snprintf_P(command, sizeof(command), PSTR("event KNXRX_CMND%d=%d"), ((chan->type) - KNX_SLOT1 + 1 ), msg.data[0]); diff --git a/tasmota/xdrv_12_home_assistant.ino b/tasmota/xdrv_12_home_assistant.ino index cd92e2e32..8ef33c91f 100644 --- a/tasmota/xdrv_12_home_assistant.ino +++ b/tasmota/xdrv_12_home_assistant.ino @@ -1,7 +1,7 @@ /* xdrv_12_home_assistant.ino - home assistant support for Tasmota - Copyright (C) 2020 Erik Montnemery, Federico Leoni and Theo Arends + Copyright (C) 2021 Erik Montnemery, Federico Leoni and 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 @@ -370,7 +370,7 @@ void TryResponseAppend_P(const char *format, ...) { AddLog_P(LOG_LEVEL_ERROR, PSTR("%s (%u/%u):"), kHAssError1, dlen, slen); va_start(args, format); - char log_data[LOGSZ]; + char log_data[MAX_LOGSZ]; vsnprintf_P(log_data, sizeof(log_data), format, args); AddLogData(LOG_LEVEL_ERROR, log_data); } diff --git a/tasmota/xdrv_13_display.ino b/tasmota/xdrv_13_display.ino index 2fa7d95d8..6bdab9d03 100644 --- a/tasmota/xdrv_13_display.ino +++ b/tasmota/xdrv_13_display.ino @@ -1,7 +1,7 @@ /* xdrv_13_display.ino - Display support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 @@ -63,6 +63,7 @@ const uint8_t DISPLAY_LOG_ROWS = 32; // Number of lines in display log #define D_CMND_DISP_TEXT "Text" #define D_CMND_DISP_WIDTH "Width" #define D_CMND_DISP_HEIGHT "Height" +#define D_CMND_DISP_BLINKRATE "Blinkrate" enum XdspFunctions { FUNC_DISPLAY_INIT_DRIVER, FUNC_DISPLAY_INIT, FUNC_DISPLAY_EVERY_50_MSECOND, FUNC_DISPLAY_EVERY_SECOND, FUNC_DISPLAY_MODEL, FUNC_DISPLAY_MODE, FUNC_DISPLAY_POWER, @@ -70,19 +71,20 @@ enum XdspFunctions { FUNC_DISPLAY_INIT_DRIVER, FUNC_DISPLAY_INIT, FUNC_DISPLAY_E FUNC_DISPLAY_DRAW_HLINE, FUNC_DISPLAY_DRAW_VLINE, FUNC_DISPLAY_DRAW_LINE, FUNC_DISPLAY_DRAW_CIRCLE, FUNC_DISPLAY_FILL_CIRCLE, FUNC_DISPLAY_DRAW_RECTANGLE, FUNC_DISPLAY_FILL_RECTANGLE, - FUNC_DISPLAY_TEXT_SIZE, FUNC_DISPLAY_FONT_SIZE, FUNC_DISPLAY_ROTATION, FUNC_DISPLAY_DRAW_STRING }; + FUNC_DISPLAY_TEXT_SIZE, FUNC_DISPLAY_FONT_SIZE, FUNC_DISPLAY_ROTATION, FUNC_DISPLAY_DRAW_STRING, + FUNC_DISPLAY_DIM, FUNC_DISPLAY_BLINKRATE }; enum DisplayInitModes { DISPLAY_INIT_MODE, DISPLAY_INIT_PARTIAL, DISPLAY_INIT_FULL }; const char kDisplayCommands[] PROGMEM = D_PRFX_DISPLAY "|" // Prefix "|" D_CMND_DISP_MODEL "|" D_CMND_DISP_WIDTH "|" D_CMND_DISP_HEIGHT "|" D_CMND_DISP_MODE "|" D_CMND_DISP_REFRESH "|" D_CMND_DISP_DIMMER "|" D_CMND_DISP_COLS "|" D_CMND_DISP_ROWS "|" D_CMND_DISP_SIZE "|" D_CMND_DISP_FONT "|" - D_CMND_DISP_ROTATE "|" D_CMND_DISP_TEXT "|" D_CMND_DISP_ADDRESS ; + D_CMND_DISP_ROTATE "|" D_CMND_DISP_TEXT "|" D_CMND_DISP_ADDRESS "|" D_CMND_DISP_BLINKRATE ; void (* const DisplayCommand[])(void) PROGMEM = { &CmndDisplay, &CmndDisplayModel, &CmndDisplayWidth, &CmndDisplayHeight, &CmndDisplayMode, &CmndDisplayRefresh, &CmndDisplayDimmer, &CmndDisplayColumns, &CmndDisplayRows, &CmndDisplaySize, &CmndDisplayFont, - &CmndDisplayRotate, &CmndDisplayText, &CmndDisplayAddress }; + &CmndDisplayRotate, &CmndDisplayText, &CmndDisplayAddress, &CmndDisplayBlinkrate }; char *dsp_str; @@ -1410,11 +1412,24 @@ void CmndDisplayDimmer(void) else if (!Settings.display_dimmer && disp_power) { ExecuteCommandPower(disp_device, POWER_OFF, SRC_DISPLAY); } - if (renderer) renderer->dim(Settings.display_dimmer); + if (renderer) + renderer->dim(Settings.display_dimmer); + else + XdspCall(FUNC_DISPLAY_DIM); } ResponseCmndNumber(Settings.display_dimmer); } +void CmndDisplayBlinkrate(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { + + if (!renderer) + XdspCall(FUNC_DISPLAY_BLINKRATE); + } + ResponseCmndNumber(XdrvMailbox.payload); +} + void CmndDisplaySize(void) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) { diff --git a/tasmota/xdrv_14_mp3.ino b/tasmota/xdrv_14_mp3.ino index ed6beee63..b0af75e57 100644 --- a/tasmota/xdrv_14_mp3.ino +++ b/tasmota/xdrv_14_mp3.ino @@ -1,7 +1,7 @@ /* xdrv_14_mp3.ino - MP3 support for Tasmota - Copyright (C) 2020 gemu2015, mike2nl and Theo Arends + Copyright (C) 2021 gemu2015, mike2nl and 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 diff --git a/tasmota/xdrv_15_pca9685.ino b/tasmota/xdrv_15_pca9685.ino index f57a10fd2..950a7df2b 100644 --- a/tasmota/xdrv_15_pca9685.ino +++ b/tasmota/xdrv_15_pca9685.ino @@ -1,7 +1,7 @@ /* xdrv_15_pca9685.ino - Support for I2C PCA9685 12bit 16 pin hardware PWM driver on Tasmota - Copyright (C) 2020 Andre Thomas and Theo Arends + Copyright (C) 2021 Andre Thomas and 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 diff --git a/tasmota/xdrv_16_tuyamcu.ino b/tasmota/xdrv_16_tuyamcu.ino index 13a7864c5..278564047 100644 --- a/tasmota/xdrv_16_tuyamcu.ino +++ b/tasmota/xdrv_16_tuyamcu.ino @@ -1,7 +1,7 @@ /* xdrv_16_tuyamcu.ino - Tuya MCU support for Tasmota - Copyright (C) 2020 Federico Leoni, digiblur, Joel Stein and Theo Arends + Copyright (C) 2021 Federico Leoni, digiblur, Joel Stein and 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 @@ -404,7 +404,7 @@ void TuyaSendCmd(uint8_t cmd, uint8_t payload[] = nullptr, uint16_t payload_len TuyaSerial->write(cmd); // Tuya command TuyaSerial->write(payload_len >> 8); // following data length (Hi) TuyaSerial->write(payload_len & 0xFF); // following data length (Lo) - char log_data[LOGSZ]; + char log_data[MAX_LOGSZ]; snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Send \"55aa00%02x%02x%02x"), cmd, payload_len >> 8, payload_len & 0xFF); for (uint32_t i = 0; i < payload_len; ++i) { TuyaSerial->write(payload[i]); @@ -517,7 +517,7 @@ bool TuyaSetChannels(void) Tuya.Snapshot[0] = changeUIntScale(Light.current_color[0], 0, 255, 0, 100); Tuya.Snapshot[1] = changeUIntScale(Light.current_color[1], 0, 255, 0, 100); } else { // CT Light or RGBWC - light_state.getCTRange(&Tuya.CTMin, &Tuya.CTMax); // SetOption82 - Reduce the CT range from 153..500 to 200..380 to accomodate with Alexa range + getCTRange(&Tuya.CTMin, &Tuya.CTMax); // SetOption82 - Reduce the CT range from 153..500 to 200..380 to accomodate with Alexa range Tuya.Snapshot[0] = light_state.getDimmer(); Tuya.Snapshot[1] = light_state.getCT(); } diff --git a/tasmota/xdrv_17_rcswitch.ino b/tasmota/xdrv_17_rcswitch.ino index 3930dd8cd..8877544df 100644 --- a/tasmota/xdrv_17_rcswitch.ino +++ b/tasmota/xdrv_17_rcswitch.ino @@ -1,7 +1,7 @@ /* xdrv_17_rcswitch.ino - RF transceiver using RcSwitch library for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xdrv_18_armtronix_dimmers.ino b/tasmota/xdrv_18_armtronix_dimmers.ino index a2fa782f5..14fba8c7b 100644 --- a/tasmota/xdrv_18_armtronix_dimmers.ino +++ b/tasmota/xdrv_18_armtronix_dimmers.ino @@ -1,7 +1,7 @@ /* xdrv_18_armtronix_dimmers.ino - Armtronix dimmers support for Tasmota - Copyright (C) 2020 wvdv2002 and Theo Arends + Copyright (C) 2021 wvdv2002 and 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 diff --git a/tasmota/xdrv_19_ps16dz_dimmer.ino b/tasmota/xdrv_19_ps16dz_dimmer.ino index f3cb9ef5f..b44a6da1b 100644 --- a/tasmota/xdrv_19_ps16dz_dimmer.ino +++ b/tasmota/xdrv_19_ps16dz_dimmer.ino @@ -1,7 +1,7 @@ /* xdrv_19_ps16dz.dimmer.ino - PS_16_DZ dimmer support for Tasmota - Copyright (C) 2020 Joel Stein and Theo Arends + Copyright (C) 2021 Joel Stein and 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 diff --git a/tasmota/xdrv_20_hue.ino b/tasmota/xdrv_20_hue.ino index 87557c997..93252af12 100644 --- a/tasmota/xdrv_20_hue.ino +++ b/tasmota/xdrv_20_hue.ino @@ -1,7 +1,7 @@ /* xdrv_20_hue.ino - Philips Hue support for Tasmota - Copyright (C) 2020 Heiko Krupp and Theo Arends + Copyright (C) 2021 Heiko Krupp and 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 @@ -17,7 +17,7 @@ along with this program. If not, see . */ -#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) +#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && (defined(USE_ZIGBEE) || defined(USE_LIGHT)) /*********************************************************************************************\ * Philips Hue bridge emulation * @@ -80,7 +80,6 @@ void HueRespondToMSearch(void) { char message[TOPSZ]; - TickerMSearch.detach(); if (PortUdp.beginPacket(udp_remote_ip, udp_remote_port)) { char response[320]; snprintf_P(response, sizeof(response), HUE_RESPONSE, WiFi.localIP().toString().c_str(), HueBridgeId().c_str()); @@ -304,6 +303,7 @@ uint16_t prev_ct = 254; char prev_x_str[24] = "\0"; // store previously set xy by Alexa app char prev_y_str[24] = "\0"; +#ifdef USE_LIGHT uint8_t getLocalLightSubtype(uint8_t device) { if (TasmotaGlobal.light_type) { if (device >= Light.device) { @@ -423,6 +423,7 @@ void HueLightStatus2(uint8_t device, String *response) *response += buf; free(buf); } +#endif // USE_LIGHT // generate a unique lightId mixing local IP address and device number // it is limited to 32 devices. @@ -497,7 +498,9 @@ void HueGlobalConfig(String *path) { path->remove(0,1); // cut leading / to get response = F("{\"lights\":{"); bool appending = false; // do we need to add a comma to append +#ifdef USE_LIGHT CheckHue(&response, appending); +#endif // USE_LIGHT #ifdef USE_ZIGBEE ZigbeeCheckHue(&response, appending); #endif // USE_ZIGBEE @@ -516,6 +519,7 @@ void HueAuthentication(String *path) AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Authentication Result (%s)"), response); } +#ifdef USE_LIGHT // refactored to remove code duplicates void CheckHue(String * response, bool &appending) { uint8_t maxhue = (TasmotaGlobal.devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : TasmotaGlobal.devices_present; @@ -622,8 +626,8 @@ void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) { strlcpy(prev_x_str, tok_x.getStr(), sizeof(prev_x_str)); strlcpy(prev_y_str, tok_y.getStr(), sizeof(prev_y_str)); uint8_t rr,gg,bb; - LightStateClass::XyToRgb(x, y, &rr, &gg, &bb); - LightStateClass::RgbToHsb(rr, gg, bb, &hue, &sat, nullptr); + XyToRgb(x, y, &rr, &gg, &bb); + RgbToHsb(rr, gg, bb, &hue, &sat, nullptr); prev_hue = changeUIntScale(hue, 0, 360, 0, 65535); // calculate back prev_hue prev_sat = (sat > 254 ? 254 : sat); //AddLog_P(LOG_LEVEL_DEBUG_MORE, "XY RGB (%d %d %d) HS (%d %d)", rr,gg,bb,hue,sat); @@ -729,6 +733,7 @@ void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) { } free(buf); } +#endif // USE_LIGHT void HueLights(String *path) { @@ -745,7 +750,9 @@ void HueLights(String *path) if (path->endsWith(F("/lights"))) { // Got /lights response = "{"; bool appending = false; +#ifdef USE_LIGHT CheckHue(&response, appending); +#endif // USE_LIGHT #ifdef USE_ZIGBEE ZigbeeCheckHue(&response, appending); #endif // USE_ZIGBEE @@ -772,9 +779,11 @@ void HueLights(String *path) return Script_Handle_Hue(path); } #endif +#ifdef USE_LIGHT if ((device >= 1) || (device <= maxhue)) { HueLightsCommand(device, device_id, response); } +#endif // USE_LIGHT } else if(path->indexOf(F("/lights/")) >= 0) { // Got /lights/ID @@ -798,12 +807,14 @@ void HueLights(String *path) } #endif +#ifdef USE_LIGHT if ((device < 1) || (device > maxhue)) { device = 1; } response += F("{\"state\":"); HueLightStatus1(device, &response); HueLightStatus2(device, &response); +#endif // USE_LIGHT } else { response = "{}"; @@ -836,7 +847,9 @@ void HueGroups(String *path) ZigbeeHueGroups(&response); #endif // USE_ZIGBEE response.replace("{l1", lights); +#ifdef USE_LIGHT HueLightStatus1(1, &response); +#endif // USE_LIGHT response += F("}"); } diff --git a/tasmota/xdrv_21_wemo.ino b/tasmota/xdrv_21_wemo.ino index af5d7f176..96e937d21 100644 --- a/tasmota/xdrv_21_wemo.ino +++ b/tasmota/xdrv_21_wemo.ino @@ -1,7 +1,7 @@ /* xdrv_21_wemo.ino - wemo support for Tasmota - Copyright (C) 2020 Heiko Krupp and Theo Arends + Copyright (C) 2021 Heiko Krupp and 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 @@ -17,7 +17,7 @@ along with this program. If not, see . */ -#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined (USE_EMULATION_WEMO_SINGLE) +#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_WEMO_SINGLE) /*********************************************************************************************\ * Belkin WeMo emulation \*********************************************************************************************/ @@ -58,7 +58,6 @@ void WemoRespondToMSearch(int echo_type) { char message[TOPSZ]; - TickerMSearch.detach(); if (PortUdp.beginPacket(udp_remote_ip, udp_remote_port)) { char type[24]; if (1 == echo_type) { // type1 echo 1g & dot 2g diff --git a/tasmota/xdrv_21_wemo_multi.ino b/tasmota/xdrv_21_wemo_multi.ino index 7806b2999..ec3fb7d42 100644 --- a/tasmota/xdrv_21_wemo_multi.ino +++ b/tasmota/xdrv_21_wemo_multi.ino @@ -1,7 +1,7 @@ /* xdrv_21_wemo_multi.ino - multiple wemo support for Tasmota - Copyright (C) 2020 Magic73, Heiko Krupp and Theo Arends + Copyright (C) 2021 Magic73, Heiko Krupp and 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 @@ -419,8 +419,6 @@ WemoSwitch *wemoDevice[MAX_FRIENDLYNAMES] = {}; int numOfWemoSwitch = 0; void WemoRespondToMSearch(int echo_type) { - TickerMSearch.detach(); - for (uint32_t i = 0; i < numOfWemoSwitch; i++) { wemoDevice[i]->WemoRespondToMSearch(echo_type); } diff --git a/tasmota/xdrv_22_sonoff_ifan.ino b/tasmota/xdrv_22_sonoff_ifan.ino index 5ea74c792..4ee897020 100644 --- a/tasmota/xdrv_22_sonoff_ifan.ino +++ b/tasmota/xdrv_22_sonoff_ifan.ino @@ -1,7 +1,7 @@ /* xdrv_22_sonoff_ifan.ino - sonoff iFan02 and iFan03 support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xdrv_23_zigbee_0_constants.ino b/tasmota/xdrv_23_zigbee_0_constants.ino index 50c9e4eee..f29c787c6 100644 --- a/tasmota/xdrv_23_zigbee_0_constants.ino +++ b/tasmota/xdrv_23_zigbee_0_constants.ino @@ -1,7 +1,7 @@ /* xdrv_23_zigbee_constants.ino - zigbee support for Tasmota - Copyright (C) 2020 Theo Arends and Stephan Hadinger + Copyright (C) 2021 Theo Arends and Stephan Hadinger 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 @@ -1165,11 +1165,11 @@ String getEmberStatus(uint8_t status) { 0x39, 0x3A, 0x3D, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x40, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x58, 0x59, 0x5A, 0x66, 0x69, 0x6A, 0x6C, - 0x70, 0x71, 0x72, 0x74, 0x75, 0x76, - 0x80, 0x81, 0x82, 0x84, 0x85, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x70, 0x71, 0x72, 0x74, 0x75, 0x76, + 0x80, 0x81, 0x82, 0x84, 0x85, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x94, 0x96, 0x98, 0x99, 0x9A, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, - 0x93, 0x95, 0xA1, 0xA3, 0xA4, 0xA5, 0xA6, 0xA8, - 0xB3, 0xB7, 0xB8, 0xBB, 0xBD, 0xA9, 0xAA, + 0x93, 0x95, 0xA1, 0xA3, 0xA4, 0xA5, 0xA6, 0xA8, + 0xB3, 0xB7, 0xB8, 0xBB, 0xBD, 0xA9, 0xAA, 0xB0, 0xB1, 0xB4, 0xB6, 0xB5, 0xBA }; char msg[32]; diff --git a/tasmota/xdrv_23_zigbee_1_headers.ino b/tasmota/xdrv_23_zigbee_1_headers.ino index 33ca5381e..3b9c73536 100644 --- a/tasmota/xdrv_23_zigbee_1_headers.ino +++ b/tasmota/xdrv_23_zigbee_1_headers.ino @@ -1,7 +1,7 @@ /* xdrv_23_zigbee_1_headers.ino - zigbee support for Tasmota - Copyright (C) 2020 Theo Arends and Stephan Hadinger + Copyright (C) 2021 Theo Arends and Stephan Hadinger 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 diff --git a/tasmota/xdrv_23_zigbee_1z_libs.ino b/tasmota/xdrv_23_zigbee_1z_libs.ino index 65ea266d2..4e018a21e 100644 --- a/tasmota/xdrv_23_zigbee_1z_libs.ino +++ b/tasmota/xdrv_23_zigbee_1z_libs.ino @@ -1,7 +1,7 @@ /* xdrv_23_zigbee_1z_libs.ino - zigbee support for Tasmota, JSON replacement libs - Copyright (C) 2020 Theo Arends and Stephan Hadinger + Copyright (C) 2021 Theo Arends and Stephan Hadinger 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 @@ -45,9 +45,9 @@ int strcmp_PP(const char *p1, const char *p2) { } /*********************************************************************************************\ - * + * * Variables for Rules from last Zigbee message received - * + * \*********************************************************************************************/ typedef struct Z_LastMessageVars { @@ -65,9 +65,9 @@ uint16_t Z_GetLastCluster(void) { return gZbLastMessage.cluster; } uint8_t Z_GetLastEndpoint(void) { return gZbLastMessage.endpoint; } /*********************************************************************************************\ - * + * * Class for single attribute - * + * \*********************************************************************************************/ enum class Za_type : uint8_t { @@ -126,7 +126,7 @@ public: attr_type(0xFF), attr_multiplier(1) {}; - + Z_attribute(const Z_attribute & rhs) { deepCopy(rhs); } @@ -213,9 +213,9 @@ protected: }; /*********************************************************************************************\ - * + * * Class for attribute ordered list - * + * \*********************************************************************************************/ @@ -309,9 +309,9 @@ Z_attribute & Z_attribute_list::addAttributePMEM(const char * name) { } /*********************************************************************************************\ - * + * * Implementation for Z_attribute - * + * \*********************************************************************************************/ // free any allocated memoruy for keys @@ -719,9 +719,9 @@ void Z_attribute::deepCopy(const Z_attribute & rhs) { } /*********************************************************************************************\ - * + * * Implementation for Z_attribute_list - * + * \*********************************************************************************************/ // add a cluster/attr_id attribute at the end of the list Z_attribute & Z_attribute_list::addAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix) { diff --git a/tasmota/xdrv_23_zigbee_2_devices.ino b/tasmota/xdrv_23_zigbee_2_devices.ino index c319bb26f..e03e27d3d 100644 --- a/tasmota/xdrv_23_zigbee_2_devices.ino +++ b/tasmota/xdrv_23_zigbee_2_devices.ino @@ -1,7 +1,7 @@ /* xdrv_23_zigbee.ino - zigbee support for Tasmota - Copyright (C) 2020 Theo Arends and Stephan Hadinger + Copyright (C) 2021 Theo Arends and Stephan Hadinger 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 @@ -235,7 +235,7 @@ public: inline void setCT(uint16_t _ct) { ct = _ct; } inline void setX(uint16_t _x) { x = _x; } inline void setY(uint16_t _y) { y = _y; } - + static const Z_Data_Type type = Z_Data_Type::Z_Light; // 12 bytes uint8_t colormode; // 0x00: Hue/Sat, 0x01: XY, 0x02: CT | 0xFF not set, default 0x01 @@ -248,7 +248,7 @@ public: /*********************************************************************************************\ * Device specific: PIR - * + * // List of occupancy time-outs: // 0xF = default (90 s) // 0x0 = no time-out @@ -274,7 +274,7 @@ public: inline uint8_t getOccupancy(void) const { return occupancy; } inline uint16_t getIlluminance(void) const { return illuminance; } - + inline void setOccupancy(uint8_t _occupancy) { occupancy = _occupancy; } inline void setIlluminance(uint16_t _illuminance) { illuminance = _illuminance; } @@ -429,7 +429,7 @@ public: } void convertZoneStatus(Z_attribute_list & attr_list, uint16_t val) const; - + // 4 bytes uint16_t zone_status; // last known state for sensor 1 & 2 uint16_t zone_type; // mapped to the Zigbee standard @@ -503,7 +503,7 @@ void Z_Data_Alarm::convertZoneStatus(Z_attribute_list & attr_list, uint16_t val) /*********************************************************************************************\ * Mode - * + * // List of modes // 0x1 = Tuya Zigbee mode // 0xF (default) = ZCL standard mode @@ -524,7 +524,7 @@ public: }; /*********************************************************************************************\ - * + * \*********************************************************************************************/ const uint8_t Z_Data_Type_len[] PROGMEM = { 0, // 0x00 Z_Data_Type::Z_Unknown @@ -556,9 +556,9 @@ size_t Z_Data::DataTypeToLength(Z_Data_Type t) { /*********************************************************************************************\ - * + * * Device specific Linked List - * + * \*********************************************************************************************/ class Z_Data_Set : public LList { public: @@ -886,7 +886,7 @@ public: Z_Device & isKnownLongAddrDevice(uint64_t longaddr) const; Z_Device & isKnownIndexDevice(uint32_t index) const; Z_Device & isKnownFriendlyNameDevice(const char * name) const; - + Z_Device & findShortAddr(uint16_t shortaddr); const Z_Device & findShortAddr(uint16_t shortaddr) const; Z_Device & findLongAddr(uint64_t longaddr); diff --git a/tasmota/xdrv_23_zigbee_2a_devices_impl.ino b/tasmota/xdrv_23_zigbee_2a_devices_impl.ino index b54f2aff1..80a69441c 100644 --- a/tasmota/xdrv_23_zigbee_2a_devices_impl.ino +++ b/tasmota/xdrv_23_zigbee_2a_devices_impl.ino @@ -1,7 +1,7 @@ /* xdrv_23_zigbee_2a_devices_impl.ino - zigbee support for Tasmota - Copyright (C) 2020 Theo Arends and Stephan Hadinger + Copyright (C) 2021 Theo Arends and Stephan Hadinger 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 @@ -511,15 +511,19 @@ void Z_Device::jsonPublishAttrList(const char * json_prefix, const Z_attribute_l TasmotaGlobal.mqtt_data[0] = 0; // clear string // Do we prefix with `ZbReceived`? - if (!Settings.flag4.remove_zbreceived) { + if (!Settings.flag4.remove_zbreceived && !Settings.flag5.zb_received_as_subtopic) { Response_P(PSTR("{\"%s\":"), json_prefix); } // What key do we use, shortaddr or name? - if (use_fname) { - Response_P(PSTR("%s{\"%s\":{"), TasmotaGlobal.mqtt_data, friendlyName); - } else { - Response_P(PSTR("%s{\"0x%04X\":{"), TasmotaGlobal.mqtt_data, shortaddr); + if (!Settings.flag5.zb_omit_json_addr) { + if (use_fname) { + Response_P(PSTR("%s{\"%s\":"), TasmotaGlobal.mqtt_data, friendlyName); + } else { + Response_P(PSTR("%s{\"0x%04X\":"), TasmotaGlobal.mqtt_data, shortaddr); + } } + ResponseAppend_P(PSTR("{")); + // Add "Device":"0x...." ResponseAppend_P(PSTR("\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\","), shortaddr); // Add "Name":"xxx" if name is present @@ -527,9 +531,13 @@ void Z_Device::jsonPublishAttrList(const char * json_prefix, const Z_attribute_l ResponseAppend_P(PSTR("\"" D_JSON_ZIGBEE_NAME "\":\"%s\","), EscapeJSONString(friendlyName).c_str()); } // Add all other attributes - ResponseAppend_P(PSTR("%s}}"), attr_list.toString(false).c_str()); + ResponseAppend_P(PSTR("%s}"), attr_list.toString(false).c_str()); - if (!Settings.flag4.remove_zbreceived) { + if (!Settings.flag5.zb_omit_json_addr) { + ResponseAppend_P(PSTR("}")); + } + + if (!Settings.flag4.remove_zbreceived && !Settings.flag5.zb_received_as_subtopic) { ResponseAppend_P(PSTR("}")); } @@ -545,7 +553,10 @@ void Z_Device::jsonPublishAttrList(const char * json_prefix, const Z_attribute_l snprintf_P(subtopic, sizeof(subtopic), PSTR("%s/%04X"), TasmotaGlobal.mqtt_topic, shortaddr); } char stopic[TOPSZ]; - GetTopic_P(stopic, TELE, subtopic, D_RSLT_SENSOR); + if (Settings.flag5.zb_received_as_subtopic) + GetTopic_P(stopic, TELE, subtopic, json_prefix); + else + GetTopic_P(stopic, TELE, subtopic, D_RSLT_SENSOR); MqttPublish(stopic, Settings.flag.mqtt_sensor_retain); } else { MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); diff --git a/tasmota/xdrv_23_zigbee_3_hue.ino b/tasmota/xdrv_23_zigbee_3_hue.ino index 2939e75b5..cc77d2314 100644 --- a/tasmota/xdrv_23_zigbee_3_hue.ino +++ b/tasmota/xdrv_23_zigbee_3_hue.ino @@ -1,7 +1,7 @@ /* xdrv_23_zigbee.ino - zigbee support for Tasmota - Copyright (C) 2020 Theo Arends and Stephan Hadinger + Copyright (C) 2021 Theo Arends and Stephan Hadinger 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 @@ -18,7 +18,7 @@ */ #ifdef USE_ZIGBEE -#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) +#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) // Add global functions for Hue Emulation diff --git a/tasmota/xdrv_23_zigbee_4_persistence.ino b/tasmota/xdrv_23_zigbee_4_persistence.ino index 91c516194..35d25922b 100644 --- a/tasmota/xdrv_23_zigbee_4_persistence.ino +++ b/tasmota/xdrv_23_zigbee_4_persistence.ino @@ -1,7 +1,7 @@ /* xdrv_23_zigbee.ino - zigbee support for Tasmota - Copyright (C) 2020 Theo Arends and Stephan Hadinger + Copyright (C) 2021 Theo Arends and Stephan Hadinger 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 diff --git a/tasmota/xdrv_23_zigbee_4a_nano_fs.ino b/tasmota/xdrv_23_zigbee_4a_nano_fs.ino index 2c9ea9ec7..007615c1b 100644 --- a/tasmota/xdrv_23_zigbee_4a_nano_fs.ino +++ b/tasmota/xdrv_23_zigbee_4a_nano_fs.ino @@ -1,7 +1,7 @@ /* xdrv_23_zigbee_4a_eeprom.ino - zigbee support for Tasmota - nano filesystem for EEPROM, with anti-weavering - Copyright (C) 2020 Theo Arends and Stephan Hadinger + Copyright (C) 2021 Theo Arends and Stephan Hadinger 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 @@ -93,9 +93,9 @@ // - only file size actually changes /*********************************************************************************************\ - * + * * Constants - * + * \*********************************************************************************************/ const size_t ZFS_BLOCK_SIZE = 256; const size_t ZFS_ENTRY_SIZE = 8; // each entry is 32 bytes @@ -124,7 +124,7 @@ public: blk_start(0), reserved(0) {} - + inline static bool validIdx(uint8_t blk_start) { return ((blk_start != 0x00) && (blk_start != 0x01) && (blk_start != 0xFF)); }; static uint16_t getAddress(uint8_t entry_idx); void read(uint8_t entry_idx); @@ -190,9 +190,9 @@ public: }; /*********************************************************************************************\ - * + * * Formatting implementations - * + * \*********************************************************************************************/ void ZFS_Dir_Block::format(void) { @@ -229,9 +229,9 @@ void ZFS_Map::format(void) { } /*********************************************************************************************\ - * + * * Writing a file - * + * \*********************************************************************************************/ class ZFS_Write_File { @@ -256,9 +256,9 @@ protected: /*********************************************************************************************\ - * + * * Check that the EEPROM is formatted - * + * \*********************************************************************************************/ // Main class for the Zigbee filesystem @@ -277,9 +277,9 @@ public: }; /*********************************************************************************************\ - * + * * Check that the EEPROM is formatted - * + * \*********************************************************************************************/ bool ZFS::findFileEntry(uint32_t name, ZFS_File_Entry & entry, uint8_t * _entry_idx) { @@ -317,9 +317,9 @@ void ZFS::erase(void) { } /*********************************************************************************************\ - * + * * Reading a file - * + * \*********************************************************************************************/ int32_t ZFS::readBytes(uint32_t name, void* buffer, size_t buffer_len, uint16_t read_start, uint16_t read_len) { if (!zigbee.eeprom_ready) { return -1; } @@ -349,9 +349,9 @@ int32_t ZFS::readBytes(uint32_t name, void* buffer, size_t buffer_len, uint16_t } /*********************************************************************************************\ - * + * * Check that the EEPROM is formatted - * + * \*********************************************************************************************/ void ZFS::initOrFormat(void) { @@ -386,7 +386,7 @@ void ZFS::initOrFormat(void) { format(); } delete dir; - + zigbee.eeprom_ready = true; } @@ -408,7 +408,7 @@ void ZFS::format(void) { zigbee.eeprom.writeBytes(0x0100, 256, (byte*) map); delete map; - // Dir + // Dir ZFS_Dir_Block * dir = new ZFS_Dir_Block(); dir->format(); zigbee.eeprom.writeBytes(0x0000, 256, (byte*) dir); diff --git a/tasmota/xdrv_23_zigbee_4b_eeprom.ino b/tasmota/xdrv_23_zigbee_4b_eeprom.ino index 360efb59d..88fa1e391 100644 --- a/tasmota/xdrv_23_zigbee_4b_eeprom.ino +++ b/tasmota/xdrv_23_zigbee_4b_eeprom.ino @@ -1,7 +1,7 @@ /* xdrv_23_zigbee_4a_eeprom.ino - zigbee support for Tasmota - saving configuration in I2C Eeprom of ZBBridge - Copyright (C) 2020 Theo Arends and Stephan Hadinger + Copyright (C) 2021 Theo Arends and Stephan Hadinger 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 @@ -107,9 +107,9 @@ int32_t hydrateSingleDevice(const class SBuffer & buf, size_t start, size_t len) } /*********************************************************************************************\ - * + * * Hydrate data from the EEPROM - * + * \*********************************************************************************************/ // Parse the entire blob // return true if ok @@ -200,9 +200,9 @@ class SBuffer hibernateDeviceData(const struct Z_Device & device, bool mqtt = fa } /*********************************************************************************************\ - * + * * Hibernate data to the EEPROM - * + * \*********************************************************************************************/ void hibernateAllData(void) { #ifdef USE_ZIGBEE_EZSP @@ -255,7 +255,7 @@ bool hibernateDevicesInEEPROM(void) { if (!zigbee.eeprom_ready) { return false; } ZFS_Write_File write_data(ZIGB_NAME2); - + // first prefix is number of devices uint8_t devices_size = zigbee_devices.devicesSize(); if (devices_size > 64) { devices_size = 64; } // arbitrarily limit to 64 devices in EEPROM instead of 32 in Flash diff --git a/tasmota/xdrv_23_zigbee_5__constants.ino b/tasmota/xdrv_23_zigbee_5__constants.ino index dd7e9234c..fdd161c50 100644 --- a/tasmota/xdrv_23_zigbee_5__constants.ino +++ b/tasmota/xdrv_23_zigbee_5__constants.ino @@ -1,7 +1,7 @@ /* xdrv_23_zigbee_5__constants.ino - zigbee support for Tasmota - Copyright (C) 2020 Theo Arends and Stephan Hadinger + Copyright (C) 2021 Theo Arends and Stephan Hadinger 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 @@ -40,30 +40,30 @@ def clean(s): def strings_to_pmem(arg): #strings = arg.split("\n") strings = re.findall(pat, arg) - + # do some basic cleaning strings_cleaned = [ clean(x) for x in strings if clean(x) != ""] - + # remove duplicates strings_cleaned = list(dict.fromkeys(strings_cleaned)) - + out_s = "const char Z_strings[] PROGMEM = \n" out_i = "enum Z_offsets {\n" - + index = 0; # add a first empty string out_s += " \"\\x00\"\n" out_i += " Zo_ = " + str(index) + ",\n" index += 1 - + for s in strings_cleaned: out_s += " \"" + s + "\" \"\\x00\"\n" out_i += " Zo_" + s + " = " + str(index) + ",\n" index += len(s) + 1 # add one for null char - + out_s += " \"\\x00\";" out_i += "};" - + return ("", out_s, out_i) @@ -73,7 +73,7 @@ def strings_to_pmem(arg): DO NOT EDIT */ -const char Z_strings[] PROGMEM = +const char Z_strings[] PROGMEM = "\x00" "ZCLVersion" "\x00" "AppVersion" "\x00" diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index 06c59ece8..8af9ee7fa 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -1,7 +1,7 @@ /* xdrv_23_zigbee_converters.ino - zigbee support for Tasmota - Copyright (C) 2020 Theo Arends and Stephan Hadinger + Copyright (C) 2021 Theo Arends and Stephan Hadinger 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 @@ -1624,7 +1624,7 @@ void ZCLFrame::parseClusterSpecificCommand(Z_attribute_list& attr_list) { void ZCLFrame::syntheticAnalogValue(Z_attribute_list &attr_list, class Z_attribute &attr) { const char * modelId_c = zigbee_devices.getModelId(_srcaddr); // null if unknown String modelId((char*) modelId_c); - + if (modelId.startsWith(F("lumi.sensor_cube"))) { attr.setKeyId(0x000C, 0xFF55); // change to AqaraRotate } diff --git a/tasmota/xdrv_23_zigbee_6_commands.ino b/tasmota/xdrv_23_zigbee_6_commands.ino index 63ea80869..89e3a6e65 100644 --- a/tasmota/xdrv_23_zigbee_6_commands.ino +++ b/tasmota/xdrv_23_zigbee_6_commands.ino @@ -1,7 +1,7 @@ /* xdrv_23_zigbee_converters.ino - zigbee support for Tasmota - Copyright (C) 2020 Theo Arends and Stephan Hadinger + Copyright (C) 2021 Theo Arends and Stephan Hadinger 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 diff --git a/tasmota/xdrv_23_zigbee_7_0_statemachine.ino b/tasmota/xdrv_23_zigbee_7_0_statemachine.ino index d314e86b4..7c00cfb42 100644 --- a/tasmota/xdrv_23_zigbee_7_0_statemachine.ino +++ b/tasmota/xdrv_23_zigbee_7_0_statemachine.ino @@ -1,7 +1,7 @@ /* xdrv_23_zigbee.ino - zigbee support for Tasmota - Copyright (C) 2020 Theo Arends and Stephan Hadinger + Copyright (C) 2021 Theo Arends and Stephan Hadinger 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 diff --git a/tasmota/xdrv_23_zigbee_7_5_map.ino b/tasmota/xdrv_23_zigbee_7_5_map.ino index 17c79d5e5..790720320 100644 --- a/tasmota/xdrv_23_zigbee_7_5_map.ino +++ b/tasmota/xdrv_23_zigbee_7_5_map.ino @@ -1,7 +1,7 @@ /* xdrv_23_zigbee_7_5_map.ino - zigbee support for Tasmota - Copyright (C) 2020 Theo Arends and Stephan Hadinger + Copyright (C) 2021 Theo Arends and Stephan Hadinger 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 diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 32709c7dc..4fc3d4f1b 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -1,7 +1,7 @@ /* xdrv_23_zigbee.ino - zigbee support for Tasmota - Copyright (C) 2020 Theo Arends and Stephan Hadinger + Copyright (C) 2021 Theo Arends and Stephan Hadinger 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 diff --git a/tasmota/xdrv_23_zigbee_9_serial.ino b/tasmota/xdrv_23_zigbee_9_serial.ino index b3600c151..e2c5550a4 100644 --- a/tasmota/xdrv_23_zigbee_9_serial.ino +++ b/tasmota/xdrv_23_zigbee_9_serial.ino @@ -1,7 +1,7 @@ /* xdrv_23_zigbee_9_serial.ino - zigbee: serial communication with MCU - Copyright (C) 2020 Theo Arends and Stephan Hadinger + Copyright (C) 2021 Theo Arends and Stephan Hadinger 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 diff --git a/tasmota/xdrv_23_zigbee_9a_upload.ino b/tasmota/xdrv_23_zigbee_9a_upload.ino index d3fff537d..b946848a3 100644 --- a/tasmota/xdrv_23_zigbee_9a_upload.ino +++ b/tasmota/xdrv_23_zigbee_9a_upload.ino @@ -1,7 +1,7 @@ /* xdrv_23_zigbee_9a_upload.ino - zigbee: serial xmodem upload to MCU - Copyright (C) 2020 Theo Arends and Stephan Hadinger + Copyright (C) 2021 Theo Arends and Stephan Hadinger 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 diff --git a/tasmota/xdrv_23_zigbee_A_impl.ino b/tasmota/xdrv_23_zigbee_A_impl.ino index df7b61b8f..9bdf84175 100644 --- a/tasmota/xdrv_23_zigbee_A_impl.ino +++ b/tasmota/xdrv_23_zigbee_A_impl.ino @@ -1,7 +1,7 @@ /* xdrv_23_zigbee.ino - zigbee support for Tasmota - Copyright (C) 2020 Theo Arends and Stephan Hadinger + Copyright (C) 2021 Theo Arends and Stephan Hadinger 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 @@ -1684,9 +1684,9 @@ const char ZB_WEB_U[] PROGMEM = // Lighting ".bx{height:14px;width:14px;display:inline-block;border:1px solid currentColor;background-color:var(--cl,#fff)}" // Signal Strength Indicator - ".ssi{display:inline-flex;align-items:flex-end;height:15px;padding:0}" - ".ssi i{width:3px;margin-right:1px;border-radius:3px;background-color:#eee}" - ".ssi .b0{height:25%%}.ssi .b1{height:50%%}.ssi .b2{height:75%%}.ssi .b3{height:100%%}.o30{opacity:.3}" + ".si{display:inline-flex;align-items:flex-end;height:15px;padding:0}" + ".si i{width:3px;margin-right:1px;border-radius:3px;background-color:#%06x}" + ".si .b0{height:25%%}.si .b1{height:50%%}.si .b2{height:75%%}.si .b3{height:100%%}.o30{opacity:.3}" "" "\0" @@ -1739,7 +1739,7 @@ const char ZB_WEB_U[] PROGMEM = "" "%s" // name "%s" // sbatt (Battery Indicator) - "
" // slqi + "
" // slqi "\0" // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ //=ZB_WEB_BATTERY @@ -1779,22 +1779,22 @@ const char ZB_WEB_U[] PROGMEM = // ++++++++++++++++++++vvvvvvvvvvvvvvvvvvv++++++++++++++++++++ enum { ZB_WEB_CSS=0, - ZB_WEB_PERMITJOIN_ACTIVE=512, - ZB_WEB_VIS_JS_BEFORE=566, - ZB_WEB_VIS_JS_AFTER=1039, - ZB_WEB_AUTO_REFRESH=1103, - ZB_WEB_MAP_REFRESH=1169, - ZB_WEB_STATUS_LINE=1235, - ZB_WEB_BATTERY=1344, - ZB_WEB_LAST_SEEN=1394, - ZB_WEB_COLOR_RGB=1442, - ZB_WEB_LINE_START=1502, - ZB_WEB_LIGHT_CT=1542, - ZB_WEB_END_STATUS=1597, - ZB_WEB_LINE_END=1614, + ZB_WEB_PERMITJOIN_ACTIVE=507, + ZB_WEB_VIS_JS_BEFORE=561, + ZB_WEB_VIS_JS_AFTER=1034, + ZB_WEB_AUTO_REFRESH=1098, + ZB_WEB_MAP_REFRESH=1164, + ZB_WEB_STATUS_LINE=1230, + ZB_WEB_BATTERY=1338, + ZB_WEB_LAST_SEEN=1388, + ZB_WEB_COLOR_RGB=1436, + ZB_WEB_LINE_START=1496, + ZB_WEB_LIGHT_CT=1536, + ZB_WEB_END_STATUS=1591, + ZB_WEB_LINE_END=1608, }; -// Compressed from 1631 to 1109, -32.0% +// Compressed from 1625 to 1111, -31.6% const char ZB_WEB[] PROGMEM = "\x00\x66\x3D\x0E\xCA\xB1\xC1\x33\xF0\xF6\xD1\xEE\x3D\x3D\x46\x41\x33\xF0\xE8\x6D" "\xA1\x15\x08\x79\xF6\x51\xDD\x3C\xCC\x6F\xFD\x47\x58\x62\xB4\x21\x0E\xF1\xED\x1F" "\xD1\x28\x51\xE6\x72\x99\x0C\x36\x1E\x0C\x67\x51\xD7\xED\x36\xB3\xCC\xE7\x99\xF4" @@ -1805,52 +1805,52 @@ const char ZB_WEB[] PROGMEM = "\x00\x66\x3D\x0E\xCA\xB1\xC1\x33\xF0\xF6\xD1\xEE\ "\x13\x7C\x30\x2B\x32\x3C\xF7\x82\xDE\x67\x58\xE0\xB0\x33\x43\xC0\xEC\xF8\x8F\xE7" "\x99\xC8\x43\x0D\x8B\xD8\x16\x88\x83\x17\xFF\xBE\xA2\x0F\x02\xCF\x9E\x07\x58\x66" "\x83\xDF\xC1\x7C\x21\xD6\x1E\x05\x9F\x3C\xCC\xEF\xE7\x74\xEB\x3A\xC3\x08\xEA\x3C" - "\x8C\x18\x30\x77\x8F\x71\xD3\xDE\xD3\xDA\x09\x59\xA1\x80\x99\xB0\xF1\x61\x68\xF7" - "\x1D\x7B\x4C\x6F\x8F\x33\x01\x33\x61\xD6\xF8\x43\xC0\x21\xEE\x87\x34\x86\x1B\x0F" - "\x03\x2C\x41\x37\x87\x8F\x33\x8C\xF7\x1D\x0B\xDE\xD5\xA0\x85\xC2\x91\xCB\x21\x86" - "\xC3\xC0\x24\xF0\x90\x30\xD8\x08\x5C\x2A\x01\x1D\x7F\xB1\x34\x5F\x8F\x33\x96\x43" - "\x0D\x80\x9B\xBA\x1E\x4D\xB0\x41\xC9\x8E\x83\x8E\x32\x04\x3E\x17\x4E\x56\x9F\x47" - "\xD1\x02\x1D\x13\x90\x81\x0E\x89\xCD\x64\x08\xB4\x4E\x51\x02\x1D\x13\x9E\x20\x46" - "\xC1\x8E\x59\x02\x27\x13\x87\x1B\x3E\x8F\xA3\xDC\x74\x2C\x39\x6C\xF6\x96\x0C\xB0" - "\xF6\x8C\x8F\x33\xA1\xCB\x3D\xC7\xA1\xD8\x40\x83\xCA\x4C\xE1\x7C\xF4\x18\x7E\x1E" - "\x83\x8F\xC3\xDE\x47\xA7\x86\x5F\x2F\x51\x90\x4C\xF8\x7D\x82\x16\xD4\x71\xFD\x9E" - "\x0F\xB3\xF0\xFA\x2F\x1E\x87\x67\x86\x5F\x1F\x88\xF7\xCF\x43\xB0\x71\xF8\x7A\x1D" - "\x83\x0F\xC9\xC2\xF9\xE9\xE0\xFF\xA3\x29\x51\x90\xC6\x7C\x3D\x94\xCD\x94\x76\x1A" - "\xEC\xCE\xC1\x06\x91\xEC\x5E\xF8\x67\xC3\xD8\x2A\x2B\xA8\x67\x8F\x33\xB0\xEC\x17" - "\xC3\x0D\x07\x8E\x81\xE0\xD3\xB0\xCF\x7C\x75\xF3\xA1\xFC\xF9\xA1\xD9\xEA\xBE\x12" - "\xC2\xCE\x67\x60\xB1\xA2\x02\x3D\x73\xA0\xDD\xE3\xA1\xAF\xC7\xB0\xFC\x3D\x0E\xC0" - "\x41\xCB\x0F\xC3\xD0\x4D\x33\x5A\x21\xF0\xF6\x0D\x32\x04\x2C\x2A\x01\xF6\x02\x17" - "\x2A\x01\xC7\xB0\x13\x78\x9F\x30\x60\xC1\xE0\x10\xF8\x1C\x38\xD9\x02\x17\x32\xC7" - "\x3E\xD9\x0C\x36\x02\x1F\x22\xC7\x31\xB2\x04\x4E\x3A\xC1\x1B\x98\xF0\xB4\x78\x55" - "\x0F\x7E\xCC\x8F\x1F\x7E\xD3\x6B\x3C\xC7\x65\x0A\x3C\x1E\xC3\xF0\x85\xF5\x8E\x09" - "\xAA\xC4\x16\x58\x88\xCF\x7C\x74\x35\xF8\xF4\x3B\x04\xD3\x33\xF0\x16\x78\x63\x3F" - "\x0C\xEF\xE8\x3C\xEA\xBD\xE7\xF3\xE0\x98\x18\xB1\xAF\xA8\xE8\x3C\xE8\x98\x4C\x6B" - "\xEA\x21\xC6\x45\xA2\x1D\xD0\x46\xE0\xC8\xEF\x1E\x0C\xEF\xEB\x06\x56\xE7\x78\xF8" - "\x7B\x47\xBF\x82\xC6\x78\xF3\x3D\xB8\x79\x9E\xDF\x0A\xB1\x8C\xF3\x3D\x81\xEF\xC3" - "\x09\x9E\xC3\xA8\x10\x78\x3D\x3D\x87\x90\x87\x37\x4F\x61\xEE\x3A\x8B\xE0\x89\x70" - "\x76\x1B\x01\x16\xC9\x81\xC7\x3C\x7B\x0F\x71\xD4\x4C\x11\x2C\xB0\x82\xD1\x9E\x04" - "\x6C\x6A\xC4\x30\x7B\x0F\x71\xEE\x3D\xC7\x83\x3B\xFA\x12\xEA\xCF\x87\xB6\x70\xBE" - "\x08\x32\x41\x0B\x6C\x3E\x73\x1F\x46\x7B\xE3\xA1\x70\x20\xCC\x3B\xA0\x89\xC1\x49" - "\xD4\x25\xD5\x9D\x40\x85\xC0\x29\xDE\x3C\x02\x27\x20\xC0\x87\xCB\xA9\xF9\xE7\x45" - "\x5A\x35\xE0\xBA\x3B\xA6\x05\xF0\x75\xB9\xC7\x74\xEF\x1E\xD0\xB0\x3B\xAD\xCE\x3A" - "\x7D\x85\x96\x21\xDD\x3B\xC7\x83\xDC\x75\x1C\x89\x32\x04\x8C\x78\x61\xF8\x7A\x1D" - "\x83\x0F\xC3\xD0\xC6\x7C\x6A\xB0\xEB\x73\x8F\x87\xD9\xB4\x77\xCF\xB4\x35\xD0\xAC" - "\x10\xF8\x7D\x8F\x3A\x3E\xCF\xC3\xD0\x70\xBA\xAC\xE3\xF0\xFA\xF1\xE8\x76\x02\x14" - "\x73\xD0\xEC\x31\x9F\x1A\x7E\x4E\x17\xCF\x4A\xFA\x0C\x2B\xF7\x8F\x87\xD9\xB6\x84" - "\x42\xAB\xE7\xD9\xF8\x7A\x50\x87\xE1\xE8\x39\x56\xD0\x4C\xF8\x7D\x9C\x64\x6C\x3E" - "\x8E\x3C\x22\x36\x23\xEB\xC8\xEB\x47\xD7\x81\x07\xA0\x7E\x38\xFC\x3D\x0E\xCA\x10" - "\xFC\x3D\x28\x43\xF0\xFA\xF0\x22\x47\x3D\x04\xD3\x30\x43\xC4\x88\x22\x35\x16\xA3" - "\xEB\xC7\xD8\x21\xE7\x1E\xF6\x9F\x67\xE4\xE1\x7C\xF4\xD0\x42\x98\x7B\x07\x51\xEC" - "\x04\x2C\x18\xF6\x1F\x42\x1F\x47\xD0\x22\x73\xFE\x75\x9D\x63\x82\x3C\xCF\xA1\x06" - "\x1B\x0F\x61\xF8\x7A\x1D\x9A\x7E\x4E\x17\xCF\x4A\x10\x10\xEB\x82\x17\x40\x10\xFA" - "\x38\xE8\x8D\x87\xD1\xC7\x44\x6C\x3E\x8E\x3A\x23\x61\xEC\x3F\x0F\xD1\xE4\x6C\x39" - "\x08\x8C\x1C\xDD\xF1\xE0\xFA\x74\x42\x1F\x41\xCE\x17\xD0\x23\x67\xE6\xC0\x46\xCC" - "\x83\x08\xF3\x3C\x8F\xA3\x8E\x88\x8D\x87\xD1\xC7\x44\x46\xC3\xE8\xE3\xA2\x23\x60" - "\x20\xE7\x60\x91\x3C\x11\xF8\x67\x04\x3E\x18\xD0\x78\x17\x86\x5F\x1F\x0F\x61\xCC" - "\x3D\x87\xE1\xFA\x3C\x96\x7B\xE7\x82\x9C\x2F\x82\x17\x45\x6C\x10\xB8\x1B\x20\xCA" - "\x91\xF4\x21\xEC\x3F\x0F\x4F\x0D\xB0\x82\x3F\x0F\xD1\xE4\x71\x7D\x7C\xF0\x77\x0F" - "\x43\xB0\x81\x06\x61\xF4\x21\x1A\x02\x17\x45\xB6\x70\xBE\x08\x5D\x06\x23\xB2\x84" - "\x3F\x0F\xAF\x1E\xD6\x7B\x81\x32\x6C\xE1\x7C"; + "\x8C\x18\x30\x77\x8F\x71\xD3\xDA\x7B\x41\x2B\x33\x30\x13\x36\x1E\x2C\x2D\x1E\xE3" + "\xAF\x69\x8D\xF1\xE6\x60\x26\x6C\x3A\xDF\x08\x78\x04\x3D\xCC\xE6\x90\xC3\x61\xE0" + "\x65\x88\x26\xF0\xF1\xE6\x71\x9E\xE3\xA1\x7B\x56\x82\x17\x0A\x07\x2C\x86\x1B\x0F" + "\x2A\x01\x93\xC2\x30\xC3\x60\x21\x6F\xC7\x5F\xEC\x4D\x17\xE3\xCC\xE5\x90\xC3\x60" + "\x26\xEE\x47\x91\xF4\x71\xF1\x1B\x0F\x71\xD3\xDA\x8E\x83\x8E\x32\x04\x3E\x16\xCE" + "\x56\x9F\x47\xD1\x02\x15\x03\x90\x81\x0E\x81\xCD\x64\x08\x94\x0E\x51\x02\x1D\x03" + "\x9E\x20\x45\xC1\x0E\x59\x02\x27\x12\xE7\x1B\x3E\x8F\xA3\xDC\x74\x2C\x39\x6C\xF6" + "\x96\x0C\xB0\xF6\x8C\x8F\x33\xA1\xCB\x3D\xC7\xA1\xD8\x40\x83\xCA\x24\xE1\x7C\xF4" + "\x18\x7E\x1E\x83\x8F\xC3\xDE\x47\xA7\x86\x5F\x2F\x51\x90\x4C\xF8\x7D\x82\x16\xCE" + "\x71\xFD\x9E\x0F\xB3\xF0\xFA\x2F\x1E\x87\x67\x86\x5F\x1F\x88\xF7\xCF\x43\xB0\x71" + "\xF8\x7A\x1D\x83\x0F\xC9\xC2\xF9\xE9\xE0\xFF\xA3\x29\x51\x90\xC6\x7C\x3D\x94\xCD" + "\x94\x76\x1A\xEC\xCE\xC1\x06\x91\xEC\x5E\xF8\x67\xC3\xD8\x2A\x2B\xA8\x67\x8F\x33" + "\xB0\xEC\x17\xC3\x0D\x07\x8E\x81\xE0\xD3\xB0\xCF\x7C\x75\xF3\xA1\xFC\xF9\xA1\xD9" + "\xEA\xBE\x12\xC2\xCE\x67\x60\xB1\xA2\x02\x3D\x73\xA0\xDD\xE3\xA1\xAF\xC7\xB0\xFC" + "\x3D\x0E\xC0\x41\xCB\x0F\xC3\xD0\x4D\x33\x5A\x21\xF0\xF6\x0D\x32\x04\x2C\x2A\x01" + "\xF6\x02\x17\x2A\x01\xC7\xB0\x13\x78\x9C\x30\x60\xC1\xE0\x10\xF8\x1C\x38\xD9\x02" + "\x17\x32\x27\x3E\xD9\x0C\x36\x02\x1F\x22\x47\x31\xB2\x04\x4E\x3A\x01\x1B\x98\xA0" + "\xB4\x78\x55\x0F\x7E\xCC\x8F\x1F\x7E\xD3\x6B\x3C\xC7\x65\x0A\x3C\x1E\xC3\xF0\x85" + "\xF5\x8E\x09\xAA\xC4\x16\x58\x88\xCF\x7C\x74\x35\xF8\xF4\x3B\x04\xD3\x33\xF0\x16" + "\x78\x63\x3F\x0C\xEF\xE8\x3C\xEA\xBD\xE7\xF3\xE0\x98\x18\xB1\xAF\xA8\xE8\x3C\xE8" + "\x98\x4C\x6B\xEA\x21\xC6\x45\xA2\x1D\xD0\x46\xE0\xC8\xEF\x1E\x0C\xEF\xEB\x06\x56" + "\xE7\x78\xF8\x7B\x47\xBF\x82\xC6\x78\xF3\x3D\xB8\x79\x9E\xDF\x0A\xB1\x8C\xF3\x3D" + "\x81\xEF\xC3\x09\x9E\xC3\xA8\x10\x78\x3D\x3D\x87\x90\x87\x37\x4F\x61\xEE\x3A\x8B" + "\xE0\x89\x70\x76\x1B\x01\x16\xC9\x81\xC7\x3C\x7B\x0F\x71\xD4\x4C\x11\x2C\xB0\x82" + "\xD1\x9E\x04\x6C\x6A\xC4\x30\x7B\x0F\x71\xEE\x3D\xC7\x83\x3B\xFA\x12\xEA\xCF\x87" + "\xB6\x70\xBE\x08\x32\x41\x0B\x6C\x3E\x73\x1F\x46\x7B\xE3\xA1\x70\x20\xCC\x3B\xA0" + "\x89\xC1\x49\xD4\x25\xD5\x9D\x40\x85\xC0\x29\xDE\x3C\x02\x27\x20\xC0\x87\xCB\xA9" + "\xF9\xE7\x45\x5A\x35\xE0\xBA\x3B\xA6\x05\xF0\x75\xB9\xC7\x74\xEF\x1E\xD0\xB0\x3B" + "\xAD\xCE\x3A\x7D\x85\x96\x21\xDD\x3B\xC7\x83\xDC\x75\x1C\x89\x32\x04\x8C\x78\x61" + "\xF8\x7A\x1D\x83\x0F\xC3\xD0\xC6\x7C\x6A\xB0\xEB\x73\x8F\x87\xD9\xB4\x77\xCF\xB4" + "\x35\xD0\xAC\x10\xF8\x7D\x8F\x3A\x3E\xCF\xC3\xD0\x70\xBA\xAC\xE3\xF0\xFA\xF1\xE8" + "\x76\x02\x14\x73\xD0\xEC\x31\x9F\x1A\x7E\x4E\x17\xCF\x4A\xFA\x0C\x2B\xF7\x8F\x87" + "\xD9\xB6\x84\x42\xAB\xE7\xD9\xF8\x7A\x50\x87\xE1\xE8\x39\x56\xD0\x4C\xF8\x7D\x9C" + "\x64\x6C\x3E\x8E\x3C\x22\x36\x23\xEB\xC8\xEB\x47\xD7\x81\x07\xA0\x7E\x38\xFC\x3D" + "\x0E\xCA\x10\xFC\x3D\x28\x43\xF0\xFA\xF0\x22\x47\x3D\x04\xD3\x30\x43\xC4\x88\x22" + "\x35\x16\xA3\xEB\xC7\xD8\x21\xE7\x1E\xD3\xEC\xFC\x9C\x2F\x9E\x9A\x08\x52\xCF\x60" + "\xEA\x3D\x80\x85\x82\x9E\xC3\xE8\x43\xE8\xFA\x04\x4E\x7F\x8E\xB3\xAC\x70\x47\x99" + "\xF4\x20\xC3\x61\xEC\x3F\x0F\x43\xB3\x4F\xC9\xC2\xF9\xE9\x42\x02\x1D\x70\x44\xE8" + "\xA7\x1C\xA2\x36\x1F\x47\x1D\x11\xB0\xFA\x38\xE8\x8D\x87\xB0\xFC\x3F\x47\x91\xB0" + "\xE4\x22\x30\x73\x77\xC7\x83\xE9\xD1\x08\x7D\x07\x38\x5F\x40\x8D\x9F\x9B\x01\x1B" + "\x32\x0C\x23\xCC\xF2\x3E\x8E\x3A\x22\x36\x1F\x47\x1D\x11\x1B\x0F\xA3\x8E\x88\x8D" + "\x80\x83\x9D\x82\x44\xF0\x47\xE1\x98\x10\xF8\x62\x41\xE0\x5E\x19\x7C\x7C\x3D\x87" + "\x30\xF6\x1F\x87\xE8\xF2\x59\xEF\x9E\x0A\x70\xBE\x08\x5D\x15\xA0\x42\xE0\x6C\x83" + "\x2A\x2B\x47\xD0\x87\xB0\xFC\x3D\x3C\x36\xC2\x08\xFC\x3F\x47\x91\xC5\xF5\xF3\xC1" + "\xDC\x3D\x0E\xC2\x04\x19\x87\xD0\x84\x68\x08\x5D\x16\xC9\xC2\xF8\x21\x74\x18\x4E" + "\xCA\x10\xFC\x3E\xBC\x7B\x59\xEE\x04\xC9\xB3\x85\xF3"; // ++++++++++++++++++++^^^^^^^^^^^^^^^^^^^++++++++++++++++++++ // ++++++++++++++++++++ DO NOT EDIT ABOVE ++++++++++++++++++++ @@ -1887,7 +1887,11 @@ extern "C" { uint32_t convert_seconds_to_dhm(uint32_t seconds, char *unit, uint8_t *color){ static uint32_t conversions[3] = {24 * 3600, 3600, 60}; static char units[3] = { 'd', 'h', 'm'}; // day, hour, minute - static uint8_t colors[3] = { 0x60, 0xA0, 0xEA}; + uint8_t color_text_8 = WebColor(COL_TEXT) & 0xFF; // color of text on 8 bits + uint8_t color_back_8 = WebColor(COL_BACKGROUND) & 0xFF; // color of background on 8 bits + uint8_t colors[3] = { (uint8_t) changeUIntScale(6, 0, 16, color_back_8, color_text_8), // 6/16 of text + (uint8_t) changeUIntScale(10, 0, 16, color_back_8, color_text_8), // 10/16 of text color + color_text_8}; for(int i = 0; i < 3; ++i) { *color = colors[i]; *unit = units[i]; @@ -1915,7 +1919,7 @@ void ZigbeeShow(bool json) if (!zigbee_num) { return; } if (zigbee_num > 255) { zigbee_num = 255; } - WSContentSend_P(msg[ZB_WEB_CSS]); + WSContentSend_P(msg[ZB_WEB_CSS], WebColor(COL_TEXT)); // WSContentSend_compressed(ZB_WEB, 0); // sort elements by name, then by id @@ -2044,11 +2048,11 @@ void ZigbeeShow(bool json) if (light.validHue() && light.validSat() && (channels >= 3)) { uint8_t r,g,b; uint8_t sat = changeUIntScale(light.getSat(), 0, 254, 0, 255); // scale to 0..255 - LightStateClass::HsToRgb(light.getHue(), sat, &r, &g, &b); + HsToRgb(light.getHue(), sat, &r, &g, &b); WSContentSend_P(msg[ZB_WEB_COLOR_RGB], r,g,b,r,g,b); } else if (light.validX() && light.validY() && (channels >= 3)) { uint8_t r,g,b; - LightStateClass::XyToRgb(light.getX() / 65535.0f, light.getY() / 65535.0f, &r, &g, &b); + XyToRgb(light.getX() / 65535.0f, light.getY() / 65535.0f, &r, &g, &b); WSContentSend_P(msg[ZB_WEB_COLOR_RGB], r,g,b,r,g,b); } } @@ -2068,7 +2072,7 @@ void ZigbeeShow(bool json) WSContentSend_P(msg[ZB_WEB_LINE_END]); // Terminate current multi column table and open new table if (zigbee.permit_end_time) { // PermitJoin in progress - + WSContentSend_P(msg[ZB_WEB_PERMITJOIN_ACTIVE], D_ZIGBEE_PERMITJOIN_ACTIVE); } #endif @@ -2081,7 +2085,7 @@ void ZigbeeMapRefresh(void) { ZigbeeMapAllDevices(); } Webserver->sendHeader("Location","/zbm"); // Add a header to respond with a new location for the browser to go to the home page again - Webserver->send(302); + Webserver->send(302); } // Display a graphical representation of the Zigbee map using vis.js network diff --git a/tasmota/xdrv_24_buzzer.ino b/tasmota/xdrv_24_buzzer.ino index 8dcb949c9..e6665e21f 100644 --- a/tasmota/xdrv_24_buzzer.ino +++ b/tasmota/xdrv_24_buzzer.ino @@ -1,7 +1,7 @@ /* xdrv_24_Buzzer.ino - buzzer support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xdrv_25_A4988_Stepper.ino b/tasmota/xdrv_25_A4988_Stepper.ino index f70ed76f0..50e9997b1 100644 --- a/tasmota/xdrv_25_A4988_Stepper.ino +++ b/tasmota/xdrv_25_A4988_Stepper.ino @@ -2,7 +2,7 @@ /* xdrv_25_a4988_stepper.ino - A4988 StepMotorDriverCircuit- support for Tasmota - Copyright (C) 2020 Tim Leuscher and Theo Arends + Copyright (C) 2021 Tim Leuscher and 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 diff --git a/tasmota/xdrv_26_ariluxrf.ino b/tasmota/xdrv_26_ariluxrf.ino index dc0010ac1..fca693c8d 100644 --- a/tasmota/xdrv_26_ariluxrf.ino +++ b/tasmota/xdrv_26_ariluxrf.ino @@ -1,7 +1,7 @@ /* xdrv_26_ariluxrf.ino - Arilux Rf support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 735277e32..cd54878d7 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -1,7 +1,7 @@ /* xdrv_27_Shutter[i].ino - Shutter/Blind support for Tasmota - Copyright (C) 2020 Stefan Bode + Copyright (C) 2021 Stefan Bode 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 @@ -107,7 +107,7 @@ void ShutterLogPos(uint32_t i) { char stemp2[10]; dtostrfd((float)Shutter[i].time / STEPS_PER_SECOND, 2, stemp2); - AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d Real %d, Start %d, Stop %d, Dir %d, Delay %d, Rtc %s [s], Freq %d, PWM %d"), + AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Real %d, Start %d, Stop %d, Dir %d, Delay %d, Rtc %s [s], Freq %d, PWM %d"), i+1, Shutter[i].real_position, Shutter[i].start_position, Shutter[i].target_position, Shutter[i].direction, Shutter[i].motordelay, stemp2, Shutter[i].pwm_velocity, Shutter[i].pwm_value); } @@ -144,7 +144,7 @@ void ShutterRtc50mS(void) case SHT_COUNTER: if (Shutter[i].accelerator) { - //AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: accelerator i=%d -> %d"),i, Shutter[i].accelerator); + //AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Accelerator i=%d -> %d"),i, Shutter[i].accelerator); ShutterUpdateVelocity(i); analogWriteFreq(Shutter[i].pwm_velocity); analogWrite(Pin(GPIO_PWM1, i), 50); @@ -155,7 +155,7 @@ void ShutterRtc50mS(void) } } -int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index) +int32_t ShutterPercentToRealPosition(int16_t percent, uint32_t index) { if (Settings.shutter_set50percent[index] != 50) { return (percent <= 5) ? Settings.shuttercoeff[2][index] * percent*10 : (Settings.shuttercoeff[1][index] * percent + (Settings.shuttercoeff[0][index]*10))*10; @@ -173,49 +173,48 @@ int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index) for (uint32_t k = 0; k < 5; k++) { if ((percent * 10) >= Settings.shuttercoeff[k][index]) { realpos = SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[k+1], 100); - //AddLog_P(LOG_LEVEL_ERROR, PSTR("Realposition TEMP1: %d, %d %%, coeff %d"), realpos, percent, Settings.shuttercoeff[k][index]); + //AddLog_P(LOG_LEVEL_ERROR, PSTR("SHT: Realposition TEMP1: %d, %d %%, coeff %d"), realpos, percent, Settings.shuttercoeff[k][index]); } else { - //AddLog_P(LOG_LEVEL_ERROR, PSTR("Shutter[%d].open_max: %d"),index, Shutter[index].open_max); + //AddLog_P(LOG_LEVEL_ERROR, PSTR("SHT: Shutter[%d].open_max: %d"),index, Shutter[index].open_max); if (0 == k) { - realpos = SHT_DIV_ROUND(SHT_DIV_ROUND(percent * Shutter[index].open_max * calibrate_pos[k+1], Settings.shuttercoeff[k][index]), 10 ); - //AddLog_P(LOG_LEVEL_ERROR, PSTR("Realposition TEMP3: %d, %d %%, coeff %d"), realpos, percent, Settings.shuttercoeff[k][index]); + realpos = SHT_DIV_ROUND((int64_t)percent * Shutter[index].open_max * calibrate_pos[k+1], Settings.shuttercoeff[k][index]*10 ); + //AddLog_P(LOG_LEVEL_ERROR, PSTR("SHT: Realposition TEMP3: %d, %d %%, coeff %d"), realpos, percent, Settings.shuttercoeff[k][index]); } else { //uint32_t addon = ( percent*10 - Settings.shuttercoeff[k-1][index] ) * Shutter[index].open_max * (calibrate_pos[k+1] - calibrate_pos[k]) / (Settings.shuttercoeff[k][index] -Settings.shuttercoeff[k-1][index]) / 100; - //AddLog_P(LOG_LEVEL_ERROR, PSTR("Realposition TEMP2: %d, %d %%, coeff %d"), addon, (calibrate_pos[k+1] - calibrate_pos[k]), (Settings.shuttercoeff[k][index] -Settings.shuttercoeff[k-1][index])); - realpos += SHT_DIV_ROUND(SHT_DIV_ROUND((percent*10 - Settings.shuttercoeff[k-1][index] ) * Shutter[index].open_max * (calibrate_pos[k+1] - calibrate_pos[k]), Settings.shuttercoeff[k][index] - Settings.shuttercoeff[k-1][index]), 100); + //AddLog_P(LOG_LEVEL_ERROR, PSTR("SHT: Realposition TEMP2: %d, %d %%, coeff %d"), addon, (calibrate_pos[k+1] - calibrate_pos[k]), (Settings.shuttercoeff[k][index] -Settings.shuttercoeff[k-1][index])); + realpos += SHT_DIV_ROUND(((int64_t)percent*10 - Settings.shuttercoeff[k-1][index] ) * Shutter[index].open_max * (calibrate_pos[k+1] - calibrate_pos[k]), (Settings.shuttercoeff[k][index] - Settings.shuttercoeff[k-1][index])*100); } break; } } - return realpos; + return realpos < 0 ? 0 : realpos; } } -uint8_t ShutterRealToPercentPosition(int64_t realpos, uint32_t index) +uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index) { if (Settings.shutter_set50percent[index] != 50) { return (Settings.shuttercoeff[2][index] * 5 > realpos/10) ? SHT_DIV_ROUND(realpos/10, Settings.shuttercoeff[2][index]) : SHT_DIV_ROUND(realpos/10-Settings.shuttercoeff[0][index]*10, Settings.shuttercoeff[1][index]); } else { - uint64_t realpercent; + int64_t realpercent; for (uint32_t j = 0; j < 5; j++) { if (realpos >= Shutter[index].open_max * calibrate_pos[j+1] / 100) { realpercent = SHT_DIV_ROUND(Settings.shuttercoeff[j][index], 10); - //AddLog_P(LOG_LEVEL_ERROR, PSTR("Realpercent TEMP1: %d %%, %d, coeff %d"), realpercent, realpos, Shutter[index].open_max * calibrate_pos[j+1] / 100); + //AddLog_P(LOG_LEVEL_ERROR, PSTR("SHT: Realpercent TEMP1: %d %%, %d, coeff %d"), realpercent, realpos, Shutter[index].open_max * calibrate_pos[j+1] / 100); } else { - //AddLog_P(LOG_LEVEL_ERROR, PSTR("Shutter[%d].open_max: %d"),index, Shutter[index].open_max); + //AddLog_P(LOG_LEVEL_ERROR, PSTR("SHT: Shutter[%d].open_max: %d"),index, Shutter[index].open_max); if (0 == j) { - realpercent = SHT_DIV_ROUND(SHT_DIV_ROUND((realpos - SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[j], 100)) * Settings.shuttercoeff[j][index], calibrate_pos[j+1]/10), Shutter[index].open_max); - //AddLog_P(LOG_LEVEL_ERROR, PSTR("Realpercent TEMP3: %d %%, %d, coeff %d"), realpercent, realpos, Shutter[index].open_max * calibrate_pos[j+1] / 100); + realpercent = SHT_DIV_ROUND(((int64_t)realpos - SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[j], 100)) * Settings.shuttercoeff[j][index], calibrate_pos[j+1]/10*Shutter[index].open_max); } else { //uint16_t addon = ( realpos - (Shutter[index].open_max * calibrate_pos[j] / 100) ) * 10 * (Settings.shuttercoeff[j][index] - Settings.shuttercoeff[j-1][index]) / (calibrate_pos[j+1] - calibrate_pos[j])/Shutter[index].open_max; //uint16_t addon = ( realpercent*10 - Settings.shuttercoeff[j-1][index] ) * Shutter[index].open_max * (calibrate_pos[j+1] - calibrate_pos[j]) / (Settings.shuttercoeff[j][index] -Settings.shuttercoeff[j-1][index]) / 100; - //AddLog_P(LOG_LEVEL_ERROR, PSTR("Realpercent TEMP2: %d %%, delta %d, %d, coeff %d"), addon,( realpos - (Shutter[index].open_max * calibrate_pos[j] / 100) ) , (calibrate_pos[j+1] - calibrate_pos[j])* Shutter[index].open_max/100, (Settings.shuttercoeff[j][index] -Settings.shuttercoeff[j-1][index])); - realpercent += SHT_DIV_ROUND(SHT_DIV_ROUND((realpos - SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[j], 100)) * (Settings.shuttercoeff[j][index] - Settings.shuttercoeff[j-1][index]), (calibrate_pos[j+1] - calibrate_pos[j])/10), Shutter[index].open_max) ; - } + //AddLog_P(LOG_LEVEL_ERROR, PSTR("SHT: Realpercent TEMP2: %d %%, delta %d, %d, coeff %d"), addon,( realpos - (Shutter[index].open_max * calibrate_pos[j] / 100) ) , (calibrate_pos[j+1] - calibrate_pos[j])* Shutter[index].open_max/100, (Settings.shuttercoeff[j][index] -Settings.shuttercoeff[j-1][index])); + realpercent += SHT_DIV_ROUND(((int64_t)realpos - SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[j], 100)) * (Settings.shuttercoeff[j][index] - Settings.shuttercoeff[j-1][index]), (calibrate_pos[j+1] - calibrate_pos[j])/10*Shutter[index].open_max) ; + } break; } } - return (int16_t)realpercent < 0 ? 0 : realpercent; + return realpercent < 0 ? 0 : realpercent; } } @@ -252,10 +251,10 @@ void ShutterInit(void) if (Settings.shutter_mode == SHT_UNDEF) { bool relay_in_interlock = false; - AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: mode undef.. calculate...")); + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Mode undef.. calculate...")); for (uint32_t j = 0; j < MAX_INTERLOCKS * Settings.flag.interlock; j++) { // CMND_INTERLOCK - Enable/disable interlock - //AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT: Interlock state i=%d %d, flag %d, , shuttermask %d, maskedIL %d"),i, Settings.interlock[i], Settings.flag.interlock,ShutterGlobal.RelayShutterMask, Settings.interlock[i]&ShutterGlobal.RelayShutterMask); + //AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT: Interlock state i=%d %d, flag %d, Shuttermask %d, MaskedIL %d"),i, Settings.interlock[i], Settings.flag.interlock,ShutterGlobal.RelayShutterMask, Settings.interlock[i]&ShutterGlobal.RelayShutterMask); if (Settings.interlock[j] && (Settings.interlock[j] & ShutterGlobal.RelayShutterMask)) { //AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT: Relay in Interlock group")); relay_in_interlock = true; @@ -294,7 +293,7 @@ void ShutterInit(void) Settings.shuttercoeff[1][i] = Shutter[i].open_max/10 * (100 - Settings.shutter_set50percent[i] ) / 5000 ; Settings.shuttercoeff[0][i] = Shutter[i].open_max/100 - (Settings.shuttercoeff[1][i] * 10); Settings.shuttercoeff[2][i] = (int32_t)(Settings.shuttercoeff[0][i]*10 + 5 * Settings.shuttercoeff[1][i]) / 5; - //AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT%d: Shutter[i].open_max %d, 50perc:%d, 0:%d, 1:%d 2:%d"), i, Shutter[i].open_max, Settings.shutter_set50percent[i], Settings.shuttercoeff[0][i],Settings.shuttercoeff[1][i],Settings.shuttercoeff[2][i]); + //AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Shutter[i].open_max %d, 50perc:%d, 0:%d, 1:%d 2:%d"), i, Shutter[i].open_max, Settings.shutter_set50percent[i], Settings.shuttercoeff[0][i],Settings.shuttercoeff[1][i],Settings.shuttercoeff[2][i]); } ShutterGlobal.RelayShutterMask |= 3 << (Settings.shutter_startrelay[i] -1); @@ -314,8 +313,8 @@ void ShutterInit(void) } Shutter[i].close_velocity_max = ShutterGlobal.open_velocity_max*Shutter[i].open_time / Shutter[i].close_time; - //AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shutter %d Openvel %d, Closevel: %d"),i, ShutterGlobal.open_velocity_max, Shutter[i].close_velocity_max); - AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT%d: Init. Pos: %d,inverted %d, locked %d, end stop time enabled %d, webButtons inverted %d"), + //AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Openvel %d, Closevel: %d"),i, ShutterGlobal.open_velocity_max, Shutter[i].close_velocity_max); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Init. Pos %d, Inverted %d, Locked %d, End stop time enabled %d, webButtons inverted %d"), i+1, Shutter[i].real_position, (Settings.shutter_options[i]&1) ? 1 : 0, (Settings.shutter_options[i]&2) ? 1 : 0, (Settings.shutter_options[i]&4) ? 1 : 0, (Settings.shutter_options[i]&8) ? 1 : 0); @@ -339,7 +338,7 @@ void ShutterReportPosition(bool always, uint32_t index) n = index+1; } for (i; i < n; i++) { - //AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Real Pos: %d"), i+1,Shutter[i].real_position); + //AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Real Pos %d"), i+1,Shutter[i].real_position); uint32_t position = ShutterRealToPercentPosition(Shutter[i].real_position, i); if (Shutter[i].direction != 0) { TasmotaGlobal.rules_flag.shutter_moving = 1; @@ -353,7 +352,7 @@ void ShutterReportPosition(bool always, uint32_t index) if (always || (TasmotaGlobal.rules_flag.shutter_moving)) { MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_PRFX_SHUTTER)); // RulesProcess() now re-entry protected } - //AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: TasmotaGlobal.rules_flag.shutter_moving: %d, moved %d"), TasmotaGlobal.rules_flag.shutter_moving, TasmotaGlobal.rules_flag.shutter_moved); + //AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: rules_flag.shutter_moving: %d, moved %d"), TasmotaGlobal.rules_flag.shutter_moving, TasmotaGlobal.rules_flag.shutter_moved); } void ShutterLimitRealAndTargetPositions(uint32_t i) { @@ -401,7 +400,7 @@ void ShutterDecellerateForStop(uint8_t i) int16_t missing_steps; Shutter[i].accelerator = -(ShutterGlobal.open_velocity_max / (Shutter[i].motordelay>4 ? (Shutter[i].motordelay*11)/10 : 4) ); while (Shutter[i].pwm_velocity > -2*Shutter[i].accelerator ) { - AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: velocity: %ld, delta: %d"), Shutter[i].pwm_velocity, Shutter[i].accelerator ); + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Velocity %ld, Delta %d"), Shutter[i].pwm_velocity, Shutter[i].accelerator ); //Shutter[i].pwm_velocity = tmax(Shutter[i].pwm_velocity-Shutter[i].accelerator , 0); // Control will be done in RTC Ticker. delay(50); @@ -409,7 +408,7 @@ void ShutterDecellerateForStop(uint8_t i) if (ShutterGlobal.position_mode == SHT_COUNTER){ missing_steps = ((Shutter[i].target_position-Shutter[i].start_position)*Shutter[i].direction*ShutterGlobal.open_velocity_max/RESOLUTION/STEPS_PER_SECOND) - RtcSettings.pulse_counter[i]; //prepare for stop PWM - AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Remain steps %d, counter %d, freq %d"), missing_steps, RtcSettings.pulse_counter[i] ,Shutter[i].pwm_velocity); + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Remain steps %d, Counter %d, Freq %d"), missing_steps, RtcSettings.pulse_counter[i] ,Shutter[i].pwm_velocity); Shutter[i].accelerator = 0; Shutter[i].pwm_velocity = Shutter[i].pwm_velocity > 250 ? 250 : Shutter[i].pwm_velocity; analogWriteFreq(Shutter[i].pwm_velocity); @@ -421,7 +420,7 @@ void ShutterDecellerateForStop(uint8_t i) } analogWrite(Pin(GPIO_PWM1, i), 0); // removed with 8.3 because of reset caused by watchog Shutter[i].real_position = ShutterCalculatePosition(i); - AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Real %d, pulsecount %d, start %d"), Shutter[i].real_position,RtcSettings.pulse_counter[i], Shutter[i].start_position); + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Real %d, Pulsecount %d, Start %d"), Shutter[i].real_position,RtcSettings.pulse_counter[i], Shutter[i].start_position); } Shutter[i].direction = 0; @@ -482,9 +481,9 @@ void ShutterUpdatePosition(void) XdrvRulesProcess(); ShutterGlobal.start_reported = 1; } - AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: time: %d, toBeAcc %d, current_stop_way %d,vel_cur %d, vel_max %d, act_vel_change %d, min_runtime_ms %d, act.pos %d, next_stop %d, target: %d, max_vel_change %d, dir: %d"),Shutter[i].time,toBeAcc,current_stop_way, - Shutter[i].pwm_velocity,velocity_max, Shutter[i].accelerator,min_runtime_ms,Shutter[i].real_position, next_possible_stop_position,Shutter[i].target_position,velocity_change_per_step_max,Shutter[i].direction); - + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Time %d, toBA %d, cStop %d, cVelo %d, mVelo %d, aVelo %d, mRun %d, aPos %d, nStop %d, Trgt %d, mVelo %d, Dir %d"), + Shutter[i].time, toBeAcc, current_stop_way, Shutter[i].pwm_velocity, velocity_max, Shutter[i].accelerator, min_runtime_ms, Shutter[i].real_position, + next_possible_stop_position, Shutter[i].target_position, velocity_change_per_step_max, Shutter[i].direction); if ( Shutter[i].real_position * Shutter[i].direction >= Shutter[i].target_position * Shutter[i].direction || Shutter[i].pwm_velocity> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_IGNORE != TasmotaGlobal.last_source && SRC_SHUTTER != TasmotaGlobal.last_source && SRC_PULSETIMER != TasmotaGlobal.last_source ; uint8 manual_relays_changed = ((ShutterGlobal.RelayCurrentMask >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_SHUTTER != TasmotaGlobal.last_source && SRC_PULSETIMER != TasmotaGlobal.last_source ; - AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shutter %d: source: %s, powerstate_local %ld, ShutterGlobal.RelayCurrentMask %d, manual change %d"), i+1, GetTextIndexed(stemp1, sizeof(stemp1), TasmotaGlobal.last_source, kCommandSource), powerstate_local,ShutterGlobal.RelayCurrentMask,manual_relays_changed); + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d, Source %s, Powerstate %ld, RelayMask %d, ManualChange %d"), + i+1, GetTextIndexed(stemp1, sizeof(stemp1), TasmotaGlobal.last_source, kCommandSource), powerstate_local,ShutterGlobal.RelayCurrentMask,manual_relays_changed); if (manual_relays_changed) { //ShutterGlobal.skip_relay_change = true; ShutterLimitRealAndTargetPositions(i); @@ -614,7 +614,8 @@ void ShutterRelayChanged(void) if (Shutter[i].direction != 0 && powerstate_local) { Shutter[i].target_position = Shutter[i].real_position; powerstate_local = 0; - AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shutter %d: Switch OFF motor. Target: %ld, source: %s, powerstate_local %ld, ShutterGlobal.RelayCurrentMask %d, manual change %d"), i+1, Shutter[i].target_position, GetTextIndexed(stemp1, sizeof(stemp1), TasmotaGlobal.last_source, kCommandSource), powerstate_local,ShutterGlobal.RelayCurrentMask,manual_relays_changed); + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d, Switch OFF motor. Target %ld, Source %s, Powerstate %ld, RelayMask %d, ManualChange %d"), + i+1, Shutter[i].target_position, GetTextIndexed(stemp1, sizeof(stemp1), TasmotaGlobal.last_source, kCommandSource), powerstate_local,ShutterGlobal.RelayCurrentMask,manual_relays_changed); } break; default: @@ -636,7 +637,7 @@ void ShutterRelayChanged(void) ShutterStartInit(i, -1, 0); break; default: - //AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shutter %d: Switch OFF motor."),i); + //AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Switch OFF motor."),i); Shutter[i].target_position = Shutter[i].real_position; } break; @@ -649,7 +650,7 @@ void ShutterRelayChanged(void) ShutterStartInit(i, -1, 0); break; default: - //AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shutter %d: Switch OFF motor."),i); + //AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Switch OFF motor."),i); Shutter[i].target_position = Shutter[i].real_position; } break; @@ -657,7 +658,7 @@ void ShutterRelayChanged(void) switch (powerstate_local) { case 1: ShutterStartInit(i, Shutter[i].lastdirection*-1 , Shutter[i].lastdirection == 1 ? 0 : Shutter[i].open_max); - AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shutter %d Garage. NewTarget %d"), i, Shutter[i].target_position); + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Garage. NewTarget %d"), i, Shutter[i].target_position); break; default: Shutter[i].target_position = Shutter[i].real_position; @@ -665,7 +666,7 @@ void ShutterRelayChanged(void) } // switch (ShutterGlobal.position_mode) - AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shutter %d: Target: %ld, powerstatelocal %d"), i+1, Shutter[i].target_position, powerstate_local); + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d, Target %ld, Powerstatelocal %d"), i+1, Shutter[i].target_position, powerstate_local); } // if (manual_relays_changed) } // for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) } @@ -756,15 +757,16 @@ void ShutterButtonHandler(void) // check for simultaneous shutter button press uint32 min_shutterbutton_press_counter = -1; // -1 == max(uint32) for (uint32_t i = 0; i < MAX_KEYS; i++) { - AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Settings.shutter_button[i] %ld, shutter_index %d, Button.press_counter[i] %d, min_shutterbutton_press_counter %d, i %d"), Settings.shutter_button[i], shutter_index, Button.press_counter[i] , min_shutterbutton_press_counter, i); + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: ShutterButton[i] %ld, ShutterIndex %d, ButtonPressCounter[i] %d, minShutterButtonPressCounter %d, i %d"), + Settings.shutter_button[i], shutter_index, Button.press_counter[i] , min_shutterbutton_press_counter, i); if ((button_index != i) && (Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (i != button_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) { min_shutterbutton_press_counter = Button.press_counter[i]; - AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: min_shutterbutton_press_counter %d"), min_shutterbutton_press_counter); + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: minShutterButtonPressCounter %d"), min_shutterbutton_press_counter); } } if (min_shutterbutton_press_counter == Button.press_counter[button_index]) { // simultaneous shutter button press detected - AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: simultanous presss deteced")); + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Simultanous press detected")); press_index = Button.press_counter[button_index]; for (uint32_t i = 0; i < MAX_KEYS; i++) if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) != shutter_index)) @@ -811,7 +813,7 @@ void ShutterButtonHandler(void) if (Settings.shutter_startrelay[shutter_index] && Settings.shutter_startrelay[shutter_index] <9) { uint8_t pos_press_index = (buttonState == SHT_PRESSED_HOLD) ? 3 : (press_index-1); if (pos_press_index>3) pos_press_index=3; - AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: shutter %d, button %d = %d (single=1, double=2, tripple=3, hold=4)"), shutter_index+1, button_index+1, pos_press_index+1); + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d, Button %d = %d (single=1, double=2, tripple=3, hold=4)"), shutter_index+1, button_index+1, pos_press_index+1); XdrvMailbox.index = shutter_index +1; TasmotaGlobal.last_source = SRC_BUTTON; XdrvMailbox.data_len = 0; @@ -829,7 +831,7 @@ void ShutterButtonHandler(void) CmndShutterStop(); } else { XdrvMailbox.payload = position = (position-1)<<1; - //AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: shutter %d -> %d"), shutter_index+1, position); + //AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d -> %d"), shutter_index+1, position); if (102 == position) { XdrvMailbox.payload = XdrvMailbox.index; CmndShutterToggle(); @@ -985,7 +987,7 @@ void CmndShutterStop(void) AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT: Stop moving %d: dir: %d"), XdrvMailbox.index, Shutter[i].direction); Shutter[i].target_position = Shutter[i].real_position; - } + } if (XdrvMailbox.command) ResponseCmndDone(); } else { @@ -1399,7 +1401,7 @@ void CmndShutterPwmRange(void) } Settings.shutter_pwmrange[i][XdrvMailbox.index -1] = field; } - AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT%d: Init1. pwmmin %d, pwmmax %d"), XdrvMailbox.index , Settings.shutter_pwmrange[0][XdrvMailbox.index -1], Settings.shutter_pwmrange[1][XdrvMailbox.index -1]); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Init1. pwmmin %d, pwmmax %d"), XdrvMailbox.index , Settings.shutter_pwmrange[0][XdrvMailbox.index -1], Settings.shutter_pwmrange[1][XdrvMailbox.index -1]); ShutterInit(); ResponseCmndIdxChar(XdrvMailbox.data); } else { @@ -1432,7 +1434,7 @@ void CmndShutterCalibration(void) Settings.shutter_set50percent[XdrvMailbox.index -1] = 50; for (i = 0; i < 5; i++) { Settings.shuttercoeff[i][XdrvMailbox.index -1] = SHT_DIV_ROUND((uint32_t)messwerte[i] * 1000, messwerte[4]); - AddLog_P(LOG_LEVEL_DEBUG, PSTR("Settings.shuttercoeff: %d, i: %d, value: %d, messwert %d"), i,XdrvMailbox.index -1,Settings.shuttercoeff[i][XdrvMailbox.index -1], messwerte[i]); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT: Shuttercoeff %d, i %d, Value %d, MeasuredValue %d"), i,XdrvMailbox.index -1,Settings.shuttercoeff[i][XdrvMailbox.index -1], messwerte[i]); } ShutterInit(); ResponseCmndIdxChar(XdrvMailbox.data); @@ -1513,7 +1515,7 @@ bool Xdrv27(uint8_t function) char stemp1[10]; // extract the number of the relay that was switched and save for later in Update Position. ShutterGlobal.RelayCurrentMask = XdrvMailbox.index ^ ShutterGlobal.RelayOldMask; - AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Switched relay: %d by %s"), ShutterGlobal.RelayCurrentMask,GetTextIndexed(stemp1, sizeof(stemp1), TasmotaGlobal.last_source, kCommandSource)); + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Switched relay %d by %s"), ShutterGlobal.RelayCurrentMask,GetTextIndexed(stemp1, sizeof(stemp1), TasmotaGlobal.last_source, kCommandSource)); ShutterRelayChanged(); ShutterGlobal.RelayOldMask = XdrvMailbox.index; break; @@ -1526,10 +1528,10 @@ bool Xdrv27(uint8_t function) } ShutterGlobal.RelayCurrentMask >>= 1; } - //AddLog_P(LOG_LEVEL_ERROR, PSTR("SHT: skip relay change: %d"),i+1); + //AddLog_P(LOG_LEVEL_ERROR, PSTR("SHT: Skip relay change %d"), i+1); result = true; ShutterGlobal.skip_relay_change = 0; - AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Skipping switch off relay %d"),i); + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Skipping switch off relay %d"), i); ExecuteCommandPowerShutter(i+1, 0, SRC_SHUTTER); } break; diff --git a/tasmota/xdrv_28_pcf8574.ino b/tasmota/xdrv_28_pcf8574.ino index f7939a815..58bb5239c 100644 --- a/tasmota/xdrv_28_pcf8574.ino +++ b/tasmota/xdrv_28_pcf8574.ino @@ -1,7 +1,7 @@ /* xdrv_28_pcf8574.ino - PCF8574 I2C support for Tasmota - Copyright (C) 2020 Stefan Bode + Copyright (C) 2021 Stefan Bode 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 diff --git a/tasmota/xdrv_29_deepsleep.ino b/tasmota/xdrv_29_deepsleep.ino index 6b6492f1a..3e28a9d31 100644 --- a/tasmota/xdrv_29_deepsleep.ino +++ b/tasmota/xdrv_29_deepsleep.ino @@ -1,7 +1,7 @@ /* xdrv_29_deepsleep.ino - DeepSleep support for Tasmota - Copyright (C) 2020 Stefan Bode + Copyright (C) 2021 Stefan Bode 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 @@ -142,6 +142,7 @@ void DeepSleepStart(void) WifiShutdown(); RtcSettings.ultradeepsleep = RtcSettings.nextwakeup - UtcTime(); RtcSettingsSave(); + RtcRebootReset(); #ifdef ESP8266 ESP.deepSleep(100 * RtcSettings.deepsleep_slip * deepsleep_sleeptime); #endif // ESP8266 diff --git a/tasmota/xdrv_30_exs_dimmer.ino b/tasmota/xdrv_30_exs_dimmer.ino index 84b051c68..b704d616d 100644 --- a/tasmota/xdrv_30_exs_dimmer.ino +++ b/tasmota/xdrv_30_exs_dimmer.ino @@ -1,7 +1,7 @@ /* xdrv_30_exs_dimmer.ino - ex-store dimmer support for Tasmota - Copyright (C) 2020 Andreas Schultz + Copyright (C) 2021 Andreas Schultz 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 diff --git a/tasmota/xdrv_31_tasmota_client.ino b/tasmota/xdrv_31_tasmota_client.ino index cac38cf01..bf4426b61 100644 --- a/tasmota/xdrv_31_tasmota_client.ino +++ b/tasmota/xdrv_31_tasmota_client.ino @@ -1,7 +1,7 @@ /* xdrv_31_tasmota_client.ino - Support for external microcontroller on serial - Copyright (C) 2020 Andre Thomas and Theo Arends + Copyright (C) 2021 Andre Thomas and 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 diff --git a/tasmota/xdrv_32_hotplug.ino b/tasmota/xdrv_32_hotplug.ino index bfdafbd4b..e7dc4ac69 100644 --- a/tasmota/xdrv_32_hotplug.ino +++ b/tasmota/xdrv_32_hotplug.ino @@ -1,7 +1,7 @@ /* xdrv_32_hotplug.ino - HotPlug support for sensors - Copyright (C) 2020 Leonid Myravjev + Copyright (C) 2021 Leonid Myravjev 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 diff --git a/tasmota/xdrv_33_nrf24l01.ino b/tasmota/xdrv_33_nrf24l01.ino index 7c4d1b843..e992c398b 100644 --- a/tasmota/xdrv_33_nrf24l01.ino +++ b/tasmota/xdrv_33_nrf24l01.ino @@ -1,7 +1,7 @@ /* xdrv_33_nrf24l01.ino - nrf24l01 support for Tasmota - Copyright (C) 2020 Christian Baars and Theo Arends + Copyright (C) 2021 Christian Baars and 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 @@ -34,7 +34,7 @@ /*********************************************************************************************\ * NRF24l01(+) * -* Usage: 5 SPI-data-wires plus VVC/ground, use hardware SPI, select GPIO_SPI_CS/GPIO_SPI_DC +* Usage: 5 SPI-data-wires plus VVC/ground, use hardware SPI, select GPIO_NRF24_CS/GPIO_NRF24_DC \*********************************************************************************************/ #define XDRV_33 33 @@ -51,45 +51,40 @@ struct { RF24 NRF24radio; -bool NRF24initRadio() -{ - NRF24radio.begin(Pin(GPIO_SPI_CS),Pin(GPIO_SPI_DC)); +bool NRF24initRadio() { + NRF24radio.begin(Pin(GPIO_NRF24_CS), Pin(GPIO_NRF24_DC)); NRF24radio.powerUp(); - if(NRF24radio.isChipConnected()){ - DEBUG_DRIVER_LOG(PSTR("NRF24 chip connected")); + if (NRF24radio.isChipConnected()) { + DEBUG_DRIVER_LOG(PSTR("NRF: Chip connected")); return true; } - DEBUG_DRIVER_LOG(PSTR("NRF24 chip NOT !!!! connected")); + DEBUG_DRIVER_LOG(PSTR("NRF: Chip NOT !!!! connected")); return false; } -bool NRF24Detect(void) -{ - if (PinUsed(GPIO_SPI_CS) && PinUsed(GPIO_SPI_DC)) { - if(NRF24initRadio()){ +void NRF24Detect(void) { + if (PinUsed(GPIO_NRF24_CS) && PinUsed(GPIO_NRF24_DC) && TasmotaGlobal.spi_enabled) { + if (NRF24initRadio()) { NRF24.chipType = 32; // SPACE - AddLog_P(LOG_LEVEL_INFO,PSTR("NRF24L01 initialized")); - if(NRF24radio.isPVariant()){ + AddLog_P(LOG_LEVEL_INFO, PSTR("NRF: Model 24L01 initialized")); + if (NRF24radio.isPVariant()) { NRF24.chipType = 43; // + - AddLog_P(LOG_LEVEL_INFO,PSTR("NRF24L01+ detected")); + AddLog_P(LOG_LEVEL_INFO, PSTR("NRF: Model 24L01+ detected")); } - return true; } } - return false; } /*********************************************************************************************\ * Interface \*********************************************************************************************/ -bool Xdrv33(uint8_t function) -{ +bool Xdrv33(uint8_t function) { bool result = false; if (FUNC_INIT == function) { - result = NRF24Detect(); + NRF24Detect(); } return result; } diff --git a/tasmota/xdrv_34_wemos_motor_v1.ino b/tasmota/xdrv_34_wemos_motor_v1.ino index 9e6c0a967..cfd9de2d2 100644 --- a/tasmota/xdrv_34_wemos_motor_v1.ino +++ b/tasmota/xdrv_34_wemos_motor_v1.ino @@ -1,7 +1,7 @@ /* xdrv_34_wemos_motor_v1.ino - Support for I2C WEMOS motor shield (6612FNG) - Copyright (C) 2020 Denis Sborets and Theo Arends + Copyright (C) 2021 Denis Sborets and 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 diff --git a/tasmota/xdrv_35_pwm_dimmer.ino b/tasmota/xdrv_35_pwm_dimmer.ino index c54d071f1..3bca88477 100644 --- a/tasmota/xdrv_35_pwm_dimmer.ino +++ b/tasmota/xdrv_35_pwm_dimmer.ino @@ -1,7 +1,7 @@ /* xdrv_35_pwm_dimmer.ino - PWM Dimmer Switch support for Tasmota - Copyright (C) 2020 Paul C Diem + Copyright (C) 2021 Paul C Diem 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 @@ -99,7 +99,7 @@ void PWMModulePreInit(void) // determine how long a button is held before a reset command is executed. If SetOption32 is // still 5, change it to 40 (the default). if (Settings.param[P_HOLD_TIME] == 5) Settings.param[P_HOLD_TIME] = 40; - + // Make sure the brightness level settings are sensible. if (!Settings.bri_power_on) Settings.bri_power_on = 128; if (!Settings.bri_preset_low) Settings.bri_preset_low = 10; @@ -286,7 +286,7 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed) uint32_t now = millis(); // If the button was pressed and released but was not processed by support_button because the - // button interval had not elapsed, + // button interval had not elapsed, if (button_unprocessed[button_index]) { mqtt_trigger = 5; #ifdef USE_PWM_DIMMER_REMOTE diff --git a/tasmota/xdrv_36_keeloq.ino b/tasmota/xdrv_36_keeloq.ino index a1a392897..4a0f33a83 100644 --- a/tasmota/xdrv_36_keeloq.ino +++ b/tasmota/xdrv_36_keeloq.ino @@ -1,7 +1,7 @@ /* xdrv_36_keeloq.ino - Jarolift Keeloq shutter support for Tasmota - Copyright (C) 2020 he-so + Copyright (C) 2021 he-so 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 diff --git a/tasmota/xdrv_37_sonoff_d1.ino b/tasmota/xdrv_37_sonoff_d1.ino index 30b061775..5abefd452 100644 --- a/tasmota/xdrv_37_sonoff_d1.ino +++ b/tasmota/xdrv_37_sonoff_d1.ino @@ -1,7 +1,7 @@ /* xdrv_37_sonoff_d1.ino - sonoff D1 dimmer support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xdrv_38_ping.ino b/tasmota/xdrv_38_ping.ino index d4d5ea5d9..3f87a54bb 100644 --- a/tasmota/xdrv_38_ping.ino +++ b/tasmota/xdrv_38_ping.ino @@ -1,7 +1,7 @@ /* xdrv_38_ping.ino - support for ICMP Ping - Copyright (C) 2020 Theo Arends and Stephan Hadinger + Copyright (C) 2021 Theo Arends and Stephan Hadinger 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 diff --git a/tasmota/xdrv_39_thermostat.ino b/tasmota/xdrv_39_thermostat.ino index d8cd0f11c..455e45f13 100644 --- a/tasmota/xdrv_39_thermostat.ino +++ b/tasmota/xdrv_39_thermostat.ino @@ -1,7 +1,7 @@ /* xdrv_39_thermostat.ino - Thermostat controller for Tasmota - Copyright (C) 2020 Javier Arigita + Copyright (C) 2021 Javier Arigita 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 diff --git a/tasmota/xdrv_40_telegram.ino b/tasmota/xdrv_40_telegram.ino index 628ae0782..a96842065 100644 --- a/tasmota/xdrv_40_telegram.ino +++ b/tasmota/xdrv_40_telegram.ino @@ -1,7 +1,7 @@ /* xdrv_40_telegram.ino - telegram for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xdrv_41_tcp_bridge.ino b/tasmota/xdrv_41_tcp_bridge.ino index 3bd1e045c..7533e7d6d 100644 --- a/tasmota/xdrv_41_tcp_bridge.ino +++ b/tasmota/xdrv_41_tcp_bridge.ino @@ -1,7 +1,7 @@ /* xdrv_41_tcp_bridge.ino - TCP to serial bridge - Copyright (C) 2020 Theo Arends and Stephan Hadinger + Copyright (C) 2021 Theo Arends and Stephan Hadinger 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 diff --git a/tasmota/xdrv_42_i2s_audio.ino b/tasmota/xdrv_42_i2s_audio.ino index 6f82b63bc..1e468593b 100644 --- a/tasmota/xdrv_42_i2s_audio.ino +++ b/tasmota/xdrv_42_i2s_audio.ino @@ -1,7 +1,7 @@ /* xdrv_42_i2s_audio.ino - audio dac support for Tasmota - Copyright (C) 2020 Gerhard Mutz and Theo Arends + Copyright (C) 2021 Gerhard Mutz and 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 @@ -17,7 +17,7 @@ along with this program. If not, see . */ -#if (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH)) +#if (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH) || defined(USE_M5STACK_CORE2)) #include "AudioFileSourcePROGMEM.h" #include "AudioFileSourceID3.h" #include "AudioGeneratorMP3.h" @@ -31,18 +31,32 @@ #include "AudioFileSourceBuffer.h" #include "AudioGeneratorAAC.h" +#undef AUDIO_PWR_ON +#undef AUDIO_PWR_OFF +#define AUDIO_PWR_ON +#define AUDIO_PWR_OFF + #ifdef USE_TTGO_WATCH -#undef TTGO_PWR_ON -#undef TTGO_PWR_OFF -#define TTGO_PWR_ON TTGO_audio_power(true); -#define TTGO_PWR_OFF TTGO_audio_power(false); -#else -#undef TTGO_PWR_ON -#undef TTGO_PWR_OFF -#define TTGO_PWR_ON -#define TTGO_PWR_OFF +#undef AUDIO_PWR_ON +#undef AUDIO_PWR_OFF +#define AUDIO_PWR_ON TTGO_audio_power(true); +#define AUDIO_PWR_OFF TTGO_audio_power(false); #endif // USE_TTGO_WATCH +#ifdef USE_M5STACK_CORE2 +#undef AUDIO_PWR_ON +#undef AUDIO_PWR_OFF +#define AUDIO_PWR_ON CORE2_audio_power(true); +#define AUDIO_PWR_OFF CORE2_audio_power(false); +#undef DAC_IIS_BCK +#undef DAC_IIS_WS +#undef DAC_IIS_DOUT +#define DAC_IIS_BCK 12 +#define DAC_IIS_WS 0 +#define DAC_IIS_DOUT 2 +#endif // USE_M5STACK_CORE2 + + #define EXTERNAL_DAC_PLAY 1 #define XDRV_42 42 @@ -82,26 +96,36 @@ AudioGeneratorTalkie *talkie = nullptr; //! MAX98357A + INMP441 DOUBLE I2S BOARD #ifdef ESP8266 -#undef TWATCH_DAC_IIS_BCK -#undef TWATCH_DAC_IIS_WS -#undef TWATCH_DAC_IIS_DOUT -#define TWATCH_DAC_IIS_BCK 15 -#define TWATCH_DAC_IIS_WS 2 -#define TWATCH_DAC_IIS_DOUT 3 +#undef DAC_IIS_BCK +#undef DAC_IIS_WS +#undef DAC_IIS_DOUT +#define DAC_IIS_BCK 15 +#define DAC_IIS_WS 2 +#define DAC_IIS_DOUT 3 #endif // ESP8266 + +// defaults to TTGO WATCH #ifdef ESP32 -#ifndef TWATCH_DAC_IIS_BCK -#undef TWATCH_DAC_IIS_BCK -#define TWATCH_DAC_IIS_BCK 26 +#ifndef DAC_IIS_BCK +#undef DAC_IIS_BCK +#define DAC_IIS_BCK 26 #endif -#ifndef TWATCH_DAC_IIS_WS -#undef TWATCH_DAC_IIS_WS -#define TWATCH_DAC_IIS_WS 25 + +#ifndef DAC_IIS_WS +#undef DAC_IIS_WS +#define DAC_IIS_WS 25 #endif -#ifndef TWATCH_DAC_IIS_DOUT -#undef TWATCH_DAC_IIS_DOUT -#define TWATCH_DAC_IIS_DOUT 33 + +#ifndef DAC_IIS_DOUT +#undef DAC_IIS_DOUT +#define DAC_IIS_DOUT 33 #endif + +#ifndef DAC_IIS_DIN +#undef DAC_IIS_DIN +#define DAC_IIS_DIN 34 +#endif + #endif // ESP32 #ifdef SAY_TIME @@ -147,7 +171,10 @@ uint8_t spPAUSE1[] PROGMEM = {0x00,0x00,0x00,0x00,0xFF,0x0F}; void sayTime(int hour, int minutes, AudioGeneratorTalkie *talkie) ; void sayTime(int hour, int minutes, AudioGeneratorTalkie *talkie) { - TTGO_PWR_ON + + if (!out) return; + + AUDIO_PWR_ON talkie = new AudioGeneratorTalkie(); talkie->begin(nullptr, out); @@ -198,7 +225,7 @@ void sayTime(int hour, int minutes, AudioGeneratorTalkie *talkie) { } delete talkie; out->stop(); - TTGO_PWR_OFF + AUDIO_PWR_OFF } #endif @@ -210,11 +237,11 @@ void I2S_Init(void) { #if EXTERNAL_DAC_PLAY out = new AudioOutputI2S(); #ifdef ESP32 - out->SetPinout(TWATCH_DAC_IIS_BCK, TWATCH_DAC_IIS_WS, TWATCH_DAC_IIS_DOUT); + out->SetPinout(DAC_IIS_BCK, DAC_IIS_WS, DAC_IIS_DOUT); #endif // ESP32 #else out = new AudioOutputI2S(0, 1); -#endif +#endif // EXTERNAL_DAC_PLAY is2_volume=10; out->SetGain(((float)is2_volume/100.0)*4.0); @@ -241,6 +268,163 @@ void I2S_Init(void) { #endif // ESP32 } + + +#ifdef ESP32 +#define MODE_MIC 0 +#define MODE_SPK 1 +#define Speak_I2S_NUMBER I2S_NUM_0 +//#define MICSRATE 44100 +#define MICSRATE 16000 + +#include + +uint32_t SpeakerMic(uint8_t spkr) { + esp_err_t err = ESP_OK; + + if (out) { + out->stop(); + delete out; + out = nullptr; + } + + i2s_driver_uninstall(Speak_I2S_NUMBER); + if (spkr==MODE_SPK) { + out = new AudioOutputI2S(); + out->SetPinout(DAC_IIS_BCK, DAC_IIS_WS, DAC_IIS_DOUT); + out->SetGain(((float)is2_volume/100.0)*4.0); + out->stop(); + } else { + // config mic + i2s_config_t i2s_config = { + .mode = (i2s_mode_t)(I2S_MODE_MASTER), + .sample_rate = MICSRATE, + .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, + .channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT, + .communication_format = I2S_COMM_FORMAT_I2S, + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, + .dma_buf_count = 2, + //.dma_buf_len = 128, + .dma_buf_len = 1024, + }; + i2s_config.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM); + err += i2s_driver_install(Speak_I2S_NUMBER, &i2s_config, 0, NULL); + + i2s_pin_config_t tx_pin_config; + tx_pin_config.bck_io_num = DAC_IIS_BCK; + tx_pin_config.ws_io_num = DAC_IIS_WS; + tx_pin_config.data_out_num = DAC_IIS_DOUT; + tx_pin_config.data_in_num = DAC_IIS_DIN; + err += i2s_set_pin(Speak_I2S_NUMBER, &tx_pin_config); + + err += i2s_set_clk(Speak_I2S_NUMBER, MICSRATE, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO); + } + return err; +} + +#define DATA_SIZE 1024 + +TaskHandle_t mic_task_h; +uint32_t mic_size; +uint8_t *mic_buff; +char mic_path[32]; + +void mic_task(void *arg){ + uint32_t data_offset = 0; + while (1) { + uint32_t bytes_read; + i2s_read(Speak_I2S_NUMBER, (char *)(mic_buff + data_offset), DATA_SIZE, &bytes_read, (100 / portTICK_RATE_MS)); + if (bytes_read != DATA_SIZE) break; + data_offset += DATA_SIZE; + if (data_offset >= mic_size-DATA_SIZE) break; + } + SpeakerMic(MODE_SPK); + SaveWav(mic_path, mic_buff, mic_size); + free(mic_buff); + vTaskDelete(mic_task_h); +} + +uint32_t i2s_record(char *path, uint32_t secs) { + esp_err_t err = ESP_OK; + + if (decoder || mp3) return 0; + + err = SpeakerMic(MODE_MIC); + if (err) { + SpeakerMic(MODE_SPK); + return err; + } + + mic_size = secs * MICSRATE * 2; + + mic_buff = (uint8_t*)heap_caps_malloc(mic_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (!mic_buff) return 2; + + if (*path=='+') { + path++; + strlcpy(mic_path, path , sizeof(mic_path)); + xTaskCreatePinnedToCore(mic_task, "MIC", 4096, NULL, 3, &mic_task_h, 1); + return 0; + } + + uint32_t data_offset = 0; + uint32_t stime=millis(); + while (1) { + uint32_t bytes_read; + i2s_read(Speak_I2S_NUMBER, (char *)(mic_buff + data_offset), DATA_SIZE, &bytes_read, (100 / portTICK_RATE_MS)); + if (bytes_read != DATA_SIZE) break; + data_offset += DATA_SIZE; + if (data_offset >= mic_size-DATA_SIZE) break; + delay(0); + } + //AddLog_P(LOG_LEVEL_INFO, PSTR("rectime: %d ms"), millis()-stime); + SpeakerMic(MODE_SPK); + // save to path + SaveWav(mic_path, mic_buff, mic_size); + free(mic_buff); + return 0; +} + +static const uint8_t wavHTemplate[] PROGMEM = { // Hardcoded simple WAV header with 0xffffffff lengths all around + 0x52, 0x49, 0x46, 0x46, 0xff, 0xff, 0xff, 0xff, 0x57, 0x41, 0x56, 0x45, + 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x22, 0x56, 0x00, 0x00, 0x88, 0x58, 0x01, 0x00, 0x04, 0x00, 0x10, 0x00, + 0x64, 0x61, 0x74, 0x61, 0xff, 0xff, 0xff, 0xff }; + +bool SaveWav(char *path, uint8_t *buff, uint32_t size) { + File fwp = fsp->open(path, FILE_WRITE); + uint8_t wavHeader[sizeof(wavHTemplate)]; + memcpy_P(wavHeader, wavHTemplate, sizeof(wavHTemplate)); + + uint8_t channels = 1; + uint32_t hertz = MICSRATE; + uint8_t bps = 16; + + wavHeader[22] = channels & 0xff; + wavHeader[23] = 0; + wavHeader[24] = hertz & 0xff; + wavHeader[25] = (hertz >> 8) & 0xff; + wavHeader[26] = (hertz >> 16) & 0xff; + wavHeader[27] = (hertz >> 24) & 0xff; + int byteRate = hertz * bps * channels / 8; + wavHeader[28] = byteRate & 0xff; + wavHeader[29] = (byteRate >> 8) & 0xff; + wavHeader[30] = (byteRate >> 16) & 0xff; + wavHeader[31] = (byteRate >> 24) & 0xff; + wavHeader[32] = channels * bps / 8; + wavHeader[33] = 0; + wavHeader[34] = bps; + wavHeader[35] = 0; + + fwp.write(wavHeader, sizeof(wavHeader)); + + fwp.write(buff, size); + fwp.close(); + + return true; +} + +#endif // ESP32 + #ifdef ESP32 TaskHandle_t mp3_task_h; @@ -286,7 +470,8 @@ void StatusCallback(void *cbData, int code, const char *string) { void Webradio(const char *url) { if (decoder || mp3) return; - TTGO_PWR_ON + if (!out) return; + AUDIO_PWR_ON ifile = new AudioFileSourceICYStream(url); ifile->RegisterMetadataCB(MDCallback, NULL); buff = new AudioFileSourceBuffer(ifile, preallocateBuffer, preallocateBufferSize); @@ -338,7 +523,7 @@ void StopPlaying() { delete ifile; ifile = NULL; } - TTGO_PWR_OFF + AUDIO_PWR_OFF } void Cmd_WebRadio(void) { @@ -369,10 +554,11 @@ void I2S_WR_Show(void) { void Play_mp3(const char *path) { #if defined(USE_SCRIPT) && defined(USE_SCRIPT_FATFS) if (decoder || mp3) return; + if (!out) return; bool I2S_Task; - TTGO_PWR_ON + AUDIO_PWR_ON if (*path=='+') { I2S_Task = true; path++; @@ -411,13 +597,15 @@ void mp3_delete(void) { delete id3; delete mp3; mp3=nullptr; - TTGO_PWR_OFF + AUDIO_PWR_OFF } #endif // ESP32 void Say(char *text) { - TTGO_PWR_ON + if (!out) return; + + AUDIO_PWR_ON out->begin(); ESP8266SAM *sam = new ESP8266SAM; @@ -425,7 +613,7 @@ void Say(char *text) { delete sam; out->stop(); - TTGO_PWR_OFF + AUDIO_PWR_OFF } diff --git a/tasmota/xdrv_43_mlx90640.ino b/tasmota/xdrv_43_mlx90640.ino index a95b0f1e0..18255c079 100644 --- a/tasmota/xdrv_43_mlx90640.ino +++ b/tasmota/xdrv_43_mlx90640.ino @@ -1,7 +1,7 @@ /* xdrv_43_mlx90640.ino - MLX90640 support for Tasmota - Copyright (C) 2020 Christian Baars and Theo Arends + Copyright (C) 2021 Christian Baars and 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 diff --git a/tasmota/xdrv_44_miel_hvac.ino b/tasmota/xdrv_44_miel_hvac.ino index aad4205bd..680d9d72f 100644 --- a/tasmota/xdrv_44_miel_hvac.ino +++ b/tasmota/xdrv_44_miel_hvac.ino @@ -1,7 +1,7 @@ /* xdrv_44_miel_hvac.ino - Mitsubishi Electric HVAC support for Tasmota - Copyright (C) 2020 David Gwynne + Copyright (C) 2021 David Gwynne 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 diff --git a/tasmota/xdrv_45_shelly_dimmer.ino b/tasmota/xdrv_45_shelly_dimmer.ino index b4785291e..0b44cde96 100644 --- a/tasmota/xdrv_45_shelly_dimmer.ino +++ b/tasmota/xdrv_45_shelly_dimmer.ino @@ -1,7 +1,7 @@ /* xdrv_45_shelly_dimmer.ino - shelly dimmer support for Tasmota - Copyright (C) 2020 James Turton + Copyright (C) 2021 James Turton 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 diff --git a/tasmota/xdrv_46_ccloader.ino b/tasmota/xdrv_46_ccloader.ino index 32901adc6..3675ca676 100644 --- a/tasmota/xdrv_46_ccloader.ino +++ b/tasmota/xdrv_46_ccloader.ino @@ -1,7 +1,7 @@ /* xdrv_46_ccloader.ino - CCLoader for Tasmota - Copyright (C) 2020 Christian Baars and Theo Arends + Copyright (C) 2021 Christian Baars and Theo Arends based on CCLoader - Copyright (c) 2012-2014 RedBearLab @@ -25,14 +25,14 @@ 0.9.0.0 20191124 started - further development by Christian Baars forked - CCLoader - Copyright (c) 2012-2014 RedBearLab - + */ #ifdef USE_CCLOADER /*********************************************************************************************\ * CCLOader * -* Usage: +* Usage: \*********************************************************************************************/ #define XDRV_46 46 @@ -123,7 +123,7 @@ struct { bool init = false; } CCL; -const char CCLtype[] PROGMEM = "CCL"; +const char CCLtype[] PROGMEM = "CCL"; // Debug control pins & the indicate LED int CCL_RESET = 14; //GPIO14=D5 on NodeMCU/WeMos D1 Mini @@ -175,7 +175,7 @@ unsigned char CCLread_debug_byte(void) if(HIGH == digitalRead(CCL_DD)) { data |= 0x01; - } + } digitalWrite(CCL_DC, LOW); // DC low } return data; @@ -604,23 +604,23 @@ bool CLLFlashFirmware(uint8_t* data, uint32_t size) // Enable DMA (Disable DMA_PAUSE bit in debug configuration) debug_config = 0x22; CCLdebug_command(CCL_CMD_WR_CONFIG, &debug_config, 1); - - unsigned char rxBuf[512]; - uint32_t block = 0; + + unsigned char rxBuf[512]; + uint32_t block = 0; unsigned int addr = 0x0000; AddLog_P(LOG_LEVEL_INFO,PSTR("CCL: will flash ....")); AddLogBuffer(LOG_LEVEL_DEBUG,data,16); // quick check to compare with a hex editor while((block*512). +*/ + +#ifdef ESP32 +#ifdef USE_ODROID_GO +/*********************************************************************************************\ + * Odroid Go + * + * Clock frequency 160MHz (board_build.f_cpu = 160000000L) + * SPI Flash Size = 16MB (board_build.partitions = esp32_partition_app1984k_ffat12M.csv) + * + * To be done: + * - Audio on GPIO25/26 + * +/*********************************************************************************************/ + +#endif // USE_ODROID_GO +#endif // ESP32 diff --git a/tasmota/xdrv_81_webcam.ino b/tasmota/xdrv_81_webcam.ino index 4cbba9757..0e090ef1c 100755 --- a/tasmota/xdrv_81_webcam.ino +++ b/tasmota/xdrv_81_webcam.ino @@ -1,7 +1,7 @@ /* xdrv_81_webcam.ino - ESP32 webcam support for Tasmota - Copyright (C) 2020 Gerhard Mutz and Theo Arends + Copyright (C) 2021 Gerhard Mutz and 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 diff --git a/tasmota/xdrv_82_ethernet.ino b/tasmota/xdrv_82_ethernet.ino index c51e8c436..7d7ae3c59 100644 --- a/tasmota/xdrv_82_ethernet.ino +++ b/tasmota/xdrv_82_ethernet.ino @@ -1,7 +1,7 @@ /* xdrv_82_ethernet.ino - ESP32 (PoE) ethernet support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xdrv_83_esp32watch.ino b/tasmota/xdrv_83_esp32watch.ino index fe6da11ea..ef564813e 100644 --- a/tasmota/xdrv_83_esp32watch.ino +++ b/tasmota/xdrv_83_esp32watch.ino @@ -1,7 +1,7 @@ /* xdrv_83_esp32watch.ino - ESP32 TTGO watch support for Tasmota - Copyright (C) 2020 Gerhard Mutz and Theo Arends + Copyright (C) 2021 Gerhard Mutz and 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 diff --git a/tasmota/xdrv_84_core2.ino b/tasmota/xdrv_84_core2.ino index e3925eef6..22b80a1b7 100644 --- a/tasmota/xdrv_84_core2.ino +++ b/tasmota/xdrv_84_core2.ino @@ -1,7 +1,7 @@ /* xdrv_84_core2.ino - ESP32 m5stack core2 support for Tasmota - Copyright (C) 2020 Gerhard Mutz and Theo Arends + Copyright (C) 2021 Gerhard Mutz and 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 @@ -19,14 +19,18 @@ /* remaining work: -i2s microphone, at least as loudness sensor -rtc use after reboot, sync with internet on regular intervals. +i2s microphone as loudness sensor +rtc better sync */ #ifdef ESP32 #ifdef USE_M5STACK_CORE2 +#include +#include +#include + #include #include #include @@ -41,14 +45,18 @@ struct CORE2_globs { BM8563_RTC Rtc; bool ready; bool tset; - uint32_t shutdownseconds; + int32_t shutdownseconds; + uint8_t wakeup_hour; + uint8_t wakeup_minute; uint8_t shutdowndelay; - + bool timesynced; } core2_globs; struct CORE2_ADC { float vbus_v; float batt_v; + float vbus_c; + float batt_c; float temp; int16_t x; int16_t y; @@ -66,6 +74,8 @@ void CORE2_Module_Init(void) { I2cSetActiveFound(AXP_ADDR, "AXP192"); core2_globs.Axp.SetAdcState(true); + // motor voltage + core2_globs.Axp.SetLDOVoltage(3,2000); core2_globs.Mpu.Init(); I2cSetActiveFound(MPU6886_ADDRESS, "MPU6886"); @@ -79,6 +89,25 @@ void CORE2_Module_Init(void) { void CORE2_Init(void) { + if (Rtc.utc_time < START_VALID_TIME) { + // set rtc from chip + Rtc.utc_time = Get_utc(); + + TIME_T tmpTime; + TasmotaGlobal.ntp_force_sync = true; //force to sync with ntp + BreakTime(Rtc.utc_time, tmpTime); + Rtc.daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year); + Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); + AddLog_P(LOG_LEVEL_INFO, PSTR("Set time from BM8563 to RTC (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), + GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); + if (Rtc.local_time < START_VALID_TIME) { // 2016-01-01 + TasmotaGlobal.rules_flag.time_init = 1; + } else { + TasmotaGlobal.rules_flag.time_set = 1; + } + + } + } void CORE2_audio_power(bool power) { @@ -88,7 +117,9 @@ void CORE2_audio_power(bool power) { #ifdef USE_WEBSERVER const char HTTP_CORE2[] PROGMEM = "{s}VBUS Voltage" "{m}%s V" "{e}" + "{s}VBUS Current" "{m}%s mA" "{e}" "{s}BATT Voltage" "{m}%s V" "{e}" + "{s}BATT Current" "{m}%s mA" "{e}" "{s}Chip Temperature" "{m}%s C" "{e}"; #ifdef USE_MPU6886 const char HTTP_CORE2_MPU[] PROGMEM = @@ -100,26 +131,31 @@ const char HTTP_CORE2_MPU[] PROGMEM = void CORE2_loop(uint32_t flg) { + } void CORE2_WebShow(uint32_t json) { char vstring[32]; char bvstring[32]; + char cstring[32]; + char bcstring[32]; char tstring[32]; dtostrfd(core2_adc.vbus_v, 3, vstring); dtostrfd(core2_adc.batt_v, 3, bvstring); + dtostrfd(core2_adc.vbus_c, 1, cstring); + dtostrfd(core2_adc.batt_c, 1, bcstring); dtostrfd(core2_adc.temp, 2, tstring); if (json) { - ResponseAppend_P(PSTR(",\"CORE2\":{\"VBV\":%s,\"BV\":%s,\"CT\":%s"), vstring, bvstring, tstring); + ResponseAppend_P(PSTR(",\"CORE2\":{\"VBV\":%s,\"BV\":%s,\"VBC\":%s,\"BC\":%s,\"CT\":%s"), vstring, cstring, bvstring, bcstring, tstring); #ifdef USE_MPU6886 ResponseAppend_P(PSTR(",\"MPUX\":%d,\"MPUY\":%d,\"MPUZ\":%d"), core2_adc.x, core2_adc.y, core2_adc.z); #endif ResponseJsonEnd(); } else { - WSContentSend_PD(HTTP_CORE2, vstring, bvstring, tstring); + WSContentSend_PD(HTTP_CORE2, vstring, cstring, bvstring, bcstring, tstring); #ifdef USE_MPU6886 WSContentSend_PD(HTTP_CORE2_MPU, core2_adc.x, core2_adc.y, core2_adc.z); @@ -135,24 +171,45 @@ void (* const CORE2_Command[])(void) PROGMEM = { void CORE2_Shutdown(void) { - if (XdrvMailbox.payload >= 30) { - core2_globs.shutdownseconds = XdrvMailbox.payload; + char *mp = strchr(XdrvMailbox.data, ':'); + if (mp) { + core2_globs.wakeup_hour = atoi(XdrvMailbox.data); + core2_globs.wakeup_minute = atoi(mp+1); + core2_globs.shutdownseconds = -1; core2_globs.shutdowndelay = 10; + char tbuff[16]; + sprintf(tbuff,"%02.2d:%02.2d", core2_globs.wakeup_hour, core2_globs.wakeup_minute ); + ResponseCmndChar(tbuff); + } else { + if (XdrvMailbox.payload >= 30) { + core2_globs.shutdownseconds = XdrvMailbox.payload; + core2_globs.shutdowndelay = 10; + } + ResponseCmndNumber(XdrvMailbox.payload); } - ResponseCmndNumber(XdrvMailbox.payload -2); + } void CORE2_DoShutdown(void) { SettingsSaveAll(); RtcSettingsSave(); core2_globs.Rtc.clearIRQ(); - core2_globs.Rtc.SetAlarmIRQ(core2_globs.shutdownseconds); + if (core2_globs.shutdownseconds > 0) { + core2_globs.Rtc.SetAlarmIRQ(core2_globs.shutdownseconds); + } else { + RTC_TimeTypeDef wut; + wut.Hours = core2_globs.wakeup_hour; + wut.Minutes = core2_globs.wakeup_minute; + core2_globs.Rtc.SetAlarmIRQ(wut); + } delay(10); core2_globs.Axp.PowerOff(); } extern uint8_t tbstate[3]; + +// c2ps(a b) float core2_setaxppin(uint32_t sel, uint32_t val) { switch (sel) { case 0: @@ -165,7 +222,25 @@ float core2_setaxppin(uint32_t sel, uint32_t val) { if (val<1 || val>3) val = 1; return tbstate[val - 1] & 1; break; - + case 3: + switch (val) { + case 0: + return core2_globs.Axp.isACIN(); + break; + case 1: + return core2_globs.Axp.isCharging(); + break; + case 2: + return core2_globs.Axp.isVBUS(); + break; + case 3: + return core2_globs.Axp.AXPInState(); + break; + } + break; + default: + GetRtc(); + break; } return 0; } @@ -187,16 +262,107 @@ uint16_t voltage = 2200; } +/* +void SetRtc(void) { + RTC_TimeTypeDef RTCtime; + RTCtime.Hours = RtcTime.hour; + RTCtime.Minutes = RtcTime.minute; + RTCtime.Seconds = RtcTime.second; + core2_globs.Rtc.SetTime(&RTCtime); + + RTC_DateTypeDef RTCdate; + RTCdate.WeekDay = RtcTime.day_of_week; + RTCdate.Month = RtcTime.month; + RTCdate.Date = RtcTime.day_of_month; + RTCdate.Year = RtcTime.year; + core2_globs.Rtc.SetDate(&RTCdate); +} +*/ + + +// needed for sd card time +void Sync_RTOS_TIME(void) { + + if (Rtc.local_time < START_VALID_TIME || core2_globs.timesynced) return; + + core2_globs.timesynced = 1; +// Set freertos time for sd card + + struct timeval tv; + //tv.tv_sec = Rtc.utc_time; + tv.tv_sec = Rtc.local_time; + tv.tv_usec = 0; + + //struct timezone tz; + //tz.tz_minuteswest = 0; + //tz.tz_dsttime = 0; + //settimeofday(&tv, &tz); + + settimeofday(&tv, NULL); +} + +void GetRtc(void) { + RTC_TimeTypeDef RTCtime; + core2_globs.Rtc.GetTime(&RTCtime); + RtcTime.hour = RTCtime.Hours; + RtcTime.minute = RTCtime.Minutes; + RtcTime.second = RTCtime.Seconds; + + + RTC_DateTypeDef RTCdate; + core2_globs.Rtc.GetDate(&RTCdate); + RtcTime.day_of_week = RTCdate.WeekDay; + RtcTime.month = RTCdate.Month; + RtcTime.day_of_month = RTCdate.Date; + RtcTime.year = RTCdate.Year; + + AddLog_P(LOG_LEVEL_INFO, PSTR("RTC: %02d:%02d:%02d"), RTCtime.Hours, RTCtime.Minutes, RTCtime.Seconds); + AddLog_P(LOG_LEVEL_INFO, PSTR("RTC: %02d.%02d.%04d"), RTCdate.Date, RTCdate.Month, RTCdate.Year); + +} + +void Set_utc(uint32_t epoch_time) { +TIME_T tm; + BreakTime(epoch_time, tm); + RTC_TimeTypeDef RTCtime; + RTCtime.Hours = tm.hour; + RTCtime.Minutes = tm.minute; + RTCtime.Seconds = tm.second; + core2_globs.Rtc.SetTime(&RTCtime); + RTC_DateTypeDef RTCdate; + RTCdate.WeekDay = tm.day_of_week; + RTCdate.Month = tm.month; + RTCdate.Date = tm.day_of_month; + RTCdate.Year = tm.year + 1970; + core2_globs.Rtc.SetDate(&RTCdate); +} + +uint32_t Get_utc(void) { + RTC_TimeTypeDef RTCtime; + // 1. read has errors ??? + core2_globs.Rtc.GetTime(&RTCtime); + core2_globs.Rtc.GetTime(&RTCtime); + RTC_DateTypeDef RTCdate; + core2_globs.Rtc.GetDate(&RTCdate); + TIME_T tm; + tm.second = RTCtime.Seconds; + tm.minute = RTCtime.Minutes; + tm.hour = RTCtime.Hours; + tm.day_of_week = RTCdate.WeekDay; + tm.day_of_month = RTCdate.Date; + tm.month = RTCdate.Month; + tm.year =RTCdate.Year - 1970; + return MakeTime(tm); +} + void CORE2_EverySecond(void) { if (core2_globs.ready) { CORE2_GetADC(); - if (RtcTime.year>2000 && core2_globs.tset==false) { - RTC_TimeTypeDef RTCtime; - RTCtime.Hours = RtcTime.hour; - RTCtime.Minutes = RtcTime.minute; - RTCtime.Seconds = RtcTime.second; - core2_globs.Rtc.SetTime(&RTCtime); + if (Rtc.utc_time > START_VALID_TIME && core2_globs.tset==false && abs(Rtc.utc_time - Get_utc()) > 3) { + Set_utc(Rtc.utc_time); + AddLog_P(LOG_LEVEL_INFO, PSTR("Write Time TO BM8563 from NTP (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), + GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); core2_globs.tset = true; } @@ -206,13 +372,17 @@ void CORE2_EverySecond(void) { CORE2_DoShutdown(); } } + + Sync_RTOS_TIME(); } } -// currents are not supported by hardware implementation void CORE2_GetADC(void) { core2_adc.vbus_v = core2_globs.Axp.GetVBusVoltage(); core2_adc.batt_v = core2_globs.Axp.GetBatVoltage(); + core2_adc.vbus_c = core2_globs.Axp.GetVinCurrent(); + core2_adc.batt_c = core2_globs.Axp.GetBatCurrent(); + core2_adc.temp = core2_globs.Axp.GetTempInAXP192(); #ifdef USE_MPU6886 float x; diff --git a/tasmota/xdrv_99_debug.ino b/tasmota/xdrv_99_debug.ino index e4f00cec2..46bfa441e 100644 --- a/tasmota/xdrv_99_debug.ino +++ b/tasmota/xdrv_99_debug.ino @@ -1,7 +1,7 @@ /* xdrv_99_debug.ino - debug support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 @@ -258,7 +258,7 @@ void DebugRtcDump(char* parms) maxrow = srow + mrow; } - char log_data[LOGSZ]; + char log_data[100]; // 020: C7 2B 2E AB 70 E8 09 AE C8 88 3D EA 7C FF 48 2F | +. p = | H/| for (row = srow; row < maxrow; row++) { idx = row * CFG_COLS; snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), idx); @@ -310,7 +310,7 @@ void DebugDump(uint32_t start, uint32_t size) { maxrow = srow + mrow; } - char log_data[LOGSZ]; + char log_data[150]; // 020: C7 2B 2E AB 70 E8 09 AE C8 88 3D EA 7C FF 48 2F 0E A7 D7 BF 02 0E D7 7D C9 6F B9 3A 1D 01 3F 28 | +. p = | H/ } o : ?(| for (row = srow; row < maxrow; row++) { idx = row * CFG_COLS; snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), idx); @@ -361,7 +361,7 @@ void DebugCfgDump(char* parms) maxrow = srow + mrow; } - char log_data[LOGSZ]; + char log_data[100]; // 020: 6D 75 73 31 3A 38 30 2F 61 70 69 2F 61 72 64 75 |mus1:80/api/ardu| for (row = srow; row < maxrow; row++) { idx = row * CFG_COLS; snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), idx); @@ -397,7 +397,7 @@ void DebugCfgPeek(char* parms) uint16_t data16 = (buffer[address +1] << 8) + buffer[address]; uint32_t data32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + data16; - char log_data[LOGSZ]; + char log_data[100]; // 000: 09 12 00 10 | | 0x09 (9), 0x1209 (4617), 0x10001209 (268440073) snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), address); for (uint32_t i = 0; i < 4; i++) { snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[address +i]); diff --git a/tasmota/xdrv_interface.ino b/tasmota/xdrv_interface.ino index 595caf04b..a5e0f6479 100644 --- a/tasmota/xdrv_interface.ino +++ b/tasmota/xdrv_interface.ino @@ -1,7 +1,7 @@ /* xdrv_interface.ino - Driver interface support for Tasmota - Copyright (C) 2020 Theo Arends inspired by ESPEasy + Copyright (C) 2021 Theo Arends inspired by ESPEasy 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 diff --git a/tasmota/xdsp_01_lcd.ino b/tasmota/xdsp_01_lcd.ino index 9c57b2943..3db1c48e3 100644 --- a/tasmota/xdsp_01_lcd.ino +++ b/tasmota/xdsp_01_lcd.ino @@ -1,7 +1,7 @@ /* xdsp_01_lcd.ino - Display LCD support for Tasmota - Copyright (C) 2020 Theo Arends and Adafruit + Copyright (C) 2021 Theo Arends and Adafruit 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 diff --git a/tasmota/xdsp_02_ssd1306.ino b/tasmota/xdsp_02_ssd1306.ino index def5d931c..d9184b790 100644 --- a/tasmota/xdsp_02_ssd1306.ino +++ b/tasmota/xdsp_02_ssd1306.ino @@ -1,7 +1,7 @@ /* xdsp_02_ssd1306.ino - Display Oled SSD1306 support for Tasmota - Copyright (C) 2020 Theo Arends and Adafruit + Copyright (C) 2021 Theo Arends and Adafruit 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 diff --git a/tasmota/xdsp_03_matrix.ino b/tasmota/xdsp_03_matrix.ino index 6bcfee2e0..e82c0586b 100644 --- a/tasmota/xdsp_03_matrix.ino +++ b/tasmota/xdsp_03_matrix.ino @@ -1,7 +1,7 @@ /* xdsp_03_matrix.ino - Display 8x8 matrix support for Tasmota - Copyright (C) 2020 Theo Arends and Adafruit + Copyright (C) 2021 Theo Arends and Adafruit 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 diff --git a/tasmota/xdsp_04_ili9341.ino b/tasmota/xdsp_04_ili9341.ino index fd61b4a82..088f545d5 100644 --- a/tasmota/xdsp_04_ili9341.ino +++ b/tasmota/xdsp_04_ili9341.ino @@ -1,7 +1,7 @@ /* xdsp_04_ili9341.ino - Display Tft Ili9341 support for Tasmota - Copyright (C) 2020 Theo Arends and Adafruit + Copyright (C) 2021 Theo Arends and Adafruit 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 @@ -38,6 +38,7 @@ uint16_t tft_top = TFT_TOP; uint16_t tft_bottom = TFT_BOTTOM; uint16_t tft_scroll = TFT_TOP; uint16_t tft_cols = 0; +bool tft_init_done = false; /*********************************************************************************************/ @@ -57,8 +58,7 @@ bool Ili9341Header(void) { return (tft_cols > 17); } -void Ili9341InitMode(void) -{ +void Ili9341InitMode(void) { tft->setRotation(Settings.display_rotate); // 0 tft->invertDisplay(0); tft->fillScreen(ILI9341_BLACK); @@ -78,8 +78,7 @@ void Ili9341InitMode(void) } } -void Ili9341Init(uint8_t mode) -{ +void Ili9341Init(uint8_t mode) { switch(mode) { case DISPLAY_INIT_MODE: Ili9341InitMode(); @@ -95,13 +94,11 @@ void Ili9341Init(uint8_t mode) } } -void Ili9341InitDriver(void) -{ - if (!Settings.display_model) { - Settings.display_model = XDSP_04; - } +void Ili9341InitDriver(void) { + if (PinUsed(GPIO_ILI9341_CS) && PinUsed(GPIO_ILI9341_DC) && TasmotaGlobal.spi_enabled) { + + Settings.display_model = XDSP_04; - if (XDSP_04 == Settings.display_model) { if (Settings.display_width != ILI9341_TFTWIDTH) { Settings.display_width = ILI9341_TFTWIDTH; } @@ -109,7 +106,7 @@ void Ili9341InitDriver(void) Settings.display_height = ILI9341_TFTHEIGHT; } - tft = new Adafruit_ILI9341(Pin(GPIO_SPI_CS), Pin(GPIO_SPI_DC)); + tft = new Adafruit_ILI9341(Pin(GPIO_ILI9341_CS), Pin(GPIO_ILI9341_DC)); tft->begin(); #ifdef USE_DISPLAY_MODES1TO5 @@ -120,18 +117,17 @@ void Ili9341InitDriver(void) Ili9341InitMode(); + tft_init_done = true; AddLog_P(LOG_LEVEL_INFO, PSTR("DSP: ILI9341")); } } -void Ili9341Clear(void) -{ +void Ili9341Clear(void) { tft->fillScreen(ILI9341_BLACK); tft->setCursor(0, 0); } -void Ili9341DrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) -{ +void Ili9341DrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) { uint16_t active_color = ILI9341_WHITE; tft->setTextSize(Settings.display_size); @@ -145,8 +141,7 @@ void Ili9341DrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint tft->println(str); } -void Ili9341DisplayOnOff() -{ +void Ili9341DisplayOnOff() { // tft->showDisplay(disp_power); // tft->invertDisplay(disp_power); if (PinUsed(GPIO_BACKLIGHT)) { @@ -159,8 +154,7 @@ void Ili9341DisplayOnOff() #ifdef USE_DISPLAY_MODES1TO5 -void Ili9341PrintLog(void) -{ +void Ili9341PrintLog(void) { disp_refresh--; if (!disp_refresh) { disp_refresh = Settings.display_refresh; @@ -206,8 +200,7 @@ void Ili9341PrintLog(void) } } -void Ili9341Refresh(void) // Every second -{ +void Ili9341Refresh(void) { // Every second if (Settings.display_mode) { // Mode 0 is User text // 24-04-2017 13:45:43 = 19 + 1 ('\0') = 20 // 24-04-2017 13:45 = 16 + 1 ('\0') = 17 @@ -252,73 +245,70 @@ void Ili9341Refresh(void) // Every second * Interface \*********************************************************************************************/ -bool Xdsp04(uint8_t function) -{ +bool Xdsp04(uint8_t function) { bool result = false; - if (TasmotaGlobal.spi_enabled) { - if (FUNC_DISPLAY_INIT_DRIVER == function) { - Ili9341InitDriver(); - } - else if (XDSP_04 == Settings.display_model) { + if (FUNC_DISPLAY_INIT_DRIVER == function) { + Ili9341InitDriver(); + } + else if (tft_init_done && (XDSP_04 == Settings.display_model)) { - if (!dsp_color) { dsp_color = ILI9341_WHITE; } + if (!dsp_color) { dsp_color = ILI9341_WHITE; } - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - case FUNC_DISPLAY_INIT: - Ili9341Init(dsp_init); - break; - case FUNC_DISPLAY_POWER: - Ili9341DisplayOnOff(); - break; - case FUNC_DISPLAY_CLEAR: - Ili9341Clear(); - break; - case FUNC_DISPLAY_DRAW_HLINE: - tft->writeFastHLine(dsp_x, dsp_y, dsp_len, dsp_color); - break; - case FUNC_DISPLAY_DRAW_VLINE: - tft->writeFastVLine(dsp_x, dsp_y, dsp_len, dsp_color); - break; - case FUNC_DISPLAY_DRAW_LINE: - tft->writeLine(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); - break; - case FUNC_DISPLAY_DRAW_CIRCLE: - tft->drawCircle(dsp_x, dsp_y, dsp_rad, dsp_color); - break; - case FUNC_DISPLAY_FILL_CIRCLE: - tft->fillCircle(dsp_x, dsp_y, dsp_rad, dsp_color); - break; - case FUNC_DISPLAY_DRAW_RECTANGLE: - tft->drawRect(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); - break; - case FUNC_DISPLAY_FILL_RECTANGLE: - tft->fillRect(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); - break; + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; + case FUNC_DISPLAY_INIT: + Ili9341Init(dsp_init); + break; + case FUNC_DISPLAY_POWER: + Ili9341DisplayOnOff(); + break; + case FUNC_DISPLAY_CLEAR: + Ili9341Clear(); + break; + case FUNC_DISPLAY_DRAW_HLINE: + tft->writeFastHLine(dsp_x, dsp_y, dsp_len, dsp_color); + break; + case FUNC_DISPLAY_DRAW_VLINE: + tft->writeFastVLine(dsp_x, dsp_y, dsp_len, dsp_color); + break; + case FUNC_DISPLAY_DRAW_LINE: + tft->writeLine(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); + break; + case FUNC_DISPLAY_DRAW_CIRCLE: + tft->drawCircle(dsp_x, dsp_y, dsp_rad, dsp_color); + break; + case FUNC_DISPLAY_FILL_CIRCLE: + tft->fillCircle(dsp_x, dsp_y, dsp_rad, dsp_color); + break; + case FUNC_DISPLAY_DRAW_RECTANGLE: + tft->drawRect(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); + break; + case FUNC_DISPLAY_FILL_RECTANGLE: + tft->fillRect(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); + break; // case FUNC_DISPLAY_DRAW_FRAME: // oled->display(); // break; - case FUNC_DISPLAY_TEXT_SIZE: - tft->setTextSize(Settings.display_size); - break; - case FUNC_DISPLAY_FONT_SIZE: + case FUNC_DISPLAY_TEXT_SIZE: + tft->setTextSize(Settings.display_size); + break; + case FUNC_DISPLAY_FONT_SIZE: // tft->setTextSize(Settings.display_font); - break; - case FUNC_DISPLAY_DRAW_STRING: - Ili9341DrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag); - break; - case FUNC_DISPLAY_ROTATION: - tft->setRotation(Settings.display_rotate); - break; + break; + case FUNC_DISPLAY_DRAW_STRING: + Ili9341DrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag); + break; + case FUNC_DISPLAY_ROTATION: + tft->setRotation(Settings.display_rotate); + break; #ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - Ili9341Refresh(); - break; + case FUNC_DISPLAY_EVERY_SECOND: + Ili9341Refresh(); + break; #endif // USE_DISPLAY_MODES1TO5 - } } } return result; diff --git a/tasmota/xdsp_05_epaper_29.ino b/tasmota/xdsp_05_epaper_29.ino index 08fcbcf9b..a607bd937 100644 --- a/tasmota/xdsp_05_epaper_29.ino +++ b/tasmota/xdsp_05_epaper_29.ino @@ -1,7 +1,7 @@ /* xdsp_05_epaper.ino - Display e-paper support for Tasmota - Copyright (C) 2020 Theo Arends, Gerhard Mutz and Waveshare + Copyright (C) 2021 Theo Arends, Gerhard Mutz and Waveshare 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 @@ -39,18 +39,18 @@ //unsigned char image[(EPD_HEIGHT * EPD_WIDTH) / 8]; extern uint8_t *buffer; uint16_t epd_scroll; +bool epd_init_done = false; Epd *epd; /*********************************************************************************************/ -void EpdInitDriver29() -{ - if (!Settings.display_model) { - Settings.display_model = XDSP_05; - } +void EpdInitDriver29(void) { + if (PinUsed(GPIO_EPAPER29_CS) && + ((TasmotaGlobal.soft_spi_enabled & SPI_MOSI) || (TasmotaGlobal.spi_enabled & SPI_MOSI))) { + + Settings.display_model = XDSP_05; - if (XDSP_05 == Settings.display_model) { if (Settings.display_width != EPD_WIDTH) { Settings.display_width = EPD_WIDTH; } @@ -64,19 +64,14 @@ void EpdInitDriver29() if (!buffer) return; // init renderer - epd = new Epd(EPD_WIDTH,EPD_HEIGHT); + epd = new Epd(EPD_WIDTH, EPD_HEIGHT); // whiten display with full update, takes 3 seconds - if (PinUsed(GPIO_SPI_CS) && PinUsed(GPIO_SPI_CLK) && PinUsed(GPIO_SPI_MOSI)) { - epd->Begin(Pin(GPIO_SPI_CS),Pin(GPIO_SPI_MOSI),Pin(GPIO_SPI_CLK)); - AddLog_P(LOG_LEVEL_DEBUG, PSTR("EPD: HardSPI CS %d, CLK %d, MOSI %d"),Pin(GPIO_SPI_CS), Pin(GPIO_SPI_CLK), Pin(GPIO_SPI_MOSI)); + if (TasmotaGlobal.soft_spi_enabled) { + epd->Begin(Pin(GPIO_EPAPER29_CS), Pin(GPIO_SSPI_MOSI), Pin(GPIO_SSPI_SCLK)); } - else if (PinUsed(GPIO_SSPI_CS) && PinUsed(GPIO_SSPI_SCLK) && PinUsed(GPIO_SSPI_MOSI)) { - epd->Begin(Pin(GPIO_SSPI_CS),Pin(GPIO_SSPI_MOSI),Pin(GPIO_SSPI_SCLK)); - AddLog_P(LOG_LEVEL_DEBUG, PSTR("EPD: SoftSPI CS %d, CLK %d, MOSI %d"),Pin(GPIO_SSPI_CS), Pin(GPIO_SSPI_SCLK), Pin(GPIO_SSPI_MOSI)); - } else { - free(buffer); - return; + else if (TasmotaGlobal.spi_enabled) { + epd->Begin(Pin(GPIO_EPAPER29_CS), Pin(GPIO_SPI_MOSI), Pin(GPIO_SPI_CLK)); } renderer = epd; @@ -95,6 +90,8 @@ void EpdInitDriver29() renderer->fillScreen(0); #endif + epd_init_done = true; + AddLog_P(LOG_LEVEL_INFO, PSTR("DSP: E-Paper 2.9")); } } @@ -186,21 +183,22 @@ void EpdRefresh29(void) // Every second bool Xdsp05(uint8_t function) { bool result = false; - if (FUNC_DISPLAY_INIT_DRIVER == function) { - EpdInitDriver29(); - } - else if (XDSP_05 == Settings.display_model) { - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + EpdInitDriver29(); + } + else if (epd_init_done && (XDSP_05 == Settings.display_model)) { + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; #ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - EpdRefresh29(); - break; + case FUNC_DISPLAY_EVERY_SECOND: + EpdRefresh29(); + break; #endif // USE_DISPLAY_MODES1TO5 - } } + } return result; } diff --git a/tasmota/xdsp_06_epaper_42.ino b/tasmota/xdsp_06_epaper_42.ino index fee42db6c..d5783668d 100644 --- a/tasmota/xdsp_06_epaper_42.ino +++ b/tasmota/xdsp_06_epaper_42.ino @@ -1,7 +1,7 @@ /* xdsp_05_epaper.ino - Display e-paper support for Tasmota - Copyright (C) 2020 Theo Arends, Gerhard Mutz and Waveshare + Copyright (C) 2021 Theo Arends, Gerhard Mutz and Waveshare 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 @@ -35,19 +35,18 @@ #include extern uint8_t *buffer; +bool epd42_init_done = false; Epd42 *epd42; /*********************************************************************************************/ -void EpdInitDriver42() -{ - if (!Settings.display_model) { - Settings.display_model = XDSP_06; - } +void EpdInitDriver42() { + if (PinUsed(GPIO_EPAPER42_CS) && + ((TasmotaGlobal.soft_spi_enabled & SPI_MOSI) || (TasmotaGlobal.spi_enabled & SPI_MOSI))) { - if (XDSP_06 == Settings.display_model) { + Settings.display_model = XDSP_06; if (Settings.display_width != EPD_WIDTH42) { Settings.display_width = EPD_WIDTH42; @@ -62,23 +61,14 @@ void EpdInitDriver42() if (!buffer) return; // init renderer - epd42 = new Epd42(EPD_WIDTH42,EPD_HEIGHT42); + epd42 = new Epd42(EPD_WIDTH42, EPD_HEIGHT42); - #ifdef USE_SPI - if (PinUsed(GPIO_SSPI_CS) && PinUsed(GPIO_SSPI_MOSI) && PinUsed(GPIO_SSPI_SCLK)) { - epd42->Begin(Pin(GPIO_SSPI_CS),Pin(GPIO_SSPI_MOSI),Pin(GPIO_SSPI_SCLK)); - } else { - free(buffer); - return; - } - #else - if (PinUsed(GPIO_SPI_CS) && PinUsed(GPIO_SPI_MOSI) && PinUsed(GPIO_SPI_CLK)) { - epd42->Begin(Pin(GPIO_SPI_CS),Pin(GPIO_SPI_MOSI),Pin(GPIO_SPI_CLK)); - } else { - free(buffer); - return; - } - #endif + if (TasmotaGlobal.soft_spi_enabled) { + epd42->Begin(Pin(GPIO_EPAPER42_CS), Pin(GPIO_SSPI_MOSI), Pin(GPIO_SSPI_SCLK)); + } + else if (TasmotaGlobal.spi_enabled) { + epd42->Begin(Pin(GPIO_EPAPER42_CS), Pin(GPIO_SPI_MOSI), Pin(GPIO_SPI_CLK)); + } renderer = epd42; @@ -105,6 +95,8 @@ void EpdInitDriver42() renderer->fillScreen(0); #endif + epd42_init_done = true; + AddLog_P(LOG_LEVEL_INFO, PSTR("DSP: E-Paper 4.2")); } } @@ -134,27 +126,24 @@ bool Xdsp06(uint8_t function) { bool result = false; - if (FUNC_DISPLAY_INIT_DRIVER == function) { - EpdInitDriver42(); - } - else if (XDSP_06 == Settings.display_model) { - - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - + if (FUNC_DISPLAY_INIT_DRIVER == function) { + EpdInitDriver42(); + } + else if (epd42_init_done && (XDSP_06 == Settings.display_model)) { + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; #ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - EpdRefresh42(); - break; + case FUNC_DISPLAY_EVERY_SECOND: + EpdRefresh42(); + break; #endif // USE_DISPLAY_MODES1TO5 - } } + } return result; } - #endif // USE_DISPLAY_EPAPER42 #endif // USE_DISPLAY #endif // USE_SPI diff --git a/tasmota/xdsp_07_sh1106.ino b/tasmota/xdsp_07_sh1106.ino index 6bb180cb8..ea09a958c 100644 --- a/tasmota/xdsp_07_sh1106.ino +++ b/tasmota/xdsp_07_sh1106.ino @@ -1,7 +1,7 @@ /* xdsp_07_SH1106.ino - Display Oled SH1106 support for Tasmota - Copyright (C) 2020 Theo Arends and Adafruit + Copyright (C) 2021 Theo Arends and Adafruit 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 diff --git a/tasmota/xdsp_08_ILI9488.ino b/tasmota/xdsp_08_ILI9488.ino index af8ac03a1..513150af7 100644 --- a/tasmota/xdsp_08_ILI9488.ino +++ b/tasmota/xdsp_08_ILI9488.ino @@ -1,7 +1,7 @@ /* xdsp_08_ILI9488.ino - Display ILI9488 support for Tasmota - Copyright (C) 2020 Theo Arends, Gerhard Mutz + Copyright (C) 2021 Theo Arends, Gerhard Mutz 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 @@ -34,6 +34,7 @@ #include uint8_t ili9488_ctouch_counter = 0; +bool ili9488_init_done = false; // currently fixed #define BACKPLANE_PIN 2 @@ -45,13 +46,10 @@ extern const uint16_t picture[]; /*********************************************************************************************/ -void ILI9488_InitDriver() -{ - if (!Settings.display_model) { - Settings.display_model = XDSP_08; - } +void ILI9488_InitDriver(void) { + if (PinUsed(GPIO_ILI9488_CS) && (TasmotaGlobal.spi_enabled & SPI_MOSI)) { - if (XDSP_08 == Settings.display_model) { + Settings.display_model = XDSP_08; if (Settings.display_width != ILI9488_TFTWIDTH) { Settings.display_width = ILI9488_TFTWIDTH; @@ -61,44 +59,19 @@ void ILI9488_InitDriver() } // disable screen buffer - buffer=NULL; + buffer = NULL; // default colors fg_color = ILI9488_WHITE; bg_color = ILI9488_BLACK; - uint8_t bppin=BACKPLANE_PIN; - if (PinUsed(GPIO_BACKLIGHT)) { - bppin=Pin(GPIO_BACKLIGHT); + uint8_t bppin = BACKPLANE_PIN; + if (PinUsed(GPIO_BACKLIGHT)) { + bppin = Pin(GPIO_BACKLIGHT); } -#ifdef ESP8266 -#undef HW_SPI_MOSI -#define HW_SPI_MOSI 13 -#undef HW_SPI_MISO -#define HW_SPI_MISO 12 -#undef HW_SPI_CLK -#define HW_SPI_CLK 14 -#endif // ESP8266 -#ifdef ESP32 -#undef HW_SPI_MOSI -#define HW_SPI_MOSI 23 -#undef HW_SPI_MISO -#define HW_SPI_MISO 19 -#undef HW_SPI_CLK -#define HW_SPI_CLK 18 -#endif // ESP32 - // init renderer, must use hardware spi - if (PinUsed(GPIO_SSPI_CS) && (Pin(GPIO_SSPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SSPI_SCLK)==HW_SPI_CLK)) { - ili9488 = new ILI9488(Pin(GPIO_SSPI_CS),Pin(GPIO_SSPI_MOSI),Pin(GPIO_SSPI_SCLK),bppin); - } else { - if (PinUsed(GPIO_SPI_CS) && (Pin(GPIO_SPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SPI_CLK)==HW_SPI_CLK)) { - ili9488 = new ILI9488(Pin(GPIO_SPI_CS),Pin(GPIO_SPI_MOSI),Pin(GPIO_SPI_CLK),bppin); - } else { - return; - } - } + ili9488 = new ILI9488(Pin(GPIO_ILI9488_CS), Pin(GPIO_SPI_MOSI), Pin(GPIO_SPI_CLK), bppin); ili9488->begin(); renderer = ili9488; @@ -120,6 +93,9 @@ void ILI9488_InitDriver() #ifdef USE_FT5206 Touch_Init(Wire); #endif + + ili9488_init_done = true; + AddLog_P(LOG_LEVEL_INFO, PSTR("DSP: ILI9488")); } } @@ -170,25 +146,23 @@ bool Xdsp08(uint8_t function) { bool result = false; - if (FUNC_DISPLAY_INIT_DRIVER == function) { - ILI9488_InitDriver(); - } - else if (XDSP_08 == Settings.display_model) { - - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - case FUNC_DISPLAY_EVERY_50_MSECOND: + if (FUNC_DISPLAY_INIT_DRIVER == function) { + ILI9488_InitDriver(); + } + else if (ili9488_init_done && (XDSP_08 == Settings.display_model)) { + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; + case FUNC_DISPLAY_EVERY_50_MSECOND: #ifdef USE_TOUCH_BUTTONS - if (FT5206_found) { - ILI9488_CheckTouch(); - } + if (FT5206_found) { + ILI9488_CheckTouch(); + } #endif - break; - } + break; } - //} + } return result; } diff --git a/tasmota/xdsp_09_SSD1351.ino b/tasmota/xdsp_09_SSD1351.ino index 1b17bd08a..f3ad53b29 100644 --- a/tasmota/xdsp_09_SSD1351.ino +++ b/tasmota/xdsp_09_SSD1351.ino @@ -1,7 +1,7 @@ /* xdsp_09_SSD1351.ino - Display SSD1351 support for Tasmota - Copyright (C) 2020 Gerhard Mutz and Theo Arends + Copyright (C) 2021 Gerhard Mutz and 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 @@ -33,6 +33,7 @@ #include +bool ssd1351_init_done = false; extern uint8_t *buffer; extern uint8_t color_type; SSD1351 *ssd1351; @@ -40,11 +41,10 @@ SSD1351 *ssd1351; /*********************************************************************************************/ void SSD1351_InitDriver() { - if (!Settings.display_model) { - Settings.display_model = XDSP_09; - } + if (PinUsed(GPIO_SSD1351_CS) && + ((TasmotaGlobal.soft_spi_enabled & SPI_MOSI) || (TasmotaGlobal.spi_enabled & SPI_MOSI))) { - if (XDSP_09 == Settings.display_model) { + Settings.display_model = XDSP_09; if (Settings.display_width != SSD1351_WIDTH) { Settings.display_width = SSD1351_WIDTH; @@ -53,21 +53,18 @@ void SSD1351_InitDriver() { Settings.display_height = SSD1351_HEIGHT; } - buffer=0; + buffer = 0; // default colors fg_color = SSD1351_WHITE; bg_color = SSD1351_BLACK; // init renderer - if (PinUsed(GPIO_SSPI_CS) && PinUsed(GPIO_SSPI_MOSI) && PinUsed(GPIO_SSPI_SCLK)){ - ssd1351 = new SSD1351(Pin(GPIO_SSPI_CS),Pin(GPIO_SSPI_MOSI),Pin(GPIO_SSPI_SCLK)); - } else { - if (PinUsed(GPIO_SPI_CS) && PinUsed(GPIO_SPI_MOSI) && PinUsed(GPIO_SPI_CLK)) { - ssd1351 = new SSD1351(Pin(GPIO_SPI_CS),Pin(GPIO_SPI_MOSI),Pin(GPIO_SPI_CLK)); - } else { - return; - } + if (TasmotaGlobal.soft_spi_enabled){ + ssd1351 = new SSD1351(Pin(GPIO_SSD1351_CS), Pin(GPIO_SSPI_MOSI), Pin(GPIO_SSPI_SCLK)); + } + else if (TasmotaGlobal.spi_enabled) { + ssd1351 = new SSD1351(Pin(GPIO_SSD1351_CS), Pin(GPIO_SPI_MOSI), Pin(GPIO_SPI_CLK)); } delay(100); @@ -85,13 +82,15 @@ void SSD1351_InitDriver() { #endif color_type = COLOR_COLOR; + + ssd1351_init_done = true; + AddLog_P(LOG_LEVEL_INFO, PSTR("DSP: SSD1351")); } } #ifdef USE_DISPLAY_MODES1TO5 -void SSD1351PrintLog(void) -{ +void SSD1351PrintLog(void) { disp_refresh--; if (!disp_refresh) { disp_refresh = Settings.display_refresh; @@ -119,8 +118,7 @@ void SSD1351PrintLog(void) } } -void SSD1351Time(void) -{ +void SSD1351Time(void) { char line[12]; renderer->clearDisplay(); @@ -133,8 +131,7 @@ void SSD1351Time(void) renderer->Updateframe(); } -void SSD1351Refresh(void) // Every second -{ +void SSD1351Refresh(void) { // Every second if (Settings.display_mode) { // Mode 0 is User text switch (Settings.display_mode) { case 1: // Time @@ -151,18 +148,18 @@ void SSD1351Refresh(void) // Every second } #endif // USE_DISPLAY_MODES1TO5 -/*********************************************************************************************/ + /*********************************************************************************************\ * Interface \*********************************************************************************************/ -bool Xdsp09(uint8_t function) -{ + +bool Xdsp09(uint8_t function) { bool result = false; if (FUNC_DISPLAY_INIT_DRIVER == function) { SSD1351_InitDriver(); } - else if (XDSP_09 == Settings.display_model) { + else if (ssd1351_init_done && (XDSP_09 == Settings.display_model)) { switch (function) { case FUNC_DISPLAY_MODEL: result = true; diff --git a/tasmota/xdsp_10_RA8876.ino b/tasmota/xdsp_10_RA8876.ino index 7cc87c4df..a56f3ebf4 100644 --- a/tasmota/xdsp_10_RA8876.ino +++ b/tasmota/xdsp_10_RA8876.ino @@ -1,7 +1,7 @@ /* xdsp_09_SSD1351.ino - Display SSD1351 support for Tasmota - Copyright (C) 2020 Gerhard Mutz and Theo Arends + Copyright (C) 2021 Gerhard Mutz and 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 @@ -33,19 +33,17 @@ #include +bool ra8876_init_done = false; uint8_t ra8876_ctouch_counter = 0; extern uint8_t *buffer; extern uint8_t color_type; RA8876 *ra8876; /*********************************************************************************************/ -void RA8876_InitDriver() -{ - if (!Settings.display_model) { - Settings.display_model = XDSP_10; - } +void RA8876_InitDriver(void) { + if (PinUsed(GPIO_RA8876_CS) && (SPI_MOSI_MISO == TasmotaGlobal.spi_enabled)) { - if (XDSP_10 == Settings.display_model) { + Settings.display_model = XDSP_10; if (Settings.display_width != RA8876_TFTWIDTH) { Settings.display_width = RA8876_TFTWIDTH; @@ -53,39 +51,15 @@ void RA8876_InitDriver() if (Settings.display_height != RA8876_TFTHEIGHT) { Settings.display_height = RA8876_TFTHEIGHT; } - buffer=0; + + buffer = 0; // default colors fg_color = RA8876_WHITE; bg_color = RA8876_BLACK; -#ifdef ESP8266 -#undef HW_SPI_MOSI -#define HW_SPI_MOSI 13 -#undef HW_SPI_MISO -#define HW_SPI_MISO 12 -#undef HW_SPI_CLK -#define HW_SPI_CLK 14 -#endif // ESP8266 -#ifdef ESP32 -#undef HW_SPI_MOSI -#define HW_SPI_MOSI 23 -#undef HW_SPI_MISO -#define HW_SPI_MISO 19 -#undef HW_SPI_CLK -#define HW_SPI_CLK 18 -#endif // ESP32 - // init renderer, must use hardware spi - if (PinUsed(GPIO_SSPI_CS) && (Pin(GPIO_SSPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SSPI_MISO)==HW_SPI_MISO) && (Pin(GPIO_SSPI_SCLK)==HW_SPI_CLK)) { - ra8876 = new RA8876(Pin(GPIO_SSPI_CS),Pin(GPIO_SSPI_MOSI),Pin(GPIO_SSPI_MISO),Pin(GPIO_SSPI_SCLK),Pin(GPIO_BACKLIGHT)); - } else { - if (PinUsed(GPIO_SPI_CS) && (Pin(GPIO_SPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SPI_MISO)==HW_SPI_MISO) && (Pin(GPIO_SPI_CLK)==HW_SPI_CLK)) { - ra8876 = new RA8876(Pin(GPIO_SPI_CS),Pin(GPIO_SPI_MOSI),Pin(GPIO_SPI_MISO),Pin(GPIO_SPI_CLK),Pin(GPIO_BACKLIGHT)); - } else { - return; - } - } + ra8876 = new RA8876(Pin(GPIO_RA8876_CS), Pin(GPIO_SPI_MOSI), Pin(GPIO_SPI_MISO), Pin(GPIO_SPI_CLK), Pin(GPIO_BACKLIGHT)); ra8876->begin(); renderer = ra8876; @@ -107,6 +81,8 @@ void RA8876_InitDriver() Touch_Init(Wire); #endif + ra8876_init_done = true; + AddLog_P(LOG_LEVEL_INFO, PSTR("DSP: RA8876")); } } @@ -329,7 +305,7 @@ bool Xdsp10(uint8_t function) if (FUNC_DISPLAY_INIT_DRIVER == function) { RA8876_InitDriver(); } - else if (XDSP_10 == Settings.display_model) { + else if (ra8876_init_done && (XDSP_10 == Settings.display_model)) { switch (function) { case FUNC_DISPLAY_MODEL: result = true; diff --git a/tasmota/xdsp_11_sevenseg.ino b/tasmota/xdsp_11_sevenseg.ino index a7d9e9b25..b3bde3149 100644 --- a/tasmota/xdsp_11_sevenseg.ino +++ b/tasmota/xdsp_11_sevenseg.ino @@ -1,7 +1,7 @@ /* xdsp_11_sevenseg.ino - Display seven segment support for Tasmota - Copyright (C) 2020 Theo Arends and Adafruit + Copyright (C) 2021 Theo Arends and Adafruit 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 @@ -62,6 +62,61 @@ void SevensegWrite(void) } } +void SevensegLog(void) +{ + // get sensor data + ResponseClear(); + ResponseAppendTime(); + XsnsCall(FUNC_JSON_APPEND); + ResponseJsonEnd(); + + // display nth sensor value on nth display + // code adapted from xdrv_13_display.ino, DisplayAnalyzeJson() + uint8_t unit = 0; + int16_t valueDecimal = 0; + double valueFloat = 0; + uint8 fDigits = 0; + String jsonStr = TasmotaGlobal.mqtt_data; // Move from stack to heap to fix watchdogs (20180626) + JsonParser parser((char*)jsonStr.c_str()); + JsonParserObject object_root = parser.getRootObject(); + if (object_root) { + for (auto key_level1 : object_root) { + JsonParserToken token_level1 = key_level1.getValue(); + if (token_level1.isObject()) { + JsonParserObject object_level1 = token_level1.getObject(); + for (auto key_level2 : object_level1) { + const char* value_level2 = key_level2.getValue().getStr(nullptr); + if (value_level2 != nullptr) { + if ((unit < sevensegs) && (sevenseg[unit] != nullptr)) { + if (strchr( value_level2, '.') == NULL) { + sevenseg[unit]->print(atoi(value_level2), DEC); + } else { + sevenseg[unit]->printFloat(atof(value_level2), 1, DEC); + } + sevenseg[unit]->writeDisplay(); + unit++; + } + } + } + } + } + } +} + +void SevensegDim(void) +{ + for (uint32_t i = 0; i < sevensegs; i++) { + sevenseg[i]->setBrightness(Settings.display_dimmer); + } +} + +void SevensegBlinkrate( void) +{ + for (uint32_t i = 0; i < sevensegs; i++) { + sevenseg[i]->blinkRate(XdrvMailbox.payload); + } +} + void SevensegClear(void) { for (uint32_t i = 0; i < sevensegs; i++) { @@ -352,6 +407,7 @@ void SevensegRefresh(void) // Every second case 4: // Mqtt case 3: // Local case 5: { // Mqtt + SevensegLog(); break; } } @@ -396,6 +452,13 @@ bool Xdsp11(uint8_t function) case FUNC_DISPLAY_DRAW_STRING: SevensegDrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag); break; + case FUNC_DISPLAY_DIM: + SevensegDim(); + break; + case FUNC_DISPLAY_BLINKRATE: + SevensegBlinkrate(); + break; + } } return result; diff --git a/tasmota/xdsp_12_ST7789.ino b/tasmota/xdsp_12_ST7789.ino index 3c85f168a..cdb9ad167 100644 --- a/tasmota/xdsp_12_ST7789.ino +++ b/tasmota/xdsp_12_ST7789.ino @@ -1,7 +1,7 @@ /* xdsp_12_ST7789.ino - Display ST7789 support for Tasmota - Copyright (C) 2020 Gerhard Mutz and Theo Arends + Copyright (C) 2021 Gerhard Mutz and 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 @@ -53,76 +53,53 @@ Arduino_ST7789 *st7789; #ifdef USE_FT5206 uint8_t st7789_ctouch_counter = 0; #endif // USE_FT5206 +bool st7789_init_done = false; /*********************************************************************************************/ -void ST7789_InitDriver() -{ - if (!Settings.display_model) { +void ST7789_InitDriver(void) { + if (PinUsed(GPIO_ST7789_DC) && // This device does not need CS which breaks SPI bus usage + ((TasmotaGlobal.soft_spi_enabled & SPI_MOSI) || (TasmotaGlobal.spi_enabled & SPI_MOSI))) { + Settings.display_model = XDSP_12; - } - if (XDSP_12 == Settings.display_model) { - - if (Settings.display_width != ST7789_TFTWIDTH) { - Settings.display_width = ST7789_TFTWIDTH; + if (!Settings.display_width) { + Settings.display_width = 240; } - if (Settings.display_height != ST7789_TFTHEIGHT) { - Settings.display_height = ST7789_TFTHEIGHT; + if (!Settings.display_height) { + Settings.display_height = 240; } // disable screen buffer - buffer=NULL; + buffer = NULL; // default colors fg_color = ST7789_WHITE; bg_color = ST7789_BLACK; - int8_t bppin=BACKPLANE_PIN; - if (PinUsed(GPIO_BACKLIGHT)) { - bppin=Pin(GPIO_BACKLIGHT); + int8_t bppin = BACKPLANE_PIN; + if (PinUsed(GPIO_BACKLIGHT)) { + bppin = Pin(GPIO_BACKLIGHT); } int8_t reset = -1; - if (PinUsed(GPIO_OLED_RESET)) { - reset=Pin(GPIO_OLED_RESET); + if (PinUsed(GPIO_OLED_RESET)) { + reset = Pin(GPIO_OLED_RESET); } int8_t cs = -1; - if (PinUsed(GPIO_SSPI_CS)) { - cs=Pin(GPIO_SSPI_CS); - } else if (PinUsed(GPIO_SPI_CS)) { - cs=Pin(GPIO_SPI_CS); + if (PinUsed(GPIO_ST7789_CS)) { + cs = Pin(GPIO_ST7789_CS); } -#ifdef ESP8266 -#undef HW_SPI_MOSI -#define HW_SPI_MOSI 13 -#undef HW_SPI_CLK -#define HW_SPI_CLK 14 -#endif // ESP8266 -#ifdef ESP32 -#undef HW_SPI_MOSI -#define HW_SPI_MOSI 23 -#undef HW_SPI_CLK -#define HW_SPI_CLK 18 -#endif // ESP32 - // init renderer, may use hardware spi - //if (PinUsed(GPIO_SPI_CS) && (Pin(GPIO_SPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SPI_CLK)==HW_SPI_CLK) && PinUsed(GPIO_SPI_DC)) { - if ((Pin(GPIO_SPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SPI_CLK)==HW_SPI_CLK) && PinUsed(GPIO_SPI_DC)) { - st7789 = new Arduino_ST7789(Pin(GPIO_SPI_DC), reset, cs, bppin); - } else { - if ((PinUsed(GPIO_SSPI_CS) || PinUsed(GPIO_OLED_RESET)) && PinUsed(GPIO_SSPI_MOSI) && PinUsed(GPIO_SSPI_SCLK) && PinUsed(GPIO_SSPI_DC)) { - if ((Pin(GPIO_SSPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SSPI_SCLK)==HW_SPI_CLK)) { - st7789 = new Arduino_ST7789(Pin(GPIO_SSPI_DC), reset, cs, bppin); - } else { - st7789 = new Arduino_ST7789(Pin(GPIO_SSPI_DC), reset, Pin(GPIO_SSPI_MOSI), Pin(GPIO_SSPI_SCLK), cs, bppin); - } - } else { - return; - } + if (TasmotaGlobal.soft_spi_enabled) { + st7789 = new Arduino_ST7789(Pin(GPIO_ST7789_DC), reset, Pin(GPIO_SSPI_MOSI), Pin(GPIO_SSPI_SCLK), cs, bppin); } + else if (TasmotaGlobal.spi_enabled) { + st7789 = new Arduino_ST7789(Pin(GPIO_ST7789_DC), reset, cs, bppin); + } + st7789->init(Settings.display_width,Settings.display_height); renderer = st7789; renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); @@ -130,9 +107,15 @@ void ST7789_InitDriver() #ifdef SHOW_SPLASH // Welcome text - renderer->setTextFont(2); renderer->setTextColor(ST7789_WHITE,ST7789_BLACK); - renderer->DrawStringAt(30, 100, "ST7789 TFT!", ST7789_WHITE,0); + int fontSize = 2; + renderer->setTextFont(2); + if (Settings.display_width<240) { + fontSize = 1; + } + renderer->setTextFont(fontSize); + int fontHeight = 12 * fontSize; + renderer->DrawStringAt(30, (Settings.display_height-fontHeight)/2, "ST7789 TFT!", ST7789_WHITE,0); delay(1000); #endif @@ -148,6 +131,8 @@ void ST7789_InitDriver() #endif // USE_FT5206 #endif // ESP32 + st7789_init_done = true; + AddLog_P(LOG_LEVEL_INFO, PSTR("DSP: ST7789")); } } @@ -206,7 +191,7 @@ bool Xdsp12(uint8_t function) if (FUNC_DISPLAY_INIT_DRIVER == function) { ST7789_InitDriver(); } - else if (XDSP_12 == Settings.display_model) { + else if (st7789_init_done && (XDSP_12 == Settings.display_model)) { switch (function) { case FUNC_DISPLAY_MODEL: result = true; diff --git a/tasmota/xdsp_13_ILI9341-2.ino b/tasmota/xdsp_13_ILI9341-2.ino index 9df5e9038..6095b5c53 100644 --- a/tasmota/xdsp_13_ILI9341-2.ino +++ b/tasmota/xdsp_13_ILI9341-2.ino @@ -1,7 +1,7 @@ /* xdsp_13_ILI9341-TTGO-TS.ino - Display ILI9341 support for Tasmota - Copyright (C) 2020 Gerhard Mutz and Theo Arends + Copyright (C) 2021 Gerhard Mutz and 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 @@ -95,8 +95,9 @@ void ILI9341_2_InitDriver() // Welcome text renderer->setTextFont(2); renderer->setTextColor(ILI9341_2_WHITE,ILI9341_2_BLACK); - renderer->DrawStringAt(30, 100, "ILI9341 TFT!", ILI9341_2_WHITE,0); + renderer->DrawStringAt(20, 140, "ILI9341 TFT!", ILI9341_2_RED,0); delay(1000); + renderer->clearDisplay(); #endif color_type = COLOR_COLOR; @@ -174,6 +175,77 @@ ili9342_ctouch_counter++; #endif // ESP32 +#ifdef USE_DISPLAY_MODES1TO5 + +void ILI9341_2_PrintLog(bool withDateTime) { + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } + + char* txt = DisplayLogBuffer('\370'); + if (txt != NULL) { + uint8_t last_row = Settings.display_rows -1; + + renderer->clearDisplay(); /** TODO: Would be smoother without clear, like ILI9341_2_Time() does. **/ + renderer->setCursor(0,0); + + if (withDateTime) { + char line[21]; + snprintf_P(line, sizeof(line), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d %02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.hour, RtcTime.minute, RtcTime.second, RtcTime.day_of_month, RtcTime.month, RtcTime.year); // [12:34:56 31-12-2021] + renderer->setTextColor(ILI9341_2_BLUE); + renderer->println(line); + renderer->setTextColor(fg_color); + last_row--; + } + + for (byte i = 0; i < last_row; i++) { + strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); + renderer->println(disp_screen_buffer[i]); + } + strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); + DisplayFillScreen(last_row); + + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); + + renderer->println(disp_screen_buffer[last_row]); + renderer->Updateframe(); + } + } +} + +void ILI9341_2_Time(void) { + char line[12]; + /** TODO: DisplaySize is working, but renderer->println() does not respect DisplayFont **/ + snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); // [ 12:34:56 ] + renderer->setCursor(60, 140); + renderer->println(line); + snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); // [01-02-2018] + renderer->setCursor(60, 160); + renderer->println(line); + renderer->Updateframe(); +} + +void ILI9341_2_Refresh(void) { // Every second + if (Settings.display_mode) { // Mode 0 is User text + switch (Settings.display_mode) { + case 1: // Time + ILI9341_2_Time(); + break; + case 2: // Local + case 4: // Mqtt + ILI9341_2_PrintLog(false); + break; + case 3: // Local + Time + case 5: // Mqtt + Time + ILI9341_2_PrintLog(true); + break; + } + } +} + +#endif // USE_DISPLAY_MODES1TO5 + /*********************************************************************************************/ /*********************************************************************************************\ * Interface @@ -190,6 +262,11 @@ bool Xdsp13(uint8_t function) case FUNC_DISPLAY_MODEL: result = true; break; + case FUNC_DISPLAY_TEXT_SIZE: + case FUNC_DISPLAY_FONT_SIZE: + case DISPLAY_INIT_MODE: + renderer->clearDisplay(); + break; #ifdef USE_FT5206 #ifdef USE_TOUCH_BUTTONS case FUNC_DISPLAY_EVERY_50_MSECOND: @@ -199,6 +276,11 @@ bool Xdsp13(uint8_t function) break; #endif // USE_TOUCH_BUTTONS #endif // USE_FT5206 +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + ILI9341_2_Refresh(); + break; +#endif // USE_DISPLAY_MODES1TO5 } } return result; diff --git a/tasmota/xdsp_14_SSD1331.ino b/tasmota/xdsp_14_SSD1331.ino new file mode 100644 index 000000000..be5417426 --- /dev/null +++ b/tasmota/xdsp_14_SSD1331.ino @@ -0,0 +1,196 @@ +/* + xdsp_14_SSD1331.ino - Display SSD1331 support for Tasmota + + Copyright (C) 2021 Jeroen Vermeulen, Gerhard Mutz and 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 . +*/ + +#ifdef USE_SPI +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_SSD1331 + +#define XDSP_14 14 + +#define COLORED 1 +#define UNCOLORED 0 +#define USE_TINY_FONT + +#define SSD1331_BLACK 0x0000 // 0, 0, 0 +#define SSD1331_WHITE 0xFFFF // 255, 255, 255 +#define SSD1331_RED 0xF800 // 255, 0, 0 +#define SSD1331_BLUE 0x001F // 0, 0, 255 + +#include +#include + +bool ssd1331_init_done = false; +extern uint8_t *buffer; +extern uint8_t color_type; +Adafruit_SSD1331 *ssd1331; + +/*********************************************************************************************/ + +void SSD1331_InitDriver() { + if (PinUsed(GPIO_SSD1331_CS) && PinUsed(GPIO_SSD1331_DC) && + ((TasmotaGlobal.soft_spi_enabled & SPI_MOSI) || (TasmotaGlobal.spi_enabled & SPI_MOSI))) { + + Settings.display_model = XDSP_14; + + if (Settings.display_width != Adafruit_SSD1331::TFTWIDTH) { + Settings.display_width = Adafruit_SSD1331::TFTWIDTH; + } + if (Settings.display_height != Adafruit_SSD1331::TFTHEIGHT) { + Settings.display_height = Adafruit_SSD1331::TFTHEIGHT; + } + + buffer = 0; + + // default colors + fg_color = SSD1331_WHITE; + bg_color = SSD1331_BLACK; + + int8_t reset = -1; + if (PinUsed(GPIO_OLED_RESET)) { + reset = Pin(GPIO_OLED_RESET); + } + + // init renderer + if (TasmotaGlobal.soft_spi_enabled) { + ssd1331 = new Adafruit_SSD1331(Pin(GPIO_SSD1331_CS), Pin(GPIO_SSD1331_DC), Pin(GPIO_SSPI_MOSI), Pin(GPIO_SSPI_SCLK), reset); + } + else if (TasmotaGlobal.spi_enabled) { + ssd1331 = new Adafruit_SSD1331(&SPI, Pin(GPIO_SSD1331_CS), Pin(GPIO_SSD1331_DC), reset); + } + + delay(100); + ssd1331->begin(); + renderer = ssd1331; + // Rotation is currently broken, https://github.com/adafruit/Adafruit-SSD1331-OLED-Driver-Library-for-Arduino/issues/26 + renderer->DisplayInit(DISPLAY_INIT_MODE, Settings.display_size, Settings.display_rotate, Settings.display_font); + renderer->dim(Settings.display_dimmer); + +#ifdef SHOW_SPLASH + // Welcome text + renderer->clearDisplay(); + renderer->setTextFont(1); + renderer->DrawStringAt(24, 27, "SSD1331", SSD1331_RED, 0); + delay(1000); +#endif + + color_type = COLOR_COLOR; + + ssd1331_init_done = true; + AddLog_P(LOG_LEVEL_INFO, PSTR("DSP: SSD1331")); + } +} + +#ifdef USE_DISPLAY_MODES1TO5 + +void SSD1331PrintLog(bool withDateTime) { + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } + + char* txt = DisplayLogBuffer('\370'); + if (txt != NULL) { + uint8_t last_row = Settings.display_rows -1; + + renderer->clearDisplay(); + renderer->setCursor(0,0); + + if (withDateTime) { + char line[17]; + snprintf_P(line, sizeof(line), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d %02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.hour, RtcTime.minute, RtcTime.day_of_month, RtcTime.month, RtcTime.year); // [12:34 01-02-2018] + renderer->setTextColor(SSD1331_BLUE); + renderer->println(line); + renderer->setTextColor(fg_color); + last_row--; + } + + for (byte i = 0; i < last_row; i++) { + strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); + renderer->println(disp_screen_buffer[i]); + } + strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); + DisplayFillScreen(last_row); + + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); + + renderer->println(disp_screen_buffer[last_row]); + renderer->Updateframe(); + } + } +} + +void SSD1331Time(void) { + char line[12]; + + renderer->clearDisplay(); + renderer->setCursor(0, 0); + snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); // [ 12:34:56 ] + renderer->println(line); + snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); // [01-02-2018] + renderer->println(line); + renderer->Updateframe(); +} + +void SSD1331Refresh(void) { // Every second + if (Settings.display_mode) { // Mode 0 is User text + switch (Settings.display_mode) { + case 1: // Time + SSD1331Time(); + break; + case 2: // Local + case 4: // Mqtt + SSD1331PrintLog(false); + break; + case 3: // Local + Time + case 5: // Mqtt + Time + SSD1331PrintLog(true); + break; + } + } +} + +#endif // USE_DISPLAY_MODES1TO5 + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xdsp14(uint8_t function) { + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + SSD1331_InitDriver(); + } + else if (ssd1331_init_done && (XDSP_14 == Settings.display_model)) { + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + SSD1331Refresh(); + break; +#endif // USE_DISPLAY_MODES1TO5 + } + } + return result; +} +#endif // USE_DISPLAY_SSD1331 +#endif // USE_DISPLAY +#endif // USE_SPI diff --git a/tasmota/xdsp_interface.ino b/tasmota/xdsp_interface.ino index 44e72a001..1ce18ff6c 100644 --- a/tasmota/xdsp_interface.ino +++ b/tasmota/xdsp_interface.ino @@ -1,7 +1,7 @@ /* xdsp_interface.ino - Display interface support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xlgt_01_ws2812.ino b/tasmota/xlgt_01_ws2812.ino index f597348b4..e479d3573 100644 --- a/tasmota/xlgt_01_ws2812.ino +++ b/tasmota/xlgt_01_ws2812.ino @@ -1,7 +1,7 @@ /* xlgt_01_ws2812.ino - led string support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xlgt_02_my92x1.ino b/tasmota/xlgt_02_my92x1.ino index 9206d32c6..412cfd771 100644 --- a/tasmota/xlgt_02_my92x1.ino +++ b/tasmota/xlgt_02_my92x1.ino @@ -1,7 +1,7 @@ /* xlgt_02_my92x1.ino - led support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xlgt_03_sm16716.ino b/tasmota/xlgt_03_sm16716.ino index 29ef77c23..129f64e1a 100644 --- a/tasmota/xlgt_03_sm16716.ino +++ b/tasmota/xlgt_03_sm16716.ino @@ -1,7 +1,7 @@ /* xlgt_03_sm16716.ino - sm16716 three channel led support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 @@ -21,7 +21,7 @@ #ifdef USE_SM16716 /*********************************************************************************************\ * SM16716 - Controlling RGB over a synchronous serial line - * Copyright (C) 2020 Gabor Simon + * Copyright (C) 2021 Gabor Simon * * Source: https://community.home-assistant.io/t/cheap-uk-wifi-bulbs-with-tasmota-teardown-help-tywe3s/40508/27 \*********************************************************************************************/ diff --git a/tasmota/xlgt_04_sm2135.ino b/tasmota/xlgt_04_sm2135.ino index 92d1d5059..c5cf52195 100644 --- a/tasmota/xlgt_04_sm2135.ino +++ b/tasmota/xlgt_04_sm2135.ino @@ -1,7 +1,7 @@ /* xlgt_04_sm2135.ino - sm2135 five channel led support for Tasmota - Copyright (C) 2020 Theo Arends and CrudelisPL + Copyright (C) 2021 Theo Arends and CrudelisPL 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 diff --git a/tasmota/xlgt_05_sonoff_l1.ino b/tasmota/xlgt_05_sonoff_l1.ino index 38f9a3000..227d8f1c9 100644 --- a/tasmota/xlgt_05_sonoff_l1.ino +++ b/tasmota/xlgt_05_sonoff_l1.ino @@ -1,7 +1,7 @@ /* xlgt_05_sonoff_l1.ino - Sonoff L1 led support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 @@ -64,7 +64,6 @@ struct SNFL1 { Ticker SnfL1StartDelay; void SnfL1SendDelayed(void) { - SnfL1StartDelay.detach(); SnfL1Send(); } @@ -276,7 +275,7 @@ bool SnfL1SetChannels(void) static bool first_call = true; if (first_call) { - SnfL1StartDelay.attach_ms(900, SnfL1SendDelayed); // Allow startup time for Nuvotron microcontroller + SnfL1StartDelay.once_ms(900, SnfL1SendDelayed); // Allow startup time for Nuvotron microcontroller first_call = false; } else { SnfL1Send(); diff --git a/tasmota/xlgt_06_electriq_moodl.ino b/tasmota/xlgt_06_electriq_moodl.ino index 6437b8f3f..3cb07a7e6 100644 --- a/tasmota/xlgt_06_electriq_moodl.ino +++ b/tasmota/xlgt_06_electriq_moodl.ino @@ -1,7 +1,7 @@ /* xlgt_06_moodlamp.ino - ElectriQ iQ-wifiMOODL LED support for Tasmota - Copyright (C) 2020 ianbyte and Theo Arends + Copyright (C) 2021 ianbyte and 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 diff --git a/tasmota/xlgt_interface.ino b/tasmota/xlgt_interface.ino index ef5934d54..4ef1928f8 100644 --- a/tasmota/xlgt_interface.ino +++ b/tasmota/xlgt_interface.ino @@ -1,7 +1,7 @@ /* xlgt_interface.ino - Light driver interface support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xnrg_01_hlw8012.ino b/tasmota/xnrg_01_hlw8012.ino index 964474ad1..a174699a0 100644 --- a/tasmota/xnrg_01_hlw8012.ino +++ b/tasmota/xnrg_01_hlw8012.ino @@ -1,7 +1,7 @@ /* xnrg_01_hlw8012.ino - HLW8012 (Sonoff Pow) energy sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xnrg_02_cse7766.ino b/tasmota/xnrg_02_cse7766.ino index e4ee38d2b..e70b0addb 100644 --- a/tasmota/xnrg_02_cse7766.ino +++ b/tasmota/xnrg_02_cse7766.ino @@ -1,7 +1,7 @@ /* xnrg_02_cse7766.ino - CSE7766 and HLW8032 energy sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xnrg_03_pzem004t.ino b/tasmota/xnrg_03_pzem004t.ino index 0ffbe433b..39a382a41 100644 --- a/tasmota/xnrg_03_pzem004t.ino +++ b/tasmota/xnrg_03_pzem004t.ino @@ -1,7 +1,7 @@ /* xnrg_03_pzem004t.ino - PZEM004T energy sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xnrg_04_mcp39f501.ino b/tasmota/xnrg_04_mcp39f501.ino index 6b7799cce..bfe7c48fd 100644 --- a/tasmota/xnrg_04_mcp39f501.ino +++ b/tasmota/xnrg_04_mcp39f501.ino @@ -1,7 +1,7 @@ /* xnrg_04_mcp39f501.ino - MCP39F501 energy sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xnrg_05_pzem_ac.ino b/tasmota/xnrg_05_pzem_ac.ino index 08971cb7f..2c79ae2f6 100644 --- a/tasmota/xnrg_05_pzem_ac.ino +++ b/tasmota/xnrg_05_pzem_ac.ino @@ -1,7 +1,7 @@ /* xnrg_05_pzem_ac.ino - PZEM-014,016 Modbus AC energy sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xnrg_06_pzem_dc.ino b/tasmota/xnrg_06_pzem_dc.ino index 8de1f7f22..8e5b13c54 100644 --- a/tasmota/xnrg_06_pzem_dc.ino +++ b/tasmota/xnrg_06_pzem_dc.ino @@ -1,7 +1,7 @@ /* xnrg_06_pzem_dc.ino - PZEM-003,017 Modbus DC energy sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xnrg_07_ade7953.ino b/tasmota/xnrg_07_ade7953.ino index 4e3dbcc0e..a9c8acc5f 100644 --- a/tasmota/xnrg_07_ade7953.ino +++ b/tasmota/xnrg_07_ade7953.ino @@ -1,7 +1,7 @@ /* xnrg_07_ade7953.ino - ADE7953 energy sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xnrg_08_sdm120.ino b/tasmota/xnrg_08_sdm120.ino index 5659f05ed..5ba6242f6 100644 --- a/tasmota/xnrg_08_sdm120.ino +++ b/tasmota/xnrg_08_sdm120.ino @@ -1,7 +1,7 @@ /* xnrg_08_sdm120.ino - Eastron SDM120-Modbus energy meter support for Tasmota - Copyright (C) 2020 Gennaro Tortone and Theo Arends + Copyright (C) 2021 Gennaro Tortone and 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 diff --git a/tasmota/xnrg_09_dds2382.ino b/tasmota/xnrg_09_dds2382.ino index 69826564b..25ae5cf35 100644 --- a/tasmota/xnrg_09_dds2382.ino +++ b/tasmota/xnrg_09_dds2382.ino @@ -1,7 +1,7 @@ /* xnrg_09_dds2382.ino - Hiking DDS238-2 Modbus energy meter support for Tasmota - Copyright (C) 2020 Matteo Campanella - based on the work of Gennaro Tortone + Copyright (C) 2021 Matteo Campanella - based on the work of Gennaro Tortone 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 diff --git a/tasmota/xnrg_10_sdm630.ino b/tasmota/xnrg_10_sdm630.ino index f002e11bb..7dcf478e4 100644 --- a/tasmota/xnrg_10_sdm630.ino +++ b/tasmota/xnrg_10_sdm630.ino @@ -1,7 +1,7 @@ /* xnrg_10_sdm630.ino - Eastron SDM630-Modbus energy meter support for Tasmota - Copyright (C) 2020 Gennaro Tortone and Theo Arends + Copyright (C) 2021 Gennaro Tortone and 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 diff --git a/tasmota/xnrg_11_ddsu666.ino b/tasmota/xnrg_11_ddsu666.ino index cd0701383..dc52cff5a 100644 --- a/tasmota/xnrg_11_ddsu666.ino +++ b/tasmota/xnrg_11_ddsu666.ino @@ -1,7 +1,7 @@ /* xnrg_11_ddsu666.ino - Chint DDSU666-Modbus energy meter support for Tasmota - Copyright (C) 2020 Pablo Zerón and Theo Arends + Copyright (C) 2021 Pablo Zerón and 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 diff --git a/tasmota/xnrg_12_solaxX1.ino b/tasmota/xnrg_12_solaxX1.ino index be0c99958..04d873deb 100644 --- a/tasmota/xnrg_12_solaxX1.ino +++ b/tasmota/xnrg_12_solaxX1.ino @@ -1,7 +1,7 @@ /* xnrg_12_solaxX1.ino - Solax X1 inverter RS485 support for Tasmota - Copyright (C) 2020 Pablo Zerón + Copyright (C) 2021 Pablo Zerón 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 diff --git a/tasmota/xnrg_13_fif_le01mr.ino b/tasmota/xnrg_13_fif_le01mr.ino index 66f93190a..8678e0a6c 100644 --- a/tasmota/xnrg_13_fif_le01mr.ino +++ b/tasmota/xnrg_13_fif_le01mr.ino @@ -1,7 +1,7 @@ /* xnrg_13_fif_le01mr.ino - F&F LE-01MR energy meter with Modbus interface - support for Tasmota - Copyright (C) 2020 Przemyslaw Wistuba + Copyright (C) 2021 Przemyslaw Wistuba 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 diff --git a/tasmota/xnrg_14_bl0940.ino b/tasmota/xnrg_14_bl0940.ino index 2310ad3b7..3237c485d 100644 --- a/tasmota/xnrg_14_bl0940.ino +++ b/tasmota/xnrg_14_bl0940.ino @@ -1,7 +1,7 @@ /* xnrg_14_bl0940.ino - BL0940 energy sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xnrg_15_teleinfo.ino b/tasmota/xnrg_15_teleinfo.ino index 1be83a57d..e2dfe6195 100755 --- a/tasmota/xnrg_15_teleinfo.ino +++ b/tasmota/xnrg_15_teleinfo.ino @@ -1,7 +1,7 @@ /* xnrg_15_Teleinfo.ino - Teleinfo support for Tasmota - Copyright (C) 2020 Charles-Henri Hallard + Copyright (C) 2021 Charles-Henri Hallard 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 diff --git a/tasmota/xnrg_16_iem3000.ino b/tasmota/xnrg_16_iem3000.ino index a3dfd2e67..c5ad359fe 100644 --- a/tasmota/xnrg_16_iem3000.ino +++ b/tasmota/xnrg_16_iem3000.ino @@ -1,7 +1,7 @@ /* xnrg_16_iem3000.ino - Schneider Electric iEM3000 series Modbus energy meter support for Tasmota - Copyright (C) 2020 Marius Bezuidenhout + Copyright (C) 2021 Marius Bezuidenhout 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 diff --git a/tasmota/xnrg_17_ornowe517.ino b/tasmota/xnrg_17_ornowe517.ino index b7eb1b1c1..d77114002 100644 --- a/tasmota/xnrg_17_ornowe517.ino +++ b/tasmota/xnrg_17_ornowe517.ino @@ -1,7 +1,7 @@ /* xnrg_17_ornowe512.ino - Orno WE517-Modbus energy meter support for Tasmota - Copyright (C) 2020 Maxime Vincent - based on the work of Gennaro Tortone and Theo Arends + Copyright (C) 2021 Maxime Vincent - based on the work of Gennaro Tortone and 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 diff --git a/tasmota/xnrg_interface.ino b/tasmota/xnrg_interface.ino index c227782b7..de019675c 100644 --- a/tasmota/xnrg_interface.ino +++ b/tasmota/xnrg_interface.ino @@ -1,7 +1,7 @@ /* xnrg_interface.ino - Energy driver interface support for Tasmota - Copyright (C) 2020 Theo Arends inspired by ESPEasy + Copyright (C) 2021 Theo Arends inspired by ESPEasy 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 diff --git a/tasmota/xsns_01_counter.ino b/tasmota/xsns_01_counter.ino index 1f2861e56..77d630851 100644 --- a/tasmota/xsns_01_counter.ino +++ b/tasmota/xsns_01_counter.ino @@ -1,7 +1,7 @@ /* xsns_01_counter.ino - Counter sensors (water meters, electricity meters etc.) sensor support for Tasmota - Copyright (C) 2020 Maarten Damen and Theo Arends + Copyright (C) 2021 Maarten Damen and 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 diff --git a/tasmota/xsns_02_analog.ino b/tasmota/xsns_02_analog.ino index a4a23de97..d9cd0c6e6 100644 --- a/tasmota/xsns_02_analog.ino +++ b/tasmota/xsns_02_analog.ino @@ -1,7 +1,7 @@ /* xsns_02_analog.ino - ADC support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xsns_04_snfsc.ino b/tasmota/xsns_04_snfsc.ino index 4822e5aa5..38f693c30 100644 --- a/tasmota/xsns_04_snfsc.ino +++ b/tasmota/xsns_04_snfsc.ino @@ -1,7 +1,7 @@ /* xsns_04_snfsc.ino - sonoff SC support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xsns_05_ds18x20.ino b/tasmota/xsns_05_ds18x20.ino index 8fbc1cf46..b09375b06 100644 --- a/tasmota/xsns_05_ds18x20.ino +++ b/tasmota/xsns_05_ds18x20.ino @@ -1,7 +1,7 @@ /* xsns_05_ds18x20.ino - DS18x20 temperature sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xsns_05_ds18x20_esp32.ino b/tasmota/xsns_05_ds18x20_esp32.ino index db95ccd71..6b6394b25 100644 --- a/tasmota/xsns_05_ds18x20_esp32.ino +++ b/tasmota/xsns_05_ds18x20_esp32.ino @@ -1,7 +1,7 @@ /* xsns_05_ds18x20_esp32.ino - DS18x20 temperature sensor support for Tasmota - Copyright (C) 2020 Heiko Krupp and Theo Arends + Copyright (C) 2021 Heiko Krupp and 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 diff --git a/tasmota/xsns_06_dht.ino b/tasmota/xsns_06_dht.ino index a6a584db8..3ae2ecc9d 100644 --- a/tasmota/xsns_06_dht.ino +++ b/tasmota/xsns_06_dht.ino @@ -1,7 +1,7 @@ /* xsns_06_dht.ino - DHTxx, AM23xx and SI7021 temperature and humidity sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xsns_07_sht1x.ino b/tasmota/xsns_07_sht1x.ino index 6d00eb80f..ed7bf3a1c 100644 --- a/tasmota/xsns_07_sht1x.ino +++ b/tasmota/xsns_07_sht1x.ino @@ -1,7 +1,7 @@ /* xsns_07_sht1x.ino - SHT1x temperature and sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xsns_08_htu21.ino b/tasmota/xsns_08_htu21.ino index 99d46c40e..18d6c2152 100644 --- a/tasmota/xsns_08_htu21.ino +++ b/tasmota/xsns_08_htu21.ino @@ -1,7 +1,7 @@ /* xsns_08_htu21.ino - HTU21 temperature and humidity sensor support for Tasmota - Copyright (C) 2020 Heiko Krupp and Theo Arends + Copyright (C) 2021 Heiko Krupp and 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 diff --git a/tasmota/xsns_09_bmp.ino b/tasmota/xsns_09_bmp.ino index d776fe793..b30615107 100644 --- a/tasmota/xsns_09_bmp.ino +++ b/tasmota/xsns_09_bmp.ino @@ -1,7 +1,7 @@ /* xsns_09_bmp.ino - BMP pressure, temperature, humidity and gas sensor support for Tasmota - Copyright (C) 2020 Heiko Krupp and Theo Arends + Copyright (C) 2021 Heiko Krupp and 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 diff --git a/tasmota/xsns_10_bh1750.ino b/tasmota/xsns_10_bh1750.ino index dfd9d013b..4fa8289ff 100644 --- a/tasmota/xsns_10_bh1750.ino +++ b/tasmota/xsns_10_bh1750.ino @@ -1,7 +1,7 @@ /* xsns_10_bh1750.ino - BH1750 ambient light sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xsns_11_veml6070.ino b/tasmota/xsns_11_veml6070.ino index cbaba7025..d49b229d1 100644 --- a/tasmota/xsns_11_veml6070.ino +++ b/tasmota/xsns_11_veml6070.ino @@ -1,7 +1,7 @@ /* xsns_11_veml6070.ino - VEML6070 ultra violet light sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xsns_12_ads1115.ino b/tasmota/xsns_12_ads1115.ino index 5ff73e021..6afb1b028 100644 --- a/tasmota/xsns_12_ads1115.ino +++ b/tasmota/xsns_12_ads1115.ino @@ -1,7 +1,7 @@ /* xsns_12_ads1115_ada.ino - ADS1115 A/D Converter support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xsns_13_ina219.ino b/tasmota/xsns_13_ina219.ino index c0c8f87d4..7518281da 100644 --- a/tasmota/xsns_13_ina219.ino +++ b/tasmota/xsns_13_ina219.ino @@ -1,7 +1,7 @@ /* xsns_13_ina219.ino - INA219 Current Sensor support for Tasmota - Copyright (C) 2020 Stefan Bode and Theo Arends + Copyright (C) 2021 Stefan Bode and 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 diff --git a/tasmota/xsns_14_sht3x.ino b/tasmota/xsns_14_sht3x.ino index bb98cc5b0..4e29742e5 100644 --- a/tasmota/xsns_14_sht3x.ino +++ b/tasmota/xsns_14_sht3x.ino @@ -1,7 +1,7 @@ /* xsns_14_sht3x.ino - SHT3X temperature and humidity sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xsns_15_mhz19.ino b/tasmota/xsns_15_mhz19.ino index d8feadb25..a2afb267f 100644 --- a/tasmota/xsns_15_mhz19.ino +++ b/tasmota/xsns_15_mhz19.ino @@ -1,7 +1,7 @@ /* xsns_15_mhz19.ino - MH-Z19(B) CO2 sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 @@ -74,7 +74,7 @@ const char kMhzModels[] PROGMEM = "|B"; const char ABC_ENABLED[] = "ABC is Enabled"; const char ABC_DISABLED[] = "ABC is Disabled"; -enum MhzCommands { MHZ_CMND_READPPM, MHZ_CMND_ABCENABLE, MHZ_CMND_ABCDISABLE, MHZ_CMND_ZEROPOINT, MHZ_CMND_RESET, MHZ_CMND_RANGE_1000, MHZ_CMND_RANGE_2000, MHZ_CMND_RANGE_3000, MHZ_CMND_RANGE_5000 }; +enum MhzCommands { MHZ_CMND_READPPM, MHZ_CMND_ABCENABLE, MHZ_CMND_ABCDISABLE, MHZ_CMND_ZEROPOINT, MHZ_CMND_RESET, MHZ_CMND_RANGE_1000, MHZ_CMND_RANGE_2000, MHZ_CMND_RANGE_3000, MHZ_CMND_RANGE_5000, MHZ_CMND_RANGE_10000 }; const uint8_t kMhzCommands[][4] PROGMEM = { // 2 3 6 7 {0x86,0x00,0x00,0x00}, // mhz_cmnd_read_ppm @@ -85,7 +85,8 @@ const uint8_t kMhzCommands[][4] PROGMEM = { {0x99,0x00,0x03,0xE8}, // mhz_cmnd_set_range_1000 {0x99,0x00,0x07,0xD0}, // mhz_cmnd_set_range_2000 {0x99,0x00,0x0B,0xB8}, // mhz_cmnd_set_range_3000 - {0x99,0x00,0x13,0x88}}; // mhz_cmnd_set_range_5000 + {0x99,0x00,0x13,0x88}, // mhz_cmnd_set_range_5000 + {0x99,0x00,0x27,0x10}}; // mhz_cmnd_set_range_10000 uint8_t mhz_type = 1; uint16_t mhz_last_ppm = 0; @@ -135,7 +136,7 @@ bool MhzCheckAndApplyFilter(uint16_t ppm, uint8_t s) if (1 == s) { return false; // S==1 => "A" version sensor bootup, do not use values. } - if (mhz_last_ppm < 400 || mhz_last_ppm > 5000) { + if (mhz_last_ppm < 400 || mhz_last_ppm > 10000) { // Prevent unrealistic values during start-up with filtering enabled. // Just assume the entered value is correct. mhz_last_ppm = ppm; @@ -269,6 +270,7 @@ void MhzEverySecond(void) #define D_JSON_RANGE_2000 "2000 ppm range" #define D_JSON_RANGE_3000 "3000 ppm range" #define D_JSON_RANGE_5000 "5000 ppm range" +#define D_JSON_RANGE_10000 "10000 ppm range" bool MhzCommandSensor(void) { @@ -309,6 +311,10 @@ bool MhzCommandSensor(void) MhzSendCmd(MHZ_CMND_RANGE_5000); Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_5000); break; + case 10000: + MhzSendCmd(MHZ_CMND_RANGE_10000); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_10000); + break; default: if (!Settings.SensorBits1.mhz19b_abc_disable) { Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); diff --git a/tasmota/xsns_16_tsl2561.ino b/tasmota/xsns_16_tsl2561.ino index 23f1b33cf..d0674c522 100644 --- a/tasmota/xsns_16_tsl2561.ino +++ b/tasmota/xsns_16_tsl2561.ino @@ -1,7 +1,7 @@ /* xsns_16_tsl2561.ino - TSL2561 light sensor support for Tasmota - Copyright (C) 2020 Theo Arends and Joachim Banzhaf + Copyright (C) 2021 Theo Arends and Joachim Banzhaf 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 diff --git a/tasmota/xsns_17_senseair.ino b/tasmota/xsns_17_senseair.ino index f731d9c1b..8d705648b 100644 --- a/tasmota/xsns_17_senseair.ino +++ b/tasmota/xsns_17_senseair.ino @@ -1,7 +1,7 @@ /* xsns_17_senseair.ino - SenseAir CO2 sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xsns_18_pms5003.ino b/tasmota/xsns_18_pms5003.ino index 009ef2857..1126aeb95 100644 --- a/tasmota/xsns_18_pms5003.ino +++ b/tasmota/xsns_18_pms5003.ino @@ -1,7 +1,7 @@ /* xsns_18_pms5003.ino - PMS3003, PMS5003, PMS7003 particle concentration sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xsns_19_mgs.ino b/tasmota/xsns_19_mgs.ino index 5a36183f8..8e62dcff9 100644 --- a/tasmota/xsns_19_mgs.ino +++ b/tasmota/xsns_19_mgs.ino @@ -1,7 +1,7 @@ /* xsns_19_mgs.ino - Xadow and Grove Mutichannel Gas sensor support for Tasmota - Copyright (C) 2020 Palich2000 and Theo Arends + Copyright (C) 2021 Palich2000 and 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 diff --git a/tasmota/xsns_20_novasds.ino b/tasmota/xsns_20_novasds.ino index 052991ea0..8263f8a65 100644 --- a/tasmota/xsns_20_novasds.ino +++ b/tasmota/xsns_20_novasds.ino @@ -1,7 +1,7 @@ /* xsns_20_novasds.ino - Nova SDS011/SDS021 particle concentration sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xsns_21_sgp30.ino b/tasmota/xsns_21_sgp30.ino index c4ca9a38a..11059d5d4 100644 --- a/tasmota/xsns_21_sgp30.ino +++ b/tasmota/xsns_21_sgp30.ino @@ -1,7 +1,7 @@ /* xsns_21_sgp30.ino - SGP30 gas and air quality sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xsns_22_sr04.ino b/tasmota/xsns_22_sr04.ino index f7cee1d20..3a075e1e1 100644 --- a/tasmota/xsns_22_sr04.ino +++ b/tasmota/xsns_22_sr04.ino @@ -1,7 +1,7 @@ /* xsns_22_sr04.ino - SR04 ultrasonic sensor support for Tasmota - Copyright (C) 2020 Nuno Ferreira and Theo Arends + Copyright (C) 2021 Nuno Ferreira and 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 diff --git a/tasmota/xsns_24_si1145.ino b/tasmota/xsns_24_si1145.ino index 032896806..c054ab834 100644 --- a/tasmota/xsns_24_si1145.ino +++ b/tasmota/xsns_24_si1145.ino @@ -1,7 +1,7 @@ /* xsns_24_si1145.ino - SI1145/46/47 UV Index / IR / Visible light sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xsns_26_lm75ad.ino b/tasmota/xsns_26_lm75ad.ino index 2a938e6e6..4f65f3d51 100644 --- a/tasmota/xsns_26_lm75ad.ino +++ b/tasmota/xsns_26_lm75ad.ino @@ -1,7 +1,7 @@ /* xsns_26_lm75ad.ino - Support for I2C LM75AD Temperature Sensor - Copyright (C) 2020 Andre Thomas and Theo Arends + Copyright (C) 2021 Andre Thomas and 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 diff --git a/tasmota/xsns_27_apds9960.ino b/tasmota/xsns_27_apds9960.ino index e332bedaa..2489329ac 100644 --- a/tasmota/xsns_27_apds9960.ino +++ b/tasmota/xsns_27_apds9960.ino @@ -1,7 +1,7 @@ /* xsns_27_apds9960.ino - Support for I2C APDS9960 Proximity Sensor for Tasmota - Copyright (C) 2020 Shawn Hymel/Sparkfun and Theo Arends + Copyright (C) 2021 Shawn Hymel/Sparkfun and Theo Arends Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/tasmota/xsns_28_tm1638.ino b/tasmota/xsns_28_tm1638.ino index 9df220848..2579a1703 100644 --- a/tasmota/xsns_28_tm1638.ino +++ b/tasmota/xsns_28_tm1638.ino @@ -1,7 +1,7 @@ /* xsns_28_tm1638.ino - TM1638 8 switch, led and 7 segment unit support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xsns_29_mcp230xx.ino b/tasmota/xsns_29_mcp230xx.ino index 6a960968a..56427278d 100644 --- a/tasmota/xsns_29_mcp230xx.ino +++ b/tasmota/xsns_29_mcp230xx.ino @@ -1,7 +1,7 @@ /* xsns_29_mcp230xx.ino - Support for I2C MCP23008/MCP23017 GPIO Expander on Tasmota - Copyright (C) 2020 Andre Thomas and Theo Arends + Copyright (C) 2021 Andre Thomas and 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 @@ -196,6 +196,7 @@ void MCP230xx_ApplySettings(void) I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPIO+mcp230xx_port, reg_portpins); #endif // USE_MCP230xx_OUTPUT } +#ifdef USE_MCP230xx_OUTPUT TasmotaGlobal.devices_present -= mcp230xx_oldoutpincount; mcp230xx_oldoutpincount = 0; for (uint32_t idx=0;idx4 && MGC_data.out.id != MGC3130_FW_VERSION){ AddLog_P(LOG_LEVEL_DEBUG,PSTR("MGC3130: missed a packet, mismatch: %u"), _mismatch - 1); AddLogBuffer(LOG_LEVEL_DEBUG,MGC_data.buffer,i); - } + } } _lastCounter = MGC_data.out.counter; success = true; diff --git a/tasmota/xsns_37_rfsensor.ino b/tasmota/xsns_37_rfsensor.ino index 7dd376b97..aee5f6641 100644 --- a/tasmota/xsns_37_rfsensor.ino +++ b/tasmota/xsns_37_rfsensor.ino @@ -1,7 +1,7 @@ /* xsns_37_rfsensor.ino - RF sensor receiver for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xsns_38_az7798.ino b/tasmota/xsns_38_az7798.ino index 1b5ba7f5f..b063dc166 100644 --- a/tasmota/xsns_38_az7798.ino +++ b/tasmota/xsns_38_az7798.ino @@ -1,7 +1,7 @@ /* xsns_38_az7798.ino - AZ_Instrument 7798 CO2/temperature/humidity meter support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xsns_39_max31855.ino b/tasmota/xsns_39_max31855.ino index a6e592c21..2a6304ce1 100644 --- a/tasmota/xsns_39_max31855.ino +++ b/tasmota/xsns_39_max31855.ino @@ -1,7 +1,7 @@ /* xsns_39_max31855.ino - MAX31855 thermocouple sensor support for Tasmota - Copyright (C) 2020 Markus Past + Copyright (C) 2021 Markus Past 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 diff --git a/tasmota/xsns_40_pn532.ino b/tasmota/xsns_40_pn532.ino index fb6d31354..4e9bbdcc4 100644 --- a/tasmota/xsns_40_pn532.ino +++ b/tasmota/xsns_40_pn532.ino @@ -1,7 +1,7 @@ /* xsns_40_pn532.ino - Support for PN532 (HSU) NFC Tag Reader on Tasmota - Copyright (C) 2020 Andre Thomas and Theo Arends + Copyright (C) 2021 Andre Thomas and 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 diff --git a/tasmota/xsns_41_max44009.ino b/tasmota/xsns_41_max44009.ino index b07d37567..7eccb043e 100644 --- a/tasmota/xsns_41_max44009.ino +++ b/tasmota/xsns_41_max44009.ino @@ -1,7 +1,7 @@ /* xsns_41_max44009.ino - MAX44009 ambient light sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xsns_42_scd30.ino b/tasmota/xsns_42_scd30.ino index c208c3307..458e046aa 100644 --- a/tasmota/xsns_42_scd30.ino +++ b/tasmota/xsns_42_scd30.ino @@ -1,7 +1,7 @@ /* xsns_42_scd30.ino - SC30 CO2 sensor support for Tasmota - Copyright (C) 2020 Frogmore42 + Copyright (C) 2021 Frogmore42 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 diff --git a/tasmota/xsns_43_hre.ino b/tasmota/xsns_43_hre.ino index f7240ec17..68299b066 100644 --- a/tasmota/xsns_43_hre.ino +++ b/tasmota/xsns_43_hre.ino @@ -1,7 +1,7 @@ /* xsns_43_hre.ino - Badger HR-E Water Meter Encoder interface - Copyright (C) 2020 Jon Little + Copyright (C) 2021 Jon Little 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 diff --git a/tasmota/xsns_44_sps30.ino b/tasmota/xsns_44_sps30.ino index c9316ba4c..9dd73dbcf 100644 --- a/tasmota/xsns_44_sps30.ino +++ b/tasmota/xsns_44_sps30.ino @@ -1,7 +1,7 @@ /* xsns_44_sps30.ino - Sensirion SPS30 support for Tasmota - Copyright (C) 2020 Gerhard Mutz and Theo Arends + Copyright (C) 2021 Gerhard Mutz and 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 diff --git a/tasmota/xsns_45_vl53l0x.ino b/tasmota/xsns_45_vl53l0x.ino index 623dda9a0..54c49534c 100644 --- a/tasmota/xsns_45_vl53l0x.ino +++ b/tasmota/xsns_45_vl53l0x.ino @@ -1,7 +1,7 @@ /* xsns_45_vl53l0x.ino - VL53L0X time of flight sensor support for Tasmota - Copyright (C) 2020 Theo Arends and Gerhard Mutz + Copyright (C) 2021 Theo Arends and Gerhard Mutz 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 diff --git a/tasmota/xsns_46_MLX90614.ino b/tasmota/xsns_46_MLX90614.ino index 54e27f359..8032cdf2f 100644 --- a/tasmota/xsns_46_MLX90614.ino +++ b/tasmota/xsns_46_MLX90614.ino @@ -1,7 +1,7 @@ /* xsns_46_MLX90614.ino - Support for MLX ir temperature sensor - Copyright (C) 2020 Gerhard Mutz and Theo Arends + Copyright (C) 2021 Gerhard Mutz and 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 diff --git a/tasmota/xsns_47_max31865.ino b/tasmota/xsns_47_max31865.ino index 4c45af4fe..83bef5e9a 100644 --- a/tasmota/xsns_47_max31865.ino +++ b/tasmota/xsns_47_max31865.ino @@ -1,7 +1,7 @@ /* xsns_39_MAX31865.ino - MAX31865 thermocouple sensor support for Tasmota - Copyright (C) 2020 Alberto Lopez Siemens + Copyright (C) 2021 Alberto Lopez Siemens 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 diff --git a/tasmota/xsns_48_chirp.ino b/tasmota/xsns_48_chirp.ino index ded5b30e6..1e92d6c79 100644 --- a/tasmota/xsns_48_chirp.ino +++ b/tasmota/xsns_48_chirp.ino @@ -1,7 +1,7 @@ /* xsns_48_chirp.ino - soil moisture sensor support for Tasmota - Copyright (C) 2020 Theo Arends & Christian Baars + Copyright (C) 2021 Theo Arends & Christian Baars 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 diff --git a/tasmota/xsns_50_paj7620.ino b/tasmota/xsns_50_paj7620.ino index ad5ce5a2c..174febc7d 100644 --- a/tasmota/xsns_50_paj7620.ino +++ b/tasmota/xsns_50_paj7620.ino @@ -1,7 +1,7 @@ /* xsns_50_paj7620.ino - gesture sensor support for Tasmota - Copyright (C) 2020 Theo Arends & Christian Baars + Copyright (C) 2021 Theo Arends & Christian Baars 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 diff --git a/tasmota/xsns_51_rdm6300.ino b/tasmota/xsns_51_rdm6300.ino index ebc9ab175..a277e7d65 100644 --- a/tasmota/xsns_51_rdm6300.ino +++ b/tasmota/xsns_51_rdm6300.ino @@ -1,7 +1,7 @@ /* xsns_51_rdm6300.ino - Support for RDM630(0) 125kHz NFC Tag Reader on Tasmota - Copyright (C) 2020 Gerhard Mutz and Theo Arends + Copyright (C) 2021 Gerhard Mutz and 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 diff --git a/tasmota/xsns_52_ibeacon.ino b/tasmota/xsns_52_ibeacon.ino index db5c5951e..731189827 100755 --- a/tasmota/xsns_52_ibeacon.ino +++ b/tasmota/xsns_52_ibeacon.ino @@ -1,7 +1,7 @@ /* xsns_52_ibeacon.ino - Support for HM17 BLE Module + ibeacon reader on Tasmota - Copyright (C) 2020 Gerhard Mutz and Theo Arends + Copyright (C) 2021 Gerhard Mutz and 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 diff --git a/tasmota/xsns_53_sml.ino b/tasmota/xsns_53_sml.ino index cccfde736..7792de29b 100755 --- a/tasmota/xsns_53_sml.ino +++ b/tasmota/xsns_53_sml.ino @@ -4,7 +4,7 @@ Created by Gerhard Mutz on 07.10.11. adapted for Tasmota - Copyright (C) 2020 Gerhard Mutz and Theo Arends + Copyright (C) 2021 Gerhard Mutz and 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 @@ -824,7 +824,7 @@ void Dump2log(void) { int16_t index=0,hcnt=0; uint32_t d_lastms; uint8_t dchars[16]; - char log_data[LOGSZ]; // May be a lot smaller... + char log_data[128]; //if (!SML_SAVAILABLE) return; diff --git a/tasmota/xsns_54_ina226.ino b/tasmota/xsns_54_ina226.ino index 49a6b5890..f89d799e9 100644 --- a/tasmota/xsns_54_ina226.ino +++ b/tasmota/xsns_54_ina226.ino @@ -1,7 +1,7 @@ /* xsns_54_ina226.ino - INA226 Current Sensor support for Tasmota - Copyright (C) 2020 Stephen Rodgers and Theo Arends + Copyright (C) 2021 Stephen Rodgers and 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 diff --git a/tasmota/xsns_55_hih_series.ino b/tasmota/xsns_55_hih_series.ino index 89278e432..d42ec8a4b 100644 --- a/tasmota/xsns_55_hih_series.ino +++ b/tasmota/xsns_55_hih_series.ino @@ -1,7 +1,7 @@ /* xsns_55_hih_series.ino - Honeywell HIH series temperature and humidity sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xsns_56_hpma.ino b/tasmota/xsns_56_hpma.ino index 576cf19d2..c400fba1e 100644 --- a/tasmota/xsns_56_hpma.ino +++ b/tasmota/xsns_56_hpma.ino @@ -1,8 +1,8 @@ /* xsns_56_hpma.ino - Honeywell HPMA115S0 particle concentration sensor support for Tasmota - Copyright (C) 2020 Theo Arends - Copyright (C) 2020 David Hunt + Copyright (C) 2021 Theo Arends + Copyright (C) 2021 David Hunt 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 diff --git a/tasmota/xsns_57_tsl2591.ino b/tasmota/xsns_57_tsl2591.ino index 395b69b23..1ec7a6838 100644 --- a/tasmota/xsns_57_tsl2591.ino +++ b/tasmota/xsns_57_tsl2591.ino @@ -1,7 +1,7 @@ /* xsns_57_tsl2591.ino - TSL2591 light sensor support for Tasmota - Copyright (C) 2020 Markus Bösling and Theo Arends + Copyright (C) 2021 Markus Bösling and 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 diff --git a/tasmota/xsns_58_dht12.ino b/tasmota/xsns_58_dht12.ino index a772e3cea..4bab87bb3 100644 --- a/tasmota/xsns_58_dht12.ino +++ b/tasmota/xsns_58_dht12.ino @@ -1,7 +1,7 @@ /* xsns_58_dht12.ino - DHT12 I2C temperature and humidity sensor support for Tasmota - Copyright (C) 2020 Stefan Oskamp and Theo Arends + Copyright (C) 2021 Stefan Oskamp and 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 diff --git a/tasmota/xsns_59_ds1624.ino b/tasmota/xsns_59_ds1624.ino index 12189164e..ccc079f4c 100644 --- a/tasmota/xsns_59_ds1624.ino +++ b/tasmota/xsns_59_ds1624.ino @@ -1,7 +1,7 @@ /* xsns_59_ds1624.ino - Support for I2C DS1624 Temperature Sensor - Copyright (C) 2020 Leonid Myravjev + Copyright (C) 2021 Leonid Myravjev 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 diff --git a/tasmota/xsns_60_GPS.ino b/tasmota/xsns_60_GPS.ino index 63fc147f2..10e02efc2 100644 --- a/tasmota/xsns_60_GPS.ino +++ b/tasmota/xsns_60_GPS.ino @@ -1,7 +1,7 @@ /* xsns_60_GPS.ino - GPS UBLOX support for Tasmota - Copyright (C) 2020 Theo Arends, Christian Baars and Adrian Scillato + Copyright (C) 2021 Theo Arends, Christian Baars and Adrian Scillato 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 diff --git a/tasmota/xsns_61_MI_NRF24.ino b/tasmota/xsns_61_MI_NRF24.ino index 4c243d4dc..8dff44920 100644 --- a/tasmota/xsns_61_MI_NRF24.ino +++ b/tasmota/xsns_61_MI_NRF24.ino @@ -1,7 +1,7 @@ /* xsns_61_MI_NRF24.ino - MI-BLE-sensors via nrf24l01 support for Tasmota - Copyright (C) 2020 Christian Baars and Theo Arends + Copyright (C) 2021 Christian Baars and 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 @@ -409,14 +409,18 @@ static union{ /********************************************************************************************/ -void MINRFinit(void){ - MINRFinitBLE(1); +void MINRFinit(void) { + if (PinUsed(GPIO_NRF24_CS) && PinUsed(GPIO_NRF24_DC) && TasmotaGlobal.spi_enabled) { + MINRFinitBLE(1); - MINRF.option.allwaysAggregate = 1; - // MINRF.option.ignoreBogusBattery = 1; // from advertisements - MINRF.option.noSummary = 0; - MINRF.option.minimalSummary = 0; - MINRF.option.directBridgeMode = 0; + MINRF.option.allwaysAggregate = 1; + // MINRF.option.ignoreBogusBattery = 1; // from advertisements + MINRF.option.noSummary = 0; + MINRF.option.minimalSummary = 0; + MINRF.option.directBridgeMode = 0; + + AddLog_P(LOG_LEVEL_INFO, PSTR("NRF: Started")); + } } /********************************************************************************************/ @@ -431,7 +435,7 @@ void MINRFinit(void){ bool MINRFinitBLE(uint8_t _mode) { if (MINRF.timer%1000 == 0){ // only re-init every 20 seconds - NRF24radio.begin(Pin(GPIO_SPI_CS),Pin(GPIO_SPI_DC)); + NRF24radio.begin(Pin(GPIO_NRF24_CS),Pin(GPIO_NRF24_DC)); NRF24radio.setAutoAck(false); NRF24radio.setDataRate(RF24_1MBPS); NRF24radio.disableCRC(); @@ -1958,7 +1962,6 @@ bool Xsns61(uint8_t function) switch (function) { case FUNC_INIT: MINRFinit(); - AddLog_P(LOG_LEVEL_INFO,PSTR("NRF: started")); break; case FUNC_EVERY_50_MSECOND: MINRF_EVERY_50_MSECOND(); diff --git a/tasmota/xsns_62_MI_ESP32.ino b/tasmota/xsns_62_MI_ESP32.ino index 44094140e..9e9c70dc5 100644 --- a/tasmota/xsns_62_MI_ESP32.ino +++ b/tasmota/xsns_62_MI_ESP32.ino @@ -1,7 +1,7 @@ /* xsns_62_MI_ESP32.ino - MI-BLE-sensors via ESP32 support for Tasmota - Copyright (C) 2020 Christian Baars and Theo Arends + Copyright (C) 2021 Christian Baars and 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 @@ -1634,7 +1634,7 @@ bool MI32isInBlockList(uint8_t* MAC){ void MI32removeMIBLEsensor(uint8_t* MAC){ MIBLEsensors.erase( std::remove_if( MIBLEsensors.begin() , MIBLEsensors.end(), [MAC]( mi_sensor_t _sensor )->bool - { return (memcmp(_sensor.MAC,MAC,6) == 0); } + { return (memcmp(_sensor.MAC,MAC,6) == 0); } ), end( MIBLEsensors ) ); } /***********************************************************************\ @@ -1930,7 +1930,7 @@ void CmndMi32Block(void){ break; case 1: ResponseCmndIdxChar(PSTR("show block list")); - break; + break; } } else { @@ -1939,7 +1939,7 @@ void CmndMi32Block(void){ switch (XdrvMailbox.index) { case 0: MIBLEBlockList.erase( std::remove_if( begin( MIBLEBlockList ), end( MIBLEBlockList ), [_MACasBytes]( MAC_t& _entry )->bool - { return (memcmp(_entry.buf,_MACasBytes.buf,6) == 0); } + { return (memcmp(_entry.buf,_MACasBytes.buf,6) == 0); } ), end( MIBLEBlockList ) ); ResponseCmndIdxChar(PSTR("MAC not blocked anymore")); break; @@ -1956,7 +1956,7 @@ void CmndMi32Block(void){ MI32removeMIBLEsensor(_MACasBytes.buf); } // AddLog_P(LOG_LEVEL_INFO,PSTR("MI32: size of ilist: %u"), MIBLEBlockList.size()); - break; + break; } } MI32.mode.shallShowBlockList = 1; diff --git a/tasmota/xsns_62_MI_HM10.ino b/tasmota/xsns_62_MI_HM10.ino index da28d7306..af3ce56ca 100644 --- a/tasmota/xsns_62_MI_HM10.ino +++ b/tasmota/xsns_62_MI_HM10.ino @@ -1,7 +1,7 @@ /* xsns_62_MI_HM10.ino - MI-BLE-sensors via HM-10 support for Tasmota - Copyright (C) 2020 Christian Baars and Theo Arends + Copyright (C) 2021 Christian Baars and 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 @@ -1085,7 +1085,7 @@ bool HM10isInBlockList(uint8_t* MAC){ void HM10removeMIBLEsensor(uint8_t* MAC){ MIBLEsensors.erase( std::remove_if( MIBLEsensors.begin() , MIBLEsensors.end(), [MAC]( mi_sensor_t _sensor )->bool - { return (memcmp(_sensor.MAC,MAC,6) == 0); } + { return (memcmp(_sensor.MAC,MAC,6) == 0); } ), end( MIBLEsensors ) ); } /*********************************************************************************************\ @@ -1693,7 +1693,7 @@ void CmndHM10Block(void){ break; case 1: ResponseCmndIdxChar(PSTR("show block list")); - break; + break; } } else { @@ -1702,7 +1702,7 @@ void CmndHM10Block(void){ switch (XdrvMailbox.index) { case 0: MIBLEBlockList.erase( std::remove_if( begin( MIBLEBlockList ), end( MIBLEBlockList ), [_MACasBytes]( MAC_t& _entry )->bool - { return (memcmp(_entry.buf,_MACasBytes.buf,6) == 0); } + { return (memcmp(_entry.buf,_MACasBytes.buf,6) == 0); } ), end( MIBLEBlockList ) ); ResponseCmndIdxChar(PSTR("MAC not blocked anymore")); break; @@ -1719,7 +1719,7 @@ void CmndHM10Block(void){ HM10removeMIBLEsensor(_MACasBytes.buf); } // AddLog_P(LOG_LEVEL_INFO,PSTR("HM10: size of ilist: %u"), MIBLEBlockList.size()); - break; + break; } } HM10.mode.shallShowBlockList = 1; diff --git a/tasmota/xsns_63_aht1x.ino b/tasmota/xsns_63_aht1x.ino index cba95662a..88da71890 100644 --- a/tasmota/xsns_63_aht1x.ino +++ b/tasmota/xsns_63_aht1x.ino @@ -1,7 +1,7 @@ /* xsns_63_AHT1x.ino - AHT10 I2C temperature and humidity sensor support for Tasmota - Copyright (C) 2020 Martin Wagner + Copyright (C) 2021 Martin Wagner 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 diff --git a/tasmota/xsns_64_hrxl.ino b/tasmota/xsns_64_hrxl.ino index 389197e1a..be78b49ec 100644 --- a/tasmota/xsns_64_hrxl.ino +++ b/tasmota/xsns_64_hrxl.ino @@ -1,7 +1,7 @@ /* xsns_64_hrxl.ino - MaxBotix HRXL serial interface - Copyright (C) 2020 Jon Little + Copyright (C) 2021 Jon Little 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 diff --git a/tasmota/xsns_65_hdc1080.ino b/tasmota/xsns_65_hdc1080.ino index ac6a71be8..d20241ab8 100644 --- a/tasmota/xsns_65_hdc1080.ino +++ b/tasmota/xsns_65_hdc1080.ino @@ -1,7 +1,7 @@ /* xsns_65_hdc1080.ino - Texas Instruments HDC1080 temperature and humidity sensor support for Tasmota - Copyright (C) 2020 Luis Teixeira + Copyright (C) 2021 Luis Teixeira 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 diff --git a/tasmota/xsns_66_iAQ.ino b/tasmota/xsns_66_iAQ.ino index 962480748..fc3dff2da 100644 --- a/tasmota/xsns_66_iAQ.ino +++ b/tasmota/xsns_66_iAQ.ino @@ -1,7 +1,7 @@ /* xsns_66_iAQ.ino - Support for iAQ-Core - Indoor Air Quality Sensor Module - Copyright (C) 2020 Christian Baars and Theo Arends + Copyright (C) 2021 Christian Baars and 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 diff --git a/tasmota/xsns_67_as3935.ino b/tasmota/xsns_67_as3935.ino index a625163b6..030581768 100644 --- a/tasmota/xsns_67_as3935.ino +++ b/tasmota/xsns_67_as3935.ino @@ -1,7 +1,7 @@ /* xsns_67_as3935.ino - AS3935 Franklin Lightning Sensor support for Tasmota - Copyright (C) 2020 Martin Wagner + Copyright (C) 2021 Martin Wagner 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 diff --git a/tasmota/xsns_68_windmeter.ino b/tasmota/xsns_68_windmeter.ino index a5b2aa49e..6b552ee38 100644 --- a/tasmota/xsns_68_windmeter.ino +++ b/tasmota/xsns_68_windmeter.ino @@ -1,7 +1,7 @@ /* xsns_68_windmeter.ino - Analog wind sensor support for Tasmota - Copyright (C) 2020 Matteo Albinola + Copyright (C) 2021 Matteo Albinola (inspired by great works of Thomas Eckerstorfer, Norbert Richter, Maarten Damen and Theo Arends) This program is free software: you can redistribute it and/or modify diff --git a/tasmota/xsns_69_opentherm.ino b/tasmota/xsns_69_opentherm.ino index 41f3377b7..adcef07b0 100644 --- a/tasmota/xsns_69_opentherm.ino +++ b/tasmota/xsns_69_opentherm.ino @@ -1,7 +1,7 @@ /* xsns_69_opentherm.ino - OpenTherm protocol support for Tasmota - Copyright (C) 2020 Yuriy Sannikov + Copyright (C) 2021 Yuriy Sannikov 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 @@ -35,7 +35,7 @@ // Seconds before OT will make an attempt to connect to the boiler after connection error #define SNS_OT_DISCONNECT_COOLDOWN_SECONDS 4 -// Number of consecutive timeouts which are accepted before entering disconnect state +// Number of consecutive timeouts which are accepted before entering disconnect state #define SNS_OT_MAX_TIMEOUTS_BEFORE_DISCONNECT 3 // Count of the OpenThermSettingsFlags diff --git a/tasmota/xsns_69_opentherm_protocol.ino b/tasmota/xsns_69_opentherm_protocol.ino index 6311b818b..6158be9c7 100644 --- a/tasmota/xsns_69_opentherm_protocol.ino +++ b/tasmota/xsns_69_opentherm_protocol.ino @@ -1,7 +1,7 @@ /* xsns_69_opentherm_protocol.ino - OpenTherm protocol support for Tasmota - Copyright (C) 2020 Yuriy Sannikov + Copyright (C) 2021 Yuriy Sannikov 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 diff --git a/tasmota/xsns_70_veml6075.ino b/tasmota/xsns_70_veml6075.ino index 4735d1140..449ec89ec 100644 --- a/tasmota/xsns_70_veml6075.ino +++ b/tasmota/xsns_70_veml6075.ino @@ -1,7 +1,7 @@ /* xsns_70_veml6075.ino - VEML6075 UVA/UVB/UVINDEX Sensor support for Tasmota - Copyright (C) 2020 Martin Wagner + Copyright (C) 2021 Martin Wagner 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 diff --git a/tasmota/xsns_71_veml7700.ino b/tasmota/xsns_71_veml7700.ino index 655d52992..a4bf12905 100644 --- a/tasmota/xsns_71_veml7700.ino +++ b/tasmota/xsns_71_veml7700.ino @@ -1,7 +1,7 @@ /* xsns_71_VEML7700.ino - VEML7700 Ambient light intensity Sensor support for Tasmota - Copyright (C) 2020 Martin Wagner + Copyright (C) 2021 Martin Wagner 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 diff --git a/tasmota/xsns_72_mcp9808.ino b/tasmota/xsns_72_mcp9808.ino index 587123d2c..98fc48066 100644 --- a/tasmota/xsns_72_mcp9808.ino +++ b/tasmota/xsns_72_mcp9808.ino @@ -1,7 +1,7 @@ /* xsns_72_mcp9808 - MCP9808 I2C temperature sensor support for Tasmota - Copyright (C) 2020 Martin Wagner and Theo Arends + Copyright (C) 2021 Martin Wagner and 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 diff --git a/tasmota/xsns_73_hp303b.ino b/tasmota/xsns_73_hp303b.ino index 30a14945c..50589e4d5 100644 --- a/tasmota/xsns_73_hp303b.ino +++ b/tasmota/xsns_73_hp303b.ino @@ -1,7 +1,7 @@ /* xsns_72_hp303b.ino - HP303B digital barometric air pressure sensor support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xsns_74_lmt01.ino b/tasmota/xsns_74_lmt01.ino index 85d97a492..8c6cfdb92 100644 --- a/tasmota/xsns_74_lmt01.ino +++ b/tasmota/xsns_74_lmt01.ino @@ -1,7 +1,7 @@ /* xns_74_lmt01.ino - Support for single wire LMT01 Temperature Sensor - Copyright (C) 2020 Theo Arends, Justifiably + Copyright (C) 2021 Theo Arends, Justifiably 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 diff --git a/tasmota/xsns_75_prometheus.ino b/tasmota/xsns_75_prometheus.ino index b6afd3f70..0dac5ed9f 100644 --- a/tasmota/xsns_75_prometheus.ino +++ b/tasmota/xsns_75_prometheus.ino @@ -1,7 +1,7 @@ /* xsns_75_prometheus.ino - Web based information for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tasmota/xsns_76_dyp.ino b/tasmota/xsns_76_dyp.ino index adfaef5bc..0c4506502 100644 --- a/tasmota/xsns_76_dyp.ino +++ b/tasmota/xsns_76_dyp.ino @@ -1,7 +1,7 @@ /* xsns_76_dyp.ino - DYP ME007 serial interface - Copyright (C) 2020 Janusz Kostorz + Copyright (C) 2021 Janusz Kostorz 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 diff --git a/tasmota/xsns_77_vl53l1x.ino b/tasmota/xsns_77_vl53l1x.ino index 23be88a69..f245fda86 100644 --- a/tasmota/xsns_77_vl53l1x.ino +++ b/tasmota/xsns_77_vl53l1x.ino @@ -1,7 +1,7 @@ /* xsns_77_vl53l1x.ino - VL53L1X sensor support for Tasmota - Copyright (C) 2020 Theo Arends, Rui Marinho and Johann Obermeier + Copyright (C) 2021 Theo Arends, Rui Marinho and Johann Obermeier 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 diff --git a/tasmota/xsns_78_ezo.ino b/tasmota/xsns_78_ezo.ino index b8ba523ea..a33ad9cdc 100644 --- a/tasmota/xsns_78_ezo.ino +++ b/tasmota/xsns_78_ezo.ino @@ -1,7 +1,7 @@ /* xsns_78_ezo.ino - EZO modules base class - Copyright (C) 2020 Christopher Tremblay + Copyright (C) 2021 Christopher Tremblay 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 diff --git a/tasmota/xsns_78_ezoco2.ino b/tasmota/xsns_78_ezoco2.ino index a7fe76cc8..8d038308a 100644 --- a/tasmota/xsns_78_ezoco2.ino +++ b/tasmota/xsns_78_ezoco2.ino @@ -1,7 +1,7 @@ /* xsns_78_ezoco2.ino - EZO CO2 I2C CO2 sensor support for Tasmota - Copyright (C) 2020 Christopher Tremblay + Copyright (C) 2021 Christopher Tremblay 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 diff --git a/tasmota/xsns_78_ezodo.ino b/tasmota/xsns_78_ezodo.ino index a0dd6a36f..8a22bceb3 100644 --- a/tasmota/xsns_78_ezodo.ino +++ b/tasmota/xsns_78_ezodo.ino @@ -1,7 +1,7 @@ /* xsns_78_ezodo.ino - EZO DO I2C DO sensor support for Tasmota - Copyright (C) 2020 Christopher Tremblay + Copyright (C) 2021 Christopher Tremblay 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 @@ -41,7 +41,7 @@ struct EZODO : public EZOStruct { if (json) { ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_DO "\":%d}" ), name, str); } -#ifdef USE_WEBSERVER +#ifdef USE_WEBSERVER else { WSContentSend_PD(HTTP_SNS_DO, name, str); #endif // USE_WEBSERVER diff --git a/tasmota/xsns_78_ezoec.ino b/tasmota/xsns_78_ezoec.ino index 1566e2907..e134e4da1 100644 --- a/tasmota/xsns_78_ezoec.ino +++ b/tasmota/xsns_78_ezoec.ino @@ -1,7 +1,7 @@ /* xsns_78_ezoec.ino - EZO EC I2C EC sensor support for Tasmota - Copyright (C) 2020 Christopher Tremblay + Copyright (C) 2021 Christopher Tremblay 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 @@ -41,7 +41,7 @@ struct EZOEC : public EZOStruct { if (json) { ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_EC "\":%s}" ), name, str); } -#ifdef USE_WEBSERVER +#ifdef USE_WEBSERVER else { WSContentSend_PD(HTTP_SNS_EC, name, str); #endif // USE_WEBSERVER diff --git a/tasmota/xsns_78_ezoflo.ino b/tasmota/xsns_78_ezoflo.ino index 31cb7c082..9b30238b9 100644 --- a/tasmota/xsns_78_ezoflo.ino +++ b/tasmota/xsns_78_ezoflo.ino @@ -1,7 +1,7 @@ /* xsns_78_ezoflo.ino - EZO FLO I2C FLO sensor support for Tasmota - Copyright (C) 2020 Christopher Tremblay + Copyright (C) 2021 Christopher Tremblay 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 diff --git a/tasmota/xsns_78_ezohum.ino b/tasmota/xsns_78_ezohum.ino index a403eeb56..04a2ce74f 100644 --- a/tasmota/xsns_78_ezohum.ino +++ b/tasmota/xsns_78_ezohum.ino @@ -1,7 +1,7 @@ /* xsns_78_ezohum.ino - EZO HUM I2C HUM sensor support for Tasmota - Copyright (C) 2020 Christopher Tremblay + Copyright (C) 2021 Christopher Tremblay 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 diff --git a/tasmota/xsns_78_ezoo2.ino b/tasmota/xsns_78_ezoo2.ino index bc98fe00c..cafdeb813 100644 --- a/tasmota/xsns_78_ezoo2.ino +++ b/tasmota/xsns_78_ezoo2.ino @@ -1,7 +1,7 @@ /* xsns_78_ezoo2.ino - EZO O2 I2C O2 sensor support for Tasmota - Copyright (C) 2020 Christopher Tremblay + Copyright (C) 2021 Christopher Tremblay 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 @@ -41,7 +41,7 @@ struct EZOO2 : public EZOStruct { if (json) { ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_O2 "\":%d}" ), name, str); } -#ifdef USE_WEBSERVER +#ifdef USE_WEBSERVER else { WSContentSend_PD(HTTP_SNS_O2, name, str); #endif // USE_WEBSERVER diff --git a/tasmota/xsns_78_ezoorp.ino b/tasmota/xsns_78_ezoorp.ino index d9faa999c..09db9983c 100644 --- a/tasmota/xsns_78_ezoorp.ino +++ b/tasmota/xsns_78_ezoorp.ino @@ -1,7 +1,7 @@ /* xsns_78_ezoorp.ino - EZO ORP I2C ORP sensor support for Tasmota - Copyright (C) 2020 Christopher Tremblay + Copyright (C) 2021 Christopher Tremblay 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 @@ -41,7 +41,7 @@ struct EZOORP : public EZOStruct { if (json) { ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ORP "\":%s}" ), name, str); } -#ifdef USE_WEBSERVER +#ifdef USE_WEBSERVER else { WSContentSend_PD(HTTP_SNS_ORP, name, str); #endif // USE_WEBSERVER diff --git a/tasmota/xsns_78_ezoph.ino b/tasmota/xsns_78_ezoph.ino index 77939d97a..c4e6a7425 100644 --- a/tasmota/xsns_78_ezoph.ino +++ b/tasmota/xsns_78_ezoph.ino @@ -1,7 +1,7 @@ /* xsns_78_ezoph.ino - EZO pH I2C pH sensor support for Tasmota - Copyright (C) 2020 Christopher Tremblay + Copyright (C) 2021 Christopher Tremblay 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 @@ -41,7 +41,7 @@ struct EZOPH : public EZOStruct { if (json) { ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_PH "\":%s}" ), name, str); } -#ifdef USE_WEBSERVER +#ifdef USE_WEBSERVER else { WSContentSend_PD(HTTP_SNS_PH, name, str); #endif // USE_WEBSERVER diff --git a/tasmota/xsns_78_ezopmp.ino b/tasmota/xsns_78_ezopmp.ino index cea7a9cf0..225c3285f 100644 --- a/tasmota/xsns_78_ezopmp.ino +++ b/tasmota/xsns_78_ezopmp.ino @@ -1,7 +1,7 @@ /* xsns_78_ezopmp.ino - EZO PMP I2C PMP sensor support for Tasmota - Copyright (C) 2020 Christopher Tremblay + Copyright (C) 2021 Christopher Tremblay 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 diff --git a/tasmota/xsns_78_ezoprs.ino b/tasmota/xsns_78_ezoprs.ino index 9ad34ab0d..f80eba82e 100644 --- a/tasmota/xsns_78_ezoprs.ino +++ b/tasmota/xsns_78_ezoprs.ino @@ -1,7 +1,7 @@ /* xsns_78_ezoprs.ino - EZO PRS I2C PRS sensor support for Tasmota - Copyright (C) 2020 Christopher Tremblay + Copyright (C) 2021 Christopher Tremblay 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 @@ -47,7 +47,7 @@ struct EZOPRS : public EZOStruct { } ResponseJsonEnd(); } -#ifdef USE_WEBSERVER +#ifdef USE_WEBSERVER else { WSContentSend_PD(HTTP_SNS_PRESSURE, name, str, PressureUnit().c_str()); if (Settings.altitude != 0) { diff --git a/tasmota/xsns_78_ezorgb.ino b/tasmota/xsns_78_ezorgb.ino index 5bbb49d79..2bbab0d24 100644 --- a/tasmota/xsns_78_ezorgb.ino +++ b/tasmota/xsns_78_ezorgb.ino @@ -1,7 +1,7 @@ /* xsns_78_ezorgb.ino - EZO RGB I2C RGB sensor support for Tasmota - Copyright (C) 2020 Christopher Tremblay + Copyright (C) 2021 Christopher Tremblay 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 diff --git a/tasmota/xsns_78_ezortd.ino b/tasmota/xsns_78_ezortd.ino index 1d564d095..cf731a346 100644 --- a/tasmota/xsns_78_ezortd.ino +++ b/tasmota/xsns_78_ezortd.ino @@ -1,7 +1,7 @@ /* xsns_78_ezortd.ino - EZO RTD I2C RTD sensor support for Tasmota - Copyright (C) 2020 Christopher Tremblay + Copyright (C) 2021 Christopher Tremblay 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 @@ -41,7 +41,7 @@ struct EZORTD : public EZOStruct { if (json) { ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"), name, str); } -#ifdef USE_WEBSERVER +#ifdef USE_WEBSERVER else { WSContentSend_PD(HTTP_SNS_TEMP, name, str, TempUnit()); #endif // USE_WEBSERVER diff --git a/tasmota/xsns_78_xezo.ino b/tasmota/xsns_78_xezo.ino index 2774c7a0c..60b3cd8e4 100644 --- a/tasmota/xsns_78_xezo.ino +++ b/tasmota/xsns_78_xezo.ino @@ -1,7 +1,7 @@ /* xsns_78_xezo.ino - EZO family I2C driver support for Tasmota - Copyright (C) 2020 Christopher Tremblay + Copyright (C) 2021 Christopher Tremblay 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 diff --git a/tasmota/xsns_79_as608.ino b/tasmota/xsns_79_as608.ino index f4e7d3939..7bff7736c 100644 --- a/tasmota/xsns_79_as608.ino +++ b/tasmota/xsns_79_as608.ino @@ -1,7 +1,7 @@ /* xsns_79_as608.ino - AS608 and R503 fingerprint sensor support for Tasmota - Copyright (C) 2020 boaschti and Theo Arends + Copyright (C) 2021 boaschti and 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 diff --git a/tasmota/xsns_80_mfrc522.ino b/tasmota/xsns_80_mfrc522.ino index 2c970119f..9a9b19e21 100644 --- a/tasmota/xsns_80_mfrc522.ino +++ b/tasmota/xsns_80_mfrc522.ino @@ -1,7 +1,7 @@ /* xsns_80_mfrc522.ino - Support for MFRC522 (SPI) NFC Tag Reader on Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 @@ -17,6 +17,7 @@ along with this program. If not, see . */ +#ifdef USE_SPI #ifdef USE_RC522 /*********************************************************************************************\ * MFRC522 - 13.56 MHz RFID reader @@ -97,8 +98,8 @@ void RC522ScanForTag(void) { } void RC522Init(void) { - if (PinUsed(GPIO_SPI_CS) && PinUsed(GPIO_RC522_RST)) { - Mfrc522 = new MFRC522(Pin(GPIO_SPI_CS), Pin(GPIO_RC522_RST)); + if (PinUsed(GPIO_RC522_CS) && PinUsed(GPIO_RC522_RST) && TasmotaGlobal.spi_enabled) { + Mfrc522 = new MFRC522(Pin(GPIO_RC522_CS), Pin(GPIO_RC522_RST)); SPI.begin(); Mfrc522->PCD_Init(); // if (Mfrc522->PCD_PerformSelfTest()) { // Saves 0k5 code @@ -155,3 +156,4 @@ bool Xsns80(uint8_t function) { } #endif // USE_RC522 +#endif // USE_SPI diff --git a/tasmota/xsns_interface.ino b/tasmota/xsns_interface.ino index fd05ccc57..21918f22c 100644 --- a/tasmota/xsns_interface.ino +++ b/tasmota/xsns_interface.ino @@ -1,7 +1,7 @@ /* xsns_interface.ino - Sensor interface support for Tasmota - Copyright (C) 2020 Theo Arends inspired by ESPEasy + Copyright (C) 2021 Theo Arends inspired by ESPEasy 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 diff --git a/tasmota/xx2c_interface.ino b/tasmota/xx2c_interface.ino index 5732fbaf9..fcbc17677 100644 --- a/tasmota/xx2c_interface.ino +++ b/tasmota/xx2c_interface.ino @@ -1,7 +1,7 @@ /* xx2c_interface.ino - I2c interface support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tools/Esptool/Odroid_go/Odroid_flash.bat b/tools/Esptool/Odroid_go/Odroid_flash.bat new file mode 100644 index 000000000..2ce84284f --- /dev/null +++ b/tools/Esptool/Odroid_go/Odroid_flash.bat @@ -0,0 +1 @@ +esptool.py --chip esp32 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dout --flash_freq 40m --flash_size detect 0x1000 bootloader_dout_40m.bin 0x8000 partitions_ffat_12M.bin 0xe000 boot_app0.bin 0x10000 tasmota32-odroid.bin \ No newline at end of file diff --git a/tools/Esptool/Odroid_go/boot_app0.bin b/tools/Esptool/Odroid_go/boot_app0.bin new file mode 100644 index 000000000..13562cabb Binary files /dev/null and b/tools/Esptool/Odroid_go/boot_app0.bin differ diff --git a/tools/Esptool/Odroid_go/bootloader_dout_40m.bin b/tools/Esptool/Odroid_go/bootloader_dout_40m.bin new file mode 100644 index 000000000..267abf3da Binary files /dev/null and b/tools/Esptool/Odroid_go/bootloader_dout_40m.bin differ diff --git a/tools/Esptool/Odroid_go/partitions_ffat_12M.bin b/tools/Esptool/Odroid_go/partitions_ffat_12M.bin new file mode 100644 index 000000000..4389fdc62 Binary files /dev/null and b/tools/Esptool/Odroid_go/partitions_ffat_12M.bin differ diff --git a/tools/decode-status.py b/tools/decode-status.py index 678cf5a73..ba5ead287 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -3,7 +3,7 @@ """ decode-status.py - decode status for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 @@ -239,9 +239,9 @@ a_features = [[ "USE_EZOORP","USE_EZORTD","USE_EZOHUM","USE_EZOEC", "USE_EZOCO2","USE_EZOO2","USE_EZOPRS","USE_EZOFLO", "USE_EZODO","USE_EZORGB","USE_EZOPMP","USE_AS608", - "USE_SHELLY_DIMMER","USE_RC522","USE_FTC532","", - "","","","", - "","","","", + "USE_SHELLY_DIMMER","USE_RC522","USE_FTC532","USE_DISPLAY_EPAPER_42", + "USE_DISPLAY_ILI9488","USE_DISPLAY_SSD1351","USE_DISPLAY_RA8876","USE_DISPLAY_ST7789", + "USE_DISPLAY_SSD1331","","","", "","","","", "","","","" ]] diff --git a/tools/serial-plotter.py b/tools/serial-plotter.py index 83ec6dba6..2e08e2c62 100644 --- a/tools/serial-plotter.py +++ b/tools/serial-plotter.py @@ -3,7 +3,7 @@ """ serial-plotter.py - for Tasmota - Copyright (C) 2020 Christian Baars + Copyright (C) 2021 Christian Baars 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 @@ -189,4 +189,3 @@ text_box.on_submit(submit) if ser.is_open==True: plt.show() - \ No newline at end of file diff --git a/tools/templates/templates.py b/tools/templates/templates.py index 5387ceaaa..5a6cea513 100644 --- a/tools/templates/templates.py +++ b/tools/templates/templates.py @@ -3,7 +3,7 @@ """ templates.py - template beautify TEMPLATES.md for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2021 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 diff --git a/tools/unishox/compress-html-uncompressed.py b/tools/unishox/compress-html-uncompressed.py new file mode 100644 index 000000000..7ee15091d --- /dev/null +++ b/tools/unishox/compress-html-uncompressed.py @@ -0,0 +1,150 @@ +############################################################### +# compresses all files found in ..\..\tasmota\html_uncompressed +# write compressed C code to ..\..\tasmota\html_compressed +# Instructions: +# open a console, e.g. in vscode, open a 'terminal' +# cd .\tools\unishox +# run: +# python compress-html-uncompressed.py +# +# The intent it to commit both uncompressed and compressed to the repo +# else this script would need to be run at build. +# +# Example Tasmota code: +# #ifdef USE_UNISHOX_COMPRESSION +# #include "./html_compressed/HTTP_SCRIPT_CONSOL.h" +# #else +# #include "./html_uncompressed/HTTP_SCRIPT_CONSOL.h" +# #endif +# +############################################################### + +import unishox +from os import listdir +from datetime import datetime + + +files = listdir('..\\..\\tasmota\\html_uncompressed') + +totalIn = 0 +totalSaved = 0 + +for file in files: + f = open('..\\..\\tasmota\\html_uncompressed\\' + file, "r") + text = f.read() + f.close() + + #text = Tk().clipboard_get() + # print(text) + + # parsing and cleaning + text_list = text.splitlines() + text = '' #just reuse the string + const_name = '' #default if no name will be found + + line_number = 0 + for line in text_list: + pos = line.find("const char") + # print(pos, line) + if pos > -1: + line_list = line.rsplit(" ") + for el in line_list: + if el.find('[]') > -1: + const_name = el[:-2] #extract the "const char" variable name + line_list.pop(line_number) + else: # remove line comments + line_el = line.rsplit("//") + # print('Splitted line list by //' % line_el) + # print(line_el[0]) + text = text + line_el[0] + line_number = line_number +1 + + # print const_name + # print text + + #remove unwanted quotation marks + qm = [] + pos =0 + last_char = "" + for char in text: + if char == "\"": + if last_char != "\\": + qm.append(pos) #find all quotation marks without preceding backslash + last_char = char + pos = pos + 1 + # print(qm) + lastel = 0 + input = "" + for pos in qm: + sub = text[lastel+1:pos:] + if not sub.isspace() and pos-lastel > 1: + # print(lastel, pos) + input = input + sub #only copy substrings that are not whitespace + # print(text[lastel+1:pos:]) + lastel = pos + + print("####### Parsing input from "+'..\\..\\tasmota\\html_uncompressed\\' + file) + print(" Const char name: "+const_name) + #print('####### Cleaned input:') + #print(input) + + #construct output (taken from shadinger) + input = input.replace("\\t", "\t") + input = input.replace("\\n", "\n") + input = input.replace("\\r", "\r") + input = input.replace("\\f", "\f") + input = input.replace("\\b", "\b") + input = input.replace("\\\"", u"\u0022") + + in_bytes = bytearray(input, 'utf-8') + in_len = len(in_bytes) + out_bytes = bytearray(in_len * 2) + + UNISHOX = unishox.Unishox() + out_len = UNISHOX.compress(in_bytes, len(in_bytes), out_bytes, len(out_bytes)) + print(" ####### Compression result:") + print(" Compressed from {i} to {o}, -{p:.1f}%".format(i=in_len, o=out_len, p=(100-(float(out_len)/float(in_len)*100)))) + out_bytes = out_bytes[:out_len] # truncate to right size + + #PROGMEM is growing in steps 0,8,24,40,56,... bytes of data resulting in size of 0,16,32,48,64,... bytes + for in_real in range(8,in_len+16,16): + if in_real>=in_len: + print(" Old real PROGMEM-size:"+str(in_real+8)+"(unused bytes:"+str(in_real-in_len)+")") + break + for out_real in range(8,out_len+16,16): + if out_real>=out_len: + print(" New real PROGMEM-size:"+str(out_real+8)+"(unused bytes:"+str(out_real-out_len)+")") + break + print(" the optimal case would be raw bytes + 8, real difference: "+str(in_real - out_real)+ "bytes") + # https://www.geeksforgeeks.org/break-list-chunks-size-n-python/ + def chunked(my_list, n): + return [my_list[i * n:(i + 1) * n] for i in range((len(my_list) + n - 1) // n )] + + # split in chunks of 20 characters + chunks = chunked(out_bytes, 20) + + lines_raw = [ "\"\\x" + "\\x".join( [ '{:02X}'.format(b) for b in chunk ] ) + "\"" for chunk in chunks ] + line_complete = "const char " + const_name + "_COMPRESSED" +"[] PROGMEM = " + ("\n" + " "*29).join(lines_raw) + ";" + lines = "\nconst size_t " + const_name +"_SIZE = {size};\n{lines}\n\n".format(size=in_len, lines=line_complete) + + #print('####### Final output:') + #print(lines) + + definition = "#define " + const_name + " Decompress(" + const_name + "_COMPRESSED" + "," + const_name +"_SIZE" + ").c_str()" + #print(definition) + + now = datetime.now() # current date and time + percent = int((float(out_real)/float(in_real))*100.0) + saving = in_real - out_real + totalIn = totalIn + in_real + totalSaved = totalSaved + saving + comment = "/////////////////////////////////////////////////////////////////////\n" + comment = comment + "// compressed by tools/unishox/compress-html-uncompressed.py\n" + comment = comment + "/////////////////////////////////////////////////////////////////////\n" + + f = open('..\\..\\tasmota\\html_compressed\\' + file, "w") + f.write(comment + lines + definition) + f.close() + print("####### Wrote output to "+'..\\..\\tasmota\\html_compressed\\' + file) + +print("If all files are in use, total saving was "+str(totalSaved)+" out of "+str(totalIn))