diff --git a/README.md b/README.md
index 952bb895e..784695004 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE.
-Current version is **5.12.0d** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information.
+Current version is **5.12.0e** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information.
### ATTENTION All versions
diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino
index 51ebe785b..721b8d376 100644
--- a/sonoff/_releasenotes.ino
+++ b/sonoff/_releasenotes.ino
@@ -1,10 +1,19 @@
-/* 5.12.0d
+/* 5.12.0e
+ * Add a second TLS fingerprint to allow switching keys in TLS mode (#2033, #2102)
+ *
+ * 5.12.0d
* Add support for optional MQTT drivers to be selected in user_config.h (#1992)
* Add Portuguese language file
* Add compiler check for stable lwIP version v1.4 (#1940)
+ * Add always suffix with device number in Mqtt discovery topic (#1962)
* Add diacritics to Polish language file (#2005)
* Add Hungarian language file (#2024)
+ * Add Czech language file
+ * Add Chinese (Traditional) in Taiwan language file (#2108)
* Add support for Nova Fitness SDS011 and possibly SDS021 particle concentration sensor (#2070)
+ * Add single decimal precision to Nova Fitness SDS0x1 sensor values (#2093)
+ * Add support for multiple SHT3X sensors (#1949, #2110)
+ * Add Sonoff SC domoticz support for Sound level as Counter and Air quality (#2118)
* Fix MQTT TLS fingerprint validation (#2033)
*
* 5.12.0c
diff --git a/sonoff/language/cz-CZ.h b/sonoff/language/cz-CZ.h
new file mode 100644
index 000000000..a3cae2bbc
--- /dev/null
+++ b/sonoff/language/cz-CZ.h
@@ -0,0 +1,458 @@
+/*
+ cz-CZ.h - localization for Czech without fonetick - Czech for Sonoff-Tasmota
+
+ Copyright (C) 2018 Theo Arends (translated by vs)
+
+ 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 .
+*/
+
+#ifndef _LANGUAGE_CZ_CZ_H_
+#define _LANGUAGE_CZ_CZ_H_
+
+/*************************** ATTENTION *******************************\
+ *
+ * Due to memory constraints only UTF-8 is supported.
+ * To save code space keep text as short as possible.
+ * Time and Date provided by SDK can not be localized (yet).
+ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
+ * Use online command Prefix to translate cmnd, stat and tele.
+ *
+\*********************************************************************/
+
+//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
+
+// "2017-03-07T11:08:02" - ISO8601:2004
+#define D_YEAR_MONTH_SEPARATOR "-"
+#define D_MONTH_DAY_SEPARATOR "-"
+#define D_DATE_TIME_SEPARATOR "T"
+#define D_HOUR_MINUTE_SEPARATOR ":"
+#define D_MINUTE_SECOND_SEPARATOR ":"
+
+#define D_DAY3LIST "PonUteStrCtvPatSobNed"
+#define D_MONTH3LIST "LedUnoBreDubKveCerCevSrpZarRijLisPro"
+
+// Non JSON decimal separator
+#define D_DECIMAL_SEPARATOR ","
+
+// Common
+#define D_ADMIN "Admin"
+#define D_AIR_QUALITY "Kvalita vzduchu"
+#define D_AP "AP" // Access Point
+#define D_AS "jako"
+#define D_AUTO "AUTO"
+#define D_BLINK "Blikani"
+#define D_BLINKOFF "BlikaniVyp"
+#define D_BOOT_COUNT "Pocitadlo spusteni"
+#define D_BRIGHTLIGHT "Svetly"
+#define D_BUTTON "Tlacitko"
+#define D_BY "by" // Written by me
+#define D_BYTES "Bytu"
+#define D_CELSIUS "Celsia"
+#define D_CO2 "Kyslicniku uhliciteho"
+#define D_CODE "kod" // Button code
+#define D_COLDLIGHT "Studeny"
+#define D_COMMAND "Prikaz"
+#define D_CONNECTED "Pripojeny"
+#define D_COUNT "Pocitej"
+#define D_COUNTER "Pocitadlo"
+#define D_CURRENT "Aktualni" // As in Voltage and Current
+#define D_DATA "Data"
+#define D_DARKLIGHT "Tmavy"
+#define D_DEBUG "Debug"
+#define D_DISABLED "Zablokovany"
+#define D_DNS_SERVER "Server DNS"
+#define D_DONE "Provedeno"
+#define D_DST_TIME "DST"
+#define D_EMULATION "Emulace"
+#define D_ENABLED "Otevrene"
+#define D_ERASE "Vymaz"
+#define D_ERROR "Chyba"
+#define D_FAHRENHEIT "Fahrenheita"
+#define D_FAILED "Chybny"
+#define D_FALLBACK "Nahradni"
+#define D_FALLBACK_TOPIC "Nahradni topic"
+#define D_FALSE "Nepravda"
+#define D_FILE "Soubor"
+#define D_FREE_MEMORY "Volna pamet"
+#define D_GAS "Gas"
+#define D_GATEWAY "Brana"
+#define D_GROUP "Skupina"
+#define D_HOST "Server"
+#define D_HOSTNAME "Nazev serveru"
+#define D_HUMIDITY "Vlhkost"
+#define D_ILLUMINANCE "Osvetleni"
+#define D_IMMEDIATE "Okamzite" // Button immediate
+#define D_INDEX "Index"
+#define D_INFO "Informace"
+#define D_INITIALIZED "Inicializovany"
+#define D_IP_ADDRESS "Adresa IP"
+#define D_LIGHT "Svetlo"
+#define D_LWT "LWT"
+#define D_MODULE "Modul"
+#define D_MQTT "MQTT"
+#define D_MULTI_PRESS "nekolikere-stisknuti"
+#define D_NOISE "Hluk"
+#define D_NONE "Neni"
+#define D_OFF "Vypnuty"
+#define D_OFFLINE "Neaktivni"
+#define D_OK "Ok"
+#define D_ON "Sepnuty"
+#define D_ONLINE "Aktivni"
+#define D_PASSWORD "Heslo"
+#define D_PORT "Port"
+#define D_POWER_FACTOR "Soucinitel prikonu"
+#define D_POWERUSAGE "Prikon"
+#define D_PRESSURE "Tlak"
+#define D_PRESSUREATSEALEVEL "Tlak na urovni hladiny more"
+#define D_PROGRAM_FLASH_SIZE "Velikost programu flash"
+#define D_PROGRAM_SIZE "Velikost programu"
+#define D_PROJECT "Projekt"
+#define D_RECEIVED "Obdrzeny"
+#define D_RESTART "Restart"
+#define D_RESTARTING "Restartovani"
+#define D_RESTART_REASON "Pricina restartu"
+#define D_RESTORE "Nacteni"
+#define D_RETAINED "Ulozene"
+#define D_SAVE "Uloz"
+#define D_SENSOR "Sensor"
+#define D_SSID "SSID"
+#define D_START "Start"
+#define D_STD_TIME "STD"
+#define D_STOP "Stop"
+#define D_SUBNET_MASK "Maska podsite"
+#define D_SUBSCRIBE_TO "Prihlas se do"
+#define D_SUCCESSFUL "uspesne."
+#define D_TEMPERATURE "Teplota"
+#define D_TO "do"
+#define D_TOGGLE "Prepni"
+#define D_TOPIC "Topic"
+#define D_TRANSMIT "Odesli"
+#define D_TRUE "Pravda"
+#define D_UPGRADE "aktualizace"
+#define D_UPLOAD "Nahrani..."
+#define D_UPTIME "Uptime"
+#define D_USER "Uzivatel"
+#define D_UTC_TIME "UTC"
+#define D_UV_LEVEL "Uroven UV"
+#define D_VERSION "Verze"
+#define D_VOLTAGE "Napeti"
+#define D_WARMLIGHT "Ohrev"
+#define D_WEB_SERVER "Web Server"
+
+// sonoff.ino
+#define D_WARNING_MINIMAL_VERSION "WARNING This version does not support persistent settings"
+#define D_LEVEL_10 "uroven 1-0"
+#define D_LEVEL_01 "uroven 0-1"
+#define D_SERIAL_LOGGING_DISABLED "Vypnute logovani na seriovem portu"
+#define D_SYSLOG_LOGGING_REENABLED "Obnoven zapis do Syslog"
+
+#define D_SET_BAUDRATE_TO "Nastaveni rychlosti prenosu na"
+#define D_RECEIVED_TOPIC "Obdrzeny topic"
+#define D_DATA_SIZE "Velikost dat"
+#define D_ANALOG_INPUT "Analogovy vstup"
+
+#define D_FINGERPRINT "Verifikuj otisk TLS..."
+#define D_TLS_CONNECT_FAILED_TO "Nepripojeno TLS do"
+#define D_RETRY_IN "Zopakuji za"
+#define D_VERIFIED "Zverifikovano otisk"
+#define D_INSECURE "Nespravne pripojeni z duvodu chybneho otisku TLS"
+#define D_CONNECT_FAILED_TO "Spojeni se nepodarilo navazat"
+
+// support.ino
+#define D_OSWATCH "osWatch"
+#define D_BLOCKED_LOOP "Zablokovani smycky"
+#define D_WPS_FAILED_WITH_STATUS "Chyba WPSconfig se statusem"
+#define D_ACTIVE_FOR_3_MINUTES "aktivni 3 minuty"
+#define D_FAILED_TO_START "nezdarilo se spustit"
+#define D_PATCH_ISSUE_2186 "Chyba 2186"
+#define D_CONNECTING_TO_AP "Pripojovani k AP"
+#define D_IN_MODE "v modu"
+#define D_CONNECT_FAILED_NO_IP_ADDRESS "Chyba pripojeni, nebyla obdrzena IP adresa"
+#define D_CONNECT_FAILED_AP_NOT_REACHED "Chyba pripojeni, nedostupny AP"
+#define D_CONNECT_FAILED_WRONG_PASSWORD "Chyba pripojeni, nespravne heslo pro AP"
+#define D_CONNECT_FAILED_AP_TIMEOUT "Chyba pripojeni, uplynul AP timeout"
+#define D_ATTEMPTING_CONNECTION "Zkouska pripojeni..."
+#define D_CHECKING_CONNECTION "Zkouska spojeni..."
+#define D_QUERY_DONE "Vyslan dotaz. Nalezena sluzba MQTT"
+#define D_MQTT_SERVICE_FOUND "Sluzba MQTT byla nalezena"
+#define D_FOUND_AT "znalezeno v"
+#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host nebyl nalezen"
+
+// settings.ino
+#define D_SAVED_TO_FLASH_AT "Ulozeno do pameti flash v"
+#define D_LOADED_FROM_FLASH_AT "Stazeno z pameti flash z"
+#define D_USE_DEFAULTS "Pouzij defaultni hodnoty"
+#define D_ERASED_SECTOR "Smazany sektor"
+
+// webserver.ino
+#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Oprogramowanie MINIMAL - prosze uaktualnic"
+#define D_WEBSERVER_ACTIVE_ON "Aktivni Web server"
+#define D_WITH_IP_ADDRESS "na adrese IP"
+#define D_WEBSERVER_STOPPED "Web server zastaven"
+#define D_FILE_NOT_FOUND "Soubor nebyl nalezen"
+#define D_REDIRECTED "Presmerovani na vlastni portal"
+#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wi-Fi manager nastavi AP a zachova STA"
+#define D_WIFIMANAGER_SET_ACCESSPOINT "Wi-Fi manager nastavi Access Point"
+#define D_TRYING_TO_CONNECT "Zkousim pripojit zarizeni k siti"
+
+#define D_RESTART_IN "Restart"
+#define D_SECONDS "sekund"
+#define D_DEVICE_WILL_RESTART "Zarizeni bude restartovano behem nekolika sekund"
+#define D_BUTTON_TOGGLE "Prepinac"
+#define D_CONFIGURATION "Nastaveni"
+#define D_INFORMATION "Informace"
+#define D_FIRMWARE_UPGRADE "Aktualizace firmware"
+#define D_CONSOLE "Konzole"
+#define D_CONFIRM_RESTART "Potvrzeni restartu"
+
+#define D_CONFIGURE_MODULE "Nastaveni modulu"
+#define D_CONFIGURE_WIFI "Nastaveni WiFi"
+#define D_CONFIGURE_MQTT "Nastaveni MQTT"
+#define D_CONFIGURE_DOMOTICZ "Nastaveni Domoticz"
+#define D_CONFIGURE_LOGGING "Nastaveni logovani"
+#define D_CONFIGURE_OTHER "Jina nastaveni"
+#define D_CONFIRM_RESET_CONFIGURATION "Potvrzeni resetu nastaveni"
+#define D_RESET_CONFIGURATION "Reset nastaveni"
+#define D_BACKUP_CONFIGURATION "Zaloha nastaveni"
+#define D_RESTORE_CONFIGURATION "Obnoveni nastaveni"
+#define D_MAIN_MENU "Hlavni menu"
+
+#define D_MODULE_PARAMETERS "Parametry modulu"
+#define D_MODULE_TYPE "Typ modulu"
+#define D_GPIO "GPIO"
+#define D_SERIAL_IN "Serial In"
+#define D_SERIAL_OUT "Serial Out"
+
+#define D_WIFI_PARAMETERS "Parametry WiFi"
+#define D_SCAN_FOR_WIFI_NETWORKS "Scan siti WiFi"
+#define D_SCAN_DONE "Scan dokoncen"
+#define D_NO_NETWORKS_FOUND "Sit nebyla nalezena"
+#define D_REFRESH_TO_SCAN_AGAIN "Zopakovat scan"
+#define D_DUPLICATE_ACCESSPOINT "Kopie AP"
+#define D_SKIPPING_LOW_QUALITY "Preskoceni z duvodu kvality signalu"
+#define D_RSSI "RSSI"
+#define D_WEP "WEP"
+#define D_WPA_PSK "WPA PSK"
+#define D_WPA2_PSK "WPA2 PSK"
+#define D_AP1_SSID "AP1 SSID"
+#define D_AP1_PASSWORD "Heslo AP1"
+#define D_AP2_SSID "AP2 SSID"
+#define D_AP2_PASSWORD "Heslo AP2"
+
+#define D_MQTT_PARAMETERS "Parametry MQTT"
+#define D_CLIENT "Klient"
+#define D_FULL_TOPIC "Cely topic"
+
+#define D_LOGGING_PARAMETERS "Volby logovani"
+#define D_SERIAL_LOG_LEVEL "Serial uroven logu"
+#define D_WEB_LOG_LEVEL "Webova uroven logu"
+#define D_SYS_LOG_LEVEL "Systemova uroven logu"
+#define D_MORE_DEBUG "Vice debug informaci"
+#define D_SYSLOG_HOST "Syslog host"
+#define D_SYSLOG_PORT "Syslog port"
+#define D_TELEMETRY_PERIOD "Interval telemetrie"
+
+#define D_OTHER_PARAMETERS "Jine parametry"
+#define D_WEB_ADMIN_PASSWORD "Heslo Web administratora"
+#define D_MQTT_ENABLE "MQTT aktivni"
+#define D_FRIENDLY_NAME "Friendly Name"
+#define D_BELKIN_WEMO "Belkin WeMo"
+#define D_HUE_BRIDGE "Hue Bridge"
+#define D_SINGLE_DEVICE "single device"
+#define D_MULTI_DEVICE "multi device"
+
+#define D_SAVE_CONFIGURATION "Uloz nastaveni"
+#define D_CONFIGURATION_SAVED "Nastaveni ulozena"
+#define D_CONFIGURATION_RESET "Nastaveni resetovano"
+
+#define D_PROGRAM_VERSION "Verze programu"
+#define D_BUILD_DATE_AND_TIME "Datum a cas kompilace"
+#define D_CORE_AND_SDK_VERSION "Verze Core/SDK"
+#define D_FLASH_WRITE_COUNT "Pocet zapisu do pameti"
+#define D_MAC_ADDRESS "Adres Mac"
+#define D_MQTT_HOST "Host MQTT"
+#define D_MQTT_PORT "Port MQTT"
+#define D_MQTT_CLIENT "Klient MQTT"
+#define D_MQTT_USER "Uzivatel MQTT"
+#define D_MQTT_TOPIC "Topic MQTT"
+#define D_MQTT_GROUP_TOPIC "Topic skupiny MQTT"
+#define D_MQTT_FULL_TOPIC "Cely topic MQTT"
+#define D_MDNS_DISCOVERY "Ziskavani mDNS"
+#define D_MDNS_ADVERTISE "Rozesilani mDNS"
+#define D_ESP_CHIP_ID "ID systemu ESP"
+#define D_FLASH_CHIP_ID "ID systemu pameti flash"
+#define D_FLASH_CHIP_SIZE "Velikost flash"
+#define D_FREE_PROGRAM_SPACE "Volne misto programu"
+
+#define D_UPGRADE_BY_WEBSERVER "Aktualizace z Web serveru"
+#define D_OTA_URL "URL OTA"
+#define D_START_UPGRADE "Start aktualizace"
+#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizace nahranim souboru"
+#define D_UPLOAD_STARTED "Nahravani zahajeno"
+#define D_UPGRADE_STARTED "Zahajeni aktualizace"
+#define D_UPLOAD_DONE "Nahravani ukonceno"
+#define D_UPLOAD_ERR_1 "Soubor nebyl vybran"
+#define D_UPLOAD_ERR_2 "Malo mista"
+#define D_UPLOAD_ERR_3 "Magicky byte ma jinou hodnotu nez 0xE9"
+#define D_UPLOAD_ERR_4 "Velikost programu je vetsi nez skutecna velikost pameti flash"
+#define D_UPLOAD_ERR_5 "Chyba nahravani, nesouhlasi porovnavane bity"
+#define D_UPLOAD_ERR_6 "Chyba nahravani. Spusten zapis do logu na urovni 3"
+#define D_UPLOAD_ERR_7 "Nahravani preruseno"
+#define D_UPLOAD_ERR_8 "Spatny soubor"
+#define D_UPLOAD_ERR_9 "Soubor je prilis velky"
+#define D_UPLOAD_ERROR_CODE "Chyba nahravani"
+
+#define D_ENTER_COMMAND "Vloz prikaz"
+#define D_ENABLE_WEBLOG_FOR_RESPONSE "Zapni uroven 2 zapisu Weblog, pokud je ocekavana odpoved"
+#define D_NEED_USER_AND_PASSWORD "Vyzadovany uzivatel=&heslo="
+
+// xdrv_wemohue.ino
+#define D_MULTICAST_DISABLED "Multicast je vypnuty"
+#define D_MULTICAST_REJOINED "Multicast opet pripojeny"
+#define D_MULTICAST_JOIN_FAILED "Multicast neuspesny"
+#define D_FAILED_TO_SEND_RESPONSE "Nepodarilo se odeslat odpoved"
+
+#define D_WEMO "WeMo"
+#define D_WEMO_BASIC_EVENT "WeMo zakladni udalost"
+#define D_WEMO_EVENT_SERVICE "WeMo servisni udalost"
+#define D_WEMO_META_SERVICE "WeMo meta udalost"
+#define D_WEMO_SETUP "WeMo setup"
+#define D_RESPONSE_SENT "Odpoved odeslana"
+
+#define D_HUE "Hue"
+#define D_HUE_BRIDGE_SETUP "Hue setup"
+#define D_HUE_API_NOT_IMPLEMENTED "Hue API neni implementovano"
+#define D_HUE_API "Hue API"
+#define D_HUE_POST_ARGS "Hue POST args"
+#define D_3_RESPONSE_PACKETS_SENT "3 pakety odpovedi odeslany"
+
+// xdrv_05_domoticz.ino
+#define D_DOMOTICZ_PARAMETERS "Parametry Domoticz"
+#define D_DOMOTICZ_IDX "Idx"
+#define D_DOMOTICZ_KEY_IDX "Key idx"
+#define D_DOMOTICZ_SWITCH_IDX "Spinac idx"
+#define D_DOMOTICZ_SENSOR_IDX "Sensor idx"
+ #define D_DOMOTICZ_TEMP "Temp"
+ #define D_DOMOTICZ_TEMP_HUM "Temp,Vlhk"
+ #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Vlhk,Tlak"
+ #define D_DOMOTICZ_POWER_ENERGY "Prikon,Energie"
+ #define D_DOMOTICZ_ILLUMINANCE "Osvetleni"
+ #define D_DOMOTICZ_COUNT "Pocitadlo"
+ #define D_DOMOTICZ_VOLTAGE "Napeti"
+ #define D_DOMOTICZ_CURRENT "Proud"
+ #define D_DOMOTICZ_AIRQUALITY "AirQuality"
+#define D_DOMOTICZ_UPDATE_TIMER "Aktualizace stopek"
+
+// xdrv_03_energy.ino
+#define D_ENERGY_TODAY "Energie Dnes"
+#define D_ENERGY_YESTERDAY "Energie Vcera"
+#define D_ENERGY_TOTAL "Energie Soucet"
+
+// xsns_05_ds18b20.ino
+#define D_SENSOR_BUSY "Sensor DS18x20 obsazen"
+#define D_SENSOR_CRC_ERROR "Sensor DS18x20 chyba CRC"
+#define D_SENSORS_FOUND "Nalezen sensor DS18x20"
+
+// xsns_06_dht.ino
+#define D_TIMEOUT_WAITING_FOR "Cekani na"
+#define D_START_SIGNAL_LOW "signal� startovni nizky"
+#define D_START_SIGNAL_HIGH "signal� startovni vysoky"
+#define D_PULSE "puls"
+#define D_CHECKSUM_FAILURE "Chybny kontrolni soucet"
+
+// xsns_07_sht1x.ino
+#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor neobdrzel prikaz ACK"
+#define D_SHT1X_FOUND "SHT1X nalezen"
+
+// xsns_18_pms5003.ino
+#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter
+#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter
+#define D_PARTICALS_BEYOND "Particals"
+
+// sonoff_template.h
+#define D_SENSOR_NONE "Neni"
+#define D_SENSOR_DHT11 "DHT11"
+#define D_SENSOR_AM2301 "AM2301"
+#define D_SENSOR_SI7021 "SI7021"
+#define D_SENSOR_DS18X20 "DS18x20"
+#define D_SENSOR_I2C_SCL "I2C SCL"
+#define D_SENSOR_I2C_SDA "I2C SDA"
+#define D_SENSOR_WS2812 "WS2812"
+#define D_SENSOR_IRSEND "IRsend"
+#define D_SENSOR_SWITCH "Spinac" // Suffix "1"
+#define D_SENSOR_BUTTON "Tlacit" // Suffix "1"
+#define D_SENSOR_RELAY "Rele" // Suffix "1i"
+#define D_SENSOR_LED "Led" // Suffix "1i"
+#define D_SENSOR_PWM "PWM" // Suffix "1"
+#define D_SENSOR_COUNTER "Pocita" // Suffix "1"
+#define D_SENSOR_IRRECV "IRrecv"
+#define D_SENSOR_MHZ_RX "MHZ Rx"
+#define D_SENSOR_MHZ_TX "MHZ Tx"
+#define D_SENSOR_PZEM_RX "PZEM Rx"
+#define D_SENSOR_PZEM_TX "PZEM Tx"
+#define D_SENSOR_SAIR_RX "SAir Rx"
+#define D_SENSOR_SAIR_TX "SAir Tx"
+#define D_SENSOR_SPI_CS "SPI CS"
+#define D_SENSOR_SPI_DC "SPI DC"
+#define D_SENSOR_BACKLIGHT "BkLight"
+#define D_SENSOR_PMS5003 "PMS5003"
+#define D_SENSOR_SDS0X1 "SDS0X1"
+
+// Units
+#define D_UNIT_AMPERE "A"
+#define D_UNIT_HOUR "Hod"
+#define D_UNIT_KILOOHM "kOhm"
+#define D_UNIT_KILOWATTHOUR "kWh"
+#define D_UNIT_LUX "lx"
+#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3"
+#define D_UNIT_MICROMETER "um"
+#define D_UNIT_MICROSECOND "us"
+#define D_UNIT_MILLIAMPERE "mA"
+#define D_UNIT_MILLISECOND "ms"
+#define D_UNIT_MINUTE "Min"
+#define D_UNIT_PARTS_PER_DECILITER "ppd"
+#define D_UNIT_PARTS_PER_MILLION "ppm"
+#define D_UNIT_PRESSURE "hPa"
+#define D_UNIT_SECOND "sec"
+#define D_UNIT_SECTORS "sektory"
+#define D_UNIT_VOLT "V"
+#define D_UNIT_WATT "W"
+#define D_UNIT_WATTHOUR "Wh"
+
+// Log message prefix
+#define D_LOG_APPLICATION "APP: " // Application
+#define D_LOG_BRIDGE "BRG: " // Bridge
+#define D_LOG_CONFIG "CFG: " // Settings
+#define D_LOG_COMMAND "CMD: " // Command
+#define D_LOG_DEBUG "DBG: " // Debug
+#define D_LOG_DHT "DHT: " // DHT sensor
+#define D_LOG_DOMOTICZ "DOM: " // Domoticz
+#define D_LOG_DSB "DSB: " // DS18xB20 sensor
+#define D_LOG_HTTP "HTP: " // HTTP webserver
+#define D_LOG_I2C "I2C: " // I2C
+#define D_LOG_IRR "IRR: " // Infra Red Received
+#define D_LOG_LOG "LOG: " // Logging
+#define D_LOG_MODULE "MOD: " // Module
+#define D_LOG_MDNS "DNS: " // mDNS
+#define D_LOG_MQTT "MQT: " // MQTT
+#define D_LOG_OTHER "OTH: " // Other
+#define D_LOG_RESULT "RSL: " // Result
+#define D_LOG_RFR "RFR: " // RF Received
+#define D_LOG_SERIAL "SER: " // Serial
+#define D_LOG_SHT1 "SHT: " // SHT1x sensor
+#define D_LOG_UPLOAD "UPL: " // Upload
+#define D_LOG_UPNP "UPP: " // UPnP
+#define D_LOG_WIFI "WIF: " // Wifi
+
+#endif // _LANGUAGE_CZ_CZ_H_
diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h
index f1eed0dac..d43055b67 100644
--- a/sonoff/language/de-DE.h
+++ b/sonoff/language/de-DE.h
@@ -165,7 +165,7 @@
#define D_FINGERPRINT "TLS-Fingerabdruck wird verifiziert..."
#define D_TLS_CONNECT_FAILED_TO "TLS-Verbindung fehlgeschlagen an"
#define D_RETRY_IN "Wiederversuch in"
-#define D_VERIFIED "verifiziert"
+#define D_VERIFIED "verifiziert mit Fingerabdruck"
#define D_INSECURE "unsichere Verbindung aufgrund ungültigen Fingerabdrucks"
#define D_CONNECT_FAILED_TO "Verbindung fehlgeschlagen aufgrund von"
diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h
index 987d0ccda..905ed5d9b 100644
--- a/sonoff/language/en-GB.h
+++ b/sonoff/language/en-GB.h
@@ -165,7 +165,7 @@
#define D_FINGERPRINT "Verify TLS fingerprint..."
#define D_TLS_CONNECT_FAILED_TO "TLS Connect failed to"
#define D_RETRY_IN "Retry in"
-#define D_VERIFIED "Verified"
+#define D_VERIFIED "Verified using Fingerprint"
#define D_INSECURE "Insecure connection due to invalid Fingerprint"
#define D_CONNECT_FAILED_TO "Connect failed to"
diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h
index 8386dd605..c46bfa1d5 100644
--- a/sonoff/language/es-AR.h
+++ b/sonoff/language/es-AR.h
@@ -165,7 +165,7 @@
#define D_FINGERPRINT "Verificar TLS fingerprint..."
#define D_TLS_CONNECT_FAILED_TO "Falló Conección TLS a"
#define D_RETRY_IN "Reintentando"
-#define D_VERIFIED "Verificado"
+#define D_VERIFIED "Verificado Fingerprint"
#define D_INSECURE "Conección insegura por Fingerprint no válido"
#define D_CONNECT_FAILED_TO "Falló Conección a"
diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h
index 9364bc102..653887508 100644
--- a/sonoff/language/fr-FR.h
+++ b/sonoff/language/fr-FR.h
@@ -165,7 +165,7 @@
#define D_FINGERPRINT "Verification empreinte TLS ..."
#define D_TLS_CONNECT_FAILED_TO "Echec de connexion TLS à"
#define D_RETRY_IN "Nouvelle tentative dans"
-#define D_VERIFIED "Verifié"
+#define D_VERIFIED "Verifié empreinte "
#define D_INSECURE "Connexion non sécurisée car empreinte non vérifée"
#define D_CONNECT_FAILED_TO "Echec de connexion à"
diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h
index f1fb99c61..9ce316cf9 100644
--- a/sonoff/language/hu-HU.h
+++ b/sonoff/language/hu-HU.h
@@ -165,7 +165,7 @@
#define D_FINGERPRINT "TLS fingerprint hitelesítése..."
#define D_TLS_CONNECT_FAILED_TO "TLS Csatlakozás sikertelen a"
#define D_RETRY_IN "Újrapróbálás"
-#define D_VERIFIED "Hitelesítve"
+#define D_VERIFIED "Hitelesítve Fingerprint"
#define D_INSECURE "Nem biztonságos kapcsolat érvénytelen Fingerprint miatt"
#define D_CONNECT_FAILED_TO "Sikertelen csatlakozás a"
diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h
index ea6ce9804..0e0f4594f 100644
--- a/sonoff/language/it-IT.h
+++ b/sonoff/language/it-IT.h
@@ -165,7 +165,7 @@
#define D_FINGERPRINT "Verifica TLS fingerprint..."
#define D_TLS_CONNECT_FAILED_TO "Connessione TLS fallita a"
#define D_RETRY_IN "Nuovo tentativo in"
-#define D_VERIFIED "Verificato"
+#define D_VERIFIED "Verificato Fingerprint"
#define D_INSECURE "Connessione insicura a causa di Fingerprint non valido"
#define D_CONNECT_FAILED_TO "Connessione Fallita a"
diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h
index c260553a0..0932a7326 100644
--- a/sonoff/language/nl-NL.h
+++ b/sonoff/language/nl-NL.h
@@ -165,7 +165,7 @@
#define D_FINGERPRINT "Controleer TLS vingerafdruk..."
#define D_TLS_CONNECT_FAILED_TO "TLS Verbinding mislukt naar"
#define D_RETRY_IN "Opnieuw proberen over"
-#define D_VERIFIED "Gecontroleerd"
+#define D_VERIFIED "Gecontroleerd met vingerafdruk"
#define D_INSECURE "Door ongeldige vingerafdruk een onveilige verbinding"
#define D_CONNECT_FAILED_TO "Verbinding mislukt naar"
diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h
index 334934a12..1b2bbb099 100644
--- a/sonoff/language/pl-PL.h
+++ b/sonoff/language/pl-PL.h
@@ -165,7 +165,7 @@
#define D_FINGERPRINT "Weryfikuj odcisk TLS..."
#define D_TLS_CONNECT_FAILED_TO "Nieudane połączenie TLS do"
#define D_RETRY_IN "Spróbuj ponownie"
-#define D_VERIFIED "Zweryfikowano"
+#define D_VERIFIED "Zweryfikowano odcisku"
#define D_INSECURE "Nieprawidłowe połączenie z powodu błędnego odcisku TLS"
#define D_CONNECT_FAILED_TO "Nie udało się nawiązać połączenia"
diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h
index 7fd9bac23..cc3b74a04 100644
--- a/sonoff/language/pt-PT.h
+++ b/sonoff/language/pt-PT.h
@@ -165,7 +165,7 @@
#define D_FINGERPRINT "Verifique a impressão digital TLS..."
#define D_TLS_CONNECT_FAILED_TO "TLS não conseguiu ligar"
#define D_RETRY_IN "Tentativa em"
-#define D_VERIFIED "Verificado"
+#define D_VERIFIED "Verificado impressão digital "
#define D_INSECURE "Ligação insegura devido à impressão digital inválida"
#define D_CONNECT_FAILED_TO "A ligação falhou ao"
diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h
index b0f5cd764..d5483b504 100644
--- a/sonoff/language/ru-RU.h
+++ b/sonoff/language/ru-RU.h
@@ -165,7 +165,7 @@
#define D_FINGERPRINT "Проверка TLS Fingerprint..."
#define D_TLS_CONNECT_FAILED_TO "Сбой подключения TLS к"
#define D_RETRY_IN "Повторить"
-#define D_VERIFIED "Проверено"
+#define D_VERIFIED "Проверено Fingerprint"
#define D_INSECURE "Небезопасное соединение, недействительный Fingerprint"
#define D_CONNECT_FAILED_TO "Ошибка подключения к"
diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h
new file mode 100644
index 000000000..8ae1618c6
--- /dev/null
+++ b/sonoff/language/zh-TW.h
@@ -0,0 +1,458 @@
+/*
+ zh-TW.h - localization for Chinese (Traditional) - Taiwan for Sonoff-Tasmota
+
+ Copyright (C) 2018 Theo Arends (translated by dannydu)
+
+ 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 .
+*/
+
+#ifndef _LANGUAGE_ZH_TW_H_
+#define _LANGUAGE_ZH_TW_H_
+
+/*************************** ATTENTION *******************************\
+ *
+ * Due to memory constraints only UTF-8 is supported.
+ * To save code space keep text as short as possible.
+ * Time and Date provided by SDK can not be localized (yet).
+ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
+ * Use online command Prefix to translate cmnd, stat and tele.
+ *
+\*********************************************************************/
+
+//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
+
+// "2017-03-07T11:08:02" - ISO8601:2004
+#define D_YEAR_MONTH_SEPARATOR "-"
+#define D_MONTH_DAY_SEPARATOR "-"
+#define D_DATE_TIME_SEPARATOR "T"
+#define D_HOUR_MINUTE_SEPARATOR ":"
+#define D_MINUTE_SECOND_SEPARATOR ":"
+
+#define D_DAY3LIST "SunMonTueWedThuFriSat"
+#define D_MONTH3LIST "JanFebMarAprMayJunJulAugSepOctNovDec"
+
+// Non JSON decimal separator
+#define D_DECIMAL_SEPARATOR "."
+
+// Common
+#define D_ADMIN "Admin"
+#define D_AIR_QUALITY "空氣品質"
+#define D_AP "AP" // Access Point
+#define D_AS "名稱:"
+#define D_AUTO "自動"
+#define D_BLINK "閃爍"
+#define D_BLINKOFF "閃爍關"
+#define D_BOOT_COUNT "啟動次數"
+#define D_BRIGHTLIGHT "亮度"
+#define D_BUTTON "按鈕"
+#define D_BY "by" // Written by me
+#define D_BYTES "大小:"
+#define D_CELSIUS "攝氏"
+#define D_CO2 "二氧化碳"
+#define D_CODE "代碼" // Button code
+#define D_COLDLIGHT "冷"
+#define D_COMMAND "命令:"
+#define D_CONNECTED "已連接"
+#define D_COUNT "數量:"
+#define D_COUNTER "Counter"
+#define D_CURRENT "電流" // As in Voltage and Current
+#define D_DATA "數據:"
+#define D_DARKLIGHT "Dark"
+#define D_DEBUG "除錯"
+#define D_DISABLED "停用"
+#define D_DNS_SERVER "DNS伺服器"
+#define D_DONE "完成"
+#define D_DST_TIME "DST"
+#define D_EMULATION "設備模擬"
+#define D_ENABLED "啟用"
+#define D_ERASE "刪除"
+#define D_ERROR "錯誤"
+#define D_FAHRENHEIT "華氏"
+#define D_FAILED "失敗"
+#define D_FALLBACK "Fallback"
+#define D_FALLBACK_TOPIC "Fallback Topic"
+#define D_FALSE "False"
+#define D_FILE "文件:"
+#define D_FREE_MEMORY "可用記憶體"
+#define D_GAS "氣體"
+#define D_GATEWAY "網關"
+#define D_GROUP "組:"
+#define D_HOST "主機"
+#define D_HOSTNAME "主機名"
+#define D_HUMIDITY "濕度"
+#define D_ILLUMINANCE "照度"
+#define D_IMMEDIATE "immediate" // Button immediate
+#define D_INDEX "索引:"
+#define D_INFO "信息"
+#define D_INITIALIZED "初始化完成"
+#define D_IP_ADDRESS "IP地址"
+#define D_LIGHT "燈"
+#define D_LWT "LWT"
+#define D_MODULE "模組"
+#define D_MQTT "MQTT"
+#define D_MULTI_PRESS "多次按鍵"
+#define D_NOISE "雜訊"
+#define D_NONE "無"
+#define D_OFF "關"
+#define D_OFFLINE "離線"
+#define D_OK "好"
+#define D_ON "開"
+#define D_ONLINE "在線"
+#define D_PASSWORD "密碼"
+#define D_PORT "端口"
+#define D_POWER_FACTOR "功率因數"
+#define D_POWERUSAGE "功率"
+#define D_PRESSURE "氣壓"
+#define D_PRESSUREATSEALEVEL "海平面氣壓"
+#define D_PROGRAM_FLASH_SIZE "韌體 Flash 大小"
+#define D_PROGRAM_SIZE "韌體大小"
+#define D_PROJECT "項目:"
+#define D_RECEIVED "已接收"
+#define D_RESTART "重啟"
+#define D_RESTARTING "正在重啟"
+#define D_RESTART_REASON "重啟原因"
+#define D_RESTORE "恢覆"
+#define D_RETAINED "已保留"
+#define D_SAVE "存檔"
+#define D_SENSOR "感測器"
+#define D_SSID "名稱"
+#define D_START "開始"
+#define D_STD_TIME "STD"
+#define D_STOP "停止"
+#define D_SUBNET_MASK "子網遮罩"
+#define D_SUBSCRIBE_TO "訂閱"
+#define D_SUCCESSFUL "成功"
+#define D_TEMPERATURE "溫度"
+#define D_TO "to"
+#define D_TOGGLE "切換"
+#define D_TOPIC "主題"
+#define D_TRANSMIT "發送"
+#define D_TRUE "True"
+#define D_UPGRADE "升級"
+#define D_UPLOAD "上傳"
+#define D_UPTIME "運行時間"
+#define D_USER "用戶名"
+#define D_UTC_TIME "UTC"
+#define D_UV_LEVEL "紫外線等級"
+#define D_VERSION "版本"
+#define D_VOLTAGE "電壓"
+#define D_WARMLIGHT "暖"
+#define D_WEB_SERVER "Web Server"
+
+// sonoff.ino
+#define D_WARNING_MINIMAL_VERSION "警告:精簡產品不支持配置寫入保存"
+#define D_LEVEL_10 "level 1-0"
+#define D_LEVEL_01 "level 0-1"
+#define D_SERIAL_LOGGING_DISABLED "串口日誌已禁用"
+#define D_SYSLOG_LOGGING_REENABLED "Syslog 日誌已開啟"
+
+#define D_SET_BAUDRATE_TO "設置波特率為:"
+#define D_RECEIVED_TOPIC "接收到的主題:"
+#define D_DATA_SIZE "數據大小:"
+#define D_ANALOG_INPUT "Analog"
+
+#define D_FINGERPRINT "驗證 TLS 指紋..."
+#define D_TLS_CONNECT_FAILED_TO "TLS 連接失敗"
+#define D_RETRY_IN "重試倒計時:"
+#define D_VERIFIED "驗證成功"
+#define D_INSECURE "指紋無效導致連接不安全"
+#define D_CONNECT_FAILED_TO "連接失敗:"
+
+// support.ino
+#define D_OSWATCH "osWatch"
+#define D_BLOCKED_LOOP "Blocked Loop"
+#define D_WPS_FAILED_WITH_STATUS "WPSconfig FAILED with status"
+#define D_ACTIVE_FOR_3_MINUTES "active for 3 minutes"
+#define D_FAILED_TO_START "未能啟動"
+#define D_PATCH_ISSUE_2186 "Patch issue 2186"
+#define D_CONNECTING_TO_AP "連接到 AP"
+#define D_IN_MODE "模式:"
+#define D_CONNECT_FAILED_NO_IP_ADDRESS "連接失敗,因為沒有獲取到IP地址"
+#define D_CONNECT_FAILED_AP_NOT_REACHED "連接失敗,無法連接AP"
+#define D_CONNECT_FAILED_WRONG_PASSWORD "連接失敗,AP密碼不正確"
+#define D_CONNECT_FAILED_AP_TIMEOUT "連接失敗,AP超時"
+#define D_ATTEMPTING_CONNECTION "嘗試連接..."
+#define D_CHECKING_CONNECTION "檢查連接..."
+#define D_QUERY_DONE "查詢完成。 發現MQTT服務"
+#define D_MQTT_SERVICE_FOUND "發現MQTT服務:"
+#define D_FOUND_AT "found at"
+#define D_SYSLOG_HOST_NOT_FOUND "Syslog主機未找到"
+
+// settings.ino
+#define D_SAVED_TO_FLASH_AT "保存到 flash:"
+#define D_LOADED_FROM_FLASH_AT "從 flash 載入"
+#define D_USE_DEFAULTS "使用默認設置"
+#define D_ERASED_SECTOR "擦除刪除"
+
+// webserver.ino
+#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "固件版本過低 - 請升級"
+#define D_WEBSERVER_ACTIVE_ON "Web服務器:"
+#define D_WITH_IP_ADDRESS "IP地址:"
+#define D_WEBSERVER_STOPPED "Web 服務器已停止"
+#define D_FILE_NOT_FOUND "文件未找到"
+#define D_REDIRECTED "重定向到認證頁面"
+#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint and keep Station"
+#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager 設置接入點"
+#define D_TRYING_TO_CONNECT "嘗試將設備連接到網絡"
+
+#define D_RESTART_IN "重啟需要"
+#define D_SECONDS "秒"
+#define D_DEVICE_WILL_RESTART "設備將在幾分鐘內重啟"
+#define D_BUTTON_TOGGLE "狀態切換"
+#define D_CONFIGURATION "設置"
+#define D_INFORMATION "信息"
+#define D_FIRMWARE_UPGRADE "固件升級"
+#define D_CONSOLE "控制台"
+#define D_CONFIRM_RESTART "確認重啟"
+
+#define D_CONFIGURE_MODULE "模塊設置"
+#define D_CONFIGURE_WIFI "WiFi設置"
+#define D_CONFIGURE_MQTT "MQTT設置"
+#define D_CONFIGURE_DOMOTICZ "Domoticz設置"
+#define D_CONFIGURE_LOGGING "日志設置"
+#define D_CONFIGURE_OTHER "其他設置"
+#define D_CONFIRM_RESET_CONFIGURATION "確認重置配置"
+#define D_RESET_CONFIGURATION "重置配置"
+#define D_BACKUP_CONFIGURATION "備份配置"
+#define D_RESTORE_CONFIGURATION "還原配置"
+#define D_MAIN_MENU "主菜單"
+
+#define D_MODULE_PARAMETERS "模塊設置"
+#define D_MODULE_TYPE "模塊類型"
+#define D_GPIO "GPIO"
+#define D_SERIAL_IN "串口輸入(RX)"
+#define D_SERIAL_OUT "串口輸出(TX)"
+
+#define D_WIFI_PARAMETERS "Wifi設置"
+#define D_SCAN_FOR_WIFI_NETWORKS "掃描無線網絡"
+#define D_SCAN_DONE "掃描完畢"
+#define D_NO_NETWORKS_FOUND "未找到任何網絡"
+#define D_REFRESH_TO_SCAN_AGAIN "刷新並重試"
+#define D_DUPLICATE_ACCESSPOINT "重覆AP"
+#define D_SKIPPING_LOW_QUALITY "忽略弱信號網絡"
+#define D_RSSI "RSSI"
+#define D_WEP "WEP"
+#define D_WPA_PSK "WPA PSK"
+#define D_WPA2_PSK "WPA2 PSK"
+#define D_AP1_SSID "AP1 名稱"
+#define D_AP1_PASSWORD "AP1 密碼"
+#define D_AP2_SSID "AP2 名稱"
+#define D_AP2_PASSWORD "AP2 密碼"
+
+#define D_MQTT_PARAMETERS "MQTT設置"
+#define D_CLIENT "客戶端"
+#define D_FULL_TOPIC "完整主題"
+
+#define D_LOGGING_PARAMETERS "日志設置"
+#define D_SERIAL_LOG_LEVEL "串口日志級別"
+#define D_WEB_LOG_LEVEL "Web 日志級別"
+#define D_SYS_LOG_LEVEL "Syslog 日志級別"
+#define D_MORE_DEBUG "全部調試"
+#define D_SYSLOG_HOST "Syslog 主機地址"
+#define D_SYSLOG_PORT "Syslog 端口"
+#define D_TELEMETRY_PERIOD "上報周期"
+
+#define D_OTHER_PARAMETERS "其他設置"
+#define D_WEB_ADMIN_PASSWORD "WEB管理密碼"
+#define D_MQTT_ENABLE "啟用MQTT"
+#define D_FRIENDLY_NAME "昵稱"
+#define D_BELKIN_WEMO "貝爾金 WeMo"
+#define D_HUE_BRIDGE "飛利浦 Hue 網橋"
+#define D_SINGLE_DEVICE "單設備"
+#define D_MULTI_DEVICE "多設備"
+
+#define D_SAVE_CONFIGURATION "保存設置"
+#define D_CONFIGURATION_SAVED "設置已保存"
+#define D_CONFIGURATION_RESET "設置已重置"
+
+#define D_PROGRAM_VERSION "固件版本"
+#define D_BUILD_DATE_AND_TIME "編譯時間"
+#define D_CORE_AND_SDK_VERSION "內核版本"
+#define D_FLASH_WRITE_COUNT "刷機次數"
+#define D_MAC_ADDRESS "MAC地址"
+#define D_MQTT_HOST "MQTT主機"
+#define D_MQTT_PORT "MQTT端口"
+#define D_MQTT_CLIENT "MQTT客戶端"
+#define D_MQTT_USER "MQTT用戶名"
+#define D_MQTT_TOPIC "MQTT 主題(Topic)"
+#define D_MQTT_GROUP_TOPIC "MQTT 主題組(Group Topic)"
+#define D_MQTT_FULL_TOPIC "MQTT 完整主題(Full Topic)"
+#define D_MDNS_DISCOVERY "mDNS 發現"
+#define D_MDNS_ADVERTISE "mDNS 廣播"
+#define D_ESP_CHIP_ID "ESP芯片ID"
+#define D_FLASH_CHIP_ID "Flash芯片ID"
+#define D_FLASH_CHIP_SIZE "Flash大小"
+#define D_FREE_PROGRAM_SPACE "空閑程序空間"
+
+#define D_UPGRADE_BY_WEBSERVER "通過Web升級"
+#define D_OTA_URL "OTA地址"
+#define D_START_UPGRADE "開始升級"
+#define D_UPGRADE_BY_FILE_UPLOAD "通過文件升級"
+#define D_UPLOAD_STARTED "開始上傳"
+#define D_UPGRADE_STARTED "開始升級"
+#define D_UPLOAD_DONE "上傳完成"
+#define D_UPLOAD_ERR_1 "沒有選擇文件"
+#define D_UPLOAD_ERR_2 "沒有足夠空間"
+#define D_UPLOAD_ERR_3 "固件頭不是 0xE9"
+#define D_UPLOAD_ERR_4 "固件太大"
+#define D_UPLOAD_ERR_5 "上傳緩沖區不匹配"
+#define D_UPLOAD_ERR_6 "上傳失敗。 啟用日志記錄 3"
+#define D_UPLOAD_ERR_7 "上傳取消"
+#define D_UPLOAD_ERR_8 "錯誤的固件"
+#define D_UPLOAD_ERR_9 "固件太大"
+#define D_UPLOAD_ERROR_CODE "上傳錯誤代碼"
+
+#define D_ENTER_COMMAND "輸入命令"
+#define D_ENABLE_WEBLOG_FOR_RESPONSE "如果預期響應,則啟用Weblog 2"
+#define D_NEED_USER_AND_PASSWORD "需要 user=<用戶名>&password=<密碼>"
+
+// xdrv_wemohue.ino
+#define D_MULTICAST_DISABLED "組播已禁用"
+#define D_MULTICAST_REJOINED "組播已(重新)加入"
+#define D_MULTICAST_JOIN_FAILED "組播加入失敗"
+#define D_FAILED_TO_SEND_RESPONSE "請求發送失敗"
+
+#define D_WEMO "WeMo"
+#define D_WEMO_BASIC_EVENT "WeMo 基礎事件"
+#define D_WEMO_EVENT_SERVICE "WeMo 事件服務"
+#define D_WEMO_META_SERVICE "WeMo meta 服務"
+#define D_WEMO_SETUP "WeMo 設置"
+#define D_RESPONSE_SENT "發送請求"
+
+#define D_HUE "Hue"
+#define D_HUE_BRIDGE_SETUP "Hue 設置"
+#define D_HUE_API_NOT_IMPLEMENTED "Hue API 未實現"
+#define D_HUE_API "Hue API"
+#define D_HUE_POST_ARGS "Hue POST 參數"
+#define D_3_RESPONSE_PACKETS_SENT "3 請求包發送"
+
+// xdrv_05_domoticz.ino
+#define D_DOMOTICZ_PARAMETERS "Domoticz 設置"
+#define D_DOMOTICZ_IDX "Idx"
+#define D_DOMOTICZ_KEY_IDX "Key idx"
+#define D_DOMOTICZ_SWITCH_IDX "開關 idx"
+#define D_DOMOTICZ_SENSOR_IDX "傳感器 idx"
+ #define D_DOMOTICZ_TEMP "溫度"
+ #define D_DOMOTICZ_TEMP_HUM "溫度,濕度"
+ #define D_DOMOTICZ_TEMP_HUM_BARO "溫度,濕度,氣壓"
+ #define D_DOMOTICZ_POWER_ENERGY "功率,電量"
+ #define D_DOMOTICZ_ILLUMINANCE "照度"
+ #define D_DOMOTICZ_COUNT "數值"
+ #define D_DOMOTICZ_VOLTAGE "電壓"
+ #define D_DOMOTICZ_CURRENT "電流"
+ #define D_DOMOTICZ_AIRQUALITY "空氣品質"
+#define D_DOMOTICZ_UPDATE_TIMER "更新計時器"
+
+// xdrv_03_energy.ino
+#define D_ENERGY_TODAY "今日用電量"
+#define D_ENERGY_YESTERDAY "昨日用電量"
+#define D_ENERGY_TOTAL "總用電量"
+
+// xsns_05_ds18b20.ino
+#define D_SENSOR_BUSY "傳感器正忙"
+#define D_SENSOR_CRC_ERROR "傳感器 CRC 校驗錯誤"
+#define D_SENSORS_FOUND "發現傳感器"
+
+// xsns_06_dht.ino
+#define D_TIMEOUT_WAITING_FOR "等待超時"
+#define D_START_SIGNAL_LOW "開始低電平"
+#define D_START_SIGNAL_HIGH "開始高電平"
+#define D_PULSE "pulse"
+#define D_CHECKSUM_FAILURE "校驗失敗"
+
+// xsns_07_sht1x.ino
+#define D_SENSOR_DID_NOT_ACK_COMMAND "傳感器沒有確認命令"
+#define D_SHT1X_FOUND "發現 SHT1X 傳感器"
+
+// xsns_18_pms5003.ino
+#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter
+#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter
+#define D_PARTICALS_BEYOND "顆粒物直徑大於"
+
+// sonoff_template.h
+#define D_SENSOR_NONE "None"
+#define D_SENSOR_DHT11 "DHT11"
+#define D_SENSOR_AM2301 "AM2301"
+#define D_SENSOR_SI7021 "SI7021"
+#define D_SENSOR_DS18X20 "DS18x20"
+#define D_SENSOR_I2C_SCL "I2C SCL"
+#define D_SENSOR_I2C_SDA "I2C SDA"
+#define D_SENSOR_WS2812 "WS2812"
+#define D_SENSOR_IRSEND "IRsend"
+#define D_SENSOR_SWITCH "Switch" // Suffix "1"
+#define D_SENSOR_BUTTON "Button" // Suffix "1"
+#define D_SENSOR_RELAY "Relay" // Suffix "1i"
+#define D_SENSOR_LED "Led" // Suffix "1i"
+#define D_SENSOR_PWM "PWM" // Suffix "1"
+#define D_SENSOR_COUNTER "Counter" // Suffix "1"
+#define D_SENSOR_IRRECV "IRrecv"
+#define D_SENSOR_MHZ_RX "MHZ Rx"
+#define D_SENSOR_MHZ_TX "MHZ Tx"
+#define D_SENSOR_PZEM_RX "PZEM Rx"
+#define D_SENSOR_PZEM_TX "PZEM Tx"
+#define D_SENSOR_SAIR_RX "SAir Rx"
+#define D_SENSOR_SAIR_TX "SAir Tx"
+#define D_SENSOR_SPI_CS "SPI CS"
+#define D_SENSOR_SPI_DC "SPI DC"
+#define D_SENSOR_BACKLIGHT "BkLight"
+#define D_SENSOR_PMS5003 "PMS5003"
+#define D_SENSOR_SDS0X1 "SDS0X1"
+
+// Units
+#define D_UNIT_AMPERE "安"
+#define D_UNIT_HOUR "時"
+#define D_UNIT_KILOOHM "千歐"
+#define D_UNIT_KILOWATTHOUR "千瓦時"
+#define D_UNIT_LUX "勒克斯"
+#define D_UNIT_MICROGRAM_PER_CUBIC_METER "微克/立方米"
+#define D_UNIT_MICROMETER "微米"
+#define D_UNIT_MICROSECOND "微秒"
+#define D_UNIT_MILLIAMPERE "毫安"
+#define D_UNIT_MILLISECOND "毫秒"
+#define D_UNIT_MINUTE "分"
+#define D_UNIT_PARTS_PER_DECILITER "每分升"
+#define D_UNIT_PARTS_PER_MILLION "ppm"
+#define D_UNIT_PRESSURE "百帕"
+#define D_UNIT_SECOND "秒"
+#define D_UNIT_SECTORS "扇區"
+#define D_UNIT_VOLT "伏"
+#define D_UNIT_WATT "瓦"
+#define D_UNIT_WATTHOUR "瓦時"
+
+// Log message prefix
+#define D_LOG_APPLICATION "APP: " // Application
+#define D_LOG_BRIDGE "BRG: " // Bridge
+#define D_LOG_CONFIG "CFG: " // Settings
+#define D_LOG_COMMAND "CMD: " // Command
+#define D_LOG_DEBUG "DBG: " // Debug
+#define D_LOG_DHT "DHT: " // DHT sensor
+#define D_LOG_DOMOTICZ "DOM: " // Domoticz
+#define D_LOG_DSB "DSB: " // DS18xB20 sensor
+#define D_LOG_HTTP "HTP: " // HTTP webserver
+#define D_LOG_I2C "I2C: " // I2C
+#define D_LOG_IRR "IRR: " // Infra Red Received
+#define D_LOG_LOG "LOG: " // Logging
+#define D_LOG_MODULE "MOD: " // Module
+#define D_LOG_MDNS "DNS: " // mDNS
+#define D_LOG_MQTT "MQT: " // MQTT
+#define D_LOG_OTHER "OTH: " // Other
+#define D_LOG_RESULT "RSL: " // Result
+#define D_LOG_RFR "RFR: " // RF Received
+#define D_LOG_SERIAL "SER: " // Serial
+#define D_LOG_SHT1 "SHT: " // SHT1x sensor
+#define D_LOG_UPLOAD "UPL: " // Upload
+#define D_LOG_UPNP "UPP: " // UPnP
+#define D_LOG_WIFI "WIF: " // Wifi
+
+#endif // _LANGUAGE_ZH_TW_H_
diff --git a/sonoff/settings.h b/sonoff/settings.h
index dab308503..a3049dbca 100644
--- a/sonoff/settings.h
+++ b/sonoff/settings.h
@@ -116,7 +116,12 @@ struct SYSCFG {
byte syslog_level; // 1AA
uint8_t webserver; // 1AB
byte weblog_level; // 1AC
- char mqtt_fingerprint[60]; // 1AD To be freed by binary fingerprint
+
+// char mqtt_fingerprint[60]; // 1AD
+ uint8_t mqtt_fingerprint[2][20]; // 1AD
+
+ byte free_1D5[20]; // 1D5
+
char mqtt_host[33]; // 1E9
uint16_t mqtt_port; // 20A
char mqtt_client[33]; // 20C
diff --git a/sonoff/settings.ino b/sonoff/settings.ino
index c702d16c2..b0d6c444e 100644
--- a/sonoff/settings.ino
+++ b/sonoff/settings.ino
@@ -472,7 +472,18 @@ void SettingsDefaultSet2()
Settings.webserver = WEB_SERVER;
Settings.weblog_level = WEB_LOG_LEVEL;
- strlcpy(Settings.mqtt_fingerprint, MQTT_FINGERPRINT, sizeof(Settings.mqtt_fingerprint));
+ char fingerprint[60];
+ strlcpy(fingerprint, MQTT_FINGERPRINT1, sizeof(fingerprint));
+ char *p = fingerprint;
+ for (byte i = 0; i < 20; i++) {
+ Settings.mqtt_fingerprint[0][i] = strtol(p, &p, 16);
+ }
+ strlcpy(fingerprint, MQTT_FINGERPRINT2, sizeof(fingerprint));
+ p = fingerprint;
+ for (byte i = 0; i < 20; i++) {
+ Settings.mqtt_fingerprint[1][i] = strtol(p, &p, 16);
+ }
+
strlcpy(Settings.mqtt_host, MQTT_HOST, sizeof(Settings.mqtt_host));
Settings.mqtt_port = MQTT_PORT;
strlcpy(Settings.mqtt_client, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client));
@@ -875,7 +886,15 @@ void SettingsDelta()
if (Settings.version < 0x050B0107) {
Settings.flag.not_power_linked = 0;
}
-
+ if (Settings.version < 0x050C0005) {
+ char fingerprint[60];
+ memcpy(fingerprint, Settings.mqtt_fingerprint, sizeof(fingerprint));
+ char *p = fingerprint;
+ for (byte i = 0; i < 20; i++) {
+ Settings.mqtt_fingerprint[0][i] = strtol(p, &p, 16);
+ Settings.mqtt_fingerprint[1][i] = Settings.mqtt_fingerprint[0][i];
+ }
+ }
Settings.version = VERSION;
SettingsSave(1);
diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino
index 099bedd9f..5f3ce3ea4 100644
--- a/sonoff/sonoff.ino
+++ b/sonoff/sonoff.ino
@@ -25,7 +25,7 @@
- Select IDE Tools - Flash Size: "1M (no SPIFFS)"
====================================================*/
-#define VERSION 0x050C0004 // 5.12.0d
+#define VERSION 0x050C0005 // 5.12.0e
// Location specific includes
#include // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0)
diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h
index 0a023ea6f..b6ab9e999 100644
--- a/sonoff/sonoff_post.h
+++ b/sonoff/sonoff_post.h
@@ -145,8 +145,12 @@ void WifiWpsStatusCallback(wps_cb_status status);
#define SWITCH_MODE TOGGLE // TOGGLE, FOLLOW or FOLLOW_INV (the wall switch state)
#endif
-#ifndef MQTT_FINGERPRINT
-#define MQTT_FINGERPRINT "A5 02 FF 13 99 9F 8B 39 8E F1 83 4F 11 23 65 0B 32 36 FC 07"
+#ifndef MQTT_FINGERPRINT1
+#define MQTT_FINGERPRINT1 "A5 02 FF 13 99 9F 8B 39 8E F1 83 4F 11 23 65 0B 32 36 FC 07"
+#endif
+
+#ifndef MQTT_FINGERPRINT2
+#define MQTT_FINGERPRINT2 "A5 02 FF 13 99 9F 8B 39 8E F1 83 4F 11 23 65 0B 32 36 FC 07"
#endif
#ifndef WS2812_LEDS
diff --git a/sonoff/user_config.h b/sonoff/user_config.h
index 4fd147b2a..6808538fb 100644
--- a/sonoff/user_config.h
+++ b/sonoff/user_config.h
@@ -29,6 +29,7 @@
\*********************************************************************************************/
// -- Localization --------------------------------
+//#define MY_LANGUAGE cz-CZ // Czech without fonetick in Czech
//#define MY_LANGUAGE de-DE // German in Germany
//#define MY_LANGUAGE en-GB // English in Great Britain. Enabled by Default
//#define MY_LANGUAGE es-AR // Spanish in Argentina
@@ -40,6 +41,7 @@
//#define MY_LANGUAGE pt-PT // Portuguese in Portugal
//#define MY_LANGUAGE ru-RU // Russian in Russia
//#define MY_LANGUAGE zh-CN // Chinese (Simplified) in China
+//#define MY_LANGUAGE zh-TW // Chinese (Traditional) in Taiwan
// -- Project -------------------------------------
#define PROJECT "sonoff" // PROJECT is used as the default topic delimiter and OTA file name
@@ -90,7 +92,8 @@
// Needs Fingerprint, TLS Port, UserId and Password
#ifdef USE_MQTT_TLS
#define MQTT_HOST "" // [MqttHost]
- #define MQTT_FINGERPRINT "A5 02 FF 13 99 9F 8B 39 8E F1 83 4F 11 23 65 0B 32 36 FC 07" // [MqttFingerprint]
+ #define MQTT_FINGERPRINT1 "A5 02 FF 13 99 9F 8B 39 8E F1 83 4F 11 23 65 0B 32 36 FC 07" // [MqttFingerprint1]
+ #define MQTT_FINGERPRINT2 "A5 02 FF 13 99 9F 8B 39 8E F1 83 4F 11 23 65 0B 32 36 FC 07" // [MqttFingerprint2]
#define MQTT_PORT 20123 // [MqttPort] MQTT TLS port
#define MQTT_USER "cloudmqttuser" // [MqttUser] Mandatory user
#define MQTT_PASS "cloudmqttpassword" // [MqttPassword] Mandatory password
diff --git a/sonoff/xdrv_00_mqtt.ino b/sonoff/xdrv_00_mqtt.ino
index 536ff1469..dd46b8c07 100644
--- a/sonoff/xdrv_00_mqtt.ino
+++ b/sonoff/xdrv_00_mqtt.ino
@@ -378,19 +378,33 @@ void MqttConnected()
#ifdef USE_MQTT_TLS
boolean MqttCheckTls()
{
+ char fingerprint1[60];
+ char fingerprint2[60];
boolean result = false;
+ fingerprint1[0] = '\0';
+ fingerprint2[0] = '\0';
+ for (byte i = 0; i < sizeof(Settings.mqtt_fingerprint[0]); i++) {
+ snprintf_P(fingerprint1, sizeof(fingerprint1), PSTR("%s%s%02X"), fingerprint1, (i) ? " " : "", Settings.mqtt_fingerprint[0][i]);
+ snprintf_P(fingerprint2, sizeof(fingerprint2), PSTR("%s%s%02X"), fingerprint2, (i) ? " " : "", Settings.mqtt_fingerprint[1][i]);
+ }
+
AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_FINGERPRINT));
if (!EspClient.connect(Settings.mqtt_host, Settings.mqtt_port)) {
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_TLS_CONNECT_FAILED_TO " %s:%d. " D_RETRY_IN " %d " D_UNIT_SECOND),
Settings.mqtt_host, Settings.mqtt_port, mqtt_retry_counter);
AddLog(LOG_LEVEL_DEBUG);
- } else if (!EspClient.verify(Settings.mqtt_fingerprint, Settings.mqtt_host)) {
- AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_INSECURE));
} else {
- AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_VERIFIED));
- result = true;
+ if (EspClient.verify(fingerprint1, Settings.mqtt_host)) {
+ AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_VERIFIED "1"));
+ result = true;
+ }
+ else if (EspClient.verify(fingerprint2, Settings.mqtt_host)) {
+ AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_VERIFIED "2"));
+ result = true;
+ }
}
+ if (!result) AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_FAILED));
EspClient.stop();
yield();
return result;
@@ -536,12 +550,22 @@ bool MqttCommand()
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, GetStateText(index -1));
}
#ifdef USE_MQTT_TLS
- else if (CMND_MQTTFINGERPRINT == command_code) {
- if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_fingerprint))) {
- strlcpy(Settings.mqtt_fingerprint, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? MQTT_FINGERPRINT : dataBuf, sizeof(Settings.mqtt_fingerprint));
+ else if ((CMND_MQTTFINGERPRINT == command_code) && (index > 0) && (index <= 2)) {
+ char fingerprint[60];
+ if ((data_len > 0) && (data_len < sizeof(fingerprint))) {
+ strlcpy(fingerprint, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? (1 == index) ? MQTT_FINGERPRINT1 : MQTT_FINGERPRINT2 : dataBuf, sizeof(fingerprint));
+ char *p = fingerprint;
+ for (byte i = 0; i < 20; i++) {
+ Settings.mqtt_fingerprint[index -1][i] = strtol(p, &p, 16);
+ }
restart_flag = 2;
}
- snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_fingerprint);
+
+ fingerprint[0] = '\0';
+ for (byte i = 0; i < sizeof(Settings.mqtt_fingerprint[index -1]); i++) {
+ snprintf_P(fingerprint, sizeof(fingerprint), PSTR("%s%s%02X"), fingerprint, (i) ? " " : "", Settings.mqtt_fingerprint[index -1][i]);
+ }
+ snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, fingerprint);
}
#endif
else if ((CMND_MQTTCLIENT == command_code) && !grpflg) {
diff --git a/sonoff/xdrv_07_home_assistant.ino b/sonoff/xdrv_07_home_assistant.ino
index d377fe535..84a218bd9 100644
--- a/sonoff/xdrv_07_home_assistant.ino
+++ b/sonoff/xdrv_07_home_assistant.ino
@@ -93,9 +93,9 @@ void HAssDiscovery()
snprintf_P(sidx, sizeof(sidx), PSTR("_%d"), i);
// Clear "other" topic first in case the device has been reconfigured
- snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s%s/config"), (is_light) ? "switch" : "light", mqtt_topic, (1 == devices_present) ? "" : sidx);
+ snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s%s/config"), (is_light) ? "switch" : "light", mqtt_topic, sidx);
MqttPublish(stopic, true);
- snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s%s/config"), (is_light) ? "light" : "switch", mqtt_topic, (1 == devices_present) ? "" : sidx);
+ snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s%s/config"), (is_light) ? "light" : "switch", mqtt_topic, sidx);
if (Settings.flag.hass_discovery) {
char name[33];
diff --git a/sonoff/xsns_04_snfsc.ino b/sonoff/xsns_04_snfsc.ino
index 51e3e1b3a..944dff985 100644
--- a/sonoff/xsns_04_snfsc.ino
+++ b/sonoff/xsns_04_snfsc.ino
@@ -125,6 +125,8 @@ void SonoffScShow(boolean json)
#ifdef USE_DOMOTICZ
DomoticzTempHumSensor(temperature, humidity);
DomoticzSensor(DZ_ILLUMINANCE, sc_value[2]);
+ DomoticzSensor(DZ_COUNT, sc_value[3]);
+ DomoticzSensor(DZ_AIRQUALITY, 500 + ((100 - sc_value[4]) * 20));
#endif // USE_DOMOTICZ
#ifdef USE_WEBSERVER
} else {
diff --git a/sonoff/xsns_14_sht3x.ino b/sonoff/xsns_14_sht3x.ino
index 381e2d204..afedf31fc 100644
--- a/sonoff/xsns_14_sht3x.ino
+++ b/sonoff/xsns_14_sht3x.ino
@@ -20,7 +20,7 @@
#ifdef USE_I2C
#ifdef USE_SHT3X
/*********************************************************************************************\
- * SHT3X and SHTC3 - Temperature and Humidy
+ * SHT3X and SHTC3 - Temperature and Humidity
*
* I2C Address: 0x44, 0x45 or 0x70 (SHTC3)
\*********************************************************************************************/
@@ -29,14 +29,18 @@
#define SHT3X_ADDR_VDD 0x45 // address pin high (VDD)
#define SHTC3_ADDR 0x70 // address for shtc3 sensor
+#define SHT3X_MAX_SENSORS 3
+
const char kShtTypes[] PROGMEM = "SHT3X|SHT3X|SHTC3";
-
-uint8_t sht3x_type = 0;
-uint8_t sht3x_address;
uint8_t sht3x_addresses[] = { SHT3X_ADDR_GND, SHT3X_ADDR_VDD, SHTC3_ADDR };
-char sht3x_types[6];
-bool Sht3xRead(float &t, float &h)
+uint8_t sht3x_count = 0;
+struct SHT3XSTRUCT {
+ uint8_t address; // I2C bus address
+ char types[6]; // Sensor type name and address - "SHT3X-0xXX"
+} sht3x_sensors[SHT3X_MAX_SENSORS];
+
+bool Sht3xRead(float &t, float &h, uint8_t sht3x_address)
{
unsigned int data[6];
@@ -49,7 +53,7 @@ bool Sht3xRead(float &t, float &h)
Wire.write(0x17); // sleep
Wire.endTransmission();
Wire.beginTransmission(sht3x_address);
- Wire.write(0x78); // Dissable clock stretching ( I don't think that wire library support clock stretching )
+ Wire.write(0x78); // Disable clock stretching ( I don't think that wire library support clock stretching )
Wire.write(0x66); // High resolution
} else {
Wire.write(0x2C); // Enable clock stretching
@@ -72,46 +76,47 @@ bool Sht3xRead(float &t, float &h)
void Sht3xDetect()
{
- if (sht3x_type) {
- return;
- }
+ if (sht3x_count) return;
float t;
float h;
- sht3x_type = 1;
- for (byte i = 0; i < sizeof(sht3x_addresses); i++) {
- sht3x_address = sht3x_addresses[i];
- if (Sht3xRead(t, h)) {
- GetTextIndexed(sht3x_types, sizeof(sht3x_types), i, kShtTypes);
- snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, sht3x_types, htu_address);
+ for (byte i = 0; i < SHT3X_MAX_SENSORS; i++) {
+ if (Sht3xRead(t, h, sht3x_addresses[i])) {
+ sht3x_sensors[sht3x_count].address = sht3x_addresses[i];
+ GetTextIndexed(sht3x_sensors[sht3x_count].types, sizeof(sht3x_sensors[sht3x_count].types), i, kShtTypes);
+ snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, sht3x_sensors[sht3x_count].types, sht3x_sensors[sht3x_count].address);
AddLog(LOG_LEVEL_DEBUG);
- return;
+ sht3x_count++;
}
}
- sht3x_type = 0;
}
void Sht3xShow(boolean json)
{
- if (sht3x_type) {
+ if (sht3x_count) {
float t;
float h;
- if (Sht3xRead(t, h)) {
- char temperature[10];
- char humidity[10];
- dtostrfd(t, Settings.flag2.temperature_resolution, temperature);
- dtostrfd(h, Settings.flag2.humidity_resolution, humidity);
-
- if (json) {
- snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, sht3x_types, temperature, humidity);
+ char temperature[10];
+ char humidity[10];
+ char types[11];
+ for (byte i = 0; i < sht3x_count; i++) {
+ if (Sht3xRead(t, h, sht3x_sensors[i].address)) {
+ dtostrfd(t, Settings.flag2.temperature_resolution, temperature);
+ dtostrfd(h, Settings.flag2.humidity_resolution, humidity);
+ snprintf_P(types, sizeof(types), PSTR("%s-0x%02X"), sht3x_sensors[i].types, sht3x_sensors[i].address); // "SHT3X-0xXX"
+ if (json) {
+ snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, types, temperature, humidity);
#ifdef USE_DOMOTICZ
- DomoticzTempHumSensor(temperature, humidity);
+ if (0 == i) { // We want the same first sensor to report to Domoticz in case a read is missed
+ DomoticzTempHumSensor(temperature, humidity);
+ }
#endif // USE_DOMOTICZ
#ifdef USE_WEBSERVER
- } else {
- snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, sht3x_types, temperature, TempUnit());
- snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, sht3x_types, humidity);
+ } else {
+ snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, types, temperature, TempUnit());
+ snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, types, humidity);
#endif // USE_WEBSERVER
+ }
}
}
}
diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino
index ed877fd2f..56d896c5e 100644
--- a/sonoff/xsns_20_novasds.ino
+++ b/sonoff/xsns_20_novasds.ino
@@ -92,18 +92,24 @@ void NovaSdsInit()
#ifdef USE_WEBSERVER
const char HTTP_SDS0X1_SNS[] PROGMEM = "%s"
- "{s}SDS0X1 " D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"
- "{s}SDS0X1 " D_ENVIRONMENTAL_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"; // {s} = , {m} = | , {e} = |
+ "{s}SDS0X1 " D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"
+ "{s}SDS0X1 " D_ENVIRONMENTAL_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"; // {s} = , {m} = | , {e} = |
#endif // USE_WEBSERVER
void NovaSdsShow(boolean json)
{
if (novasds_valid) {
+ char pm10[10];
+ char pm2_5[10];
+ float pm10f = (float)(novasds_data.pm100) / 10.0f;
+ float pm2_5f = (float)(novasds_data.pm25) / 10.0f;
+ dtostrfd(pm10f, 1, pm10);
+ dtostrfd(pm2_5f, 1, pm2_5);
if (json) {
- snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SDS0X1\":{\"PM2.5\":%d,\"PM10\":%d}"), mqtt_data, novasds_data.pm25, novasds_data.pm100);
+ snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SDS0X1\":{\"PM2.5\":%s,\"PM10\":%s}"), mqtt_data, pm2_5, pm10);
#ifdef USE_WEBSERVER
} else {
- snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SDS0X1_SNS, mqtt_data, novasds_data.pm25/10, novasds_data.pm100/10);
+ snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SDS0X1_SNS, mqtt_data, pm2_5, pm10);
#endif // USE_WEBSERVER
}
}