diff --git a/BUILDS.md b/BUILDS.md index e29ba5f5b..6242714e1 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -119,6 +119,8 @@ | USE_CHIRP | - | - | - | - | - | - | - | | USE_PAJ7620 | - | - | - | - | - | - | - | | USE_PCF8574 | - | - | - | - | - | - | - | +| | | | | | | | | +| Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks | USE_HIH6 | - | - | - | - | x | - | - | | USE_DHT12 | - | - | - | - | x | - | - | | USE_DS1624 | - | - | - | - | x | - | - | @@ -133,9 +135,12 @@ | USE_HP303B | - | - | - | - | - | - | - | | USE_EZOCO2 | - | - | - | - | - | - | - | | USE_EZOEC | - | - | - | - | - | - | - | +| USE_EZOFLO | - | - | - | - | - | - | - | | USE_EZOHUM | - | - | - | - | - | - | - | +| USE_EZOO2 | - | - | - | - | - | - | - | | USE_EZOORP | - | - | - | - | - | - | - | | USE_EZOPH | - | - | - | - | - | - | - | +| USE_EZOPRS | - | - | - | - | - | - | - | | USE_EZORTD | - | - | - | - | - | - | - | | | | | | | | | | | Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks diff --git a/CHANGELOG.md b/CHANGELOG.md index 06d99d492..3f795cf3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,10 +11,20 @@ All notable changes to this project will be documented in this file. ## [9.0.0.3] ### Added -- TLS in binary tasmota-zbbridge (#9620) +- TLS in binary tasmota-zbbridge (#9635) +- Support for EZO O2 sensors by Christopher Tremblay (#9619) +- Support for EZO PRS sensors by Christopher Tremblay (#9659) +- Support for EZO FLO sensors by Christopher Tremblay (#9697) +- Zigbee reduce battery drain (#9642) +- Zigbee command ``ZbMap`` to describe Zigbee topology (#9651) +- Zigbee command ``ZbOccupancy`` to configure the time-out for PIR +- Command ``Gpios 255`` to show all possible GPIO configurations +- Command ``SwitchText`` to change JSON switch names by barbudor (#9691) ### Changed - PlatformIO library structure redesigned for compilation speed by Jason2866 +- Zigbee flash storage refactor adding commands ``ZbProbe``, ``ZbStatus2`` and ``ZbRestore`` (#9641) +- Default otaurl in my_user_config.h to http://ota.tasmota.com/tasmota/release/tasmota.bin.gz ### Fixed - Rule Break not working as expected when ONCE is enabled (#9245) @@ -164,7 +174,7 @@ All notable changes to this project will be documented in this file. ### Added - Zigbee better support for IKEA Motion Sensor - ESP32 Analog input support for GPIO32 to GPIO39 -- Zigbee options to ``ZbSend`` ``Config`` and ``ReadCondig`` +- Zigbee options to ``ZbSend`` ``Config`` and ``ReadConfig`` - Command ``Restart 2`` to halt system. Needs hardware reset or power cycle to restart (#9046) - Command ``SetOption102 0/1`` to switch between Teleinfo French Metering mode, legacy 1200 bps (0) or Linky standard 9600 bps (1) diff --git a/I2CDEVICES.md b/I2CDEVICES.md index c572f50a1..57b10538c 100644 --- a/I2CDEVICES.md +++ b/I2CDEVICES.md @@ -83,3 +83,6 @@ Index | Define | Driver | Device | Address(es) | Description 55 | USE_EZOHUM | xsns_78 | EZOHUM | 0x61 - 0x70 | Humidity sensor 55 | USE_EZOEC | xsns_78 | EZOEC | 0x61 - 0x70 | Electric conductivity sensor 55 | USE_EZOCO2 | xsns_78 | EZOCO2 | 0x61 - 0x70 | CO2 sensor + 55 | USE_EZOO2 | xsns_78 | EZOO2 | 0x61 - 0x70 | O2 sensor + 55 | USE_EZOPRS | xsns_78 | EZOPRS | 0x61 - 0x70 | Pressure sensor + 55 | USE_EZOFLO | xsns_78 | EZOFLO | 0x61 - 0x70 | Flow meter sensor diff --git a/MODULES.md b/MODULES.md index dfc413b1a..8b81a8652 100644 --- a/MODULES.md +++ b/MODULES.md @@ -80,4 +80,4 @@ Module | LCode | Description 74 Sonoff D1 | x | Sonoff D1 Wifi and RF Dimmer 75 Sonoff ZbBridge | x | Sonoff Zigbee bridge -Over 1600 additional devices are supported using [templates](TEMPLATES.md). +Over 1650 additional devices are supported using [templates](TEMPLATES.md). diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 778200c95..37e7e802a 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -51,7 +51,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - **tasmota-zbbridge.bin** = The dedicated Sonoff Zigbee Bridge version. - **tasmota-minimal.bin** = The Minimal version allows intermediate OTA uploads to support larger versions and does NOT change any persistent parameter. This version **should NOT be used for initial installation**. -The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota/release for ESP8266 or http://ota.tasmota.com/tasmota32/release for ESP32. The links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmota.com/tasmota/release/tasmota.bin`` +The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota/release for ESP8266 or http://ota.tasmota.com/tasmota32/release for ESP32. The links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmota.com/tasmota/release/tasmota.bin.gz`` [List](MODULES.md) of embedded modules. @@ -59,11 +59,14 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota ## Changelog v9.1.0 Imogen ### Added +- Command ``Gpios 255`` to show all possible GPIO configurations - Command ``NoDelay`` for immediate backlog command execution by Erik Montnemery (#9544) - Command ``SwitchMode 15`` sending only MQTT message on switch change (#9593) - Command ``ShutterChange`` to increment change position (#9594) - Command ``SetOption113 1`` to set dimmer low on rotary dial after power off +- Command ``SwitchText`` to change JSON switch names by barbudor (#9691) - Zigbee command ``ZbData`` for better support of device specific data +- Zigbee command ``ZbOccupancy`` to configure the time-out for PIR - Optional support for Mitsubishi Electric HVAC by David Gwynne (#9237) - Optional support for Orno WE517-Modbus energy meter by Maxime Vincent (#9353) - SDM630 three phase ImportActive Energy display when ``#define SDM630_IMPORT`` is enabled by Janusz Kostorz (#9124) @@ -73,9 +76,10 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota - Support for analog buttons indexed within standard button range - Support for Vietnamese language translations by Tâm.NT - Support for timers in case of no-sunset permanent day by cybermaus (#9543) -- Support for EZO CO2, EC, HUM, ORP, Ph and RTD sensors by Christopher Tremblay +- Support for EZO sensors by Christopher Tremblay - Support for fixed output Hi or Lo GPIO selection - TLS in binary tasmota-zbbridge (#9620) +- Zigbee reduce battery drain (#9642) - ESP32 support for Wireless-Tag WT32-ETH01 (#9496) - ESP32 MI32 Beacon support, RSSI at TELEPERIOD, refactoring (#9609) @@ -98,6 +102,8 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota - Tasmota Arduino Core v2.7.4.5 allowing webpassword over 47 characters (#9687) - Webserver code optimizations (#9580, #9590) - PlatformIO library structure redesigned for compilation speed by Jason2866 +- Zigbee flash storage refactor adding commands ``ZbProbe``, ``ZbStatus2`` and ``ZbRestore`` (#9641) +- Default otaurl in my_user_config.h to http://ota.tasmota.com/tasmota/release/tasmota.bin.gz ### Fixed - Ledlink blink when no network connected regression from v8.3.1.4 (#9292) diff --git a/TEMPLATES.md b/TEMPLATES.md index 0d590c203..eb1e997eb 100644 --- a/TEMPLATES.md +++ b/TEMPLATES.md @@ -2,7 +2,7 @@ # Templates -Find below the available templates as of October 2020. More template information can be found in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates) +Find below the available templates as of November 2020. More template information can be found in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates) ## Aromatherapy Diffuser ``` @@ -24,6 +24,7 @@ Arlec Smart Home Hub {"NAME":"Arlec Hub","GPIO":[0,107,0,108,0,0,0,0,0,0,0,0 ## Bulb Socket ``` +Blitzwolf E27 {"NAME":"Blitzwolf BW-LT30","GPIO":[17,0,0,0,21,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} Elegant Choice E27/E26 {"NAME":"name","GPIO":[0,0,0,0,0,0,0,0,0,0,0,21,0],"FLAG":0,"BASE":18} Slampher {"NAME":"Slampher","GPIO":[17,255,0,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":9} SmartBase E0260 {"NAME":"SmartBaseE0260","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} @@ -62,11 +63,13 @@ Globe A19 10W 800lm {"NAME":"GlobeCCT","GPIO":[0,0,0,0,38,37,0,0,0,0,0,0,0] Globe G25 Edison 500lm {"NAME":"Globe 34920","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} Globe ST19 Edison 500lm {"NAME":"Globe 34919","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} Hama 806lm {"NAME":"Hama 00176550","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} +Hama 4.5W 300lm {"NAME":"Hama LED-Bulb GU10","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} Hama 4.5W 350lm {"NAME":"Hama LED-Bulb","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} Hykker SL-0392 650lm {"NAME":"Hykker 7W","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} Iotton 9W 700lm {"NAME":"Iotton Light","GPIO":[0,0,0,0,37,38,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +iView 10W 1050lm {"NAME":"iView ISB1000-D","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} Kogan 10W Cool & Warm White 1050lm {"NAME":"Kogan 10W CCT","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":48} -Kogan 4.5W 330lm 110C {"NAME":"Kogan White/Wa","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} +Kogan 4.5W 330lm 110 {"NAME":"Kogan White/Wa","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} Kogan 5W {"NAME":"Kogan Co/Wa","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} Laser 10W 1000lm {"NAME":"Laser 10W CCT","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":48} Laser 10W 1000lm {"NAME":"Laster 10W CCT","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} @@ -76,12 +79,12 @@ ledscom.de 4.5W 430lm {"NAME":"GX53","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FL Lenovo 800lm {"NAME":"LenovoLB","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} Lohas ZN051 5W 420lm {"NAME":"Lohas ZN051","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} Lohas ZN070 720lm {"NAME":"Lohas ZN070","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} +LSC A55 14W 1400lm {"NAME":"LSC CT E27","GPIO":[0,0,0,0,37,47,0,0,0,0,0,0,0],"FLAG":0,"BASE":48} Lumiman A19 7.5W 800lm {"NAME":"Lumiman LM520","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} Luminea ZX-2831 {"NAME":"Luminea CCT","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} LVWIT A60 6.5W 806lm Filament {"NAME":"LVWIT-E27-WiFi-6.5","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} LVWIT E14 Smart Wifi LED Bulb, 470Lm, 4.5W {"NAME":"LVWIT 4.5w CCT","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} -Merkury MI-BW905-999W 700lm {"NAME":"MI-BW905-999W","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} -Mimoodz A21 10.5W 1050lm {"NAME":"Mimoodz","GPIO":[0,0,0,0,21,22,0,0,23,24,25,26,27],"FLAG":0,"BASE":18} +Mimoodz A21 10.5W 1050lm {"NAME":"Mimoodz","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} Mirabella Genio 6W 500lm {"NAME":"GenioGU10","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} Mirabella Genio 9W 800lm {"NAME":"GenioBulbCCT","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} Mirabella Genio 9W 800lm {"NAME":"GenioBulbCCT","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} @@ -93,15 +96,19 @@ Nedis A60 800lm {"NAME":"WIFILW10WTE27","GPIO":[0,0,0,0,0,37,0,0,38,0,0 Nedis C10 350lm {"NAME":"WIFILW10WTE14","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} Nedis G125 5.5W 350lm Twisted Filament {"NAME":"WIFILF10GDG125","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} Nedis PAR16 330lm {"NAME":"Nedis WIFILW30","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} -Nedis PAR16 4.5W 330lm 110C {"NAME":"WIFILW30","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} +Nedis PAR16 4.5W 330lm 110 {"NAME":"WIFILW30","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} Philips Zhirui Candle 250lm {"NAME":"Xiaomi Philips","GPIO":[0,0,0,0,0,0,0,0,38,0,0,37,0],"FLAG":0,"BASE":48} Phillips Zhirui 450lm {"NAME":"Xiaomi Philips","GPIO":[0,0,0,0,0,0,0,0,38,0,0,37,0],"FLAG":0,"BASE":48} Polux ST64 5.5W 470lm {"NAME":"basic","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} +Prokord 10W 1050lm {"NAME":"PSH-E2745-CCT","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":1,"BASE":18} +Prokord 5W 1050lm {"NAME":"Prokord-PSH-GU1045-CCT","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} Shelly DUO 800lm {"NAME":"Shelly DUO","GPIO":[0,0,0,0,38,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} SmartDGM L-WT9W1 9W 800lm {"NAME":"L-WT9W1","GPIO":[0,0,0,0,0,37,0,0,9,38,0,0,0],"FLAG":0,"BASE":18} +Solimo 12W 1080lm {"NAME":"Solimo WCCT 12","GPIO":[0,0,0,0,9,37,0,0,10,38,11,0,0],"FLAG":0,"BASE":18} Spectrum Smart 5W 410lm Candle {"NAME":"lightbulb","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} Swisstone SH 330 806lm {"NAME":"SwisstoneSH330","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} -V-Tac PAR16 4.5W 300lm 110C {"NAME":"V-TAC VT-5174","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} +Treatlife A19 9W 800lm {"NAME":"Treatlife SL20","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} +V-Tac PAR16 4.5W 300lm 110 {"NAME":"V-TAC VT-5174","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} Vestaiot BR30 800lm {"NAME":"Vesta BR30 CCT","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} Wipro Garnet NS9100 810lm {"NAME":"WiproSmartBulb","GPIO":[0,0,0,0,38,0,0,0,37,0,0,0,0],"FLAG":0,"BASE":18} Wyze WLPA19 A19 800lm {"NAME":"Wyze Bulb","GPIO":[0,0,0,0,0,0,0,0,0,37,38,0,0],"FLAG":0,"BASE":48} @@ -149,7 +156,7 @@ Konesky {"NAME":"KingArt","GPIO":[157,0,53,11,23,17,0,0,18,22,5 LoraTap SC400W-EU {"NAME":"Loratap SC400W","GPIO":[0,0,0,19,0,17,0,0,18,22,0,21,0],"FLAG":0,"BASE":18} LoraTap SC411WSC-EU RF Remote {"NAME":"Loratap","GPIO":[0,0,0,19,23,17,0,0,18,22,0,21,0],"FLAG":0,"BASE":18} LoraTap SC500W Roller Shutter {"NAME":"SC500W","GPIO":[0,0,0,158,9,10,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} -LoraTap SC511WSC Roller Shutter {"NAME":"SC511WSC","GPIO":[0,255,0,56,17,18,0,0,21,19,22,0,0],"FLAG":0,"BASE":18} +LoraTap SC511WSC Roller Shutter {"NAME":"SC511WSC","GPIO":[0,255,0,56,17,19,0,0,21,18,23,22,0],"FLAG":0,"BASE":18} Maxcio WF-CS01 {"NAME":"Maxcio","GPIO":[157,0,53,11,23,18,0,0,17,21,54,22,52],"FLAG":0,"BASE":18} SCS86-03AJAI {"NAME":"ESE86-03AJAI","GPIO":[157,0,58,18,22,19,0,0,17,21,57,23,56],"FLAG":0,"BASE":18} Teekar SYS-CS 01 {"NAME":"Teekar-Tag","GPIO":[56,0,157,18,22,11,0,0,0,21,57,31,17],"FLAG":0,"BASE":18} @@ -190,6 +197,7 @@ Feit Electric 800lm {"NAME":" Feit P_A800_2","GPIO":[0,0,0,0,0,37,0,0,0,0,0 Feit Electric 8.8W 800lm Vintage {"NAME":"FEIT A1960CL","GPIO":[0,0,0,0,0,0,0,0,0,0,37,0,0],"FLAG":0,"BASE":18} Feit Electric BR30 650lm {"NAME":"Feit BR30 WW","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} Feit Electric BR30 650lm {"NAME":"Feit BR30 CW","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +Geeni LUX 800 {"NAME":"Geeni GN-BW902-999","GPIO":[0,0,0,0,37,0,0,0,0,9,0,0,0],"FLAG":0,"BASE":18} Geeni LUX 800 {"NAME":"Geeni-LUX-800","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} Geeni LUX Edison {"NAME":"Geeni-Edison","GPIO":[0,0,0,0,0,0,0,0,0,0,37,0,0],"FLAG":0,"BASE":18} Globe A19 10W 800lm {"NAME":"Globe WW 800lm","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} @@ -213,6 +221,7 @@ Luminea ZX-2880 A60 800lm {"NAME":"LAV-110.w","GPIO":[0,0,0,0,37,40,0,0,38,41,3 Luminea ZX-2982 ST64 Filament {"NAME":"Luminea ZX2982","GPIO":[0,0,0,0,0,0,0,0,0,0,37,0,0],"FLAG":0,"BASE":18} MagicHome 7.5W Warm White {"NAME":"ZJ-8C2B-CCT-AV1.1","GPIO":[0,0,0,0,0,0,0,0,37,0,0,0,0],"FLAG":0,"BASE":18} Merkury 9W 800lm {"NAME":"MI-BW320-999W","GPIO":[0,0,0,0,0,0,0,0,0,0,21,0,0],"FLAG":0,"BASE":18} +Merkury BR30 750lm {"NAME":"MI-BW905-999W","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} Merkury MI-BW902-999W 800lm {"NAME":"MI-BW902-999W","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} Merkury MI-BW942-999W 800lm {"NAME":"MI-BW942-999W","GPIO":[0,0,0,0,37,0,0,0,0,52,0,0,0],"FLAG":0,"BASE":18} Merkury MIC-BW902-999W {"NAME":"MI-BW902-999W","GPIO":[0,0,0,0,0,0,0,0,0,0,37,0,0],"FLAG":0,"BASE":18} @@ -231,6 +240,7 @@ Nedis PAR16 330lm {"NAME":"Nedis WIFILW31","GPIO":[0,0,0,0,0,37,0,0,0,0,0 NiteBird 8W 800lm 2700k {"NAME":"Nitebird-smart28k","GPIO":[0,0,0,0,37,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} Sealight Vintage Edison A19 {"NAME":"SealightEdison","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} SmartDGM 9W 806lm {"NAME":"L-WB9W1","GPIO":[0,0,0,0,0,37,0,0,9,0,0,0,0],"FLAG":0,"BASE":18} +Smitch 10W 6500K {"NAME":"Smitch Ambience SB-0110","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} TCP Smart 810lm Filament {"NAME":"TCP Filament","GPIO":[0,0,0,0,0,0,0,0,0,0,46,0,0],"FLAG":0,"BASE":18} TCP Smart 810lm Filament {"NAME":"TCP Filament","GPIO":[0,0,0,0,0,0,0,0,0,0,46,0,0],"FLAG":0,"BASE":18} Xiaomi Philips MUE4088RT {"NAME":"Xiaomi Philips","GPIO":[0,0,0,0,0,0,0,0,0,0,0,37,0],"FLAG":0,"BASE":18} @@ -250,10 +260,11 @@ CNSKOU Touch {"NAME":"CNSKOU Dimmer Switch","GPIO":[0,0,0,0,0,0,0,0, Eva Logik {"NAME":"WF31 Dimmer","GPIO":[255,107,255,108,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} Eva Logik 3 Way {"NAME":"EL WF31T","GPIO":[255,107,255,108,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} EX-Store 2 Kanal RS232 V4 {"NAME":"EXS Dimmer","GPIO":[0,148,0,149,0,0,0,0,0,183,0,0,0],"FLAG":0,"BASE":72} -Feit Electric DIM/WIFI {"NAME":"Generic","GPIO":[255,107,255,108,255,255,0,0,255,0,255,0,255],"FLAG":0,"BASE":54} +Feit Electric Smart {"NAME":"Generic","GPIO":[255,107,255,108,255,255,0,0,255,0,255,0,255],"FLAG":0,"BASE":54} Gosund SW2 {"NAME":"Gosund Dimmer","GPIO":[255,148,255,149,17,0,255,255,56,158,37,255,255],"FLAG":0,"BASE":18} iSwitch Touch Switch {"NAME":"iSwitchOZ Dimmer","GPIO":[0,0,0,0,0,0,0,0,0,0,54,0,0],"FLAG":0,"BASE":54} Martin Jerry SD01 {"NAME":"MJ-SD02","GPIO":[19,18,0,59,158,58,0,0,57,37,56,122,29],"FLAG":0,"BASE":73} +Martin Jerry Single Pole {"NAME":"MJ-KN01 Dimmer","GPIO":[0,107,0,108,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54} Minoston 3-Way {"NAME":"MS10W","GPIO":[255,107,255,108,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} Moes DS01-1 {"NAME":"MOES DS01","GPIO":[255,255,255,255,255,255,0,0,255,108,255,107,255],"FLAG":0,"BASE":54} Moes MS-105-1 v2 {"NAME":"MS-105","GPIO":[0,107,0,108,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54} @@ -274,7 +285,23 @@ Zemismart KS-7011 {"NAME":"KS-7011 Dimmer","GPIO":[255,107,255,108,255,25 ## Downlight ``` -Philips 5/6 in. RGBCCT Downlight {"NAME":"Philips","GPIO":[0,0,0,0,40,0,0,0,37,41,39,38,0],"FLAG":0,"BASE":48} +BrilliantSmart Prism 10W RGBCCT {"NAME":"Prism","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +BrilliantSmart Trilogy 9W CCT {"NAME":"SmartCCTDwnLgt","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":48} +Connect SmartHome RGB {"NAME":"CSH-240RGB10W","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Deta 10W RGBCCT {"NAME":"Deta DownLight","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +Feit Electric 6in. RGBW Recessed {"NAME":"Feit LEDR6/RGB","GPIO":[0,0,0,0,37,40,0,0,38,50,39,0,0],"FLAG":0,"BASE":48} +Globe 5W 4" Recessed RGBCCT {"NAME":"GlobeRGBWW","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Hyperikon 14W 1000lm 6" {"NAME":"HyperikonDL6","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +iHomma 6W RGBCCT {"NAME":"iHomma RGBWW","GPIO":[0,0,0,0,41,40,0,0,37,38,39,0,0],"FLAG":0,"BASE":18} +iHomma RGB BT+IR 12W {"NAME":"iHommaLEDDownl","GPIO":[0,0,0,0,0,40,0,0,37,38,39,0,0],"FLAG":0,"BASE":18} +Kogan 9W RGBCCT {"NAME":"Kogan_SMARTLED","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +Mirabella Genio 9W CCT {"NAME":"GenioDLightCCT","GPIO":[0,0,0,0,0,0,0,0,47,0,37,0,0],"FLAG":0,"BASE":48} +Mirabella Genio 9W RGBCCT {"NAME":"GenioDLightRGB","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +Moes 7W RGBCCT {"NAME":"Moes Downlight","GPIO":[0,0,0,0,40,41,0,0,37,38,39,0,0],"FLAG":0,"BASE":18} +Philips 5/6 in. RGBCCT {"NAME":"Philips","GPIO":[0,0,0,0,40,0,0,0,37,41,39,38,0],"FLAG":0,"BASE":48} +Zemismart 4" 10W RGBCCT {"NAME":"ZemiDownLight4","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Zemismart 4" 10W RGBW {"NAME":"ZemiDownLight","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} +Zemismart 6" 14W RGBCCT {"NAME":"ZemiDownLight6","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} ``` ## Energy Meter @@ -341,6 +368,7 @@ Arilux AL-LC06 {"NAME":"Arilux LC06","GPIO":[17,0,0,0,0,0,0,0,38,39,37 Arilux AL-LC11 {"NAME":"Arilux LC11","GPIO":[17,0,59,0,38,37,0,0,41,40,39,147,0],"FLAG":0,"BASE":38} Arilux SL-LC 03 {"NAME":"Arilux LC03","GPIO":[0,0,0,0,51,38,0,0,37,39,0,40,0],"FLAG":0,"BASE":34} Arilux SL-LC 09 {"NAME":"Arilux LC09","GPIO":[0,0,0,0,106,37,0,0,39,0,38,0,0],"FLAG":0,"BASE":18} +Bakeey RGB {"NAME":"Bakeey Strip Controller","GPIO":[17,0,0,0,37,41,0,0,39,0,38,40,0],"FLAG":0,"BASE":18} CIN-03 96W RGB {"NAME":"CIN03-03 Strip","GPIO":[0,0,0,0,38,0,0,0,37,0,39,0,0],"FLAG":0,"BASE":18} DD001-MINI(G)-IR-V03 {"NAME":"WIFI-RGB","GPIO":[17,0,0,0,0,0,0,0,38,39,37,0,0],"FLAG":0,"BASE":40} DD001-MINI(G)-IR-V08 {"NAME":"WIFI-RGB","GPIO":[0,0,0,0,37,0,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} @@ -354,6 +382,7 @@ Luminea ZX-2844 {"NAME":"Luminea ZX-284","GPIO":[40,0,0,0,0,39,0,0,38,1 Luminea ZX-2844-675 {"NAME":"ZX-2844-675","GPIO":[17,0,0,0,38,40,0,0,37,0,39,0,0],"FLAG":0,"BASE":18} Lustreon {"NAME":"Lustreon WiFi ","GPIO":[17,0,55,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":38} Magic UFO RGBW {"NAME":"Magic UFO","GPIO":[17,0,157,0,0,37,0,0,39,40,38,56,0],"FLAG":0,"BASE":18} +MagicHome RGB {"NAME":"Magic Home RGB","GPIO":[0,0,0,0,147,37,0,0,39,0,38,0,159],"FLAG":0,"BASE":18} MagicHome RGB ZJ-WFMN-A V1.1 {"NAME":"MagicHome RGB","GPIO":[0,0,0,0,0,37,0,0,38,39,0,0,0],"FLAG":0,"BASE":34} MagicHome RGBW {"NAME":"ESP-IR-B-v2.3","GPIO":[0,0,51,0,0,38,0,0,37,39,0,40,0],"FLAG":0,"BASE":18} MagicHome RGBW RF {"NAME":"MagicHome RGBW RF","GPIO":[0,0,56,0,147,38,0,0,39,40,37,159,0],"FLAG":0,"BASE":18} @@ -371,7 +400,7 @@ ZJ-WF-ESP-A v1.1 {"NAME":"RGB2","GPIO":[0,0,0,0,0,0,0,0,38,37,39,0,0],"F ## LED Strip ``` Arlec Smart 2m LED Colour Changing Strip Light {"NAME":"Arlec ALD233AH","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} -B.K. Licht BKL1268 2m RGB {"NAME":"RGBW-Strip","GPIO":[0,0,0,0,37,17,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +B.K. Licht 2m RGB {"NAME":"RGBW-Strip","GPIO":[0,0,0,0,37,17,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} BlitzWolf BW-LT11 {"NAME":"BW-LT11 Strip","GPIO":[17,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} BrilliantSmart 20743 RGB+W {"NAME":"BrilliantStrip","GPIO":[17,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} Briloner 2256-150 RGB {"NAME":"Briloner2256-1","GPIO":[51,0,0,0,37,0,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} @@ -401,10 +430,12 @@ Maxonar Lightstrip Pro XS-SLD001 {"NAME":"Maxonar LED","GPIO":[0,0,0,0,0,37,0,0 Merkury Innovations MI-EW003-999W {"NAME":"MI-EW003-999W ","GPIO":[17,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} Mirabella Genio RGB+CW {"NAME":"MirabellaStrip","GPIO":[17,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} Monster Smart IlluminEssence {"NAME":"MI-EW003-999W ","GPIO":[17,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +NiteBird 9.2ft RGB TV Backlight {"NAME":"NiteBird Smart LED Light Strip","GPIO":[17,0,0,0,0,0,0,0,37,39,38,0,0],"FLAG":0,"BASE":18} Polux RGB+NW 2m {"NAME":"Polux Wi-Fi SM","GPIO":[17,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":37} Powertech 5m RGBW {"NAME":"Jaycar ST3992 LED Strip","GPIO":[122,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} Reafoo RGBW 5m {"NAME":"REAFOO RGBW LS","GPIO":[17,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} Sonoff L1 {"NAME":"SonoffL1","GPIO":[0,148,0,149,0,0,0,0,0,56,0,0,0],"FLAG":0,"BASE":70} +Techvilla TE001 {"NAME":"TE-TE001","GPIO":[0,107,0,108,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54} Teckin SL02 {"NAME":"Teckin SL02","GPIO":[51,0,0,0,37,0,0,0,38,0,39,0,0],"FLAG":0,"BASE":52} Teckin SL07 32.8ft RGB {"NAME":"WIFI RGB","GPIO":[51,0,0,0,37,0,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} TORCHSTAR CCT 30W Lighting Kit {"NAME":"Torchstar CCT ","GPIO":[0,0,0,0,52,38,0,0,0,17,0,37,53],"FLAG":0,"BASE":18} @@ -422,40 +453,26 @@ Arlec Smart 40W 4000lm LED Batten {"NAME":"Arlec Batten","GPIO":[0,0,0,0,0,37,0 Arlec Smart Portable Floodlight 10.5W {"NAME":"Arlec GLD301HA","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} Arlec Smart Up & Down LED Wall {"NAME":"Arlec Up Down CCT","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} BAZZ 4 in. RGB Recessed Fixture {"NAME":"SLMR4RGBWWFW","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +BAZZ 6 in. CCT Recessed Fixture {"NAME":"SLDSK6TNWWF","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} Brelong USB Charging Night {"NAME":"Brelong Smart USB Charging Lamp","GPIO":[0,0,0,0,37,0,0,0,38,0,39,0,40],"FLAG":0,"BASE":18} Brilex Nightstand Lamp {"NAME":"Smart Table Lamp","GPIO":[0,0,18,0,37,157,0,0,38,17,39,0,40],"FLAG":0,"BASE":18} -BrilliantSmart 20695 Downlight CCT {"NAME":"SmartCCTDwnLgt","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":48} -BrilliantSmart Prism LED RGBCCT Downlight {"NAME":"Prism","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} BrilliantSmart RGB Garden Kit {"NAME":"Brilliant Gard","GPIO":[0,0,0,0,37,0,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} -Connect SmartHome CSH-240RGB10W {"NAME":"CSH-240RGB10W","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} Connect SmartHome CSH-FSTN12 {"NAME":"CSH-FSTN12","GPIO":[0,0,0,0,37,0,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} Deta 18W 1900lm T8 Tube {"NAME":"DETA Smart LED","GPIO":[0,0,0,0,0,0,0,0,0,0,37,0,0],"FLAG":0,"BASE":18} -Deta DET902HA 10W 940lm RGB+CCT {"NAME":"Deta DownLight","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} electriQ MOODL Ambiance Lamp {"NAME":"ElectriQ MOODL","GPIO":[0,201,0,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} -Feit Electric 6in. RGBW Recessed Downlight {"NAME":"Feit LEDR6/RGB","GPIO":[0,0,0,0,37,40,0,0,38,50,39,0,0],"FLAG":0,"BASE":48} -Globe 5W 4" Recessed RGBCCT {"NAME":"GlobeRGBWW","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} Hugoai Table Lamp {"NAME":"HG02","GPIO":[255,107,255,108,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} -Hyperikon 14W 1000lm 6" Downlight {"NAME":"HyperikonDL6","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} -iHomma 6W RGBCCT Downlight {"NAME":"iHomma RGBWW","GPIO":[0,0,0,0,41,40,0,0,37,38,39,0,0],"FLAG":0,"BASE":18} -iHomma Downlight {"NAME":"iHommaLEDDownl","GPIO":[0,0,0,0,0,40,0,0,37,38,39,0,0],"FLAG":0,"BASE":18} -Kogan 9W Downlight RGBCCT {"NAME":"Kogan_SMARTLED","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +Iwoole Table Lamp {"NAME":"GLOBELAMP","GPIO":[0,0,0,0,0,0,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} Lumary 18W RGBCCT Recessed Panel {"NAME":"LumaryDLghtRGB","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} -Mi LED Desk Lamp MJTD01YL {"NAME":"Mi Desk Lamp","GPIO":[0,0,17,0,37,38,0,0,150,151,0,0,0],"FLAG":0,"BASE":66} +Mi LED Desk Lamp {"NAME":"Mi Desk Lamp","GPIO":[0,0,17,0,37,38,0,0,150,151,0,0,0],"FLAG":0,"BASE":66} Mirabella Genio 10 LED Filament Festoon {"NAME":"GenioFestoon","GPIO":[0,0,0,0,0,0,0,0,0,0,37,0,0],"FLAG":0,"BASE":18} Mirabella Genio 4 Black LED Garden Path {"NAME":"GenioGardenStr","GPIO":[0,0,0,0,37,0,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} -Mirabella Genio 9W CCT Downlight {"NAME":"GenioDLightCCT","GPIO":[0,0,0,0,0,0,0,0,47,0,37,0,0],"FLAG":0,"BASE":48} -Mirabella Genio 9W RGBCCT Downlight {"NAME":"GenioDLightRGB","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} Mirabella Genio CCT 6 LED 30mm Stainless Steel Deck {"NAME":"Mirabella Deck CCT","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} MiraBella Genio Colour 6 LED 30mm Stainless Steel Deck {"NAME":"Genio RGB Deck Lights","GPIO":[0,0,0,0,37,0,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} -Moes 7W RGBCCT Downlight {"NAME":"Moes Downlight","GPIO":[0,0,0,0,40,41,0,0,37,38,39,0,0],"FLAG":0,"BASE":18} Novostella UT88835 20W Floodlight {"NAME":"Novo 20W Flood","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} Sonoff BN-SZ01 {"NAME":"Sonoff BN-SZ","GPIO":[0,0,0,0,0,0,0,0,37,56,0,0,0],"FLAG":0,"BASE":22} Spotlight 9cm RGB+W 7W {"NAME":"Spotlight RGBW","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} Teckin FL41 {"NAME":"Teckin FL41","GPIO":[0,0,0,0,0,17,0,0,0,0,37,0,0],"FLAG":0,"BASE":18} Wipro Next 20W Smart LED Batten {"NAME":"WIPROBatten","GPIO":[0,0,0,0,0,37,0,0,0,47,0,0,0],"FLAG":1,"BASE":18} -Zemismart 4" 10W RGBCCT {"NAME":"ZemiDownLight4","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} -Zemismart 4" 10W RGBW {"NAME":"ZemiDownLight","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} -Zemismart 6" 14W RGBCCT {"NAME":"ZemiDownLight6","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} ``` ## Miscellaneous @@ -468,6 +485,7 @@ Kogan 1500w Panel Heater {"NAME":"Kogan Panel Heater","GPIO":[0,0,0,0,0,0,0,0,0 Kogan 4.1kW Portable Air Conditioner (Reverse Cycle) {"NAME":"Kogan Panel Heater","GPIO":[0,0,0,0,0,0,0,0,0,108,0,107,0],"FLAG":0,"BASE":54} LED Starry Sky Projector Light {"NAME":"STAR PROJECTOR","GPIO":[0,0,0,0,37,0,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} Mosquito Killer Lamp {"NAME":"MosquitoKiller","GPIO":[17,0,0,0,0,0,0,0,37,56,0,0,0],"FLAG":0,"BASE":18} +NEO Coolcam Mouse Trap {"NAME":"Neo Mouse Trap","GPIO":[255,107,255,108,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} Proscenic 807C Humidifier {"NAME":"Generic","GPIO":[255,255,255,255,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} Sonoff RM433 RF Remote Controller {"NAME":"REQUIRES RF DEVICE"} ``` @@ -496,7 +514,7 @@ Sonoff SC {"NAME":"Sonoff SC","GPIO":[17,148,255,149,0,0,0,0,0,56 ## Outdoor Plug ``` Acenx SOP04-US Dual {"NAME":"SOP04-US Dual","GPIO":[255,255,255,255,56,57,0,0,21,17,22,255,255],"FLAG":0,"BASE":18} -Aicliv SOP03-US {"NAME":"AICLIV SOP03US","GPIO":[0,0,0,23,57,0,0,0,21,18,22,0,0],"FLAG":15,"BASE":18} +Aicliv 3 Outlet {"NAME":"AICLIV SOP03US","GPIO":[0,0,0,23,57,0,0,0,21,18,22,0,0],"FLAG":0,"BASE":18} Albohes PC-1606 {"NAME":"Albohes PC1606","GPIO":[17,0,0,0,0,22,18,0,21,0,0,0,0],"FLAG":1,"BASE":39} Albohes PS-1602 {"NAME":"Albohes PC1606","GPIO":[17,0,0,0,0,22,18,0,21,0,0,0,0],"FLAG":1,"BASE":39} Amzdest IP55 {"NAME":"C168 Outdoor","GPIO":[0,0,0,130,134,132,0,0,21,56,22,23,17],"FLAG":0,"BASE":18} @@ -508,12 +526,15 @@ C137 IP55 {"NAME":"C137 Outdoor","GPIO":[0,17,0,56,134,132,0,0,21 C168 IP64 {"NAME":"C188","GPIO":[56,0,57,0,18,0,0,0,21,17,157,22,0],"FLAG":0,"BASE":18} ECF-SOP03 {"NAME":"Outdoor3Outlet","GPIO":[0,0,0,23,56,0,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} Ecoolbuy 4 socket {"NAME":"ECCOLBUY 4","GPIO":[0,0,0,0,22,23,0,0,21,57,17,0,24],"FLAG":0,"BASE":18} +Edimax 2AC {"NAME":"EDI SP-1122WTO","GPIO":[0,0,0,0,22,158,0,0,21,0,17,0,0],"FLAG":0,"BASE":18} +Etekcity {"NAME":"ES015-TB","GPIO":[0,0,0,0,21,22,0,0,132,133,17,130,56],"FLAG":0,"BASE":18} Feit Electric PLUG/WIFI/WP {"NAME":"Prime Smart ou","GPIO":[0,255,0,255,157,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} Forrinx SH-18EU-A {"NAME":"SH-18EU-A","GPIO":[0,0,0,0,22,52,21,57,17,0,0,0,0],"FLAG":0,"BASE":18} -Geeni Outdoor {"NAME":"Geeni Outdoor","GPIO":[17,0,0,0,0,57,0,0,0,52,21,0,0],"FLAG":0,"BASE":18} Geeni Outdoor DUO Dual Outlet {"NAME":"Geeni Dual Out","GPIO":[17,0,0,0,0,57,0,0,0,56,21,0,22],"FLAG":0,"BASE":18} Globe 2-Outlet {"NAME":"Globe SK509W2S","GPIO":[0,0,0,0,22,0,0,0,17,21,56,0,0],"FLAG":0,"BASE":18} HA109US {"NAME":"HA109US","GPIO":[17,0,0,0,52,53,0,0,21,0,22,0,0],"FLAG":0,"BASE":18} +HBN 6 Outlet Yard Stake {"NAME":"BNC-60/U13WT","GPIO":[0,0,0,0,0,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +HBN Heavy Duty {"NAME":"HBN U151T","GPIO":[0,0,0,0,52,53,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} iClever IC-BS06 {"NAME":"iClever Switch","GPIO":[0,0,0,0,157,56,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} Jackyled IP55 3AC {"NAME":"JackyLed 3","GPIO":[0,0,56,0,0,23,0,0,22,57,17,0,21],"FLAG":0,"BASE":18} King-Link C128 {"NAME":"King-Link C128","GPIO":[0,0,58,0,22,56,0,0,23,157,17,21,57],"FLAG":0,"BASE":18} @@ -532,6 +553,7 @@ Oittm Outdoor {"NAME":"Oittm Outdoor","GPIO":[17,0,0,0,0,0,0,0,0,0,56 Peteme PS-1602 {"NAME":"Peteme Outdoor","GPIO":[17,0,0,0,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":18} Poweradd {"NAME":"POWERADD","GPIO":[0,0,0,0,56,57,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} Prime RCWFIO 2-Outlet {"NAME":"Prime Outdoor","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Prime Smart Outlet {"NAME":"Prime CCWFIO232PK","GPIO":[0,0,0,57,22,0,0,0,17,21,52,0,0],"FLAG":0,"BASE":18} Signstek EOP03-EU {"NAME":"Signstek EOP03","GPIO":[0,0,0,0,56,57,0,0,21,17,22,0,0],"FLAG":15,"BASE":18} SK03 {"NAME":"SK03 Outdoor","GPIO":[17,0,0,0,133,132,0,0,131,57,56,21,0],"FLAG":0,"BASE":57} STITCH by Monoprice 35556 {"NAME":"STITCH 35556","GPIO":[255,255,255,255,22,57,0,0,21,56,17,255,255],"FLAG":0,"BASE":18} @@ -575,11 +597,11 @@ Anoopsyche SP-G01 {"NAME":"SP-G01","GPIO":[0,145,0,146,0,0,0,0,17,56,21,0 Anoopsyche SP15 {"NAME":"Anoop SP15","GPIO":[0,0,0,0,56,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} Anoopsyche UK1D {"NAME":"UK1D","GPIO":[0,17,0,0,133,132,0,0,130,52,21,0,0],"FLAG":0,"BASE":6} AOFO 10A {"NAME":"AOFO Smart Plug Wifi","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Aoycocr {"NAME":"Aoycocr X10S","GPIO":[56,0,57,0,21,134,0,0,131,17,132,0,0],"FLAG":0,"BASE":45} Aoycocr EU5 16A {"NAME":"Aoycocr","GPIO":[255,0,56,0,0,0,0,0,255,17,0,21,0],"FLAG":0,"BASE":17} Aoycocr EU6S {"NAME":"Aoycocr EU6S","GPIO":[255,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":17} Aoycocr U2S {"NAME":"Aoycocr U2S","GPIO":[56,0,57,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} Aoycocr U3S {"NAME":"Aoycocr U3S","GPIO":[56,255,57,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} -Aoycocr X10S {"NAME":"Aoycocr X10S","GPIO":[56,0,57,0,21,134,0,0,131,17,132,0,0],"FLAG":0,"BASE":45} Aoycocr X5P {"NAME":"Aoycocr X5P","GPIO":[56,0,57,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} Aoycocr X6 {"NAME":"Aoycocr X6","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} Aquiv S1 {"NAME":"Aquiv S1","GPIO":[0,0,157,0,56,0,0,0,21,17,0,0,0],"FLAG":15,"BASE":18} @@ -588,7 +610,7 @@ Arlec Heavy Duty 20m Extension Lead {"NAME":"Arlec Ext Cord","GPIO":[0,17,0,0,0 Arlec Smart 2.1A USB Charger {"NAME":"Arlec Single","GPIO":[0,0,0,0,57,0,0,0,21,0,90,0,0],"FLAG":0,"BASE":18} Arlec Smart PC189HA {"NAME":"Arlec Single","GPIO":[0,0,0,0,57,0,0,0,21,0,90,0,0],"FLAG":0,"BASE":18} Arlec Smart PC190HA {"NAME":"Arlec-PC190HA","GPIO":[0,0,0,0,56,0,0,0,21,158,17,0,0],"FLAG":0,"BASE":18} -Arlec Smart PC399HA Plug {"NAME":"PC399HA","GPIO":[0,0,0,17,134,132,0,0,131,158,21,0,0],"FLAG":0,"BASE":52} +Arlec Smart PC399HA Plug {"NAME":"PC399HA","GPIO":[0,0,0,17,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":52} Arlec Twin PC288HA {"NAME":"Arlec Twin","GPIO":[0,17,0,22,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} Athom 16A {"NAME":"Athom PG01EU16A","GPIO":[0,0,0,17,134,132,0,0,131,157,21,0,0],"FLAG":0,"BASE":1} Atomi AT1217 {"NAME":"AT1217","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} @@ -597,6 +619,7 @@ Aukey SH-PA2 {"NAME":"AUKEY SH-PA2","GPIO":[0,0,0,0,158,0,0,0,21,0,1 Aukey SH-PA3 {"NAME":"Aukey SH-PA3","GPIO":[0,0,158,0,57,17,0,0,22,0,0,21,0],"FLAG":0,"BASE":18} Aunics Smart EU {"NAME":"AUNICS","GPIO":[0,0,0,17,134,132,0,0,131,157,21,0,0],"FLAG":0,"BASE":18} Aunics Smart IT {"NAME":"AUNICS","GPIO":[0,0,0,17,134,132,0,0,131,157,21,0,0],"FLAG":0,"BASE":18} +Avatar {"NAME":"Avatar UK 10A","GPIO":[0,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} Avatar AWP01L {"NAME":"AWP01L","GPIO":[0,0,0,0,0,56,0,0,0,17,21,0,0],"FLAG":0,"BASE":18} Avatar AWP02L-N {"NAME":"AWP02L-N","GPIO":[158,0,0,0,56,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} Avatar AWP03L {"NAME":"AWP03L","GPIO":[0,0,0,0,0,0,0,0,21,17,56,57,0],"FLAG":0,"BASE":18} @@ -604,7 +627,6 @@ Avatar AWP04L {"NAME":"AWP04L","GPIO":[57,255,255,131,255,134,0,0,21, Avatar AWP07L {"NAME":"AWP07L","GPIO":[56,255,255,255,255,134,255,255,131,17,132,21,255],"FLAG":0,"BASE":18} Avatar AWP08L {"NAME":"AWP08L","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} Avatar AWP12L Capsule 2-in-1 {"NAME":"AWP12L","GPIO":[56,0,0,131,18,134,0,0,21,17,132,22,0],"FLAG":0,"BASE":18} -Avatar AWP14H {"NAME":"Avatar UK 10A","GPIO":[0,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} Avatto JH-G01E {"NAME":"AVATTO JH-G01E","GPIO":[0,145,0,146,0,0,0,0,17,56,21,0,0],"FLAG":0,"BASE":41} Avatto NAS-WR01W 10A {"NAME":"AvattoNAS-WR01W","GPIO":[0,0,0,0,52,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} Avatto OT06 16A {"NAME":"Avatto OT06","GPIO":[17,0,0,0,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":49} @@ -618,18 +640,20 @@ Bardi 16A {"NAME":"BARDI","GPIO":[56,0,0,0,0,134,0,0,21,17,132,57 Bauhn ASPU-1019 {"NAME":"Bauhn Smart Pl","GPIO":[0,0,0,0,21,22,0,0,0,56,17,0,0],"FLAG":0,"BASE":18} Bearware 303492 3AC+2USB {"NAME":"Bearware 30349","GPIO":[0,56,0,17,22,23,0,0,24,21,157,0,0],"FLAG":0,"BASE":18} Bestek MRJ1011 {"NAME":"BestekMRJ1011","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":1} +BlitzWolf 1200W Dual {"NAME":"BlitzWolf SHP3","GPIO":[56,0,57,0,22,134,0,0,131,18,132,21,17],"FLAG":0,"BASE":45} BlitzWolf BW-SHP10 {"NAME":"BW-SHP10","GPIO":[0,0,0,0,157,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} BlitzWolf BW-SHP10-P {"NAME":"BW-SHP10 PM","GPIO":[0,148,0,207,158,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} BlitzWolf BW-SHP2 {"NAME":"BlitzWolf SHP","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} -BlitzWolf BW-SHP3 {"NAME":"BlitzWolf SHP3","GPIO":[56,0,57,0,22,134,0,0,131,18,132,21,17],"FLAG":0,"BASE":45} BlitzWolf BW-SHP3 alt {"NAME":"BlitzWolf SHP3","GPIO":[18,56,0,131,134,132,0,0,17,0,22,21,0],"FLAG":0,"BASE":18} BlitzWolf BW-SHP4 {"NAME":"BlitzWolf SHP","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} BlitzWolf BW-SHP5 {"NAME":"SHP5","GPIO":[57,145,56,146,0,22,0,0,0,0,21,0,17],"FLAG":0,"BASE":18} BlitzWolf BW-SHP6 10A {"NAME":"BW-SHP6 10A","GPIO":[158,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} BlitzWolf BW-SHP6 15A {"NAME":"BlitzWolf SHP6","GPIO":[56,255,158,255,132,134,0,0,131,17,0,21,0],"FLAG":0,"BASE":45} BlitzWolf BW-SHP7 {"NAME":"SHP7","GPIO":[17,158,57,131,134,132,0,0,18,56,21,0,22],"FLAG":0,"BASE":45} +BlitzWolf SHP1 {"NAME":"BlitzWolf-SHP1","GPIO":[56,0,57,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} BN-Link {"NAME":"BNC-60/U133TJ","GPIO":[0,56,0,17,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":18} BNETA IO-WIFI-PlugSA {"NAME":"BNETA WifiPlug","GPIO":[17,0,0,0,133,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":18} +Bontec SPEU {"NAME":"Bontec SPEU","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} Brennenstuhl WA 3000 {"NAME":"WA 3000 XS01","GPIO":[0,0,0,0,21,17,0,0,158,52,0,0,0],"FLAG":0,"BASE":61} Bright {"NAME":"Bright Wi-Fi Smart Plug","GPIO":[0,0,0,0,56,0,0,0,21,0,17,0,0],"FLAG":0,"BASE":18} Brilliant {"NAME":"HK17654S05","GPIO":[17,255,255,255,133,132,255,255,131,56,21,255,255],"FLAG":0,"BASE":18} @@ -653,6 +677,7 @@ CE Smart Home LA-WF3 {"NAME":"CE LA-WF3","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0 Cloudfree Runs Tasmota {"NAME":"CloudFree 1","GPIO":[255,255,56,255,255,255,0,0,255,17,255,21,255],"FLAG":0,"BASE":18} Conico SM-PW70 {"NAME":"Conico SM-PW70","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} Connex CC-P1000 {"NAME":"Connex Smart T","GPIO":[17,0,0,0,133,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":18} +Connex Type F {"NAME":"Connex CC-P1001","GPIO":[0,0,56,0,0,133,0,0,131,17,132,21,0],"FLAG":0,"BASE":18} Coosa {"NAME":"COOSA","GPIO":[0,0,0,0,57,52,0,0,21,17,255,0,0],"FLAG":0,"BASE":1} Coosa SP1 {"NAME":"COOSA SP1","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} CrazyLynX WiFi {"NAME":"CrazyLynX","GPIO":[0,0,0,0,57,56,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} @@ -660,6 +685,7 @@ CYYLTF BIFANS J23 {"NAME":"CYYLTD BIFANS J23","GPIO":[56,0,0,0,0,0,0,0,21 D3D Smart Plug with USB & Power Monitor {"NAME":"D3D FLHS-ZN04","GPIO":[57,255,56,131,255,133,255,255,255,17,132,21,255],"FLAG":15,"BASE":18} DE-1 16A {"NAME":"DE-1","GPIO":[0,17,0,0,133,0,0,0,0,52,21,0,0],"FLAG":1,"BASE":18} DeLock Power Socket Switch MQTT {"NAME":"DeLock 11826","GPIO":[17,0,0,0,0,0,0,0,21,158,0,0,0],"FLAG":0,"BASE":1} +Delock Power Socket Switch MQTT {"NAME":"Delock 11827","GPIO":[0,0,0,17,133,132,0,0,131,158,21,0,0],"FLAG":0,"BASE":53} Deltaco SH-P01 {"NAME":"DELTACO SH-P01","GPIO":[0,0,0,0,0,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} Deltaco SH-P01E {"NAME":"DELTACO SH-P01E","GPIO":[0,56,0,17,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":55} Deltaco SH-P02 {"NAME":"Deltaco SH-P02","GPIO":[18,0,0,0,134,132,0,0,131,56,21,22,17],"FLAG":0,"BASE":18} @@ -704,7 +730,8 @@ Frankever USB {"NAME":"FK-PW301U","GPIO":[0,0,255,0,158,0,0,0,21,17,0 GDTech W-US001 {"NAME":"GDTech W-US001","GPIO":[255,17,255,255,255,255,0,0,255,56,21,255,255],"FLAG":1,"BASE":18} GDTech W-US003 {"NAME":"W-US003","GPIO":[0,17,255,255,255,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} Geekbes YM-WS-1 {"NAME":"Office Test Pl","GPIO":[255,255,255,255,255,255,255,255,158,17,12,21,255],"FLAG":15,"BASE":18} -Geeni Spot {"NAME":"Geeni Spot","GPIO":[0,0,0,0,52,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Geeni OUTDOOR {"NAME":"Geeni Outdoor","GPIO":[17,0,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +Geeni Spot {"NAME":"Geeni Spot","GPIO":[158,0,0,0,56,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} Geeni Spot Glo {"NAME":"Geeni Glo","GPIO":[0,0,0,0,56,0,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} Geeni SWITCH {"NAME":"Geeni Switch","GPIO":[0,0,0,0,52,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} Geeni Switch Duo {"NAME":"Geeni Duo","GPIO":[0,0,0,0,18,22,0,0,17,52,21,0,53],"FLAG":0,"BASE":18} @@ -713,6 +740,7 @@ Globe 2 Outlet {"NAME":"Globe 50020","GPIO":[0,158,0,57,18,17,0,0,21,5 Globe Smart {"NAME":"GlobeSmartPlug","GPIO":[0,0,0,0,56,0,0,0,21,0,17,0,0],"FLAG":0,"BASE":18} GoldenDot Mini {"NAME":"GoldenDot Mini","GPIO":[0,17,0,0,0,0,0,0,0,57,21,0,0],"FLAG":0,"BASE":52} GoldenDot with ADC {"NAME":"W-US003-Power","GPIO":[56,0,0,0,0,0,0,0,0,17,0,21,0],"FLAG":7,"BASE":18} +Gosund {"NAME":"Gosund EP2","GPIO":[56,255,158,255,132,134,0,0,131,17,0,21,0],"FLAG":0,"BASE":45} Gosund 2 in 1 {"NAME":"Gosund WP212","GPIO":[57,52,157,0,21,134,0,0,131,17,132,22,18],"FLAG":0,"BASE":18} Gosund SP1 {"NAME":"Gosund SP1 v23","GPIO":[0,56,0,17,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":55} Gosund SP111 {"NAME":"Gosund SP111","GPIO":[56,0,57,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":18} @@ -726,7 +754,7 @@ Gosund UP111 {"NAME":"Gosund UP111","GPIO":[0,52,0,17,134,132,0,0,13 Gosund WP1 {"NAME":"Gosund WP1-1","GPIO":[0,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} Gosund WP2 {"NAME":"Gosund WP2","GPIO":[17,158,57,0,18,0,0,0,22,56,21,0,0],"FLAG":0,"BASE":18} Gosund WP211 {"NAME":"Gosund wp211","GPIO":[0,0,0,0,21,0,0,0,0,17,0,22,18],"FLAG":0,"BASE":18} -Gosund WP212 {"NAME":"Gosund_WP212","GPIO":[17,0,0,0,18,0,0,0,22,0,21,0,0],"FLAG":0,"BASE":18} +Gosund WP212 {"NAME":"Gosund_WP212","GPIO":[17,157,57,0,18,0,0,0,22,56,21,0,0],"FLAG":0,"BASE":18} Gosund WP3 {"NAME":"Gosund WP3","GPIO":[0,0,0,0,17,0,0,0,56,57,21,0,0],"FLAG":0,"BASE":18} Gosund WP5 {"NAME":"Gosund-WP5","GPIO":[0,0,0,0,17,0,0,0,56,57,21,0,0],"FLAG":0,"BASE":18} Gosund WP6 {"NAME":"Gosund WP6","GPIO":[0,0,0,17,0,0,0,0,56,57,21,0,0],"FLAG":0,"BASE":18} @@ -758,7 +786,7 @@ Hyleton 317 {"NAME":"hyleton-317","GPIO":[56,0,57,0,58,0,0,0,0,90,0 Hyleton HLT-311 {"NAME":"HLT-311","GPIO":[56,0,0,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} iClever IC-BS08 {"NAME":"iClever BS08","GPIO":[0,0,0,0,157,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} iDIGITAL {"NAME":"Brilliant","GPIO":[0,0,0,0,52,0,0,0,21,90,0,0,0],"FLAG":0,"BASE":18} -Ihommate ZCH-02 {"NAME":"ZCH-02","GPIO":[0,0,0,17,133,132,0,0,130,56,21,0,0],"FLAG":1,"BASE":18} +Ihommate 16A {"NAME":"ZCH-02","GPIO":[0,0,0,17,133,132,0,0,130,56,21,0,0],"FLAG":1,"BASE":18} Infray 16A {"NAME":"AWP08L","GPIO":[17,0,52,0,0,0,0,0,0,0,0,21,0],"FLAG":1,"BASE":18} Insmart WP5 {"NAME":"INSMART","GPIO":[0,0,46,0,0,0,0,0,0,9,0,21,0],"FLAG":0,"BASE":18} iSwitch {"NAME":"Smart Plug XSA","GPIO":[255,17,255,255,255,255,0,0,255,56,21,255,255],"FLAG":0,"BASE":18} @@ -810,7 +838,6 @@ Luminea ZX-2858 {"NAME":"Luminea SF-200","GPIO":[0,0,0,17,0,0,0,0,0,56, Lunvon {"NAME":"Lunvon Smart Plug","GPIO":[17,0,0,0,0,0,52,21,0,0,0,0,0],"FLAG":0,"BASE":18} Martin Jerry V01 {"NAME":"MJ V01","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} Martin Jerry XS-SSA01 {"NAME":"MJ_XS-SSA01","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} -Maxcio W-DE004 {"NAME":"Maxcio W-DE004","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":1,"BASE":18} Maxcio W-UK007S {"NAME":"Maxcio","GPIO":[56,0,255,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} Maxcio W-US002S {"NAME":"W-US002S","GPIO":[57,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} Maxcio W-US003 {"NAME":"W-US003","GPIO":[255,17,255,255,255,255,0,0,255,22,21,255,255],"FLAG":0,"BASE":18} @@ -844,6 +871,7 @@ Nightlight and AC Outlet {"NAME":"SWN03","GPIO":[17,0,0,0,0,0,255,255,37,0,0,21 Nishica SM-PW701I {"NAME":"SM-PW701I","GPIO":[255,255,255,255,255,255,255,255,21,52,17,255,255],"FLAG":15,"BASE":18} NX-SM112 {"NAME":"NX-SM112v3","GPIO":[0,0,0,0,134,132,0,0,158,17,130,21,0],"FLAG":0,"BASE":45} NX-SM200 {"NAME":"NX-SM200","GPIO":[56,0,0,0,0,134,0,0,21,17,132,57,131],"FLAG":0,"BASE":18} +NX-SM210 {"NAME":"NX-SM210","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} NX-SM223 {"NAME":"Smart Thurmm","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} Obi Stecker {"NAME":"OBI Socket","GPIO":[255,255,0,255,52,21,0,0,54,255,17,0,255],"FLAG":1,"BASE":51} Obi Stecker 2 {"NAME":"OBI Socket 2","GPIO":[0,0,0,0,21,17,0,0,56,53,0,0,0],"FLAG":0,"BASE":61} @@ -880,7 +908,9 @@ Robaxo {"NAME":"Robaxo RSP-025","GPIO":[17,0,0,0,134,132,0,0,1 RSH-WS005 {"NAME":"RSH-WS005 Energy Monitor","GPIO":[56,0,158,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":18} RSH-WS007-EU {"NAME":"RSH-WS007","GPIO":[0,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":1,"BASE":18} S126 {"NAME":"tuya-plug","GPIO":[0,0,0,0,0,0,0,0,21,20,0,0,0],"FLAG":0,"BASE":8} +SA-001 {"NAME":"SA-001","GPIO":[17,145,0,146,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":41} SA-P202C 16A {"NAME":"Elivco 202C-G","GPIO":[0,0,0,17,134,132,0,0,130,56,21,0,0],"FLAG":0,"BASE":18} +SA-P302A {"NAME":"KinCam SA-P302A","GPIO":[0,0,0,0,0,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} Sansui {"NAME":"Sansui YSP-1","GPIO":[52,0,53,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} Shelly Plug S {"NAME":"Shelly Plug S","GPIO":[56,255,158,255,255,134,0,0,131,17,132,21,255],"FLAG":2,"BASE":45} Shelly Plug US {"NAME":"Shelly Plug US","GPIO":[52,0,57,0,21,134,0,0,131,17,132,157,0],"FLAG":0,"BASE":45} @@ -957,6 +987,7 @@ Vivanco 39625 Smart Home Power Adapter {"NAME":"Vivianco","GPIO":[0,0,0,17,133, Vivitar {"NAME":"Vivitar HA1003","GPIO":[158,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} Vivitar HA-1006 {"NAME":"HA-1006","GPIO":[0,0,0,0,56,0,0,0,21,90,0,0,0],"FLAG":0,"BASE":18} Vivitar HA-1006-AU {"NAME":"HA-1006-AU","GPIO":[0,0,0,0,56,0,0,0,21,90,0,0,0],"FLAG":0,"BASE":18} +W-DE004 {"NAME":"W-DE004","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":1,"BASE":18} WAGA life CHCZ02MB {"NAME":"WAGA CHCZ02MB","GPIO":[57,0,0,131,0,134,0,0,21,17,132,56,0],"FLAG":0,"BASE":68} WAZA 10A {"NAME":"WAZA","GPIO":[0,0,0,0,21,17,0,0,56,0,0,0,0],"FLAG":1,"BASE":18} WAZA JH-G01B {"NAME":"Teckin SP27","GPIO":[255,255,255,255,53,255,0,0,21,17,255,255,255],"FLAG":0,"BASE":18} @@ -1019,6 +1050,7 @@ Arlec Smart PB88UHA {"NAME":"Arlec PB88UHA","GPIO":[0,56,0,17,22,21,0,0,24, Arlec Smart PB89HA {"NAME":"Arlec PB89HA","GPIO":[0,56,0,17,22,21,0,0,24,23,0,0,0],"FLAG":0,"BASE":18} Bauhn ASPBU-1019 {"NAME":"Bauhn 3AC+3USB","GPIO":[0,157,0,0,22,21,0,0,0,23,17,0,0],"FLAG":0,"BASE":18} BlitzWolf BW-SHP9 {"NAME":"BlitzWolf SHP9","GPIO":[158,255,0,255,0,23,0,0,21,17,22,24,0],"FLAG":0,"BASE":45} +Brennenstuhl Connect Eco-Line {"NAME":"WS EL01 DE","GPIO":[19,18,0,17,21,22,0,0,52,0,0,53,158],"FLAG":0,"BASE":18} BrilliantSmart 20691 Powerboard with USB Chargers {"NAME":"B_WiFi-4","GPIO":[56,0,0,57,29,17,0,0,31,30,32,0,25],"FLAG":1,"BASE":18} CE Smart Home {"NAME":"CE Power Strip","GPIO":[52,0,0,0,22,21,0,0,24,23,25,26,17],"FLAG":0,"BASE":18} CE Smart Home Garden Stake {"NAME":"CE Power Stake","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} @@ -1027,6 +1059,7 @@ Deltaco SH-P03USB {"NAME":"Deltaco SH-P03","GPIO":[56,0,0,0,0,23,0,0,21,1 Digoo DG-PS01 {"NAME":"Digoo DG-PS01","GPIO":[0,56,0,17,23,22,0,0,0,24,21,0,0],"FLAG":1,"BASE":18} Geekbes 4AC+4USB {"NAME":"Geekbes 4xStri","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":1,"BASE":18} Geeni Surge {"NAME":"Geeni GNCSW003","GPIO":[52,0,0,0,22,21,0,0,24,25,23,26,17],"FLAG":0,"BASE":18} +Geeni Surge + Charge 2 USB {"NAME":"Geeni GN-SW023","GPIO":[52,0,0,0,22,21,0,0,23,24,25,0,17],"FLAG":0,"BASE":18} Geeni SURGE 6-Outlet Surge Protector {"NAME":"Geeni 6 Strip","GPIO":[56,0,0,0,22,21,0,0,24,25,23,26,0],"FLAG":0,"BASE":18} Geeni Surge Mini {"NAME":"Geeni-GN-SW004","GPIO":[56,0,0,17,0,0,0,0,22,21,23,0,0],"FLAG":15,"BASE":18} Globe 4 Outlet 2 USB {"NAME":"PowerBar","GPIO":[56,0,0,0,24,17,0,0,22,23,21,0,0],"FLAG":15,"BASE":18} @@ -1049,6 +1082,7 @@ KMC 5AC 3USB QC {"NAME":"KMC 5-Outlet","GPIO":[56,0,0,0,25,9,0,0,22,21, Kogan Power Strip USB Ports & Energy Meter {"NAME":"Generic","GPIO":[90,56,0,24,134,132,0,0,131,22,23,21,0],"FLAG":0,"BASE":18} Konesky Type 1 {"NAME":"Konesky","GPIO":[0,0,0,0,25,22,0,0,24,17,23,21,0],"FLAG":0,"BASE":18} Koogeek KLOE4 {"NAME":"Koogeek KLOE4","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":1,"BASE":18} +Larkkey 4AC 4USB {"NAME":"LARKKEY Strip","GPIO":[0,157,0,17,22,21,0,0,23,24,25,0,0],"FLAG":0,"BASE":18} LeFun SK2 {"NAME":"LeFun SK2","GPIO":[0,0,0,17,22,21,0,0,23,24,25,0,0],"FLAG":0,"BASE":18} Luminea 3AC+4USB 16A {"NAME":"Luminea-NX4473","GPIO":[0,56,0,17,22,21,0,0,0,23,24,0,0],"FLAG":0,"BASE":18} Maxcio ZLD-34EU-W {"NAME":"MAXCIO","GPIO":[0,56,0,17,22,21,0,0,0,23,24,0,0],"FLAG":1,"BASE":18} @@ -1080,6 +1114,7 @@ WP40 {"NAME":"WP40","GPIO":[33,0,0,0,56,0,0,0,21,17,22,23,32 Xenon SM-S0301 {"NAME":"SM-SO301","GPIO":[52,255,255,57,29,17,0,0,31,30,32,255,25],"FLAG":0,"BASE":18} Xenon SM-S0301-U {"NAME":"SM-SO301-U","GPIO":[52,255,255,57,29,17,0,0,31,30,32,255,25],"FLAG":0,"BASE":18} Xenon SM-SO301 v2 {"NAME":"SM-SO301","GPIO":[56,0,0,0,30,17,0,0,32,31,33,0,21],"FLAG":0,"BASE":18} +Xenta 3 AC 6 USB {"NAME":"Xenta-3-Gang","GPIO":[52,0,0,57,29,17,0,0,31,30,0,0,24],"FLAG":0,"BASE":18} XS-A25 {"NAME":"XS-A25","GPIO":[52,0,53,0,25,22,0,0,24,17,23,21,0],"FLAG":0,"BASE":18} XS-A26 {"NAME":"XS-A26","GPIO":[52,0,53,0,25,22,0,0,24,17,23,21,0],"FLAG":0,"BASE":18} XS-A34 {"NAME":"XS-A24","GPIO":[52,0,53,0,25,22,0,0,24,17,23,21,0],"FLAG":0,"BASE":18} @@ -1088,6 +1123,7 @@ Yagala SWB3 {"NAME":"YAGALA SWB3","GPIO":[157,0,53,0,0,23,0,0,21,17 Yagala Z1 {"NAME":"YAGALA Z1","GPIO":[0,157,0,17,22,24,0,0,23,25,21,0,0],"FLAG":0,"BASE":18} Yuanguo 4AC + 2 USB {"NAME":"YUANGUO","GPIO":[0,20,0,24,19,18,0,0,17,22,21,23,0],"FLAG":0,"BASE":1} Yuanguo 4AC+2USB {"NAME":"YUANGUO","GPIO":[13,20,0,24,19,18,0,0,17,22,21,23,157],"FLAG":0,"BASE":1} +Zeoota 4AC 2USB {"NAME":"Zeoota WP30","GPIO":[0,17,0,24,0,0,0,0,0,22,21,23,0],"FLAG":7,"BASE":18} Zeoota PS022 {"NAME":"ZEOOTA 3x plus","GPIO":[0,57,0,56,22,21,0,0,17,23,24,0,0],"FLAG":1,"BASE":18} Zeoota ZLD-44EU-W {"NAME":"ZEOOTA-ZLD-44E","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":1,"BASE":18} ZLD-44EU-W {"NAME":"ZLD-44EU-W","GPIO":[17,255,255,255,22,21,18,19,23,24,25,0,0],"FLAG":0,"BASE":23} @@ -1125,9 +1161,10 @@ Athom 7W 600lm {"NAME":"Athom LB017W","GPIO":[0,0,0,0,37,40,0,0,38,41, Aunics 7W 600lm {"NAME":"Aunics RGBW","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} Avatar ALB201W 720lm {"NAME":"AVATAR ALB201W","GPIO":[0,0,0,0,0,39,0,0,38,0,37,40,0],"FLAG":0,"BASE":18} Avatar ALS18L A60 800lm {"NAME":"Avatar E14 7W","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":20} -B.K.Licht BKL1253 9W 806lm {"NAME":"BKL1253","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +B.K. Licht 5.5W 350lm {"NAME":"BKL1262","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +B.K. Licht 9W 806lm {"NAME":"BKL1253","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} Bakibo TB95 9W 1000lm {"NAME":"Bakibo A19 9W","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} -BAZZ BR30 650lm {"NAME":"BAZZrgb","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":1,"BASE":18} +BAZZ BR30 650lm {"NAME":"BAZZrgb","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} BlitzWolf w/ remote 850lm {"NAME":"BW-LT27","GPIO":[0,0,0,0,41,38,0,0,39,51,40,37,0],"FLAG":0,"BASE":18} BNETA 8.5W 800lm {"NAME":"BNETA IO-WIFI60-E27P","GPIO":[0,0,0,0,37,40,0,0,38,50,39,0,0],"FLAG":0,"BASE":18} BNETA 8.5W 800lm {"NAME":"OM60/RGBW","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} @@ -1138,6 +1175,7 @@ Calex 5W 350lm Reflector {"NAME":"Calex RGBW","GPIO":[0,0,0,0,0,0,0,0,181,0,180 Cleverio 51395 806lm {"NAME":"CleverioE27RGB","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} CMARS 4W Reflector {"NAME":"RGBWW GU10","GPIO":[0,0,0,0,40,41,0,0,38,39,37,0,0],"FLAG":15,"BASE":18} Connect SmartHome 5W GU5.3 {"NAME":"CSH-GU53RGB5W","GPIO":[0,0,0,0,40,41,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} +Diolamp E27 9W 800lm {"NAME":"Diolamp A609WIFI","GPIO":[0,0,0,0,180,0,0,0,0,0,181,0,0],"FLAG":0,"BASE":18} Dogain 320lm {"NAME":"DOGAIN","GPIO":[0,0,0,0,40,41,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} Emuni TB95 9W 850Lm {"NAME":"TB95","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} Ener-J SHA5262 800lm {"NAME":"ENER-J RGBWWW ","GPIO":[0,0,0,0,40,41,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} @@ -1162,6 +1200,7 @@ Helloify BR30 9W 600lm {"NAME":"Helloify","GPIO":[255,255,255,255,37,40,255,25 HIPER IoT A61 {"NAME":"HIPER IoT A61","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} HIPER IoT C1 {"NAME":"Hiper IoT C1 RGB","GPIO":[0,0,0,0,0,0,0,0,181,0,180,0,0],"FLAG":0,"BASE":18} Holdpeak BR40 12W 1100lm {"NAME":"HP-BR40-12W","GPIO":[0,0,0,0,140,37,0,0,38,0,141,0,0],"FLAG":0,"BASE":18} +Hombli 9W 800lm {"NAME":"HBEB-0124","GPIO":[0,0,0,0,39,38,0,0,40,37,41,0,0],"FLAG":0,"BASE":18} Infray 9W 900LM {"NAME":"InfrayRGBCCT","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} Jeeo TF-QPZ13 800lm {"NAME":"Jeeo","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} Julun JL-021 5W Candle {"NAME":"E14 RGBCCT","GPIO":[0,0,0,0,40,41,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} @@ -1189,6 +1228,7 @@ Lohas ZN036 900 lm {"NAME":"Lohas RGBCCT","GPIO":[0,0,0,0,38,37,0,0,41,39, Lohas ZN037 450lm {"NAME":"Lohas LH-ZN037","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":20} Lohas ZN038 BR20 8W 750lm {"NAME":"Lohas LH-ZN038","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} Lohas ZN039 BR40 1450lm {"NAME":"Lohas ZN039","GPIO":[0,0,0,0,39,37,0,0,41,38,40,0,0],"FLAG":0,"BASE":18} +Lohas ZN041 BR30 12W 1080lm {"NAME":"Lohas ZN041","GPIO":[0,0,0,0,39,37,0,0,41,38,40,0,0],"FLAG":0,"BASE":18} Longlifelamps A60 9W {"NAME":"longlifelamps A60 RGBWW","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} Lumary 9W 800lm {"NAME":"Lumary / iLint","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} Luminea 5.5W 470lm {"NAME":"Luminea ZX-2983","GPIO":[0,0,0,0,0,0,0,0,181,0,180,0,0],"FLAG":0,"BASE":18} @@ -1203,7 +1243,7 @@ Nishica JBT 9W 806lm {"NAME":"Nishica","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0, Novostella 7W 600lm {"NAME":"Novostella E27","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} Novostella 7W 600lm {"NAME":"Novostella B22","GPIO":[0,0,0,0,37,41,0,0,38,40,39,0,0],"FLAG":0,"BASE":18} Novostella HM-LB09 13W 1300lm {"NAME":"Novostella 13W","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} -Novostella NTB10 9W 900lm {"NAME":"NTB10","GPIO":[0,0,0,0,41,38,0,0,39,0,40,37,0],"FLAG":0,"BASE":18} +Novostella NTB10 9W 900lm {"NAME":"NTB10","GPIO":[0,0,0,0,41,38,0,0,39,51,40,37,0],"FLAG":0,"BASE":18} Novostella UT55507 9W 900lm {"NAME":"Novostella UT55507","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} Novostella UT55507 9W 900lm {"NAME":"Novostella UT55507","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} Novostella UT55508 12W 1150lm {"NAME":"Novostella","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} @@ -1223,6 +1263,7 @@ RYE 5W 450LM Candle {"NAME":"RYE Candlebra","GPIO":[0,0,0,0,37,40,0,0,38,41 Saudio A19 7W 700lm {"NAME":"X002BU0DOL","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} Sealight A19 9W 810lm {"NAME":"DGO/SEASTAR","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} Slitinto TB95 9W 1000lm {"NAME":"Slitinto 9W","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Smart 9W 800lm {"NAME":"SmartLED ","GPIO":[0,0,0,0,41,38,0,0,39,0,40,37,0],"FLAG":0,"BASE":18} SmartLED 9W 400lm {"NAME":"SmartLED","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} Sonoff B1 (R2) {"NAME":"Sonoff B1","GPIO":[17,0,0,0,0,0,0,0,143,0,144,0,0],"FLAG":0,"BASE":26} Spectrum Smart GLS 9W 850lm {"NAME":"SPECTR. RGBCCT","GPIO":[0,0,0,0,0,0,0,0,181,0,180,0,0],"FLAG":0,"BASE":18} @@ -1233,7 +1274,8 @@ Techlux A19 9W 806lm {"NAME":"TECHLUX A19 RGBCW 806lm 9w","GPIO":[0,0,0,0,37 Teckin SB50 v3 A19 800lm {"NAME":"Teckin SB50v3","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} Teckin SB53 1300lm {"NAME":"Teckin SB53","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} Treatlife A19 8W 650lm {"NAME":"Treatlife RGBW","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} -V-Tac PAR16 4.5W 400lm 100C {"NAME":"V-TAC VT5164","GPIO":[0,0,0,0,0,0,0,0,181,0,180,0,0],"FLAG":0,"BASE":18} +V-TAC 10W 806lm {"NAME":"V-TAC VT-5119","GPIO":[0,0,0,0,180,0,0,0,0,0,181,0,0],"FLAG":0,"BASE":18} +V-Tac PAR16 4.5W 400lm 100 {"NAME":"V-TAC VT5164","GPIO":[0,0,0,0,0,0,0,0,181,0,180,0,0],"FLAG":0,"BASE":18} Vizia 5W GU10 {"NAME":"Vizia RGBWW","GPIO":[0,0,0,0,40,41,0,0,38,39,37,0,0],"FLAG":15,"BASE":18} Wipro Garnet 9W 810lm {"NAME":"Wipro","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} Zemismart 5W 480lm {"NAME":"Zemismart 5W","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} @@ -1259,7 +1301,7 @@ Avatar Controls A19 10W 900lm {"NAME":"Avatar E26 10W","GPIO":[0,0,0,0,0,39,0,0 AWOW A60 9W 800lm {"NAME":"AWOW 9W RGBW","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} Axtee AI-003 A19 700lm {"NAME":"Axtee E26 7W","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":20} Bawoo EUWL122130 925lm {"NAME":"Bawoo","GPIO":[0,0,0,0,140,37,0,0,0,142,141,0,0],"FLAG":0,"BASE":18} -BlitzWolf 900lm {"NAME":"BlitzWolf LT21","GPIO":[0,0,0,0,41,39,0,0,38,0,37,40,0],"FLAG":0,"BASE":18} +BlitzWolf 900lm {"NAME":"BlitzWolf LT21","GPIO":[0,0,0,0,0,39,0,0,38,0,37,40,0],"FLAG":0,"BASE":18} BNeta 4.5W 380lm {"NAME":"BNeta","GPIO":[0,0,0,0,141,140,0,0,37,142,0,0,0],"FLAG":0,"BASE":18} BriHome 6,5W 500lm {"NAME":"BRI E27 6,5W","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":20} Brilliant 350lm Candle {"NAME":"HK17653S72","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} @@ -1309,7 +1351,7 @@ Kainsy 600lm {"NAME":"KAINSY","GPIO":[17,0,0,0,143,144,0,0,0,0,0,0,0 Kkmoon 9W 800lm {"NAME":"KKMOON V21","GPIO":[0,0,0,0,40,0,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} Koaanw 650lm {"NAME":"KOAANW Bulb","GPIO":[0,0,0,0,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27} Kogan 10W Ambient 1050lm {"NAME":"Kogan RGB","GPIO":[0,0,0,0,140,37,0,0,0,0,141,0,0],"FLAG":0,"BASE":18} -Kogan 4.5W 330lm 110C {"NAME":"Kogan_GU10","GPIO":[0,0,0,0,39,40,0,0,37,0,38,0,0],"FLAG":0,"BASE":18} +Kogan 4.5W 330lm 110 {"NAME":"Kogan_GU10","GPIO":[0,0,0,0,39,40,0,0,37,0,38,0,0],"FLAG":0,"BASE":18} Kogan Ambient Candle {"NAME":"Kogan_E14","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} Kuled 800lm {"NAME":"KULED 60W RGB","GPIO":[0,0,0,0,39,40,0,0,37,0,38,0,0],"FLAG":1,"BASE":18} Laideyi 7W {"NAME":"7W-E14-RGBW-La","GPIO":[0,0,0,0,38,37,0,0,39,0,40,0,0],"FLAG":0,"BASE":18} @@ -1371,6 +1413,7 @@ Saudio 7W 700lm {"NAME":"X002BU0DOL","GPIO":[0,0,0,0,37,40,0,0,38,41,39 Smart 810lm {"NAME":"OOOLED 60W RGB","GPIO":[0,0,0,0,39,40,0,0,37,0,38,0,0],"FLAG":1,"BASE":18} SmartLED 9W 400lm {"NAME":"SmartLED RGBWW","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} Smartyfi 600lm {"NAME":"SMARTYFI 9W","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +Smitch 7W {"NAME":"Smitch RGB 7W SB-1602","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} Solimo 12W {"NAME":"Solimo RGBCCT 12","GPIO":[0,0,0,0,37,41,0,0,38,40,39,0,0],"FLAG":0,"BASE":18} Solimo 810lm {"NAME":"Solimo RGBWW 9","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} Swisstone SH 320 350lm {"NAME":"SH 320","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} @@ -1401,7 +1444,7 @@ Zilotek A19 800lm {"NAME":"Zilotek RGBW","GPIO":[0,0,0,0,140,37,0,0,38,14 ## Relay ``` Anmbest 2 Channel Inching Self-locking Switch Module {"NAME":"Generic","GPIO":[17,255,255,255,255,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":1} -Athom 16A {"NAME":"Athom CB0110A","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":1} +Athom 10A {"NAME":"Athom CB0110A","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":1} BH OnOfre Dual Rev5 Silent Edition {"NAME":"bhonofre","GPIO":[0,0,0,0,22,21,0,0,9,10,0,0,0],"FLAG":0,"BASE":18} DoHome HomeKit DIY Switch {"NAME":"DoHome DIY","GPIO":[255,255,0,255,255,157,0,0,21,0,0,0,0],"FLAG":0,"BASE":1} Eachen ST-DC2 {"NAME":"Garage Control","GPIO":[11,0,0,0,23,22,18,0,21,52,12,24,0],"FLAG":1,"BASE":18} @@ -1422,6 +1465,7 @@ LC Technology DC8V-80V/5V 1 Channel ESP-12F Dev Board {"NAME":"LC Relay-ESP12-1 LC Technology ESP8266 5V {"NAME":"ESP8266-01S","GPIO":[21,148,0,149,0,0,0,0,0,0,0,0,0],"FLAG":1,"BASE":18} LinkNode R4 {"NAME":"LinkNode R4","GPIO":[0,0,0,0,0,0,0,0,21,22,23,0,24],"FLAG":0,"BASE":18} LinkNode R8 {"NAME":"LinkNode R8","GPIO":[0,0,0,0,25,26,0,28,23,24,22,27,21],"FLAG":0,"BASE":18} +LoveAnna AC85-250V 10A {"NAME":"2xSwitch No RF LoveAnna","GPIO":[17,0,0,0,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":18} Mhcozy 5V {"NAME":"Portail","GPIO":[9,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":1,"BASE":18} Sinilink DC6V-36V Module {"NAME":"Sinilink XY-WF5V","GPIO":[0,0,0,0,21,255,0,0,17,52,0,0,255],"FLAG":0,"BASE":18} Sinilink MOS {"NAME":"Sinilink MOS","GPIO":[0,0,0,0,21,255,0,0,17,52,0,0,255],"FLAG":0,"BASE":18} @@ -1438,10 +1482,11 @@ Smoke Alarm {"NAME":"YG400A","GPIO":[255,107,255,108,255,255,0,0,25 ## Switch ``` +3 Way Smart Light {"NAME":"Nexete KS-602F 3-Way","GPIO":[255,255,255,255,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} 3A Smart Home {"NAME":"3A Smart Home ","GPIO":[52,0,55,18,22,19,0,0,17,21,54,23,53],"FLAG":0,"BASE":18} AGL 2 Gang {"NAME":"AGL WiFi 02","GPIO":[0,0,157,0,0,18,0,0,22,21,0,0,17],"FLAG":0,"BASE":18} AGL 3 Gang {"NAME":"AGL WiFi 03","GPIO":[0,0,157,0,19,18,0,0,22,21,23,0,17],"FLAG":0,"BASE":18} -AGL Modulo Relay 01 Canal {"NAME":"AGL-Basic","GPIO":[0,255,0,0,21,17,0,0,0,0,56,0,0],"FLAG":0,"BASE":18} +AGL Modulo Rel 01 Canal {"NAME":"AGL-Basic","GPIO":[0,255,0,0,21,17,0,0,0,0,56,0,0],"FLAG":0,"BASE":18} Albohes 2 Channel {"NAME":"Albohes SH-08","GPIO":[0,148,18,149,57,56,0,0,21,157,17,0,22],"FLAG":15,"BASE":18} Aoycocr SW1 {"NAME":"Aoycocr SW1","GPIO":[158,255,57,255,255,255,255,255,56,17,255,21,255],"FLAG":15,"BASE":18} Athom 1 Gang {"NAME":"Athom SW011EU","GPIO":[158,0,0,17,0,0,0,0,0,21,52,0,0],"FLAG":0,"BASE":1} @@ -1466,6 +1511,7 @@ BlitzWolf BW-SS3 3 Gang {"NAME":"BlitzWolf SS3","GPIO":[158,0,0,10,22,11,0,0,9, BlitzWolf BW-SS5 1 Gang {"NAME":"BlitzWolf SS5 1 Gang","GPIO":[0,0,0,0,0,0,0,0,9,21,0,0,0],"FLAG":0,"BASE":18} BlitzWolf BW-SS5 2 Gang {"NAME":"BlitzWolf SS5 2 Gang","GPIO":[0,0,17,0,160,0,0,0,10,9,21,22,0],"FLAG":0,"BASE":18} BlitzWolf SS4 {"NAME":"BlitzWolf SS4 Two Gang","GPIO":[0,0,0,0,56,21,0,0,22,17,0,0,0],"FLAG":0,"BASE":18} +BSEED 2 Gang 1 Way {"NAME":"BSEED Switch 2Ch","GPIO":[0,0,0,18,22,0,0,0,17,21,0,52,53],"FLAG":0,"BASE":18} Canwing CW-001 {"NAME":"Canwing CW-001","GPIO":[17,255,0,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} CD303 3 Gang Touch {"NAME":"Touch Switch 3","GPIO":[54,57,255,19,23,18,255,255,17,21,255,22,52],"FLAG":15,"BASE":18} Century Aoke Smart Switch {"NAME":"CenturyAoke","GPIO":[0,255,0,255,21,0,0,0,17,56,255,0,0],"FLAG":0,"BASE":18} @@ -1478,9 +1524,12 @@ Deta 6000HA Smart Inline Switch {"NAME":"DETA-6000HA","GPIO":[0,17,0,0,0,0,0,0, Deta Fan Speed Controller with Light {"NAME":"Deta Fan Speed and Light Controller","GPIO":[18,0,0,157,23,19,0,0,0,22,21,24,17],"FLAG":0,"BASE":18} dewenwils Outdoor Timer Box {"NAME":"Dewenwils50054","GPIO":[0,0,54,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} Digoo DG-S811 3 Gang {"NAME":"DIGOO Switch","GPIO":[0,0,0,0,19,18,0,0,22,21,23,0,17],"FLAG":0,"BASE":18} -DS-102 1 Gang {"NAME":"DS-102 1 Gang","GPIO":[57,0,0,17,0,0,0,0,0,21,56,0,0],"FLAG":1,"BASE":18} +DS-101 1 Gang {"NAME":"Smart Life Switch","GPIO":[0,0,0,0,0,17,0,0,0,0,0,21,52],"FLAG":0,"BASE":18} +DS-102 1 Gang {"NAME":"DS-102 1 Gang","GPIO":[158,0,0,17,0,0,0,0,0,21,52,0,0],"FLAG":0,"BASE":18} DS-102 2 Gang {"NAME":"DS-102 2 Gang","GPIO":[158,57,0,17,22,18,0,0,0,21,56,255,0],"FLAG":0,"BASE":18} DS-102 3 Gang {"NAME":"DS-102 3 Gang","GPIO":[158,58,0,18,22,19,0,0,17,21,57,23,56],"FLAG":0,"BASE":18} +DS-121 2 Gang No Neutral {"NAME":"2 Gang Switch","GPIO":[0,57,0,17,22,18,0,0,0,21,56,0,0],"FLAG":0,"BASE":18} +DS-121 4 Gang No Neutral {"NAME":"4 Gang Switch","GPIO":[52,255,255,18,22,19,0,0,17,21,24,23,20],"FLAG":0,"BASE":18} Eachen CD303 3 Gang {"NAME":"ID Components","GPIO":[157,53,0,11,21,10,0,0,9,22,54,23,52],"FLAG":15,"BASE":18} Eachen SWT-2Gang {"NAME":"ID Components","GPIO":[157,255,255,255,255,10,255,255,9,21,53,22,52],"FLAG":15,"BASE":18} eMylo 2 Channel {"NAME":"eMylo XL9252WI","GPIO":[0,255,0,0,56,22,0,0,21,0,12,0,0],"FLAG":0,"BASE":18} @@ -1537,7 +1586,7 @@ L-5A01 {"NAME":"L-5A01","GPIO":[17,255,0,255,0,0,0,0,21,56,0,0 Laghten SS02S {"NAME":"Laghten SS02S","GPIO":[0,0,0,0,52,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} LCARE Modular 2 Gang {"NAME":"2SW1-In","GPIO":[17,255,255,255,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":29} LerLink X801A-L No Neutral {"NAME":"LerLink X801-L","GPIO":[0,0,0,0,17,0,0,0,21,56,0,0,0],"FLAG":15,"BASE":18} -Lerlink X802A 2 Gang {"NAME":"Lerlink X802A","GPIO":[0,0,0,18,17,0,0,0,21,23,22,0,0],"FLAG":15,"BASE":18} +Lerlink X802A 2 Gang {"NAME":"Lerlink X802A","GPIO":[0,0,0,18,17,0,0,0,21,52,22,0,0],"FLAG":0,"BASE":18} LerLink X802A-L No Neutral {"NAME":"LerLink X802-L","GPIO":[0,0,0,18,17,0,0,0,21,158,22,0,0],"FLAG":0,"BASE":18} Lightstory WT02S {"NAME":"WT02S","GPIO":[0,0,0,0,57,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":50} Lonsonho 3 Gang {"NAME":"Lonsonho X803A","GPIO":[0,0,0,18,17,19,0,0,21,29,22,23,0],"FLAG":0,"BASE":18} @@ -1660,8 +1709,8 @@ STITCH by Monoprice 35557 {"NAME":"Tuya WF15S ","GPIO":[255,255,0,0,255,255,0,0 SUPLA inCan by Espablo {"NAME":"Supla Espablo","GPIO":[0,255,4,255,17,21,0,0,255,22,255,0,52],"FLAG":1,"BASE":31} SW-R03 {"NAME":"SW-R03","GPIO":[0,0,0,0,0,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} TCP Smart 1 Gang {"NAME":"TCP 1 Gang 1 Way","GPIO":[157,0,0,17,21,0,0,0,0,0,56,0,0],"FLAG":0,"BASE":18} +Teckin 2 Gang {"NAME":"Teckin SR43","GPIO":[0,0,52,0,0,17,0,0,21,22,0,0,18],"FLAG":0,"BASE":18} Teckin SR-41 Single Pole {"NAME":"Teckin SR-41","GPIO":[17,0,0,0,0,0,0,0,21,158,0,0,0],"FLAG":0,"BASE":18} -Teckin SR43 {"NAME":"Teckin SR43","GPIO":[0,0,52,0,0,17,0,0,21,22,0,0,18],"FLAG":0,"BASE":18} Teekar 10 Way 1 Gang {"NAME":"Teekar 10way","GPIO":[9,10,11,20,13,14,0,0,15,16,0,0,0],"FLAG":0,"BASE":18} Teekar Wi-Fi Light 1 Gang {"NAME":"TeeKar Touch","GPIO":[0,0,255,0,255,21,0,0,0,255,17,0,255],"FLAG":0,"BASE":18} Teepao Smart-Rollladen-Schalter {"NAME":"Teepao","GPIO":[158,58,23,18,22,19,0,0,56,21,57,0,17],"FLAG":0,"BASE":18} @@ -1675,10 +1724,11 @@ TreatLife SS02 3-Way {"NAME":"TreatLife 3Way","GPIO":[0,0,0,0,53,29,0,0,30,1 TreatLife SS02S {"NAME":"Treatlife SS02","GPIO":[0,0,0,0,53,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} TY-US-L1-W {"NAME":"TY-US-L1-W","GPIO":[0,0,0,0,0,17,0,0,0,21,0,0,158],"FLAG":0,"BASE":18} TY-US-L3-W {"NAME":"TY-US-L3-W","GPIO":[0,0,0,0,21,18,0,0,19,23,17,22,158],"FLAG":15,"BASE":18} -Unbranded 2 Gang {"NAME":"Smart Life Switch 2","GPIO":[157,57,0,17,21,18,0,0,0,22,56,0,0],"FLAG":0,"BASE":18} Useelink 1 Gang {"NAME":"USEELINK-SW-1G","GPIO":[52,0,0,0,0,0,0,0,17,21,0,0,0],"FLAG":0,"BASE":18} +Useelink 2 Gang {"NAME":"SM-SW101-2","GPIO":[158,52,0,18,22,0,0,0,17,21,0,0,0],"FLAG":1,"BASE":18} Useelink 3 Gang {"NAME":"Useelink 3 Gang Wall Switch","GPIO":[158,52,0,18,22,17,0,0,19,23,53,21,52],"FLAG":0,"BASE":18} Vaticas 1 {"NAME":"Vaticas","GPIO":[0,0,0,17,21,0,0,0,0,0,52,0,0],"FLAG":0,"BASE":18} +VHome RF433 1 Gang Switch {"NAME":"VH-TW-CL-01","GPIO":[0,0,0,0,0,17,0,0,0,0,0,21,157],"FLAG":15,"BASE":18} vhome RF433 3 Gang {"NAME":"VH-TB-US-003","GPIO":[0,0,0,0,21,18,0,0,19,23,17,22,158],"FLAG":15,"BASE":18} WiFi Smart Switch 2 Gang {"NAME":"Kingart N2","GPIO":[17,255,0,255,0,22,18,0,21,0,0,0,0],"FLAG":15,"BASE":18} WiFi Smart Switch 3 Gang {"NAME":"KingArt-3CH","GPIO":[17,255,0,255,23,22,18,19,21,52,0,0,0],"FLAG":15,"BASE":18} @@ -1728,7 +1778,7 @@ Owfeel EN71 {"NAME":"SmartValve","GPIO":[21,0,0,0,0,0,0,0,17,52,0,0 Aseer THWFS01 {"NAME":"ASEER-THWFS01","GPIO":[56,18,157,59,134,132,0,0,131,22,57,21,17],"FLAG":0,"BASE":18} Bestten LO-2-W {"NAME":"BESTTEN LO-2-W","GPIO":[0,0,0,0,158,17,0,0,21,0,0,0,0],"FLAG":0,"BASE":18} BlitzWolf BW-SHP8 {"NAME":"SHP8","GPIO":[0,56,0,17,134,132,0,0,131,53,21,0,0],"FLAG":0,"BASE":64} -BSEED Smart Socket / WIFI {"NAME":"BSEED Socket","GPIO":[0,0,0,0,157,52,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +BSEED Smart Socket {"NAME":"BSEED Socket","GPIO":[0,0,0,0,157,52,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} CE Smart Home {"NAME":"CE Smart Wall","GPIO":[255,255,255,255,157,17,0,0,21,255,255,255,255],"FLAG":15,"BASE":18} CE Smart Home LQ-2-W3 {"NAME":"LITESUN","GPIO":[0,0,0,0,157,17,0,0,21,0,0,0,0],"FLAG":0,"BASE":18} Deta 6922HA {"NAME":"DETA 2G GPO","GPIO":[0,0,0,0,157,0,0,0,91,21,22,0,90],"FLAG":0,"BASE":18} @@ -1742,6 +1792,7 @@ Makegood MG-AUWF01 {"NAME":"MG-AUWF01","GPIO":[56,10,157,59,134,132,0,0,13 Makegood MG-UKWSG01 {"NAME":"Aseer 2-Gang","GPIO":[57,9,157,59,134,132,0,0,131,21,56,22,10],"FLAG":0,"BASE":18} Makegood MG-UKWSW/B {"NAME":"Aseer 1-Gang","GPIO":[56,0,157,57,134,132,0,0,131,0,0,21,9],"FLAG":0,"BASE":18} Moes WWK Glass Panel {"NAME":"Smart Socket","GPIO":[0,0,0,0,52,53,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Oittm 120 {"NAME":"Oittm WS01","GPIO":[17,0,0,0,0,130,0,0,21,132,133,52,0],"FLAG":0,"BASE":18} PS-1607 {"NAME":"PS-1607","GPIO":[17,0,0,0,0,22,18,0,21,0,0,0,0],"FLAG":0,"BASE":18} Smanergy KA10 {"NAME":"KA10","GPIO":[0,56,0,17,134,132,0,0,131,53,21,0,0],"FLAG":0,"BASE":64} Sonoff IW100 {"NAME":"Sonoff IW100","GPIO":[17,145,0,146,0,0,0,0,21,157,0,0,0],"FLAG":0,"BASE":41} @@ -1756,6 +1807,7 @@ Vigica VGSPK00815 {"NAME":"VIGICA outlet","GPIO":[17,255,255,255,255,22,1 ## Water Sensor ``` W06 {"NAME":"W06 Water Sensor","GPIO":[0,148,0,149,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +Y09 {"NAME":"Y09","GPIO":[0,107,0,108,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54} ``` ## Zigbee Bridge diff --git a/platformio_tasmota_env.ini b/platformio_tasmota_env.ini index 9817fdb0f..ed4d5ce65 100644 --- a/platformio_tasmota_env.ini +++ b/platformio_tasmota_env.ini @@ -30,6 +30,8 @@ lib_ignore = EspSoftwareSerial SPISlave Hash +; Disable next if you want to use ArduinoOTA in Tasmota (default disabled) + ArduinoOTA [env:tasmota] diff --git a/platformio_tasmota_env32.ini b/platformio_tasmota_env32.ini index 58eb34a4a..04b0fa2db 100644 --- a/platformio_tasmota_env32.ini +++ b/platformio_tasmota_env32.ini @@ -21,12 +21,14 @@ lib_ignore = ESP32 Azure IoT Arduino ESP32 Async UDP ESP32 BLE Arduino - SimpleBLE +; SimpleBLE NetBIOS ESP32 Preferences BluetoothSerial - +; Disable next if you want to use ArduinoOTA in Tasmota32 (default disabled) + ArduinoOTA + [env:tasmota32-webcam] extends = env:tasmota32 board = esp32cam diff --git a/tasmota/i18n.h b/tasmota/i18n.h index a21734ae9..9649e0ec6 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -113,6 +113,7 @@ #define D_JSON_NONE "None" #define D_JSON_OR "or" #define D_JSON_ORP "ORP" +#define D_JSON_O2 "Oxygen" #define D_JSON_PERIOD "Period" #define D_JSON_PH "pH" #define D_JSON_PHASE_ANGLE "PhaseAngle" @@ -181,6 +182,7 @@ #define D_JSON_VCC "Vcc" #define D_JSON_VERSION "Version" #define D_JSON_VOLTAGE "Voltage" +#define D_JSON_VOLUME "Volume" #define D_JSON_WEIGHT "Weight" #define D_JSON_WIFI "Wifi" #define D_JSON_WRONG "Wrong" @@ -263,6 +265,7 @@ #define D_CMND_PWMRANGE "PWMRange" #define D_CMND_BUTTONDEBOUNCE "ButtonDebounce" #define D_CMND_SWITCHDEBOUNCE "SwitchDebounce" +#define D_CMND_SWITCHTEXT "SwitchText" #define D_CMND_SLEEP "Sleep" #define D_CMND_UPLOAD "Upload" #define D_CMND_UPGRADE "Upgrade" @@ -564,6 +567,8 @@ #define D_JSON_ZIGBEE_UNBIND "ZbUnbind" #define D_CMND_ZIGBEE_BIND_STATE "BindState" #define D_JSON_ZIGBEE_BIND_STATE "ZbBindState" +#define D_CMND_ZIGBEE_MAP "Map" + #define D_JSON_ZIGBEE_MAP "ZbMap" #define D_JSON_ZIGBEE_PARENT "ZbParent" #define D_CMND_ZIGBEE_PING "Ping" #define D_JSON_ZIGBEE_PING "ZbPing" @@ -574,6 +579,8 @@ #define D_JSON_ZIGBEE_STATUS_MSG "StatusMessage" #define D_CMND_ZIGBEE_LIGHT "Light" #define D_JSON_ZIGBEE_LIGHT "Light" +#define D_CMND_ZIGBEE_OCCUPANCY "Occupancy" + #define D_JSON_ZIGBEE_OCCUPANCY "Occupancy" #define D_CMND_ZIGBEE_RESTORE "Restore" #define D_CMND_ZIGBEE_CONFIG "Config" #define D_JSON_ZIGBEE_CONFIG "Config" @@ -775,6 +782,9 @@ const char HTTP_SNS_ENERGY_TOTAL[] PROGMEM = "{s}" D_ENERGY_TOTAL "{ const char HTTP_SNS_PH[] PROGMEM = "{s}%s " D_PH "{m}%s " "{e}"; const char HTTP_SNS_ORP[] PROGMEM = "{s}%s " D_ORP "{m}%s " D_UNIT_MILLIVOLT "{e}"; const char HTTP_SNS_EC[] PROGMEM = "{s}%s " D_EC "{m}%s " D_UNIT_MICROSIEMENS_PER_CM "{e}"; +const char HTTP_SNS_O2[] PROGMEM = "{s}%s " D_O2 "{m}%s " D_UNIT_PERCENT "{e}"; +const char HTTP_SNS_LITERS[] PROGMEM = "{s}%s " D_VOLUME "{m}%s " D_UNIT_LITERS "{e}"; +const char HTTP_SNS_LPM[] PROGMEM = "{s}%s " D_FLOW_RATE "{m}%s " D_UNIT_LITERS_PER_MIN "{e}"; const char S_MAIN_MENU[] PROGMEM = D_MAIN_MENU; const char S_CONFIGURATION[] PROGMEM = D_CONFIGURATION; diff --git a/tasmota/language/bg_BG.h b/tasmota/language/bg_BG.h index 59663bfa2..162c0d564 100644 --- a/tasmota/language/bg_BG.h +++ b/tasmota/language/bg_BG.h @@ -125,6 +125,7 @@ #define D_MULTI_PRESS "неколкократно натискане" #define D_NOISE "Шум" #define D_NONE "Няма" +#define D_O2 "Oxygen" #define D_OFF "Изкл." #define D_OFFLINE "Офлайн" #define D_OK "Ок" @@ -190,6 +191,7 @@ #define D_UV_POWER "UV мощност" #define D_VERSION "Версия" #define D_VOLTAGE "Напрежение" +#define D_VOLUME "Volume" #define D_WEIGHT "Тегло" #define D_WARMLIGHT "Топла" #define D_WEB_SERVER "Уеб сървър" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "lx" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "µm" diff --git a/tasmota/language/cs_CZ.h b/tasmota/language/cs_CZ.h index ca1efaf6b..e4e07aa03 100644 --- a/tasmota/language/cs_CZ.h +++ b/tasmota/language/cs_CZ.h @@ -125,6 +125,7 @@ #define D_MULTI_PRESS "několikeré-stisknutí" #define D_NOISE "Hluk" #define D_NONE "Žádný" +#define D_O2 "Oxygen" #define D_OFF "Vyp." #define D_OFFLINE "Offline" // Don't translate, LWT message! Nepředkládat, LWT zpráva! #define D_OK "OK" @@ -190,6 +191,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "Verze" #define D_VOLTAGE "Napětí" +#define D_VOLUME "Volume" #define D_WEIGHT "Hmotnost" #define D_WARMLIGHT "Teplé světlo" #define D_WEB_SERVER "Web Server" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "lx" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "µm" diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h index f7d17cced..5ab4b8df4 100644 --- a/tasmota/language/de_DE.h +++ b/tasmota/language/de_DE.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v8.4.0.3 + * Updated until v9.0.0.3 \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -125,6 +125,7 @@ #define D_MULTI_PRESS "Mehrfachdruck" #define D_NOISE "Lautstärke" #define D_NONE "keine" +#define D_O2 "Sauerstoff" #define D_OFF "aus" #define D_OFFLINE "Offline" #define D_OK "OK" @@ -190,6 +191,7 @@ #define D_UV_POWER "UV Intensität" #define D_VERSION "Version" #define D_VOLTAGE "Spannung" +#define D_VOLUME "Volume" #define D_WEIGHT "Gewicht" #define D_WARMLIGHT "warm" #define D_WEB_SERVER "Web-Server" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "lx" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "µm" diff --git a/tasmota/language/el_GR.h b/tasmota/language/el_GR.h index e516c5348..5fdbb305b 100644 --- a/tasmota/language/el_GR.h +++ b/tasmota/language/el_GR.h @@ -125,6 +125,7 @@ #define D_MULTI_PRESS "ανίχνευση για πολλαπλά πατήματα" #define D_NOISE "Θόρυβος" #define D_NONE "Κανένα" +#define D_O2 "Oxygen" #define D_OFF "Off" #define D_OFFLINE "Offline" #define D_OK "Ok" @@ -190,6 +191,7 @@ #define D_UV_POWER "Ένταση UV" #define D_VERSION "Έκδοση" #define D_VOLTAGE "Τάση" +#define D_VOLUME "Volume" #define D_WEIGHT "Βάρος" #define D_WARMLIGHT "Θερμό" #define D_WEB_SERVER "Διακομιστής Web" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "lx" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "µm" diff --git a/tasmota/language/en_GB.h b/tasmota/language/en_GB.h index bf78441af..25fa29550 100644 --- a/tasmota/language/en_GB.h +++ b/tasmota/language/en_GB.h @@ -125,6 +125,7 @@ #define D_MULTI_PRESS "multi-press" #define D_NOISE "Noise" #define D_NONE "None" +#define D_O2 "Oxygen" #define D_OFF "Off" #define D_OFFLINE "Offline" #define D_OK "Ok" @@ -190,6 +191,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "Version" #define D_VOLTAGE "Voltage" +#define D_VOLUME "Volume" #define D_WEIGHT "Weight" #define D_WARMLIGHT "Warm" #define D_WEB_SERVER "Web Server" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "lx" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "µm" diff --git a/tasmota/language/es_ES.h b/tasmota/language/es_ES.h index 3d9fe8472..88537c607 100644 --- a/tasmota/language/es_ES.h +++ b/tasmota/language/es_ES.h @@ -125,6 +125,7 @@ #define D_MULTI_PRESS "multi-press" #define D_NOISE "Ruido" #define D_NONE "Ninguno" +#define D_O2 "Oxygen" #define D_OFF "Apagado" #define D_OFFLINE "Offline" #define D_OK "Ok" @@ -190,6 +191,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "Versión" #define D_VOLTAGE "Tensión" +#define D_VOLUME "Volume" #define D_WEIGHT "Peso" #define D_WARMLIGHT "Cálida" #define D_WEB_SERVER "Servidor Web" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "lx" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "µm" diff --git a/tasmota/language/fr_FR.h b/tasmota/language/fr_FR.h index 0ec56b863..4fb5a3452 100644 --- a/tasmota/language/fr_FR.h +++ b/tasmota/language/fr_FR.h @@ -121,6 +121,7 @@ #define D_MULTI_PRESS "multi-pression" #define D_NOISE "Bruit" #define D_NONE "Aucun" +#define D_O2 "Oxygen" #define D_OFF "Arrêt" #define D_OFFLINE "Déconnecté" #define D_OK "Ok" @@ -186,6 +187,7 @@ #define D_UV_POWER "Puissance UV" #define D_VERSION "Version" #define D_VOLTAGE "Tension" +#define D_VOLUME "Volume" #define D_WEIGHT "Poids" #define D_WARMLIGHT "Chaud" #define D_WEB_SERVER "Serveur web" @@ -740,6 +742,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "lx" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "µm" diff --git a/tasmota/language/he_HE.h b/tasmota/language/he_HE.h index d4a4a9f4d..032ce5c04 100644 --- a/tasmota/language/he_HE.h +++ b/tasmota/language/he_HE.h @@ -125,6 +125,7 @@ #define D_MULTI_PRESS "לחיצה מרובה" #define D_NOISE "רעש" #define D_NONE "כלום" +#define D_O2 "Oxygen" #define D_OFF "כבוי" #define D_OFFLINE "מנותק" #define D_OK "אוקיי" @@ -190,6 +191,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "גרסה" #define D_VOLTAGE "מתח" +#define D_VOLUME "Volume" #define D_WEIGHT "משקל" #define D_WARMLIGHT "חום" #define D_WEB_SERVER "Web שרת" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "lx" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "µm" diff --git a/tasmota/language/hu_HU.h b/tasmota/language/hu_HU.h index a32f4ea24..be7590886 100644 --- a/tasmota/language/hu_HU.h +++ b/tasmota/language/hu_HU.h @@ -125,6 +125,7 @@ #define D_MULTI_PRESS "több lenyomás" #define D_NOISE "Zaj" #define D_NONE "nincs" +#define D_O2 "Oxygen" #define D_OFF "Ki" #define D_OFFLINE "Offline" #define D_OK "OK" @@ -190,6 +191,7 @@ #define D_UV_POWER "UV teljesítmény" #define D_VERSION "Verzió" #define D_VOLTAGE "Feszültség" +#define D_VOLUME "Volume" #define D_WEIGHT "Tömeg" #define D_WARMLIGHT "Meleg fény" #define D_WEB_SERVER "Webszerver" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "lx" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "µm" diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h index d169e7ae0..614d47a95 100644 --- a/tasmota/language/it_IT.h +++ b/tasmota/language/it_IT.h @@ -1,7 +1,7 @@ /* it-IT.h - localization for Italian - Italy for Tasmota - Copyright (C) 2020 Gennaro Tortone - some mods by Antonio Fragola - Updated by bovirus - rev. 03.10.2020 + Copyright (C) 2020 Gennaro Tortone - some mods by Antonio Fragola - Updated by bovirus - rev. 30.10.2020 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 @@ -125,6 +125,7 @@ #define D_MULTI_PRESS "multi-pressione" #define D_NOISE "Rumore" #define D_NONE "Nessuno" +#define D_O2 "Ossigeno" #define D_OFF "OFF" #define D_OFFLINE "Offline" #define D_OK "OK" @@ -190,6 +191,7 @@ #define D_UV_POWER "Intensità UV" #define D_VERSION "Versione" #define D_VOLTAGE "Tensione" +#define D_VOLUME "Volume" #define D_WEIGHT "Peso" #define D_WARMLIGHT "Calda" #define D_WEB_SERVER "Server web" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "lx" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "µm" diff --git a/tasmota/language/ko_KO.h b/tasmota/language/ko_KO.h index 08eddb3fa..0dce6d865 100644 --- a/tasmota/language/ko_KO.h +++ b/tasmota/language/ko_KO.h @@ -125,6 +125,7 @@ #define D_MULTI_PRESS "multi-press" #define D_NOISE "소음" #define D_NONE "없음" +#define D_O2 "Oxygen" #define D_OFF "꺼짐" #define D_OFFLINE "오프라인" #define D_OK "Ok" @@ -190,6 +191,7 @@ #define D_UV_POWER "UV 파워" #define D_VERSION "버전" #define D_VOLTAGE "전압" +#define D_VOLUME "Volume" #define D_WEIGHT "무게" #define D_WARMLIGHT "따뜻하게" #define D_WEB_SERVER "웹 서버" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "lx" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "마이크로미터" diff --git a/tasmota/language/nl_NL.h b/tasmota/language/nl_NL.h index 9ce3012fa..24e02a07f 100644 --- a/tasmota/language/nl_NL.h +++ b/tasmota/language/nl_NL.h @@ -120,11 +120,12 @@ #define D_LWT "LWT" #define D_LQI "LQI" // Zigbee Link Quality Index #define D_MODULE "Module" -#define D_MOISTURE "Moisture" +#define D_MOISTURE "Vochtigheid" #define D_MQTT "MQTT" #define D_MULTI_PRESS "meervoudig" #define D_NOISE "Lawaai" #define D_NONE "Geen" +#define D_O2 "Zuurstof" #define D_OFF "Uit" #define D_OFFLINE "Offline" #define D_OK "Ok" @@ -190,6 +191,7 @@ #define D_UV_POWER "UV intensiteit" #define D_VERSION "Versie" #define D_VOLTAGE "Spanning" +#define D_VOLUME "Volume" #define D_WEIGHT "Gewicht" #define D_WARMLIGHT "Warm" #define D_WEB_SERVER "Webserver" @@ -497,12 +499,12 @@ #define D_PARTICALS_BEYOND "Stofdeeltjes" // xsns_27_apds9960.ino -#define D_GESTURE "Gesture" -#define D_COLOR_RED "Red" -#define D_COLOR_GREEN "Green" -#define D_COLOR_BLUE "Blue" +#define D_GESTURE "Gebaar" +#define D_COLOR_RED "Rood" +#define D_COLOR_GREEN "Groen" +#define D_COLOR_BLUE "Blauw" #define D_CCT "CCT" -#define D_PROXIMITY "Proximity" +#define D_PROXIMITY "Nabijheid" // xsns_32_mpu6050.ino #define D_AX_AXIS "Versn. X-as" @@ -536,23 +538,23 @@ #define D_TX20_WEST "W" // xsns_53_sml.ino -#define D_TPWRIN "Energy Total-In" -#define D_TPWROUT "Energy Total-Out" -#define D_TPWRCURR "Active Power-In/Out" -#define D_TPWRCURR1 "Active Power-In p1" -#define D_TPWRCURR2 "Active Power-In p2" -#define D_TPWRCURR3 "Active Power-In p3" -#define D_Strom_L1 "Current L1" -#define D_Strom_L2 "Current L2" -#define D_Strom_L3 "Current L3" +#define D_TPWRIN "Totaal energie-In" +#define D_TPWROUT "Totaal energie-Uit" +#define D_TPWRCURR "Werkelijk vermogen-In/Uit" +#define D_TPWRCURR1 "Werkelijk vermogen-In p1" +#define D_TPWRCURR2 "Werkelijk vermogen-In p2" +#define D_TPWRCURR3 "Werkelijk vermogen-In p3" +#define D_Strom_L1 "Stroom L1" +#define D_Strom_L2 "Stroom L2" +#define D_Strom_L3 "Stroom L3" #define D_Spannung_L1 "Voltage L1" #define D_Spannung_L2 "Voltage L2" #define D_Spannung_L3 "Voltage L3" -#define D_METERNR "Meter_number" +#define D_METERNR "Meter_nummer" #define D_METERSID "Service ID" -#define D_GasIN "Counter" -#define D_H2oIN "Counter" -#define D_StL1L2L3 "Current L1+L2+L3" +#define D_GasIN "Teller" +#define D_H2oIN "Teller" +#define D_StL1L2L3 "Stroom L1+L2+L3" #define D_SpL1L2L3 "Voltage L1+L2+L3/3" // tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box @@ -678,9 +680,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_CLIENT_TX "Client TX" -#define D_SENSOR_CLIENT_RX "Client RX" -#define D_SENSOR_CLIENT_RESET "Client RST" +#define D_SENSOR_CLIENT_TX "Client TX" +#define D_SENSOR_CLIENT_RX "Client RX" +#define D_SENSOR_CLIENT_RESET "Client RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_HM10_RX "HM10 RX" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "lx" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "µm" @@ -778,7 +782,7 @@ #define D_TOTAL_REACTIVE "Totaal blind" #define D_UNIT_KWARH "kVArh" #define D_UNIT_ANGLE "Deg" -#define D_TOTAL_ACTIVE "Total Active" +#define D_TOTAL_ACTIVE "Totaal werkelijk" //SOLAXX1 #define D_PV1_VOLTAGE "PV1 spanning" diff --git a/tasmota/language/pl_PL.h b/tasmota/language/pl_PL.h index 2f5e6b72e..764396b4e 100644 --- a/tasmota/language/pl_PL.h +++ b/tasmota/language/pl_PL.h @@ -125,6 +125,7 @@ #define D_MULTI_PRESS "Wielokrotne naciśnięcie" #define D_NOISE "Szum" #define D_NONE "Brak" +#define D_O2 "Oxygen" #define D_OFF "Wyłączony" #define D_OFFLINE "Nieaktywny" #define D_OK "Ok" @@ -190,6 +191,7 @@ #define D_UV_POWER "Moc UV" #define D_VERSION "Wersja" #define D_VOLTAGE "Napięcie" +#define D_VOLUME "Volume" #define D_WEIGHT "Waga" #define D_WARMLIGHT "Temperatura światła" #define D_WEB_SERVER "Serwer Web" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "lx" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "µm" diff --git a/tasmota/language/pt_BR.h b/tasmota/language/pt_BR.h index f1f900acf..fc69677ab 100644 --- a/tasmota/language/pt_BR.h +++ b/tasmota/language/pt_BR.h @@ -125,6 +125,7 @@ #define D_MULTI_PRESS "multi-pressão" #define D_NOISE "Ruído" #define D_NONE "Nenhum" +#define D_O2 "Oxygen" #define D_OFF "Desligado" #define D_OFFLINE "Desconectado" #define D_OK "Ok" @@ -190,6 +191,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "Versão" #define D_VOLTAGE "Voltagem" +#define D_VOLUME "Volume" #define D_WEIGHT "Peso" #define D_WARMLIGHT "Luz quente" #define D_WEB_SERVER "Servidor WEB" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "lx" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "µm" diff --git a/tasmota/language/pt_PT.h b/tasmota/language/pt_PT.h index 94daa7603..a3b7a5542 100644 --- a/tasmota/language/pt_PT.h +++ b/tasmota/language/pt_PT.h @@ -125,6 +125,7 @@ #define D_MULTI_PRESS "multi-pressão" #define D_NOISE "Ruído" #define D_NONE "Nenhum" +#define D_O2 "Oxygen" #define D_OFF "Off" #define D_OFFLINE "Desconetado" #define D_OK "Ok" @@ -190,6 +191,7 @@ #define D_UV_POWER "Poder UV" #define D_VERSION "Versão" #define D_VOLTAGE "Voltagem" +#define D_VOLUME "Volume" #define D_WEIGHT "Peso" #define D_WARMLIGHT "Luz Quente" #define D_WEB_SERVER "Servidor WEB" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "lx" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "µm" diff --git a/tasmota/language/ro_RO.h b/tasmota/language/ro_RO.h index 432e66877..eea0cc635 100644 --- a/tasmota/language/ro_RO.h +++ b/tasmota/language/ro_RO.h @@ -125,6 +125,7 @@ #define D_MULTI_PRESS "selectare multiplă" #define D_NOISE "Zgomot" #define D_NONE "Lipsă" +#define D_O2 "Oxygen" #define D_OFF "Închis" #define D_OFFLINE "Offline" #define D_OK "Ok" @@ -190,6 +191,7 @@ #define D_UV_POWER "Putere UV" #define D_VERSION "Versiune" #define D_VOLTAGE "Voltaj" +#define D_VOLUME "Volume" #define D_WEIGHT "Greutate" #define D_WARMLIGHT "Cald" #define D_WEB_SERVER "Server Web" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "lx" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "µm" diff --git a/tasmota/language/ru_RU.h b/tasmota/language/ru_RU.h index 83292385c..8e51ec376 100644 --- a/tasmota/language/ru_RU.h +++ b/tasmota/language/ru_RU.h @@ -125,6 +125,7 @@ #define D_MULTI_PRESS "многократное нажатие" #define D_NOISE "Шум" #define D_NONE "Нет" +#define D_O2 "Oxygen" #define D_OFF "Выкл" #define D_OFFLINE "Офф-лайн" #define D_OK "Ок" @@ -190,6 +191,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "Версия" #define D_VOLTAGE "Напряжение" +#define D_VOLUME "Volume" #define D_WEIGHT "Weight" #define D_WARMLIGHT "Тепло" #define D_WEB_SERVER "Web сервер" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "кОм" #define D_UNIT_KILOWATTHOUR "кВт" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "лк" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "мкг/м³" #define D_UNIT_MICROMETER "мкм" diff --git a/tasmota/language/sk_SK.h b/tasmota/language/sk_SK.h index 7e8df3c03..c84590e18 100644 --- a/tasmota/language/sk_SK.h +++ b/tasmota/language/sk_SK.h @@ -125,6 +125,7 @@ #define D_MULTI_PRESS "multi-stlačenie" #define D_NOISE "Hluk" #define D_NONE "Žiadny" +#define D_O2 "Oxygen" #define D_OFF "Vyp." #define D_OFFLINE "Neaktívny" #define D_OK "OK" @@ -190,6 +191,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "Verzia" #define D_VOLTAGE "Napätie" +#define D_VOLUME "Volume" #define D_WEIGHT "Hmotnosť" #define D_WARMLIGHT "Teplé svetlo" #define D_WEB_SERVER "Web Server" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "lx" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "µm" diff --git a/tasmota/language/sv_SE.h b/tasmota/language/sv_SE.h index 58283b3d5..615669f74 100644 --- a/tasmota/language/sv_SE.h +++ b/tasmota/language/sv_SE.h @@ -125,6 +125,7 @@ #define D_MULTI_PRESS "fler tryck" #define D_NOISE "Oväsen" #define D_NONE "Ingen" +#define D_O2 "Oxygen" #define D_OFF "Av" #define D_OFFLINE "Off-line" #define D_OK "Ok" @@ -190,6 +191,7 @@ #define D_UV_POWER "UV kraft" #define D_VERSION "Version" #define D_VOLTAGE "Volttal" +#define D_VOLUME "Volume" #define D_WEIGHT "Vikt" #define D_WARMLIGHT "Varm" #define D_WEB_SERVER "Webbserver" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "lx" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "µm" diff --git a/tasmota/language/tr_TR.h b/tasmota/language/tr_TR.h index 37564aa84..29558e865 100644 --- a/tasmota/language/tr_TR.h +++ b/tasmota/language/tr_TR.h @@ -125,6 +125,7 @@ #define D_MULTI_PRESS "multi-press" #define D_NOISE "Noise" #define D_NONE "None" +#define D_O2 "Oxygen" #define D_OFF "Off" #define D_OFFLINE "Çevirimdışı" #define D_OK "Tamam" @@ -190,6 +191,7 @@ #define D_UV_POWER "UV Power" #define D_VERSION "Versiyon" #define D_VOLTAGE "Voltaj" +#define D_VOLUME "Volume" #define D_WEIGHT "Weight" #define D_WARMLIGHT "Sıcak" #define D_WEB_SERVER "Web Sunucusu" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "lx" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "µm" diff --git a/tasmota/language/uk_UA.h b/tasmota/language/uk_UA.h index b926afada..f5b0d3e9a 100644 --- a/tasmota/language/uk_UA.h +++ b/tasmota/language/uk_UA.h @@ -125,6 +125,7 @@ #define D_MULTI_PRESS "Багаторазове натискання" #define D_NOISE "Шум" #define D_NONE "Нічого" +#define D_O2 "Oxygen" #define D_OFF "Вимкнено" #define D_OFFLINE "Неактивний" #define D_OK "Ок" @@ -190,6 +191,7 @@ #define D_UV_POWER "Потужність УФ" #define D_VERSION "Версія" #define D_VOLTAGE "Напруга" +#define D_VOLUME "Volume" #define D_WEIGHT "Вага" #define D_WARMLIGHT "Тепло" #define D_WEB_SERVER "Web сервер" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "км/г" // or "km/h" #define D_UNIT_KILOOHM "㏀" #define D_UNIT_KILOWATTHOUR "кВт/г" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "лк" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "µг/м³" #define D_UNIT_MICROMETER "µм" diff --git a/tasmota/language/vi_VN.h b/tasmota/language/vi_VN.h index eee00907c..c1dd6ed19 100644 --- a/tasmota/language/vi_VN.h +++ b/tasmota/language/vi_VN.h @@ -125,6 +125,7 @@ #define D_MULTI_PRESS "bấm nhiều lần" #define D_NOISE "Nhiễu" #define D_NONE "Không" +#define D_O2 "Oxygen" #define D_OFF "Tắt" #define D_OFFLINE "Ngoại tuyến" #define D_OK "Ok" @@ -190,6 +191,7 @@ #define D_UV_POWER "Công suất UV" #define D_VERSION "Phiên bản" #define D_VOLTAGE "Điện áp" +#define D_VOLUME "Volume" #define D_WEIGHT "Cân nặng" #define D_WARMLIGHT "Ấm" #define D_WEB_SERVER "Máy chủ Web" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "lx" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "µm" diff --git a/tasmota/language/zh_CN.h b/tasmota/language/zh_CN.h index 9a232796a..fa9c04339 100644 --- a/tasmota/language/zh_CN.h +++ b/tasmota/language/zh_CN.h @@ -125,6 +125,7 @@ #define D_MULTI_PRESS "多次按键" #define D_NOISE "嘈杂" #define D_NONE "无" +#define D_O2 "Oxygen" #define D_OFF "关" #define D_OFFLINE "离线" #define D_OK "好" @@ -190,6 +191,7 @@ #define D_UV_POWER "紫外线功率 " #define D_VERSION "版本" #define D_VOLTAGE "电压" +#define D_VOLUME "Volume" #define D_WEIGHT "重量" #define D_WARMLIGHT "暖" #define D_WEB_SERVER "Web Server" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "公里/时" // or "km/h" #define D_UNIT_KILOOHM "千欧" #define D_UNIT_KILOWATTHOUR "千瓦时" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "勒克斯" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "微克/立方米" #define D_UNIT_MICROMETER "微米" diff --git a/tasmota/language/zh_TW.h b/tasmota/language/zh_TW.h index fb93ef634..0dd6d15d4 100644 --- a/tasmota/language/zh_TW.h +++ b/tasmota/language/zh_TW.h @@ -125,6 +125,7 @@ #define D_MULTI_PRESS "多重點擊" #define D_NOISE "雜訊" #define D_NONE "無" +#define D_O2 "Oxygen" #define D_OFF "關閉" #define D_OFFLINE "離線" #define D_OK "好" @@ -190,6 +191,7 @@ #define D_UV_POWER "紫外線能量" #define D_VERSION "版本" #define D_VOLTAGE "電壓" +#define D_VOLUME "Volume" #define D_WEIGHT "重量" #define D_WARMLIGHT "暖光" #define D_WEB_SERVER "網頁伺服器" @@ -744,6 +746,8 @@ #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "千歐姆" #define D_UNIT_KILOWATTHOUR "千瓦小時" +#define D_UNIT_LITERS "L" +#define D_UNIT_LITERS_PER_MIN "L/m" #define D_UNIT_LUX "lux" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "微克/立方公尺" #define D_UNIT_MICROMETER "微米" diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index e1497d93a..b0b06a64e 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -90,7 +90,7 @@ #define MQTT_LOG_LEVEL LOG_LEVEL_NONE // [MqttLog] (LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE) // -- Ota ----------------------------------------- -#define OTA_URL "http://ota.tasmota.com/tasmota/release/tasmota.bin" // [OtaUrl] +#define OTA_URL "http://ota.tasmota.com/tasmota/release/tasmota.bin.gz" // [OtaUrl] #define OTA_COMPATIBILITY false // [SetOption78] Disable OTA compatibility check // -- MQTT ---------------------------------------- @@ -568,6 +568,9 @@ // #define USE_EZOHUM // [I2cDriver55] Enable support for EZO's HUM sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) // #define USE_EZOEC // [I2cDriver55] Enable support for EZO's EC sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) // #define USE_EZOCO2 // [I2cDriver55] Enable support for EZO's CO2 sensor (+0k2 code) - Shared EZO code required for any EZO device (+1k2 code) +// #define USE_EZOO2 // [I2cDriver55] Enable support for EZO's O2 sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) +// #define USE_EZOPRS // [I2cDriver55] Enable support for EZO's PRS sensor (+0k7 code) - Shared EZO code required for any EZO device (+1k2 code) +// #define USE_EZOFLO // [I2cDriver55] Enable support for EZO's FLO sensor (+0k4 code) - Shared EZO code required for any EZO device (+1k2 code) // #define USE_DISPLAY // Add I2C Display Support (+2k code) #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 @@ -719,6 +722,7 @@ #define USE_ZIGBEE_COALESCE_ATTR_TIMER 350 // timer to coalesce attribute values (in ms) #define USE_ZIGBEE_MODELID "Tasmota Z2T" // reported "ModelId" (cluster 0000 / attribute 0005) #define USE_ZIGBEE_MANUFACTURER "Tasmota" // reported "Manufacturer" (cluster 0000 / attribute 0004) + #define USE_ZBBRIDGE_TLS // TLS support for zbbridge // -- Other sensors/drivers ----------------------- diff --git a/tasmota/settings.ino b/tasmota/settings.ino index a40f84aee..c1aa605e1 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -321,7 +321,7 @@ uint32_t GetSettingsCrc32(void) void SettingsSaveAll(void) { if (Settings.flag.save_state) { - Settings.power = power; + Settings.power = TasmotaGlobal.power; } else { Settings.power = 0; } @@ -526,12 +526,12 @@ void SettingsSave(uint8_t rotate) UpdateBackwardCompatibility(); if ((GetSettingsCrc32() != settings_crc32) || rotate) { if (1 == rotate) { // Use eeprom flash slot only and disable flash rotate from now on (upgrade) - stop_flash_rotate = 1; + TasmotaGlobal.stop_flash_rotate = 1; } if (2 == rotate) { // Use eeprom flash slot and erase next flash slots if stop_flash_rotate is off (default) settings_location = SETTINGS_LOCATION +1; } - if (stop_flash_rotate) { + if (TasmotaGlobal.stop_flash_rotate) { settings_location = SETTINGS_LOCATION; } else { settings_location--; @@ -555,7 +555,7 @@ void SettingsSave(uint8_t rotate) ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings)); } - if (!stop_flash_rotate && rotate) { + if (!TasmotaGlobal.stop_flash_rotate && rotate) { for (uint32_t i = 1; i < CFG_ROTATES; i++) { ESP.flashEraseSector(settings_location -i); // Delete previous configurations by resetting to 0xFF delay(1); @@ -615,7 +615,7 @@ void SettingsLoad(void) { void EspErase(uint32_t start_sector, uint32_t end_sector) { - bool serial_output = (LOG_LEVEL_DEBUG_MORE <= seriallog_level); + bool serial_output = (LOG_LEVEL_DEBUG_MORE <= TasmotaGlobal.seriallog_level); for (uint32_t sector = start_sector; sector < end_sector; sector++) { bool result = ESP.flashEraseSector(sector); // Arduino core - erases flash as seen by SDK diff --git a/tasmota/support.ino b/tasmota/support.ino index dd51c8004..bcaac70c4 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -607,7 +607,7 @@ bool NewerVersion(char* version_str) char* GetPowerDevice(char* dest, uint32_t idx, size_t size, uint32_t option) { strncpy_P(dest, S_RSLT_POWER, size); // POWER - if ((devices_present + option) > 1) { + if ((TasmotaGlobal.devices_present + option) > 1) { char sidx[8]; snprintf_P(sidx, sizeof(sidx), PSTR("%d"), idx); // x strncat(dest, sidx, size - strlen(dest) -1); // POWERx @@ -629,12 +629,12 @@ void GetEspHardwareType(void) // uint32_t efuse3 = *(uint32_t*)(0x3FF00058); // uint32_t efuse4 = *(uint32_t*)(0x3FF0005C); - is_8285 = ( (efuse1 & (1 << 4)) || (efuse2 & (1 << 16)) ); - if (is_8285 && (ESP.getFlashChipRealSize() > 1048576)) { - is_8285 = false; // ESP8285 can only have 1M flash + TasmotaGlobal.is_8285 = ( (efuse1 & (1 << 4)) || (efuse2 & (1 << 16)) ); + if (TasmotaGlobal.is_8285 && (ESP.getFlashChipRealSize() > 1048576)) { + TasmotaGlobal.is_8285 = false; // ESP8285 can only have 1M flash } #else - is_8285 = false; // ESP8285 can only have 1M flash + TasmotaGlobal.is_8285 = false; // ESP8285 can only have 1M flash #endif } @@ -642,7 +642,7 @@ String GetDeviceHardware(void) { char buff[10]; #ifdef ESP8266 - if (is_8285) { + if (TasmotaGlobal.is_8285) { strcpy_P(buff, PSTR("ESP8285")); } else { strcpy_P(buff, PSTR("ESP8266EX")); @@ -657,8 +657,8 @@ float ConvertTemp(float c) { float result = c; - global_update = uptime; - global_temperature_celsius = c; + TasmotaGlobal.global_update = TasmotaGlobal.uptime; + TasmotaGlobal.temperature_celsius = c; if (!isnan(c) && Settings.flag.temperature_conversion) { // SetOption8 - Switch between Celsius or Fahrenheit result = c * 1.8 + 32; // Fahrenheit @@ -688,8 +688,8 @@ float ConvertHumidity(float h) { float result = h; - global_update = uptime; - global_humidity = h; + TasmotaGlobal.global_update = TasmotaGlobal.uptime; + TasmotaGlobal.humidity = h; result = result + (0.1 * Settings.hum_comp); @@ -717,8 +717,8 @@ float ConvertPressure(float p) { float result = p; - global_update = uptime; - global_pressure_hpa = p; + TasmotaGlobal.global_update = TasmotaGlobal.uptime; + TasmotaGlobal.pressure_hpa = p; if (!isnan(p) && Settings.flag.pressure_conversion) { // SetOption24 - Switch between hPa or mmHg pressure unit result = p * 0.75006375541921; // mmHg @@ -726,6 +726,14 @@ float ConvertPressure(float p) return result; } +float ConvertPressureForSeaLevel(float pressure) +{ + if (pressure == 0.0f) + return pressure; + + return ConvertPressure((pressure / FastPrecisePow(1.0 - ((float)Settings.altitude / 44330.0f), 5.255f)) - 21.6f); +} + String PressureUnit(void) { return (Settings.flag.pressure_conversion) ? String(D_UNIT_MILLIMETER_MERCURY) : String(D_UNIT_PRESSURE); @@ -745,11 +753,11 @@ String SpeedUnit(void) void ResetGlobalValues(void) { - if ((uptime - global_update) > GLOBAL_VALUES_VALID) { // Reset after 5 minutes - global_update = 0; - global_temperature_celsius = NAN; - global_humidity = 0.0f; - global_pressure_hpa = 0.0f; + if ((TasmotaGlobal.uptime - TasmotaGlobal.global_update) > GLOBAL_VALUES_VALID) { // Reset after 5 minutes + TasmotaGlobal.global_update = 0; + TasmotaGlobal.temperature_celsius = NAN; + TasmotaGlobal.humidity = 0.0f; + TasmotaGlobal.pressure_hpa = 0.0f; } } @@ -902,10 +910,18 @@ String GetSerialConfig(void) { } void SetSerialBegin(void) { - baudrate = Settings.baudrate * 300; - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_SERIAL "Set to %s %d bit/s"), GetSerialConfig().c_str(), baudrate); + TasmotaGlobal.baudrate = Settings.baudrate * 300; + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_SERIAL "Set to %s %d bit/s"), GetSerialConfig().c_str(), TasmotaGlobal.baudrate); Serial.flush(); - Serial.begin(baudrate, (SerialConfig)pgm_read_byte(kTasmotaSerialConfig + Settings.serial_config)); +#ifdef ESP8266 + Serial.begin(TasmotaGlobal.baudrate, (SerialConfig)pgm_read_byte(kTasmotaSerialConfig + Settings.serial_config)); +#else // ESP32 + delay(10); // Allow time to cleanup queues - if not used hangs ESP32 + Serial.end(); + delay(10); // Allow time to cleanup queues - if not used hangs ESP32 + uint32_t config = pgm_read_dword(kTasmotaSerialConfig + Settings.serial_config); + Serial.begin(TasmotaGlobal.baudrate, config); +#endif } void SetSerialConfig(uint32_t serial_config) { @@ -918,29 +934,29 @@ void SetSerialConfig(uint32_t serial_config) { } } -void SetSerialBaudrate(uint32_t ubaudrate) { - baudrate = ubaudrate; - Settings.baudrate = baudrate / 300; - if (Serial.baudRate() != baudrate) { +void SetSerialBaudrate(uint32_t baudrate) { + TasmotaGlobal.baudrate = baudrate; + Settings.baudrate = TasmotaGlobal.baudrate / 300; + if (Serial.baudRate() != TasmotaGlobal.baudrate) { SetSerialBegin(); } } -void SetSerial(uint32_t ubaudrate, uint32_t serial_config) { +void SetSerial(uint32_t baudrate, uint32_t serial_config) { Settings.flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG Settings.serial_config = serial_config; - baudrate = ubaudrate; - Settings.baudrate = baudrate / 300; + TasmotaGlobal.baudrate = baudrate; + Settings.baudrate = TasmotaGlobal.baudrate / 300; SetSeriallog(LOG_LEVEL_NONE); SetSerialBegin(); } void ClaimSerial(void) { - serial_local = true; + TasmotaGlobal.serial_local = true; AddLog_P(LOG_LEVEL_INFO, PSTR("SNS: Hardware Serial")); SetSeriallog(LOG_LEVEL_NONE); - baudrate = Serial.baudRate(); - Settings.baudrate = baudrate / 300; + TasmotaGlobal.baudrate = Serial.baudRate(); + Settings.baudrate = TasmotaGlobal.baudrate / 300; } void SerialSendRaw(char *codes) @@ -1073,12 +1089,16 @@ char* ResponseGetTime(uint32_t format, char* time_str) return time_str; } +void ResponseClear(void) { + TasmotaGlobal.mqtt_data[0] = '\0'; +} + int Response_P(const char* format, ...) // Content send snprintf_P char data { // This uses char strings. Be aware of sending %% if % is needed va_list args; va_start(args, format); - int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), format, args); + int len = vsnprintf_P(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), format, args); va_end(args); return len; } @@ -1089,10 +1109,10 @@ int ResponseTime_P(const char* format, ...) // Content send snprintf_P char d va_list args; va_start(args, format); - ResponseGetTime(Settings.flag2.time_format, mqtt_data); + ResponseGetTime(Settings.flag2.time_format, TasmotaGlobal.mqtt_data); - int mlen = strlen(mqtt_data); - int len = vsnprintf_P(mqtt_data + mlen, sizeof(mqtt_data) - mlen, format, args); + int mlen = strlen(TasmotaGlobal.mqtt_data); + int len = vsnprintf_P(TasmotaGlobal.mqtt_data + mlen, sizeof(TasmotaGlobal.mqtt_data) - mlen, format, args); va_end(args); return len + mlen; } @@ -1102,8 +1122,8 @@ int ResponseAppend_P(const char* format, ...) // Content send snprintf_P char d // This uses char strings. Be aware of sending %% if % is needed va_list args; va_start(args, format); - int mlen = strlen(mqtt_data); - int len = vsnprintf_P(mqtt_data + mlen, sizeof(mqtt_data) - mlen, format, args); + int mlen = strlen(TasmotaGlobal.mqtt_data); + int len = vsnprintf_P(TasmotaGlobal.mqtt_data + mlen, sizeof(TasmotaGlobal.mqtt_data) - mlen, format, args); va_end(args); return len + mlen; } @@ -1225,7 +1245,7 @@ void DumpConvertTable(void) { lines++; } } - mqtt_data[0] = '\0'; + ResponseClear(); } */ #endif // ESP8266 @@ -1238,8 +1258,8 @@ uint32_t ICACHE_RAM_ATTR Pin(uint32_t gpio, uint32_t index) { real_gpio += index; mask = 0xFFFF; } - for (uint32_t i = 0; i < ARRAY_SIZE(gpio_pin); i++) { - if ((gpio_pin[i] & mask) == real_gpio) { + for (uint32_t i = 0; i < ARRAY_SIZE(TasmotaGlobal.gpio_pin); i++) { + if ((TasmotaGlobal.gpio_pin[i] & mask) == real_gpio) { return i; // Pin number configured for gpio } } @@ -1252,15 +1272,15 @@ bool PinUsed(uint32_t gpio, uint32_t index) { } uint32_t GetPin(uint32_t lpin) { - if (lpin < ARRAY_SIZE(gpio_pin)) { - return gpio_pin[lpin]; + if (lpin < ARRAY_SIZE(TasmotaGlobal.gpio_pin)) { + return TasmotaGlobal.gpio_pin[lpin]; } else { return GPIO_NONE; } } void SetPin(uint32_t lpin, uint32_t gpio) { - gpio_pin[lpin] = gpio; + TasmotaGlobal.gpio_pin[lpin] = gpio; } void DigitalWrite(uint32_t gpio_pin, uint32_t index, uint32_t state) @@ -1422,7 +1442,7 @@ void ModuleDefault(uint32_t module) void SetModuleType(void) { - my_module_type = (USER_MODULE == Settings.module) ? Settings.user_template_base : Settings.module; + TasmotaGlobal.module_type = (USER_MODULE == Settings.module) ? Settings.user_template_base : Settings.module; } bool FlashPin(uint32_t pin) @@ -1436,7 +1456,7 @@ uint32_t ValidPin(uint32_t pin, uint32_t gpio) return GPIO_NONE; // Disable flash pins GPIO6, GPIO7, GPIO8 and GPIO11 } -// if (!is_8285 && !Settings.flag3.user_esp8285_enable) { // SetOption51 - Enable ESP8285 user GPIO's +// if (!TasmotaGlobal.is_8285 && !Settings.flag3.user_esp8285_enable) { // SetOption51 - Enable ESP8285 user GPIO's if ((WEMOS == Settings.module) && !Settings.flag3.user_esp8285_enable) { // SetOption51 - Enable ESP8285 user GPIO's if ((9 == pin) || (10 == pin)) { return GPIO_NONE; // Disable possible flash GPIO9 and GPIO10 @@ -1632,7 +1652,7 @@ bool TimeReached(uint32_t timer) return (passed >= 0); } -void SetNextTimeInterval(unsigned long& timer, const unsigned long step) +void SetNextTimeInterval(uint32_t& timer, const uint32_t step) { timer += step; const long passed = TimePassedSince(timer); @@ -1919,15 +1939,15 @@ bool I2cSetDevice(uint32_t addr) void SetSeriallog(uint32_t loglevel) { Settings.seriallog_level = loglevel; - seriallog_level = loglevel; - seriallog_timer = 0; + TasmotaGlobal.seriallog_level = loglevel; + TasmotaGlobal.seriallog_timer = 0; } void SetSyslog(uint32_t loglevel) { Settings.syslog_level = loglevel; - syslog_level = loglevel; - syslog_timer = 0; + TasmotaGlobal.syslog_level = loglevel; + TasmotaGlobal.syslog_timer = 0; } #ifdef USE_WEBSERVER @@ -1937,7 +1957,7 @@ void GetLog(uint32_t idx, char** entry_pp, size_t* len_p) size_t len = 0; if (idx) { - char* it = web_log; + char* it = TasmotaGlobal.web_log; do { uint32_t cur_idx = *it; it++; @@ -1949,7 +1969,7 @@ void GetLog(uint32_t idx, char** entry_pp, size_t* len_p) break; } it += tmp; - } while (it < web_log + WEB_LOG_SIZE && *it != '\0'); + } while (it < TasmotaGlobal.web_log + WEB_LOG_SIZE && *it != '\0'); } *entry_pp = entry_p; *len_p = len; @@ -1958,7 +1978,7 @@ void GetLog(uint32_t idx, char** entry_pp, size_t* len_p) void Syslog(void) { - // Destroys log_data + // Destroys TasmotaGlobal.log_data uint32_t current_hash = GetHash(SettingsText(SET_SYSLOG_HOST), strlen(SettingsText(SET_SYSLOG_HOST))); if (syslog_host_hash != current_hash) { @@ -1968,15 +1988,15 @@ void Syslog(void) if (PortUdp.beginPacket(syslog_host_addr, Settings.syslog_port)) { char syslog_preamble[64]; // Hostname + Id snprintf_P(syslog_preamble, sizeof(syslog_preamble), PSTR("%s ESP-"), NetworkHostname()); - memmove(log_data + strlen(syslog_preamble), log_data, sizeof(log_data) - strlen(syslog_preamble)); - log_data[sizeof(log_data) -1] = '\0'; - memcpy(log_data, syslog_preamble, strlen(syslog_preamble)); - PortUdp_write(log_data, strlen(log_data)); + memmove(TasmotaGlobal.log_data + strlen(syslog_preamble), TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data) - strlen(syslog_preamble)); + TasmotaGlobal.log_data[sizeof(TasmotaGlobal.log_data) -1] = '\0'; + memcpy(TasmotaGlobal.log_data, syslog_preamble, strlen(syslog_preamble)); + PortUdp_write(TasmotaGlobal.log_data, strlen(TasmotaGlobal.log_data)); PortUdp.endPacket(); delay(1); // Add time for UDP handling (#5512) } else { - syslog_level = 0; - syslog_timer = SYSLOG_TIMER; + TasmotaGlobal.syslog_level = 0; + TasmotaGlobal.syslog_timer = SYSLOG_TIMER; AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SYSLOG_HOST_NOT_FOUND ". " D_RETRY_IN " %d " D_UNIT_SECOND), SYSLOG_TIMER); } } @@ -1986,57 +2006,61 @@ void AddLog(uint32_t loglevel) char mxtime[10]; // "13:45:21 " snprintf_P(mxtime, sizeof(mxtime), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d "), RtcTime.hour, RtcTime.minute, RtcTime.second); - if ((loglevel <= seriallog_level) && - (masterlog_level <= seriallog_level)) { - Serial.printf("%s%s\r\n", mxtime, log_data); + if ((loglevel <= TasmotaGlobal.seriallog_level) && + (TasmotaGlobal.masterlog_level <= TasmotaGlobal.seriallog_level)) { + Serial.printf("%s%s\r\n", mxtime, TasmotaGlobal.log_data); } #ifdef USE_WEBSERVER if (Settings.webserver && (loglevel <= Settings.weblog_level) && - (masterlog_level <= Settings.weblog_level)) { + (TasmotaGlobal.masterlog_level <= Settings.weblog_level)) { // Delimited, zero-terminated buffer of log lines. // Each entry has this format: [index][log data]['\1'] - web_log_index &= 0xFF; - if (!web_log_index) web_log_index++; // Index 0 is not allowed as it is the end of char string - while (web_log_index == web_log[0] || // If log already holds the next index, remove it - strlen(web_log) + strlen(log_data) + 13 > WEB_LOG_SIZE) // 13 = web_log_index + mxtime + '\1' + '\0' + TasmotaGlobal.web_log_index &= 0xFF; + if (!TasmotaGlobal.web_log_index) { + TasmotaGlobal.web_log_index++; // Index 0 is not allowed as it is the end of char string + } + while (TasmotaGlobal.web_log_index == TasmotaGlobal.web_log[0] || // If log already holds the next index, remove it + strlen(TasmotaGlobal.web_log) + strlen(TasmotaGlobal.log_data) + 13 > WEB_LOG_SIZE) // 13 = web_log_index + mxtime + '\1' + '\0' { - char* it = web_log; + char* it = TasmotaGlobal.web_log; it++; // Skip web_log_index it += strchrspn(it, '\1'); // Skip log line it++; // Skip delimiting "\1" - memmove(web_log, it, WEB_LOG_SIZE -(it-web_log)); // Move buffer forward to remove oldest log line + memmove(TasmotaGlobal.web_log, it, WEB_LOG_SIZE -(it-TasmotaGlobal.web_log)); // Move buffer forward to remove oldest log line + } + snprintf_P(TasmotaGlobal.web_log, sizeof(TasmotaGlobal.web_log), PSTR("%s%c%s%s\1"), TasmotaGlobal.web_log, TasmotaGlobal.web_log_index++, mxtime, TasmotaGlobal.log_data); + TasmotaGlobal.web_log_index &= 0xFF; + if (!TasmotaGlobal.web_log_index) { + TasmotaGlobal.web_log_index++; // Index 0 is not allowed as it is the end of char string } - snprintf_P(web_log, sizeof(web_log), PSTR("%s%c%s%s\1"), web_log, web_log_index++, mxtime, log_data); - web_log_index &= 0xFF; - if (!web_log_index) web_log_index++; // Index 0 is not allowed as it is the end of char string } #endif // USE_WEBSERVER if (Settings.flag.mqtt_enabled && // SetOption3 - Enable MQTT - !global_state.mqtt_down && + !TasmotaGlobal.global_state.mqtt_down && (loglevel <= Settings.mqttlog_level) && - (masterlog_level <= Settings.mqttlog_level)) { MqttPublishLogging(mxtime); } + (TasmotaGlobal.masterlog_level <= Settings.mqttlog_level)) { MqttPublishLogging(mxtime); } - if (!global_state.network_down && - (loglevel <= syslog_level) && - (masterlog_level <= syslog_level)) { Syslog(); } + if (!TasmotaGlobal.global_state.network_down && + (loglevel <= TasmotaGlobal.syslog_level) && + (TasmotaGlobal.masterlog_level <= TasmotaGlobal.syslog_level)) { Syslog(); } - prepped_loglevel = 0; + TasmotaGlobal.prepped_loglevel = 0; } void AddLog_P(uint32_t loglevel, const char *formatP) { - snprintf_P(log_data, sizeof(log_data), formatP); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), formatP); AddLog(loglevel); } void AddLog_P(uint32_t loglevel, const char *formatP, const char *formatP2) { - char message[sizeof(log_data)]; + char message[sizeof(TasmotaGlobal.log_data)]; - snprintf_P(log_data, sizeof(log_data), formatP); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), formatP); snprintf_P(message, sizeof(message), formatP2); - strncat(log_data, message, sizeof(log_data) - strlen(log_data) -1); + strncat(TasmotaGlobal.log_data, message, sizeof(TasmotaGlobal.log_data) - strlen(TasmotaGlobal.log_data) -1); AddLog(loglevel); } @@ -2044,17 +2068,17 @@ void PrepLog_P2(uint32_t loglevel, PGM_P formatP, ...) { va_list arg; va_start(arg, formatP); - vsnprintf_P(log_data, sizeof(log_data), formatP, arg); + vsnprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), formatP, arg); va_end(arg); - prepped_loglevel = loglevel; + TasmotaGlobal.prepped_loglevel = loglevel; } void AddLog_P2(uint32_t loglevel, PGM_P formatP, ...) { va_list arg; va_start(arg, formatP); - vsnprintf_P(log_data, sizeof(log_data), formatP, arg); + vsnprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), formatP, arg); va_end(arg); AddLog(loglevel); @@ -2064,7 +2088,7 @@ void AddLog_Debug(PGM_P formatP, ...) { va_list arg; va_start(arg, formatP); - vsnprintf_P(log_data, sizeof(log_data), formatP, arg); + vsnprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), formatP, arg); va_end(arg); AddLog(LOG_LEVEL_DEBUG); @@ -2073,15 +2097,15 @@ void AddLog_Debug(PGM_P formatP, ...) void AddLogBuffer(uint32_t loglevel, uint8_t *buffer, uint32_t count) { /* - snprintf_P(log_data, sizeof(log_data), PSTR("DMP:")); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("DMP:")); for (uint32_t i = 0; i < count; i++) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, *(buffer++)); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s %02X"), TasmotaGlobal.log_data, *(buffer++)); } AddLog(loglevel); */ /* - strcpy_P(log_data, PSTR("DMP: ")); - ToHex_P(buffer, count, log_data + strlen(log_data), sizeof(log_data) - strlen(log_data), ' '); + strcpy_P(TasmotaGlobal.log_data, PSTR("DMP: ")); + ToHex_P(buffer, count, TasmotaGlobal.log_data + strlen(TasmotaGlobal.log_data), sizeof(TasmotaGlobal.log_data) - strlen(TasmotaGlobal.log_data), ' '); AddLog(loglevel); */ char hex_char[(count * 3) + 2]; @@ -2090,7 +2114,7 @@ void AddLogBuffer(uint32_t loglevel, uint8_t *buffer, uint32_t count) void AddLogSerial(uint32_t loglevel) { - AddLogBuffer(loglevel, (uint8_t*)serial_in_buffer, serial_in_byte_counter); + AddLogBuffer(loglevel, (uint8_t*)TasmotaGlobal.serial_in_buffer, TasmotaGlobal.serial_in_byte_counter); } void AddLogMissed(const char *sensor, uint32_t misses) @@ -2099,12 +2123,12 @@ void AddLogMissed(const char *sensor, uint32_t misses) } void AddLogBufferSize(uint32_t loglevel, uint8_t *buffer, uint32_t count, uint32_t size) { - snprintf_P(log_data, sizeof(log_data), PSTR("DMP:")); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("DMP:")); for (uint32_t i = 0; i < count; i++) { if (1 == size) { // uint8_t - snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, *(buffer)); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s %02X"), TasmotaGlobal.log_data, *(buffer)); } else { // uint16_t - snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X%02X"), log_data, *(buffer +1), *(buffer)); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s %02X%02X"), TasmotaGlobal.log_data, *(buffer +1), *(buffer)); } buffer += size; } diff --git a/tasmota/support_button.ino b/tasmota/support_button.ino index 4dc5aa097..811767aae 100644 --- a/tasmota/support_button.ino +++ b/tasmota/support_button.ino @@ -33,7 +33,7 @@ const char kMultiPress[] PROGMEM = "|SINGLE|DOUBLE|TRIPLE|QUAD|PENTA|"; struct BUTTON { - unsigned long debounce = 0; // Button debounce timer + uint32_t debounce = 0; // Button debounce timer uint16_t hold_timer[MAX_KEYS] = { 0 }; // Timer for button hold uint16_t dual_code = 0; // Sonoff dual received code @@ -80,7 +80,7 @@ void ButtonInit(void) { Button.present = 0; #ifdef ESP8266 - if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { + if ((SONOFF_DUAL == TasmotaGlobal.module_type) || (CH4 == TasmotaGlobal.module_type)) { Button.present++; } #endif // ESP8266 @@ -135,7 +135,7 @@ uint8_t ButtonSerial(uint8_t serial_in_byte) void ButtonHandler(void) { - if (uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit + if (TasmotaGlobal.uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit uint8_t hold_time_extent = IMMINENT_RESET_FACTOR; // Extent hold time factor in case of iminnent Reset command uint16_t loops_per_second = 1000 / Settings.button_debounce; // ButtonDebounce (50) @@ -146,7 +146,7 @@ void ButtonHandler(void) uint8_t button_present = 0; #ifdef ESP8266 - if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) { + if (!button_index && ((SONOFF_DUAL == TasmotaGlobal.module_type) || (CH4 == TasmotaGlobal.module_type))) { button_present = 1; if (Button.dual_code) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON " " D_CODE " %04X"), Button.dual_code); @@ -204,7 +204,7 @@ void ButtonHandler(void) // Serviced } #ifdef ESP8266 - else if (SONOFF_4CHPRO == my_module_type) { + else if (SONOFF_4CHPRO == TasmotaGlobal.module_type) { if (Button.hold_timer[button_index]) { Button.hold_timer[button_index]--; } bool button_pressed = false; @@ -245,7 +245,7 @@ void ButtonHandler(void) AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_MULTI_PRESS " %d"), button_index +1, Button.press_counter[button_index]); Button.window_timer[button_index] = loops_per_second / 2; // 0.5 second multi press window } - blinks = 201; + TasmotaGlobal.blinks = 201; } if (NOT_PRESSED == button) { @@ -281,18 +281,18 @@ void ButtonHandler(void) if (Button.window_timer[button_index]) { Button.window_timer[button_index]--; } else { - if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0) && (Button.press_counter[button_index] < 7)) { + if (!TasmotaGlobal.restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0) && (Button.press_counter[button_index] < 7)) { bool single_press = false; if (Button.press_counter[button_index] < 3) { // Single or Double press #ifdef ESP8266 - if ((SONOFF_DUAL_R2 == my_module_type) || (SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { + if ((SONOFF_DUAL_R2 == TasmotaGlobal.module_type) || (SONOFF_DUAL == TasmotaGlobal.module_type) || (CH4 == TasmotaGlobal.module_type)) { single_press = true; } else #endif // ESP8266 { single_press = (Settings.flag.button_swap +1 == Button.press_counter[button_index]); // SetOption11 (0) - if ((1 == Button.present) && (2 == devices_present)) { // Single Button with two devices only + if ((1 == Button.present) && (2 == TasmotaGlobal.devices_present)) { // Single Button with two devices only if (Settings.flag.button_swap) { // SetOption11 (0) Button.press_counter[button_index] = (single_press) ? 1 : 2; } @@ -307,7 +307,7 @@ void ButtonHandler(void) } else { if (Button.press_counter[button_index] < 6) { // Single to Penta press if (WifiState() > WIFI_RESTART) { // Wifimanager active - restart_flag = 1; + TasmotaGlobal.restart_flag = 1; } if (!Settings.flag3.mqtt_buttons) { // SetOption73 - Detach buttons from relays and enable MQTT action state for multipress if (Button.press_counter[button_index] == 1) { // By default first press always send a TOGGLE (2) @@ -317,8 +317,8 @@ void ButtonHandler(void) if (0 == button_index) { // BUTTON1 can toggle up to 5 relays if present. If a relay is not present will send out the key value (2,11,12,13 and 14) for rules bool valid_relay = PinUsed(GPIO_REL1, Button.press_counter[button_index]-1); #ifdef ESP8266 - if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { - valid_relay = (Button.press_counter[button_index] <= devices_present); + if ((SONOFF_DUAL == TasmotaGlobal.module_type) || (CH4 == TasmotaGlobal.module_type)) { + valid_relay = (Button.press_counter[button_index] <= TasmotaGlobal.devices_present); } #endif // ESP8266 if ((Button.press_counter[button_index] > 1) && valid_relay && (Button.press_counter[button_index] <= MAX_RELAY_BUTTON1)) { @@ -366,7 +366,7 @@ void MqttButtonTopic(uint8_t button_id, uint8_t action, uint8_t hold) if (!Settings.flag.hass_discovery) { GetTextIndexed(mqttstate, sizeof(mqttstate), action, kMultiPress); snprintf_P(scommand, sizeof(scommand), PSTR("BUTTON%d"), button_id); - GetTopic_P(stopic, STAT, mqtt_topic, scommand); + GetTopic_P(stopic, STAT, TasmotaGlobal.mqtt_topic, scommand); Response_P(S_JSON_COMMAND_SVALUE, "ACTION", (hold) ? SettingsText(SET_STATE_TXT4) : mqttstate); MqttPublish(stopic); } diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 9176f3a7c..c4deba6ce 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -27,7 +27,7 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix D_CMND_SERIALDELIMITER "|" D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|" D_CMND_WIFICONFIG "|" D_CMND_DEVICENAME "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TELEPERIOD "|" D_CMND_RESET "|" D_CMND_TIME "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_LEDMASK "|" D_CMND_LEDPWM_ON "|" D_CMND_LEDPWM_OFF "|" D_CMND_LEDPWM_MODE "|" - D_CMND_WIFIPOWER "|" D_CMND_TEMPOFFSET "|" D_CMND_HUMOFFSET "|" D_CMND_SPEEDUNIT "|" D_CMND_GLOBAL_TEMP "|" D_CMND_GLOBAL_HUM "|" D_CMND_WIFI "|" + D_CMND_WIFIPOWER "|" D_CMND_TEMPOFFSET "|" D_CMND_HUMOFFSET "|" D_CMND_SPEEDUNIT "|" D_CMND_GLOBAL_TEMP "|" D_CMND_GLOBAL_HUM "|" D_CMND_WIFI "|" D_CMND_SWITCHTEXT "|" #ifdef USE_I2C D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|" #endif @@ -54,7 +54,7 @@ void (* const TasmotaCommand[])(void) PROGMEM = { &CmndSerialDelimiter, &CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig, &CmndDevicename, &CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset, &CmndTime, &CmndTimezone, &CmndTimeStd, &CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndLedPwmOn, &CmndLedPwmOff, &CmndLedPwmMode, - &CmndWifiPower, &CmndTempOffset, &CmndHumOffset, &CmndSpeedUnit, &CmndGlobalTemp, &CmndGlobalHum, &CmndWifi, + &CmndWifiPower, &CmndTempOffset, &CmndHumOffset, &CmndSpeedUnit, &CmndGlobalTemp, &CmndGlobalHum, &CmndWifi, &CmndSwitchText, #ifdef USE_I2C &CmndI2cScan, CmndI2cDriver, #endif @@ -121,7 +121,7 @@ void ResponseCmndIdxChar(const char* value) void ResponseCmndAll(uint32_t text_index, uint32_t count) { uint32_t real_index = text_index; - mqtt_data[0] = '\0'; + ResponseClear(); for (uint32_t i = 0; i < count; i++) { if ((SET_MQTT_GRP_TOPIC == text_index) && (1 == i)) { real_index = SET_MQTT_GRP_TOPIC2 -1; } ResponseAppend_P(PSTR("%c\"%s%d\":\"%s\""), (i) ? ',' : '{', XdrvMailbox.command, i +1, EscapeJSONString(SettingsText(real_index +i)).c_str()); @@ -200,7 +200,7 @@ void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len) char stemp1[TOPSZ]; GetFallbackTopic_P(stemp1, ""); // Full Fallback topic = cmnd/DVES_xxxxxxxx_fb/ - fallback_topic_flag = (!strncmp(topicBuf, stemp1, strlen(stemp1))); + TasmotaGlobal.fallback_topic_flag = (!strncmp(topicBuf, stemp1, strlen(stemp1))); char *type = strrchr(topicBuf, '/'); // Last part of received topic is always the command (type) @@ -232,7 +232,7 @@ void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len) if (type != nullptr) { Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_ERROR "\"}")); - if (Settings.ledstate &0x02) { blinks++; } + if (Settings.ledstate &0x02) { TasmotaGlobal.blinks++; } if (!strcmp(dataBuf,"?")) { data_len = 0; } @@ -244,8 +244,8 @@ void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len) DEBUG_CORE_LOG(PSTR("CMD: Payload %d"), payload); -// backlog_delay = millis() + (100 * MIN_BACKLOG_DELAY); - backlog_delay = millis() + Settings.param[P_BACKLOG_DELAY]; +// TasmotaGlobal.backlog_delay = millis() + (100 * MIN_BACKLOG_DELAY); + TasmotaGlobal.backlog_delay = millis() + Settings.param[P_BACKLOG_DELAY]; char command[CMDSZ] = { 0 }; XdrvMailbox.command = command; @@ -281,28 +281,28 @@ void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len) } if (type == nullptr) { - blinks = 201; + TasmotaGlobal.blinks = 201; snprintf_P(stemp1, sizeof(stemp1), PSTR(D_JSON_COMMAND)); Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_UNKNOWN "\"}")); type = (char*)stemp1; } - if (mqtt_data[0] != '\0') { + if (TasmotaGlobal.mqtt_data[0] != '\0') { /* // Add "Command":"POWERONSTATE", like: // 12:15:37 MQT: stat/wemos4/RESULT = {"Command":"POWERONSTATE","PowerOnState":3} char json_command[TOPSZ]; snprintf_P(json_command, sizeof(json_command), PSTR("{\"" D_JSON_COMMAND "\":\"%s\","), type); uint32_t jc_len = strlen(json_command); - uint32_t mq_len = strlen(mqtt_data) +1; - if (mq_len < sizeof(mqtt_data) - jc_len) { - memmove(mqtt_data +jc_len -1, mqtt_data, mq_len); - memmove(mqtt_data, json_command, jc_len); + uint32_t mq_len = strlen(TasmotaGlobal.mqtt_data) +1; + if (mq_len < sizeof(TasmotaGlobal.mqtt_data) - jc_len) { + memmove(TasmotaGlobal.mqtt_data +jc_len -1, TasmotaGlobal.mqtt_data, mq_len); + memmove(TasmotaGlobal.mqtt_data, json_command, jc_len); } */ MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, type); } - fallback_topic_flag = false; + TasmotaGlobal.fallback_topic_flag = false; } /********************************************************************************************/ @@ -315,10 +315,10 @@ void CmndBacklog(void) char *blcommand = strtok(XdrvMailbox.data, ";"); while ((blcommand != nullptr) && (backlog.size() < MAX_BACKLOG)) #else - uint32_t bl_pointer = (!backlog_pointer) ? MAX_BACKLOG -1 : backlog_pointer; + uint32_t bl_pointer = (!TasmotaGlobal.backlog_pointer) ? MAX_BACKLOG -1 : TasmotaGlobal.backlog_pointer; bl_pointer--; char *blcommand = strtok(XdrvMailbox.data, ";"); - while ((blcommand != nullptr) && (backlog_index != bl_pointer)) + while ((blcommand != nullptr) && (TasmotaGlobal.backlog_index != bl_pointer)) #endif { while(true) { @@ -335,22 +335,22 @@ void CmndBacklog(void) backlog.add(blcommand); } #else - backlog[backlog_index] = blcommand; - backlog_index++; - if (backlog_index >= MAX_BACKLOG) backlog_index = 0; + TasmotaGlobal.backlog[TasmotaGlobal.backlog_index] = blcommand; + TasmotaGlobal.backlog_index++; + if (TasmotaGlobal.backlog_index >= MAX_BACKLOG) TasmotaGlobal.backlog_index = 0; #endif } blcommand = strtok(nullptr, ";"); } // ResponseCmndChar(D_JSON_APPENDED); - mqtt_data[0] = '\0'; - backlog_delay = 0; + ResponseClear(); + TasmotaGlobal.backlog_delay = 0; } else { bool blflag = BACKLOG_EMPTY; #ifdef SUPPORT_IF_STATEMENT backlog.clear(); #else - backlog_pointer = backlog_index; + TasmotaGlobal.backlog_pointer = TasmotaGlobal.backlog_index; #endif ResponseCmndChar(blflag ? D_JSON_EMPTY : D_JSON_ABORTED); } @@ -359,23 +359,23 @@ void CmndBacklog(void) void CmndDelay(void) { if ((XdrvMailbox.payload >= (MIN_BACKLOG_DELAY / 100)) && (XdrvMailbox.payload <= 3600)) { - backlog_delay = millis() + (100 * XdrvMailbox.payload); + TasmotaGlobal.backlog_delay = millis() + (100 * XdrvMailbox.payload); } uint32_t bl_delay = 0; - long bl_delta = TimePassedSince(backlog_delay); + long bl_delta = TimePassedSince(TasmotaGlobal.backlog_delay); if (bl_delta < 0) { bl_delay = (bl_delta *-1) / 100; } ResponseCmndNumber(bl_delay); } void CmndPower(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= devices_present)) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.devices_present)) { if ((XdrvMailbox.payload < POWER_OFF) || (XdrvMailbox.payload > POWER_BLINK_STOP)) { XdrvMailbox.payload = POWER_SHOW_STATE; } // Settings.flag.device_index_enable = XdrvMailbox.usridx; // SetOption26 - Switch between POWER or POWER1 ExecuteCommandPower(XdrvMailbox.index, XdrvMailbox.payload, SRC_IGNORE); - mqtt_data[0] = '\0'; + ResponseClear(); } else if (0 == XdrvMailbox.index) { if ((XdrvMailbox.payload < POWER_OFF) || (XdrvMailbox.payload > POWER_TOGGLE)) { @@ -385,7 +385,7 @@ void CmndPower(void) if (Settings.flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT MqttPublishTeleState(); } - mqtt_data[0] = '\0'; + ResponseClear(); } } @@ -395,7 +395,7 @@ void CmndStatus(void) if (payload > MAX_STATUS) { return; } // {"Command":"Error"} if (!Settings.flag.mqtt_enabled && (6 == payload)) { return; } // SetOption3 - Enable MQTT - if (!energy_flg && (9 == payload)) { return; } + if (!TasmotaGlobal.energy_driver && (9 == payload)) { return; } if (!CrashFlag() && (12 == payload)) { return; } if (!Settings.flag3.shutter_mode && (13 == payload)) { return; } @@ -403,7 +403,7 @@ void CmndStatus(void) char stemp2[TOPSZ]; if (0 == payload) { - uint32_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; + uint32_t maxfn = (TasmotaGlobal.devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!TasmotaGlobal.devices_present) ? 1 : TasmotaGlobal.devices_present; #ifdef USE_SONOFF_IFAN if (IsModuleIfan()) { maxfn = 1; } #endif // USE_SONOFF_IFAN @@ -419,8 +419,8 @@ void CmndStatus(void) D_CMND_BUTTONTOPIC "\":\"%s\",\"" D_CMND_POWER "\":%d,\"" D_CMND_POWERONSTATE "\":%d,\"" D_CMND_LEDSTATE "\":%d,\"" D_CMND_LEDMASK "\":\"%04X\",\"" D_CMND_SAVEDATA "\":%d,\"" D_JSON_SAVESTATE "\":%d,\"" D_CMND_SWITCHTOPIC "\":\"%s\",\"" D_CMND_SWITCHMODE "\":[%s],\"" D_CMND_BUTTONRETAIN "\":%d,\"" D_CMND_SWITCHRETAIN "\":%d,\"" D_CMND_SENSORRETAIN "\":%d,\"" D_CMND_POWERRETAIN "\":%d}}"), - ModuleNr(), EscapeJSONString(SettingsText(SET_DEVICENAME)).c_str(), stemp, mqtt_topic, - SettingsText(SET_MQTT_BUTTON_TOPIC), power, Settings.poweronstate, Settings.ledstate, + ModuleNr(), EscapeJSONString(SettingsText(SET_DEVICENAME)).c_str(), stemp, TasmotaGlobal.mqtt_topic, + SettingsText(SET_MQTT_BUTTON_TOPIC), TasmotaGlobal.power, Settings.poweronstate, Settings.ledstate, Settings.ledmask, Settings.save_data, Settings.flag.save_state, // SetOption0 - Save power state and use after restart SettingsText(SET_MQTT_SWITCH_TOPIC), @@ -440,7 +440,7 @@ void CmndStatus(void) ",\"" D_JSON_SAVEADDRESS "\":\"%X\"" #endif "}}"), - baudrate, GetSerialConfig().c_str(), SettingsText(SET_MQTT_GRP_TOPIC), SettingsText(SET_OTAURL), + TasmotaGlobal.baudrate, GetSerialConfig().c_str(), SettingsText(SET_MQTT_GRP_TOPIC), SettingsText(SET_OTAURL), GetResetReason().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep, Settings.cfg_holder, Settings.bootcount, GetDateAndTime(DT_BOOTCOUNT).c_str(), Settings.save_flag #ifdef ESP8266 @@ -458,7 +458,7 @@ void CmndStatus(void) ",\"" D_JSON_COREVERSION "\":\"" ARDUINO_CORE_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"," "\"CpuFrequency\":%d,\"Hardware\":\"%s\"" "%s}}"), - my_version, my_image, GetBuildDateAndTime().c_str() + TasmotaGlobal.version, TasmotaGlobal.image_name, GetBuildDateAndTime().c_str() #ifdef ESP8266 , ESP.getBootVersion() #endif @@ -488,8 +488,7 @@ void CmndStatus(void) #ifdef ESP8266 ",\"" D_JSON_FLASHCHIPID "\":\"%06X\"" #endif - ",\"FlashFrequency\":%d,\"" D_JSON_FLASHMODE "\":%d,\"" - D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]"), + ",\"FlashFrequency\":%d,\"" D_JSON_FLASHMODE "\":%d"), ESP_getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP_getFreeHeap()/1024, #ifdef ESP32 ESP.getPsramSize()/1024, ESP.getFreePsram()/1024, @@ -498,8 +497,8 @@ void CmndStatus(void) #ifdef ESP8266 , ESP.getFlashChipId() #endif - , ESP.getFlashChipSpeed()/1000000, ESP.getFlashChipMode(), - LANGUAGE_LCID, feature_drv1, feature_drv2, feature_sns1, feature_sns2, feature5, feature6, feature7); + , ESP.getFlashChipSpeed()/1000000, ESP.getFlashChipMode()); + ResponseAppendFeatures(); XsnsDriverState(); ResponseAppend_P(PSTR(",\"Sensors\":")); XsnsSensorState(); @@ -521,7 +520,7 @@ void CmndStatus(void) Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS6_MQTT "\":{\"" D_CMND_MQTTHOST "\":\"%s\",\"" D_CMND_MQTTPORT "\":%d,\"" D_CMND_MQTTCLIENT D_JSON_MASK "\":\"%s\",\"" D_CMND_MQTTCLIENT "\":\"%s\",\"" D_CMND_MQTTUSER "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"), SettingsText(SET_MQTT_HOST), Settings.mqtt_port, EscapeJSONString(SettingsText(SET_MQTT_CLIENT)).c_str(), - mqtt_client, EscapeJSONString(SettingsText(SET_MQTT_USER)).c_str(), MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); + TasmotaGlobal.mqtt_client, EscapeJSONString(SettingsText(SET_MQTT_USER)).c_str(), MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_STATUS "6")); } @@ -546,7 +545,7 @@ void CmndStatus(void) } #if defined(USE_ENERGY_SENSOR) && defined(USE_ENERGY_MARGIN_DETECTION) - if (energy_flg) { + if (TasmotaGlobal.energy_driver) { if ((0 == payload) || (9 == payload)) { Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS9_MARGIN "\":{\"" D_CMND_POWERDELTA "\":[%d,%d,%d],\"" D_CMND_POWERLOW "\":%d,\"" D_CMND_POWERHIGH "\":%d,\"" D_CMND_VOLTAGELOW "\":%d,\"" D_CMND_VOLTAGEHIGH "\":%d,\"" D_CMND_CURRENTLOW "\":%d,\"" D_CMND_CURRENTHIGH "\":%d}}"), @@ -607,19 +606,19 @@ void CmndStatus(void) #endif #ifdef USE_SCRIPT_STATUS - if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">U",2,mqtt_data); + if (bitRead(Settings.rule_enabled, 0)) { Run_Scripter(">U", 2, TasmotaGlobal.mqtt_data); } #endif if (payload) { XdrvRulesProcess(); // Allow rule processing on single Status command only } - mqtt_data[0] = '\0'; + ResponseClear(); } void CmndState(void) { - mqtt_data[0] = '\0'; + ResponseClear(); MqttShowState(); if (Settings.flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); @@ -662,10 +661,10 @@ void CmndGlobalTemp(void) } if ((temperature >= -50.0f) && (temperature <= 100.0f)) { ConvertTemp(temperature); - global_update = 1; // Keep global values just entered valid + TasmotaGlobal.global_update = 1; // Keep global values just entered valid } } - ResponseCmndFloat(global_temperature_celsius, 1); + ResponseCmndFloat(TasmotaGlobal.temperature_celsius, 1); } void CmndGlobalHum(void) @@ -674,20 +673,20 @@ void CmndGlobalHum(void) float humidity = CharToFloat(XdrvMailbox.data); if ((humidity >= 0.0) && (humidity <= 100.0)) { ConvertHumidity(humidity); - global_update = 1; // Keep global values just entered valid + TasmotaGlobal.global_update = 1; // Keep global values just entered valid } } - ResponseCmndFloat(global_humidity, 1); + ResponseCmndFloat(TasmotaGlobal.humidity, 1); } void CmndSleep(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 251)) { Settings.sleep = XdrvMailbox.payload; - ssleep = XdrvMailbox.payload; + TasmotaGlobal.sleep = XdrvMailbox.payload; WiFiSetSleepMode(); } - Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.sleep, ssleep); + Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.sleep, TasmotaGlobal.sleep); } @@ -698,11 +697,11 @@ void CmndUpgrade(void) // Check if the version we have been asked to upgrade to is higher than our current version. // We also need at least 3 chars to make a valid version number string. if (((1 == XdrvMailbox.data_len) && (1 == XdrvMailbox.payload)) || ((XdrvMailbox.data_len >= 3) && NewerVersion(XdrvMailbox.data))) { - ota_state_flag = 3; + TasmotaGlobal.ota_state_flag = 3; char stemp1[TOPSZ]; - Response_P(PSTR("{\"%s\":\"" D_JSON_VERSION " %s " D_JSON_FROM " %s\"}"), XdrvMailbox.command, my_version, GetOtaUrl(stemp1, sizeof(stemp1))); + Response_P(PSTR("{\"%s\":\"" D_JSON_VERSION " %s " D_JSON_FROM " %s\"}"), XdrvMailbox.command, TasmotaGlobal.version, GetOtaUrl(stemp1, sizeof(stemp1))); } else { - Response_P(PSTR("{\"%s\":\"" D_JSON_ONE_OR_GT "\"}"), XdrvMailbox.command, my_version); + Response_P(PSTR("{\"%s\":\"" D_JSON_ONE_OR_GT "\"}"), XdrvMailbox.command, TasmotaGlobal.version); } } @@ -720,19 +719,19 @@ void CmndSeriallog(void) Settings.flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG SetSeriallog(XdrvMailbox.payload); } - Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.seriallog_level, seriallog_level); + Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.seriallog_level, TasmotaGlobal.seriallog_level); } void CmndRestart(void) { switch (XdrvMailbox.payload) { case 1: - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; ResponseCmndChar(D_JSON_RESTARTING); break; case 2: - restart_flag = 2; - restart_halt = true; + TasmotaGlobal.restart_flag = 2; + TasmotaGlobal.restart_halt = true; ResponseCmndChar(D_JSON_HALTING); break; case -1: @@ -756,7 +755,7 @@ void CmndRestart(void) void CmndPowerOnState(void) { #ifdef ESP8266 - if (my_module_type != MOTOR) + if (TasmotaGlobal.module_type != MOTOR) #endif // ESP8266 { /* 0 = Keep relays off after power on @@ -769,7 +768,7 @@ void CmndPowerOnState(void) if ((XdrvMailbox.payload >= POWER_ALL_OFF) && (XdrvMailbox.payload <= POWER_ALL_OFF_PULSETIME_ON)) { Settings.poweronstate = XdrvMailbox.payload; if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { - for (uint32_t i = 1; i <= devices_present; i++) { + for (uint32_t i = 1; i <= TasmotaGlobal.devices_present; i++) { ExecuteCommandPower(i, POWER_ON, SRC_IGNORE); } } @@ -790,7 +789,7 @@ void CmndPulsetime(void) SetPulseTimer(XdrvMailbox.index -1, XdrvMailbox.payload); } } - mqtt_data[0] = '\0'; + ResponseClear(); for (uint32_t i = 0; i < items; i++) { uint32_t index = (1 == items) ? XdrvMailbox.index : i +1; ResponseAppend_P(PSTR("%c\"%s%d\":{\"" D_JSON_SET "\":%d,\"" D_JSON_REMAINING "\":%d}"), @@ -806,7 +805,9 @@ void CmndBlinktime(void) { if ((XdrvMailbox.payload > 1) && (XdrvMailbox.payload <= 3600)) { Settings.blinktime = XdrvMailbox.payload; - if (blink_timer > 0) { blink_timer = millis() + (100 * XdrvMailbox.payload); } + if (TasmotaGlobal.blink_timer > 0) { + TasmotaGlobal.blink_timer = millis() + (100 * XdrvMailbox.payload); + } } ResponseCmndNumber(Settings.blinktime); } @@ -815,7 +816,7 @@ void CmndBlinkcount(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 65536)) { Settings.blinkcount = XdrvMailbox.payload; // 0 - 65535 - if (blink_counter) { blink_counter = Settings.blinkcount *2; } + if (TasmotaGlobal.blink_counter) { TasmotaGlobal.blink_counter = Settings.blinkcount *2; } } ResponseCmndNumber(Settings.blinkcount); } @@ -824,7 +825,7 @@ void CmndSavedata(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3600)) { Settings.save_data = XdrvMailbox.payload; - save_data_counter = Settings.save_data; + TasmotaGlobal.save_data_counter = Settings.save_data; } SettingsSaveAll(); char stemp1[TOPSZ]; @@ -878,7 +879,7 @@ void CmndSetoption(void) #ifdef USE_LIGHT if (P_RGB_REMAP == pindex) { LightUpdateColorMapping(); - restart_flag = 2; // SetOption37 needs a reboot in most cases + TasmotaGlobal.restart_flag = 2; // SetOption37 needs a reboot in most cases } #endif #if (defined(USE_IR_REMOTE) && defined(USE_IR_RECEIVE)) || defined(USE_IR_REMOTE_FULL) @@ -906,12 +907,12 @@ void CmndSetoption(void) break; // Ignore command SetOption case 3: // mqtt case 15: // pwm_control - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; default: bitWrite(Settings.flag.data, pindex, XdrvMailbox.payload); } if (12 == pindex) { // stop_flash_rotate - stop_flash_rotate = XdrvMailbox.payload; + TasmotaGlobal.stop_flash_rotate = XdrvMailbox.payload; SettingsSave(2); } #ifdef USE_HOME_ASSISTANT @@ -925,7 +926,7 @@ void CmndSetoption(void) switch (pindex) { case 5: // SetOption55 if (0 == XdrvMailbox.payload) { - restart_flag = 2; // Disable mDNS needs restart + TasmotaGlobal.restart_flag = 2; // Disable mDNS needs restart } break; case 10: // SetOption60 enable or disable traditional sleep @@ -933,7 +934,7 @@ void CmndSetoption(void) break; case 18: // SetOption68 for multi-channel PWM, requires a reboot case 25: // SetOption75 grouptopic change - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; break; } } @@ -948,7 +949,7 @@ void CmndSetoption(void) case 22: // SetOption104 - No Retain - disable all MQTT retained messages, some brokers don't support it: AWS IoT, Losant case 24: // SetOption106 - Virtual CT - Creates a virtual White ColorTemp for RGBW lights case 25: // SetOption107 - Virtual CT Channel - signals whether the hardware white is cold CW (true) or warm WW (false) - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; break; } } @@ -1084,7 +1085,7 @@ void CmndModule(void) Settings.my_gp.io[i] = GPIO_NONE; } } - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } } } @@ -1119,7 +1120,7 @@ void CmndModules(void) lines++; } } - mqtt_data[0] = '\0'; + ResponseClear(); } void CmndGpio(void) @@ -1143,7 +1144,7 @@ void CmndGpio(void) } } Settings.my_gp.io[XdrvMailbox.index] = XdrvMailbox.payload; - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } } Response_P(PSTR("{")); @@ -1188,13 +1189,20 @@ void CmndGpio(void) } void ShowGpios(const uint16_t *NiceList, uint32_t size, uint32_t offset, uint32_t &lines) { + uint32_t ridx; + uint32_t midx; myio cmodule; ModuleGpios(&cmodule); bool jsflg = false; for (uint32_t i = offset; i < size; i++) { // Skip ADC_NONE - uint32_t ridx = pgm_read_word(NiceList + i) & 0xFFE0; - uint32_t midx = BGPIO(ridx); - if ((XdrvMailbox.payload != 255) && GetUsedInModule(midx, cmodule.io)) { continue; } + if (NiceList == nullptr) { + ridx = AGPIO(i); + midx = i; + } else { + ridx = pgm_read_word(NiceList + i) & 0xFFE0; + midx = BGPIO(ridx); + if ((XdrvMailbox.payload != 255) && GetUsedInModule(midx, cmodule.io)) { continue; } + } if (!jsflg) { Response_P(PSTR("{\"" D_CMND_GPIOS "%d\":{"), lines); } else { @@ -1213,20 +1221,19 @@ void ShowGpios(const uint16_t *NiceList, uint32_t size, uint32_t offset, uint32_ void CmndGpios(void) { -/* - if (XdrvMailbox.payload == 17) { - DumpConvertTable(); - return; - } -*/ uint32_t lines = 1; - ShowGpios(kGpioNiceList, ARRAY_SIZE(kGpioNiceList), 0, lines); + if (XdrvMailbox.payload == 255) { +// DumpConvertTable(); + ShowGpios(nullptr, GPIO_SENSOR_END, 0, lines); + } else { + ShowGpios(kGpioNiceList, ARRAY_SIZE(kGpioNiceList), 0, lines); #ifdef ESP8266 #ifndef USE_ADC_VCC - ShowGpios(kAdcNiceList, ARRAY_SIZE(kAdcNiceList), 1, lines); + ShowGpios(kAdcNiceList, ARRAY_SIZE(kAdcNiceList), 1, lines); #endif // USE_ADC_VCC #endif // ESP8266 - mqtt_data[0] = '\0'; + } + ResponseClear(); } void CmndTemplate(void) @@ -1240,7 +1247,7 @@ void CmndTemplate(void) XdrvMailbox.payload--; if (ValidTemplateModule(XdrvMailbox.payload)) { ModuleDefault(XdrvMailbox.payload); // Copy template module - if (USER_MODULE == Settings.module) { restart_flag = 2; } + if (USER_MODULE == Settings.module) { TasmotaGlobal.restart_flag = 2; } } } else if (0 == XdrvMailbox.payload) { // Copy current template to user template @@ -1257,8 +1264,8 @@ void CmndTemplate(void) for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) { if (6 == i) { j = 9; } if (8 == i) { j = 12; } - if (my_module.io[j] > GPIO_NONE) { - Settings.user_template.gp.io[i] = my_module.io[j]; + if (TasmotaGlobal.my_module.io[j] > GPIO_NONE) { + Settings.user_template.gp.io[i] = TasmotaGlobal.my_module.io[j]; } j++; } @@ -1266,7 +1273,7 @@ void CmndTemplate(void) } else { if (JsonTemplate(XdrvMailbox.data)) { // Free 336 bytes StaticJsonBuffer stack space by moving code to function - if (USER_MODULE == Settings.module) { restart_flag = 2; } + if (USER_MODULE == Settings.module) { TasmotaGlobal.restart_flag = 2; } } else { ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); error = true; @@ -1277,10 +1284,10 @@ void CmndTemplate(void) void CmndPwm(void) { - if (pwm_present && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_PWMS)) { + if (TasmotaGlobal.pwm_present && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_PWMS)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= Settings.pwm_range) && PinUsed(GPIO_PWM1, XdrvMailbox.index -1)) { Settings.pwm_value[XdrvMailbox.index -1] = XdrvMailbox.payload; - analogWrite(Pin(GPIO_PWM1, XdrvMailbox.index -1), bitRead(pwm_inverted, XdrvMailbox.index -1) ? Settings.pwm_range - XdrvMailbox.payload : XdrvMailbox.payload); + analogWrite(Pin(GPIO_PWM1, XdrvMailbox.index -1), bitRead(TasmotaGlobal.pwm_inverted, XdrvMailbox.index -1) ? Settings.pwm_range - XdrvMailbox.payload : XdrvMailbox.payload); } Response_P(PSTR("{")); MqttShowPWMState(); // Render the PWM status to MQTT @@ -1341,10 +1348,10 @@ void CmndBaudrate(void) { if (XdrvMailbox.payload >= 300) { XdrvMailbox.payload /= 300; // Make it a valid baudrate - baudrate = (XdrvMailbox.payload & 0xFFFF) * 300; - SetSerialBaudrate(baudrate); + TasmotaGlobal.baudrate = (XdrvMailbox.payload & 0xFFFF) * 300; + SetSerialBaudrate(TasmotaGlobal.baudrate); } - ResponseCmndNumber(baudrate); + ResponseCmndNumber(TasmotaGlobal.baudrate); } void CmndSerialConfig(void) @@ -1438,7 +1445,7 @@ void CmndSyslog(void) if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) { SetSyslog(XdrvMailbox.payload); } - Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.syslog_level, syslog_level); + Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.syslog_level, TasmotaGlobal.syslog_level); } void CmndLoghost(void) @@ -1463,7 +1470,7 @@ void CmndIpAddress(void) uint32_t address; if (ParseIp(&address, XdrvMailbox.data)) { Settings.ip_address[XdrvMailbox.index -1] = address; -// restart_flag = 2; +// TasmotaGlobal.restart_flag = 2; } char stemp1[TOPSZ]; snprintf_P(stemp1, sizeof(stemp1), PSTR(" (%s)"), WiFi.localIP().toString().c_str()); @@ -1482,8 +1489,8 @@ void CmndNtpServer(void) SettingsUpdateText(ntp_server, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? PSTR(NTP_SERVER1) : (2 == XdrvMailbox.index) ? PSTR(NTP_SERVER2) : PSTR(NTP_SERVER3) : XdrvMailbox.data); SettingsUpdateText(ntp_server, ReplaceCommaWithDot(SettingsText(ntp_server))); - // restart_flag = 2; // Issue #3890 - ntp_force_sync = true; + // TasmotaGlobal.restart_flag = 2; // Issue #3890 + TasmotaGlobal.ntp_force_sync = true; } ResponseCmndIdxChar(SettingsText(ntp_server)); } @@ -1502,7 +1509,7 @@ void CmndAp(void) Settings.sta_active = XdrvMailbox.payload -1; } Settings.wifi_channel = 0; // Disable stored AP - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, Settings.sta_active +1, EscapeJSONString(SettingsText(SET_STASSID1 + Settings.sta_active)).c_str()); } @@ -1517,7 +1524,7 @@ void CmndSsid(void) SettingsUpdateText(SET_STASSID1 + XdrvMailbox.index -1, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_SSID1 : STA_SSID2 : XdrvMailbox.data); Settings.sta_active = XdrvMailbox.index -1; - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } ResponseCmndIdxChar(SettingsText(SET_STASSID1 + XdrvMailbox.index -1)); } @@ -1531,7 +1538,7 @@ void CmndPassword(void) SettingsUpdateText(SET_STAPWD1 + XdrvMailbox.index -1, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_PASS1 : STA_PASS2 : XdrvMailbox.data); Settings.sta_active = XdrvMailbox.index -1; - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; ResponseCmndIdxChar(SettingsText(SET_STAPWD1 + XdrvMailbox.index -1)); } else { Response_P(S_JSON_COMMAND_INDEX_ASTERISK, XdrvMailbox.command, XdrvMailbox.index); @@ -1546,7 +1553,7 @@ void CmndHostname(void) if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) { SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); } - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } ResponseCmndChar(SettingsText(SET_HOSTNAME)); } @@ -1558,9 +1565,9 @@ void CmndWifiConfig(void) XdrvMailbox.payload = WIFI_MANAGER; } Settings.sta_config = XdrvMailbox.payload; - wifi_state_flag = Settings.sta_config; + TasmotaGlobal.wifi_state_flag = Settings.sta_config; if (WifiState() > WIFI_RESTART) { - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } } char stemp1[TOPSZ]; @@ -1571,7 +1578,7 @@ void CmndWifi(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { Settings.flag4.network_wifi = XdrvMailbox.payload; - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } ResponseCmndStateText(Settings.flag4.network_wifi); } @@ -1604,6 +1611,20 @@ void CmndFriendlyname(void) } } +void CmndSwitchText(void) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SWITCHES)) { + if (!XdrvMailbox.usridx && !XdrvMailbox.data_len) { + ResponseCmndAll(SET_SWITCH_TXT1, MAX_SWITCHES); + } else { + if (XdrvMailbox.data_len > 0) { + RemoveSpace(XdrvMailbox.data); + SettingsUpdateText(SET_SWITCH_TXT1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data); + } + ResponseCmndIdxChar(SettingsText(SET_SWITCH_TXT1 + XdrvMailbox.index -1)); + } + } +} + void CmndSwitchMode(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SWITCHES)) { @@ -1617,8 +1638,8 @@ void CmndSwitchMode(void) void CmndInterlock(void) { // Interlock 0 - Off, Interlock 1 - On, Interlock 1,2 3,4 5,6,7 - uint32_t max_relays = devices_present; - if (light_type) { max_relays--; } + uint32_t max_relays = TasmotaGlobal.devices_present; + if (TasmotaGlobal.light_type) { max_relays--; } if (max_relays > sizeof(Settings.interlock[0]) * 8) { max_relays = sizeof(Settings.interlock[0]) * 8; } if (max_relays > 1) { // Only interlock with more than 1 relay if (XdrvMailbox.data_len > 0) { @@ -1653,7 +1674,7 @@ void CmndInterlock(void) } else { Settings.flag.interlock = XdrvMailbox.payload &1; // CMND_INTERLOCK - Enable/disable interlock if (Settings.flag.interlock) { - SetDevicePower(power, SRC_IGNORE); // Remove multiple relays if set + SetDevicePower(TasmotaGlobal.power, SRC_IGNORE); // Remove multiple relays if set } } #ifdef USE_SHUTTER @@ -1697,9 +1718,9 @@ void CmndTeleperiod(void) if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { Settings.tele_period = (1 == XdrvMailbox.payload) ? TELE_PERIOD : XdrvMailbox.payload; if ((Settings.tele_period > 0) && (Settings.tele_period < 10)) Settings.tele_period = 10; // Do not allow periods < 10 seconds -// tele_period = Settings.tele_period; +// TasmotaGlobal.tele_period = Settings.tele_period; } - tele_period = Settings.tele_period; // Show teleperiod data also on empty command + TasmotaGlobal.tele_period = Settings.tele_period; // Show teleperiod data also on empty command ResponseCmndNumber(Settings.tele_period); } @@ -1707,11 +1728,11 @@ void CmndReset(void) { switch (XdrvMailbox.payload) { case 1: - restart_flag = 211; + TasmotaGlobal.restart_flag = 211; ResponseCmndChar(PSTR(D_JSON_RESET_AND_RESTARTING)); break; case 2 ... 6: - restart_flag = 210 + XdrvMailbox.payload; + TasmotaGlobal.restart_flag = 210 + XdrvMailbox.payload; Response_P(PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}")); break; case 99: @@ -1743,7 +1764,7 @@ void CmndTime(void) RtcSetTime(XdrvMailbox.payload); } } - mqtt_data[0] = '\0'; + ResponseClear(); ResponseAppendTimeFormat(format); ResponseJsonEnd(); } @@ -1765,7 +1786,7 @@ void CmndTimezone(void) } else { Settings.timezone = 99; } - ntp_force_sync = true; + TasmotaGlobal.ntp_force_sync = true; } if (99 == Settings.timezone) { ResponseCmndNumber(Settings.timezone); @@ -1801,7 +1822,7 @@ void CmndTimeStdDst(uint32_t ts) value = strtol(p, &p, 10); tpos++; // Next parameter } - ntp_force_sync = true; + TasmotaGlobal.ntp_force_sync = true; } else { if (0 == XdrvMailbox.payload) { if (0 == ts) { @@ -1810,7 +1831,7 @@ void CmndTimeStdDst(uint32_t ts) SettingsResetDst(); } } - ntp_force_sync = true; + TasmotaGlobal.ntp_force_sync = true; } } Response_P(PSTR("{\"%s\":{\"Hemisphere\":%d,\"Week\":%d,\"Month\":%d,\"Day\":%d,\"Hour\":%d,\"Offset\":%d}}"), @@ -1836,7 +1857,7 @@ void CmndAltitude(void) } void CmndLedPower(void) { - // If GPIO_LEDLINK (used for network status) then allow up to 4 GPIO_LEDx control using led_power + // If GPIO_LEDLINK (used for network status) then allow up to 4 GPIO_LEDx control using TasmotaGlobal.led_power // If no GPIO_LEDLINK then allow legacy single led GPIO_LED1 control using Settings.ledstate if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_LEDS)) { if (!PinUsed(GPIO_LEDLNK)) { XdrvMailbox.index = 1; } @@ -1845,26 +1866,26 @@ void CmndLedPower(void) { uint32_t mask = 1 << (XdrvMailbox.index -1); // Led to control switch (XdrvMailbox.payload) { case 0: // Off - led_power &= (0xFF ^ mask); + TasmotaGlobal.led_power &= (0xFF ^ mask); Settings.ledstate = 0; break; case 1: // On - led_power |= mask; + TasmotaGlobal.led_power |= mask; Settings.ledstate = 8; break; case 2: // Toggle - led_power ^= mask; + TasmotaGlobal.led_power ^= mask; Settings.ledstate ^= 8; break; } - blinks = 0; + TasmotaGlobal.blinks = 0; if (!PinUsed(GPIO_LEDLNK)) { SetLedPower(Settings.ledstate &8); } else { - SetLedPowerIdx(XdrvMailbox.index -1, (led_power & mask)); + SetLedPowerIdx(XdrvMailbox.index -1, (TasmotaGlobal.led_power & mask)); } } - bool state = bitRead(led_power, XdrvMailbox.index -1); + bool state = bitRead(TasmotaGlobal.led_power, XdrvMailbox.index -1); if (!PinUsed(GPIO_LEDLNK)) { state = bitRead(Settings.ledstate, 3); } @@ -1966,8 +1987,8 @@ void CmndWifiPower(void) #ifdef USE_I2C void CmndI2cScan(void) { - if (i2c_flg) { - I2cScan(mqtt_data, sizeof(mqtt_data)); + if (TasmotaGlobal.i2c_enabled) { + I2cScan(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data)); } } @@ -1976,7 +1997,7 @@ void CmndI2cDriver(void) if (XdrvMailbox.index < MAX_I2C_DRIVERS) { if (XdrvMailbox.payload >= 0) { bitWrite(Settings.i2c_drivers[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1); - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } } Response_P(PSTR("{\"" D_CMND_I2CDRIVER "\":")); @@ -1995,7 +2016,7 @@ void CmndDevGroupName(void) else if (1 == XdrvMailbox.data_len && ('"' == XdrvMailbox.data[0] || '0' == XdrvMailbox.data[0])) XdrvMailbox.data[0] = 0; SettingsUpdateText(SET_DEV_GROUP_NAME1 + XdrvMailbox.index - 1, XdrvMailbox.data); - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } ResponseCmndAll(SET_DEV_GROUP_NAME1, MAX_DEV_GROUP_NAMES); } diff --git a/tasmota/support_device_groups.ino b/tasmota/support_device_groups.ino index 7fb719d0f..52141aec2 100644 --- a/tasmota/support_device_groups.ino +++ b/tasmota/support_device_groups.ino @@ -166,7 +166,7 @@ void DeviceGroupsInit(void) void DeviceGroupsStart() { - if (Settings.flag4.device_groups_enabled && !device_groups_up && !restart_flag) { + if (Settings.flag4.device_groups_enabled && !device_groups_up && !TasmotaGlobal.restart_flag) { // If we haven't successfuly initialized device groups yet, attempt to do it now. if (!device_groups_initialized) { @@ -295,7 +295,7 @@ void SendReceiveDeviceGroupMessage(struct device_group * device_group, struct de XdrvMailbox.index = flags | message_sequence << 16; if (device_group_index == 0 && first_device_group_is_local) XdrvMailbox.index |= DGR_FLAG_LOCAL; XdrvMailbox.topic = (char *)&device_group_index; - if (flags & (DGR_FLAG_MORE_TO_COME | DGR_FLAG_DIRECT)) skip_light_fade = true; + if (flags & (DGR_FLAG_MORE_TO_COME | DGR_FLAG_DIRECT)) TasmotaGlobal.skip_light_fade = true; // Set the flag to ignore device group send message request so callbacks from the drivers do not // send updates. @@ -386,18 +386,18 @@ void SendReceiveDeviceGroupMessage(struct device_group * device_group, struct de switch (item) { case DGR_ITEM_POWER: if (Settings.flag4.multiple_device_groups) { // SetOption88 - Enable relays in separate device groups - if (device_group_index < devices_present) { + if (device_group_index < TasmotaGlobal.devices_present) { bool on = (value & 1); - if (on != (power & (1 << device_group_index))) ExecuteCommandPower(device_group_index + 1, (on ? POWER_ON : POWER_OFF), SRC_REMOTE); + if (on != (TasmotaGlobal.power & (1 << device_group_index))) ExecuteCommandPower(device_group_index + 1, (on ? POWER_ON : POWER_OFF), SRC_REMOTE); } } else if (XdrvMailbox.index & DGR_FLAG_LOCAL) { uint8_t mask_devices = value >> 24; - if (mask_devices > devices_present) mask_devices = devices_present; + if (mask_devices > TasmotaGlobal.devices_present) mask_devices = TasmotaGlobal.devices_present; for (uint32_t i = 0; i < mask_devices; i++) { uint32_t mask = 1 << i; bool on = (value & mask); - if (on != (power & mask)) ExecuteCommandPower(i + 1, (on ? POWER_ON : POWER_OFF), SRC_REMOTE); + if (on != (TasmotaGlobal.power & mask)) ExecuteCommandPower(i + 1, (on ? POWER_ON : POWER_OFF), SRC_REMOTE); } } break; @@ -455,7 +455,7 @@ badmsg: cleanup: if (received) { - skip_light_fade = false; + TasmotaGlobal.skip_light_fade = false; ignore_dgr_sends = false; } } @@ -505,7 +505,7 @@ bool _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes building_status_message = true; // Call the drivers to build the status update. - SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_POWER, power); + SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_POWER, TasmotaGlobal.power); XdrvMailbox.index = 0; if (device_group_index == 0 && first_device_group_is_local) XdrvMailbox.index = DGR_FLAG_LOCAL; XdrvMailbox.command_code = DGR_ITEM_STATUS; @@ -679,7 +679,7 @@ bool _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes *message_ptr++ = value & 0xff; value >>= 8; // For the power item, the device count is overlayed onto the highest 8 bits. - if (item == DGR_ITEM_POWER && !value) value = (device_group_index == 0 && first_device_group_is_local ? devices_present : 1); + if (item == DGR_ITEM_POWER && !value) value = (device_group_index == 0 && first_device_group_is_local ? TasmotaGlobal.devices_present : 1); *message_ptr++ = value; } } @@ -806,7 +806,7 @@ void DeviceGroupStatus(uint8_t device_group_index) void DeviceGroupsLoop(void) { - if (!device_groups_up || restart_flag) return; + if (!device_groups_up || TasmotaGlobal.restart_flag) return; while (device_groups_udp.parsePacket()) { uint8_t packet_buffer[512]; diff --git a/tasmota/support_eeprom.ino b/tasmota/support_eeprom.ino index b990aa242..009026e56 100644 --- a/tasmota/support_eeprom.ino +++ b/tasmota/support_eeprom.ino @@ -39,7 +39,7 @@ void eeprom_readBytes(uint32_t addr, uint32_t len, uint8_t *buff) { } uint32_t eeprom_init(uint32_t size) { - if (i2c_flg) { + if (TasmotaGlobal.i2c_enabled) { if (I2cActive(EEPROM_ADDRESS) || I2cSetDevice(EEPROM_ADDRESS)) { // eeprom is present I2cSetActiveFound(EEPROM_ADDRESS, "24C256"); diff --git a/tasmota/support_esp32.ino b/tasmota/support_esp32.ino index 38e8c908f..c1cc3dd8e 100644 --- a/tasmota/support_esp32.ino +++ b/tasmota/support_esp32.ino @@ -168,13 +168,13 @@ void SntpInit() { uint32_t SntpGetCurrentTimestamp(void) { time_t now = 0; - if (bNetIsTimeSync || ntp_force_sync) + if (bNetIsTimeSync || TasmotaGlobal.ntp_force_sync) { - //Serial_DebugX(("timesync configTime %d\n", ntp_force_sync, bNetIsTimeSync)); + //Serial_DebugX(("timesync configTime %d\n", TasmotaGlobal.ntp_force_sync, bNetIsTimeSync)); // init to UTC Time configTime(0, 0, SettingsText(SET_NTPSERVER1), SettingsText(SET_NTPSERVER2), SettingsText(SET_NTPSERVER3)); bNetIsTimeSync = false; - ntp_force_sync = false; + TasmotaGlobal.ntp_force_sync = false; } time(&now); return now; diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index f4ee77603..4181a7f77 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -21,663 +21,668 @@ * Fill feature list \*********************************************************************************************/ -void GetFeatures(void) +void ResponseAppendFeatures(void) { - feature_drv1 = 0x00000000; - + static uint32_t feature1 = 0x00000000; + if (!feature1) { // Only fill this once #if defined(USE_ENERGY_SENSOR) && defined(USE_ENERGY_MARGIN_DETECTION) - feature_drv1 |= 0x00000001; // xdrv_03_energy.ino + feature1 |= 0x00000001; // xdrv_03_energy.ino #endif #ifdef USE_LIGHT - feature_drv1 |= 0x00000002; // tasmota.ino, xdrv_04_light.ino + feature1 |= 0x00000002; // tasmota.ino, xdrv_04_light.ino #endif #ifdef USE_I2C - feature_drv1 |= 0x00000004; // tasmota.ino + feature1 |= 0x00000004; // tasmota.ino #endif #ifdef USE_SPI - feature_drv1 |= 0x00000008; // tasmota.ino + feature1 |= 0x00000008; // tasmota.ino #endif #ifdef USE_DISCOVERY - feature_drv1 |= 0x00000010; // tasmota.ino + feature1 |= 0x00000010; // tasmota.ino #endif #ifdef USE_ARDUINO_OTA - feature_drv1 |= 0x00000020; // tasmota.ino + feature1 |= 0x00000020; // tasmota.ino #endif #ifdef USE_MQTT_TLS - feature_drv1 |= 0x00000040; // xdrv_02_mqtt.ino + feature1 |= 0x00000040; // xdrv_02_mqtt.ino #endif #ifdef USE_WEBSERVER - feature_drv1 |= 0x00000080; // xdrv_01_webserver.ino + feature1 |= 0x00000080; // xdrv_01_webserver.ino #endif #if defined(USE_WEBSERVER) && defined(WEBSERVER_ADVERTISE) - feature_drv1 |= 0x00000100; // xdrv_01_webserver.ino + feature1 |= 0x00000100; // xdrv_01_webserver.ino #endif #if defined(USE_WEBSERVER) && defined(USE_EMULATION_HUE) - feature_drv1 |= 0x00000200; // xdrv_20_hue.ino + feature1 |= 0x00000200; // xdrv_20_hue.ino #endif //#if (MQTT_LIBRARY_TYPE == MQTT_PUBSUBCLIENT) - feature_drv1 |= 0x00000400; // xdrv_02_mqtt.ino + feature1 |= 0x00000400; // xdrv_02_mqtt.ino //#endif //#if (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT) -// feature_drv1 |= 0x00000800; // xdrv_02_mqtt.ino +// feature1 |= 0x00000800; // xdrv_02_mqtt.ino //#endif //#if (MQTT_LIBRARY_TYPE == MQTT_ESPMQTTARDUINO) // Obsolete since 6.2.1.11 -// feature_drv1 |= 0x00001000; // xdrv_02_mqtt.ino +// feature1 |= 0x00001000; // xdrv_02_mqtt.ino //#endif #if defined(USE_DISCOVERY) && defined(MQTT_HOST_DISCOVERY) - feature_drv1 |= 0x00002000; // xdrv_02_mqtt.ino + feature1 |= 0x00002000; // xdrv_02_mqtt.ino #endif #if defined(USE_LIGHT) && defined(USE_ARILUX_RF) - feature_drv1 |= 0x00004000; // xdrv_04_light.ino + feature1 |= 0x00004000; // xdrv_04_light.ino #endif #if defined(USE_LIGHT) && defined(USE_WS2812) - feature_drv1 |= 0x00008000; // xdrv_04_light.ino + feature1 |= 0x00008000; // xdrv_04_light.ino #endif #if defined(USE_LIGHT) && defined(USE_WS2812) && defined(USE_WS2812_DMA) - feature_drv1 |= 0x00010000; // xdrv_04_light.ino + feature1 |= 0x00010000; // xdrv_04_light.ino #endif #if defined(USE_IR_REMOTE) || defined(USE_IR_REMOTE_FULL) - feature_drv1 |= 0x00020000; // xdrv_05_irremote.ino + feature1 |= 0x00020000; // xdrv_05_irremote.ino #endif #ifdef USE_IR_HVAC - feature_drv1 |= 0x00040000; // xdrv_05_irremote.ino + feature1 |= 0x00040000; // xdrv_05_irremote.ino #endif #if defined(USE_IR_REMOTE) && defined(USE_IR_RECEIVE) - feature_drv1 |= 0x00080000; // xdrv_05_irremote.ino + feature1 |= 0x00080000; // xdrv_05_irremote.ino #endif #ifdef USE_DOMOTICZ - feature_drv1 |= 0x00100000; // xdrv_07_domoticz.ino + feature1 |= 0x00100000; // xdrv_07_domoticz.ino #endif #ifdef USE_DISPLAY - feature_drv1 |= 0x00200000; // xdrv_13_display.ino + feature1 |= 0x00200000; // xdrv_13_display.ino #endif #ifdef USE_HOME_ASSISTANT - feature_drv1 |= 0x00400000; // xdrv_12_home_assistant.ino + feature1 |= 0x00400000; // xdrv_12_home_assistant.ino #endif #ifdef USE_SERIAL_BRIDGE - feature_drv1 |= 0x00800000; // xdrv_08_serial_bridge.ino + feature1 |= 0x00800000; // xdrv_08_serial_bridge.ino #endif #ifdef USE_TIMERS - feature_drv1 |= 0x01000000; // xdrv_09_timers.ino + feature1 |= 0x01000000; // xdrv_09_timers.ino #endif #if defined(USE_TIMERS) && defined(USE_SUNRISE) - feature_drv1 |= 0x02000000; // xdrv_09_timers.ino + feature1 |= 0x02000000; // xdrv_09_timers.ino #endif #if defined(USE_TIMERS) && defined(USE_TIMERS_WEB) - feature_drv1 |= 0x04000000; // xdrv_09_timers.ino + feature1 |= 0x04000000; // xdrv_09_timers.ino #endif #ifdef USE_RULES - feature_drv1 |= 0x08000000; // xdrv_10_rules.ino + feature1 |= 0x08000000; // xdrv_10_rules.ino #endif #ifdef USE_KNX - feature_drv1 |= 0x10000000; // xdrv_11_knx.ino + feature1 |= 0x10000000; // xdrv_11_knx.ino #endif #ifdef USE_WPS - feature_drv1 |= 0x20000000; // support.ino - removed with version 6.6.0.21 + feature1 |= 0x20000000; // support.ino - removed with version 6.6.0.21 #endif #ifdef USE_SMARTCONFIG - feature_drv1 |= 0x40000000; // support.ino - removed with version 6.6.0.21 + feature1 |= 0x40000000; // support.ino - removed with version 6.6.0.21 #endif #if defined(USE_ENERGY_SENSOR) && defined(USE_ENERGY_POWER_LIMIT) - feature_drv1 |= 0x80000000; // xdrv_03_energy.ino + feature1 |= 0x80000000; // xdrv_03_energy.ino #endif + } -/*********************************************************************************************/ - - feature_drv2 = 0x00000000; - + static uint32_t feature2 = 0x00000000; + if (!feature2) { // Only fill this once #ifdef USE_CONFIG_OVERRIDE - feature_drv2 |= 0x00000001; // user_config(_override).h + feature2 |= 0x00000001; // user_config(_override).h #endif #ifdef FIRMWARE_MINIMAL - feature_drv2 |= 0x00000002; // user_config(_override).h + feature2 |= 0x00000002; // user_config(_override).h #endif #ifdef FIRMWARE_SENSORS - feature_drv2 |= 0x00000004; // user_config(_override).h + feature2 |= 0x00000004; // user_config(_override).h #endif #ifdef FIRMWARE_CLASSIC - feature_drv2 |= 0x00000008; // user_config(_override).h + feature2 |= 0x00000008; // user_config(_override).h #endif #ifdef FIRMWARE_KNX_NO_EMULATION - feature_drv2 |= 0x00000010; // user_config(_override).h + feature2 |= 0x00000010; // user_config(_override).h #endif #if defined(USE_DISPLAY) && defined(USE_DISPLAY_MODES1TO5) - feature_drv2 |= 0x00000020; // xdrv_13_display.ino + feature2 |= 0x00000020; // xdrv_13_display.ino #endif #if defined(USE_DISPLAY) && defined(USE_DISPLAY_GRAPH) - feature_drv2 |= 0x00000040; // xdrv_13_display.ino + feature2 |= 0x00000040; // xdrv_13_display.ino #endif #if defined(USE_I2C) && defined(USE_DISPLAY) && defined(USE_DISPLAY_LCD) - feature_drv2 |= 0x00000080; // xdsp_01_lcd.ino + feature2 |= 0x00000080; // xdsp_01_lcd.ino #endif #if defined(USE_I2C) && defined(USE_DISPLAY) && defined(USE_DISPLAY_SSD1306) - feature_drv2 |= 0x00000100; // xdsp_02_ssd1306.ino + feature2 |= 0x00000100; // xdsp_02_ssd1306.ino #endif #if defined(USE_I2C) && defined(USE_DISPLAY) && defined(USE_DISPLAY_MATRIX) - feature_drv2 |= 0x00000200; // xdsp_03_matrix.ino + feature2 |= 0x00000200; // xdsp_03_matrix.ino #endif #if defined(USE_SPI) && defined(USE_DISPLAY) && defined(USE_DISPLAY_ILI9341) - feature_drv2 |= 0x00000400; // xdsp_04_ili9341.ino + feature2 |= 0x00000400; // xdsp_04_ili9341.ino #endif #if defined(USE_SPI) && defined(USE_DISPLAY) && defined(USE_DISPLAY_EPAPER_29) - feature_drv2 |= 0x00000800; // xdsp_05_epaper.ino + feature2 |= 0x00000800; // xdsp_05_epaper.ino #endif #if defined(USE_I2C) && defined(USE_DISPLAY) && defined(USE_DISPLAY_SH1106) - feature_drv2 |= 0x00001000; // xdsp_06_sh1106.ino + feature2 |= 0x00001000; // xdsp_06_sh1106.ino #endif #ifdef USE_MP3_PLAYER - feature_drv2 |= 0x00002000; // xdrv_14_mp3.ino + feature2 |= 0x00002000; // xdrv_14_mp3.ino #endif #if defined(USE_I2C) && defined(USE_PCA9685) - feature_drv2 |= 0x00004000; // xdrv_15_pca9685.ino + feature2 |= 0x00004000; // xdrv_15_pca9685.ino #endif #if defined(USE_LIGHT) && defined(USE_TUYA_MCU) - feature_drv2 |= 0x00008000; // xdrv_16_tuyadimmer.ino + feature2 |= 0x00008000; // xdrv_16_tuyadimmer.ino #endif #ifdef USE_RC_SWITCH - feature_drv2 |= 0x00010000; // xdrv_17_rcswitch.ino + feature2 |= 0x00010000; // xdrv_17_rcswitch.ino #endif #if defined(USE_LIGHT) && defined(USE_ARMTRONIX_DIMMERS) - feature_drv2 |= 0x00020000; // xdrv_18_armtronixdimmer.ino + feature2 |= 0x00020000; // xdrv_18_armtronixdimmer.ino #endif #if defined(USE_LIGHT) && defined(USE_SM16716) - feature_drv2 |= 0x00040000; // xdrv_04_light.ino + feature2 |= 0x00040000; // xdrv_04_light.ino #endif #ifdef USE_SCRIPT - feature_drv2 |= 0x00080000; // xdrv_10_scripter.ino + feature2 |= 0x00080000; // xdrv_10_scripter.ino #endif #if defined(USE_WEBSERVER) && defined(USE_EMULATION_WEMO) - feature_drv2 |= 0x00100000; // xdrv_21_wemo.ino + feature2 |= 0x00100000; // xdrv_21_wemo.ino #endif #ifdef USE_SONOFF_IFAN - feature_drv2 |= 0x00200000; // xdrv_22_sonoff_ifan.ino + feature2 |= 0x00200000; // xdrv_22_sonoff_ifan.ino #endif #ifdef USE_ZIGBEE - feature_drv2 |= 0x00400000; // xdrv_23_zigbee.ino + feature2 |= 0x00400000; // xdrv_23_zigbee.ino #endif #ifdef NO_EXTRA_4K_HEAP - feature_drv2 |= 0x00800000; // sonoff_post.h + feature2 |= 0x00800000; // sonoff_post.h #endif #ifdef VTABLES_IN_IRAM - feature_drv2 |= 0x01000000; // platformio.ini + feature2 |= 0x01000000; // platformio.ini #endif #ifdef VTABLES_IN_DRAM - feature_drv2 |= 0x02000000; // platformio.ini + feature2 |= 0x02000000; // platformio.ini #endif #ifdef VTABLES_IN_FLASH - feature_drv2 |= 0x04000000; // platformio.ini + feature2 |= 0x04000000; // platformio.ini #endif #ifdef PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH - feature_drv2 |= 0x08000000; // platformio.ini + feature2 |= 0x08000000; // platformio.ini #endif #ifdef PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY - feature_drv2 |= 0x10000000; // platformio.ini + feature2 |= 0x10000000; // platformio.ini #endif #ifdef PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH - feature_drv2 |= 0x20000000; // platformio.ini + feature2 |= 0x20000000; // platformio.ini #endif #ifdef DEBUG_THEO - feature_drv2 |= 0x40000000; // xdrv_99_debug.ino + feature2 |= 0x40000000; // xdrv_99_debug.ino #endif #ifdef USE_DEBUG_DRIVER - feature_drv2 |= 0x80000000; // xdrv_99_debug.ino + feature2 |= 0x80000000; // xdrv_99_debug.ino #endif + } -/*********************************************************************************************/ - - feature_sns1 = 0x00000000; - + static uint32_t feature3 = 0x00000000; + if (!feature3) { // Only fill this once #ifdef USE_COUNTER - feature_sns1 |= 0x00000001; // xsns_01_counter.ino + feature3 |= 0x00000001; // xsns_01_counter.ino #endif #if defined(USE_ADC_VCC) || defined(USE_ADC) - feature_sns1 |= 0x00000002; // xsns_02_analog.ino + feature3 |= 0x00000002; // xsns_02_analog.ino #endif #ifdef USE_ENERGY_SENSOR - feature_sns1 |= 0x00000004; // xdrv_03_energy.ino + feature3 |= 0x00000004; // xdrv_03_energy.ino #endif #if defined(USE_ENERGY_SENSOR) && defined(USE_PZEM004T) - feature_sns1 |= 0x00000008; // xnrg_03_pzem004t.ino + feature3 |= 0x00000008; // xnrg_03_pzem004t.ino #endif #ifdef USE_DS18B20 - feature_sns1 |= 0x00000010; // xsns_05_ds18b20.ino - no more support since 6.6.0.18 + feature3 |= 0x00000010; // xsns_05_ds18b20.ino - no more support since 6.6.0.18 #endif #ifdef USE_DS18x20_LEGACY - feature_sns1 |= 0x00000020; // xsns_05_ds18x20_legacy.ino - no more support since 6.6.0.14 + feature3 |= 0x00000020; // xsns_05_ds18x20_legacy.ino - no more support since 6.6.0.14 #endif #ifdef USE_DS18x20 - feature_sns1 |= 0x00000040; // xsns_05_ds18x20.ino + feature3 |= 0x00000040; // xsns_05_ds18x20.ino #endif #ifdef USE_DHT - feature_sns1 |= 0x00000080; // xsns_06_dht.ino + feature3 |= 0x00000080; // xsns_06_dht.ino #endif #if defined(USE_I2C) && defined(USE_SHT) - feature_sns1 |= 0x00000100; // xsns_07_sht1x.ino + feature3 |= 0x00000100; // xsns_07_sht1x.ino #endif #if defined(USE_I2C) && defined(USE_HTU) - feature_sns1 |= 0x00000200; // xsns_08_htu21.ino + feature3 |= 0x00000200; // xsns_08_htu21.ino #endif #if defined(USE_I2C) && defined(USE_BMP) - feature_sns1 |= 0x00000400; // xsns_09_bmp.ino + feature3 |= 0x00000400; // xsns_09_bmp.ino #endif #if defined(USE_I2C) && defined(USE_BMP) && defined(USE_BME680) - feature_sns1 |= 0x00000800; // xsns_09_bmp.ino - BME680 + feature3 |= 0x00000800; // xsns_09_bmp.ino - BME680 #endif #if defined(USE_I2C) && defined(USE_BH1750) - feature_sns1 |= 0x00001000; // xsns_10_bh1750.ino + feature3 |= 0x00001000; // xsns_10_bh1750.ino #endif #if defined(USE_I2C) && defined(USE_VEML6070) - feature_sns1 |= 0x00002000; // xsns_11_veml6070.ino + feature3 |= 0x00002000; // xsns_11_veml6070.ino #endif #if defined(USE_I2C) && defined(USE_ADS1115_I2CDEV) - feature_sns1 |= 0x00004000; // xsns_12_ads1115_i2cdev.ino + feature3 |= 0x00004000; // xsns_12_ads1115_i2cdev.ino #endif #if defined(USE_I2C) && defined(USE_ADS1115) - feature_sns1 |= 0x00008000; // xsns_12_ads1115.ino + feature3 |= 0x00008000; // xsns_12_ads1115.ino #endif #if defined(USE_I2C) && defined(USE_INA219) - feature_sns1 |= 0x00010000; // xsns_13_ina219.ino + feature3 |= 0x00010000; // xsns_13_ina219.ino #endif #if defined(USE_I2C) && defined(USE_SHT3X) - feature_sns1 |= 0x00020000; // xsns_14_sht3x.ino + feature3 |= 0x00020000; // xsns_14_sht3x.ino #endif #ifdef USE_MHZ19 - feature_sns1 |= 0x00040000; // xsns_15_mhz19.ino + feature3 |= 0x00040000; // xsns_15_mhz19.ino #endif #if defined(USE_I2C) && defined(USE_TSL2561) - feature_sns1 |= 0x00080000; // xsns_16_tsl2561.ino + feature3 |= 0x00080000; // xsns_16_tsl2561.ino #endif #ifdef USE_SENSEAIR - feature_sns1 |= 0x00100000; // xsns_17_senseair.ino + feature3 |= 0x00100000; // xsns_17_senseair.ino #endif #ifdef USE_PMS5003 - feature_sns1 |= 0x00200000; // xsns_18_pms5003.ino + feature3 |= 0x00200000; // xsns_18_pms5003.ino #endif #if defined(USE_I2C) && defined(USE_MGS) - feature_sns1 |= 0x00400000; // xsns_19_mgs.ino + feature3 |= 0x00400000; // xsns_19_mgs.ino #endif #ifdef USE_NOVA_SDS - feature_sns1 |= 0x00800000; // xsns_20_novasds.ino + feature3 |= 0x00800000; // xsns_20_novasds.ino #endif #if defined(USE_I2C) && defined(USE_SGP30) - feature_sns1 |= 0x01000000; // xsns_21_sgp30.ino + feature3 |= 0x01000000; // xsns_21_sgp30.ino #endif #ifdef USE_SR04 - feature_sns1 |= 0x02000000; // xsns_22_sr04.ino + feature3 |= 0x02000000; // xsns_22_sr04.ino #endif #if defined(USE_ENERGY_SENSOR) && defined(USE_SDM120) - feature_sns1 |= 0x04000000; // xnrg_08_sdm120.ino + feature3 |= 0x04000000; // xnrg_08_sdm120.ino #endif #if defined(USE_I2C) && defined(USE_SI1145) - feature_sns1 |= 0x08000000; // xsns_24_si1145.ino + feature3 |= 0x08000000; // xsns_24_si1145.ino #endif #if defined(USE_ENERGY_SENSOR) && defined(USE_SDM630) - feature_sns1 |= 0x10000000; // xnrg_10_sdm630.ino + feature3 |= 0x10000000; // xnrg_10_sdm630.ino #endif #if defined(USE_I2C) && defined(USE_LM75AD) - feature_sns1 |= 0x20000000; // xsns_26_lm75ad.ino + feature3 |= 0x20000000; // xsns_26_lm75ad.ino #endif #if defined(USE_I2C) && defined(USE_APDS9960) - feature_sns1 |= 0x40000000; // xsns_27_apds9960.ino + feature3 |= 0x40000000; // xsns_27_apds9960.ino #endif #ifdef USE_TM1638 - feature_sns1 |= 0x80000000; // xsns_28_tm1638.ino + feature3 |= 0x80000000; // xsns_28_tm1638.ino #endif -/*********************************************************************************************/ - - feature_sns2 = 0x00000000; + } + static uint32_t feature4 = 0x00000000; + if (!feature4) { // Only fill this once #if defined(USE_I2C) && defined(USE_MCP230xx) - feature_sns2 |= 0x00000001; // xsns_29_mcp230xx.ino + feature4 |= 0x00000001; // xsns_29_mcp230xx.ino #endif #if defined(USE_I2C) && defined(USE_MPR121) - feature_sns2 |= 0x00000002; // xsns_30_mpr121.ino + feature4 |= 0x00000002; // xsns_30_mpr121.ino #endif #if defined(USE_I2C) && defined(USE_CCS811) - feature_sns2 |= 0x00000004; // xsns_31_ccs811.ino + feature4 |= 0x00000004; // xsns_31_ccs811.ino #endif #if defined(USE_I2C) && defined(USE_MPU6050) - feature_sns2 |= 0x00000008; // xsns_32_mpu6050.ino + feature4 |= 0x00000008; // xsns_32_mpu6050.ino #endif #if defined(USE_I2C) && defined(USE_MCP230xx) && defined(USE_MCP230xx_OUTPUT) - feature_sns2 |= 0x00000010; // xsns_29_mcp230xx.ino + feature4 |= 0x00000010; // xsns_29_mcp230xx.ino #endif #if defined(USE_I2C) && defined(USE_MCP230xx) && defined(USE_MCP230xx_DISPLAYOUTPUT) - feature_sns2 |= 0x00000020; // xsns_29_mcp230xx.ino + feature4 |= 0x00000020; // xsns_29_mcp230xx.ino #endif #if defined(USE_ENERGY_SENSOR) && defined(USE_HLW8012) - feature_sns2 |= 0x00000040; // xnrg_01_hlw8012.ino + feature4 |= 0x00000040; // xnrg_01_hlw8012.ino #endif #if defined(USE_ENERGY_SENSOR) && defined(USE_CSE7766) - feature_sns2 |= 0x00000080; // xnrg_02_cse7766.ino + feature4 |= 0x00000080; // xnrg_02_cse7766.ino #endif #if defined(USE_ENERGY_SENSOR) && defined(USE_MCP39F501) - feature_sns2 |= 0x00000100; // xnrg_04_mcp39f501.ino + feature4 |= 0x00000100; // xnrg_04_mcp39f501.ino #endif #if defined(USE_ENERGY_SENSOR) && defined(USE_PZEM_AC) - feature_sns2 |= 0x00000200; // xnrg_05_pzem_ac.ino + feature4 |= 0x00000200; // xnrg_05_pzem_ac.ino #endif #if defined(USE_I2C) && defined(USE_DS3231) - feature_sns2 |= 0x00000400; // xsns_33_ds3231.ino + feature4 |= 0x00000400; // xsns_33_ds3231.ino #endif #ifdef USE_HX711 - feature_sns2 |= 0x00000800; // xsns_34_hx711.ino + feature4 |= 0x00000800; // xsns_34_hx711.ino #endif #if defined(USE_ENERGY_SENSOR) && defined(USE_PZEM_DC) - feature_sns2 |= 0x00001000; // xnrg_06_pzem_dc.ino + feature4 |= 0x00001000; // xnrg_06_pzem_dc.ino #endif #if defined(USE_TX20_WIND_SENSOR) || defined(USE_TX23_WIND_SENSOR) - feature_sns2 |= 0x00002000; // xsns_35_tx20.ino + feature4 |= 0x00002000; // xsns_35_tx20.ino #endif #if defined(USE_I2C) && defined(USE_MGC3130) - feature_sns2 |= 0x00004000; // xsns_36_mgc3130.ino + feature4 |= 0x00004000; // xsns_36_mgc3130.ino #endif #ifdef USE_RF_SENSOR - feature_sns2 |= 0x00008000; // xsns_37_rfsensor.ino + feature4 |= 0x00008000; // xsns_37_rfsensor.ino #endif #if defined(USE_RF_SENSOR) && defined(USE_THEO_V2) - feature_sns2 |= 0x00010000; // xsns_37_rfsensor.ino + feature4 |= 0x00010000; // xsns_37_rfsensor.ino #endif #if defined(USE_RF_SENSOR) && defined(USE_ALECTO_V2) - feature_sns2 |= 0x00020000; // xsns_37_rfsensor.ino + feature4 |= 0x00020000; // xsns_37_rfsensor.ino #endif #ifdef USE_AZ7798 - feature_sns2 |= 0x00040000; // xsns_38_az7798.ino + feature4 |= 0x00040000; // xsns_38_az7798.ino #endif #ifdef USE_MAX31855 - feature_sns2 |= 0x00080000; // xsns_39_max31855.ino + feature4 |= 0x00080000; // xsns_39_max31855.ino #endif #ifdef USE_PN532_HSU - feature_sns2 |= 0x00100000; // xsns_40_pn532.ino + feature4 |= 0x00100000; // xsns_40_pn532.ino #endif #if defined(USE_I2C) && defined(USE_MAX44009) - feature_sns2 |= 0x00200000; // xsns_41_max44009.ino + feature4 |= 0x00200000; // xsns_41_max44009.ino #endif #if defined(USE_I2C) && defined(USE_SCD30) - feature_sns2 |= 0x00400000; // xsns_42_scd30.ino + feature4 |= 0x00400000; // xsns_42_scd30.ino #endif #ifdef USE_HRE - feature_sns2 |= 0x00800000; // xsns_43_hre.ino + feature4 |= 0x00800000; // xsns_43_hre.ino #endif #if defined(USE_ENERGY_SENSOR) && defined(USE_ADE7953) - feature_sns2 |= 0x01000000; // xnrg_07_ade7953.ino + feature4 |= 0x01000000; // xnrg_07_ade7953.ino #endif #if defined(USE_I2C) && defined(USE_SPS30) - feature_sns2 |= 0x02000000; // xsns_44_sps30.ino + feature4 |= 0x02000000; // xsns_44_sps30.ino #endif #if defined(USE_I2C) && defined(USE_VL53L0X) - feature_sns2 |= 0x04000000; // xsns_45_vl53l0x.ino + feature4 |= 0x04000000; // xsns_45_vl53l0x.ino #endif #if defined(USE_I2C) && defined(USE_MLX90614) - feature_sns2 |= 0x08000000; // xsns_46_MLX90614.ino + feature4 |= 0x08000000; // xsns_46_MLX90614.ino #endif #ifdef USE_MAX31865 - feature_sns2 |= 0x10000000; // xsns_47-max31865.ino + feature4 |= 0x10000000; // xsns_47-max31865.ino #endif #if defined(USE_I2C) && defined(USE_CHIRP) - feature_sns2 |= 0x20000000; // xsns_48_chirp.ino + feature4 |= 0x20000000; // xsns_48_chirp.ino #endif #if defined(USE_ENERGY_SENSOR) && defined(USE_SOLAX_X1) - feature_sns2 |= 0x40000000; // xnrg_12_solaxX1.ino + feature4 |= 0x40000000; // xnrg_12_solaxX1.ino #endif #if defined(USE_I2C) && defined(USE_PAJ7620) - feature_sns2 |= 0x80000000; // xsns_50_paj7620.ino + feature4 |= 0x80000000; // xsns_50_paj7620.ino #endif + } -/*********************************************************************************************/ - - feature5 = 0x00000000; - + static uint32_t feature5 = 0x00000000; + if (!feature5) { // Only fill this once #ifdef USE_BUZZER - feature5 |= 0x00000001; // xdrv_24_buzzer.ino + feature5 |= 0x00000001; // xdrv_24_buzzer.ino #endif #ifdef USE_RDM6300 - feature5 |= 0x00000002; // xsns_51_rdm6300.ino + feature5 |= 0x00000002; // xsns_51_rdm6300.ino #endif #ifdef USE_IBEACON - feature5 |= 0x00000004; // xsns_52_ibeacon.ino + feature5 |= 0x00000004; // xsns_52_ibeacon.ino #endif #ifdef USE_SML_M - feature5 |= 0x00000008; // xsns_53_sml.ino + feature5 |= 0x00000008; // xsns_53_sml.ino #endif #if defined(USE_I2C) && defined(USE_INA226) - feature5 |= 0x00000010; // xsns_54_ina226.ino + feature5 |= 0x00000010; // xsns_54_ina226.ino #endif #ifdef USE_A4988_STEPPER - feature5 |= 0x00000020; // xdrv_25_A4988.ino + feature5 |= 0x00000020; // xdrv_25_A4988.ino #endif #if defined(USE_ENERGY_SENSOR) && defined(USE_DDS2382) - feature5 |= 0x00000040; // xnrg_09_dds2382.ino + feature5 |= 0x00000040; // xnrg_09_dds2382.ino #endif #if defined(USE_LIGHT) && defined(USE_SM2135) - feature5 |= 0x00000080; // xdrv_026_sm2135.ino + feature5 |= 0x00000080; // xdrv_026_sm2135.ino #endif #ifdef USE_SHUTTER - feature5 |= 0x00000100; // xdrv_027_shutter.ino + feature5 |= 0x00000100; // xdrv_027_shutter.ino #endif #if defined(USE_I2C) && defined(USE_PCF8574) - feature5 |= 0x00000200; // xdrv_028_pcf8574.ino + feature5 |= 0x00000200; // xdrv_028_pcf8574.ino #endif #if defined(USE_ENERGY_SENSOR) && defined(USE_DDSU666) - feature5 |= 0x00000400; // xnrg_11_ddsu666.ino + feature5 |= 0x00000400; // xnrg_11_ddsu666.ino #endif #ifdef USE_DEEPSLEEP - feature5 |= 0x00000800; // xdrv_029_deepsleep.ino + feature5 |= 0x00000800; // xdrv_029_deepsleep.ino #endif #ifdef USE_SONOFF_SC - feature5 |= 0x00001000; // xsns_04_snfsc.ino + feature5 |= 0x00001000; // xsns_04_snfsc.ino #endif #ifdef USE_SONOFF_RF - feature5 |= 0x00002000; // xdrv_06_snfbridge.ino + feature5 |= 0x00002000; // xdrv_06_snfbridge.ino #endif #if defined(USE_LIGHT) && defined(USE_SONOFF_L1) - feature5 |= 0x00004000; // xlgt_05_sonoff_l1.ino + feature5 |= 0x00004000; // xlgt_05_sonoff_l1.ino #endif #if defined(USE_LIGHT) && defined(USE_EXS_DIMMER) - feature5 |= 0x00008000; // xdrv_30_exs_dimmer.ino + feature5 |= 0x00008000; // xdrv_30_exs_dimmer.ino #endif #ifdef USE_TASMOTA_CLIENT - feature5 |= 0x00010000; // xdrv_31_tasmota_client.ino + feature5 |= 0x00010000; // xdrv_31_tasmota_client.ino #endif #if defined(USE_I2C) && defined(USE_HIH6) - feature5 |= 0x00020000; // xsns_55_hih_series.ino + feature5 |= 0x00020000; // xsns_55_hih_series.ino #endif #ifdef USE_HPMA - feature5 |= 0x00040000; // xsns_56_hpma.ino + feature5 |= 0x00040000; // xsns_56_hpma.ino #endif #if defined(USE_I2C) && defined(USE_TSL2591) - feature5 |= 0x00080000; // xsns_57_tsl2591.ino + feature5 |= 0x00080000; // xsns_57_tsl2591.ino #endif #if defined(USE_I2C) && defined(USE_DHT12) - feature5 |= 0x00100000; // xsns_58_dht12.ino + feature5 |= 0x00100000; // xsns_58_dht12.ino #endif #if defined(USE_I2C) && defined(USE_DS1624) - feature5 |= 0x00200000; // xsns_59_ds1624.ino + feature5 |= 0x00200000; // xsns_59_ds1624.ino #endif #ifdef USE_GPS - feature5 |= 0x00400000; // xsns_60_GPS.ino + feature5 |= 0x00400000; // xsns_60_GPS.ino #endif #if defined(USE_I2C) && defined(USE_HOTPLUG) - feature5 |= 0x00800000; // xdrv_32_hotplug.ino + feature5 |= 0x00800000; // xdrv_32_hotplug.ino #endif #ifdef USE_NRF24 - feature5 |= 0x01000000; // xsns_33_nrf24l01.ino + feature5 |= 0x01000000; // xsns_33_nrf24l01.ino #endif #ifdef USE_MIBLE - feature5 |= 0x02000000; // xsns_61_MI_BLE.ino + feature5 |= 0x02000000; // xsns_61_MI_BLE.ino #endif #ifdef USE_HM10 - feature5 |= 0x04000000; // xsns_62_MI_HM10.ino + feature5 |= 0x04000000; // xsns_62_MI_HM10.ino #endif #if defined(USE_ENERGY_SENSOR) && defined(USE_LE01MR) - feature5 |= 0x08000000; // xnrg_13_fif_le01mr.ino + feature5 |= 0x08000000; // xnrg_13_fif_le01mr.ino #endif #if defined(USE_I2C) && defined(USE_AHT1x) - feature5 |= 0x10000000; // xsns_63_aht1x.ino + feature5 |= 0x10000000; // xsns_63_aht1x.ino #endif #if defined(USE_I2C) && defined(USE_WEMOS_MOTOR_V1) - feature5 |= 0x20000000; // xdrv_34_wemos_motor_v1.ino + feature5 |= 0x20000000; // xdrv_34_wemos_motor_v1.ino #endif #ifdef USE_DEVICE_GROUPS - feature5 |= 0x40000000; // support_device_groups.ino + feature5 |= 0x40000000; // support_device_groups.ino #endif #ifdef USE_PWM_DIMMER - feature5 |= 0x80000000; // xdrv_35_pwm_dimmer + feature5 |= 0x80000000; // xdrv_35_pwm_dimmer #endif + } -/*********************************************************************************************/ - - feature6 = 0x00000000; - + static uint32_t feature6 = 0x00000000; + if (!feature6) { // Only fill this once #ifdef USE_KEELOQ - feature6 |= 0x00000001; // xdrv_36_keeloq.ino + feature6 |= 0x00000001; // xdrv_36_keeloq.ino #endif #ifdef USE_HRXL - feature6 |= 0x00000002; // xsns_64_hrxl.ino + feature6 |= 0x00000002; // xsns_64_hrxl.ino #endif #ifdef USE_SONOFF_D1 - feature6 |= 0x00000004; // xdrv_37_sonoff_d1.ino + feature6 |= 0x00000004; // xdrv_37_sonoff_d1.ino #endif #if defined(USE_I2C) && defined(USE_HDC1080) - feature6 |= 0x00000008; // xsns_65_hdc1080.ino + feature6 |= 0x00000008; // xsns_65_hdc1080.ino #endif #if defined(USE_I2C) && defined(USE_IAQ) - feature6 |= 0x00000010; // xsns_66_iAQ.ino + feature6 |= 0x00000010; // xsns_66_iAQ.ino #endif #if defined(USE_DISPLAY) && defined(USE_DISPLAY_SEVENSEG) - feature6 |= 0x00000020; // xdsp_11_sevenseg.ino + feature6 |= 0x00000020; // xdsp_11_sevenseg.ino #endif #if defined(USE_I2C) && defined(USE_AS3935) - feature6 |= 0x00000040; // xsns_67_as3935.ino + feature6 |= 0x00000040; // xsns_67_as3935.ino #endif #ifdef USE_PING - feature6 |= 0x00000080; // xdrv_38_ping.ino + feature6 |= 0x00000080; // xdrv_38_ping.ino #endif #ifdef USE_WINDMETER - feature6 |= 0x00000100; // xsns_68_windmeter.ino + feature6 |= 0x00000100; // xsns_68_windmeter.ino #endif #ifdef USE_OPENTHERM - feature6 |= 0x00000200; // xsns_69_opentherm.ino + feature6 |= 0x00000200; // xsns_69_opentherm.ino #endif #ifdef USE_THERMOSTAT - feature6 |= 0x00000400; // xdrv_39_heating.ino + feature6 |= 0x00000400; // xdrv_39_heating.ino #endif #if defined(USE_I2C) && defined(USE_VEML6075) - feature6 |= 0x00000800; // xsns_70_veml6075.ino + feature6 |= 0x00000800; // xsns_70_veml6075.ino #endif #if defined(USE_I2C) && defined(USE_VEML7700) - feature6 |= 0x00001000; // xsns_71_veml7700.ino + feature6 |= 0x00001000; // xsns_71_veml7700.ino #endif #if defined(USE_I2C) && defined(USE_MCP9808) - feature6 |= 0x00002000; // xsns_72_mcp9808.ino + feature6 |= 0x00002000; // xsns_72_mcp9808.ino #endif #if defined(USE_ENERGY_SENSOR) && defined(USE_BL0940) - feature6 |= 0x00004000; // xnrg_14_bl0940.ino + feature6 |= 0x00004000; // xnrg_14_bl0940.ino #endif #ifdef USE_TELEGRAM - feature6 |= 0x00008000; // xdrv_40_telegram.ino + feature6 |= 0x00008000; // xdrv_40_telegram.ino #endif #if defined(USE_I2C) && defined(USE_HP303B) - feature6 |= 0x00010000; // xsns_73_hp303b.ino + feature6 |= 0x00010000; // xsns_73_hp303b.ino #endif #ifdef USE_TCP_BRIDGE - feature6 |= 0x00020000; // xdrv_41_tcp_bridge.ino + feature6 |= 0x00020000; // xdrv_41_tcp_bridge.ino #endif #if defined(USE_ENERGY_SENSOR) && defined(USE_TELEINFO) - feature6 |= 0x00040000; // xnrg_15_teleinfo.ino + feature6 |= 0x00040000; // xnrg_15_teleinfo.ino #endif #ifdef USE_LMT01 - feature6 |= 0x00080000; // xsns_74_lmt01.ino + feature6 |= 0x00080000; // xsns_74_lmt01.ino #endif #ifdef USE_PROMETHEUS - feature6 |= 0x00100000; // xsns_75_prometheus.ino + feature6 |= 0x00100000; // xsns_75_prometheus.ino #endif #if defined(USE_ENERGY_SENSOR) && defined(USE_IEM3000) - feature6 |= 0x00200000; // xnrg_16_iem3000.ino + feature6 |= 0x00200000; // xnrg_16_iem3000.ino #endif #ifdef USE_DYP - feature6 |= 0x00400000; // xsns_76_dyp.ino + feature6 |= 0x00400000; // xsns_76_dyp.ino #endif #ifdef USE_I2S_AUDIO - feature6 |= 0x00800000; // xdrv_42_i2s_audio.ino + feature6 |= 0x00800000; // xdrv_42_i2s_audio.ino #endif #ifdef USE_MLX90640 - feature6 |= 0x01000000; // xdrv_43_mlx90640.ino + feature6 |= 0x01000000; // xdrv_43_mlx90640.ino #endif #if defined(USE_I2C) && defined(USE_VL53L1X) - feature6 |= 0x02000000; // xsns_77_vl53l1x.ino + feature6 |= 0x02000000; // xsns_77_vl53l1x.ino #endif #ifdef USE_MIEL_HVAC - feature6 |= 0x04000000; // xdrv_44_miel_hvac.ino + feature6 |= 0x04000000; // xdrv_44_miel_hvac.ino #endif #if defined(USE_ENERGY_SENSOR) && defined(USE_WE517) - feature6 |= 0x08000000; // xnrg_17_ornowe517.ino + feature6 |= 0x08000000; // xnrg_17_ornowe517.ino #endif #if defined(USE_I2C) && defined(USE_EZOPH) - feature6 |= 0x10000000; // xsns_78_ezoph.ino + feature6 |= 0x10000000; // xsns_78_ezoph.ino #endif #if defined(ESP32) && defined(USE_TTGO_WATCH) - feature6 |= 0x20000000; // xdrv_83_esp32watch.ino + feature6 |= 0x20000000; // xdrv_83_esp32watch.ino #endif #if defined(ESP32) && defined(USE_ETHERNET) - feature6 |= 0x40000000; // xdrv_82_ethernet.ino + feature6 |= 0x40000000; // xdrv_82_ethernet.ino #endif #if defined(ESP32) && defined(USE_WEBCAM) - feature6 |= 0x80000000; // xdrv_81_webcam.ino + feature6 |= 0x80000000; // xdrv_81_webcam.ino #endif + } + + static uint32_t feature7 = 0x00000000; + if (!feature7) { // Only fill this once +#if defined(USE_I2C) && defined(USE_EZOORP) + feature7 |= 0x00000001; // xsns_78_ezoorp.ino +#endif +#if defined(USE_I2C) && defined(USE_EZORTD) + feature7 |= 0x00000002; // xsns_78_ezortd.ino +#endif +#if defined(USE_I2C) && defined(USE_EZOHUM) + feature7 |= 0x00000004; // xsns_78_ezohum.ino +#endif +#if defined(USE_I2C) && defined(USE_EZOEC) + feature7 |= 0x00000008; // xsns_78_ezoec.ino +#endif +#if defined(USE_I2C) && defined(USE_EZOCO2) + feature7 |= 0x00000010; // xsns_78_ezoco2.ino +#endif +#if defined(USE_I2C) && defined(USE_EZOO2) + feature7 |= 0x00000020; // xsns_78_ezoo2.ino +#endif +#if defined(USE_I2C) && defined(USE_EZOPRS) + feature7 |= 0x00000040; // xsns_78_ezoprs.ino +#endif +#if defined(USE_I2C) && defined(USE_EZOFLO) + feature7 |= 0x00000080; +#endif + +// feature7 |= 0x00000100; +// feature7 |= 0x00000200; +// feature7 |= 0x00000400; +// feature7 |= 0x00000800; + +// feature7 |= 0x00001000; +// feature7 |= 0x00002000; +// feature7 |= 0x00004000; +// feature7 |= 0x00008000; + +// feature7 |= 0x00010000; +// feature7 |= 0x00020000; +// feature7 |= 0x00040000; +// feature7 |= 0x00080000; + +// feature7 |= 0x00100000; +// feature7 |= 0x00200000; +// feature7 |= 0x00400000; +// feature7 |= 0x00800000; + +// feature7 |= 0x01000000; +// feature7 |= 0x02000000; +// feature7 |= 0x04000000; +// feature7 |= 0x08000000; + +// feature7 |= 0x10000000; +// feature7 |= 0x20000000; +// feature7 |= 0x40000000; +// feature7 |= 0x80000000; + } /*********************************************************************************************/ - feature7 = 0x00000000; - -#if defined(USE_I2C) && defined(USE_EZOORP) - feature7 |= 0x00000001; // xsns_78_ezoorp.ino -#endif -#if defined(USE_I2C) && defined(USE_EZORTD) - feature7 |= 0x00000002; // xsns_78_ezortd.ino -#endif -#if defined(USE_I2C) && defined(USE_EZOHUM) - feature7 |= 0x00000004; // xsns_78_ezohum.ino -#endif -#if defined(USE_I2C) && defined(USE_EZOEC) - feature7 |= 0x00000008; // xsns_78_ezoec.ino -#endif -#if defined(USE_I2C) && defined(USE_EZOCO2) - feature7 |= 0x00000010; -#endif -// feature7 |= 0x00000020; -// feature7 |= 0x00000040; -// feature7 |= 0x00000080; - -// feature7 |= 0x00000100; -// feature7 |= 0x00000200; -// feature7 |= 0x00000400; -// feature7 |= 0x00000800; - -// feature7 |= 0x00001000; -// feature7 |= 0x00002000; -// feature7 |= 0x00004000; -// feature7 |= 0x00008000; - -// feature7 |= 0x00010000; -// feature7 |= 0x00020000; -// feature7 |= 0x00040000; -// feature7 |= 0x00080000; - -// feature7 |= 0x00100000; -// feature7 |= 0x00200000; -// feature7 |= 0x00400000; -// feature7 |= 0x00800000; - -// feature7 |= 0x01000000; -// feature7 |= 0x02000000; -// feature7 |= 0x04000000; -// feature7 |= 0x08000000; - -// feature7 |= 0x10000000; -// feature7 |= 0x20000000; -// feature7 |= 0x40000000; -// feature7 |= 0x80000000; - - -} // GetFeatures + ResponseAppend_P(PSTR(",\"" D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]"), + LANGUAGE_LCID, feature1, feature2, feature3, feature4, feature5, feature6, feature7); +} diff --git a/tasmota/support_flash_log.ino b/tasmota/support_flash_log.ino index 5055e5f21..a1bdd5012 100644 --- a/tasmota/support_flash_log.ino +++ b/tasmota/support_flash_log.ino @@ -397,7 +397,7 @@ void FLOG::stopRecording(void){ if(k%128 == 0){ // give control to the system every x iteration, TODO: This will fail, when record/entry-size is not 8 // DEBUG_SENSOR_LOG(PSTR("FLOG: now loop(), %u bytes left"), Flog->bytes_left); OsWatchLoop(); - delay(ssleep); + delay(TasmotaGlobal.sleep); } k+=size; if(bytes_left>7){ @@ -416,7 +416,7 @@ void FLOG::stopRecording(void){ _readSector(next_sector); bytes_left = sector.header.buf_pointer - sizeof(sector.header); OsWatchLoop(); - delay(ssleep); + delay(TasmotaGlobal.sleep); } running_download = false; // Callback 3: create a footer or simply finish the download with an empty payload diff --git a/tasmota/support_network.ino b/tasmota/support_network.ino index ed4df6705..c67ffa82d 100644 --- a/tasmota/support_network.ino +++ b/tasmota/support_network.ino @@ -27,16 +27,18 @@ struct { #ifdef USE_DISCOVERY void StartMdns(void) { +// static uint8_t mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START]; + if (Settings.flag3.mdns_enabled) { // SetOption55 - Control mDNS service if (!Mdns.begun) { -// if (mdns_delayed_start) { -// AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_ATTEMPTING_CONNECTION)); -// mdns_delayed_start--; -// } else { -// mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START]; - Mdns.begun = (uint8_t)MDNS.begin(my_hostname); +// if (mdns_delayed_start) { +// AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_ATTEMPTING_CONNECTION)); +// mdns_delayed_start--; +// } else { +// mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START]; + Mdns.begun = (uint8_t)MDNS.begin(TasmotaGlobal.hostname); AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS "%s"), (Mdns.begun) ? D_INITIALIZED : D_FAILED); -// } +// } } } } @@ -92,18 +94,18 @@ void MdnsUpdate(void) { char* NetworkHostname(void) { #ifdef ESP32 #ifdef USE_ETHERNET - if (!global_state.eth_down) { + if (!TasmotaGlobal.global_state.eth_down) { return EthernetHostname(); } #endif #endif - return my_hostname; + return TasmotaGlobal.hostname; } IPAddress NetworkAddress(void) { #ifdef ESP32 #ifdef USE_ETHERNET - if (!global_state.eth_down) { + if (!TasmotaGlobal.global_state.eth_down) { return EthernetLocalIP(); } #endif @@ -114,7 +116,7 @@ IPAddress NetworkAddress(void) { String NetworkMacAddress(void) { #ifdef ESP32 #ifdef USE_ETHERNET - if (!global_state.eth_down) { + if (!TasmotaGlobal.global_state.eth_down) { return EthernetMacAddress(); } #endif diff --git a/tasmota/support_rotary.ino b/tasmota/support_rotary.ino index e91fcdd4b..bb5520c15 100644 --- a/tasmota/support_rotary.ino +++ b/tasmota/support_rotary.ino @@ -81,7 +81,7 @@ bool RotaryButtonPressed(uint32_t button_index) { if (-1 == Encoder[index].pinb) { continue; } if (index != button_index) { continue; } - bool powered_on = (power); + bool powered_on = (TasmotaGlobal.power); #ifdef USE_LIGHT if (!Settings.flag4.rotary_uses_rules) { // SetOption98 - Use rules instead of light control powered_on = LightPower(); @@ -126,7 +126,7 @@ void RotaryInit(void) { Rotary.present = false; Rotary.model = 1; #ifdef ESP8266 - if (MI_DESK_LAMP == my_module_type) { + if (MI_DESK_LAMP == TasmotaGlobal.module_type) { Rotary.model = 0; } #endif // ESP8266 @@ -180,8 +180,8 @@ void RotaryHandler(void) { Encoder[index].position = rotary_offset; interrupts(); - if (Settings.save_data && (save_data_counter < 2)) { - save_data_counter = 3; // Postpone flash writes while rotary is turned + if (Settings.save_data && (TasmotaGlobal.save_data_counter < 2)) { + TasmotaGlobal.save_data_counter = 3; // Postpone flash writes while rotary is turned } bool button_pressed = (Button.hold_timer[index]); // Button is pressed: set color temperature @@ -202,7 +202,7 @@ void RotaryHandler(void) { } } else { // Dimmer RGBCW or RGB only if second rotary uint32_t dimmer_index = second_rotary ? 1 : 0; - if (!Settings.flag4.rotary_poweron_dimlow || power) { // SetOption113 - On rotary dial after power off set dimmer low + if (!Settings.flag4.rotary_poweron_dimlow || TasmotaGlobal.power) { // SetOption113 - On rotary dial after power off set dimmer low LightDimmerOffset(dimmer_index, rotary_position * rotary_dimmer_increment[Rotary.model]); } else { if (rotary_position > 0) { // Only power on if rotary increase diff --git a/tasmota/support_rtc.ino b/tasmota/support_rtc.ino index 25ad82435..cb6539aeb 100644 --- a/tasmota/support_rtc.ino +++ b/tasmota/support_rtc.ino @@ -225,7 +225,7 @@ uint32_t UpTime(void) if (Rtc.restart_time) { return Rtc.utc_time - Rtc.restart_time; } else { - return uptime; + return TasmotaGlobal.uptime; } } @@ -379,23 +379,23 @@ void RtcSecond(void) Rtc.millis = millis(); if (!Rtc.user_time_entry) { - if (!global_state.network_down) { - uint8_t uptime_minute = (uptime / 60) % 60; // 0 .. 59 + if (!TasmotaGlobal.global_state.network_down) { + uint8_t uptime_minute = (TasmotaGlobal.uptime / 60) % 60; // 0 .. 59 if ((Rtc.ntp_sync_minute > 59) && (uptime_minute > 2)) { Rtc.ntp_sync_minute = 1; // If sync prepare for a new cycle } - uint8_t offset = (uptime < 30) ? RtcTime.second : (((ESP_getChipId() & 0xF) * 3) + 3) ; // First try ASAP to sync. If fails try once every 60 seconds based on chip id + uint8_t offset = (TasmotaGlobal.uptime < 30) ? RtcTime.second : (((ESP_getChipId() & 0xF) * 3) + 3) ; // First try ASAP to sync. If fails try once every 60 seconds based on chip id if ( (((offset == RtcTime.second) && ( (RtcTime.year < 2016) || // Never synced (Rtc.ntp_sync_minute == uptime_minute))) || // Re-sync every hour - ntp_force_sync ) ) { // Forced sync + TasmotaGlobal.ntp_force_sync ) ) { // Forced sync Rtc.ntp_time = sntp_get_current_timestamp(); if (Rtc.ntp_time > START_VALID_TIME) { // Fix NTP bug in core 2.4.1/SDK 2.2.1 (returns Thu Jan 01 08:00:10 1970 after power on) - ntp_force_sync = false; + TasmotaGlobal.ntp_force_sync = false; Rtc.utc_time = Rtc.ntp_time; Rtc.last_sync = Rtc.ntp_time; Rtc.ntp_sync_minute = 60; // Sync so block further requests if (Rtc.restart_time == 0) { - Rtc.restart_time = Rtc.utc_time - uptime; // save first ntp time as restart time + Rtc.restart_time = Rtc.utc_time - TasmotaGlobal.uptime; // save first ntp time as restart time } BreakTime(Rtc.utc_time, tmpTime); RtcTime.year = tmpTime.year + 1970; @@ -407,9 +407,9 @@ void RtcSecond(void) 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 - rules_flag.time_init = 1; + TasmotaGlobal.rules_flag.time_init = 1; } else { - rules_flag.time_set = 1; + TasmotaGlobal.rules_flag.time_set = 1; } } else { Rtc.ntp_sync_minute++; // Try again in next minute @@ -476,7 +476,7 @@ void RtcSetTime(uint32_t epoch) { if (epoch < START_VALID_TIME) { // 2016-01-01 Rtc.user_time_entry = false; - ntp_force_sync = true; + TasmotaGlobal.ntp_force_sync = true; sntp_init(); } else { sntp_stop(); diff --git a/tasmota/support_static_buffer.ino b/tasmota/support_static_buffer.ino index 9f4a8456b..5fa0e603c 100644 --- a/tasmota/support_static_buffer.ino +++ b/tasmota/support_static_buffer.ino @@ -194,14 +194,10 @@ public: return 0; } - // if no NULL is found, returns length until the end of the buffer - inline size_t strlen(const size_t offset) const { - return strnlen((const char*) &_buf->buf[offset], len() - offset); - } - - size_t strlen_s(const size_t offset) const { - size_t slen = this->strlen(offset); - if (slen == len() - offset) { + size_t strlen(const size_t offset) const { + if (offset >= len()) { return 0; } + size_t slen = strnlen((const char*) &_buf->buf[offset], len() - offset); + if (slen == (len() - offset)) { return 0; // we didn't find a NULL char } else { return slen; diff --git a/tasmota/support_switch.ino b/tasmota/support_switch.ino index 91a2d59c6..b1822a1b0 100644 --- a/tasmota/support_switch.ino +++ b/tasmota/support_switch.ino @@ -40,7 +40,7 @@ const uint8_t AC_PERIOD = (20 + SWITCH_FAST_PROBE_INTERVAL - 1) / SWITCH_FAST_PR Ticker TickerSwitch; struct SWITCH { - unsigned long debounce = 0; // Switch debounce timer + uint32_t debounce = 0; // Switch debounce timer uint16_t no_pullup_mask = 0; // Switch pull-up bitmask flags uint8_t state[MAX_SWITCHES] = { 0 }; uint8_t last_state[MAX_SWITCHES]; // Last wall switch states @@ -88,7 +88,7 @@ bool SwitchState(uint32_t index) void SwitchProbe(void) { - if (uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit + if (TasmotaGlobal.uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit uint8_t state_filter; uint8_t debounce_flags = Settings.switch_debounce % 10; @@ -232,7 +232,7 @@ void SwitchInit(void) void SwitchHandler(uint8_t mode) { - if (uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit + if (TasmotaGlobal.uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit uint16_t loops_per_second = 1000 / Settings.switch_debounce; @@ -401,7 +401,7 @@ void SwitchHandler(uint8_t mode) } if (switchflag <= POWER_TOGGLE) { if (!SendKey(KEY_SWITCH, i +1, switchflag)) { // Execute command via MQTT - ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); // Execute command internally (if i < devices_present) + ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); // Execute command internally (if i < TasmotaGlobal.devices_present) } } } diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index b3aa012cf..14d68b57b 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -92,14 +92,14 @@ char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopi String fulltopic; snprintf_P(romram, sizeof(romram), subtopic); - if (fallback_topic_flag || (prefix > 3)) { + if (TasmotaGlobal.fallback_topic_flag || (prefix > 3)) { bool fallback = (prefix < 8); prefix &= 3; char stemp[11]; fulltopic = GetTextIndexed(stemp, sizeof(stemp), prefix, kPrefixes); fulltopic += F("/"); if (fallback) { - fulltopic += mqtt_client; + fulltopic += TasmotaGlobal.mqtt_client; fulltopic += F("_fb"); // cmnd/_fb } else { fulltopic += topic; // cmnd/ @@ -119,7 +119,7 @@ char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopi fulltopic.replace(FPSTR(MQTT_TOKEN_PREFIX), SettingsText(SET_MQTTPREFIX1 + prefix)); fulltopic.replace(FPSTR(MQTT_TOKEN_TOPIC), topic); - fulltopic.replace(F("%hostname%"), my_hostname); + fulltopic.replace(F("%hostname%"), TasmotaGlobal.hostname); String token_id = WiFi.macAddress(); token_id.replace(":", ""); fulltopic.replace(F("%id%"), token_id); @@ -157,37 +157,38 @@ char* GetStateText(uint32_t state) void SetLatchingRelay(power_t lpower, uint32_t state) { - // power xx00 - toggle REL1 (Off) and REL3 (Off) - device 1 Off, device 2 Off - // power xx01 - toggle REL2 (On) and REL3 (Off) - device 1 On, device 2 Off - // power xx10 - toggle REL1 (Off) and REL4 (On) - device 1 Off, device 2 On - // power xx11 - toggle REL2 (On) and REL4 (On) - device 1 On, device 2 On + // TasmotaGlobal.power xx00 - toggle REL1 (Off) and REL3 (Off) - device 1 Off, device 2 Off + // TasmotaGlobal.power xx01 - toggle REL2 (On) and REL3 (Off) - device 1 On, device 2 Off + // TasmotaGlobal.power xx10 - toggle REL1 (Off) and REL4 (On) - device 1 Off, device 2 On + // TasmotaGlobal.power xx11 - toggle REL2 (On) and REL4 (On) - device 1 On, device 2 On + static power_t latching_power = 0; // Power state at latching start - if (state && !latching_relay_pulse) { // Set latching relay to power if previous pulse has finished + if (state && !TasmotaGlobal.latching_relay_pulse) { // Set latching relay to power if previous pulse has finished latching_power = lpower; - latching_relay_pulse = 2; // max 200mS (initiated by stateloop()) + TasmotaGlobal.latching_relay_pulse = 2; // max 200mS (initiated by stateloop()) } - for (uint32_t i = 0; i < devices_present; i++) { + for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { uint32_t port = (i << 1) + ((latching_power >> i) &1); - DigitalWrite(GPIO_REL1, port, bitRead(rel_inverted, port) ? !state : state); + DigitalWrite(GPIO_REL1, port, bitRead(TasmotaGlobal.rel_inverted, port) ? !state : state); } } void SetDevicePower(power_t rpower, uint32_t source) { ShowSource(source); - last_source = source; + TasmotaGlobal.last_source = source; if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { // All on and stay on - power = (1 << devices_present) -1; - rpower = power; + TasmotaGlobal.power = (1 << TasmotaGlobal.devices_present) -1; + rpower = TasmotaGlobal.power; } if (Settings.flag.interlock) { // Allow only one or no relay set - CMND_INTERLOCK - Enable/disable interlock for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { power_t mask = 1; uint32_t count = 0; - for (uint32_t j = 0; j < devices_present; j++) { + for (uint32_t j = 0; j < TasmotaGlobal.devices_present; j++) { if ((Settings.interlock[i] & mask) && (rpower & mask)) { count++; } @@ -195,14 +196,14 @@ void SetDevicePower(power_t rpower, uint32_t source) } if (count > 1) { mask = ~Settings.interlock[i]; // Turn interlocked group off as there would be multiple relays on - power &= mask; + TasmotaGlobal.power &= mask; rpower &= mask; } } } if (rpower) { // Any power set - last_power = rpower; + TasmotaGlobal.last_power = rpower; } XdrvMailbox.index = rpower; @@ -215,7 +216,7 @@ void SetDevicePower(power_t rpower, uint32_t source) // Serviced } #ifdef ESP8266 - else if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { + else if ((SONOFF_DUAL == TasmotaGlobal.module_type) || (CH4 == TasmotaGlobal.module_type)) { Serial.write(0xA0); Serial.write(0x04); Serial.write(rpower &0xFF); @@ -223,16 +224,16 @@ void SetDevicePower(power_t rpower, uint32_t source) Serial.write('\n'); Serial.flush(); } - else if (EXS_RELAY == my_module_type) { + else if (EXS_RELAY == TasmotaGlobal.module_type) { SetLatchingRelay(rpower, 1); } #endif // ESP8266 else { - for (uint32_t i = 0; i < devices_present; i++) { + for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { power_t state = rpower &1; if (i < MAX_RELAYS) { - DigitalWrite(GPIO_REL1, i, bitRead(rel_inverted, i) ? !state : state); + DigitalWrite(GPIO_REL1, i, bitRead(TasmotaGlobal.rel_inverted, i) ? !state : state); } rpower >>= 1; } @@ -241,9 +242,9 @@ void SetDevicePower(power_t rpower, uint32_t source) void RestorePower(bool publish_power, uint32_t source) { - if (power != last_power) { - power = last_power; - SetDevicePower(power, source); + if (TasmotaGlobal.power != TasmotaGlobal.last_power) { + TasmotaGlobal.power = TasmotaGlobal.last_power; + SetDevicePower(TasmotaGlobal.power, source); if (publish_power) { MqttPublishAllPowerState(); } @@ -266,18 +267,18 @@ void SetAllPower(uint32_t state, uint32_t source) publish_power = false; } if ((state >= POWER_OFF) && (state <= POWER_TOGGLE)) { - power_t all_on = (1 << devices_present) -1; + power_t all_on = (1 << TasmotaGlobal.devices_present) -1; switch (state) { case POWER_OFF: - power = 0; + TasmotaGlobal.power = 0; break; case POWER_ON: - power = all_on; + TasmotaGlobal.power = all_on; break; case POWER_TOGGLE: - power ^= all_on; // Complement current state + TasmotaGlobal.power ^= all_on; // Complement current state } - SetDevicePower(power, source); + SetDevicePower(TasmotaGlobal.power, source); } if (publish_power) { MqttPublishAllPowerState(); @@ -287,7 +288,7 @@ void SetAllPower(uint32_t state, uint32_t source) void SetPowerOnState(void) { #ifdef ESP8266 - if (MOTOR == my_module_type) { + if (MOTOR == TasmotaGlobal.module_type) { Settings.poweronstate = POWER_ALL_ON; // Needs always on else in limbo! } #endif // ESP8266 @@ -298,52 +299,52 @@ void SetPowerOnState(void) switch (Settings.poweronstate) { case POWER_ALL_OFF: case POWER_ALL_OFF_PULSETIME_ON: - power = 0; - SetDevicePower(power, SRC_RESTART); + TasmotaGlobal.power = 0; + SetDevicePower(TasmotaGlobal.power, SRC_RESTART); break; case POWER_ALL_ON: // All on - power = (1 << devices_present) -1; - SetDevicePower(power, SRC_RESTART); + TasmotaGlobal.power = (1 << TasmotaGlobal.devices_present) -1; + SetDevicePower(TasmotaGlobal.power, SRC_RESTART); break; case POWER_ALL_SAVED_TOGGLE: - power = (Settings.power & ((1 << devices_present) -1)) ^ POWER_MASK; + TasmotaGlobal.power = (Settings.power & ((1 << TasmotaGlobal.devices_present) -1)) ^ POWER_MASK; if (Settings.flag.save_state) { // SetOption0 - Save power state and use after restart - SetDevicePower(power, SRC_RESTART); + SetDevicePower(TasmotaGlobal.power, SRC_RESTART); } break; case POWER_ALL_SAVED: - power = Settings.power & ((1 << devices_present) -1); + TasmotaGlobal.power = Settings.power & ((1 << TasmotaGlobal.devices_present) -1); if (Settings.flag.save_state) { // SetOption0 - Save power state and use after restart - SetDevicePower(power, SRC_RESTART); + SetDevicePower(TasmotaGlobal.power, SRC_RESTART); } break; } } else { - power = Settings.power & ((1 << devices_present) -1); + TasmotaGlobal.power = Settings.power & ((1 << TasmotaGlobal.devices_present) -1); if (Settings.flag.save_state) { // SetOption0 - Save power state and use after restart - SetDevicePower(power, SRC_RESTART); + SetDevicePower(TasmotaGlobal.power, SRC_RESTART); } } } // Issue #526 and #909 - for (uint32_t i = 0; i < devices_present; i++) { + for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { if (!Settings.flag3.no_power_feedback) { // SetOption63 - Don't scan relay power state at restart - #5594 and #5663 if ((i < MAX_RELAYS) && PinUsed(GPIO_REL1, i)) { - bitWrite(power, i, digitalRead(Pin(GPIO_REL1, i)) ^ bitRead(rel_inverted, i)); + bitWrite(TasmotaGlobal.power, i, digitalRead(Pin(GPIO_REL1, i)) ^ bitRead(TasmotaGlobal.rel_inverted, i)); } } - if (bitRead(power, i) || (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate)) { + if (bitRead(TasmotaGlobal.power, i) || (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate)) { SetPulseTimer(i % MAX_PULSETIMERS, Settings.pulse_timer[i % MAX_PULSETIMERS]); } } - blink_powersave = power; + TasmotaGlobal.blink_powersave = TasmotaGlobal.power; } void UpdateLedPowerAll() { - for (uint32_t i = 0; i < leds_present; i++) { - SetLedPowerIdx(i, bitRead(led_power, i)); + for (uint32_t i = 0; i < TasmotaGlobal.leds_present; i++) { + SetLedPowerIdx(i, bitRead(TasmotaGlobal.led_power, i)); } } @@ -358,9 +359,9 @@ void SetLedPowerIdx(uint32_t led, uint32_t state) uint32_t mask = 1 << led; if (state) { state = 1; - led_power |= mask; + TasmotaGlobal.led_power |= mask; } else { - led_power &= (0xFF ^ mask); + TasmotaGlobal.led_power &= (0xFF ^ mask); } uint16_t pwm = 0; if (bitRead(Settings.ledpwm_mask, led)) { @@ -369,9 +370,9 @@ void SetLedPowerIdx(uint32_t led, uint32_t state) #else //USE_LIGHT pwm = changeUIntScale((uint16_t)(state ? Settings.ledpwm_on : Settings.ledpwm_off), 0, 255, 0, Settings.pwm_range); // linear #endif //USE_LIGHT - analogWrite(Pin(GPIO_LED1, led), bitRead(led_inverted, led) ? Settings.pwm_range - pwm : pwm); + analogWrite(Pin(GPIO_LED1, led), bitRead(TasmotaGlobal.led_inverted, led) ? Settings.pwm_range - pwm : pwm); } else { - DigitalWrite(GPIO_LED1, led, bitRead(led_inverted, led) ? !state : state); + DigitalWrite(GPIO_LED1, led, bitRead(TasmotaGlobal.led_inverted, led) ? !state : state); } } #ifdef USE_BUZZER @@ -387,8 +388,8 @@ void SetLedPower(uint32_t state) SetLedPowerIdx(0, state); } else { power_t mask = 1; - for (uint32_t i = 0; i < leds_present; i++) { // Map leds to power - bool tstate = (power & mask); + for (uint32_t i = 0; i < TasmotaGlobal.leds_present; i++) { // Map leds to power + bool tstate = (TasmotaGlobal.power & mask); SetLedPowerIdx(i, tstate); mask <<= 1; } @@ -397,7 +398,7 @@ void SetLedPower(uint32_t state) void SetLedPowerAll(uint32_t state) { - for (uint32_t i = 0; i < leds_present; i++) { + for (uint32_t i = 0; i < TasmotaGlobal.leds_present; i++) { SetLedPowerIdx(i, state); } } @@ -405,7 +406,7 @@ void SetLedPowerAll(uint32_t state) void SetLedLink(uint32_t state) { uint32_t led_pin = Pin(GPIO_LEDLNK); - uint32_t led_inv = ledlnk_inverted; + uint32_t led_inv = TasmotaGlobal.ledlnk_inverted; if (99 == led_pin) { // Legacy - LED1 is status SetLedPowerIdx(0, state); } @@ -420,12 +421,12 @@ void SetLedLink(uint32_t state) void SetPulseTimer(uint32_t index, uint32_t time) { - pulse_timer[index] = (time > 111) ? millis() + (1000 * (time - 100)) : (time > 0) ? millis() + (100 * time) : 0L; + TasmotaGlobal.pulse_timer[index] = (time > 111) ? millis() + (1000 * (time - 100)) : (time > 0) ? millis() + (100 * time) : 0L; } uint32_t GetPulseTimer(uint32_t index) { - long time = TimePassedSince(pulse_timer[index]); + long time = TimePassedSince(TasmotaGlobal.pulse_timer[index]); if (time < 0) { time *= -1; return (time > 11100) ? (time / 1000) + 100 : (time > 0) ? time / 100 : 0; @@ -458,24 +459,24 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state) char *tmp = (key) ? SettingsText(SET_MQTT_SWITCH_TOPIC) : SettingsText(SET_MQTT_BUTTON_TOPIC); Format(key_topic, tmp, sizeof(key_topic)); if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) { // SetOption3 - Enable MQTT - if (!key && (device > devices_present)) { + if (!key && (device > TasmotaGlobal.devices_present)) { device = 1; // Only allow number of buttons up to number of devices } GetTopic_P(stopic, CMND, key_topic, GetPowerDevice(scommand, device, sizeof(scommand), (key + Settings.flag.device_index_enable))); // cmnd/switchtopic/POWERx - SetOption26 - Switch between POWER or POWER1 if (CLEAR_RETAIN == state) { - mqtt_data[0] = '\0'; + ResponseClear(); } else { if ((Settings.flag3.button_switch_force_local || // SetOption61 - Force local operation when button/switch topic is set - !strcmp(mqtt_topic, key_topic) || + !strcmp(TasmotaGlobal.mqtt_topic, key_topic) || !strcmp(SettingsText(SET_MQTT_GRP_TOPIC), key_topic)) && (POWER_TOGGLE == state)) { - state = ~(power >> (device -1)) &1; // POWER_OFF or POWER_ON + state = ~(TasmotaGlobal.power >> (device -1)) &1; // POWER_OFF or POWER_ON } - snprintf_P(mqtt_data, sizeof(mqtt_data), GetStateText(state)); + snprintf_P(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), GetStateText(state)); } #ifdef USE_DOMOTICZ - if (!(DomoticzSendKey(key, device, state, strlen(mqtt_data)))) { + if (!(DomoticzSendKey(key, device, state, strlen(TasmotaGlobal.mqtt_data)))) { #endif // USE_DOMOTICZ MqttPublish(stopic, ((key) ? Settings.flag.mqtt_switch_retain // CMND_SWITCHRETAIN : Settings.flag.mqtt_button_retain) && // CMND_BUTTONRETAIN @@ -489,7 +490,7 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state) result = XdrvRulesProcess(); } #ifdef USE_PWM_DIMMER - if (PWM_DIMMER == my_module_type && !result) { + if (PWM_DIMMER == TasmotaGlobal.module_type && !result) { #endif // USE_PWM_DIMMER int32_t payload_save = XdrvMailbox.payload; XdrvMailbox.payload = device_save << 24 | key << 16 | state << 8 | device; @@ -519,7 +520,7 @@ void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source) #ifdef USE_SONOFF_IFAN if (IsModuleIfan()) { - blink_mask &= 1; // No blinking on the fan relays + TasmotaGlobal.blink_mask &= 1; // No blinking on the fan relays Settings.flag.interlock = 0; // No interlock mode as it is already done by the microcontroller - CMND_INTERLOCK - Enable/disable interlock Settings.pulse_timer[1] = 0; // No pulsetimers on the fan relays Settings.pulse_timer[2] = 0; @@ -533,30 +534,31 @@ void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source) publish_power = false; } - if ((device < 1) || (device > devices_present)) { + if ((device < 1) || (device > TasmotaGlobal.devices_present)) { device = 1; } - active_device = device; + TasmotaGlobal.active_device = device; SetPulseTimer((device -1) % MAX_PULSETIMERS, 0); + static bool interlock_mutex = false; // Interlock power command pending power_t mask = 1 << (device -1); // Device to control if (state <= POWER_TOGGLE) { - if ((blink_mask & mask)) { - blink_mask &= (POWER_MASK ^ mask); // Clear device mask + if ((TasmotaGlobal.blink_mask & mask)) { + TasmotaGlobal.blink_mask &= (POWER_MASK ^ mask); // Clear device mask MqttPublishPowerBlinkState(device); } if (Settings.flag.interlock && // CMND_INTERLOCK - Enable/disable interlock !interlock_mutex && - ((POWER_ON == state) || ((POWER_TOGGLE == state) && !(power & mask))) + ((POWER_ON == state) || ((POWER_TOGGLE == state) && !(TasmotaGlobal.power & mask))) ) { interlock_mutex = true; // Clear all but masked relay in interlock group if new set requested for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { if (Settings.interlock[i] & mask) { // Find interlock group - for (uint32_t j = 0; j < devices_present; j++) { + for (uint32_t j = 0; j < TasmotaGlobal.devices_present; j++) { power_t imask = 1 << j; - if ((Settings.interlock[i] & imask) && (power & imask) && (mask != imask)) { + if ((Settings.interlock[i] & imask) && (TasmotaGlobal.power & imask) && (mask != imask)) { ExecuteCommandPower(j +1, POWER_OFF, SRC_IGNORE); delay(50); // Add some delay to make sure never have more than one relay on } @@ -569,53 +571,53 @@ void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source) switch (state) { case POWER_OFF: { - power &= (POWER_MASK ^ mask); + TasmotaGlobal.power &= (POWER_MASK ^ mask); break; } case POWER_ON: - power |= mask; + TasmotaGlobal.power |= mask; break; case POWER_TOGGLE: - power ^= mask; + TasmotaGlobal.power ^= mask; } #ifdef USE_DEVICE_GROUPS if (SRC_REMOTE != source && SRC_RETRY != source) { if (Settings.flag4.multiple_device_groups) // SetOption88 - Enable relays in separate device groups - SendDeviceGroupMessage(device - 1, DGR_MSGTYP_UPDATE, DGR_ITEM_POWER, (power >> (device - 1)) & 1 | 0x01000000); // Explicitly set number of relays to one + SendDeviceGroupMessage(device - 1, DGR_MSGTYP_UPDATE, DGR_ITEM_POWER, (TasmotaGlobal.power >> (device - 1)) & 1 | 0x01000000); // Explicitly set number of relays to one else - SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_POWER, power); + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_POWER, TasmotaGlobal.power); } #endif // USE_DEVICE_GROUPS - SetDevicePower(power, source); + SetDevicePower(TasmotaGlobal.power, source); #ifdef USE_DOMOTICZ DomoticzUpdatePowerState(device); #endif // USE_DOMOTICZ #ifdef USE_KNX - KnxUpdatePowerState(device, power); + KnxUpdatePowerState(device, TasmotaGlobal.power); #endif // USE_KNX if (publish_power && Settings.flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT MqttPublishTeleState(); } // Restart PulseTime if powered On - SetPulseTimer((device -1) % MAX_PULSETIMERS, (((POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? ~power : power) & mask) ? Settings.pulse_timer[(device -1) % MAX_PULSETIMERS] : 0); + SetPulseTimer((device -1) % MAX_PULSETIMERS, (((POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? ~TasmotaGlobal.power : TasmotaGlobal.power) & mask) ? Settings.pulse_timer[(device -1) % MAX_PULSETIMERS] : 0); } else if (POWER_BLINK == state) { - if (!(blink_mask & mask)) { - blink_powersave = (blink_powersave & (POWER_MASK ^ mask)) | (power & mask); // Save state - blink_power = (power >> (device -1))&1; // Prep to Toggle + if (!(TasmotaGlobal.blink_mask & mask)) { + TasmotaGlobal.blink_powersave = (TasmotaGlobal.blink_powersave & (POWER_MASK ^ mask)) | (TasmotaGlobal.power & mask); // Save state + TasmotaGlobal.blink_power = (TasmotaGlobal.power >> (device -1))&1; // Prep to Toggle } - blink_timer = millis() + 100; - blink_counter = ((!Settings.blinkcount) ? 64000 : (Settings.blinkcount *2)) +1; - blink_mask |= mask; // Set device mask + TasmotaGlobal.blink_timer = millis() + 100; + TasmotaGlobal.blink_counter = ((!Settings.blinkcount) ? 64000 : (Settings.blinkcount *2)) +1; + TasmotaGlobal.blink_mask |= mask; // Set device mask MqttPublishPowerBlinkState(device); return; } else if (POWER_BLINK_STOP == state) { - bool flag = (blink_mask & mask); - blink_mask &= (POWER_MASK ^ mask); // Clear device mask + bool flag = (TasmotaGlobal.blink_mask & mask); + TasmotaGlobal.blink_mask &= (POWER_MASK ^ mask); // Clear device mask MqttPublishPowerBlinkState(device); if (flag) { - ExecuteCommandPower(device, (blink_powersave >> (device -1))&1, SRC_IGNORE); // Restore state + ExecuteCommandPower(device, (TasmotaGlobal.blink_powersave >> (device -1))&1, SRC_IGNORE); // Restore state } return; } @@ -628,12 +630,12 @@ void StopAllPowerBlink(void) { power_t mask; - for (uint32_t i = 1; i <= devices_present; i++) { + for (uint32_t i = 1; i <= TasmotaGlobal.devices_present; i++) { mask = 1 << (i -1); - if (blink_mask & mask) { - blink_mask &= (POWER_MASK ^ mask); // Clear device mask + if (TasmotaGlobal.blink_mask & mask) { + TasmotaGlobal.blink_mask &= (POWER_MASK ^ mask); // Clear device mask MqttPublishPowerBlinkState(i); - ExecuteCommandPower(i, (blink_powersave >> (i -1))&1, SRC_IGNORE); // Restore state + ExecuteCommandPower(i, (TasmotaGlobal.blink_powersave >> (i -1))&1, SRC_IGNORE); // Restore state } } } @@ -667,16 +669,16 @@ void MqttShowState(void) ResponseAppend_P(PSTR(",\"" D_JSON_HEAPSIZE "\":%d,\"SleepMode\":\"%s\",\"Sleep\":%u,\"LoadAvg\":%u,\"MqttCount\":%u"), ESP_getFreeHeap()/1024, GetTextIndexed(stemp1, sizeof(stemp1), Settings.flag3.sleep_normal, kSleepMode), // SetOption60 - Enable normal sleep instead of dynamic sleep - ssleep, loop_load_avg, MqttConnectCount()); + TasmotaGlobal.sleep, TasmotaGlobal.loop_load_avg, MqttConnectCount()); - for (uint32_t i = 1; i <= devices_present; i++) { + for (uint32_t i = 1; i <= TasmotaGlobal.devices_present; i++) { #ifdef USE_LIGHT if ((LightDevice()) && (i >= LightDevice())) { if (i == LightDevice()) { ResponseLightState(1); } // call it only once } else { #endif ResponseAppend_P(PSTR(",\"%s\":\"%s\""), GetPowerDevice(stemp1, i, sizeof(stemp1), Settings.flag.device_index_enable), // SetOption26 - Switch between POWER or POWER1 - GetStateText(bitRead(power, i-1))); + GetStateText(bitRead(TasmotaGlobal.power, i-1))); #ifdef USE_SONOFF_IFAN if (IsModuleIfan()) { ResponseAppend_P(PSTR(",\"" D_CMND_FANSPEED "\":%d"), GetFanspeed()); @@ -688,12 +690,12 @@ void MqttShowState(void) #endif } - if (pwm_present) { + if (TasmotaGlobal.pwm_present) { ResponseAppend_P(PSTR(",")); MqttShowPWMState(); } - if (!global_state.wifi_down) { + if (!TasmotaGlobal.global_state.wifi_down) { int32_t rssi = WiFi.RSSI(); ResponseAppend_P(PSTR(",\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_SIGNAL "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}"), Settings.sta_active +1, EscapeJSONString(SettingsText(SET_STASSID1 + Settings.sta_active)).c_str(), WiFi.BSSIDstr().c_str(), WiFi.channel(), @@ -705,7 +707,7 @@ void MqttShowState(void) void MqttPublishTeleState(void) { - mqtt_data[0] = '\0'; + ResponseClear(); MqttShowState(); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); #if defined(USE_RULES) || defined(USE_SCRIPT) @@ -737,31 +739,39 @@ void TempHumDewShow(bool json, bool pass_on, const char *types, float f_temperat } } +String GetSwitchText(uint32_t i) { + String switch_text = SettingsText(SET_SWITCH_TXT1 + i); + if ('\0' == switch_text[0]) { + switch_text = D_JSON_SWITCH + String(i +1); + } + return switch_text; +} + bool MqttShowSensor(void) { ResponseAppendTime(); - int json_data_start = strlen(mqtt_data); + int json_data_start = strlen(TasmotaGlobal.mqtt_data); for (uint32_t i = 0; i < MAX_SWITCHES; i++) { #ifdef USE_TM1638 if (PinUsed(GPIO_SWT1, i) || (PinUsed(GPIO_TM16CLK) && PinUsed(GPIO_TM16DIO) && PinUsed(GPIO_TM16STB))) { #else if (PinUsed(GPIO_SWT1, i)) { #endif // USE_TM1638 - ResponseAppend_P(PSTR(",\"" D_JSON_SWITCH "%d\":\"%s\""), i +1, GetStateText(SwitchState(i))); + ResponseAppend_P(PSTR(",\"%s\":\"%s\""), GetSwitchText(i).c_str(), GetStateText(SwitchState(i))); } } XsnsCall(FUNC_JSON_APPEND); XdrvCall(FUNC_JSON_APPEND); - bool json_data_available = (strlen(mqtt_data) - json_data_start); - if (strstr_P(mqtt_data, PSTR(D_JSON_PRESSURE)) != nullptr) { + bool json_data_available = (strlen(TasmotaGlobal.mqtt_data) - json_data_start); + if (strstr_P(TasmotaGlobal.mqtt_data, PSTR(D_JSON_PRESSURE)) != nullptr) { ResponseAppend_P(PSTR(",\"" D_JSON_PRESSURE_UNIT "\":\"%s\""), PressureUnit().c_str()); } - if (strstr_P(mqtt_data, PSTR(D_JSON_TEMPERATURE)) != nullptr) { + if (strstr_P(TasmotaGlobal.mqtt_data, PSTR(D_JSON_TEMPERATURE)) != nullptr) { ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE_UNIT "\":\"%c\""), TempUnit()); } - if ((strstr_P(mqtt_data, PSTR(D_JSON_SPEED)) != nullptr) && Settings.flag2.speed_conversion) { + if ((strstr_P(TasmotaGlobal.mqtt_data, PSTR(D_JSON_SPEED)) != nullptr) && Settings.flag2.speed_conversion) { ResponseAppend_P(PSTR(",\"" D_JSON_SPEED_UNIT "\":\"%s\""), SpeedUnit().c_str()); } ResponseJsonEnd(); @@ -772,7 +782,7 @@ bool MqttShowSensor(void) void MqttPublishSensor(void) { - mqtt_data[0] = '\0'; + ResponseClear(); if (MqttShowSensor()) { MqttPublishTeleSensor(); } @@ -787,15 +797,17 @@ void MqttPublishSensor(void) void PerformEverySecond(void) { - uptime++; + TasmotaGlobal.uptime++; - if (POWER_CYCLE_TIME == uptime) { + if (POWER_CYCLE_TIME == TasmotaGlobal.uptime) { UpdateQuickPowerCycle(false); } - if (BOOT_LOOP_TIME == uptime) { + if (BOOT_LOOP_TIME == TasmotaGlobal.uptime) { RtcRebootReset(); + Settings.last_module = Settings.module; + #ifdef USE_DEEPSLEEP if (!(DeepSleepEnabled() && !Settings.flag3.bootcount_update)) { #endif @@ -806,27 +818,27 @@ void PerformEverySecond(void) #endif } - if (mqtt_cmnd_blocked_reset) { - mqtt_cmnd_blocked_reset--; - if (!mqtt_cmnd_blocked_reset) { - mqtt_cmnd_blocked = 0; // Clean up MQTT cmnd loop block + if (TasmotaGlobal.mqtt_cmnd_blocked_reset) { + TasmotaGlobal.mqtt_cmnd_blocked_reset--; + if (!TasmotaGlobal.mqtt_cmnd_blocked_reset) { + TasmotaGlobal.mqtt_cmnd_blocked = 0; // Clean up MQTT cmnd loop block } } - if (seriallog_timer) { - seriallog_timer--; - if (!seriallog_timer) { - if (seriallog_level) { + if (TasmotaGlobal.seriallog_timer) { + TasmotaGlobal.seriallog_timer--; + if (!TasmotaGlobal.seriallog_timer) { + if (TasmotaGlobal.seriallog_level) { AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SERIAL_LOGGING_DISABLED)); } - seriallog_level = 0; + TasmotaGlobal.seriallog_level = 0; } } - if (syslog_timer) { // Restore syslog level - syslog_timer--; - if (!syslog_timer) { - syslog_level = Settings.syslog_level; + if (TasmotaGlobal.syslog_timer) { // Restore syslog level + TasmotaGlobal.syslog_timer--; + if (!TasmotaGlobal.syslog_timer) { + TasmotaGlobal.syslog_level = Settings.syslog_level; if (Settings.syslog_level) { AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SYSLOG_LOGGING_REENABLED)); // Might trigger disable again (on purpose) } @@ -836,18 +848,18 @@ void PerformEverySecond(void) ResetGlobalValues(); if (Settings.tele_period) { - if (tele_period >= 9999) { - if (!global_state.network_down) { - tele_period = 0; // Allow teleperiod once wifi is connected + if (TasmotaGlobal.tele_period >= 9999) { + if (!TasmotaGlobal.global_state.network_down) { + TasmotaGlobal.tele_period = 0; // Allow teleperiod once wifi is connected } } else { - tele_period++; - if (tele_period >= Settings.tele_period) { - tele_period = 0; + TasmotaGlobal.tele_period++; + if (TasmotaGlobal.tele_period >= Settings.tele_period) { + TasmotaGlobal.tele_period = 0; MqttPublishTeleState(); - mqtt_data[0] = '\0'; + ResponseClear(); if (MqttShowSensor()) { MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); // CMND_SENSORRETAIN #if defined(USE_RULES) || defined(USE_SCRIPT) @@ -865,8 +877,8 @@ void PerformEverySecond(void) wifiKeepAlive(); #ifdef ESP32 - if (11 == uptime) { // Perform one-time ESP32 houskeeping - ESP_getSketchSize(); // Init sketchsize as it can take up to 2 seconds + if (11 == TasmotaGlobal.uptime) { // Perform one-time ESP32 houskeeping + ESP_getSketchSize(); // Init sketchsize as it can take up to 2 seconds } #endif } @@ -880,35 +892,35 @@ void Every100mSeconds(void) // As the max amount of sleep = 250 mSec this loop will shift in time... power_t power_now; - if (prepped_loglevel) { - AddLog(prepped_loglevel); + if (TasmotaGlobal.prepped_loglevel) { + AddLog(TasmotaGlobal.prepped_loglevel); } - if (latching_relay_pulse) { - latching_relay_pulse--; - if (!latching_relay_pulse) SetLatchingRelay(0, 0); + if (TasmotaGlobal.latching_relay_pulse) { + TasmotaGlobal.latching_relay_pulse--; + if (!TasmotaGlobal.latching_relay_pulse) SetLatchingRelay(0, 0); } for (uint32_t i = 0; i < MAX_PULSETIMERS; i++) { - if (pulse_timer[i] != 0L) { // Timer active? - if (TimeReached(pulse_timer[i])) { // Timer finished? - pulse_timer[i] = 0L; // Turn off this timer - for (uint32_t j = 0; j < devices_present; j = j +MAX_PULSETIMERS) { + if (TasmotaGlobal.pulse_timer[i] != 0L) { // Timer active? + if (TimeReached(TasmotaGlobal.pulse_timer[i])) { // Timer finished? + TasmotaGlobal.pulse_timer[i] = 0L; // Turn off this timer + for (uint32_t j = 0; j < TasmotaGlobal.devices_present; j = j +MAX_PULSETIMERS) { ExecuteCommandPower(i + j +1, (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? POWER_ON : POWER_OFF, SRC_PULSETIMER); } } } } - if (blink_mask) { - if (TimeReached(blink_timer)) { - SetNextTimeInterval(blink_timer, 100 * Settings.blinktime); - blink_counter--; - if (!blink_counter) { + if (TasmotaGlobal.blink_mask) { + if (TimeReached(TasmotaGlobal.blink_timer)) { + SetNextTimeInterval(TasmotaGlobal.blink_timer, 100 * Settings.blinktime); + TasmotaGlobal.blink_counter--; + if (!TasmotaGlobal.blink_counter) { StopAllPowerBlink(); } else { - blink_power ^= 1; - power_now = (power & (POWER_MASK ^ blink_mask)) | ((blink_power) ? blink_mask : 0); + TasmotaGlobal.blink_power ^= 1; + power_now = (TasmotaGlobal.power & (POWER_MASK ^ TasmotaGlobal.blink_mask)) | ((TasmotaGlobal.blink_power) ? TasmotaGlobal.blink_mask : 0); SetDevicePower(power_now, SRC_IGNORE); } } @@ -923,43 +935,44 @@ void Every250mSeconds(void) { // As the max amount of sleep = 250 mSec this loop should always be taken... + static uint8_t blinkspeed = 1; // LED blink rate uint32_t blinkinterval = 1; - state_250mS++; - state_250mS &= 0x3; + TasmotaGlobal.state_250mS++; + TasmotaGlobal.state_250mS &= 0x3; - global_state.network_down = (global_state.wifi_down && global_state.eth_down) ? 1 : 0; + TasmotaGlobal.global_state.network_down = (TasmotaGlobal.global_state.wifi_down && TasmotaGlobal.global_state.eth_down) ? 1 : 0; if (!Settings.flag.global_state) { // SetOption31 - Control link led blinking - if (global_state.data &0x03) { // Network or MQTT problem - if (global_state.mqtt_down) { blinkinterval = 7; } // MQTT problem so blink every 2 seconds (slowest) - if (global_state.network_down) { blinkinterval = 3; } // Network problem so blink every second (slow) - blinks = 201; // Allow only a single blink in case the problem is solved + if (TasmotaGlobal.global_state.data &0x03) { // Network or MQTT problem + if (TasmotaGlobal.global_state.mqtt_down) { blinkinterval = 7; } // MQTT problem so blink every 2 seconds (slowest) + if (TasmotaGlobal.global_state.network_down) { blinkinterval = 3; } // Network problem so blink every second (slow) + TasmotaGlobal.blinks = 201; // Allow only a single blink in case the problem is solved } } - if (blinks || restart_flag || ota_state_flag) { - if (restart_flag || ota_state_flag) { // Overrule blinks and keep led lit - blinkstate = true; // Stay lit + if (TasmotaGlobal.blinks || TasmotaGlobal.restart_flag || TasmotaGlobal.ota_state_flag) { + if (TasmotaGlobal.restart_flag || TasmotaGlobal.ota_state_flag) { // Overrule blinks and keep led lit + TasmotaGlobal.blinkstate = true; // Stay lit } else { blinkspeed--; if (!blinkspeed) { blinkspeed = blinkinterval; // Set interval to 0.2 (default), 1 or 2 seconds - blinkstate ^= 1; // Blink + TasmotaGlobal.blinkstate ^= 1; // Blink } } - if ((!(Settings.ledstate &0x08)) && ((Settings.ledstate &0x06) || (blinks > 200) || (blinkstate))) { - SetLedLink(blinkstate); // Set led on or off + if ((!(Settings.ledstate &0x08)) && ((Settings.ledstate &0x06) || (TasmotaGlobal.blinks > 200) || (TasmotaGlobal.blinkstate))) { + SetLedLink(TasmotaGlobal.blinkstate); // Set led on or off } - if (!blinkstate) { - blinks--; - if (200 == blinks) blinks = 0; // Disable blink + if (!TasmotaGlobal.blinkstate) { + TasmotaGlobal.blinks--; + if (200 == TasmotaGlobal.blinks) { TasmotaGlobal.blinks = 0; } // Disable blink } } - if (Settings.ledstate &1 && (PinUsed(GPIO_LEDLNK) || !(blinks || restart_flag || ota_state_flag)) ) { - bool tstate = power & Settings.ledmask; + if (Settings.ledstate &1 && (PinUsed(GPIO_LEDLNK) || !(TasmotaGlobal.blinks || TasmotaGlobal.restart_flag || TasmotaGlobal.ota_state_flag)) ) { + bool tstate = TasmotaGlobal.power & Settings.ledmask; #ifdef ESP8266 - if ((SONOFF_TOUCH == my_module_type) || (SONOFF_T11 == my_module_type) || (SONOFF_T12 == my_module_type) || (SONOFF_T13 == my_module_type)) { - tstate = (!power) ? 1 : 0; // As requested invert signal for Touch devices to find them in the dark + if ((SONOFF_TOUCH == TasmotaGlobal.module_type) || (SONOFF_T11 == TasmotaGlobal.module_type) || (SONOFF_T12 == TasmotaGlobal.module_type) || (SONOFF_T13 == TasmotaGlobal.module_type)) { + tstate = (!TasmotaGlobal.power) ? 1 : 0; // As requested invert signal for Touch devices to find them in the dark } #endif // ESP8266 SetLedPower(tstate); @@ -969,17 +982,20 @@ void Every250mSeconds(void) * Every second at 0.25 second interval \*-------------------------------------------------------------------------------------------*/ - switch (state_250mS) { + static int ota_result = 0; + static uint8_t ota_retry_counter = OTA_ATTEMPTS; + + switch (TasmotaGlobal.state_250mS) { case 0: // Every x.0 second - if (ota_state_flag && BACKLOG_EMPTY) { - ota_state_flag--; - if (2 == ota_state_flag) { + if (TasmotaGlobal.ota_state_flag && BACKLOG_EMPTY) { + TasmotaGlobal.ota_state_flag--; + if (2 == TasmotaGlobal.ota_state_flag) { RtcSettings.ota_loader = 0; // Try requested image first ota_retry_counter = OTA_ATTEMPTS; ESPhttpUpdate.rebootOnUpdate(false); SettingsSave(1); // Free flash for OTA update } - if (ota_state_flag <= 0) { + if (TasmotaGlobal.ota_state_flag <= 0) { #ifdef USE_COUNTER CounterInterruptDisable(true); // Prevent OTA failures on 100Hz counter interrupts #endif // USE_COUNTER @@ -989,11 +1005,11 @@ void Every250mSeconds(void) #ifdef USE_ARILUX_RF AriluxRfDisable(); // Prevent restart exception on Arilux Interrupt routine #endif // USE_ARILUX_RF - ota_state_flag = 92; + TasmotaGlobal.ota_state_flag = 92; ota_result = 0; ota_retry_counter--; if (ota_retry_counter) { - strlcpy(mqtt_data, GetOtaUrl(log_data, sizeof(log_data)), sizeof(mqtt_data)); + strlcpy(TasmotaGlobal.mqtt_data, GetOtaUrl(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data)), sizeof(TasmotaGlobal.mqtt_data)); #ifndef FIRMWARE_MINIMAL if (RtcSettings.ota_loader) { // OTA File too large so try OTA minimal version @@ -1012,10 +1028,10 @@ void Every250mSeconds(void) // Replace http://192.168.2.17:80/api/arduino/tasmota.bin with http://192.168.2.17:80/api/arduino/tasmota-minimal.bin // Replace http://192.168.2.17/api/arduino/tasmota.bin.gz with http://192.168.2.17/api/arduino/tasmota-minimal.bin.gz - char *bch = strrchr(mqtt_data, '/'); // Only consider filename after last backslash prevent change of urls having "-" in it - if (bch == nullptr) { bch = mqtt_data; } // No path found so use filename only + char *bch = strrchr(TasmotaGlobal.mqtt_data, '/'); // Only consider filename after last backslash prevent change of urls having "-" in it + if (bch == nullptr) { bch = TasmotaGlobal.mqtt_data; } // No path found so use filename only char *ech = strchr(bch, '.'); // Find file type in filename (none, .ino.bin, .ino.bin.gz, .bin, .bin.gz or .gz) - if (ech == nullptr) { ech = mqtt_data + strlen(mqtt_data); } // Point to '/0' at end of mqtt_data becoming an empty string + if (ech == nullptr) { ech = TasmotaGlobal.mqtt_data + strlen(TasmotaGlobal.mqtt_data); } // Point to '/0' at end of mqtt_data becoming an empty string //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("OTA: File type [%s]"), ech); @@ -1025,12 +1041,12 @@ void Every250mSeconds(void) char *pch = strrchr(bch, '-'); // Find last dash (-) and ignore remainder - handles tasmota-DE if (pch == nullptr) { pch = ech; } // No dash so ignore filetype *pch = '\0'; // mqtt_data = http://domus1:80/api/arduino/tasmota - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s-" D_JSON_MINIMAL "%s"), mqtt_data, ota_url_type); // Minimal filename must be filename-minimal + snprintf_P(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), PSTR("%s-" D_JSON_MINIMAL "%s"), TasmotaGlobal.mqtt_data, ota_url_type); // Minimal filename must be filename-minimal } #endif // FIRMWARE_MINIMAL - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "%s"), mqtt_data); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "%s"), TasmotaGlobal.mqtt_data); WiFiClient OTAclient; - ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(OTAclient, mqtt_data)); + ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(OTAclient, TasmotaGlobal.mqtt_data)); if (!ota_result) { #ifndef FIRMWARE_MINIMAL int ota_error = ESPhttpUpdate.getLastError(); @@ -1039,12 +1055,12 @@ void Every250mSeconds(void) RtcSettings.ota_loader = 1; // Try minimal image next } #endif // FIRMWARE_MINIMAL - ota_state_flag = 2; // Upgrade failed - retry + TasmotaGlobal.ota_state_flag = 2; // Upgrade failed - retry } } } - if (90 == ota_state_flag) { // Allow MQTT to reconnect - ota_state_flag = 0; + if (90 == TasmotaGlobal.ota_state_flag) { // Allow MQTT to reconnect + TasmotaGlobal.ota_state_flag = 0; Response_P(PSTR("{\"" D_CMND_UPGRADE "\":\"")); if (ota_result) { // SetFlashModeDout(); // Force DOUT for both ESP8266 and ESP8285 @@ -1052,13 +1068,13 @@ void Every250mSeconds(void) ResponseAppend_P(PSTR(D_JSON_FAILED " " D_UPLOAD_ERR_14)); } else { ResponseAppend_P(PSTR(D_JSON_SUCCESSFUL ". " D_JSON_RESTARTING)); - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } } else { ResponseAppend_P(PSTR(D_JSON_FAILED " %s"), ESPhttpUpdate.getLastErrorString().c_str()); } ResponseAppend_P(PSTR("\"}")); -// restart_flag = 2; // Restart anyway to keep memory clean webserver +// TasmotaGlobal.restart_flag = 2; // Restart anyway to keep memory clean webserver MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_UPGRADE)); #ifdef USE_COUNTER CounterInterruptDisable(false); @@ -1070,28 +1086,28 @@ void Every250mSeconds(void) if (MidnightNow()) { XsnsCall(FUNC_SAVE_AT_MIDNIGHT); } - if (save_data_counter && BACKLOG_EMPTY) { - save_data_counter--; - if (save_data_counter <= 0) { + if (TasmotaGlobal.save_data_counter && BACKLOG_EMPTY) { + TasmotaGlobal.save_data_counter--; + if (TasmotaGlobal.save_data_counter <= 0) { if (Settings.flag.save_state) { // SetOption0 - Save power state and use after restart power_t mask = POWER_MASK; - for (uint32_t i = 0; i < devices_present; i++) { + for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { if ((Settings.pulse_timer[i % MAX_PULSETIMERS] > 0) && (Settings.pulse_timer[i % MAX_PULSETIMERS] < 30)) { // 3 seconds mask &= ~(1 << i); } } - if (!((Settings.power &mask) == (power &mask))) { - Settings.power = power; + if (!((Settings.power &mask) == (TasmotaGlobal.power &mask))) { + Settings.power = TasmotaGlobal.power; } } else { Settings.power = 0; } - if (!restart_flag) { SettingsSave(0); } - save_data_counter = Settings.save_data; + if (!TasmotaGlobal.restart_flag) { SettingsSave(0); } + TasmotaGlobal.save_data_counter = Settings.save_data; } } - if (restart_flag && BACKLOG_EMPTY) { - if ((214 == restart_flag) || (215 == restart_flag) || (216 == restart_flag)) { + if (TasmotaGlobal.restart_flag && BACKLOG_EMPTY) { + if ((214 == TasmotaGlobal.restart_flag) || (215 == TasmotaGlobal.restart_flag) || (216 == TasmotaGlobal.restart_flag)) { // Backup current SSIDs and Passwords char storage_ssid1[strlen(SettingsText(SET_STASSID1)) +1]; strncpy(storage_ssid1, SettingsText(SET_STASSID1), sizeof(storage_ssid1)); @@ -1112,10 +1128,10 @@ void Every250mSeconds(void) strncpy(storage_mqtttopic, SettingsText(SET_MQTT_TOPIC), sizeof(storage_mqtttopic)); uint16_t mqtt_port = Settings.mqtt_port; -// if (216 == restart_flag) { +// if (216 == TasmotaGlobal.restart_flag) { // Backup mqtt host, port, client, username and password // } - if ((215 == restart_flag) || (216 == restart_flag)) { + if ((215 == TasmotaGlobal.restart_flag) || (216 == TasmotaGlobal.restart_flag)) { SettingsErase(0); // Erase all flash from program end to end of physical flash } SettingsDefault(); @@ -1124,7 +1140,7 @@ void Every250mSeconds(void) SettingsUpdateText(SET_STASSID2, storage_ssid2); SettingsUpdateText(SET_STAPWD1, storage_pass1); SettingsUpdateText(SET_STAPWD2, storage_pass2); - if (216 == restart_flag) { + if (216 == TasmotaGlobal.restart_flag) { // Restore the mqtt host, port, client, username and password SettingsUpdateText(SET_MQTT_HOST, storage_mqtthost); SettingsUpdateText(SET_MQTT_USER, storage_mqttuser); @@ -1132,42 +1148,42 @@ void Every250mSeconds(void) SettingsUpdateText(SET_MQTT_TOPIC, storage_mqtttopic); Settings.mqtt_port = mqtt_port; } - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } - else if (213 == restart_flag) { + else if (213 == TasmotaGlobal.restart_flag) { SettingsSdkErase(); // Erase flash SDK parameters - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } - else if (212 == restart_flag) { + else if (212 == TasmotaGlobal.restart_flag) { SettingsErase(0); // Erase all flash from program end to end of physical flash - restart_flag = 211; + TasmotaGlobal.restart_flag = 211; } - if (211 == restart_flag) { + if (211 == TasmotaGlobal.restart_flag) { SettingsDefault(); - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } - if (2 == restart_flag) { + if (2 == TasmotaGlobal.restart_flag) { SettingsSaveAll(); } - restart_flag--; - if (restart_flag <= 0) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "%s"), (restart_halt) ? "Halted" : D_RESTARTING); + TasmotaGlobal.restart_flag--; + if (TasmotaGlobal.restart_flag <= 0) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "%s"), (TasmotaGlobal.restart_halt) ? "Halted" : D_RESTARTING); EspRestart(); } } break; case 2: // Every x.5 second if (Settings.flag4.network_wifi) { - WifiCheck(wifi_state_flag); - wifi_state_flag = WIFI_RESTART; + WifiCheck(TasmotaGlobal.wifi_state_flag); + TasmotaGlobal.wifi_state_flag = WIFI_RESTART; } break; case 3: // Every x.75 second - if (!global_state.network_down) { + if (!TasmotaGlobal.global_state.network_down) { #ifdef FIRMWARE_MINIMAL if (1 == RtcSettings.ota_loader) { RtcSettings.ota_loader = 0; - ota_state_flag = 3; + TasmotaGlobal.ota_state_flag = 3; } #endif // FIRMWARE_MINIMAL @@ -1269,7 +1285,7 @@ void ArduinoOTAInit(void) ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { - if ((LOG_LEVEL_DEBUG <= seriallog_level)) { + if ((LOG_LEVEL_DEBUG <= TasmotaGlobal.seriallog_level)) { arduino_ota_progress_dot_count++; Serial.printf("."); if (!(arduino_ota_progress_dot_count % 80)) { Serial.println(); } @@ -1284,7 +1300,7 @@ void ArduinoOTAInit(void) */ char error_str[100]; - if ((LOG_LEVEL_DEBUG <= seriallog_level) && arduino_ota_progress_dot_count) { Serial.println(); } + if ((LOG_LEVEL_DEBUG <= TasmotaGlobal.seriallog_level) && arduino_ota_progress_dot_count) { Serial.println(); } switch (error) { case OTA_BEGIN_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_2), sizeof(error_str)); break; case OTA_RECEIVE_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_5), sizeof(error_str)); break; @@ -1298,7 +1314,7 @@ void ArduinoOTAInit(void) ArduinoOTA.onEnd([]() { - if ((LOG_LEVEL_DEBUG <= seriallog_level)) { Serial.println(); } + if ((LOG_LEVEL_DEBUG <= TasmotaGlobal.seriallog_level)) { Serial.println(); } AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_SUCCESSFUL ". " D_RESTARTING)); EspRestart(); }); @@ -1320,15 +1336,18 @@ void ArduinoOtaLoop(void) void SerialInput(void) { + static uint32_t serial_polling_window = 0; + static bool serial_buffer_overrun = false; + while (Serial.available()) { // yield(); delay(0); - serial_in_byte = Serial.read(); + TasmotaGlobal.serial_in_byte = Serial.read(); - if (0 == serial_in_byte_counter) { + if (0 == TasmotaGlobal.serial_in_byte_counter) { serial_buffer_overrun = false; } - else if ((serial_in_byte_counter == INPUT_BUFFER_SIZE) + else if ((TasmotaGlobal.serial_in_byte_counter == INPUT_BUFFER_SIZE) #ifdef ESP8266 || Serial.hasOverrun() #endif @@ -1340,46 +1359,46 @@ void SerialInput(void) /*-------------------------------------------------------------------------------------------*\ * Sonoff dual and ch4 19200 baud serial interface \*-------------------------------------------------------------------------------------------*/ - if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { - serial_in_byte = ButtonSerial(serial_in_byte); + if ((SONOFF_DUAL == TasmotaGlobal.module_type) || (CH4 == TasmotaGlobal.module_type)) { + TasmotaGlobal.serial_in_byte = ButtonSerial(TasmotaGlobal.serial_in_byte); } #endif // ESP8266 /*-------------------------------------------------------------------------------------------*/ if (XdrvCall(FUNC_SERIAL)) { - serial_in_byte_counter = 0; + TasmotaGlobal.serial_in_byte_counter = 0; Serial.flush(); return; } /*-------------------------------------------------------------------------------------------*/ - if (serial_in_byte > 127 && !Settings.flag.mqtt_serial_raw) { // Discard binary data above 127 if no raw reception allowed - CMND_SERIALSEND3 - serial_in_byte_counter = 0; + if (TasmotaGlobal.serial_in_byte > 127 && !Settings.flag.mqtt_serial_raw) { // Discard binary data above 127 if no raw reception allowed - CMND_SERIALSEND3 + TasmotaGlobal.serial_in_byte_counter = 0; Serial.flush(); return; } if (!Settings.flag.mqtt_serial) { // SerialSend active - CMND_SERIALSEND and CMND_SERIALLOG - if (isprint(serial_in_byte)) { // Any char between 32 and 127 - if (serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { // Add char to string if it still fits - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + if (isprint(TasmotaGlobal.serial_in_byte)) { // Any char between 32 and 127 + if (TasmotaGlobal.serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { // Add char to string if it still fits + TasmotaGlobal.serial_in_buffer[TasmotaGlobal.serial_in_byte_counter++] = TasmotaGlobal.serial_in_byte; } else { serial_buffer_overrun = true; // Signal overrun but continue reading input to flush until '\n' (EOL) } } } else { - if (serial_in_byte || Settings.flag.mqtt_serial_raw) { // Any char between 1 and 127 or any char (0 - 255) - CMND_SERIALSEND3 + if (TasmotaGlobal.serial_in_byte || Settings.flag.mqtt_serial_raw) { // Any char between 1 and 127 or any char (0 - 255) - CMND_SERIALSEND3 bool in_byte_is_delimiter = // Char is delimiter when... - (((Settings.serial_delimiter < 128) && (serial_in_byte == Settings.serial_delimiter)) || // Any char between 1 and 127 and being delimiter - ((Settings.serial_delimiter == 128) && !isprint(serial_in_byte))) && // Any char not between 32 and 127 + (((Settings.serial_delimiter < 128) && (TasmotaGlobal.serial_in_byte == Settings.serial_delimiter)) || // Any char between 1 and 127 and being delimiter + ((Settings.serial_delimiter == 128) && !isprint(TasmotaGlobal.serial_in_byte))) && // Any char not between 32 and 127 !Settings.flag.mqtt_serial_raw; // In raw mode (CMND_SERIALSEND3) there is never a delimiter - if ((serial_in_byte_counter < INPUT_BUFFER_SIZE -1) && // Add char to string if it still fits and ... + if ((TasmotaGlobal.serial_in_byte_counter < INPUT_BUFFER_SIZE -1) && // Add char to string if it still fits and ... !in_byte_is_delimiter) { // Char is not a delimiter - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + TasmotaGlobal.serial_in_buffer[TasmotaGlobal.serial_in_byte_counter++] = TasmotaGlobal.serial_in_byte; } - if ((serial_in_byte_counter >= INPUT_BUFFER_SIZE -1) || // Send message when buffer is full or ... + if ((TasmotaGlobal.serial_in_byte_counter >= INPUT_BUFFER_SIZE -1) || // Send message when buffer is full or ... in_byte_is_delimiter) { // Char is delimiter serial_polling_window = 0; // Reception done - send mqtt break; @@ -1393,11 +1412,11 @@ void SerialInput(void) /*-------------------------------------------------------------------------------------------*\ * Sonoff SC 19200 baud serial interface \*-------------------------------------------------------------------------------------------*/ - if (SONOFF_SC == my_module_type) { - if (serial_in_byte == '\x1B') { // Sonoff SC status from ATMEGA328P - serial_in_buffer[serial_in_byte_counter] = 0; // Serial data completed - SonoffScSerialInput(serial_in_buffer); - serial_in_byte_counter = 0; + if (SONOFF_SC == TasmotaGlobal.module_type) { + if (TasmotaGlobal.serial_in_byte == '\x1B') { // Sonoff SC status from ATMEGA328P + TasmotaGlobal.serial_in_buffer[TasmotaGlobal.serial_in_byte_counter] = 0; // Serial data completed + SonoffScSerialInput(TasmotaGlobal.serial_in_buffer); + TasmotaGlobal.serial_in_byte_counter = 0; Serial.flush(); return; } @@ -1405,43 +1424,43 @@ void SerialInput(void) #endif // USE_SONOFF_SC /*-------------------------------------------------------------------------------------------*/ - if (!Settings.flag.mqtt_serial && (serial_in_byte == '\n')) { // CMND_SERIALSEND and CMND_SERIALLOG - serial_in_buffer[serial_in_byte_counter] = 0; // Serial data completed - seriallog_level = (Settings.seriallog_level < LOG_LEVEL_INFO) ? (uint8_t)LOG_LEVEL_INFO : Settings.seriallog_level; + if (!Settings.flag.mqtt_serial && (TasmotaGlobal.serial_in_byte == '\n')) { // CMND_SERIALSEND and CMND_SERIALLOG + TasmotaGlobal.serial_in_buffer[TasmotaGlobal.serial_in_byte_counter] = 0; // Serial data completed + TasmotaGlobal.seriallog_level = (Settings.seriallog_level < LOG_LEVEL_INFO) ? (uint8_t)LOG_LEVEL_INFO : Settings.seriallog_level; if (serial_buffer_overrun) { AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "Serial buffer overrun")); } else { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "%s"), serial_in_buffer); - ExecuteCommand(serial_in_buffer, SRC_SERIAL); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "%s"), TasmotaGlobal.serial_in_buffer); + ExecuteCommand(TasmotaGlobal.serial_in_buffer, SRC_SERIAL); } - serial_in_byte_counter = 0; + TasmotaGlobal.serial_in_byte_counter = 0; serial_polling_window = 0; Serial.flush(); return; } } - if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) { // CMND_SERIALSEND and CMND_SERIALLOG - serial_in_buffer[serial_in_byte_counter] = 0; // Serial data completed - bool assume_json = (!Settings.flag.mqtt_serial_raw && (serial_in_buffer[0] == '{')); + if (Settings.flag.mqtt_serial && TasmotaGlobal.serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) { // CMND_SERIALSEND and CMND_SERIALLOG + TasmotaGlobal.serial_in_buffer[TasmotaGlobal.serial_in_byte_counter] = 0; // Serial data completed + bool assume_json = (!Settings.flag.mqtt_serial_raw && (TasmotaGlobal.serial_in_buffer[0] == '{')); Response_P(PSTR("{\"" D_JSON_SERIALRECEIVED "\":")); if (assume_json) { - ResponseAppend_P(serial_in_buffer); + ResponseAppend_P(TasmotaGlobal.serial_in_buffer); } else { ResponseAppend_P(PSTR("\"")); if (Settings.flag.mqtt_serial_raw) { - char hex_char[(serial_in_byte_counter * 2) + 2]; - ResponseAppend_P(ToHex_P((unsigned char*)serial_in_buffer, serial_in_byte_counter, hex_char, sizeof(hex_char))); + char hex_char[(TasmotaGlobal.serial_in_byte_counter * 2) + 2]; + ResponseAppend_P(ToHex_P((unsigned char*)TasmotaGlobal.serial_in_buffer, TasmotaGlobal.serial_in_byte_counter, hex_char, sizeof(hex_char))); } else { - ResponseAppend_P(EscapeJSONString(serial_in_buffer).c_str()); + ResponseAppend_P(EscapeJSONString(TasmotaGlobal.serial_in_buffer).c_str()); } ResponseAppend_P(PSTR("\"")); } ResponseJsonEnd(); MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED)); - serial_in_byte_counter = 0; + TasmotaGlobal.serial_in_byte_counter = 0; } } @@ -1451,8 +1470,8 @@ void ResetPwm(void) { for (uint32_t i = 0; i < MAX_PWMS; i++) { // Basic PWM control only if (PinUsed(GPIO_PWM1, i)) { - analogWrite(Pin(GPIO_PWM1, i), bitRead(pwm_inverted, i) ? Settings.pwm_range : 0); -// analogWrite(Pin(GPIO_PWM1, i), bitRead(pwm_inverted, i) ? Settings.pwm_range - Settings.pwm_value[i] : Settings.pwm_value[i]); + analogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings.pwm_range : 0); +// analogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings.pwm_range - Settings.pwm_value[i] : Settings.pwm_value[i]); } } } @@ -1477,7 +1496,8 @@ void GpioInit(void) } SetModuleType(); - if (Settings.module != Settings.last_module) { + TasmotaGlobal.module_changed = (Settings.module != Settings.last_module); + if (TasmotaGlobal.module_changed) { Settings.baudrate = APP_BAUDRATE / 300; Settings.serial_config = TS_SERIAL_8N1; SetSerialBegin(); @@ -1502,15 +1522,15 @@ void GpioInit(void) Settings.my_gp.io[i] = GPIO_NONE; // Fix not supported sensor ids in module } else if (Settings.my_gp.io[i] > GPIO_NONE) { - my_module.io[i] = Settings.my_gp.io[i]; // Set User selected Module sensors + TasmotaGlobal.my_module.io[i] = Settings.my_gp.io[i]; // Set User selected Module sensors } if ((def_gp.io[i] > GPIO_NONE) && (def_gp.io[i] < AGPIO(GPIO_USER))) { - my_module.io[i] = def_gp.io[i]; // Force Template override + TasmotaGlobal.my_module.io[i] = def_gp.io[i]; // Force Template override } } - for (uint32_t i = 0; i < ARRAY_SIZE(my_module.io); i++) { - uint32_t mpin = ValidPin(i, my_module.io[i]); + for (uint32_t i = 0; i < ARRAY_SIZE(TasmotaGlobal.my_module.io); i++) { + uint32_t mpin = ValidPin(i, TasmotaGlobal.my_module.io[i]); DEBUG_CORE_LOG(PSTR("INI: gpio pin %d, mpin %d"), i, mpin); @@ -1542,19 +1562,19 @@ void GpioInit(void) } #endif //ESP32 else if ((mpin >= AGPIO(GPIO_REL1_INV)) && (mpin < (AGPIO(GPIO_REL1_INV) + MAX_RELAYS))) { - bitSet(rel_inverted, mpin - AGPIO(GPIO_REL1_INV)); + bitSet(TasmotaGlobal.rel_inverted, mpin - AGPIO(GPIO_REL1_INV)); mpin -= (AGPIO(GPIO_REL1_INV) - AGPIO(GPIO_REL1)); } else if ((mpin >= AGPIO(GPIO_LED1_INV)) && (mpin < (AGPIO(GPIO_LED1_INV) + MAX_LEDS))) { - bitSet(led_inverted, mpin - AGPIO(GPIO_LED1_INV)); + bitSet(TasmotaGlobal.led_inverted, mpin - AGPIO(GPIO_LED1_INV)); mpin -= (AGPIO(GPIO_LED1_INV) - AGPIO(GPIO_LED1)); } else if (mpin == AGPIO(GPIO_LEDLNK_INV)) { - ledlnk_inverted = 1; + TasmotaGlobal.ledlnk_inverted = 1; mpin -= (AGPIO(GPIO_LEDLNK_INV) - AGPIO(GPIO_LEDLNK)); } else if ((mpin >= AGPIO(GPIO_PWM1_INV)) && (mpin < (AGPIO(GPIO_PWM1_INV) + MAX_PWMS))) { - bitSet(pwm_inverted, mpin - AGPIO(GPIO_PWM1_INV)); + bitSet(TasmotaGlobal.pwm_inverted, mpin - AGPIO(GPIO_PWM1_INV)); mpin -= (AGPIO(GPIO_PWM1_INV) - AGPIO(GPIO_PWM1)); } else if (XdrvCall(FUNC_PIN_STATE)) { @@ -1567,22 +1587,22 @@ void GpioInit(void) if (mpin) { SetPin(i, mpin); } // Anything above GPIO_NONE and below GPIO_SENSOR_END } -// AddLogBufferSize(LOG_LEVEL_DEBUG, (uint8_t*)gpio_pin, ARRAY_SIZE(gpio_pin), sizeof(gpio_pin[0])); +// AddLogBufferSize(LOG_LEVEL_DEBUG, (uint8_t*)TasmotaGlobal.gpio_pin, ARRAY_SIZE(TasmotaGlobal.gpio_pin), sizeof(TasmotaGlobal.gpio_pin[0])); analogWriteRange(Settings.pwm_range); // Default is 1023 (Arduino.h) analogWriteFreq(Settings.pwm_frequency); // Default is 1000 (core_esp8266_wiring_pwm.c) #ifdef ESP8266 - if ((2 == Pin(GPIO_TXD)) || (H801 == my_module_type)) { Serial.set_tx(2); } + if ((2 == Pin(GPIO_TXD)) || (H801 == TasmotaGlobal.module_type)) { Serial.set_tx(2); } #ifdef USE_SPI - spi_flg = (((PinUsed(GPIO_SPI_CS) && (Pin(GPIO_SPI_CS) > 14)) || (Pin(GPIO_SPI_CS) < 12)) || ((PinUsed(GPIO_SPI_DC) && (Pin(GPIO_SPI_DC) > 14)) || (Pin(GPIO_SPI_DC) < 12))); - if (spi_flg) { - my_module.io[12] = GPIO_SPI_MISO; + TasmotaGlobal.spi_enabled = (((PinUsed(GPIO_SPI_CS) && (Pin(GPIO_SPI_CS) > 14)) || (Pin(GPIO_SPI_CS) < 12)) || ((PinUsed(GPIO_SPI_DC) && (Pin(GPIO_SPI_DC) > 14)) || (Pin(GPIO_SPI_DC) < 12))); + if (TasmotaGlobal.spi_enabled) { + TasmotaGlobal.my_module.io[12] = GPIO_SPI_MISO; SetPin(12, GPIO_SPI_MISO); - my_module.io[13] = GPIO_SPI_MOSI; + TasmotaGlobal.my_module.io[13] = GPIO_SPI_MOSI; SetPin(13, GPIO_SPI_MOSI); - my_module.io[14] = GPIO_SPI_CLK; + TasmotaGlobal.my_module.io[14] = GPIO_SPI_CLK; SetPin(14, GPIO_SPI_CLK); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SPI: Using GPIO12(MISO), GPIO13(MOSI) and GPIO14(CLK)")); } @@ -1591,39 +1611,39 @@ void GpioInit(void) #ifdef USE_SPI if (PinUsed(GPIO_SPI_CS) || PinUsed(GPIO_SPI_DC)) { if ((15 == Pin(GPIO_SPI_CS)) && (!GetPin(12) && !GetPin(13) && !GetPin(14))) { // HSPI - my_module.io[12] = AGPIO(GPIO_SPI_MISO); + TasmotaGlobal.my_module.io[12] = AGPIO(GPIO_SPI_MISO); SetPin(12, AGPIO(GPIO_SPI_MISO)); - my_module.io[13] = AGPIO(GPIO_SPI_MOSI); + TasmotaGlobal.my_module.io[13] = AGPIO(GPIO_SPI_MOSI); SetPin(13, AGPIO(GPIO_SPI_MOSI)); - my_module.io[14] = AGPIO(GPIO_SPI_CLK); + TasmotaGlobal.my_module.io[14] = AGPIO(GPIO_SPI_CLK); SetPin(14, AGPIO(GPIO_SPI_CLK)); } else if ((5 == Pin(GPIO_SPI_CS)) && (!GetPin(19) && !GetPin(23) && !GetPin(18))) { // VSPI - my_module.io[19] = AGPIO(GPIO_SPI_MISO); + TasmotaGlobal.my_module.io[19] = AGPIO(GPIO_SPI_MISO); SetPin(19, AGPIO(GPIO_SPI_MISO)); - my_module.io[23] = AGPIO(GPIO_SPI_MOSI); + TasmotaGlobal.my_module.io[23] = AGPIO(GPIO_SPI_MOSI); SetPin(23, AGPIO(GPIO_SPI_MOSI)); - my_module.io[18] = AGPIO(GPIO_SPI_CLK); + TasmotaGlobal.my_module.io[18] = AGPIO(GPIO_SPI_CLK); SetPin(18, AGPIO(GPIO_SPI_CLK)); } else if ((12 == Pin(GPIO_SPI_MISO)) || (13 == Pin(GPIO_SPI_MOSI)) || (14 == Pin(GPIO_SPI_CLK))) { // HSPI - my_module.io[12] = AGPIO(GPIO_SPI_MISO); + TasmotaGlobal.my_module.io[12] = AGPIO(GPIO_SPI_MISO); SetPin(12, AGPIO(GPIO_SPI_MISO)); - my_module.io[13] = AGPIO(GPIO_SPI_MOSI); + TasmotaGlobal.my_module.io[13] = AGPIO(GPIO_SPI_MOSI); SetPin(13, AGPIO(GPIO_SPI_MOSI)); - my_module.io[14] = AGPIO(GPIO_SPI_CLK); + TasmotaGlobal.my_module.io[14] = AGPIO(GPIO_SPI_CLK); SetPin(14, AGPIO(GPIO_SPI_CLK)); } else if ((19 == Pin(GPIO_SPI_MISO)) || (23 == Pin(GPIO_SPI_MOSI)) || (18 == Pin(GPIO_SPI_CLK))) { // VSPI - my_module.io[19] = AGPIO(GPIO_SPI_MISO); + TasmotaGlobal.my_module.io[19] = AGPIO(GPIO_SPI_MISO); SetPin(19, AGPIO(GPIO_SPI_MISO)); - my_module.io[23] = AGPIO(GPIO_SPI_MOSI); + TasmotaGlobal.my_module.io[23] = AGPIO(GPIO_SPI_MOSI); SetPin(23, AGPIO(GPIO_SPI_MOSI)); - my_module.io[18] = AGPIO(GPIO_SPI_CLK); + TasmotaGlobal.my_module.io[18] = AGPIO(GPIO_SPI_CLK); SetPin(18, AGPIO(GPIO_SPI_CLK)); } - spi_flg = (PinUsed(GPIO_SPI_CLK) && (PinUsed(GPIO_SPI_MOSI) || PinUsed(GPIO_SPI_MISO))); - if (spi_flg) { + TasmotaGlobal.spi_enabled = (PinUsed(GPIO_SPI_CLK) && (PinUsed(GPIO_SPI_MOSI) || PinUsed(GPIO_SPI_MISO))); + if (TasmotaGlobal.spi_enabled) { if (PinUsed(GPIO_SPI_MOSI) && PinUsed(GPIO_SPI_MISO)) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SPI: Using GPIO%02d(MISO), GPIO%02d(MOSI) and GPIO%02d(CLK)"), Pin(GPIO_SPI_MISO), Pin(GPIO_SPI_MOSI), Pin(GPIO_SPI_CLK)); @@ -1640,10 +1660,10 @@ void GpioInit(void) } #endif // USE_SPI #endif // ESP8266 - ESP32 - soft_spi_flg = (PinUsed(GPIO_SSPI_SCLK) && (PinUsed(GPIO_SSPI_MOSI) || PinUsed(GPIO_SSPI_MISO))); + TasmotaGlobal.soft_spi_enabled = (PinUsed(GPIO_SSPI_SCLK) && (PinUsed(GPIO_SSPI_MOSI) || PinUsed(GPIO_SSPI_MISO))); - for (uint32_t i = 0; i < ARRAY_SIZE(my_module.io); i++) { - uint32_t mpin = ValidPin(i, my_module.io[i]); + for (uint32_t i = 0; i < ARRAY_SIZE(TasmotaGlobal.my_module.io); i++) { + uint32_t mpin = ValidPin(i, TasmotaGlobal.my_module.io[i]); // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("INI: gpio pin %d, mpin %d"), i, mpin); if (AGPIO(GPIO_OUTPUT_HI) == mpin) { pinMode(i, OUTPUT); @@ -1663,14 +1683,14 @@ void GpioInit(void) } #ifdef USE_I2C - i2c_flg = (PinUsed(GPIO_I2C_SCL) && PinUsed(GPIO_I2C_SDA)); - if (i2c_flg) { + TasmotaGlobal.i2c_enabled = (PinUsed(GPIO_I2C_SCL) && PinUsed(GPIO_I2C_SDA)); + if (TasmotaGlobal.i2c_enabled) { Wire.begin(Pin(GPIO_I2C_SDA), Pin(GPIO_I2C_SCL)); } #endif // USE_I2C - devices_present = 0; - light_type = LT_BASIC; // Use basic PWM control if SetOption15 = 0 + TasmotaGlobal.devices_present = 0; + TasmotaGlobal.light_type = LT_BASIC; // Use basic PWM control if SetOption15 = 0 XsnsCall(FUNC_MODULE_INIT); @@ -1678,20 +1698,20 @@ void GpioInit(void) // Serviced } #ifdef ESP8266 - else if (YTF_IR_BRIDGE == my_module_type) { + else if (YTF_IR_BRIDGE == TasmotaGlobal.module_type) { ClaimSerial(); // Stop serial loopback mode -// devices_present = 1; +// TasmotaGlobal.devices_present = 1; } - else if (SONOFF_DUAL == my_module_type) { - devices_present = 2; + else if (SONOFF_DUAL == TasmotaGlobal.module_type) { + TasmotaGlobal.devices_present = 2; SetSerial(19200, TS_SERIAL_8N1); } - else if (CH4 == my_module_type) { - devices_present = 4; + else if (CH4 == TasmotaGlobal.module_type) { + TasmotaGlobal.devices_present = 4; SetSerial(19200, TS_SERIAL_8N1); } #ifdef USE_SONOFF_SC - else if (SONOFF_SC == my_module_type) { + else if (SONOFF_SC == TasmotaGlobal.module_type) { SetSerial(19200, TS_SERIAL_8N1); } #endif // USE_SONOFF_SC @@ -1704,12 +1724,12 @@ void GpioInit(void) #else // ESP32 analogAttach(Pin(GPIO_PWM1, i), i); #endif - if (light_type) { + if (TasmotaGlobal.light_type) { // force PWM GPIOs to low or high mode, see #7165 - analogWrite(Pin(GPIO_PWM1, i), bitRead(pwm_inverted, i) ? Settings.pwm_range : 0); + analogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings.pwm_range : 0); } else { - pwm_present = true; - analogWrite(Pin(GPIO_PWM1, i), bitRead(pwm_inverted, i) ? Settings.pwm_range - Settings.pwm_value[i] : Settings.pwm_value[i]); + TasmotaGlobal.pwm_present = true; + analogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings.pwm_range - Settings.pwm_value[i] : Settings.pwm_value[i]); } } } @@ -1717,11 +1737,11 @@ void GpioInit(void) for (uint32_t i = 0; i < MAX_RELAYS; i++) { if (PinUsed(GPIO_REL1, i)) { pinMode(Pin(GPIO_REL1, i), OUTPUT); - devices_present++; + TasmotaGlobal.devices_present++; #ifdef ESP8266 - if (EXS_RELAY == my_module_type) { - digitalWrite(Pin(GPIO_REL1, i), bitRead(rel_inverted, i) ? 1 : 0); - if (i &1) { devices_present--; } + if (EXS_RELAY == TasmotaGlobal.module_type) { + digitalWrite(Pin(GPIO_REL1, i), bitRead(TasmotaGlobal.rel_inverted, i) ? 1 : 0); + if (i &1) { TasmotaGlobal.devices_present--; } } #endif // ESP8266 } @@ -1730,13 +1750,13 @@ void GpioInit(void) for (uint32_t i = 0; i < MAX_LEDS; i++) { if (PinUsed(GPIO_LED1, i)) { #ifdef USE_ARILUX_RF - if ((3 == i) && (leds_present < 2) && !PinUsed(GPIO_ARIRFSEL)) { + if ((3 == i) && (TasmotaGlobal.leds_present < 2) && !PinUsed(GPIO_ARIRFSEL)) { SetPin(Pin(GPIO_LED1, i), AGPIO(GPIO_ARIRFSEL)); // Legacy support where LED4 was Arilux RF enable } else { #endif pinMode(Pin(GPIO_LED1, i), OUTPUT); - leds_present++; - digitalWrite(Pin(GPIO_LED1, i), bitRead(led_inverted, i)); + TasmotaGlobal.leds_present++; + digitalWrite(Pin(GPIO_LED1, i), bitRead(TasmotaGlobal.led_inverted, i)); #ifdef USE_ARILUX_RF } #endif @@ -1744,11 +1764,11 @@ void GpioInit(void) } if (PinUsed(GPIO_LEDLNK)) { pinMode(Pin(GPIO_LEDLNK), OUTPUT); - digitalWrite(Pin(GPIO_LEDLNK), ledlnk_inverted); + digitalWrite(Pin(GPIO_LEDLNK), TasmotaGlobal.ledlnk_inverted); } #ifdef USE_PWM_DIMMER - if (PWM_DIMMER == my_module_type && PinUsed(GPIO_REL1)) { devices_present--; } + if (PWM_DIMMER == TasmotaGlobal.module_type && PinUsed(GPIO_REL1)) { TasmotaGlobal.devices_present--; } #endif // USE_PWM_DIMMER ButtonInit(); diff --git a/tasmota/support_udp.ino b/tasmota/support_udp.ino index cccb64b4e..3520d4b76 100644 --- a/tasmota/support_udp.ino +++ b/tasmota/support_udp.ino @@ -79,7 +79,7 @@ bool UdpDisconnect(void) bool UdpConnect(void) { - if (!udp_connected && !restart_flag) { + if (!udp_connected && !TasmotaGlobal.restart_flag) { // Simple Service Discovery Protocol (SSDP) #ifdef ESP8266 UdpCtx.reset(); @@ -133,7 +133,7 @@ void PollUdp(void) #if defined(USE_SCRIPT_HUE) || defined(USE_ZIGBEE) if (!udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) { #else - if (devices_present && !udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) { + if (TasmotaGlobal.devices_present && !udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) { #endif udp_response_mutex = true; diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 8246539a7..f25e710e7 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -97,9 +97,9 @@ void WifiConfig(uint8_t type) Wifi.config_counter = WIFI_CONFIG_SEC; // Allow up to WIFI_CONFIG_SECS seconds for phone to provide ssid/pswd Wifi.counter = Wifi.config_counter +5; - blinks = 1999; + TasmotaGlobal.blinks = 255; if (WIFI_RESTART == Wifi.config_type) { - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } else if (WIFI_SERIAL == Wifi.config_type) { AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_6_SERIAL " " D_ACTIVE_FOR_3_MINUTES)); @@ -153,7 +153,7 @@ void WiFiSetSleepMode(void) */ // Sleep explanation: https://github.com/esp8266/Arduino/blob/3f0c601cfe81439ce17e9bd5d28994a7ed144482/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp#L255 - if (ssleep && Settings.flag3.sleep_normal) { // SetOption60 - Enable normal sleep instead of dynamic sleep + if (TasmotaGlobal.sleep && Settings.flag3.sleep_normal) { // SetOption60 - Enable normal sleep instead of dynamic sleep WiFi.setSleepMode(WIFI_LIGHT_SLEEP); // Allow light sleep during idle times } else { WiFi.setSleepMode(WIFI_MODEM_SLEEP); // Disable sleep (Esp8288/Arduino core and sdk default) @@ -193,7 +193,7 @@ void WifiBegin(uint8_t flag, uint8_t channel) if (Settings.ip_address[0]) { WiFi.config(Settings.ip_address[0], Settings.ip_address[1], Settings.ip_address[2], Settings.ip_address[3]); // Set static IP } - WiFi.hostname(my_hostname); + WiFi.hostname(TasmotaGlobal.hostname); char stemp[40] = { 0 }; if (channel) { @@ -205,7 +205,7 @@ void WifiBegin(uint8_t flag, uint8_t channel) WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active)); } AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s%s " D_IN_MODE " 11%c " D_AS " %s..."), - Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), stemp, kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); + Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), stemp, kWifiPhyMode[WiFi.getPhyMode() & 0x3], TasmotaGlobal.hostname); #if LWIP_IPV6 for (bool configured = false; !configured;) { @@ -331,19 +331,19 @@ String WifiDowntime(void) void WifiSetState(uint8_t state) { - if (state == global_state.wifi_down) { + if (state == TasmotaGlobal.global_state.wifi_down) { if (state) { - rules_flag.wifi_connected = 1; + TasmotaGlobal.rules_flag.wifi_connected = 1; Wifi.link_count++; Wifi.downtime += UpTime() - Wifi.last_event; } else { - rules_flag.wifi_disconnected = 1; + TasmotaGlobal.rules_flag.wifi_disconnected = 1; Wifi.last_event = UpTime(); } } - global_state.wifi_down = state ^1; - if (!global_state.wifi_down) { - global_state.network_down = 0; + TasmotaGlobal.global_state.wifi_down = state ^1; + if (!TasmotaGlobal.global_state.wifi_down) { + TasmotaGlobal.global_state.network_down = 0; } } @@ -503,7 +503,7 @@ void WifiCheck(uint8_t param) } if (!Wifi.config_counter) { // SettingsSdkErase(); // Disabled v6.1.0b due to possible bad wifi connects - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } } else { if (Wifi.scan_state) { WifiBeginAfterScan(); } @@ -520,7 +520,7 @@ void WifiCheck(uint8_t param) #endif // LWIP_IPV6=1 WifiSetState(1); if (Settings.flag3.use_wifi_rescan) { // SetOption57 - Scan wifi network every 44 minutes for configured AP's - if (!(uptime % (60 * WIFI_RESCAN_MINUTES))) { + if (!(TasmotaGlobal.uptime % (60 * WIFI_RESCAN_MINUTES))) { Wifi.scan_state = 2; } } @@ -536,7 +536,7 @@ int WifiState(void) { int state = -1; - if (!global_state.wifi_down) { state = WIFI_RESTART; } + if (!TasmotaGlobal.global_state.wifi_down) { state = WIFI_RESTART; } if (Wifi.config_type) { state = Wifi.config_type; } return state; } @@ -641,7 +641,7 @@ void EspRestart(void) WifiShutdown(true); CrashDumpClear(); // Clear the stack dump in RTC - if (restart_halt) { + if (TasmotaGlobal.restart_halt) { while (1) { OsWatchLoop(); // Feed OsWatch timer to prevent restart SetLedLink(1); // Wifi led on @@ -666,8 +666,6 @@ extern "C" { #endif } -unsigned long wifiTimer = 0; - void stationKeepAliveNow(void) { AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_WIFI "Sending Gratuitous ARP")); for (netif* interface = netif_list; interface != nullptr; interface = interface->next) @@ -689,15 +687,17 @@ void stationKeepAliveNow(void) { } void wifiKeepAlive(void) { - uint32_t wifiTimerSec = Settings.param[P_ARP_GRATUITOUS]; // 8-bits number of seconds, or minutes if > 100 + static uint32_t wifi_timer = 0; // Wifi keepalive timer + + uint32_t wifiTimerSec = Settings.param[P_ARP_GRATUITOUS]; // 8-bits number of seconds, or minutes if > 100 if ((WL_CONNECTED != Wifi.status) || (0 == wifiTimerSec)) { return; } // quick exit if wifi not connected or feature disabled - if (TimeReached(wifiTimer)) { + if (TimeReached(wifi_timer)) { stationKeepAliveNow(); if (wifiTimerSec > 100) { - wifiTimerSec = (wifiTimerSec - 100) * 60; // convert >100 as minutes, ex: 105 = 5 minutes, 110 = 10 minutes + wifiTimerSec = (wifiTimerSec - 100) * 60; // convert >100 as minutes, ex: 105 = 5 minutes, 110 = 10 minutes } - SetNextTimeInterval(wifiTimer, wifiTimerSec * 1000); + SetNextTimeInterval(wifi_timer, wifiTimerSec * 1000); } } diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index 6a5c4f851..9484b8f2a 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -306,6 +306,7 @@ enum SettingsTextIndex { SET_OTAURL, #else // ESP32 SET_ADC_PARAM1, SET_ADC_PARAM2, SET_ADC_PARAM3, SET_ADC_PARAM4, SET_ADC_PARAM5, SET_ADC_PARAM6, SET_ADC_PARAM7, SET_ADC_PARAM8, // MAX_ADCS #endif + SET_SWITCH_TXT1, SET_SWITCH_TXT2, SET_SWITCH_TXT3, SET_SWITCH_TXT4, SET_SWITCH_TXT5, SET_SWITCH_TXT6, SET_SWITCH_TXT7, SET_SWITCH_TXT8, // MAX_SWITCHES SET_MAX }; enum DevGroupMessageType { DGR_MSGTYP_FULL_STATUS, DGR_MSGTYP_PARTIAL_UPDATE, DGR_MSGTYP_UPDATE, DGR_MSGTYP_UPDATE_MORE_TO_COME, DGR_MSGTYP_UPDATE_DIRECT, DGR_MSGTYPE_UPDATE_COMMAND, DGR_MSGTYPFLAG_WITH_LOCAL = 128 }; @@ -348,6 +349,7 @@ enum TasmotaSerialConfig { TS_SERIAL_5O1, TS_SERIAL_6O1, TS_SERIAL_7O1, TS_SERIAL_8O1, TS_SERIAL_5O2, TS_SERIAL_6O2, TS_SERIAL_7O2, TS_SERIAL_8O2 }; +#ifdef ESP8266 const SerConfu8 kTasmotaSerialConfig[] PROGMEM = { SERIAL_5N1, SERIAL_6N1, SERIAL_7N1, SERIAL_8N1, SERIAL_5N2, SERIAL_6N2, SERIAL_7N2, SERIAL_8N2, @@ -356,6 +358,16 @@ const SerConfu8 kTasmotaSerialConfig[] PROGMEM = { SERIAL_5O1, SERIAL_6O1, SERIAL_7O1, SERIAL_8O1, SERIAL_5O2, SERIAL_6O2, SERIAL_7O2, SERIAL_8O2 }; +#else // ESP32 +const uint32_t kTasmotaSerialConfig[] PROGMEM = { + SERIAL_5N1, SERIAL_6N1, SERIAL_7N1, SERIAL_8N1, + SERIAL_5N2, SERIAL_6N2, SERIAL_7N2, SERIAL_8N2, + SERIAL_5E1, SERIAL_6E1, SERIAL_7E1, SERIAL_8E1, + SERIAL_5E2, SERIAL_6E2, SERIAL_7E2, SERIAL_8E2, + SERIAL_5O1, SERIAL_6O1, SERIAL_7O1, SERIAL_8O1, + SERIAL_5O2, SERIAL_6O2, SERIAL_7O2, SERIAL_8O2 +}; +#endif enum TuyaSupportedFunctions { TUYA_MCU_FUNC_NONE, TUYA_MCU_FUNC_SWT1 = 1, TUYA_MCU_FUNC_SWT2, TUYA_MCU_FUNC_SWT3, TUYA_MCU_FUNC_SWT4, diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 179e2241b..9e13d9c49 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -77,111 +77,105 @@ WiFiUDP PortUdp; // UDP Syslog and Alexa -unsigned long feature_drv1; // Compiled driver feature map -unsigned long feature_drv2; // Compiled driver feature map -unsigned long feature_sns1; // Compiled sensor feature map -unsigned long feature_sns2; // Compiled sensor feature map -unsigned long feature5; // Compiled feature map -unsigned long feature6; // Compiled feature map -unsigned long feature7; // Compiled feature map -unsigned long serial_polling_window = 0; // Serial polling window -unsigned long state_second = 0; // State second timer -unsigned long state_50msecond = 0; // State 50msecond timer -unsigned long state_100msecond = 0; // State 100msecond timer -unsigned long state_250msecond = 0; // State 250msecond timer -unsigned long pulse_timer[MAX_PULSETIMERS] = { 0 }; // Power off timer -unsigned long blink_timer = 0; // Power cycle timer -unsigned long backlog_delay = 0; // Command backlog delay -power_t power = 0; // Current copy of Settings.power -power_t last_power = 0; // Last power set state -power_t blink_power; // Blink power state -power_t blink_mask = 0; // Blink relay active mask -power_t blink_powersave; // Blink start power save state -power_t latching_power = 0; // Power state at latching start -power_t rel_inverted = 0; // Relay inverted flag (1 = (0 = On, 1 = Off)) -int serial_in_byte_counter = 0; // Index in receive buffer -int ota_state_flag = 0; // OTA state flag -int ota_result = 0; // OTA result -int restart_flag = 0; // Tasmota restart flag -int wifi_state_flag = WIFI_RESTART; // Wifi state flag -int blinks = 201; // Number of LED blinks -uint32_t uptime = 0; // Counting every second until 4294967295 = 130 year -uint32_t loop_load_avg = 0; // Indicative loop load average -uint32_t global_update = 0; // Timestamp of last global temperature and humidity update -uint32_t web_log_index = 1; // Index in Web log buffer (should never be 0) -uint32_t baudrate = APP_BAUDRATE; // Current Serial baudrate -float global_temperature_celsius = NAN; // Provide a global temperature to be used by some sensors -float global_humidity = 0.0f; // Provide a global humidity to be used by some sensors -float global_pressure_hpa = 0.0f; // Provide a global pressure to be used by some sensors -uint16_t tele_period = 9999; // Tele period timer -uint16_t blink_counter = 0; // Number of blink cycles -uint16_t seriallog_timer = 0; // Timer to disable Seriallog -uint16_t syslog_timer = 0; // Timer to re-enable syslog_level -uint16_t gpio_pin[MAX_GPIO_PIN] = { 0 }; // GPIO functions indexed by pin number -int16_t save_data_counter; // Counter and flag for config save to Flash -RulesBitfield rules_flag; // Rule state flags (16 bits) -uint8_t mqtt_cmnd_blocked = 0; // Ignore flag for publish command -uint8_t mqtt_cmnd_blocked_reset = 0; // Count down to reset if needed -uint8_t state_250mS = 0; // State 250msecond per second flag -uint8_t latching_relay_pulse = 0; // Latching relay pulse timer -uint8_t ssleep; // Current copy of Settings.sleep -uint8_t blinkspeed = 1; // LED blink rate -uint8_t active_device = 1; // Active device in ExecuteCommandPower -uint8_t leds_present = 0; // Max number of LED supported -uint8_t led_inverted = 0; // LED inverted flag (1 = (0 = On, 1 = Off)) -uint8_t led_power = 0; // LED power state -uint8_t ledlnk_inverted = 0; // Link LED inverted flag (1 = (0 = On, 1 = Off)) -uint8_t pwm_inverted = 0; // PWM inverted flag (1 = inverted) -uint8_t energy_flg = 0; // Energy monitor configured -uint8_t light_flg = 0; // Light module configured -uint8_t light_type = 0; // Light types -uint8_t serial_in_byte; // Received byte -uint8_t ota_retry_counter = OTA_ATTEMPTS; // OTA retry counter -uint8_t devices_present = 0; // Max number of devices supported -uint8_t masterlog_level = 0; // Master log level used to override set log level -uint8_t seriallog_level; // Current copy of Settings.seriallog_level -uint8_t syslog_level; // Current copy of Settings.syslog_level -uint8_t my_module_type; // Current copy of Settings.module or user template type -uint8_t last_source = 0; // Last command source -uint8_t shutters_present = 0; // Number of actual define shutters -uint8_t prepped_loglevel = 0; // Delayed log level message -//uint8_t mdns_delayed_start = 0; // mDNS delayed start -bool serial_local = false; // Handle serial locally -bool serial_buffer_overrun = false; // Serial buffer overrun -bool fallback_topic_flag = false; // Use Topic or FallbackTopic -bool backlog_mutex = false; // Command backlog pending -bool interlock_mutex = false; // Interlock power command pending -bool stop_flash_rotate = false; // Allow flash configuration rotation -bool blinkstate = false; // LED state -//bool latest_uptime_flag = true; // Signal latest uptime -bool pwm_present = false; // Any PWM channel configured with SetOption15 0 -bool i2c_flg = false; // I2C configured -bool spi_flg = false; // SPI configured -bool soft_spi_flg = false; // Software SPI configured -bool ntp_force_sync = false; // Force NTP sync -bool is_8285 = false; // Hardware device ESP8266EX (0) or ESP8285 (1) -bool skip_light_fade; // Temporarily skip light fading -bool restart_halt = false; // Do not restart but stay in wait loop -myio my_module; // Active copy of Module GPIOs (17 x 8 bits) -StateBitfield global_state; // Global states (currently Wifi and Mqtt) (8 bits) -char my_version[33]; // Composed version string -char my_image[33]; // Code image and/or commit -char my_hostname[33]; // Composed Wifi hostname -char mqtt_client[TOPSZ]; // Composed MQTT Clientname -char mqtt_topic[TOPSZ]; // Composed MQTT topic -char serial_in_buffer[INPUT_BUFFER_SIZE]; // Receive buffer -char mqtt_data[MESSZ]; // MQTT publish buffer and web page ajax buffer -char log_data[LOGSZ]; // Logging -char web_log[WEB_LOG_SIZE] = {'\0'}; // Web log buffer +struct { + uint32_t global_update; // Timestamp of last global temperature and humidity update + uint32_t baudrate; // Current Serial baudrate + uint32_t pulse_timer[MAX_PULSETIMERS]; // Power off timer + uint32_t blink_timer; // Power cycle timer + uint32_t backlog_delay; // Command backlog delay + uint32_t loop_load_avg; // Indicative loop load average + uint32_t web_log_index; // Index in Web log buffer + uint32_t uptime; // Counting every second until 4294967295 = 130 year + + power_t power; // Current copy of Settings.power + power_t rel_inverted; // Relay inverted flag (1 = (0 = On, 1 = Off)) + power_t last_power; // Last power set state + power_t blink_power; // Blink power state + power_t blink_powersave; // Blink start power save state + power_t blink_mask; // Blink relay active mask + + int serial_in_byte_counter; // Index in receive buffer + + float temperature_celsius; // Provide a global temperature to be used by some sensors + float humidity; // Provide a global humidity to be used by some sensors + float pressure_hpa; // Provide a global pressure to be used by some sensors + + uint16_t gpio_pin[MAX_GPIO_PIN]; // GPIO functions indexed by pin number + myio my_module; // Active copy of Module GPIOs (17 x 16 bits) + uint16_t blink_counter; // Number of blink cycles + uint16_t seriallog_timer; // Timer to disable Seriallog + uint16_t syslog_timer; // Timer to re-enable syslog_level + uint16_t tele_period; // Tele period timer + int16_t save_data_counter; // Counter and flag for config save to Flash + RulesBitfield rules_flag; // Rule state flags (16 bits) + + bool serial_local; // Handle serial locally + bool fallback_topic_flag; // Use Topic or FallbackTopic + bool backlog_mutex; // Command backlog pending + bool stop_flash_rotate; // Allow flash configuration rotation + bool blinkstate; // LED state + bool pwm_present; // Any PWM channel configured with SetOption15 0 + bool i2c_enabled; // I2C configured + bool spi_enabled; // SPI configured + bool soft_spi_enabled; // Software SPI configured + bool ntp_force_sync; // Force NTP sync + bool is_8285; // Hardware device ESP8266EX (0) or ESP8285 (1) + bool skip_light_fade; // Temporarily skip light fading + bool restart_halt; // Do not restart but stay in wait loop + bool module_changed; // Indicate module changed since last restart + + StateBitfield global_state; // Global states (currently Wifi and Mqtt) (8 bits) + uint8_t blinks; // Number of LED blinks + uint8_t restart_flag; // Tasmota restart flag + uint8_t ota_state_flag; // OTA state flag + uint8_t wifi_state_flag; // Wifi state flag + uint8_t mqtt_cmnd_blocked; // Ignore flag for publish command + uint8_t mqtt_cmnd_blocked_reset; // Count down to reset if needed + uint8_t state_250mS; // State 250msecond per second flag + uint8_t latching_relay_pulse; // Latching relay pulse timer + uint8_t active_device; // Active device in ExecuteCommandPower + uint8_t sleep; // Current copy of Settings.sleep + uint8_t leds_present; // Max number of LED supported + uint8_t led_inverted; // LED inverted flag (1 = (0 = On, 1 = Off)) + uint8_t led_power; // LED power state + uint8_t ledlnk_inverted; // Link LED inverted flag (1 = (0 = On, 1 = Off)) + uint8_t pwm_inverted; // PWM inverted flag (1 = inverted) + uint8_t energy_driver; // Energy monitor configured + uint8_t light_driver; // Light module configured + uint8_t light_type; // Light types + uint8_t serial_in_byte; // Received byte + uint8_t devices_present; // Max number of devices supported + uint8_t masterlog_level; // Master log level used to override set log level + uint8_t seriallog_level; // Current copy of Settings.seriallog_level + uint8_t syslog_level; // Current copy of Settings.syslog_level + uint8_t module_type; // Current copy of Settings.module or user template type + uint8_t last_source; // Last command source + uint8_t shutters_present; // Number of actual define shutters + uint8_t prepped_loglevel; // Delayed log level message + +#ifndef SUPPORT_IF_STATEMENT + uint8_t backlog_index; // Command backlog index + uint8_t backlog_pointer; // Command backlog pointer + String backlog[MAX_BACKLOG]; // Command backlog buffer +#endif + + char version[16]; // Composed version string like 255.255.255.255 + char image_name[33]; // Code image and/or commit + char hostname[33]; // Composed Wifi hostname + char serial_in_buffer[INPUT_BUFFER_SIZE]; // Receive buffer + char mqtt_client[99]; // Composed MQTT Clientname + char mqtt_topic[TOPSZ]; // Composed MQTT topic + char mqtt_data[MESSZ]; // MQTT publish buffer and web page ajax buffer + char log_data[LOGSZ]; // Logging + char web_log[WEB_LOG_SIZE]; // Web log buffer +} TasmotaGlobal; + #ifdef SUPPORT_IF_STATEMENT #include LinkedList backlog; // Command backlog implemented with LinkedList #define BACKLOG_EMPTY (backlog.size() == 0) #else - uint8_t backlog_index = 0; // Command backlog index - uint8_t backlog_pointer = 0; // Command backlog pointer - String backlog[MAX_BACKLOG]; // Command backlog buffer - #define BACKLOG_EMPTY (backlog_pointer == backlog_index) + #define BACKLOG_EMPTY (TasmotaGlobal.backlog_pointer == TasmotaGlobal.backlog_index) #endif /*********************************************************************************************\ @@ -195,7 +189,14 @@ void setup(void) { #endif #endif - global_state.data = 0xF; // Init global state (wifi_down, mqtt_down) to solve possible network issues + memset(&TasmotaGlobal, 0, sizeof(TasmotaGlobal)); + TasmotaGlobal.baudrate = APP_BAUDRATE; + TasmotaGlobal.temperature_celsius = NAN; + TasmotaGlobal.blinks = 201; + TasmotaGlobal.wifi_state_flag = WIFI_RESTART; + TasmotaGlobal.tele_period = 9999; + TasmotaGlobal.active_device = 1; + TasmotaGlobal.global_state.data = 0xF; // Init global state (wifi_down, mqtt_down) to solve possible network issues RtcRebootLoad(); if (!RtcRebootValid()) { @@ -208,36 +209,33 @@ void setup(void) { #endif RtcRebootSave(); - Serial.begin(baudrate); + Serial.begin(TasmotaGlobal.baudrate); // Serial.setRxBufferSize(INPUT_BUFFER_SIZE); // Default is 256 chars - seriallog_level = LOG_LEVEL_INFO; // Allow specific serial messages until config loaded + TasmotaGlobal.seriallog_level = LOG_LEVEL_INFO; // Allow specific serial messages until config loaded - snprintf_P(my_version, sizeof(my_version), PSTR("%d.%d.%d"), VERSION >> 24 & 0xff, VERSION >> 16 & 0xff, VERSION >> 8 & 0xff); // Release version 6.3.0 + snprintf_P(TasmotaGlobal.version, sizeof(TasmotaGlobal.version), PSTR("%d.%d.%d"), VERSION >> 24 & 0xff, VERSION >> 16 & 0xff, VERSION >> 8 & 0xff); // Release version 6.3.0 if (VERSION & 0xff) { // Development or patched version 6.3.0.10 - snprintf_P(my_version, sizeof(my_version), PSTR("%s.%d"), my_version, VERSION & 0xff); + snprintf_P(TasmotaGlobal.version, sizeof(TasmotaGlobal.version), PSTR("%s.%d"), TasmotaGlobal.version, VERSION & 0xff); } // Thehackbox inserts "release" or "commit number" before compiling using sed -i -e 's/PSTR("(%s)")/PSTR("(85cff52-%s)")/g' tasmota.ino - snprintf_P(my_image, sizeof(my_image), PSTR("(%s)"), CODE_IMAGE_STR); // Results in (85cff52-tasmota) or (release-tasmota) + snprintf_P(TasmotaGlobal.image_name, sizeof(TasmotaGlobal.image_name), PSTR("(%s)"), CODE_IMAGE_STR); // Results in (85cff52-tasmota) or (release-tasmota) SettingsLoad(); SettingsDelta(); OsWatchInit(); - GetFeatures(); - if (1 == RtcReboot.fast_reboot_count) { // Allow setting override only when all is well UpdateQuickPowerCycle(true); XdrvCall(FUNC_SETTINGS_OVERRIDE); } -// mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START]; - seriallog_level = Settings.seriallog_level; - seriallog_timer = SERIALLOG_TIMER; - syslog_level = Settings.syslog_level; - stop_flash_rotate = Settings.flag.stop_flash_rotate; // SetOption12 - Switch between dynamic or fixed slot flash save location - save_data_counter = Settings.save_data; - ssleep = Settings.sleep; + TasmotaGlobal.seriallog_level = Settings.seriallog_level; + TasmotaGlobal.seriallog_timer = SERIALLOG_TIMER; + TasmotaGlobal.syslog_level = Settings.syslog_level; + TasmotaGlobal.stop_flash_rotate = Settings.flag.stop_flash_rotate; // SetOption12 - Switch between dynamic or fixed slot flash save location + TasmotaGlobal.save_data_counter = Settings.save_data; + TasmotaGlobal.sleep = Settings.sleep; #ifndef USE_EMULATION Settings.flag2.emulation = 0; #else @@ -249,6 +247,8 @@ void setup(void) { #endif #endif // USE_EMULATION +// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t*)&TasmotaGlobal, sizeof(TasmotaGlobal)); + if (Settings.param[P_BOOT_LOOP_OFFSET]) { // SetOption36 // Disable functionality as possible cause of fast restart within BOOT_LOOP_TIME seconds (Exception, WDT or restarts) if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET]) { // Restart twice @@ -276,13 +276,13 @@ void setup(void) { } } - Format(mqtt_client, SettingsText(SET_MQTT_CLIENT), sizeof(mqtt_client)); - Format(mqtt_topic, SettingsText(SET_MQTT_TOPIC), sizeof(mqtt_topic)); + Format(TasmotaGlobal.mqtt_client, SettingsText(SET_MQTT_CLIENT), sizeof(TasmotaGlobal.mqtt_client)); + Format(TasmotaGlobal.mqtt_topic, SettingsText(SET_MQTT_TOPIC), sizeof(TasmotaGlobal.mqtt_topic)); if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) { SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); - snprintf_P(my_hostname, sizeof(my_hostname)-1, SettingsText(SET_HOSTNAME), mqtt_topic, ESP_getChipId() & 0x1FFF); + snprintf_P(TasmotaGlobal.hostname, sizeof(TasmotaGlobal.hostname)-1, SettingsText(SET_HOSTNAME), TasmotaGlobal.mqtt_topic, ESP_getChipId() & 0x1FFF); } else { - snprintf_P(my_hostname, sizeof(my_hostname)-1, SettingsText(SET_HOSTNAME)); + snprintf_P(TasmotaGlobal.hostname, sizeof(TasmotaGlobal.hostname)-1, SettingsText(SET_HOSTNAME)); } GetEspHardwareType(); @@ -294,12 +294,12 @@ void setup(void) { SetPowerOnState(); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_PROJECT " %s %s " D_VERSION " %s%s-" ARDUINO_CORE_RELEASE), PROJECT, SettingsText(SET_DEVICENAME), my_version, my_image); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_PROJECT " %s %s " D_VERSION " %s%s-" ARDUINO_CORE_RELEASE), PROJECT, SettingsText(SET_DEVICENAME), TasmotaGlobal.version, TasmotaGlobal.image_name); #ifdef FIRMWARE_MINIMAL AddLog_P2(LOG_LEVEL_INFO, PSTR(D_WARNING_MINIMAL_VERSION)); #endif // FIRMWARE_MINIMAL - memcpy_P(log_data, VERSION_MARKER, 1); // Dummy for compiler saving VERSION_MARKER + memcpy_P(TasmotaGlobal.log_data, VERSION_MARKER, 1); // Dummy for compiler saving VERSION_MARKER RtcInit(); @@ -313,13 +313,13 @@ void setup(void) { if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">BS",3,0); #endif - rules_flag.system_init = 1; + TasmotaGlobal.rules_flag.system_init = 1; } void BacklogLoop(void) { - if (TimeReached(backlog_delay)) { - if (!BACKLOG_EMPTY && !backlog_mutex) { - backlog_mutex = true; + if (TimeReached(TasmotaGlobal.backlog_delay)) { + if (!BACKLOG_EMPTY && !TasmotaGlobal.backlog_mutex) { + TasmotaGlobal.backlog_mutex = true; bool nodelay = false; bool nodelay_detected = false; String cmd; @@ -327,17 +327,21 @@ void BacklogLoop(void) { #ifdef SUPPORT_IF_STATEMENT cmd = backlog.shift(); #else - cmd = backlog[backlog_pointer]; - backlog[backlog_pointer] = (const char*) nullptr; // Force deallocation of the String internal memory - backlog_pointer++; - if (backlog_pointer >= MAX_BACKLOG) { backlog_pointer = 0; } + cmd = TasmotaGlobal.backlog[TasmotaGlobal.backlog_pointer]; + TasmotaGlobal.backlog[TasmotaGlobal.backlog_pointer] = (const char*) nullptr; // Force deallocation of the String internal memory + TasmotaGlobal.backlog_pointer++; + if (TasmotaGlobal.backlog_pointer >= MAX_BACKLOG) { TasmotaGlobal.backlog_pointer = 0; } #endif nodelay_detected = !strncasecmp_P(cmd.c_str(), PSTR(D_CMND_NODELAY), strlen(D_CMND_NODELAY)); if (nodelay_detected) { nodelay = true; } } while (!BACKLOG_EMPTY && nodelay_detected); - if (!nodelay_detected) { ExecuteCommand((char*)cmd.c_str(), SRC_BACKLOG); } - if (nodelay) { backlog_delay = 0; } // Reset backlog_delay which has been set by ExecuteCommand (CommandHandler) - backlog_mutex = false; + if (!nodelay_detected) { + ExecuteCommand((char*)cmd.c_str(), SRC_BACKLOG); + } + if (nodelay) { + TasmotaGlobal.backlog_delay = 0; // Reset backlog_delay which has been set by ExecuteCommand (CommandHandler) + } + TasmotaGlobal.backlog_mutex = false; } } } @@ -368,6 +372,7 @@ void loop(void) { #endif // USE_DEVICE_GROUPS BacklogLoop(); + static uint32_t state_50msecond = 0; // State 50msecond timer if (TimeReached(state_50msecond)) { SetNextTimeInterval(state_50msecond, 50); #ifdef ROTARY_V1 @@ -376,18 +381,24 @@ void loop(void) { XdrvCall(FUNC_EVERY_50_MSECOND); XsnsCall(FUNC_EVERY_50_MSECOND); } + + static uint32_t state_100msecond = 0; // State 100msecond timer if (TimeReached(state_100msecond)) { SetNextTimeInterval(state_100msecond, 100); Every100mSeconds(); XdrvCall(FUNC_EVERY_100_MSECOND); XsnsCall(FUNC_EVERY_100_MSECOND); } + + static uint32_t state_250msecond = 0; // State 250msecond timer if (TimeReached(state_250msecond)) { SetNextTimeInterval(state_250msecond, 250); Every250mSeconds(); XdrvCall(FUNC_EVERY_250_MSECOND); XsnsCall(FUNC_EVERY_250_MSECOND); } + + static uint32_t state_second = 0; // State second timer if (TimeReached(state_second)) { SetNextTimeInterval(state_second, 1000); PerformEverySecond(); @@ -395,7 +406,7 @@ void loop(void) { XsnsCall(FUNC_EVERY_SECOND); } - if (!serial_local) { SerialInput(); } + if (!TasmotaGlobal.serial_local) { SerialInput(); } #ifdef USE_ARDUINO_OTA ArduinoOtaLoop(); @@ -405,21 +416,21 @@ void loop(void) { if (Settings.flag3.sleep_normal) { // SetOption60 - Enable normal sleep instead of dynamic sleep // yield(); // yield == delay(0), delay contains yield, auto yield in loop - SleepDelay(ssleep); // https://github.com/esp8266/Arduino/issues/2021 + SleepDelay(TasmotaGlobal.sleep); // https://github.com/esp8266/Arduino/issues/2021 } else { - if (my_activity < (uint32_t)ssleep) { - SleepDelay((uint32_t)ssleep - my_activity); // Provide time for background tasks like wifi + if (my_activity < (uint32_t)TasmotaGlobal.sleep) { + SleepDelay((uint32_t)TasmotaGlobal.sleep - my_activity); // Provide time for background tasks like wifi } else { - if (global_state.network_down) { + if (TasmotaGlobal.global_state.network_down) { SleepDelay(my_activity /2); // If wifi down and my_activity > setoption36 then force loop delay to 1/3 of my_activity period } } } if (!my_activity) { my_activity++; } // We cannot divide by 0 - uint32_t loop_delay = ssleep; + uint32_t loop_delay = TasmotaGlobal.sleep; if (!loop_delay) { loop_delay++; } // We cannot divide by 0 uint32_t loops_per_second = 1000 / loop_delay; // We need to keep track of this many loops per second uint32_t this_cycle_ratio = 100 * my_activity / loop_delay; - loop_load_avg = loop_load_avg - (loop_load_avg / loops_per_second) + (this_cycle_ratio / loops_per_second); // Take away one loop average away and add the new one + TasmotaGlobal.loop_load_avg = TasmotaGlobal.loop_load_avg - (TasmotaGlobal.loop_load_avg / loops_per_second) + (this_cycle_ratio / loops_per_second); // Take away one loop average away and add the new one } diff --git a/tasmota/tasmota_configurations.h b/tasmota/tasmota_configurations.h index ed425a645..47caeb9cd 100644 --- a/tasmota/tasmota_configurations.h +++ b/tasmota/tasmota_configurations.h @@ -133,6 +133,9 @@ //#define USE_EZOHUM // [I2cDriver55] Enable support for EZO's HUM sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) //#define USE_EZOEC // [I2cDriver55] Enable support for EZO's EC sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) //#define USE_EZOCO2 // [I2cDriver55] Enable support for EZO's CO2 sensor (+0k2 code) - Shared EZO code required for any EZO device (+1k2 code) +//#define USE_EZOO2 // [I2cDriver55] Enable support for EZO's O2 sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) +//#define USE_EZOPRS // [I2cDriver55] Enable support for EZO's PRS sensor (+0k7 code) - Shared EZO code required for any EZO device (+1k2 code) +//#define USE_EZOFLO // [I2cDriver55] Enable support for EZO's FLO sensor (+0k4 code) - Shared EZO code required for any EZO device (+1k2 code) #define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code) #define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code) @@ -443,12 +446,14 @@ #undef USE_HOME_ASSISTANT // Disable Home Assistant // -- MQTT - TLS - AWS IoT ------------------------ -#define USE_MQTT_TLS // Use TLS for MQTT connection (+34.5k code, +7.0k mem and +4.8k additional during connection handshake) - #define USE_MQTT_TLS_CA_CERT // Force full CA validation instead of fingerprints, slower, but simpler to use. (+2.2k code, +1.9k mem during connection handshake) - // This includes the LetsEncrypt CA in tasmota_ca.ino for verifying server certificates - #define USE_MQTT_TLS_FORCE_EC_CIPHER // Force Elliptic Curve cipher (higher security) required by some servers (automatically enabled with USE_MQTT_AWS_IOT) (+11.4k code, +0.4k mem) - #define USE_MQTT_AWS_IOT_LIGHT // Enable MQTT for AWS IoT in light mode, with user/password instead of private certificate -#define USE_TLS // flag indicates we need to include TLS code +#ifdef USE_ZBBRIDGE_TLS // Enable TLS for ZbBridge + #define USE_MQTT_TLS // Use TLS for MQTT connection (+34.5k code, +7.0k mem and +4.8k additional during connection handshake) + #define USE_MQTT_TLS_CA_CERT // Force full CA validation instead of fingerprints, slower, but simpler to use. (+2.2k code, +1.9k mem during connection handshake) + // This includes the LetsEncrypt CA in tasmota_ca.ino for verifying server certificates + #define USE_MQTT_TLS_FORCE_EC_CIPHER // Force Elliptic Curve cipher (higher security) required by some servers (automatically enabled with USE_MQTT_AWS_IOT) (+11.4k code, +0.4k mem) + #define USE_MQTT_AWS_IOT_LIGHT // Enable MQTT for AWS IoT in light mode, with user/password instead of private certificate + #define USE_TLS // flag indicates we need to include TLS code +#endif // USE_ZBBRIDGE_TLS #undef USE_KNX // Disable KNX IP Protocol Support //#undef USE_WEBSERVER // Disable Webserver diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 689b4bdd6..3a9cf89aa 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -840,7 +840,7 @@ void ShowWebSource(uint32_t source) void ExecuteWebCommand(char* svalue, uint32_t source) { ShowWebSource(source); - last_source = source; + TasmotaGlobal.last_source = source; ExecuteCommand(svalue, SRC_IGNORE); } @@ -875,7 +875,11 @@ const WebServerDispatch_t WebServerDispatch[] PROGMEM = { }; void WebServer_on(const char * prefix, void (*func)(void), uint8_t method = HTTP_ANY) { +#ifdef ESP8266 Webserver->on((const __FlashStringHelper *) prefix, (HTTPMethod) method, func); +#else + Webserver->on(prefix, (HTTPMethod) method, func); +#endif } void StartWebserver(int type, IPAddress ipweb) @@ -921,7 +925,7 @@ void StartWebserver(int type, IPAddress ipweb) AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s"), NetworkHostname(), (Mdns.begun) ? ".local" : "", ipweb.toString().c_str()); #endif // LWIP_IPV6 = 1 - rules_flag.http_init = 1; + TasmotaGlobal.rules_flag.http_init = 1; } if (type) { Web.state = type; } } @@ -938,7 +942,7 @@ void StopWebserver(void) void WifiManagerBegin(bool reset_only) { // setup AP - if (!global_state.wifi_down) { + if (!TasmotaGlobal.global_state.wifi_down) { // WiFi.mode(WIFI_AP_STA); WifiSetMode(WIFI_AP_STA); AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION)); @@ -956,7 +960,7 @@ void WifiManagerBegin(bool reset_only) if ((channel < 1) || (channel > 13)) { channel = 1; } // bool softAP(const char* ssid, const char* passphrase = NULL, int channel = 1, int ssid_hidden = 0, int max_connection = 4); - WiFi.softAP(my_hostname, WIFI_AP_PASSPHRASE, channel, 0, 1); + WiFi.softAP(TasmotaGlobal.hostname, WIFI_AP_PASSPHRASE, channel, 0, 1); delay(500); // Without delay I've seen the IP address blank /* Setup the DNS server redirecting all the domains to the apIP */ DnsServer->setErrorReplyCode(DNSReplyCode::NoError); @@ -1041,7 +1045,7 @@ void _WSContentSend(const String& content) // Low level sendContent for a #ifdef USE_DEBUG_DRIVER ShowFreeMem(PSTR("WSContentSend")); #endif - DEBUG_CORE_LOG(PSTR("WEB: Chunk size %d/%d"), len, sizeof(mqtt_data)); + DEBUG_CORE_LOG(PSTR("WEB: Chunk size %d/%d"), len, sizeof(TasmotaGlobal.mqtt_data)); } void WSContentFlush(void) @@ -1054,24 +1058,24 @@ void WSContentFlush(void) void _WSContentSendBuffer(void) { - int len = strlen(mqtt_data); + int len = strlen(TasmotaGlobal.mqtt_data); if (0 == len) { // No content return; } - else if (len == sizeof(mqtt_data)) { + else if (len == sizeof(TasmotaGlobal.mqtt_data)) { AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: Content too large")); } else if (len < CHUNKED_BUFFER_SIZE) { // Append chunk buffer with small content - Web.chunk_buffer += mqtt_data; + Web.chunk_buffer += TasmotaGlobal.mqtt_data; len = Web.chunk_buffer.length(); } if (len >= CHUNKED_BUFFER_SIZE) { // Either content or chunk buffer is oversize WSContentFlush(); // Send chunk buffer before possible content oversize } - if (strlen(mqtt_data) >= CHUNKED_BUFFER_SIZE) { // Content is oversize - _WSContentSend(mqtt_data); // Send content + if (strlen(TasmotaGlobal.mqtt_data) >= CHUNKED_BUFFER_SIZE) { // Content is oversize + _WSContentSend(TasmotaGlobal.mqtt_data); // Send content } } @@ -1080,13 +1084,13 @@ void WSContentSend_P(const char* formatP, ...) // Content send snprintf_P ch // This uses char strings. Be aware of sending %% if % is needed va_list arg; va_start(arg, formatP); - int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), formatP, arg); + int len = vsnprintf_P(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), formatP, arg); va_end(arg); #ifdef DEBUG_TASMOTA_CORE - if (len > (sizeof(mqtt_data) -1)) { - mqtt_data[33] = '\0'; - DEBUG_CORE_LOG(PSTR("ERROR: WSContentSend_P size %d > mqtt_data size %d. Start of data [%s...]"), len, sizeof(mqtt_data), mqtt_data); + if (len > (sizeof(TasmotaGlobal.mqtt_data) -1)) { + TasmotaGlobal.mqtt_data[33] = '\0'; + DEBUG_CORE_LOG(PSTR("ERROR: WSContentSend_P size %d > mqtt_data size %d. Start of data [%s...]"), len, sizeof(TasmotaGlobal.mqtt_data), TasmotaGlobal.mqtt_data); } #endif @@ -1098,20 +1102,20 @@ void WSContentSend_PD(const char* formatP, ...) // Content send snprintf_P ch // This uses char strings. Be aware of sending %% if % is needed va_list arg; va_start(arg, formatP); - int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), formatP, arg); + int len = vsnprintf_P(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), formatP, arg); va_end(arg); #ifdef DEBUG_TASMOTA_CORE - if (len > (sizeof(mqtt_data) -1)) { - mqtt_data[33] = '\0'; - DEBUG_CORE_LOG(PSTR("ERROR: WSContentSend_PD size %d > mqtt_data size %d. Start of data [%s...]"), len, sizeof(mqtt_data), mqtt_data); + if (len > (sizeof(TasmotaGlobal.mqtt_data) -1)) { + TasmotaGlobal.mqtt_data[33] = '\0'; + DEBUG_CORE_LOG(PSTR("ERROR: WSContentSend_PD size %d > mqtt_data size %d. Start of data [%s...]"), len, sizeof(TasmotaGlobal.mqtt_data), TasmotaGlobal.mqtt_data); } #endif if (D_DECIMAL_SEPARATOR[0] != '.') { for (uint32_t i = 0; i < len; i++) { - if ('.' == mqtt_data[i]) { - mqtt_data[i] = D_DECIMAL_SEPARATOR[0]; + if ('.' == TasmotaGlobal.mqtt_data[i]) { + TasmotaGlobal.mqtt_data[i] = D_DECIMAL_SEPARATOR[0]; } } } @@ -1162,13 +1166,13 @@ void WSContentSendStyle_P(const char* formatP, ...) // This uses char strings. Be aware of sending %% if % is needed va_list arg; va_start(arg, formatP); - int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), formatP, arg); + int len = vsnprintf_P(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), formatP, arg); va_end(arg); #ifdef DEBUG_TASMOTA_CORE - if (len > (sizeof(mqtt_data) -1)) { - mqtt_data[33] = '\0'; - DEBUG_CORE_LOG(PSTR("ERROR: WSContentSendStyle_P size %d > mqtt_data size %d. Start of data [%s...]"), len, sizeof(mqtt_data), mqtt_data); + if (len > (sizeof(TasmotaGlobal.mqtt_data) -1)) { + TasmotaGlobal.mqtt_data[33] = '\0'; + DEBUG_CORE_LOG(PSTR("ERROR: WSContentSendStyle_P size %d > mqtt_data size %d. Start of data [%s...]"), len, sizeof(TasmotaGlobal.mqtt_data), TasmotaGlobal.mqtt_data); } #endif @@ -1248,7 +1252,7 @@ void WSContentStop(void) WSContentSend_P(HTTP_COUNTER); } } - WSContentSend_P(HTTP_END, my_version); + WSContentSend_P(HTTP_END, TasmotaGlobal.version); WSContentEnd(); } @@ -1282,7 +1286,7 @@ void WebRestart(uint32_t type) WSContentStop(); ShowWebSource(SRC_WEBGUI); - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } /*********************************************************************************************/ @@ -1360,12 +1364,12 @@ void HandleRoot(void) WSContentSendStyle(); WSContentSend_P(PSTR("
")); - if (devices_present) { + if (TasmotaGlobal.devices_present) { #ifdef USE_LIGHT - if (light_type) { - uint8_t light_subtype = light_type &7; + if (TasmotaGlobal.light_type) { + uint8_t light_subtype = TasmotaGlobal.light_type &7; if (!Settings.flag3.pwm_multi_channels) { // SetOption68 0 - Enable multi-channels PWM instead of Color PWM - bool split_white = ((LST_RGBW <= light_subtype) && (devices_present > 1)); // Only on RGBW or RGBCW and SetOption37 128 + bool split_white = ((LST_RGBW <= light_subtype) && (TasmotaGlobal.devices_present > 1)); // Only on RGBW or RGBCW and SetOption37 128 if ((LST_COLDWARM == light_subtype) || ((LST_RGBCW == light_subtype) && !split_white)) { WebSliderColdWarm(); @@ -1439,7 +1443,7 @@ void HandleRoot(void) #endif // USE_LIGHT #ifdef USE_SHUTTER if (Settings.flag3.shutter_mode) { // SetOption80 - Enable shutter support - for (uint32_t i = 0; i < shutters_present; i++) { + for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) { WSContentSend_P(HTTP_MSG_SLIDER_SHUTTER, Settings.shutter_position[i], i+1); } } @@ -1459,21 +1463,21 @@ void HandleRoot(void) } } else { #endif // USE_SONOFF_IFAN - for (uint32_t idx = 1; idx <= devices_present; idx++) { + for (uint32_t idx = 1; idx <= TasmotaGlobal.devices_present; idx++) { bool set_button = ((idx <= MAX_BUTTON_TEXT) && strlen(SettingsText(SET_BUTTON1 + idx -1))); #ifdef USE_SHUTTER int32_t ShutterWebButton; if (ShutterWebButton = IsShutterWebButton(idx)) { - WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, + WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / TasmotaGlobal.devices_present, idx, (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : ((Settings.shutter_options[abs(ShutterWebButton)-1] & 2) /* is locked */ ? "-" : ((Settings.shutter_options[abs(ShutterWebButton)-1] & 8) /* invert web buttons */ ? ((ShutterWebButton>0) ? "▼" : "▲") : ((ShutterWebButton>0) ? "▲" : "▼"))), ""); continue; } #endif // USE_SHUTTER snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx); - WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, - (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : (devices_present < 5) ? D_BUTTON_TOGGLE : "", - (set_button) ? "" : (devices_present > 1) ? stemp : ""); + WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / TasmotaGlobal.devices_present, idx, + (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : (TasmotaGlobal.devices_present < 5) ? D_BUTTON_TOGGLE : "", + (set_button) ? "" : (TasmotaGlobal.devices_present > 1) ? stemp : ""); } #ifdef USE_SONOFF_IFAN } @@ -1487,13 +1491,13 @@ void HandleRoot(void) WSContentSend_P(HTTP_TABLE100); WSContentSend_P(PSTR("
")); snprintf_P(stemp, sizeof(stemp), PSTR("" D_JSON_IRHVAC_MODE "")); - WSContentSend_P(HTTP_DEVICE_CONTROL, 26, devices_present + 1, - (strlen(SettingsText(SET_BUTTON1 + devices_present))) ? SettingsText(SET_BUTTON1 + devices_present) : stemp, ""); + WSContentSend_P(HTTP_DEVICE_CONTROL, 26, TasmotaGlobal.devices_present + 1, + (strlen(SettingsText(SET_BUTTON1 + TasmotaGlobal.devices_present))) ? SettingsText(SET_BUTTON1 + TasmotaGlobal.devices_present) : stemp, ""); WSContentSend_P(PSTR("")); modeset = 1; } if (IsTuyaFanCtrl()) { - uint8_t device = devices_present + modeset; + uint8_t device = TasmotaGlobal.devices_present + modeset; WSContentSend_P(HTTP_TABLE100); WSContentSend_P(PSTR("
")); for (uint32_t i = device + 1; i <= (TuyaFanSpeeds() + device) + 1; i++) { @@ -1506,7 +1510,7 @@ void HandleRoot(void) } #endif // USE_TUYA_MCU #ifdef USE_SONOFF_RF - if (SONOFF_BRIDGE == my_module_type) { + if (SONOFF_BRIDGE == TasmotaGlobal.module_type) { WSContentSend_P(HTTP_TABLE100); WSContentSend_P(PSTR("")); uint32_t idx = 0; @@ -1578,10 +1582,10 @@ bool HandleRootStatusRefresh(void) #ifdef USE_TUYA_MCU if (IsModuleTuya()) { uint8_t FuncIdx = 0; - if (device <= devices_present) { + if (device <= TasmotaGlobal.devices_present) { ExecuteCommandPower(device, POWER_TOGGLE, SRC_IGNORE); } else { - if (AsModuleTuyaMS() && device == devices_present + 1) { + if (AsModuleTuyaMS() && device == TasmotaGlobal.devices_present + 1) { uint8_t dpId = TuyaGetDpId(TUYA_MCU_FUNC_MODESET); snprintf_P(svalue, sizeof(svalue), PSTR("Tuyasend4 %d,%d"), dpId, !TuyaModeSet()); ExecuteCommand(svalue, SRC_WEBGUI); @@ -1593,9 +1597,9 @@ bool HandleRootStatusRefresh(void) dpId = TuyaGetDpId(TUYA_MCU_FUNC_FAN3 + i); } } - if ((AsModuleTuyaMS() && device != devices_present + 1) || !AsModuleTuyaMS()) { + if ((AsModuleTuyaMS() && device != TasmotaGlobal.devices_present + 1) || !AsModuleTuyaMS()) { if (AsModuleTuyaMS()) {FuncIdx = 1;} - snprintf_P(svalue, sizeof(svalue), PSTR("Tuyasend2 %d,%d"), dpId, (device - (devices_present + FuncIdx) - 1)); + snprintf_P(svalue, sizeof(svalue), PSTR("Tuyasend2 %d,%d"), dpId, (device - (TasmotaGlobal.devices_present + FuncIdx) - 1)); ExecuteCommand(svalue, SRC_WEBGUI); } } @@ -1632,7 +1636,7 @@ bool HandleRootStatusRefresh(void) ExecuteWebCommand(svalue, SRC_WEBGUI); } uint32_t light_device = LightDevice(); // Channel number offset - uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); + uint32_t pwm_channels = (TasmotaGlobal.light_type & 7) > LST_MAX ? LST_MAX : (TasmotaGlobal.light_type & 7); for (uint32_t j = 0; j < pwm_channels; j++) { snprintf_P(webindex, sizeof(webindex), PSTR("e%d"), j +1); WebGetArg(webindex, tmp, sizeof(tmp)); // 0 - 100 percent @@ -1658,7 +1662,7 @@ bool HandleRootStatusRefresh(void) } #endif // USE_LIGHT #ifdef USE_SHUTTER - for (uint32_t j = 1; j <= shutters_present; j++) { + for (uint32_t j = 1; j <= TasmotaGlobal.shutters_present; j++) { snprintf_P(webindex, sizeof(webindex), PSTR("u%d"), j); WebGetArg(webindex, tmp, sizeof(tmp)); // 0 - 100 percent if (strlen(tmp)) { @@ -1681,20 +1685,20 @@ bool HandleRootStatusRefresh(void) WSContentSend_P(PSTR("")); - if (devices_present) { + if (TasmotaGlobal.devices_present) { WSContentSend_P(PSTR("{t}")); - uint32_t fsize = (devices_present < 5) ? 70 - (devices_present * 8) : 32; + uint32_t fsize = (TasmotaGlobal.devices_present < 5) ? 70 - (TasmotaGlobal.devices_present * 8) : 32; #ifdef USE_SONOFF_IFAN if (IsModuleIfan()) { - WSContentSend_P(HTTP_DEVICE_STATE, 36, (bitRead(power, 0)) ? "bold" : "normal", 54, GetStateText(bitRead(power, 0))); + WSContentSend_P(HTTP_DEVICE_STATE, 36, (bitRead(TasmotaGlobal.power, 0)) ? "bold" : "normal", 54, GetStateText(bitRead(TasmotaGlobal.power, 0))); uint32_t fanspeed = GetFanspeed(); snprintf_P(svalue, sizeof(svalue), PSTR("%d"), fanspeed); WSContentSend_P(HTTP_DEVICE_STATE, 64, (fanspeed) ? "bold" : "normal", 54, (fanspeed) ? svalue : GetStateText(0)); } else { #endif // USE_SONOFF_IFAN - for (uint32_t idx = 1; idx <= devices_present; idx++) { - snprintf_P(svalue, sizeof(svalue), PSTR("%d"), bitRead(power, idx -1)); - WSContentSend_P(HTTP_DEVICE_STATE, 100 / devices_present, (bitRead(power, idx -1)) ? "bold" : "normal", fsize, (devices_present < 5) ? GetStateText(bitRead(power, idx -1)) : svalue); + for (uint32_t idx = 1; idx <= TasmotaGlobal.devices_present; idx++) { + snprintf_P(svalue, sizeof(svalue), PSTR("%d"), bitRead(TasmotaGlobal.power, idx -1)); + WSContentSend_P(HTTP_DEVICE_STATE, 100 / TasmotaGlobal.devices_present, (bitRead(TasmotaGlobal.power, idx -1)) ? "bold" : "normal", fsize, (TasmotaGlobal.devices_present < 5) ? GetStateText(bitRead(TasmotaGlobal.power, idx -1)) : svalue); } #ifdef USE_SONOFF_IFAN } @@ -1997,7 +2001,7 @@ void HandleModuleConfiguration(void) for (uint32_t i = 0; i < ARRAY_SIZE(cmodule.io); i++) { if (ValidGPIO(i, cmodule.io[i])) { - WSContentSend_P(PSTR("sk(%d,%d);"), my_module.io[i], i); // g0 - g17 + WSContentSend_P(PSTR("sk(%d,%d);"), TasmotaGlobal.my_module.io[i], i); // g0 - g17 } } @@ -2016,7 +2020,7 @@ void HandleModuleConfiguration(void) if (ValidGPIO(i, cmodule.io[i])) { snprintf_P(stemp, 3, PINS_WEMOS +i*2); WSContentSend_P(PSTR("%s " D_GPIO "%d"), - (WEMOS==my_module_type)?stemp:"", i, i, i); + (WEMOS==TasmotaGlobal.module_type)?stemp:"", i, i, i); WSContentSend_P(PSTR(""), i); } } @@ -2281,13 +2285,13 @@ void HandleOtherConfiguration(void) WSContentSendStyle(); TemplateJson(); - char stemp[strlen(mqtt_data) +1]; - strlcpy(stemp, mqtt_data, sizeof(stemp)); // Get JSON template + char stemp[strlen(TasmotaGlobal.mqtt_data) +1]; + strlcpy(stemp, TasmotaGlobal.mqtt_data, sizeof(stemp)); // Get JSON template WSContentSend_P(HTTP_FORM_OTHER, stemp, (USER_MODULE == Settings.module) ? " checked disabled" : "", (Settings.flag.mqtt_enabled) ? " checked" : "", // SetOption3 - Enable MQTT SettingsText(SET_FRIENDLYNAME1), SettingsText(SET_DEVICENAME)); - uint32_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; + uint32_t maxfn = (TasmotaGlobal.devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!TasmotaGlobal.devices_present) ? 1 : TasmotaGlobal.devices_present; #ifdef USE_SONOFF_IFAN if (IsModuleIfan()) { maxfn = 1; } #endif // USE_SONOFF_IFAN @@ -2382,10 +2386,10 @@ void HandleBackupConfiguration(void) char attachment[TOPSZ]; // char friendlyname[TOPSZ]; -// snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=Config_%s_%s.dmp"), NoAlNumToUnderscore(friendlyname, SettingsText(SET_FRIENDLYNAME1)), my_version); +// snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=Config_%s_%s.dmp"), NoAlNumToUnderscore(friendlyname, SettingsText(SET_FRIENDLYNAME1)), TasmotaGlobal.version); - char hostname[sizeof(my_hostname)]; - snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=Config_%s_%s.dmp"), NoAlNumToUnderscore(hostname, my_hostname), my_version); + char hostname[sizeof(TasmotaGlobal.hostname)]; + snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=Config_%s_%s.dmp"), NoAlNumToUnderscore(hostname, TasmotaGlobal.hostname), TasmotaGlobal.version); Webserver->sendHeader(F("Content-Disposition"), attachment); @@ -2467,7 +2471,7 @@ void HandleInformation(void) // }2 = WSContentSend_P(HTTP_SCRIPT_INFO_BEGIN); WSContentSend_P(PSTR("" - "" // name + "" // name "" // sbatt (Battery Indicator) "
")); - WSContentSend_P(PSTR(D_PROGRAM_VERSION "}2%s%s"), my_version, my_image); + WSContentSend_P(PSTR(D_PROGRAM_VERSION "}2%s%s"), TasmotaGlobal.version, TasmotaGlobal.image_name); WSContentSend_P(PSTR("}1" D_BUILD_DATE_AND_TIME "}2%s"), GetBuildDateAndTime().c_str()); WSContentSend_P(PSTR("}1" D_CORE_AND_SDK_VERSION "}2" ARDUINO_CORE_RELEASE "/%s"), ESP.getSdkVersion()); WSContentSend_P(PSTR("}1" D_UPTIME "}2%s"), GetUptime().c_str()); @@ -2478,7 +2482,7 @@ void HandleInformation(void) #endif WSContentSend_P(PSTR("}1" D_BOOT_COUNT "}2%d"), Settings.bootcount); WSContentSend_P(PSTR("}1" D_RESTART_REASON "}2%s"), GetResetReason().c_str()); - uint32_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : devices_present; + uint32_t maxfn = (TasmotaGlobal.devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : TasmotaGlobal.devices_present; #ifdef USE_SONOFF_IFAN if (IsModuleIfan()) { maxfn = 1; } #endif // USE_SONOFF_IFAN @@ -2499,7 +2503,7 @@ void HandleInformation(void) if (Settings.flag4.network_wifi) { int32_t rssi = WiFi.RSSI(); WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm)"), Settings.sta_active +1, HtmlEscape(SettingsText(SET_STASSID1 + Settings.sta_active)).c_str(), WifiGetRssiAsQuality(rssi), rssi); - WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), my_hostname, (Mdns.begun) ? ".local" : ""); + WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), TasmotaGlobal.hostname, (Mdns.begun) ? ".local" : ""); #if LWIP_IPV6 String ipv6_addr = WifiGetIPv6(); if (ipv6_addr != "") { @@ -2512,7 +2516,7 @@ void HandleInformation(void) WSContentSend_P(PSTR("}1
}2
")); } } - if (!global_state.network_down) { + if (!TasmotaGlobal.global_state.network_down) { WSContentSend_P(PSTR("}1" D_GATEWAY "}2%s"), IPAddress(Settings.ip_address[1]).toString().c_str()); WSContentSend_P(PSTR("}1" D_SUBNET_MASK "}2%s"), IPAddress(Settings.ip_address[2]).toString().c_str()); WSContentSend_P(PSTR("}1" D_DNS_SERVER "}2%s"), IPAddress(Settings.ip_address[3]).toString().c_str()); @@ -2531,7 +2535,7 @@ void HandleInformation(void) WSContentSend_P(PSTR("}1" D_MQTT_TLS_ENABLE "}2%s"), Settings.flag4.mqtt_tls ? PSTR(D_ENABLED) : PSTR(D_DISABLED)); #endif // USE_MQTT_TLS WSContentSend_P(PSTR("}1" D_MQTT_USER "}2%s"), SettingsText(SET_MQTT_USER)); - WSContentSend_P(PSTR("}1" D_MQTT_CLIENT "}2%s"), mqtt_client); + WSContentSend_P(PSTR("}1" D_MQTT_CLIENT "}2%s"), TasmotaGlobal.mqtt_client); WSContentSend_P(PSTR("}1" D_MQTT_TOPIC "}2%s"), SettingsText(SET_MQTT_TOPIC)); uint32_t real_index = SET_MQTT_GRP_TOPIC; for (uint32_t i = 0; i < MAX_GROUP_TOPICS; i++) { @@ -2540,7 +2544,7 @@ void HandleInformation(void) WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC " %d}2%s"), 1 +i, GetGroupTopic_P(stopic, "", real_index +i)); } } - WSContentSend_P(PSTR("}1" D_MQTT_FULL_TOPIC "}2%s"), GetTopic_P(stopic, CMND, mqtt_topic, "")); + WSContentSend_P(PSTR("}1" D_MQTT_FULL_TOPIC "}2%s"), GetTopic_P(stopic, CMND, TasmotaGlobal.mqtt_topic, "")); WSContentSend_P(PSTR("}1" D_MQTT " " D_FALLBACK_TOPIC "}2%s"), GetFallbackTopic_P(stopic, "")); WSContentSend_P(PSTR("}1" D_MQTT_NO_RETAIN "}2%s"), Settings.flag4.mqtt_no_retain ? PSTR(D_ENABLED) : PSTR(D_DISABLED)); } else { @@ -2662,7 +2666,7 @@ void HandleUploadDone(void) char error[100]; WifiConfigCounter(); - restart_flag = 0; + TasmotaGlobal.restart_flag = 0; MqttRetryCounter(0); #ifdef USE_COUNTER CounterInterruptDisable(false); @@ -2694,17 +2698,17 @@ void HandleUploadDone(void) } WSContentSend_P(error); DEBUG_CORE_LOG(PSTR("UPL: %s"), error); - stop_flash_rotate = Settings.flag.stop_flash_rotate; // SetOption12 - Switch between dynamic or fixed slot flash save location + TasmotaGlobal.stop_flash_rotate = Settings.flag.stop_flash_rotate; // SetOption12 - Switch between dynamic or fixed slot flash save location } else { WSContentSend_P(PSTR("%06x'>" D_SUCCESSFUL "
"), WebColor(COL_TEXT_SUCCESS)); - restart_flag = 2; // Always restart to re-enable disabled features during update + TasmotaGlobal.restart_flag = 2; // Always restart to re-enable disabled features during update #ifdef USE_TASMOTA_CLIENT if (TasmotaClient_GetFlagFlashing()) { WSContentSend_P(PSTR("
" D_TRANSFER_STARTED " ...
")); - restart_flag = 0; // Hold restart as code still needs to be transferred to Atmega + TasmotaGlobal.restart_flag = 0; // Hold restart as code still needs to be transferred to Atmega } #endif // USE_TASMOTA_CLIENT - if (restart_flag) { + if (TasmotaGlobal.restart_flag) { WSContentSend_P(HTTP_MSG_RSTRT); ShowWebSource(SRC_WEBGUI); } @@ -2724,7 +2728,7 @@ void HandleUploadDone(void) void HandleUploadLoop(void) { // Based on ESP8266HTTPUpdateServer.cpp uses ESP8266WebServer Parsing.cpp and Cores Updater.cpp (Update) - bool _serialoutput = (LOG_LEVEL_DEBUG <= seriallog_level); + bool _serialoutput = (LOG_LEVEL_DEBUG <= TasmotaGlobal.seriallog_level); if (HTTP_USER == Web.state) { return; } if (Web.upload_error) { @@ -2736,7 +2740,7 @@ void HandleUploadLoop(void) // ***** Step1: Start upload file if (UPLOAD_FILE_START == upload.status) { - restart_flag = 60; + TasmotaGlobal.restart_flag = 60; if (0 == upload.filename.c_str()[0]) { Web.upload_error = 1; // No file selected return; @@ -2786,7 +2790,7 @@ void HandleUploadLoop(void) else { #if defined(USE_ZIGBEE) && defined(USE_ZIGBEE_EZSP) #ifdef ESP8266 - if ((SONOFF_ZB_BRIDGE == my_module_type) && (upload.buf[0] == 0xEB)) { // Check if this is a Zigbee bridge FW file + if ((SONOFF_ZB_BRIDGE == TasmotaGlobal.module_type) && (upload.buf[0] == 0xEB)) { // Check if this is a Zigbee bridge FW file #else // ESP32 if (PinUsed(GPIO_ZIGBEE_RX) && PinUsed(GPIO_ZIGBEE_TX) && (upload.buf[0] == 0xEB)) { // Check if this is a Zigbee bridge FW file #endif // ESP8266 or ESP32 @@ -2798,7 +2802,7 @@ void HandleUploadLoop(void) } else #endif // USE_ZIGBEE and USE_ZIGBEE_EZSP #ifdef USE_RF_FLASH - if ((SONOFF_BRIDGE == my_module_type) && (upload.buf[0] == ':')) { // Check if this is a RF bridge FW file + if ((SONOFF_BRIDGE == TasmotaGlobal.module_type) && (upload.buf[0] == ':')) { // Check if this is a RF bridge FW file Update.end(); // End esp8266 update session Web.upload_file_type = UPL_EFM8BB1; @@ -2986,7 +2990,7 @@ void HandleUploadLoop(void) // ***** Step4: Abort upload file else if (UPLOAD_FILE_ABORTED == upload.status) { - restart_flag = 0; + TasmotaGlobal.restart_flag = 0; MqttRetryCounter(0); #ifdef USE_COUNTER CounterInterruptDisable(false); @@ -3029,11 +3033,11 @@ void HandleHttpCommand(void) } WSContentBegin(200, CT_JSON); - uint32_t curridx = web_log_index; + uint32_t curridx = TasmotaGlobal.web_log_index; String svalue = Webserver->arg("cmnd"); if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) { ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCOMMAND); - if (web_log_index != curridx) { + if (TasmotaGlobal.web_log_index != curridx) { uint32_t counter = curridx; WSContentSend_P(PSTR("{")); bool cflg = false; @@ -3046,7 +3050,7 @@ void HandleHttpCommand(void) char* JSON = (char*)memchr(tmp, '{', len); if (JSON) { // Is it a JSON message (and not only [15:26:08 MQT: stat/wemos5/POWER = O]) size_t JSONlen = len - (JSON - tmp); - if (JSONlen > sizeof(mqtt_data)) { JSONlen = sizeof(mqtt_data); } + if (JSONlen > sizeof(TasmotaGlobal.mqtt_data)) { JSONlen = sizeof(TasmotaGlobal.mqtt_data); } char stemp[JSONlen]; strlcpy(stemp, JSON +1, JSONlen -2); WSContentSend_P(PSTR("%s%s"), (cflg) ? "," : "", stemp); @@ -3056,7 +3060,7 @@ void HandleHttpCommand(void) counter++; counter &= 0xFF; if (!counter) counter++; // Skip 0 as it is not allowed - } while (counter != web_log_index); + } while (counter != TasmotaGlobal.web_log_index); WSContentSend_P(PSTR("}")); } else { WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_ENABLE_WEBLOG_FOR_RESPONSE "\"}")); @@ -3104,14 +3108,14 @@ void HandleConsoleRefresh(void) if (strlen(stmp)) { counter = atoi(stmp); } WSContentBegin(200, CT_PLAIN); - WSContentSend_P(PSTR("%d}1%d}1"), web_log_index, Web.reset_web_log_flag); + WSContentSend_P(PSTR("%d}1%d}1"), TasmotaGlobal.web_log_index, Web.reset_web_log_flag); if (!Web.reset_web_log_flag) { counter = 0; Web.reset_web_log_flag = true; } - if (counter != web_log_index) { + if (counter != TasmotaGlobal.web_log_index) { if (!counter) { - counter = web_log_index; + counter = TasmotaGlobal.web_log_index; cflg = false; } do { @@ -3119,7 +3123,7 @@ void HandleConsoleRefresh(void) size_t len; GetLog(counter, &tmp, &len); if (len) { - if (len > sizeof(mqtt_data) -2) { len = sizeof(mqtt_data); } + if (len > sizeof(TasmotaGlobal.mqtt_data) -2) { len = sizeof(TasmotaGlobal.mqtt_data); } char stemp[len +1]; strlcpy(stemp, tmp, len); WSContentSend_P(PSTR("%s%s"), (cflg) ? "\n" : "", stemp); @@ -3128,7 +3132,7 @@ void HandleConsoleRefresh(void) counter++; counter &= 0xFF; if (!counter) { counter++; } // Skip log index 0 as it is not allowed - } while (counter != web_log_index); + } while (counter != TasmotaGlobal.web_log_index); } WSContentSend_P(PSTR("}1")); WSContentEnd(); @@ -3264,11 +3268,11 @@ int WebSend(char *buffer) while (text != '\0') { text = *read++; if (text > 31) { // Remove control characters like linefeed - mqtt_data[j++] = text; - if (j == sizeof(mqtt_data) -2) { break; } + TasmotaGlobal.mqtt_data[j++] = text; + if (j == sizeof(TasmotaGlobal.mqtt_data) -2) { break; } } } - mqtt_data[j] = '\0'; + TasmotaGlobal.mqtt_data[j] = '\0'; MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_WEBSEND)); #ifdef USE_SCRIPT extern uint8_t tasm_cmd_activ; @@ -3355,7 +3359,7 @@ void CmndEmulation(void) #endif #endif Settings.flag2.emulation = XdrvMailbox.payload; - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } #endif ResponseCmndNumber(Settings.flag2.emulation); diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index b62f2d12e..b976dd843 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -210,12 +210,12 @@ bool MqttPublishLib(const char* topic, bool retained) if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2))) { char *str = strstr(topic, SettingsText(SET_MQTTPREFIX1)); if (str == topic) { - mqtt_cmnd_blocked_reset = 4; // Allow up to four seconds before resetting residual cmnd blocks - mqtt_cmnd_blocked++; + TasmotaGlobal.mqtt_cmnd_blocked_reset = 4; // Allow up to four seconds before resetting residual cmnd blocks + TasmotaGlobal.mqtt_cmnd_blocked++; } } - bool result = MqttClient.publish(topic, mqtt_data, retained); + bool result = MqttClient.publish(topic, TasmotaGlobal.mqtt_data, retained); yield(); // #3313 return result; } @@ -238,8 +238,8 @@ void MqttDataHandler(char* mqtt_topic, uint8_t* mqtt_data, unsigned int data_len // Do not execute multiple times if Prefix1 equals Prefix2 if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2))) { char *str = strstr(mqtt_topic, SettingsText(SET_MQTTPREFIX1)); - if ((str == mqtt_topic) && mqtt_cmnd_blocked) { - mqtt_cmnd_blocked--; + if ((str == mqtt_topic) && TasmotaGlobal.mqtt_cmnd_blocked) { + TasmotaGlobal.mqtt_cmnd_blocked--; return; } } @@ -252,7 +252,7 @@ void MqttDataHandler(char* mqtt_topic, uint8_t* mqtt_data, unsigned int data_len memcpy(data, mqtt_data, sizeof(data)); // AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_MQTT D_DATA_SIZE " %d, \"%s %s\""), data_len, topic, data); -// if (LOG_LEVEL_DEBUG_MORE <= seriallog_level) { Serial.println(data); } +// if (LOG_LEVEL_DEBUG_MORE <= TasmotaGlobal.seriallog_level) { Serial.println(data); } MqttDumpData(topic, data, data_len); // Use a function to save stack space used by dump_data // MQTT pre-processing @@ -288,16 +288,16 @@ void MqttUnsubscribe(const char *topic) void MqttPublishLogging(const char *mxtime) { - char saved_mqtt_data[strlen(mqtt_data) +1]; - memcpy(saved_mqtt_data, mqtt_data, sizeof(saved_mqtt_data)); + char saved_mqtt_data[strlen(TasmotaGlobal.mqtt_data) +1]; + memcpy(saved_mqtt_data, TasmotaGlobal.mqtt_data, sizeof(saved_mqtt_data)); -// ResponseTime_P(PSTR(",\"Log\":{\"%s\"}}"), log_data); // Will fail as some messages contain JSON - Response_P(PSTR("%s%s"), mxtime, log_data); // No JSON and ugly!! +// ResponseTime_P(PSTR(",\"Log\":{\"%s\"}}"), TasmotaGlobal.log_data); // Will fail as some messages contain JSON + Response_P(PSTR("%s%s"), mxtime, TasmotaGlobal.log_data); // No JSON and ugly!! char stopic[TOPSZ]; - GetTopic_P(stopic, STAT, mqtt_topic, PSTR("LOGGING")); + GetTopic_P(stopic, STAT, TasmotaGlobal.mqtt_topic, PSTR("LOGGING")); MqttPublishLib(stopic, false); - memcpy(mqtt_data, saved_mqtt_data, sizeof(saved_mqtt_data)); + memcpy(TasmotaGlobal.mqtt_data, saved_mqtt_data, sizeof(saved_mqtt_data)); } void MqttPublish(const char* topic, bool retained) @@ -324,16 +324,16 @@ void MqttPublish(const char* topic, bool retained) } } - snprintf_P(log_data, sizeof(log_data), PSTR("%s%s = %s"), slog_type, (Settings.flag.mqtt_enabled) ? topic : strrchr(topic,'/')+1, mqtt_data); // SetOption3 - Enable MQTT - if (strlen(log_data) >= (sizeof(log_data) - strlen(sretained) -1)) { - log_data[sizeof(log_data) - strlen(sretained) -5] = '\0'; - snprintf_P(log_data, sizeof(log_data), PSTR("%s ..."), log_data); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s%s = %s"), slog_type, (Settings.flag.mqtt_enabled) ? topic : strrchr(topic,'/')+1, TasmotaGlobal.mqtt_data); // SetOption3 - Enable MQTT + if (strlen(TasmotaGlobal.log_data) >= (sizeof(TasmotaGlobal.log_data) - strlen(sretained) -1)) { + TasmotaGlobal.log_data[sizeof(TasmotaGlobal.log_data) - strlen(sretained) -5] = '\0'; + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s ..."), TasmotaGlobal.log_data); } - snprintf_P(log_data, sizeof(log_data), PSTR("%s%s"), log_data, sretained); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s%s"), TasmotaGlobal.log_data, sretained); AddLog(LOG_LEVEL_INFO); if (Settings.ledstate &0x04) { - blinks++; + TasmotaGlobal.blinks++; } } @@ -359,7 +359,7 @@ void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retain romram[i] = toupper(romram[i]); } prefix &= 3; - GetTopic_P(stopic, prefix, mqtt_topic, romram); + GetTopic_P(stopic, prefix, TasmotaGlobal.mqtt_topic, romram); MqttPublish(stopic, retained); #if defined(USE_MQTT_AWS_IOT) || defined(USE_MQTT_AWS_IOT_LIGHT) @@ -380,13 +380,13 @@ void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retain snprintf_P(romram, sizeof(romram), PSTR("$aws/things/%s/shadow/update"), topic2); // copy buffer - char *mqtt_save = (char*) malloc(strlen(mqtt_data)+1); + char *mqtt_save = (char*) malloc(strlen(TasmotaGlobal.mqtt_data)+1); if (!mqtt_save) { return; } // abort - strcpy(mqtt_save, mqtt_data); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"state\":{\"reported\":%s}}"), mqtt_save); + strcpy(mqtt_save, TasmotaGlobal.mqtt_data); + snprintf_P(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), PSTR("{\"state\":{\"reported\":%s}}"), mqtt_save); free(mqtt_save); - bool result = MqttClient.publish(romram, mqtt_data, false); + bool result = MqttClient.publish(romram, TasmotaGlobal.mqtt_data, false); AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT "Updated shadow: %s"), romram); yield(); // #3313 } @@ -419,7 +419,7 @@ void MqttPublishPowerState(uint32_t device) char stopic[TOPSZ]; char scommand[33]; - if ((device < 1) || (device > devices_present)) { device = 1; } + if ((device < 1) || (device > TasmotaGlobal.devices_present)) { device = 1; } #ifdef USE_SONOFF_IFAN if (IsModuleIfan() && (device > 1)) { @@ -428,20 +428,20 @@ void MqttPublishPowerState(uint32_t device) DomoticzUpdateFanState(); // RC Button feedback #endif // USE_DOMOTICZ snprintf_P(scommand, sizeof(scommand), PSTR(D_CMND_FANSPEED)); - GetTopic_P(stopic, STAT, mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT); // SetOption4 - Switch between MQTT RESULT or COMMAND + GetTopic_P(stopic, STAT, TasmotaGlobal.mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT); // SetOption4 - Switch between MQTT RESULT or COMMAND Response_P(S_JSON_COMMAND_NVALUE, scommand, GetFanspeed()); MqttPublish(stopic); } } else { #endif // USE_SONOFF_IFAN GetPowerDevice(scommand, device, sizeof(scommand), Settings.flag.device_index_enable); // SetOption26 - Switch between POWER or POWER1 - GetTopic_P(stopic, STAT, mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT); // SetOption4 - Switch between MQTT RESULT or COMMAND - Response_P(S_JSON_COMMAND_SVALUE, scommand, GetStateText(bitRead(power, device -1))); + GetTopic_P(stopic, STAT, TasmotaGlobal.mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT); // SetOption4 - Switch between MQTT RESULT or COMMAND + Response_P(S_JSON_COMMAND_SVALUE, scommand, GetStateText(bitRead(TasmotaGlobal.power, device -1))); MqttPublish(stopic); if (!Settings.flag4.only_json_message) { // SetOption90 - Disable non-json MQTT response - GetTopic_P(stopic, STAT, mqtt_topic, scommand); - Response_P(GetStateText(bitRead(power, device -1))); + GetTopic_P(stopic, STAT, TasmotaGlobal.mqtt_topic, scommand); + Response_P(GetStateText(bitRead(TasmotaGlobal.power, device -1))); MqttPublish(stopic, Settings.flag.mqtt_power_retain); // CMND_POWERRETAIN } #ifdef USE_SONOFF_IFAN @@ -451,7 +451,7 @@ void MqttPublishPowerState(uint32_t device) void MqttPublishAllPowerState(void) { - for (uint32_t i = 1; i <= devices_present; i++) { + for (uint32_t i = 1; i <= TasmotaGlobal.devices_present; i++) { MqttPublishPowerState(i); #ifdef USE_SONOFF_IFAN if (IsModuleIfan()) { break; } // Report status of light relay only @@ -463,11 +463,11 @@ void MqttPublishPowerBlinkState(uint32_t device) { char scommand[33]; - if ((device < 1) || (device > devices_present)) { + if ((device < 1) || (device > TasmotaGlobal.devices_present)) { device = 1; } Response_P(PSTR("{\"%s\":\"" D_JSON_BLINK " %s\"}"), - GetPowerDevice(scommand, device, sizeof(scommand), Settings.flag.device_index_enable), GetStateText(bitRead(blink_mask, device -1))); // SetOption26 - Switch between POWER or POWER1 + GetPowerDevice(scommand, device, sizeof(scommand), Settings.flag.device_index_enable), GetStateText(bitRead(TasmotaGlobal.blink_mask, device -1))); // SetOption26 - Switch between POWER or POWER1 MqttPublishPrefixTopic_P(RESULT_OR_STAT, S_RSLT_POWER); } @@ -487,7 +487,7 @@ void MqttDisconnected(int state) MqttClient.disconnect(); AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CONNECT_FAILED_TO " %s:%d, rc %d. " D_RETRY_IN " %d " D_UNIT_SECOND), SettingsText(SET_MQTT_HOST), Settings.mqtt_port, state, Mqtt.retry_counter); - rules_flag.mqtt_disconnected = 1; + TasmotaGlobal.rules_flag.mqtt_disconnected = 1; } void MqttConnected(void) @@ -500,17 +500,17 @@ void MqttConnected(void) Mqtt.retry_counter = 0; Mqtt.connect_count++; - GetTopic_P(stopic, TELE, mqtt_topic, S_LWT); + GetTopic_P(stopic, TELE, TasmotaGlobal.mqtt_topic, S_LWT); Response_P(PSTR(MQTT_LWT_ONLINE)); MqttPublish(stopic, true); if (!Settings.flag4.only_json_message) { // SetOption90 - Disable non-json MQTT response // Satisfy iobroker (#299) - mqtt_data[0] = '\0'; + ResponseClear(); MqttPublishPrefixTopic_P(CMND, S_RSLT_POWER); } - GetTopic_P(stopic, CMND, mqtt_topic, PSTR("#")); + GetTopic_P(stopic, CMND, TasmotaGlobal.mqtt_topic, PSTR("#")); MqttSubscribe(stopic); if (strstr_P(SettingsText(SET_MQTT_FULLTOPIC), MQTT_TOKEN_TOPIC) != nullptr) { uint32_t real_index = SET_MQTT_GRP_TOPIC; @@ -532,7 +532,7 @@ void MqttConnected(void) if (ResetReason() != REASON_DEEP_SLEEP_AWAKE) { char stopic2[TOPSZ]; Response_P(PSTR("{\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_FALLBACKTOPIC "\":\"%s\",\"" D_CMND_GROUPTOPIC "\":\"%s\"}"), - ModuleName().c_str(), my_version, my_image, GetFallbackTopic_P(stopic, ""), GetGroupTopic_P(stopic2, "", SET_MQTT_GRP_TOPIC)); + ModuleName().c_str(), TasmotaGlobal.version, TasmotaGlobal.image_name, GetFallbackTopic_P(stopic, ""), GetGroupTopic_P(stopic2, "", SET_MQTT_GRP_TOPIC)); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "1")); #ifdef USE_WEBSERVER if (Settings.webserver) { @@ -558,16 +558,16 @@ void MqttConnected(void) MqttPublishAllPowerState(); if (Settings.tele_period) { - tele_period = Settings.tele_period -5; // Enable TelePeriod in 5 seconds + TasmotaGlobal.tele_period = Settings.tele_period -5; // Enable TelePeriod in 5 seconds } - rules_flag.system_boot = 1; + TasmotaGlobal.rules_flag.system_boot = 1; XdrvCall(FUNC_MQTT_INIT); } Mqtt.initial_connection_state = 0; - global_state.mqtt_down = 0; + TasmotaGlobal.global_state.mqtt_down = 0; if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT - rules_flag.mqtt_connected = 1; + TasmotaGlobal.rules_flag.mqtt_connected = 1; } } @@ -603,11 +603,20 @@ void MqttReconnect(void) UdpDisconnect(); #endif // USE_EMULATION - AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_ATTEMPTING_CONNECTION)); - Mqtt.connected = false; Mqtt.retry_counter = Settings.mqtt_retry; - global_state.mqtt_down = 1; + TasmotaGlobal.global_state.mqtt_down = 1; + +#ifdef FIRMWARE_MINIMAL +#ifndef USE_MQTT_TLS + // Don't try to connect if MQTT requires TLS but TLS is not supported + if (Settings.flag4.mqtt_tls) { + return; + } +#endif +#endif + + AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_ATTEMPTING_CONNECTION)); char *mqtt_user = nullptr; char *mqtt_pwd = nullptr; @@ -618,7 +627,7 @@ void MqttReconnect(void) mqtt_pwd = SettingsText(SET_MQTT_PWD); } - GetTopic_P(stopic, TELE, mqtt_topic, S_LWT); + GetTopic_P(stopic, TELE, TasmotaGlobal.mqtt_topic, S_LWT); Response_P(S_LWT_OFFLINE); if (MqttClient.connected()) { MqttClient.disconnect(); } @@ -678,7 +687,7 @@ void MqttReconnect(void) } #endif - if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, lwt_retain, mqtt_data, MQTT_CLEAN_SESSION)) { + if (MqttClient.connect(TasmotaGlobal.mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, lwt_retain, TasmotaGlobal.mqtt_data, MQTT_CLEAN_SESSION)) { #ifdef USE_MQTT_TLS if (Mqtt.mqtt_tls) { AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "TLS connected in %d ms, max ThunkStack used %d"), @@ -764,17 +773,17 @@ void MqttCheck(void) { if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT if (!MqttIsConnected()) { - global_state.mqtt_down = 1; + TasmotaGlobal.global_state.mqtt_down = 1; if (!Mqtt.retry_counter) { MqttReconnect(); } else { Mqtt.retry_counter--; } } else { - global_state.mqtt_down = 0; + TasmotaGlobal.global_state.mqtt_down = 0; } } else { - global_state.mqtt_down = 0; + TasmotaGlobal.global_state.mqtt_down = 0; if (Mqtt.initial_connection_state) { MqttReconnect(); } @@ -810,7 +819,7 @@ void CmndMqttFingerprint(void) Settings.mqtt_fingerprint[XdrvMailbox.index -1][i] = strtol(p, &p, 16); } } - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } ResponseCmndIdxChar(ToHex_P((unsigned char *)Settings.mqtt_fingerprint[XdrvMailbox.index -1], 20, fingerprint, sizeof(fingerprint), ' ')); } @@ -821,7 +830,7 @@ void CmndMqttUser(void) { if (XdrvMailbox.data_len > 0) { SettingsUpdateText(SET_MQTT_USER, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_USER : XdrvMailbox.data); - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } ResponseCmndChar(SettingsText(SET_MQTT_USER)); } @@ -831,7 +840,7 @@ 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)); - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } else { Response_P(S_JSON_COMMAND_ASTERISK, XdrvMailbox.command); } @@ -849,7 +858,7 @@ void CmndMqttHost(void) { if (XdrvMailbox.data_len > 0) { SettingsUpdateText(SET_MQTT_HOST, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_HOST : XdrvMailbox.data); - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } ResponseCmndChar(SettingsText(SET_MQTT_HOST)); } @@ -858,7 +867,7 @@ void CmndMqttPort(void) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 65536)) { Settings.mqtt_port = (1 == XdrvMailbox.payload) ? MQTT_PORT : XdrvMailbox.payload; - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } ResponseCmndNumber(Settings.mqtt_port); } @@ -893,7 +902,7 @@ void CmndMqttClient(void) { if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { SettingsUpdateText(SET_MQTT_CLIENT, (SC_DEFAULT == Shortcut()) ? MQTT_CLIENT_ID : XdrvMailbox.data); - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } ResponseCmndChar(SettingsText(SET_MQTT_CLIENT)); } @@ -902,14 +911,14 @@ void CmndFullTopic(void) { if (XdrvMailbox.data_len > 0) { MakeValidMqtt(1, XdrvMailbox.data); - if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } + if (!strcmp(XdrvMailbox.data, TasmotaGlobal.mqtt_client)) { SetShortcutDefault(); } char stemp1[TOPSZ]; strlcpy(stemp1, (SC_DEFAULT == Shortcut()) ? MQTT_FULLTOPIC : XdrvMailbox.data, sizeof(stemp1)); if (strcmp(stemp1, SettingsText(SET_MQTT_FULLTOPIC))) { Response_P((Settings.flag.mqtt_offline) ? S_LWT_OFFLINE : ""); // SetOption10 - Control MQTT LWT message format MqttPublishPrefixTopic_P(TELE, S_LWT, true); // Offline or remove previous retained topic SettingsUpdateText(SET_MQTT_FULLTOPIC, stemp1); - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } } ResponseCmndChar(SettingsText(SET_MQTT_FULLTOPIC)); @@ -925,7 +934,7 @@ void CmndPrefix(void) MakeValidMqtt(0, XdrvMailbox.data); SettingsUpdateText(SET_MQTTPREFIX1 + XdrvMailbox.index -1, (SC_DEFAULT == Shortcut()) ? (1==XdrvMailbox.index) ? SUB_PREFIX : (2==XdrvMailbox.index) ? PUB_PREFIX : PUB_PREFIX2 : XdrvMailbox.data); - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } ResponseCmndIdxChar(SettingsText(SET_MQTTPREFIX1 + XdrvMailbox.index -1)); } @@ -941,13 +950,13 @@ void CmndPublish(void) char stemp1[TOPSZ]; strlcpy(stemp1, mqtt_part, sizeof(stemp1)); if ((payload_part != nullptr) && strlen(payload_part)) { - strlcpy(mqtt_data, payload_part, sizeof(mqtt_data)); + strlcpy(TasmotaGlobal.mqtt_data, payload_part, sizeof(TasmotaGlobal.mqtt_data)); } else { - mqtt_data[0] = '\0'; + ResponseClear(); } MqttPublish(stemp1, (XdrvMailbox.index == 2)); // ResponseCmndDone(); - mqtt_data[0] = '\0'; + ResponseClear(); } } } @@ -958,7 +967,7 @@ void CmndGroupTopic(void) if (XdrvMailbox.data_len > 0) { uint32_t settings_text_index = (1 == XdrvMailbox.index) ? SET_MQTT_GRP_TOPIC : SET_MQTT_GRP_TOPIC2 + XdrvMailbox.index - 2; MakeValidMqtt(0, XdrvMailbox.data); - if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } + if (!strcmp(XdrvMailbox.data, TasmotaGlobal.mqtt_client)) { SetShortcutDefault(); } SettingsUpdateText(settings_text_index, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_GRPTOPIC : XdrvMailbox.data); // Eliminate duplicates, have at least one and fill from index 1 @@ -996,7 +1005,7 @@ void CmndGroupTopic(void) } } - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } ResponseCmndAll(SET_MQTT_GRP_TOPIC, MAX_GROUP_TOPICS); } @@ -1006,14 +1015,14 @@ void CmndTopic(void) { if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { MakeValidMqtt(0, XdrvMailbox.data); - if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } + if (!strcmp(XdrvMailbox.data, TasmotaGlobal.mqtt_client)) { SetShortcutDefault(); } char stemp1[TOPSZ]; strlcpy(stemp1, (SC_DEFAULT == Shortcut()) ? MQTT_TOPIC : XdrvMailbox.data, sizeof(stemp1)); if (strcmp(stemp1, SettingsText(SET_MQTT_TOPIC))) { Response_P((Settings.flag.mqtt_offline) ? S_LWT_OFFLINE : ""); // SetOption10 - Control MQTT LWT message format MqttPublishPrefixTopic_P(TELE, S_LWT, true); // Offline or remove previous retained topic SettingsUpdateText(SET_MQTT_TOPIC, stemp1); - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } } ResponseCmndChar(SettingsText(SET_MQTT_TOPIC)); @@ -1023,10 +1032,10 @@ void CmndButtonTopic(void) { if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { MakeValidMqtt(0, XdrvMailbox.data); - if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } + if (!strcmp(XdrvMailbox.data, TasmotaGlobal.mqtt_client)) { SetShortcutDefault(); } switch (Shortcut()) { case SC_CLEAR: SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, ""); break; - case SC_DEFAULT: SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, mqtt_topic); break; + case SC_DEFAULT: SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, TasmotaGlobal.mqtt_topic); break; case SC_USER: SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, MQTT_BUTTON_TOPIC); break; default: SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, XdrvMailbox.data); } @@ -1038,10 +1047,10 @@ void CmndSwitchTopic(void) { if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { MakeValidMqtt(0, XdrvMailbox.data); - if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } + if (!strcmp(XdrvMailbox.data, TasmotaGlobal.mqtt_client)) { SetShortcutDefault(); } switch (Shortcut()) { case SC_CLEAR: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, ""); break; - case SC_DEFAULT: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, mqtt_topic); break; + case SC_DEFAULT: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, TasmotaGlobal.mqtt_topic); break; case SC_USER: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, MQTT_SWITCH_TOPIC); break; default: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, XdrvMailbox.data); } @@ -1081,9 +1090,9 @@ void CmndPowerRetain(void) if (!XdrvMailbox.payload) { char stemp1[TOPSZ]; char scommand[CMDSZ]; - for (uint32_t i = 1; i <= devices_present; i++) { // Clear MQTT retain in broker - GetTopic_P(stemp1, STAT, mqtt_topic, GetPowerDevice(scommand, i, sizeof(scommand), Settings.flag.device_index_enable)); // SetOption26 - Switch between POWER or POWER1 - mqtt_data[0] = '\0'; + for (uint32_t i = 1; i <= TasmotaGlobal.devices_present; i++) { // Clear MQTT retain in broker + GetTopic_P(stemp1, STAT, TasmotaGlobal.mqtt_topic, GetPowerDevice(scommand, i, sizeof(scommand), Settings.flag.device_index_enable)); // SetOption26 - Switch between POWER or POWER1 + ResponseClear(); MqttPublish(stemp1, Settings.flag.mqtt_power_retain); // CMND_POWERRETAIN } } @@ -1099,7 +1108,7 @@ void CmndSensorRetain(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { if (!XdrvMailbox.payload) { - mqtt_data[0] = '\0'; + ResponseClear(); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); // CMND_SENSORRETAIN MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_ENERGY), Settings.flag.mqtt_sensor_retain); // CMND_SENSORRETAIN } diff --git a/tasmota/xdrv_03_energy.ino b/tasmota/xdrv_03_energy.ino index 79e34e44b..4f41fa229 100644 --- a/tasmota/xdrv_03_energy.ino +++ b/tasmota/xdrv_03_energy.ino @@ -253,7 +253,7 @@ void EnergyUpdateTotal(float value, bool kwh) void Energy200ms(void) { - Energy.power_on = (power != 0) | Settings.flag.no_power_on_check; // SetOption21 - Show voltage even if powered off + Energy.power_on = (TasmotaGlobal.power != 0) | Settings.flag.no_power_on_check; // SetOption21 - Show voltage even if powered off Energy.fifth_second++; if (5 == Energy.fifth_second) { @@ -338,6 +338,8 @@ void EnergyMarginCheck(void) for (uint32_t phase = 0; phase < Energy.phase_count; phase++) { uint16_t active_power = (uint16_t)(Energy.active_power[phase]); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: APower %d, HPower0 %d, HPower1 %d, HPower2 %d"), active_power, Energy.power_history[phase][0], Energy.power_history[phase][1], Energy.power_history[phase][2]); + if (Settings.energy_power_delta[phase]) { power_diff[phase] = active_power - Energy.power_history[phase][0]; uint16_t delta = abs(power_diff[phase]); @@ -437,12 +439,12 @@ void EnergyMarginCheck(void) } } } - else if (power && (energy_power_u <= Settings.energy_max_power_limit)) { + else if (TasmotaGlobal.power && (energy_power_u <= Settings.energy_max_power_limit)) { Energy.mplh_counter = 0; Energy.mplr_counter = 0; Energy.mplw_counter = 0; } - if (!power) { + if (!TasmotaGlobal.power) { if (Energy.mplw_counter) { Energy.mplw_counter--; } else { @@ -488,12 +490,12 @@ void EnergyMarginCheck(void) void EnergyMqttShow(void) { // {"Time":"2017-12-16T11:48:55","ENERGY":{"Total":0.212,"Yesterday":0.000,"Today":0.014,"Period":2.0,"Power":22.0,"Factor":1.00,"Voltage":213.6,"Current":0.100}} - int tele_period_save = tele_period; - tele_period = 2; - mqtt_data[0] = '\0'; + int tele_period_save = TasmotaGlobal.tele_period; + TasmotaGlobal.tele_period = 2; + ResponseClear(); ResponseAppendTime(); EnergyShow(true); - tele_period = tele_period_save; + TasmotaGlobal.tele_period = tele_period_save; ResponseJsonEnd(); MqttPublishTeleSensor(); } @@ -502,11 +504,11 @@ void EnergyMqttShow(void) void EnergyEverySecond(void) { // Overtemp check - if (global_update) { - if (power && !isnan(global_temperature_celsius) && (global_temperature_celsius > (float)Settings.param[P_OVER_TEMP])) { // Device overtemp, turn off relays + if (TasmotaGlobal.global_update) { + if (TasmotaGlobal.power && !isnan(TasmotaGlobal.temperature_celsius) && (TasmotaGlobal.temperature_celsius > (float)Settings.param[P_OVER_TEMP])) { // Device overtemp, turn off relays char temperature[33]; - dtostrfd(global_temperature_celsius, 1, temperature); + dtostrfd(TasmotaGlobal.temperature_celsius, 1, temperature); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: GlobTemp %s"), temperature); SetAllPower(POWER_ALL_OFF, SRC_OVERTEMP); @@ -896,7 +898,7 @@ void EnergySnsInit(void) { XnrgCall(FUNC_INIT); - if (energy_flg) { + if (TasmotaGlobal.energy_driver) { Energy.kWhtoday_offset = 0; // Do not use at Power On as Rtc was invalid (but has been restored from Settings already) if ((ResetReason() != REASON_DEFAULT_RST) && RtcSettingsValid()) { @@ -1031,7 +1033,7 @@ void EnergyShow(bool json) char value3_chr[FLOATSZ *3]; if (json) { - bool show_energy_period = (0 == tele_period); + bool show_energy_period = (0 == TasmotaGlobal.tele_period); ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL_START_TIME "\":\"%s\",\"" D_JSON_TOTAL "\":%s"), GetDateAndTime(DT_ENERGY).c_str(), @@ -1178,16 +1180,18 @@ bool Xdrv03(uint8_t function) bool result = false; if (FUNC_PRE_INIT == function) { - energy_flg = ENERGY_NONE; + TasmotaGlobal.energy_driver = ENERGY_NONE; XnrgCall(FUNC_PRE_INIT); // Find first energy driver } - else if (energy_flg) { + else if (TasmotaGlobal.energy_driver) { switch (function) { case FUNC_LOOP: XnrgCall(FUNC_LOOP); break; case FUNC_EVERY_250_MSECOND: - XnrgCall(FUNC_EVERY_250_MSECOND); + if (TasmotaGlobal.uptime > 4) { + XnrgCall(FUNC_EVERY_250_MSECOND); + } break; case FUNC_EVERY_SECOND: XnrgCall(FUNC_EVERY_SECOND); @@ -1212,7 +1216,7 @@ bool Xsns03(uint8_t function) { bool result = false; - if (energy_flg) { + if (TasmotaGlobal.energy_driver) { switch (function) { case FUNC_EVERY_SECOND: EnergyEverySecond(); diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 6a507db06..fb6f06dd2 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -572,7 +572,7 @@ class LightStateClass { _briRGB = bri_rgb; if (bri_rgb > 0) { addRGBMode(); } #ifdef USE_PWM_DIMMER - if (PWM_DIMMER == my_module_type) PWMDimmerSetBrightnessLeds(-1); + if (PWM_DIMMER == TasmotaGlobal.module_type) PWMDimmerSetBrightnessLeds(-1); #endif // USE_PWM_DIMMER return prev_bri; } @@ -583,7 +583,7 @@ class LightStateClass { _briCT = bri_ct; if (bri_ct > 0) { addCTMode(); } #ifdef USE_PWM_DIMMER - if (PWM_DIMMER == my_module_type) PWMDimmerSetBrightnessLeds(-1); + if (PWM_DIMMER == TasmotaGlobal.module_type) PWMDimmerSetBrightnessLeds(-1); #endif // USE_PWM_DIMMER return prev_bri; } @@ -973,7 +973,7 @@ public: Settings.light_color[0], Settings.light_color[1], Settings.light_color[2], Settings.light_color[3], Settings.light_color[4], Settings.light_dimmer); AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::loadSettings light_type/sub (%d %d)", - light_type, Light.subtype); + TasmotaGlobal.light_type, Light.subtype); #endif if (_pwm_multi_channels) { _state->setChannelsRaw(Settings.light_color); @@ -1246,64 +1246,64 @@ void LightPwmOffset(uint32_t offset) bool LightModuleInit(void) { - light_type = LT_BASIC; // Use basic PWM control if SetOption15 = 0 + TasmotaGlobal.light_type = LT_BASIC; // Use basic PWM control if SetOption15 = 0 if (Settings.flag.pwm_control) { // SetOption15 - Switch between commands PWM or COLOR/DIMMER/CT/CHANNEL for (uint32_t i = 0; i < MAX_PWMS; i++) { - if (PinUsed(GPIO_PWM1, i)) { light_type++; } // Use Dimmer/Color control for all PWM as SetOption15 = 1 + if (PinUsed(GPIO_PWM1, i)) { TasmotaGlobal.light_type++; } // Use Dimmer/Color control for all PWM as SetOption15 = 1 } } - light_flg = 0; + TasmotaGlobal.light_driver = 0; if (XlgtCall(FUNC_MODULE_INIT)) { // serviced } #ifdef ESP8266 - else if (SONOFF_BN == my_module_type) { // PWM Single color led (White) - light_type = LT_PWM1; + else if (SONOFF_BN == TasmotaGlobal.module_type) { // PWM Single color led (White) + TasmotaGlobal.light_type = LT_PWM1; } - else if (SONOFF_LED == my_module_type) { // PWM Dual color led (White warm and cold) - if (!my_module.io[4]) { // Fix Sonoff Led instabilities + else if (SONOFF_LED == TasmotaGlobal.module_type) { // PWM Dual color led (White warm and cold) + if (!TasmotaGlobal.my_module.io[4]) { // Fix Sonoff Led instabilities pinMode(4, OUTPUT); // Stop floating outputs digitalWrite(4, LOW); } - if (!my_module.io[5]) { + if (!TasmotaGlobal.my_module.io[5]) { pinMode(5, OUTPUT); // Stop floating outputs digitalWrite(5, LOW); } - if (!my_module.io[14]) { + if (!TasmotaGlobal.my_module.io[14]) { pinMode(14, OUTPUT); // Stop floating outputs digitalWrite(14, LOW); } - light_type = LT_PWM2; + TasmotaGlobal.light_type = LT_PWM2; } #endif // ESP8266 #ifdef USE_PWM_DIMMER #ifdef USE_DEVICE_GROUPS - else if (PWM_DIMMER == my_module_type) { - light_type = Settings.pwm_dimmer_cfg.pwm_count + 1; + else if (PWM_DIMMER == TasmotaGlobal.module_type) { + TasmotaGlobal.light_type = Settings.pwm_dimmer_cfg.pwm_count + 1; } #endif // USE_DEVICE_GROUPS #endif // USE_PWM_DIMMER - if (light_type > LT_BASIC) { - devices_present++; + if (TasmotaGlobal.light_type > LT_BASIC) { + TasmotaGlobal.devices_present++; } // post-process for lights - uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); + uint32_t pwm_channels = (TasmotaGlobal.light_type & 7) > LST_MAX ? LST_MAX : (TasmotaGlobal.light_type & 7); if (Settings.flag3.pwm_multi_channels) { // SetOption68 - Enable multi-channels PWM instead of Color PWM if (0 == pwm_channels) { pwm_channels = 1; } - devices_present += pwm_channels - 1; // add the pwm channels controls at the end + TasmotaGlobal.devices_present += pwm_channels - 1; // add the pwm channels controls at the end } else if ((Settings.param[P_RGB_REMAP] & 128) && (LST_RGBW <= pwm_channels)) { // if RGBW or RGBCW, and SetOption37 >= 128, we manage RGB and W separately, hence adding a device - devices_present++; + TasmotaGlobal.devices_present++; } else if ((Settings.flag4.virtual_ct) && (LST_RGBW == pwm_channels)) { Light.virtual_ct = true; // enabled - light_type++; // create an additional virtual 5th channel + TasmotaGlobal.light_type++; // create an additional virtual 5th channel } - return (light_type > LT_BASIC); + return (TasmotaGlobal.light_type > LT_BASIC); } // compute actual PWM min/max values from DimmerRange @@ -1333,8 +1333,8 @@ void LightInit(void) Settings.rgbwwTable[4] = 255; // set RGBWWTable value to its default } - Light.device = devices_present; - Light.subtype = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); // Always 0 - LST_MAX (5) + Light.device = TasmotaGlobal.devices_present; + Light.subtype = (TasmotaGlobal.light_type & 7) > LST_MAX ? LST_MAX : (TasmotaGlobal.light_type & 7); // Always 0 - LST_MAX (5) Light.pwm_multi_channels = Settings.flag3.pwm_multi_channels; // SetOption68 - Enable multi-channels PWM instead of Color PWM if (LST_RGBW <= Light.subtype) { @@ -1347,15 +1347,15 @@ void LightInit(void) if ((LST_SINGLE <= Light.subtype) && Light.pwm_multi_channels) { // we treat each PWM channel as an independant one, hence we switch to light_controller.setPWMMultiChannel(true); - Light.device = devices_present - Light.subtype + 1; // adjust if we also have relays + Light.device = TasmotaGlobal.devices_present - Light.subtype + 1; // adjust if we also have relays } else if (!light_controller.isCTRGBLinked()) { // if RGBW or RGBCW, and SetOption37 >= 128, we manage RGB and W separately Light.device--; // we take the last two devices as lights } LightCalcPWMRange(); #ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightInit Light.pwm_multi_channels=%d Light.subtype=%d Light.device=%d devices_present=%d", - Light.pwm_multi_channels, Light.subtype, Light.device, devices_present); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightInit Light.pwm_multi_channels=%d Light.subtype=%d Light.device=%d TasmotaGlobal.devices_present=%d", + Light.pwm_multi_channels, Light.subtype, Light.device, TasmotaGlobal.devices_present); #endif light_controller.setSubType(Light.subtype); @@ -1366,8 +1366,8 @@ void LightInit(void) if (LST_SINGLE == Light.subtype) { Settings.light_color[0] = 255; // One channel only supports Dimmer but needs max color } - if (light_type < LT_PWM6) { // PWM - for (uint32_t i = 0; i < light_type; i++) { + if (TasmotaGlobal.light_type < LT_PWM6) { // PWM + for (uint32_t i = 0; i < TasmotaGlobal.light_type; i++) { Settings.pwm_value[i] = 0; // Disable direct PWM control if (PinUsed(GPIO_PWM1, i)) { #ifdef ESP8266 @@ -1457,7 +1457,7 @@ void LightHsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t uint8_t LightGetBri(uint8_t device) { uint8_t bri = 254; // default value if relay if (Light.pwm_multi_channels) { - if ((device >= Light.device) && (device < Light.device + LST_MAX) && (device <= devices_present)) { + if ((device >= Light.device) && (device < Light.device + LST_MAX) && (device <= TasmotaGlobal.devices_present)) { bri = Light.current_color[device - Light.device]; } } else if (light_controller.isCTRGBLinked()) { // standard behavior @@ -1477,7 +1477,7 @@ uint8_t LightGetBri(uint8_t device) { // If SetOption68 is set, set the brightness for a specific device void LightSetBri(uint8_t device, uint8_t bri) { if (Light.pwm_multi_channels) { - if ((device >= Light.device) && (device < Light.device + LST_MAX) && (device <= devices_present)) { + if ((device >= Light.device) && (device < Light.device + LST_MAX) && (device <= TasmotaGlobal.devices_present)) { Light.current_color[device - Light.device] = bri; light_controller.changeChannels(Light.current_color); } @@ -1668,7 +1668,7 @@ void ResponseLightState(uint8_t append) void LightPreparePower(power_t channels = 0xFFFFFFFF) { // 1 = only RGB, 2 = only CT, 3 = both RGB and CT #ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower power=%d Light.power=%d", power, Light.power); + AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower power=%d Light.power=%d", TasmotaGlobal.power, Light.power); #endif // If multi-channels, then we only switch off channels with a value of zero if (Light.pwm_multi_channels) { @@ -1731,9 +1731,9 @@ void LightPreparePower(power_t channels = 0xFFFFFFFF) { // 1 = only RGB, 2 = } #ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower End power=%d Light.power=%d", power, Light.power); + AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower End power=%d Light.power=%d", TasmotaGlobal.power, Light.power); #endif - Light.power = power >> (Light.device - 1); // reset next state, works also with unlinked RGB/CT + Light.power = TasmotaGlobal.power >> (Light.device - 1); // reset next state, works also with unlinked RGB/CT ResponseLightState(0); } @@ -1825,10 +1825,10 @@ void LightSetPower(void) } uint32_t shift = Light.device - 1; // If PWM multi_channels - // Ex: 3 Relays and 4 PWM - devices_present = 7, Light.device = 4, Light.subtype = 4 + // Ex: 3 Relays and 4 PWM - TasmotaGlobal.devices_present = 7, Light.device = 4, Light.subtype = 4 // Result: mask = 0b00001111 = 0x0F, shift = 3. // Power bits we consider are: 0b01111000 = 0x78 - // If regular situation: devices_present == Light.subtype + // If regular situation: TasmotaGlobal.devices_present == Light.subtype Light.power = (XdrvMailbox.index & (mask << shift)) >> shift; if (Light.wakeup_active) { Light.wakeup_active--; @@ -1859,12 +1859,12 @@ void LightAnimate(void) // or set a maximum of PWM_MAX_SLEEP if light is on or Fade is running if (Light.power || Light.fade_running) { if (Settings.sleep > PWM_MAX_SLEEP) { - ssleep = PWM_MAX_SLEEP; // set a maxumum value of 10 milliseconds to ensure that animations are smooth + TasmotaGlobal.sleep = PWM_MAX_SLEEP; // set a maxumum value of 10 milliseconds to ensure that animations are smooth } else { - ssleep = Settings.sleep; // or keep the current sleep if it's lower than 50 + TasmotaGlobal.sleep = Settings.sleep; // or keep the current sleep if it's lower than 50 } } else { - ssleep = Settings.sleep; + TasmotaGlobal.sleep = Settings.sleep; } if (!Light.power) { // All channels powered off @@ -2035,7 +2035,7 @@ void LightAnimate(void) cur_col_10[i] = orig_col_10bits[Light.color_remap[i]]; } - if (!Settings.light_fade || skip_light_fade || power_off || (!Light.fade_initialized)) { // no fade + if (!Settings.light_fade || TasmotaGlobal.skip_light_fade || power_off || (!Light.fade_initialized)) { // no fade // record the current value for a future Fade memcpy(Light.fade_start_10, cur_col_10, sizeof(Light.fade_start_10)); // push the final values at 8 and 10 bits resolution to the PWMs @@ -2063,7 +2063,7 @@ void LightAnimate(void) } #ifdef USE_PWM_DIMMER // If the power is off and the fade is done, turn the relay off. - if (PWM_DIMMER == my_module_type && !Light.power && !Light.fade_running) PWMDimmerSetPower(); + if (PWM_DIMMER == TasmotaGlobal.module_type && !Light.power && !Light.fade_running) PWMDimmerSetPower(); #endif // USE_PWM_DIMMER } } @@ -2072,7 +2072,7 @@ bool isChannelGammaCorrected(uint32_t channel) { if (!Settings.light_correction) { return false; } // Gamma correction not activated if (channel >= Light.subtype) { return false; } // Out of range #ifdef ESP8266 - if ((PHILIPS == my_module_type) || (Settings.flag4.pwm_ct_mode)) { + if ((PHILIPS == TasmotaGlobal.module_type) || (Settings.flag4.pwm_ct_mode)) { if ((LST_COLDWARM == Light.subtype) && (1 == channel)) { return false; } // PMW reserved for CT if ((LST_RGBCW == Light.subtype) && (4 == channel)) { return false; } // PMW reserved for CT } @@ -2083,7 +2083,7 @@ bool isChannelGammaCorrected(uint32_t channel) { // is the channel a regular PWM or ColorTemp control bool isChannelCT(uint32_t channel) { #ifdef ESP8266 - if ((PHILIPS == my_module_type) || (Settings.flag4.pwm_ct_mode)) { + if ((PHILIPS == TasmotaGlobal.module_type) || (Settings.flag4.pwm_ct_mode)) { if ((LST_COLDWARM == Light.subtype) && (1 == channel)) { return true; } // PMW reserved for CT if ((LST_RGBCW == Light.subtype) && (4 == channel)) { return true; } // PMW reserved for CT } @@ -2134,9 +2134,9 @@ bool LightApplyFade(void) { // did the value chanegd and needs to be applied if (Settings.save_data) { // Also postpone the save_data for the duration of the Fade (in seconds) uint32_t delay_seconds = 1 + (Light.fade_duration + 999) / 1000; // add one more second - // AddLog_P2(LOG_LEVEL_INFO, PSTR("delay_seconds %d, save_data_counter %d"), delay_seconds, save_data_counter); - if (save_data_counter < delay_seconds) { - save_data_counter = delay_seconds; // pospone + // AddLog_P2(LOG_LEVEL_INFO, PSTR("delay_seconds %d, save_data_counter %d"), delay_seconds, TasmotaGlobal.save_data_counter); + if (TasmotaGlobal.save_data_counter < delay_seconds) { + TasmotaGlobal.save_data_counter = delay_seconds; // pospone } } } else { @@ -2207,7 +2207,7 @@ void LightApplyPower(uint8_t new_color[LST_MAX], power_t power) { void LightSetOutputs(const uint16_t *cur_col_10) { // now apply the actual PWM values, adjusted and remapped 10-bits range - if (light_type < LT_PWM6) { // only for direct PWM lights, not for Tuya, Armtronix... + if (TasmotaGlobal.light_type < LT_PWM6) { // only for direct PWM lights, not for Tuya, Armtronix... for (uint32_t i = 0; i < (Light.subtype - Light.pwm_offset); i++) { if (PinUsed(GPIO_PWM1, i)) { //AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Cur_Col%d 10 bits %d"), i, cur_col_10[i]); @@ -2216,7 +2216,7 @@ void LightSetOutputs(const uint16_t *cur_col_10) { cur_col = cur_col > 0 ? changeUIntScale(cur_col, 0, Settings.pwm_range, Light.pwm_min, Light.pwm_max) : 0; // shrink to the range of pwm_min..pwm_max } if (!Settings.flag4.zerocross_dimmer) { - analogWrite(Pin(GPIO_PWM1, i), bitRead(pwm_inverted, i) ? Settings.pwm_range - cur_col : cur_col); + analogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings.pwm_range - cur_col : cur_col); } } } @@ -2269,7 +2269,7 @@ void calcGammaBulbs(uint16_t cur_col_10[5]) { uint16_t white_bri10_1023 = (white_bri10 > 1023) ? 1023 : white_bri10; // max 1023 #ifdef ESP8266 - if ((PHILIPS == my_module_type) || (Settings.flag4.pwm_ct_mode)) { // channel 1 is the color tone, mapped to cold channel (0..255) + 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 @@ -2833,7 +2833,7 @@ void CmndDimmer(void) // Dimmer - - Decrement Dimmer in steps of 10 uint32_t dimmer; if (XdrvMailbox.index == 3) { - skip_light_fade = true; + TasmotaGlobal.skip_light_fade = true; XdrvMailbox.index = 0; } else if (XdrvMailbox.index > 2) { @@ -2878,11 +2878,11 @@ void CmndDimmer(void) } #endif // USE_PWM_DIMMER && USE_DEVICE_GROUPS Light.update = true; - if (skip_light_fade) LightAnimate(); + if (TasmotaGlobal.skip_light_fade) LightAnimate(); } else { ResponseCmndNumber(dimmer); } - skip_light_fade = false; + TasmotaGlobal.skip_light_fade = false; } void CmndDimmerRange(void) @@ -3093,7 +3093,7 @@ void CmndUndocA(void) scolor[6] = '\0'; // RGB only Response_P(PSTR("%s,%d,%d,%d,%d,%d"), scolor, Settings.light_fade, Settings.light_correction, Settings.light_scheme, Settings.light_speed, Settings.light_width); MqttPublishPrefixTopic_P(STAT, XdrvMailbox.topic); - mqtt_data[0] = '\0'; + ResponseClear(); } /*********************************************************************************************\ @@ -3107,7 +3107,7 @@ bool Xdrv04(uint8_t function) if (FUNC_MODULE_INIT == function) { return LightModuleInit(); } - else if (light_type) { + else if (TasmotaGlobal.light_type) { switch (function) { case FUNC_SERIAL: result = XlgtCall(FUNC_SERIAL); diff --git a/tasmota/xdrv_05_irremote.ino b/tasmota/xdrv_05_irremote.ino index da60ed813..bcca685c5 100644 --- a/tasmota/xdrv_05_irremote.ino +++ b/tasmota/xdrv_05_irremote.ino @@ -62,7 +62,7 @@ def ir_expand(ir_compact): #include #include -enum IrErrors { IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND }; +enum IrErrors { IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND, IE_PROTO_UNSUPPORTED }; const char kIrRemoteCommands[] PROGMEM = "|" D_CMND_IRSEND ; @@ -72,7 +72,7 @@ void (* const IrRemoteCommand[])(void) PROGMEM = { /*********************************************************************************************\ * Class used to make a compact IR Raw format. - * + * * We round timings to the closest 10ms value, * and store up to last 26 values with seen. * A value already seen is encoded with a letter indicating the position in the table. @@ -215,7 +215,7 @@ void IrReceiveCheck(void) ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":\"")); size_t rawlen = results.rawlen; uint32_t i; - + for (i = 1; i < rawlen; i++) { // round to closest 10ms uint32_t raw_val_millis = results.rawbuf[i] * kRawTick; @@ -232,7 +232,7 @@ void IrReceiveCheck(void) prev_number = true; } ir_high = !ir_high; - if (strlen(mqtt_data) > sizeof(mqtt_data) - 40) { break; } // Quit if char string becomes too long + if (strlen(TasmotaGlobal.mqtt_data) > sizeof(TasmotaGlobal.mqtt_data) - 40) { break; } // Quit if char string becomes too long } uint16_t extended_length = getCorrectedRawLength(&results); ResponseAppend_P(PSTR("\",\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), extended_length, i -1, results.overflow); @@ -274,7 +274,7 @@ uint32_t IrRemoteCmndIrSendJson(void) uint16_t bits = root.getUInt(PSTR(D_JSON_IR_BITS), 0); uint64_t data = root.getULong(PSTR(D_JSON_IR_DATA), 0); uint16_t repeat = root.getUInt(PSTR(D_JSON_IR_REPEAT), 0); - + // check if the IRSend is great than repeat if (XdrvMailbox.index > repeat + 1) { repeat = XdrvMailbox.index - 1; @@ -307,7 +307,7 @@ uint32_t IrRemoteCmndIrSendJson(void) #endif default: irsend_active = false; - ResponseCmndChar(D_JSON_PROTOCOL_NOT_SUPPORTED); + return IE_PROTO_UNSUPPORTED; } return IE_NO_ERROR; @@ -336,6 +336,9 @@ void IrRemoteCmndResponse(uint32_t error) case IE_INVALID_JSON: ResponseCmndChar_P(PSTR(D_JSON_INVALID_JSON)); break; + case IE_PROTO_UNSUPPORTED: + ResponseCmndChar(D_JSON_PROTOCOL_NOT_SUPPORTED); + break; case IE_SYNTAX_IRSEND: Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_PROTOCOL ", " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}")); break; diff --git a/tasmota/xdrv_05_irremote_full.ino b/tasmota/xdrv_05_irremote_full.ino index 622bfba55..a64e87aff 100644 --- a/tasmota/xdrv_05_irremote_full.ino +++ b/tasmota/xdrv_05_irremote_full.ino @@ -76,7 +76,7 @@ void (* const IrRemoteCommand[])(void) PROGMEM = { /*********************************************************************************************\ * Class used to make a compact IR Raw format. - * + * * We round timings to the closest 10ms value, * and store up to last 26 values with seen. * A value already seen is encoded with a letter indicating the position in the table. @@ -303,7 +303,7 @@ void IrReceiveCheck(void) ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":\"")); size_t rawlen = results.rawlen; uint32_t i; - + for (i = 1; i < rawlen; i++) { // round to closest 10ms uint32_t raw_val_millis = results.rawbuf[i] * kRawTick; @@ -320,7 +320,7 @@ void IrReceiveCheck(void) prev_number = true; } ir_high = !ir_high; - if (strlen(mqtt_data) > sizeof(mqtt_data) - 40) { break; } // Quit if char string becomes too long + if (strlen(TasmotaGlobal.mqtt_data) > sizeof(TasmotaGlobal.mqtt_data) - 40) { break; } // Quit if char string becomes too long } uint16_t extended_length = getCorrectedRawLength(&results); ResponseAppend_P(PSTR("\",\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), extended_length, i -1, results.overflow); @@ -646,7 +646,7 @@ uint32_t IrRemoteSendRawFormatted(char ** pp, uint32_t count, uint32_t repeat) { return IE_NO_ERROR; } -// +// // Parse data as compact or standard form // // In: diff --git a/tasmota/xdrv_06_snfbridge.ino b/tasmota/xdrv_06_snfbridge.ino index 228564a45..b7516fd2b 100644 --- a/tasmota/xdrv_06_snfbridge.ino +++ b/tasmota/xdrv_06_snfbridge.ino @@ -213,14 +213,14 @@ void SonoffBridgeReceivedRaw(void) // Decoding according to https://github.com/Portisch/RF-Bridge-EFM8BB1 uint8_t buckets = 0; - if (0xB1 == serial_in_buffer[1]) { buckets = serial_in_buffer[2] << 1; } // Bucket sniffing + if (0xB1 == TasmotaGlobal.serial_in_buffer[1]) { buckets = TasmotaGlobal.serial_in_buffer[2] << 1; } // Bucket sniffing ResponseTime_P(PSTR(",\"" D_CMND_RFRAW "\":{\"" D_JSON_DATA "\":\"")); - for (uint32_t i = 0; i < serial_in_byte_counter; i++) { - ResponseAppend_P(PSTR("%02X"), serial_in_buffer[i]); - if (0xB1 == serial_in_buffer[1]) { + for (uint32_t i = 0; i < TasmotaGlobal.serial_in_byte_counter; i++) { + ResponseAppend_P(PSTR("%02X"), TasmotaGlobal.serial_in_buffer[i]); + if (0xB1 == TasmotaGlobal.serial_in_buffer[1]) { if ((i > 3) && buckets) { buckets--; } - if ((i < 3) || (buckets % 2) || (i == serial_in_byte_counter -2)) { + if ((i < 3) || (buckets % 2) || (i == TasmotaGlobal.serial_in_byte_counter -2)) { ResponseAppend_P(PSTR(" ")); } } @@ -249,16 +249,16 @@ void SonoffBridgeReceived(void) AddLogSerial(LOG_LEVEL_DEBUG); - if (0xA2 == serial_in_buffer[0]) { // Learn timeout + if (0xA2 == TasmotaGlobal.serial_in_buffer[0]) { // Learn timeout SonoffBridgeLearnFailed(); } - else if (0xA3 == serial_in_buffer[0]) { // Learned A3 20 F8 01 18 03 3E 2E 1A 22 55 + else if (0xA3 == TasmotaGlobal.serial_in_buffer[0]) { // Learned A3 20 F8 01 18 03 3E 2E 1A 22 55 SnfBridge.learn_active = 0; - low_time = serial_in_buffer[3] << 8 | serial_in_buffer[4]; // Low time in uSec - high_time = serial_in_buffer[5] << 8 | serial_in_buffer[6]; // High time in uSec + low_time = TasmotaGlobal.serial_in_buffer[3] << 8 | TasmotaGlobal.serial_in_buffer[4]; // Low time in uSec + high_time = TasmotaGlobal.serial_in_buffer[5] << 8 | TasmotaGlobal.serial_in_buffer[6]; // High time in uSec if (low_time && high_time) { for (uint32_t i = 0; i < 9; i++) { - Settings.rf_code[SnfBridge.learn_key][i] = serial_in_buffer[i +1]; + Settings.rf_code[SnfBridge.learn_key][i] = TasmotaGlobal.serial_in_buffer[i +1]; } Response_P(S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, SnfBridge.learn_key, D_JSON_LEARNED); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RFKEY)); @@ -266,14 +266,14 @@ void SonoffBridgeReceived(void) SonoffBridgeLearnFailed(); } } - else if (0xA4 == serial_in_buffer[0]) { // Received RF data A4 20 EE 01 18 03 3E 2E 1A 22 55 + else if (0xA4 == TasmotaGlobal.serial_in_buffer[0]) { // Received RF data A4 20 EE 01 18 03 3E 2E 1A 22 55 if (SnfBridge.learn_active) { SonoffBridgeLearnFailed(); } else { - sync_time = serial_in_buffer[1] << 8 | serial_in_buffer[2]; // Sync time in uSec - low_time = serial_in_buffer[3] << 8 | serial_in_buffer[4]; // Low time in uSec - high_time = serial_in_buffer[5] << 8 | serial_in_buffer[6]; // High time in uSec - received_id = serial_in_buffer[7] << 16 | serial_in_buffer[8] << 8 | serial_in_buffer[9]; + sync_time = TasmotaGlobal.serial_in_buffer[1] << 8 | TasmotaGlobal.serial_in_buffer[2]; // Sync time in uSec + low_time = TasmotaGlobal.serial_in_buffer[3] << 8 | TasmotaGlobal.serial_in_buffer[4]; // Low time in uSec + high_time = TasmotaGlobal.serial_in_buffer[5] << 8 | TasmotaGlobal.serial_in_buffer[6]; // High time in uSec + received_id = TasmotaGlobal.serial_in_buffer[7] << 16 | TasmotaGlobal.serial_in_buffer[8] << 8 | TasmotaGlobal.serial_in_buffer[9]; unsigned long now = millis(); if (!((received_id == SnfBridge.last_received_id) && (now - SnfBridge.last_time < SFB_TIME_AVOID_DUPLICATE))) { @@ -312,45 +312,45 @@ bool SonoffBridgeSerialInput(void) if (SnfBridge.receive_flag) { if (SnfBridge.receive_raw_flag) { - if (!serial_in_byte_counter) { - serial_in_buffer[serial_in_byte_counter++] = 0xAA; + if (!TasmotaGlobal.serial_in_byte_counter) { + TasmotaGlobal.serial_in_buffer[TasmotaGlobal.serial_in_byte_counter++] = 0xAA; } - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - if (serial_in_byte_counter == 3) { - if ((0xA6 == serial_in_buffer[1]) || (0xAB == serial_in_buffer[1])) { // AA A6 06 023908010155 55 - 06 is receive_len - receive_len = serial_in_buffer[2] + 4; // Get at least receive_len bytes + TasmotaGlobal.serial_in_buffer[TasmotaGlobal.serial_in_byte_counter++] = TasmotaGlobal.serial_in_byte; + if (TasmotaGlobal.serial_in_byte_counter == 3) { + if ((0xA6 == TasmotaGlobal.serial_in_buffer[1]) || (0xAB == TasmotaGlobal.serial_in_buffer[1])) { // AA A6 06 023908010155 55 - 06 is receive_len + receive_len = TasmotaGlobal.serial_in_buffer[2] + 4; // Get at least receive_len bytes } } - if ((!receive_len && (0x55 == serial_in_byte)) || (receive_len && (serial_in_byte_counter == receive_len))) { // 0x55 - End of text + if ((!receive_len && (0x55 == TasmotaGlobal.serial_in_byte)) || (receive_len && (TasmotaGlobal.serial_in_byte_counter == receive_len))) { // 0x55 - End of text SonoffBridgeReceivedRaw(); SnfBridge.receive_flag = 0; return 1; } } - else if (!((0 == serial_in_byte_counter) && (0 == serial_in_byte))) { // Skip leading 0 - if (0 == serial_in_byte_counter) { + else if (!((0 == TasmotaGlobal.serial_in_byte_counter) && (0 == TasmotaGlobal.serial_in_byte))) { // Skip leading 0 + if (0 == TasmotaGlobal.serial_in_byte_counter) { SnfBridge.expected_bytes = 2; // 0xA0, 0xA1, 0xA2 - if (serial_in_byte >= 0xA3) { + if (TasmotaGlobal.serial_in_byte >= 0xA3) { SnfBridge.expected_bytes = 11; // 0xA3, 0xA4, 0xA5 } - if (serial_in_byte == 0xA6) { + if (TasmotaGlobal.serial_in_byte == 0xA6) { SnfBridge.expected_bytes = 0; // 0xA6 and up supported by Portisch firmware only - serial_in_buffer[serial_in_byte_counter++] = 0xAA; + TasmotaGlobal.serial_in_buffer[TasmotaGlobal.serial_in_byte_counter++] = 0xAA; SnfBridge.receive_raw_flag = 1; } } - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - if ((SnfBridge.expected_bytes == serial_in_byte_counter) && (0x55 == serial_in_byte)) { // 0x55 - End of text + TasmotaGlobal.serial_in_buffer[TasmotaGlobal.serial_in_byte_counter++] = TasmotaGlobal.serial_in_byte; + if ((SnfBridge.expected_bytes == TasmotaGlobal.serial_in_byte_counter) && (0x55 == TasmotaGlobal.serial_in_byte)) { // 0x55 - End of text SonoffBridgeReceived(); SnfBridge.receive_flag = 0; return 1; } } - serial_in_byte = 0; + TasmotaGlobal.serial_in_byte = 0; } - if (0xAA == serial_in_byte) { // 0xAA - Start of text - serial_in_byte_counter = 0; - serial_in_byte = 0; + if (0xAA == TasmotaGlobal.serial_in_byte) { // 0xAA - Start of text + TasmotaGlobal.serial_in_byte_counter = 0; + TasmotaGlobal.serial_in_byte = 0; SnfBridge.receive_flag = 1; receive_len = 0; } @@ -563,7 +563,7 @@ bool Xdrv06(uint8_t function) bool result = false; #ifdef ESP8266 - if (SONOFF_BRIDGE == my_module_type) { + if (SONOFF_BRIDGE == TasmotaGlobal.module_type) { switch (function) { case FUNC_SERIAL: result = SonoffBridgeSerialInput(); diff --git a/tasmota/xdrv_07_domoticz.ino b/tasmota/xdrv_07_domoticz.ino index 2236b124d..842c1a35f 100644 --- a/tasmota/xdrv_07_domoticz.ino +++ b/tasmota/xdrv_07_domoticz.ino @@ -112,7 +112,7 @@ void DomoticzUpdateFanState(void) { void MqttPublishDomoticzPowerState(uint8_t device) { if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT if (device < 1) { device = 1; } - if ((device > devices_present) || (device > MAX_DOMOTICZ_IDX)) { return; } + if ((device > TasmotaGlobal.devices_present) || (device > MAX_DOMOTICZ_IDX)) { return; } if (Settings.domoticz_relay_idx[device -1]) { #ifdef USE_SHUTTER if (domoticz_is_shutter) { @@ -127,7 +127,7 @@ void MqttPublishDomoticzPowerState(uint8_t device) { char svalue[8]; // Dimmer value snprintf_P(svalue, sizeof(svalue), PSTR("%d"), Settings.light_dimmer); - Response_P(DOMOTICZ_MESSAGE, (int)Settings.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0, (light_type) ? svalue : "", DomoticzBatteryQuality(), DomoticzRssiQuality()); + Response_P(DOMOTICZ_MESSAGE, (int)Settings.domoticz_relay_idx[device -1], (TasmotaGlobal.power & (1 << (device -1))) ? 1 : 0, (TasmotaGlobal.light_type) ? svalue : "", DomoticzBatteryQuality(), DomoticzRssiQuality()); MqttPublish(domoticz_in_topic); #ifdef USE_SONOFF_IFAN } @@ -151,7 +151,7 @@ void DomoticzMqttUpdate(void) { domoticz_update_timer--; if (domoticz_update_timer <= 0) { domoticz_update_timer = Settings.domoticz_update_timer; - for (uint32_t i = 1; i <= devices_present; i++) { + for (uint32_t i = 1; i <= TasmotaGlobal.devices_present; i++) { #ifdef USE_SHUTTER if (domoticz_is_shutter) { @@ -175,7 +175,7 @@ void DomoticzMqttUpdate(void) { } void DomoticzMqttSubscribe(void) { - uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present; + uint8_t maxdev = (TasmotaGlobal.devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : TasmotaGlobal.devices_present; for (uint32_t i = 0; i < maxdev; i++) { if (Settings.domoticz_relay_idx[i]) { domoticz_subscribe = true; @@ -223,7 +223,7 @@ bool DomoticzMqttData(void) { bool found = false; if ((idx > 0) && (nvalue >= 0) && (nvalue <= 15)) { - uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present; + uint8_t maxdev = (TasmotaGlobal.devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : TasmotaGlobal.devices_present; for (uint32_t i = 0; i < maxdev; i++) { if (idx == Settings.domoticz_relay_idx[i]) { bool iscolordimmer = strcmp_P(domoticz.getStr(PSTR("dtype")), PSTR("Color Switch")) == 0; @@ -293,7 +293,7 @@ bool DomoticzMqttData(void) { } else { return true; // Invalid data } - if (light_type && (Settings.light_dimmer == nvalue) && ((power >> i) &1)) { + if (TasmotaGlobal.light_type && (Settings.light_dimmer == nvalue) && ((TasmotaGlobal.power >> i) &1)) { return true; // State already set } snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_DIMMER)); @@ -302,10 +302,10 @@ bool DomoticzMqttData(void) { } else #endif // USE_LIGHT if (1 == nvalue || 0 == nvalue) { - if (((power >> i) &1) == (power_t)nvalue) { + if (((TasmotaGlobal.power >> i) &1) == (power_t)nvalue) { return true; // Stop loop } - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_POWER "%s"), (devices_present > 1) ? stemp1 : ""); + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_POWER "%s"), (TasmotaGlobal.devices_present > 1) ? stemp1 : ""); snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); found = true; } @@ -381,9 +381,9 @@ void DomoticzSensor(uint8_t idx, char *data) { if (Settings.domoticz_sensor_idx[idx]) { char dmess[128]; // {"idx":26700,"nvalue":0,"svalue":"22330.1;10234.4;22000.5;10243.4;1006;3000","Battery":100,"RSSI":10} - memcpy(dmess, mqtt_data, sizeof(dmess)); + memcpy(dmess, TasmotaGlobal.mqtt_data, sizeof(dmess)); DomoticzSendData(idx, Settings.domoticz_sensor_idx[idx], data); - memcpy(mqtt_data, dmess, sizeof(dmess)); + memcpy(TasmotaGlobal.mqtt_data, dmess, sizeof(dmess)); } } @@ -448,7 +448,7 @@ void CmndDomoticzIdx(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { if (XdrvMailbox.payload >= 0) { Settings.domoticz_relay_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } ResponseCmndIdxNumber(Settings.domoticz_relay_idx[XdrvMailbox.index -1]); } @@ -560,7 +560,7 @@ void HandleDomoticzConfiguration(void) { WSContentSendStyle(); WSContentSend_P(HTTP_FORM_DOMOTICZ); for (uint32_t i = 0; i < MAX_DOMOTICZ_IDX; i++) { - if (i < devices_present) { + if (i < TasmotaGlobal.devices_present) { WSContentSend_P(HTTP_FORM_DOMOTICZ_RELAY, i +1, i, Settings.domoticz_relay_idx[i], i +1, i, Settings.domoticz_key_idx[i]); diff --git a/tasmota/xdrv_08_serial_bridge.ino b/tasmota/xdrv_08_serial_bridge.ino index cf0a1d386..01e1cc5f0 100644 --- a/tasmota/xdrv_08_serial_bridge.ino +++ b/tasmota/xdrv_08_serial_bridge.ino @@ -109,7 +109,7 @@ void SerialBridgeInit(void) if (SerialBridgeSerial->begin(Settings.sbaudrate * 300)) { // Baud rate is stored div 300 so it fits into 16 bits if (SerialBridgeSerial->hardwareSerial()) { ClaimSerial(); - serial_bridge_buffer = serial_in_buffer; // Use idle serial buffer to save RAM + serial_bridge_buffer = TasmotaGlobal.serial_in_buffer; // Use idle serial buffer to save RAM } else { serial_bridge_buffer = (char*)(malloc(SERIAL_BRIDGE_BUFFER_SIZE)); } diff --git a/tasmota/xdrv_09_timers.ino b/tasmota/xdrv_09_timers.ino index f398b0922..6ac31c1c3 100644 --- a/tasmota/xdrv_09_timers.ino +++ b/tasmota/xdrv_09_timers.ino @@ -177,7 +177,7 @@ void ApplyTimerOffsets(Timer *duskdawn) if (hour[mode]==255) { // Permanent day/night sets the unreachable limit values if ((Settings.latitude > 0) != (RtcTime.month>=4 && RtcTime.month<=9)) { - duskdawn->time=2046; // permanent night + duskdawn->time=2046; // permanent night } else { duskdawn->time=2047; // permanent day } @@ -256,7 +256,7 @@ void TimerEverySecond(void) if (RtcTime.valid) { if (!RtcTime.hour && !RtcTime.minute && !RtcTime.second) { TimerSetRandomWindows(); } // Midnight if (Settings.flag3.timers_enable && // CMND_TIMERS - (uptime > 60) && (RtcTime.minute != timer_last_minute)) { // Execute from one minute after restart every minute only once + (TasmotaGlobal.uptime > 60) && (RtcTime.minute != timer_last_minute)) { // Execute from one minute after restart every minute only once timer_last_minute = RtcTime.minute; int32_t time = (RtcTime.hour *60) + RtcTime.minute; uint8_t days = 1 << (RtcTime.day_of_week -1); @@ -290,7 +290,7 @@ void TimerEverySecond(void) XdrvRulesProcess(); } else #endif // USE_RULES - if (devices_present) { ExecuteCommandPower(xtimer.device +1, xtimer.power, SRC_TIMER); } + if (TasmotaGlobal.devices_present) { ExecuteCommandPower(xtimer.device +1, xtimer.power, SRC_TIMER); } } } } @@ -311,7 +311,7 @@ void PrepShowTimer(uint32_t index) char soutput[80]; soutput[0] = '\0'; - if (devices_present) { + if (TasmotaGlobal.devices_present) { snprintf_P(soutput, sizeof(soutput), PSTR(",\"" D_JSON_TIMER_OUTPUT "\":%d"), xtimer.device +1); } #ifdef USE_SUNRISE @@ -350,7 +350,7 @@ void CmndTimer(void) } else { //#ifndef USE_RULES #if defined(USE_RULES)==0 && defined(USE_SCRIPT)==0 - if (devices_present) { + if (TasmotaGlobal.devices_present) { #endif JsonParser parser(XdrvMailbox.data); JsonParserObject root = parser.getRootObject(); @@ -425,12 +425,12 @@ void CmndTimer(void) val = root[PSTR(D_JSON_TIMER_OUTPUT)]; if (val) { uint8_t device = (val.getUInt() -1) & 0x0F; - Settings.timer[index].device = (device < devices_present) ? device : 0; + Settings.timer[index].device = (device < TasmotaGlobal.devices_present) ? device : 0; } val = root[PSTR(D_JSON_TIMER_ACTION)]; if (val) { uint8_t action = val.getUInt() & 0x03; - Settings.timer[index].power = (devices_present) ? action : 3; // If no devices than only allow rules + Settings.timer[index].power = (TasmotaGlobal.devices_present) ? action : 3; // If no devices than only allow rules } index++; @@ -482,7 +482,7 @@ void CmndTimers(void) jsflg = 0; } } - mqtt_data[0] = '\0'; + ResponseClear(); } #ifdef USE_SUNRISE @@ -856,10 +856,10 @@ void HandleTimerConfiguration(void) #ifdef USE_SUNRISE WSContentSend_P(HTTP_TIMER_SCRIPT2); #endif // USE_SUNRISE - WSContentSend_P(HTTP_TIMER_SCRIPT3, devices_present); - WSContentSend_P(HTTP_TIMER_SCRIPT4, WebColor(COL_TIMER_TAB_BACKGROUND), WebColor(COL_TIMER_TAB_TEXT), WebColor(COL_FORM), WebColor(COL_TEXT), devices_present); - WSContentSend_P(HTTP_TIMER_SCRIPT5, MAX_TIMERS, devices_present); - WSContentSend_P(HTTP_TIMER_SCRIPT6, devices_present); + WSContentSend_P(HTTP_TIMER_SCRIPT3, TasmotaGlobal.devices_present); + WSContentSend_P(HTTP_TIMER_SCRIPT4, WebColor(COL_TIMER_TAB_BACKGROUND), WebColor(COL_TIMER_TAB_TEXT), WebColor(COL_FORM), WebColor(COL_TEXT), TasmotaGlobal.devices_present); + WSContentSend_P(HTTP_TIMER_SCRIPT5, MAX_TIMERS, TasmotaGlobal.devices_present); + WSContentSend_P(HTTP_TIMER_SCRIPT6, TasmotaGlobal.devices_present); WSContentSendStyle_P(HTTP_TIMER_STYLE, WebColor(COL_FORM)); WSContentSend_P(HTTP_FORM_TIMER1, (Settings.flag3.timers_enable) ? " checked" : ""); // CMND_TIMERS for (uint32_t i = 0; i < MAX_TIMERS; i++) { @@ -924,7 +924,7 @@ bool Xdrv09(uint8_t function) #if defined(USE_RULES) || defined(USE_SCRIPT) WSContentSend_P(HTTP_BTN_MENU_TIMER); #else - if (devices_present) { WSContentSend_P(HTTP_BTN_MENU_TIMER); } + if (TasmotaGlobal.devices_present) { WSContentSend_P(HTTP_BTN_MENU_TIMER); } #endif // USE_RULES break; case FUNC_WEB_ADD_HANDLER: diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino index accb43042..528eb752b 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/xdrv_10_rules.ino @@ -725,7 +725,7 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved) RulesVarReplace(commands, F("%UTCTIME%"), String(UtcTime())); RulesVarReplace(commands, F("%UPTIME%"), String(MinutesUptime())); RulesVarReplace(commands, F("%TIMESTAMP%"), GetDateAndTime(DT_LOCAL)); - RulesVarReplace(commands, F("%TOPIC%"), mqtt_topic); + RulesVarReplace(commands, F("%TOPIC%"), TasmotaGlobal.mqtt_topic); snprintf_P(stemp, sizeof(stemp), PSTR("%06X"), ESP_getChipId()); RulesVarReplace(commands, F("%DEVICEID%"), stemp); String mac_address = WiFi.macAddress(); @@ -805,7 +805,7 @@ bool RulesProcessEvent(char *json_event) bool RulesProcess(void) { - return RulesProcessEvent(mqtt_data); + return RulesProcessEvent(TasmotaGlobal.mqtt_data); } void RulesInit(void) @@ -815,7 +815,7 @@ void RulesInit(void) // and indicates scripter do not use compress bitWrite(Settings.rule_once, 6, 0); - rules_flag.data = 0; + TasmotaGlobal.rules_flag.data = 0; for (uint32_t i = 0; i < MAX_RULE_SETS; i++) { if (0 == GetRuleLen(i)) { bitWrite(Settings.rule_enabled, i, 0); @@ -830,10 +830,10 @@ void RulesEvery50ms(void) if (Settings.rule_enabled && !Rules.busy) { // Any rule enabled char json_event[120]; - if (-1 == Rules.new_power) { Rules.new_power = power; } + if (-1 == Rules.new_power) { Rules.new_power = TasmotaGlobal.power; } if (Rules.new_power != Rules.old_power) { if (Rules.old_power != -1) { - for (uint32_t i = 0; i < devices_present; i++) { + for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { uint8_t new_state = (Rules.new_power >> i) &1; if (new_state != ((Rules.old_power >> i) &1)) { snprintf_P(json_event, sizeof(json_event), PSTR("{\"Power%d\":{\"State\":%d}}"), i +1, new_state); @@ -842,7 +842,7 @@ void RulesEvery50ms(void) } } else { // Boot time POWER OUTPUTS (Relays) Status - for (uint32_t i = 0; i < devices_present; i++) { + for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { uint8_t new_state = (Rules.new_power >> i) &1; snprintf_P(json_event, sizeof(json_event), PSTR("{\"Power%d\":{\"Boot\":%d}}"), i +1, new_state); RulesProcessEvent(json_event); @@ -854,7 +854,7 @@ void RulesEvery50ms(void) #else if (PinUsed(GPIO_SWT1, i)) { #endif // USE_TM1638 - snprintf_P(json_event, sizeof(json_event), PSTR("{\"" D_JSON_SWITCH "%d\":{\"Boot\":%d}}"), i +1, (SwitchState(i))); + snprintf_P(json_event, sizeof(json_event), PSTR("{\"%s\":{\"Boot\":%d}}"), GetSwitchText(i).c_str(), (SwitchState(i))); RulesProcessEvent(json_event); } } @@ -911,11 +911,11 @@ void RulesEvery50ms(void) } } } - else if (rules_flag.data) { + else if (TasmotaGlobal.rules_flag.data) { uint16_t mask = 1; for (uint32_t i = 0; i < MAX_RULES_FLAG; i++) { - if (rules_flag.data & mask) { - rules_flag.data ^= mask; + if (TasmotaGlobal.rules_flag.data & mask) { + TasmotaGlobal.rules_flag.data ^= mask; json_event[0] = '\0'; switch (i) { case 0: strncpy_P(json_event, PSTR("{\"System\":{\"Init\":1}}"), sizeof(json_event)); break; @@ -947,16 +947,16 @@ uint8_t rules_xsns_index = 0; void RulesEvery100ms(void) { - if (Settings.rule_enabled && !Rules.busy && (uptime > 4)) { // Any rule enabled and allow 4 seconds start-up time for sensors (#3811) - mqtt_data[0] = '\0'; - int tele_period_save = tele_period; - tele_period = 2; // Do not allow HA updates during next function call + if (Settings.rule_enabled && !Rules.busy && (TasmotaGlobal.uptime > 4)) { // Any rule enabled and allow 4 seconds start-up time for sensors (#3811) + ResponseClear(); + int tele_period_save = TasmotaGlobal.tele_period; + TasmotaGlobal.tele_period = 2; // Do not allow HA updates during next function call XsnsNextCall(FUNC_JSON_APPEND, rules_xsns_index); // ,"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} - tele_period = tele_period_save; - if (strlen(mqtt_data)) { - mqtt_data[0] = '{'; // {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} + TasmotaGlobal.tele_period = tele_period_save; + if (strlen(TasmotaGlobal.mqtt_data)) { + TasmotaGlobal.mqtt_data[0] = '{'; // {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} ResponseJsonEnd(); - RulesProcessEvent(mqtt_data); + RulesProcessEvent(TasmotaGlobal.mqtt_data); } } } @@ -967,7 +967,7 @@ void RulesEverySecond(void) char json_event[120]; if (RtcTime.valid) { - if ((uptime > 60) && (RtcTime.minute != Rules.last_minute)) { // Execute from one minute after restart every minute only once + if ((TasmotaGlobal.uptime > 60) && (RtcTime.minute != Rules.last_minute)) { // Execute from one minute after restart every minute only once Rules.last_minute = RtcTime.minute; snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Minute\":%d}}"), MinutesPastMidnight()); RulesProcessEvent(json_event); @@ -1882,12 +1882,12 @@ void ExecuteCommandBlock(const char * commands, int len) String sCurrentCommand = oneCommand; sCurrentCommand.trim(); if (sCurrentCommand.length() > 0 - && backlog.size() < MAX_BACKLOG && !backlog_mutex) + && backlog.size() < MAX_BACKLOG && !TasmotaGlobal.backlog_mutex) { //Insert into backlog - backlog_mutex = true; + TasmotaGlobal.backlog_mutex = true; backlog.add(insertPosition, sCurrentCommand); - backlog_mutex = false; + TasmotaGlobal.backlog_mutex = false; insertPosition++; } } @@ -2030,7 +2030,7 @@ void CmndRule(void) CmndRule(); MqttPublishPrefixTopic_P(RESULT_OR_STAT, XdrvMailbox.command); } - mqtt_data[0] = '\0'; // Disable further processing + ResponseClear(); // Disable further processing return; } uint8_t index = XdrvMailbox.index; @@ -2099,10 +2099,10 @@ void CmndRule(void) rule = rule.substring(0, MAX_RULE_SIZE); rule += F("..."); } - // snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s\",\"Once\":\"%s\",\"StopOnError\":\"%s\",\"Free\":%d,\"Rules\":\"%s\"}"), + // snprintf_P (TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), PSTR("{\"%s%d\":\"%s\",\"Once\":\"%s\",\"StopOnError\":\"%s\",\"Free\":%d,\"Rules\":\"%s\"}"), // XdrvMailbox.command, index, GetStateText(bitRead(Settings.rule_enabled, index -1)), GetStateText(bitRead(Settings.rule_once, index -1)), // GetStateText(bitRead(Settings.rule_stop, index -1)), sizeof(Settings.rules[index -1]) - strlen(Settings.rules[index -1]) -1, Settings.rules[index -1]); - snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s\",\"Once\":\"%s\",\"StopOnError\":\"%s\",\"Length\":%d,\"Free\":%d,\"Rules\":\"%s\"}"), + snprintf_P (TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), PSTR("{\"%s%d\":\"%s\",\"Once\":\"%s\",\"StopOnError\":\"%s\",\"Length\":%d,\"Free\":%d,\"Rules\":\"%s\"}"), XdrvMailbox.command, index, GetStateText(bitRead(Settings.rule_enabled, index -1)), GetStateText(bitRead(Settings.rule_once, index -1)), GetStateText(bitRead(Settings.rule_stop, index -1)), rule_len, MAX_RULE_SIZE - GetRuleLenStorage(index - 1), @@ -2121,7 +2121,7 @@ void CmndRuleTimer(void) Rules.timer[XdrvMailbox.index -1] = (XdrvMailbox.payload > 0) ? millis() + (1000 * XdrvMailbox.payload) : 0; #endif // USE_EXPRESSION } - mqtt_data[0] = '\0'; + ResponseClear(); for (uint32_t i = 0; i < MAX_RULE_TIMERS; i++) { ResponseAppend_P(PSTR("%c\"T%d\":%d"), (i) ? ',' : '{', i +1, (Rules.timer[i]) ? (Rules.timer[i] - millis()) / 1000 : 0); } @@ -2144,7 +2144,7 @@ void CmndVariable(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_RULE_VARS)) { if (!XdrvMailbox.usridx) { - mqtt_data[0] = '\0'; + ResponseClear(); for (uint32_t i = 0; i < MAX_RULE_VARS; i++) { ResponseAppend_P(PSTR("%c\"Var%d\":\"%s\""), (i) ? ',' : '{', i +1, rules_vars[i]); } @@ -2179,7 +2179,6 @@ void CmndMemory(void) char rules_mem[FLOATSZ]; dtostrfd(evaluateExpression(XdrvMailbox.data + 1, XdrvMailbox.data_len - 1), Settings.flag2.calc_resolution, rules_mem); SettingsUpdateText(SET_MEM1 + XdrvMailbox.index -1, rules_mem); - } else { SettingsUpdateText(SET_MEM1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data); } diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index 9725e94a2..2ef634dac 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -512,7 +512,7 @@ void ScriptEverySecond(void) { } void RulesTeleperiod(void) { - if (bitRead(Settings.rule_enabled, 0) && mqtt_data[0]) Run_Scripter(">T", 2, mqtt_data); + if (bitRead(Settings.rule_enabled, 0) && TasmotaGlobal.mqtt_data[0]) Run_Scripter(">T", 2, TasmotaGlobal.mqtt_data); } // EEPROM MACROS @@ -1019,7 +1019,7 @@ void Script_Stop_UDP(void) { } void Script_Init_UDP() { - if (global_state.network_down) return; + if (TasmotaGlobal.global_state.network_down) return; if (!glob_script_mem.udp_flags.udp_used) return; if (glob_script_mem.udp_flags.udp_connected) return; @@ -1033,7 +1033,7 @@ void Script_Init_UDP() { } void Script_PollUdp(void) { - if (global_state.network_down) return; + if (TasmotaGlobal.global_state.network_down) return; if (!glob_script_mem.udp_flags.udp_used) return; if (glob_script_mem.udp_flags.udp_connected ) { while (Script_PortUdp.parsePacket()) { @@ -1826,8 +1826,8 @@ chknext: case 'b': if (!strncmp(vname, "boot", 4)) { - if (rules_flag.system_boot) { - rules_flag.system_boot = 0; + if (TasmotaGlobal.rules_flag.system_boot) { + TasmotaGlobal.rules_flag.system_boot = 0; fvar = 1; } goto exit; @@ -2343,15 +2343,15 @@ chknext: break; case 'g': if (!strncmp(vname, "gtmp", 4)) { - fvar = global_temperature_celsius; + fvar = TasmotaGlobal.temperature_celsius; goto exit; } if (!strncmp(vname, "ghum", 4)) { - fvar = global_humidity; + fvar = TasmotaGlobal.humidity; goto exit; } if (!strncmp(vname, "gprs", 4)) { - fvar = global_pressure_hpa; + fvar = TasmotaGlobal.pressure_hpa; goto exit; } if (!strncmp(vname, "gtopic", 6)) { @@ -2534,21 +2534,21 @@ chknext: goto exit; } if (!strncmp(vname, "mqttc", 5)) { - if (rules_flag.mqtt_connected) { - rules_flag.mqtt_connected = 0; + if (TasmotaGlobal.rules_flag.mqtt_connected) { + TasmotaGlobal.rules_flag.mqtt_connected = 0; fvar = 1; } goto exit; } if (!strncmp(vname, "mqttd", 5)) { - if (rules_flag.mqtt_disconnected) { - rules_flag.mqtt_disconnected = 0; + if (TasmotaGlobal.rules_flag.mqtt_disconnected) { + TasmotaGlobal.rules_flag.mqtt_disconnected = 0; fvar = 1; } goto exit; } if (!strncmp(vname, "mqtts", 5)) { - fvar = !global_state.mqtt_down; + fvar = !TasmotaGlobal.global_state.mqtt_down; goto exit; } if (!strncmp(vname, "mp(", 3)) { @@ -2637,8 +2637,8 @@ chknext: } } */ - if ((gpiopin < ARRAY_SIZE(gpio_pin)) && (gpio_pin[gpiopin] > 0)) { - fvar = gpio_pin[gpiopin]; + if ((gpiopin < ARRAY_SIZE(TasmotaGlobal.gpio_pin)) && (TasmotaGlobal.gpio_pin[gpiopin] > 0)) { + fvar = TasmotaGlobal.gpio_pin[gpiopin]; // skip ] bracket len++; goto exit; @@ -2680,8 +2680,8 @@ chknext: if (!strncmp(vname, "pwr[", 4)) { GetNumericArgument(vname + 4, OPER_EQU, &fvar, 0); uint8_t index = fvar; - if (index<=devices_present) { - fvar = bitRead(power, index - 1); + if (index<=TasmotaGlobal.devices_present) { + fvar = bitRead(TasmotaGlobal.power, index - 1); } else { fvar = -1; } @@ -2854,7 +2854,7 @@ chknext: if (!strncmp(vname, "sht[", 4)) { GetNumericArgument(vname + 4, OPER_EQU, &fvar, 0); uint8_t index = fvar; - if (index<=shutters_present) { + if (index<=TasmotaGlobal.shutters_present) { fvar = Settings.shutter_position[index - 1]; } else { fvar = -1; @@ -2937,11 +2937,11 @@ chknext: goto exit_settable; } if (!strncmp(vname, "tinit", 5)) { - fvar = rules_flag.time_init; + fvar = TasmotaGlobal.rules_flag.time_init; goto exit; } if (!strncmp(vname, "tset", 4)) { - fvar = rules_flag.time_set; + fvar = TasmotaGlobal.rules_flag.time_set; goto exit; } if (!strncmp(vname, "tstamp", 6)) { @@ -3012,7 +3012,7 @@ chknext: goto exit; } if (!strncmp(vname, "upsecs", 6)) { - fvar = uptime; + fvar = TasmotaGlobal.uptime; goto exit; } if (!strncmp(vname, "upd[", 4)) { @@ -3125,21 +3125,21 @@ chknext: goto exit; } if (!strncmp(vname, "wific", 5)) { - if (rules_flag.wifi_connected) { - rules_flag.wifi_connected = 0; + if (TasmotaGlobal.rules_flag.wifi_connected) { + TasmotaGlobal.rules_flag.wifi_connected = 0; fvar = 1; } goto exit; } if (!strncmp(vname, "wifid", 5)) { - if (rules_flag.wifi_disconnected) { - rules_flag.wifi_disconnected = 0; + if (TasmotaGlobal.rules_flag.wifi_disconnected) { + TasmotaGlobal.rules_flag.wifi_disconnected = 0; fvar = 1; } goto exit; } if (!strncmp(vname, "wifis", 5)) { - fvar = !global_state.wifi_down; + fvar = !TasmotaGlobal.global_state.wifi_down; goto exit; } break; @@ -3555,7 +3555,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 *cp = log_data; + char *cp = TasmotaGlobal.log_data; strcpy(cp, s1); cp += strlen(s1); while (*str) { @@ -4495,16 +4495,16 @@ uint8_t script_xsns_index = 0; void ScripterEvery100ms(void) { - if (Settings.rule_enabled && (uptime > 4)) { - mqtt_data[0] = '\0'; - uint16_t script_tele_period_save = tele_period; - tele_period = 2; + if (Settings.rule_enabled && (TasmotaGlobal.uptime > 4)) { + ResponseClear(); + uint16_t script_tele_period_save = TasmotaGlobal.tele_period; + TasmotaGlobal.tele_period = 2; XsnsNextCall(FUNC_JSON_APPEND, script_xsns_index); - tele_period = script_tele_period_save; - if (strlen(mqtt_data)) { - mqtt_data[0] = '{'; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); - Run_Scripter(">T", 2, mqtt_data); + TasmotaGlobal.tele_period = script_tele_period_save; + if (strlen(TasmotaGlobal.mqtt_data)) { + TasmotaGlobal.mqtt_data[0] = '{'; + snprintf_P(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), PSTR("%s}"), TasmotaGlobal.mqtt_data); + Run_Scripter(">T", 2, TasmotaGlobal.mqtt_data); } } if (Settings.rule_enabled) { @@ -5517,14 +5517,14 @@ void Script_Check_Hue(String *response) { } // append response if (response) { - if (devices_present) { + if (TasmotaGlobal.devices_present) { *response += ",\""; } else { if (hue_devs>0) *response += ",\""; else *response += "\""; } - *response += String(EncodeLightId(hue_devs + devices_present + 1))+"\":"; + *response += String(EncodeLightId(hue_devs + TasmotaGlobal.devices_present + 1))+"\":"; Script_HueStatus(response, hue_devs); //AddLog_P2(LOG_LEVEL_INFO, PSTR("Hue: %s - %d "),response->c_str(), hue_devs); } @@ -5571,7 +5571,7 @@ void Script_Handle_Hue(String *path) { bool resp = false; uint8_t device = DecodeLightId(atoi(path->c_str())); - uint8_t index = device - devices_present - 1; + uint8_t index = device - TasmotaGlobal.devices_present - 1; if (Webserver->args()) { response = "["; @@ -5784,7 +5784,7 @@ bool ScriptCommand(void) { } else { if ('>' == XdrvMailbox.data[0]) { // execute script - snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\"}"), command,XdrvMailbox.data); + snprintf_P (TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), PSTR("{\"%s\":\"%s\"}"), command,XdrvMailbox.data); if (bitRead(Settings.rule_enabled, 0)) { for (uint8_t count = 0; count, [, ] String result = ScriptSubscribe(XdrvMailbox.data, XdrvMailbox.data_len); @@ -7231,7 +7231,7 @@ uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core, uint32 // get tesla powerwall info page json string uint32_t call2https(const char *host, const char *path) { - if (global_state.wifi_down) return 1; + if (TasmotaGlobal.global_state.wifi_down) return 1; uint32_t status = 0; #ifdef ESP32 WiFiClientSecure *httpsClient; @@ -7481,7 +7481,7 @@ bool Xdrv10(uint8_t function) break; case FUNC_RULES_PROCESS: if (bitRead(Settings.rule_enabled, 0)) { - Run_Scripter(">E", 2, mqtt_data); + Run_Scripter(">E", 2, TasmotaGlobal.mqtt_data); result = event_handeled; } break; diff --git a/tasmota/xdrv_11_knx.ino b/tasmota/xdrv_11_knx.ino index 1e3a12c7c..ac5bb080d 100644 --- a/tasmota/xdrv_11_knx.ino +++ b/tasmota/xdrv_11_knx.ino @@ -468,45 +468,45 @@ void KNX_INIT(void) // and activate options according to the hardware /*for (uint32_t i = GPIO_REL1; i < GPIO_REL8 + 1; ++i) { - if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_REL1].show = true; } + if (GetUsedInModule(i, TasmotaGlobal.my_module.io)) { device_param[i - GPIO_REL1].show = true; } } for (uint32_t i = GPIO_REL1_INV; i < GPIO_REL8_INV + 1; ++i) { - if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_REL1_INV].show = true; } + if (GetUsedInModule(i, TasmotaGlobal.my_module.io)) { device_param[i - GPIO_REL1_INV].show = true; } }*/ - for (uint32_t i = 0; i < devices_present; ++i) + for (uint32_t i = 0; i < TasmotaGlobal.devices_present; ++i) { device_param[i].show = true; } for (uint32_t i = GPIO_SWT1; i < GPIO_SWT1 + 4; ++i) { - if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_SWT1 + 8].show = true; } + if (GetUsedInModule(i, TasmotaGlobal.my_module.io)) { device_param[i - GPIO_SWT1 + 8].show = true; } } for (uint32_t i = GPIO_KEY1; i < GPIO_KEY1 + 4; ++i) { - if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_KEY1 + 8].show = true; } + if (GetUsedInModule(i, TasmotaGlobal.my_module.io)) { device_param[i - GPIO_KEY1 + 8].show = true; } } for (uint32_t i = GPIO_SWT1_NP; i < GPIO_SWT1_NP + 4; ++i) { - if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_SWT1_NP + 8].show = true; } + if (GetUsedInModule(i, TasmotaGlobal.my_module.io)) { device_param[i - GPIO_SWT1_NP + 8].show = true; } } for (uint32_t i = GPIO_KEY1_NP; i < GPIO_KEY1_NP + 4; ++i) { - if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_KEY1_NP + 8].show = true; } + if (GetUsedInModule(i, TasmotaGlobal.my_module.io)) { device_param[i - GPIO_KEY1_NP + 8].show = true; } } - if (GetUsedInModule(GPIO_DHT11, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } - if (GetUsedInModule(GPIO_DHT22, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } - if (GetUsedInModule(GPIO_SI7021, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } + if (GetUsedInModule(GPIO_DHT11, TasmotaGlobal.my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } + if (GetUsedInModule(GPIO_DHT22, TasmotaGlobal.my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } + if (GetUsedInModule(GPIO_SI7021, TasmotaGlobal.my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } #ifdef USE_DS18x20 - if (GetUsedInModule(GPIO_DSB, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } + if (GetUsedInModule(GPIO_DSB, TasmotaGlobal.my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } #endif - if (GetUsedInModule(GPIO_DHT11, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } - if (GetUsedInModule(GPIO_DHT22, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } - if (GetUsedInModule(GPIO_SI7021, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } + if (GetUsedInModule(GPIO_DHT11, TasmotaGlobal.my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } + if (GetUsedInModule(GPIO_DHT22, TasmotaGlobal.my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } + if (GetUsedInModule(GPIO_SI7021, TasmotaGlobal.my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } #if defined(USE_ENERGY_SENSOR) // Any device with a Power Monitoring - if ( energy_flg != ENERGY_NONE ) { + if ( TasmotaGlobal.energy_driver != ENERGY_NONE ) { device_param[KNX_ENERGY_POWER-1].show = true; device_param[KNX_ENERGY_DAILY-1].show = true; device_param[KNX_ENERGY_START-1].show = true; @@ -565,7 +565,7 @@ void KNX_CB_Action(message_t const &msg, void *arg) sprintf(tempchar,"%d",msg.data[0]); } else if (chan->type == KNX_SCENE) { // VALUE - uint8_t tempvar = knx.data_to_1byte_uint(msg.data); + uint8_t tempvar = knx.data_to_1byte_uint(msg.data); dtostrfd(tempvar,0,tempchar); } else { // VALUE @@ -623,7 +623,7 @@ void KNX_CB_Action(message_t const &msg, void *arg) toggle_inhibit = TOGGLE_INHIBIT_TIME; } } - } + } #endif break; @@ -1097,7 +1097,7 @@ void CmndKnxTxScene(void) device_param_ga[KNX_SCENE-1], XdrvMailbox.data, KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); ResponseCmndIdxChar (XdrvMailbox.data); - } + } } } @@ -1255,7 +1255,7 @@ bool Xdrv11(uint8_t function) bool result = false; switch (function) { case FUNC_LOOP: - if (!global_state.network_down) { knx.loop(); } // Process knx events + if (!TasmotaGlobal.global_state.network_down) { knx.loop(); } // Process knx events break; case FUNC_EVERY_50_MSECOND: if (toggle_inhibit) { diff --git a/tasmota/xdrv_12_home_assistant.ino b/tasmota/xdrv_12_home_assistant.ino index 85483c62c..b6ee170c7 100644 --- a/tasmota/xdrv_12_home_assistant.ino +++ b/tasmota/xdrv_12_home_assistant.ino @@ -213,27 +213,27 @@ void HassDiscoveryRelays(struct HASS &Hass) uint8_t lightidx = MAX_RELAYS + 1; // Will store the starting position of the lights bool iFan = false; - Hass.RelPst = devices_present > 0; + Hass.RelPst = TasmotaGlobal.devices_present > 0; #ifdef ESP8266 - if (SONOFF_IFAN02 == my_module_type || SONOFF_IFAN03 == my_module_type) { iFan = true;} + if (SONOFF_IFAN02 == TasmotaGlobal.module_type || SONOFF_IFAN03 == TasmotaGlobal.module_type) { iFan = true;} #endif // ESP8266 if (Light.subtype > LST_NONE) { if (!light_controller.isCTRGBLinked()) { // One or two lights present - lightidx = devices_present - 2; + lightidx = TasmotaGlobal.devices_present - 2; } else { - lightidx = devices_present - 1; + lightidx = TasmotaGlobal.devices_present - 1; } } if (Light.device > 0 && Settings.flag3.pwm_multi_channels) { // How many relays are light devices? - lightidx = devices_present - Light.subtype; + lightidx = TasmotaGlobal.devices_present - Light.subtype; } for (uint32_t i = 0; i < MAX_RELAYS; i++) { - if (i < devices_present) { + if (i < TasmotaGlobal.devices_present) { #ifdef USE_SHUTTER if (Settings.flag3.shutter_mode) { @@ -255,7 +255,7 @@ void HassDiscoveryRelays(struct HASS &Hass) if (i >= lightidx || (iFan && i == 0)) { // First relay on Ifan controls the light Hass.Relay[i] = 2; // Relay is a light } else { - if (!iFan) { // Relays 2-4 for ifan are controlled by FANSPEED and don't need to be present if my_module_type = SONOFF_IFAN02 or SONOFF_IFAN03 + if (!iFan) { // Relays 2-4 for ifan are controlled by FANSPEED and don't need to be present if TasmotaGlobal.module_type = SONOFF_IFAN02 or SONOFF_IFAN03 Hass.Relay[i] = 1; // Simple Relay } } @@ -282,7 +282,7 @@ void NewHAssDiscovery(void) struct HASS Hass; HassDiscoveryRelays(Hass); - uint32_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; + uint32_t maxfn = (TasmotaGlobal.devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!TasmotaGlobal.devices_present) ? 1 : TasmotaGlobal.devices_present; for (uint32_t i = 0; i < MAX_FRIENDLYNAMES; i++) { char fname[TOPSZ]; snprintf_P(fname, sizeof(fname), PSTR("\"%s\""), EscapeJSONString(SettingsText(SET_FRIENDLYNAME1 +i)).c_str()); @@ -291,7 +291,7 @@ void NewHAssDiscovery(void) stemp3[0] = '\0'; // Enable Discovery for Switches only if SwitchTopic is set to a custom name or if there is not a Power device - auto discover_switches = ((KeyTopicActive(1) && (strcmp(SettingsText(SET_MQTT_SWITCH_TOPIC), mqtt_topic))) || !Hass.RelPst); + auto discover_switches = ((KeyTopicActive(1) && (strcmp(SettingsText(SET_MQTT_SWITCH_TOPIC), TasmotaGlobal.mqtt_topic))) || !Hass.RelPst); for (uint32_t i = 0; i < MAX_SWITCHES; i++) { snprintf_P(stemp3, sizeof(stemp3), PSTR("%s%s%d"), stemp3, (i > 0 ? "," : ""), (PinUsed(GPIO_SWT1, i) & discover_switches) ? Settings.switchmode[i] : -1); } @@ -301,15 +301,15 @@ void NewHAssDiscovery(void) for (uint32_t i = 0; i < MAX_KEYS; i++) { #ifdef ESP8266 - if (i == 0 && (SONOFF_DUAL == my_module_type )) { SerialButton = true; } - if (TUYA_DIMMER == my_module_type || SK03_TUYA == my_module_type) { TuyaMod = true; } + if (i == 0 && (SONOFF_DUAL == TasmotaGlobal.module_type )) { SerialButton = true; } + if (TUYA_DIMMER == TasmotaGlobal.module_type || SK03_TUYA == TasmotaGlobal.module_type) { TuyaMod = true; } #endif // ESP8266 snprintf_P(stemp4, sizeof(stemp4), PSTR("%s%s%d"), stemp4, (i > 0 ? "," : ""), (SerialButton ? 1 : (PinUsed(GPIO_KEY1, i)) & Settings.flag3.mqtt_buttons)); SerialButton = false; } - mqtt_data[0] = '\0'; // Clear retained message + ResponseClear(); // Clear retained message // Full 12 chars MAC address as ID String mac_address = WiFi.macAddress(); @@ -318,11 +318,11 @@ void NewHAssDiscovery(void) snprintf_P(stopic, sizeof(stopic), PSTR("tasmota/discovery/%s/config"), unique_id); // Send empty message if new discovery is disabled - masterlog_level = 4; // Hide topic on clean and remove use weblog 4 to see it + TasmotaGlobal.masterlog_level = 4; // Hide topic on clean and remove use weblog 4 to see it if (!Settings.flag.hass_discovery) { // HassDiscoveryRelays(relays) Response_P(HASS_DISCOVER_DEVICE, WiFi.localIP().toString().c_str(), SettingsText(SET_DEVICENAME), - stemp2, my_hostname, unique_id, ModuleName().c_str(), TuyaMod, GetStateText(0), GetStateText(1), GetStateText(2), GetStateText(3), - my_version, mqtt_topic, SettingsText(SET_MQTT_FULLTOPIC), SUB_PREFIX, PUB_PREFIX, PUB_PREFIX2, Hass.RelLst, stemp3, stemp4, Settings.flag.button_swap, + stemp2, TasmotaGlobal.hostname, unique_id, ModuleName().c_str(), TuyaMod, GetStateText(0), GetStateText(1), GetStateText(2), GetStateText(3), + TasmotaGlobal.version, TasmotaGlobal.mqtt_topic, SettingsText(SET_MQTT_FULLTOPIC), SUB_PREFIX, PUB_PREFIX, PUB_PREFIX2, Hass.RelLst, stemp3, stemp4, Settings.flag.button_swap, Settings.flag.button_single, Settings.flag.decimal_text, Settings.flag.not_power_linked, Settings.flag.hass_light, Settings.flag3.pwm_multi_channels, Settings.flag3.mqtt_buttons, Settings.flag3.shutter_mode, Settings.flag4.alexa_ct_range, light_controller.isCTRGBLinked(), Light.subtype); } @@ -335,7 +335,7 @@ void NewHAssDiscovery(void) ResponseAppend_P(PSTR(",\"ver\":1}")); MqttPublish(stopic, true); } - masterlog_level = 0; // Restore WebLog state + TasmotaGlobal.masterlog_level = 0; // Restore WebLog state } // NEW DISCOVERY @@ -347,19 +347,19 @@ void TryResponseAppend_P(const char *format, ...) char dummy[2]; int dlen = vsnprintf_P(dummy, 1, format, args); - int mlen = strlen(mqtt_data); - int slen = sizeof(mqtt_data) - 1 - mlen; + int mlen = strlen(TasmotaGlobal.mqtt_data); + int slen = sizeof(TasmotaGlobal.mqtt_data) - 1 - mlen; if (dlen >= slen) { AddLog_P2(LOG_LEVEL_ERROR, PSTR("%s (%u/%u):"), kHAssError1, dlen, slen); va_start(args, format); - vsnprintf_P(log_data, sizeof(log_data), format, args); + vsnprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), format, args); AddLog(LOG_LEVEL_ERROR); } else { va_start(args, format); - vsnprintf_P(mqtt_data + mlen, slen, format, args); + vsnprintf_P(TasmotaGlobal.mqtt_data + mlen, slen, format, args); } va_end(args); } @@ -393,10 +393,10 @@ void HAssAnnounceRelayLight(void) uint8_t shutter_mask = 0; #ifdef ESP8266 - if (PWM_DIMMER == my_module_type ) { PwmMod = true; } // - if (SONOFF_IFAN02 == my_module_type || SONOFF_IFAN03 == my_module_type) { FanMod = true; } - if (SONOFF_DUAL == my_module_type) { valid_relay = 2; } - if (TUYA_DIMMER == my_module_type || SK03_TUYA == my_module_type) { TuyaMod = true; } + if (PWM_DIMMER == TasmotaGlobal.module_type ) { PwmMod = true; } // + if (SONOFF_IFAN02 == TasmotaGlobal.module_type || SONOFF_IFAN03 == TasmotaGlobal.module_type) { FanMod = true; } + if (SONOFF_DUAL == TasmotaGlobal.module_type) { valid_relay = 2; } + if (TUYA_DIMMER == TasmotaGlobal.module_type || SK03_TUYA == TasmotaGlobal.module_type) { TuyaMod = true; } #endif //ESP8266 // If there is a special Light to be enabled and managed with SetOption68 or SetOption37 >= 128, Discovery calculates the maximum number of entities to be generated in advance @@ -423,16 +423,16 @@ void HAssAnnounceRelayLight(void) { #ifdef USE_TUYA_MCU - TuyaRel = TuyaGetDpId((TUYA_MCU_FUNC_REL1+ i-1) + active_device - 1); - TuyaRelInv = TuyaGetDpId((TUYA_MCU_FUNC_REL1_INV+ i-1) + active_device - 1); - TuyaDim = TuyaGetDpId((TUYA_MCU_FUNC_DIMMER) + active_device - 1); + TuyaRel = TuyaGetDpId((TUYA_MCU_FUNC_REL1+ i-1) + TasmotaGlobal.active_device - 1); + TuyaRelInv = TuyaGetDpId((TUYA_MCU_FUNC_REL1_INV+ i-1) + TasmotaGlobal.active_device - 1); + TuyaDim = TuyaGetDpId((TUYA_MCU_FUNC_DIMMER) + TasmotaGlobal.active_device - 1); #endif //USE_TUYA_MCU - masterlog_level = ShowTopic = 4; // Hide topic on clean and remove use weblog 4 to see it + TasmotaGlobal.masterlog_level = ShowTopic = 4; // Hide topic on clean and remove use weblog 4 to see it bool RelayX = PinUsed(GPIO_REL1, i-1) || (valid_relay >= i) || (TuyaRel > 0 && TuyaMod) || (TuyaRelInv > 0 && TuyaMod); // Check if the gpio is configured as Relay or force it for Sonoff DUAL R1 with MCU and Tuya MCU - is_topic_light = Settings.flag.hass_light && RelayX || light_type && !RelayX || PwmMod || (TuyaDim > 0 && TuyaMod); // SetOption30 - Enforce HAss autodiscovery as light - mqtt_data[0] = '\0'; // Clear retained message + is_topic_light = Settings.flag.hass_light && RelayX || TasmotaGlobal.light_type && !RelayX || PwmMod || (TuyaDim > 0 && TuyaMod); // SetOption30 - Enforce HAss autodiscovery as light + ResponseClear(); // Clear retained message // Clear "other" topic first in case the device has been reconfigured from light to switch or vice versa snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP_getChipId(), (is_topic_light) ? "RL" : "LI", i); @@ -468,9 +468,9 @@ void HAssAnnounceRelayLight(void) } GetPowerDevice(value_template, i, sizeof(value_template), Settings.flag.device_index_enable); // SetOption26 - Switch between POWER or POWER1 - GetTopic_P(command_topic, CMND, mqtt_topic, value_template); - GetTopic_P(state_topic, TELE, mqtt_topic, D_RSLT_STATE); - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + GetTopic_P(command_topic, CMND, TasmotaGlobal.mqtt_topic, value_template); + GetTopic_P(state_topic, TELE, TasmotaGlobal.mqtt_topic, D_RSLT_STATE); + GetTopic_P(availability_topic, TELE, TasmotaGlobal.mqtt_topic, S_LWT); Response_P(HASS_DISCOVER_BASE, name, state_topic); TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic); TryResponseAppend_P(HASS_DISCOVER_RELAY, command_topic, value_template, SettingsText(SET_STATE_TXT1), SettingsText(SET_STATE_TXT2)); @@ -492,7 +492,7 @@ void HAssAnnounceRelayLight(void) snprintf_P(channel_num, sizeof(channel_num), PSTR("" D_CMND_DIMMER "")); } } - GetTopic_P(brightness_command_topic, CMND, mqtt_topic, channel_num); + GetTopic_P(brightness_command_topic, CMND, TasmotaGlobal.mqtt_topic, channel_num); TryResponseAppend_P(HASS_DISCOVER_BASE_LIGHT, brightness_command_topic, state_topic, stemp3, channel_num); } if ((ind_light && !PwmMulti) || LightControl) { @@ -500,11 +500,11 @@ void HAssAnnounceRelayLight(void) if (Light.subtype >= LST_RGB) { char *rgb_command_topic = stemp1; - GetTopic_P(rgb_command_topic, CMND, mqtt_topic, D_CMND_COLOR); + GetTopic_P(rgb_command_topic, CMND, TasmotaGlobal.mqtt_topic, D_CMND_COLOR); TryResponseAppend_P(HASS_DISCOVER_LIGHT_COLOR, rgb_command_topic, state_topic); char *effect_command_topic = stemp1; - GetTopic_P(effect_command_topic, CMND, mqtt_topic, D_CMND_SCHEME); + GetTopic_P(effect_command_topic, CMND, TasmotaGlobal.mqtt_topic, D_CMND_SCHEME); TryResponseAppend_P(HASS_DISCOVER_LIGHT_SCHEME, effect_command_topic, state_topic); } if (LST_RGBW <= Light.subtype) { wt_light = true; } @@ -515,7 +515,7 @@ void HAssAnnounceRelayLight(void) !PwmMulti && LightControl)) { char *color_temp_command_topic = stemp1; - GetTopic_P(color_temp_command_topic, CMND, mqtt_topic, D_CMND_COLORTEMPERATURE); + GetTopic_P(color_temp_command_topic, CMND, TasmotaGlobal.mqtt_topic, D_CMND_COLORTEMPERATURE); TryResponseAppend_P(HASS_DISCOVER_LIGHT_CT, color_temp_command_topic, state_topic); ct_light = false; } @@ -523,7 +523,7 @@ void HAssAnnounceRelayLight(void) !PwmMulti && LightControl)) { char *white_temp_command_topic = stemp1; - GetTopic_P(white_temp_command_topic, CMND, mqtt_topic, D_CMND_WHITE); + GetTopic_P(white_temp_command_topic, CMND, TasmotaGlobal.mqtt_topic, D_CMND_WHITE); TryResponseAppend_P(HASS_DISCOVER_LIGHT_WHITE, white_temp_command_topic, state_topic); wt_light = false; } @@ -534,7 +534,7 @@ void HAssAnnounceRelayLight(void) TryResponseAppend_P(PSTR("}")); } } - masterlog_level = ShowTopic; + TasmotaGlobal.masterlog_level = ShowTopic; MqttPublish(stopic, true); } } @@ -549,14 +549,14 @@ void HAssAnnouncerTriggers(uint8_t device, uint8_t present, uint8_t key, uint8_t char unique_id[30]; char trigger2[8]; uint8_t ShowTopic; // Used to hide/unhide a topic during Discovery to spare some cpu load - mqtt_data[0] = '\0'; // Clear retained message + ResponseClear(); // Clear retained message for (uint8_t i = trg_start; i <= trg_end; i++) { GetTextIndexed(trigger2, sizeof(trigger2), i, kHAssTriggerStringButtons); snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d_%s"), ESP_getChipId(), key ? "SW" : "BTN", device + 1, key ? GetStateText(i) : trigger2); snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/device_automation/%s/config"), unique_id); - masterlog_level = ShowTopic = 4; // Hide topic on clean and remove use weblog 4 to see it + TasmotaGlobal.masterlog_level = ShowTopic = 4; // Hide topic on clean and remove use weblog 4 to see it if (Settings.flag.hass_discovery && present) { // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59) char name[TOPSZ]; // friendlyname(33) + " " + "BTN" + " " + index @@ -569,8 +569,8 @@ void HAssAnnouncerTriggers(uint8_t device, uint8_t present, uint8_t key, uint8_t GetPowerDevice(value_template, device + 1, sizeof(value_template), key + Settings.flag.device_index_enable); // Force index for Switch 1, Index on Button1 is controlled by SetOption26 - Switch between POWER or POWER1 snprintf_P(jsoname, sizeof(jsoname), PSTR("%s%d"), key ? "SWITCH" : "BUTTON", device + 1); - GetTopic_P(state_topic, STAT, mqtt_topic, jsoname); - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + GetTopic_P(state_topic, STAT, TasmotaGlobal.mqtt_topic, jsoname); + GetTopic_P(availability_topic, TELE, TasmotaGlobal.mqtt_topic, S_LWT); char param[21]; char subtype[9]; @@ -581,19 +581,19 @@ void HAssAnnouncerTriggers(uint8_t device, uint8_t present, uint8_t key, uint8_t GetTextIndexed(param, sizeof(param), pload, kHAssTriggerType); snprintf_P(subtype, sizeof(subtype), PSTR("switch_%d"), device + 1); Response_P(HASS_TRIGGER_TYPE, state_topic, GetStateText(i), param, subtype, ESP_getChipId()); - } else { mqtt_data[0] = '\0'; } // Need to be cleaned again to avoid duplicate + } else { ResponseClear(); } // Need to be cleaned again to avoid duplicate } else { char trigger1[24]; GetTextIndexed(trigger1, sizeof(trigger1), i, kHAssTriggerTypeButtons); snprintf_P(subtype, sizeof(subtype), PSTR("button_%d"), device + 1); if (i > 1 && single) { - mqtt_data[0] = '\0'; // Need to be cleaned again to avoid duplicate + ResponseClear(); // Need to be cleaned again to avoid duplicate } else { Response_P(HASS_TRIGGER_TYPE, state_topic, trigger2, trigger1, subtype, ESP_getChipId()); } } } - masterlog_level = ShowTopic; + TasmotaGlobal.masterlog_level = ShowTopic; MqttPublish(stopic, true); } } @@ -606,14 +606,14 @@ void HAssAnnouncerBinSensors(uint8_t device, uint8_t present, uint8_t dual, uint char unique_id[30]; uint8_t ShowTopic; // Used to hide/unhide a topic during Discovery to spare some cpu load - mqtt_data[0] = '\0'; // Clear retained message - masterlog_level = 4; // Hide topic on clean and remove use weblog 4 to see it + ResponseClear(); // Clear retained message + TasmotaGlobal.masterlog_level = 4; // Hide topic on clean and remove use weblog 4 to see it snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_SW_%d"), ESP_getChipId(), device + 1); snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/binary_sensor/%s/config"), unique_id); - masterlog_level = ShowTopic = 4; // Hide topic on clean and remove use weblog 4 to see it + TasmotaGlobal.masterlog_level = ShowTopic = 4; // Hide topic on clean and remove use weblog 4 to see it if (Settings.flag.hass_discovery && present ) { // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59) if (!toggle || dual) { @@ -628,8 +628,8 @@ void HAssAnnouncerBinSensors(uint8_t device, uint8_t present, uint8_t dual, uint GetPowerDevice(value_template, device + 1, sizeof(value_template), 1 + Settings.flag.device_index_enable); // Force index for Switch 1, Index on Button1 is controlled by SetOption26 - Switch between POWER or POWER1 snprintf_P(jsoname, sizeof(jsoname), PSTR("SWITCH%d"), device + 1); - GetTopic_P(state_topic, STAT, mqtt_topic, jsoname); - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + GetTopic_P(state_topic, STAT, TasmotaGlobal.mqtt_topic, jsoname); + GetTopic_P(availability_topic, TELE, TasmotaGlobal.mqtt_topic, S_LWT); snprintf_P(name, sizeof(name), PSTR("%s Switch%d"), SettingsText(SET_DEVICENAME), device + 1); Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); @@ -650,7 +650,7 @@ void HAssAnnouncerBinSensors(uint8_t device, uint8_t present, uint8_t dual, uint TryResponseAppend_P(PSTR("}")); } } - masterlog_level = ShowTopic; + TasmotaGlobal.masterlog_level = ShowTopic; MqttPublish(stopic, true); } @@ -667,7 +667,7 @@ void HAssAnnounceSwitches(void) if (PinUsed(GPIO_SWT1, switch_index)) { switch_present = 1; } - if (KeyTopicActive(1) && strcmp(SettingsText(SET_MQTT_SWITCH_TOPIC), mqtt_topic)) // Enable Discovery for Switches only if SwitchTopic is set to a custom name + if (KeyTopicActive(1) && strcmp(SettingsText(SET_MQTT_SWITCH_TOPIC), TasmotaGlobal.mqtt_topic)) // Enable Discovery for Switches only if SwitchTopic is set to a custom name { // switch matrix for triggers and binary sensor generation when switchtopic is set as custom (default index is 0,0 - TOGGLE, TOGGLE): @@ -739,7 +739,7 @@ void HAssAnnounceButtons(void) uint8_t single = 0; #ifdef ESP8266 - if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) + if (!button_index && ((SONOFF_DUAL == TasmotaGlobal.module_type) || (CH4 == TasmotaGlobal.module_type))) { button_present = 1; } else @@ -782,7 +782,7 @@ void HAssAnnounceSensor(const char *sensorname, const char *subsensortype, const char unique_id[30]; char subname[20]; - mqtt_data[0] = '\0'; // Clear retained message + ResponseClear(); // Clear retained message // Clear or Set topic NoAlNumToUnderscore(subname, MultiSubName); //Replace all non alphaumeric characters to '_' to avoid topic name issues @@ -794,11 +794,11 @@ void HAssAnnounceSensor(const char *sensorname, const char *subsensortype, const char prefix[TOPSZ]; char *state_topic = stemp1; char *availability_topic = stemp2; - masterlog_level = 0; // Show the new generated topic + TasmotaGlobal.masterlog_level = 0; // Show the new generated topic - GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_SENSOR)); + GetTopic_P(state_topic, TELE, TasmotaGlobal.mqtt_topic, PSTR(D_RSLT_SENSOR)); snprintf_P(name, sizeof(name), PSTR("%s %s %s"), SettingsText(SET_DEVICENAME), sensorname, MultiSubName); - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + GetTopic_P(availability_topic, TELE, TasmotaGlobal.mqtt_topic, S_LWT); Response_P(HASS_DISCOVER_BASE, name, state_topic); #ifdef DEEPSLEEP_LWT_HA_DISCOVERY @@ -850,14 +850,14 @@ void HAssAnnounceSensors(void) uint8_t hass_xsns_index = 0; do { - mqtt_data[0] = '\0'; - int tele_period_save = tele_period; - tele_period = 2; // Do not allow HA updates during next function call + ResponseClear(); + int tele_period_save = TasmotaGlobal.tele_period; + TasmotaGlobal.tele_period = 2; // Do not allow HA updates during next function call XsnsNextCall(FUNC_JSON_APPEND, hass_xsns_index); // ,"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} - tele_period = tele_period_save; - size_t sensordata_len = strlen(mqtt_data); + TasmotaGlobal.tele_period = tele_period_save; + size_t sensordata_len = strlen(TasmotaGlobal.mqtt_data); char sensordata[sensordata_len+2]; // dynamically adjust the size - strcpy(sensordata, mqtt_data); // we can use strcpy since the buffer has the right size + strcpy(sensordata, TasmotaGlobal.mqtt_data); // we can use strcpy since the buffer has the right size // ******************* JSON TEST ******************* // char sensordata[512]; @@ -932,8 +932,8 @@ void HAssAnnounceShutters(void) uint8_t ShowTopic; // Used to hide/unhide a topic during Discovery to spare some cpu load for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { - mqtt_data[0] = '\0'; // Clear retained message - masterlog_level = ShowTopic = 4; // Hide topic on clean and remove use weblog 4 to see it + ResponseClear(); // Clear retained message + TasmotaGlobal.masterlog_level = ShowTopic = 4; // Hide topic on clean and remove use weblog 4 to see it snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_SHT_%d"), ESP_getChipId(), i + 1); @@ -946,24 +946,24 @@ void HAssAnnounceShutters(void) } else { snprintf_P(stemp1, sizeof(stemp1), PSTR("%s"), SettingsText(SET_FRIENDLYNAME1 + i)); } - GetTopic_P(stemp2, TELE, mqtt_topic, D_RSLT_STATE); + GetTopic_P(stemp2, TELE, TasmotaGlobal.mqtt_topic, D_RSLT_STATE); Response_P(HASS_DISCOVER_BASE, stemp1, stemp2); - GetTopic_P(stemp1, TELE, mqtt_topic, S_LWT); + GetTopic_P(stemp1, TELE, TasmotaGlobal.mqtt_topic, S_LWT); TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, stemp1); - GetTopic_P(stemp1, CMND, mqtt_topic, PSTR("Backlog")); + GetTopic_P(stemp1, CMND, TasmotaGlobal.mqtt_topic, PSTR("Backlog")); TryResponseAppend_P(HASS_DISCOVER_SHUTTER_BASE, stemp1, i + 1, i + 1, i + 1); - GetTopic_P(stemp1, STAT, mqtt_topic, PSTR("SHUTTER")); - GetTopic_P(stemp2, CMND, mqtt_topic, PSTR("ShutterPosition")); + GetTopic_P(stemp1, STAT, TasmotaGlobal.mqtt_topic, PSTR("SHUTTER")); + GetTopic_P(stemp2, CMND, TasmotaGlobal.mqtt_topic, PSTR("ShutterPosition")); TryResponseAppend_P(HASS_DISCOVER_SHUTTER_POS, stemp1, i + 1, stemp2, i + 1); TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP_getChipId()); TryResponseAppend_P(PSTR("}")); } - masterlog_level = ShowTopic; + TasmotaGlobal.masterlog_level = ShowTopic; MqttPublish(stopic, true); } #endif @@ -978,8 +978,8 @@ void HAssAnnounceDeviceInfoAndStatusSensor(void) uint8_t ShowTopic; // Used to hide/unhide a topic during Discovery to spare some cpu load // Announce sensor - mqtt_data[0] = '\0'; // Clear retained message - masterlog_level = ShowTopic = 4; // Hide topic on clean and remove use weblog 4 to see it + ResponseClear(); // Clear retained message + TasmotaGlobal.masterlog_level = ShowTopic = 4; // Hide topic on clean and remove use weblog 4 to see it // Clear or Set topic snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_status"), ESP_getChipId()); snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); @@ -992,21 +992,21 @@ void HAssAnnounceDeviceInfoAndStatusSensor(void) char *availability_topic = stemp2; ShowTopic = 0; // Show the new generated topic snprintf_P(name, sizeof(name), PSTR("%s status"), SettingsText(SET_DEVICENAME)); - GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_HASS_STATE)); - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + GetTopic_P(state_topic, TELE, TasmotaGlobal.mqtt_topic, PSTR(D_RSLT_HASS_STATE)); + GetTopic_P(availability_topic, TELE, TasmotaGlobal.mqtt_topic, S_LWT); Response_P(HASS_DISCOVER_BASE, name, state_topic); TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic); TryResponseAppend_P(HASS_DISCOVER_SENSOR_HASS_STATUS, state_topic); TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO, unique_id, ESP_getChipId(), SettingsText(SET_DEVICENAME), - ModuleName().c_str(), my_version, my_image); + ModuleName().c_str(), TasmotaGlobal.version, TasmotaGlobal.image_name); TryResponseAppend_P(PSTR("}")); } - masterlog_level = ShowTopic; + TasmotaGlobal.masterlog_level = ShowTopic; MqttPublish(stopic, true); if (!Settings.flag.hass_discovery) { - masterlog_level = 0; + TasmotaGlobal.masterlog_level = 0; AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_LOG "Home Assistant MQTT Discovery disabled.")); } } @@ -1017,9 +1017,9 @@ void HAssPublishStatus(void) "\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\"," "\"" D_CMND_IPADDRESS "\":\"%s\",\"" D_JSON_RSSI "\":\"%d\",\"" D_JSON_SIGNAL " (dBm)""\":\"%d\"," "\"WiFi " D_JSON_LINK_COUNT "\":%d,\"WiFi " D_JSON_DOWNTIME "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"LoadAvg\":%lu}"), - my_version, my_image, GetBuildDateAndTime().c_str(), ModuleName().c_str(), GetResetReason().c_str(), - GetUptime().c_str(), my_hostname, WiFi.localIP().toString().c_str(), WifiGetRssiAsQuality(WiFi.RSSI()), - WiFi.RSSI(), WifiLinkCount(), WifiDowntime().c_str(), MqttConnectCount(), loop_load_avg); + TasmotaGlobal.version, TasmotaGlobal.image_name, GetBuildDateAndTime().c_str(), ModuleName().c_str(), GetResetReason().c_str(), + GetUptime().c_str(), TasmotaGlobal.hostname, WiFi.localIP().toString().c_str(), WifiGetRssiAsQuality(WiFi.RSSI()), + WiFi.RSSI(), WifiLinkCount(), WifiDowntime().c_str(), MqttConnectCount(), TasmotaGlobal.loop_load_avg); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_HASS_STATE)); } @@ -1056,7 +1056,7 @@ void HAssDiscovery(void) // Send info about status sensor HAssAnnounceDeviceInfoAndStatusSensor(); - masterlog_level = 0; // Restores weblog level + TasmotaGlobal.masterlog_level = 0; // Restores weblog level hass_mode = 3; // Needed for generating bluetooth entities for MI_ESP32 } } @@ -1102,7 +1102,7 @@ void HAssAnyKey(void) } } - GetTopic_P(stopic, STAT, mqtt_topic, scommand); + GetTopic_P(stopic, STAT, TasmotaGlobal.mqtt_topic, scommand); Response_P(S_JSON_COMMAND_SVALUE, (evkey) ? "TRIG" : PSTR(D_RSLT_STATE), (key) ? GetStateText(state) : trg_state); MqttPublish(stopic); } @@ -1155,7 +1155,7 @@ bool Xdrv12(uint8_t function) if (hass_tele_period >= Settings.tele_period) { hass_tele_period = 0; - mqtt_data[0] = '\0'; + ResponseClear(); HAssPublishStatus(); } } diff --git a/tasmota/xdrv_13_display.ino b/tasmota/xdrv_13_display.ino index 68e190f1c..8c5bf5870 100644 --- a/tasmota/xdrv_13_display.ino +++ b/tasmota/xdrv_13_display.ino @@ -776,7 +776,7 @@ void DisplayText(void) buttons[num]->vpower.disable=dis; if (!dis) { if (buttons[num]->vpower.is_virtual) buttons[num]->xdrawButton(buttons[num]->vpower.on_off); - else buttons[num]->xdrawButton(bitRead(power,num)); + else buttons[num]->xdrawButton(bitRead(TasmotaGlobal.power,num)); } } break; @@ -828,7 +828,7 @@ void DisplayText(void) renderer->GetColorFromIndex(fill),renderer->GetColorFromIndex(textcolor),bbuff,textsize); if (!bflags) { // power button - if (dflg) buttons[num]->xdrawButton(bitRead(power,num)); + if (dflg) buttons[num]->xdrawButton(bitRead(TasmotaGlobal.power,num)); buttons[num]->vpower.is_virtual=0; } else { // virtual button @@ -1034,7 +1034,7 @@ void DisplayLogBufferInit(void) DisplayReAllocLogBuffer(); char buffer[40]; - snprintf_P(buffer, sizeof(buffer), PSTR(D_VERSION " %s%s"), my_version, my_image); + snprintf_P(buffer, sizeof(buffer), PSTR(D_VERSION " %s%s"), TasmotaGlobal.version, TasmotaGlobal.image_name); DisplayLogBufferAdd(buffer); snprintf_P(buffer, sizeof(buffer), PSTR("Display mode %d"), Settings.display_mode); DisplayLogBufferAdd(buffer); @@ -1045,7 +1045,7 @@ void DisplayLogBufferInit(void) DisplayLogBufferAdd(buffer); snprintf_P(buffer, sizeof(buffer), PSTR("IP %s"), NetworkAddress().toString().c_str()); DisplayLogBufferAdd(buffer); - if (!global_state.wifi_down) { + if (!TasmotaGlobal.global_state.wifi_down) { snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_SSID " %s"), SettingsText(SET_STASSID1 + Settings.sta_active)); DisplayLogBufferAdd(buffer); snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_RSSI " %d%%"), WifiGetRssiAsQuality(WiFi.RSSI())); @@ -1262,10 +1262,10 @@ bool DisplayMqttData(void) void DisplayLocalSensor(void) { - if ((Settings.display_mode &0x02) && (0 == tele_period)) { + if ((Settings.display_mode &0x02) && (0 == TasmotaGlobal.tele_period)) { char no_topic[1] = { 0 }; -// DisplayAnalyzeJson(mqtt_topic, mqtt_data); // Add local topic - DisplayAnalyzeJson(no_topic, mqtt_data); // Discard any topic +// DisplayAnalyzeJson(TasmotaGlobal.mqtt_topic, TasmotaGlobal.mqtt_data); // Add local topic + DisplayAnalyzeJson(no_topic, TasmotaGlobal.mqtt_data); // Discard any topic } } @@ -1288,13 +1288,13 @@ void DisplayInitDriver(void) // AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Display model %d"), Settings.display_model); if (Settings.display_model) { - devices_present++; + TasmotaGlobal.devices_present++; if (!PinUsed(GPIO_BACKLIGHT)) { - if (light_type && (4 == Settings.display_model)) { - devices_present--; // Assume PWM channel is used for backlight + if (TasmotaGlobal.light_type && (4 == Settings.display_model)) { + TasmotaGlobal.devices_present--; // Assume PWM channel is used for backlight } } - disp_device = devices_present; + disp_device = TasmotaGlobal.devices_present; #ifndef USE_DISPLAY_MODES1TO5 Settings.display_mode = 0; @@ -1339,7 +1339,7 @@ void CmndDisplayModel(void) uint32_t last_display_model = Settings.display_model; Settings.display_model = XdrvMailbox.payload; if (XdspCall(FUNC_DISPLAY_MODEL)) { - restart_flag = 2; // Restart to re-init interface and add/Remove MQTT subscribe + TasmotaGlobal.restart_flag = 2; // Restart to re-init interface and add/Remove MQTT subscribe } else { Settings.display_model = last_display_model; } @@ -1352,7 +1352,7 @@ void CmndDisplayWidth(void) if (XdrvMailbox.payload > 0) { if (XdrvMailbox.payload != Settings.display_width) { Settings.display_width = XdrvMailbox.payload; - restart_flag = 2; // Restart to re-init width + TasmotaGlobal.restart_flag = 2; // Restart to re-init width } } ResponseCmndNumber(Settings.display_width); @@ -1363,7 +1363,7 @@ void CmndDisplayHeight(void) if (XdrvMailbox.payload > 0) { if (XdrvMailbox.payload != Settings.display_height) { Settings.display_height = XdrvMailbox.payload; - restart_flag = 2; // Restart to re-init height + TasmotaGlobal.restart_flag = 2; // Restart to re-init height } } ResponseCmndNumber(Settings.display_height); @@ -1384,7 +1384,7 @@ void CmndDisplayMode(void) Settings.display_mode = XdrvMailbox.payload; if (disp_subscribed != (Settings.display_mode &0x04)) { - restart_flag = 2; // Restart to Add/Remove MQTT subscribe + TasmotaGlobal.restart_flag = 2; // Restart to Add/Remove MQTT subscribe } else { if (last_display_mode && !Settings.display_mode) { // Switch to mode 0 DisplayInit(DISPLAY_INIT_MODE); @@ -2124,7 +2124,7 @@ uint8_t vbutt=0; buttons[count]->press(true); if (buttons[count]->justPressed()) { if (!buttons[count]->vpower.is_virtual) { - uint8_t pwr=bitRead(power, rbutt); + uint8_t pwr=bitRead(TasmotaGlobal.power, rbutt); if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) { ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON); Touch_RDW_BUTT(count, !pwr); @@ -2171,7 +2171,7 @@ uint8_t vbutt=0; } if (!buttons[count]->vpower.is_virtual) { // check if power button stage changed - uint8_t pwr = bitRead(power, rbutt); + uint8_t pwr = bitRead(TasmotaGlobal.power, rbutt); uint8_t vpwr = buttons[count]->vpower.on_off; if (pwr != vpwr) { Touch_RDW_BUTT(count, pwr); @@ -2196,7 +2196,7 @@ bool Xdrv13(uint8_t function) { bool result = false; - if ((i2c_flg || spi_flg || soft_spi_flg) && XdspPresent()) { + if ((TasmotaGlobal.i2c_enabled || TasmotaGlobal.spi_enabled || TasmotaGlobal.soft_spi_enabled) && XdspPresent()) { switch (function) { case FUNC_PRE_INIT: DisplayInitDriver(); diff --git a/tasmota/xdrv_15_pca9685.ino b/tasmota/xdrv_15_pca9685.ino index e4852ad92..f57a10fd2 100644 --- a/tasmota/xdrv_15_pca9685.ino +++ b/tasmota/xdrv_15_pca9685.ino @@ -196,7 +196,7 @@ bool Xdrv15(uint8_t function) else if (pca9685_detected) { switch (function) { case FUNC_EVERY_SECOND: - if (tele_period == 0) { + if (TasmotaGlobal.tele_period == 0) { PCA9685_OutputTelemetry(true); } break; diff --git a/tasmota/xdrv_16_tuyamcu.ino b/tasmota/xdrv_16_tuyamcu.ino index f750302cc..bec39bf22 100644 --- a/tasmota/xdrv_16_tuyamcu.ino +++ b/tasmota/xdrv_16_tuyamcu.ino @@ -93,12 +93,12 @@ void (* const TuyaCommand[])(void) PROGMEM = { \*********************************************************************************************/ bool IsModuleTuya(void) { - return ((TUYA_DIMMER == my_module_type) || (SK03_TUYA == my_module_type)); + return ((TUYA_DIMMER == TasmotaGlobal.module_type) || (SK03_TUYA == TasmotaGlobal.module_type)); } bool AsModuleTuyaMS(void) // ModeSet Layout { - return ((light_type > LT_RGB) && TuyaGetDpId(TUYA_MCU_FUNC_MODESET) != 0); + return ((TasmotaGlobal.light_type > LT_RGB) && TuyaGetDpId(TUYA_MCU_FUNC_MODESET) != 0); } bool IsTuyaFanCtrl(void) // Fan Speed Controller Layout @@ -195,7 +195,7 @@ void CmndTuyaMcu(void) { if (TuyaFuncIdValid(parm[0])) { // TuyaAddMcuFunc(parm[0], parm[1]); - // restart_flag = 2; + // TasmotaGlobal.restart_flag = 2; // } else { // AddLog_P2(LOG_LEVEL_ERROR, PSTR("TYA: TuyaMcu Invalid function id=%d"), parm[0]); // } @@ -212,7 +212,7 @@ void CmndTuyaMcu(void) { Settings.flag3.pwm_multi_channels = 1; } else { Settings.flag3.pwm_multi_channels = 0; } TuyaAddMcuFunc(parm[0], parm[1]); - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } else { AddLog_P2(LOG_LEVEL_ERROR, PSTR("TYA: TuyaMcu Invalid function id=%d"), parm[0]); } @@ -270,9 +270,9 @@ void UpdateDevices() { if (fnId > TUYA_MCU_FUNC_NONE && Settings.tuya_fnid_map[i].dpid > 0) { if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { //Relay - bitClear(rel_inverted, fnId - TUYA_MCU_FUNC_REL1); + bitClear(TasmotaGlobal.rel_inverted, fnId - TUYA_MCU_FUNC_REL1); } else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) { // Inverted Relay - bitSet(rel_inverted, fnId - TUYA_MCU_FUNC_REL1_INV); + bitSet(TasmotaGlobal.rel_inverted, fnId - TUYA_MCU_FUNC_REL1_INV); } } @@ -317,15 +317,15 @@ 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) - snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Send \"55aa00%02x%02x%02x"), cmd, payload_len >> 8, payload_len & 0xFF); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.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]); checksum += payload[i]; - snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, payload[i]); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s%02x"), TasmotaGlobal.log_data, payload[i]); } TuyaSerial->write(checksum); TuyaSerial->flush(); - snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x\""), log_data, checksum); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s%02x\""), TasmotaGlobal.log_data, checksum); AddLog(LOG_LEVEL_DEBUG); } @@ -397,11 +397,11 @@ bool TuyaSetPower(void) uint8_t rpower = XdrvMailbox.index; int16_t source = XdrvMailbox.payload; - uint8_t dpid = TuyaGetDpId(TUYA_MCU_FUNC_REL1 + active_device - 1); - if (dpid == 0) dpid = TuyaGetDpId(TUYA_MCU_FUNC_REL1_INV + active_device - 1); + uint8_t dpid = TuyaGetDpId(TUYA_MCU_FUNC_REL1 + TasmotaGlobal.active_device - 1); + if (dpid == 0) dpid = TuyaGetDpId(TUYA_MCU_FUNC_REL1_INV + TasmotaGlobal.active_device - 1); if (source != SRC_SWITCH && TuyaSerial) { // ignore to prevent loop from pushing state from faceplate interaction - TuyaSendBool(dpid, bitRead(rpower, active_device-1) ^ bitRead(rel_inverted, active_device-1)); + TuyaSendBool(dpid, bitRead(rpower, TasmotaGlobal.active_device-1) ^ bitRead(TasmotaGlobal.rel_inverted, TasmotaGlobal.active_device-1)); delay(20); // Hack when power is off and dimmer is set then both commands go too soon to Serial out. status = true; } @@ -419,12 +419,12 @@ bool TuyaSetChannels(void) uint8_t idx = 0; snprintf_P(hex_char, sizeof(hex_char), PSTR("000000000000")); - if (LT_SERIAL1 == light_type) { + if (LT_SERIAL1 == TasmotaGlobal.light_type) { Tuya.Snapshot[0] = light_state.getDimmer(); } - if (LT_SERIAL2 == light_type || LT_RGBWC == light_type) { + if (LT_SERIAL2 == TasmotaGlobal.light_type || LT_RGBWC == TasmotaGlobal.light_type) { idx = 1; - if (LT_SERIAL2 == light_type && Settings.flag3.pwm_multi_channels && (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER2) != 0)) { + if (LT_SERIAL2 == TasmotaGlobal.light_type && Settings.flag3.pwm_multi_channels && (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER2) != 0)) { // Special setup for dual dimmer (like the MOES 2 Way Dimmer) emulating 2 PWM channels Tuya.Snapshot[0] = changeUIntScale(Light.current_color[0], 0, 255, 0, 100); Tuya.Snapshot[1] = changeUIntScale(Light.current_color[1], 0, 255, 0, 100); @@ -434,15 +434,15 @@ bool TuyaSetChannels(void) Tuya.Snapshot[1] = light_state.getCT(); } } - if (LT_RGBW == light_type) { + if (LT_RGBW == TasmotaGlobal.light_type) { idx = 1; Tuya.Snapshot[0] = light_state.getDimmer(1); Tuya.Snapshot[1] = light_state.getDimmer(2); } - if (light_type > LT_BASIC) { + if (TasmotaGlobal.light_type > LT_BASIC) { - if (LT_RGB != light_type) { + if (LT_RGB != TasmotaGlobal.light_type) { for (uint8_t i = 0; i <= idx; i++) { if (Tuya.Snapshot[i] != Tuya.Levels[i]) { if (i == 0 && LightMode && Tuya.ModeSet ) { noupd = true;} @@ -455,13 +455,13 @@ bool TuyaSetChannels(void) } } - if (light_type >= LT_RGB) { + if (TasmotaGlobal.light_type >= LT_RGB) { light_state.getHSB(&hue, &sat, &bri); sat = changeUIntScale(sat, 0, 255, 0, 100); bri = changeUIntScale(bri, 0, 255, 0, 100); if (hue != Tuya.Snapshot[2] || sat != Tuya.Snapshot[3] || bri != Tuya.Snapshot[4]) { - if ((LightMode && Tuya.ModeSet) || LT_RGB == light_type) { + if ((LightMode && Tuya.ModeSet) || LT_RGB == TasmotaGlobal.light_type) { snprintf_P(hex_char, sizeof(hex_char), PSTR("%04X%04X%04X"), hue, sat * 10, bri * 10); // Create a TuyaMCU readable RGB payload LightSerialDuty(0, &hex_char[0], 3); memcpy_P(Tuya.HSBColor, hex_char, strlen(hex_char)); @@ -496,7 +496,7 @@ void LightSerialDuty(uint16_t duty, char *hex_char, uint8_t TuyaIdx) if (duty < Settings.dimmer_hw_min) { duty = Settings.dimmer_hw_min; } // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself Tuya.ignore_dimmer_cmd_timeout = millis() + 250; // Ignore serial received dim commands for the next 250ms - if (Tuya.ModeSet && (TuyaGetDpId(TUYA_MCU_FUNC_MODESET) != 0) && light_type > LT_RGB) { + if (Tuya.ModeSet && (TuyaGetDpId(TUYA_MCU_FUNC_MODESET) != 0) && TasmotaGlobal.light_type > LT_RGB) { TuyaSendEnum(TuyaGetDpId(TUYA_MCU_FUNC_MODESET), 0); } TuyaSendValue(dpid, duty); @@ -518,7 +518,7 @@ void LightSerialDuty(uint16_t duty, char *hex_char, uint8_t TuyaIdx) if (TuyaIdx == 3) { dpid = TuyaGetDpId(TUYA_MCU_FUNC_RGB); - if (!Tuya.ModeSet && (TuyaGetDpId(TUYA_MCU_FUNC_MODESET) != 0) && light_type > LT_RGB) { + if (!Tuya.ModeSet && (TuyaGetDpId(TUYA_MCU_FUNC_MODESET) != 0) && TasmotaGlobal.light_type > LT_RGB) { TuyaSendEnum(TuyaGetDpId(TUYA_MCU_FUNC_MODESET), 1); } TuyaSendString(dpid, hex_char); @@ -568,13 +568,13 @@ void TuyaProcessStatePacket(void) { if (Tuya.buffer[dpidStart + 1] == 1) { // Data Type 1 if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[dpidStart + 4]?"On":"Off",bitRead(power, fnId - TUYA_MCU_FUNC_REL1)?"On":"Off"); - if ((power || Settings.light_dimmer > 0) && (Tuya.buffer[dpidStart + 4] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1))) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[dpidStart + 4]?"On":"Off",bitRead(TasmotaGlobal.power, fnId - TUYA_MCU_FUNC_REL1)?"On":"Off"); + if ((TasmotaGlobal.power || Settings.light_dimmer > 0) && (Tuya.buffer[dpidStart + 4] != bitRead(TasmotaGlobal.power, fnId - TUYA_MCU_FUNC_REL1))) { ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[dpidStart + 4], SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction } } else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d-Inverted --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[dpidStart + 4]?"Off":"On",bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1?"Off":"On"); - if (Tuya.buffer[dpidStart + 4] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d-Inverted --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[dpidStart + 4]?"Off":"On",bitRead(TasmotaGlobal.power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1?"Off":"On"); + if (Tuya.buffer[dpidStart + 4] != bitRead(TasmotaGlobal.power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1) { ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[dpidStart + 4] ^ 1, SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction } } else if (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) { @@ -587,7 +587,7 @@ void TuyaProcessStatePacket(void) { } } else if (Tuya.buffer[dpidStart + 1] == 2) { // Data Type 2 - bool tuya_energy_enabled = (XNRG_32 == energy_flg); + bool tuya_energy_enabled = (XNRG_32 == TasmotaGlobal.energy_driver); uint16_t packetValue = Tuya.buffer[dpidStart + 6] << 8 | Tuya.buffer[dpidStart + 7]; uint8_t dimIndex; if ((fnId == TUYA_MCU_FUNC_FAN3) || (fnId == TUYA_MCU_FUNC_FAN4) || @@ -613,10 +613,10 @@ void TuyaProcessStatePacket(void) { if (Tuya.ignore_dimmer_cmd_timeout < millis()) { - if ((power || Settings.flag3.tuya_apply_o20) && ((Tuya.Levels[dimIndex] > 0) && (Tuya.Levels[dimIndex] != Tuya.Snapshot[dimIndex]))) { // SetOption54 - Apply SetOption20 settings to Tuya device + if ((TasmotaGlobal.power || Settings.flag3.tuya_apply_o20) && ((Tuya.Levels[dimIndex] > 0) && (Tuya.Levels[dimIndex] != Tuya.Snapshot[dimIndex]))) { // SetOption54 - Apply SetOption20 settings to Tuya device Tuya.ignore_dim = true; - skip_light_fade = true; + TasmotaGlobal.skip_light_fade = true; scmnd[0] = '\0'; if ((fnId == TUYA_MCU_FUNC_DIMMER) || (fnId == TUYA_MCU_FUNC_REPORT1)) { @@ -770,11 +770,11 @@ void TuyaNormalPowerModePacketProcess(void) } if (!Settings.my_gp.io[led1_gpio] && !led1_set) { Settings.my_gp.io[led1_gpio] = AGPIO(GPIO_LED1); - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } if (!Settings.my_gp.io[key1_gpio] && !key1_set) { Settings.my_gp.io[key1_gpio] = AGPIO(GPIO_KEY1); - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } } TuyaRequestState(0); @@ -796,7 +796,7 @@ bool TuyaModuleSelected(void) SetPin(3, AGPIO(GPIO_TUYA_RX)); Settings.my_gp.io[1] = AGPIO(GPIO_TUYA_TX); Settings.my_gp.io[3] = AGPIO(GPIO_TUYA_RX); - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) == 0 && TUYA_DIMMER_ID > 0) { @@ -809,13 +809,13 @@ bool TuyaModuleSelected(void) if ((Settings.tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1 && Settings.tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8 ) || (Settings.tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1_INV && Settings.tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8_INV )) { relaySet = true; - devices_present++; + TasmotaGlobal.devices_present++; } } if (!relaySet && TuyaGetDpId(TUYA_MCU_FUNC_DUMMY) == 0) { //by default the first relay is created automatically the dummy let remove it if not needed TuyaAddMcuFunc(TUYA_MCU_FUNC_REL1, 1); - devices_present++; + TasmotaGlobal.devices_present++; SettingsSaveAll(); } @@ -831,17 +831,17 @@ bool TuyaModuleSelected(void) if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) != 0) { if (TuyaGetDpId(TUYA_MCU_FUNC_RGB) != 0) { if (TuyaGetDpId(TUYA_MCU_FUNC_CT) != 0) { - light_type = LT_RGBWC; + TasmotaGlobal.light_type = LT_RGBWC; } else if (TuyaGetDpId(TUYA_MCU_FUNC_WHITE) != 0) { - light_type = LT_RGBW; - } else { light_type = LT_RGB; } + TasmotaGlobal.light_type = LT_RGBW; + } else { TasmotaGlobal.light_type = LT_RGB; } } else if (TuyaGetDpId(TUYA_MCU_FUNC_CT) != 0 || TuyaGetDpId(TUYA_MCU_FUNC_DIMMER2) != 0) { if (TuyaGetDpId(TUYA_MCU_FUNC_RGB) != 0) { - light_type = LT_RGBWC; - } else { light_type = LT_SERIAL2; } - } else { light_type = LT_SERIAL1; } + TasmotaGlobal.light_type = LT_RGBWC; + } else { TasmotaGlobal.light_type = LT_SERIAL2; } + } else { TasmotaGlobal.light_type = LT_SERIAL1; } } else { - light_type = LT_BASIC; + TasmotaGlobal.light_type = LT_BASIC; } if (TuyaGetDpId(TUYA_MCU_FUNC_LOWPOWER_MODE) != 0) { @@ -963,7 +963,7 @@ void TuyaSerialInput(void) if (Settings.flag3.tuya_serial_mqtt_publish) { // SetOption66 - Enable TuyaMcuReceived messages over Mqtt MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_TUYA_MCU_RECEIVED)); } else { - AddLog_P(LOG_LEVEL_DEBUG, mqtt_data); + AddLog_P(LOG_LEVEL_DEBUG, TasmotaGlobal.mqtt_data); } XdrvRulesProcess(); @@ -1071,7 +1071,7 @@ bool Xnrg32(uint8_t function) { bool result = false; - if (TUYA_DIMMER == my_module_type) { + if (TUYA_DIMMER == TasmotaGlobal.module_type) { if (FUNC_PRE_INIT == function) { if (TuyaGetDpId(TUYA_MCU_FUNC_POWER) != 0) { if (TuyaGetDpId(TUYA_MCU_FUNC_CURRENT) == 0) { @@ -1080,7 +1080,7 @@ bool Xnrg32(uint8_t function) if (TuyaGetDpId(TUYA_MCU_FUNC_VOLTAGE) == 0) { Energy.voltage_available = false; } - energy_flg = XNRG_32; + TasmotaGlobal.energy_driver = XNRG_32; } } } @@ -1096,7 +1096,7 @@ bool Xdrv16(uint8_t function) { bool result = false; - if (TUYA_DIMMER == my_module_type) { + if (TUYA_DIMMER == TasmotaGlobal.module_type) { switch (function) { case FUNC_LOOP: if (TuyaSerial) { TuyaSerialInput(); } @@ -1123,7 +1123,7 @@ bool Xdrv16(uint8_t function) TuyaSendCmd(TUYA_CMD_HEARTBEAT); } #ifdef USE_TUYA_TIME - if (!(uptime % 60)) { + if (!(TasmotaGlobal.uptime % 60)) { TuyaSetTime(); } #endif //USE_TUYA_TIME diff --git a/tasmota/xdrv_18_armtronix_dimmers.ino b/tasmota/xdrv_18_armtronix_dimmers.ino index 710697a28..c49769e9e 100644 --- a/tasmota/xdrv_18_armtronix_dimmers.ino +++ b/tasmota/xdrv_18_armtronix_dimmers.ino @@ -86,8 +86,8 @@ void ArmtronixRequestState(void) bool ArmtronixModuleSelected(void) { - devices_present++; - light_type = LT_SERIAL2; + TasmotaGlobal.devices_present++; + TasmotaGlobal.light_type = LT_SERIAL2; return true; } @@ -168,7 +168,7 @@ bool Xdrv18(uint8_t function) { bool result = false; - if (ARMTRONIX_DIMMERS == my_module_type) { + if (ARMTRONIX_DIMMERS == TasmotaGlobal.module_type) { switch (function) { case FUNC_LOOP: if (ArmtronixSerial) { ArmtronixSerialInput(); } @@ -182,7 +182,7 @@ bool Xdrv18(uint8_t function) case FUNC_EVERY_SECOND: if (ArmtronixSerial) { if (Armtronix.wifi_state!=WifiState()) { ArmtronixSetWifiLed(); } - if (uptime &1) { + if (TasmotaGlobal.uptime &1) { ArmtronixSerial->println("Status"); } } diff --git a/tasmota/xdrv_19_ps16dz_dimmer.ino b/tasmota/xdrv_19_ps16dz_dimmer.ino index d387ae05c..341f276af 100644 --- a/tasmota/xdrv_19_ps16dz_dimmer.ino +++ b/tasmota/xdrv_19_ps16dz_dimmer.ino @@ -69,7 +69,7 @@ void PS16DZSerialSendUpdateCommand(void) char tx_buffer[80]; snprintf_P(tx_buffer, sizeof(tx_buffer), PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"bright\":%d"), - LocalTime(), millis()%1000, power?"on":"off", light_state_dimmer); + LocalTime(), millis()%1000, TasmotaGlobal.power?"on":"off", light_state_dimmer); PS16DZSerialSend(tx_buffer); } @@ -120,7 +120,7 @@ void PS16DZSerialInput(void) // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Switch %d"), switch_state); - is_switch_change = (switch_state != power); + is_switch_change = (switch_state != TasmotaGlobal.power); if (is_switch_change) { ExecuteCommandPower(1, switch_state, SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction } @@ -131,7 +131,7 @@ void PS16DZSerialInput(void) // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: Brightness %d"), Ps16dz.dimmer); is_brightness_change = Ps16dz.dimmer != Settings.light_dimmer; - if (power && (Ps16dz.dimmer > 0) && is_brightness_change) { + if (TasmotaGlobal.power && (Ps16dz.dimmer > 0) && is_brightness_change) { snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), Ps16dz.dimmer); ExecuteCommand(scmnd, SRC_SWITCH); } @@ -196,8 +196,8 @@ void PS16DZInit(void) bool PS16DZModuleSelected(void) { - devices_present++; - light_type = LT_SERIAL1; + TasmotaGlobal.devices_present++; + TasmotaGlobal.light_type = LT_SERIAL1; return true; } @@ -210,7 +210,7 @@ bool Xdrv19(uint8_t function) { bool result = false; - if (PS_16_DZ == my_module_type) { + if (PS_16_DZ == TasmotaGlobal.module_type) { switch (function) { case FUNC_LOOP: if (PS16DZSerial) { PS16DZSerialInput(); } diff --git a/tasmota/xdrv_20_hue.ino b/tasmota/xdrv_20_hue.ino index fea0411eb..6c86b5424 100644 --- a/tasmota/xdrv_20_hue.ino +++ b/tasmota/xdrv_20_hue.ino @@ -305,7 +305,7 @@ char prev_x_str[24] = "\0"; // store previously set xy by Alexa app char prev_y_str[24] = "\0"; uint8_t getLocalLightSubtype(uint8_t device) { - if (light_type) { + if (TasmotaGlobal.light_type) { if (device >= Light.device) { if (Settings.flag3.pwm_multi_channels) { // SetOption68 - Enable multi-channels PWM instead of Color PWM return LST_SINGLE; // If SetOption68, each channel acts like a dimmer @@ -343,7 +343,7 @@ void HueLightStatus1(uint8_t device, String *response) } #endif - if (light_type) { + if (TasmotaGlobal.light_type) { light_state.getHSB(&hue, &sat, nullptr); if (sat > 254) sat = 254; // Philips Hue only accepts 254 as max hue hue = changeUIntScale(hue, 0, 360, 0, 65535); @@ -361,7 +361,7 @@ void HueLightStatus1(uint8_t device, String *response) const size_t buf_size = 256; char * buf = (char*) malloc(buf_size); // temp buffer for strings, avoid stack - snprintf_P(buf, buf_size, PSTR("{\"on\":%s,"), (power & (1 << (device-1))) ? "true" : "false"); + snprintf_P(buf, buf_size, PSTR("{\"on\":%s,"), (TasmotaGlobal.power & (1 << (device-1))) ? "true" : "false"); // Brightness for all devices with PWM if ((1 == echo_gen) || (LST_SINGLE <= local_light_subtype)) { // force dimmer for 1st gen Echo snprintf_P(buf, buf_size, PSTR("%s\"bri\":%d,"), buf, bri); @@ -475,6 +475,7 @@ uint32_t DecodeLightId(uint32_t hue_id, uint16_t * shortaddr = nullptr) relay_id = 32; } #ifdef USE_ZIGBEE + if (shortaddr) { *shortaddr = 0x0000; } if (hue_id & (1 << 29)) { // this is actually a Zigbee ID if (shortaddr) { *shortaddr = hue_id & 0xFFFF; } @@ -517,7 +518,7 @@ void HueAuthentication(String *path) // refactored to remove code duplicates void CheckHue(String * response, bool &appending) { - uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; + uint8_t maxhue = (TasmotaGlobal.devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : TasmotaGlobal.devices_present; for (uint32_t i = 1; i <= maxhue; i++) { if (HueActive(i)) { if (appending) { *response += ","; } @@ -576,7 +577,7 @@ void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) { #endif // USE_SHUTTER } - if (light_type && (local_light_subtype >= LST_SINGLE)) { + if (TasmotaGlobal.light_type && (local_light_subtype >= LST_SINGLE)) { if (!Settings.flag3.pwm_multi_channels) { // SetOption68 - Enable multi-channels PWM instead of Color PWM light_state.getHSB(&hue, &sat, nullptr); bri = light_state.getBri(); // get the combined bri for CT and RGB, not only the RGB one @@ -691,7 +692,7 @@ void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) { } resp = true; } - + if (change) { #ifdef USE_SHUTTER if (ShutterState(device)) { @@ -699,7 +700,7 @@ void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) { ShutterSetPosition(device, bri * 100.0f ); } else #endif - if (light_type && (local_light_subtype > LST_NONE)) { // not relay + if (TasmotaGlobal.light_type && (local_light_subtype > LST_NONE)) { // not relay if (!Settings.flag3.pwm_multi_channels) { // SetOption68 - Enable multi-channels PWM instead of Color PWM if (g_gotct) { light_controller.changeCTB(ct, bri); @@ -739,7 +740,7 @@ void HueLights(String *path) int code = 200; uint8_t device = 1; uint32_t device_id; // the raw device_id used by Hue emulation - uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; + uint8_t maxhue = (TasmotaGlobal.devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : TasmotaGlobal.devices_present; path->remove(0,path->indexOf(F("/lights"))); // Remove until /lights if (path->endsWith(F("/lights"))) { // Got /lights @@ -768,7 +769,7 @@ void HueLights(String *path) #endif // USE_ZIGBEE #ifdef USE_SCRIPT_HUE - if (device > devices_present) { + if (device > TasmotaGlobal.devices_present) { return Script_Handle_Hue(path); } #endif @@ -792,8 +793,8 @@ void HueLights(String *path) #endif // USE_ZIGBEE #ifdef USE_SCRIPT_HUE - if (device > devices_present) { - Script_HueStatus(&response, device-devices_present - 1); + if (device > TasmotaGlobal.devices_present) { + Script_HueStatus(&response, device-TasmotaGlobal.devices_present - 1); goto exit; } #endif @@ -820,7 +821,7 @@ void HueGroups(String *path) * http://tasmota/api/username/groups?1={"name":"Woonkamer","lights":[],"type":"Room","class":"Living room"}) */ String response = "{}"; - uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; + uint8_t maxhue = (TasmotaGlobal.devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : TasmotaGlobal.devices_present; //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " HueGroups (%s)"), path->c_str()); if (path->endsWith("/0")) { @@ -893,7 +894,7 @@ bool Xdrv20(uint8_t function) #if defined(USE_SCRIPT_HUE) || defined(USE_ZIGBEE) if ((EMUL_HUE == Settings.flag2.emulation)) { #else - if (devices_present && (EMUL_HUE == Settings.flag2.emulation)) { + if (TasmotaGlobal.devices_present && (EMUL_HUE == Settings.flag2.emulation)) { #endif switch (function) { case FUNC_WEB_ADD_HANDLER: diff --git a/tasmota/xdrv_21_wemo.ino b/tasmota/xdrv_21_wemo.ino index 1f52fb474..6cd5ce4ce 100644 --- a/tasmota/xdrv_21_wemo.ino +++ b/tasmota/xdrv_21_wemo.ino @@ -292,15 +292,15 @@ void HandleUpnpEvent(void) power = POWER_OFF; } if (power != POWER_TOGGLE) { - uint8_t device = (light_type) ? devices_present : 1; // Select either a configured light or relay1 + uint8_t device = (TasmotaGlobal.light_type) ? TasmotaGlobal.devices_present : 1; // Select either a configured light or relay1 ExecuteCommandPower(device, power, SRC_WEMO); } } #ifdef USE_UNISHOX_COMPRESSION - snprintf_P(event, sizeof(event), Decompress(WEMO_RESPONSE_STATE_SOAP, WEMO_RESPONSE_STATE_SOAP_SIZE).c_str(), state, bitRead(power, devices_present -1), state); + snprintf_P(event, sizeof(event), Decompress(WEMO_RESPONSE_STATE_SOAP, WEMO_RESPONSE_STATE_SOAP_SIZE).c_str(), state, bitRead(TasmotaGlobal.power, TasmotaGlobal.devices_present -1), state); #else - snprintf_P(event, sizeof(event), WEMO_RESPONSE_STATE_SOAP, state, bitRead(power, devices_present -1), state); + snprintf_P(event, sizeof(event), WEMO_RESPONSE_STATE_SOAP, state, bitRead(TasmotaGlobal.power, TasmotaGlobal.devices_present -1), state); #endif WSSend(200, CT_XML, event); } @@ -350,7 +350,7 @@ bool Xdrv21(uint8_t function) { bool result = false; - if (devices_present && (EMUL_WEMO == Settings.flag2.emulation)) { + if (TasmotaGlobal.devices_present && (EMUL_WEMO == Settings.flag2.emulation)) { switch (function) { case FUNC_WEB_ADD_HANDLER: WebServer_on(PSTR("/upnp/control/basicevent1"), HandleUpnpEvent, HTTP_POST); diff --git a/tasmota/xdrv_22_sonoff_ifan.ino b/tasmota/xdrv_22_sonoff_ifan.ino index a51265f99..5ea74c792 100644 --- a/tasmota/xdrv_22_sonoff_ifan.ino +++ b/tasmota/xdrv_22_sonoff_ifan.ino @@ -45,7 +45,7 @@ bool ifan_restart_flag = true; bool IsModuleIfan(void) { - return ((SONOFF_IFAN02 == my_module_type) || (SONOFF_IFAN03 == my_module_type)); + return ((SONOFF_IFAN02 == TasmotaGlobal.module_type) || (SONOFF_IFAN03 == TasmotaGlobal.module_type)); } uint8_t MaxFanspeed(void) @@ -64,7 +64,7 @@ uint8_t GetFanspeed(void) 011x = 2 101x = 3 (ifan02) or 100x = 3 (ifan03) */ - uint8_t fanspeed = (uint8_t)(power &0xF) >> 1; + uint8_t fanspeed = (uint8_t)(TasmotaGlobal.power &0xF) >> 1; if (fanspeed) { fanspeed = (fanspeed >> 1) +1; } // 0, 1, 2, 3 return fanspeed; } @@ -82,7 +82,7 @@ void SonoffIFanSetFanspeed(uint8_t fanspeed, bool sequence) if (fanspeed == fanspeed_now) { return; } uint8_t fans = kIFan02Speed[fanspeed]; - if (SONOFF_IFAN03 == my_module_type) { + if (SONOFF_IFAN03 == TasmotaGlobal.module_type) { if (sequence) { fanspeed = kIFan03Sequence[fanspeed_now][ifan_fanspeed_goal]; if (fanspeed != ifan_fanspeed_goal) { @@ -112,8 +112,8 @@ void SonoffIfanReceived(void) { char svalue[32]; - uint8_t mode = serial_in_buffer[3]; - uint8_t action = serial_in_buffer[6]; + uint8_t mode = TasmotaGlobal.serial_in_buffer[3]; + uint8_t action = TasmotaGlobal.serial_in_buffer[6]; if (4 == mode) { if (action < 4) { @@ -146,25 +146,25 @@ void SonoffIfanReceived(void) // Send Acknowledge - Copy first 5 bytes, reset byte 6 and store crc in byte 7 // AA 55 01 04 00 00 05 - serial_in_buffer[5] = 0; // Ack - serial_in_buffer[6] = 0; // Crc + TasmotaGlobal.serial_in_buffer[5] = 0; // Ack + TasmotaGlobal.serial_in_buffer[6] = 0; // Crc for (uint32_t i = 0; i < 7; i++) { - if ((i > 1) && (i < 6)) { serial_in_buffer[6] += serial_in_buffer[i]; } - Serial.write(serial_in_buffer[i]); + if ((i > 1) && (i < 6)) { TasmotaGlobal.serial_in_buffer[6] += TasmotaGlobal.serial_in_buffer[i]; } + Serial.write(TasmotaGlobal.serial_in_buffer[i]); } } bool SonoffIfanSerialInput(void) { - if (SONOFF_IFAN03 != my_module_type) { return false; } + if (SONOFF_IFAN03 != TasmotaGlobal.module_type) { return false; } - if (0xAA == serial_in_byte) { // 0xAA - Start of text - serial_in_byte_counter = 0; + if (0xAA == TasmotaGlobal.serial_in_byte) { // 0xAA - Start of text + TasmotaGlobal.serial_in_byte_counter = 0; ifan_receive_flag = true; } if (ifan_receive_flag) { - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - if (serial_in_byte_counter == 8) { + TasmotaGlobal.serial_in_buffer[TasmotaGlobal.serial_in_byte_counter++] = TasmotaGlobal.serial_in_byte; + if (TasmotaGlobal.serial_in_byte_counter == 8) { // AA 55 01 01 00 01 01 04 - Wifi long press - start wifi setup // AA 55 01 01 00 01 02 05 - Rf and Wifi short press // AA 55 01 04 00 01 00 06 - Fan 0 @@ -177,15 +177,15 @@ bool SonoffIfanSerialInput(void) AddLogSerial(LOG_LEVEL_DEBUG); uint8_t crc = 0; for (uint32_t i = 2; i < 7; i++) { - crc += serial_in_buffer[i]; + crc += TasmotaGlobal.serial_in_buffer[i]; } - if (crc == serial_in_buffer[7]) { + if (crc == TasmotaGlobal.serial_in_buffer[7]) { SonoffIfanReceived(); ifan_receive_flag = false; return true; } } - serial_in_byte = 0; + TasmotaGlobal.serial_in_byte = 0; } return false; } @@ -216,7 +216,7 @@ void CmndFanspeed(void) bool SonoffIfanInit(void) { - if (SONOFF_IFAN03 == my_module_type) { + if (SONOFF_IFAN03 == TasmotaGlobal.module_type) { SetSerial(9600, TS_SERIAL_8N1); } return false; // Continue init chain @@ -224,7 +224,7 @@ bool SonoffIfanInit(void) void SonoffIfanUpdate(void) { - if (SONOFF_IFAN03 == my_module_type) { + if (SONOFF_IFAN03 == TasmotaGlobal.module_type) { if (ifan_fanspeed_timer) { ifan_fanspeed_timer--; if (!ifan_fanspeed_timer) { @@ -233,10 +233,10 @@ void SonoffIfanUpdate(void) } } - if (ifan_restart_flag && (4 == uptime) && (SONOFF_IFAN02 == my_module_type)) { // Microcontroller needs 3 seconds before accepting commands + if (ifan_restart_flag && (4 == TasmotaGlobal.uptime) && (SONOFF_IFAN02 == TasmotaGlobal.module_type)) { // Microcontroller needs 3 seconds before accepting commands ifan_restart_flag = false; SetDevicePower(1, SRC_RETRY); // Sync with default power on state microcontroller being Light ON and Fan OFF - SetDevicePower(power, SRC_RETRY); // Set required power on state + SetDevicePower(TasmotaGlobal.power, SRC_RETRY); // Set required power on state } } diff --git a/tasmota/xdrv_23_zigbee_1z_libs.ino b/tasmota/xdrv_23_zigbee_1z_libs.ino index 8b64baa5b..82555c941 100644 --- a/tasmota/xdrv_23_zigbee_1z_libs.ino +++ b/tasmota/xdrv_23_zigbee_1z_libs.ino @@ -64,46 +64,6 @@ uint16_t Z_GetLastGroup(void) { return gZbLastMessage.groupaddr; } uint16_t Z_GetLastCluster(void) { return gZbLastMessage.cluster; } uint8_t Z_GetLastEndpoint(void) { return gZbLastMessage.endpoint; } -/*********************************************************************************************\ - * - * Class for attribute array of values - * This is a helper function to generate a clean list of unsigned ints - * -\*********************************************************************************************/ - -class Z_json_array { -public: - - Z_json_array(): val("[]") {} // start with empty array - void add(uint32_t uval32) { - // remove trailing ']' - val.remove(val.length()-1); - if (val.length() > 1) { // if not empty, prefix with comma - val += ','; - } - val += uval32; - val += ']'; - } - void addStrRaw(const char * sval) { - // remove trailing ']' - val.remove(val.length()-1); - if (val.length() > 1) { // if not empty, prefix with comma - val += ','; - } - val += sval; - val += ']'; - } - void addStr(const char * sval) { - addStrRaw(EscapeJSONString(sval).c_str()); - } - String &toString(void) { - return val; - } - -private : - String val; -}; - /*********************************************************************************************\ * * Class for single attribute @@ -143,8 +103,8 @@ public: float fval; SBuffer* bval; char* sval; - class Z_attribute_list * objval; - class Z_json_array * arrval; + class Z_attribute_list * objval; + class JsonGeneratorArray * arrval; } val; Za_type type; // uint8_t in size, type of attribute, see above bool key_is_str; // is the key a string? @@ -217,7 +177,7 @@ public: } Z_attribute_list & newAttrList(void); - Z_json_array & newJsonArray(void); + JsonGeneratorArray & newJsonArray(void); inline bool isNum(void) const { return (type >= Za_type::Za_bool) && (type <= Za_type::Za_float); } inline bool isNone(void) const { return (type == Za_type::Za_none);} @@ -446,9 +406,9 @@ Z_attribute_list & Z_attribute::newAttrList(void) { return *val.objval; } -Z_json_array & Z_attribute::newJsonArray(void) { +JsonGeneratorArray & Z_attribute::newJsonArray(void) { freeVal(); - val.arrval = new Z_json_array(); + val.arrval = new JsonGeneratorArray(); type = Za_type::Za_arr; return *val.arrval; } @@ -849,11 +809,10 @@ Z_attribute & Z_attribute_list::findOrCreateAttribute(const char * name, uint8_t // same but passing a Z_attribute as key Z_attribute & Z_attribute_list::findOrCreateAttribute(const Z_attribute &attr) { - if (attr.key_is_str) { - return findOrCreateAttribute(attr.key.key, attr.key_suffix); - } else { - return findOrCreateAttribute(attr.key.id.cluster, attr.key.id.attr_id, attr.key_suffix); - } + Z_attribute & ret = attr.key_is_str ? findOrCreateAttribute(attr.key.key, attr.key_suffix) + : findOrCreateAttribute(attr.key.id.cluster, attr.key.id.attr_id, attr.key_suffix); + ret.key_suffix = attr.key_suffix; + return ret; } // replace the entire content with new attribute or create Z_attribute & Z_attribute_list::replaceOrCreate(const Z_attribute &attr) { @@ -870,9 +829,17 @@ bool Z_attribute_list::mergeList(const Z_attribute_list &attr_list) { } else if (0xFF != attr_list.src_ep) { if (src_ep != attr_list.src_ep) { return false; } } + // Check group address + if (0xFFFF == group_id) { + group_id = attr_list.group_id; + } else if (0xFFFF != attr_list.group_id) { + if (group_id != attr_list.group_id) { return false; } + } + // copy LQI if (0xFF != attr_list.lqi) { lqi = attr_list.lqi; } + // merge attributes for (auto & attr : attr_list) { replaceOrCreate(attr); } diff --git a/tasmota/xdrv_23_zigbee_2_devices.ino b/tasmota/xdrv_23_zigbee_2_devices.ino index d46debf02..db74e7220 100644 --- a/tasmota/xdrv_23_zigbee_2_devices.ino +++ b/tasmota/xdrv_23_zigbee_2_devices.ino @@ -36,31 +36,110 @@ enum class Z_Data_Type : uint8_t { Z_Device = 0xFF // special value when parsing Device level attributes }; +const uint8_t Z_Data_Type_char[] PROGMEM = { + '?', // 0x00 Z_Data_Type::Z_Unknown + 'L', // 0x01 Z_Data_Type::Z_Light + 'P', // 0x02 Z_Data_Type::Z_Plug + 'I', // 0x03 Z_Data_Type::Z_PIR + 'A', // 0x04 Z_Data_Type::Z_Alarm + 'T', // 0x05 Z_Data_Type::Z_Thermo + 'O', // 0x05 Z_Data_Type::Z_OnOff + '\0', // 0x06 + '\0', // 0x07 + '\0', // 0x08 + '\0', // 0x09 + '\0', // 0x0A + '\0', // 0x0B + '\0', // 0x0C + '\0', // 0x0D + '\0', // 0x0E + 'E', // 0x05 Z_Data_Type::Z_Ext + // '_' maps to 0xFF Z_Data_Type::Z_Device +}; + class Z_Data_Set; /*********************************************************************************************\ * Device specific data, sensors... \*********************************************************************************************/ class Z_Data { public: - Z_Data(Z_Data_Type type = Z_Data_Type::Z_Unknown, uint8_t endpoint = 0) : _type(type), _endpoint(endpoint), _config(-1), _power(0) {} + Z_Data(Z_Data_Type type = Z_Data_Type::Z_Unknown, uint8_t endpoint = 0) : _type(type), _endpoint(endpoint), _config(0xF), _power(0) {} inline Z_Data_Type getType(void) const { return _type; } inline int8_t getConfig(void) const { return _config; } + inline bool validConfig(void) const { return _config != 0xF; } inline void setConfig(int8_t config) { _config = config; } + uint8_t getConfigByte(void) const { return ( ((uint8_t)_type) << 4) | ((_config & 0xF) & 0x0F); } inline uint8_t getEndpoint(void) const { return _endpoint; } void toAttributes(Z_attribute_list & attr_list, Z_Data_Type type) const; static const Z_Data_Type type = Z_Data_Type::Z_Unknown; + static bool ConfigToZData(const char * config_str, Z_Data_Type * type, uint8_t * ep, uint8_t * config); + + static Z_Data_Type CharToDataType(char c); + static char DataTypeToChar(Z_Data_Type t); friend class Z_Data_Set; protected: Z_Data_Type _type; // encoded on 4 bits, type of the device uint8_t _endpoint; // source endpoint, or 0x00 if any endpoint - int8_t _config; // encoded on 4 bits, customize behavior + uint8_t _config : 4; // encoded on 4 bits, customize behavior uint8_t _power; // power state if the type supports it }; +Z_Data_Type Z_Data::CharToDataType(char c) { + if (c) { + if (c == '_') { + return Z_Data_Type::Z_Device; + } else { + for (uint32_t i=0; i 8) { val_15 = 8; } + _config = val_15; + } +} + /*********************************************************************************************\ * Device specific: Sensors: temp, humidity, pressure... \*********************************************************************************************/ @@ -286,6 +422,8 @@ Z_Data & Z_Data_Set::getByType(Z_Data_Type type, uint8_t ep) { return get(ep); case Z_Data_Type::Z_OnOff: return get(ep); + case Z_Data_Type::Z_PIR: + return get(ep); default: return *(Z_Data*)nullptr; } @@ -330,14 +468,6 @@ const Z_Data & Z_Data_Set::find(Z_Data_Type type, uint8_t ep) const { return *(Z_Data*)nullptr; } -// Low-level -// Add light attributes, used by dumpLightState and by SbData -// -void Z_Data_Light::toAttributes(Z_attribute_list & attr_list, Z_Data_Type type) const { - attr_list.addAttribute(PSTR(D_JSON_ZIGBEE_LIGHT)).setInt(getConfig()); // special case, since type is 0x00 we can assume getConfig() is good - Z_Data::toAttributes(attr_list, type); -} - void Z_Data_OnOff::toAttributes(Z_attribute_list & attr_list, Z_Data_Type type) const { if (validPower()) { attr_list.addAttribute(PSTR("Power")).setUInt(getPower() ? 1 : 0); } } @@ -370,7 +500,7 @@ public: // Light information for Hue integration integration, last known values // New version of device data handling - Z_Data_Set data; // Linkedlist of device data per endpoint + Z_Data_Set data; // Linkedlist of device data per endpoint // other status uint8_t lqi; // lqi from last message, 0xFF means unknown uint8_t batterypercent; // battery percentage (0..100), 0xFF means unknwon @@ -390,7 +520,7 @@ public: seqNumber(0), hidden(false), reachable(false), - // Hue support + data(), lqi(0xFF), batterypercent(0xFF), last_seen(0) @@ -413,6 +543,15 @@ public: inline bool getReachable(void) const { return reachable; } inline bool getPower(uint8_t ep =0) const; + // Add an endpoint to a device + bool addEndpoint(uint8_t endpoint); + void clearEndpoints(void); + uint32_t countEndpoints(void) const; // return the number of known endpoints (0 if unknown) + + void setManufId(const char * str); + void setModelId(const char * str); + void setFriendlyName(const char * str); + // dump device attributes to ZbData void toAttributes(Z_attribute_list & attr_list) const; @@ -439,10 +578,12 @@ public: light.setConfig(channels); dirty = true; } + Z_Data_OnOff & onoff = data.get(0); } else { - // remove light object if any + // remove light / onoff object if any for (auto & data_elt : data) { - if (data_elt.getType() == Z_Data_Type::Z_Light) { + if ((data_elt.getType() == Z_Data_Type::Z_Light) || + (data_elt.getType() == Z_Data_Type::Z_OnOff)) { // remove light object data.remove(&data_elt); dirty = true; @@ -451,6 +592,9 @@ public: } return dirty; } +protected: + + static void setStringAttribute(char*& attr, const char * str); }; /*********************************************************************************************\ @@ -533,16 +677,8 @@ public: // Add new device, provide ShortAddr and optional longAddr // If it is already registered, update information, otherwise create the entry - void updateDevice(uint16_t shortaddr, uint64_t longaddr = 0); + Z_Device & updateDevice(uint16_t shortaddr, uint64_t longaddr = 0); - // Add an endpoint to a device - void addEndpoint(uint16_t shortaddr, uint8_t endpoint); - void clearEndpoints(uint16_t shortaddr); - uint32_t countEndpoints(uint16_t shortaddr) const; // return the number of known endpoints (0 if unknown) - - void setManufId(uint16_t shortaddr, const char * str); - void setModelId(uint16_t shortaddr, const char * str); - void setFriendlyName(uint16_t shortaddr, const char * str); inline const char * getFriendlyName(uint16_t shortaddr) const { return findShortAddr(shortaddr).friendlyName; } @@ -629,8 +765,6 @@ private: // Create a new entry in the devices list - must be called if it is sure it does not already exist Z_Device & createDeviceEntry(uint16_t shortaddr, uint64_t longaddr = 0); void freeDeviceEntry(Z_Device *device); - - void setStringAttribute(char*& attr, const char * str); }; /*********************************************************************************************\ diff --git a/tasmota/xdrv_23_zigbee_2a_devices_impl.ino b/tasmota/xdrv_23_zigbee_2a_devices_impl.ino index 9c25cde89..9e648f7d4 100644 --- a/tasmota/xdrv_23_zigbee_2a_devices_impl.ino +++ b/tasmota/xdrv_23_zigbee_2a_devices_impl.ino @@ -29,10 +29,12 @@ // Z_Device & Z_Devices::createDeviceEntry(uint16_t shortaddr, uint64_t longaddr) { if ((BAD_SHORTADDR == shortaddr) && !longaddr) { return (Z_Device&) device_unk; } // it is not legal to create this entry - Z_Device device(shortaddr, longaddr); + Z_Device & device = _devices.addToLast(); + device.shortaddr = shortaddr; + device.longaddr = longaddr; dirty(); - return _devices.addHead(device); + return device; } void Z_Devices::freeDeviceEntry(Z_Device *device) { @@ -178,7 +180,7 @@ bool Z_Devices::removeDevice(uint16_t shortaddr) { // In: // shortaddr // longaddr (both can't be null at the same time) -void Z_Devices::updateDevice(uint16_t shortaddr, uint64_t longaddr) { +Z_Device & Z_Devices::updateDevice(uint16_t shortaddr, uint64_t longaddr) { Z_Device * s_found = &findShortAddr(shortaddr); // is there already a shortaddr entry Z_Device * l_found = &findLongAddr(longaddr); // is there already a longaddr entry @@ -191,64 +193,64 @@ void Z_Devices::updateDevice(uint16_t shortaddr, uint64_t longaddr) { freeDeviceEntry(s_found); _devices.remove(s_found); dirty(); + return *l_found; } } else if (foundDevice(*s_found)) { // shortaddr already exists but longaddr not // add the longaddr to the entry s_found->longaddr = longaddr; dirty(); + return *s_found; } else if (foundDevice(*l_found)) { // longaddr entry exists, update shortaddr l_found->shortaddr = shortaddr; dirty(); + return *l_found; } else { // neither short/lonf addr are found. if ((BAD_SHORTADDR != shortaddr) || longaddr) { - createDeviceEntry(shortaddr, longaddr); + return createDeviceEntry(shortaddr, longaddr); } + return (Z_Device&) device_unk; } } // // Clear all endpoints // -void Z_Devices::clearEndpoints(uint16_t shortaddr) { - Z_Device &device = getShortAddr(shortaddr); +void Z_Device::clearEndpoints(void) { for (uint32_t i = 0; i < endpoints_max; i++) { - device.endpoints[i] = 0; + endpoints[i] = 0; // no dirty here because it doesn't make sense to store it, does it? } } // // Add an endpoint to a shortaddr +// return true if a change was made // -void Z_Devices::addEndpoint(uint16_t shortaddr, uint8_t endpoint) { - if (0x00 == endpoint) { return; } - Z_Device &device = getShortAddr(shortaddr); +bool Z_Device::addEndpoint(uint8_t endpoint) { + if ((0x00 == endpoint) || (endpoint > 240)) { return false; } for (uint32_t i = 0; i < endpoints_max; i++) { - if (endpoint == device.endpoints[i]) { - return; // endpoint already there + if (endpoint == endpoints[i]) { + return false; // endpoint already there } - if (0 == device.endpoints[i]) { - device.endpoints[i] = endpoint; - dirty(); - return; + if (0 == endpoints[i]) { + endpoints[i] = endpoint; + return true; } } + return false; } // // Count the number of known endpoints // -uint32_t Z_Devices::countEndpoints(uint16_t shortaddr) const { +uint32_t Z_Device::countEndpoints(void) const { uint32_t count_ep = 0; - const Z_Device & device =findShortAddr(shortaddr); - if (!foundDevice(device)) return 0; - for (uint32_t i = 0; i < endpoints_max; i++) { - if (0 != device.endpoints[i]) { + if (0 != endpoints[i]) { count_ep++; } } @@ -262,7 +264,7 @@ uint8_t Z_Devices::findFirstEndpoint(uint16_t shortaddr) const { return findShortAddr(shortaddr).endpoints[0]; // returns 0x00 if no endpoint } -void Z_Devices::setStringAttribute(char*& attr, const char * str) { +void Z_Device::setStringAttribute(char*& attr, const char * str) { if (nullptr == str) { return; } // ignore a null parameter size_t str_len = strlen(str); @@ -278,10 +280,11 @@ void Z_Devices::setStringAttribute(char*& attr, const char * str) { } } if (str_len) { + if (str_len > 31) { str_len = 31; } attr = (char*) malloc(str_len + 1); strlcpy(attr, str, str_len + 1); } - dirty(); + zigbee_devices.dirty(); } // @@ -293,16 +296,16 @@ void Z_Devices::setStringAttribute(char*& attr, const char * str) { // Impact: // - Any actual change in ManufId (i.e. setting a different value) triggers a `dirty()` and saving to Flash // -void Z_Devices::setManufId(uint16_t shortaddr, const char * str) { - setStringAttribute(getShortAddr(shortaddr).manufacturerId, str); +void Z_Device::setManufId(const char * str) { + setStringAttribute(manufacturerId, str); } -void Z_Devices::setModelId(uint16_t shortaddr, const char * str) { - setStringAttribute(getShortAddr(shortaddr).modelId, str); +void Z_Device::setModelId(const char * str) { + setStringAttribute(modelId, str); } -void Z_Devices::setFriendlyName(uint16_t shortaddr, const char * str) { - setStringAttribute(getShortAddr(shortaddr).friendlyName, str); +void Z_Device::setFriendlyName(const char * str) { + setStringAttribute(friendlyName, str); } @@ -473,7 +476,7 @@ bool Z_Devices::jsonIsConflict(uint16_t shortaddr, const Z_attribute_list &attr_ if (device.attr_list.isValidSrcEp() && attr_list.isValidSrcEp()) { if (device.attr_list.src_ep != attr_list.src_ep) { return true; } } - + // LQI does not count as conflicting // parse all other parameters @@ -507,28 +510,28 @@ void Z_Devices::jsonPublishFlush(uint16_t shortaddr) { gZbLastMessage.groupaddr = attr_list.group_id; // %zbgroup% gZbLastMessage.endpoint = attr_list.src_ep; // %zbendpoint% - mqtt_data[0] = 0; // clear string + TasmotaGlobal.mqtt_data[0] = 0; // clear string // Do we prefix with `ZbReceived`? if (!Settings.flag4.remove_zbreceived) { Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED "\":")); } // What key do we use, shortaddr or name? if (use_fname) { - Response_P(PSTR("%s{\"%s\":{"), mqtt_data, fname); + Response_P(PSTR("%s{\"%s\":{"), TasmotaGlobal.mqtt_data, fname); } else { - Response_P(PSTR("%s{\"0x%04X\":{"), mqtt_data, shortaddr); + Response_P(PSTR("%s{\"0x%04X\":{"), TasmotaGlobal.mqtt_data, shortaddr); } // Add "Device":"0x...." - Response_P(PSTR("%s\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\","), mqtt_data, shortaddr); + ResponseAppend_P(PSTR("\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\","), shortaddr); // Add "Name":"xxx" if name is present if (fname) { - Response_P(PSTR("%s\"" D_JSON_ZIGBEE_NAME "\":\"%s\","), mqtt_data, EscapeJSONString(fname).c_str()); + ResponseAppend_P(PSTR("\"" D_JSON_ZIGBEE_NAME "\":\"%s\","), EscapeJSONString(fname).c_str()); } // Add all other attributes - Response_P(PSTR("%s%s}}"), mqtt_data, attr_list.toString().c_str()); - + ResponseAppend_P(PSTR("%s}}"), attr_list.toString().c_str()); + if (!Settings.flag4.remove_zbreceived) { - Response_P(PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); } attr_list.reset(); // clear the attributes @@ -636,7 +639,7 @@ String Z_Devices::dumpLightState(uint16_t shortaddr) const { } // Z_Data_Light::toAttributes(attr_list, device.data.find(0)); } - + Z_attribute_list attr_list_root; Z_attribute * attr_root; if (use_fname) { @@ -652,7 +655,7 @@ String Z_Devices::dumpLightState(uint16_t shortaddr) const { // Mode = 1: simple dump of devices addresses // Mode = 2: simple dump of devices addresses and names, endpoints, light String Z_Devices::dump(uint32_t dump_mode, uint16_t status_shortaddr) const { - Z_json_array json_arr; + JsonGeneratorArray json_arr; for (const auto & device : _devices) { uint16_t shortaddr = device.shortaddr; @@ -678,20 +681,30 @@ String Z_Devices::dump(uint32_t dump_mode, uint16_t status_shortaddr) const { if (device.modelId) { attr_list.addAttribute(F(D_JSON_MODEL D_JSON_ID)).setStr(device.modelId); } - int8_t bulbtype = getHueBulbtype(shortaddr); - if (bulbtype >= 0) { - attr_list.addAttribute(F(D_JSON_ZIGBEE_LIGHT)).setInt(bulbtype); // sign extend, 0xFF changed as -1 - } if (device.manufacturerId) { attr_list.addAttribute(F("Manufacturer")).setStr(device.manufacturerId); } - Z_json_array arr_ep; + + JsonGeneratorArray arr_ep; for (uint32_t i = 0; i < endpoints_max; i++) { uint8_t endpoint = device.endpoints[i]; if (0x00 == endpoint) { break; } arr_ep.add(endpoint); } attr_list.addAttribute(F("Endpoints")).setStrRaw(arr_ep.toString().c_str()); + + JsonGeneratorArray arr_data; + for (auto & data_elt : device.data) { + char key[8]; + if (data_elt.validConfig()) { + snprintf_P(key, sizeof(key), "?%02X.%1X", data_elt.getEndpoint(), data_elt.getConfig()); + } else { + snprintf_P(key, sizeof(key), "?%02X", data_elt.getEndpoint()); + } + key[0] = Z_Data::DataTypeToChar(data_elt.getType()); + arr_data.addStr(key); + } + attr_list.addAttribute(F("Config")).setStrRaw(arr_data.toString().c_str()); } json_arr.addStrRaw(attr_list.toString(true).c_str()); } @@ -710,18 +723,17 @@ String Z_Devices::dump(uint32_t dump_mode, uint16_t status_shortaddr) const { int32_t Z_Devices::deviceRestore(JsonParserObject json) { // params - uint16_t device = 0x0000; // 0x0000 is coordinator so considered invalid + uint16_t shortaddr = 0x0000; // 0x0000 is coordinator so considered invalid uint64_t ieeeaddr = 0x0000000000000000LL; // 0 means unknown const char * modelid = nullptr; const char * manufid = nullptr; const char * friendlyname = nullptr; - int8_t bulbtype = -1; size_t endpoints_len = 0; // read mandatory "Device" JsonParserToken val_device = json[PSTR("Device")]; if (val_device) { - device = (uint32_t) val_device.getUInt(device); + shortaddr = (uint32_t) val_device.getUInt(shortaddr); } else { return -1; // missing "Device" attribute } @@ -730,23 +742,41 @@ int32_t Z_Devices::deviceRestore(JsonParserObject json) { friendlyname = json.getStr(PSTR("Name"), nullptr); // read "Name" modelid = json.getStr(PSTR("ModelId"), nullptr); manufid = json.getStr(PSTR("Manufacturer"), nullptr); - JsonParserToken tok_bulbtype = json[PSTR(D_JSON_ZIGBEE_LIGHT)]; // update internal device information - updateDevice(device, ieeeaddr); - if (modelid) { setModelId(device, modelid); } - if (manufid) { setManufId(device, manufid); } - if (friendlyname) { setFriendlyName(device, friendlyname); } - if (tok_bulbtype) { setLightProfile(device, tok_bulbtype.getInt()); } + updateDevice(shortaddr, ieeeaddr); + Z_Device & device = getShortAddr(shortaddr); + if (modelid) { device.setModelId(modelid); } + if (manufid) { device.setManufId(manufid); } + if (friendlyname) { device.setFriendlyName(friendlyname); } // read "Endpoints" JsonParserToken val_endpoints = json[PSTR("Endpoints")]; if (val_endpoints.isArray()) { JsonParserArray arr_ep = JsonParserArray(val_endpoints); - clearEndpoints(device); // clear even if array is empty + device.clearEndpoints(); // clear even if array is empty for (auto ep_elt : arr_ep) { uint8_t ep = ep_elt.getUInt(); - if (ep) { addEndpoint(device, ep); } + if (ep) { device.addEndpoint(ep); } + } + } + + // read "Config" + JsonParserToken val_config = json[PSTR("Config")]; + if (val_config.isArray()) { + JsonParserArray arr_config = JsonParserArray(val_config); + device.data.reset(); // remove existing configuration + for (auto config_elt : arr_config) { + const char * conf_str = config_elt.getStr(); + Z_Data_Type data_type; + uint8_t ep, config; + + if (Z_Data::ConfigToZData(conf_str, &data_type, &ep, &config)) { + Z_Data & data = device.data.getByType(data_type, ep); + if (&data != nullptr) { + data.setConfig(config); + } + } } } diff --git a/tasmota/xdrv_23_zigbee_4_persistence.ino b/tasmota/xdrv_23_zigbee_4_persistence.ino index 0e688c960..f893bc004 100644 --- a/tasmota/xdrv_23_zigbee_4_persistence.ino +++ b/tasmota/xdrv_23_zigbee_4_persistence.ino @@ -26,6 +26,14 @@ // uint16 - start address in Flash (offset) // uint16 - length in bytes (makes sure parsing stops) // +// First byte: +// 0x00 - Empty or V3 format +// 0x01-0xFE - Legacy format +// 0xFF - invalid +// +// +// V1 Legacy +// ========= // File structure: // uint8 - number of devices, 0=none, 0xFF=invalid entry (probably Flash was erased) // @@ -47,6 +55,29 @@ // reserved for extensions // -- V2 -- // int8_t - zigbee profile of the device +// +// ======================= +// v3 with version number +// File structure: +// +// uint8 - number of devices, 0=none, 0xFF=invalid entry (probably Flash was erased) +// +// [Array of devices] +// [Offset = 2] +// uint8 - length of device record +// uint16 - short address +// uint64 - long IEEE address +// +// str - ModelID (null terminated C string, 32 chars max) +// str - Manuf (null terminated C string, 32 chars max) +// str - FriendlyName (null terminated C string, 32 chars max) +// +// [Array of endpoints] +// uint8 - endpoint number, 0xFF marks the end of endpoints +// uint8[] - list of configuration bytes, 0xFF marks the end +// i.e. 0xFF-0xFF marks the end of the array of endpoints +// + // Memory footprint #ifdef ESP8266 @@ -63,71 +94,81 @@ const static size_t z_block_offset = 0x0000; // No offset needed const static size_t z_block_len = 0x1000; // 4kb #endif -class z_flashdata_t { +// Each entry consumes 8 bytes +class Z_Flashentry { public: + uint32_t name; // simple 4 letters name. Currently 'zig1', 'zig2'. 0xFFFFFFFF if not entry + uint16_t len; // len of object in bytes, 0xFFFF if no entry + uint16_t start; // address of start, 0xFFFF if empty, must be aligned on 128 bytes boundaries +}; + +class Z_Flashdirectory { +public: + // 8 bytes header + uint32_t magic; // magic value 'Tsmt' to check that the block is initialized + uint32_t clock; // clock vector to discard entries that are made before this one. This should be incremented by 1 for each new entry (future anti-weavering) + // entries, 14*8 = 112 bytes + Z_Flashentry entries[14]; uint32_t name; // simple 4 letters name. Currently 'skey', 'crt ', 'crt1', 'crt2' uint16_t len; // len of object uint16_t reserved; // align on 4 bytes boundary + // link to next entry, none for now, but may be used for anti-weavering + uint16_t next_dir; // 0xFFFF if none + uint16_t reserved1; // must be 0xFFFF + uint32_t reserved2; // must be 0xFFFFFFFF }; -const static uint32_t ZIGB_NAME = 0x3167697A; // 'zig1' little endian -const static size_t Z_MAX_FLASH = z_block_len - sizeof(z_flashdata_t); // 2040 +const static uint32_t ZIGB_NAME1 = 0x3167697A; // 'zig1' little endian +const static uint32_t ZIGB_NAME2 = 0x3267697A; // 'zig2' little endian, v2 +const static size_t Z_MAX_FLASH = z_block_len - sizeof(Z_Flashentry); // 2040 -class SBuffer hibernateDevice(const struct Z_Device &device) { +bool hibernateDeviceConfiguration(SBuffer & buf, const class Z_Data_Set & data, uint8_t endpoint) { + bool found = false; + for (auto & elt : data) { + if (endpoint == elt.getEndpoint()) { + buf.add8(elt.getConfigByte()); + found = true; + } + } + return found; +} + +class SBuffer hibernateDevicev2(const struct Z_Device &device) { SBuffer buf(128); buf.add8(0x00); // overall length, will be updated later buf.add16(device.shortaddr); buf.add64(device.longaddr); - uint32_t endpoints_count = 0; - for (endpoints_count = 0; endpoints_count < endpoints_max; endpoints_count++) { - if (0x00 == device.endpoints[endpoints_count]) { break; } + char *names[3] = { device.modelId, device.manufacturerId, device.friendlyName }; + + for (uint32_t i=0; i 32) { len = 32; } // max 32 chars + buf.addBuffer(p, len); + } + buf.add8(0x00); // end of string marker } - buf.add8(endpoints_count); - // iterate on endpoints - for (uint32_t i = 0; i < endpoints_max; i++) { + // check if we need to write fake endpoint 0x00 + buf.add8(0x00); + if (hibernateDeviceConfiguration(buf, device.data, 0)) { + buf.add8(0xFF); // end of configuration + } else { + buf.setLen(buf.len()-1); // remove 1 byte header + } + // scan endpoints + for (uint32_t i=0; i 32) { model_len = 32; } // max 32 chars - buf.addBuffer(device.modelId, model_len); - } - buf.add8(0x00); // end of string marker - - // ManufID - if (device.manufacturerId) { - size_t manuf_len = strlen(device.manufacturerId); - if (manuf_len > 32) { manuf_len = 32; } // max 32 chars - buf.addBuffer(device.manufacturerId, manuf_len); - } - buf.add8(0x00); // end of string marker - - // FriendlyName - if (device.friendlyName) { - size_t frname_len = strlen(device.friendlyName); - if (frname_len > 32) {frname_len = 32; } // max 32 chars - buf.addBuffer(device.friendlyName, frname_len); - } - buf.add8(0x00); // end of string marker - - // Zigbee Profile - buf.add8(device.getLightChannels()); + buf.add8(0xFF); // end of endpoints // update overall length buf.set8(0, buf.len()); @@ -144,7 +185,7 @@ class SBuffer hibernateDevices(void) { for (uint32_t i = 0; i < devices_size; i++) { const Z_Device & device = zigbee_devices.devicesAt(i); - const SBuffer buf_device = hibernateDevice(device); + const SBuffer buf_device = hibernateDevicev2(device); buf.addBuffer(buf_device); } @@ -164,74 +205,102 @@ class SBuffer hibernateDevices(void) { return buf; } -void hydrateDevices(const SBuffer &buf) { - uint32_t buf_len = buf.len(); - if (buf_len <= 10) { return; } +// parse a single string from the saved data +// if something wrong happens, returns nullptr to ignore the string +// Index d is incremented to just after the string +const char * hydrateSingleString(const SBuffer & buf, uint32_t *d) { + size_t s_len = buf.strlen(*d); + const char * ptr = s_len ? buf.charptr(*d) : ""; + *d += s_len + 1; + return ptr; +} - uint32_t k = 0; - uint32_t num_devices = buf.get8(k++); - for (uint32_t i = 0; (i < num_devices) && (k < buf_len); i++) { - uint32_t dev_record_len = buf.get8(k); - - SBuffer buf_d = buf.subBuffer(k, dev_record_len); - - uint32_t d = 1; // index in device buffer - uint16_t shortaddr = buf_d.get16(d); d += 2; - uint64_t longaddr = buf_d.get64(d); d += 8; - zigbee_devices.updateDevice(shortaddr, longaddr); // update device's addresses +void hydrateSingleDevice(const SBuffer & buf_d, uint32_t version) { + uint32_t d = 1; // index in device buffer + uint16_t shortaddr = buf_d.get16(d); d += 2; + uint64_t longaddr = buf_d.get64(d); d += 8; + size_t buf_len = buf_d.len(); + Z_Device & device = zigbee_devices.updateDevice(shortaddr, longaddr); // update device's addresses + if (1 == version) { uint32_t endpoints = buf_d.get8(d++); for (uint32_t j = 0; j < endpoints; j++) { uint8_t ep = buf_d.get8(d++); uint16_t ep_profile = buf_d.get16(d); d += 2; - zigbee_devices.addEndpoint(shortaddr, ep); + device.addEndpoint(ep); // in clusters - while (d < dev_record_len) { // safe guard against overflow + while (d < buf_len) { // safe guard against overflow uint8_t ep_cluster = buf_d.get8(d++); if (0xFF == ep_cluster) { break; } // end of block // ignore } // out clusters - while (d < dev_record_len) { // safe guard against overflow + while (d < buf_len) { // safe guard against overflow uint8_t ep_cluster = buf_d.get8(d++); if (0xFF == ep_cluster) { break; } // end of block // ignore } } + } - // parse 3 strings - char empty[] = ""; + // ModelId + device.setModelId(hydrateSingleString(buf_d, &d)); - // ManufID - uint32_t s_len = buf_d.strlen_s(d); - char *ptr = s_len ? buf_d.charptr(d) : empty; - zigbee_devices.setModelId(shortaddr, ptr); - d += s_len + 1; + // ManufID + device.setManufId(hydrateSingleString(buf_d, &d)); - // ManufID - s_len = buf_d.strlen_s(d); - ptr = s_len ? buf_d.charptr(d) : empty; - zigbee_devices.setManufId(shortaddr, ptr); - d += s_len + 1; + // FriendlyName + device.setFriendlyName(hydrateSingleString(buf_d, &d)); - // FriendlyName - s_len = buf_d.strlen_s(d); - ptr = s_len ? buf_d.charptr(d) : empty; - zigbee_devices.setFriendlyName(shortaddr, ptr); - d += s_len + 1; + if (d >= buf_len) { return; } - // Hue bulbtype - if present - if (d < dev_record_len) { - zigbee_devices.setLightProfile(shortaddr, buf_d.get8(d)); - d++; + // Hue bulbtype - if present + if (1 == version) { + zigbee_devices.setLightProfile(shortaddr, buf_d.get8(d)); + d++; + } else if (2 == version) { + // v2 parser + while (d < buf_len) { + uint8_t ep = buf_d.get8(d++); + if (0xFF == ep) { break; } // ep 0xFF marks the end of the endpoints + if (ep > 240) { ep = 0xFF; } // ep == 0xFF means ignore + device.addEndpoint(ep); // it will ignore invalid endpoints + while (d < buf_len) { + uint8_t config_type = buf_d.get8(d++); + if (0xFF == config_type) { break; } // 0xFF marks the end of congiguration + uint8_t config = config_type & 0x0F; + Z_Data_Type type = (Z_Data_Type) (config_type >> 4); + // set the configuration + if (ep != 0xFF) { + Z_Data & z_data = device.data.getByType(type, ep); + if (&z_data != nullptr) { + z_data.setConfig(config); + } + } + } } + } +} + +void hydrateDevices(const SBuffer &buf, uint32_t version) { + uint32_t buf_len = buf.len(); + if (buf_len <= 10) { return; } + + uint32_t k = 0; // byte index in global buffer + uint32_t num_devices = buf.get8(k++); + for (uint32_t i = 0; (i < num_devices) && (k < buf_len); i++) { + uint32_t dev_record_len = buf.get8(k); + + SBuffer buf_d = buf.subBuffer(k, dev_record_len); + hydrateSingleDevice(buf_d, version); // next iteration k += dev_record_len; } } + void loadZigbeeDevices(void) { #ifdef ESP32 // first copy SPI buffer into ram @@ -243,19 +312,24 @@ void loadZigbeeDevices(void) { ZigbeeRead(&spi_buffer, z_spi_len); z_dev_start = spi_buffer; #endif // ESP32 - z_flashdata_t flashdata; - memcpy_P(&flashdata, z_dev_start, sizeof(z_flashdata_t)); + Z_Flashentry flashdata; + memcpy_P(&flashdata, z_dev_start, sizeof(Z_Flashentry)); // AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "Memory %d"), ESP_getFreeHeap()); AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "Zigbee signature in Flash: %08X - %d"), flashdata.name, flashdata.len); // Check the signature - if ((flashdata.name == ZIGB_NAME) && (flashdata.len > 0)) { + if ( ((flashdata.name == ZIGB_NAME1) || (flashdata.name == ZIGB_NAME2)) + && (flashdata.len > 0)) { uint16_t buf_len = flashdata.len; + uint32_t version = (flashdata.name == ZIGB_NAME2) ? 2 : 1; // parse what seems to be a valid entry SBuffer buf(buf_len); - buf.addBuffer(z_dev_start + sizeof(z_flashdata_t), buf_len); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee devices data in Flash (%d bytes)"), buf_len); - hydrateDevices(buf); + buf.addBuffer(z_dev_start + sizeof(Z_Flashentry), buf_len); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee devices data in Flash v%d (%d bytes)"), version, buf_len); + // Serial.printf(">> Buffer="); + // for (uint32_t i=0; iname = ZIGB_NAME; + Z_Flashentry *flashdata = (Z_Flashentry*)(spi_buffer + z_block_offset); + flashdata->name = ZIGB_NAME2; // v2 flashdata->len = buf_len; - flashdata->reserved = 0; + flashdata->start = 0; - memcpy(spi_buffer + z_block_offset + sizeof(z_flashdata_t), buf.getBuffer(), buf_len); + memcpy(spi_buffer + z_block_offset + sizeof(Z_Flashentry), buf.getBuffer(), buf_len); // buffer is now ready, write it back #ifdef ESP8266 diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index 5d96d9c70..c90c0f8e0 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -504,7 +504,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { Zuint8, Cx0300, 0x003C, Z_(ColorPointBIntensity), Cm1, 0 }, // Illuminance Measurement cluster - { Zuint16, Cx0400, 0x0000, Z_(Illuminance), Cm1, 0 }, // Illuminance (in Lux) + { Zuint16, Cx0400, 0x0000, Z_(Illuminance), Cm1 + Z_EXPORT_DATA, Z_MAPPING(Z_Data_PIR, illuminance) }, // Illuminance (in Lux) { Zuint16, Cx0400, 0x0001, Z_(IlluminanceMinMeasuredValue), Cm1, 0 }, // { Zuint16, Cx0400, 0x0002, Z_(IlluminanceMaxMeasuredValue), Cm1, 0 }, // { Zuint16, Cx0400, 0x0003, Z_(IlluminanceTolerance), Cm1, 0 }, // @@ -552,7 +552,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { Zunk, Cx0405, 0xFFFF, Z_(), Cm0, 0 }, // Remove all other values // Occupancy Sensing cluster - { Zmap8, Cx0406, 0x0000, Z_(Occupancy), Cm1, 0 }, // Occupancy (map8) + { Zmap8, Cx0406, 0x0000, Z_(Occupancy), Cm1 + Z_EXPORT_DATA, Z_MAPPING(Z_Data_PIR, occupancy) }, // Occupancy (map8) { Zenum8, Cx0406, 0x0001, Z_(OccupancySensorType), Cm1, 0 }, // OccupancySensorType { Zunk, Cx0406, 0xFFFF, Z_(), Cm0, 0 }, // Remove all other values @@ -706,7 +706,7 @@ public: if (Settings.flag3.tuya_serial_mqtt_publish) { MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_RSLT_SENSOR)); } else { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "%s"), mqtt_data); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "%s"), TasmotaGlobal.mqtt_data); } } @@ -749,7 +749,6 @@ public: void parseResponse(void); void parseResponseOld(void); void parseClusterSpecificCommand(Z_attribute_list& attr_list); - void postProcessAttributes(uint16_t shortaddr, Z_attribute_list& attr_list); // synthetic attributes converters void syntheticAqaraSensor(Z_attribute_list &attr_list, class Z_attribute &attr); @@ -1239,6 +1238,15 @@ void ZCLFrame::computeSyntheticAttributes(Z_attribute_list& attr_list) { attr_list.addAttribute(0x0001, 0x0021).setUInt(toPercentageCR2032(mv) * 2); } break; + case 0x00010021: // BatteryPercentage + { + const char * model_c = zigbee_devices.getModelId(_srcaddr); // null if unknown + String modelId((char*) model_c); + if (modelId.startsWith(F("TRADFRI"))) { + attr.setUInt(attr.getUInt() * 2); // bug in TRADFRI battery, need to double the value + } + } + break; case 0x02010008: // Pi Heating Demand - solve Eutotronic bug { const char * manufacturer_c = zigbee_devices.getManufacturerId(_srcaddr); // null if unknown @@ -1277,10 +1285,15 @@ void ZCLFrame::generateCallBacks(Z_attribute_list& attr_list) { case 0x04060000: // Occupancy uint32_t occupancy = attr.getUInt(); if (occupancy) { - zigbee_devices.setTimer(_srcaddr, 0 /* groupaddr */, OCCUPANCY_TIMEOUT, _cluster_id, _srcendpoint, Z_CAT_VIRTUAL_OCCUPANCY, 0, &Z_OccupancyCallback); + uint32_t pir_timer = OCCUPANCY_TIMEOUT; + const Z_Data_PIR & pir_found = (const Z_Data_PIR&) zigbee_devices.getShortAddr(_srcaddr).data.find(Z_Data_Type::Z_PIR, _srcendpoint); + if (&pir_found != nullptr) { + pir_timer = pir_found.getTimeoutSeconds() * 1000; + } + zigbee_devices.setTimer(_srcaddr, 0 /* groupaddr */, pir_timer, _cluster_id, _srcendpoint, Z_CAT_VIRTUAL_OCCUPANCY, 0, &Z_OccupancyCallback); } else { zigbee_devices.resetTimersForDevice(_srcaddr, 0 /* groupaddr */, Z_CAT_VIRTUAL_OCCUPANCY); - } + } break; } } @@ -1332,7 +1345,7 @@ void ZCLFrame::parseReadAttributes(Z_attribute_list& attr_list) { attr_list.addAttribute(F(D_CMND_ZIGBEE_CLUSTER)).setUInt(_cluster_id); - Z_json_array attr_numbers; + JsonGeneratorArray attr_numbers; Z_attribute_list attr_names; while (len >= 2 + i) { uint16_t attrid = _payload.get16(i); @@ -1354,7 +1367,7 @@ void ZCLFrame::parseReadAttributes(Z_attribute_list& attr_list) { } attr_list.addAttribute(F("Read")).setStrRaw(attr_numbers.toString().c_str()); attr_list.addAttribute(F("ReadNames")).setStrRaw(attr_names.toString(true).c_str()); - + // call auto-responder autoResponder(read_attr_ids, len/2); } @@ -1755,22 +1768,30 @@ void ZCLFrame::syntheticAqaraVibration(class Z_attribute_list &attr_list, class /// Publish a message for `"Occupancy":0` when the timer expired void Z_OccupancyCallback(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { Z_attribute_list attr_list; - attr_list.addAttribute(F(OCCUPANCY)).setUInt(0); + attr_list.addAttribute(0x0406, 0x0000).setUInt(0); // Occupancy + Z_postProcessAttributes(shortaddr, endpoint, attr_list); // make sure all is updated accordingly zigbee_devices.jsonPublishNow(shortaddr, attr_list); } // ====================================================================== -void ZCLFrame::postProcessAttributes(uint16_t shortaddr, Z_attribute_list& attr_list) { - // source endpoint - uint8_t src_ep = _srcendpoint; - +void Z_postProcessAttributes(uint16_t shortaddr, uint16_t src_ep, class Z_attribute_list& attr_list) { + Z_Device & device = zigbee_devices.getShortAddr(shortaddr); + uint8_t count_ep = device.countEndpoints(); + for (auto &attr : attr_list) { + // add endpoint suffix if needed + if ((Settings.flag4.zb_index_ep) && (src_ep != 1) && (count_ep > 1)) { + // we need to add suffix if the suffix is not already different from 1 + if (attr.key_suffix == 1) { + attr.key_suffix = src_ep; + } + } + // attr is Z_attribute& if (!attr.key_is_str) { uint16_t cluster = attr.key.id.cluster; uint16_t attribute = attr.key.id.attr_id; uint32_t ccccaaaa = (attr.key.id.cluster << 16) | attr.key.id.attr_id; - Z_Device & device = zigbee_devices.getShortAddr(shortaddr); // Look for an entry in the converter table bool found = false; @@ -1803,6 +1824,8 @@ void ZCLFrame::postProcessAttributes(uint16_t shortaddr, Z_attribute_list& attr_ // First we find or instantiate the correct Z_Data_XXX accorfing to the endpoint // Then store the attribute at the attribute addres (via offset) and according to size 8/16/32 bits + // add the endpoint if it was not already known + device.addEndpoint(src_ep); // we don't apply the multiplier, but instead store in Z_Data_XXX object Z_Data & data = device.data.getByType(map_type, src_ep); uint8_t *attr_address = ((uint8_t*)&data) + sizeof(Z_Data) + map_offset; @@ -1811,8 +1834,10 @@ void ZCLFrame::postProcessAttributes(uint16_t shortaddr, Z_attribute_list& attr_ // AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "Mapping type=%d offset=%d zigbee_type=%02X value=%d\n"), (uint8_t) map_type, map_offset, zigbee_type, ival32); switch (zigbee_type) { case Zenum8: + case Zmap8: case Zuint8: *(uint8_t*)attr_address = uval32; break; case Zenum16: + case Zmap16: case Zuint16: *(uint16_t*)attr_address = uval32; break; case Zuint32: *(uint32_t*)attr_address = uval32; break; case Zint8: *(int8_t*)attr_address = ival32; break; @@ -1826,8 +1851,8 @@ void ZCLFrame::postProcessAttributes(uint16_t shortaddr, Z_attribute_list& attr_ Z_Data_Set & data = device.data; // update any internal structure switch (ccccaaaa) { - case 0x00000004: zigbee_devices.setManufId(shortaddr, attr.getStr()); break; - case 0x00000005: zigbee_devices.setModelId(shortaddr, attr.getStr()); break; + case 0x00000004: device.setManufId(attr.getStr()); break; + case 0x00000005: device.setModelId(attr.getStr()); break; case 0x00010021: zigbee_devices.setBatteryPercent(shortaddr, uval16 / 2); break; case 0x00060000: case 0x00068000: device.setPower(attr.getBool(), src_ep); break; @@ -1952,7 +1977,9 @@ void Z_Data::toAttributes(Z_attribute_list & attr_list, Z_Data_Type type) const uint32_t uval32; switch (zigbee_type) { case Zenum8: + case Zmap8: case Zuint8: uval32 = *(uint8_t*)attr_address; if (uval32 != 0xFF) data_size = 8; break; + case Zmap16: case Zenum16: case Zuint16: uval32 = *(uint16_t*)attr_address; if (uval32 != 0xFFFF) data_size = 16; break; case Zuint32: uval32 = *(uint32_t*)attr_address; if (uval32 != 0xFFFFFFFF) data_size = 32; break; @@ -1963,7 +1990,7 @@ void Z_Data::toAttributes(Z_attribute_list & attr_list, Z_Data_Type type) const if (data_size != 0) { Z_attribute & attr = attr_list.addAttribute(conv_name); - if (data_size > 0) { attr.setUInt(uval32); } + if (data_size > 0) { attr.setUInt(uval32); } else { attr.setInt(ival32); } } } diff --git a/tasmota/xdrv_23_zigbee_6_commands.ino b/tasmota/xdrv_23_zigbee_6_commands.ino index b409dcf86..d3bdc3253 100644 --- a/tasmota/xdrv_23_zigbee_6_commands.ino +++ b/tasmota/xdrv_23_zigbee_6_commands.ino @@ -370,7 +370,7 @@ void convertClusterSpecific(class Z_attribute_list &attr_list, uint16_t cluster, attr_list.addAttribute(command_name, PSTR("Count")).setUInt(xyz.y); { - Z_json_array group_list; + JsonGeneratorArray group_list; for (uint32_t i = 0; i < xyz.y; i++) { group_list.add(payload.get16(2 + 2*i)); } @@ -431,7 +431,7 @@ void convertClusterSpecific(class Z_attribute_list &attr_list, uint16_t cluster, char command_suffix[4] = { 0x00 }; // empty string by default // if SO101 and multiple endpoints, append endpoint number if (Settings.flag4.zb_index_ep) { - if (zigbee_devices.countEndpoints(shortaddr) > 0) { + if (zigbee_devices.getShortAddr(shortaddr).countEndpoints() > 0) { snprintf_P(command_suffix, sizeof(command_suffix), PSTR("%d"), srcendpoint); } } @@ -441,7 +441,7 @@ void convertClusterSpecific(class Z_attribute_list &attr_list, uint16_t cluster, attr_list.addAttribute(command_name, command_suffix).setUInt(xyz.x); } else { // multiple answers, create an array - Z_json_array arr; + JsonGeneratorArray arr; arr.add(xyz.x); arr.add(xyz.y); if (xyz.z_type) { diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index b6ba038e9..2ce31fa92 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -165,7 +165,7 @@ int32_t EZ_RouteError(int32_t res, const class SBuffer &buf) { // int32_t EZ_PermitJoinRsp(int32_t res, const class SBuffer &buf) { uint8_t status = buf.get8(2); - + if (status) { // only report if there is an error Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{\"Status\":23,\"Message\":\"Pairing mode error 0x%02X\"}}"), status); MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); @@ -539,7 +539,7 @@ int32_t Z_ReceiveActiveEp(int32_t res, const class SBuffer &buf) { for (uint32_t i = 0; i < activeEpCount; i++) { uint8_t ep = activeEpList[i]; - zigbee_devices.addEndpoint(nwkAddr, ep); + zigbee_devices.getShortAddr(nwkAddr).addEndpoint(ep); if ((i < 4) && (ep < 0x10)) { zigbee_devices.queueTimer(nwkAddr, 0 /* groupaddr */, 1500, ep /* fake cluster as ep */, ep, Z_CAT_EP_DESC, 0 /* value */, &Z_SendSimpleDescReq); } @@ -925,6 +925,7 @@ int32_t Z_UnbindRsp(int32_t res, const class SBuffer &buf) { return -1; } + // // Handle MgMt Bind Rsp incoming message // @@ -1002,6 +1003,116 @@ int32_t Z_MgmtBindRsp(int32_t res, const class SBuffer &buf) { return -1; } +// Return false, true or null (if unknown) +const char * TrueFalseNull(uint32_t value) { + if (value == 0) { + return PSTR("false"); + } else if (value == 1) { + return PSTR("true"); + } else { + return PSTR("null"); + } +} + +const char * Z_DeviceRelationship(uint32_t value) { + switch (value) { + case 0: return PSTR("Parent"); + case 1: return PSTR("Child"); + case 2: return PSTR("Sibling"); + case 4: return PSTR("Previous"); + case 3: + default: return PSTR("None"); + } +} + +const char * Z_DeviceType(uint32_t value) { + switch (value) { + case 0: return PSTR("Coordinator"); + case 1: return PSTR("Router"); + case 2: return PSTR("Device"); + default: return PSTR("Unknown"); + } +} + +// +// Handle MgMt Bind Rsp incoming message +// +int32_t Z_MgmtLqiRsp(int32_t res, const class SBuffer &buf) { +#ifdef USE_ZIGBEE_ZNP + uint16_t shortaddr = buf.get16(2); + uint8_t status = buf.get8(4); + uint8_t lqi_total = buf.get8(5); + uint8_t lqi_start = buf.get8(6); + uint8_t lqi_len = buf.get8(7); + const size_t prefix_len = 8; +#endif // USE_ZIGBEE_ZNP +#ifdef USE_ZIGBEE_EZSP + uint16_t shortaddr = buf.get16(buf.len()-2); + uint8_t status = buf.get8(0); + uint8_t lqi_total = buf.get8(1); + uint8_t lqi_start = buf.get8(2); + uint8_t lqi_len = buf.get8(3); + const size_t prefix_len = 4; +#endif // USE_ZIGBEE_EZSP + + const char * friendlyName = zigbee_devices.getFriendlyName(shortaddr); + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_MAP "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\""), shortaddr); + if (friendlyName) { + ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_NAME "\":\"%s\""), friendlyName); + } + ResponseAppend_P(PSTR(",\"" D_JSON_ZIGBEE_STATUS "\":%d" + ",\"" D_JSON_ZIGBEE_STATUS_MSG "\":\"%s\"" + ",\"MapTotal\":%d" + ",\"MapStart\":%d" + ",\"Map\":[" + ), status, getZigbeeStatusMessage(status).c_str(), lqi_total, lqi_start + 1); + + uint32_t idx = prefix_len; + for (uint32_t i = 0; i < lqi_len; i++) { + if (idx + 22 > buf.len()) { break; } // size 22 for EZSP + + //uint64_t extpanid = buf.get16(idx); // unused + // uint64_t m_longaddr = buf.get64(idx + 8); + uint16_t m_shortaddr = buf.get16(idx + 16); + uint8_t m_dev_type = buf.get8(idx + 18); + uint8_t m_permitjoin = buf.get8(idx + 19); + uint8_t m_depth = buf.get8(idx + 20); + uint8_t m_lqi = buf.get8(idx + 21); + idx += 22; + + if (i > 0) { + ResponseAppend_P(PSTR(",")); + } + ResponseAppend_P(PSTR("{\"Device\":\"0x%04X\","), m_shortaddr); + + const char * friendlyName = zigbee_devices.getFriendlyName(m_shortaddr); + if (friendlyName) { + ResponseAppend_P(PSTR("\"Name\":\"%s\","), friendlyName); + } + ResponseAppend_P(PSTR("\"DeviceType\":\"%s\"," + "\"RxOnWhenIdle\":%s," + "\"Relationship\":\"%s\"," + "\"PermitJoin\":%s," + "\"Depth\":%d," + "\"LinkQuality\":%d" + "}" + ), + Z_DeviceType(m_dev_type & 0x03), + TrueFalseNull((m_dev_type & 0x0C) >> 2), + Z_DeviceRelationship((m_dev_type & 0x70) >> 4), + TrueFalseNull(m_permitjoin & 0x02), + m_depth, + m_lqi); + } + + ResponseAppend_P(PSTR("]}}")); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_MAP)); + + return -1; +} + #ifdef USE_ZIGBEE_EZSP // // Handle Parent Annonce Rsp incoming message @@ -1116,7 +1227,7 @@ void Z_SendSimpleDescReq(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluste // Queue requests for the device // 1. Request for 'ModelId' and 'Manufacturer': 0000/0005, 0000/0006 // 2. Auto-bind to coordinator: -// Iterate among +// Iterate among // void Z_SendDeviceInfoRequest(uint16_t shortaddr) { uint8_t endpoint = zigbee_devices.findFirstEndpoint(shortaddr); @@ -1167,7 +1278,7 @@ void Z_SendSingleAttributeRead(uint16_t shortaddr, uint16_t groupaddr, uint16_t // void Z_AutoBind(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) { uint64_t srcLongAddr = zigbee_devices.getDeviceLongAddr(shortaddr); - + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "auto-bind `ZbBind {\"Device\":\"0x%04X\",\"Endpoint\":%d,\"Cluster\":\"0x%04X\"}`"), shortaddr, endpoint, cluster); #ifdef USE_ZIGBEE_ZNP @@ -1215,8 +1326,8 @@ typedef struct Z_autoAttributeReporting_t { // Note the attribute must be registered in the converter list, used to retrieve the type of the attribute const Z_autoAttributeReporting_t Z_autoAttributeReporting[] PROGMEM = { - { 0x0001, 0x0020, 15*60, 15*60, 0.1 }, // BatteryVoltage - { 0x0001, 0x0021, 15*60, 15*60, 1 }, // BatteryPercentage + { 0x0001, 0x0020, 60*60, 4*60*60, 0.1 }, // BatteryVoltage + { 0x0001, 0x0021, 60*60, 4*60*60, 1 }, // BatteryPercentage { 0x0006, 0x0000, 1, 60*60, 0 }, // Power { 0x0201, 0x0000, 60, 60*10, 0.5 }, // LocalTemperature { 0x0201, 0x0008, 60, 60*10, 10 }, // PIHeatingDemand @@ -1293,7 +1404,7 @@ void Z_AutoConfigReportingForCluster(uint16_t shortaddr, uint16_t groupaddr, uin ResponseAppend_P(PSTR("}}")); if (buf.len() > 0) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "auto-bind `%s`"), mqtt_data); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "auto-bind `%s`"), TasmotaGlobal.mqtt_data); ZigbeeZCLSend_Raw(ZigbeeZCLSendMessage({ shortaddr, 0x0000, /* group */ @@ -1404,7 +1515,7 @@ void Z_IncomingMessage(class ZCLFrame &zcl_received) { zcl_received.generateSyntheticAttributes(attr_list); zcl_received.computeSyntheticAttributes(attr_list); zcl_received.generateCallBacks(attr_list); // set deferred callbacks, ex: Occupancy - zcl_received.postProcessAttributes(srcaddr, attr_list); + Z_postProcessAttributes(srcaddr, zcl_received.getSrcEndpoint(), attr_list); // since we just receveived data from the device, it is reachable zigbee_devices.resetTimersForDevice(srcaddr, 0 /* groupaddr */, Z_CAT_REACHABILITY); // remove any reachability timer already there @@ -1494,7 +1605,7 @@ int32_t EZ_IncomingMessage(int32_t res, const class SBuffer &buf) { uint16_t groupid = buf.get16(11); uint8_t seqnumber = buf.get8(13); int8_t linkrssi = buf.get8(15); - uint8_t linkquality = ZNP_RSSI2Lqi(linkrssi); // don't take EZSP LQI but calculate our own based on ZNP + uint8_t linkquality = ZNP_RSSI2Lqi(linkrssi); // don't take EZSP LQI but calculate our own based on ZNP uint16_t srcaddr = buf.get16(16); // uint8_t bindingindex = buf.get8(18); // not sure we need this one as a coordinator // uint8_t addressindex = buf.get8(19); // not sure how to handle this one @@ -1524,6 +1635,8 @@ int32_t EZ_IncomingMessage(int32_t res, const class SBuffer &buf) { return Z_BindRsp(res, zdo_buf); case ZDO_Unbind_rsp: return Z_UnbindRsp(res, zdo_buf); + case ZDO_Mgmt_Lqi_rsp: + return Z_MgmtLqiRsp(res, zdo_buf); case ZDO_Mgmt_Bind_rsp: return Z_MgmtBindRsp(res, zdo_buf); case ZDO_Parent_annce: @@ -1697,6 +1810,7 @@ const Z_Dispatcher Z_DispatchTable[] PROGMEM = { { { Z_AREQ | Z_ZDO, ZDO_IEEE_ADDR_RSP }, &Z_ReceiveIEEEAddr }, // 4581 { { Z_AREQ | Z_ZDO, ZDO_BIND_RSP }, &Z_BindRsp }, // 45A1 { { Z_AREQ | Z_ZDO, ZDO_UNBIND_RSP }, &Z_UnbindRsp }, // 45A2 + { { Z_AREQ | Z_ZDO, ZDO_MGMT_LQI_RSP }, &Z_MgmtLqiRsp }, // 45B1 { { Z_AREQ | Z_ZDO, ZDO_MGMT_BIND_RSP }, &Z_MgmtBindRsp }, // 45B3 }; diff --git a/tasmota/xdrv_23_zigbee_9_serial.ino b/tasmota/xdrv_23_zigbee_9_serial.ino index 4a9141d7f..b09562088 100644 --- a/tasmota/xdrv_23_zigbee_9_serial.ino +++ b/tasmota/xdrv_23_zigbee_9_serial.ino @@ -156,7 +156,7 @@ void ZigbeeInputLoop(void) { if (Settings.flag3.tuya_serial_mqtt_publish) { MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_RSLT_SENSOR)); } else { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "%s"), mqtt_data); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "%s"), TasmotaGlobal.mqtt_data); } // now process the message ZigbeeProcessInput(znp_buffer); @@ -293,13 +293,13 @@ void ZigbeeInitSerial(void) zigbee.active = false; if (PinUsed(GPIO_ZIGBEE_RX) && PinUsed(GPIO_ZIGBEE_TX)) { AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "GPIOs Rx:%d Tx:%d"), Pin(GPIO_ZIGBEE_RX), Pin(GPIO_ZIGBEE_TX)); - // if seriallog_level is 0, we allow GPIO 13/15 to switch to Hardware Serial - ZigbeeSerial = new TasmotaSerial(Pin(GPIO_ZIGBEE_RX), Pin(GPIO_ZIGBEE_TX), seriallog_level ? 1 : 2, 0, 256); // set a receive buffer of 256 bytes + // if TasmotaGlobal.seriallog_level is 0, we allow GPIO 13/15 to switch to Hardware Serial + ZigbeeSerial = new TasmotaSerial(Pin(GPIO_ZIGBEE_RX), Pin(GPIO_ZIGBEE_TX), TasmotaGlobal.seriallog_level ? 1 : 2, 0, 256); // set a receive buffer of 256 bytes ZigbeeSerial->begin(115200); if (ZigbeeSerial->hardwareSerial()) { ClaimSerial(); - uint32_t aligned_buffer = ((uint32_t)serial_in_buffer + 3) & ~3; - zigbee_buffer = new PreAllocatedSBuffer(sizeof(serial_in_buffer) - 3, (char*) aligned_buffer); + uint32_t aligned_buffer = ((uint32_t)TasmotaGlobal.serial_in_buffer + 3) & ~3; + zigbee_buffer = new PreAllocatedSBuffer(sizeof(TasmotaGlobal.serial_in_buffer) - 3, (char*) aligned_buffer); } else { // AddLog_P2(LOG_LEVEL_INFO, PSTR("ZigbeeInit Mem2 = %d"), ESP_getFreeHeap()); zigbee_buffer = new SBuffer(ZIGBEE_BUFFER_SIZE); @@ -545,7 +545,7 @@ void ZigbeeEZSPSendDATA(const uint8_t *msg, size_t len) { } EZSP_Serial.to_packets[to_frm] = buf; EZSP_Serial.to_end = (to_frm + 1) & 0x07; // move cursor - + // ZigbeeEZSPSendDATA_frm(send_cancel, to_frm, EZSP_Serial.from_ack); // increment to_frame @@ -609,7 +609,7 @@ int32_t ZigbeeProcessInputEZSP(class SBuffer &buf) { log_level = LOG_LEVEL_DEBUG; break; } - AddLog_P2(log_level, PSTR(D_LOG_ZIGBEE "%s"), mqtt_data); // TODO move to LOG_LEVEL_DEBUG when stable + AddLog_P2(log_level, PSTR(D_LOG_ZIGBEE "%s"), TasmotaGlobal.mqtt_data); // TODO move to LOG_LEVEL_DEBUG when stable } // Pass message to state machine @@ -672,14 +672,14 @@ int32_t ZigbeeProcessInputRaw(class SBuffer &buf) { // ERROR EZ_ERROR(buf.get8(2)); zigbee.active = false; // stop all zigbee activities - restart_flag = 2; // there is nothing more we can do except restart + TasmotaGlobal.restart_flag = 2; // there is nothing more we can do except restart } else { // Unknown AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZIG: Received unknown control byte 0x%02X"), control_byte); } } else { // DATA Frame - + // adjust to latest acked packet uint8_t new_ack = control_byte & 0x07; EZSP_HandleAck(new_ack); diff --git a/tasmota/xdrv_23_zigbee_9a_upload.ino b/tasmota/xdrv_23_zigbee_9a_upload.ino index e3c233152..e4b154dac 100644 --- a/tasmota/xdrv_23_zigbee_9a_upload.ino +++ b/tasmota/xdrv_23_zigbee_9a_upload.ino @@ -347,8 +347,8 @@ bool ZigbeeUploadXmodem(void) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: Init sync")); ZigbeeSerial->flush(); ZigbeeSerial->write('1'); // upload ebl - if (ssleep > 0) { - ssleep = 1; // Speed up loop used for xmodem upload + if (TasmotaGlobal.sleep > 0) { + TasmotaGlobal.sleep = 1; // Speed up loop used for xmodem upload } XModem.timeout = millis() + (XMODEM_SYNC_TIMEOUT * 1000); ZbUpload.ota_step = ZBU_SYNC; @@ -442,10 +442,10 @@ bool ZigbeeUploadXmodem(void) { case ZBU_DONE: { // *** Clean up and restart to disable bootloader and use new firmware AddLog_P2(LOG_LEVEL_DEBUG, PSTR("XMD: " D_RESTARTING)); ZigbeeUploadSetBootloader(1); // Disable bootloader and reset MCU - should happen at restart - if (1 == ssleep) { - ssleep = Settings.sleep; // Restore loop sleep + if (1 == TasmotaGlobal.sleep) { + TasmotaGlobal.sleep = Settings.sleep; // Restore loop sleep } -// restart_flag = 2; // Restart to disable bootloader and use new firmware +// TasmotaGlobal.restart_flag = 2; // Restart to disable bootloader and use new firmware ZbUpload.ota_step = ZBU_FINISH; // Never return to zero without a restart to get a sane Zigbee environment break; } diff --git a/tasmota/xdrv_23_zigbee_A_impl.ino b/tasmota/xdrv_23_zigbee_A_impl.ino index 3e68b20cc..950646563 100644 --- a/tasmota/xdrv_23_zigbee_A_impl.ino +++ b/tasmota/xdrv_23_zigbee_A_impl.ino @@ -32,7 +32,8 @@ const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" // prefix D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND "|" D_CMND_ZIGBEE_UNBIND "|" D_CMND_ZIGBEE_PING "|" D_CMND_ZIGBEE_MODELID "|" - D_CMND_ZIGBEE_LIGHT "|" D_CMND_ZIGBEE_RESTORE "|" D_CMND_ZIGBEE_BIND_STATE "|" + D_CMND_ZIGBEE_LIGHT "|" D_CMND_ZIGBEE_OCCUPANCY "|" + D_CMND_ZIGBEE_RESTORE "|" D_CMND_ZIGBEE_BIND_STATE "|" D_CMND_ZIGBEE_MAP "|" D_CMND_ZIGBEE_CONFIG "|" D_CMND_ZIGBEE_DATA ; @@ -47,7 +48,8 @@ void (* const ZigbeeCommand[])(void) PROGMEM = { &CmndZbStatus, &CmndZbReset, &CmndZbSend, &CmndZbProbe, &CmndZbForget, &CmndZbSave, &CmndZbName, &CmndZbBind, &CmndZbUnbind, &CmndZbPing, &CmndZbModelId, - &CmndZbLight, &CmndZbRestore, &CmndZbBindState, + &CmndZbLight, &CmndZbOccupancy, + &CmndZbRestore, &CmndZbBindState, &CmndZbMap, &CmndZbConfig, CmndZbData, }; @@ -126,7 +128,7 @@ void CmndZbReset(void) { eraseZigbeeDevices(); case 2: // fall through Settings.zb_txradio_dbm = - abs(Settings.zb_txradio_dbm); - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; #ifdef USE_ZIGBEE_ZNP ResponseCmndChar_P(PSTR(D_JSON_ZIGBEE_CC2530 " " D_JSON_RESET_AND_RESTARTING)); #endif // USE_ZIGBEE_ZNP @@ -937,11 +939,7 @@ void CmndZbUnbind(void) { ZbBindUnbind(true); } -// -// Command `ZbBindState` -// `ZbBindState` as index if it does not fit. If default, `1` starts at the beginning -// -void CmndZbBindState(void) { +void CmndZbBindState_or_Map(uint16_t zdo_cmd) { if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } @@ -950,7 +948,7 @@ void CmndZbBindState(void) { #ifdef USE_ZIGBEE_ZNP SBuffer buf(10); buf.add8(Z_SREQ | Z_ZDO); // 25 - buf.add8(ZDO_MGMT_BIND_REQ); // 33 + buf.add8(zdo_cmd); // 33 buf.add16(shortaddr); // shortaddr buf.add8(index); // StartIndex = 0 @@ -962,12 +960,38 @@ void CmndZbBindState(void) { // ZDO message payload (see Zigbee spec 2.4.3.3.4) uint8_t buf[] = { index }; // index = 0 - EZ_SendZDO(shortaddr, ZDO_Mgmt_Bind_req, buf, sizeof(buf)); + EZ_SendZDO(shortaddr, zdo_cmd, buf, sizeof(buf)); #endif // USE_ZIGBEE_EZSP ResponseCmndDone(); } +// +// Command `ZbBindState` +// `ZbBindState` as index if it does not fit. If default, `1` starts at the beginning +// +void CmndZbBindState(void) { +#ifdef USE_ZIGBEE_ZNP + CmndZbBindState_or_Map(ZDO_MGMT_BIND_REQ); +#endif // USE_ZIGBEE_ZNP +#ifdef USE_ZIGBEE_EZSP + CmndZbBindState_or_Map(ZDO_Mgmt_Bind_req); +#endif // USE_ZIGBEE_EZSP +} + +// +// Command `ZbMap` +// `ZbMap` as index if it does not fit. If default, `1` starts at the beginning +// +void CmndZbMap(void) { +#ifdef USE_ZIGBEE_ZNP + CmndZbBindState_or_Map(ZDO_MGMT_LQI_REQ); +#endif // USE_ZIGBEE_ZNP +#ifdef USE_ZIGBEE_EZSP + CmndZbBindState_or_Map(ZDO_Mgmt_Lqi_req); +#endif // USE_ZIGBEE_EZSP +} + // Probe a specific device to get its endpoints and supported clusters void CmndZbProbe(void) { CmndZbProbeOrPing(true); @@ -1021,7 +1045,7 @@ void CmndZbName(void) { Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), shortaddr, friendlyName ? friendlyName : ""); } else { if (strlen(p) > 32) { p[32] = 0x00; } // truncate to 32 chars max - zigbee_devices.setFriendlyName(shortaddr, p); + zigbee_devices.getShortAddr(shortaddr).setFriendlyName(p); Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), shortaddr, p); } } @@ -1052,7 +1076,7 @@ void CmndZbModelId(void) { const char * modelId = zigbee_devices.getModelId(shortaddr); Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_MODELID "\":\"%s\"}}"), shortaddr, modelId ? modelId : ""); } else { - zigbee_devices.setModelId(shortaddr, p); + zigbee_devices.getShortAddr(shortaddr).setModelId(p); Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_MODELID "\":\"%s\"}}"), shortaddr, p); } } @@ -1089,6 +1113,56 @@ void CmndZbLight(void) { MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_PRFX_ZB D_CMND_ZIGBEE_LIGHT)); ResponseCmndDone(); } +// +// Command `ZbOccupancy` +// Specify, read or erase the Occupancy detector configuration +void CmndZbOccupancy(void) { + // Syntax is: + // ZbOccupancy , - set the occupancy time-out + // ZbOccupancy - display the configuration + // + // List of occupancy time-outs: + // 0xF = default (90 s) + // 0x0 = no time-out + // 0x1 = 15 s + // 0x2 = 30 s + // 0x3 = 45 s + // 0x4 = 60 s + // 0x5 = 75 s + // 0x6 = 90 s -- default + // 0x7 = 105 s + // 0x8 = 120 s + // Where can be: short_addr, long_addr, device_index, friendly_name + + if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; } + + // check if parameters contain a comma ',' + char *p; + char *str = strtok_r(XdrvMailbox.data, ", ", &p); + + // parse first part, + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); // in case of short_addr, it must be already registered + if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } + + Z_Device & device = zigbee_devices.getShortAddr(shortaddr); + + int8_t occupancy_time = -1; + if (p) { + Z_Data_PIR & pir = (Z_Data_PIR&) device.data.getByType(Z_Data_Type::Z_PIR); + occupancy_time = strtol(p, nullptr, 10); + pir.setTimeoutSeconds(occupancy_time); + zigbee_devices.dirty(); + } else { + const Z_Data_PIR & pir_found = (const Z_Data_PIR&) device.data.find(Z_Data_Type::Z_PIR); + if (&pir_found != nullptr) { + occupancy_time = pir_found.getTimeoutSeconds(); + } + } + Response_P(PSTR("{\"" D_PRFX_ZB D_CMND_ZIGBEE_OCCUPANCY "\":%d}"), occupancy_time); + + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_PRFX_ZB D_CMND_ZIGBEE_LIGHT)); + ResponseCmndDone(); +} // // Command `ZbForget` @@ -1283,7 +1357,7 @@ void ZigbeeGlowPermitJoinLight(void) { // change the led state uint32_t led_pin = Pin(GPIO_LEDLNK); if (led_pin < 99) { - analogWrite(led_pin, ledlnk_inverted ? 1023 - led_power : led_power); + analogWrite(led_pin, TasmotaGlobal.ledlnk_inverted ? 1023 - led_power : led_power); } } } @@ -1314,17 +1388,12 @@ bool parseDeviceInnerData(class Z_Device & device, JsonParserObject root) { // Parse key in format "L02":.... const char * data_type_str = data_elt.getStr(); Z_Data_Type data_type; + uint8_t endpoint; + uint8_t config = 0xFF; // unspecified + + // parse key in the form "L01.5" + if (!Z_Data::ConfigToZData(data_type_str, &data_type, &endpoint, &config)) { data_type = Z_Data_Type::Z_Unknown; } - switch (data_type_str[0]) { - case 'P': data_type = Z_Data_Type::Z_Plug; break; - case 'L': data_type = Z_Data_Type::Z_Light; break; - case 'O': data_type = Z_Data_Type::Z_OnOff; break; - case 'T': data_type = Z_Data_Type::Z_Thermo; break; - case 'A': data_type = Z_Data_Type::Z_Alarm; break; - case '_': data_type = Z_Data_Type::Z_Device; break; - default: data_type = Z_Data_Type::Z_Unknown; break; - } - // The format should be a valid Code Lette followed by '-' if (data_type == Z_Data_Type::Z_Unknown) { Response_P(PSTR("{\"%s\":\"%s \"%s\"\"}"), XdrvMailbox.command, PSTR("Invalid Parameters"), data_type_str); return false; @@ -1333,79 +1402,82 @@ bool parseDeviceInnerData(class Z_Device & device, JsonParserObject root) { JsonParserObject data_values = data_elt.getValue().getObject(); if (!data_values) { return false; } - // Decode the endpoint number - uint8_t endpoint = strtoul(&data_type_str[1], nullptr, 16); // hex base 16 JsonParserToken val; + if (data_type == Z_Data_Type::Z_Device) { + if (val = data_values[PSTR(D_CMND_ZIGBEE_LINKQUALITY)]) { device.lqi = val.getUInt(); } + if (val = data_values[PSTR("BatteryPercentage")]) { device.batterypercent = val.getUInt(); } + if (val = data_values[PSTR("LastSeen")]) { device.last_seen = val.getUInt(); } + } else { + // Import generic attributes first + device.addEndpoint(endpoint); + Z_Data & data = device.data.getByType(data_type, endpoint); - // Import generic attributes first - Z_Data & data = device.data.getByType(data_type, endpoint); + // scan through attributes + if (&data != nullptr) { + if (config != 0xFF) { + data.setConfig(config); + } - // scan through attributes - for (auto attr : data_values) { - JsonParserToken attr_value = attr.getValue(); - uint8_t conv_zigbee_type; - Z_Data_Type conv_data_type; - uint8_t conv_map_offset; - if (zigbeeFindAttributeByName(attr.getStr(), nullptr, nullptr, nullptr, &conv_zigbee_type, &conv_data_type, &conv_map_offset) != nullptr) { - // found an attribute matching the name, does is fit the type? - if (conv_data_type == data_type) { - // we got a match. Bear in mind that a zero value is not a valid 'data_type' + for (auto attr : data_values) { + JsonParserToken attr_value = attr.getValue(); + uint8_t conv_zigbee_type; + Z_Data_Type conv_data_type; + uint8_t conv_map_offset; + if (zigbeeFindAttributeByName(attr.getStr(), nullptr, nullptr, nullptr, &conv_zigbee_type, &conv_data_type, &conv_map_offset) != nullptr) { + // found an attribute matching the name, does is fit the type? + if (conv_data_type == data_type) { + // we got a match. Bear in mind that a zero value is not a valid 'data_type' - uint8_t *attr_address = ((uint8_t*)&data) + sizeof(Z_Data) + conv_map_offset; - uint32_t uval32 = attr_value.getUInt(); // call converter to uint only once - int32_t ival32 = attr_value.getInt(); // call converter to int only once - switch (conv_zigbee_type) { - case Zenum8: - case Zuint8: *(uint8_t*)attr_address = uval32; break; - case Zenum16: - case Zuint16: *(uint16_t*)attr_address = uval32; break; - case Zuint32: *(uint32_t*)attr_address = uval32; break; - case Zint8: *(int8_t*)attr_address = ival32; break; - case Zint16: *(int16_t*)attr_address = ival32; break; - case Zint32: *(int32_t*)attr_address = ival32; break; + uint8_t *attr_address = ((uint8_t*)&data) + sizeof(Z_Data) + conv_map_offset; + uint32_t uval32 = attr_value.getUInt(); // call converter to uint only once + int32_t ival32 = attr_value.getInt(); // call converter to int only once + switch (conv_zigbee_type) { + case Zenum8: + case Zuint8: *(uint8_t*)attr_address = uval32; break; + case Zenum16: + case Zuint16: *(uint16_t*)attr_address = uval32; break; + case Zuint32: *(uint32_t*)attr_address = uval32; break; + case Zint8: *(int8_t*)attr_address = ival32; break; + case Zint16: *(int16_t*)attr_address = ival32; break; + case Zint32: *(int32_t*)attr_address = ival32; break; + } + } else if (conv_data_type != Z_Data_Type::Z_Unknown) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "attribute %s is wrong type %d (expected %d)"), attr.getStr(), (uint8_t)data_type, (uint8_t)conv_data_type); + } } - } else if (conv_data_type != Z_Data_Type::Z_Unknown) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "attribute %s is wrong type %d (expected %d)"), attr.getStr(), (uint8_t)data_type, (uint8_t)conv_data_type); } } - } - // Import specific attributes that are not handled with the generic method - switch (data_type) { - // case Z_Data_Type::Z_Plug: - // { - // Z_Data_Plug & plug = (Z_Data_Plug&) data; - // } - // break; - // case Z_Data_Type::Z_Light: - // { - // Z_Data_Light & light = (Z_Data_Light&) data; - // } - // break; - case Z_Data_Type::Z_OnOff: - { - Z_Data_OnOff & onoff = (Z_Data_OnOff&) data; + // Import specific attributes that are not handled with the generic method + switch (data_type) { + // case Z_Data_Type::Z_Plug: + // { + // Z_Data_Plug & plug = (Z_Data_Plug&) data; + // } + // break; + // case Z_Data_Type::Z_Light: + // { + // Z_Data_Light & light = (Z_Data_Light&) data; + // } + // break; + case Z_Data_Type::Z_OnOff: + { + Z_Data_OnOff & onoff = (Z_Data_OnOff&) data; - if (val = data_values[PSTR("Power")]) { onoff.setPower(val.getUInt() ? true : false); } + if (val = data_values[PSTR("Power")]) { onoff.setPower(val.getUInt() ? true : false); } + } + break; + // case Z_Data_Type::Z_Thermo: + // { + // Z_Data_Thermo & thermo = (Z_Data_Thermo&) data; + // } + // break; + // case Z_Data_Type::Z_Alarm: + // { + // Z_Data_Alarm & alarm = (Z_Data_Alarm&) data; + // } + // break; } - break; - // case Z_Data_Type::Z_Thermo: - // { - // Z_Data_Thermo & thermo = (Z_Data_Thermo&) data; - // } - // break; - // case Z_Data_Type::Z_Alarm: - // { - // Z_Data_Alarm & alarm = (Z_Data_Alarm&) data; - // } - // break; - case Z_Data_Type::Z_Device: - { - if (val = data_values[PSTR(D_CMND_ZIGBEE_LINKQUALITY)]) { device.lqi = val.getUInt(); } - if (val = data_values[PSTR("BatteryPercentage")]) { device.batterypercent = val.getUInt(); } - if (val = data_values[PSTR("LastSeen")]) { device.last_seen = val.getUInt(); } - } - break; } } return true; @@ -1440,6 +1512,7 @@ void CmndZbData(void) { } } } + zigbee_devices.dirty(); // save to flash ResponseCmndDone(); } else { // non-JSON, export current data @@ -1454,56 +1527,42 @@ void CmndZbData(void) { { // scope to force object deallocation Z_attribute_list device_attr; device.toAttributes(device_attr); - attr_data.addAttribute(F("_00")).setStrRaw(device_attr.toString(true).c_str()); + attr_data.addAttribute(F("_")).setStrRaw(device_attr.toString(true).c_str()); } // Iterate on data objects for (auto & data_elt : device.data) { Z_attribute_list inner_attr; - char key[4]; - snprintf_P(key, sizeof(key), "?%02X", data_elt.getEndpoint()); - // The key is in the form "L01", where 'L' is the type and '01' the endpoint in hex format - // 'P' = Power - // 'L' = Light - // 'O' = OnOff - // 'T' = Thermo & sensors - // 'A' = Alarm - // '?' = Device wide - // + char key[8]; + if (data_elt.validConfig()) { + snprintf_P(key, sizeof(key), "?%02X.%1X", data_elt.getEndpoint(), data_elt.getConfig()); + } else { + snprintf_P(key, sizeof(key), "?%02X", data_elt.getEndpoint()); + } + Z_Data_Type data_type = data_elt.getType(); + key[0] = Z_Data::DataTypeToChar(data_type); switch (data_type) { case Z_Data_Type::Z_Plug: - { - key[0] = 'P'; - ((Z_Data_Plug&)data_elt).toAttributes(inner_attr, data_type); - } + ((Z_Data_Plug&)data_elt).toAttributes(inner_attr, data_type); break; case Z_Data_Type::Z_Light: - { - key[0] = 'L'; - ((Z_Data_Light&)data_elt).toAttributes(inner_attr, data_type); - } + ((Z_Data_Light&)data_elt).toAttributes(inner_attr, data_type); break; case Z_Data_Type::Z_OnOff: - { - key[0] = 'O'; - ((Z_Data_OnOff&)data_elt).toAttributes(inner_attr, data_type); - } + ((Z_Data_OnOff&)data_elt).toAttributes(inner_attr, data_type); break; case Z_Data_Type::Z_Thermo: - { - key[0] = 'T'; - ((Z_Data_Thermo&)data_elt).toAttributes(inner_attr, data_type); - } + ((Z_Data_Thermo&)data_elt).toAttributes(inner_attr, data_type); break; case Z_Data_Type::Z_Alarm: - { - key[0] = 'A'; - ((Z_Data_Alarm&)data_elt).toAttributes(inner_attr, data_type); - } + ((Z_Data_Alarm&)data_elt).toAttributes(inner_attr, data_type); + break; + case Z_Data_Type::Z_PIR: + ((Z_Data_PIR&)data_elt).toAttributes(inner_attr, data_type); break; } - if (key[0] != '?') { + if ((key[0] != '\0') && (key[0] != '?')) { attr_data.addAttribute(key).setStrRaw(inner_attr.toString(true).c_str()); } } @@ -1564,7 +1623,7 @@ void CmndZbConfig(void) { Settings.zb_precfgkey_l = zb_precfgkey_l; Settings.zb_precfgkey_h = zb_precfgkey_h; Settings.zb_txradio_dbm = zb_txradio_dbm; - restart_flag = 2; // save and reboot + TasmotaGlobal.restart_flag = 2; // save and reboot } } @@ -1710,10 +1769,13 @@ void ZigbeeShow(bool json) WSContentSend_PD(PSTR( "
%s%s%s
" // slqi - ), name, sbatt, slqi); + ), shortaddr, + device.modelId ? device.modelId : "", + device.manufacturerId ? device.manufacturerId : "", + name, sbatt, slqi); if(device.validLqi()) { for(uint32_t j = 0; j < 4; ++j) { @@ -1736,28 +1798,36 @@ void ZigbeeShow(bool json) const Z_Data_Thermo & thermo = device.data.find(); if (&thermo != nullptr) { - WSContentSend_P(PSTR("
┆")); - if (thermo.validTemperature()) { - char buf[12]; - dtostrf(thermo.getTemperature() / 100.0f, 3, 1, buf); - WSContentSend_PD(PSTR(" ☀️ %s°C"), buf); - } - if (thermo.validTempTarget()) { - char buf[12]; - dtostrf(thermo.getTempTarget() / 100.0f, 3, 1, buf); - WSContentSend_PD(PSTR(" 🎯 %s°C"), buf); - } - if (thermo.validThSetpoint()) { - WSContentSend_PD(PSTR(" ⚙️ %d%%"), thermo.getThSetpoint()); - } - if (thermo.validHumidity()) { - WSContentSend_P(PSTR(" 💧 %d%%"), (uint16_t)(thermo.getHumidity() / 100.0f + 0.5f)); - } - if (thermo.validPressure()) { - WSContentSend_P(PSTR(" ⛅ %d hPa"), thermo.getPressure()); - } + bool validTemp = thermo.validTemperature(); + bool validTempTarget = thermo.validTempTarget(); + bool validThSetpoint = thermo.validThSetpoint(); + bool validHumidity = thermo.validHumidity(); + bool validPressure = thermo.validPressure(); - WSContentSend_P(PSTR("{e}")); + if (validTemp || validTempTarget || validThSetpoint || validHumidity || validPressure) { + WSContentSend_P(PSTR("
┆")); + if (validTemp) { + char buf[12]; + dtostrf(thermo.getTemperature() / 100.0f, 3, 1, buf); + WSContentSend_PD(PSTR(" ☀️ %s°C"), buf); + } + if (validTempTarget) { + char buf[12]; + dtostrf(thermo.getTempTarget() / 100.0f, 3, 1, buf); + WSContentSend_PD(PSTR(" 🎯 %s°C"), buf); + } + if (validThSetpoint) { + WSContentSend_PD(PSTR(" ⚙️ %d%%"), thermo.getThSetpoint()); + } + if (validHumidity) { + WSContentSend_P(PSTR(" 💧 %d%%"), (uint16_t)(thermo.getHumidity() / 100.0f + 0.5f)); + } + if (validPressure) { + WSContentSend_P(PSTR(" ⛅ %d hPa"), thermo.getPressure()); + } + + WSContentSend_P(PSTR("{e}")); + } } // Light, switches and plugs @@ -1792,12 +1862,16 @@ void ZigbeeShow(bool json) } } if (&plug != nullptr) { - WSContentSend_P(PSTR(" ⚡ ")); - if (plug.validMainsVoltage()) { - WSContentSend_P(PSTR(" %dV"), plug.getMainsVoltage()); - } - if (plug.validMainsPower()) { - WSContentSend_P(PSTR(" %dW"), plug.getMainsPower()); + bool validMainsVoltage = plug.validMainsVoltage(); + bool validMainsPower = plug.validMainsPower(); + if (validMainsVoltage || validMainsPower) { + WSContentSend_P(PSTR(" ⚡ ")); + if (validMainsVoltage) { + WSContentSend_P(PSTR(" %dV"), plug.getMainsVoltage()); + } + if (validMainsPower) { + WSContentSend_P(PSTR(" %dW"), plug.getMainsPower()); + } } } WSContentSend_P(PSTR("{e}")); diff --git a/tasmota/xdrv_24_buzzer.ino b/tasmota/xdrv_24_buzzer.ino index 8ca94b023..25411b7b1 100644 --- a/tasmota/xdrv_24_buzzer.ino +++ b/tasmota/xdrv_24_buzzer.ino @@ -53,7 +53,7 @@ void BuzzerSet(uint8_t state) analogWrite(Pin(GPIO_BUZZER, 0), Settings.pwm_range / 2); // set 50% duty cycle for frequency output } else { - analogWrite(Pin(GPIO_BUZZER, 0), 0); // set 0% (or 100% for inverted PWM) duty cycle which turns off frequency output either way + analogWrite(Pin(GPIO_BUZZER, 0), 0); // set 0% (or 100% for inverted PWM) duty cycle which turns off frequency output either way } last_state = state; } @@ -61,7 +61,7 @@ void BuzzerSet(uint8_t state) else { DigitalWrite(GPIO_BUZZER, 0, state); // Buzzer On/Off } - + } //void BuzzerBeep(uint32_t count = 1, uint32_t on = 1, uint32_t off = 1, uint32_t tune = 0, uint32_t mode = 0); @@ -101,14 +101,14 @@ void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune, uint32 Buzzer.enable = (Buzzer.count > 0); if (Buzzer.enable) { - if (Settings.sleep > PWM_MAX_SLEEP) { - ssleep = PWM_MAX_SLEEP; // set a maxumum value of 10 milliseconds to ensure that buzzer periods are a bit more accurate - } else { - ssleep = Settings.sleep; // or keep the current sleep if it's lower than 10 - } + if (Settings.sleep > PWM_MAX_SLEEP) { + TasmotaGlobal.sleep = PWM_MAX_SLEEP; // set a maxumum value of 10 milliseconds to ensure that buzzer periods are a bit more accurate + } else { + TasmotaGlobal.sleep = Settings.sleep; // or keep the current sleep if it's lower than 10 + } } else { - ssleep = Settings.sleep; // restore original sleep + TasmotaGlobal.sleep = Settings.sleep; // restore original sleep BuzzerSet(0); } } diff --git a/tasmota/xdrv_26_ariluxrf.ino b/tasmota/xdrv_26_ariluxrf.ino index d4491423d..8f23b54da 100644 --- a/tasmota/xdrv_26_ariluxrf.ino +++ b/tasmota/xdrv_26_ariluxrf.ino @@ -146,10 +146,9 @@ void AriluxRfHandler(void) void AriluxRfInit(void) { if (PinUsed(GPIO_ARIRFRCV) && PinUsed(GPIO_ARIRFSEL)) { - if (Settings.last_module != Settings.module) { + if (TasmotaGlobal.module_changed) { Settings.rf_code[1][6] = 0; Settings.rf_code[1][7] = 0; - Settings.last_module = Settings.module; } Arilux.rf_received_value = 0; @@ -179,7 +178,7 @@ bool Xdrv26(uint8_t function) if (PinUsed(GPIO_ARIRFRCV)) { AriluxRfHandler(); } break; case FUNC_EVERY_SECOND: - if (10 == uptime) { AriluxRfInit(); } // Needs rest before enabling RF interrupts + if (10 == TasmotaGlobal.uptime) { AriluxRfInit(); } // Needs rest before enabling RF interrupts break; } return result; diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 0d7f38748..204f4a900 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -114,7 +114,7 @@ void ShutterLogPos(uint32_t i) void ExecuteCommandPowerShutter(uint32_t device, uint32_t state, uint32_t source) { // first implementation for virtual relays. Avoid switching relay numbers that do not exist. - if (device <= devices_present) ExecuteCommandPower(device,state,source); + if (device <= TasmotaGlobal.devices_present) ExecuteCommandPower(device,state,source); } void ShutterUpdateVelocity(uint8_t i) @@ -128,7 +128,7 @@ void ShutterUpdateVelocity(uint8_t i) void ShutterRtc50mS(void) { // No Logging allowed. RTC Timer - for (uint8_t i = 0; i < shutters_present; i++) { + for (uint8_t i = 0; i < TasmotaGlobal.shutters_present; i++) { if (Shutter[i].direction) { // update position data before increasing counter Shutter[i].real_position = ShutterCalculatePosition(i); @@ -218,10 +218,10 @@ uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index) void ShutterInit(void) { - shutters_present = 0; + TasmotaGlobal.shutters_present = 0; ShutterGlobal.RelayShutterMask = 0; //Initialize to get relay that changed - ShutterGlobal.RelayOldMask = power; + ShutterGlobal.RelayOldMask = TasmotaGlobal.power; // if shutter 4 is unused @@ -232,7 +232,7 @@ void ShutterInit(void) // set startrelay to 1 on first init, but only to shutter 1. 90% usecase Settings.shutter_startrelay[i] = (Settings.shutter_startrelay[i] == 0 && i == 0? 1 : Settings.shutter_startrelay[i]); if (Settings.shutter_startrelay[i] && (Settings.shutter_startrelay[i] < 9)) { - shutters_present++; + TasmotaGlobal.shutters_present++; // Add the two relays to the mask to knaw they belong to shutters ShutterGlobal.RelayShutterMask |= 3 << (Settings.shutter_startrelay[i] -1) ; @@ -328,9 +328,9 @@ void ShutterInit(void) void ShutterReportPosition(bool always, uint32_t index) { Response_P(PSTR("{")); - rules_flag.shutter_moving = 0; + TasmotaGlobal.rules_flag.shutter_moving = 0; uint32_t i = 0; - uint32_t n = shutters_present; + uint32_t n = TasmotaGlobal.shutters_present; if( index != MAX_SHUTTERS) { i = index; n = index+1; @@ -339,7 +339,7 @@ void ShutterReportPosition(bool always, uint32_t index) //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Real Pos: %d"), i+1,Shutter[i].real_position); uint32_t position = ShutterRealToPercentPosition(Shutter[i].real_position, i); if (Shutter[i].direction != 0) { - rules_flag.shutter_moving = 1; + TasmotaGlobal.rules_flag.shutter_moving = 1; ShutterLogPos(i); } if (i && index == MAX_SHUTTERS) { ResponseAppend_P(PSTR(",")); } @@ -347,10 +347,10 @@ void ShutterReportPosition(bool always, uint32_t index) ResponseAppend_P(JSON_SHUTTER_POS, i+1, (Settings.shutter_options[i] & 1) ? 100-position : position, Shutter[i].direction,(Settings.shutter_options[i] & 1) ? 100-target : target ); } ResponseJsonEnd(); - if (always || (rules_flag.shutter_moving)) { + if (always || (TasmotaGlobal.rules_flag.shutter_moving)) { MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_PRFX_SHUTTER)); // RulesProcess() now re-entry protected } - //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: rules_flag.shutter_moving: %d, moved %d"), rules_flag.shutter_moving, rules_flag.shutter_moved); + //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: TasmotaGlobal.rules_flag.shutter_moving: %d, moved %d"), TasmotaGlobal.rules_flag.shutter_moving, TasmotaGlobal.rules_flag.shutter_moved); } void ShutterLimitRealAndTargetPositions(uint32_t i) { @@ -436,24 +436,24 @@ void ShutterPowerOff(uint8_t i) { } switch (Shutter[i].switch_mode) { case SHT_SWITCH: - if ((1 << (Settings.shutter_startrelay[i]-1)) & power) { + if ((1 << (Settings.shutter_startrelay[i]-1)) & TasmotaGlobal.power) { ExecuteCommandPowerShutter(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); } - if ((1 << (Settings.shutter_startrelay[i])) & power) { + if ((1 << (Settings.shutter_startrelay[i])) & TasmotaGlobal.power) { ExecuteCommandPowerShutter(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER); } break; case SHT_PULSE: uint8_t cur_relay = Settings.shutter_startrelay[i] + (Shutter[i].direction == 1 ? 0 : (uint8_t)(ShutterGlobal.position_mode == SHT_TIME)) ; // we have a momentary switch here. Needs additional pulse on same relay after the end - if ((SRC_PULSETIMER == last_source || SRC_SHUTTER == last_source || SRC_WEBGUI == last_source)) { + if ((SRC_PULSETIMER == TasmotaGlobal.last_source || SRC_SHUTTER == TasmotaGlobal.last_source || SRC_WEBGUI == TasmotaGlobal.last_source)) { ExecuteCommandPowerShutter(cur_relay, 1, SRC_SHUTTER); // switch off direction relay to make it power less - if ((1 << (Settings.shutter_startrelay[i])) & power) { + if ((1 << (Settings.shutter_startrelay[i])) & TasmotaGlobal.power) { ExecuteCommandPowerShutter(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER); } } else { - last_source = SRC_SHUTTER; + TasmotaGlobal.last_source = SRC_SHUTTER; } break; } @@ -472,7 +472,7 @@ void ShutterUpdatePosition(void) char scommand[CMDSZ]; char stopic[TOPSZ]; - for (uint32_t i = 0; i < shutters_present; i++) { + for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) { if (Shutter[i].direction != 0) { if (!ShutterGlobal.start_reported) { ShutterReportPosition(true, i); @@ -496,11 +496,11 @@ void ShutterUpdatePosition(void) // sending MQTT result to broker snprintf_P(scommand, sizeof(scommand),PSTR(D_SHUTTER "%d"), i+1); - GetTopic_P(stopic, STAT, mqtt_topic, scommand); + GetTopic_P(stopic, STAT, TasmotaGlobal.mqtt_topic, scommand); Response_P("%d", (Settings.shutter_options[i] & 1) ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]); MqttPublish(stopic, Settings.flag.mqtt_power_retain); // CMND_POWERRETAIN ShutterReportPosition(true, i); - rules_flag.shutter_moved = 1; + TasmotaGlobal.rules_flag.shutter_moved = 1; XdrvRulesProcess(); } } @@ -520,10 +520,10 @@ void ShutterAllowPreStartProcedure(uint8_t i) #ifdef USE_RULES uint32_t uptime_Local=0; AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Delay Start. var%d <99>=<%s>, max10s?"),i+i, rules_vars[i]); - rules_flag.shutter_moving = 1; + TasmotaGlobal.rules_flag.shutter_moving = 1; XdrvRulesProcess(); - uptime_Local = uptime; - while (uptime_Local+10 > uptime && (String)rules_vars[i] == "99") { + uptime_Local = TasmotaGlobal.uptime; + while (uptime_Local+10 > TasmotaGlobal.uptime && (String)rules_vars[i] == "99") { loop(); } AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Delay Start. Done")); @@ -550,12 +550,12 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) Shutter[i].accelerator = ShutterGlobal.open_velocity_max / (Shutter[i].motordelay>0 ? Shutter[i].motordelay : 1); Shutter[i].target_position = target_pos; Shutter[i].start_position = Shutter[i].real_position; - rules_flag.shutter_moving = 1; + TasmotaGlobal.rules_flag.shutter_moving = 1; ShutterAllowPreStartProcedure(i); Shutter[i].time = 0; Shutter[i].direction = direction; ShutterGlobal.skip_relay_change = 0; - rules_flag.shutter_moved = 0; + TasmotaGlobal.rules_flag.shutter_moved = 0; ShutterGlobal.start_reported = 0; //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: real %d, start %d, counter %d,freq_max %d, dir %d, freq %d"),Shutter[i].real_position, Shutter[i].start_position ,RtcSettings.pulse_counter[i],ShutterGlobal.open_velocity_max , Shutter[i].direction ,ShutterGlobal.open_velocity_max ); } @@ -596,12 +596,12 @@ void ShutterRelayChanged(void) // relays_changed = bool if one of the relays that belong to the shutter changed not by shutter or pulsetimer char stemp1[10]; - for (uint32_t i = 0; i < shutters_present; i++) { - power_t powerstate_local = (power >> (Settings.shutter_startrelay[i] -1)) & 3; + for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) { + power_t powerstate_local = (TasmotaGlobal.power >> (Settings.shutter_startrelay[i] -1)) & 3; // SRC_IGNORE added because INTERLOCK function bite causes this as last source for changing the relay. - //uint8 manual_relays_changed = ((ShutterGlobal.RelayCurrentMask >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_IGNORE != last_source && SRC_SHUTTER != last_source && SRC_PULSETIMER != last_source ; - uint8 manual_relays_changed = ((ShutterGlobal.RelayCurrentMask >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_SHUTTER != last_source && SRC_PULSETIMER != last_source ; - AddLog_P2(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), last_source, kCommandSource), powerstate_local,ShutterGlobal.RelayCurrentMask,manual_relays_changed); + //uint8 manual_relays_changed = ((ShutterGlobal.RelayCurrentMask >> (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_P2(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); if (manual_relays_changed) { //ShutterGlobal.skip_relay_change = true; ShutterLimitRealAndTargetPositions(i); @@ -610,11 +610,11 @@ void ShutterRelayChanged(void) if (Shutter[i].direction != 0 && powerstate_local) { Shutter[i].target_position = Shutter[i].real_position; powerstate_local = 0; - AddLog_P2(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), last_source, kCommandSource), powerstate_local,ShutterGlobal.RelayCurrentMask,manual_relays_changed); + AddLog_P2(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); } break; default: - last_source = SRC_SHUTTER; // avoid switch off in the next loop + TasmotaGlobal.last_source = SRC_SHUTTER; // avoid switch off in the next loop if (Shutter[i].direction != 0 ) ShutterPowerOff(i); } switch (ShutterGlobal.position_mode) { @@ -663,7 +663,7 @@ void ShutterRelayChanged(void) } // switch (ShutterGlobal.position_mode) AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shutter %d: Target: %ld, powerstatelocal %d"), i+1, Shutter[i].target_position, powerstate_local); } // if (manual_relays_changed) - } // for (uint32_t i = 0; i < shutters_present; i++) + } // for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) } bool ShutterButtonIsSimultaneousHold(uint32_t button_index, uint32_t shutter_index) { @@ -700,7 +700,7 @@ void ShutterButtonHandler(void) Button.window_timer[button_index] = (loops_per_second >> 2) * 3; // 0.75 second multi press window } } - blinks = 201; + TasmotaGlobal.blinks = 201; } if (NOT_PRESSED == button) { @@ -747,7 +747,7 @@ void ShutterButtonHandler(void) if (Button.window_timer[button_index]) { Button.window_timer[button_index]--; } else { - if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0)) { + if (!TasmotaGlobal.restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0)) { if (Button.press_counter[button_index]<99) { // check for simultaneous shutter button press uint32 min_shutterbutton_press_counter = -1; // -1 == max(uint32) @@ -809,7 +809,7 @@ void ShutterButtonHandler(void) if (pos_press_index>3) pos_press_index=3; AddLog_P2(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); XdrvMailbox.index = shutter_index +1; - last_source = SRC_BUTTON; + TasmotaGlobal.last_source = SRC_BUTTON; XdrvMailbox.data_len = 0; char databuf[1] = ""; XdrvMailbox.data = databuf; @@ -870,7 +870,7 @@ void ShutterToggle(bool dir) if ((1 == XdrvMailbox.index) && (XdrvMailbox.payload != -99)) { XdrvMailbox.index = XdrvMailbox.payload; } - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { uint32_t index = XdrvMailbox.index-1; if (dir) { XdrvMailbox.payload = (Shutter[index].lastdirection > 0) ? 0 : 100; @@ -879,7 +879,7 @@ void ShutterToggle(bool dir) XdrvMailbox.payload = (50 < ShutterRealToPercentPosition(Shutter[index].real_position, index)) ? 0 : 100; } XdrvMailbox.data_len = 0; - last_source = SRC_WEBGUI; + TasmotaGlobal.last_source = SRC_WEBGUI; CmndShutterPosition(); } } @@ -895,13 +895,13 @@ void CmndShutterOpen(void) XdrvMailbox.index = XdrvMailbox.payload; } XdrvMailbox.payload = 100; - last_source = SRC_WEBGUI; + TasmotaGlobal.last_source = SRC_WEBGUI; CmndShutterPosition(); } void CmndShutterStopOpen(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { uint32_t index = XdrvMailbox.index-1; if (Shutter[index].direction) { CmndShutterStop(); @@ -919,13 +919,13 @@ void CmndShutterClose(void) } XdrvMailbox.payload = 0; XdrvMailbox.data_len = 0; - last_source = SRC_WEBGUI; + TasmotaGlobal.last_source = SRC_WEBGUI; CmndShutterPosition(); } void CmndShutterStopClose(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { uint32_t index = XdrvMailbox.index-1; if (Shutter[index].direction) { CmndShutterStop(); @@ -947,7 +947,7 @@ void CmndShutterToggleDir(void) void CmndShutterStopToggle(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { uint32_t index = XdrvMailbox.index-1; if (Shutter[index].direction) { CmndShutterStop(); @@ -959,7 +959,7 @@ void CmndShutterStopToggle(void) void CmndShutterStopToggleDir(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { uint32_t index = XdrvMailbox.index-1; if (Shutter[index].direction) { CmndShutterStop(); @@ -971,7 +971,7 @@ void CmndShutterStopToggleDir(void) void CmndShutterStop(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { if (!(Settings.shutter_options[XdrvMailbox.index-1] & 2)) { if ((1 == XdrvMailbox.index) && (XdrvMailbox.payload != -99)) { XdrvMailbox.index = XdrvMailbox.payload; @@ -983,7 +983,7 @@ void CmndShutterStop(void) int32_t temp_realpos = ShutterCalculatePosition(i); XdrvMailbox.payload = ShutterRealToPercentPosition(temp_realpos, i); - last_source = SRC_WEBGUI; + TasmotaGlobal.last_source = SRC_WEBGUI; CmndShutterPosition(); } else { if (XdrvMailbox.command) @@ -998,8 +998,8 @@ void CmndShutterStop(void) void CmndShutterIncDec(void) { - //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Change in: payload %s (%d), payload %d, idx %d, src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, last_source ); - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Change in: payload %s (%d), payload %d, idx %d, src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, TasmotaGlobal.last_source ); + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { if (XdrvMailbox.data_len > 0) { XdrvMailbox.payload = ShutterRealToPercentPosition(Shutter[XdrvMailbox.index-1].target_position, XdrvMailbox.index-1)+XdrvMailbox.payload; // limit position to boundaries @@ -1012,11 +1012,11 @@ void CmndShutterIncDec(void) void CmndShutterPosition(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { if (!(Settings.shutter_options[XdrvMailbox.index-1] & 2)) { uint32_t index = XdrvMailbox.index-1; //limit the payload - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Pos. in: payload %s (%d), payload %d, idx %d, src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, last_source ); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Pos. in: payload %s (%d), payload %d, idx %d, src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, TasmotaGlobal.last_source ); // value 0 with data_len > 0 can mean Open // special handling fo UP,DOWN,TOGGLE,STOP command comming with payload -99 @@ -1047,13 +1047,13 @@ void CmndShutterPosition(void) int8_t target_pos_percent = (XdrvMailbox.payload < 0) ? (XdrvMailbox.payload == -99 ? ShutterRealToPercentPosition(Shutter[index].real_position, index) : 0) : ((XdrvMailbox.payload > 100) ? 100 : XdrvMailbox.payload); // webgui still send also on inverted shutter the native position. - target_pos_percent = ((Settings.shutter_options[index] & 1) && (SRC_WEBGUI != last_source)) ? 100 - target_pos_percent : target_pos_percent; + target_pos_percent = ((Settings.shutter_options[index] & 1) && (SRC_WEBGUI != TasmotaGlobal.last_source)) ? 100 - target_pos_percent : target_pos_percent; if (XdrvMailbox.payload != -99) { //target_pos_percent = (Settings.shutter_options[index] & 1) ? 100 - target_pos_percent : target_pos_percent; Shutter[index].target_position = ShutterPercentToRealPosition(target_pos_percent, index); //Shutter[i].accelerator[index] = ShutterGlobal.open_velocity_max / ((Shutter[i].motordelay[index] > 0) ? Shutter[i].motordelay[index] : 1); //Shutter[i].target_position[index] = XdrvMailbox.payload < 5 ? Settings.shuttercoeff[2][index] * XdrvMailbox.payload : Settings.shuttercoeff[1][index] * XdrvMailbox.payload + Settings.shuttercoeff[0,index]; - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: lastsource %d:, real %d, target %d, payload %d"), last_source, Shutter[index].real_position ,Shutter[index].target_position,target_pos_percent); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: lastsource %d:, real %d, target %d, payload %d"), TasmotaGlobal.last_source, Shutter[index].real_position ,Shutter[index].target_position,target_pos_percent); } if ( (target_pos_percent >= 0) && (target_pos_percent <= 100) && abs(Shutter[index].target_position - Shutter[index].real_position ) / Shutter[index].close_velocity > 2) { if (Settings.shutter_options[index] & 4) { @@ -1081,7 +1081,7 @@ void CmndShutterPosition(void) break; case SHT_TIME: if (!ShutterGlobal.skip_relay_change) { - if ( (power >> (Settings.shutter_startrelay[index] -1)) & 3 > 0 ) { + if ( (TasmotaGlobal.power >> (Settings.shutter_startrelay[index] -1)) & 3 > 0 ) { ExecuteCommandPowerShutter(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 1 : 0), Shutter[index].switch_mode == SHT_SWITCH ? 0 : 1, SRC_SHUTTER); } ExecuteCommandPowerShutter(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER); @@ -1123,7 +1123,7 @@ void CmndShutterPosition(void) void CmndShutterStopPosition(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { uint32_t index = XdrvMailbox.index-1; if (Shutter[index].direction) { XdrvMailbox.payload = -99; @@ -1135,7 +1135,7 @@ void CmndShutterStopPosition(void) } void CmndShutterOpenTime(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { if (XdrvMailbox.data_len > 0) { Settings.shutter_opentime[XdrvMailbox.index -1] = (uint16_t)(10 * CharToFloat(XdrvMailbox.data)); ShutterInit(); @@ -1148,7 +1148,7 @@ void CmndShutterOpenTime(void) void CmndShutterCloseTime(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { if (XdrvMailbox.data_len > 0) { Settings.shutter_closetime[XdrvMailbox.index -1] = (uint16_t)(10 * CharToFloat(XdrvMailbox.data)); ShutterInit(); @@ -1161,7 +1161,7 @@ void CmndShutterCloseTime(void) void CmndShutterMotorDelay(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { if (XdrvMailbox.data_len > 0) { Settings.shutter_motordelay[XdrvMailbox.index -1] = (uint16_t)(STEPS_PER_SECOND * CharToFloat(XdrvMailbox.data)); ShutterInit(); @@ -1339,9 +1339,10 @@ void CmndShutterButton(void) void CmndShutterSetHalfway(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { Settings.shutter_set50percent[XdrvMailbox.index -1] = (Settings.shutter_options[XdrvMailbox.index -1] & 1) ? 100 - XdrvMailbox.payload : XdrvMailbox.payload; + Settings.shuttercoeff[0][XdrvMailbox.index -1] = 0; ShutterInit(); } ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 1) ? 100 - Settings.shutter_set50percent[XdrvMailbox.index -1] : Settings.shutter_set50percent[XdrvMailbox.index -1]); @@ -1352,7 +1353,7 @@ void CmndShutterFrequency(void) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 20000)) { ShutterGlobal.open_velocity_max = XdrvMailbox.payload; - if (shutters_present < 4) { + if (TasmotaGlobal.shutters_present < 4) { Settings.shuttercoeff[4][3] = ShutterGlobal.open_velocity_max; } ShutterInit(); @@ -1362,7 +1363,7 @@ void CmndShutterFrequency(void) void CmndShutterSetClose(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { Shutter[XdrvMailbox.index -1].real_position = 0; ShutterStartInit(XdrvMailbox.index -1, 0, 0); Settings.shutter_position[XdrvMailbox.index -1] = 0; @@ -1372,7 +1373,7 @@ void CmndShutterSetClose(void) void CmndShutterSetOpen(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { Shutter[XdrvMailbox.index -1].real_position = Shutter[XdrvMailbox.index -1].open_max; ShutterStartInit(XdrvMailbox.index -1, 0, Shutter[XdrvMailbox.index -1].open_max); Settings.shutter_position[XdrvMailbox.index -1] = 100; @@ -1382,7 +1383,7 @@ void CmndShutterSetOpen(void) void CmndShutterPwmRange(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { if (XdrvMailbox.data_len > 0) { uint8_t i = 0; char *str_ptr; @@ -1412,7 +1413,7 @@ void CmndShutterPwmRange(void) void CmndShutterCalibration(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { if (XdrvMailbox.data_len > 0) { uint8_t i = 0; char *str_ptr; @@ -1429,6 +1430,7 @@ void CmndShutterCalibration(void) } messwerte[i] = field; } + 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_P2(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]); @@ -1444,7 +1446,7 @@ void CmndShutterCalibration(void) } void ShutterOptionsSetHelper(uint16_t option){ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) { if (XdrvMailbox.payload == 0) { Settings.shutter_options[XdrvMailbox.index -1] &= ~(option); } else if (XdrvMailbox.payload == 1) { @@ -1495,14 +1497,14 @@ bool Xdrv27(uint8_t function) result = DecodeCommand(kShutterCommands, ShutterCommand); break; case FUNC_JSON_APPEND: - for (uint8_t i = 0; i < shutters_present; i++) { + for (uint8_t i = 0; i < TasmotaGlobal.shutters_present; i++) { uint8_t position = (Settings.shutter_options[i] & 1) ? 100 - Settings.shutter_position[i] : Settings.shutter_position[i]; uint8_t target = (Settings.shutter_options[i] & 1) ? 100 - ShutterRealToPercentPosition(Shutter[i].target_position, i) : ShutterRealToPercentPosition(Shutter[i].target_position, i); ResponseAppend_P(","); ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, Shutter[i].direction,target); #ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == i)) { + if ((0 == TasmotaGlobal.tele_period) && (0 == i)) { DomoticzSensor(DZ_SHUTTER, position); } #endif // USE_DOMOTICZ @@ -1512,14 +1514,14 @@ 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_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Switched relay: %d by %s"), ShutterGlobal.RelayCurrentMask,GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource)); + AddLog_P2(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; case FUNC_SET_DEVICE_POWER: if (ShutterGlobal.skip_relay_change ) { uint8_t i; - for (i = 0; i < devices_present; i++) { + for (i = 0; i < TasmotaGlobal.devices_present; i++) { if (ShutterGlobal.RelayCurrentMask &1) { break; } diff --git a/tasmota/xdrv_28_pcf8574.ino b/tasmota/xdrv_28_pcf8574.ino index 202acffee..a129fef62 100644 --- a/tasmota/xdrv_28_pcf8574.ino +++ b/tasmota/xdrv_28_pcf8574.ino @@ -45,7 +45,7 @@ struct PCF8574 { void Pcf8574SwitchRelay(void) { - for (uint32_t i = 0; i < devices_present; i++) { + for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) { uint8_t relay_state = bitRead(XdrvMailbox.index, i); //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PCF: Pcf8574.max_devices %d requested pin %d"), Pcf8574.max_devices,Pcf8574.pin[i]); @@ -53,7 +53,7 @@ void Pcf8574SwitchRelay(void) if (Pcf8574.max_devices > 0 && Pcf8574.pin[i] < 99) { uint8_t board = Pcf8574.pin[i]>>3; uint8_t oldpinmask = Pcf8574.pin_mask[board]; - uint8_t _val = bitRead(rel_inverted, i) ? !relay_state : relay_state; + uint8_t _val = bitRead(TasmotaGlobal.rel_inverted, i) ? !relay_state : relay_state; //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PCF: Pcf8574SwitchRelay %d on pin %d"), i,state); @@ -67,7 +67,7 @@ void Pcf8574SwitchRelay(void) Wire.write(Pcf8574.pin_mask[board]); Pcf8574.error = Wire.endTransmission(); } - //pcf8574.write(Pcf8574.pin[i]&0x7, rel_inverted[i] ? !state : state); + //pcf8574.write(Pcf8574.pin[i]&0x7, TasmotaGlobal.rel_inverted[i] ? !state : state); } } } @@ -111,7 +111,7 @@ void Pcf8574Init(void) for (uint32_t i = 0; i < sizeof(Pcf8574.pin); i++) { Pcf8574.pin[i] = 99; } - devices_present = devices_present - Pcf8574.max_connected_ports; // reset no of devices to avoid duplicate ports on duplicate init. + TasmotaGlobal.devices_present = TasmotaGlobal.devices_present - Pcf8574.max_connected_ports; // reset no of devices to avoid duplicate ports on duplicate init. Pcf8574.max_connected_ports = 0; // reset no of devices to avoid duplicate ports on duplicate init. for (uint32_t idx = 0; idx < Pcf8574.max_devices; idx++) { // suport up to 8 boards PCF8574 @@ -119,11 +119,11 @@ void Pcf8574Init(void) for (uint32_t i = 0; i < 8; i++) { uint8_t _result = Settings.pcf8574_config[idx] >> i &1; - //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PCF: I2C shift i %d: %d. Powerstate: %d, devices_present: %d"), i,_result, Settings.power>>i&1, devices_present); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PCF: I2C shift i %d: %d. Powerstate: %d, TasmotaGlobal.devices_present: %d"), i,_result, Settings.power>>i&1, TasmotaGlobal.devices_present); if (_result > 0) { - Pcf8574.pin[devices_present] = i + 8 * idx; - bitWrite(rel_inverted, devices_present, Settings.flag3.pcf8574_ports_inverted); // SetOption81 - Invert all ports on PCF8574 devices - devices_present++; + Pcf8574.pin[TasmotaGlobal.devices_present] = i + 8 * idx; + bitWrite(TasmotaGlobal.rel_inverted, TasmotaGlobal.devices_present, Settings.flag3.pcf8574_ports_inverted); // SetOption81 - Invert all ports on PCF8574 devices + TasmotaGlobal.devices_present++; Pcf8574.max_connected_ports++; } } @@ -203,8 +203,8 @@ void Pcf8574SaveSettings(void) n = n&(n-1); count++; } - if (count <= devices_present) { - devices_present = devices_present - count; + if (count <= TasmotaGlobal.devices_present) { + TasmotaGlobal.devices_present = TasmotaGlobal.devices_present - count; } for (byte i = 0; i < 8; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("i2cs%d"), i+8*idx); @@ -212,7 +212,7 @@ void Pcf8574SaveSettings(void) byte _value = (!strlen(tmp)) ? 0 : atoi(tmp); if (_value) { Settings.pcf8574_config[idx] = Settings.pcf8574_config[idx] | 1 << i; - devices_present++; + TasmotaGlobal.devices_present++; Pcf8574.max_connected_ports++; } else { Settings.pcf8574_config[idx] = Settings.pcf8574_config[idx] & ~(1 << i ); diff --git a/tasmota/xdrv_30_exs_dimmer.ino b/tasmota/xdrv_30_exs_dimmer.ino index a6b14ca9a..e882cdd84 100644 --- a/tasmota/xdrv_30_exs_dimmer.ino +++ b/tasmota/xdrv_30_exs_dimmer.ino @@ -124,12 +124,12 @@ void ExsSerialSend(const uint8_t data[] = nullptr, uint16_t len = 0) char rc; #ifdef EXS_DEBUG - snprintf_P(log_data, sizeof(log_data), PSTR("EXS: Tx Packet: \"")); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("EXS: Tx Packet: \"")); for (uint32_t i = 0; i < len; i++) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, data[i]); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s%02x"), TasmotaGlobal.log_data, data[i]); } - snprintf_P(log_data, sizeof(log_data), PSTR("%s\""), log_data); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s\""), TasmotaGlobal.log_data); AddLog(LOG_LEVEL_DEBUG_MORE); #endif @@ -360,20 +360,20 @@ bool ExsModuleSelected(void) Settings.flag3.pwm_multi_channels = 1; // SetOption68 - Enable multi-channels PWM instead of Color PWM SetSeriallog(LOG_LEVEL_NONE); - devices_present = +2; - light_type = LT_SERIAL2; + TasmotaGlobal.devices_present = +2; + TasmotaGlobal.light_type = LT_SERIAL2; return true; } bool ExsSetChannels(void) { #ifdef EXS_DEBUG - snprintf_P(log_data, sizeof(log_data), PSTR("EXS: SetChannels: \"")); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("EXS: SetChannels: \"")); for (int i = 0; i < XdrvMailbox.data_len; i++) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, ((uint8_t *)XdrvMailbox.data)[i]); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s%02x"), TasmotaGlobal.log_data, ((uint8_t *)XdrvMailbox.data)[i]); } - snprintf_P(log_data, sizeof(log_data), PSTR("%s\""), log_data); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s\""), TasmotaGlobal.log_data); AddLog(LOG_LEVEL_DEBUG_MORE); #endif @@ -385,7 +385,7 @@ bool ExsSetChannels(void) bool ExsSetPower(void) { AddLog_P2(LOG_LEVEL_INFO, PSTR("EXS: Set Power, Device %d, Power 0x%02x"), - active_device, XdrvMailbox.index); + TasmotaGlobal.active_device, XdrvMailbox.index); Exs.power = XdrvMailbox.index; return ExsSyncState(); @@ -466,12 +466,12 @@ void ExsSerialInput(void) Exs.cmd_status = 0; #ifdef EXS_DEBUG - snprintf_P(log_data, sizeof(log_data), PSTR("EXS: RX Packet: \"")); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("EXS: RX Packet: \"")); for (uint32_t i = 0; i < Exs.byte_counter; i++) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, Exs.buffer[i]); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s%02x"), TasmotaGlobal.log_data, Exs.buffer[i]); } - snprintf_P(log_data, sizeof(log_data), PSTR("%s\", CRC: 0x%02x"), log_data, crc); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s\", CRC: 0x%02x"), TasmotaGlobal.log_data, crc); AddLog(LOG_LEVEL_DEBUG_MORE); #endif @@ -604,7 +604,7 @@ bool Xdrv30(uint8_t function) { bool result = false; - if (EXS_DIMMER == my_module_type) + if (EXS_DIMMER == TasmotaGlobal.module_type) { switch (function) { diff --git a/tasmota/xdrv_31_tasmota_client.ino b/tasmota/xdrv_31_tasmota_client.ino index 89402b408..1f355f8de 100644 --- a/tasmota/xdrv_31_tasmota_client.ino +++ b/tasmota/xdrv_31_tasmota_client.ino @@ -347,7 +347,7 @@ void TasmotaClient_Flash(void) { if (!TasmotaClient_SetupFlash()) { AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Flashing aborted!")); TClient.flashing = false; - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; return; } @@ -385,7 +385,7 @@ void TasmotaClient_Flash(void) { TasmotaClient_exitProgMode(); AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Flash done!")); TClient.flashing = false; - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } void TasmotaClient_SetFlagFlashing(bool value) { @@ -543,7 +543,7 @@ void TasmotaClient_ProcessIn(void) { Response_P(PSTR("{\"TasmotaClient\":")); ResponseAppend_P("%s", inbuf); ResponseJsonEnd(); - MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, mqtt_data); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, TasmotaGlobal.mqtt_data); } if (CMND_EXECUTE_CMND == TClientCommand.command) { // We need to execute the incoming command ExecuteCommand(inbuf, SRC_IGNORE); diff --git a/tasmota/xdrv_35_pwm_dimmer.ino b/tasmota/xdrv_35_pwm_dimmer.ino index 744e5a29b..aa4c6b95c 100644 --- a/tasmota/xdrv_35_pwm_dimmer.ino +++ b/tasmota/xdrv_35_pwm_dimmer.ino @@ -88,10 +88,9 @@ void PWMModulePreInit(void) Settings.ledstate = 0; // Disable LED usage // If the module was just changed to PWM Dimmer, set the defaults. - if (Settings.last_module != Settings.module) { +if (TasmotaGlobal.module_changed) { Settings.flag.pwm_control = true; // SetOption15 - Switch between commands PWM or COLOR/DIMMER/CT/CHANNEL Settings.bri_power_on = Settings.bri_preset_low = Settings.bri_preset_high = 0; - Settings.last_module = Settings.module; // Previous versions of PWM Dimmer used SetOption32 - Button held for factor times longer as the // hold time. The hold time is now fixed and SetOption32 is used as normal including to @@ -108,7 +107,7 @@ void PWMModulePreInit(void) PWMDimmerSetPoweredOffLed(); // The relay initializes to on. If the power is supposed to be off, turn the relay off. -// if (!power && PinUsed(GPIO_REL1)) digitalWrite(Pin(GPIO_REL1), bitRead(rel_inverted, 0) ? 1 : 0); +// if (!TasmotaGlobal.power && PinUsed(GPIO_REL1)) digitalWrite(Pin(GPIO_REL1), bitRead(TasmotaGlobal.rel_inverted, 0) ? 1 : 0); #ifdef USE_PWM_DIMMER_REMOTE // If remote device mode is enabled, set the device group count to the number of buttons @@ -126,8 +125,8 @@ void PWMModulePreInit(void) first_device_group_is_local = false; // Back out the changes made in the light module under the assumtion we have a relay or PWM. - devices_present--; - light_type = 0; + TasmotaGlobal.devices_present--; + TasmotaGlobal.light_type = 0; } for (uint8_t i = 0; i < MAX_PWM_DIMMER_KEYS; i++) { @@ -148,7 +147,7 @@ void PWMDimmerSetBrightnessLeds(int32_t bri) uint32_t leds = 0; uint32_t mask = 1; int32_t led; - for (led = 0; led < leds_present; led++) { + for (led = 0; led < TasmotaGlobal.leds_present; led++) { if (Settings.ledmask & mask) leds++; mask <<= 1; } @@ -184,15 +183,15 @@ void PWMDimmerSetPoweredOffLed(void) { // Set the powered-off LED state. if (PinUsed(GPIO_LEDLNK)) { - bool power_off_led_on = !power && Settings.flag4.powered_off_led; - if (ledlnk_inverted) power_off_led_on ^= 1; + bool power_off_led_on = !TasmotaGlobal.power && Settings.flag4.powered_off_led; + if (TasmotaGlobal.ledlnk_inverted) power_off_led_on ^= 1; digitalWrite(Pin(GPIO_LEDLNK), power_off_led_on); } } void PWMDimmerSetPower(void) { - DigitalWrite(GPIO_REL1, 0, bitRead(rel_inverted, 0) ? !power : power); + DigitalWrite(GPIO_REL1, 0, bitRead(TasmotaGlobal.rel_inverted, 0) ? !TasmotaGlobal.power : TasmotaGlobal.power); PWMDimmerSetBrightnessLeds(-1); PWMDimmerSetPoweredOffLed(); } @@ -272,11 +271,11 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed) // Initialize some variables. #ifdef USE_PWM_DIMMER_REMOTE - bool power_is_on = (active_remote_pwm_dimmer ? active_remote_pwm_dimmer->power_on : power); + bool power_is_on = (active_remote_pwm_dimmer ? active_remote_pwm_dimmer->power_on : TasmotaGlobal.power); bool is_power_button = (button_index == power_button_index); bool is_down_button = (button_index == down_button_index); #else // USE_PWM_DIMMER_REMOTE - bool power_is_on = power; + bool power_is_on = TasmotaGlobal.power; bool is_power_button = !button_index; bool is_down_button = (button_index == (power_button_index ? 0 : 1)); #endif // USE_PWM_DIMMER_REMOTE @@ -502,13 +501,13 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed) } else { #endif // USE_PWM_DIMMER_REMOTE - skip_light_fade = true; + TasmotaGlobal.skip_light_fade = true; #ifdef USE_DEVICE_GROUPS ignore_dgr_sends = true; #endif // USE_DEVICE_GROUPS light_state.setBri(new_bri); LightAnimate(); - skip_light_fade = false; + TasmotaGlobal.skip_light_fade = false; #ifdef USE_DEVICE_GROUPS ignore_dgr_sends = false; #endif // USE_DEVICE_GROUPS @@ -537,7 +536,7 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed) } else { #endif // USE_PWM_DIMMER_REMOTE - new_power = power ^ 1; + new_power = TasmotaGlobal.power ^ 1; #ifdef USE_PWM_DIMMER_REMOTE } #endif // USE_PWM_DIMMER_REMOTE @@ -599,7 +598,7 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed) // If we need to publish an MQTT trigger, do it. if (mqtt_trigger) { char topic[TOPSZ]; - sprintf_P(mqtt_data, PSTR("Trigger%u"), mqtt_trigger); + sprintf_P(TasmotaGlobal.mqtt_data, PSTR("Trigger%u"), mqtt_trigger); #ifdef USE_PWM_DIMMER_REMOTE if (active_remote_pwm_dimmer) { snprintf_P(topic, sizeof(topic), PSTR("cmnd/%s/EVENT"), device_groups[power_button_index].group_name); @@ -615,9 +614,9 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed) #ifdef USE_DEVICE_GROUPS DevGroupMessageType message_type = DGR_MSGTYP_UPDATE_DIRECT; #ifdef USE_PWM_DIMMER_REMOTE - if (handle_tap && !active_remote_pwm_dimmer) + if (handle_tap && !active_remote_pwm_dimmer) #else // USE_PWM_DIMMER_REMOTE - if (handle_tap) + if (handle_tap) #endif // USE_PWM_DIMMER_REMOTE message_type = (DevGroupMessageType)(message_type + DGR_MSGTYPFLAG_WITH_LOCAL); SendDeviceGroupMessage(power_button_index, message_type, dgr_item, dgr_value); @@ -690,7 +689,7 @@ void CmndPWMDimmerPWMs(void) { if (XdrvMailbox.data_len > 0 && XdrvMailbox.payload <= 5) { Settings.pwm_dimmer_cfg.pwm_count = XdrvMailbox.payload - 1; - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } Response_P(PSTR("{\"" D_CMND_PWM_DIMMER_PWMS "\":%u}"), Settings.pwm_dimmer_cfg.pwm_count + 1); } @@ -704,7 +703,7 @@ bool Xdrv35(uint8_t function) { bool result = false; - if (PWM_DIMMER != my_module_type) return result; + if (PWM_DIMMER != TasmotaGlobal.module_type) return result; switch (function) { case FUNC_EVERY_SECOND: @@ -717,7 +716,7 @@ bool Xdrv35(uint8_t function) // the LED will be set to a blinking state and will be turned off when the connection is // restored. If the state is blinking now, set a flag so we know that we need to restore it // when it stops blinking. - if (global_state.data) + if (TasmotaGlobal.global_state.data) restore_powered_off_led_counter = 5; else if (restore_powered_off_led_counter) { PWMDimmerSetPoweredOffLed(); @@ -758,7 +757,7 @@ bool Xdrv35(uint8_t function) // Bottom 15 3 15 1 if (buttons_pressed == 1 && Settings.flag4.multiple_device_groups) { power_button_index = button_index; - down_button_index = (Pin(GPIO_KEY1, power_button_index) == 15 ? gpio_pin[1] : gpio_pin[15]) - 32; + down_button_index = (Pin(GPIO_KEY1, power_button_index) == 15 ? TasmotaGlobal.gpio_pin[1] : TasmotaGlobal.gpio_pin[15]) - 32; active_remote_pwm_dimmer = nullptr; if (power_button_index || !first_device_group_is_local) active_remote_pwm_dimmer = &remote_pwm_dimmers[power_button_index]; diff --git a/tasmota/xdrv_37_sonoff_d1.ino b/tasmota/xdrv_37_sonoff_d1.ino index cd1bdd4b2..a27420e2f 100644 --- a/tasmota/xdrv_37_sonoff_d1.ino +++ b/tasmota/xdrv_37_sonoff_d1.ino @@ -44,9 +44,9 @@ struct SONOFFD1 { void SonoffD1Received(void) { - if (serial_in_byte_counter < 8) { return; } // Received ack from Rf chip (aa 55 01 04 00 00 05) + if (TasmotaGlobal.serial_in_byte_counter < 8) { return; } // Received ack from Rf chip (aa 55 01 04 00 00 05) - uint8_t action = serial_in_buffer[6] & 1; + uint8_t action = TasmotaGlobal.serial_in_buffer[6] & 1; if (action != SnfD1.power) { SnfD1.power = action; @@ -55,7 +55,7 @@ void SonoffD1Received(void) ExecuteCommandPower(1, action, SRC_SWITCH); } - uint8_t dimmer = serial_in_buffer[7]; + uint8_t dimmer = TasmotaGlobal.serial_in_buffer[7]; if (dimmer != SnfD1.dimmer) { SnfD1.dimmer = dimmer; @@ -69,27 +69,27 @@ void SonoffD1Received(void) /* // Send Acknowledge - Copy first 5 bytes, reset byte 6 and store crc in byte 7 // AA 55 01 04 00 00 05 - serial_in_buffer[5] = 0; // Ack - serial_in_buffer[6] = 0; // Crc + TasmotaGlobal.serial_in_buffer[5] = 0; // Ack + TasmotaGlobal.serial_in_buffer[6] = 0; // Crc for (uint32_t i = 0; i < 7; i++) { - if ((i > 1) && (i < 6)) { serial_in_buffer[6] += serial_in_buffer[i]; } - Serial.write(serial_in_buffer[i]); + if ((i > 1) && (i < 6)) { TasmotaGlobal.serial_in_buffer[6] += TasmotaGlobal.serial_in_buffer[i]; } + Serial.write(TasmotaGlobal.serial_in_buffer[i]); } */ } bool SonoffD1SerialInput(void) { - if (0xAA == serial_in_byte) { // 0xAA - Start of text - serial_in_byte_counter = 0; + if (0xAA == TasmotaGlobal.serial_in_byte) { // 0xAA - Start of text + TasmotaGlobal.serial_in_byte_counter = 0; SnfD1.receive_len = 7; } if (SnfD1.receive_len) { - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - if (6 == serial_in_byte_counter) { - SnfD1.receive_len += serial_in_byte; // 8 or 17 + TasmotaGlobal.serial_in_buffer[TasmotaGlobal.serial_in_byte_counter++] = TasmotaGlobal.serial_in_byte; + if (6 == TasmotaGlobal.serial_in_byte_counter) { + SnfD1.receive_len += TasmotaGlobal.serial_in_byte; // 8 or 17 } - if (serial_in_byte_counter == SnfD1.receive_len) { + if (TasmotaGlobal.serial_in_byte_counter == SnfD1.receive_len) { // Sonoff D1 codes // aa 55 01 04 00 0a 01 01 ff ff ff ff ff ff ff ff 09 - Power On, Dimmer 1% @@ -102,15 +102,15 @@ bool SonoffD1SerialInput(void) AddLogSerial(LOG_LEVEL_DEBUG); uint8_t crc = 0; for (uint32_t i = 2; i < SnfD1.receive_len -1; i++) { - crc += serial_in_buffer[i]; + crc += TasmotaGlobal.serial_in_buffer[i]; } - if (crc == serial_in_buffer[SnfD1.receive_len -1]) { + if (crc == TasmotaGlobal.serial_in_buffer[SnfD1.receive_len -1]) { SonoffD1Received(); SnfD1.receive_len = 0; return true; } } - serial_in_byte = 0; + TasmotaGlobal.serial_in_byte = 0; } return false; } @@ -163,8 +163,8 @@ bool SonoffD1ModuleSelected(void) { SetSerial(9600, TS_SERIAL_8N1); - devices_present++; - light_type = LT_SERIAL1; + TasmotaGlobal.devices_present++; + TasmotaGlobal.light_type = LT_SERIAL1; return true; } @@ -177,7 +177,7 @@ bool Xdrv37(uint8_t function) { bool result = false; - if (SONOFF_D1 == my_module_type) { + if (SONOFF_D1 == TasmotaGlobal.module_type) { switch (function) { case FUNC_SERIAL: result = SonoffD1SerialInput(); diff --git a/tasmota/xdrv_39_thermostat.ino b/tasmota/xdrv_39_thermostat.ino index 2fa479d46..a5c618af3 100644 --- a/tasmota/xdrv_39_thermostat.ino +++ b/tasmota/xdrv_39_thermostat.ino @@ -323,7 +323,7 @@ uint8_t ThermostatInputStatus(uint8_t input_switch) uint8_t ThermostatOutputStatus(uint8_t output_switch) { - return (uint8_t)bitRead(power, (output_switch - 1)); + return (uint8_t)bitRead(TasmotaGlobal.power, (output_switch - 1)); } int16_t ThermostatCelsiusToFahrenheit(const int32_t deg, uint8_t conv_type) { @@ -367,7 +367,7 @@ int16_t ThermostatFahrenheitToCelsius(const int32_t deg, uint8_t conv_type) { void ThermostatSignalPreProcessingSlow(uint8_t ctr_output) { // Update input sensor status - if ((uptime - Thermostat[ctr_output].timestamp_temp_measured_update) > ((uint32_t)Thermostat[ctr_output].time_sens_lost * 60)) { + if ((TasmotaGlobal.uptime - Thermostat[ctr_output].timestamp_temp_measured_update) > ((uint32_t)Thermostat[ctr_output].time_sens_lost * 60)) { Thermostat[ctr_output].status.sensor_alive = IFACE_OFF; Thermostat[ctr_output].temp_measured_gradient = 0; Thermostat[ctr_output].temp_measured = 0; @@ -392,7 +392,7 @@ void ThermostatSignalProcessingFast(uint8_t ctr_output) Thermostat[ctr_output].status.status_input = (uint32_t)ThermostatInputStatus(Thermostat[ctr_output].status.input_switch_number); // Update timestamp of last input if (Thermostat[ctr_output].status.status_input == IFACE_ON) { - Thermostat[ctr_output].timestamp_input_on = uptime; + Thermostat[ctr_output].timestamp_input_on = TasmotaGlobal.uptime; } // Update real status of the output Thermostat[ctr_output].status.status_output = (uint32_t)ThermostatOutputStatus(Thermostat[ctr_output].status.output_relay_number); @@ -453,7 +453,7 @@ void ThermostatHybridCtrPhase(uint8_t ctr_output) // If ramp-up offtime counter has been initalized // AND ramp-up offtime counter value reached if((Thermostat[ctr_output].time_ctr_checkpoint != 0) - && (uptime >= Thermostat[ctr_output].time_ctr_checkpoint)) { + && (TasmotaGlobal.uptime >= Thermostat[ctr_output].time_ctr_checkpoint)) { // Reset pause period Thermostat[ctr_output].time_ctr_checkpoint = 0; // Reset timers @@ -468,13 +468,13 @@ void ThermostatHybridCtrPhase(uint8_t ctr_output) // AND temp target has changed // AND value of temp target - actual temperature bigger than threshold for heating and lower for cooling // then go to ramp-up - if (((uptime - Thermostat[ctr_output].timestamp_output_off) > (60 * (uint32_t)Thermostat[ctr_output].time_allow_rampup)) + if (((TasmotaGlobal.uptime - Thermostat[ctr_output].timestamp_output_off) > (60 * (uint32_t)Thermostat[ctr_output].time_allow_rampup)) && (Thermostat[ctr_output].temp_target_level != Thermostat[ctr_output].temp_target_level_ctr) && ( ( (Thermostat[ctr_output].temp_target_level - Thermostat[ctr_output].temp_measured > Thermostat[ctr_output].temp_rampup_delta_in) && (flag_heating)) || ( (Thermostat[ctr_output].temp_measured - Thermostat[ctr_output].temp_target_level > Thermostat[ctr_output].temp_rampup_delta_in) && (!flag_heating)))) { - Thermostat[ctr_output].timestamp_rampup_start = uptime; + Thermostat[ctr_output].timestamp_rampup_start = TasmotaGlobal.uptime; Thermostat[ctr_output].temp_rampup_start = Thermostat[ctr_output].temp_measured; Thermostat[ctr_output].temp_rampup_meas_gradient = 0; Thermostat[ctr_output].time_rampup_deadtime = 0; @@ -541,7 +541,7 @@ bool ThermostatStateManualToAuto(uint8_t ctr_output) // then go to automatic if ((Thermostat[ctr_output].status.status_input == IFACE_OFF) &&(Thermostat[ctr_output].status.sensor_alive == IFACE_ON) - && ((uptime - Thermostat[ctr_output].timestamp_input_on) > ((uint32_t)Thermostat[ctr_output].time_manual_to_auto * 60))) { + && ((TasmotaGlobal.uptime - Thermostat[ctr_output].timestamp_input_on) > ((uint32_t)Thermostat[ctr_output].time_manual_to_auto * 60))) { change_state = true; } return change_state; @@ -608,7 +608,7 @@ void ThermostatOutputRelay(uint8_t ctr_output, uint32_t command) ExecuteCommandPower(Thermostat[ctr_output].status.output_relay_number, POWER_OFF, SRC_THERMOSTAT); } //#endif // DEBUG_THERMOSTAT - Thermostat[ctr_output].timestamp_output_off = uptime; + Thermostat[ctr_output].timestamp_output_off = TasmotaGlobal.uptime; Thermostat[ctr_output].status.status_output = IFACE_OFF; #ifdef DEBUG_THERMOSTAT ThermostatVirtualSwitch(ctr_output); @@ -793,15 +793,15 @@ void ThermostatCalculatePI(uint8_t ctr_output) } // Adjust output switch point - Thermostat[ctr_output].time_ctr_changepoint = uptime + (uint32_t)Thermostat[ctr_output].time_total_pi; + Thermostat[ctr_output].time_ctr_changepoint = TasmotaGlobal.uptime + (uint32_t)Thermostat[ctr_output].time_total_pi; // Adjust next cycle point - Thermostat[ctr_output].time_ctr_checkpoint = uptime + ((uint32_t)Thermostat[ctr_output].time_pi_cycle * 60); + Thermostat[ctr_output].time_ctr_checkpoint = TasmotaGlobal.uptime + ((uint32_t)Thermostat[ctr_output].time_pi_cycle * 60); } void ThermostatWorkAutomaticPI(uint8_t ctr_output) { bool flag_heating = (Thermostat[ctr_output].status.climate_mode == CLIMATE_HEATING); - if ( (uptime >= Thermostat[ctr_output].time_ctr_checkpoint) + if ( (TasmotaGlobal.uptime >= Thermostat[ctr_output].time_ctr_checkpoint) || (Thermostat[ctr_output].temp_target_level != Thermostat[ctr_output].temp_target_level_ctr) || ( (( (Thermostat[ctr_output].temp_measured < Thermostat[ctr_output].temp_target_level) && (Thermostat[ctr_output].temp_measured_gradient < 0) @@ -815,7 +815,7 @@ void ThermostatWorkAutomaticPI(uint8_t ctr_output) // Reset cycle active Thermostat[ctr_output].status.status_cycle_active = CYCLE_OFF; } - if (uptime < Thermostat[ctr_output].time_ctr_changepoint) { + if (TasmotaGlobal.uptime < Thermostat[ctr_output].time_ctr_changepoint) { Thermostat[ctr_output].status.status_cycle_active = CYCLE_ON; Thermostat[ctr_output].status.command_output = IFACE_ON; } @@ -842,7 +842,7 @@ void ThermostatWorkAutomaticRampUp(uint8_t ctr_output) } // Update time in ramp-up as well as delta temp - time_in_rampup = uptime - Thermostat[ctr_output].timestamp_rampup_start; + time_in_rampup = TasmotaGlobal.uptime - Thermostat[ctr_output].timestamp_rampup_start; temp_delta_rampup = Thermostat[ctr_output].temp_measured - Thermostat[ctr_output].temp_rampup_start; // Init command output status to true Thermostat[ctr_output].status.command_output = IFACE_ON; @@ -873,14 +873,14 @@ void ThermostatWorkAutomaticRampUp(uint8_t ctr_output) } // Calculate absolute gradient since start of ramp-up (considering deadtime) in thousandths of º/hour Thermostat[ctr_output].temp_rampup_meas_gradient = (int32_t)((360000 * (int32_t)temp_delta_rampup) / (int32_t)time_in_rampup); - Thermostat[ctr_output].time_rampup_nextcycle = uptime + ((uint32_t)Thermostat[ctr_output].time_rampup_cycle * 60); + Thermostat[ctr_output].time_rampup_nextcycle = TasmotaGlobal.uptime + ((uint32_t)Thermostat[ctr_output].time_rampup_cycle * 60); // Set auxiliary variables Thermostat[ctr_output].temp_rampup_cycle = Thermostat[ctr_output].temp_measured; - Thermostat[ctr_output].time_ctr_changepoint = uptime + (60 * (uint32_t)Thermostat[ctr_output].time_rampup_max); + Thermostat[ctr_output].time_ctr_changepoint = TasmotaGlobal.uptime + (60 * (uint32_t)Thermostat[ctr_output].time_rampup_max); Thermostat[ctr_output].temp_rampup_output_off = Thermostat[ctr_output].temp_target_level_ctr; } // Gradient calculation every time_rampup_cycle - else if ((Thermostat[ctr_output].time_rampup_deadtime > 0) && (uptime >= Thermostat[ctr_output].time_rampup_nextcycle)) { + else if ((Thermostat[ctr_output].time_rampup_deadtime > 0) && (TasmotaGlobal.uptime >= Thermostat[ctr_output].time_rampup_nextcycle)) { // Calculate temp. gradient in º/hour and set again time_rampup_nextcycle and temp_rampup_cycle // temp_rampup_meas_gradient = ((3600 * temp_delta_rampup) / (os.time() - time_rampup_nextcycle)) temp_delta_rampup = Thermostat[ctr_output].temp_measured - Thermostat[ctr_output].temp_rampup_cycle; @@ -900,9 +900,9 @@ void ThermostatWorkAutomaticRampUp(uint8_t ctr_output) // Calculate temperature for switching off the output // y = (((y2-y1)/(x2-x1))*(x-x1)) + y1 - Thermostat[ctr_output].temp_rampup_output_off = (int16_t)(((int32_t)temp_delta_rampup * (int32_t)(Thermostat[ctr_output].time_ctr_changepoint - (uptime - (time_total_rampup)))) / (int32_t)(time_total_rampup * Thermostat[ctr_output].counter_rampup_cycles)) + Thermostat[ctr_output].temp_rampup_cycle; + Thermostat[ctr_output].temp_rampup_output_off = (int16_t)(((int32_t)temp_delta_rampup * (int32_t)(Thermostat[ctr_output].time_ctr_changepoint - (TasmotaGlobal.uptime - (time_total_rampup)))) / (int32_t)(time_total_rampup * Thermostat[ctr_output].counter_rampup_cycles)) + Thermostat[ctr_output].temp_rampup_cycle; // Set auxiliary variables - Thermostat[ctr_output].time_rampup_nextcycle = uptime + ((uint32_t)Thermostat[ctr_output].time_rampup_cycle * 60); + Thermostat[ctr_output].time_rampup_nextcycle = TasmotaGlobal.uptime + ((uint32_t)Thermostat[ctr_output].time_rampup_cycle * 60); Thermostat[ctr_output].temp_rampup_cycle = Thermostat[ctr_output].temp_measured; // Reset period counter Thermostat[ctr_output].counter_rampup_cycles = 1; @@ -911,9 +911,9 @@ void ThermostatWorkAutomaticRampUp(uint8_t ctr_output) // Increase the period counter Thermostat[ctr_output].counter_rampup_cycles++; // Set another period - Thermostat[ctr_output].time_rampup_nextcycle = uptime + ((uint32_t)Thermostat[ctr_output].time_rampup_cycle * 60); + Thermostat[ctr_output].time_rampup_nextcycle = TasmotaGlobal.uptime + ((uint32_t)Thermostat[ctr_output].time_rampup_cycle * 60); // Reset time_ctr_changepoint and temp_rampup_output_off - Thermostat[ctr_output].time_ctr_changepoint = uptime + (60 * (uint32_t)Thermostat[ctr_output].time_rampup_max) - time_in_rampup; + Thermostat[ctr_output].time_ctr_changepoint = TasmotaGlobal.uptime + (60 * (uint32_t)Thermostat[ctr_output].time_rampup_max) - time_in_rampup; Thermostat[ctr_output].temp_rampup_output_off = Thermostat[ctr_output].temp_target_level_ctr; } // Set time to get out of ramp-up @@ -927,7 +927,7 @@ void ThermostatWorkAutomaticRampUp(uint8_t ctr_output) // or gradient is <= 0 for heating of >= 0 for cooling if ((Thermostat[ctr_output].time_rampup_deadtime == 0) || (Thermostat[ctr_output].time_ctr_checkpoint == 0) - || (uptime < Thermostat[ctr_output].time_ctr_changepoint) + || (TasmotaGlobal.uptime < Thermostat[ctr_output].time_ctr_changepoint) || ( ((Thermostat[ctr_output].temp_measured < Thermostat[ctr_output].temp_rampup_output_off) && (flag_heating)) || ((Thermostat[ctr_output].temp_measured > Thermostat[ctr_output].temp_rampup_output_off) @@ -951,7 +951,7 @@ void ThermostatWorkAutomaticRampUp(uint8_t ctr_output) Thermostat[ctr_output].temp_pi_accum_error = Thermostat[ctr_output].temp_rampup_pi_acc_error; } // Set to now time to get out of ramp-up - Thermostat[ctr_output].time_ctr_checkpoint = uptime; + Thermostat[ctr_output].time_ctr_checkpoint = TasmotaGlobal.uptime; // Switch Off output Thermostat[ctr_output].status.command_output = IFACE_OFF; } @@ -971,7 +971,7 @@ void ThermostatPeakDetectorInit(uint8_t ctr_output) Thermostat[ctr_output].peak_ctr = 0; Thermostat[ctr_output].temp_abs_max_atune = 0; Thermostat[ctr_output].temp_abs_min_atune = 100; - Thermostat[ctr_output].time_ctr_checkpoint = uptime + THERMOSTAT_TIME_MAX_AUTOTUNE; + Thermostat[ctr_output].time_ctr_checkpoint = TasmotaGlobal.uptime + THERMOSTAT_TIME_MAX_AUTOTUNE; } void ThermostatPeakDetector(uint8_t ctr_output) @@ -1020,7 +1020,7 @@ void ThermostatPeakDetector(uint8_t ctr_output) if ( (cond_peak_2) && (abs(Thermostat[ctr_output].temp_measured - Thermostat[ctr_output].temp_peaks_atune[peak_num]) > Thermostat[ctr_output].temp_band_no_peak_det)) { // Register peak timestamp; - Thermostat[ctr_output].time_peak_timestamps_atune[peak_num] = (uptime / 60); + Thermostat[ctr_output].time_peak_timestamps_atune[peak_num] = (TasmotaGlobal.uptime / 60); Thermostat[ctr_output].peak_ctr++; peak_transition = true; } @@ -1040,7 +1040,7 @@ void ThermostatPeakDetector(uint8_t ctr_output) && (abs(Thermostat[ctr_output].temp_measured - Thermostat[ctr_output].temp_peaks_atune[peak_num]) > Thermostat[ctr_output].temp_band_no_peak_det)) { // Calculate period // Register peak timestamp; - Thermostat[ctr_output].time_peak_timestamps_atune[peak_num] = (uptime / 60); + Thermostat[ctr_output].time_peak_timestamps_atune[peak_num] = (TasmotaGlobal.uptime / 60); Thermostat[ctr_output].peak_ctr++; peak_transition = true; } @@ -1117,17 +1117,17 @@ void ThermostatWorkAutomaticPIAutotune(uint8_t ctr_output) bool flag_heating = (Thermostat[ctr_output].status.climate_mode == CLIMATE_HEATING); // If no timeout of the PI Autotune function // AND no change in setpoint - if ((uptime < Thermostat[ctr_output].time_ctr_checkpoint) + if ((TasmotaGlobal.uptime < Thermostat[ctr_output].time_ctr_checkpoint) &&(Thermostat[ctr_output].temp_target_level_ctr == Thermostat[ctr_output].temp_target_level)) { - if (uptime >= Thermostat[ctr_output].time_ctr_checkpoint) { + if (TasmotaGlobal.uptime >= Thermostat[ctr_output].time_ctr_checkpoint) { Thermostat[ctr_output].temp_target_level_ctr = Thermostat[ctr_output].temp_target_level; // Calculate time_ctr_changepoint - Thermostat[ctr_output].time_ctr_changepoint = uptime + (((uint32_t)Thermostat[ctr_output].time_pi_cycle * (uint32_t)Thermostat[ctr_output].dutycycle_step_autotune) / (uint32_t)100); + Thermostat[ctr_output].time_ctr_changepoint = TasmotaGlobal.uptime + (((uint32_t)Thermostat[ctr_output].time_pi_cycle * (uint32_t)Thermostat[ctr_output].dutycycle_step_autotune) / (uint32_t)100); // Reset cycle active Thermostat[ctr_output].status.status_cycle_active = CYCLE_OFF; } // Set Output On/Off depending on the changepoint - if (uptime < Thermostat[ctr_output].time_ctr_changepoint) { + if (TasmotaGlobal.uptime < Thermostat[ctr_output].time_ctr_changepoint) { Thermostat[ctr_output].status.status_cycle_active = CYCLE_ON; Thermostat[ctr_output].status.command_output = IFACE_ON; } @@ -1318,9 +1318,9 @@ void ThermostatDebug(uint8_t ctr_output) AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].temp_rampup_output_off: %s"), result_chr); dtostrfd(Thermostat[ctr_output].time_ctr_checkpoint, 0, result_chr); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Thermostat[ctr_output].time_ctr_checkpoint: %s"), result_chr); - dtostrfd(uptime, 0, result_chr); + dtostrfd(TasmotaGlobal.uptime, 0, result_chr); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("uptime: %s"), result_chr); - dtostrfd(power, 0, result_chr); + dtostrfd(TasmotaGlobal.power, 0, result_chr); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("power: %s"), result_chr); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("------ Thermostat End ------")); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("")); @@ -1328,7 +1328,7 @@ void ThermostatDebug(uint8_t ctr_output) #endif // DEBUG_THERMOSTAT void ThermostatGetLocalSensor(uint8_t ctr_output) { - String buf = mqtt_data; // copy the string into a new buffer that will be modified + String buf = TasmotaGlobal.mqtt_data; // copy the string into a new buffer that will be modified JsonParser parser((char*)buf.c_str()); JsonParserObject root = parser.getRootObject(); if (root) { @@ -1341,7 +1341,7 @@ void ThermostatGetLocalSensor(uint8_t ctr_output) { if ( (value >= -1000) && (value <= 1000) && (Thermostat[ctr_output].status.sensor_type == SENSOR_LOCAL)) { - uint32_t timestamp = uptime; + uint32_t timestamp = TasmotaGlobal.uptime; // Calculate temperature gradient if temperature value has changed if (value != Thermostat[ctr_output].temp_measured) { int32_t temp_delta = (value - Thermostat[ctr_output].temp_measured); // in tenths of degrees @@ -1385,7 +1385,7 @@ void CmndClimateModeSet(void) if ((value >= CLIMATE_HEATING) && (value < CLIMATE_MODES_MAX)) { Thermostat[ctr_output].status.climate_mode = value; // Trigger a restart of the controller - Thermostat[ctr_output].time_ctr_checkpoint = uptime; + Thermostat[ctr_output].time_ctr_checkpoint = TasmotaGlobal.uptime; } } ResponseCmndNumber((int)Thermostat[ctr_output].status.climate_mode); @@ -1428,7 +1428,7 @@ void CmndControllerModeSet(void) if ((value >= CTR_HYBRID) && (value < CTR_MODES_MAX)) { Thermostat[ctr_output].status.controller_mode = value; // Reset controller variables - Thermostat[ctr_output].timestamp_rampup_start = uptime; + Thermostat[ctr_output].timestamp_rampup_start = TasmotaGlobal.uptime; Thermostat[ctr_output].temp_rampup_start = Thermostat[ctr_output].temp_measured; Thermostat[ctr_output].temp_rampup_meas_gradient = 0; Thermostat[ctr_output].time_rampup_deadtime = 0; @@ -1449,7 +1449,7 @@ void CmndInputSwitchSet(void) uint8_t value = (uint8_t)(XdrvMailbox.payload); if (ThermostatSwitchIdValid(value)) { Thermostat[ctr_output].status.input_switch_number = value; - Thermostat[ctr_output].timestamp_input_on = uptime; + Thermostat[ctr_output].timestamp_input_on = TasmotaGlobal.uptime; } } ResponseCmndNumber((int)Thermostat[ctr_output].status.input_switch_number); @@ -1538,7 +1538,7 @@ void CmndTempMeasuredSet(void) if ( (value >= -1000) && (value <= 1000) && (Thermostat[ctr_output].status.sensor_type == SENSOR_MQTT)) { - uint32_t timestamp = uptime; + uint32_t timestamp = TasmotaGlobal.uptime; // Calculate temperature gradient if temperature value has changed if (value != Thermostat[ctr_output].temp_measured) { int32_t temp_delta = (value - Thermostat[ctr_output].temp_measured); // in tenths of degrees diff --git a/tasmota/xdrv_40_telegram.ino b/tasmota/xdrv_40_telegram.ino index ddec0b3fb..ba1c6fde3 100644 --- a/tasmota/xdrv_40_telegram.ino +++ b/tasmota/xdrv_40_telegram.ino @@ -289,9 +289,9 @@ void TelegramSendGetMe(void) { String TelegramExecuteCommand(const char *svalue) { String response = ""; - uint32_t curridx = web_log_index; + uint32_t curridx = TasmotaGlobal.web_log_index; ExecuteCommand(svalue, SRC_CHAT); - if (web_log_index != curridx) { + if (TasmotaGlobal.web_log_index != curridx) { uint32_t counter = curridx; response = F("{"); bool cflg = false; @@ -304,7 +304,7 @@ String TelegramExecuteCommand(const char *svalue) { char* JSON = (char*)memchr(tmp, '{', len); if (JSON) { // Is it a JSON message (and not only [15:26:08 MQT: stat/wemos5/POWER = O]) size_t JSONlen = len - (JSON - tmp); - if (JSONlen > sizeof(mqtt_data)) { JSONlen = sizeof(mqtt_data); } + if (JSONlen > sizeof(TasmotaGlobal.mqtt_data)) { JSONlen = sizeof(TasmotaGlobal.mqtt_data); } char stemp[JSONlen]; strlcpy(stemp, JSON +1, JSONlen -2); if (cflg) { response += F(","); } @@ -315,7 +315,7 @@ String TelegramExecuteCommand(const char *svalue) { counter++; counter &= 0xFF; if (!counter) counter++; // Skip 0 as it is not allowed - } while (counter != web_log_index); + } while (counter != TasmotaGlobal.web_log_index); response += F("}"); } else { response = F("{\"" D_RSLT_WARNING "\":\"" D_ENABLE_WEBLOG_FOR_RESPONSE "\"}"); @@ -325,7 +325,7 @@ String TelegramExecuteCommand(const char *svalue) { } void TelegramLoop(void) { - if (!global_state.network_down && (Telegram.recv_enable || Telegram.echo_enable)) { + if (!TasmotaGlobal.global_state.network_down && (Telegram.recv_enable || Telegram.echo_enable)) { switch (Telegram.state) { case 0: TelegramInit(); @@ -412,7 +412,7 @@ void CmndTmState(void) { } } } - snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":{\"Send\":\"%s\",\"Receive\":\"%s\",\"Echo\":\"%s\"}}"), + snprintf_P (TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), PSTR("{\"%s\":{\"Send\":\"%s\",\"Receive\":\"%s\",\"Echo\":\"%s\"}}"), XdrvMailbox.command, GetStateText(Telegram.send_enable), GetStateText(Telegram.recv_enable), GetStateText(Telegram.echo_enable)); } diff --git a/tasmota/xdrv_41_tcp_bridge.ino b/tasmota/xdrv_41_tcp_bridge.ino index a6513ec46..88255fb6d 100644 --- a/tasmota/xdrv_41_tcp_bridge.ino +++ b/tasmota/xdrv_41_tcp_bridge.ino @@ -130,7 +130,7 @@ void TCPInit(void) { if (!tcp_buf) { AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_TCP "could not allocate buffer")); return; } if (!Settings.tcp_baudrate) { Settings.tcp_baudrate = 115200 / 1200; } - TCPSerial = new TasmotaSerial(Pin(GPIO_TCP_RX), Pin(GPIO_TCP_TX), seriallog_level ? 1 : 2, 0, TCP_BRIDGE_BUF_SIZE); // set a receive buffer of 256 bytes + TCPSerial = new TasmotaSerial(Pin(GPIO_TCP_RX), Pin(GPIO_TCP_TX), TasmotaGlobal.seriallog_level ? 1 : 2, 0, TCP_BRIDGE_BUF_SIZE); // set a receive buffer of 256 bytes TCPSerial->begin(Settings.tcp_baudrate * 1200); if (TCPSerial->hardwareSerial()) { ClaimSerial(); @@ -168,7 +168,7 @@ void CmndTCPStart(void) { server_tcp->setNoDelay(true); } - ResponseCmndDone(); + ResponseCmndDone(); } void CmndTCPBaudrate(void) { diff --git a/tasmota/xdrv_44_miel_hvac.ino b/tasmota/xdrv_44_miel_hvac.ino index cd08d1c54..6a9dda6c5 100644 --- a/tasmota/xdrv_44_miel_hvac.ino +++ b/tasmota/xdrv_44_miel_hvac.ino @@ -926,7 +926,7 @@ miel_hvac_input_settings(struct miel_hvac_softc *sc, return; } - if (bitRead(power, sc->sc_device) != !!state) + if (bitRead(TasmotaGlobal.power, sc->sc_device) != !!state) ExecuteCommandPower(sc->sc_device, state, SRC_SWITCH); publish = (sc->sc_settings_set == 0) || @@ -1044,7 +1044,7 @@ miel_hvac_pre_init(void) SetSerial(baudrate, TS_SERIAL_8E1); } - sc->sc_device = devices_present++; /* claim a POWER device slot */ + sc->sc_device = TasmotaGlobal.devices_present++; /* claim a POWER device slot */ miel_hvac_sc = sc; return; diff --git a/tasmota/xdrv_81_webcam.ino b/tasmota/xdrv_81_webcam.ino index d10bca647..d87723cd3 100755 --- a/tasmota/xdrv_81_webcam.ino +++ b/tasmota/xdrv_81_webcam.ino @@ -807,7 +807,7 @@ void HandleWebcamRoot(void) { /*********************************************************************************************/ uint32_t WcSetStreamserver(uint32_t flag) { - if (global_state.network_down) { return 0; } + if (TasmotaGlobal.global_state.network_down) { return 0; } Wc.stream_active = 0; @@ -857,7 +857,7 @@ void WcLoop(void) { #ifdef ENABLE_RTSPSERVER - if (!rtsp_start && !global_state.wifi_down && Wc.up) { + if (!rtsp_start && !TasmotaGlobal.global_state.wifi_down && Wc.up) { rtspServer.begin(); rtsp_start = 1; AddLog_P2(LOG_LEVEL_INFO, PSTR("CAM: RTSP init")); diff --git a/tasmota/xdrv_82_ethernet.ino b/tasmota/xdrv_82_ethernet.ino index fde8a417a..a25cc1072 100644 --- a/tasmota/xdrv_82_ethernet.ino +++ b/tasmota/xdrv_82_ethernet.ino @@ -80,7 +80,7 @@ #include -char eth_hostname[sizeof(my_hostname)]; +char eth_hostname[sizeof(TasmotaGlobal.hostname)]; void EthernetEvent(WiFiEvent_t event) { switch (event) { @@ -98,15 +98,15 @@ void EthernetEvent(WiFiEvent_t event) { Settings.ip_address[1] = (uint32_t)ETH.gatewayIP(); Settings.ip_address[2] = (uint32_t)ETH.subnetMask(); Settings.ip_address[3] = (uint32_t)ETH.dnsIP(); - global_state.eth_down = 0; + TasmotaGlobal.global_state.eth_down = 0; break; case SYSTEM_EVENT_ETH_DISCONNECTED: AddLog_P2(LOG_LEVEL_INFO, PSTR("ETH: Disconnected")); - global_state.eth_down = 1; + TasmotaGlobal.global_state.eth_down = 1; break; case SYSTEM_EVENT_ETH_STOP: AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: Stopped")); - global_state.eth_down = 1; + TasmotaGlobal.global_state.eth_down = 1; break; default: break; @@ -120,8 +120,8 @@ void EthernetInit(void) { return; } -// snprintf_P(Eth.hostname, sizeof(Eth.hostname), PSTR("%s_eth"), my_hostname); - strlcpy(eth_hostname, my_hostname, sizeof(eth_hostname) -5); // Make sure there is room for "_eth" +// snprintf_P(Eth.hostname, sizeof(Eth.hostname), PSTR("%s_eth"), TasmotaGlobal.hostname); + strlcpy(eth_hostname, TasmotaGlobal.hostname, sizeof(eth_hostname) -5); // Make sure there is room for "_eth" strcat(eth_hostname, "_eth"); WiFi.onEvent(EthernetEvent); @@ -164,7 +164,7 @@ void CmndEthernet(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { Settings.flag4.network_ethernet = XdrvMailbox.payload; - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } ResponseCmndStateText(Settings.flag4.network_ethernet); } @@ -173,7 +173,7 @@ void CmndEthAddress(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 31)) { Settings.eth_address = XdrvMailbox.payload; - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } ResponseCmndNumber(Settings.eth_address); } @@ -182,7 +182,7 @@ void CmndEthType(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { Settings.eth_type = XdrvMailbox.payload; - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } ResponseCmndNumber(Settings.eth_type); } @@ -191,7 +191,7 @@ void CmndEthClockMode(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { Settings.eth_clk_mode = XdrvMailbox.payload; - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } ResponseCmndNumber(Settings.eth_clk_mode); } diff --git a/tasmota/xdrv_99_debug.ino b/tasmota/xdrv_99_debug.ino index 7471d3095..32c296485 100644 --- a/tasmota/xdrv_99_debug.ino +++ b/tasmota/xdrv_99_debug.ino @@ -172,11 +172,11 @@ void CpuLoadLoop(void) CPU_loops ++; if ((CPU_last_millis + (CPU_load_check *1000)) <= CPU_last_loop_time) { #if defined(F_CPU) && (F_CPU == 160000000L) - int CPU_load = 100 - ( (CPU_loops*(1 + 30*ssleep)) / (CPU_load_check *800) ); + int CPU_load = 100 - ( (CPU_loops*(1 + 30*TasmotaGlobal.sleep)) / (CPU_load_check *800) ); CPU_loops = CPU_loops / CPU_load_check; AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(160MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops); #else - int CPU_load = 100 - ( (CPU_loops*(1 + 30*ssleep)) / (CPU_load_check *400) ); + int CPU_load = 100 - ( (CPU_loops*(1 + 30*TasmotaGlobal.sleep)) / (CPU_load_check *400) ); CPU_loops = CPU_loops / CPU_load_check; AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(80MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops); #endif @@ -259,21 +259,21 @@ void DebugRtcDump(char* parms) for (row = srow; row < maxrow; row++) { idx = row * CFG_COLS; - snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), idx); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%03X:"), idx); for (col = 0; col < CFG_COLS; col++) { if (!(col%4)) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s "), TasmotaGlobal.log_data); } - snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[idx + col]); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s %02X"), TasmotaGlobal.log_data, buffer[idx + col]); } - snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s |"), TasmotaGlobal.log_data); for (col = 0; col < CFG_COLS; col++) { // if (!(col%4)) { -// snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); +// snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s "), TasmotaGlobal.log_data); // } - snprintf_P(log_data, sizeof(log_data), PSTR("%s%c"), log_data, ((buffer[idx + col] > 0x20) && (buffer[idx + col] < 0x7F)) ? (char)buffer[idx + col] : ' '); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s%c"), TasmotaGlobal.log_data, ((buffer[idx + col] > 0x20) && (buffer[idx + col] < 0x7F)) ? (char)buffer[idx + col] : ' '); } - snprintf_P(log_data, sizeof(log_data), PSTR("%s|"), log_data); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s|"), TasmotaGlobal.log_data); AddLog(LOG_LEVEL_INFO); } #endif // ESP8266 @@ -311,21 +311,21 @@ void DebugCfgDump(char* parms) for (row = srow; row < maxrow; row++) { idx = row * CFG_COLS; - snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), idx); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%03X:"), idx); for (col = 0; col < CFG_COLS; col++) { if (!(col%4)) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s "), TasmotaGlobal.log_data); } - snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[idx + col]); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s %02X"), TasmotaGlobal.log_data, buffer[idx + col]); } - snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s |"), TasmotaGlobal.log_data); for (col = 0; col < CFG_COLS; col++) { // if (!(col%4)) { -// snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); +// snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s "), TasmotaGlobal.log_data); // } - snprintf_P(log_data, sizeof(log_data), PSTR("%s%c"), log_data, ((buffer[idx + col] > 0x20) && (buffer[idx + col] < 0x7F)) ? (char)buffer[idx + col] : ' '); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s%c"), TasmotaGlobal.log_data, ((buffer[idx + col] > 0x20) && (buffer[idx + col] < 0x7F)) ? (char)buffer[idx + col] : ' '); } - snprintf_P(log_data, sizeof(log_data), PSTR("%s|"), log_data); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s|"), TasmotaGlobal.log_data); AddLog(LOG_LEVEL_INFO); delay(1); } @@ -344,15 +344,15 @@ 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; - snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), address); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.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]); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s %02X"), TasmotaGlobal.log_data, buffer[address +i]); } - snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s |"), TasmotaGlobal.log_data); for (uint32_t i = 0; i < 4; i++) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s%c"), log_data, ((buffer[address +i] > 0x20) && (buffer[address +i] < 0x7F)) ? (char)buffer[address +i] : ' '); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s%c"), TasmotaGlobal.log_data, ((buffer[address +i] > 0x20) && (buffer[address +i] < 0x7F)) ? (char)buffer[address +i] : ' '); } - snprintf_P(log_data, sizeof(log_data), PSTR("%s| 0x%02X (%d), 0x%04X (%d), 0x%0LX (%lu)"), log_data, data8, data8, data16, data16, data32, data32); + snprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), PSTR("%s| 0x%02X (%d), 0x%04X (%d), 0x%0LX (%lu)"), TasmotaGlobal.log_data, data8, data8, data16, data16, data32, data32); AddLog(LOG_LEVEL_INFO); } @@ -487,7 +487,7 @@ void CmndSetSensor(void) if (XdrvMailbox.payload >= 0) { bitWrite(Settings.sensors[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1); if (1 == XdrvMailbox.payload) { - restart_flag = 2; // To safely re-enable a sensor currently most sensor need to follow complete restart init cycle + TasmotaGlobal.restart_flag = 2; // To safely re-enable a sensor currently most sensor need to follow complete restart init cycle } } Response_P(PSTR("{\"" D_CMND_SETSENSOR "\":")); @@ -551,7 +551,7 @@ void CmndFlashDump(void) void CmndI2cWrite(void) { // I2cWrite
,.. - if (i2c_flg) { + if (TasmotaGlobal.i2c_enabled) { char* parms = XdrvMailbox.data; uint8_t buffer[100]; uint32_t index = 0; @@ -580,7 +580,7 @@ void CmndI2cWrite(void) void CmndI2cRead(void) { // I2cRead
, - if (i2c_flg) { + if (TasmotaGlobal.i2c_enabled) { char* parms = XdrvMailbox.data; uint8_t buffer[100]; uint32_t index = 0; @@ -613,7 +613,7 @@ void CmndI2cRead(void) void CmndI2cStretch(void) { #ifdef ESP8266 - if (i2c_flg && (XdrvMailbox.payload > 0)) { + if (TasmotaGlobal.i2c_enabled && (XdrvMailbox.payload > 0)) { Wire.setClockStretchLimit(XdrvMailbox.payload); } ResponseCmndDone(); @@ -622,7 +622,7 @@ void CmndI2cStretch(void) void CmndI2cClock(void) { - if (i2c_flg && (XdrvMailbox.payload > 0)) { + if (TasmotaGlobal.i2c_enabled && (XdrvMailbox.payload > 0)) { Wire.setClock(XdrvMailbox.payload); } ResponseCmndDone(); diff --git a/tasmota/xdsp_04_ili9341.ino b/tasmota/xdsp_04_ili9341.ino index 68be6a73a..019cd883e 100644 --- a/tasmota/xdsp_04_ili9341.ino +++ b/tasmota/xdsp_04_ili9341.ino @@ -256,7 +256,7 @@ bool Xdsp04(uint8_t function) { bool result = false; - if (spi_flg) { + if (TasmotaGlobal.spi_enabled) { if (FUNC_DISPLAY_INIT_DRIVER == function) { Ili9341InitDriver(); } diff --git a/tasmota/xlgt_01_ws2812.ino b/tasmota/xlgt_01_ws2812.ino index e22d090d4..e98d3ec12 100644 --- a/tasmota/xlgt_01_ws2812.ino +++ b/tasmota/xlgt_01_ws2812.ino @@ -461,7 +461,7 @@ void Ws2812ShowScheme(void) switch (scheme) { case 0: // Clock - if ((1 == state_250mS) || (Ws2812.show_next)) { + if ((1 == TasmotaGlobal.state_250mS) || (Ws2812.show_next)) { Ws2812Clock(); Ws2812.show_next = 0; } @@ -491,11 +491,11 @@ void Ws2812ModuleSelected(void) Light.max_scheme += WS2812_SCHEMES; #if (USE_WS2812_CTYPE > NEO_3LED) - light_type = LT_RGBW; + TasmotaGlobal.light_type = LT_RGBW; #else - light_type = LT_RGB; + TasmotaGlobal.light_type = LT_RGB; #endif - light_flg = XLGT_01; + TasmotaGlobal.light_driver = XLGT_01; } } diff --git a/tasmota/xlgt_02_my92x1.ino b/tasmota/xlgt_02_my92x1.ino index 6d12abf84..bd5deb2ff 100644 --- a/tasmota/xlgt_02_my92x1.ino +++ b/tasmota/xlgt_02_my92x1.ino @@ -125,19 +125,19 @@ void My92x1ModuleSelected(void) digitalWrite(My92x1.pdcki_pin, LOW); My92x1.model = 2; - light_type = LT_RGBW; // RGBW (2 chips) as used in Lohas - if (AILIGHT == my_module_type) { // RGBW (1 chip) as used in Ailight + TasmotaGlobal.light_type = LT_RGBW; // RGBW (2 chips) as used in Lohas + if (AILIGHT == TasmotaGlobal.module_type) { // RGBW (1 chip) as used in Ailight My92x1.model = 0; -// light_type = LT_RGBW; +// TasmotaGlobal.light_type = LT_RGBW; } - else if (SONOFF_B1 == my_module_type) { // RGBWC (2 chips) as used in Sonoff B1 + else if (SONOFF_B1 == TasmotaGlobal.module_type) { // RGBWC (2 chips) as used in Sonoff B1 My92x1.model = 1; - light_type = LT_RGBWC; + TasmotaGlobal.light_type = LT_RGBWC; } LightMy92x1Init(); - light_flg = XLGT_02; + TasmotaGlobal.light_driver = XLGT_02; AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: MY29x1 Found")); } } diff --git a/tasmota/xlgt_03_sm16716.ino b/tasmota/xlgt_03_sm16716.ino index 0c6866ada..b670b3ed8 100644 --- a/tasmota/xlgt_03_sm16716.ino +++ b/tasmota/xlgt_03_sm16716.ino @@ -124,7 +124,7 @@ bool Sm16716SetChannels(void) for (uint32_t i = 3; i < Light.subtype; i++) { if (PinUsed(GPIO_PWM1, i-3)) { //AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Cur_Col%d 10 bits %d, Pwm%d %d"), i, cur_col[i], i+1, curcol); - analogWrite(Pin(GPIO_PWM1, i-3), bitRead(pwm_inverted, i-3) ? Settings.pwm_range - cur_col_10bits[i] : cur_col_10bits[i]); + analogWrite(Pin(GPIO_PWM1, i-3), bitRead(TasmotaGlobal.pwm_inverted, i-3) ? Settings.pwm_range - cur_col_10bits[i] : cur_col_10bits[i]); } } */ @@ -174,8 +174,8 @@ void Sm16716ModuleSelected(void) } LightPwmOffset(LST_RGB); // Handle any PWM pins, skipping the first 3 color values for sm16716 - light_type += LST_RGB; // Add RGB to be controlled by sm16716 - light_flg = XLGT_03; + TasmotaGlobal.light_type += LST_RGB; // Add RGB to be controlled by sm16716 + TasmotaGlobal.light_driver = XLGT_03; AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: SM16716 Found")); } } diff --git a/tasmota/xlgt_04_sm2135.ino b/tasmota/xlgt_04_sm2135.ino index b48da2308..c0128dbb7 100644 --- a/tasmota/xlgt_04_sm2135.ino +++ b/tasmota/xlgt_04_sm2135.ino @@ -176,8 +176,8 @@ void Sm2135ModuleSelected(void) Sm2135Init(); - light_type = LT_RGBWC; - light_flg = XLGT_04; + TasmotaGlobal.light_type = LT_RGBWC; + TasmotaGlobal.light_driver = XLGT_04; AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: SM2135 (%s) Found"), (SM2135_WCBGR == Sm2135.model) ? PSTR("BGR") : PSTR("GRB")); } } diff --git a/tasmota/xlgt_05_sonoff_l1.ino b/tasmota/xlgt_05_sonoff_l1.ino index 295330142..7cf9590f2 100644 --- a/tasmota/xlgt_05_sonoff_l1.ino +++ b/tasmota/xlgt_05_sonoff_l1.ino @@ -66,29 +66,29 @@ void SnfL1SerialSendOk(void) bool SnfL1SerialInput(void) { - if (serial_in_byte != 0x1B) { - if (serial_in_byte_counter >= 140) { - serial_in_byte_counter = 0; + if (TasmotaGlobal.serial_in_byte != 0x1B) { + if (TasmotaGlobal.serial_in_byte_counter >= 140) { + TasmotaGlobal.serial_in_byte_counter = 0; } - if (serial_in_byte_counter || (!serial_in_byte_counter && ('A' == serial_in_byte))) { // A from AT - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + if (TasmotaGlobal.serial_in_byte_counter || (!TasmotaGlobal.serial_in_byte_counter && ('A' == TasmotaGlobal.serial_in_byte))) { // A from AT + TasmotaGlobal.serial_in_buffer[TasmotaGlobal.serial_in_byte_counter++] = TasmotaGlobal.serial_in_byte; } } else { - serial_in_buffer[serial_in_byte_counter++] = 0x00; + TasmotaGlobal.serial_in_buffer[TasmotaGlobal.serial_in_byte_counter++] = 0x00; // AT+RESULT="sequence":"1554682835320" // AT+UPDATE="sequence":"34906","switch":"on","light_type":1,"colorR":0,"colorG":16,"colorB":0,"bright":6,"mode":1 // AT+UPDATE="switch":"on","light_type":1,"colorR":255,"colorG":0,"colorB":0,"bright":6,"mode":1,"speed":100,"sensitive":10 -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd %s"), serial_in_buffer); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd %s"), TasmotaGlobal.serial_in_buffer); - if (!strncmp(serial_in_buffer +3, "RESULT", 6)) { + if (!strncmp(TasmotaGlobal.serial_in_buffer +3, "RESULT", 6)) { Snfl1.receive_ready = true; } - else if (!strncmp(serial_in_buffer +3, "UPDATE", 6)) { + else if (!strncmp(TasmotaGlobal.serial_in_buffer +3, "UPDATE", 6)) { char cmnd_dimmer[20]; char cmnd_color[20]; char *end_str; - char *string = serial_in_buffer +10; + char *string = TasmotaGlobal.serial_in_buffer +10; char *token = strtok_r(string, ",", &end_str); bool color_updated[3] = { false, false, false }; @@ -190,7 +190,7 @@ bool SnfL1SerialInput(void) return true; } - serial_in_byte = 0; + TasmotaGlobal.serial_in_byte = 0; return false; } @@ -220,12 +220,12 @@ bool SnfL1SetChannels(void) void SnfL1ModuleSelected(void) { - if (SONOFF_L1 == my_module_type) { + if (SONOFF_L1 == TasmotaGlobal.module_type) { if (PinUsed(GPIO_RXD) && PinUsed(GPIO_TXD)) { SetSerial(19200, TS_SERIAL_8N1); - light_type = LT_RGB; - light_flg = XLGT_05; + TasmotaGlobal.light_type = LT_RGB; + TasmotaGlobal.light_driver = XLGT_05; AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: Sonoff L1 Found")); } } diff --git a/tasmota/xlgt_06_electriq_moodl.ino b/tasmota/xlgt_06_electriq_moodl.ino index 57c493e64..802b658cc 100644 --- a/tasmota/xlgt_06_electriq_moodl.ino +++ b/tasmota/xlgt_06_electriq_moodl.ino @@ -72,8 +72,8 @@ void ElectriqMoodLModuleSelected(void) { if (PinUsed(GPIO_ELECTRIQ_MOODL_TX)) { SetSerial(9600, TS_SERIAL_8N1); - light_type = LT_RGBW; - light_flg = XLGT_06; + TasmotaGlobal.light_type = LT_RGBW; + TasmotaGlobal.light_driver = XLGT_06; AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: ElectriQ Mood Lamp Found")); } } diff --git a/tasmota/xlgt_interface.ino b/tasmota/xlgt_interface.ino index b38481fb1..ef5934d54 100644 --- a/tasmota/xlgt_interface.ino +++ b/tasmota/xlgt_interface.ino @@ -101,13 +101,13 @@ bool XlgtCall(uint8_t function) if (FUNC_MODULE_INIT == function) { for (uint32_t x = 0; x < xlgt_present; x++) { xlgt_func_ptr[x](function); - if (light_flg) { + if (TasmotaGlobal.light_driver) { xlgt_active = x; return true; // Stop further driver investigation } } } - else if (light_flg) { + else if (TasmotaGlobal.light_driver) { return xlgt_func_ptr[xlgt_active](function); } return false; diff --git a/tasmota/xnrg_01_hlw8012.ino b/tasmota/xnrg_01_hlw8012.ino index d137cb2eb..c7dbc631f 100644 --- a/tasmota/xnrg_01_hlw8012.ino +++ b/tasmota/xnrg_01_hlw8012.ino @@ -270,7 +270,7 @@ void HlwDrvInit(void) Energy.voltage_available = false; } - energy_flg = XNRG_01; + TasmotaGlobal.energy_driver = XNRG_01; } } diff --git a/tasmota/xnrg_02_cse7766.ino b/tasmota/xnrg_02_cse7766.ino index 053c4c6ba..e6e2eebc3 100644 --- a/tasmota/xnrg_02_cse7766.ino +++ b/tasmota/xnrg_02_cse7766.ino @@ -231,7 +231,7 @@ void CseSnsInit(void) { } Cse.power_invalid = Settings.param[P_CSE7766_INVALID_POWER]; } else { - energy_flg = ENERGY_NONE; + TasmotaGlobal.energy_driver = ENERGY_NONE; } } @@ -240,7 +240,7 @@ void CseDrvInit(void) { if (PinUsed(GPIO_CSE7766_RX)) { Cse.rx_buffer = (uint8_t*)(malloc(CSE_BUFFER_SIZE)); if (Cse.rx_buffer != nullptr) { - energy_flg = XNRG_02; + TasmotaGlobal.energy_driver = XNRG_02; } } } diff --git a/tasmota/xnrg_03_pzem004t.ino b/tasmota/xnrg_03_pzem004t.ino index f06b34b0e..36b21564c 100644 --- a/tasmota/xnrg_03_pzem004t.ino +++ b/tasmota/xnrg_03_pzem004t.ino @@ -194,7 +194,7 @@ void PzemEvery250ms(void) Pzem.energy += value; if (Pzem.phase == Energy.phase_count -1) { if (Pzem.energy > Pzem.last_energy) { // Handle missed phase - if (uptime > PZEM_STABILIZE) { + if (TasmotaGlobal.uptime > PZEM_STABILIZE) { EnergyUpdateTotal(Pzem.energy, false); } Pzem.last_energy = Pzem.energy; @@ -232,7 +232,7 @@ void PzemEvery250ms(void) } else { Pzem.send_retry--; - if ((Energy.phase_count > 1) && (0 == Pzem.send_retry) && (uptime < PZEM_STABILIZE)) { + if ((Energy.phase_count > 1) && (0 == Pzem.send_retry) && (TasmotaGlobal.uptime < PZEM_STABILIZE)) { Energy.phase_count--; // Decrement phases if no response after retry within 30 seconds after restart } } @@ -250,14 +250,14 @@ void PzemSnsInit(void) Pzem.phase = 0; Pzem.read_state = 1; } else { - energy_flg = ENERGY_NONE; + TasmotaGlobal.energy_driver = ENERGY_NONE; } } void PzemDrvInit(void) { if (PinUsed(GPIO_PZEM004_RX) && PinUsed(GPIO_PZEM0XX_TX)) { // Any device with a Pzem004T - energy_flg = XNRG_03; + TasmotaGlobal.energy_driver = XNRG_03; } } @@ -285,7 +285,7 @@ bool Xnrg03(uint8_t function) switch (function) { case FUNC_EVERY_250_MSECOND: - if (PzemSerial && (uptime > 4)) { PzemEvery250ms(); } + if (PzemSerial) { PzemEvery250ms(); } break; case FUNC_COMMAND: result = PzemCommand(); diff --git a/tasmota/xnrg_04_mcp39f501.ino b/tasmota/xnrg_04_mcp39f501.ino index b3f8dbe6c..6b7799cce 100644 --- a/tasmota/xnrg_04_mcp39f501.ino +++ b/tasmota/xnrg_04_mcp39f501.ino @@ -566,13 +566,13 @@ void McpSnsInit(void) if (McpSerial->begin(MCP_BAUDRATE)) { if (McpSerial->hardwareSerial()) { ClaimSerial(); - mcp_buffer = serial_in_buffer; // Use idle serial buffer to save RAM + mcp_buffer = TasmotaGlobal.serial_in_buffer; // Use idle serial buffer to save RAM } else { mcp_buffer = (char*)(malloc(MCP_BUFFER_SIZE)); } DigitalWrite(GPIO_MCP39F5_RST, 0, 1); // MCP enable } else { - energy_flg = ENERGY_NONE; + TasmotaGlobal.energy_driver = ENERGY_NONE; } } @@ -586,7 +586,7 @@ void McpDrvInit(void) mcp_calibrate = 0; mcp_timeout = 2; // Initial wait mcp_init = 2; // Initial setup steps - energy_flg = XNRG_04; + TasmotaGlobal.energy_driver = XNRG_04; } } diff --git a/tasmota/xnrg_05_pzem_ac.ino b/tasmota/xnrg_05_pzem_ac.ino index bd656a874..580682609 100644 --- a/tasmota/xnrg_05_pzem_ac.ino +++ b/tasmota/xnrg_05_pzem_ac.ino @@ -81,7 +81,7 @@ void PzemAcEverySecond(void) PzemAc.energy += (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]); // 4294967295 Wh if (PzemAc.phase == Energy.phase_count -1) { if (PzemAc.energy > PzemAc.last_energy) { // Handle missed phase - if (uptime > PZEM_AC_STABILIZE) { + if (TasmotaGlobal.uptime > PZEM_AC_STABILIZE) { EnergyUpdateTotal(PzemAc.energy, false); } PzemAc.last_energy = PzemAc.energy; @@ -109,7 +109,7 @@ void PzemAcEverySecond(void) } else { PzemAc.send_retry--; - if ((Energy.phase_count > 1) && (0 == PzemAc.send_retry) && (uptime < PZEM_AC_STABILIZE)) { + if ((Energy.phase_count > 1) && (0 == PzemAc.send_retry) && (TasmotaGlobal.uptime < PZEM_AC_STABILIZE)) { Energy.phase_count--; // Decrement phases if no response after retry within 30 seconds after restart } } @@ -124,14 +124,14 @@ void PzemAcSnsInit(void) Energy.phase_count = 3; // Start off with three phases PzemAc.phase = 0; } else { - energy_flg = ENERGY_NONE; + TasmotaGlobal.energy_driver = ENERGY_NONE; } } void PzemAcDrvInit(void) { if (PinUsed(GPIO_PZEM016_RX) && PinUsed(GPIO_PZEM0XX_TX)) { - energy_flg = XNRG_05; + TasmotaGlobal.energy_driver = XNRG_05; } } @@ -158,7 +158,7 @@ bool Xnrg05(uint8_t function) switch (function) { case FUNC_ENERGY_EVERY_SECOND: - if (uptime > 4) { PzemAcEverySecond(); } // Fix start up issue #5875 + if (TasmotaGlobal.uptime > 4) { PzemAcEverySecond(); } // Fix start up issue #5875 break; case FUNC_COMMAND: result = PzemAcCommand(); diff --git a/tasmota/xnrg_06_pzem_dc.ino b/tasmota/xnrg_06_pzem_dc.ino index 444861fb0..b96aad085 100644 --- a/tasmota/xnrg_06_pzem_dc.ino +++ b/tasmota/xnrg_06_pzem_dc.ino @@ -78,7 +78,7 @@ void PzemDcEverySecond(void) PzemDc.energy += (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]); // 4294967295 Wh if (PzemDc.channel == Energy.phase_count -1) { if (PzemDc.energy > PzemDc.last_energy) { // Handle missed channel - if (uptime > PZEM_DC_STABILIZE) { + if (TasmotaGlobal.uptime > PZEM_DC_STABILIZE) { EnergyUpdateTotal(PzemDc.energy, false); } PzemDc.last_energy = PzemDc.energy; @@ -105,7 +105,7 @@ void PzemDcEverySecond(void) } else { PzemDc.send_retry--; - if ((Energy.phase_count > 1) && (0 == PzemDc.send_retry) && (uptime < PZEM_DC_STABILIZE)) { + if ((Energy.phase_count > 1) && (0 == PzemDc.send_retry) && (TasmotaGlobal.uptime < PZEM_DC_STABILIZE)) { Energy.phase_count--; // Decrement channels if no response after retry within 30 seconds after restart } } @@ -121,14 +121,14 @@ void PzemDcSnsInit(void) Energy.phase_count = 3; // Start off with three channels PzemDc.channel = 0; } else { - energy_flg = ENERGY_NONE; + TasmotaGlobal.energy_driver = ENERGY_NONE; } } void PzemDcDrvInit(void) { if (PinUsed(GPIO_PZEM017_RX) && PinUsed(GPIO_PZEM0XX_TX)) { - energy_flg = XNRG_06; + TasmotaGlobal.energy_driver = XNRG_06; } } @@ -155,7 +155,7 @@ bool Xnrg06(uint8_t function) switch (function) { case FUNC_ENERGY_EVERY_SECOND: - if (uptime > 4) { PzemDcEverySecond(); } // Fix start up issue #5875 + if (TasmotaGlobal.uptime > 4) { PzemDcEverySecond(); } // Fix start up issue #5875 break; case FUNC_COMMAND: result = PzemDcCommand(); diff --git a/tasmota/xnrg_07_ade7953.ino b/tasmota/xnrg_07_ade7953.ino index beaea9635..6e4dd48ce 100644 --- a/tasmota/xnrg_07_ade7953.ino +++ b/tasmota/xnrg_07_ade7953.ino @@ -213,7 +213,7 @@ void Ade7953DrvInit(void) Energy.phase_count = 2; // Handle two channels as two phases Energy.voltage_common = true; // Use common voltage Energy.frequency_common = true; // Use common frequency - energy_flg = XNRG_07; + TasmotaGlobal.energy_driver = XNRG_07; } } } diff --git a/tasmota/xnrg_08_sdm120.ino b/tasmota/xnrg_08_sdm120.ino index 8f764ad52..b21cf12b8 100644 --- a/tasmota/xnrg_08_sdm120.ino +++ b/tasmota/xnrg_08_sdm120.ino @@ -181,14 +181,14 @@ void Sdm120SnsInit(void) if (result) { if (2 == result) { ClaimSerial(); } } else { - energy_flg = ENERGY_NONE; + TasmotaGlobal.energy_driver = ENERGY_NONE; } } void Sdm120DrvInit(void) { if (PinUsed(GPIO_SDM120_RX) && PinUsed(GPIO_SDM120_TX)) { - energy_flg = XNRG_08; + TasmotaGlobal.energy_driver = XNRG_08; } } @@ -242,7 +242,7 @@ bool Xnrg08(uint8_t function) switch (function) { case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { SDM120Every250ms(); } + SDM120Every250ms(); break; case FUNC_JSON_APPEND: Sdm220Show(1); diff --git a/tasmota/xnrg_09_dds2382.ino b/tasmota/xnrg_09_dds2382.ino index 7acb36f05..3138bc444 100644 --- a/tasmota/xnrg_09_dds2382.ino +++ b/tasmota/xnrg_09_dds2382.ino @@ -96,14 +96,14 @@ void Dds2382SnsInit(void) if (result) { if (2 == result) { ClaimSerial(); } } else { - energy_flg = ENERGY_NONE; + TasmotaGlobal.energy_driver = ENERGY_NONE; } } void Dds2382DrvInit(void) { if (PinUsed(GPIO_DDS2382_RX) && PinUsed(GPIO_DDS2382_TX)) { - energy_flg = XNRG_09; + TasmotaGlobal.energy_driver = XNRG_09; } } @@ -117,7 +117,7 @@ bool Xnrg09(uint8_t function) switch (function) { case FUNC_ENERGY_EVERY_SECOND: - if (uptime > 4) { Dds2382EverySecond(); } + if (TasmotaGlobal.uptime > 4) { Dds2382EverySecond(); } break; case FUNC_INIT: Dds2382SnsInit(); diff --git a/tasmota/xnrg_10_sdm630.ino b/tasmota/xnrg_10_sdm630.ino index c1f36b110..145898f6f 100644 --- a/tasmota/xnrg_10_sdm630.ino +++ b/tasmota/xnrg_10_sdm630.ino @@ -221,14 +221,14 @@ void Sdm630SnsInit(void) Energy.phase_count = 3; Energy.frequency_common = true; // Use common frequency } else { - energy_flg = ENERGY_NONE; + TasmotaGlobal.energy_driver = ENERGY_NONE; } } void Sdm630DrvInit(void) { if (PinUsed(GPIO_SDM630_RX) && PinUsed(GPIO_SDM630_TX)) { - energy_flg = XNRG_10; + TasmotaGlobal.energy_driver = XNRG_10; } } @@ -242,7 +242,7 @@ bool Xnrg10(uint8_t function) switch (function) { case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { SDM630Every250ms(); } + SDM630Every250ms(); break; case FUNC_INIT: Sdm630SnsInit(); diff --git a/tasmota/xnrg_11_ddsu666.ino b/tasmota/xnrg_11_ddsu666.ino index f01ad50a5..8f453e766 100644 --- a/tasmota/xnrg_11_ddsu666.ino +++ b/tasmota/xnrg_11_ddsu666.ino @@ -138,14 +138,14 @@ void Ddsu666SnsInit(void) if (result) { if (2 == result) { ClaimSerial(); } } else { - energy_flg = ENERGY_NONE; + TasmotaGlobal.energy_driver = ENERGY_NONE; } } void Ddsu666DrvInit(void) { if (PinUsed(GPIO_DDSU666_RX) && PinUsed(GPIO_DDSU666_TX)) { - energy_flg = XNRG_11; + TasmotaGlobal.energy_driver = XNRG_11; } } @@ -159,7 +159,7 @@ bool Xnrg11(uint8_t function) switch (function) { case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { DDSU666Every250ms(); } + DDSU666Every250ms(); break; case FUNC_INIT: Ddsu666SnsInit(); diff --git a/tasmota/xnrg_12_solaxX1.ino b/tasmota/xnrg_12_solaxX1.ino index 513cf1317..be0c99958 100644 --- a/tasmota/xnrg_12_solaxX1.ino +++ b/tasmota/xnrg_12_solaxX1.ino @@ -414,14 +414,14 @@ void solaxX1SnsInit(void) if (solaxX1Serial->begin(SOLAXX1_SPEED)) { if (solaxX1Serial->hardwareSerial()) { ClaimSerial(); } } else { - energy_flg = ENERGY_NONE; + TasmotaGlobal.energy_driver = ENERGY_NONE; } } void solaxX1DrvInit(void) { if (PinUsed(GPIO_SOLAXX1_RX) && PinUsed(GPIO_SOLAXX1_TX)) { - energy_flg = XNRG_12; + TasmotaGlobal.energy_driver = XNRG_12; } } @@ -505,7 +505,7 @@ bool Xnrg12(uint8_t function) switch (function) { case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { solaxX1250MSecond(); } + solaxX1250MSecond(); break; case FUNC_JSON_APPEND: solaxX1Show(1); diff --git a/tasmota/xnrg_13_fif_le01mr.ino b/tasmota/xnrg_13_fif_le01mr.ino index f8d25e06f..a36e99b62 100644 --- a/tasmota/xnrg_13_fif_le01mr.ino +++ b/tasmota/xnrg_13_fif_le01mr.ino @@ -218,14 +218,14 @@ void FifLESnsInit(void) if (result) { if (2 == result) { ClaimSerial(); } } else { - energy_flg = ENERGY_NONE; + TasmotaGlobal.energy_driver = ENERGY_NONE; } } void FifLEDrvInit(void) { if (PinUsed(GPIO_LE01MR_RX) && PinUsed(GPIO_LE01MR_TX)) { - energy_flg = XNRG_13; + TasmotaGlobal.energy_driver = XNRG_13; } } @@ -269,9 +269,7 @@ bool Xnrg13(uint8_t function) switch (function) { case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { - FifLEEvery250ms(); - } + FifLEEvery250ms(); break; case FUNC_JSON_APPEND: FifLEShow(1); diff --git a/tasmota/xnrg_14_bl0940.ino b/tasmota/xnrg_14_bl0940.ino index 7b021106f..e2c4528e9 100644 --- a/tasmota/xnrg_14_bl0940.ino +++ b/tasmota/xnrg_14_bl0940.ino @@ -229,7 +229,7 @@ void Bl0940SnsInit(void) { } } else { - energy_flg = ENERGY_NONE; + TasmotaGlobal.energy_driver = ENERGY_NONE; } } @@ -237,7 +237,7 @@ void Bl0940DrvInit(void) { if (PinUsed(GPIO_BL0940_RX) && PinUsed(GPIO_TXD)) { Bl0940.rx_buffer = (uint8_t*)(malloc(BL0940_BUFFER_SIZE)); if (Bl0940.rx_buffer != nullptr) { - energy_flg = XNRG_14; + TasmotaGlobal.energy_driver = XNRG_14; } } } @@ -273,7 +273,7 @@ void Bl0940Show(bool json) { if (json) { ResponseAppend_P(JSON_SNS_TEMP, "BL0940", temperature); - if (0 == tele_period) { + if (0 == TasmotaGlobal.tele_period) { #ifdef USE_DOMOTICZ DomoticzSensor(DZ_TEMP, temperature); #endif // USE_DOMOTICZ diff --git a/tasmota/xnrg_15_teleinfo.ino b/tasmota/xnrg_15_teleinfo.ino index e87d899f8..db5f37b1d 100755 --- a/tasmota/xnrg_15_teleinfo.ino +++ b/tasmota/xnrg_15_teleinfo.ino @@ -20,73 +20,73 @@ #ifdef USE_ENERGY_SENSOR #ifdef USE_TELEINFO /*********************************************************************************************\ - * Teleinfo : French energy provider metering telemety data + * Teleinfo : French energy provider metering telemety data * Source: http://hallard.me/category/tinfo/ * * Denky ESP32 Teleinfo Template * {"NAME":"Denky (Teleinfo)","GPIO":[1,1,1,1,5664,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1376,1,1,0,0,0,0,1,5632,1,1,1,0,0,1],"FLAG":0,"BASE":1} - * + * * Denky (aka WifInfo) ESP8266 Teleinfo Template * {"NAME":"WifInfo v1.0a","GPIO":[17,255,255,255,6,5,255,255,7,210,255,255,255],"FLAG":15,"BASE":18} * {"NAME":"WifInfo","GPIO":[7,255,255,210,6,5,255,255,255,255,255,255,255],"FLAG":15,"BASE":18} - * + * \*********************************************************************************************/ -#define XNRG_15 15 +#define XNRG_15 15 #include "LibTeleinfo.h" #include -#define TINFO_READ_TIMEOUT 400 +#define TINFO_READ_TIMEOUT 400 // All contract type for legacy, standard mode has in clear text enum TInfoContrat{ - CONTRAT_BAS = 1, // BASE => Option Base. - CONTRAT_HC, // HC.. => Option Heures Creuses. - CONTRAT_EJP, // EJP. => Option EJP. + CONTRAT_BAS = 1, // BASE => Option Base. + CONTRAT_HC, // HC.. => Option Heures Creuses. + CONTRAT_EJP, // EJP. => Option EJP. CONTRAT_BBR, // BBRx => Option Tempo CONTRAT_END }; // contract displayed name for legacy, standard mode has in clear text -const char kContratName[] PROGMEM = +const char kContratName[] PROGMEM = "|Base|Heures Creuses|EJP|Bleu Blanc Rouge" ; // Received current contract value for legacy, standard mode has in clear text -const char kContratValue[] PROGMEM = +const char kContratValue[] PROGMEM = "|BASE|HC..|EJP.|BBR" ; // all tariff type for legacy, standard mode has in clear text enum TInfoTarif{ - TARIF_TH = 1, - TARIF_HC, TARIF_HP, + TARIF_TH = 1, + TARIF_HC, TARIF_HP, TARIF_HN, TARIF_PM, TARIF_CB, TARIF_CW, TARIF_CR, TARIF_PB, TARIF_PW, TARIF_PR, TARIF_END }; -// Received current tariff values +// Received current tariff values // for legacy, standard mode has in clear text -const char kTarifValue[] PROGMEM = - "|TH..|HC..|HP.." - "|HN..|PM.." - "|HCJB|HCJW|HCJR" - "|HPJB|HPJW|HPJR" +const char kTarifValue[] PROGMEM = + "|TH..|HC..|HP.." + "|HN..|PM.." + "|HCJB|HCJW|HCJR" + "|HPJB|HPJW|HPJR" ; // tariff displayed name (for legacy, standard mode has in clear text) -const char kTarifName[] PROGMEM = - "|Toutes|Creuses|Pleines" - "|Normales|Pointe Mobile" - "|Creuses Bleu|Creuses Blanc|Creuse Rouges" - "|Pleines Bleu|Pleines Blanc|Pleines Rouges" +const char kTarifName[] PROGMEM = + "|Toutes|Creuses|Pleines" + "|Normales|Pointe Mobile" + "|Creuses Bleu|Creuses Blanc|Creuse Rouges" + "|Pleines Bleu|Pleines Blanc|Pleines Rouges" ; // Label used to do some post processing and/or calculation enum TInfoLabel{ - LABEL_BASE = 1, + LABEL_BASE = 1, LABEL_ADCO, LABEL_ADSC, LABEL_HCHC, LABEL_HCHP, LABEL_EAST, LABEL_EASF01, LABEL_EASF02, LABEL_OPTARIF, LABEL_NGTF, LABEL_ISOUSC, LABEL_PREF, LABEL_PTEC, LABEL_LTARF, LABEL_NTARF, @@ -96,7 +96,7 @@ enum TInfoLabel{ LABEL_END }; -const char kLabel[] PROGMEM = +const char kLabel[] PROGMEM = "|BASE|ADCO|ADSC" "|HCHC|HCHP|EAST|EASF01|EASF02" "|OPTARIF|NGTF|ISOUSC|PREF|PTEC|LTARF|NTARF" @@ -117,7 +117,7 @@ int isousc; /*********************************************************************************************/ /* ====================================================================== -Function: getValueFromLabelIndex +Function: getValueFromLabelIndex Purpose : return label value from label index Input : label index to search for Output : value filled @@ -133,14 +133,14 @@ char * getValueFromLabelIndex(int labelIndex, char * value) } /* ====================================================================== -Function: ADPSCallback +Function: ADPSCallback Purpose : called by library when we detected a ADPS on any phased -Input : phase number +Input : phase number 0 for ADPS (monophase) 1 for ADIR1 triphase 2 for ADIR2 triphase 3 for ADIR3 triphase -Output : - +Output : - Comments: should have been initialised with a tinfo.attachADPSCallback(ADPSCallback()) ====================================================================== */ @@ -152,7 +152,7 @@ void ADPSCallback(uint8_t phase) } Response_P(PSTR("{")); - ResponseAppend_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":{\"ADPS\":%i}}"), serialNumber, phase ); + ResponseAppend_P(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), PSTR("{\"%s\":{\"ADPS\":%i}}"), serialNumber, phase ); ResponseJsonEnd(); // Publish adding ADCO serial number into the topic @@ -162,11 +162,11 @@ void ADPSCallback(uint8_t phase) } /* ====================================================================== -Function: DataCallback +Function: DataCallback Purpose : callback when we detected new or modified data received Input : linked list pointer on the concerned data current flags value -Output : - +Output : - Comments: - ====================================================================== */ void DataCallback(struct _ValueList * me, uint8_t flags) @@ -180,7 +180,7 @@ void DataCallback(struct _ValueList * me, uint8_t flags) // Find the label index for ( ilabel = 1 ; ilabel < LABEL_END ; ilabel++) { GetTextIndexed(labelName, sizeof(labelName), ilabel, kLabel); - if (!strcmp(labelName, me->name)) { + if (!strcmp(labelName, me->name)) { break; } } @@ -198,24 +198,24 @@ void DataCallback(struct _ValueList * me, uint8_t flags) // Find the tariff index for (tarif = TARIF_TH ; tarif < TARIF_END ; tarif++) { GetTextIndexed(tarif_value, sizeof(tarif_value), tarif-1, kTarifValue); - if (!strcmp(tarif_value, me->value)) { + if (!strcmp(tarif_value, me->value)) { break; } } AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Tarif changed, now '%s' (%d)"), me->value, tarif); - } + } // Current tariff (standard is in clear text in value) else if (ilabel == LABEL_LTARF) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Tarif name changed, now '%s'"), me->value); - } + } // Current tariff (standard index is is in clear text in value) else if (ilabel == LABEL_NTARF) { tarif = atoi(me->value); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Tarif index changed, now '%d'"), tarif); - } + } // Voltage V (not present on all Smart Meter) @@ -257,14 +257,14 @@ void DataCallback(struct _ValueList * me, uint8_t flags) // Heures creuses get heures pleines if (ilabel == LABEL_HCHC) { hc = atoi(me->value); - if ( getValueFromLabelIndex(LABEL_HCHP, value) ) { + if ( getValueFromLabelIndex(LABEL_HCHP, value) ) { hp = atoi(value); } - + // Heures pleines, get heures creuses } else if (ilabel == LABEL_HCHP) { hp = atoi(me->value); - if ( getValueFromLabelIndex(LABEL_HCHC, value) ) { + if ( getValueFromLabelIndex(LABEL_HCHC, value) ) { hc = atoi(value); } } @@ -272,17 +272,17 @@ void DataCallback(struct _ValueList * me, uint8_t flags) AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: HC:%u HP:%u Total:%u"), hc, hp, total); } - if (!Settings.flag4.teleinfo_rawdata) { - EnergyUpdateTotal(total/1000.0f, true); + if (!Settings.flag4.teleinfo_rawdata) { + EnergyUpdateTotal(total/1000.0f, true); } } - // Wh total index (standard) + // Wh total index (standard) else if ( ilabel == LABEL_EAST) { uint32_t total = atoi(me->value); - if (!Settings.flag4.teleinfo_rawdata) { - EnergyUpdateTotal(total/1000.0f, true); + if (!Settings.flag4.teleinfo_rawdata) { + EnergyUpdateTotal(total/1000.0f, true); } AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Total:%uWh"), total); } @@ -304,45 +304,45 @@ void DataCallback(struct _ValueList * me, uint8_t flags) // Find the contract index for (contrat = CONTRAT_BAS ; contrat < CONTRAT_END ; contrat++) { GetTextIndexed(contrat_value, sizeof(contrat_value), contrat, kContratValue); - if (!strcmp(contrat_value, me->value)) { + if (!strcmp(contrat_value, me->value)) { break; } } AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Contract changed, now '%s' (%d)"), me->value, contrat); - } + } // Contract subscribed (standard is in clear text in value) else if (ilabel == LABEL_NGTF) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: Contract changed, now '%s'"), me->value); - } + } // Contract subscribed (Power) else if (ilabel == LABEL_ISOUSC || ilabel == LABEL_PREF) { isousc = atoi( me->value); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: ISousc set to %d"), isousc); - } + } // Serial Number of device else if (ilabel == LABEL_ADCO || ilabel == LABEL_ADSC) { strcpy(serialNumber, me->value); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: %s set to %s"), me->name, serialNumber); - } + } } } - + } /* ====================================================================== -Function: responseDumpTInfo +Function: responseDumpTInfo Purpose : add teleinfo values into JSON response Input : 1st separator space if begining of JSON, else comma -Output : - +Output : - Comments: - ====================================================================== */ void ResponseAppendTInfo(char sep) @@ -383,17 +383,17 @@ void ResponseAppendTInfo(char sep) ResponseAppend_P( PSTR("%d"), atoi(me->value)); } - // Now JSON separator is needed + // Now JSON separator is needed sep =','; } } } /* ====================================================================== -Function: NewFrameCallback +Function: NewFrameCallback Purpose : callback when we received a complete Teleinfo frama Input : linked list pointer on the concerned data -Output : - +Output : - Comments: - ====================================================================== */ void NewFrameCallback(struct _ValueList * me) @@ -403,7 +403,7 @@ void NewFrameCallback(struct _ValueList * me) // send teleinfo full frame only if setup like that // see setOption108 - if (Settings.flag4.teleinfo_rawdata) { + if (Settings.flag4.teleinfo_rawdata) { Response_P(PSTR("{")); ResponseAppendTInfo(' '); ResponseJsonEnd(); @@ -414,24 +414,24 @@ void NewFrameCallback(struct _ValueList * me) } /* ====================================================================== -Function: TInfoDrvInit -Purpose : Tasmota core driver init +Function: TInfoDrvInit +Purpose : Tasmota core driver init Input : - -Output : - +Output : - Comments: - ====================================================================== */ void TInfoDrvInit(void) { if (PinUsed(GPIO_TELEINFO_RX)) { - energy_flg = XNRG_15; + TasmotaGlobal.energy_driver = XNRG_15; Energy.voltage_available = false; } } /* ====================================================================== -Function: TInfoInit -Purpose : Tasmota core device init +Function: TInfoInit +Purpose : Tasmota core device init Input : - -Output : - +Output : - Comments: - ====================================================================== */ void TInfoInit(void) @@ -439,16 +439,16 @@ void TInfoInit(void) int baudrate; // SetOption102 - Set Baud rate for Teleinfo serial communication (0 = 1200 or 1 = 9600) - if (Settings.flag4.teleinfo_baudrate) { - baudrate = 9600; + if (Settings.flag4.teleinfo_baudrate) { + baudrate = 9600; tinfo_mode = TINFO_MODE_STANDARD; } else { - baudrate = 1200; + baudrate = 1200; tinfo_mode = TINFO_MODE_HISTORIQUE; } AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TIC: inferface speed %d bps"),baudrate); - + if (PinUsed(GPIO_TELEINFO_RX)) { uint8_t rx_pin = Pin(GPIO_TELEINFO_RX); AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: RX on GPIO%d"), rx_pin); @@ -456,7 +456,7 @@ void TInfoInit(void) // Enable Teleinfo pin used, control it if (PinUsed(GPIO_TELEINFO_ENABLE)) { uint8_t en_pin = Pin(GPIO_TELEINFO_ENABLE); - pinMode(en_pin, OUTPUT); + pinMode(en_pin, OUTPUT); digitalWrite(en_pin, HIGH); AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: Enable with GPIO%d"), en_pin); } else { @@ -472,7 +472,7 @@ void TInfoInit(void) #endif // Trick here even using SERIAL_7E1 or TS_SERIAL_7E1 - // this is not working, need to call SetSerialConfig after + // this is not working, need to call SetSerialConfig after if (TInfoSerial->begin(baudrate)) { @@ -481,9 +481,9 @@ void TInfoInit(void) ClaimSerial(); // This is a hack, looks like begin does not take into account - // the TS_SERIAL_7E1 configuration so on ESP8266 this is + // the TS_SERIAL_7E1 configuration so on ESP8266 this is // working only on Serial RX pin (Hardware Serial) for now - + //SetSerialConfig(TS_SERIAL_7E1); //TInfoSerial->setTimeout(TINFO_READ_TIMEOUT); @@ -499,8 +499,8 @@ void TInfoInit(void) tinfo.init(tinfo_mode); // Attach needed callbacks tinfo.attachADPS(ADPSCallback); - tinfo.attachData(DataCallback); - tinfo.attachNewFrame(NewFrameCallback); + tinfo.attachData(DataCallback); + tinfo.attachNewFrame(NewFrameCallback); tinfo_found = true; AddLog_P2(LOG_LEVEL_INFO, PSTR("TIC: Ready")); @@ -509,10 +509,10 @@ void TInfoInit(void) } /* ====================================================================== -Function: TInfoEvery250ms +Function: TInfoEvery250ms Purpose : Tasmota callback executed every 250ms Input : - -Output : - +Output : - Comments: - ====================================================================== */ void TInfoEvery250ms(void) @@ -536,10 +536,10 @@ void TInfoEvery250ms(void) } /* ====================================================================== -Function: TInfoShow +Function: TInfoShow Purpose : Tasmota callback executed to send telemetry or WEB display Input : - -Output : - +Output : - Comments: - ====================================================================== */ #ifdef USE_WEBSERVER @@ -556,7 +556,7 @@ const char HTTP_ENERGY_PMAX_TELEINFO[] PROGMEM = "{s}" D_MAX_POWER "{m}%d" D_UN void TInfoShow(bool json) { - // Since it's an Energy device , current, voltage and power are + // Since it's an Energy device , current, voltage and power are // already present on the telemetry frame. No need to add here // Just add the raw label/values of the teleinfo frame if (json) @@ -567,7 +567,7 @@ void TInfoShow(bool json) } // add teleinfo full frame only if no teleinfo raw data setup - if (!Settings.flag4.teleinfo_rawdata) { + if (!Settings.flag4.teleinfo_rawdata) { ResponseAppendTInfo(','); } @@ -640,7 +640,7 @@ bool Xnrg15(uint8_t function) switch (function) { case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { TInfoEvery250ms(); } + TInfoEvery250ms(); break; case FUNC_JSON_APPEND: TInfoShow(1); diff --git a/tasmota/xnrg_16_iem3000.ino b/tasmota/xnrg_16_iem3000.ino index 807d142e3..6cf92ebc4 100644 --- a/tasmota/xnrg_16_iem3000.ino +++ b/tasmota/xnrg_16_iem3000.ino @@ -171,14 +171,14 @@ void Iem3000SnsInit(void) Energy.phase_count = 3; Energy.frequency_common = true; // Use common frequency } else { - energy_flg = ENERGY_NONE; + TasmotaGlobal.energy_driver = ENERGY_NONE; } } void Iem3000DrvInit(void) { if (PinUsed(GPIO_IEM3000_RX) && PinUsed(GPIO_IEM3000_TX)) { - energy_flg = XNRG_16; + TasmotaGlobal.energy_driver = XNRG_16; } } @@ -192,7 +192,7 @@ bool Xnrg16(uint8_t function) switch (function) { case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { IEM3000Every250ms(); } + IEM3000Every250ms(); break; case FUNC_INIT: Iem3000SnsInit(); diff --git a/tasmota/xnrg_17_ornowe517.ino b/tasmota/xnrg_17_ornowe517.ino index c62cccc4a..1e1ed928d 100644 --- a/tasmota/xnrg_17_ornowe517.ino +++ b/tasmota/xnrg_17_ornowe517.ino @@ -195,14 +195,14 @@ void We517SnsInit(void) Energy.phase_count = 3; Energy.frequency_common = true; // Use common frequency } else { - energy_flg = ENERGY_NONE; + TasmotaGlobal.energy_driver = ENERGY_NONE; } } void We517DrvInit(void) { if (PinUsed(GPIO_WE517_RX) && PinUsed(GPIO_WE517_TX)) { - energy_flg = XNRG_17; + TasmotaGlobal.energy_driver = XNRG_17; } } @@ -216,7 +216,7 @@ bool Xnrg17(uint8_t function) switch (function) { case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { WE517Every250ms(); } + WE517Every250ms(); break; case FUNC_INIT: We517SnsInit(); diff --git a/tasmota/xnrg_interface.ino b/tasmota/xnrg_interface.ino index 97ab5aec2..5d59dc4d5 100644 --- a/tasmota/xnrg_interface.ino +++ b/tasmota/xnrg_interface.ino @@ -165,13 +165,13 @@ bool XnrgCall(uint8_t function) if (FUNC_PRE_INIT == function) { for (uint32_t x = 0; x < xnrg_present; x++) { xnrg_func_ptr[x](function); - if (energy_flg) { + if (TasmotaGlobal.energy_driver) { xnrg_active = x; return true; // Stop further driver investigation } } } - else if (energy_flg) { + else if (TasmotaGlobal.energy_driver) { return xnrg_func_ptr[xnrg_active](function); } return false; diff --git a/tasmota/xsns_01_counter.ino b/tasmota/xsns_01_counter.ino index fd6b26ca5..234401ffe 100644 --- a/tasmota/xsns_01_counter.ino +++ b/tasmota/xsns_01_counter.ino @@ -210,12 +210,12 @@ void CounterShow(bool json) ResponseAppend_P(PSTR("%s\"C%d\":%s"), (header)?",":"", i +1, counter); header = true; #ifdef USE_DOMOTICZ - if ((0 == tele_period) && (1 == dsxflg)) { + if ((0 == TasmotaGlobal.tele_period) && (1 == dsxflg)) { DomoticzSensor(DZ_COUNT, RtcSettings.pulse_counter[i]); dsxflg++; } #endif // USE_DOMOTICZ - if ((0 == tele_period ) && (Settings.flag3.counter_reset_on_tele)) { + if ((0 == TasmotaGlobal.tele_period ) && (Settings.flag3.counter_reset_on_tele)) { RtcSettings.pulse_counter[i] = 0; } #ifdef USE_WEBSERVER diff --git a/tasmota/xsns_02_analog.ino b/tasmota/xsns_02_analog.ino index 8802fc12e..89281e467 100644 --- a/tasmota/xsns_02_analog.ino +++ b/tasmota/xsns_02_analog.ino @@ -414,7 +414,7 @@ void AdcShow(bool json) { if (json) { AdcShowContinuation(&jsonflg); ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "%s\":%s"), adc_idx, temperature); - if ((0 == tele_period) && (!domo_flag[ADC_TEMP])) { + if ((0 == TasmotaGlobal.tele_period) && (!domo_flag[ADC_TEMP])) { #ifdef USE_DOMOTICZ DomoticzSensor(DZ_TEMP, temperature); domo_flag[ADC_TEMP] = true; @@ -437,7 +437,7 @@ void AdcShow(bool json) { AdcShowContinuation(&jsonflg); ResponseAppend_P(PSTR("\"" D_JSON_ILLUMINANCE "%s\":%d"), adc_idx, adc_light); #ifdef USE_DOMOTICZ - if ((0 == tele_period) && (!domo_flag[ADC_LIGHT])) { + if ((0 == TasmotaGlobal.tele_period) && (!domo_flag[ADC_LIGHT])) { DomoticzSensor(DZ_ILLUMINANCE, adc_light); domo_flag[ADC_LIGHT] = true; } @@ -480,7 +480,7 @@ void AdcShow(bool json) { ResponseAppend_P(PSTR("\"CTEnergy%s\":{\"" D_JSON_ENERGY "\":%s,\"" D_JSON_POWERUSAGE "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"), adc_idx, energy_chr, power_chr, voltage_chr, current_chr); #ifdef USE_DOMOTICZ - if ((0 == tele_period) && (!domo_flag[ADC_CT_POWER])) { + if ((0 == TasmotaGlobal.tele_period) && (!domo_flag[ADC_CT_POWER])) { DomoticzSensor(DZ_POWER_ENERGY, power_chr); DomoticzSensor(DZ_VOLTAGE, voltage_chr); DomoticzSensor(DZ_CURRENT, current_chr); diff --git a/tasmota/xsns_04_snfsc.ino b/tasmota/xsns_04_snfsc.ino index 7652f8483..77c8dad12 100644 --- a/tasmota/xsns_04_snfsc.ino +++ b/tasmota/xsns_04_snfsc.ino @@ -120,7 +120,7 @@ void SonoffScShow(bool json) ResponseAppendTHD(t, h); ResponseAppend_P(PSTR(",\"" D_JSON_LIGHT "\":%d,\"" D_JSON_NOISE "\":%d,\"" D_JSON_AIRQUALITY "\":%d}"), sc_value[2], sc_value[3], sc_value[4]); #ifdef USE_DOMOTICZ - if (0 == tele_period) { + if (0 == TasmotaGlobal.tele_period) { DomoticzTempHumPressureSensor(t, h); DomoticzSensor(DZ_ILLUMINANCE, sc_value[2]); DomoticzSensor(DZ_COUNT, sc_value[3]); @@ -129,7 +129,7 @@ void SonoffScShow(bool json) #endif // USE_DOMOTICZ #ifdef USE_KNX - if (0 == tele_period) { + if (0 == TasmotaGlobal.tele_period) { KnxSensor(KNX_TEMPERATURE, t); KnxSensor(KNX_HUMIDITY, h); } @@ -152,7 +152,7 @@ bool Xsns04(uint8_t function) { bool result = false; - if (SONOFF_SC == my_module_type) { + if (SONOFF_SC == TasmotaGlobal.module_type) { switch (function) { case FUNC_JSON_APPEND: SonoffScShow(1); diff --git a/tasmota/xsns_05_ds18x20.ino b/tasmota/xsns_05_ds18x20.ino index e828c55d6..303cd1035 100644 --- a/tasmota/xsns_05_ds18x20.ino +++ b/tasmota/xsns_05_ds18x20.ino @@ -457,7 +457,7 @@ void Ds18x20EverySecond(void) if (now < w1_power_until) return; #endif - if (uptime & 1 + if (TasmotaGlobal.uptime & 1 #ifdef W1_PARASITE_POWER // if more than 1 sensor and only parasite power: convert every cycle || ds18x20_sensors >= 2 @@ -500,12 +500,12 @@ void Ds18x20Show(bool json) } ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ID "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), ds18x20_types, address, temperature); #ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == i)) { + if ((0 == TasmotaGlobal.tele_period) && (0 == i)) { DomoticzSensor(DZ_TEMP, temperature); } #endif // USE_DOMOTICZ #ifdef USE_KNX - if ((0 == tele_period) && (0 == i)) { + if ((0 == TasmotaGlobal.tele_period) && (0 == i)) { KnxSensor(KNX_TEMPERATURE, ds18x20_sensor[index].temperature); } #endif // USE_KNX diff --git a/tasmota/xsns_05_ds18x20_esp32.ino b/tasmota/xsns_05_ds18x20_esp32.ino index 1d622448c..e33c5f245 100644 --- a/tasmota/xsns_05_ds18x20_esp32.ino +++ b/tasmota/xsns_05_ds18x20_esp32.ino @@ -167,7 +167,7 @@ void Ds18x20EverySecond(void) { if (!ds18x20_sensors) { return; } - if (uptime & 1) { + if (TasmotaGlobal.uptime & 1) { // 2mS // Ds18x20Search(); // Check for changes in sensors number Ds18x20Convert(); // Start Conversion, takes up to one second @@ -203,12 +203,12 @@ void Ds18x20Show(bool json) ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ID "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), ds18x20_types, address, temperature); dsxflg++; #ifdef USE_DOMOTICZ - if ((0 == tele_period) && (1 == dsxflg)) { + if ((0 == TasmotaGlobal.tele_period) && (1 == dsxflg)) { DomoticzSensor(DZ_TEMP, temperature); } #endif // USE_DOMOTICZ #ifdef USE_KNX - if ((0 == tele_period) && (1 == dsxflg)) { + if ((0 == TasmotaGlobal.tele_period) && (1 == dsxflg)) { KnxSensor(KNX_TEMPERATURE, t); } #endif // USE_KNX diff --git a/tasmota/xsns_06_dht.ino b/tasmota/xsns_06_dht.ino index d2e47fe17..705e91cad 100644 --- a/tasmota/xsns_06_dht.ino +++ b/tasmota/xsns_06_dht.ino @@ -228,7 +228,7 @@ void DhtInit(void) void DhtEverySecond(void) { - if (uptime &1) { // Every 2 seconds + if (TasmotaGlobal.uptime &1) { // Every 2 seconds for (uint32_t sensor = 0; sensor < dht_sensors; sensor++) { // DHT11 and AM2301 25mS per sensor, SI7021 5mS per sensor if (!DhtRead(sensor)) { @@ -245,7 +245,7 @@ void DhtEverySecond(void) void DhtShow(bool json) { for (uint32_t i = 0; i < dht_sensors; i++) { - TempHumDewShow(json, ((0 == tele_period) && (0 == i)), Dht[i].stype, Dht[i].t, Dht[i].h); + TempHumDewShow(json, ((0 == TasmotaGlobal.tele_period) && (0 == i)), Dht[i].stype, Dht[i].t, Dht[i].h); } } diff --git a/tasmota/xsns_07_sht1x.ino b/tasmota/xsns_07_sht1x.ino index e58c5553f..16161a9a1 100644 --- a/tasmota/xsns_07_sht1x.ino +++ b/tasmota/xsns_07_sht1x.ino @@ -172,7 +172,7 @@ void ShtDetect(void) void ShtEverySecond(void) { - if (!(uptime %4)) { // Every 4 seconds + if (!(TasmotaGlobal.uptime %4)) { // Every 4 seconds // 344mS if (!ShtRead()) { AddLogMissed(sht_types, sht_valid); @@ -183,7 +183,7 @@ void ShtEverySecond(void) void ShtShow(bool json) { if (sht_valid) { - TempHumDewShow(json, (0 == tele_period), sht_types, sht_temperature, sht_humidity); + TempHumDewShow(json, (0 == TasmotaGlobal.tele_period), sht_types, sht_temperature, sht_humidity); } } diff --git a/tasmota/xsns_08_htu21.ino b/tasmota/xsns_08_htu21.ino index 1dc4d4fb1..d27d1bbec 100644 --- a/tasmota/xsns_08_htu21.ino +++ b/tasmota/xsns_08_htu21.ino @@ -236,7 +236,7 @@ void HtuDetect(void) void HtuEverySecond(void) { - if (uptime &1) { // Every 2 seconds + if (TasmotaGlobal.uptime &1) { // Every 2 seconds // HTU21: 68mS, SI70xx: 37mS if (!HtuRead()) { AddLogMissed(Htu.types, Htu.valid); @@ -247,7 +247,7 @@ void HtuEverySecond(void) void HtuShow(bool json) { if (Htu.valid) { - TempHumDewShow(json, (0 == tele_period), Htu.types, Htu.temperature, Htu.humidity); + TempHumDewShow(json, (0 == TasmotaGlobal.tele_period), Htu.types, Htu.temperature, Htu.humidity); } } diff --git a/tasmota/xsns_09_bmp.ino b/tasmota/xsns_09_bmp.ino index 8e1bd074a..d776fe793 100644 --- a/tasmota/xsns_09_bmp.ino +++ b/tasmota/xsns_09_bmp.ino @@ -517,11 +517,7 @@ void BmpShow(bool json) { for (uint32_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { if (bmp_sensors[bmp_idx].bmp_type) { - float bmp_sealevel = 0.0; - if (bmp_sensors[bmp_idx].bmp_pressure != 0.0) { - bmp_sealevel = (bmp_sensors[bmp_idx].bmp_pressure / FastPrecisePow(1.0 - ((float)Settings.altitude / 44330.0), 5.255)) - 21.6; - bmp_sealevel = ConvertPressure(bmp_sealevel); - } + float bmp_sealevel = ConvertPressureForSeaLevel(bmp_sensors[bmp_idx].bmp_pressure); float bmp_temperature = ConvertTemp(bmp_sensors[bmp_idx].bmp_temperature); float bmp_pressure = ConvertPressure(bmp_sensors[bmp_idx].bmp_pressure); @@ -571,7 +567,7 @@ void BmpShow(bool json) #endif // USE_BME680 #ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == bmp_idx)) { // We want the same first sensor to report to Domoticz in case a read is missed + if ((0 == TasmotaGlobal.tele_period) && (0 == bmp_idx)) { // We want the same first sensor to report to Domoticz in case a read is missed DomoticzTempHumPressureSensor(bmp_temperature, bmp_humidity, bmp_pressure); #ifdef USE_BME680 if (bmp_sensors[bmp_idx].bmp_model >= 3) { DomoticzSensor(DZ_AIRQUALITY, (uint32_t)bmp_sensors[bmp_idx].bmp_gas_resistance); } @@ -580,7 +576,7 @@ void BmpShow(bool json) #endif // USE_DOMOTICZ #ifdef USE_KNX - if (0 == tele_period) { + if (0 == TasmotaGlobal.tele_period) { KnxSensor(KNX_TEMPERATURE, bmp_temperature); KnxSensor(KNX_HUMIDITY, bmp_humidity); } diff --git a/tasmota/xsns_10_bh1750.ino b/tasmota/xsns_10_bh1750.ino index 2c3c801a7..dfd9d013b 100644 --- a/tasmota/xsns_10_bh1750.ino +++ b/tasmota/xsns_10_bh1750.ino @@ -176,7 +176,7 @@ void Bh1750Show(bool json) { if (json) { ResponseAppend_P(JSON_SNS_ILLUMINANCE, sensor_name, Bh1750_sensors[sensor_index].illuminance); #ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == sensor_index)) { + if ((0 == TasmotaGlobal.tele_period) && (0 == sensor_index)) { DomoticzSensor(DZ_ILLUMINANCE, Bh1750_sensors[sensor_index].illuminance); } #endif // USE_DOMOTICZ diff --git a/tasmota/xsns_11_veml6070.ino b/tasmota/xsns_11_veml6070.ino index 600364503..c97e68c97 100644 --- a/tasmota/xsns_11_veml6070.ino +++ b/tasmota/xsns_11_veml6070.ino @@ -277,7 +277,7 @@ void Veml6070Show(bool json) veml6070_name, str_uvrisk, str_uvrisk_text, str_uvpower); #endif // USE_VEML6070_SHOW_RAW #ifdef USE_DOMOTICZ - if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, uvlevel); } + if (0 == TasmotaGlobal.tele_period) { DomoticzSensor(DZ_ILLUMINANCE, uvlevel); } #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { diff --git a/tasmota/xsns_13_ina219.ino b/tasmota/xsns_13_ina219.ino index 854cca5cd..c0c8f87d4 100644 --- a/tasmota/xsns_13_ina219.ino +++ b/tasmota/xsns_13_ina219.ino @@ -233,7 +233,7 @@ bool Ina219CommandSensor(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 255)) { Settings.ina219_mode = XdrvMailbox.payload; - restart_flag = 2; + TasmotaGlobal.restart_flag = 2; } Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_13, Settings.ina219_mode); @@ -297,7 +297,7 @@ void Ina219Show(bool json) ResponseAppend_P(PSTR(",\"%s\":{\"Id\":%02x,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), name, ina219_addresses[i], voltage, current, power); #ifdef USE_DOMOTICZ - if (0 == tele_period) { + if (0 == TasmotaGlobal.tele_period) { DomoticzSensor(DZ_VOLTAGE, voltage); DomoticzSensor(DZ_CURRENT, current); } diff --git a/tasmota/xsns_14_sht3x.ino b/tasmota/xsns_14_sht3x.ino index ca3bcf78e..bb98cc5b0 100644 --- a/tasmota/xsns_14_sht3x.ino +++ b/tasmota/xsns_14_sht3x.ino @@ -100,7 +100,7 @@ void Sht3xShow(bool json) if (Sht3xRead(t, h, sht3x_sensors[i].address)) { char types[11]; snprintf_P(types, sizeof(types), PSTR("%s%c0x%02X"), sht3x_sensors[i].types, IndexSeparator(), sht3x_sensors[i].address); // "SHT3X-0xXX" - TempHumDewShow(json, ((0 == tele_period) && (0 == i)), types, t, h); + TempHumDewShow(json, ((0 == TasmotaGlobal.tele_period) && (0 == i)), types, t, h); } } } diff --git a/tasmota/xsns_15_mhz19.ino b/tasmota/xsns_15_mhz19.ino index bc0ee8904..8fe450f87 100644 --- a/tasmota/xsns_15_mhz19.ino +++ b/tasmota/xsns_15_mhz19.ino @@ -346,7 +346,7 @@ void MhzShow(bool json) if (json) { ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_MODEL "\":\"%s\",\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s}"), types, model, mhz_last_ppm, temperature); #ifdef USE_DOMOTICZ - if (0 == tele_period) { + if (0 == TasmotaGlobal.tele_period) { DomoticzSensor(DZ_AIRQUALITY, mhz_last_ppm); DomoticzSensor(DZ_TEMP, temperature); } diff --git a/tasmota/xsns_16_tsl2561.ino b/tasmota/xsns_16_tsl2561.ino index 573fc3b93..23f1b33cf 100644 --- a/tasmota/xsns_16_tsl2561.ino +++ b/tasmota/xsns_16_tsl2561.ino @@ -82,7 +82,7 @@ void Tsl2561Detect(void) void Tsl2561EverySecond(void) { - if (!(uptime %2)) { // Every 2 seconds + if (!(TasmotaGlobal.uptime %2)) { // Every 2 seconds // ?mS - 4Sec if (!Tsl2561Read()) { AddLogMissed(tsl2561_types, tsl2561_valid); @@ -102,7 +102,7 @@ void Tsl2561Show(bool json) ResponseAppend_P(PSTR(",\"TSL2561\":{\"" D_JSON_ILLUMINANCE "\":%u.%03u,\"IR\":%u,\"Broadband\":%u}"), tsl2561_milliLux / 1000, tsl2561_milliLux % 1000, tsl2561_ir, tsl2561_full); #ifdef USE_DOMOTICZ - if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, (tsl2561_milliLux + 500) / 1000); } + if (0 == TasmotaGlobal.tele_period) { DomoticzSensor(DZ_ILLUMINANCE, (tsl2561_milliLux + 500) / 1000); } #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { diff --git a/tasmota/xsns_17_senseair.ino b/tasmota/xsns_17_senseair.ino index 90ba979bb..eb6d3030f 100644 --- a/tasmota/xsns_17_senseair.ino +++ b/tasmota/xsns_17_senseair.ino @@ -154,7 +154,7 @@ void SenseairShow(bool json) } ResponseJsonEnd(); #ifdef USE_DOMOTICZ - if (0 == tele_period) { + if (0 == TasmotaGlobal.tele_period) { DomoticzSensor(DZ_AIRQUALITY, senseair_co2); } #endif // USE_DOMOTICZ diff --git a/tasmota/xsns_18_pms5003.ino b/tasmota/xsns_18_pms5003.ino index d54527ddc..a203b6846 100644 --- a/tasmota/xsns_18_pms5003.ino +++ b/tasmota/xsns_18_pms5003.ino @@ -295,7 +295,7 @@ void PmsShow(bool json) pms_data.particles_03um, pms_data.particles_05um, pms_data.particles_10um, pms_data.particles_25um, pms_data.particles_50um, pms_data.particles_100um); #endif // PMS_MODEL_PMS3003 #ifdef USE_DOMOTICZ - if (0 == tele_period) { + if (0 == TasmotaGlobal.tele_period) { DomoticzSensor(DZ_COUNT, pms_data.pm10_env); // PM1 DomoticzSensor(DZ_VOLTAGE, pms_data.pm25_env); // PM2.5 DomoticzSensor(DZ_CURRENT, pms_data.pm100_env); // PM10 diff --git a/tasmota/xsns_20_novasds.ino b/tasmota/xsns_20_novasds.ino index ffaee14bc..3834ff984 100644 --- a/tasmota/xsns_20_novasds.ino +++ b/tasmota/xsns_20_novasds.ino @@ -162,17 +162,17 @@ void NovaSdsSecond(void) // Every second else cont_mode = 0; - if(tele_period == Settings.tele_period - Settings.novasds_startingoffset && !cont_mode) + if(TasmotaGlobal.tele_period == Settings.tele_period - Settings.novasds_startingoffset && !cont_mode) { //lets start fan and laser NovaSdsCommand(NOVA_SDS_SLEEP_AND_WORK, NOVA_SDS_SET_MODE, NOVA_SDS_WORK, NOVA_SDS_DEVICE_ID, nullptr); } - if(tele_period >= Settings.tele_period-5 && tele_period <= Settings.tele_period-2) + if(TasmotaGlobal.tele_period >= Settings.tele_period-5 && TasmotaGlobal.tele_period <= Settings.tele_period-2) { //we are doing 4 measurements here if(!(NovaSdsReadData())) novasds_valid=0; pm100_sum += novasds_data.pm100; pm25_sum += novasds_data.pm25; } - if(tele_period == Settings.tele_period-1) + if(TasmotaGlobal.tele_period == Settings.tele_period-1) { //calculate the average of 4 measuremens novasds_data.pm100 = pm100_sum >> 2; novasds_data.pm25 = pm25_sum >> 2; @@ -232,7 +232,7 @@ void NovaSdsShow(bool json) if (json) { ResponseAppend_P(PSTR(",\"SDS0X1\":{\"PM2.5\":%s,\"PM10\":%s}"), pm2_5, pm10); #ifdef USE_DOMOTICZ - if (0 == tele_period) { + if (0 == TasmotaGlobal.tele_period) { DomoticzSensor(DZ_VOLTAGE, pm2_5); // PM2.5 DomoticzSensor(DZ_CURRENT, pm10); // PM10 } diff --git a/tasmota/xsns_21_sgp30.ino b/tasmota/xsns_21_sgp30.ino index 6f52f14a4..bac02976c 100644 --- a/tasmota/xsns_21_sgp30.ino +++ b/tasmota/xsns_21_sgp30.ino @@ -83,15 +83,15 @@ void Sgp30Update(void) // Perform every second to ensure proper operation of th if (!sgp.IAQmeasure()) { return; // Measurement failed } - if (global_update && (global_humidity > 0) && !isnan(global_temperature_celsius)) { + if (TasmotaGlobal.global_update && (TasmotaGlobal.humidity > 0) && !isnan(TasmotaGlobal.temperature_celsius)) { // abs hum in mg/m3 - sgp30_abshum = sgp30_AbsoluteHumidity(global_temperature_celsius, global_humidity); + sgp30_abshum = sgp30_AbsoluteHumidity(TasmotaGlobal.temperature_celsius, TasmotaGlobal.humidity); sgp.setHumidity(sgp30_abshum*1000); } sgp30_ready = true; // these should normally be stored permanently and used for fast restart - if (!(uptime%SAVE_PERIOD)) { + if (!(TasmotaGlobal.uptime%SAVE_PERIOD)) { // store settings every N seconds uint16_t TVOC_base; uint16_t eCO2_base; @@ -115,23 +115,23 @@ void Sgp30Show(bool json) if (sgp30_ready) { char abs_hum[33]; - if (global_update && (global_humidity > 0) && !isnan(global_temperature_celsius)) { + if (TasmotaGlobal.global_update && (TasmotaGlobal.humidity > 0) && !isnan(TasmotaGlobal.temperature_celsius)) { // has humidity + temperature dtostrfd(sgp30_abshum,4,abs_hum); } if (json) { ResponseAppend_P(PSTR(",\"SGP30\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d"), sgp.eCO2, sgp.TVOC); - if (global_update && global_humidity>0 && !isnan(global_temperature_celsius)) { + if (TasmotaGlobal.global_update && TasmotaGlobal.humidity>0 && !isnan(TasmotaGlobal.temperature_celsius)) { ResponseAppend_P(PSTR(",\"" D_JSON_AHUM "\":%s"),abs_hum); } ResponseJsonEnd(); #ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, sgp.eCO2); + if (0 == TasmotaGlobal.tele_period) DomoticzSensor(DZ_AIRQUALITY, sgp.eCO2); #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_SNS_SGP30, sgp.eCO2, sgp.TVOC); - if (global_update) { + if (TasmotaGlobal.global_update) { WSContentSend_PD(HTTP_SNS_AHUM, abs_hum); } #endif diff --git a/tasmota/xsns_22_sr04.ino b/tasmota/xsns_22_sr04.ino index 187a67c3f..70f0308f9 100644 --- a/tasmota/xsns_22_sr04.ino +++ b/tasmota/xsns_22_sr04.ino @@ -170,7 +170,7 @@ void Sr04Show(bool json) if(json) { ResponseAppend_P(PSTR(",\"SR04\":{\"" D_JSON_DISTANCE "\":%s}"), distance_chr); #ifdef USE_DOMOTICZ - if (0 == tele_period) { + if (0 == TasmotaGlobal.tele_period) { DomoticzSensor(DZ_COUNT, distance_chr); // Send distance as Domoticz Counter value } #endif // USE_DOMOTICZ diff --git a/tasmota/xsns_24_si1145.ino b/tasmota/xsns_24_si1145.ino index ad89cad3b..e7d4e8577 100644 --- a/tasmota/xsns_24_si1145.ino +++ b/tasmota/xsns_24_si1145.ino @@ -355,7 +355,7 @@ void Si1145Show(bool json) ResponseAppend_P(PSTR(",\"SI1145\":{\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_INFRARED "\":%d,\"" D_JSON_UV_INDEX "\":%d.%d}"), si1145_visible, si1145_infrared, si1145_uvindex /100, si1145_uvindex %100); #ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_ILLUMINANCE, si1145_visible); + if (0 == TasmotaGlobal.tele_period) DomoticzSensor(DZ_ILLUMINANCE, si1145_visible); #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { diff --git a/tasmota/xsns_26_lm75ad.ino b/tasmota/xsns_26_lm75ad.ino index d5073f759..2a938e6e6 100644 --- a/tasmota/xsns_26_lm75ad.ino +++ b/tasmota/xsns_26_lm75ad.ino @@ -91,7 +91,7 @@ void LM75ADShow(bool json) if (json) { ResponseAppend_P(JSON_SNS_TEMP, "LM75AD", temperature); #ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_TEMP, temperature); + if (0 == TasmotaGlobal.tele_period) DomoticzSensor(DZ_TEMP, temperature); #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { diff --git a/tasmota/xsns_27_apds9960.ino b/tasmota/xsns_27_apds9960.ino index f8857ff0b..e9ec54bef 100644 --- a/tasmota/xsns_27_apds9960.ino +++ b/tasmota/xsns_27_apds9960.ino @@ -379,7 +379,7 @@ void calculateColorTemperature(void) { return; } -#endif // USE_APDS9960_COLOR +#endif // USE_APDS9960_COLOR /******************************************************************************\ * Getters and setters for register values @@ -1787,7 +1787,7 @@ void APDS9960_loop(void) { enableGestureSensor(); APDS9960_overload = false; Response_P(PSTR("{\"Gesture\":\"On\"}")); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); // only after the long break we report, that we are online again + MqttPublishPrefixTopic_P(RESULT_OR_TELE, TasmotaGlobal.mqtt_data); // only after the long break we report, that we are online again gesture_mode = 1; } @@ -1799,7 +1799,7 @@ void APDS9960_loop(void) { disableGestureSensor(); recovery_loop_counter = APDS9960_LONG_RECOVERY; // long pause after overload/long press - number of stateloops Response_P(PSTR("{\"Gesture\":\"Off\"}")); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, TasmotaGlobal.mqtt_data); gesture_mode = 0; } } diff --git a/tasmota/xsns_29_mcp230xx.ino b/tasmota/xsns_29_mcp230xx.ino index b12eceeff..b96fd272b 100644 --- a/tasmota/xsns_29_mcp230xx.ino +++ b/tasmota/xsns_29_mcp230xx.ino @@ -196,7 +196,7 @@ void MCP230xx_ApplySettings(void) I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPIO+mcp230xx_port, reg_portpins); #endif // USE_MCP230xx_OUTPUT } - devices_present -= mcp230xx_oldoutpincount; + TasmotaGlobal.devices_present -= mcp230xx_oldoutpincount; mcp230xx_oldoutpincount = 0; for (uint32_t idx=0;idx= 5) { @@ -205,7 +205,7 @@ void MCP230xx_ApplySettings(void) } int_millis[idx]=millis(); } - devices_present += mcp230xx_oldoutpincount; + TasmotaGlobal.devices_present += mcp230xx_oldoutpincount; mcp230xx_int_en = int_en; MCP230xx_CheckForIntCounter(); // update register on whether or not we should be counting interrupts MCP230xx_CheckForIntRetainer(); // update register on whether or not we should be retaining interrupt events for teleperiod @@ -649,7 +649,7 @@ bool MCP230xx_Command(void) for (relay_no = 0; relay_no < mcp230xx_pincount ; relay_no ++) { if ( mcp230xx_outpinmapping[relay_no] == pin) break; } - relay_no = devices_present - mcp230xx_oldoutpincount + relay_no +1; + relay_no = TasmotaGlobal.devices_present - mcp230xx_oldoutpincount + relay_no +1; if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "ON")) || (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "1"))) { ExecuteCommandPower(relay_no, 1, SRC_IGNORE); return serviced; @@ -797,8 +797,8 @@ void MCP230xx_Interrupt_Retain_Report(void) { #ifdef USE_MCP230xx_OUTPUT void MCP230xx_SwitchRelay() { - for (uint32_t i = devices_present - mcp230xx_oldoutpincount; i < devices_present; i++) { - uint8_t pin = mcp230xx_outpinmapping[i - (devices_present - mcp230xx_oldoutpincount)]; + for (uint32_t i = TasmotaGlobal.devices_present - mcp230xx_oldoutpincount; i < TasmotaGlobal.devices_present; i++) { + uint8_t pin = mcp230xx_outpinmapping[i - (TasmotaGlobal.devices_present - mcp230xx_oldoutpincount)]; uint8_t pincmd = Settings.mcp230xx_config[pin].pinmode - 5; uint8_t relay_state = bitRead(XdrvMailbox.index, i); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MCP: relay %d pin_no %d state %d"), i,pin, relay_state); @@ -845,7 +845,7 @@ bool Xsns29(uint8_t function) MCP230xx_Interrupt_Counter_Report(); } } - if (tele_period == 0) { + if (TasmotaGlobal.tele_period == 0) { if (mcp230xx_int_retainer_en) { // We have pins configured for interrupt retain reporting MCP230xx_Interrupt_Retain_Report(); } diff --git a/tasmota/xsns_30_mpr121.ino b/tasmota/xsns_30_mpr121.ino index 9522f5383..6fb12cd19 100644 --- a/tasmota/xsns_30_mpr121.ino +++ b/tasmota/xsns_30_mpr121.ino @@ -362,7 +362,7 @@ void Mpr121Show(struct mpr121 *pS, uint8_t function) if ((FUNC_EVERY_50_MSECOND == function) && (BITC(i, j) != BITP(i, j))) { Response_P(PSTR("{\"MPR121%c\":{\"Button%i\":%i}}"), pS->id[i], j, BITC(i, j)); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, TasmotaGlobal.mqtt_data); } // Add buttons to web string #ifdef USE_WEBSERVER diff --git a/tasmota/xsns_31_ccs811.ino b/tasmota/xsns_31_ccs811.ino index 71bac8240..c11fd79d4 100644 --- a/tasmota/xsns_31_ccs811.ino +++ b/tasmota/xsns_31_ccs811.ino @@ -65,8 +65,8 @@ void CCS811Update(void) // Perform every n second TVOC = ccs.getTVOC(); eCO2 = ccs.geteCO2(); CCS811_ready = 1; - if (global_update && (global_humidity > 0) && !isnan(global_temperature_celsius)) { - ccs.setEnvironmentalData((uint8_t)global_humidity, global_temperature_celsius); + if (TasmotaGlobal.global_update && (TasmotaGlobal.humidity > 0) && !isnan(TasmotaGlobal.temperature_celsius)) { + ccs.setEnvironmentalData((uint8_t)TasmotaGlobal.humidity, TasmotaGlobal.temperature_celsius); } ecnt = 0; } @@ -91,7 +91,7 @@ void CCS811Show(bool json) if (json) { ResponseAppend_P(PSTR(",\"CCS811\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d}"), eCO2,TVOC); #ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, eCO2); + if (0 == TasmotaGlobal.tele_period) DomoticzSensor(DZ_AIRQUALITY, eCO2); #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { diff --git a/tasmota/xsns_32_mpu6050.ino b/tasmota/xsns_32_mpu6050.ino index c1f792ae7..e02933798 100644 --- a/tasmota/xsns_32_mpu6050.ino +++ b/tasmota/xsns_32_mpu6050.ino @@ -262,7 +262,7 @@ bool Xsns32(uint8_t function) else if (MPU_6050_found) { switch (function) { case FUNC_EVERY_SECOND: - if (tele_period == Settings.tele_period -3) { + if (TasmotaGlobal.tele_period == Settings.tele_period -3) { MPU_6050PerformReading(); } break; diff --git a/tasmota/xsns_33_ds3231.ino b/tasmota/xsns_33_ds3231.ino index 09814bcf0..02c065e8b 100644 --- a/tasmota/xsns_33_ds3231.ino +++ b/tasmota/xsns_33_ds3231.ino @@ -131,7 +131,7 @@ void DS3231EverySecond(void) { TIME_T tmpTime; if (!ds3231ReadStatus && Rtc.utc_time < START_VALID_TIME ) { // We still did not sync with NTP (time not valid) , so, read time from DS3231 - ntp_force_sync = true; //force to sync with ntp + TasmotaGlobal.ntp_force_sync = true; //force to sync with ntp Rtc.utc_time = ReadFromDS3231(); //we read UTC TIME from DS3231 // from this line, we just copy the function from "void RtcSecond()" at the support.ino ,line 2143 and above // We need it to set rules etc. @@ -145,9 +145,9 @@ void DS3231EverySecond(void) AddLog_P2(LOG_LEVEL_INFO, PSTR("Set time from DS3231 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 - rules_flag.time_init = 1; + TasmotaGlobal.rules_flag.time_init = 1; } else { - rules_flag.time_set = 1; + TasmotaGlobal.rules_flag.time_set = 1; } } else if (!ds3231WriteStatus && Rtc.utc_time > START_VALID_TIME && abs(Rtc.utc_time - ReadFromDS3231()) > 60) {//if time is valid and is drift from RTC in more that 60 second diff --git a/tasmota/xsns_34_hx711.ino b/tasmota/xsns_34_hx711.ino index a29eceb2d..def1276a9 100644 --- a/tasmota/xsns_34_hx711.ino +++ b/tasmota/xsns_34_hx711.ino @@ -395,7 +395,7 @@ void HxEvery100mSecond(void) Hx.weight_changed = true; } else if (Hx.weight_changed && (Hx.weight == Hx.weight_diff)) { - mqtt_data[0] = '\0'; + ResponseClear(); ResponseAppendTime(); HxShow(true); ResponseJsonEnd(); diff --git a/tasmota/xsns_35_tx20.ino b/tasmota/xsns_35_tx20.ino index 3ab33e402..474e43cae 100644 --- a/tasmota/xsns_35_tx20.ino +++ b/tasmota/xsns_35_tx20.ino @@ -238,7 +238,7 @@ void ICACHE_RAM_ATTR TX2xStartRead(void) #else if ((chk == tx2x_sd) && (tx2x_sb==tx2x_se) && (tx2x_sc==tx2x_sf) && (tx2x_sc < 511)) { #endif - tx2x_last_available = uptime; + tx2x_last_available = TasmotaGlobal.uptime; // Wind speed spec: 0 to 180 km/h (0 to 50 m/s) tx2x_wind_speed = tx2x_sc; tx2x_wind_direction = tx2x_sb; @@ -264,7 +264,7 @@ void ICACHE_RAM_ATTR TX2xStartRead(void) bool Tx2xAvailable(void) { - return ((uptime - tx2x_last_available) < TX2X_TIMEOUT); + return ((TasmotaGlobal.uptime - tx2x_last_available) < TX2X_TIMEOUT); } #ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS @@ -306,7 +306,7 @@ void Tx2xCheckSampleCount(void) void Tx2xResetStat(void) { DEBUG_SENSOR_LOG(PSTR(D_TX2x_NAME ": reset statistics")); - tx2x_last_uptime = uptime; + tx2x_last_uptime = TasmotaGlobal.uptime; Tx2xResetStatData(); } @@ -330,13 +330,13 @@ void Tx2xRead(void) // // note: TX23 speed calculation is unstable when conversion starts // less than 2 seconds after last request - if ((uptime % TX23_READ_INTERVAL)==0) { + if ((TasmotaGlobal.uptime % TX23_READ_INTERVAL)==0) { // TX23 start transmission by pulling down TxD line for at minimum 500ms // so we pull TxD signal to low every 3 seconds tx23_stage = 0; pinMode(Pin(GPIO_TX2X_TXD_BLACK), OUTPUT); digitalWrite(Pin(GPIO_TX2X_TXD_BLACK), LOW); - } else if ((uptime % TX23_READ_INTERVAL)==1) { + } else if ((TasmotaGlobal.uptime % TX23_READ_INTERVAL)==1) { // after pulling down TxD: pull-up TxD every x+1 seconds // to trigger TX23 start transmission tx23_stage = 1; // first rising signal is invalid @@ -419,7 +419,7 @@ void Tx2xRead(void) char siny[FLOATSZ]; dtostrfd(tx2x_wind_direction_avg_y, 1, siny); DEBUG_SENSOR_LOG(PSTR(D_TX2x_NAME ": dir stat - counter=%ld, actint=%ld, avgint=%ld, avg=%s (cosx=%s, siny=%s), min %d, max %d"), - (uptime-tx2x_last_uptime), + (TasmotaGlobal.uptime-tx2x_last_uptime), tx2x_wind_direction, tx2x_wind_direction_avg_int, diravg, @@ -443,7 +443,7 @@ void Tx2xRead(void) #ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS Tx2xCheckSampleCount(); - if (0==Settings.tele_period && (uptime-tx2x_last_uptime)>=tx2x_avg_samples) { + if (0==Settings.tele_period && (TasmotaGlobal.uptime-tx2x_last_uptime)>=tx2x_avg_samples) { Tx2xResetStat(); } #endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS diff --git a/tasmota/xsns_37_rfsensor.ino b/tasmota/xsns_37_rfsensor.ino index 53945f2bb..55895a29d 100644 --- a/tasmota/xsns_37_rfsensor.ino +++ b/tasmota/xsns_37_rfsensor.ino @@ -279,7 +279,7 @@ void RfSnsTheoV2Show(bool json) ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_VOLTAGE "\":%s}"), sensor, temperature, rfsns_theo_v2_t1[i].lux, voltage); #ifdef USE_DOMOTICZ - if ((0 == tele_period) && !sensor_once) { + if ((0 == TasmotaGlobal.tele_period) && !sensor_once) { DomoticzSensor(DZ_TEMP, temperature); DomoticzSensor(DZ_ILLUMINANCE, rfsns_theo_v2_t1[i].lux); sensor_once = true; @@ -317,7 +317,7 @@ void RfSnsTheoV2Show(bool json) ResponseAppendTHD(temp, humi); ResponseAppend_P(PSTR(",\"" D_JSON_VOLTAGE "\":%s}"), voltage); - if ((0 == tele_period) && !sensor_once) { + if ((0 == TasmotaGlobal.tele_period) && !sensor_once) { #ifdef USE_DOMOTICZ DomoticzTempHumPressureSensor(temp, humi); // #endif // USE_DOMOTICZ @@ -573,7 +573,7 @@ void RfSnsAlectoV2Show(bool json) ResponseAppendTHD(temp, humi); ResponseAppend_P(PSTR(",\"Rain\":%s,\"Wind\":%s,\"Gust\":%s%s}"), rain, wind, gust, (rfsns_alecto_v2->type) ? direction : ""); - if (0 == tele_period) { + if (0 == TasmotaGlobal.tele_period) { #ifdef USE_DOMOTICZ // Use a rules to send data to Domoticz where also a local BMP280 is connected: // on tele-alectov2#temperature do var1 %value% endon on tele-alectov2#humidity do var2 %value% endon on tele-bmp280#pressure do publish domoticz/in {"idx":68,"svalue":"%var1%;%var2%;0;%value%;0"} endon @@ -665,7 +665,7 @@ bool Xsns37(uint8_t function) RfSnsAnalyzeRawSignal(); } } - ssleep = 0; + TasmotaGlobal.sleep = 0; break; case FUNC_EVERY_SECOND: RfSnsEverySecond(); diff --git a/tasmota/xsns_38_az7798.ino b/tasmota/xsns_38_az7798.ino index 352f59389..1b5ba7f5f 100644 --- a/tasmota/xsns_38_az7798.ino +++ b/tasmota/xsns_38_az7798.ino @@ -283,7 +283,7 @@ void AzShow(bool json) ResponseAppendTHD(az_temperature, az_humidity); ResponseJsonEnd(); #ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, az_co2); + if (0 == TasmotaGlobal.tele_period) DomoticzSensor(DZ_AIRQUALITY, az_co2); #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { diff --git a/tasmota/xsns_39_max31855.ino b/tasmota/xsns_39_max31855.ino index fcdb69094..a6e592c21 100644 --- a/tasmota/xsns_39_max31855.ino +++ b/tasmota/xsns_39_max31855.ino @@ -151,12 +151,12 @@ void MAX31855_Show(bool Json) { ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_PROBETEMPERATURE "\":%s,\"" D_JSON_REFERENCETEMPERATURE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ sensor_name, probetemp, referencetemp, MAX31855_Result.ErrorCode); #ifdef USE_DOMOTICZ - if (0 == tele_period) { + if (0 == TasmotaGlobal.tele_period) { DomoticzSensor(DZ_TEMP, probetemp); } #endif // USE_DOMOTICZ #ifdef USE_KNX - if (0 == tele_period) { + if (0 == TasmotaGlobal.tele_period) { KnxSensor(KNX_TEMPERATURE, MAX31855_Result.ProbeTemperature); } #endif // USE_KNX diff --git a/tasmota/xsns_41_max44009.ino b/tasmota/xsns_41_max44009.ino index 231cc961a..471840050 100644 --- a/tasmota/xsns_41_max44009.ino +++ b/tasmota/xsns_41_max44009.ino @@ -122,7 +122,7 @@ void Max4409Show(bool json) if (json) { ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ILLUMINANCE "\":%s}"), max44009_types, illum_str); #ifdef USE_DOMOTICZ - if (0 == tele_period) { + if (0 == TasmotaGlobal.tele_period) { DomoticzSensor(DZ_ILLUMINANCE, illum_str); } #endif // USE_DOMOTICZ diff --git a/tasmota/xsns_42_scd30.ino b/tasmota/xsns_42_scd30.ino index 4c73d3b15..50e3968ec 100644 --- a/tasmota/xsns_42_scd30.ino +++ b/tasmota/xsns_42_scd30.ino @@ -372,7 +372,7 @@ void Scd30Show(bool json) ResponseAppendTHD(t, h); ResponseJsonEnd(); #ifdef USE_DOMOTICZ - if (0 == tele_period) { + if (0 == TasmotaGlobal.tele_period) { DomoticzSensor(DZ_AIRQUALITY, scd30_CO2); DomoticzTempHumPressureSensor(t, h); } diff --git a/tasmota/xsns_43_hre.ino b/tasmota/xsns_43_hre.ino index 19fffe957..2b5a3dff3 100644 --- a/tasmota/xsns_43_hre.ino +++ b/tasmota/xsns_43_hre.ino @@ -137,7 +137,7 @@ void hreEvery50ms(void) switch (hre_state) { case hre_sync: - if (uptime < 10) + if (TasmotaGlobal.uptime < 10) break; sync_run = 0; sync_counter = 0; @@ -174,7 +174,7 @@ void hreEvery50ms(void) AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "sync_run:%d, sync_counter:%d"), sync_run, sync_counter); read_counter = 0; parity_errors = 0; - curr_start = uptime; + curr_start = TasmotaGlobal.uptime; memset(buff, 0, sizeof(buff)); hre_state = hre_reading; AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_reading")); @@ -223,7 +223,7 @@ void hreEvery50ms(void) case hre_sleeping: // If there isn't some delay between readings, rate calculations // aren't as accurate. 27 seconds will give about a 30 second refresh rate - if (uptime - hre_usage_time >= 27) + if (TasmotaGlobal.uptime - hre_usage_time >= 27) hre_state = hre_sync; } } diff --git a/tasmota/xsns_44_sps30.ino b/tasmota/xsns_44_sps30.ino index 441a05754..ce7912c88 100644 --- a/tasmota/xsns_44_sps30.ino +++ b/tasmota/xsns_44_sps30.ino @@ -158,7 +158,7 @@ const char HTTP_SNS_SPS30_c[] PROGMEM ="{s}SPS30 " "TYPSIZ" "{m}%s " "um" "{e}"; void SPS30_Every_Second() { if (!sps30_running) return; - if (uptime%10==0) { + if (TasmotaGlobal.uptime%10==0) { uint8_t vars[sizeof(float)*10]; sps30_get_data(SPS_CMD_READ_MEASUREMENT,vars,sizeof(vars)); float *fp=&sps30_result.PM1_0; @@ -178,7 +178,7 @@ void SPS30_Every_Second() { } } - if (uptime%3600==0 && uptime>60) { + if (TasmotaGlobal.uptime%3600==0 && TasmotaGlobal.uptime>60) { // should auto clean once per week runtime // so count hours, should be in Settings SPS30_HOURS++; diff --git a/tasmota/xsns_45_vl53l0x.ino b/tasmota/xsns_45_vl53l0x.ino index f3a9bbe74..623dda9a0 100644 --- a/tasmota/xsns_45_vl53l0x.ino +++ b/tasmota/xsns_45_vl53l0x.ino @@ -119,7 +119,7 @@ void Vl53l0Show(boolean json) { if (json) { ResponseAppend_P(PSTR(",\"VL53L0X\":{\"" D_JSON_DISTANCE "\":%d}"), Vl53l0x.distance); #ifdef USE_DOMOTICZ - if (0 == tele_period) { + if (0 == TasmotaGlobal.tele_period) { DomoticzSensor(DZ_ILLUMINANCE, Vl53l0x.distance); } #endif // USE_DOMOTICZ diff --git a/tasmota/xsns_47_max31865.ino b/tasmota/xsns_47_max31865.ino index adf4d3611..de67a737e 100644 --- a/tasmota/xsns_47_max31865.ino +++ b/tasmota/xsns_47_max31865.ino @@ -97,7 +97,7 @@ void MAX31865_Show(bool Json) { if (Json) { ResponseAppend_P(PSTR(",\"MAX31865%c%d\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_RESISTANCE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ IndexSeparator(), i, temperature, resistance, MAX31865_Result[i].ErrorCode); - if ((0 == tele_period) && (!report_once)) { + if ((0 == TasmotaGlobal.tele_period) && (!report_once)) { #ifdef USE_DOMOTICZ DomoticzSensor(DZ_TEMP, temperature); #endif // USE_DOMOTICZ diff --git a/tasmota/xsns_48_chirp.ino b/tasmota/xsns_48_chirp.ino index 934dff205..3ef5ea72c 100644 --- a/tasmota/xsns_48_chirp.ino +++ b/tasmota/xsns_48_chirp.ino @@ -443,7 +443,7 @@ void ChirpShow(bool json) ResponseAppend_P(PSTR(",\"%s%u\":{\"sleeping\"}"),chirp_name, i); } #ifdef USE_DOMOTICZ - if (0 == tele_period) { + if (0 == TasmotaGlobal.tele_period) { DomoticzTempHumPressureSensor(t_temperature, chirp_sensor[i].moisture); DomoticzSensor(DZ_ILLUMINANCE,chirp_sensor[i].light); // this is not LUX!! } diff --git a/tasmota/xsns_52_ibeacon.ino b/tasmota/xsns_52_ibeacon.ino index 5c8b0afd4..a733e97da 100755 --- a/tasmota/xsns_52_ibeacon.ino +++ b/tasmota/xsns_52_ibeacon.ino @@ -119,7 +119,7 @@ void hm17_every_second(void) { if (!IBEACON_Serial) return; if (hm17_found) { - if (IB_UPDATE_TIME && (uptime%IB_UPDATE_TIME==0)) { + if (IB_UPDATE_TIME && (TasmotaGlobal.uptime%IB_UPDATE_TIME==0)) { if (hm17_cmd!=99) { if (hm17_flag&2) { ib_sendbeep(); @@ -140,7 +140,7 @@ void hm17_every_second(void) { } } } else { - if (uptime%20==0) { + if (TasmotaGlobal.uptime%20==0) { hm17_sendcmd(HM17_TEST); } } diff --git a/tasmota/xsns_53_sml.ino b/tasmota/xsns_53_sml.ino index b37ea147b..7984b2fc3 100755 --- a/tasmota/xsns_53_sml.ino +++ b/tasmota/xsns_53_sml.ino @@ -763,7 +763,7 @@ ADS1115 adc; void ADS1115_init(void) { ads1115_up=0; - if (!i2c_flg) return; + if (!TasmotaGlobal.i2c_enabled) return; adc.begin(); adc.set_data_rate(ADS1115_DATA_RATE_128_SPS); @@ -818,31 +818,31 @@ uint8_t dchars[16]; if (dump2log&8) { // combo mode while (SML_SAVAILABLE) { - log_data[index]=':'; + TasmotaGlobal.log_data[index]=':'; index++; - log_data[index]=' '; + TasmotaGlobal.log_data[index]=' '; index++; d_lastms=millis(); while ((millis()-d_lastms)<40) { if (SML_SAVAILABLE) { uint8_t c=SML_SREAD; - sprintf(&log_data[index],"%02x ",c); + sprintf(&TasmotaGlobal.log_data[index],"%02x ",c); dchars[hcnt]=c; index+=3; hcnt++; if (hcnt>15) { // line complete, build asci chars - log_data[index]='='; + TasmotaGlobal.log_data[index]='='; index++; - log_data[index]='>'; + TasmotaGlobal.log_data[index]='>'; index++; - log_data[index]=' '; + TasmotaGlobal.log_data[index]=' '; index++; for (uint8_t ccnt=0; ccnt<16; ccnt++) { if (isprint(dchars[ccnt])) { - log_data[index]=dchars[ccnt]; + TasmotaGlobal.log_data[index]=dchars[ccnt]; } else { - log_data[index]=' '; + TasmotaGlobal.log_data[index]=' '; } index++; } @@ -851,7 +851,7 @@ uint8_t dchars[16]; } } if (index>0) { - log_data[index]=0; + TasmotaGlobal.log_data[index]=0; AddLog(LOG_LEVEL_INFO); index=0; hcnt=0; @@ -863,24 +863,24 @@ uint8_t dchars[16]; while (SML_SAVAILABLE) { char c=SML_SREAD&0x7f; if (c=='\n' || c=='\r') { - log_data[sml_logindex]=0; + TasmotaGlobal.log_data[sml_logindex]=0; AddLog(LOG_LEVEL_INFO); sml_logindex=2; - log_data[0]=':'; - log_data[1]=' '; + TasmotaGlobal.log_data[0]=':'; + TasmotaGlobal.log_data[1]=' '; break; } - log_data[sml_logindex]=c; - if (sml_logindex2) { - log_data[index]=0; + TasmotaGlobal.log_data[index]=0; AddLog(LOG_LEVEL_INFO); } } @@ -1796,7 +1796,7 @@ void SML_Show(boolean json) { /* #ifdef USE_DOMOTICZ - if (json && !tele_period) { + if (json && !TasmotaGlobal.tele_period) { char str[16]; dtostrfd(meter_vars[0], 1, str); DomoticzSensorPowerEnergy(meter_vars[1], str); // PowerUsage, EnergyToday @@ -1924,7 +1924,7 @@ bool Gpio_used(uint8_t gpiopin) { } } */ - if ((gpiopin < ARRAY_SIZE(gpio_pin)) && (gpio_pin[gpiopin] > 0)) { + if ((gpiopin < ARRAY_SIZE(TasmotaGlobal.gpio_pin)) && (TasmotaGlobal.gpio_pin[gpiopin] > 0)) { return true; } return false; diff --git a/tasmota/xsns_54_ina226.ino b/tasmota/xsns_54_ina226.ino index 81c4bafc3..f9ec67221 100644 --- a/tasmota/xsns_54_ina226.ino +++ b/tasmota/xsns_54_ina226.ino @@ -206,7 +206,7 @@ void Ina226Init() //AddLog_P2( LOG_LEVEL_NONE, "Ina226Init"); // AddLog_P2( LOG_LEVEL_NONE, "Size of Settings: %d bytes", sizeof(Settings)); -// if (!i2c_flg) +// if (!TasmotaGlobal.i2c_enabled) // AddLog_P2(LOG_LEVEL_DEBUG, "INA226: Initialization failed: No I2C support"); @@ -417,8 +417,8 @@ bool Ina226CommandSensor() break; case 2: // Save and restart - restart_flag = 2; - Response_P(PSTR("{\"Sensor54-Command-Result\":{\"Restart_flag\":%d}}"),restart_flag); + TasmotaGlobal.restart_flag = 2; + Response_P(PSTR("{\"Sensor54-Command-Result\":{\"Restart_flag\":%d}}"),TasmotaGlobal.restart_flag); break; default: @@ -516,7 +516,7 @@ void Ina226Show(bool json) ResponseAppend_P(PSTR(",\"%s\":{\"Id\":%d,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), name, i, voltage, current, power); #ifdef USE_DOMOTICZ - if (0 == tele_period) { + if (0 == TasmotaGlobal.tele_period) { DomoticzSensor(DZ_VOLTAGE, voltage); DomoticzSensor(DZ_CURRENT, current); } diff --git a/tasmota/xsns_55_hih_series.ino b/tasmota/xsns_55_hih_series.ino index c108cce07..89278e432 100644 --- a/tasmota/xsns_55_hih_series.ino +++ b/tasmota/xsns_55_hih_series.ino @@ -76,7 +76,7 @@ void Hih6Detect(void) { if (I2cActive(HIH6_ADDR)) { return; } - if (uptime < 2) { delay(20); } // Skip entering power on comand mode + if (TasmotaGlobal.uptime < 2) { delay(20); } // Skip entering power on comand mode Hih6.type = Hih6Read(); if (Hih6.type) { I2cSetActiveFound(HIH6_ADDR, Hih6.types); @@ -85,7 +85,7 @@ void Hih6Detect(void) void Hih6EverySecond(void) { - if (uptime &1) { + if (TasmotaGlobal.uptime &1) { // HIH6130: 30mS if (!Hih6Read()) { AddLogMissed(Hih6.types, Hih6.valid); @@ -96,7 +96,7 @@ void Hih6EverySecond(void) void Hih6Show(bool json) { if (Hih6.valid) { - TempHumDewShow(json, (0 == tele_period), Hih6.types, Hih6.temperature, Hih6.humidity); + TempHumDewShow(json, (0 == TasmotaGlobal.tele_period), Hih6.types, Hih6.temperature, Hih6.humidity); } } diff --git a/tasmota/xsns_56_hpma.ino b/tasmota/xsns_56_hpma.ino index a0e8aef5a..576cf19d2 100644 --- a/tasmota/xsns_56_hpma.ino +++ b/tasmota/xsns_56_hpma.ino @@ -96,7 +96,7 @@ void HpmaShow(bool json) if (json) { ResponseAppend_P(PSTR(",\"HPMA\":{\"PM2.5\":%d,\"PM10\":%d}"), hpma_data.pm2_5, hpma_data.pm10); #ifdef USE_DOMOTICZ - if (0 == tele_period) { + if (0 == TasmotaGlobal.tele_period) { DomoticzSensor(DZ_VOLTAGE, pm2_5); // PM2.5 DomoticzSensor(DZ_CURRENT, pm10); // PM10 } diff --git a/tasmota/xsns_57_tsl2591.ino b/tasmota/xsns_57_tsl2591.ino index 8a96648e1..ae7bdba8d 100644 --- a/tasmota/xsns_57_tsl2591.ino +++ b/tasmota/xsns_57_tsl2591.ino @@ -80,7 +80,7 @@ void Tsl2591Show(bool json) if (json) { ResponseAppend_P(PSTR(",\"TSL2591\":{\"" D_JSON_ILLUMINANCE "\":%s}"), lux_str); #ifdef USE_DOMOTICZ - if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, tsl2591_lux); } + if (0 == TasmotaGlobal.tele_period) { DomoticzSensor(DZ_ILLUMINANCE, tsl2591_lux); } #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { diff --git a/tasmota/xsns_58_dht12.ino b/tasmota/xsns_58_dht12.ino index 55c78a486..a772e3cea 100644 --- a/tasmota/xsns_58_dht12.ino +++ b/tasmota/xsns_58_dht12.ino @@ -79,7 +79,7 @@ void Dht12Detect(void) void Dht12EverySecond(void) { - if (uptime &1) { + if (TasmotaGlobal.uptime &1) { // DHT12: 55mS if (!Dht12Read()) { AddLogMissed(Dht12.name, Dht12.valid); @@ -90,7 +90,7 @@ void Dht12EverySecond(void) void Dht12Show(bool json) { if (Dht12.valid) { - TempHumDewShow(json, (0 == tele_period), Dht12.name, Dht12.temperature, Dht12.humidity); + TempHumDewShow(json, (0 == TasmotaGlobal.tele_period), Dht12.name, Dht12.temperature, Dht12.humidity); } } diff --git a/tasmota/xsns_59_ds1624.ino b/tasmota/xsns_59_ds1624.ino index 96adc4938..7fece459d 100644 --- a/tasmota/xsns_59_ds1624.ino +++ b/tasmota/xsns_59_ds1624.ino @@ -185,7 +185,7 @@ void DS1624Show(bool json) dtostrfd(ds1624_sns[i].value, Settings.flag2.temperature_resolution, temperature); if (json) { ResponseAppend_P(JSON_SNS_TEMP, ds1624_sns[i].name, temperature); - if ((0 == tele_period) && once) { + if ((0 == TasmotaGlobal.tele_period) && once) { #ifdef USE_DOMOTICZ DomoticzSensor(DZ_TEMP, temperature); #endif // USE_DOMOTICZ diff --git a/tasmota/xsns_60_GPS.ino b/tasmota/xsns_60_GPS.ino index 7e9b7265d..63fc147f2 100644 --- a/tasmota/xsns_60_GPS.ino +++ b/tasmota/xsns_60_GPS.ino @@ -340,7 +340,7 @@ void UBXsendCFGLine(uint8_t _line) void UBXTriggerTele(void) { - mqtt_data[0] = '\0'; + ResponseClear(); if (MqttShowSensor()) { MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); #ifdef USE_RULES diff --git a/tasmota/xsns_61_MI_NRF24.ino b/tasmota/xsns_61_MI_NRF24.ino index e76909a4e..06ac83062 100644 --- a/tasmota/xsns_61_MI_NRF24.ino +++ b/tasmota/xsns_61_MI_NRF24.ino @@ -186,8 +186,8 @@ struct mi_beacon_t{ uint16_t fert; //09 struct{ //01 uint16_t num; - uint8_t longPress; - }Btn; + uint8_t longPress; + }Btn; }; }; @@ -493,13 +493,13 @@ bool MINRFreceivePacket(void) // AddLog_P2(LOG_LEVEL_INFO,PSTR("NRF: _lsfrlist: %x, chan: %u, mode: %u"),_lsfrlist[MINRF.currentChan],MINRF.currentChan, MINRF.packetMode); switch (MINRF.packetMode) { - case 0: case NLIGHT: case MJYD2S: + case 0: case NLIGHT: case MJYD2S: MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), MINRF.channel[MINRF.currentChan] | 0x40); // "BEACON" mode, "NLIGHT" mode, "MJYD2S" mode break; case FLORA: case LYWSD02: case MHOC303: MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_A[MINRF.currentChan]); // "flora" mode, "LYWSD02" mode break; - case MJ_HT_V1: case LYWSD03: case CGG1: case CGD1: case MHOC401: + case MJ_HT_V1: case LYWSD03: case CGG1: case CGD1: case MHOC401: MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_B[MINRF.currentChan]); // "MJ_HT_V1" mode, LYWSD03" mode, "CGG1" mode, "CGD1" mode break; case YEERC: @@ -977,7 +977,7 @@ void MINRFcomputefirstUsedPacketMode(void){ /** * @brief Recalculates the receive buffer with an offset in relation to a standard BLE advertisement. * Used for custom PDU, typically based on a MAC - * + * * @param _buf - The receive buffer * @param offset - in bytes */ @@ -1026,7 +1026,7 @@ void MINRFchangePacketModeTo(uint8_t _mode) { NRF24radio.openReadingPipe(0,MIBLElights[MINRF.activeLight].PDU[_nextchannel]); // computed from MAC -> NLIGHT and MJYSD2S MINRF.activeLight++; break; - case YEERC: // YEE-RC packet + case YEERC: // YEE-RC packet NRF24radio.openReadingPipe(0,kMINRFYRCPDU[_nextchannel]);// 95 fe 50 30 -> YEE-RC break; case ATC: @@ -1095,7 +1095,7 @@ uint32_t MINRFgetSensorSlot(uint8_t (&_MAC)[6], uint16_t _type){ _newSensor.feature.lux=1; _newSensor.feature.bat=0; break; - case NLIGHT: + case NLIGHT: _newSensor.events=0x00; _newSensor.feature.PIR=1; _newSensor.feature.NMT=1; @@ -1155,11 +1155,11 @@ void MINRFconfirmSensors(void){ /** * @brief trigger real-time message for PIR or RC - * + * */ void MINRFtriggerTele(void){ MINRF.mode.triggeredTele= true; - mqtt_data[0] = '\0'; + ResponseClear(); if (MqttShowSensor()) { MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); #ifdef USE_RULES @@ -1506,7 +1506,7 @@ void MINRF_EVERY_50_MSECOND() { // Every 50mseconds } else MINRF.packetMode+=2; } - else{ + else{ MINRF.packetMode = (MINRF.packetMode+1>MI_TYPES) ? MINRF.firstUsedPacketMode : MINRF.packetMode+1; for (uint32_t i = MINRF.packetMode; i150){ break; @@ -1007,7 +1007,7 @@ void MI32TimeTask(void *pvParameters){ pChr = pSvc->getCharacteristic(charUUID); } - if (pChr){ + if (pChr){ if(pChr->canWrite()) { union { uint8_t buf[5]; @@ -1054,7 +1054,7 @@ void MI32UnitTask(void *pvParameters){ vTaskDelete( NULL ); } - if(MI32ConnectActiveSensor()){ + if(MI32ConnectActiveSensor()){ uint32_t timer = 0; while (MI32.mode.connected == 0){ if (timer>1000){ @@ -1354,7 +1354,7 @@ if(decryptRet!=0){ if (MIBLEsensors[_slot].type==NLIGHT){ MIBLEsensors[_slot].eventType.motion = 1; //PIR MIBLEsensors[_slot].events++; - MIBLEsensors[_slot].NMT = 0; + MIBLEsensors[_slot].NMT = 0; MIBLEsensors[_slot].lastTime = millis(); MI32.mode.shallTriggerTele = 1; // AddLog_P2(LOG_LEVEL_DEBUG,PSTR("PIR: primary"),MIBLEsensors[_slot].lux ); @@ -1446,12 +1446,12 @@ void MI32ParseResponse(char *buf, uint16_t bufsize, uint8_t addr[6], int RSSI) { /** * @brief Parse a BLE advertisement packet - * - * @param payload - * @param payloadLength - * @param CID - * @param SVC - * @param UUID + * + * @param payload + * @param payloadLength + * @param CID + * @param SVC + * @param UUID */ void MI32ParseGenericBeacon(uint8_t* payload, size_t payloadLength, uint16_t* CID, uint16_t*SVC, uint16_t* UUID){ AddLog_P2(LOG_LEVEL_DEBUG_MORE,PSTR("MI32: Beacon:____________")); @@ -1492,14 +1492,14 @@ void MI32ParseGenericBeacon(uint8_t* payload, size_t payloadLength, uint16_t* CI /** * @brief Handle a generic BLE advertisment in a running scan or to check a beacon - * - * @param payload - * @param payloadLength - * @param RSSI - * @param addr + * + * @param payload + * @param payloadLength + * @param RSSI + * @param addr */ void MI32HandleGenericBeacon(uint8_t* payload, size_t payloadLength, int RSSI, uint8_t* addr){ - if(MI32.state.beaconScanCounter==0){ //handle beacon + if(MI32.state.beaconScanCounter==0){ //handle beacon for(auto &_beacon : MIBLEbeacons){ if(memcmp(addr,_beacon.MAC,6)==0){ MI32ParseGenericBeacon(payload,payloadLength,&_beacon.CID,&_beacon.SVC,&_beacon.UUID); @@ -1535,7 +1535,7 @@ void MI32HandleGenericBeacon(uint8_t* payload, size_t payloadLength, int RSSI, u /** * @brief Add a beacon defined by its MAC-address, if only zeros are given, the beacon will be deactivated - * + * * @param index 1-4 beacons are currently supported * @param data null terminated char array representing a MAC-address in hex */ @@ -1559,7 +1559,7 @@ void MI32addBeacon(uint8_t index, char* data){ /** * @brief Present BLE scan in the console, after that deleting the scan data - * + * */ void MI32showScanResults(){ AddLog_P2(LOG_LEVEL_INFO,PSTR("MI32: found %u devices in scan:"), MINBLEscanResult.size()); @@ -1628,7 +1628,7 @@ bool MI32readBat(char *_buf){ /** * @brief Launch functions from Core 1 to make race conditions less likely - * + * */ void MI32Every50mSecond(){ @@ -1719,7 +1719,7 @@ void MI32EverySecond(bool restart){ } if(_counter==0) { - + MI32.state.sensor = _nextSensorSlot; MI32.mode.canScan = 0; // if (MI32.mode.runningScan|| MI32.mode.connected || MI32.mode.willConnect) return; @@ -1830,7 +1830,7 @@ bool MI32Cmd(void) { XdrvMailbox.payload = MI32.period; Response_P(S_JSON_MI32_COMMAND, command, ""); break; -#ifdef USE_MI_DECRYPTION +#ifdef USE_MI_DECRYPTION case CMND_MI32_KEY: if (XdrvMailbox.data_len==44){ // a KEY-MAC-string MI32AddKey(XdrvMailbox.data); @@ -1916,12 +1916,12 @@ void MI32Show(bool json) for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { if(MI32.mode.triggeredTele && MIBLEsensors[i].eventType.raw == 0) continue; if(MI32.mode.triggeredTele && MIBLEsensors[i].shallSendMQTT==0) continue; - + ResponseAppend_P(PSTR(",\"%s-%02x%02x%02x\":"), // do not add the '{' now ... kMI32DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].MAC[3], MIBLEsensors[i].MAC[4], MIBLEsensors[i].MAC[5]); - uint32_t _positionCurlyBracket = strlen(mqtt_data); // ... this will be a ',' first, but later be replaced + uint32_t _positionCurlyBracket = strlen(TasmotaGlobal.mqtt_data); // ... this will be a ',' first, but later be replaced if((!MI32.mode.triggeredTele && !MI32.option.minimalSummary)||MI32.mode.triggeredTele){ bool tempHumSended = false; @@ -2053,9 +2053,9 @@ void MI32Show(bool json) } if (MI32.option.showRSSI) ResponseAppend_P(PSTR(",\"RSSI\":%d"), MIBLEsensors[i].RSSI); - if(_positionCurlyBracket==strlen(mqtt_data)) ResponseAppend_P(PSTR(",")); // write some random char, to be overwritten in the next step + if(_positionCurlyBracket==strlen(TasmotaGlobal.mqtt_data)) ResponseAppend_P(PSTR(",")); // write some random char, to be overwritten in the next step ResponseAppend_P(PSTR("}")); - mqtt_data[_positionCurlyBracket] = '{'; + TasmotaGlobal.mqtt_data[_positionCurlyBracket] = '{'; MIBLEsensors[i].eventType.raw = 0; if(MIBLEsensors[i].shallSendMQTT==1){ MIBLEsensors[i].shallSendMQTT = 0; diff --git a/tasmota/xsns_62_MI_HM10.ino b/tasmota/xsns_62_MI_HM10.ino index b236a1d05..f8f700807 100644 --- a/tasmota/xsns_62_MI_HM10.ino +++ b/tasmota/xsns_62_MI_HM10.ino @@ -137,8 +137,8 @@ struct mi_beacon_t{ uint32_t NMT; //17 struct{ //01 uint16_t num; - uint8_t longPress; - }Btn; + uint8_t longPress; + }Btn; }; uint8_t padding[12]; }; @@ -191,7 +191,7 @@ struct mi_sensor_t{ }; uint32_t raw; } eventType; - + int rssi; uint32_t lastTime; uint32_t lux; @@ -244,7 +244,7 @@ const char kHM10_Commands[] PROGMEM = "Scan|AT|Period|Baud|Time|Auto #define HM10_TYPES 12 //count this manually -const uint16_t kHM10SlaveID[HM10_TYPES]={ +const uint16_t kHM10SlaveID[HM10_TYPES]={ 0x0098, // Flora 0x01aa, // MJ_HT_V1 0x045b, // LYWSD02 @@ -490,7 +490,7 @@ uint32_t MIBLEgetSensorSlot(uint8_t (&_MAC)[6], uint16_t _type, uint32_t _rssi){ _newSensor.feature.lux=1; _newSensor.feature.bat=1; break; - case NLIGHT: + case NLIGHT: _newSensor.events=0x00; _newSensor.feature.PIR=1; _newSensor.feature.NMT=1; @@ -685,7 +685,7 @@ char* HM10ParseResponse(char *buf, uint16_t bufsize) { while(_pos = (char*) memchr(buf+_idx, 'I', 60)){ //strstr() does miss too much _idx=_pos-buf; if(memcmp(&_pos+1,_subStr,3)){ - break; + break; } } if(_pos) { @@ -1371,11 +1371,11 @@ bool HM10Cmd(void) { /** * @brief trigger real-time message - * + * */ void HM10triggerTele(void){ HM10.mode.triggeredTele = 1; - mqtt_data[0] = '\0'; + ResponseClear(); if (MqttShowSensor()) { MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); #ifdef USE_RULES @@ -1405,12 +1405,12 @@ void HM10Show(bool json) for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { if(HM10.mode.triggeredTele && MIBLEsensors[i].eventType.raw == 0) continue; if(HM10.mode.triggeredTele && MIBLEsensors[i].shallSendMQTT==0) continue; - + ResponseAppend_P(PSTR(",\"%s-%02x%02x%02x\":"), // do not add the '{' now ... kHM10DeviceType[MIBLEsensors[i].type-1], MIBLEsensors[i].MAC[3], MIBLEsensors[i].MAC[4], MIBLEsensors[i].MAC[5]); - uint32_t _positionCurlyBracket = strlen(mqtt_data); // ... this will be a ',' first, but later be replaced + uint32_t _positionCurlyBracket = strlen(TasmotaGlobal.mqtt_data); // ... this will be a ',' first, but later be replaced if((!HM10.mode.triggeredTele && !HM10.option.minimalSummary)||HM10.mode.triggeredTele){ bool tempHumSended = false; @@ -1499,9 +1499,9 @@ void HM10Show(bool json) if (HM10.option.showRSSI && HM10.mode.triggeredTele) ResponseAppend_P(PSTR(",\"RSSI\":%d"), MIBLEsensors[i].rssi); - if(_positionCurlyBracket==strlen(mqtt_data)) ResponseAppend_P(PSTR(",")); // write some random char, to be overwritten in the next step + if(_positionCurlyBracket==strlen(TasmotaGlobal.mqtt_data)) ResponseAppend_P(PSTR(",")); // write some random char, to be overwritten in the next step ResponseAppend_P(PSTR("}")); - mqtt_data[_positionCurlyBracket] = '{'; + TasmotaGlobal.mqtt_data[_positionCurlyBracket] = '{'; MIBLEsensors[i].eventType.raw = 0; if(MIBLEsensors[i].shallSendMQTT==1){ MIBLEsensors[i].shallSendMQTT = 0; diff --git a/tasmota/xsns_63_aht1x.ino b/tasmota/xsns_63_aht1x.ino index 101c8495b..cba95662a 100644 --- a/tasmota/xsns_63_aht1x.ino +++ b/tasmota/xsns_63_aht1x.ino @@ -176,7 +176,7 @@ void AHT1XShow(bool json) { float hum = ConvertHumidity(aht1x_sensors[i].humidity); char types[11]; // AHT1X-0x38 snprintf_P(types, sizeof(types), PSTR("%s%c0x%02X"), aht1x_sensors[i].types, IndexSeparator(), aht1x_sensors[i].address); // "X-0xXX" - TempHumDewShow(json, ((0 == tele_period) && (0 == i)), types, tem, hum); + TempHumDewShow(json, ((0 == TasmotaGlobal.tele_period) && (0 == i)), types, tem, hum); } } diff --git a/tasmota/xsns_65_hdc1080.ino b/tasmota/xsns_65_hdc1080.ino index 5b3b159ba..1a70cf0a0 100644 --- a/tasmota/xsns_65_hdc1080.ino +++ b/tasmota/xsns_65_hdc1080.ino @@ -259,7 +259,7 @@ void HdcDetect(void) { * */ void HdcEverySecond(void) { - if (uptime &1) { // Every 2 seconds + if (TasmotaGlobal.uptime &1) { // Every 2 seconds if (!HdcTriggerRead()) { AddLogMissed((char*) hdc_type_name, hdc_valid); } @@ -273,7 +273,7 @@ void HdcEverySecond(void) { */ void HdcShow(bool json) { if (hdc_valid) { - TempHumDewShow(json, (0 == tele_period), hdc_type_name, hdc_temperature, hdc_humidity); + TempHumDewShow(json, (0 == TasmotaGlobal.tele_period), hdc_type_name, hdc_temperature, hdc_humidity); } } diff --git a/tasmota/xsns_66_iAQ.ino b/tasmota/xsns_66_iAQ.ino index d115d0965..ed89c855e 100644 --- a/tasmota/xsns_66_iAQ.ino +++ b/tasmota/xsns_66_iAQ.ino @@ -50,14 +50,14 @@ void IAQ_Read(void) { uint8_t buf[9]; buf[2] = IAQ_STATUS_I2C_ERR; // populate entry with error code - Wire.requestFrom((uint8_t)I2_ADR_IAQ,sizeof(buf)); + Wire.requestFrom((uint8_t)I2_ADR_IAQ,sizeof(buf)); for( uint32_t i=0; i<9; i++ ) { buf[i]= Wire.read(); } // AddLog_P2(LOG_LEVEL_DEBUG, "iAQ: buffer %x %x %x %x %x %x %x %x %x ", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8]); iAQ.pred = (buf[0]<<8) + buf[1]; iAQ.status = buf[2]; - iAQ.resistance = ((uint32_t)buf[3]<<24) + ((uint32_t)buf[4]<<16) + ((uint32_t)buf[5]<<8) + (uint32_t)buf[6]; + iAQ.resistance = ((uint32_t)buf[3]<<24) + ((uint32_t)buf[4]<<16) + ((uint32_t)buf[5]<<8) + (uint32_t)buf[6]; iAQ.Tvoc = (buf[7]<<8) + buf[8]; } @@ -86,7 +86,7 @@ void IAQ_Show(uint8_t json) else { ResponseAppend_P(PSTR(",\"IAQ\":{\"" D_JSON_ECO2 "\":%u,\"" D_JSON_TVOC "\":%u,\"" D_JSON_RESISTANCE "\":%u}"), iAQ.pred, iAQ.Tvoc, iAQ.resistance); #ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, iAQ.pred); + if (0 == TasmotaGlobal.tele_period) DomoticzSensor(DZ_AIRQUALITY, iAQ.pred); #endif // USE_DOMOTICZ } #ifdef USE_WEBSERVER @@ -100,7 +100,7 @@ void IAQ_Show(uint8_t json) break; default: WSContentSend_PD(HTTP_SNS_IAQ_ERROR, D_ERROR); - } + } #endif } } diff --git a/tasmota/xsns_68_windmeter.ino b/tasmota/xsns_68_windmeter.ino index 677cfc8b3..e30d245d2 100644 --- a/tasmota/xsns_68_windmeter.ino +++ b/tasmota/xsns_68_windmeter.ino @@ -274,7 +274,7 @@ void WindMeterShow(bool json) void WindMeterTriggerTele(void) { - mqtt_data[0] = '\0'; + ResponseClear(); if (MqttShowSensor()) { MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); #ifdef USE_RULES diff --git a/tasmota/xsns_69_opentherm.ino b/tasmota/xsns_69_opentherm.ino index 39b7748fe..f08a83f0d 100644 --- a/tasmota/xsns_69_opentherm.ino +++ b/tasmota/xsns_69_opentherm.ino @@ -498,7 +498,7 @@ void sns_opentherm_flags_cmd(void) sns_opentherm_init_boiler_status(); } bool addComma = false; - mqtt_data[0] = 0; + TasmotaGlobal.mqtt_data[0] = 0; for (int pos = 0; pos < OT_FLAGS_COUNT; ++pos) { int mask = 1 << pos; @@ -507,9 +507,9 @@ void sns_opentherm_flags_cmd(void) { if (addComma) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); + snprintf_P(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), PSTR("%s,"), TasmotaGlobal.mqtt_data); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s"), mqtt_data, sns_opentherm_flag_text(mode)); + snprintf_P(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), PSTR("%s%s"), TasmotaGlobal.mqtt_data, sns_opentherm_flag_text(mode)); addComma = true; } } diff --git a/tasmota/xsns_71_veml7700.ino b/tasmota/xsns_71_veml7700.ino index 695e35824..655d52992 100644 --- a/tasmota/xsns_71_veml7700.ino +++ b/tasmota/xsns_71_veml7700.ino @@ -107,7 +107,7 @@ void VEML7700Show(bool json) ResponseAppend_P(JSON_SNS_VEML7700, D_NAME_VEML7700, veml7700_sensor.lux_normalized, veml7700_sensor.white_normalized); #ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_ILLUMINANCE, veml7700_sensor.lux_normalized); + if (0 == TasmotaGlobal.tele_period) DomoticzSensor(DZ_ILLUMINANCE, veml7700_sensor.lux_normalized); #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { @@ -157,7 +157,7 @@ bool VEML7700Cmd(void) { } } Response_P(S_JSON_VEML7700_COMMAND_NVALUE, command, veml7700.getPersistence()); - break; + break; default: return false; } diff --git a/tasmota/xsns_72_mcp9808.ino b/tasmota/xsns_72_mcp9808.ino index 8af129f97..587123d2c 100644 --- a/tasmota/xsns_72_mcp9808.ino +++ b/tasmota/xsns_72_mcp9808.ino @@ -86,7 +86,7 @@ void MCP9808Show(bool json) { if (json) { ResponseAppend_P(JSON_SNS_TEMP, sensor_name, temperature); - if ((0 == tele_period) && (0 == i)) { + if ((0 == TasmotaGlobal.tele_period) && (0 == i)) { #ifdef USE_DOMOTICZ DomoticzSensor(DZ_TEMP, temperature); #endif // USE_DOMOTICZ diff --git a/tasmota/xsns_73_hp303b.ino b/tasmota/xsns_73_hp303b.ino index 0d9363409..30a14945c 100644 --- a/tasmota/xsns_73_hp303b.ino +++ b/tasmota/xsns_73_hp303b.ino @@ -88,7 +88,7 @@ void HP303B_Detect(void) { void HP303B_EverySecond(void) { for (uint32_t i = 0; i < hp303b_cfg.count; i++) { - if (uptime &1) { + if (TasmotaGlobal.uptime &1) { if (!HP303B_Read(i)) { AddLogMissed(hp303b_cfg.types, hp303b_sensor[i].valid); } @@ -105,11 +105,7 @@ void HP303B_Show(bool json) { snprintf_P(sensor_name, sizeof(sensor_name), PSTR("%s%c%02X"), sensor_name, IndexSeparator(), hp303b_sensor[i].address); // HP303B-76, HP303B-77 } - float sealevel = 0.0; - if (hp303b_sensor[i].pressure != 0.0) { - sealevel = (hp303b_sensor[i].pressure / FastPrecisePow(1.0 - ((float)Settings.altitude / 44330.0), 5.255)) - 21.6; - sealevel = ConvertPressure(sealevel); - } + float sealevel = ConvertPressureForSeaLevel(hp303b_sensor[i].pressure); char str_temperature[33]; dtostrfd(hp303b_sensor[i].temperature, Settings.flag2.temperature_resolution, str_temperature); @@ -126,7 +122,7 @@ void HP303B_Show(bool json) { ResponseJsonEnd(); #ifdef USE_DOMOTICZ // Domoticz and knx only support one temp sensor - if ((0 == tele_period) && (0 == i)) { + if ((0 == TasmotaGlobal.tele_period) && (0 == i)) { DomoticzSensor(DZ_TEMP, hp303b_sensor[i].temperature); } #endif // USE_DOMOTICZ diff --git a/tasmota/xsns_74_lmt01.ino b/tasmota/xsns_74_lmt01.ino index 522b82281..85d97a492 100644 --- a/tasmota/xsns_74_lmt01.ino +++ b/tasmota/xsns_74_lmt01.ino @@ -91,12 +91,12 @@ void LMT01_Show(bool Json) { if (Json) { ResponseAppend_P(JSON_SNS_TEMP, "LMT01", temp); #ifdef USE_DOMOTICZ - if (0 == tele_period) { + if (0 == TasmotaGlobal.tele_period) { DomoticzSensor(DZ_TEMP, temp); } #endif // USE_DOMOTICZ #ifdef USE_KNX - if (0 == tele_period) { + if (0 == TasmotaGlobal.tele_period) { KnxSensor(KNX_TEMPERATURE, lmt01_temperature); } #endif // USE_KNX diff --git a/tasmota/xsns_75_prometheus.ino b/tasmota/xsns_75_prometheus.ino index 1cd95e177..020cc3798 100644 --- a/tasmota/xsns_75_prometheus.ino +++ b/tasmota/xsns_75_prometheus.ino @@ -37,8 +37,8 @@ void HandleMetrics(void) // Pseudo-metric providing metadata about the running firmware version. WSContentSend_P(PSTR("# TYPE tasmota_info gauge\ntasmota_info{version=\"%s\",image=\"%s\",build_timestamp=\"%s\"} 1\n"), - my_version, my_image, GetBuildDateAndTime().c_str()); - WSContentSend_P(PSTR("# TYPE tasmota_uptime_seconds gauge\ntasmota_uptime_seconds %d\n"), uptime); + TasmotaGlobal.version, TasmotaGlobal.image_name, GetBuildDateAndTime().c_str()); + WSContentSend_P(PSTR("# TYPE tasmota_uptime_seconds gauge\ntasmota_uptime_seconds %d\n"), TasmotaGlobal.uptime); WSContentSend_P(PSTR("# TYPE tasmota_boot_count counter\ntasmota_boot_count %d\n"), Settings.bootcount); WSContentSend_P(PSTR("# TYPE tasmota_flash_writes_total counter\ntasmota_flash_writes_total %d\n"), Settings.save_flag); @@ -49,17 +49,17 @@ void HandleMetrics(void) // Wi-Fi Signal strength WSContentSend_P(PSTR("# TYPE tasmota_wifi_station_signal_dbm gauge\ntasmota_wifi_station_signal_dbm{mac_address=\"%s\"} %d\n"), WiFi.BSSIDstr().c_str(), WiFi.RSSI()); - if (!isnan(global_temperature_celsius)) { - dtostrfd(global_temperature_celsius, Settings.flag2.temperature_resolution, parameter); - WSContentSend_P(PSTR("# TYPE global_temperature_celsius gauge\nglobal_temperature_celsius %s\n"), parameter); + if (!isnan(TasmotaGlobal.temperature_celsius)) { + dtostrfd(TasmotaGlobal.temperature_celsius, Settings.flag2.temperature_resolution, parameter); + WSContentSend_P(PSTR("# TYPE tasmotaglobal_temperature_celsius gauge\ntasmotaglobal_temperature_celsius %s\n"), parameter); } - if (global_humidity != 0) { - dtostrfd(global_humidity, Settings.flag2.humidity_resolution, parameter); - WSContentSend_P(PSTR("# TYPE global_humidity gauge\nglobal_humidity %s\n"), parameter); + if (TasmotaGlobal.humidity != 0) { + dtostrfd(TasmotaGlobal.humidity, Settings.flag2.humidity_resolution, parameter); + WSContentSend_P(PSTR("# TYPE tasmotaglobal_humidity gauge\ntasmotaglobal_humidity %s\n"), parameter); } - if (global_pressure_hpa != 0) { - dtostrfd(global_pressure_hpa, Settings.flag2.pressure_resolution, parameter); - WSContentSend_P(PSTR("# TYPE global_pressure_hpa gauge\nglobal_pressure_hpa %s\n"), parameter); + if (TasmotaGlobal.pressure_hpa != 0) { + dtostrfd(TasmotaGlobal.pressure_hpa, Settings.flag2.pressure_resolution, parameter); + WSContentSend_P(PSTR("# TYPE tasmotaglobal_pressure_hpa gauge\ntasmotaglobal_pressure_hpa %s\n"), parameter); } #ifdef USE_ENERGY_SENSOR @@ -78,10 +78,10 @@ void HandleMetrics(void) /* // Alternative method using the complete sensor JSON data // For prometheus it may need to be decoded to # TYPE messages - mqtt_data[0] = '\0'; + ResponseClear(); MqttShowSensor(); - char json[strlen(mqtt_data) +1]; - snprintf_P(json, sizeof(json), mqtt_data); + char json[strlen(TasmotaGlobal.mqtt_data) +1]; + snprintf_P(json, sizeof(json), TasmotaGlobal.mqtt_data); // Do your Prometheus specific processing here. // Look at function DisplayAnalyzeJson() in file xdrv_13_display.ino as an example how to decode the JSON message diff --git a/tasmota/xsns_77_vl53l1x.ino b/tasmota/xsns_77_vl53l1x.ino index 170ca4128..23be88a69 100644 --- a/tasmota/xsns_77_vl53l1x.ino +++ b/tasmota/xsns_77_vl53l1x.ino @@ -79,7 +79,7 @@ void Vl53l1Every_Second(void) { void Vl53l1Show(bool json) { if (json) { #ifdef USE_DOMOTICZ - if (0 == tele_period) { + if (0 == TasmotaGlobal.tele_period) { Vl53l1Every_Second(); } #endif // USE_DOMOTICZ diff --git a/tasmota/xsns_78_ezo.ino b/tasmota/xsns_78_ezo.ino index 36fcea423..a92df5d87 100644 --- a/tasmota/xsns_78_ezo.ino +++ b/tasmota/xsns_78_ezo.ino @@ -18,7 +18,7 @@ */ #ifdef USE_I2C -#if defined(USE_EZOPH) || defined(USE_EZOORP) || defined(USE_EZORTD) || defined(USE_EZOHUM) || defined(USE_EZOEC) || defined(USE_EZOCO2) +#if defined(USE_EZOPH) || defined(USE_EZOORP) || defined(USE_EZORTD) || defined(USE_EZOHUM) || defined(USE_EZOEC) || defined(USE_EZOCO2) || defined(USE_EZOO2) || defined(USE_EZOPRS) || defined(USE_EZOFLO) #define USE_EZO #endif #if defined(USE_EZO) diff --git a/tasmota/xsns_78_ezoco2.ino b/tasmota/xsns_78_ezoco2.ino index f9f09e1c4..a7fe76cc8 100644 --- a/tasmota/xsns_78_ezoco2.ino +++ b/tasmota/xsns_78_ezoco2.ino @@ -32,7 +32,7 @@ struct EZOCO2 : public EZOStruct { EZOStruct::ProcessMeasurement(data, sizeof(data), EZO_CO2_READ_LATENCY); // sensor has a 10s warmup period - if (uptime >= 10) { + if (TasmotaGlobal.uptime >= 10) { CO2 = atoi(data); } } @@ -42,7 +42,7 @@ struct EZOCO2 : public EZOStruct { if (json) { ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_CO2 "\":%d}" ), name, CO2); } -#ifdef USE_WEBSERVER +#ifdef USE_WEBSERVER else { WSContentSend_PD(HTTP_SNS_CO2, name, CO2); #endif // USE_WEBSERVER diff --git a/tasmota/xsns_78_ezoflo.ino b/tasmota/xsns_78_ezoflo.ino new file mode 100644 index 000000000..214069001 --- /dev/null +++ b/tasmota/xsns_78_ezoflo.ino @@ -0,0 +1,81 @@ +/* + xsns_78_ezoflo.ino - EZO FLO I2C FLO sensor support for Tasmota + + Copyright (C) 2020 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 + 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_I2C +#ifdef USE_EZOFLO + +#define EZO_FLO_READ_LATENCY 300 + +struct EZOFLO : public EZOStruct { + EZOFLO(uint32_t addr) : EZOStruct(addr), totalVolume(NAN), flowRate(NAN) {} + + virtual void ProcessMeasurement(void) + { + char data[D_EZO_MAX_BUF]; + // Total Volume, Flow Rate + + EZOStruct::ProcessMeasurement(data, sizeof(data), EZO_FLO_READ_LATENCY); + + totalVolume = CharToFloat(data); + + char *next = strchr(data, ','); + if (next) { + flowRate = CharToFloat(next + 1); + } + } + + virtual void Show(bool json, const char *name) + { + char volume[FLOATSZ]; + char rate[FLOATSZ]; + bool hasFlow = !isnan(flowRate); + + dtostrfd(totalVolume, 2, volume); + + dtostrfd(flowRate, 2, rate); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_VOLUME "\":%s"), name, volume); + if (hasFlow) { + ResponseAppend_P(PSTR(",\"" D_JSON_FLOWRATE "\":%s"), name, rate); + } + ResponseJsonEnd(); + +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_LITERS, name, volume); + + if (hasFlow) { + WSContentSend_PD(HTTP_SNS_LPM, name, rate); + } +#endif + } + } + + static const char id[] PROGMEM; + +private: + float totalVolume; + float flowRate; +}; + +const char EZOFLO::id[] PROGMEM = "FLO"; + +#endif // USE_EZOFLO +#endif // USE_I2C diff --git a/tasmota/xsns_78_ezohum.ino b/tasmota/xsns_78_ezohum.ino index 62b6edc68..a403eeb56 100644 --- a/tasmota/xsns_78_ezohum.ino +++ b/tasmota/xsns_78_ezohum.ino @@ -48,7 +48,7 @@ struct EZOHUM : public EZOStruct { dtostrfd(humidity, Settings.flag2.humidity_resolution, parameter); WSContentSend_PD(HTTP_SNS_HUM, name, parameter); } else { - TempHumDewShow(json, (0 == tele_period), name, temperature, humidity); + TempHumDewShow(json, (0 == TasmotaGlobal.tele_period), name, temperature, humidity); } } diff --git a/tasmota/xsns_78_ezoo2.ino b/tasmota/xsns_78_ezoo2.ino new file mode 100644 index 000000000..bc98fe00c --- /dev/null +++ b/tasmota/xsns_78_ezoo2.ino @@ -0,0 +1,60 @@ +/* + xsns_78_ezoo2.ino - EZO O2 I2C O2 sensor support for Tasmota + + Copyright (C) 2020 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 + 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_I2C +#ifdef USE_EZOO2 + +#define EZO_O2_READ_LATENCY 900 + +struct EZOO2 : public EZOStruct { + EZOO2(uint32_t addr) : EZOStruct(addr), O2(0) {} + + virtual void ProcessMeasurement(void) + { + char data[D_EZO_MAX_BUF]; + + EZOStruct::ProcessMeasurement(data, sizeof(data), EZO_O2_READ_LATENCY); + O2 = CharToFloat(data); + } + + virtual void Show(bool json, const char *name) + { + char str[8]; + dtostrfd(O2, 2, str); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_O2 "\":%d}" ), name, str); + } +#ifdef USE_WEBSERVER + else { + WSContentSend_PD(HTTP_SNS_O2, name, str); +#endif // USE_WEBSERVER + } + } + + static const char id[] PROGMEM; + +private: + float O2; +}; + +const char EZOO2::id[] PROGMEM = "O2"; + +#endif // USE_EZOO2 +#endif // USE_I2C diff --git a/tasmota/xsns_78_ezoprs.ino b/tasmota/xsns_78_ezoprs.ino new file mode 100644 index 000000000..9ad34ab0d --- /dev/null +++ b/tasmota/xsns_78_ezoprs.ino @@ -0,0 +1,69 @@ +/* + xsns_78_ezoprs.ino - EZO PRS I2C PRS sensor support for Tasmota + + Copyright (C) 2020 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 + 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_I2C +#ifdef USE_EZOPRS + +#define EZO_PRS_READ_LATENCY 900 + +struct EZOPRS : public EZOStruct { + EZOPRS(uint32_t addr) : EZOStruct(addr), pressure(NAN) {} + + virtual void ProcessMeasurement(void) + { + char data[D_EZO_MAX_BUF]; + + EZOStruct::ProcessMeasurement(data, sizeof(data), EZO_PRS_READ_LATENCY); + pressure = CharToFloat(data) * 68.9476f; // Convert to hPa + } + + virtual void Show(bool json, const char *name) + { + char str[33]; + char sealevelstr[33]; + dtostrfd(ConvertPressure(pressure), Settings.flag2.pressure_resolution, str); + dtostrfd(ConvertPressureForSeaLevel(pressure), Settings.flag2.pressure_resolution, sealevelstr); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_PRESSURE "\":%s"), name, str); + if (Settings.altitude != 0) { + ResponseAppend_P(PSTR(",\"" D_JSON_PRESSUREATSEALEVEL "\":%s"), sealevelstr); + } + ResponseJsonEnd(); + } +#ifdef USE_WEBSERVER + else { + WSContentSend_PD(HTTP_SNS_PRESSURE, name, str, PressureUnit().c_str()); + if (Settings.altitude != 0) { + WSContentSend_PD(HTTP_SNS_SEAPRESSURE, name, sealevelstr, PressureUnit().c_str()); + } +#endif // USE_WEBSERVER + } + } + + static const char id[] PROGMEM; + +private: + float pressure; +}; + +const char EZOPRS::id[] PROGMEM = "PRS"; + +#endif // USE_EZOPRS +#endif // USE_I2C diff --git a/tasmota/xsns_78_xezo.ino b/tasmota/xsns_78_xezo.ino index 0415c335d..95019cb50 100644 --- a/tasmota/xsns_78_xezo.ino +++ b/tasmota/xsns_78_xezo.ino @@ -49,29 +49,59 @@ enum { -// Creates a complex preprocessor macro to fetch a specified class OR EZOStruct if it wasn't defined -template struct IsComplete : std::false_type {}; -template struct IsComplete< T, decltype(void(sizeof(T))) > : std::true_type {}; - -#define GET_EZO_CLASS(CLASS) std::conditional::value, CLASS, EZOStruct>::type - // The order of the EZO devices must map with the enum declared above const char *const EZOSupport[EZO_ADDR_n] PROGMEM = { EZOStruct::id, // "DO" - GET_EZO_CLASS(EZOORP)::id, - GET_EZO_CLASS(EZOPH)::id, - GET_EZO_CLASS(EZOEC)::id, +#ifdef USE_EZOORP + EZOORP::id, +#else EZOStruct::id, - GET_EZO_CLASS(EZORTD)::id, +#endif +#ifdef USE_EZOPH + EZOPH::id, +#else + EZOStruct::id, +#endif +#ifdef USE_EZOEC + EZOEC::id, +#else + EZOStruct::id, +#endif + EZOStruct::id, +#ifdef USE_EZORTD + EZORTD::id, +#else + EZOStruct::id, +#endif EZOStruct::id, // "PMP" - EZOStruct::id, // "FLO" - GET_EZO_CLASS(EZOCO2)::id, - EZOStruct::id, // "PRS" +#ifdef USE_EZOFLO + EZOFLO::id, +#else EZOStruct::id, - EZOStruct::id, // "O2" +#endif +#ifdef USE_EZOCO2 + EZOCO2::id, +#else + EZOStruct::id, +#endif +#ifdef USE_EZOPRS + EZOPRS::id, +#else + EZOStruct::id, +#endif + EZOStruct::id, +#ifdef USE_EZOO2 + EZOO2::id, +#else + EZOStruct::id, +#endif EZOStruct::id, EZOStruct::id, - GET_EZO_CLASS(EZOHUM)::id, +#ifdef USE_EZOHUM + EZOHUM::id, +#else + EZOStruct::id, +#endif EZOStruct::id, // "RGB" }; @@ -116,12 +146,12 @@ struct EZOManager { // Do we have to deal with the 2 stage booting process? if (count < 0) { // EZO devices take 2s to boot - if (uptime >= next) { + if (TasmotaGlobal.uptime >= next) { count++; if (count == -1) { DetectRequest(); - next = uptime + 1; + next = TasmotaGlobal.uptime + 1; } else if (count == 0) { ProcessDetection(); } @@ -216,14 +246,22 @@ private: #ifdef USE_EZORTD CREATE_EZO_CLASS(RTD) #endif +#ifdef USE_EZOFLO + CREATE_EZO_CLASS(FLO) +#endif #ifdef USE_EZOCO2 CREATE_EZO_CLASS(CO2) #endif +#ifdef USE_EZOPRS + CREATE_EZO_CLASS(PRS) +#endif +#ifdef USE_EZOO2 + CREATE_EZO_CLASS(O2) +#endif #ifdef USE_EZOHUM CREATE_EZO_CLASS(HUM) #endif } - count++; } } diff --git a/tasmota/xsns_interface.ino b/tasmota/xsns_interface.ino index 0c85854de..c6427c0b7 100644 --- a/tasmota/xsns_interface.ino +++ b/tasmota/xsns_interface.ino @@ -917,7 +917,7 @@ bool XsnsCall(uint8_t Function) uint32_t profile_millis = millis() - profile_start_millis; if (profile_millis) { if (FUNC_EVERY_SECOND == Function) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PRF: At %08u XsnsCall %d to Sensor %d took %u mS"), uptime, Function, x, profile_millis); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PRF: At %08u XsnsCall %d to Sensor %d took %u mS"), TasmotaGlobal.uptime, Function, x, profile_millis); } } #endif // PROFILE_XSNS_SENSOR_EVERY_SECOND @@ -937,7 +937,7 @@ bool XsnsCall(uint8_t Function) uint32_t profile_millis = millis() - profile_start_millis; if (profile_millis) { if (FUNC_EVERY_SECOND == Function) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PRF: At %08u XsnsCall %d took %u mS"), uptime, Function, profile_millis); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PRF: At %08u XsnsCall %d took %u mS"), TasmotaGlobal.uptime, Function, profile_millis); } } #endif // PROFILE_XSNS_EVERY_SECOND diff --git a/tasmota/xx2c_interface.ino b/tasmota/xx2c_interface.ino index d27459027..5732fbaf9 100644 --- a/tasmota/xx2c_interface.ino +++ b/tasmota/xx2c_interface.ino @@ -414,7 +414,7 @@ const uint8_t kI2cList[] = { bool I2cEnabled(uint32_t i2c_index) { - return (i2c_flg && bitRead(Settings.i2c_drivers[i2c_index / 32], i2c_index % 32)); + return (TasmotaGlobal.i2c_enabled && bitRead(Settings.i2c_drivers[i2c_index / 32], i2c_index % 32)); } void I2cDriverState(void) diff --git a/tools/decode-status.py b/tools/decode-status.py index 1bff40a71..453832a27 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -234,7 +234,7 @@ a_features = [[ "USE_EZOPH","USE_TTGO_WATCH","USE_ETHERNET","USE_WEBCAM" ],[ "USE_EZOORP","USE_EZORTD","USE_EZOHUM","USE_EZOEC", - "","","","", + "USE_EZOCO2","USE_EZOO2","USE_EZOPRS","USE_EZOFLO", "","","","", "","","","", "","","","", @@ -268,7 +268,7 @@ else: obj = json.load(fp) def StartDecode(): - print ("\n*** decode-status.py v20201025 by Theo Arends and Jacek Ziolkowski ***") + print ("\n*** decode-status.py v20201101 by Theo Arends and Jacek Ziolkowski ***") # print("Decoding\n{}".format(obj))