diff --git a/I2CDEVICES.md b/I2CDEVICES.md index c7b42108f..b607b3241 100644 --- a/I2CDEVICES.md +++ b/I2CDEVICES.md @@ -64,4 +64,4 @@ Index | Define | Driver | Device | Address(es) | Description 41 | USE_DHT12 | xsns_58 | DHT12 | 0x5C | Temperature and humidity sensor 42 | USE_DS1624 | xsns_59 | DS1621 | 0x48 - 0x4F | Temperature sensor 42 | USE_DS1624 | xsns_59 | DS1624 | 0x48 - 0x4F | Temperature sensor - + 43 | USE_AHT1x | xsns_63 | AHT10/15 | 0x38 | Temperature and humidity sensor diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 0962f6617..dba7abeed 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -52,15 +52,14 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 8.1.0.8 +### Version 8.1.0.9 - Change Lights: simplified gamma correction and 10 bits internal computation - Change commands ``Prefix``, ``Ssid``, ``StateText``, ``NTPServer``, and ``FriendlyName`` displaying all items - Change IRremoteESP8266 library updated to v2.7.3 - Change Zigbee command prefix from ``Zigbee*`` to ``Zb*`` -- Change wifi connectivity stability (#7602) -- Change some wifi code to attempt faster connection (#7621) - Change MQTT message size with additional 200 characters +- Change display of some date and time messages from "Wed Feb 19 10:45:12 2020" to "2020-02-19T10:45:12" - Fix Sonoff Bridge, Sc, L1, iFan03 and CSE7766 serial interface to forced speed, config and disable logging - Fix commands ``Display`` and ``Counter`` from overruling command processing (#7322) - Fix ``White`` added to light status (#7142) @@ -74,6 +73,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Fix PWM flickering at low levels (#7415) - Fix Hass sensor discovery part 1/4 by Federico Leoni (#7582, #7548) - Fix MaxPower functionality (#7647) +- Fix relation between RSSI and signal strength - Add command ``SetOption79 0/1`` to enable reset of counters at teleperiod time by Andre Thomas (#7355) - Add command ``SetOption82 0/1`` to limit the CT range for Alexa to 200..380 - Add command ``SetOption84 1`` to send AWS IoT device shadow updates (alternative to retained) @@ -103,3 +103,4 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add support for FiF LE-01MR energy meter by saper-2 (#7584) - Add new DHT driver. The old driver can still be used using define USE_DHT_OLD (#7468) - Add another new DHT driver based on ESPEasy. The old driver can still be used using define USE_DHT_OLD. The previous new driver can be used with define USE_DHT_V2 (#7717) +- Add initial support for Sensors AHT10 and AHT15 by Martin Wagner (#7596) \ No newline at end of file diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index 383e7f04b..93bbbb5ba 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -226,10 +226,10 @@ build_flags = ${esp82xx_defaults.build_flags} [core_stage] ; *** Esp8266 core for Arduino version latest beta -platform = espressif8266@2.3.1 +platform = espressif8266@2.3.2 platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git +board_build.ldscript = eagle.flash.1m.ld build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Teagle.flash.1m.ld -DBEARSSL_SSL_BASIC -DNOPRINTFLOAT ; NONOSDK221 diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 0366cfb7f..2689a7222 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,9 +1,16 @@ ## Unreleased (development) +### 8.1.0.9 20200220 + +- Revert most wifi connectivity changes introduced in 8.1.0.5 (#7746, #7602, #7621) +- Add initial support for Sensors AHT10 and AHT15 by Martin Wagner (#7596) + ### 8.1.0.8 20200212 - Change MQTT message size with additional 200 characters - Change some wifi code to attempt faster connection (#7621) +- Change display of some date and time messages from "Wed Feb 19 10:45:12 2020" to "2020-02-19T10:45:12" +- Fix relation between RSSI and signal strength - Add another new DHT driver based on ESPEasy. The old driver can still be used using define USE_DHT_OLD. The previous new driver can be used with define USE_DHT_V2 (#7717) ### 8.1.0.7 20200210 diff --git a/tasmota/language/bg-BG.h b/tasmota/language/bg-BG.h index 270300bf7..be2fceb3c 100644 --- a/tasmota/language/bg-BG.h +++ b/tasmota/language/bg-BG.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/cs-CZ.h b/tasmota/language/cs-CZ.h index 8c47e47ab..6ef51f27d 100644 --- a/tasmota/language/cs-CZ.h +++ b/tasmota/language/cs-CZ.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/de-DE.h b/tasmota/language/de-DE.h index 615020f33..cf2aa258b 100644 --- a/tasmota/language/de-DE.h +++ b/tasmota/language/de-DE.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/el-GR.h b/tasmota/language/el-GR.h index a73651d93..b3608bb7b 100644 --- a/tasmota/language/el-GR.h +++ b/tasmota/language/el-GR.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/en-GB.h b/tasmota/language/en-GB.h index b9f03bacc..66a6e0243 100644 --- a/tasmota/language/en-GB.h +++ b/tasmota/language/en-GB.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/es-ES.h b/tasmota/language/es-ES.h index 9b0b08888..59916f487 100644 --- a/tasmota/language/es-ES.h +++ b/tasmota/language/es-ES.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/fr-FR.h b/tasmota/language/fr-FR.h index 455bec483..5356848d8 100644 --- a/tasmota/language/fr-FR.h +++ b/tasmota/language/fr-FR.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RF TX" #define D_SENSOR_RFRECV "RF RX" #define D_SENSOR_TUYA_TX "Tuya TX" diff --git a/tasmota/language/he-HE.h b/tasmota/language/he-HE.h index 009191f54..fa3b07a31 100644 --- a/tasmota/language/he-HE.h +++ b/tasmota/language/he-HE.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/hu-HU.h b/tasmota/language/hu-HU.h index 65de942cb..541d0c783 100644 --- a/tasmota/language/hu-HU.h +++ b/tasmota/language/hu-HU.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/it-IT.h b/tasmota/language/it-IT.h index a8ab6f1c6..62127ef24 100644 --- a/tasmota/language/it-IT.h +++ b/tasmota/language/it-IT.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/ko-KO.h b/tasmota/language/ko-KO.h index 9607cd9d5..2a20ce2d0 100644 --- a/tasmota/language/ko-KO.h +++ b/tasmota/language/ko-KO.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/nl-NL.h b/tasmota/language/nl-NL.h index 6602a7129..658f18547 100644 --- a/tasmota/language/nl-NL.h +++ b/tasmota/language/nl-NL.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/pl-PL.h b/tasmota/language/pl-PL.h index 06bf65d06..e2d59a2dc 100644 --- a/tasmota/language/pl-PL.h +++ b/tasmota/language/pl-PL.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/pt-BR.h b/tasmota/language/pt-BR.h index a896196b1..da386917c 100644 --- a/tasmota/language/pt-BR.h +++ b/tasmota/language/pt-BR.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/pt-PT.h b/tasmota/language/pt-PT.h index 551f4767e..1f9c36a6b 100644 --- a/tasmota/language/pt-PT.h +++ b/tasmota/language/pt-PT.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/ru-RU.h b/tasmota/language/ru-RU.h index b4708ac10..846a653ac 100644 --- a/tasmota/language/ru-RU.h +++ b/tasmota/language/ru-RU.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/sk-SK.h b/tasmota/language/sk-SK.h index 5427059bc..f335ca42d 100644 --- a/tasmota/language/sk-SK.h +++ b/tasmota/language/sk-SK.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/sv-SE.h b/tasmota/language/sv-SE.h index dea7e0210..9485c1f4e 100644 --- a/tasmota/language/sv-SE.h +++ b/tasmota/language/sv-SE.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/tr-TR.h b/tasmota/language/tr-TR.h index 8fc13e0df..ee2a548ae 100644 --- a/tasmota/language/tr-TR.h +++ b/tasmota/language/tr-TR.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/uk-UA.h b/tasmota/language/uk-UA.h index 9365f68e7..98a352ea7 100644 --- a/tasmota/language/uk-UA.h +++ b/tasmota/language/uk-UA.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFRecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/zh-CN.h b/tasmota/language/zh-CN.h index 019b679f4..c46d353ea 100644 --- a/tasmota/language/zh-CN.h +++ b/tasmota/language/zh-CN.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/zh-TW.h b/tasmota/language/zh-TW.h index 5d7c00069..118aeb501 100644 --- a/tasmota/language/zh-TW.h +++ b/tasmota/language/zh-TW.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 406fd19af..57e10c955 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -487,6 +487,7 @@ // #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_DS1624 // [I2cDriver42] Enable DS1624, DS1621 temperature sensor (I2C addresses 0x48 - 0x4F) (+1k2 code) +// #define USE_AHT1x // [I2cDriver43] Enable AHT10/15 humidity and temperature sensor (I2C address 0x38) (+0k8 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 @@ -618,7 +619,9 @@ #define USE_HX711 // Add support for HX711 load cell (+1k5 code) // #define USE_HX711_GUI // Add optional web GUI to HX711 as scale (+1k8 code) -//#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+2k code) +// Select none or only one of the below defines +//#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+1k3 code) +//#define USE_TX23_WIND_SENSOR // Add support for La Crosse TX23 anemometer (+1k4 code) //#define USE_RC_SWITCH // Add support for RF transceiver using library RcSwitch (+2k7 code, 460 iram) diff --git a/tasmota/support.ino b/tasmota/support.ino index 336774105..ed2cea4c1 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -51,7 +51,8 @@ void OsWatchTicker(void) uint32_t last_run = abs(t - oswatch_last_loop_time); #ifdef DEBUG_THEO - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_OSWATCH " FreeRam %d, rssi %d %% (%d dBm), last_run %d"), ESP.getFreeHeap(), WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.RSSI(), last_run); + int32_t rssi = WiFi.RSSI(); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_OSWATCH " FreeRam %d, rssi %d %% (%d dBm), last_run %d"), ESP.getFreeHeap(), WifiGetRssiAsQuality(rssi), rssi, last_run); #endif // DEBUG_THEO if (last_run >= (OSWATCH_RESET_TIME * 1000)) { // AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_OSWATCH " " D_BLOCKED_LOOP ". " D_RESTARTING)); // Save iram space diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index b4c575e31..772e22eeb 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -455,13 +455,13 @@ void CmndStatus(void) #if defined(USE_TIMERS) && defined(USE_SUNRISE) Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS7_TIME "\":{\"" D_JSON_UTC_TIME "\":\"%s\",\"" D_JSON_LOCAL_TIME "\":\"%s\",\"" D_JSON_STARTDST "\":\"%s\",\"" D_JSON_ENDDST "\":\"%s\",\"" D_CMND_TIMEZONE "\":%s,\"" D_JSON_SUNRISE "\":\"%s\",\"" D_JSON_SUNSET "\":\"%s\"}}"), - GetTime(0).c_str(), GetTime(1).c_str(), GetTime(2).c_str(), - GetTime(3).c_str(), stemp, GetSun(0).c_str(), GetSun(1).c_str()); + GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_LOCALNOTZ).c_str(), GetDateAndTime(DT_DST).c_str(), + GetDateAndTime(DT_STD).c_str(), stemp, GetSun(0).c_str(), GetSun(1).c_str()); #else Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS7_TIME "\":{\"" D_JSON_UTC_TIME "\":\"%s\",\"" D_JSON_LOCAL_TIME "\":\"%s\",\"" D_JSON_STARTDST "\":\"%s\",\"" D_JSON_ENDDST "\":\"%s\",\"" D_CMND_TIMEZONE "\":%s}}"), - GetTime(0).c_str(), GetTime(1).c_str(), GetTime(2).c_str(), - GetTime(3).c_str(), stemp); + GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_LOCALNOTZ).c_str(), GetDateAndTime(DT_DST).c_str(), + GetDateAndTime(DT_STD).c_str(), stemp); #endif // USE_TIMERS and USE_SUNRISE MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "7")); } diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index 2dc25b8e5..ba1a2e465 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -367,7 +367,7 @@ void GetFeatures(void) #ifdef USE_PZEM_DC feature_sns2 |= 0x00001000; // xnrg_06_pzem_dc.ino #endif -#ifdef USE_TX20_WIND_SENSOR +#if defined(USE_TX20_WIND_SENSOR) || defined(USE_TX23_WIND_SENSOR) feature_sns2 |= 0x00002000; // xsns_35_tx20.ino #endif #ifdef USE_MGC3130 @@ -513,8 +513,9 @@ void GetFeatures(void) #ifdef USE_LE01MR feature5 |= 0x08000000; // xnrg_13_fif_le01mr.ino #endif - -// feature5 |= 0x10000000; +#ifdef USE_AHT1x + feature5 |= 0x10000000; // xsns_63_aht1x.ino +#endif // feature5 |= 0x20000000; // feature5 |= 0x40000000; // feature5 |= 0x80000000; diff --git a/tasmota/support_rtc.ino b/tasmota/support_rtc.ino index f8fb25779..3b7da8e37 100644 --- a/tasmota/support_rtc.ino +++ b/tasmota/support_rtc.ino @@ -47,7 +47,6 @@ struct RTC { uint32_t ntp_time = 0; uint32_t midnight = 0; uint32_t restart_time = 0; - int32_t drift_time = 0; int32_t time_timezone = 0; uint8_t ntp_sync_minute = 0; bool midnight_now = false; @@ -64,11 +63,6 @@ uint32_t LocalTime(void) return Rtc.local_time; } -int32_t DriftTime(void) -{ - return Rtc.drift_time; -} - uint32_t Midnight(void) { return Rtc.midnight; @@ -170,8 +164,8 @@ String GetDT(uint32_t time) /* * timestamps in https://en.wikipedia.org/wiki/ISO_8601 format * - * DT_UTC - current data and time in Greenwich, England (aka GMT) - * DT_LOCAL - current date and time taking timezone into account + * DT_UTC - current data and time in Greenwich, England (aka GMT) + * DT_LOCAL - current date and time taking timezone into account * DT_RESTART - the date and time this device last started, in local timezone * * Format: @@ -184,21 +178,30 @@ String GetDateAndTime(uint8_t time_type) uint32_t time = Rtc.local_time; switch (time_type) { - case DT_BOOTCOUNT: - time = Settings.bootcount_reset_time; - break; - case DT_ENERGY: - time = Settings.energy_kWhtotal_time; - break; case DT_UTC: time = Rtc.utc_time; break; +// case DT_LOCALNOTZ: // Is default anyway but allows for not appendig timezone +// time = Rtc.local_time; +// break; + case DT_DST: + time = Rtc.daylight_saving_time; + break; + case DT_STD: + time = Rtc.standard_time; + break; case DT_RESTART: if (Rtc.restart_time == 0) { return ""; } time = Rtc.restart_time; break; + case DT_ENERGY: + time = Settings.energy_kWhtotal_time; + break; + case DT_BOOTCOUNT: + time = Settings.bootcount_reset_time; + break; } String dt = GetDT(time); // 2017-03-07T11:08:02 if (Settings.flag3.time_append_timezone && (DT_LOCAL == time_type)) { // SetOption52 - Append timezone to JSON time @@ -207,23 +210,6 @@ String GetDateAndTime(uint8_t time_type) return dt; // 2017-03-07T11:08:02-07:00 } -String GetTime(int type) -{ - /* type 1 - Local time - * type 2 - Daylight Savings time - * type 3 - Standard time - */ - char stime[25]; // Skip newline - - uint32_t time = Rtc.utc_time; - if (1 == type) time = Rtc.local_time; - if (2 == type) time = Rtc.daylight_saving_time; - if (3 == type) time = Rtc.standard_time; - snprintf_P(stime, sizeof(stime), sntp_get_real_time(time)); - - return String(stime); // Thu Nov 01 11:41:02 2018 -} - uint32_t UpTime(void) { if (Rtc.restart_time) { @@ -388,7 +374,6 @@ void RtcSecond(void) Rtc.ntp_time = sntp_get_current_timestamp(); if (Rtc.ntp_time > START_VALID_TIME) { // Fix NTP bug in core 2.4.1/SDK 2.2.1 (returns Thu Jan 01 08:00:10 1970 after power on) ntp_force_sync = false; - if (Rtc.utc_time > START_VALID_TIME) { Rtc.drift_time = Rtc.ntp_time - Rtc.utc_time; } Rtc.utc_time = Rtc.ntp_time; Rtc.ntp_sync_minute = 60; // Sync so block further requests if (Rtc.restart_time == 0) { @@ -400,8 +385,8 @@ void RtcSecond(void) Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); // Do not use AddLog_P2 here (interrupt routine) if syslog or mqttlog is enabled. UDP/TCP will force exception 9 - PrepLog_P2(LOG_LEVEL_DEBUG, PSTR("NTP: Drift %d, (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), - DriftTime(), GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); + PrepLog_P2(LOG_LEVEL_DEBUG, PSTR("NTP: " D_UTC_TIME " %s, " D_DST_TIME " %s, " D_STD_TIME " %s"), + GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); if (Rtc.local_time < START_VALID_TIME) { // 2016-01-01 rules_flag.time_init = 1; diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index a638ef26e..b4d699cb6 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -650,9 +650,10 @@ void MqttShowState(void) MqttShowPWMState(); } + int32_t rssi = WiFi.RSSI(); ResponseAppend_P(PSTR(",\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_SIGNAL "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}}"), Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), WiFi.BSSIDstr().c_str(), WiFi.channel(), - WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.RSSI(), WifiLinkCount(), WifiDowntime().c_str()); + WifiGetRssiAsQuality(rssi), rssi, WifiLinkCount(), WifiDowntime().c_str()); } void MqttPublishTeleState(void) diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 47a45ba00..58656c4a9 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -22,17 +22,14 @@ \*********************************************************************************************/ #ifndef WIFI_RSSI_THRESHOLD -// Decrease the roam threshold from 10 to 5 to address devices connecting at very low RSSI and being close to inoperative -#define WIFI_RSSI_THRESHOLD 5 // Difference in dB between current network and scanned network +#define WIFI_RSSI_THRESHOLD 10 // Difference in dB between current network and scanned network #endif #ifndef WIFI_RESCAN_MINUTES -// Increase rescan interval from 44 to 5 minutes to improve ability for devices to reach network harmony -#define WIFI_RESCAN_MINUTES 5 // Number of minutes between wifi network rescan +#define WIFI_RESCAN_MINUTES 44 // Number of minutes between wifi network rescan #endif const uint8_t WIFI_CONFIG_SEC = 180; // seconds before restart -// Drop from 20 seconds to 5 seconds since we control the reconnections, not the Arduino SDK -const uint8_t WIFI_CHECK_SEC = 5; // seconds +const uint8_t WIFI_CHECK_SEC = 20; // seconds const uint8_t WIFI_RETRY_OFFSET_SEC = 20; // seconds #include // Wifi, MQTT, Ota, WifiManager @@ -52,8 +49,7 @@ struct WIFI { uint8_t config_counter = 0; uint8_t mdns_begun = 0; // mDNS active uint8_t scan_state; - uint8_t bssid[6] = {0}; - uint8_t bssid_last[6] = {0}; // store the last connect bssid + uint8_t bssid[6]; int8_t best_network_db; } Wifi; @@ -187,11 +183,7 @@ void WifiBegin(uint8_t flag, uint8_t channel) // if (WiFi.getPhyMode() != WIFI_PHY_MODE_11N) { WiFi.setPhyMode(WIFI_PHY_MODE_11N); } // B/G/N // if (WiFi.getPhyMode() != WIFI_PHY_MODE_11G) { WiFi.setPhyMode(WIFI_PHY_MODE_11G); } // B/G if (!WiFi.getAutoConnect()) { WiFi.setAutoConnect(true); } - - // Handle the reconnection in WifiCheckIp() since the autoreconnect keeps sending deauthentication messages which causes the AP to block traffic as it looks like an DoS attack - // This needs to be explicitly called as "false" otherwise the default is enabled -// WiFi.setAutoReconnect(false); // See #7621 - +// WiFi.setAutoReconnect(true); switch (flag) { case 0: // AP1 case 1: // AP2 @@ -249,7 +241,7 @@ void WifiBeginAfterScan(void) if (2 == Wifi.scan_state) { uint8_t* bssid = WiFi.BSSID(); // Get current bssid memcpy((void*) &Wifi.bssid, (void*) bssid, sizeof(Wifi.bssid)); - Wifi.best_network_db = WiFi.RSSI(); // Get current rssi and add threshold + Wifi.best_network_db = WiFi.RSSI(); // Get current rssi and add threshold if (Wifi.best_network_db < -WIFI_RSSI_THRESHOLD) { Wifi.best_network_db += WIFI_RSSI_THRESHOLD; } @@ -273,12 +265,6 @@ void WifiBeginAfterScan(void) } // Scan done if (5 == Wifi.scan_state) { - uint32_t number_known = 0; // count the number of known AP's so we can clear the Wifi.bssid_last if there is only one - int32_t channel_max = 0; // No scan result - int8_t ap_max = 3; // AP default if not found - uint8_t bssid_max[6]; // Save last bssid - memcpy((void*) &bssid_max, (void*) &Wifi.bssid, sizeof(bssid_max)); // store the strongest bssid - int32_t channel = 0; // No scan result int8_t ap = 3; // AP default if not found uint8_t last_bssid[6]; // Save last bssid @@ -302,25 +288,12 @@ void WifiBeginAfterScan(void) for (j = 0; j < MAX_SSIDS; j++) { if (ssid_scan == SettingsText(SET_STASSID1 + j)) { // SSID match known = true; - number_known++; if (rssi_scan > Wifi.best_network_db) { // Best network if (sec_scan == ENC_TYPE_NONE || SettingsText(SET_STAPWD1 + j)) { // Check for passphrase if not open wlan - // store the max values in case there is only one AP and we need to try to reconnect - memcpy((void*) &bssid_max, (void*) bssid_scan, sizeof(bssid_max)); - channel_max = chan_scan; - ap_max = j; - // if the bssid is not the same as the last failed attempt, force picking the next strongest AP to prevent getting stuck on a strong RSSI, but poor channel health - for (uint32_t i = 0; i < sizeof(Wifi.bssid_last); i++) { - if (bssid_scan[i] != Wifi.bssid_last[i]) { - Wifi.best_network_db = (int8_t)rssi_scan; - channel = chan_scan; - ap = j; // AP1 or AP2 - memcpy((void*) &Wifi.bssid, (void*) bssid_scan, sizeof(Wifi.bssid)); - // save the last bssid used - memcpy((void*) &Wifi.bssid_last, (void*) bssid_scan, sizeof(Wifi.bssid_last)); - break; - } - } + Wifi.best_network_db = (int8_t)rssi_scan; + channel = chan_scan; + ap = j; // AP1 or AP2 + memcpy((void*) &Wifi.bssid, (void*) bssid_scan, sizeof(Wifi.bssid)); } } break; @@ -340,16 +313,6 @@ void WifiBeginAfterScan(void) WiFi.scanDelete(); // Clean up Ram delay(0); } - - // reset the last bssid if there is only one AP to allow the reconnect of the same AP on the next cycle - if (number_known == 1) { - // clear the last value - memset((void*) &Wifi.bssid_last, 0, sizeof(Wifi.bssid_last)); - memcpy((void*) &Wifi.bssid, (void*) bssid_max, sizeof(Wifi.bssid)); - channel = channel_max; - ap = ap_max; - } - Wifi.scan_state = 0; // If bssid changed then (re)connect wifi for (uint32_t i = 0; i < sizeof(Wifi.bssid); i++) { @@ -424,13 +387,15 @@ void WifiCheckIp(void) #else if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0)) { #endif // LWIP_IPV6=1 - // initialize the last connect bssid since we had a successful connection - memset((void*) &Wifi.bssid_last, 0, sizeof(Wifi.bssid_last)); WifiSetState(1); Wifi.counter = WIFI_CHECK_SEC; Wifi.retry = Wifi.retry_init; if (Wifi.status != WL_CONNECTED) { AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECTED)); +// AddLog_P(LOG_LEVEL_INFO, PSTR("Wifi: Set IP addresses")); + Settings.ip_address[1] = (uint32_t)WiFi.gatewayIP(); + Settings.ip_address[2] = (uint32_t)WiFi.subnetMask(); + Settings.ip_address[3] = (uint32_t)WiFi.dnsIP(); } Wifi.status = WL_CONNECTED; #ifdef USE_DISCOVERY @@ -448,13 +413,11 @@ void WifiCheckIp(void) switch (Wifi.status) { case WL_CONNECTED: AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_NO_IP_ADDRESS)); - // if poor channel health prevents DHCP broadcast from succeeding, restart the request - // The code will eventually do a recoonect when the 1/2 interval is hit to try another access point if this remains unsuccessful - wifi_station_dhcpc_start(); + Wifi.status = 0; + Wifi.retry = Wifi.retry_init; break; case WL_NO_SSID_AVAIL: AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_NOT_REACHED)); - if (WIFI_WAIT == Settings.sta_config) { Wifi.retry = Wifi.retry_init; } else { @@ -465,21 +428,17 @@ void WifiCheckIp(void) Wifi.retry = 0; } } - break; case WL_CONNECT_FAILED: AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_WRONG_PASSWORD)); - if (Wifi.retry > (Wifi.retry_init / 2)) { Wifi.retry = Wifi.retry_init / 2; } else if (Wifi.retry) { Wifi.retry = 0; } - break; default: // WL_IDLE_STATUS and WL_DISCONNECTED - // log on the 1/2 or full interval if (!Wifi.retry || ((Wifi.retry_init / 2) == Wifi.retry)) { AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_TIMEOUT)); } else { @@ -491,11 +450,9 @@ void WifiCheckIp(void) } } } - if (Wifi.retry) { if (Settings.flag3.use_wifi_scan) { // SetOption56 - Scan wifi network at restart for configured AP's - // check the 1/2 interval as well when rescanning - scan state machine takes 4 seconds - if ((Wifi.retry_init == Wifi.retry) || ((Wifi.retry_init / 2) == Wifi.retry)){ + if (Wifi.retry_init == Wifi.retry) { Wifi.scan_state = 1; // Select scanned SSID } } else { @@ -646,6 +603,7 @@ String WifiGetOutputPower(void) dtostrfd((float)(Settings.wifi_output_power) / 10, 1, stemp1); return String(stemp1); } + void WifiSetOutputPower(void) { WiFi.setOutputPower((float)(Settings.wifi_output_power) / 10); @@ -657,9 +615,7 @@ void WifiConnect(void) WifiSetOutputPower(); WiFi.persistent(false); // Solve possible wifi init errors Wifi.status = 0; - // lower the rety times now Tasmota control the reconnections, not the Arduino SDK - // Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + ((ESP.getChipId() & 0xF) * 2); - Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + (ESP.getChipId() & 0xF); + Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + ((ESP.getChipId() & 0xF) * 2); Wifi.retry = Wifi.retry_init; Wifi.counter = 1; } diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index d5db7abb9..5745ff9c6 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -226,7 +226,7 @@ enum WeekInMonthOptions {Last, First, Second, Third, Fourth}; enum DayOfTheWeekOptions {Sun=1, Mon, Tue, Wed, Thu, Fri, Sat}; enum MonthNamesOptions {Jan=1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec}; enum HemisphereOptions {North, South}; -enum GetDateAndTimeOptions { DT_LOCAL, DT_UTC, DT_RESTART, DT_ENERGY, DT_BOOTCOUNT }; +enum GetDateAndTimeOptions { DT_LOCAL, DT_UTC, DT_LOCALNOTZ, DT_DST, DT_STD, DT_RESTART, DT_ENERGY, DT_BOOTCOUNT }; enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE}; diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index 74d6b0d84..fc94e5167 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -167,6 +167,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack //#define USE_PAJ7620 // Enable PAJ7620 gesture sensor (I2C address 0x73) (+2.5k code) //#define USE_PCF8574 // Enable PCF8574 I/O Expander (I2C addresses 0x20 - 0x26 and 0x39 - 0x3F) (+1k9 code) #define USE_HIH6 // Enable Honywell HIH Humidity and Temperature sensor (I2C address 0x27) (+0k6) +//#define USE_AHT1x // Enable AHT10/15 humidity and temperature sensor (I2C address 0x38) (+0k8 code) #define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code) #define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code) @@ -214,7 +215,8 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #define USE_TM1638 // Add support for TM1638 switches copying Switch1 .. Switch8 (+1k code) #define USE_HX711 // Add support for HX711 load cell (+1k5 code) //#define USE_HX711_GUI // Add optional web GUI to HX711 as scale (+1k8 code) -//#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+2k code) +//#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+1k3 code) +//#define USE_TX23_WIND_SENSOR // Add support for La Crosse TX23 anemometer (+1k4 code) #define USE_RC_SWITCH // Add support for RF transceiver using library RcSwitch (+2k7 code, 460 iram) #define USE_RF_SENSOR // Add support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) // #define USE_THEO_V2 // Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver (+1k4 code) @@ -406,6 +408,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 #undef USE_HX711 // Disable support for HX711 load cell #undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer +#undef USE_TX23_WIND_SENSOR // Disable support for La Crosse TX23 anemometer #undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) @@ -515,6 +518,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 #undef USE_HX711 // Disable support for HX711 load cell #undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer +#undef USE_TX23_WIND_SENSOR // Disable support for La Crosse TX23 anemometer #undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) @@ -627,6 +631,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 #undef USE_HX711 // Disable support for HX711 load cell #undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer +#undef USE_TX23_WIND_SENSOR // Disable support for La Crosse TX23 anemometer #undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index b099eb49b..c4ee7b19d 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -128,7 +128,7 @@ enum UserSelectablePins { GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface GPIO_HX711_SCK, // HX711 Load Cell clock GPIO_HX711_DAT, // HX711 Load Cell data - GPIO_TX20_TXD_BLACK, // TX20 Transmission Pin + GPIO_TX2X_TXD_BLACK, // TX20/TX23 Transmission Pin GPIO_RFSEND, // RF transmitter GPIO_RFRECV, // RF receiver GPIO_TUYA_TX, // Tuya Serial interface @@ -267,7 +267,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_PZEM016_RX "|" D_SENSOR_PZEM017_RX "|" D_SENSOR_DFR562 "|" D_SENSOR_SDS0X1_TX "|" D_SENSOR_HX711_SCK "|" D_SENSOR_HX711_DAT "|" - D_SENSOR_TX20_TX "|" + D_SENSOR_TX2X_TX "|" D_SENSOR_RFSEND "|" D_SENSOR_RFRECV "|" D_SENSOR_TUYA_TX "|" D_SENSOR_TUYA_RX "|" D_SENSOR_MGC3130_XFER "|" D_SENSOR_MGC3130_RESET "|" @@ -721,8 +721,8 @@ const uint8_t kGpioNiceList[] PROGMEM = { #ifdef USE_PMS5003 GPIO_PMS5003, // Plantower PMS5003 Serial interface #endif -#ifdef USE_TX20_WIND_SENSOR - GPIO_TX20_TXD_BLACK, // TX20 Transmission Pin +#if defined(USE_TX20_WIND_SENSOR) || defined(USE_TX23_WIND_SENSOR) + GPIO_TX2X_TXD_BLACK, // TX20/TX23 Transmission Pin #endif #ifdef USE_MP3_PLAYER GPIO_MP3_DFR562, // RB-DFR-562, DFPlayer Mini MP3 Player Serial interface diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index d0db39f4b..b1e4eba9f 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,7 +20,7 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x08010008; +const uint32_t VERSION = 0x08010009; // Lowest compatible version const uint32_t VERSION_COMPATIBLE = 0x07010006; diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 4296583e1..3eaa24ef5 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1719,16 +1719,17 @@ void HandleWifiConfiguration(void) //display networks in page for (uint32_t i = 0; i < n; i++) { if (-1 == indices[i]) { continue; } // skip dups + int32_t rssi = WiFi.RSSI(indices[i]) DEBUG_CORE_LOG(PSTR(D_LOG_WIFI D_SSID " %s, " D_BSSID " %s, " D_CHANNEL " %d, " D_RSSI " %d"), - WiFi.SSID(indices[i]).c_str(), WiFi.BSSIDstr(indices[i]).c_str(), WiFi.channel(indices[i]), WiFi.RSSI(indices[i])); - int quality = WifiGetRssiAsQuality(WiFi.RSSI(indices[i])); + WiFi.SSID(indices[i]).c_str(), WiFi.BSSIDstr(indices[i]).c_str(), WiFi.channel(indices[i]), rssi); + int quality = WifiGetRssiAsQuality(rssi); int auth = WiFi.encryptionType(indices[i]); char encryption[20]; WSContentSend_P(PSTR("
%s (%d) %s %d%% (%d dBm)
"), HtmlEscape(WiFi.SSID(indices[i])).c_str(), WiFi.channel(indices[i]), GetTextIndexed(encryption, sizeof(encryption), auth +1, kEncryptionType), - quality, WiFi.RSSI(indices[i]) + quality, rssi ); delay(0); @@ -2067,7 +2068,8 @@ void HandleInformation(void) WSContentSend_P(PSTR("}1" D_FRIENDLY_NAME " %d}2%s"), i +1, SettingsText(SET_FRIENDLYNAME1 +i)); } WSContentSend_P(PSTR("}1}2 ")); // Empty line - WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm)"), Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.RSSI()); + int32_t rssi = WiFi.RSSI(); + WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm)"), Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), WifiGetRssiAsQuality(rssi), rssi); WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), my_hostname, (Wifi.mdns_begun) ? ".local" : ""); #if LWIP_IPV6 String ipv6_addr = WifiGetIPv6(); diff --git a/tasmota/xdrv_16_tuyamcu.ino b/tasmota/xdrv_16_tuyamcu.ino index da189c568..f250f6409 100644 --- a/tasmota/xdrv_16_tuyamcu.ino +++ b/tasmota/xdrv_16_tuyamcu.ino @@ -114,6 +114,7 @@ void (* const TuyaCommand[])(void) PROGMEM = { TuyaSend dpId,data +TuyaSend0 -> Sends TUYA_CMD_QUERY_STATE TuyaSend1 11,1 -> Sends boolean (Type 1) data 0/1 to dpId 11 (Max data length 1 byte) TuyaSend2 11,100 -> Sends integer (Type 2) data 100 to dpId 11 (Max data length 4 bytes) TuyaSend2 11,0xAABBCCDD -> Sends 4 bytes (Type 2) data to dpId 11 (Max data length 4 bytes) @@ -124,9 +125,13 @@ TuyaSend4 11,1 -> Sends enum (Type 4) data 0/1/2/3/4/5 to dpId 11 (Max data leng void CmndTuyaSend(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { + if (XdrvMailbox.index > 4) { + return; + } + if (XdrvMailbox.index == 0) { + TuyaRequestState(); + } else { if (XdrvMailbox.data_len > 0) { - char *p; char *data; uint8_t i = 0; @@ -150,8 +155,8 @@ void CmndTuyaSend(void) { TuyaSendEnum(dpId, strtoul(data, nullptr, 0)); } } - ResponseCmndDone(); } + ResponseCmndDone(); } /* @@ -682,10 +687,31 @@ void TuyaSerialInput(void) // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 uint8_t dpidStart = 6; while (dpidStart + 4 < Tuya.byte_counter) { + uint8_t dpId = Tuya.buffer[dpidStart]; + uint8_t dpDataType = Tuya.buffer[dpidStart + 1]; uint16_t dpDataLen = Tuya.buffer[dpidStart + 2] << 8 | Tuya.buffer[dpidStart + 3]; - ResponseAppend_P(PSTR(",\"%d\":{\"DpId\":%d,\"DpIdType\":%d,\"DpIdData\":\"%s\""), Tuya.buffer[dpidStart], Tuya.buffer[dpidStart], Tuya.buffer[dpidStart + 1], ToHex_P((unsigned char*)&Tuya.buffer[dpidStart + 4], dpDataLen, hex_char, sizeof(hex_char))); - if (TUYA_TYPE_STRING == Tuya.buffer[dpidStart + 1]) { - ResponseAppend_P(PSTR(",\"Type3Data\":\"%.*s\""), dpDataLen, (char *)&Tuya.buffer[dpidStart + 4]); + const unsigned char *dpData = (unsigned char*)&Tuya.buffer[dpidStart + 4]; + const char *dpHexData = ToHex_P(dpData, dpDataLen, hex_char, sizeof(hex_char)); + + if (TUYA_CMD_STATE == Tuya.buffer[3]) { + ResponseAppend_P(PSTR(",\"DpType%uId%u\":"), dpDataType, dpId); + if (TUYA_TYPE_BOOL == dpDataType && dpDataLen == 1) { + ResponseAppend_P(PSTR("%u"), dpData[0]); + } else if (TUYA_TYPE_VALUE == dpDataType && dpDataLen == 4) { + uint32_t dpValue = (uint32_t)dpData[0] << 24 | (uint32_t)dpData[1] << 16 | (uint32_t)dpData[2] << 8 | (uint32_t)dpData[3] << 0; + ResponseAppend_P(PSTR("%u"), dpValue); + } else if (TUYA_TYPE_STRING == dpDataType) { + ResponseAppend_P(PSTR("\"%.*s\""), dpDataLen, dpData); + } else if (TUYA_TYPE_ENUM == dpDataType && dpDataLen == 1) { + ResponseAppend_P(PSTR("%u"), dpData[0]); + } else { + ResponseAppend_P(PSTR("\"0x%s\""), dpHexData); + } + } + + ResponseAppend_P(PSTR(",\"%d\":{\"DpId\":%d,\"DpIdType\":%d,\"DpIdData\":\"%s\""), dpId, dpId, dpDataType, dpHexData); + if (TUYA_TYPE_STRING == dpDataType) { + ResponseAppend_P(PSTR(",\"Type3Data\":\"%.*s\""), dpDataLen, dpData); } ResponseAppend_P(PSTR("}")); dpidStart += dpDataLen + 4; diff --git a/tasmota/xsns_05_ds18x20.ino b/tasmota/xsns_05_ds18x20.ino index ba87e3a5d..5b46d5519 100644 --- a/tasmota/xsns_05_ds18x20.ino +++ b/tasmota/xsns_05_ds18x20.ino @@ -126,6 +126,8 @@ void OneWireWriteBit(uint8_t v) delayMicroseconds(delay_high[v]); } +/* +// Fails for reasons unknown to me uint8_t OneWireReadBit(void) { if (!ds18x20_dual_mode) { @@ -143,6 +145,35 @@ uint8_t OneWireReadBit(void) delayMicroseconds(53); return r; } +*/ +// Works fine in contrast to above. Why? +void OneWireReadBit1(void) +{ + pinMode(ds18x20_pin, OUTPUT); + digitalWrite(ds18x20_pin, LOW); + delayMicroseconds(3); + pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); // SetOption74 - Enable internal pullup for single DS18x20 sensor +} + +void OneWireReadBit2(void) +{ + digitalWrite(ds18x20_pin_out, LOW); + delayMicroseconds(3); + digitalWrite(ds18x20_pin_out, HIGH); +} + +uint8_t OneWireReadBit(void) +{ + if (!ds18x20_dual_mode) { + OneWireReadBit1(); + } else { + OneWireReadBit2(); + } + delayMicroseconds(10); + uint8_t r = digitalRead(ds18x20_pin); + delayMicroseconds(53); + return r; +} /*------------------------------------------------------------------------------------------*/ @@ -284,6 +315,7 @@ void Ds18x20Init(void) uint64_t ids[DS18X20_MAX_SENSORS]; ds18x20_pin = pin[GPIO_DSB]; + if (pin[GPIO_DSB_OUT] < 99) { ds18x20_pin_out = pin[GPIO_DSB_OUT]; ds18x20_dual_mode = true; // Dual pins mode as used by Shelly @@ -419,6 +451,8 @@ void Ds18x20Name(uint8_t sensor) void Ds18x20EverySecond(void) { + if (!ds18x20_sensors) { return; } + #ifdef W1_PARASITE_POWER // skip access if there is still an eeprom write ongoing unsigned long now = millis(); diff --git a/tasmota/xsns_33_ds3231.ino b/tasmota/xsns_33_ds3231.ino index 0c72c6b11..09814bcf0 100644 --- a/tasmota/xsns_33_ds3231.ino +++ b/tasmota/xsns_33_ds3231.ino @@ -143,7 +143,7 @@ void DS3231EverySecond(void) Rtc.daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year); Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); AddLog_P2(LOG_LEVEL_INFO, PSTR("Set time from DS3231 to RTC (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), - GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); + GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); if (Rtc.local_time < START_VALID_TIME) { // 2016-01-01 rules_flag.time_init = 1; } else { @@ -152,7 +152,7 @@ void DS3231EverySecond(void) } else if (!ds3231WriteStatus && Rtc.utc_time > START_VALID_TIME && abs(Rtc.utc_time - ReadFromDS3231()) > 60) {//if time is valid and is drift from RTC in more that 60 second AddLog_P2(LOG_LEVEL_INFO, PSTR("Write Time TO DS3231 from NTP (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), - GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); + GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); SetDS3231Time (Rtc.utc_time); //update the DS3231 time ds3231WriteStatus = true; } diff --git a/tasmota/xsns_35_tx20.ino b/tasmota/xsns_35_tx20.ino index 0c61392bc..850c7deda 100644 --- a/tasmota/xsns_35_tx20.ino +++ b/tasmota/xsns_35_tx20.ino @@ -1,7 +1,7 @@ /* - xsns_35_Tx20.ino - La Crosse Tx20 wind sensor support for Tasmota + xsns_35_Tx20.ino - La Crosse Tx20/Tx23 wind sensor support for Tasmota - Copyright (C) 2020 Thomas Eckerstorfer and Theo Arends + Copyright (C) 2020 Thomas Eckerstorfer, Norbert Richter and Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,19 +17,31 @@ along with this program. If not, see . */ -#ifdef USE_TX20_WIND_SENSOR +#if defined(USE_TX20_WIND_SENSOR) || defined(USE_TX23_WIND_SENSOR) +#if defined(USE_TX20_WIND_SENSOR) && defined(USE_TX23_WIND_SENSOR) +#undef USE_TX20_WIND_SENSOR +#warning **** use USE_TX20_WIND_SENSOR or USE_TX23_WIND_SENSOR but not both together, TX20 disabled **** +#endif /*********************************************************************************************\ - * La Crosse Tx20 wind sensor + * La Crosse TX20/TX23 Anemometer * * based on https://github.com/bunnyhu/ESP8266_TX20_wind_sensor/ * http://blog.bubux.de/windsensor-tx20-mit-esp8266/ * https://www.john.geek.nz/2011/07/la-crosse-tx20-anemometer-communication-protocol/ + * http://www.rd-1000.com/chpm78/lacrosse/Lacrosse_TX23_protocol.html + * https://www.john.geek.nz/2012/08/la-crosse-tx23u-anemometer-communication-protocol/ + * + * TX23 RJ11 connection: + * 1 yellow - GND + * 2 green - NC + * 3 red - Vcc 3.3V + * 4 black/brown - TxD Signal (GPIOxx) \*********************************************************************************************/ #define XSNS_35 35 -#define TX20_BIT_TIME 1220 // microseconds -#define TX20_RESET_VALUES 60 // seconds +#define TX2X_BIT_TIME 1220 // microseconds +#define TX2X_RESET_VALUES 60 // seconds // The Arduino standard GPIO routines are not enough, // must use some from the Espressif SDK as well @@ -37,17 +49,21 @@ extern "C" { #include "gpio.h" } +#ifdef USE_TX20_WIND_SENSOR + #define D_TX2x_NAME "TX20" +#else + #define D_TX2x_NAME "TX23" +#endif + #ifdef USE_WEBSERVER - -const char HTTP_SNS_TX20[] PROGMEM = - "{s}TX20 " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}TX20 " D_TX20_WIND_SPEED_AVG "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}TX20 " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}TX20 " D_TX20_WIND_DIRECTION "{m}%s{e}"; - +const char HTTP_SNS_TX2X[] PROGMEM = + "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_AVG "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION "{m}%s (%s°){e}"; #endif // USE_WEBSERVER -const char kTx20Directions[] PROGMEM = D_TX20_NORTH "|" +const char kTx2xDirections[] PROGMEM = D_TX20_NORTH "|" D_TX20_NORTH D_TX20_NORTH D_TX20_EAST "|" D_TX20_NORTH D_TX20_EAST "|" D_TX20_EAST D_TX20_NORTH D_TX20_EAST "|" @@ -64,133 +80,218 @@ const char kTx20Directions[] PROGMEM = D_TX20_NORTH "|" D_TX20_NORTH D_TX20_WEST "|" D_TX20_NORTH D_TX20_NORTH D_TX20_WEST; -uint8_t tx20_sa = 0; -uint8_t tx20_sb = 0; -uint8_t tx20_sd = 0; -uint8_t tx20_se = 0; -uint16_t tx20_sc = 0; -uint16_t tx20_sf = 0; +uint8_t tx2x_sa = 0; +uint8_t tx2x_sb = 0; +uint8_t tx2x_sd = 0; +uint8_t tx2x_se = 0; +uint16_t tx2x_sc = 0; +uint16_t tx2x_sf = 0; -float tx20_wind_speed_kmh = 0; -float tx20_wind_speed_max = 0; -float tx20_wind_speed_avg = 0; -float tx20_wind_sum = 0; -int tx20_count = 0; -uint8_t tx20_wind_direction = 0; +float tx2x_wind_speed_kmh = 0; +float tx2x_wind_speed_max = 0; +float tx2x_wind_speed_avg = 0; +float tx2x_wind_sum = 0; +int tx2x_count = 0; +uint8_t tx2x_wind_direction = 0; -bool tx20_available = false; +bool tx2x_available = false; + +#ifdef USE_TX23_WIND_SENSOR +uint8_t tx23_stage = 0; +#endif #ifndef ARDUINO_ESP8266_RELEASE_2_3_0 // Fix core 2.5.x ISR not in IRAM Exception -void Tx20StartRead(void) ICACHE_RAM_ATTR; // As iram is tight and it works this way too +void TX2xStartRead(void) ICACHE_RAM_ATTR; // As iram is tight and it works this way too #endif // ARDUINO_ESP8266_RELEASE_2_3_0 -void Tx20StartRead(void) +void TX2xStartRead(void) { - /* La Crosse TX20 Anemometer datagram every 2 seconds + /** + * La Crosse TX20 Anemometer datagram every 2 seconds * 0-0 11011 0011 111010101111 0101 1100 000101010000 0-0 - Received pin data at 1200 uSec per bit * sa sb sc sd se sf * 00100 1100 000101010000 1010 1100 000101010000 - sa to sd inverted user data, LSB first - * sa - Start frame always 00100 + * sa - Start frame (invert) 00100 + * sb - Wind direction (invert) 0 - 15 + * sc - Wind speed 0 (invert) - 511 + * sd - Checksum (invert) + * se - Wind direction 0 - 15 + * sf - Wind speed 0 - 511 + * + * La Crosse TX23 Anemometer datagram after setting TxD to low/high + * 1-1 0 1 0-0 11011 0011 111010101111 0101 1100 000101010000 1-1 - Received pin data at 1200 uSec per bit + * t s c sa sb sc sd se sf + * 1 0 1-1 00100 1100 000101010000 1010 1100 000101010000 - sa to sd inverted user data, LSB first + * t - host pulls TxD low - signals TX23 to sent measurement + * s - TxD released - TxD is pulled high due to pullup + * c - TX23U pulls TxD low - calculation in progress + * sa - Start frame 11011 * sb - Wind direction 0 - 15 * sc - Wind speed 0 - 511 * sd - Checksum - * se - Wind direction 0 - 15 - * sf - Wind speed 0 - 511 + * se - Wind direction (invert) 0 - 15 + * sf - Wind speed (invert) 0 - 511 */ +#ifdef USE_TX23_WIND_SENSOR + if (0!=tx23_stage) + { + if ((2==tx23_stage) || (3==tx23_stage)) + { +#endif + tx2x_available = false; - tx20_available = false; + tx2x_sa = 0; + tx2x_sb = 0; + tx2x_sd = 0; + tx2x_se = 0; + tx2x_sc = 0; + tx2x_sf = 0; - tx20_sa = 0; - tx20_sb = 0; - tx20_sd = 0; - tx20_se = 0; - tx20_sc = 0; - tx20_sf = 0; + delayMicroseconds(TX2X_BIT_TIME / 2); - delayMicroseconds(TX20_BIT_TIME / 2); + for (int32_t bitcount = 41; bitcount > 0; bitcount--) { + uint8_t dpin = (digitalRead(pin[GPIO_TX2X_TXD_BLACK])); +#ifdef USE_TX23_WIND_SENSOR + if (bitcount > 41 - 5) { + // start + tx2x_sa = (tx2x_sa << 1) | (dpin); + } else if (bitcount > 41 - 5 - 4) { + // wind dir + tx2x_sb = tx2x_sb >> 1 | ((dpin) << 3); + } else if (bitcount > 41 - 5 - 4 - 12) { + // windspeed + tx2x_sc = tx2x_sc >> 1 | ((dpin) << 11); + } else if (bitcount > 41 - 5 - 4 - 12 - 4) { + // checksum + tx2x_sd = tx2x_sd >> 1 | ((dpin) << 3); + } else if (bitcount > 41 - 5 - 4 - 12 - 4 - 4) { + // wind dir (invert) + tx2x_se = tx2x_se >> 1 | ((dpin ^ 1) << 3); + } else { + // windspeed (invert) + tx2x_sf = tx2x_sf >> 1 | ((dpin ^ 1) << 11); + } +#else + if (bitcount > 41 - 5) { + // start frame (invert) + tx2x_sa = (tx2x_sa << 1) | (dpin ^ 1); + } else if (bitcount > 41 - 5 - 4) { + // wind dir (invert) + tx2x_sb = tx2x_sb >> 1 | ((dpin ^ 1) << 3); + } else if (bitcount > 41 - 5 - 4 - 12) { + // windspeed (invert) + tx2x_sc = tx2x_sc >> 1 | ((dpin ^ 1) << 11); + } else if (bitcount > 41 - 5 - 4 - 12 - 4) { + // checksum (invert) + tx2x_sd = tx2x_sd >> 1 | ((dpin ^ 1) << 3); + } else if (bitcount > 41 - 5 - 4 - 12 - 4 - 4) { + // wind dir + tx2x_se = tx2x_se >> 1 | (dpin << 3); + } else { + // windspeed + tx2x_sf = tx2x_sf >> 1 | (dpin << 11); + } +#endif + delayMicroseconds(TX2X_BIT_TIME); + } - for (int32_t bitcount = 41; bitcount > 0; bitcount--) { - uint8_t dpin = (digitalRead(pin[GPIO_TX20_TXD_BLACK])); - if (bitcount > 41 - 5) { - // start, inverted - tx20_sa = (tx20_sa << 1) | (dpin ^ 1); - } else if (bitcount > 41 - 5 - 4) { - // wind dir, inverted - tx20_sb = tx20_sb >> 1 | ((dpin ^ 1) << 3); - } else if (bitcount > 41 - 5 - 4 - 12) { - // windspeed, inverted - tx20_sc = tx20_sc >> 1 | ((dpin ^ 1) << 11); - } else if (bitcount > 41 - 5 - 4 - 12 - 4) { - // checksum, inverted - tx20_sd = tx20_sd >> 1 | ((dpin ^ 1) << 3); - } else if (bitcount > 41 - 5 - 4 - 12 - 4 - 4) { - // wind dir - tx20_se = tx20_se >> 1 | (dpin << 3); - } else { - // windspeed - tx20_sf = tx20_sf >> 1 | (dpin << 11); + uint8_t chk = (tx2x_sb + (tx2x_sc & 0xf) + ((tx2x_sc >> 4) & 0xf) + ((tx2x_sc >> 8) & 0xf)); + chk &= 0xf; + +#ifdef USE_TX23_WIND_SENSOR + // check checksum, non-inverted with inverted values and max. speed + if ((chk == tx2x_sd) && (tx2x_sb==tx2x_se) && (tx2x_sc==tx2x_sf) && (tx2x_sc < 511)) { + tx2x_available = true; + } +#else + if ((chk == tx2x_sd) && (tx2x_sc < 511)) { // if checksum seems to be ok and wind speed below 51.1 m/s + tx2x_available = true; + } +#endif +#ifdef USE_TX23_WIND_SENSOR } - - delayMicroseconds(TX20_BIT_TIME); + tx23_stage++; } +#endif - uint8_t chk = (tx20_sb + (tx20_sc & 0xf) + ((tx20_sc >> 4) & 0xf) + ((tx20_sc >> 8) & 0xf)); - chk &= 0xf; - - if ((chk == tx20_sd) && (tx20_sc < 400)) { // if checksum seems to be ok and wind speed below 40 m/s - tx20_available = true; - } -/* - if ((tx20_sb == tx20_se) && (tx20_sc == tx20_sf) && (tx20_sc < 400)) { - tx20_available = true; - } -*/ // Must clear this bit in the interrupt register, // it gets set even when interrupts are disabled - GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << pin[GPIO_TX20_TXD_BLACK]); + GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << pin[GPIO_TX2X_TXD_BLACK]); } -void Tx20Read(void) +void Tx2xReset(void) { - if (!(uptime % TX20_RESET_VALUES)) { - tx20_count = 0; - tx20_wind_sum = 0; - tx20_wind_speed_max = 0; + tx2x_count = 0; + tx2x_wind_sum = 0; + tx2x_wind_speed_max = 0; +} + +void Tx2xRead(void) +{ +#ifdef USE_TX23_WIND_SENSOR + // note: TX23 speed calculation is unstable when conversion starts + // less than 2 seconds after last request + if ((uptime % 3)==0) { + // TX23 start transmission by pulling down TxD line for at minimum 500ms + // so we pull TxD signal to low every 3 seconds + tx23_stage = 0; + pinMode(pin[GPIO_TX2X_TXD_BLACK], OUTPUT); + digitalWrite(pin[GPIO_TX2X_TXD_BLACK], LOW); + } else if ((uptime % 3)==1) { + // after pulling down TxD every 3 second we pull-up TxD every 3+1 seconds + // to trigger start transmission + tx23_stage = 1; // first rising signal is invalid + pinMode(pin[GPIO_TX2X_TXD_BLACK], INPUT_PULLUP); } - else if (tx20_available) { - tx20_wind_speed_kmh = float(tx20_sc) * 0.36; - if (tx20_wind_speed_kmh > tx20_wind_speed_max) { - tx20_wind_speed_max = tx20_wind_speed_kmh; +#endif + if (0==Settings.tele_period && !(uptime % TX2X_RESET_VALUES)) { + Tx2xReset(); + } + else if (tx2x_available) { + // Wind speed spec: 0 to 180 km/h (0 to 50 m/s) + tx2x_wind_speed_kmh = float(tx2x_sc) * 0.36; + if (tx2x_wind_speed_kmh > tx2x_wind_speed_max) { + tx2x_wind_speed_max = tx2x_wind_speed_kmh; } - tx20_count++; - tx20_wind_sum += tx20_wind_speed_kmh; - tx20_wind_speed_avg = tx20_wind_sum / tx20_count; - tx20_wind_direction = tx20_sb; + tx2x_count++; + tx2x_wind_sum += tx2x_wind_speed_kmh; + tx2x_wind_speed_avg = tx2x_wind_sum / tx2x_count; + tx2x_wind_direction = tx2x_sb; } } -void Tx20Init(void) { - pinMode(pin[GPIO_TX20_TXD_BLACK], INPUT); - attachInterrupt(pin[GPIO_TX20_TXD_BLACK], Tx20StartRead, RISING); +void Tx2xInit(void) +{ +#ifdef USE_TX23_WIND_SENSOR + tx23_stage = 0; + pinMode(pin[GPIO_TX2X_TXD_BLACK], OUTPUT); + digitalWrite(pin[GPIO_TX2X_TXD_BLACK], LOW); +#else + pinMode(pin[GPIO_TX2X_TXD_BLACK], INPUT); +#endif + attachInterrupt(pin[GPIO_TX2X_TXD_BLACK], TX2xStartRead, RISING); } -void Tx20Show(bool json) +void Tx2xShow(bool json) { char wind_speed_string[33]; - dtostrfd(tx20_wind_speed_kmh, 2, wind_speed_string); + dtostrfd(tx2x_wind_speed_kmh, 1, wind_speed_string); char wind_speed_max_string[33]; - dtostrfd(tx20_wind_speed_max, 2, wind_speed_max_string); + dtostrfd(tx2x_wind_speed_max, 1, wind_speed_max_string); char wind_speed_avg_string[33]; - dtostrfd(tx20_wind_speed_avg, 2, wind_speed_avg_string); + dtostrfd(tx2x_wind_speed_avg, 1, wind_speed_avg_string); char wind_direction_string[4]; - GetTextIndexed(wind_direction_string, sizeof(wind_direction_string), tx20_wind_direction, kTx20Directions); + GetTextIndexed(wind_direction_string, sizeof(wind_direction_string), tx2x_wind_direction, kTx2xDirections); + char wind_direction_degree[33]; + dtostrfd(tx2x_wind_direction*22.5, 1, wind_direction_degree); if (json) { - ResponseAppend_P(PSTR(",\"TX20\":{\"Speed\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\"}"), - wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); + ResponseAppend_P(PSTR(",\"" D_TX2x_NAME "\":{\"Speed\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\",\"Degree\":%s}"), + wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string, wind_direction_degree); + Tx2xReset(); #ifdef USE_WEBSERVER } else { - WSContentSend_PD(HTTP_SNS_TX20, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); + WSContentSend_PD(HTTP_SNS_TX2X, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string, wind_direction_degree); #endif // USE_WEBSERVER } } @@ -203,20 +304,20 @@ bool Xsns35(uint8_t function) { bool result = false; - if (pin[GPIO_TX20_TXD_BLACK] < 99) { + if (pin[GPIO_TX2X_TXD_BLACK] < 99) { switch (function) { case FUNC_INIT: - Tx20Init(); + Tx2xInit(); break; case FUNC_EVERY_SECOND: - Tx20Read(); + Tx2xRead(); break; case FUNC_JSON_APPEND: - Tx20Show(1); + Tx2xShow(1); break; #ifdef USE_WEBSERVER case FUNC_WEB_SENSOR: - Tx20Show(0); + Tx2xShow(0); break; #endif // USE_WEBSERVER } @@ -224,4 +325,4 @@ bool Xsns35(uint8_t function) return result; } -#endif // USE_TX20_WIND_SENSOR \ No newline at end of file +#endif // USE_TX20_WIND_SENSOR || USE_TX23_WIND_SENSOR \ No newline at end of file diff --git a/tasmota/xsns_63_aht1x.ino b/tasmota/xsns_63_aht1x.ino new file mode 100644 index 000000000..542cb72ea --- /dev/null +++ b/tasmota/xsns_63_aht1x.ino @@ -0,0 +1,190 @@ +/* + xsns_63_AHT1x.ino - AHT10 I2C temperature and humidity sensor support for Tasmota + + Copyright (C) 2020 Martin Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_I2C +#ifdef USE_AHT1x +/*********************************************************************************************\ + * AHT10/15 - Temperature and Humidity + * + * I2C Address: 0x38 +\*********************************************************************************************/ + +#define XSNS_63 63 +#define XI2C_43 43 // See I2CDEVICES.md + +#define AHT10_ADDR 0x38 + +uint8_t eSensorCalibrateCmd[3] = {0xE1, 0x08, 0x00}; +uint8_t eSensorNormalCmd[3] = {0xA8, 0x00, 0x00}; +uint8_t eSensorMeasureCmd[3] = {0xAC, 0x33, 0x00}; +uint8_t eSensorResetCmd = 0xBA; + +struct AHT10 { + float humidity = NAN; + float temperature = NAN; + uint8_t valid = 0; + uint8_t count = 0; + char name[6] = "AHT1x"; +} AHT10; + +bool AHT10Read(void) +{ + if (AHT10.valid) { AHT10.valid--; } + + uint8_t data[6]; + + Wire.beginTransmission(AHT10_ADDR); + Wire.write(eSensorMeasureCmd, 3); + Wire.endTransmission(); + delay(100); + + Wire.requestFrom(AHT10_ADDR, 6); + for (uint32_t i = 0; Wire.available() > 0; i++) { + data[i] = Wire.read(); + } + + uint32_t result_h = ((data[1] << 16) | (data[2] << 8) | data[3]) >> 4; + uint32_t result_t = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5]; + + float humidity = result_h * 100 / 1048576; + float temperature = ((200 * result_t) / 1048576) - 50; + + if (isnan(temperature) || isnan(humidity)) { return false; } + + AHT10.humidity = ConvertHumidity(humidity); + AHT10.temperature = ConvertTemp(temperature); + + AHT10.valid = SENSOR_MAX_MISS; + return true; +} + +/********************************************************************************************/ + +bool AHT10Init(void) +{ + Wire.begin(AHT10_ADDR); + Wire.beginTransmission(AHT10_ADDR); + Wire.write(eSensorCalibrateCmd, 3); + Wire.endTransmission(); + + delay(500); // ?!?! too long + + return (0x08 == (AHT10ReadStatus() & 0x68)); +} + +uint8_t AHT10ReadStatus(void) +{ + Wire.requestFrom(AHT10_ADDR, 1); + uint8_t result = Wire.read(); + return result; +} + +void AHT10Reset(void) +{ + Wire.beginTransmission(AHT10_ADDR); + Wire.write(eSensorResetCmd); + Wire.endTransmission(); + delay(20); +} + +/********************************************************************************************/ + +void AHT10Detect(void) +{ + if (I2cActive(AHT10_ADDR)) { return; } + + if (AHT10Init()) { + I2cSetActiveFound(AHT10_ADDR, AHT10.name); + AHT10.count = 1; + } +} + +void AHT10EverySecond(void) +{ + if (uptime &1) { + // AHT10: 55mS + if (!AHT10Read()) { + AddLogMissed(AHT10.name, AHT10.valid); + } + } +} + +void AHT10Show(bool json) +{ + if (AHT10.valid) { + char temperature[33]; + dtostrfd(AHT10.temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(AHT10.humidity, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, AHT10.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, AHT10.temperature); + KnxSensor(KNX_HUMIDITY, AHT10.humidity); + } +#endif // USE_KNX +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, AHT10.name, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, AHT10.name, humidity); +#endif // USE_WEBSERVER + } + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xsns63(uint8_t function) +{ + if (!I2cEnabled(XI2C_43)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + AHT10Detect(); + } + else if (AHT10.count) { + switch (function) { + case FUNC_EVERY_SECOND: + AHT10EverySecond(); + break; + case FUNC_JSON_APPEND: + AHT10Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + AHT10Show(0); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + +#endif // USE_AHT10 +#endif // USE_I2C diff --git a/tools/decode-status.py b/tools/decode-status.py index f4d00833a..210175de8 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -193,7 +193,7 @@ a_features = [[ "USE_ARDUINO_SLAVE","USE_HIH6","USE_HPMA","USE_TSL2591", "USE_DHT12","USE_DS1624","USE_GPS","USE_HOTPLUG", "USE_NRF24","USE_MIBLE","USE_HM10","USE_LE01MR", - "","","","" + "USE_AHT1x","","","" ],[ "","","","", "","","","", @@ -236,7 +236,7 @@ else: obj = json.load(fp) def StartDecode(): - print ("\n*** decode-status.py v20200210 by Theo Arends and Jacek Ziolkowski ***") + print ("\n*** decode-status.py v20200220 by Theo Arends and Jacek Ziolkowski ***") # print("Decoding\n{}".format(obj))