Merge branch 'development' into patch-4

This commit is contained in:
Adrian Scillato 2019-12-21 23:15:43 -03:00 committed by GitHub
commit 17a0cb6982
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
58 changed files with 645 additions and 420 deletions

View File

@ -29,7 +29,7 @@ _Make sure your have performed every step and checked the applicable boxes befor
- [ ] Read the [Contributing Guide and Policy](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md) and [the Code of Conduct](https://github.com/arendst/Tasmota/blob/development/CODE_OF_CONDUCT.md)
- [ ] Searched the problem in [issues](https://github.com/arendst/Tasmota/issues)
- [ ] Searched the problem in the [wiki](https://github.com/arendst/Tasmota/wiki/Troubleshooting)
- [ ] Searched the problem in the [docs](https://tasmota.github.io/docs/#/help/FAQ)
- [ ] Searched the problem in the [forum](https://groups.google.com/d/forum/sonoffusers)
- [ ] Searched the problem in the [chat](https://discord.gg/Ks2Kzd4)
- [ ] Device used (e.g., Sonoff Basic): _____

View File

@ -10,7 +10,7 @@ Please take a few minutes to complete the requested information below. Our abili
DO NOT DELETE ANY TEXT from this template! Otherwise the issue will be auto-closed.
-->
**Have you looked for this feature in other issues and in the wiki?**
**Have you looked for this feature in other issues and in the docs?**
**Is your feature request related to a problem? Please describe.**
_A clear and concise description of what the problem is._

View File

@ -39,7 +39,7 @@ issueConfigs:
- "EXPECTED BEHAVIOUR"
- content:
# template 2: feature request
- "Have you looked for this feature in other issues and in the wiki"
- "Have you looked for this feature in other issues and in the docs"
- "Describe the solution you'd like"
# Optional configuration:

View File

@ -12,7 +12,7 @@ cache: false
env:
- ENV=tasmota
- ENV=tasmota-minimal
- ENV=tasmota-basic
- ENV=tasmota-lite
- ENV=tasmota-knx
- ENV=tasmota-sensors
- ENV=tasmota-display

View File

@ -1,6 +1,6 @@
## Available Features and Sensors
| Feature or Sensor | minimal | basic | tasmota | knx | sensors | ir | display | Remarks
| Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks
|-----------------------|---------|-------|--------|-----|---------|----|---------|--------
| MY_LANGUAGE en-GB | x | x | x | x | x | x | x |
| USE_ARDUINO_OTA | - | - | - | - | - | - | - |
@ -27,7 +27,7 @@
| USE_EXPRESSION | - | - | - | - | - | - | - |
| SUPPORT_IF_STATEMENT | - | - | - | - | - | - | - |
| | | | | | | | |
| Feature or Sensor | minimal | basic | tasmota | knx | sensors | ir | display | Remarks
| Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks
| ROTARY_V1 | - | - | - | - | - | - | - |
| USE_SONOFF_RF | - | - | x | x | x | - | - |
| USE_RF_FLASH | - | - | x | x | x | - | - |
@ -42,7 +42,7 @@
| USE_DEEPSLEEP | - | - | x | - | x | - | - |
| USE_EXS_DIMMER | - | - | x | x | - | - | - |
| | | | | | | | |
| Feature or Sensor | minimal | basic | tasmota | knx | sensors | ir | display | Remarks
| Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks
| USE_LIGHT | - | x | x | x | x | x | x |
| USE_WS2812 | - | - | x | x | x | - | x |
| USE_WS2812_DMA | - | - | - | - | - | - | - |
@ -69,7 +69,7 @@
| USE_MAX31855 | - | - | - | - | x | - | - |
| USE_MAX31865 | - | - | - | - | - | - | - |
| | | | | | | | |
| Feature or Sensor | minimal | basic | tasmota | knx | sensors | ir | display | Remarks
| Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks
| USE_I2C | - | - | x | x | x | - | x |
| USE_SHT | - | - | x | x | x | - | x |
| USE_HTU | - | - | x | x | x | - | x |
@ -106,8 +106,9 @@
| USE_PAJ7620 | - | - | - | - | - | - | - |
| USE_PCF8574 | - | - | - | - | - | - | - |
| USE_HIH6 | - | - | - | - | x | - | - |
| USE_DHT12 | - | - | - | - | x | - | - |
| | | | | | | | |
| Feature or Sensor | minimal | basic | tasmota | knx | sensors | ir | display | Remarks
| Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks
| USE_SPI | - | - | - | - | - | - | x |
| USE_MHZ19 | - | - | x | x | x | - | x |
| USE_SENSEAIR | - | - | x | x | x | - | x |
@ -133,7 +134,7 @@
| USE_A4988_STEPPER | - | - | - | - | - | - | - |
| USE_TASMOTA_SLAVE | - | - | - | - | - | - | - | Experimental
| | | | | | | | |
| Feature or Sensor | minimal | basic | tasmota | knx | sensors | ir | display | Remarks
| Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks
| USE_DISPLAY | - | - | - | - | - | - | x |
| USE_DISPLAY_LCD | - | - | - | - | - | - | x |
| USE_DISPLAY_SSD1306 | - | - | - | - | - | - | x |

View File

@ -61,4 +61,5 @@ Index | Define | Driver | Device | Address(es) | Description
38 | USE_DISPLAY_ILI9488 | xdsp_08 | FT6236 | 0x38 | Touch panel controller
39 | USE_DISPLAY_RA8876 | xdsp_10 | FT5316 | 0x38 | Touch panel controller
40 | USE_TSL2591 | xsns_57 | TLS2591 | 0x29 | Light intensity sensor
41 | USE_DHT12 | xsns_58 | DHT12 | 0x5C | Temperature and humidity sensor

View File

@ -20,7 +20,7 @@ In addition to the [release webpage](https://github.com/arendst/Tasmota/releases
## Development
[![Dev Version](https://img.shields.io/badge/development%20version-v7.1.2.x-blue.svg)](https://github.com/arendst/Tasmota)
[![Dev Version](https://img.shields.io/badge/development%20version-v7.2.x.x-blue.svg)](https://github.com/arendst/Tasmota)
[![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://thehackbox.org/tasmota/)
[![Build Status](https://img.shields.io/travis/arendst/Tasmota.svg)](https://travis-ci.org/arendst/Tasmota)

View File

@ -2,8 +2,6 @@
# RELEASE NOTES
### Sonoff-Tasmota is now Tasmota
## Migration Information
See [migration path](https://tasmota.github.io/docs/#/Upgrading?id=migration-path) for instructions how to migrate to a major version. Pay attention to the following version breaks due to dynamic settings updates:
@ -13,6 +11,7 @@ See [migration path](https://tasmota.github.io/docs/#/Upgrading?id=migration-pat
3. Migrate to **Sonoff-Tasmota 5.14**
4. Migrate to **Sonoff-Tasmota 6.x**
5. Migrate to **Tasmota 7.x**
6. Migrate to **Tasmota 8.x**
## Supported Core versions
@ -34,7 +33,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
- **tasmota.bin** = The Tasmota version with sensors. **RECOMMENDED RELEASE BINARY**
- **tasmota-BG.bin** to **tasmota-TW.bin** = The Tasmota version in different languages.
- **tasmota-basic.bin** = The Basic version without most sensors.
- **tasmota-lite.bin** = The Lite version without most sensors.
- **tasmota-knx.bin** = The Knx version without some features but adds KNX support.
- **tasmota-sensors.bin** = The Sensors version adds more useful sensors.
- **tasmota-ir** = The InfraRed Receiver and transmitter version allowing all available protocols provided by library IRremoteESP8266 but without most other features.
@ -47,27 +46,6 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
## Changelog
### Version 7.1.2.6
### Version 8.0.0.1
- Change Exception reporting removing exception details from ``Status 1`` and consolidated in ``Status 12`` if available
- Change HTTP CORS from command ``SetOption73 0/1`` to ``Cors <cors_domain>`` allowing user control of specific CORS domain by Shantur Rathore (#7066)
- Change GUI Shutter button text to Up and Down Arrows based on PR by Xavier Muller (#7166)
- Change amount of supported DHT sensors from 3 to 4 by Xavier Muller (#7167)
- Change some Settings locations freeing up space for future single char allowing variable length text
- Fix flashing H801 led at boot by Stefan Hadinger (#7165, #649)
- Fix duplicated ``Backlog`` when using Event inside a Backlog by Adrian Scillato (#7178, #7147)
- Fix Gui Timer when using a negative zero offset of -00:00 by Peter Ooms (#7174)
- Add command ``SerialConfig 0..23`` or ``SerialConfig 8N1`` to select Serial Config based in PR by Luis Teixeira (#7108)
- Add command ``Sensor34 9 <weight code>`` to set minimum delta to trigger JSON message by @tobox (#7188)
- Add rule var ``%topic%`` by Adrian Scillato (#5522)
- Add rule triggers ``tele-wifi1#xxx`` by Adrian Scillato (#7093)
- Add SML bus decoder syntax support for byte order by Gerhard Mutz (#7112)
- Add experimental support for stepper motor shutter control by Stefan Bode
- Add optional USE_MQTT_TLS to tasmota-minimal.bin by Bohdan Kmit (#7115)
- Add save call stack in RTC memory in case of crash, command ``Status 12`` to dump the stack by Stefan Hadinger
- Add Home Assistant force update by Frederico Leoni (#7140, #7074)
- Add Wifi Signal Strength in dBm in addition to RSSI Wifi Experience by Andreas Schultz (#7145)
- Add Yaw, Pitch and Roll support for MPU6050 by Philip Barclay (#7058)
- Add reporting of raw weight to JSON from HX711 to overcome auto-tare functionality by @tobox (#7171)
- Add Zigbee support for Xiaomi Aqara Vibration Sensor and Presence Sensor by Stefan Hadinger
- Add Shutter functions ramp up/down and MQTT reporting by Stefan Bode
- Change Settings text handling allowing variable length text within a total text pool of 699 characters

View File

@ -20,7 +20,7 @@ default_envs =
; tasmota
; tasmota-ircustom ; alternative to 'tasmota' with full IR protocols activated, you will need to disable some features to keep code not too big
; tasmota-minimal
; tasmota-basic
; tasmota-lite
; tasmota-knx
; tasmota-sensors
; tasmota-display

View File

@ -19,7 +19,7 @@ default_envs =
; tasmota-debug
; tasmota-ircustom ; alternative to 'tasmota' with full IR protocols activated, you will need to disable some features to keep code not too big
; tasmota-minimal
; tasmota-basic
; tasmota-lite
; tasmota-knx
; tasmota-sensors
; tasmota-display
@ -36,7 +36,7 @@ build_flags = ${core_active.build_flags}
; *** Optional Firmware configurations
; -DFIRMWARE_MINIMAL
; -DFIRMWARE_SENSORS
; -DFIRMWARE_BASIC
; -DFIRMWARE_LITE
; -DFIRMWARE_KNX_NO_EMULATION
; -DFIRMWARE_DISPLAYS
; -DFIRMWARE_IR

View File

@ -18,8 +18,8 @@ extra_scripts = ${common.extra_scripts}
[env:tasmota-minimal]
build_flags = ${common.build_flags} -DFIRMWARE_MINIMAL
[env:tasmota-basic]
build_flags = ${common.build_flags} -DFIRMWARE_BASIC
[env:tasmota-lite]
build_flags = ${common.build_flags} -DFIRMWARE_LITE
[env:tasmota-knx]
build_flags = ${common.build_flags} -DFIRMWARE_KNX_NO_EMULATION

View File

@ -1,11 +1,30 @@
## Unreleased (development)
### 8.0.0.1 20191221
- Change Settings text handling allowing variable length text within a total text pool of 699 characters
- Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179)
## Released
### 7.2.0 20191221
- Release
- Fix Arduino IDE compile error (#7277)
- Fix restore ShutterAccuracy, MqttLog, WifiConfig, WifiPower and SerialConfig (#7281)
- Fix no AP on initial install (#7282)
### 7.1.2.6 20191214
- Change some more Settings locations freeing up space for future single char allowing variable length text
- Change tasmota-basic.bin and FIRMWARE_BASIC to tasmota-lite.bin and FIRMWARE_LITE
- Fix DeepSleep in case there is no wifi by Stefan Bode (#7213)
- Fix Fade would ignore ``savedata 0`` and store to flash anyways (#7262)
- Add Zigbee send automatic ZigbeeRead after sending a command
- Add Zigbee improving Occupancy:false detection for Aqara sensor
- Add fallback functionality from next version 7.1.2.7
- Add fallback support from version 8.x
- Add restriction if fallback firmware is incompatible with settings resulting in unreachable device
- Add support for DHT12 Temperature and Humidity sensor by Stefan Oskamp
### 7.1.2.5 20191213
@ -46,8 +65,6 @@
- Add experimental support for stepper motor shutter control by Stefan Bode
- Add optional USE_MQTT_TLS to tasmota-minimal.bin by Bohdan Kmit (#7115)
## Released
### 7.1.2 20191206
- Maintenance Release

View File

@ -635,4 +635,8 @@ const char S_INFORMATION[] PROGMEM = D_INFORMATION;
const char S_RESTART[] PROGMEM = D_RESTART;
#endif // USE_WEBSERVER
const uint32_t MARKER_START = 0x5AA55AA5;
const uint32_t MARKER_END = 0xA55AA55A;
const uint32_t VERSION_MARKER[] PROGMEM = { MARKER_START, VERSION, MARKER_END };
#endif // _I18N_H_

View File

@ -353,6 +353,7 @@
#define D_UPLOAD_ERR_11 "Грешка при изтриване на RF чипа"
#define D_UPLOAD_ERR_12 "Грешка при записване в RF чипа"
#define D_UPLOAD_ERR_13 "Грешка при декодиране на RF фърмуера"
#define D_UPLOAD_ERR_14 "Not compatible"
#define D_UPLOAD_ERROR_CODE "Код на грешка при зареждането"
#define D_ENTER_COMMAND "Въвеждане на команда"

View File

@ -353,6 +353,7 @@
#define D_UPLOAD_ERR_11 "Chyba smazání RF chipu"
#define D_UPLOAD_ERR_12 "Chyba při zápisu do RF chipu"
#define D_UPLOAD_ERR_13 "Chyba dekódování RF firmwaru"
#define D_UPLOAD_ERR_14 "Not compatible"
#define D_UPLOAD_ERROR_CODE "Chyba nahrávání"
#define D_ENTER_COMMAND "Vlož příkaz"

View File

@ -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 v6.6.0.21
* Updated until v8.0.0
\*********************************************************************/
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
@ -353,6 +353,7 @@
#define D_UPLOAD_ERR_11 "RF Chip löschen fehlgeschlagen"
#define D_UPLOAD_ERR_12 "RF Chip beschreiben fehlgeschlagen"
#define D_UPLOAD_ERR_13 "RF Firmware ungültig"
#define D_UPLOAD_ERR_14 "Nicht kompatibel"
#define D_UPLOAD_ERROR_CODE "Upload Fehler Nummer"
#define D_ENTER_COMMAND "Befehl eingeben"

View File

@ -353,6 +353,7 @@
#define D_UPLOAD_ERR_11 "Αποτυχία σβησίματος στο RF chip"
#define D_UPLOAD_ERR_12 "Αποτυχία εγγραφής στο RF chip"
#define D_UPLOAD_ERR_13 "Failed to decode RF firmware"
#define D_UPLOAD_ERR_14 "Not compatible"
#define D_UPLOAD_ERROR_CODE "Κωδικός λάθους στη μεταφόρτωση"
#define D_ENTER_COMMAND "Εισαγωγή εντολής"

View File

@ -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 v6.2.1.11
* Updated until v8.0.0.0
\*********************************************************************/
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
@ -353,6 +353,7 @@
#define D_UPLOAD_ERR_11 "Failed to erase RF chip"
#define D_UPLOAD_ERR_12 "Failed to write to RF chip"
#define D_UPLOAD_ERR_13 "Failed to decode RF firmware"
#define D_UPLOAD_ERR_14 "Not compatible"
#define D_UPLOAD_ERROR_CODE "Upload error code"
#define D_ENTER_COMMAND "Enter command"

View File

@ -353,6 +353,7 @@
#define D_UPLOAD_ERR_11 "No se pudo borrar en el chip RF"
#define D_UPLOAD_ERR_12 "No se puedo escribir en el chip RF"
#define D_UPLOAD_ERR_13 "No se pudo decodificar firmware RF"
#define D_UPLOAD_ERR_14 "Not compatible"
#define D_UPLOAD_ERROR_CODE "Código de error de carga"
#define D_ENTER_COMMAND "Ingresar comando"

View File

@ -353,6 +353,7 @@
#define D_UPLOAD_ERR_11 "Erreur d'effacement du chip RF"
#define D_UPLOAD_ERR_12 "Erreur d'accès en écriture au chip RF"
#define D_UPLOAD_ERR_13 "Erreur de décodage du firmware RF"
#define D_UPLOAD_ERR_14 "Not compatible"
#define D_UPLOAD_ERROR_CODE "Code d'erreur téléchargement"
#define D_ENTER_COMMAND "Saisir une commande"

View File

@ -353,6 +353,7 @@
#define D_UPLOAD_ERR_11 "נכשלה RF מחיקת שבב"
#define D_UPLOAD_ERR_12 "נכשלה RF כתיבת שבב"
#define D_UPLOAD_ERR_13 "נכשלה RF קידוד קושחת שבב"
#define D_UPLOAD_ERR_14 "Not compatible"
#define D_UPLOAD_ERROR_CODE "שגיאת קוד העלאה"
#define D_ENTER_COMMAND "הקש פקודה"

View File

@ -353,6 +353,7 @@
#define D_UPLOAD_ERR_11 "Az RF chip törlése sikertelen"
#define D_UPLOAD_ERR_12 "Az RF chip írása sikertelen"
#define D_UPLOAD_ERR_13 "Az RF firmware dekódolása sikertelen"
#define D_UPLOAD_ERR_14 "Not compatible"
#define D_UPLOAD_ERROR_CODE "Feltöltési hibakód"
#define D_ENTER_COMMAND "Kérem a parancsot..."

View File

@ -353,6 +353,7 @@
#define D_UPLOAD_ERR_11 "Cancellazione fallita del chip RF"
#define D_UPLOAD_ERR_12 "Scrittura fallita del chip RF"
#define D_UPLOAD_ERR_13 "Decodifica fallita del firmware RF"
#define D_UPLOAD_ERR_14 "Not compatible"
#define D_UPLOAD_ERROR_CODE "Codice errore invio"
#define D_ENTER_COMMAND "Inserire comando"

View File

@ -353,6 +353,7 @@
#define D_UPLOAD_ERR_11 "RF 칩 삭제 실패"
#define D_UPLOAD_ERR_12 "RF 칩 쓰기 실패"
#define D_UPLOAD_ERR_13 "RF 펌웨어 decode 실패"
#define D_UPLOAD_ERR_14 "Not compatible"
#define D_UPLOAD_ERROR_CODE "업로드 에러 코드"
#define D_ENTER_COMMAND "커맨드 입력"

View File

@ -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 v6.7.0
* Updated until v8.0.0
\*********************************************************************/
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
@ -353,6 +353,7 @@
#define D_UPLOAD_ERR_11 "Wissen RF chip mislukt"
#define D_UPLOAD_ERR_12 "Opwaarderen RF chip mislukt"
#define D_UPLOAD_ERR_13 "Decoderen RF bestand mislukt"
#define D_UPLOAD_ERR_14 "Niet geschikt"
#define D_UPLOAD_ERROR_CODE "Opwaardeer foutcode"
#define D_ENTER_COMMAND "Geef opdracht"
@ -478,12 +479,12 @@
#define D_PARTICALS_BEYOND "Stofdeeltjes"
// xsns_32_mpu6050.ino
#define D_AX_AXIS "Accel. X-Axis"
#define D_AY_AXIS "Accel. Y-Axis"
#define D_AZ_AXIS "Accel. Z-Axis"
#define D_GX_AXIS "Gyro X-Axis"
#define D_GY_AXIS "Gyro Y-Axis"
#define D_GZ_AXIS "Gyro Z-Axis"
#define D_AX_AXIS "Versn. X-as"
#define D_AY_AXIS "Versn. Y-as"
#define D_AZ_AXIS "Versn. Z-as"
#define D_GX_AXIS "Gyro X-as"
#define D_GY_AXIS "Gyro Y-as"
#define D_GZ_AXIS "Gyro Z-as"
// xsns_34_hx711.ino
#define D_HX_CAL_REMOVE "Verwijder gewicht"
@ -626,9 +627,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "DeepSleep"
#define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_SLAVE_TX "Slave TX"
#define D_SENSOR_SLAVE_RX "Slave RX"
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_SLAVE_TX "Slave TX"
#define D_SENSOR_SLAVE_RX "Slave RX"
#define D_SENSOR_SLAVE_RESET "Slave RST"
#define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX"

View File

@ -353,6 +353,7 @@
#define D_UPLOAD_ERR_11 "Błąd kasowania układu RF"
#define D_UPLOAD_ERR_12 "Błąd zapisu układu RF"
#define D_UPLOAD_ERR_13 "Błąd dekodowania oprrogramowania układu RF"
#define D_UPLOAD_ERR_14 "Not compatible"
#define D_UPLOAD_ERROR_CODE "Błąd wgrywania"
#define D_ENTER_COMMAND "Wprowadź polecenie"

View File

@ -353,6 +353,7 @@
#define D_UPLOAD_ERR_11 "Falha ao apagar o chip RF"
#define D_UPLOAD_ERR_12 "Falha ao escrever o chip RF"
#define D_UPLOAD_ERR_13 "Falha ao decodificar o firmware de RF"
#define D_UPLOAD_ERR_14 "Not compatible"
#define D_UPLOAD_ERROR_CODE "Código de erro do envio"
#define D_ENTER_COMMAND "Inserir comando"

View File

@ -353,6 +353,7 @@
#define D_UPLOAD_ERR_11 "Falha ao apagar o chip de RF"
#define D_UPLOAD_ERR_12 "Falha ao escrever no chip de RF"
#define D_UPLOAD_ERR_13 "Falha ao descodificar o firmware RF"
#define D_UPLOAD_ERR_14 "Not compatible"
#define D_UPLOAD_ERROR_CODE "Código de erro do envio"
#define D_ENTER_COMMAND "Inserir comando"

View File

@ -353,6 +353,7 @@
#define D_UPLOAD_ERR_11 "Failed to erase RF chip"
#define D_UPLOAD_ERR_12 "Failed to write to RF chip"
#define D_UPLOAD_ERR_13 "Failed to decode RF firmware"
#define D_UPLOAD_ERR_14 "Not compatible"
#define D_UPLOAD_ERROR_CODE "Код ошибки загрузки"
#define D_ENTER_COMMAND "Введите команду"

View File

@ -353,6 +353,7 @@
#define D_UPLOAD_ERR_11 "Chyba zmazania RF chipu"
#define D_UPLOAD_ERR_12 "Chyba pri zápise do RF chipu"
#define D_UPLOAD_ERR_13 "Chyba dekódovania RF firmwaru"
#define D_UPLOAD_ERR_14 "Not compatible"
#define D_UPLOAD_ERROR_CODE "Chyba nahrávania"
#define D_ENTER_COMMAND "Vlož príkaz"

View File

@ -353,6 +353,7 @@
#define D_UPLOAD_ERR_11 "Misslyckades rensa RF chip"
#define D_UPLOAD_ERR_12 "Misslyckades skriva till RF chip"
#define D_UPLOAD_ERR_13 "Misslyckades avkoda RF firmware"
#define D_UPLOAD_ERR_14 "Not compatible"
#define D_UPLOAD_ERROR_CODE "Uppladdningsfelkod"
#define D_ENTER_COMMAND "Ange kommando"

View File

@ -353,6 +353,7 @@
#define D_UPLOAD_ERR_11 "Failed to erase RF chip"
#define D_UPLOAD_ERR_12 "Failed to write to RF chip"
#define D_UPLOAD_ERR_13 "Failed to decode RF firmware"
#define D_UPLOAD_ERR_14 "Not compatible"
#define D_UPLOAD_ERROR_CODE "Upload error code"
#define D_ENTER_COMMAND "Komut girişi"

View File

@ -353,6 +353,7 @@
#define D_UPLOAD_ERR_11 "Помилка стирання чипу RF"
#define D_UPLOAD_ERR_12 "Помилка запису чипу RF"
#define D_UPLOAD_ERR_13 "Помилка розкодування прошивки RF"
#define D_UPLOAD_ERR_14 "Not compatible"
#define D_UPLOAD_ERROR_CODE "Код помилки завантаження"
#define D_ENTER_COMMAND "Уведіть команду"

View File

@ -353,6 +353,7 @@
#define D_UPLOAD_ERR_11 "擦除 RF 芯片失败"
#define D_UPLOAD_ERR_12 "写入 RF 芯片失败"
#define D_UPLOAD_ERR_13 "解码 RF 固件失败"
#define D_UPLOAD_ERR_14 "Not compatible"
#define D_UPLOAD_ERROR_CODE "上传错误代码"
#define D_ENTER_COMMAND "输入命令"

View File

@ -353,6 +353,7 @@
#define D_UPLOAD_ERR_11 "Failed to erase RF chip"
#define D_UPLOAD_ERR_12 "Failed to write to RF chip"
#define D_UPLOAD_ERR_13 "Failed to decode RF firmware"
#define D_UPLOAD_ERR_14 "Not compatible"
#define D_UPLOAD_ERROR_CODE "上傳錯誤代碼"
#define D_ENTER_COMMAND "輸入命令"

View File

@ -418,6 +418,7 @@
// #define USE_PAJ7620 // [I2cDriver34] Enable PAJ7620 gesture sensor (I2C address 0x73) (+2.5k code)
// #define USE_PCF8574 // [I2cDriver2] Enable PCF8574 I/O Expander (I2C addresses 0x20 - 0x26 and 0x39 - 0x3F) (+1k9 code)
// #define USE_HIH6 // [I2cDriver36] Enable Honeywell HIH Humidity and Temperature sensor (I2C address 0x27) (+0k6)
// #define USE_DHT12 // [I2cDriver41] Enable DHT12 humidity and temperature sensor (I2C address 0x5C) (+0k7 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
@ -572,7 +573,7 @@
* See RELEASENOTES.md for selected features
\*********************************************************************************************/
//#define FIRMWARE_BASIC // Create tasmota-basic with no sensors
//#define FIRMWARE_LITE // Create tasmota-lite with no sensors
//#define FIRMWARE_SENSORS // Create tasmota-sensors with useful sensors enabled
//#define FIRMWARE_KNX_NO_EMULATION // Create tasmota-knx with KNX but without Emulation
//#define FIRMWARE_DISPLAYS // Create tasmota-display with display drivers enabled

View File

@ -91,7 +91,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
uint32_t grouptopic_mode : 1; // bit 25 (v7.0.0.1) - SetOption75 - GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1)
uint32_t bootcount_update : 1; // bit 26 (v7.0.0.4) - SetOption76 - Enable incrementing bootcount when deepsleep is enabled
uint32_t slider_dimmer_stay_on : 1; // bit 27 (v7.0.0.6) - SetOption77 - Do not power off if slider moved to far left
uint32_t spare28 : 1;
uint32_t compatibility_check : 1; // bit 28 (v7.1.2.6) - SetOption78 - Disable OTA compatibility check
uint32_t spare29 : 1;
uint32_t shutter_mode : 1; // bit 30 (v6.6.0.14) - SetOption80 - Enable shutter support
uint32_t pcf8574_ports_inverted : 1; // bit 31 (v6.6.0.14) - SetOption81 - Invert all ports on PCF8574 devices
@ -231,13 +231,6 @@ typedef struct {
const uint8_t MAX_TUYA_FUNCTIONS = 16;
/*
struct SYSCFG {
unsigned long cfg_holder; // 000 Pre v6 header
unsigned long save_flag; // 004
unsigned long version; // 008
unsigned long bootcount; // 00C
*/
struct SYSCFG {
uint16_t cfg_holder; // 000 v6 header
uint16_t cfg_size; // 002
@ -274,8 +267,6 @@ struct SYSCFG {
uint8_t ex_free_1d6[10]; // 1D6
// End of single char array of 456 chars max (phase 3)
SysBitfield4 ex_flag4; // 1E0
uint8_t ex_serial_config; // 1E4
uint8_t ex_wifi_output_power; // 1E5
@ -428,7 +419,7 @@ struct SYSCFG {
unsigned long weight_calibration; // 7C4
unsigned long energy_frequency_calibration; // 7C8 also used by HX711 to save last weight
uint16_t web_refresh; // 7CC
char mems[MAX_RULE_MEMS][10]; // 7CE
char mems[MAX_RULE_MEMS][10]; // 7CE - Used by scripter as script_pram
char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b

View File

@ -343,6 +343,48 @@ void SetFlashModeDout(void)
delete[] _buffer;
}
uint32_t OtaVersion(void)
{
if (Settings.flag3.compatibility_check) {
return 0xFFFFFFFF;
}
eboot_command ebcmd;
eboot_command_read(&ebcmd);
uint32_t start_address = ebcmd.args[0];
uint32_t end_address = start_address + (ebcmd.args[2] & 0xFFFFF000) + FLASH_SECTOR_SIZE;
uint32_t* buffer = new uint32_t[FLASH_SECTOR_SIZE / 4];
uint32_t version[3] = { 0 };
bool found = false;
for (uint32_t address = start_address; address < end_address; address = address + FLASH_SECTOR_SIZE) {
ESP.flashRead(address, (uint32_t*)buffer, FLASH_SECTOR_SIZE);
for (uint32_t i = 0; i < (FLASH_SECTOR_SIZE / 4); i++) {
version[0] = version[1];
version[1] = version[2];
version[2] = buffer[i];
if ((version[0] == MARKER_START) && (version[2] == MARKER_END)) {
found = true;
break;
}
}
if (found) { break; }
}
delete[] buffer;
if (!found) { version[1] = 0; }
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("OTA: Version 0x%08X, Compatible 0x%08X"), version[1], VERSION_COMPATIBLE);
return version[1];
}
void AbandonOta(void)
{
uint32_t eboot_magic = 0;
ESP.rtcUserMemoryWrite(0, (uint32_t*)&eboot_magic, sizeof(eboot_magic));
}
void SettingsBufferFree(void)
{
if (settings_buffer != nullptr) {
@ -446,10 +488,7 @@ void UpdateQuickPowerCycle(bool update)
* Config Settings.text char array support
\*********************************************************************************************/
char aws_mqtt_host[66];
char aws_mqtt_user[1] { 0 };
const uint32_t settings_text_size = 457; // Settings.flag4 (1E0) - Settings.ota_url (017)
const uint32_t settings_text_size = 699; // Settings.flag4 (2D2) - Settings.ota_url (017)
uint32_t GetSettingsTextLen(void)
{
@ -471,98 +510,43 @@ bool SettingsUpdateText(uint32_t index, const char* replace_me)
char replace[replace_len +1];
memcpy(replace, replace_me, sizeof(replace));
if (Settings.version < 0x07010207) {
uint32_t idx = 0;
switch (index) {
case SET_OTAURL: strlcpy(Settings.ota_url, replace, sizeof(Settings.ota_url)); break;
case SET_MQTTPREFIX3: idx++;
case SET_MQTTPREFIX2: idx++;
case SET_MQTTPREFIX1: strlcpy(Settings.mqtt_prefix[idx], replace, sizeof(Settings.mqtt_prefix[idx])); break;
case SET_STASSID2: idx++;
case SET_STASSID1: strlcpy(Settings.sta_ssid[idx], replace, sizeof(Settings.sta_ssid[idx])); break;
case SET_STAPWD2: idx++;
case SET_STAPWD1: strlcpy(Settings.sta_pwd[idx], replace, sizeof(Settings.sta_pwd[idx])); break;
case SET_HOSTNAME: strlcpy(Settings.hostname, replace, sizeof(Settings.hostname)); break;
case SET_SYSLOG_HOST: strlcpy(Settings.syslog_host, replace, sizeof(Settings.syslog_host)); break;
case SET_WEBPWD: strlcpy(Settings.web_password, replace, sizeof(Settings.web_password)); break;
#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT)
case SET_MQTT_HOST:
if (strlen(replace) <= sizeof(Settings.mqtt_host)) {
strlcpy(Settings.mqtt_host, replace, sizeof(Settings.mqtt_host));
Settings.mqtt_user[0] = 0;
} else {
// need to split in mqtt_user first then mqtt_host
strlcpy(Settings.mqtt_user, replace, sizeof(Settings.mqtt_user));
strlcpy(Settings.mqtt_host, &replace[sizeof(Settings.mqtt_user)-1], sizeof(Settings.mqtt_host));
}
break;
case SET_MQTT_USER: break;
#else
case SET_MQTT_HOST: strlcpy(Settings.mqtt_host, replace, sizeof(Settings.mqtt_host)); break;
case SET_MQTT_USER: strlcpy(Settings.mqtt_user, replace, sizeof(Settings.mqtt_user)); break;
#endif
case SET_MQTT_CLIENT: strlcpy(Settings.mqtt_client, replace, sizeof(Settings.mqtt_client)); break;
case SET_MQTT_PWD: strlcpy(Settings.mqtt_pwd, replace, sizeof(Settings.mqtt_pwd)); break;
case SET_MQTT_FULLTOPIC: strlcpy(Settings.mqtt_fulltopic, replace, sizeof(Settings.mqtt_fulltopic)); break;
case SET_MQTT_TOPIC: strlcpy(Settings.mqtt_topic, replace, sizeof(Settings.mqtt_topic)); break;
case SET_MQTT_BUTTON_TOPIC: strlcpy(Settings.button_topic, replace, sizeof(Settings.button_topic)); break;
case SET_MQTT_SWITCH_TOPIC: strlcpy(Settings.switch_topic, replace, sizeof(Settings.switch_topic)); break;
case SET_MQTT_GRP_TOPIC: strlcpy(Settings.mqtt_grptopic, replace, sizeof(Settings.mqtt_grptopic)); break;
case SET_STATE_TXT4: idx++;
case SET_STATE_TXT3: idx++;
case SET_STATE_TXT2: idx++;
case SET_STATE_TXT1: strlcpy(Settings.state_text[idx], replace, sizeof(Settings.state_text[idx])); break;
case SET_NTPSERVER3: idx++;
case SET_NTPSERVER2: idx++;
case SET_NTPSERVER1: strlcpy(Settings.ntp_server[idx], replace, sizeof(Settings.ntp_server[idx])); break;
case SET_MEM5: idx++;
case SET_MEM4: idx++;
case SET_MEM3: idx++;
case SET_MEM2: idx++;
case SET_MEM1: strlcpy(Settings.mems[idx], replace, sizeof(Settings.mems[idx])); break;
case SET_CORS: strlcpy(Settings.cors_domain, replace, sizeof(Settings.cors_domain)); break;
case SET_FRIENDLYNAME4: idx++;
case SET_FRIENDLYNAME3: idx++;
case SET_FRIENDLYNAME2: idx++;
case SET_FRIENDLYNAME1: strlcpy(Settings.friendlyname[idx], replace, sizeof(Settings.friendlyname[idx])); break;
uint32_t start_pos = 0;
uint32_t end_pos = 0;
char* position = Settings.ota_url;
for (uint32_t size = 0; size < SET_MAX; size++) {
while (*position++ != '\0') { }
if (1 == index) {
start_pos = position - Settings.ota_url;
}
} else {
uint32_t start_pos = 0;
uint32_t end_pos = 0;
char* position = Settings.ota_url;
for (uint32_t size = 0; size < SET_MAX; size++) {
while (*position++ != '\0') { }
if (1 == index) {
start_pos = position - Settings.ota_url;
}
else if (0 == index) {
end_pos = position - Settings.ota_url -1;
}
index--;
else if (0 == index) {
end_pos = position - Settings.ota_url -1;
}
uint32_t char_len = position - Settings.ota_url;
uint32_t current_len = end_pos - start_pos;
int diff = replace_len - current_len;
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TST: start %d, end %d, len %d, current %d, replace %d, diff %d"),
// start_pos, end_pos, char_len, current_len, replace_len, diff);
int too_long = (char_len + diff) - settings_text_size;
if (too_long > 0) {
// AddLog_P2(LOG_LEVEL_INFO, PSTR("CFG: Text too long by %d char(s)"), too_long);
return false; // Replace text too long
}
if (diff != 0) {
// Shift Settings.text up or down
memmove_P(Settings.ota_url + start_pos + replace_len, Settings.ota_url + end_pos, char_len - end_pos);
}
// Replace text
memmove_P(Settings.ota_url + start_pos, replace, replace_len);
// Fill for future use
memset(Settings.ota_url + char_len + diff, 0x00, settings_text_size - char_len - diff);
index--;
}
uint32_t char_len = position - Settings.ota_url;
uint32_t current_len = end_pos - start_pos;
int diff = replace_len - current_len;
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TST: start %d, end %d, len %d, current %d, replace %d, diff %d"),
// start_pos, end_pos, char_len, current_len, replace_len, diff);
int too_long = (char_len + diff) - settings_text_size;
if (too_long > 0) {
// AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_CONFIG "Text too long by %d char(s)"), too_long);
return false; // Replace text too long
}
if (diff != 0) {
// Shift Settings.text up or down
memmove_P(Settings.ota_url + start_pos + replace_len, Settings.ota_url + end_pos, char_len - end_pos);
}
// Replace text
memmove_P(Settings.ota_url + start_pos, replace, replace_len);
// Fill for future use
memset(Settings.ota_url + char_len + diff, 0x00, settings_text_size - char_len - diff);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG "CR %d/%d"), GetSettingsTextLen(), settings_text_size);
return true;
}
@ -574,62 +558,9 @@ char* SettingsText(uint32_t index)
}
char* position = Settings.ota_url;
if (Settings.version < 0x07010207) {
uint32_t idx = 0;
switch (index) {
case SET_MQTTPREFIX3: idx++;
case SET_MQTTPREFIX2: idx++;
case SET_MQTTPREFIX1: position = Settings.mqtt_prefix[idx]; break;
case SET_STASSID2: idx++;
case SET_STASSID1: position = Settings.sta_ssid[idx]; break;
case SET_STAPWD2: idx++;
case SET_STAPWD1: position = Settings.sta_pwd[idx]; break;
case SET_HOSTNAME: position = Settings.hostname; break;
case SET_SYSLOG_HOST: position = Settings.syslog_host; break;
case SET_WEBPWD: position = Settings.web_password; break;
#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT)
case SET_MQTT_HOST:
strlcpy(aws_mqtt_host, Settings.mqtt_user, strlen(Settings.mqtt_user));
strlcpy(&aws_mqtt_host[strlen(Settings.mqtt_user)], Settings.mqtt_host, sizeof(Settings.mqtt_host));
position = aws_mqtt_host; break;
case SET_MQTT_USER: position = aws_mqtt_user; break;
#else
case SET_MQTT_HOST: position = Settings.mqtt_host; break;
case SET_MQTT_USER: position = Settings.mqtt_user; break;
#endif
case SET_MQTT_CLIENT: position = Settings.mqtt_client; break;
case SET_MQTT_PWD: position = Settings.mqtt_pwd; break;
case SET_MQTT_FULLTOPIC: position = Settings.mqtt_fulltopic; break;
case SET_MQTT_TOPIC: position = Settings.mqtt_topic; break;
case SET_MQTT_BUTTON_TOPIC: position = Settings.button_topic; break;
case SET_MQTT_SWITCH_TOPIC: position = Settings.switch_topic; break;
case SET_MQTT_GRP_TOPIC: position = Settings.mqtt_grptopic; break;
case SET_STATE_TXT4: idx++;
case SET_STATE_TXT3: idx++;
case SET_STATE_TXT2: idx++;
case SET_STATE_TXT1: position = Settings.state_text[idx]; break;
case SET_NTPSERVER3: idx++;
case SET_NTPSERVER2: idx++;
case SET_NTPSERVER1: position = Settings.ntp_server[idx]; break;
case SET_MEM5: idx++;
case SET_MEM4: idx++;
case SET_MEM3: idx++;
case SET_MEM2: idx++;
case SET_MEM1: position = Settings.mems[idx]; break;
case SET_CORS: position = Settings.cors_domain; break;
case SET_FRIENDLYNAME4: idx++;
case SET_FRIENDLYNAME3: idx++;
case SET_FRIENDLYNAME2: idx++;
case SET_FRIENDLYNAME1: position = Settings.friendlyname[idx]; break;
}
} else {
for (;index > 0; index--) {
while (*position++ != '\0') { }
}
for (;index > 0; index--) {
while (*position++ != '\0') { }
}
return position;
}
@ -1309,8 +1240,8 @@ void SettingsDelta(void)
memset((char*)&Settings +0x1D6, 0x00, 16);
}
if (Settings.version < 0x0606000F) {
Settings.shutter_accuracy = 0;
Settings.mqttlog_level = MQTT_LOG_LEVEL;
Settings.ex_shutter_accuracy = 0;
Settings.ex_mqttlog_level = MQTT_LOG_LEVEL;
}
if (Settings.version < 0x06060011) {
Settings.param[P_BACKLOG_DELAY] = MIN_BACKLOG_DELAY;
@ -1350,7 +1281,7 @@ void SettingsDelta(void)
}
if (Settings.version < 0x06060015) {
if ((EX_WIFI_SMARTCONFIG == Settings.sta_config) || (EX_WIFI_WPSCONFIG == Settings.sta_config)) {
Settings.sta_config = WIFI_MANAGER;
Settings.ex_sta_config = WIFI_MANAGER;
}
}
@ -1363,10 +1294,10 @@ void SettingsDelta(void)
SettingsEnableAllI2cDrivers();
}
if (Settings.version < 0x07000004) {
Settings.wifi_output_power = 170;
Settings.ex_wifi_output_power = 170;
}
if (Settings.version < 0x07010202) {
Settings.serial_config = TS_SERIAL_8N1;
Settings.ex_serial_config = TS_SERIAL_8N1;
}
if (Settings.version < 0x07010204) {
if (Settings.flag3.ex_cors_enabled == 1) {
@ -1387,20 +1318,26 @@ void SettingsDelta(void)
memcpy((char*)&Settings.serial_config, (char*)&Settings.ex_serial_config, 5); // 1E4 -> EFE
}
if ((VERSION < 0x7010207) && (Settings.version > VERSION)) {
char temp[strlen(SettingsText(SET_OTAURL)) +1]; strncpy(temp, SettingsText(SET_OTAURL), sizeof(temp));
char temp21[strlen(SettingsText(SET_MQTTPREFIX1)) +1]; strncpy(temp21, SettingsText(SET_MQTTPREFIX1), sizeof(temp21));
char temp22[strlen(SettingsText(SET_MQTTPREFIX2)) +1]; strncpy(temp22, SettingsText(SET_MQTTPREFIX2), sizeof(temp22));
char temp23[strlen(SettingsText(SET_MQTTPREFIX3)) +1]; strncpy(temp23, SettingsText(SET_MQTTPREFIX3), sizeof(temp23));
char temp31[strlen(SettingsText(SET_STASSID1)) +1]; strncpy(temp31, SettingsText(SET_STASSID1), sizeof(temp31));
char temp32[strlen(SettingsText(SET_STASSID2)) +1]; strncpy(temp32, SettingsText(SET_STASSID2), sizeof(temp32));
char temp41[strlen(SettingsText(SET_STAPWD1)) +1]; strncpy(temp41, SettingsText(SET_STAPWD1), sizeof(temp41));
char temp42[strlen(SettingsText(SET_STAPWD2)) +1]; strncpy(temp42, SettingsText(SET_STAPWD2), sizeof(temp42));
char temp5[strlen(SettingsText(SET_HOSTNAME)) +1]; strncpy(temp5, SettingsText(SET_HOSTNAME), sizeof(temp5));
char temp6[strlen(SettingsText(SET_SYSLOG_HOST)) +1]; strncpy(temp6, SettingsText(SET_SYSLOG_HOST), sizeof(temp5));
if (Settings.version < 0x08000000) {
char temp[strlen(Settings.ota_url) +1]; strncpy(temp, Settings.ota_url, sizeof(temp));
char temp21[strlen(Settings.mqtt_prefix[0]) +1]; strncpy(temp21, Settings.mqtt_prefix[0], sizeof(temp21));
char temp22[strlen(Settings.mqtt_prefix[1]) +1]; strncpy(temp22, Settings.mqtt_prefix[1], sizeof(temp22));
char temp23[strlen(Settings.mqtt_prefix[2]) +1]; strncpy(temp23, Settings.mqtt_prefix[2], sizeof(temp23));
char temp31[strlen(Settings.sta_ssid[0]) +1]; strncpy(temp31, Settings.sta_ssid[0], sizeof(temp31));
char temp32[strlen(Settings.sta_ssid[1]) +1]; strncpy(temp32, Settings.sta_ssid[1], sizeof(temp32));
char temp41[strlen(Settings.sta_pwd[0]) +1]; strncpy(temp41, Settings.sta_pwd[0], sizeof(temp41));
char temp42[strlen(Settings.sta_pwd[1]) +1]; strncpy(temp42, Settings.sta_pwd[1], sizeof(temp42));
char temp5[strlen(Settings.hostname) +1]; strncpy(temp5, Settings.hostname, sizeof(temp5));
char temp6[strlen(Settings.syslog_host) +1]; strncpy(temp6, Settings.syslog_host, sizeof(temp6));
char temp7[strlen(Settings.mqtt_host) +1]; strncpy(temp7, Settings.mqtt_host, sizeof(temp7));
char temp8[strlen(Settings.mqtt_client) +1]; strncpy(temp8, Settings.mqtt_client, sizeof(temp8));
char temp9[strlen(Settings.mqtt_user) +1]; strncpy(temp9, Settings.mqtt_user, sizeof(temp9));
char temp10[strlen(Settings.mqtt_pwd) +1]; strncpy(temp10, Settings.mqtt_pwd, sizeof(temp10));
char temp11[strlen(Settings.mqtt_topic) +1]; strncpy(temp11, Settings.mqtt_topic, sizeof(temp11));
char temp12[strlen(Settings.button_topic) +1]; strncpy(temp12, Settings.button_topic, sizeof(temp12));
char temp13[strlen(Settings.mqtt_grptopic) +1]; strncpy(temp13, Settings.mqtt_grptopic, sizeof(temp13));
uint32_t version = Settings.version;
Settings.version = VERSION;
memset(Settings.ota_url, 0x00, settings_text_size);
SettingsUpdateText(SET_OTAURL, temp);
SettingsUpdateText(SET_MQTTPREFIX1, temp21);
SettingsUpdateText(SET_MQTTPREFIX2, temp22);
@ -1411,7 +1348,46 @@ void SettingsDelta(void)
SettingsUpdateText(SET_STAPWD2, temp42);
SettingsUpdateText(SET_HOSTNAME, temp5);
SettingsUpdateText(SET_SYSLOG_HOST, temp6);
Settings.version = version;
#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT)
if (!strlen(Settings.mqtt_user)) {
SettingsUpdateText(SET_MQTT_HOST, temp7);
SettingsUpdateText(SET_MQTT_USER, temp9);
} else {
char aws_mqtt_host[66];
snprintf_P(aws_mqtt_host, sizeof(aws_mqtt_host), PSTR("%s%s"), temp9, temp7);
SettingsUpdateText(SET_MQTT_HOST, aws_mqtt_host);
SettingsUpdateText(SET_MQTT_USER, "");
}
#else
SettingsUpdateText(SET_MQTT_HOST, temp7);
SettingsUpdateText(SET_MQTT_USER, temp9);
#endif
SettingsUpdateText(SET_MQTT_CLIENT, temp8);
SettingsUpdateText(SET_MQTT_PWD, temp10);
SettingsUpdateText(SET_MQTT_TOPIC, temp11);
SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, temp12);
SettingsUpdateText(SET_MQTT_GRP_TOPIC, temp13);
SettingsUpdateText(SET_WEBPWD, Settings.web_password);
SettingsUpdateText(SET_CORS, Settings.cors_domain);
SettingsUpdateText(SET_MQTT_FULLTOPIC, Settings.mqtt_fulltopic);
SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, Settings.switch_topic);
SettingsUpdateText(SET_STATE_TXT1, Settings.state_text[0]);
SettingsUpdateText(SET_STATE_TXT2, Settings.state_text[1]);
SettingsUpdateText(SET_STATE_TXT3, Settings.state_text[2]);
SettingsUpdateText(SET_STATE_TXT4, Settings.state_text[3]);
SettingsUpdateText(SET_NTPSERVER1, Settings.ntp_server[0]);
SettingsUpdateText(SET_NTPSERVER2, Settings.ntp_server[1]);
SettingsUpdateText(SET_NTPSERVER3, Settings.ntp_server[2]);
SettingsUpdateText(SET_MEM1, Settings.mems[0]);
SettingsUpdateText(SET_MEM2, Settings.mems[1]);
SettingsUpdateText(SET_MEM3, Settings.mems[2]);
SettingsUpdateText(SET_MEM4, Settings.mems[3]);
SettingsUpdateText(SET_MEM5, Settings.mems[4]);
SettingsUpdateText(SET_FRIENDLYNAME1, Settings.friendlyname[0]);
SettingsUpdateText(SET_FRIENDLYNAME2, Settings.friendlyname[1]);
SettingsUpdateText(SET_FRIENDLYNAME3, Settings.friendlyname[2]);
SettingsUpdateText(SET_FRIENDLYNAME4, Settings.friendlyname[3]);
}
Settings.version = VERSION;

View File

@ -995,6 +995,13 @@ int ResponseJsonEndEnd(void)
* GPIO Module and Template management
\*********************************************************************************************/
void DigitalWrite(uint32_t gpio_pin, uint32_t state)
{
if (pin[gpio_pin] < 99) {
digitalWrite(pin[gpio_pin], state &1);
}
}
uint8_t ModuleNr(void)
{
// 0 = User module (255)

View File

@ -489,7 +489,9 @@ void GetFeatures(void)
#ifdef USE_TSL2591
feature5 |= 0x00080000;
#endif
// feature5 |= 0x00100000;
#ifdef USE_DHT12
feature5 |= 0x00100000;
#endif
// feature5 |= 0x00200000;
// feature5 |= 0x00400000;
// feature5 |= 0x00800000;

View File

@ -108,7 +108,7 @@ char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopi
fulltopic += FPSTR(MQTT_TOKEN_PREFIX); // Need prefix for commands to handle mqtt topic loops
}
for (uint32_t i = 0; i < 3; i++) {
if ('\0' == SettingsText(SET_MQTTPREFIX1 + i)) {
if (!strlen(SettingsText(SET_MQTTPREFIX1 + i))) {
char temp[TOPSZ];
SettingsUpdateText(SET_MQTTPREFIX1 + i, GetTextIndexed(temp, sizeof(temp), i, kPrefixes));
}
@ -166,9 +166,7 @@ void SetLatchingRelay(power_t lpower, uint32_t state)
for (uint32_t i = 0; i < devices_present; i++) {
uint32_t port = (i << 1) + ((latching_power >> i) &1);
if (pin[GPIO_REL1 +port] < 99) {
digitalWrite(pin[GPIO_REL1 +port], bitRead(rel_inverted, port) ? !state : state);
}
DigitalWrite(GPIO_REL1 +port, bitRead(rel_inverted, port) ? !state : state);
}
}
@ -226,8 +224,8 @@ void SetDevicePower(power_t rpower, uint32_t source)
else {
for (uint32_t i = 0; i < devices_present; i++) {
power_t state = rpower &1;
if ((i < MAX_RELAYS) && (pin[GPIO_REL1 +i] < 99)) {
digitalWrite(pin[GPIO_REL1 +i], bitRead(rel_inverted, i) ? !state : state);
if (i < MAX_RELAYS) {
DigitalWrite(GPIO_REL1 +i, bitRead(rel_inverted, i) ? !state : state);
}
rpower >>= 1;
}
@ -293,7 +291,7 @@ void SetLedPowerIdx(uint32_t led, uint32_t state)
} else {
led_power &= (0xFF ^ mask);
}
digitalWrite(pin[GPIO_LED1 + led], bitRead(led_inverted, led) ? !state : state);
DigitalWrite(GPIO_LED1 + led, bitRead(led_inverted, led) ? !state : state);
}
}
@ -868,13 +866,21 @@ void Every250mSeconds(void)
}
if (90 == ota_state_flag) { // Allow MQTT to reconnect
ota_state_flag = 0;
Response_P(PSTR("{\"" D_CMND_UPGRADE "\":\""));
if (ota_result) {
// SetFlashModeDout(); // Force DOUT for both ESP8266 and ESP8285
Response_P(PSTR(D_JSON_SUCCESSFUL ". " D_JSON_RESTARTING));
if (OtaVersion() < VERSION_COMPATIBLE) {
AbandonOta();
ResponseAppend_P(PSTR(D_JSON_FAILED " " D_UPLOAD_ERR_14));
} else {
ResponseAppend_P(PSTR(D_JSON_SUCCESSFUL ". " D_JSON_RESTARTING));
restart_flag = 2;
}
} else {
Response_P(PSTR(D_JSON_FAILED " %s"), ESPhttpUpdate.getLastErrorString().c_str());
ResponseAppend_P(PSTR(D_JSON_FAILED " %s"), ESPhttpUpdate.getLastErrorString().c_str());
}
restart_flag = 2; // Restart anyway to keep memory clean webserver
ResponseAppend_P(PSTR("\"}"));
// restart_flag = 2; // Restart anyway to keep memory clean webserver
MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_UPGRADE));
}
}

View File

@ -191,7 +191,7 @@ void WifiBegin(uint8_t flag, uint8_t channel)
case 2: // Toggle
Settings.sta_active ^= 1;
} // 3: Current AP
if ('\0' == SettingsText(SET_STASSID1 + Settings.sta_active)) {
if (!strlen(SettingsText(SET_STASSID1 + Settings.sta_active))) {
Settings.sta_active ^= 1; // Skip empty SSID
}
if (Settings.ip_address[0]) {
@ -436,7 +436,7 @@ void WifiCheckIp(void)
if (!Wifi.retry || ((Wifi.retry_init / 2) == Wifi.retry)) {
AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_TIMEOUT));
} else {
if (('\0' == SettingsText(SET_STASSID1)) && ('\0' == SettingsText(SET_STASSID2))) {
if (!strlen(SettingsText(SET_STASSID1)) && !strlen(SettingsText(SET_STASSID2))) {
wifi_config_tool = WIFI_MANAGER; // Skip empty SSIDs and start Wifi config tool
Wifi.retry = 0;
} else {

View File

@ -277,15 +277,15 @@ enum SettingsTextIndex { SET_OTAURL,
SET_STASSID1, SET_STASSID2,
SET_STAPWD1, SET_STAPWD2,
SET_HOSTNAME, SET_SYSLOG_HOST,
SET_WEBPWD,
SET_WEBPWD, SET_CORS,
SET_MQTT_HOST, SET_MQTT_CLIENT,
SET_MQTT_USER, SET_MQTT_PWD,
SET_MQTT_FULLTOPIC, SET_MQTT_TOPIC,
SET_MQTT_BUTTON_TOPIC, SET_MQTT_SWITCH_TOPIC, SET_MQTT_GRP_TOPIC,
SET_STATE_TXT1, SET_STATE_TXT2, SET_STATE_TXT3, SET_STATE_TXT4,
SET_NTPSERVER1, SET_NTPSERVER2, SET_NTPSERVER3,
SET_MEM1, SET_MEM2, SET_MEM3, SET_MEM4, SET_MEM5,
SET_CORS,
SET_MEM1, SET_MEM2, SET_MEM3, SET_MEM4, SET_MEM5, SET_MEM6, SET_MEM7, SET_MEM8,
SET_MEM9, SET_MEM10, SET_MEM11, SET_MEM12, SET_MEM13, SET_MEM14, SET_MEM15, SET_MEM16,
SET_FRIENDLYNAME1, SET_FRIENDLYNAME2, SET_FRIENDLYNAME3, SET_FRIENDLYNAME4,
// SET_FRIENDLYNAME5, SET_FRIENDLYNAME6, SET_FRIENDLYNAME7, SET_FRIENDLYNAME8, // Future extension

View File

@ -334,6 +334,8 @@ void setup(void)
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
RtcInit();
#ifdef USE_ARDUINO_OTA

View File

@ -21,7 +21,7 @@
#define _TASMOTA_POST_H_
/*********************************************************************************************\
* Function declarations
* Function prototypes
\*********************************************************************************************/
// Needed for core 2.3.0 compilation (#6721)
@ -39,6 +39,7 @@ void KNX_CB_Action(message_t const &msg, void *arg);
//#endif // USE_KNX
char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, char inbetween = '\0');
extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end);
/*********************************************************************************************\
* Default global defines
@ -135,6 +136,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c
#define USE_SGP30 // Add I2C code for SGP30 sensor (+1k1 code)
//#define USE_SI1145 // Add I2C code for SI1145/46/47 sensor (+1k code)
#define USE_LM75AD // Add I2C code for LM75AD sensor (+0k5 code)
#define USE_DHT12 // Add I2C code for DHT12 temperature and humidity sensor (+0k7 code)
//#define USE_APDS9960 // Add I2C code for APDS9960 Proximity Sensor. Disables SHT and VEML6070 (+4k7 code)
//#define USE_MCP230xx // Enable MCP23008/MCP23017 - Must define I2C Address in #define USE_MCP230xx_ADDR below - range 0x20 - 0x27 (+4k7 code)
// #define USE_MCP230xx_ADDR 0x20 // Enable MCP23008/MCP23017 I2C Address to use (Must be within range 0x20 through 0x27 - set according to your wired setup)
@ -390,17 +392,17 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c
#endif // FIRMWARE_IR
/*********************************************************************************************\
* [tasmota-basic.bin]
* [tasmota-lite.bin]
* Provide an image without sensors
\*********************************************************************************************/
#ifdef FIRMWARE_BASIC
#ifdef FIRMWARE_LITE
#undef CODE_IMAGE
#define CODE_IMAGE 4
#undef APP_SLEEP
#define APP_SLEEP 1 // Default to sleep = 1 for FIRMWARE_BASIC
#define APP_SLEEP 1 // Default to sleep = 1 for FIRMWARE_LITE
#undef USE_ARDUINO_OTA // Disable support for Arduino OTA
#undef USE_DOMOTICZ // Disable Domoticz
@ -502,7 +504,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c
#undef CODE_IMAGE
#define CODE_IMAGE 1
#undef FIRMWARE_BASIC // Disable tasmota-basic with no sensors
#undef FIRMWARE_LITE // Disable tasmota-lite with no sensors
#undef FIRMWARE_SENSORS // Disable tasmota-sensors with useful sensors enabled
#undef FIRMWARE_KNX_NO_EMULATION // Disable tasmota-knx with KNX but without Emulation
#undef FIRMWARE_DISPLAYS // Disable tasmota-display with display drivers enabled

View File

@ -20,6 +20,9 @@
#ifndef _TASMOTA_VERSION_H_
#define _TASMOTA_VERSION_H_
const uint32_t VERSION = 0x07010206;
const uint32_t VERSION = 0x08000001;
// Lowest compatible version
const uint32_t VERSION_COMPATIBLE = 0x07010006;
#endif // _TASMOTA_VERSION_H_

View File

@ -512,6 +512,7 @@ const char kUploadErrors[] PROGMEM =
#ifdef USE_RF_FLASH
"|" D_UPLOAD_ERR_10 "|" D_UPLOAD_ERR_11 "|" D_UPLOAD_ERR_12 "|" D_UPLOAD_ERR_13
#endif
"|" D_UPLOAD_ERR_14
;
const uint16_t DNS_PORT = 53;
@ -2137,12 +2138,12 @@ void HandleUploadDone(void)
WSContentSendStyle();
WSContentSend_P(PSTR("<div style='text-align:center;'><b>" D_UPLOAD " <font color='#"));
if (Web.upload_error) {
// WSContentSend_P(PSTR(COLOR_TEXT_WARNING "'>" D_FAILED "</font></b><br><br>"));
WSContentSend_P(PSTR("%06x'>" D_FAILED "</font></b><br><br>"), WebColor(COL_TEXT_WARNING));
#ifdef USE_RF_FLASH
if (Web.upload_error < 14) {
if (Web.upload_error < 15) {
#else
if (Web.upload_error < 10) {
if ((Web.upload_error < 10) || (14 == Web.upload_error)) {
if (14 == Web.upload_error) { Web.upload_error = 10; }
#endif
GetTextIndexed(error, sizeof(error), Web.upload_error -1, kUploadErrors);
} else {
@ -2237,7 +2238,7 @@ void HandleUploadLoop(void)
Update.end(); // End esp8266 update session
Web.upload_file_type = UPL_EFM8BB1;
Web.upload_error = SnfBrUpdateInit();
Web.upload_error = SnfBrUpdateInit(); // 10, 11
if (Web.upload_error != 0) { return; }
} else
#endif // USE_RF_FLASH
@ -2245,7 +2246,7 @@ void HandleUploadLoop(void)
if ((WEMOS == my_module_type) && (upload.buf[0] == ':')) { // Check if this is a ARDUINO SLAVE hex file
Update.end(); // End esp8266 update session
Web.upload_file_type = UPL_TASMOTASLAVE;
Web.upload_error = TasmotaSlave_UpdateInit();
Web.upload_error = TasmotaSlave_UpdateInit(); // 0
if (Web.upload_error != 0) { return; }
} else
#endif
@ -2280,13 +2281,13 @@ void HandleUploadLoop(void)
free(efm8bb1_update);
efm8bb1_update = nullptr;
if (result != 0) {
Web.upload_error = abs(result); // 2 = Not enough space, 8 = File invalid
Web.upload_error = abs(result); // 2 = Not enough space, 8 = File invalid, 12, 13
return;
}
}
ssize_t result = rf_search_and_write(upload.buf, upload.currentSize);
if (result < 0) {
Web.upload_error = abs(result);
Web.upload_error = abs(result); // 8, 12, 13
return;
} else if (result > 0) {
if ((size_t)result > upload.currentSize) {
@ -2376,6 +2377,11 @@ void HandleUploadLoop(void)
Web.upload_error = 6; // Upload failed. Enable logging 3
return;
}
if (OtaVersion() < VERSION_COMPATIBLE) {
AbandonOta();
Web.upload_error = 14; // Not compatible
return;
}
}
if (!Web.upload_error) {
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD D_SUCCESSFUL " %u bytes. " D_RESTARTING), upload.totalSize);

View File

@ -262,8 +262,8 @@ struct LIGHT {
uint16_t fade_start_10[LST_MAX] = {0,0,0,0,0};
uint16_t fade_cur_10[LST_MAX];
uint16_t fade_end_10[LST_MAX]; // 10 bits resolution target channel values
uint16_t fade_counter = 0; // fade timer in ticks (50ms)
uint16_t fade_duration = 0; // duration of fade in ticks (50ms)
uint16_t fade_duration = 0; // duration of fade in milliseconds
uint32_t fade_start = 0; // fade start time in milliseconds, compared to millis()
} Light;
power_t LightPower(void)
@ -1574,20 +1574,25 @@ void LightAnimate(void)
bool power_off = false;
Light.strip_timer_counter++;
if (!Light.power) { // All channels powered off
Light.strip_timer_counter = 0;
if (!Light.fade_running) {
sleep = Settings.sleep;
}
if (Settings.light_scheme >= LS_MAX) {
power_off = true;
}
} else {
// set sleep parameter: either settings,
// 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) {
sleep = PWM_MAX_SLEEP; // set a maxumum value of 50 milliseconds to ensure that animations are smooth
} else {
sleep = Settings.sleep; // or keep the current sleep if it's lower than 50
}
} else {
sleep = Settings.sleep;
}
if (!Light.power) { // All channels powered off
Light.strip_timer_counter = 0;
if (Settings.light_scheme >= LS_MAX) {
power_off = true;
}
} else {
switch (Settings.light_scheme) {
case LS_POWER:
light_controller.calcLevels(Light.new_color);
@ -1733,27 +1738,35 @@ void LightAnimate(void)
memcpy(Light.fade_end_8, cur_col, sizeof(Light.fade_start_8));
memcpy(Light.fade_end_10, cur_col_10bits, sizeof(Light.fade_start_10));
Light.fade_running = true;
Light.fade_counter = 0;
Light.fade_duration = 0; // set the value to zero to force a recompute
Light.fade_start = 0;
// Fade will applied immediately below
}
}
if (Light.fade_running) {
LightApplyFade();
// AddLog_P2(LOG_LEVEL_INFO, PSTR("LightApplyFade %d %d %d %d %d - %d %d %d %d %d"),
// Light.fade_cur_8[0], Light.fade_cur_8[1], Light.fade_cur_8[2], Light.fade_cur_8[3], Light.fade_cur_8[4],
// Light.fade_cur_10[0], Light.fade_cur_10[1], Light.fade_cur_10[2], Light.fade_cur_10[3], Light.fade_cur_10[4]);
if (LightApplyFade()) {
// AddLog_P2(LOG_LEVEL_INFO, PSTR("LightApplyFade %d %d %d %d %d - %d %d %d %d %d"),
// Light.fade_cur_8[0], Light.fade_cur_8[1], Light.fade_cur_8[2], Light.fade_cur_8[3], Light.fade_cur_8[4],
// Light.fade_cur_10[0], Light.fade_cur_10[1], Light.fade_cur_10[2], Light.fade_cur_10[3], Light.fade_cur_10[4]);
LightSetOutputs(Light.fade_cur_8, Light.fade_cur_10);
LightSetOutputs(Light.fade_cur_8, Light.fade_cur_10);
}
}
}
}
void LightApplyFade(void) {
bool LightApplyFade(void) { // did the value chanegd and needs to be applied
static uint32_t last_millis = 0;
uint32_t now = millis();
if ((now - last_millis) <= 5) {
return false; // the value was not changed in the last 5 milliseconds, ignore
}
last_millis = now;
// Check if we need to calculate the duration
if (0 == Light.fade_duration) {
Light.fade_counter = 0;
Light.fade_start = now;
// compute the distance between start and and color (max of distance for each channel)
uint32_t distance = 0;
for (uint32_t i = 0; i < Light.subtype; i++) {
@ -1764,26 +1777,30 @@ void LightApplyFade(void) {
if (distance > 0) {
// compute the duration of the animation
// Note: Settings.light_speed is the number of half-seconds for a 100% fade,
// i.e. light_speed=1 means 1024 steps in 10 ticks (500ms)
Light.fade_duration = (distance * Settings.light_speed * 10) / 1024;
// Also postpone the save_data for the duration of the Fade (in seconds)
uint32_t delay_seconds = 1 + (Light.fade_duration + 19) / 20; // 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
// i.e. light_speed=1 means 1024 steps in 500ms
Light.fade_duration = (distance * Settings.light_speed * 500) / 1023;
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
}
}
} else {
// no fade needed, we keep the duration at zero, it will fallback directly to end of fade
Light.fade_running = false;
}
}
Light.fade_counter++;
if (Light.fade_counter <= Light.fade_duration) { // fade not finished
uint16_t fade_current = now - Light.fade_start; // number of milliseconds since start of fade
if (fade_current <= Light.fade_duration) { // fade not finished
//Serial.printf("Fade: %d / %d - ", fade_current, Light.fade_duration);
for (uint32_t i = 0; i < Light.subtype; i++) {
Light.fade_cur_8[i] = changeUIntScale(Light.fade_counter,
Light.fade_cur_8[i] = changeUIntScale(fade_current,
0, Light.fade_duration,
Light.fade_start_8[i], Light.fade_end_8[i]);
Light.fade_cur_10[i] = changeUIntScale(Light.fade_counter,
Light.fade_cur_10[i] = changeUIntScale(fade_current,
0, Light.fade_duration,
Light.fade_start_10[i], Light.fade_end_10[i]);
}
@ -1791,7 +1808,7 @@ void LightApplyFade(void) {
// stop fade
//AddLop_P2(LOG_LEVEL_DEBUG, PSTR("Stop fade"));
Light.fade_running = false;
Light.fade_counter = 0;
Light.fade_start = 0;
Light.fade_duration = 0;
// set light to target value
memcpy(Light.fade_cur_8, Light.fade_end_8, sizeof(Light.fade_end_8));
@ -1800,7 +1817,7 @@ void LightApplyFade(void) {
memcpy(Light.fade_start_8, Light.fade_end_8, sizeof(Light.fade_start_8));
memcpy(Light.fade_start_10, Light.fade_end_10, sizeof(Light.fade_start_10));
}
return true;
}
// On entry we take the 5 channels 8 bits entry, and we apply Power modifiers
@ -2426,6 +2443,13 @@ bool Xdrv04(uint8_t function)
case FUNC_SERIAL:
result = XlgtCall(FUNC_SERIAL);
break;
case FUNC_LOOP:
if (Light.fade_running) {
if (LightApplyFade()) {
LightSetOutputs(Light.fade_cur_8, Light.fade_cur_10);
}
}
break;
case FUNC_EVERY_50_MSECOND:
LightAnimate();
break;

View File

@ -499,6 +499,7 @@ void KNX_INIT(void)
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 defined(USE_ENERGY_SENSOR)
// Any device with a Power Monitoring
if ( energy_flg != ENERGY_NONE ) {
device_param[KNX_ENERGY_POWER-1].show = true;
@ -509,6 +510,7 @@ void KNX_INIT(void)
device_param[KNX_ENERGY_CURRENT-1].show = true;
device_param[KNX_ENERGY_POWERFACTOR-1].show = true;
}
#endif
#ifdef USE_RULES
device_param[KNX_SLOT1-1].show = true;

View File

@ -340,10 +340,10 @@ void HAssAnnounceButtonSwitch(uint8_t device, char* topic, uint8_t present, uint
if (strlen(prefix) > 0 ) TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix);
if (toggle) {
if (!key) {
TryResponseAppend_P(HASS_DISCOVER_BUTTON_TOGGLE, PSTR(D_RSLT_STATE), SettingsText(SET_STATE_TXT1 + toggle?2:1));
TryResponseAppend_P(HASS_DISCOVER_BUTTON_TOGGLE, PSTR(D_RSLT_STATE), SettingsText(SET_STATE_TXT3));
} else {TryResponseAppend_P(HASS_DISCOVER_SWITCH_TOGGLE);}
}
else TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_ONOFF, PSTR(D_RSLT_STATE), SettingsText(SET_STATE_TXT1 + toggle?2:1), SettingsText(SET_STATE_TXT1));
else TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_ONOFF, PSTR(D_RSLT_STATE), SettingsText(SET_STATE_TXT2), SettingsText(SET_STATE_TXT1));
TryResponseAppend_P(PSTR("}"));
}

View File

@ -511,6 +511,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = {
// On/off cluster
{ 0x0006, 0x0000, "Power", &Z_Copy },
{ 0x0006, 0x8000, "Power", &Z_Copy }, // See 7280
// On/Off Switch Configuration cluster
{ 0x0007, 0x0000, "SwitchType", &Z_Copy },

View File

@ -39,7 +39,7 @@ struct BUZZER {
void BuzzerOff(void)
{
digitalWrite(pin[GPIO_BUZZER], Buzzer.inverted); // Buzzer Off
DigitalWrite(GPIO_BUZZER, Buzzer.inverted); // Buzzer Off
}
//void BuzzerBeep(uint32_t count = 1, uint32_t on = 1, uint32_t off = 1, uint32_t tune = 0);
@ -124,7 +124,7 @@ void BuzzerEvery100mSec(void)
Buzzer.duration = Buzzer.set[Buzzer.state];
}
}
digitalWrite(pin[GPIO_BUZZER], (Buzzer.inverted) ? !Buzzer.state : Buzzer.state);
DigitalWrite(GPIO_BUZZER, (Buzzer.inverted) ? !Buzzer.state : Buzzer.state);
} else {
Buzzer.enable = false;
}

View File

@ -27,11 +27,13 @@
#define D_SHUTTER "SHUTTER"
const uint16_t MOTOR_STOP_TIME = 500; // in mS
const uint8_t steps_per_second = 20; // FUNC_EVERY_50_MSECOND
uint8_t calibrate_pos[6] = {0,30,50,70,90,100};
uint16_t messwerte[5] = {30,50,70,90,100};
uint16_t last_execute_step;
enum ShutterModes { SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE };
enum ShutterModes { SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE, SHT_OFF_ON__OPEN_CLOSE_STEPPER,};
const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|"
D_CMND_SHUTTER_OPEN "|" D_CMND_SHUTTER_CLOSE "|" D_CMND_SHUTTER_STOP "|" D_CMND_SHUTTER_POSITION "|"
@ -68,43 +70,51 @@ struct SHUTTER {
uint8_t mode = 0; // operation mode definition. see enum type above SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE
int16_t motordelay[MAX_SHUTTERS]; // initial motorstarttime in 0.05sec.
int16_t pwm_frequency; // frequency of PWN for stepper motors
uint16_t max_pwm_frequency = 1000; // maximum of PWM frequency that can be used. depend on the motor and drivers
uint16_t max_pwm_frequency = 1000; // maximum of PWM frequency for openig the shutter. depend on the motor and drivers
uint16_t max_close_pwm_frequency[MAX_SHUTTERS];// maximum of PWM frequency for closeing the shutter. depend on the motor and drivers
uint8_t skip_relay_change; // avoid overrun at endstops
int32_t accelerator[MAX_SHUTTERS]; // speed of ramp-up, ramp down of shutter
} Shutter;
void ShutterRtc50mS(void)
{
for (uint32_t i = 0; i < shutters_present; i++) {
Shutter.time[i]++;
if (Shutter.accelerator[i]) {
Shutter.pwm_frequency += Shutter.accelerator[i];
Shutter.pwm_frequency = tmax(0,tmin(Shutter.direction[i]==1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i],Shutter.pwm_frequency));
analogWriteFreq(Shutter.pwm_frequency);
analogWrite(pin[GPIO_PWM1+i], 50);
}
}
}
int32_t ShutterPercentToRealPosition(uint8_t percent,uint8_t index)
int32_t ShutterPercentToRealPosition(uint8_t percent,uint8_t i)
{
if (Settings.shutter_set50percent[index] != 50) {
return percent <= 5 ? Settings.shuttercoeff[2][index] * percent : Settings.shuttercoeff[1][index] * percent + Settings.shuttercoeff[0][index];
if (Settings.shutter_set50percent[i] != 50) {
return percent <= 5 ? Settings.shuttercoeff[2][i] * percent : Settings.shuttercoeff[1][i] * percent + Settings.shuttercoeff[0][i];
} else {
int32_t realpos;
// check against DIV 0
for (uint8_t j=0 ; j < 5 ; j++) {
if (Settings.shuttercoeff[j][index] == 0) {
if (Settings.shuttercoeff[j][i] == 0) {
AddLog_P2(LOG_LEVEL_ERROR, PSTR("SHT: RESET/INIT CALIBRATION MATRIX DIV 0"));
for (uint8_t k=0 ; k < 5 ; k++) {
Settings.shuttercoeff[k][index] = messwerte[k] * 1000 / messwerte[4];
Settings.shuttercoeff[k][i] = messwerte[k] * 1000 / messwerte[4];
}
}
}
for (uint8_t i=0 ; i < 5 ; i++) {
if (percent*10 > Settings.shuttercoeff[i][index]) {
realpos = Shutter.open_max[index] * calibrate_pos[i+1] / 100;
//AddLog_P2(LOG_LEVEL_INFO, PSTR("Realposition TEMP1: %d, %% %d, coeff %d"), realpos, percent, Settings.shuttercoeff[i][index]);
for (uint8_t l=0 ; l < 5 ; l++) {
if (percent*10 > Settings.shuttercoeff[l][i]) {
realpos = Shutter.open_max[i] * calibrate_pos[l+1] / 100;
//AddLog_P2(LOG_LEVEL_INFO, PSTR("Realposition TEMP1: %d, %% %d, coeff %d"), realpos, percent, Settings.shuttercoeff[l][i]);
} else {
if ( i == 0) {
realpos = percent * Shutter.open_max[index] * calibrate_pos[i+1] / Settings.shuttercoeff[i][index] / 10;
if ( l == 0) {
realpos = percent * Shutter.open_max[i] * calibrate_pos[l+1] / Settings.shuttercoeff[l][i] / 10;
} else {
//uint16_t addon = ( percent*10 - Settings.shuttercoeff[i-1][index] ) * Shutter_Open_Max[index] * (calibrate_pos[i+1] - calibrate_pos[i]) / (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index]) / 100;
//AddLog_P2(LOG_LEVEL_INFO, PSTR("Realposition TEMP2: %d, %% %d, coeff %d"), addon, (calibrate_pos[i+1] - calibrate_pos[i]), (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index]));
realpos += ( percent*10 - Settings.shuttercoeff[i-1][index] ) * Shutter.open_max[index] * (calibrate_pos[i+1] - calibrate_pos[i]) / (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index]) / 100;
//uint16_t addon = ( percent*10 - Settings.shuttercoeff[i-1][i] ) * Shutter_Open_Max[i] * (calibrate_pos[l+1] - calibrate_pos[l]) / (Settings.shuttercoeff[l][i] -Settings.shuttercoeff[l-1][l]) / 100;
//AddLog_P2(LOG_LEVEL_INFO, PSTR("Realposition TEMP2: %d, %% %d, coeff %d"), addon, (calibrate_pos[l+1] - calibrate_pos[l]), (Settings.shuttercoeff[l][i] -Settings.shuttercoeff[l-1][l]));
realpos += ( percent*10 - Settings.shuttercoeff[l-1][i] ) * Shutter.open_max[i] * (calibrate_pos[l+1] - calibrate_pos[l]) / (Settings.shuttercoeff[l][i] -Settings.shuttercoeff[l-1][i]) / 100;
}
break;
}
@ -113,25 +123,25 @@ int32_t ShutterPercentToRealPosition(uint8_t percent,uint8_t index)
}
}
uint8_t ShutterRealToPercentPosition(int32_t realpos, uint8_t index)
uint8_t ShutterRealToPercentPosition(int32_t realpos, uint8_t i)
{
if (Settings.shutter_set50percent[index] != 50) {
return Settings.shuttercoeff[2][index] * 5 > realpos ? realpos / Settings.shuttercoeff[2][index] : (realpos-Settings.shuttercoeff[0][index]) / Settings.shuttercoeff[1][index];
if (Settings.shutter_set50percent[i] != 50) {
return Settings.shuttercoeff[2][i] * 5 > realpos ? realpos / Settings.shuttercoeff[2][i] : (realpos-Settings.shuttercoeff[0][i]) / Settings.shuttercoeff[1][i];
} else {
int16_t realpercent;
for (uint8_t i=0 ; i < 5 ; i++) {
if (realpos > Shutter.open_max[index] * calibrate_pos[i+1] / 100) {
realpercent = Settings.shuttercoeff[i][index] /10;
//AddLog_P2(LOG_LEVEL_INFO, PSTR("Realpercent TEMP1: %d, %% %d, coeff %d"), realpercent, realpos, Shutter_Open_Max[index] * calibrate_pos[i+1] / 100);
for (uint8_t j=0 ; j < 5 ; j++) {
if (realpos > Shutter.open_max[i] * calibrate_pos[j+1] / 100) {
realpercent = Settings.shuttercoeff[j][i] /10;
//AddLog_P2(LOG_LEVEL_INFO, PSTR("Realpercent TEMP1: %d, %% %d, coeff %d"), realpercent, realpos, Shutter_Open_Max[i] * calibrate_pos[i+1] / 100);
} else {
if ( i == 0) {
realpercent = ( realpos - (Shutter.open_max[index] * calibrate_pos[i] / 100) ) * 10 * Settings.shuttercoeff[i][index] / calibrate_pos[i+1] / Shutter.open_max[index];
realpercent = ( realpos - (Shutter.open_max[i] * calibrate_pos[j] / 100) ) * 10 * Settings.shuttercoeff[j][i] / calibrate_pos[j+1] / Shutter.open_max[i];
} else {
//uint16_t addon = ( realpos - (Shutter_Open_Max[index] * calibrate_pos[i] / 100) ) * 10 * (Settings.shuttercoeff[i][index] - Settings.shuttercoeff[i-1][index]) / (calibrate_pos[i+1] - calibrate_pos[i])/ Shutter_Open_Max[index];
//uint16_t addon = ( percent*10 - Settings.shuttercoeff[i-1][index] ) * Shutter_Open_Max[index] * (calibrate_pos[i+1] - calibrate_pos[i]) / (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index]) / 100;
//AddLog_P2(LOG_LEVEL_INFO, PSTR("Realpercent TEMP2: %d, delta %d, %% %d, coeff %d"), addon,( realpos - (Shutter_Open_Max[index] * calibrate_pos[i] / 100) ) , (calibrate_pos[i+1] - calibrate_pos[i])* Shutter_Open_Max[index]/100, (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index]));
realpercent += ( realpos - (Shutter.open_max[index] * calibrate_pos[i] / 100) ) * 10 * (Settings.shuttercoeff[i][index] - Settings.shuttercoeff[i-1][index]) / (calibrate_pos[i+1] - calibrate_pos[i]) / Shutter.open_max[index] ;
//uint16_t addon = ( realpos - (Shutter_Open_Max[i] * calibrate_pos[i] / 100) ) * 10 * (Settings.shuttercoeff[i][i] - Settings.shuttercoeff[i-1][i]) / (calibrate_pos[i+1] - calibrate_pos[i])/ Shutter_Open_Max[i];
//uint16_t addon = ( percent*10 - Settings.shuttercoeff[i-1][i] ) * Shutter_Open_Max[i] * (calibrate_pos[i+1] - calibrate_pos[i]) / (Settings.shuttercoeff[i][i] -Settings.shuttercoeff[i-1][i]) / 100;
//AddLog_P2(LOG_LEVEL_INFO, PSTR("Realpercent TEMP2: %d, delta %d, %% %d, coeff %d"), addon,( realpos - (Shutter_Open_Max[i] * calibrate_pos[i] / 100) ) , (calibrate_pos[i+1] - calibrate_pos[i])* Shutter_Open_Max[i]/100, (Settings.shuttercoeff[i][i] -Settings.shuttercoeff[i-1][i]));
realpercent += ( realpos - (Shutter.open_max[i] * calibrate_pos[j] / 100) ) * 10 * (Settings.shuttercoeff[j][i] - Settings.shuttercoeff[j-1][i]) / (calibrate_pos[j+1] - calibrate_pos[j]) / Shutter.open_max[i] ;
}
break;
}
@ -148,12 +158,11 @@ void ShutterInit(void)
Shutter.old_power = power;
bool relay_in_interlock = false;
// if shutter 4 is unused
if (Settings.shutter_startrelay[MAX_SHUTTERS] == 0) {
Shutter.max_pwm_frequency = Settings.shuttercoeff[4][3] > 0 ? Settings.shuttercoeff[4][3] : Shutter.max_pwm_frequency;
}
for (uint32_t i = 0; i < MAX_SHUTTERS; i++) {
// upgrade to 0.1sec calculation base.
if ( Settings.shutter_accuracy == 0) {
Settings.shutter_closetime[i] = Settings.shutter_closetime[i] * 10;
Settings.shutter_opentime[i] = Settings.shutter_opentime[i] * 10;
}
// 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) {
@ -177,7 +186,8 @@ void ShutterInit(void)
}
} else {
Shutter.mode = SHT_OFF_ON__OPEN_CLOSE;
if (pin[GPIO_PWM1+i] < 99) {
if (pin[GPIO_PWM1+i] < 99 && pin[GPIO_CNTR1+i]) {
Shutter.mode = SHT_OFF_ON__OPEN_CLOSE_STEPPER;
Shutter.pwm_frequency = 0;
analogWriteFreq(Shutter.pwm_frequency);
analogWrite(pin[GPIO_PWM1+i], 50);
@ -195,6 +205,8 @@ void ShutterInit(void)
// Update Calculation 20 because time interval is 0.05 sec
Shutter.open_max[i] = 200 * Shutter.open_time[i];
Shutter.close_velocity[i] = Shutter.open_max[i] / Shutter.close_time[i] / 2 ;
Shutter.max_close_pwm_frequency[i] = Shutter.max_pwm_frequency*Shutter.open_time[i]/Shutter.close_time[i];
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d Closefreq: %d"),i, Shutter.max_close_pwm_frequency[i]);
// calculate a ramp slope at the first 5 percent to compensate that shutters move with down part later than the upper part
if (Settings.shutter_set50percent[i] != 50) {
@ -222,43 +234,54 @@ void ShutterInit(void)
// terminate loop at first INVALID shutter.
break;
}
if (shutters_present < 4) {
Shutter.max_pwm_frequency = Settings.shuttercoeff[4][4] > 0 ? Settings.shuttercoeff[4][4] : Shutter.max_pwm_frequency;
}
Settings.shutter_accuracy = 1;
}
}
void ShutterUpdatePosition(void)
{
char scommand[CMDSZ];
char stopic[TOPSZ];
char stemp2[10];
for (uint32_t i = 0; i < shutters_present; i++) {
if (Shutter.direction[i] != 0) {
if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE && pin[GPIO_PWM1+i] < 99 && pin[GPIO_CNTR1+i] < 99 ) {
int32_t stop_position_delta = 20;
if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) {
// Calculate position with counter. Much more accurate and no need for motordelay workaround
// adding some steps to stop early
Shutter.real_position[i] = Shutter.direction[i] * 20 + ShutterCounterBasedPosition(i);;
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: real %d, start %d, counter %d, max_freq %d, dir %d, freq %d"),Shutter.real_position[i], Shutter.start_position[i] ,RtcSettings.pulse_counter[i],Shutter.max_pwm_frequency , Shutter.direction[i] ,Shutter.max_pwm_frequency );
Shutter.real_position[i] = ShutterCounterBasedPosition(i);
int32_t max_frequency = Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i];
int32_t max_freq_change_per_sec = Shutter.max_pwm_frequency*steps_per_second / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1);
int32_t min_runtime_ms = Shutter.pwm_frequency*1000 / max_freq_change_per_sec;
int32_t velocity = Shutter.direction[i] == 1 ? 100 : Shutter.close_velocity[i];
int32_t minstopway = min_runtime_ms * velocity / 100 * Shutter.pwm_frequency / max_frequency * Shutter.direction[i] ;
int32_t next_possible_stop = Shutter.real_position[i] + minstopway ;
stop_position_delta =200 * Shutter.pwm_frequency/max_frequency + Shutter.direction[i] * (next_possible_stop - Shutter.target_position[i]);
//Shutter.accelerator[i] = tmin(tmax(max_freq_change_per_sec*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_freq_change_per_sec*9/200), max_freq_change_per_sec*11/200);
//int32_t act_freq_change = max_freq_change_per_sec/20;
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: time: %d, velocity %d, minstopway %d,cur_freq %d, max_frequency %d, act_freq_change %d, min_runtime_ms %d, act.pos %d, next_stop %d, target: %d"),Shutter.time[i],velocity,minstopway,
Shutter.pwm_frequency,max_frequency, Shutter.accelerator[i],min_runtime_ms,Shutter.real_position[i], next_possible_stop,Shutter.target_position[i]);
if (Shutter.accelerator[i] < 0 || next_possible_stop * Shutter.direction[i] > Shutter.target_position[i] * Shutter.direction[i] ) {
Shutter.accelerator[i] = - tmin(tmax(max_freq_change_per_sec*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_freq_change_per_sec*9/200), max_freq_change_per_sec*12/200);
//AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Ramp down: acc: %d"), Shutter.accelerator[i]);
} else if ( Shutter.accelerator[i] > 0 && Shutter.pwm_frequency == max_frequency) {
Shutter.accelerator[i] = 0;
}
} else {
Shutter.real_position[i] = Shutter.start_position[i] + ( (Shutter.time[i] - Shutter.motordelay[i]) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i]));
}
if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE && pin[GPIO_PWM1+i] < 99) {
uint16_t freq_change = Shutter.max_pwm_frequency/(Shutter.motordelay[i]+1);
// ramp up phase. calculate frequency
Shutter.pwm_frequency = tmin(freq_change * Shutter.time[i],Shutter.max_pwm_frequency);
// ramp down at the end of the movement time will not be exactly motordelay
Shutter.pwm_frequency = tmax(tmin(freq_change * (Shutter.target_position[i]-Shutter.real_position[i])*Shutter.direction[i]/30, Shutter.pwm_frequency),10);
analogWriteFreq(Shutter.pwm_frequency);
analogWrite(pin[GPIO_PWM1+i], 50);
}
if (Shutter.real_position[i] * Shutter.direction[i] >= Shutter.target_position[i] * Shutter.direction[i] ) {
if ( Shutter.real_position[i] * Shutter.direction[i] + stop_position_delta >= Shutter.target_position[i] * Shutter.direction[i] ) {
// calculate relay number responsible for current movement.
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Stop Condition detected: real: %d, Target: %d, direction: %d"),Shutter.real_position[i], Shutter.target_position[i],Shutter.direction[i]);
uint8_t cur_relay = Settings.shutter_startrelay[i] + (Shutter.direction[i] == 1 ? 0 : 1) ;
int16_t missing_steps;
switch (Shutter.mode) {
case SHT_PULSE_OPEN__PULSE_CLOSE:
@ -269,29 +292,34 @@ void ShutterUpdatePosition(void)
last_source = SRC_SHUTTER;
}
break;
case SHT_OFF_ON__OPEN_CLOSE:
// This is a failsafe configuration. Relay1 ON/OFF Relay2 -1/1 direction
// Only allow PWM microstepping if PWM and COUNTER are defined.
// see wiki to connect PWM and COUNTER
if (pin[GPIO_PWM1+i] < 99 && pin[GPIO_CNTR1+i] < 99 ) {
int16_t missing_steps = ((Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) - RtcSettings.pulse_counter[i];
//prepare for stop PWM
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Remain steps %d, counter %d, freq %d"), missing_steps, RtcSettings.pulse_counter[i] ,Shutter.pwm_frequency);
Shutter.pwm_frequency = 0;
analogWriteFreq(Shutter.pwm_frequency);
while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) {
delay(1);
}
analogWrite(pin[GPIO_PWM1+i], 0);
Shutter.real_position[i] = ShutterCounterBasedPosition(i);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:Real %d, pulsecount %d, start %d"), Shutter.real_position[i],RtcSettings.pulse_counter[i], Shutter.start_position[i]);
case SHT_OFF_ON__OPEN_CLOSE_STEPPER:
missing_steps = ((Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) - RtcSettings.pulse_counter[i];
//prepare for stop PWM
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Remain steps %d, counter %d, freq %d"), missing_steps, RtcSettings.pulse_counter[i] ,Shutter.pwm_frequency);
Shutter.accelerator[i] = 0;
Shutter.pwm_frequency = Shutter.pwm_frequency > 250 ? 250 : Shutter.pwm_frequency;
analogWriteFreq(Shutter.pwm_frequency);
analogWrite(pin[GPIO_PWM1+i], 50);
Shutter.pwm_frequency = 0;
analogWriteFreq(Shutter.pwm_frequency);
while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) {
delay(1);
}
analogWrite(pin[GPIO_PWM1+i], 0);
Shutter.real_position[i] = ShutterCounterBasedPosition(i);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:Real %d, pulsecount %d, start %d"), Shutter.real_position[i],RtcSettings.pulse_counter[i], Shutter.start_position[i]);
if ((1 << (Settings.shutter_startrelay[i]-1)) & power) {
ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER);
ExecuteCommandPower(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER);
}
break;
case SHT_OFF_ON__OPEN_CLOSE:
if ((1 << (Settings.shutter_startrelay[i]-1)) & power) {
ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER);
ExecuteCommandPower(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER);
}
break;
case SHT_OFF_OPEN__OFF_CLOSE:
// avoid switching OFF a relay already OFF
if ((1 << (cur_relay-1)) & power) {
@ -302,7 +330,7 @@ void ShutterUpdatePosition(void)
}
Settings.shutter_position[i] = ShutterRealToPercentPosition(Shutter.real_position[i], i);
dtostrfd((float)Shutter.time[i] / 20, 1, stemp2);
dtostrfd((float)Shutter.time[i] / steps_per_second, 1, stemp2);
AddLog_P2(LOG_LEVEL_INFO, MSG_SHUTTER_POS, i+1, Shutter.real_position[i], Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i], Shutter.motordelay[i],stemp2,Shutter.pwm_frequency);
Shutter.start_position[i] = Shutter.real_position[i];
@ -332,50 +360,51 @@ bool ShutterState(uint8_t device)
(Shutter.mask & (1 << (Settings.shutter_startrelay[device]-1))) );
}
void ShutterStartInit(uint8_t index, int8_t direction, int32_t target_pos)
void ShutterStartInit(uint8_t i, int8_t direction, int32_t target_pos)
{
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: dir %d, delta1 %d, delta2 %d, grant %d"),direction, (Shutter.open_max[index] - Shutter.real_position[index]) / Shutter.close_velocity[index], Shutter.real_position[index] / Shutter.close_velocity[index], 2+Shutter.motordelay[index]);
if ( ( direction == 1 && (Shutter.open_max[index] - Shutter.real_position[index]) / 100 <= 2 )
|| ( direction == -1 && Shutter.real_position[index] / Shutter.close_velocity[index] <= 2)) {
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: dir %d, delta1 %d, delta2 %d, grant %d"),direction, (Shutter.open_max[i] - Shutter.real_position[i]) / Shutter.close_velocity[i], Shutter.real_position[i] / Shutter.close_velocity[i], 2+Shutter.motordelay[i]);
if ( ( direction == 1 && (Shutter.open_max[i] - Shutter.real_position[i]) / 100 <= 2 )
|| ( direction == -1 && Shutter.real_position[i] / Shutter.close_velocity[i] <= 2)) {
Shutter.skip_relay_change = 1 ;
} else {
if (pin[GPIO_PWM1+index] < 99) {
if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) {
Shutter.pwm_frequency = 0;
analogWriteFreq(Shutter.pwm_frequency);
analogWrite(pin[GPIO_PWM1+index], 0);
analogWrite(pin[GPIO_PWM1+i], 0);
// can be operated without counter, but then not that acurate.
if (pin[GPIO_CNTR1+index] < 99) {
RtcSettings.pulse_counter[index] = 0;
if (pin[GPIO_CNTR1+i] < 99) {
RtcSettings.pulse_counter[i] = 0;
}
Shutter.accelerator[i] = Shutter.max_pwm_frequency / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Ramp up: %d"), Shutter.accelerator[i]);
}
Shutter.target_position[index] = target_pos;
Shutter.start_position[index] = Shutter.real_position[index];
Shutter.time[index] = 0;
Shutter.target_position[i] = target_pos;
Shutter.start_position[i] = Shutter.real_position[i];
Shutter.time[i] = 0;
Shutter.skip_relay_change = 0;
Shutter.direction[index] = direction;
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: real %d, start %d, counter %d, max_freq %d, dir %d, freq %d"),Shutter.real_position[index], Shutter.start_position[index] ,RtcSettings.pulse_counter[index],Shutter.max_pwm_frequency , Shutter.direction[index] ,Shutter.max_pwm_frequency );
Shutter.direction[i] = direction;
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: real %d, start %d, counter %d, max_freq %d, dir %d, freq %d"),Shutter.real_position[i], Shutter.start_position[i] ,RtcSettings.pulse_counter[i],Shutter.max_pwm_frequency , Shutter.direction[i] ,Shutter.max_pwm_frequency );
}
//AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter: %d from %d to %d in directin %d"), index, Shutter.start_position[index], Shutter.target_position[index], Shutter.direction[index]);
//AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter: %d from %d to %d in directin %d"), i, Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i]);
}
void ShutterWaitForMotorStop(uint8_t index)
void ShutterWaitForMotorStop(uint8_t i)
{
AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Wait for Motorstop.."));
if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE) {
if (pin[GPIO_PWM1+index] < 99 && pin[GPIO_CNTR1+index] < 99 ) {
if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE || Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) {
if ( Shutter.mode = SHT_OFF_ON__OPEN_CLOSE_STEPPER) {
//AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Frequency change %d"), Shutter.pwm_frequency);
while (Shutter.pwm_frequency > 100) {
Shutter.pwm_frequency = tmax(Shutter.pwm_frequency-(Shutter.max_pwm_frequency/(Shutter.motordelay[index]+1)) , 0);
while (Shutter.pwm_frequency > 0) {
Shutter.accelerator[i] = 0;
Shutter.pwm_frequency = tmax(Shutter.pwm_frequency-((Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i])/(Shutter.motordelay[i]+1)) , 0);
analogWriteFreq(Shutter.pwm_frequency);
analogWrite(pin[GPIO_PWM1+index], 50);
analogWrite(pin[GPIO_PWM1+i], 50);
delay(50);
}
Shutter.pwm_frequency = 0;
analogWriteFreq(Shutter.pwm_frequency);
analogWrite(pin[GPIO_PWM1+index], 0);
Shutter.real_position[index] = ShutterCounterBasedPosition(index);
analogWrite(pin[GPIO_PWM1+i], 0);
Shutter.real_position[i] = ShutterCounterBasedPosition(i);
} else {
ExecuteCommandPower(Settings.shutter_startrelay[index], 0, SRC_SHUTTER);
ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER);
delay(MOTOR_STOP_TIME);
}
} else {
@ -391,7 +420,7 @@ void ShutterReportPosition(void)
if (Shutter.direction[i] != 0) {
char stemp2[10];
uint8_t position = ShutterRealToPercentPosition(Shutter.real_position[i], i);
dtostrfd((float)Shutter.time[i] / 20, 2, stemp2);
dtostrfd((float)Shutter.time[i] / steps_per_second, 2, stemp2);
shutter_moving = 1;
//Settings.shutter_position[i] = Settings.shuttercoeff[2][i] * 5 > Shutter.real_position[i] ? Shutter.real_position[i] / Settings.shuttercoeff[2][i] : (Shutter.real_position[i]-Settings.shuttercoeff[0,i]) / Settings.shuttercoeff[1][i];
AddLog_P2(LOG_LEVEL_INFO, MSG_SHUTTER_POS, i+1, Shutter.real_position[i], Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i], Shutter.motordelay[i],stemp2,Shutter.pwm_frequency);
@ -430,7 +459,7 @@ void ShutterRelayChanged(void)
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: source: %s, powerstate_local %ld, Shutter.switched_relay %d, manual change %d"), i+1, GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), powerstate_local,Shutter.switched_relay,manual_relays_changed);
if (manual_relays_changed) {
//Shutter.skip_relay_change = true;
if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE) {
if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE || Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) {
ShutterWaitForMotorStop(i);
switch (powerstate_local) {
case 1:
@ -478,7 +507,7 @@ void ShutterSetPosition(uint8_t device, uint8_t position)
void CmndShutterOpen(void)
{
//AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Payload close: %d, index %d"), XdrvMailbox.payload, XdrvMailbox.index);
//AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Payload close: %d, i %d"), XdrvMailbox.payload, XdrvMailbox.i);
if ( XdrvMailbox.index == 1 && XdrvMailbox.payload != -99) {
XdrvMailbox.index = XdrvMailbox.payload;
}
@ -489,7 +518,7 @@ void CmndShutterOpen(void)
void CmndShutterClose(void)
{
//AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Payload open: %d, index %d"), XdrvMailbox.payload, XdrvMailbox.index);
//AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Payload open: %d, i %d"), XdrvMailbox.payload, XdrvMailbox.i);
if ( XdrvMailbox.index == 1 && XdrvMailbox.payload != -99) {
XdrvMailbox.index = XdrvMailbox.payload;
}
@ -505,14 +534,14 @@ void CmndShutterStop(void)
if ( XdrvMailbox.index == 1 && XdrvMailbox.payload != -99) {
XdrvMailbox.index = XdrvMailbox.payload;
}
uint32_t index = XdrvMailbox.index -1;
if (Shutter.direction[index] != 0) {
uint32_t i = XdrvMailbox.index -1;
if (Shutter.direction[i] != 0) {
AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving %d: dir: %d"), XdrvMailbox.index, Shutter.direction[index]);
AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving %d: dir: %d"), XdrvMailbox.index, Shutter.direction[i]);
// set stop position 10 steps ahead (0.5sec to allow normal stop)
int32_t temp_realpos = Shutter.start_position[index] + ( (Shutter.time[index]+10) * (Shutter.direction[index] > 0 ? 100 : -Shutter.close_velocity[index]));
XdrvMailbox.payload = ShutterRealToPercentPosition(temp_realpos, index);
//XdrvMailbox.payload = Settings.shuttercoeff[2][index] * 5 > temp_realpos ? temp_realpos / Settings.shuttercoeff[2][index] : (temp_realpos-Settings.shuttercoeff[0,index]) / Settings.shuttercoeff[1][index];
int32_t temp_realpos = Shutter.start_position[i] + ( (Shutter.time[i]+10) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i]));
XdrvMailbox.payload = ShutterRealToPercentPosition(temp_realpos, i);
//XdrvMailbox.payload = Settings.shuttercoeff[2][i] * 5 > temp_realpos ? temp_realpos / Settings.shuttercoeff[2][i] : (temp_realpos-Settings.shuttercoeff[0,i]) / Settings.shuttercoeff[1][i];
last_source = SRC_WEBGUI;
CmndShutterPosition();
} else {
@ -524,7 +553,7 @@ void CmndShutterStop(void)
void CmndShutterPosition(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) {
uint32_t index = XdrvMailbox.index -1;
uint32_t index = XdrvMailbox.index-1;
//limit the payload
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Pos. in: payload %s (%d), payload %d, idx %d, src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, last_source );
@ -542,6 +571,7 @@ void CmndShutterPosition(void)
if (XdrvMailbox.payload != -99) {
//target_pos_percent = Settings.shutter_invert[index] ? 100 - target_pos_percent : target_pos_percent;
Shutter.target_position[index] = ShutterPercentToRealPosition(target_pos_percent, index);
Shutter.accelerator[index] = Shutter.max_pwm_frequency / (Shutter.motordelay[index]>0 ? Shutter.motordelay[index] : 1);
//Shutter.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, PSTR("SHT: lastsource %d:, real %d, target %d, payload %d"), last_source, Shutter.real_position[index] ,Shutter.target_position[index],target_pos_percent);
}
@ -561,7 +591,7 @@ void CmndShutterPosition(void)
}
}
if (Shutter.direction[index] != new_shutterdirection ) {
if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE) {
if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE || Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) {
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Delay5 5s, xdrv %d"), XdrvMailbox.payload);
ShutterWaitForMotorStop(index);
ExecuteCommandPower(Settings.shutter_startrelay[index], 0, SRC_SHUTTER);
@ -617,11 +647,11 @@ void CmndShutterMotorDelay(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) {
if (XdrvMailbox.data_len > 0) {
Settings.shutter_motordelay[XdrvMailbox.index -1] = (uint16_t)(20 * CharToFloat(XdrvMailbox.data));
Settings.shutter_motordelay[XdrvMailbox.index -1] = (uint16_t)(steps_per_second * CharToFloat(XdrvMailbox.data));
ShutterInit();
}
char time_chr[10];
dtostrfd((float)(Settings.shutter_motordelay[XdrvMailbox.index -1]) / 20, 2, time_chr);
dtostrfd((float)(Settings.shutter_motordelay[XdrvMailbox.index -1]) / steps_per_second, 2, time_chr);
ResponseCmndIdxChar(time_chr);
}
}
@ -660,8 +690,9 @@ void CmndShutterFrequency(void)
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 20000)) {
Shutter.max_pwm_frequency = XdrvMailbox.payload;
if (shutters_present < 4) {
Settings.shuttercoeff[4][4] = Shutter.max_pwm_frequency;
Settings.shuttercoeff[4][3] = Shutter.max_pwm_frequency;
}
ShutterInit();
ResponseCmndNumber(XdrvMailbox.payload); // ????
} else {
ResponseCmndNumber(Shutter.max_pwm_frequency);
@ -707,8 +738,8 @@ void CmndShutterCalibration(void) // ????
messwerte[i] = field;
}
for (i=0 ; i < 5 ; i++) {
Settings.shuttercoeff[i][XdrvMailbox.index-1] = messwerte[i] * 1000 / messwerte[4];
AddLog_P2(LOG_LEVEL_INFO, PSTR("Settings.shuttercoeff: %d, i: %d, value: %d, messwert %d"), i,XdrvMailbox.index-1,Settings.shuttercoeff[i][XdrvMailbox.index-1], messwerte[i]);
Settings.shuttercoeff[i][XdrvMailbox.index -1] = messwerte[i] * 1000 / messwerte[4];
AddLog_P2(LOG_LEVEL_INFO, PSTR("Settings.shuttercoeff: %d, i: %d, value: %d, messwert %d"), i,XdrvMailbox.index -1,Settings.shuttercoeff[i][XdrvMailbox.index -1], messwerte[i]);
}
ShutterInit();
ResponseCmndIdxChar(XdrvMailbox.data);

View File

@ -103,7 +103,7 @@ void DeepSleepPrepare(void)
// if more then 10% timeslip = 0 == non valid wakeup; maybe manual
timeslip = (timeslip < -(int32_t)Settings.deepsleep) ? 0 : (timeslip > (int32_t)Settings.deepsleep) ? 0 : 1;
if (timeslip) {
RtcSettings.deepsleep_slip = (Settings.deepsleep + RtcSettings.nextwakeup - UtcTime()) * RtcSettings.deepsleep_slip / (Settings.deepsleep - (millis() / 1000));
RtcSettings.deepsleep_slip = (Settings.deepsleep + RtcSettings.nextwakeup - UtcTime()) * RtcSettings.deepsleep_slip / tmax((Settings.deepsleep - (millis() / 1000)),5);
// Avoid crazy numbers. Again maximum 10% deviation.
RtcSettings.deepsleep_slip = tmin(tmax(RtcSettings.deepsleep_slip, 9000), 11000);
RtcSettings.nextwakeup += Settings.deepsleep;

View File

@ -143,9 +143,7 @@ void HlwEvery200ms(void)
if (Hlw.cf1_timer >= 8) {
Hlw.cf1_timer = 0;
Hlw.select_ui_flag = (Hlw.select_ui_flag) ? false : true;
if (pin[GPIO_NRG_SEL] < 99) {
digitalWrite(pin[GPIO_NRG_SEL], Hlw.select_ui_flag);
}
DigitalWrite(GPIO_NRG_SEL, Hlw.select_ui_flag);
if (Hlw.cf1_pulse_counter) {
cf1_pulse_length = Hlw.cf1_summed_pulse_length / Hlw.cf1_pulse_counter;

View File

@ -570,9 +570,7 @@ void McpSnsInit(void)
} else {
mcp_buffer = (char*)(malloc(MCP_BUFFER_SIZE));
}
if (pin[GPIO_MCP39F5_RST] < 99) {
digitalWrite(pin[GPIO_MCP39F5_RST], 1); // MCP enable
}
DigitalWrite(GPIO_MCP39F5_RST, 1); // MCP enable
} else {
energy_flg = ENERGY_NONE;
}

152
tasmota/xsns_58_dht12.ino Normal file
View File

@ -0,0 +1,152 @@
/*
xsns_58_dht12.ino - DHT12 I2C temperature and humidity sensor support for Tasmota
Copyright (C) 2019 Stefan Oskamp and Theo Arends
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
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 <http://www.gnu.org/licenses/>.
*/
#ifdef USE_I2C
#ifdef USE_DHT12
/*********************************************************************************************\
* DHT12 - Temperature and Humidity
*
* I2C Address: 0x5C
\*********************************************************************************************/
#define XSNS_58 58
#define XI2C_41 41 // See I2CDEVICES.md
#define DHT12_ADDR 0x5C
struct DHT12 {
float temperature = NAN;
float humidity = NAN;
uint8_t valid = 0;
uint8_t count = 0;
char name[6] = "DHT12";
} Dht12;
bool Dht12Read(void)
{
if (Dht12.valid) { Dht12.valid--; }
Wire.beginTransmission(DHT12_ADDR);
Wire.write(0);
if (Wire.endTransmission() != 0) { return false; }
delay(50);
Wire.requestFrom(DHT12_ADDR, 5);
delay(5);
uint8_t humidity = Wire.read();
uint8_t humidityTenth = Wire.read();
uint8_t temp = Wire.read();
uint8_t tempTenth = Wire.read();
uint8_t checksum = Wire.read();
Dht12.humidity = ConvertHumidity( (float) humidity + (float) humidityTenth/(float) 10.0 );
Dht12.temperature = ConvertTemp( (float) temp + (float) tempTenth/(float) 10.0 );
if (isnan(Dht12.temperature) || isnan(Dht12.humidity)) { return false; }
Dht12.valid = SENSOR_MAX_MISS;
return true;
}
/********************************************************************************************/
void Dht12Detect(void)
{
if (I2cActive(DHT12_ADDR)) { return; }
if (Dht12Read()) {
I2cSetActiveFound(DHT12_ADDR, Dht12.name);
Dht12.count = 1;
}
}
void Dht12EverySecond(void)
{
if (uptime &1) {
// DHT12: 55mS
if (!Dht12Read()) {
AddLogMissed(Dht12.name, Dht12.valid);
}
}
}
void Dht12Show(bool json)
{
if (Dht12.valid) {
char temperature[33];
dtostrfd(Dht12.temperature, Settings.flag2.temperature_resolution, temperature);
char humidity[33];
dtostrfd(Dht12.humidity, Settings.flag2.humidity_resolution, humidity);
if (json) {
ResponseAppend_P(JSON_SNS_TEMPHUM, Dht12.name, temperature, humidity);
#ifdef USE_DOMOTICZ
if ((0 == tele_period)) {
DomoticzTempHumSensor(temperature, humidity);
}
#endif // USE_DOMOTICZ
#ifdef USE_KNX
if (0 == tele_period) {
KnxSensor(KNX_TEMPERATURE, Dht12.temperature);
KnxSensor(KNX_HUMIDITY, Dht12.humidity);
}
#endif // USE_KNX
#ifdef USE_WEBSERVER
} else {
WSContentSend_PD(HTTP_SNS_TEMP, Dht12.name, temperature, TempUnit());
WSContentSend_PD(HTTP_SNS_HUM, Dht12.name, humidity);
#endif // USE_WEBSERVER
}
}
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
bool Xsns58(uint8_t function)
{
if (!I2cEnabled(XI2C_41)) { return false; }
bool result = false;
if (FUNC_INIT == function) {
Dht12Detect();
}
else if (Dht12.count) {
switch (function) {
case FUNC_EVERY_SECOND:
Dht12EverySecond();
break;
case FUNC_JSON_APPEND:
Dht12Show(1);
break;
#ifdef USE_WEBSERVER
case FUNC_WEB_SENSOR:
Dht12Show(0);
break;
#endif // USE_WEBSERVER
}
}
return result;
}
#endif // USE_DHT12
#endif // USE_I2C

View File

@ -187,7 +187,7 @@ a_features = [[
"USE_SHUTTER","USE_PCF8574","USE_DDSU666","USE_DEEPSLEEP",
"USE_SONOFF_SC","USE_SONOFF_RF","USE_SONOFF_L1","USE_EXS_DIMMER",
"USE_ARDUINO_SLAVE","USE_HIH6","USE_HPMA","USE_TSL2591",
"","","","",
"USE_DHT12","","","",
"","","","",
"","","",""
]]