diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index 0baecb42a..42cc68e3f 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -47,10 +47,28 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
## Changelog
-### Version 7.1.2 Betty
+### Version 7.2.0 Constance
-- Fix lost functionality of GPIO9 and GPIO10 on some devices (#7080)
-- Fix Zigbee uses Hardware Serial if GPIO 1/3 or GPIO 13/15 and SerialLog 0 (#7071)
-- Fix WS2812 power control (#7090)
-- Change light color schemes 2, 3 and 4 from color wheel to Hue driven with user Saturation control
-- Change log buffer size from 520 to 700 characters accomodating full rule text (#7110)
+- Change Exception reporting removing exception details from ``Status 1`` and consolidated in ``Status 12`` if available
+- Change HTTP CORS from command ``SetOption73 0/1`` to ``Cors `` allowing user control of specific CORS domain by Shantur Rathore (#7066)
+- Change GUI Shutter button text to Up and Down Arrows based on PR by Xavier Muller (#7166)
+- Change amount of supported DHT sensors from 3 to 4 by Xavier Muller (#7167)
+- Change some Settings locations freeing up space for future single char allowing variable length text
+- Fix flashing H801 led at boot by Stefan Hadinger (#7165, #649)
+- Fix duplicated ``Backlog`` when using Event inside a Backlog by Adrian Scillato (#7178, #7147)
+- Fix Gui Timer when using a negative zero offset of -00:00 by Peter Ooms (#7174)
+- Add command ``SerialConfig 0..23`` or ``SerialConfig 8N1`` to select Serial Config based in PR by Luis Teixeira (#7108)
+- Add command ``Sensor34 9 `` to set minimum delta to trigger JSON message by @tobox (#7188)
+- Add rule var ``%topic%`` by Adrian Scillato (#5522)
+- Add rule triggers ``tele-wifi1#xxx`` by Adrian Scillato (#7093)
+- Add SML bus decoder syntax support for byte order by Gerhard Mutz (#7112)
+- Add experimental support for stepper motor shutter control by Stefan Bode
+- Add optional USE_MQTT_TLS to tasmota-minimal.bin by Bohdan Kmit (#7115)
+- Add save call stack in RTC memory in case of crash, command ``Status 12`` to dump the stack by Stefan Hadinger
+- Add Home Assistant force update by Frederico Leoni (#7140, #7074)
+- Add Wifi Signal Strength in dBm in addition to RSSI Wifi Experience by Andreas Schultz (#7145)
+- Add Yaw, Pitch and Roll support for MPU6050 by Philip Barclay (#7058)
+- Add reporting of raw weight to JSON from HX711 to overcome auto-tare functionality by @tobox (#7171)
+- Add Zigbee support for Xiaomi Aqara Vibration Sensor and Presence Sensor by Stefan Hadinger
+- Add Shutter functions ramp up/down and MQTT reporting by Stefan Bode
+- Add fallback functionality from version 8.x
diff --git a/lib/esp-knx-ip-0.5.2/esp-knx-ip.h b/lib/esp-knx-ip-0.5.2/esp-knx-ip.h
index eb5ecf7b0..7c6377bec 100644
--- a/lib/esp-knx-ip-0.5.2/esp-knx-ip.h
+++ b/lib/esp-knx-ip-0.5.2/esp-knx-ip.h
@@ -32,8 +32,18 @@
#define DISABLE_RESTORE_BUTTON 1 // [Default 0] Set to 1 to disable the "restore defaults" button in the web ui.
// These values normally don't need adjustment
-#define MULTICAST_PORT 3671 // [Default 3671]
+#ifndef MULTICAST_IP
#define MULTICAST_IP IPAddress(224, 0, 23, 12) // [Default IPAddress(224, 0, 23, 12)]
+#else
+#warning USING CUSTOM MULTICAST_IP
+#endif
+
+#ifndef MULTICAST_PORT
+#define MULTICAST_PORT 3671 // [Default 3671]
+#else
+#warning USING CUSTOM MULTICAST_PORT
+#endif
+
#define SEND_CHECKSUM 0
// Uncomment to enable printing out debug messages.
diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md
index 9d8e5cb72..c56de751e 100644
--- a/tasmota/CHANGELOG.md
+++ b/tasmota/CHANGELOG.md
@@ -2,6 +2,56 @@
## Released
+### 7.2.0 20191221
+
+- Release
+
+### 7.1.2.6 20191214
+
+- Change some more Settings locations freeing up space for future single char allowing variable length text
+- Add Zigbee send automatic ZigbeeRead after sending a command
+- Add Zigbee improving Occupancy:false detection for Aqara sensor
+- Add fallback functionality from version 8.x
+
+### 7.1.2.5 20191213
+
+- Change some Settings locations freeing up space for future single char allowing variable length text
+- Add Zigbee support for Xiaomi Aqara Vibration Sensor and Presence Sensor by Stefan Hadinger
+- Add Shutter functions ramp up/down and MQTT reporting by Stefan Bode
+
+### 7.1.2.4 20191209
+
+- Change HTTP CORS from command ``SetOption73 0/1`` to ``Cors `` allowing user control of specific CORS domain by Shantur Rathore (#7066)
+- Change GUI Shutter button text to Up and Down Arrows based on PR by Xavier Muller (#7166)
+- Change amount of supported DHT sensors from 3 to 4 by Xavier Muller (#7167)
+- Revert removal of exception details from MQTT info on restart
+- Add Wifi Signal Strength in dBm in addition to RSSI Wifi Experience by Andreas Schultz (#7145)
+- Add Yaw, Pitch and Roll support for MPU6050 by Philip Barclay (#7058)
+- Add reporting of raw weight to JSON from HX711 to overcome auto-tare functionality by @tobox (#7171)
+- Add command ``Sensor34 9 `` to set minimum delta to trigger JSON message by @tobox (#7188)
+- Fix flashing H801 led at boot by Stefan Hadinger (#7165, #649)
+- Fix duplicated ``Backlog`` when using Event inside a Backlog by Adrian Scillato (#7178, #7147)
+- Fix Gui Timer when using a negative zero offset of -00:00 by Peter Ooms (#7174)
+
+### 7.1.2.3 20191208
+
+- Change Exception reporting removing exception details from both MQTT info and ``Status 1``. Now consolidated in ``Status 12`` if available.
+
+### 7.1.2.2 20191206
+
+- Remove rule trigger ``tele_power1#state`` due to compatibility
+- Add command ``SerialConfig 0..23`` or ``SerialConfig 8N1`` to select Serial Config based in PR by Luis Teixeira (#7108)
+- Add save call stack in RTC memory in case of crash, command ``Status 12`` to dump the stack by Stefan Hadinger
+- Add Home Assistant force update by Frederico Leoni (#7140, #7074)
+
+### 7.1.2.1 20191206
+
+- Add SML bus decoder syntax support for byte order by Gerhard Mutz (#7112)
+- Add rule var ``%topic%`` by Adrian Scillato (#5522)
+- Add rule triggers ``tele_power1#state`` and multiple ``tele-wifi1#xxx`` by Adrian Scillato (#7093)
+- Add experimental support for stepper motor shutter control by Stefan Bode
+- Add optional USE_MQTT_TLS to tasmota-minimal.bin by Bohdan Kmit (#7115)
+
### 7.1.2 20191206
- Maintenance Release
diff --git a/tasmota/i18n.h b/tasmota/i18n.h
index 5de4b7a1d..fed6930d7 100644
--- a/tasmota/i18n.h
+++ b/tasmota/i18n.h
@@ -134,6 +134,7 @@
#define D_JSON_SELECTED "selected"
#define D_JSON_SERIALRECEIVED "SerialReceived"
#define D_JSON_SET "Set"
+#define D_JSON_SIGNAL "Signal"
#define D_JSON_SSID "SSId"
#define D_JSON_STARTDST "StartDST" // Start Daylight Savings Time
#define D_JSON_STARTED "Started"
@@ -208,6 +209,7 @@
#define D_STATUS9_MARGIN "PTH"
#define D_STATUS10_SENSOR "SNS"
#define D_STATUS11_STATUS "STS"
+ #define D_STATUS12_STATUS "STK"
#define D_CMND_STATE "State"
#define D_CMND_POWER "Power"
#define D_CMND_FANSPEED "FanSpeed"
@@ -285,6 +287,7 @@
#define D_CMND_SERIALSEND "SerialSend"
#define D_CMND_SERIALDELIMITER "SerialDelimiter"
#define D_CMND_BAUDRATE "Baudrate"
+#define D_CMND_SERIALCONFIG "SerialConfig"
#define D_CMND_TEMPLATE "Template"
#define D_JSON_NAME "NAME"
#define D_JSON_GPIO "GPIO"
@@ -332,6 +335,7 @@
#define D_CMND_WEBSENSOR "WebSensor"
#define D_CMND_EMULATION "Emulation"
#define D_CMND_SENDMAIL "Sendmail"
+#define D_CMND_CORS "CORS"
// Commands xdrv_03_energy.ino
#define D_CMND_POWERLOW "PowerLow"
@@ -490,6 +494,24 @@
#define D_JSON_MOTOR_MIS "setMIS"
#endif
+ // Commands xdrv_27_Shutter.ino
+ #ifdef USE_SHUTTER
+ #define D_PRFX_SHUTTER "Shutter"
+ #define D_CMND_SHUTTER_OPEN "Open"
+ #define D_CMND_SHUTTER_CLOSE "Close"
+ #define D_CMND_SHUTTER_STOP "Stop"
+ #define D_CMND_SHUTTER_POSITION "Position"
+ #define D_CMND_SHUTTER_OPENTIME "OpenDuration"
+ #define D_CMND_SHUTTER_CLOSETIME "CloseDuration"
+ #define D_CMND_SHUTTER_RELAY "Relay"
+ #define D_CMND_SHUTTER_SETHALFWAY "SetHalfway"
+ #define D_CMND_SHUTTER_SETCLOSE "SetClose"
+ #define D_CMND_SHUTTER_INVERT "Invert"
+ #define D_CMND_SHUTTER_CLIBRATION "Calibration"
+ #define D_CMND_SHUTTER_MOTORDELAY "MotorDelay"
+ #define D_CMND_SHUTTER_FREQUENCY "Frequency"
+ #endif
+
/********************************************************************************************/
// Log message prefix
diff --git a/tasmota/language/bg-BG.h b/tasmota/language/bg-BG.h
index 4bc5feebd..1f18d8efb 100644
--- a/tasmota/language/bg-BG.h
+++ b/tasmota/language/bg-BG.h
@@ -28,7 +28,7 @@
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
* Use online command Prefix to translate cmnd, stat and tele.
*
- * Updated until v6.5.0.8
+ * Updated until v7.1.2.4
\*********************************************************************/
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
@@ -71,6 +71,7 @@
#define D_COLDLIGHT "Хладна"
#define D_COMMAND "Команда"
#define D_CONNECTED "Свързан"
+#define D_CORS_DOMAIN "CORS домейн"
#define D_COUNT "Брой"
#define D_COUNTER "Брояч"
#define D_CURRENT "Ток" // As in Voltage and Current
@@ -113,7 +114,7 @@
#define D_LWT "LWT"
#define D_MODULE "Модул"
#define D_MQTT "MQTT"
-#define D_MULTI_PRESS "множествено натискане"
+#define D_MULTI_PRESS "неколкократно натискане"
#define D_NOISE "Шум"
#define D_NONE "Няма"
#define D_OFF "Изкл."
@@ -284,10 +285,10 @@
#define D_LOGGING_PARAMETERS "Параметри на лога"
#define D_SERIAL_LOG_LEVEL "Степен на серийния лог"
-#define D_MQTT_LOG_LEVEL "Mqtt log level"
+#define D_MQTT_LOG_LEVEL "Степен на MQTT лога"
#define D_WEB_LOG_LEVEL "Степен на уеб лога"
#define D_SYS_LOG_LEVEL "Степен на системния лог"
-#define D_MORE_DEBUG "Още дебъгване"
+#define D_MORE_DEBUG "Допълнителна debug информация"
#define D_SYSLOG_HOST "Хост на системния лог"
#define D_SYSLOG_PORT "Порт на системния лог"
#define D_TELEMETRY_PERIOD "Период на телеметрия"
@@ -381,7 +382,7 @@
#define D_HUE "Hue"
#define D_HUE_BRIDGE_SETUP "Настройка на Hue bridge"
-#define D_HUE_API_NOT_IMPLEMENTED "Hue API не е внедрено"
+#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 пакета за отговор"
@@ -443,17 +444,17 @@
#define D_ENERGY_TOTAL "Използвана енергия общо"
// xdrv_27_shutter.ino
-#define D_OPEN "Open"
-#define D_CLOSE "Close"
-#define D_DOMOTICZ_SHUTTER "Shutter"
+#define D_OPEN "Отворена"
+#define D_CLOSE "Затворена"
+#define D_DOMOTICZ_SHUTTER "Щора"
// xdrv_28_pcf8574.ino
-#define D_CONFIGURE_PCF8574 "Configure PCF8574"
-#define D_PCF8574_PARAMETERS "PCF8574 parameters"
-#define D_INVERT_PORTS "Invert Ports"
-#define D_DEVICE "Device"
-#define D_DEVICE_INPUT "Input"
-#define D_DEVICE_OUTPUT "Output"
+#define D_CONFIGURE_PCF8574 "Конфигуриране на PCF8574"
+#define D_PCF8574_PARAMETERS "PCF8574 параметри"
+#define D_INVERT_PORTS "Обърни портовете"
+#define D_DEVICE "Устройство"
+#define D_DEVICE_INPUT "Вход"
+#define D_DEVICE_OUTPUT "Изход"
// xsns_05_ds18b20.ino
#define D_SENSOR_BUSY "Датчикът DS18x20 е зает"
@@ -674,27 +675,27 @@
#define D_UNIT_ANGLE "°"
//SOLAXX1
-#define D_PV1_VOLTAGE "PV1 Voltage"
-#define D_PV1_CURRENT "PV1 Current"
-#define D_PV1_POWER "PV1 Power"
-#define D_PV2_VOLTAGE "PV2 Voltage"
-#define D_PV2_CURRENT "PV2 Current"
-#define D_PV2_POWER "PV2 Power"
-#define D_SOLAR_POWER "Solar Power"
-#define D_INVERTER_POWER "Inverter Power"
-#define D_STATUS "Status"
-#define D_WAITING "Waiting"
-#define D_CHECKING "Checking"
-#define D_WORKING "Working"
-#define D_FAILURE "Failure"
-#define D_SOLAX_ERROR_0 "No Error Code"
-#define D_SOLAX_ERROR_1 "Grid Lost Fault"
-#define D_SOLAX_ERROR_2 "Grid Voltage Fault"
-#define D_SOLAX_ERROR_3 "Grid Frequency Fault"
-#define D_SOLAX_ERROR_4 "Pv Voltage Fault"
-#define D_SOLAX_ERROR_5 "Isolation Fault"
-#define D_SOLAX_ERROR_6 "Over Temperature Fault"
-#define D_SOLAX_ERROR_7 "Fan Fault"
-#define D_SOLAX_ERROR_8 "Other Device Fault"
+#define D_PV1_VOLTAGE "Напрежение на PV1"
+#define D_PV1_CURRENT "Ток на PV1"
+#define D_PV1_POWER "Мощност на PV1"
+#define D_PV2_VOLTAGE "Напрежение на PV2"
+#define D_PV2_CURRENT "Ток на PV2"
+#define D_PV2_POWER "Мощност на PV2"
+#define D_SOLAR_POWER "Слънчева мощност"
+#define D_INVERTER_POWER "Мощност на инвертера"
+#define D_STATUS "Състояние"
+#define D_WAITING "Очакване"
+#define D_CHECKING "Проверка"
+#define D_WORKING "Работи"
+#define D_FAILURE "Грешка"
+#define D_SOLAX_ERROR_0 "Грешка - няма код"
+#define D_SOLAX_ERROR_1 "Грешка - загуба на мрежата"
+#define D_SOLAX_ERROR_2 "Грешка - мрежово напрежение"
+#define D_SOLAX_ERROR_3 "Грешка - мрежова честота"
+#define D_SOLAX_ERROR_4 "Грешка - напрежение на Pv"
+#define D_SOLAX_ERROR_5 "Грешка - проблем с изолацията"
+#define D_SOLAX_ERROR_6 "Грешка - прегряване"
+#define D_SOLAX_ERROR_7 "Грешка - вентилатор"
+#define D_SOLAX_ERROR_8 "Грешка - друго оборудване"
#endif // _LANGUAGE_BG_BG_H_
diff --git a/tasmota/language/cs-CZ.h b/tasmota/language/cs-CZ.h
index 8800368a3..1d7c6f381 100644
--- a/tasmota/language/cs-CZ.h
+++ b/tasmota/language/cs-CZ.h
@@ -71,6 +71,7 @@
#define D_COLDLIGHT "Studené světlo"
#define D_COMMAND "Příkaz"
#define D_CONNECTED "...připojeno"
+#define D_CORS_DOMAIN "CORS Domain"
#define D_COUNT "Počítej"
#define D_COUNTER "Počítadlo"
#define D_CURRENT "Proud" // As in Voltage and Current
diff --git a/tasmota/language/de-DE.h b/tasmota/language/de-DE.h
index c50de823f..6569dd232 100644
--- a/tasmota/language/de-DE.h
+++ b/tasmota/language/de-DE.h
@@ -71,6 +71,7 @@
#define D_COLDLIGHT "kalt"
#define D_COMMAND "Befehl"
#define D_CONNECTED "verbunden"
+#define D_CORS_DOMAIN "CORS Domain"
#define D_COUNT "zählen"
#define D_COUNTER "Zähler"
#define D_CURRENT "Strom" // As in Voltage and Current
diff --git a/tasmota/language/el-GR.h b/tasmota/language/el-GR.h
index 4fe47ae6d..f8b9c9614 100644
--- a/tasmota/language/el-GR.h
+++ b/tasmota/language/el-GR.h
@@ -72,6 +72,7 @@
#define D_COMMAND "Εντολή"
#define D_CONNECTED "Συνδεδεμένο"
#define D_COUNT "Μέτρηση"
+#define D_CORS_DOMAIN "CORS Domain"
#define D_COUNTER "Μετρητής"
#define D_CURRENT "Ένταση" // As in Voltage and Current
#define D_DATA "Δεδομένα"
diff --git a/tasmota/language/en-GB.h b/tasmota/language/en-GB.h
index a98087a18..257a34c86 100644
--- a/tasmota/language/en-GB.h
+++ b/tasmota/language/en-GB.h
@@ -71,6 +71,7 @@
#define D_COLDLIGHT "Cold"
#define D_COMMAND "Command"
#define D_CONNECTED "Connected"
+#define D_CORS_DOMAIN "CORS Domain"
#define D_COUNT "Count"
#define D_COUNTER "Counter"
#define D_CURRENT "Current" // As in Voltage and Current
diff --git a/tasmota/language/es-ES.h b/tasmota/language/es-ES.h
index 014d822a9..7527bb77a 100644
--- a/tasmota/language/es-ES.h
+++ b/tasmota/language/es-ES.h
@@ -71,6 +71,7 @@
#define D_COLDLIGHT "Fría"
#define D_COMMAND "Comando"
#define D_CONNECTED "Conectado"
+#define D_CORS_DOMAIN "CORS Domain"
#define D_COUNT "Conteo"
#define D_COUNTER "Contador"
#define D_CURRENT "Corriente" // As in Voltage and Current
diff --git a/tasmota/language/fr-FR.h b/tasmota/language/fr-FR.h
index 4704c49e7..e107409e3 100644
--- a/tasmota/language/fr-FR.h
+++ b/tasmota/language/fr-FR.h
@@ -28,7 +28,7 @@
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
* Use online command Prefix to translate cmnd, stat and tele.
*
- * Updated until v6.6.0.15
+ * Updated until v7.1.2.4
\*********************************************************************/
#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
@@ -71,6 +71,7 @@
#define D_COLDLIGHT "Froid"
#define D_COMMAND "Commande"
#define D_CONNECTED "Connecté"
+#define D_CORS_DOMAIN "Domaine CORS"
#define D_COUNT "Compte"
#define D_COUNTER "Compteur"
#define D_CURRENT "Courant" // As in Voltage and Current
@@ -280,7 +281,7 @@
#define D_MQTT_PARAMETERS "Paramètres MQTT"
#define D_CLIENT "Client"
-#define D_FULL_TOPIC "topic complet"
+#define D_FULL_TOPIC "Topic complet"
#define D_LOGGING_PARAMETERS "Paramètres du journal"
#define D_SERIAL_LOG_LEVEL "Niveau de journalisation série"
@@ -687,7 +688,7 @@
#define D_CHECKING "En test"
#define D_WORKING "En marche"
#define D_FAILURE "Défault"
-#define D_SOLAX_ERROR_0 "Aucun Code d'erreur"
+#define D_SOLAX_ERROR_0 "Aucun code d'erreur"
#define D_SOLAX_ERROR_1 "Défaut Perte de réseau"
#define D_SOLAX_ERROR_2 "Défaut Tension réseau"
#define D_SOLAX_ERROR_3 "Défaut Fréquence réseau"
diff --git a/tasmota/language/he-HE.h b/tasmota/language/he-HE.h
index 69387ceca..ac4dadb8e 100644
--- a/tasmota/language/he-HE.h
+++ b/tasmota/language/he-HE.h
@@ -71,6 +71,7 @@
#define D_COLDLIGHT "אור קר"
#define D_COMMAND "פקודה"
#define D_CONNECTED "מחובר"
+#define D_CORS_DOMAIN "CORS Domain"
#define D_COUNT "סופר"
#define D_COUNTER "מונה"
#define D_CURRENT "נוכחי" // As in Voltage and Current
diff --git a/tasmota/language/hu-HU.h b/tasmota/language/hu-HU.h
index 58f85eb22..62806fa46 100644
--- a/tasmota/language/hu-HU.h
+++ b/tasmota/language/hu-HU.h
@@ -71,6 +71,7 @@
#define D_COLDLIGHT "Hideg fény"
#define D_COMMAND "Parancs"
#define D_CONNECTED "Csatlakoztatva"
+#define D_CORS_DOMAIN "CORS Domain"
#define D_COUNT "Szám"
#define D_COUNTER "Számláló"
#define D_CURRENT "Áramerősség" // As in Voltage and Current
diff --git a/tasmota/language/it-IT.h b/tasmota/language/it-IT.h
index 3029f37da..0585c12d8 100644
--- a/tasmota/language/it-IT.h
+++ b/tasmota/language/it-IT.h
@@ -71,6 +71,7 @@
#define D_COLDLIGHT "Fredda"
#define D_COMMAND "Comando"
#define D_CONNECTED "Connesso"
+#define D_CORS_DOMAIN "CORS Domain"
#define D_COUNT "Conteggio"
#define D_COUNTER "Contatore"
#define D_CURRENT "Corrente" // As in Voltage and Current
diff --git a/tasmota/language/ko-KO.h b/tasmota/language/ko-KO.h
index c6236a05f..bff508474 100644
--- a/tasmota/language/ko-KO.h
+++ b/tasmota/language/ko-KO.h
@@ -72,6 +72,7 @@
#define D_COMMAND "커맨드"
#define D_CONNECTED "연결됨"
#define D_COUNT "횟수"
+#define D_CORS_DOMAIN "CORS Domain"
#define D_COUNTER "Counter"
#define D_CURRENT "전류" // As in Voltage and Current
#define D_DATA "Data"
diff --git a/tasmota/language/nl-NL.h b/tasmota/language/nl-NL.h
index da20ff1d7..75d841ddc 100644
--- a/tasmota/language/nl-NL.h
+++ b/tasmota/language/nl-NL.h
@@ -72,6 +72,7 @@
#define D_COMMAND "Opdracht"
#define D_CONNECTED "Verbonden"
#define D_COUNT "Aantal"
+#define D_CORS_DOMAIN "CORS Domain"
#define D_COUNTER "Teller"
#define D_CURRENT "Stroom" // As in Voltage and Current
#define D_DATA "Data"
diff --git a/tasmota/language/pl-PL.h b/tasmota/language/pl-PL.h
index 7a631f95f..8f5af6813 100644
--- a/tasmota/language/pl-PL.h
+++ b/tasmota/language/pl-PL.h
@@ -71,6 +71,7 @@
#define D_COLDLIGHT "Zimny"
#define D_COMMAND "Komenda"
#define D_CONNECTED "Połączony"
+#define D_CORS_DOMAIN "CORS Domain"
#define D_COUNT "Licz"
#define D_COUNTER "Licznik"
#define D_CURRENT "Prąd" // As in Voltage and Current
diff --git a/tasmota/language/pt-BR.h b/tasmota/language/pt-BR.h
index 2eb81f294..0efa57789 100644
--- a/tasmota/language/pt-BR.h
+++ b/tasmota/language/pt-BR.h
@@ -71,6 +71,7 @@
#define D_COLDLIGHT "Luz fria"
#define D_COMMAND "Comando"
#define D_CONNECTED "Ligado"
+#define D_CORS_DOMAIN "CORS Domain"
#define D_COUNT "Contagem"
#define D_COUNTER "Contador"
#define D_CURRENT "Corrente" // As in Voltage and Current
diff --git a/tasmota/language/pt-PT.h b/tasmota/language/pt-PT.h
index 46bafdef6..a6299c0c8 100644
--- a/tasmota/language/pt-PT.h
+++ b/tasmota/language/pt-PT.h
@@ -71,6 +71,7 @@
#define D_COLDLIGHT "Luz Fria"
#define D_COMMAND "Comando"
#define D_CONNECTED "Ligado"
+#define D_CORS_DOMAIN "CORS Domain"
#define D_COUNT "Contagem"
#define D_COUNTER "Contador"
#define D_CURRENT "Corrente" // As in Voltage and Current
diff --git a/tasmota/language/ru-RU.h b/tasmota/language/ru-RU.h
index 5ff9bff50..3bd788ede 100644
--- a/tasmota/language/ru-RU.h
+++ b/tasmota/language/ru-RU.h
@@ -71,6 +71,7 @@
#define D_COLDLIGHT "Холодный"
#define D_COMMAND "Команда"
#define D_CONNECTED "Соединен"
+#define D_CORS_DOMAIN "CORS Domain"
#define D_COUNT "Подсчет"
#define D_COUNTER "Счетчик"
#define D_CURRENT "Ток" // As in Voltage and Current
diff --git a/tasmota/language/sk-SK.h b/tasmota/language/sk-SK.h
index 57ec74f8a..a64e49e01 100644
--- a/tasmota/language/sk-SK.h
+++ b/tasmota/language/sk-SK.h
@@ -71,6 +71,7 @@
#define D_COLDLIGHT "Studené svetlo"
#define D_COMMAND "Príkaz"
#define D_CONNECTED "...pripojené"
+#define D_CORS_DOMAIN "CORS Domain"
#define D_COUNT "Počítaj"
#define D_COUNTER "Počítadlo"
#define D_CURRENT "Prúd" // As in Voltage and Current
diff --git a/tasmota/language/sv-SE.h b/tasmota/language/sv-SE.h
index aee8fd25d..51ffc2ae3 100644
--- a/tasmota/language/sv-SE.h
+++ b/tasmota/language/sv-SE.h
@@ -71,6 +71,7 @@
#define D_COLDLIGHT "Kallt"
#define D_COMMAND "Kommando"
#define D_CONNECTED "Ansluten"
+#define D_CORS_DOMAIN "CORS Domain"
#define D_COUNT "Räkna"
#define D_COUNTER "Räknare"
#define D_CURRENT "Ström" // As in Voltage and Current
diff --git a/tasmota/language/tr-TR.h b/tasmota/language/tr-TR.h
index 78612dace..6bc48c40f 100644
--- a/tasmota/language/tr-TR.h
+++ b/tasmota/language/tr-TR.h
@@ -71,6 +71,7 @@
#define D_COLDLIGHT "Soğuk"
#define D_COMMAND "Komut"
#define D_CONNECTED "Bağlandı"
+#define D_CORS_DOMAIN "CORS Domain"
#define D_COUNT "Sayı"
#define D_COUNTER "Sayaç"
#define D_CURRENT "Current" // As in Voltage and Current
diff --git a/tasmota/language/uk-UK.h b/tasmota/language/uk-UK.h
index f16d66648..b4a314630 100644
--- a/tasmota/language/uk-UK.h
+++ b/tasmota/language/uk-UK.h
@@ -71,6 +71,7 @@
#define D_COLDLIGHT "Холодний"
#define D_COMMAND "Команда"
#define D_CONNECTED "Під'єднано"
+#define D_CORS_DOMAIN "CORS Domain"
#define D_COUNT "Розмір"
#define D_COUNTER "Лічильник"
#define D_CURRENT "Струм" // As in Voltage and Current
diff --git a/tasmota/language/zh-CN.h b/tasmota/language/zh-CN.h
index 2c8610400..21aa63be3 100644
--- a/tasmota/language/zh-CN.h
+++ b/tasmota/language/zh-CN.h
@@ -71,6 +71,7 @@
#define D_COLDLIGHT "冷"
#define D_COMMAND "命令:"
#define D_CONNECTED "已连接"
+#define D_CORS_DOMAIN "CORS Domain"
#define D_COUNT "数量:"
#define D_COUNTER "计数器"
#define D_CURRENT "电流" // As in Voltage and Current
diff --git a/tasmota/language/zh-TW.h b/tasmota/language/zh-TW.h
index e5ef8926a..1d78f181e 100644
--- a/tasmota/language/zh-TW.h
+++ b/tasmota/language/zh-TW.h
@@ -71,6 +71,7 @@
#define D_COLDLIGHT "冷"
#define D_COMMAND "命令:"
#define D_CONNECTED "已連接"
+#define D_CORS_DOMAIN "CORS Domain"
#define D_COUNT "數量:"
#define D_COUNTER "Counter"
#define D_CURRENT "電流" // As in Voltage and Current
diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h
index 7ef154d53..5ff6bb6a2 100644
--- a/tasmota/my_user_config.h
+++ b/tasmota/my_user_config.h
@@ -132,6 +132,7 @@
#define WEB_PASSWORD "" // [WebPassword] Web server Admin mode Password for WEB_USERNAME (empty string = Disable)
#define FRIENDLY_NAME "Tasmota" // [FriendlyName] Friendlyname up to 32 characters used by webpages and Alexa
#define EMULATION EMUL_NONE // [Emulation] Select Belkin WeMo (single relay/light) or Hue Bridge emulation (multi relay/light) (EMUL_NONE, EMUL_WEMO or EMUL_HUE)
+#define CORS_DOMAIN "" // [Cors] CORS Domain for preflight requests
// -- HTTP GUI Colors -----------------------------
// HTML hex color codes. Only 3 and 6 digit hex string values are supported!! See https://www.w3schools.com/colors/colors_hex.asp
@@ -219,7 +220,7 @@
#define APP_BLINKTIME 10 // [BlinkTime] Time in 0.1 Sec to blink/toggle power for relay 1
#define APP_BLINKCOUNT 10 // [BlinkCount] Number of blinks (0 = 32000)
#define APP_SLEEP 0 // [Sleep] Sleep time to lower energy consumption (0 = Off, 1 - 250 mSec),
-#define PWM_MAX_SLEEP 10 // Sleep will be lowered to this value when light is on, to avoid flickering
+#define PWM_MAX_SLEEP 10 // Sleep will be lowered to this value when light is on, to avoid flickering
#define KEY_DEBOUNCE_TIME 50 // [ButtonDebounce] Number of mSeconds button press debounce time
#define KEY_HOLD_TIME 40 // [SetOption32] Number of 0.1 seconds to hold Button or external Pushbutton before sending HOLD message
@@ -284,14 +285,14 @@
#define DOMOTICZ_OUT_TOPIC "domoticz/out" // Domoticz Output Topic
// -- MQTT - Home Assistant Discovery -------------
-#define USE_HOME_ASSISTANT // Enable Home Assistant Discovery Support (+7k code)
+#define USE_HOME_ASSISTANT // Enable Home Assistant Discovery Support (+4.1k code, +6 bytes mem)
#define HOME_ASSISTANT_DISCOVERY_PREFIX "homeassistant" // Home Assistant discovery prefix
// -- MQTT - TLS - AWS IoT ------------------------
// Using TLS starting with version v6.5.0.16 compilation will only work using Core 2.4.2 and 2.5.2. No longer supported: 2.3.0
//#define USE_MQTT_TLS // Use TLS for MQTT connection (+34.5k code, +7.0k mem and +4.8k additional during connection handshake)
// #define USE_MQTT_TLS_CA_CERT // Force full CA validation instead of fingerprints, slower, but simpler to use. (+2.2k code, +1.9k mem during connection handshake)
- // This includes the LetsEncrypt CA in tasmota_ca.ino for verifying server certificates
+ // This includes the LetsEncrypt CA in tasmota_ca.ino for verifying server certificates
// #define USE_MQTT_TLS_FORCE_EC_CIPHER // Force Elliptic Curve cipher (higher security) required by some servers (automatically enabled with USE_MQTT_AWS_IOT) (+11.4k code, +0.4k mem)
// #define USE_MQTT_AWS_IOT // Enable MQTT for AWS IoT - requires a private key (+11.9k code, +0.4k mem)
// Note: you need to generate a private key + certificate per device and update 'tasmota/tasmota_aws_iot.cpp'
diff --git a/tasmota/settings.h b/tasmota/settings.h
index 554711cad..af74422df 100644
--- a/tasmota/settings.h
+++ b/tasmota/settings.h
@@ -86,7 +86,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
uint32_t energy_weekend : 1; // bit 20 (v6.6.0.8) - CMND_TARIFF
uint32_t dds2382_model : 1; // bit 21 (v6.6.0.14) - SetOption71 - Select different Modbus registers for Active Energy (#6531)
uint32_t hardware_energy_total : 1; // bit 22 (v6.6.0.15) - SetOption72 - Enable hardware energy total counter as reference (#6561)
- uint32_t cors_enabled : 1; // bit 23 (v7.0.0.1) - SetOption73 - Enable HTTP CORS
+ uint32_t ex_cors_enabled : 1; // bit 23 (v7.0.0.1) - SetOption73 - Enable HTTP CORS
uint32_t ds18x20_internal_pullup : 1; // bit 24 (v7.0.0.1) - SetOption74 - Enable internal pullup for single DS18x20 sensor
uint32_t grouptopic_mode : 1; // bit 25 (v7.0.0.1) - SetOption75 - GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1)
uint32_t bootcount_update : 1; // bit 26 (v7.0.0.4) - SetOption76 - Enable incrementing bootcount when deepsleep is enabled
@@ -248,42 +248,54 @@ struct SYSCFG {
SysBitfield flag; // 010
int16_t save_data; // 014
int8_t timezone; // 016
+
+ // Start of single char array Settings.text
+
char ota_url[101]; // 017
char mqtt_prefix[3][11]; // 07C
+
uint8_t ex_baudrate; // 09D - Free since 6.6.0.9
- uint8_t seriallog_level; // 09E
- uint8_t sta_config; // 09F
- uint8_t sta_active; // 0A0
+ uint8_t ex_seriallog_level; // 09E
+ uint8_t ex_sta_config; // 09F
+ uint8_t ex_sta_active; // 0A0
+
char sta_ssid[2][33]; // 0A1 - Keep together with sta_pwd as being copied as one chunck with reset 5
char sta_pwd[2][65]; // 0E3 - Keep together with sta_ssid as being copied as one chunck with reset 5
char hostname[33]; // 165
char syslog_host[33]; // 186
- uint8_t rule_stop; // 1A7
- uint16_t syslog_port; // 1A8
- uint8_t syslog_level; // 1AA
- uint8_t webserver; // 1AB
- uint8_t weblog_level; // 1AC
- uint8_t mqtt_fingerprint[2][20]; // 1AD
- uint8_t adc_param_type; // 1D5
- uint8_t free_1d6[10]; // 1D6
+ uint8_t ex_rule_stop; // 1A7
+ uint16_t ex_syslog_port; // 1A8
+ uint8_t ex_syslog_level; // 1AA
+ uint8_t ex_webserver; // 1AB
+ uint8_t ex_weblog_level; // 1AC
+ uint8_t ex_mqtt_fingerprint[2][20]; // 1AD
+ uint8_t ex_adc_param_type; // 1D5
- SysBitfield4 flag4; // 1E0
+ uint8_t ex_free_1d6[10]; // 1D6
- uint8_t free_1e4; // 1E4
+ // End of single char array of 456 chars max (phase 3)
+
+ SysBitfield4 ex_flag4; // 1E0
+ uint8_t ex_serial_config; // 1E4
+ uint8_t ex_wifi_output_power; // 1E5
+ uint8_t ex_shutter_accuracy; // 1E6
+ uint8_t ex_mqttlog_level; // 1E7
+ uint8_t ex_sps30_inuse_hours; // 1E8
- uint8_t wifi_output_power; // 1E5
- uint8_t shutter_accuracy; // 1E6
- uint8_t mqttlog_level; // 1E7
- uint8_t sps30_inuse_hours; // 1E8
char mqtt_host[33]; // 1E9 - Keep together with below as being copied as one chunck with reset 6
- uint16_t mqtt_port; // 20A - Keep together
+
+ uint16_t ex_mqtt_port; // 20A - Keep together
+
char mqtt_client[33]; // 20C - Keep together
char mqtt_user[33]; // 22D - Keep together
char mqtt_pwd[33]; // 24E - Keep together
char mqtt_topic[33]; // 26F - Keep together with above items as being copied as one chunck with reset 6
char button_topic[33]; // 290
char mqtt_grptopic[33]; // 2B1
+
+ // Optional end of single char array of 698 chars max (phase 5)
+
uint8_t display_model; // 2D2
uint8_t display_mode; // 2D3
uint8_t display_refresh; // 2D4
@@ -304,7 +316,9 @@ struct SYSCFG {
int16_t toffset[2]; // 30E
uint8_t display_font; // 312
char state_text[4][11]; // 313
+
uint8_t ex_energy_power_delta; // 33F - Free since 6.6.0.20
+
uint16_t domoticz_update_timer; // 340
uint16_t pwm_range; // 342
unsigned long domoticz_relay_idx[MAX_DOMOTICZ_IDX]; // 344
@@ -340,7 +354,7 @@ struct SYSCFG {
char friendlyname[MAX_FRIENDLYNAMES][33]; // 3AC
char switch_topic[33]; // 430
char serial_delimiter; // 451
- uint8_t ex_sbaudrate; // 452 - Free since 6.6.0.9
+ uint8_t seriallog_level; // 452
uint8_t sleep; // 453
uint16_t domoticz_switch_idx[MAX_DOMOTICZ_IDX]; // 454
uint16_t domoticz_sensor_idx[MAX_DOMOTICZ_SNS_IDX]; // 45C
@@ -400,7 +414,6 @@ struct SYSCFG {
uint16_t baudrate; // 778
uint16_t sbaudrate; // 77A
EnergyUsage energy_usage; // 77C
-// uint32_t drivers[3]; // 794 - 6.5.0.12 replaced by below three entries
uint32_t adc_param1; // 794
uint32_t adc_param2; // 798
int adc_param3; // 79C
@@ -416,7 +429,9 @@ struct SYSCFG {
unsigned long energy_frequency_calibration; // 7C8 also used by HX711 to save last weight
uint16_t web_refresh; // 7CC
char mems[MAX_RULE_MEMS][10]; // 7CE
+
char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b
+
TuyaFnidDpidMap tuya_fnid_map[MAX_TUYA_FUNCTIONS]; // E00 32 bytes
uint16_t ina226_r_shunt[4]; // E20
uint16_t ina226_i_fs[4]; // E28
@@ -435,12 +450,27 @@ struct SYSCFG {
uint16_t energy_power_delta; // E98
uint8_t shutter_motordelay[MAX_SHUTTERS]; // E9A
int8_t temp_comp; // E9E
-
- uint8_t free_e9f[1]; // E9F
-
+ uint8_t weight_change; // E9F
uint8_t web_color2[2][3]; // EA0 - Needs to be on integer / 3 distance from web_color
+ char cors_domain[33]; // EA6
+ uint8_t sta_config; // EC7
+ uint8_t sta_active; // EC8
+ uint8_t rule_stop; // EC9
+ uint16_t syslog_port; // ECA
+ uint8_t syslog_level; // ECC
+ uint8_t webserver; // ECD
+ uint8_t weblog_level; // ECE
+ uint8_t mqtt_fingerprint[2][20]; // ECF
+ uint8_t adc_param_type; // EF7
+ SysBitfield4 flag4; // EF8
+ uint16_t mqtt_port; // EFC
+ uint8_t serial_config; // EFE
+ uint8_t wifi_output_power; // EFF
+ uint8_t shutter_accuracy; // F00
+ uint8_t mqttlog_level; // F01
+ uint8_t sps30_inuse_hours; // F02
- uint8_t free_ea4[326]; // EA6
+ uint8_t free_f03[233]; // F03
uint32_t i2c_drivers[3]; // FEC I2cDriver
uint32_t cfg_timestamp; // FF8
diff --git a/tasmota/settings.ino b/tasmota/settings.ino
index 9ca979b45..d5c59246f 100644
--- a/tasmota/settings.ino
+++ b/tasmota/settings.ino
@@ -140,6 +140,10 @@
#ifndef DEFAULT_LIGHT_COMPONENT
#define DEFAULT_LIGHT_COMPONENT 255
#endif
+#ifndef CORS_ENABLED_ALL
+#define CORS_ENABLED_ALL "*"
+#endif
+
enum WebColors {
COL_TEXT, COL_BACKGROUND, COL_FORM,
@@ -156,6 +160,23 @@ const char kWebColors[] PROGMEM =
COLOR_BUTTON_TEXT "|" COLOR_BUTTON "|" COLOR_BUTTON_HOVER "|" COLOR_BUTTON_RESET "|" COLOR_BUTTON_RESET_HOVER "|" COLOR_BUTTON_SAVE "|" COLOR_BUTTON_SAVE_HOVER "|"
COLOR_TIMER_TAB_TEXT "|" COLOR_TIMER_TAB_BACKGROUND "|" COLOR_TITLE_TEXT;
+enum TasmotaSerialConfig {
+ TS_SERIAL_5N1, TS_SERIAL_6N1, TS_SERIAL_7N1, TS_SERIAL_8N1,
+ TS_SERIAL_5N2, TS_SERIAL_6N2, TS_SERIAL_7N2, TS_SERIAL_8N2,
+ TS_SERIAL_5E1, TS_SERIAL_6E1, TS_SERIAL_7E1, TS_SERIAL_8E1,
+ TS_SERIAL_5E2, TS_SERIAL_6E2, TS_SERIAL_7E2, TS_SERIAL_8E2,
+ TS_SERIAL_5O1, TS_SERIAL_6O1, TS_SERIAL_7O1, TS_SERIAL_8O1,
+ TS_SERIAL_5O2, TS_SERIAL_6O2, TS_SERIAL_7O2, TS_SERIAL_8O2 };
+
+const uint8_t kTasmotaSerialConfig[] PROGMEM = {
+ SERIAL_5N1, SERIAL_6N1, SERIAL_7N1, SERIAL_8N1,
+ SERIAL_5N2, SERIAL_6N2, SERIAL_7N2, SERIAL_8N2,
+ SERIAL_5E1, SERIAL_6E1, SERIAL_7E1, SERIAL_8E1,
+ SERIAL_5E2, SERIAL_6E2, SERIAL_7E2, SERIAL_8E2,
+ SERIAL_5O1, SERIAL_6O1, SERIAL_7O1, SERIAL_8O1,
+ SERIAL_5O2, SERIAL_6O2, SERIAL_7O2, SERIAL_8O2
+};
+
/*********************************************************************************************\
* RTC memory
\*********************************************************************************************/
@@ -421,6 +442,197 @@ void UpdateQuickPowerCycle(bool update)
}
}
+/*********************************************************************************************\
+ * Config Settings.text char array support
+\*********************************************************************************************/
+
+char aws_mqtt_host[66];
+char aws_mqtt_user[1] { 0 };
+
+const uint32_t settings_text_size = 457; // Settings.flag4 (1E0) - Settings.ota_url (017)
+
+uint32_t GetSettingsTextLen(void)
+{
+ char* position = Settings.ota_url;
+ for (uint32_t size = 0; size < SET_MAX; size++) {
+ while (*position++ != '\0') { }
+ }
+ return position - Settings.ota_url;
+}
+
+bool SettingsUpdateText(uint32_t index, const char* replace_me)
+{
+ if (index >= SET_MAX) {
+ return false; // Setting not supported - internal error
+ }
+
+ // Make a copy first in case we use source from Settings.text
+ uint32_t replace_len = strlen(replace_me);
+ char replace[replace_len +1];
+ memcpy(replace, replace_me, sizeof(replace));
+
+ if (Settings.version < 0x08000000) {
+ uint32_t idx = 0;
+ switch (index) {
+ case SET_OTAURL: strlcpy(Settings.ota_url, replace, sizeof(Settings.ota_url)); break;
+ case SET_MQTTPREFIX3: idx++;
+ case SET_MQTTPREFIX2: idx++;
+ case SET_MQTTPREFIX1: strlcpy(Settings.mqtt_prefix[idx], replace, sizeof(Settings.mqtt_prefix[idx])); break;
+ case SET_STASSID2: idx++;
+ case SET_STASSID1: strlcpy(Settings.sta_ssid[idx], replace, sizeof(Settings.sta_ssid[idx])); break;
+ case SET_STAPWD2: idx++;
+ case SET_STAPWD1: strlcpy(Settings.sta_pwd[idx], replace, sizeof(Settings.sta_pwd[idx])); break;
+ case SET_HOSTNAME: strlcpy(Settings.hostname, replace, sizeof(Settings.hostname)); break;
+ case SET_SYSLOG_HOST: strlcpy(Settings.syslog_host, replace, sizeof(Settings.syslog_host)); break;
+ case SET_WEBPWD: strlcpy(Settings.web_password, replace, sizeof(Settings.web_password)); break;
+#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT)
+ case SET_MQTT_HOST:
+ if (strlen(replace) <= sizeof(Settings.mqtt_host)) {
+ strlcpy(Settings.mqtt_host, replace, sizeof(Settings.mqtt_host));
+ Settings.mqtt_user[0] = 0;
+ } else {
+ // need to split in mqtt_user first then mqtt_host
+ strlcpy(Settings.mqtt_user, replace, sizeof(Settings.mqtt_user));
+ strlcpy(Settings.mqtt_host, &replace[sizeof(Settings.mqtt_user)-1], sizeof(Settings.mqtt_host));
+ }
+ break;
+ case SET_MQTT_USER: break;
+#else
+ case SET_MQTT_HOST: strlcpy(Settings.mqtt_host, replace, sizeof(Settings.mqtt_host)); break;
+ case SET_MQTT_USER: strlcpy(Settings.mqtt_user, replace, sizeof(Settings.mqtt_user)); break;
+#endif
+ case SET_MQTT_CLIENT: strlcpy(Settings.mqtt_client, replace, sizeof(Settings.mqtt_client)); break;
+ case SET_MQTT_PWD: strlcpy(Settings.mqtt_pwd, replace, sizeof(Settings.mqtt_pwd)); break;
+ case SET_MQTT_FULLTOPIC: strlcpy(Settings.mqtt_fulltopic, replace, sizeof(Settings.mqtt_fulltopic)); break;
+ case SET_MQTT_TOPIC: strlcpy(Settings.mqtt_topic, replace, sizeof(Settings.mqtt_topic)); break;
+ case SET_MQTT_BUTTON_TOPIC: strlcpy(Settings.button_topic, replace, sizeof(Settings.button_topic)); break;
+ case SET_MQTT_SWITCH_TOPIC: strlcpy(Settings.switch_topic, replace, sizeof(Settings.switch_topic)); break;
+ case SET_MQTT_GRP_TOPIC: strlcpy(Settings.mqtt_grptopic, replace, sizeof(Settings.mqtt_grptopic)); break;
+ case SET_STATE_TXT4: idx++;
+ case SET_STATE_TXT3: idx++;
+ case SET_STATE_TXT2: idx++;
+ case SET_STATE_TXT1: strlcpy(Settings.state_text[idx], replace, sizeof(Settings.state_text[idx])); break;
+ case SET_NTPSERVER3: idx++;
+ case SET_NTPSERVER2: idx++;
+ case SET_NTPSERVER1: strlcpy(Settings.ntp_server[idx], replace, sizeof(Settings.ntp_server[idx])); break;
+ case SET_MEM5: idx++;
+ case SET_MEM4: idx++;
+ case SET_MEM3: idx++;
+ case SET_MEM2: idx++;
+ case SET_MEM1: strlcpy(Settings.mems[idx], replace, sizeof(Settings.mems[idx])); break;
+ case SET_CORS: strlcpy(Settings.cors_domain, replace, sizeof(Settings.cors_domain)); break;
+ case SET_FRIENDLYNAME4: idx++;
+ case SET_FRIENDLYNAME3: idx++;
+ case SET_FRIENDLYNAME2: idx++;
+ case SET_FRIENDLYNAME1: strlcpy(Settings.friendlyname[idx], replace, sizeof(Settings.friendlyname[idx])); break;
+ }
+ } else {
+ uint32_t start_pos = 0;
+ uint32_t end_pos = 0;
+ char* position = Settings.ota_url;
+ for (uint32_t size = 0; size < SET_MAX; size++) {
+ while (*position++ != '\0') { }
+ if (1 == index) {
+ start_pos = position - Settings.ota_url;
+ }
+ else if (0 == index) {
+ end_pos = position - Settings.ota_url -1;
+ }
+ index--;
+ }
+ uint32_t char_len = position - Settings.ota_url;
+
+ uint32_t current_len = end_pos - start_pos;
+ int diff = replace_len - current_len;
+
+ // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TST: start %d, end %d, len %d, current %d, replace %d, diff %d"),
+ // start_pos, end_pos, char_len, current_len, replace_len, diff);
+
+ int too_long = (char_len + diff) - settings_text_size;
+ if (too_long > 0) {
+ // AddLog_P2(LOG_LEVEL_INFO, PSTR("CFG: Text too long by %d char(s)"), too_long);
+ return false; // Replace text too long
+ }
+
+ if (diff != 0) {
+ // Shift Settings.text up or down
+ memmove_P(Settings.ota_url + start_pos + replace_len, Settings.ota_url + end_pos, char_len - end_pos);
+ }
+ // Replace text
+ memmove_P(Settings.ota_url + start_pos, replace, replace_len);
+ // Fill for future use
+ memset(Settings.ota_url + char_len + diff, 0x00, settings_text_size - char_len - diff);
+ }
+
+ return true;
+}
+
+char* SettingsText(uint32_t index)
+{
+ if (index >= SET_MAX) {
+ return nullptr; // Setting not supported - internal error
+ }
+
+ char* position = Settings.ota_url;
+
+ if (Settings.version < 0x08000000) {
+ uint32_t idx = 0;
+ switch (index) {
+ case SET_MQTTPREFIX3: idx++;
+ case SET_MQTTPREFIX2: idx++;
+ case SET_MQTTPREFIX1: position = Settings.mqtt_prefix[idx]; break;
+ case SET_STASSID2: idx++;
+ case SET_STASSID1: position = Settings.sta_ssid[idx]; break;
+ case SET_STAPWD2: idx++;
+ case SET_STAPWD1: position = Settings.sta_pwd[idx]; break;
+ case SET_HOSTNAME: position = Settings.hostname; break;
+ case SET_SYSLOG_HOST: position = Settings.syslog_host; break;
+ case SET_WEBPWD: position = Settings.web_password; break;
+#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT)
+ case SET_MQTT_HOST:
+ strlcpy(aws_mqtt_host, Settings.mqtt_user, strlen(Settings.mqtt_user));
+ strlcpy(&aws_mqtt_host[strlen(Settings.mqtt_user)], Settings.mqtt_host, sizeof(Settings.mqtt_host));
+ position = aws_mqtt_host; break;
+ case SET_MQTT_USER: position = aws_mqtt_user; break;
+#else
+ case SET_MQTT_HOST: position = Settings.mqtt_host; break;
+ case SET_MQTT_USER: position = Settings.mqtt_user; break;
+#endif
+ case SET_MQTT_CLIENT: position = Settings.mqtt_client; break;
+ case SET_MQTT_PWD: position = Settings.mqtt_pwd; break;
+ case SET_MQTT_FULLTOPIC: position = Settings.mqtt_fulltopic; break;
+ case SET_MQTT_TOPIC: position = Settings.mqtt_topic; break;
+ case SET_MQTT_BUTTON_TOPIC: position = Settings.button_topic; break;
+ case SET_MQTT_SWITCH_TOPIC: position = Settings.switch_topic; break;
+ case SET_MQTT_GRP_TOPIC: position = Settings.mqtt_grptopic; break;
+ case SET_STATE_TXT4: idx++;
+ case SET_STATE_TXT3: idx++;
+ case SET_STATE_TXT2: idx++;
+ case SET_STATE_TXT1: position = Settings.state_text[idx]; break;
+ case SET_NTPSERVER3: idx++;
+ case SET_NTPSERVER2: idx++;
+ case SET_NTPSERVER1: position = Settings.ntp_server[idx]; break;
+ case SET_MEM5: idx++;
+ case SET_MEM4: idx++;
+ case SET_MEM3: idx++;
+ case SET_MEM2: idx++;
+ case SET_MEM1: position = Settings.mems[idx]; break;
+ case SET_CORS: position = Settings.cors_domain; break;
+ case SET_FRIENDLYNAME4: idx++;
+ case SET_FRIENDLYNAME3: idx++;
+ case SET_FRIENDLYNAME2: idx++;
+ case SET_FRIENDLYNAME1: position = Settings.friendlyname[idx]; break;
+ }
+
+ } else {
+ for (;index > 0; index--) {
+ while (*position++ != '\0') { }
+ }
+ }
+
+ return position;
+}
+
/*********************************************************************************************\
* Config Save - Save parameters to Flash ONLY if any parameter has changed
\*********************************************************************************************/
@@ -652,11 +864,11 @@ void SettingsDefaultSet2(void)
Settings.module = MODULE;
ModuleDefault(WEMOS);
// for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { Settings.my_gp.io[i] = GPIO_NONE; }
- strlcpy(Settings.friendlyname[0], FRIENDLY_NAME, sizeof(Settings.friendlyname[0]));
- strlcpy(Settings.friendlyname[1], FRIENDLY_NAME"2", sizeof(Settings.friendlyname[1]));
- strlcpy(Settings.friendlyname[2], FRIENDLY_NAME"3", sizeof(Settings.friendlyname[2]));
- strlcpy(Settings.friendlyname[3], FRIENDLY_NAME"4", sizeof(Settings.friendlyname[3]));
- strlcpy(Settings.ota_url, OTA_URL, sizeof(Settings.ota_url));
+ SettingsUpdateText(SET_FRIENDLYNAME1, FRIENDLY_NAME);
+ SettingsUpdateText(SET_FRIENDLYNAME2, FRIENDLY_NAME"2");
+ SettingsUpdateText(SET_FRIENDLYNAME3, FRIENDLY_NAME"3");
+ SettingsUpdateText(SET_FRIENDLYNAME4, FRIENDLY_NAME"4");
+ SettingsUpdateText(SET_OTAURL, OTA_URL);
// Power
Settings.flag.save_state = SAVE_STATE;
@@ -670,6 +882,7 @@ void SettingsDefaultSet2(void)
// for (uint32_t i = 1; i < MAX_PULSETIMERS; i++) { Settings.pulse_timer[i] = 0; }
// Serial
+ Settings.serial_config = TS_SERIAL_8N1;
Settings.baudrate = APP_BAUDRATE / 300;
Settings.sbaudrate = SOFT_BAUDRATE / 300;
Settings.serial_delimiter = 0xff;
@@ -683,14 +896,14 @@ void SettingsDefaultSet2(void)
ParseIp(&Settings.ip_address[3], WIFI_DNS);
Settings.sta_config = WIFI_CONFIG_TOOL;
// Settings.sta_active = 0;
- strlcpy(Settings.sta_ssid[0], STA_SSID1, sizeof(Settings.sta_ssid[0]));
- strlcpy(Settings.sta_pwd[0], STA_PASS1, sizeof(Settings.sta_pwd[0]));
- strlcpy(Settings.sta_ssid[1], STA_SSID2, sizeof(Settings.sta_ssid[1]));
- strlcpy(Settings.sta_pwd[1], STA_PASS2, sizeof(Settings.sta_pwd[1]));
- strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname));
+ SettingsUpdateText(SET_STASSID1, STA_SSID1);
+ SettingsUpdateText(SET_STASSID2, STA_SSID2);
+ SettingsUpdateText(SET_STAPWD1, STA_PASS1);
+ SettingsUpdateText(SET_STAPWD2, STA_PASS2);
+ SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME);
// Syslog
- strlcpy(Settings.syslog_host, SYS_LOG_HOST, sizeof(Settings.syslog_host));
+ SettingsUpdateText(SET_SYSLOG_HOST, SYS_LOG_HOST);
Settings.syslog_port = SYS_LOG_PORT;
Settings.syslog_level = SYS_LOG_LEVEL;
@@ -698,8 +911,9 @@ void SettingsDefaultSet2(void)
Settings.flag2.emulation = EMULATION;
Settings.webserver = WEB_SERVER;
Settings.weblog_level = WEB_LOG_LEVEL;
- strlcpy(Settings.web_password, WEB_PASSWORD, sizeof(Settings.web_password));
+ SettingsUpdateText(SET_WEBPWD, WEB_PASSWORD);
Settings.flag3.mdns_enabled = MDNS_ENABLED;
+ SettingsUpdateText(SET_CORS, CORS_DOMAIN);
// Button
// Settings.flag.button_restrict = 0;
@@ -722,24 +936,24 @@ void SettingsDefaultSet2(void)
// Settings.flag.mqtt_offline = 0;
// Settings.flag.mqtt_serial = 0;
// Settings.flag.device_index_enable = 0;
- strlcpy(Settings.mqtt_host, MQTT_HOST, sizeof(Settings.mqtt_host));
+ SettingsUpdateText(SET_MQTT_HOST, MQTT_HOST);
Settings.mqtt_port = MQTT_PORT;
- strlcpy(Settings.mqtt_client, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client));
- strlcpy(Settings.mqtt_user, MQTT_USER, sizeof(Settings.mqtt_user));
- strlcpy(Settings.mqtt_pwd, MQTT_PASS, sizeof(Settings.mqtt_pwd));
- strlcpy(Settings.mqtt_topic, MQTT_TOPIC, sizeof(Settings.mqtt_topic));
- strlcpy(Settings.button_topic, MQTT_BUTTON_TOPIC, sizeof(Settings.button_topic));
- strlcpy(Settings.switch_topic, MQTT_SWITCH_TOPIC, sizeof(Settings.switch_topic));
- strlcpy(Settings.mqtt_grptopic, MQTT_GRPTOPIC, sizeof(Settings.mqtt_grptopic));
- strlcpy(Settings.mqtt_fulltopic, MQTT_FULLTOPIC, sizeof(Settings.mqtt_fulltopic));
+ SettingsUpdateText(SET_MQTT_CLIENT, MQTT_CLIENT_ID);
+ SettingsUpdateText(SET_MQTT_USER, MQTT_USER);
+ SettingsUpdateText(SET_MQTT_PWD, MQTT_PASS);
+ SettingsUpdateText(SET_MQTT_TOPIC, MQTT_TOPIC);
+ SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, MQTT_BUTTON_TOPIC);
+ SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, MQTT_SWITCH_TOPIC);
+ SettingsUpdateText(SET_MQTT_GRP_TOPIC, MQTT_GRPTOPIC);
+ SettingsUpdateText(SET_MQTT_FULLTOPIC, MQTT_FULLTOPIC);
Settings.mqtt_retry = MQTT_RETRY_SECS;
- strlcpy(Settings.mqtt_prefix[0], SUB_PREFIX, sizeof(Settings.mqtt_prefix[0]));
- strlcpy(Settings.mqtt_prefix[1], PUB_PREFIX, sizeof(Settings.mqtt_prefix[1]));
- strlcpy(Settings.mqtt_prefix[2], PUB_PREFIX2, sizeof(Settings.mqtt_prefix[2]));
- strlcpy(Settings.state_text[0], MQTT_STATUS_OFF, sizeof(Settings.state_text[0]));
- strlcpy(Settings.state_text[1], MQTT_STATUS_ON, sizeof(Settings.state_text[1]));
- strlcpy(Settings.state_text[2], MQTT_CMND_TOGGLE, sizeof(Settings.state_text[2]));
- strlcpy(Settings.state_text[3], MQTT_CMND_HOLD, sizeof(Settings.state_text[3]));
+ SettingsUpdateText(SET_MQTTPREFIX1, SUB_PREFIX);
+ SettingsUpdateText(SET_MQTTPREFIX2, PUB_PREFIX);
+ SettingsUpdateText(SET_MQTTPREFIX3, PUB_PREFIX2);
+ SettingsUpdateText(SET_STATE_TXT1, MQTT_STATUS_OFF);
+ SettingsUpdateText(SET_STATE_TXT2, MQTT_STATUS_ON);
+ SettingsUpdateText(SET_STATE_TXT3, MQTT_CMND_TOGGLE);
+ SettingsUpdateText(SET_STATE_TXT4, MQTT_CMND_HOLD);
char fingerprint[60];
strlcpy(fingerprint, MQTT_FINGERPRINT1, sizeof(fingerprint));
char *p = fingerprint;
@@ -891,15 +1105,11 @@ void SettingsDefaultSet2(void)
Settings.timezone = APP_TIMEZONE / 60;
Settings.timezone_minutes = abs(APP_TIMEZONE % 60);
}
- strlcpy(Settings.ntp_server[0], NTP_SERVER1, sizeof(Settings.ntp_server[0]));
- strlcpy(Settings.ntp_server[1], NTP_SERVER2, sizeof(Settings.ntp_server[1]));
- strlcpy(Settings.ntp_server[2], NTP_SERVER3, sizeof(Settings.ntp_server[2]));
- for (uint32_t j = 0; j < 3; j++) {
- for (uint32_t i = 0; i < strlen(Settings.ntp_server[j]); i++) {
- if (Settings.ntp_server[j][i] == ',') {
- Settings.ntp_server[j][i] = '.';
- }
- }
+ SettingsUpdateText(SET_NTPSERVER1, NTP_SERVER1);
+ SettingsUpdateText(SET_NTPSERVER2, NTP_SERVER2);
+ SettingsUpdateText(SET_NTPSERVER3, NTP_SERVER3);
+ for (uint32_t i = 0; i < 3; i++) {
+ SettingsUpdateText(SET_NTPSERVER1 +i, ReplaceCommaWithDot(SettingsText(SET_NTPSERVER1 +i)));
}
Settings.latitude = (int)((double)LATITUDE * 1000000);
Settings.longitude = (int)((double)LONGITUDE * 1000000);
@@ -1059,8 +1269,8 @@ void SettingsDelta(void)
}
}
if (Settings.version < 0x06060009) {
- Settings.baudrate = Settings.ex_baudrate * 4;
- Settings.sbaudrate = Settings.ex_sbaudrate * 4;
+ Settings.baudrate = APP_BAUDRATE / 300;
+ Settings.sbaudrate = SOFT_BAUDRATE / 300;
}
if (Settings.version < 0x0606000A) {
uint8_t tuyaindex = 0;
@@ -1155,6 +1365,54 @@ void SettingsDelta(void)
if (Settings.version < 0x07000004) {
Settings.wifi_output_power = 170;
}
+ if (Settings.version < 0x07010202) {
+ Settings.serial_config = TS_SERIAL_8N1;
+ }
+ if (Settings.version < 0x07010204) {
+ if (Settings.flag3.ex_cors_enabled == 1) {
+ strlcpy(Settings.cors_domain, CORS_ENABLED_ALL, sizeof(Settings.cors_domain));
+ } else {
+ Settings.cors_domain[0] = 0;
+ }
+ }
+ if (Settings.version < 0x07010205) {
+ Settings.seriallog_level = Settings.ex_seriallog_level; // 09E -> 452
+ Settings.sta_config = Settings.ex_sta_config; // 09F -> EC7
+ Settings.sta_active = Settings.ex_sta_active; // 0A0 -> EC8
+ memcpy((char*)&Settings.rule_stop, (char*)&Settings.ex_rule_stop, 47); // 1A7 -> EC9
+ }
+ if (Settings.version < 0x07010206) {
+ Settings.flag4 = Settings.ex_flag4; // 1E0 -> EF8
+ Settings.mqtt_port = Settings.ex_mqtt_port; // 20A -> EFC
+ memcpy((char*)&Settings.serial_config, (char*)&Settings.ex_serial_config, 5); // 1E4 -> EFE
+ }
+
+ if ((VERSION < 0x08000000) && (Settings.version > VERSION)) {
+ char temp[strlen(SettingsText(SET_OTAURL)) +1]; strncpy(temp, SettingsText(SET_OTAURL), sizeof(temp));
+ char temp21[strlen(SettingsText(SET_MQTTPREFIX1)) +1]; strncpy(temp21, SettingsText(SET_MQTTPREFIX1), sizeof(temp21));
+ char temp22[strlen(SettingsText(SET_MQTTPREFIX2)) +1]; strncpy(temp22, SettingsText(SET_MQTTPREFIX2), sizeof(temp22));
+ char temp23[strlen(SettingsText(SET_MQTTPREFIX3)) +1]; strncpy(temp23, SettingsText(SET_MQTTPREFIX3), sizeof(temp23));
+ char temp31[strlen(SettingsText(SET_STASSID1)) +1]; strncpy(temp31, SettingsText(SET_STASSID1), sizeof(temp31));
+ char temp32[strlen(SettingsText(SET_STASSID2)) +1]; strncpy(temp32, SettingsText(SET_STASSID2), sizeof(temp32));
+ char temp41[strlen(SettingsText(SET_STAPWD1)) +1]; strncpy(temp41, SettingsText(SET_STAPWD1), sizeof(temp41));
+ char temp42[strlen(SettingsText(SET_STAPWD2)) +1]; strncpy(temp42, SettingsText(SET_STAPWD2), sizeof(temp42));
+ char temp5[strlen(SettingsText(SET_HOSTNAME)) +1]; strncpy(temp5, SettingsText(SET_HOSTNAME), sizeof(temp5));
+ char temp6[strlen(SettingsText(SET_SYSLOG_HOST)) +1]; strncpy(temp6, SettingsText(SET_SYSLOG_HOST), sizeof(temp5));
+
+ uint32_t version = Settings.version;
+ Settings.version = VERSION;
+ SettingsUpdateText(SET_OTAURL, temp);
+ SettingsUpdateText(SET_MQTTPREFIX1, temp21);
+ SettingsUpdateText(SET_MQTTPREFIX2, temp22);
+ SettingsUpdateText(SET_MQTTPREFIX3, temp23);
+ SettingsUpdateText(SET_STASSID1, temp31);
+ SettingsUpdateText(SET_STASSID2, temp32);
+ SettingsUpdateText(SET_STAPWD1, temp41);
+ SettingsUpdateText(SET_STAPWD2, temp42);
+ SettingsUpdateText(SET_HOSTNAME, temp5);
+ SettingsUpdateText(SET_SYSLOG_HOST, temp6);
+ Settings.version = version;
+ }
Settings.version = VERSION;
SettingsSave(1);
diff --git a/tasmota/support.ino b/tasmota/support.ino
index 8ce7f2840..87f05ad27 100644
--- a/tasmota/support.ino
+++ b/tasmota/support.ino
@@ -51,7 +51,7 @@ 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, last_run %d"), ESP.getFreeHeap(), WifiGetRssiAsQuality(WiFi.RSSI()), last_run);
+ 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);
#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
@@ -107,12 +107,6 @@ String GetResetReason(void)
}
}
-String GetResetReasonInfo(void)
-{
- // "Fatal exception:0 flag:2 (EXCEPTION) epc1:0x704022a7 epc2:0x00000000 epc3:0x00000000 excvaddr:0x00000000 depc:0x00000000"
- return (ResetReason() == REASON_EXCEPTION_RST) ? ESP.getResetInfo() : GetResetReason();
-}
-
/*********************************************************************************************\
* Miscellaneous
\*********************************************************************************************/
@@ -334,6 +328,22 @@ char* RemoveSpace(char* p)
return p;
}
+char* ReplaceCommaWithDot(char* p)
+{
+ char* write = (char*)p;
+ char* read = (char*)p;
+ char ch = '.';
+
+ while (ch != '\0') {
+ ch = *read++;
+ if (ch == ',') {
+ ch = '.';
+ }
+ *write++ = ch;
+ }
+ return p;
+}
+
char* LowerCase(char* dest, const char* source)
{
char* write = dest;
@@ -383,6 +393,23 @@ char* Trim(char* p)
return p;
}
+char* RemoveAllSpaces(char* p)
+{
+ // remove any white space from the base64
+ char *cursor = p;
+ uint32_t offset = 0;
+ while (1) {
+ *cursor = *(cursor + offset);
+ if ((' ' == *cursor) || ('\t' == *cursor) || ('\n' == *cursor)) { // if space found, remove this char until end of string
+ offset++;
+ } else {
+ if (0 == *cursor) { break; }
+ cursor++;
+ }
+ }
+ return p;
+}
+
char* NoAlNumToUnderscore(char* dest, const char* source)
{
char* write = dest;
@@ -737,19 +764,50 @@ int GetStateNumber(char *state_text)
return state_number;
}
+String GetSerialConfig(void)
+{
+ // Settings.serial_config layout
+ // b000000xx - 5, 6, 7 or 8 data bits
+ // b00000x00 - 1 or 2 stop bits
+ // b000xx000 - None, Even or Odd parity
+
+ const char kParity[] = "NEOI";
+
+ char config[4];
+ config[0] = '5' + (Settings.serial_config & 0x3);
+ config[1] = kParity[(Settings.serial_config >> 3) & 0x3];
+ config[2] = '1' + ((Settings.serial_config >> 2) & 0x1);
+ config[3] = '\0';
+ return String(config);
+}
+
+void SetSerialBegin(uint32_t baudrate)
+{
+ if (seriallog_level) {
+ AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "Set Serial to %s %d bit/s"), GetSerialConfig().c_str(), baudrate);
+ delay(100);
+ }
+ Serial.flush();
+ Serial.begin(baudrate, (SerialConfig)pgm_read_byte(kTasmotaSerialConfig + Settings.serial_config));
+ delay(10);
+ Serial.println();
+}
+
+void SetSerialConfig(uint32_t serial_config)
+{
+ if (serial_config == Settings.serial_config) { return; }
+ if (serial_config > TS_SERIAL_8O2) { return; }
+
+ Settings.serial_config = serial_config;
+ SetSerialBegin(Serial.baudRate());
+}
+
void SetSerialBaudrate(int baudrate)
{
Settings.baudrate = baudrate / 300;
- if (Serial.baudRate() != baudrate) {
- if (seriallog_level) {
- AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SET_BAUDRATE_TO " %d"), baudrate);
- }
- delay(100);
- Serial.flush();
- Serial.begin(baudrate, serial_config);
- delay(10);
- Serial.println();
- }
+ if (Serial.baudRate() == baudrate) { return; }
+
+ SetSerialBegin(baudrate);
}
void ClaimSerial(void)
@@ -1529,10 +1587,10 @@ void Syslog(void)
{
// Destroys log_data
- uint32_t current_hash = GetHash(Settings.syslog_host, strlen(Settings.syslog_host));
+ uint32_t current_hash = GetHash(SettingsText(SET_SYSLOG_HOST), strlen(SettingsText(SET_SYSLOG_HOST)));
if (syslog_host_hash != current_hash) {
syslog_host_hash = current_hash;
- WiFi.hostByName(Settings.syslog_host, syslog_host_addr); // If sleep enabled this might result in exception so try to do it once using hash
+ WiFi.hostByName(SettingsText(SET_SYSLOG_HOST), syslog_host_addr); // If sleep enabled this might result in exception so try to do it once using hash
}
if (PortUdp.beginPacket(syslog_host_addr, Settings.syslog_port)) {
char syslog_preamble[64]; // Hostname + Id
diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino
index fe8640045..b8fbd4a7a 100644
--- a/tasmota/support_command.ino
+++ b/tasmota/support_command.ino
@@ -23,7 +23,7 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix
D_CMND_SETOPTION "|" D_CMND_TEMPERATURE_RESOLUTION "|" D_CMND_HUMIDITY_RESOLUTION "|" D_CMND_PRESSURE_RESOLUTION "|" D_CMND_POWER_RESOLUTION "|"
D_CMND_VOLTAGE_RESOLUTION "|" D_CMND_FREQUENCY_RESOLUTION "|" D_CMND_CURRENT_RESOLUTION "|" D_CMND_ENERGY_RESOLUTION "|" D_CMND_WEIGHT_RESOLUTION "|"
D_CMND_MODULE "|" D_CMND_MODULES "|" D_CMND_GPIO "|" D_CMND_GPIOS "|" D_CMND_TEMPLATE "|" D_CMND_PWM "|" D_CMND_PWMFREQUENCY "|" D_CMND_PWMRANGE "|"
- D_CMND_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" D_CMND_SYSLOG "|" D_CMND_LOGHOST "|" D_CMND_LOGPORT "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|"
+ D_CMND_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" D_CMND_SYSLOG "|" D_CMND_LOGHOST "|" D_CMND_LOGPORT "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALCONFIG "|"
D_CMND_SERIALDELIMITER "|" D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|" D_CMND_WIFICONFIG "|"
D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TELEPERIOD "|" D_CMND_RESET "|" D_CMND_TIME "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|"
D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_LEDMASK "|" D_CMND_WIFIPOWER "|" D_CMND_TEMPOFFSET "|"
@@ -38,7 +38,7 @@ void (* const TasmotaCommand[])(void) PROGMEM = {
&CmndSetoption, &CmndTemperatureResolution, &CmndHumidityResolution, &CmndPressureResolution, &CmndPowerResolution,
&CmndVoltageResolution, &CmndFrequencyResolution, &CmndCurrentResolution, &CmndEnergyResolution, &CmndWeightResolution,
&CmndModule, &CmndModules, &CmndGpio, &CmndGpios, &CmndTemplate, &CmndPwm, &CmndPwmfrequency, &CmndPwmrange,
- &CmndButtonDebounce, &CmndSwitchDebounce, &CmndSyslog, &CmndLoghost, &CmndLogport, &CmndSerialSend, &CmndBaudrate,
+ &CmndButtonDebounce, &CmndSwitchDebounce, &CmndSyslog, &CmndLoghost, &CmndLogport, &CmndSerialSend, &CmndBaudrate, &CmndSerialConfig,
&CmndSerialDelimiter, &CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig,
&CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset, &CmndTime, &CmndTimezone, &CmndTimeStd,
&CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndWifiPower, &CmndTempOffset,
@@ -147,7 +147,7 @@ void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len)
data_len--;
}
- bool grpflg = (strstr(topicBuf, Settings.mqtt_grptopic) != nullptr);
+ bool grpflg = (strstr(topicBuf, SettingsText(SET_MQTT_GRP_TOPIC)) != nullptr);
char stemp1[TOPSZ];
GetFallbackTopic_P(stemp1, ""); // Full Fallback topic = cmnd/DVES_xxxxxxxx_fb/
@@ -325,15 +325,18 @@ void CmndStatus(void)
uint32_t payload = ((XdrvMailbox.payload < 0) || (XdrvMailbox.payload > MAX_STATUS)) ? 99 : XdrvMailbox.payload;
uint32_t option = STAT;
- char stemp[MAX_FRIENDLYNAMES * (sizeof(Settings.friendlyname[0]) +MAX_FRIENDLYNAMES)];
+ char stemp[200];
char stemp2[100];
// Workaround MQTT - TCP/IP stack queueing when SUB_PREFIX = PUB_PREFIX
- if (!strcmp(Settings.mqtt_prefix[0],Settings.mqtt_prefix[1]) && (!payload)) { option++; } // TELE
+ if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2)) && (!payload)) { option++; } // TELE
if ((!Settings.flag.mqtt_enabled) && (6 == payload)) { payload = 99; } // SetOption3 - Enable MQTT
if (!energy_flg && (9 == payload)) { payload = 99; }
+ bool exception_flg = (ResetReason() == REASON_EXCEPTION_RST);
+ if (!exception_flg && (12 == payload)) { payload = 99; }
+
if ((0 == payload) || (99 == payload)) {
uint32_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present;
#ifdef USE_SONOFF_IFAN
@@ -341,7 +344,7 @@ void CmndStatus(void)
#endif // USE_SONOFF_IFAN
stemp[0] = '\0';
for (uint32_t i = 0; i < maxfn; i++) {
- snprintf_P(stemp, sizeof(stemp), PSTR("%s%s\"%s\"" ), stemp, (i > 0 ? "," : ""), Settings.friendlyname[i]);
+ snprintf_P(stemp, sizeof(stemp), PSTR("%s%s\"%s\"" ), stemp, (i > 0 ? "," : ""), SettingsText(SET_FRIENDLYNAME1 +i));
}
stemp2[0] = '\0';
for (uint32_t i = 0; i < MAX_SWITCHES; i++) {
@@ -352,10 +355,10 @@ void CmndStatus(void)
D_CMND_LEDMASK "\":\"%04X\",\"" D_CMND_SAVEDATA "\":%d,\"" D_JSON_SAVESTATE "\":%d,\"" D_CMND_SWITCHTOPIC "\":\"%s\",\""
D_CMND_SWITCHMODE "\":[%s],\"" D_CMND_BUTTONRETAIN "\":%d,\"" D_CMND_SWITCHRETAIN "\":%d,\"" D_CMND_SENSORRETAIN "\":%d,\"" D_CMND_POWERRETAIN "\":%d}}"),
ModuleNr(), stemp, mqtt_topic,
- Settings.button_topic, power, Settings.poweronstate, Settings.ledstate,
+ SettingsText(SET_MQTT_BUTTON_TOPIC), power, Settings.poweronstate, Settings.ledstate,
Settings.ledmask, Settings.save_data,
Settings.flag.save_state, // SetOption0 - Save power state and use after restart
- Settings.switch_topic,
+ SettingsText(SET_MQTT_SWITCH_TOPIC),
stemp2,
Settings.flag.mqtt_button_retain, // CMND_BUTTONRETAIN
Settings.flag.mqtt_switch_retain, // CMND_SWITCHRETAIN
@@ -368,8 +371,8 @@ void CmndStatus(void)
Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS1_PARAMETER "\":{\"" D_JSON_BAUDRATE "\":%d,\"" D_CMND_GROUPTOPIC "\":\"%s\",\"" D_CMND_OTAURL "\":\"%s\",\""
D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_JSON_STARTUPUTC "\":\"%s\",\"" D_CMND_SLEEP "\":%d,\""
D_JSON_CONFIG_HOLDER "\":%d,\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_JSON_SAVEADDRESS "\":\"%X\"}}"),
- baudrate, Settings.mqtt_grptopic, Settings.ota_url,
- GetResetReasonInfo().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep,
+ baudrate, SettingsText(SET_MQTT_GRP_TOPIC), SettingsText(SET_OTAURL),
+ GetResetReason().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep,
Settings.cfg_holder, Settings.bootcount, Settings.save_flag, GetSettingsAddress());
MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "1"));
}
@@ -377,9 +380,12 @@ void CmndStatus(void)
if ((0 == payload) || (2 == payload)) {
Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS2_FIRMWARE "\":{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\",\""
D_JSON_BOOTVERSION "\":%d,\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\","
- "\"Hardware\":\"%s\"}}"),
+ "\"Hardware\":\"%s\""
+ "%s}}"),
my_version, my_image, GetBuildDateAndTime().c_str(),
- ESP.getBootVersion(), ESP.getSdkVersion(), GetDeviceHardware().c_str());
+ ESP.getBootVersion(), ESP.getSdkVersion(),
+ GetDeviceHardware().c_str(),
+ GetStatistics().c_str());
MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "2"));
}
@@ -388,7 +394,7 @@ void CmndStatus(void)
D_CMND_LOGHOST "\":\"%s\",\"" D_CMND_LOGPORT "\":%d,\"" D_CMND_SSID "\":[\"%s\",\"%s\"],\"" D_CMND_TELEPERIOD "\":%d,\""
D_JSON_RESOLUTION "\":\"%08X\",\"" D_CMND_SETOPTION "\":[\"%08X\",\"%s\",\"%08X\",\"%08X\"]}}"),
Settings.seriallog_level, Settings.weblog_level, Settings.mqttlog_level, Settings.syslog_level,
- Settings.syslog_host, Settings.syslog_port, Settings.sta_ssid[0], Settings.sta_ssid[1], Settings.tele_period,
+ SettingsText(SET_SYSLOG_HOST), Settings.syslog_port, SettingsText(SET_STASSID1), SettingsText(SET_STASSID2), Settings.tele_period,
Settings.flag2.data, Settings.flag.data, ToHex_P((unsigned char*)Settings.param, PARAM8_SIZE, stemp2, sizeof(stemp2)),
Settings.flag3.data, Settings.flag4.data);
MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "3"));
@@ -419,17 +425,10 @@ void CmndStatus(void)
}
if (((0 == payload) || (6 == payload)) && Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT
-#ifdef USE_MQTT_AWS_IOT
- Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS6_MQTT "\":{\"" D_CMND_MQTTHOST "\":\"%s%s\",\"" D_CMND_MQTTPORT "\":%d,\"" D_CMND_MQTTCLIENT D_JSON_MASK "\":\"%s\",\""
- D_CMND_MQTTCLIENT "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"),
- Settings.mqtt_user, Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client,
- mqtt_client, MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE);
-#else
Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS6_MQTT "\":{\"" D_CMND_MQTTHOST "\":\"%s\",\"" D_CMND_MQTTPORT "\":%d,\"" D_CMND_MQTTCLIENT D_JSON_MASK "\":\"%s\",\""
D_CMND_MQTTCLIENT "\":\"%s\",\"" D_CMND_MQTTUSER "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"),
- Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client,
- mqtt_client, Settings.mqtt_user, MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE);
-#endif
+ SettingsText(SET_MQTT_HOST), Settings.mqtt_port, SettingsText(SET_MQTT_CLIENT),
+ mqtt_client, SettingsText(SET_MQTT_USER), MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE);
MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "6"));
}
@@ -483,6 +482,15 @@ void CmndStatus(void)
MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "11"));
}
+ if (exception_flg) {
+ if ((0 == payload) || (12 == payload)) {
+ Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS12_STATUS "\":"));
+ CrashDump();
+ ResponseJsonEnd();
+ MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "12"));
+ }
+ }
+
#ifdef USE_SCRIPT_STATUS
if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">U",2,mqtt_data);
#endif
@@ -542,10 +550,10 @@ void CmndUpgrade(void)
void CmndOtaUrl(void)
{
- if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.ota_url))) {
- strlcpy(Settings.ota_url, (SC_DEFAULT == Shortcut()) ? OTA_URL : XdrvMailbox.data, sizeof(Settings.ota_url));
+ if (XdrvMailbox.data_len > 0) {
+ SettingsUpdateText(SET_OTAURL, (SC_DEFAULT == Shortcut()) ? OTA_URL : XdrvMailbox.data);
}
- ResponseCmndChar(Settings.ota_url);
+ ResponseCmndChar(SettingsText(SET_OTAURL));
}
void CmndSeriallog(void)
@@ -564,6 +572,9 @@ void CmndRestart(void)
restart_flag = 2;
ResponseCmndChar(D_JSON_RESTARTING);
break;
+ case -1:
+ CmndCrash(); // force a crash
+ break;
case 99:
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING));
EspRestart();
@@ -1082,6 +1093,48 @@ void CmndBaudrate(void)
ResponseCmndNumber(Settings.baudrate * 300);
}
+void CmndSerialConfig(void)
+{
+ // See TasmotaSerialConfig for possible options
+ // SerialConfig 0..23 where 3 equals 8N1
+ // SerialConfig 8N1
+
+ if (XdrvMailbox.data_len > 0) {
+ if (XdrvMailbox.data_len < 3) { // Use 0..23 as serial config option
+ if ((XdrvMailbox.payload >= TS_SERIAL_5N1) && (XdrvMailbox.payload <= TS_SERIAL_8O2)) {
+ SetSerialConfig(XdrvMailbox.payload);
+ }
+ }
+ else if ((XdrvMailbox.payload >= 5) && (XdrvMailbox.payload <= 8)) {
+ uint8_t serial_config = XdrvMailbox.payload -5; // Data bits 5, 6, 7 or 8, No parity and 1 stop bit
+
+ bool valid = true;
+ char parity = (XdrvMailbox.data[1] & 0xdf);
+ if ('E' == parity) {
+ serial_config += 0x08; // Even parity
+ }
+ else if ('O' == parity) {
+ serial_config += 0x10; // Odd parity
+ }
+ else if ('N' != parity) {
+ valid = false;
+ }
+
+ if ('2' == XdrvMailbox.data[2]) {
+ serial_config += 0x04; // Stop bits 2
+ }
+ else if ('1' != XdrvMailbox.data[2]) {
+ valid = false;
+ }
+
+ if (valid) {
+ SetSerialConfig(serial_config);
+ }
+ }
+ }
+ ResponseCmndChar(GetSerialConfig().c_str());
+}
+
void CmndSerialSend(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 5)) {
@@ -1133,10 +1186,10 @@ void CmndSyslog(void)
void CmndLoghost(void)
{
- if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.syslog_host))) {
- strlcpy(Settings.syslog_host, (SC_DEFAULT == Shortcut()) ? SYS_LOG_HOST : XdrvMailbox.data, sizeof(Settings.syslog_host));
+ if (XdrvMailbox.data_len > 0) {
+ SettingsUpdateText(SET_SYSLOG_HOST, (SC_DEFAULT == Shortcut()) ? SYS_LOG_HOST : XdrvMailbox.data);
}
- ResponseCmndChar(Settings.syslog_host);
+ ResponseCmndChar(SettingsText(SET_SYSLOG_HOST));
}
void CmndLogport(void)
@@ -1164,17 +1217,15 @@ void CmndIpAddress(void)
void CmndNtpServer(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) {
- if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.ntp_server[0]))) {
- strlcpy(Settings.ntp_server[XdrvMailbox.index -1],
- (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1==XdrvMailbox.index)?NTP_SERVER1:(2==XdrvMailbox.index)?NTP_SERVER2:NTP_SERVER3 : XdrvMailbox.data,
- sizeof(Settings.ntp_server[0]));
- for (uint32_t i = 0; i < strlen(Settings.ntp_server[XdrvMailbox.index -1]); i++) {
- if (Settings.ntp_server[XdrvMailbox.index -1][i] == ',') Settings.ntp_server[XdrvMailbox.index -1][i] = '.';
- }
+ uint32_t ntp_server = SET_NTPSERVER1 + XdrvMailbox.index -1;
+ if (XdrvMailbox.data_len > 0) {
+ SettingsUpdateText(ntp_server,
+ (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? NTP_SERVER1 : (2 == XdrvMailbox.index) ? NTP_SERVER2 : NTP_SERVER3 : XdrvMailbox.data);
+ SettingsUpdateText(ntp_server, ReplaceCommaWithDot(SettingsText(ntp_server)));
// restart_flag = 2; // Issue #3890
ntp_force_sync = true;
}
- ResponseCmndIdxChar(Settings.ntp_server[XdrvMailbox.index -1]);
+ ResponseCmndIdxChar(SettingsText(ntp_server));
}
}
@@ -1191,33 +1242,31 @@ void CmndAp(void)
}
restart_flag = 2;
}
- Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active]);
+ Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active));
}
void CmndSsid(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) {
- if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.sta_ssid[0]))) {
- strlcpy(Settings.sta_ssid[XdrvMailbox.index -1],
- (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_SSID1 : STA_SSID2 : XdrvMailbox.data,
- sizeof(Settings.sta_ssid[0]));
+ if (XdrvMailbox.data_len > 0) {
+ SettingsUpdateText(SET_STASSID1 + XdrvMailbox.index -1,
+ (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_SSID1 : STA_SSID2 : XdrvMailbox.data);
Settings.sta_active = XdrvMailbox.index -1;
restart_flag = 2;
}
- ResponseCmndIdxChar(Settings.sta_ssid[XdrvMailbox.index -1]);
+ ResponseCmndIdxChar(SettingsText(SET_STASSID1 + XdrvMailbox.index -1));
}
}
void CmndPassword(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) {
- if ((XdrvMailbox.data_len > 4 || SC_CLEAR == Shortcut() || SC_DEFAULT == Shortcut()) && (XdrvMailbox.data_len < sizeof(Settings.sta_pwd[0]))) {
- strlcpy(Settings.sta_pwd[XdrvMailbox.index -1],
- (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_PASS1 : STA_PASS2 : XdrvMailbox.data,
- sizeof(Settings.sta_pwd[0]));
+ if ((XdrvMailbox.data_len > 4) || (SC_CLEAR == Shortcut()) || (SC_DEFAULT == Shortcut())) {
+ SettingsUpdateText(SET_STAPWD1 + XdrvMailbox.index -1,
+ (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_PASS1 : STA_PASS2 : XdrvMailbox.data);
Settings.sta_active = XdrvMailbox.index -1;
restart_flag = 2;
- ResponseCmndIdxChar(Settings.sta_pwd[XdrvMailbox.index -1]);
+ ResponseCmndIdxChar(SettingsText(SET_STAPWD1 + XdrvMailbox.index -1));
} else {
Response_P(S_JSON_COMMAND_INDEX_ASTERISK, XdrvMailbox.command, XdrvMailbox.index);
}
@@ -1226,14 +1275,14 @@ void CmndPassword(void)
void CmndHostname(void)
{
- if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.hostname))) {
- strlcpy(Settings.hostname, (SC_DEFAULT == Shortcut()) ? WIFI_HOSTNAME : XdrvMailbox.data, sizeof(Settings.hostname));
- if (strstr(Settings.hostname, "%") != nullptr) {
- strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname));
+ if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) {
+ SettingsUpdateText(SET_HOSTNAME, (SC_DEFAULT == Shortcut()) ? WIFI_HOSTNAME : XdrvMailbox.data);
+ if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) {
+ SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME);
}
restart_flag = 2;
}
- ResponseCmndChar(Settings.hostname);
+ ResponseCmndChar(SettingsText(SET_HOSTNAME));
}
void CmndWifiConfig(void)
@@ -1255,16 +1304,16 @@ void CmndWifiConfig(void)
void CmndFriendlyname(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_FRIENDLYNAMES)) {
- if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.friendlyname[0]))) {
+ if (XdrvMailbox.data_len > 0) {
char stemp1[TOPSZ];
if (1 == XdrvMailbox.index) {
snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME));
} else {
snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME "%d"), XdrvMailbox.index);
}
- strlcpy(Settings.friendlyname[XdrvMailbox.index -1], (SC_DEFAULT == Shortcut()) ? stemp1 : XdrvMailbox.data, sizeof(Settings.friendlyname[XdrvMailbox.index -1]));
+ SettingsUpdateText(SET_FRIENDLYNAME1 + XdrvMailbox.index -1, (SC_DEFAULT == Shortcut()) ? stemp1 : XdrvMailbox.data);
}
- ResponseCmndIdxChar(Settings.friendlyname[XdrvMailbox.index -1]);
+ ResponseCmndIdxChar(SettingsText(SET_FRIENDLYNAME1 + XdrvMailbox.index -1));
}
}
diff --git a/tasmota/support_crash_recorder.ino b/tasmota/support_crash_recorder.ino
new file mode 100644
index 000000000..87009bbc5
--- /dev/null
+++ b/tasmota/support_crash_recorder.ino
@@ -0,0 +1,89 @@
+/*
+ support_crash_recorder.ino - record the call stack in RTC in case of crash
+
+ Copyright (C) 2019 Stephan Hadinger, Theo Arends,
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+const uint32_t crash_magic = 0x53415400; // Stack trace magic number (TASx)
+const uint32_t crash_rtc_offset = 32; // Offset in RTC memory skipping OTA used block
+const uint32_t crash_dump_max_len = 31; // Dump only 31 call addresses to satisfy max JSON length of about 600 characters
+
+/**
+ * Save crash information in RTC memory
+ * This function is called automatically if ESP8266 suffers an exception
+ * It should be kept quick / consise to be able to execute before hardware wdt may kick in
+ */
+extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end )
+{
+ uint32_t addr_written = 0; // how many addresses have we already written in RTC
+ uint32_t value; // 4 bytes buffer to write to RTC
+
+ for (uint32_t i = stack; i < stack_end; i += 4) {
+ value = *((uint32_t*) i); // load value from stack
+ if ((value >= 0x40000000) && (value < 0x40300000)) { // keep only addresses in code area
+ ESP.rtcUserMemoryWrite(crash_rtc_offset + addr_written, (uint32_t*)&value, sizeof(value));
+ addr_written++;
+ if (addr_written >= crash_dump_max_len) { break; } // we store only 31 addresses
+ }
+ }
+ value = crash_magic + addr_written;
+ ESP.rtcUserMemoryWrite(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value));
+}
+
+// Generate a crash to test the crash recorder
+void CmndCrash(void)
+{
+ volatile uint32_t dummy;
+ dummy = *((uint32_t*) 0x00000000);
+}
+
+// Clear the RTC dump counter when we do a normal reboot, this avoids garbage data to stay in RTC
+void CrashDumpClear(void)
+{
+ uint32_t value = 0;
+ ESP.rtcUserMemoryWrite(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value));
+}
+
+/*********************************************************************************************\
+ * CmndCrashDump - dump the crash history - called by `Status 12`
+\*********************************************************************************************/
+
+void CrashDump(void)
+{
+ ResponseAppend_P(PSTR("{\"Exception\":%d,\"Reason\":\"%s\",\"EPC\":[\"%08x\",\"%08x\",\"%08x\"],\"EXCVADDR\":\"%08x\",\"DEPC\":\"%08x\""),
+ resetInfo.exccause, // Exception Cause
+ GetResetReason().c_str(), // Reset Reason
+ resetInfo.epc1, // Exception Progam Counter
+ resetInfo.epc2, // Exception Progam Counter - High-Priority Interrupt 1
+ resetInfo.epc3, // Exception Progam Counter - High-Priority Interrupt 2
+ resetInfo.excvaddr, // Exception Virtual Address Register - Virtual address that caused last fetch, load, or store exception
+ resetInfo.depc); // Double Exception Program Counter
+
+ uint32_t value;
+ ESP.rtcUserMemoryRead(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value));
+ if (crash_magic == (value & 0xFFFFFF00)) {
+ ResponseAppend_P(PSTR(",\"CallChain\":["));
+ uint32_t count = value & 0x3F;
+ for (uint32_t i = 0; i < count; i++) {
+ ESP.rtcUserMemoryRead(crash_rtc_offset +i, (uint32_t*)&value, sizeof(value));
+ if (i > 0) { ResponseAppend_P(PSTR(",")); }
+ ResponseAppend_P(PSTR("\"%08x\""), value);
+ }
+ ResponseAppend_P(PSTR("]"));
+ }
+
+ ResponseJsonEnd();
+}
diff --git a/tasmota/support_float.ino b/tasmota/support_float.ino
index 21ec2f47d..d08fc13f9 100644
--- a/tasmota/support_float.ino
+++ b/tasmota/support_float.ino
@@ -172,6 +172,7 @@ double const f_sixthpi = f_pi / 6.0; // f_pi/6.0, used in
double const f_tansixthpi = tan(f_sixthpi); // tan(f_pi/6), used in atan routines
double const f_twelfthpi = f_pi / 12.0; // f_pi/12.0, used in atan routines
double const f_tantwelfthpi = tan(f_twelfthpi); // tan(f_pi/12), used in atan routines
+float const f_180pi = 180 / f_pi; // 180 / pi for angles in degrees
// *******************************************************************
// ***
diff --git a/tasmota/support_rtc.ino b/tasmota/support_rtc.ino
index ffb7239a6..ffaf171a3 100644
--- a/tasmota/support_rtc.ino
+++ b/tasmota/support_rtc.ino
@@ -379,7 +379,9 @@ void RtcSecond(void)
Rtc.ntp_sync_minute = 1; // If sync prepare for a new cycle
}
uint8_t offset = (uptime < 30) ? RtcTime.second : (((ESP.getChipId() & 0xF) * 3) + 3) ; // First try ASAP to sync. If fails try once every 60 seconds based on chip id
- if ( (((offset == RtcTime.second) && ( (RtcTime.year < 2016) || (Rtc.ntp_sync_minute == uptime_minute))) || ntp_force_sync ) ) {
+ if ( (((offset == RtcTime.second) && ( (RtcTime.year < 2016) || // Never synced
+ (Rtc.ntp_sync_minute == uptime_minute))) || // Re-sync every hour
+ ntp_force_sync ) ) { // Forced sync
Rtc.ntp_time = sntp_get_current_timestamp();
if (Rtc.ntp_time > START_VALID_TIME) { // Fix NTP bug in core 2.4.1/SDK 2.2.1 (returns Thu Jan 01 08:00:10 1970 after power on)
ntp_force_sync = false;
@@ -467,9 +469,9 @@ void RtcSetTime(uint32_t epoch)
void RtcInit(void)
{
- sntp_setservername(0, Settings.ntp_server[0]);
- sntp_setservername(1, Settings.ntp_server[1]);
- sntp_setservername(2, Settings.ntp_server[2]);
+ sntp_setservername(0, SettingsText(SET_NTPSERVER1));
+ sntp_setservername(1, SettingsText(SET_NTPSERVER2));
+ sntp_setservername(2, SettingsText(SET_NTPSERVER3));
sntp_stop();
sntp_set_timezone(0); // UTC time
sntp_init();
diff --git a/tasmota/support_statistics.ino b/tasmota/support_statistics.ino
new file mode 100644
index 000000000..b8f65bd20
--- /dev/null
+++ b/tasmota/support_statistics.ino
@@ -0,0 +1,76 @@
+/*
+ support_statistics.ino - gather statistics for Tasmota
+
+ Copyright (C) 2019 Theo Arends
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#define USE_STATS_CODE
+
+#ifdef USE_STATS_CODE
+/*********************************************************************************************\
+ * Gather statistics
+\*********************************************************************************************/
+
+String GetStatistics(void)
+{
+ char data[40];
+
+ if (Settings.version < 0x08000000) {
+ uint32_t str_len = 0;
+ for (uint32_t i = 0; i < 2; i++) {
+ str_len += strlen(Settings.sta_ssid[i]);
+ str_len += strlen(Settings.sta_pwd[i]);
+ }
+ for (uint32_t i = 0; i < 3; i++) {
+ str_len += strlen(Settings.mqtt_prefix[i]);
+ str_len += strlen(Settings.ntp_server[i]);
+ }
+ for (uint32_t i = 0; i < 4; i++) {
+ str_len += strlen(Settings.state_text[i]);
+ str_len += strlen(Settings.friendlyname[i]);
+ }
+ for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) {
+ str_len += strlen(Settings.mems[i]);
+ }
+ str_len += strlen(Settings.ota_url);
+ str_len += strlen(Settings.hostname);
+ str_len += strlen(Settings.syslog_host);
+ str_len += strlen(Settings.mqtt_host);
+ str_len += strlen(Settings.mqtt_client);
+ str_len += strlen(Settings.mqtt_user);
+ str_len += strlen(Settings.mqtt_pwd);
+ str_len += strlen(Settings.mqtt_topic);
+ str_len += strlen(Settings.button_topic);
+ str_len += strlen(Settings.switch_topic);
+ str_len += strlen(Settings.mqtt_grptopic);
+ str_len += strlen(Settings.web_password);
+ str_len += strlen(Settings.mqtt_fulltopic);
+ str_len += strlen(Settings.cors_domain);
+ snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/1151\""), 37 + str_len); // Char Usage Ratio
+ } else {
+ snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/%d\""), GetSettingsTextLen(), settings_text_size); // Char Usage Ratio
+ }
+ return String(data);
+}
+
+#else
+
+String GetStatistics(void)
+{
+ return String("");
+}
+
+#endif // USE_STATS_CODE
\ No newline at end of file
diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino
index e7099affd..ff2b6f40a 100644
--- a/tasmota/support_tasmota.ino
+++ b/tasmota/support_tasmota.ino
@@ -60,15 +60,16 @@ char* Format(char* output, const char* input, int size)
char* GetOtaUrl(char *otaurl, size_t otaurl_size)
{
- if (strstr(Settings.ota_url, "%04d") != nullptr) { // OTA url contains placeholder for chip ID
- snprintf(otaurl, otaurl_size, Settings.ota_url, ESP.getChipId() & 0x1fff);
+ if (strstr(SettingsText(SET_OTAURL), "%04d") != nullptr) { // OTA url contains placeholder for chip ID
+ snprintf(otaurl, otaurl_size, SettingsText(SET_OTAURL), ESP.getChipId() & 0x1fff);
}
- else if (strstr(Settings.ota_url, "%d") != nullptr) { // OTA url contains placeholder for chip ID
- snprintf_P(otaurl, otaurl_size, Settings.ota_url, ESP.getChipId());
+ else if (strstr(SettingsText(SET_OTAURL), "%d") != nullptr) { // OTA url contains placeholder for chip ID
+ snprintf_P(otaurl, otaurl_size, SettingsText(SET_OTAURL), ESP.getChipId());
}
else {
- strlcpy(otaurl, Settings.ota_url, otaurl_size);
+ strlcpy(otaurl, SettingsText(SET_OTAURL), otaurl_size);
}
+
return otaurl;
}
@@ -101,17 +102,19 @@ char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopi
fulltopic += topic; // cmnd/
}
} else {
- fulltopic = Settings.mqtt_fulltopic;
+ fulltopic = SettingsText(SET_MQTT_FULLTOPIC);
if ((0 == prefix) && (-1 == fulltopic.indexOf(FPSTR(MQTT_TOKEN_PREFIX)))) {
fulltopic += F("/");
fulltopic += FPSTR(MQTT_TOKEN_PREFIX); // Need prefix for commands to handle mqtt topic loops
}
for (uint32_t i = 0; i < 3; i++) {
- if ('\0' == Settings.mqtt_prefix[i][0]) {
- GetTextIndexed(Settings.mqtt_prefix[i], sizeof(Settings.mqtt_prefix[i]), i, kPrefixes);
+ if ('\0' == SettingsText(SET_MQTTPREFIX1 + i)) {
+ char temp[TOPSZ];
+ SettingsUpdateText(SET_MQTTPREFIX1 + i, GetTextIndexed(temp, sizeof(temp), i, kPrefixes));
}
}
- fulltopic.replace(FPSTR(MQTT_TOKEN_PREFIX), Settings.mqtt_prefix[prefix]);
+ fulltopic.replace(FPSTR(MQTT_TOKEN_PREFIX), SettingsText(SET_MQTTPREFIX1 + prefix));
+
fulltopic.replace(FPSTR(MQTT_TOKEN_TOPIC), topic);
fulltopic.replace(F("%hostname%"), my_hostname);
String token_id = WiFi.macAddress();
@@ -131,7 +134,7 @@ char* GetGroupTopic_P(char *stopic, const char* subtopic)
{
// SetOption75 0: %prefix%/nothing/%topic% = cmnd/nothing//#
// SetOption75 1: cmnd/
- return GetTopic_P(stopic, (Settings.flag3.grouptopic_mode) ? CMND +8 : CMND, Settings.mqtt_grptopic, subtopic); // SetOption75 - GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1)
+ return GetTopic_P(stopic, (Settings.flag3.grouptopic_mode) ? CMND +8 : CMND, SettingsText(SET_MQTT_GRP_TOPIC), subtopic); // SetOption75 - GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1)
}
char* GetFallbackTopic_P(char *stopic, const char* subtopic)
@@ -144,7 +147,7 @@ char* GetStateText(uint32_t state)
if (state > 3) {
state = 1;
}
- return Settings.state_text[state];
+ return SettingsText(SET_STATE_TXT1 + state);
}
/********************************************************************************************/
@@ -358,10 +361,10 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state)
char stopic[TOPSZ];
char scommand[CMDSZ];
- char key_topic[sizeof(Settings.button_topic)];
+ char key_topic[TOPSZ];
bool result = false;
- char *tmp = (key) ? Settings.switch_topic : Settings.button_topic;
+ char *tmp = (key) ? SettingsText(SET_MQTT_SWITCH_TOPIC) : SettingsText(SET_MQTT_BUTTON_TOPIC);
Format(key_topic, tmp, sizeof(key_topic));
if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) { // SetOption3 - Enable MQTT
if (!key && (device > devices_present)) {
@@ -374,7 +377,7 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state)
} else {
if ((Settings.flag3.button_switch_force_local || // SetOption61 - Force local operation when button/switch topic is set
!strcmp(mqtt_topic, key_topic) ||
- !strcmp(Settings.mqtt_grptopic, key_topic)) &&
+ !strcmp(SettingsText(SET_MQTT_GRP_TOPIC), key_topic)) &&
(POWER_TOGGLE == state)) {
state = ~(power >> (device -1)) &1; // POWER_OFF or POWER_ON
}
@@ -583,8 +586,9 @@ void MqttShowState(void)
MqttShowPWMState();
}
- 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_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}}"),
- Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI()), WifiLinkCount(), WifiDowntime().c_str());
+ 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());
}
void MqttPublishTeleState(void)
@@ -592,7 +596,7 @@ void MqttPublishTeleState(void)
mqtt_data[0] = '\0';
MqttShowState();
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN);
-#ifdef USE_SCRIPT
+#if defined(USE_RULES) || defined(USE_SCRIPT)
RulesTeleperiod(); // Allow rule based HA messages
#endif // USE_SCRIPT
}
@@ -812,7 +816,6 @@ void Every250mSeconds(void)
if (ota_state_flag && BACKLOG_EMPTY) {
ota_state_flag--;
if (2 == ota_state_flag) {
- ota_url = Settings.ota_url;
RtcSettings.ota_loader = 0; // Try requested image first
ota_retry_counter = OTA_ATTEMPTS;
ESPhttpUpdate.rebootOnUpdate(false);
@@ -838,7 +841,7 @@ void Every250mSeconds(void)
if (!pch) { pch = ech; }
if (pch) {
mqtt_data[pch - mqtt_data] = '\0';
- char *ech = strrchr(Settings.ota_url, '.'); // Change from filename.bin into filename-minimal.bin
+ char *ech = strrchr(SettingsText(SET_OTAURL), '.'); // Change from filename.bin into filename-minimal.bin
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s-" D_JSON_MINIMAL "%s"), mqtt_data, ech); // Minimal filename must be filename-minimal
}
}
@@ -902,26 +905,45 @@ void Every250mSeconds(void)
}
if (restart_flag && BACKLOG_EMPTY) {
if ((214 == restart_flag) || (215 == restart_flag) || (216 == restart_flag)) {
- char storage_wifi[sizeof(Settings.sta_ssid) +
- sizeof(Settings.sta_pwd)];
- char storage_mqtt[sizeof(Settings.mqtt_host) +
- sizeof(Settings.mqtt_port) +
- sizeof(Settings.mqtt_client) +
- sizeof(Settings.mqtt_user) +
- sizeof(Settings.mqtt_pwd) +
- sizeof(Settings.mqtt_topic)];
- memcpy(storage_wifi, Settings.sta_ssid, sizeof(storage_wifi)); // Backup current SSIDs and Passwords
- if (216 == restart_flag) {
- memcpy(storage_mqtt, Settings.mqtt_host, sizeof(storage_mqtt)); // Backup mqtt host, port, client, username and password
- }
+ // Backup current SSIDs and Passwords
+ char storage_ssid1[strlen(SettingsText(SET_STASSID1)) +1];
+ strncpy(storage_ssid1, SettingsText(SET_STASSID1), sizeof(storage_ssid1));
+ char storage_ssid2[strlen(SettingsText(SET_STASSID2)) +1];
+ strncpy(storage_ssid2, SettingsText(SET_STASSID2), sizeof(storage_ssid2));
+ char storage_pass1[strlen(SettingsText(SET_STAPWD1)) +1];
+ strncpy(storage_pass1, SettingsText(SET_STAPWD1), sizeof(storage_pass1));
+ char storage_pass2[strlen(SettingsText(SET_STAPWD2)) +1];
+ strncpy(storage_pass2, SettingsText(SET_STAPWD2), sizeof(storage_pass2));
+
+ char storage_mqtthost[strlen(SettingsText(SET_MQTT_HOST)) +1];
+ strncpy(storage_mqtthost, SettingsText(SET_MQTT_HOST), sizeof(storage_mqtthost));
+ char storage_mqttuser[strlen(SettingsText(SET_MQTT_USER)) +1];
+ strncpy(storage_mqttuser, SettingsText(SET_MQTT_USER), sizeof(storage_mqttuser));
+ char storage_mqttpwd[strlen(SettingsText(SET_MQTT_PWD)) +1];
+ strncpy(storage_mqttpwd, SettingsText(SET_MQTT_PWD), sizeof(storage_mqttpwd));
+ char storage_mqtttopic[strlen(SettingsText(SET_MQTT_TOPIC)) +1];
+ strncpy(storage_mqtttopic, SettingsText(SET_MQTT_TOPIC), sizeof(storage_mqtttopic));
+ uint16_t mqtt_port = Settings.mqtt_port;
+
+// if (216 == restart_flag) {
+ // Backup mqtt host, port, client, username and password
+// }
if ((215 == restart_flag) || (216 == restart_flag)) {
SettingsErase(0); // Erase all flash from program end to end of physical flash
}
SettingsDefault();
- memcpy(Settings.sta_ssid, storage_wifi, sizeof(storage_wifi)); // Restore current SSIDs and Passwords
+ // Restore current SSIDs and Passwords
+ SettingsUpdateText(SET_STASSID1, storage_ssid1);
+ SettingsUpdateText(SET_STASSID2, storage_ssid2);
+ SettingsUpdateText(SET_STAPWD1, storage_pass1);
+ SettingsUpdateText(SET_STAPWD2, storage_pass2);
if (216 == restart_flag) {
- memcpy(Settings.mqtt_host, storage_mqtt, sizeof(storage_mqtt)); // Restore the mqtt host, port, client, username and password
- strlcpy(Settings.mqtt_client, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client)); // Set client to default
+ // Restore the mqtt host, port, client, username and password
+ SettingsUpdateText(SET_MQTT_HOST, storage_mqtthost);
+ SettingsUpdateText(SET_MQTT_USER, storage_mqttuser);
+ SettingsUpdateText(SET_MQTT_PWD, storage_mqttpwd);
+ SettingsUpdateText(SET_MQTT_TOPIC, storage_mqtttopic);
+ Settings.mqtt_port = mqtt_port;
}
restart_flag = 2;
}
@@ -972,7 +994,7 @@ void ArduinoOTAInit(void)
{
ArduinoOTA.setPort(8266);
ArduinoOTA.setHostname(my_hostname);
- if (Settings.web_password[0] !=0) { ArduinoOTA.setPassword(Settings.web_password); }
+ if (strlen(SettingsText(SET_WEBPWD))) { ArduinoOTA.setPassword(SettingsText(SET_WEBPWD)); }
ArduinoOTA.onStart([]()
{
@@ -1285,15 +1307,19 @@ void GpioInit(void)
}
#endif // USE_SONOFF_SC
- if (!light_type) {
- for (uint32_t i = 0; i < MAX_PWMS; i++) { // Basic PWM control only
- if (pin[GPIO_PWM1 +i] < 99) {
+ for (uint32_t i = 0; i < MAX_PWMS; i++) { // Basic PWM control only
+ if (pin[GPIO_PWM1 +i] < 99) {
+ pinMode(pin[GPIO_PWM1 +i], OUTPUT);
+ if (light_type) {
+ // force PWM GPIOs to low or high mode, see #7165
+ analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range : 0);
+ } else {
pwm_present = true;
- pinMode(pin[GPIO_PWM1 +i], OUTPUT);
analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - Settings.pwm_value[i] : Settings.pwm_value[i]);
}
}
}
+
for (uint32_t i = 0; i < MAX_RELAYS; i++) {
if (pin[GPIO_REL1 +i] < 99) {
pinMode(pin[GPIO_REL1 +i], OUTPUT);
diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino
index 49faa0663..86cc81dd8 100644
--- a/tasmota/support_wifi.ino
+++ b/tasmota/support_wifi.ino
@@ -191,18 +191,20 @@ void WifiBegin(uint8_t flag, uint8_t channel)
case 2: // Toggle
Settings.sta_active ^= 1;
} // 3: Current AP
- if ('\0' == Settings.sta_ssid[Settings.sta_active][0]) { Settings.sta_active ^= 1; } // Skip empty SSID
+ if ('\0' == SettingsText(SET_STASSID1 + Settings.sta_active)) {
+ Settings.sta_active ^= 1; // Skip empty SSID
+ }
if (Settings.ip_address[0]) {
WiFi.config(Settings.ip_address[0], Settings.ip_address[1], Settings.ip_address[2], Settings.ip_address[3]); // Set static IP
}
WiFi.hostname(my_hostname);
if (channel) {
- WiFi.begin(Settings.sta_ssid[Settings.sta_active], Settings.sta_pwd[Settings.sta_active], channel, Wifi.bssid);
+ WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active), channel, Wifi.bssid);
} else {
- WiFi.begin(Settings.sta_ssid[Settings.sta_active], Settings.sta_pwd[Settings.sta_active]);
+ WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active));
}
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s " D_IN_MODE " 11%c " D_AS " %s..."),
- Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname);
+ Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname);
#if LWIP_IPV6
for (bool configured = false; !configured;) {
@@ -278,10 +280,10 @@ void WifiBeginAfterScan(void)
bool known = false;
uint32_t j;
for (j = 0; j < 2; j++) {
- if (ssid_scan == Settings.sta_ssid[j]) { // SSID match
+ if (ssid_scan == SettingsText(SET_STASSID1 + j)) { // SSID match
known = true;
if (rssi_scan > best_network_db) { // Best network
- if (sec_scan == ENC_TYPE_NONE || Settings.sta_pwd[j]) { // Check for passphrase if not open wlan
+ if (sec_scan == ENC_TYPE_NONE || SettingsText(SET_STAPWD1 + j)) { // Check for passphrase if not open wlan
best_network_db = (int8_t)rssi_scan;
channel = chan_scan;
ap = j; // AP1 or AP2
@@ -352,6 +354,14 @@ bool WifiCheckIPv6(void)
return ipv6_global;
}
+String WifiGetIPv6(void)
+{
+ for (auto a : addrList) {
+ if(!a.isLocal() && a.isV6()) return a.toString();
+ }
+ return "";
+}
+
bool WifiCheckIPAddrStatus(void) // Return false for 169.254.x.x or fe80::/64
{
bool ip_global=false;
@@ -426,7 +436,7 @@ void WifiCheckIp(void)
if (!Wifi.retry || ((Wifi.retry_init / 2) == Wifi.retry)) {
AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_TIMEOUT));
} else {
- if (('\0' == Settings.sta_ssid[0][0]) && ('\0' == Settings.sta_ssid[1][0])) {
+ if (('\0' == SettingsText(SET_STASSID1)) && ('\0' == SettingsText(SET_STASSID2))) {
wifi_config_tool = WIFI_MANAGER; // Skip empty SSIDs and start Wifi config tool
Wifi.retry = 0;
} else {
@@ -472,13 +482,13 @@ void WifiCheck(uint8_t param)
if (Wifi.config_counter) {
if (!Wifi.config_counter) {
if (strlen(WiFi.SSID().c_str())) {
- strlcpy(Settings.sta_ssid[0], WiFi.SSID().c_str(), sizeof(Settings.sta_ssid[0]));
+ SettingsUpdateText(SET_STASSID1, WiFi.SSID().c_str());
}
if (strlen(WiFi.psk().c_str())) {
- strlcpy(Settings.sta_pwd[0], WiFi.psk().c_str(), sizeof(Settings.sta_pwd[0]));
+ SettingsUpdateText(SET_STAPWD1, WiFi.psk().c_str());
}
Settings.sta_active = 0;
- AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_WCFG_2_WIFIMANAGER D_CMND_SSID "1 %s"), Settings.sta_ssid[0]);
+ AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_WCFG_2_WIFIMANAGER D_CMND_SSID "1 %s"), SettingsText(SET_STASSID1));
}
}
if (!Wifi.config_counter) {
@@ -617,6 +627,7 @@ void WifiShutdown(void)
void EspRestart(void)
{
WifiShutdown();
+ CrashDumpClear(); // Clear the stack dump in RTC
// ESP.restart(); // This results in exception 3 on restarts on core 2.3.0
ESP.reset();
}
diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h
index cefef3a06..1f676acd4 100644
--- a/tasmota/tasmota.h
+++ b/tasmota/tasmota.h
@@ -131,7 +131,7 @@ const uint32_t SOFT_BAUDRATE = 9600; // Default software serial baudrate
const uint32_t APP_BAUDRATE = 115200; // Default serial baudrate
const uint32_t SERIAL_POLLING = 100; // Serial receive polling in ms
const uint32_t ZIGBEE_POLLING = 100; // Serial receive polling in ms
-const uint8_t MAX_STATUS = 11; // Max number of status lines
+const uint8_t MAX_STATUS = 12; // Max number of status lines
const uint32_t START_VALID_TIME = 1451602800; // Time is synced and after 2016-01-01
@@ -272,6 +272,30 @@ enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_PIN_STATE, FUNC_MODULE_INIT, FU
enum AddressConfigSteps { ADDR_IDLE, ADDR_RECEIVE, ADDR_SEND };
+enum SettingsTextIndex { SET_OTAURL,
+ SET_MQTTPREFIX1, SET_MQTTPREFIX2, SET_MQTTPREFIX3,
+ SET_STASSID1, SET_STASSID2,
+ SET_STAPWD1, SET_STAPWD2,
+ SET_HOSTNAME, SET_SYSLOG_HOST,
+ SET_WEBPWD,
+ SET_MQTT_HOST, SET_MQTT_CLIENT,
+ SET_MQTT_USER, SET_MQTT_PWD,
+ SET_MQTT_FULLTOPIC, SET_MQTT_TOPIC,
+ SET_MQTT_BUTTON_TOPIC, SET_MQTT_SWITCH_TOPIC, SET_MQTT_GRP_TOPIC,
+ SET_STATE_TXT1, SET_STATE_TXT2, SET_STATE_TXT3, SET_STATE_TXT4,
+ SET_NTPSERVER1, SET_NTPSERVER2, SET_NTPSERVER3,
+ SET_MEM1, SET_MEM2, SET_MEM3, SET_MEM4, SET_MEM5,
+ SET_CORS,
+ SET_FRIENDLYNAME1, SET_FRIENDLYNAME2, SET_FRIENDLYNAME3, SET_FRIENDLYNAME4,
+
+// SET_FRIENDLYNAME5, SET_FRIENDLYNAME6, SET_FRIENDLYNAME7, SET_FRIENDLYNAME8, // Future extension
+// SET_BUTTON1, SET_BUTTON2, SET_BUTTON3, SET_BUTTON4, // Future extension
+// SET_BUTTON5, SET_BUTTON6, SET_BUTTON7, SET_BUTTON8, // Future extension
+// SET_BUTTON9, SET_BUTTON10, SET_BUTTON11, SET_BUTTON12, // Future extension
+// SET_BUTTON13, SET_BUTTON14, SET_BUTTON15, SET_BUTTON16, // Future extension
+
+ SET_MAX };
+
enum CommandSource { SRC_IGNORE, SRC_MQTT, SRC_RESTART, SRC_BUTTON, SRC_SWITCH, SRC_BACKLOG, SRC_SERIAL, SRC_WEBGUI, SRC_WEBCOMMAND, SRC_WEBCONSOLE, SRC_PULSETIMER,
SRC_TIMER, SRC_RULE, SRC_MAXPOWER, SRC_MAXENERGY, SRC_OVERTEMP, SRC_LIGHT, SRC_KNX, SRC_DISPLAY, SRC_WEMO, SRC_HUE, SRC_RETRY, SRC_REMOTE, SRC_SHUTTER,
SRC_MAX };
diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino
index e10dfdb63..3b9e64a25 100644
--- a/tasmota/tasmota.ino
+++ b/tasmota/tasmota.ino
@@ -74,8 +74,6 @@ const char kCodeImage[] PROGMEM = "tasmota|minimal|sensors|knx|basic|display|ir"
* Global variables
\*********************************************************************************************/
-SerialConfig serial_config = SERIAL_8N1; // Serial interface configuration 8 data bits, No parity, 1 stop bit
-
WiFiUDP PortUdp; // UDP Syslog and Alexa
unsigned long feature_drv1; // Compiled driver feature map
@@ -112,7 +110,6 @@ uint32_t web_log_index = 1; // Index in Web log buffer (should n
float global_temperature = 9999; // Provide a global temperature to be used by some sensors
float global_humidity = 0; // Provide a global humidity to be used by some sensors
float global_pressure = 0; // Provide a global pressure to be used by some sensors
-char *ota_url; // OTA url string pointer
uint16_t tele_period = 9999; // Tele period timer
uint16_t mqtt_cmnd_publish = 0; // ignore flag for publish command
uint16_t blink_counter = 0; // Number of blink cycles
@@ -267,13 +264,13 @@ void setup(void)
}
}
- Format(mqtt_client, Settings.mqtt_client, sizeof(mqtt_client));
- Format(mqtt_topic, Settings.mqtt_topic, sizeof(mqtt_topic));
- if (strstr(Settings.hostname, "%") != nullptr) {
- strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname));
- snprintf_P(my_hostname, sizeof(my_hostname)-1, Settings.hostname, mqtt_topic, ESP.getChipId() & 0x1FFF);
+ Format(mqtt_client, SettingsText(SET_MQTT_CLIENT), sizeof(mqtt_client));
+ Format(mqtt_topic, SettingsText(SET_MQTT_TOPIC), sizeof(mqtt_topic));
+ if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) {
+ SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME);
+ snprintf_P(my_hostname, sizeof(my_hostname)-1, SettingsText(SET_HOSTNAME), mqtt_topic, ESP.getChipId() & 0x1FFF);
} else {
- snprintf_P(my_hostname, sizeof(my_hostname)-1, Settings.hostname);
+ snprintf_P(my_hostname, sizeof(my_hostname)-1, SettingsText(SET_HOSTNAME));
}
GetEspHardwareType();
@@ -332,7 +329,7 @@ void setup(void)
}
blink_powersave = power;
- AddLog_P2(LOG_LEVEL_INFO, PSTR(D_PROJECT " %s %s " D_VERSION " %s%s-" ARDUINO_ESP8266_RELEASE), PROJECT, Settings.friendlyname[0], my_version, my_image);
+ AddLog_P2(LOG_LEVEL_INFO, PSTR(D_PROJECT " %s %s " D_VERSION " %s%s-" ARDUINO_ESP8266_RELEASE), PROJECT, SettingsText(SET_FRIENDLYNAME1), my_version, my_image);
#ifdef FIRMWARE_MINIMAL
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_WARNING_MINIMAL_VERSION));
#endif // FIRMWARE_MINIMAL
@@ -351,15 +348,18 @@ void BacklogLoop(void)
{
if (TimeReached(backlog_delay)) {
if (!BACKLOG_EMPTY && !backlog_mutex) {
- backlog_mutex = true;
#ifdef SUPPORT_IF_STATEMENT
- ExecuteCommand((char*)backlog.shift().c_str(), SRC_BACKLOG);
+ backlog_mutex = true;
+ String cmd = backlog.shift();
+ backlog_mutex = false;
+ ExecuteCommand((char*)cmd.c_str(), SRC_BACKLOG);
#else
+ backlog_mutex = true;
ExecuteCommand((char*)backlog[backlog_pointer].c_str(), SRC_BACKLOG);
backlog_pointer++;
if (backlog_pointer >= MAX_BACKLOG) { backlog_pointer = 0; }
-#endif
backlog_mutex = false;
+#endif
}
}
}
diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h
index be3b503f0..cc47e3fc1 100644
--- a/tasmota/tasmota_post.h
+++ b/tasmota/tasmota_post.h
@@ -512,7 +512,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c
#undef USE_ARDUINO_OTA // Disable support for Arduino OTA
#undef USE_DOMOTICZ // Disable Domoticz
#undef USE_HOME_ASSISTANT // Disable Home Assistant
-#undef USE_MQTT_TLS // Disable TLS support won't work as the MQTTHost is not set
+//#undef USE_MQTT_TLS // Disable TLS support won't work as the MQTTHost is not set
#undef USE_KNX // Disable KNX IP Protocol Support
//#undef USE_WEBSERVER // Disable Webserver
#undef USE_WEBSEND_RESPONSE // Disable command WebSend response message (+1k code)
diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h
index f8eee8abd..8fe799b5b 100644
--- a/tasmota/tasmota_version.h
+++ b/tasmota/tasmota_version.h
@@ -20,6 +20,6 @@
#ifndef _TASMOTA_VERSION_H_
#define _TASMOTA_VERSION_H_
-const uint32_t VERSION = 0x07010200;
+const uint32_t VERSION = 0x07020000;
#endif // _TASMOTA_VERSION_H_
diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino
index 48e2cd26a..9c8131ad3 100644
--- a/tasmota/xdrv_01_webserver.ino
+++ b/tasmota/xdrv_01_webserver.ino
@@ -414,7 +414,8 @@ const char HTTP_FORM_WIFI[] PROGMEM =
"" D_AP1_PASSWORD "
"
"" D_AP2_SSID " (" STA_SSID2 ")
"
"" D_AP2_PASSWORD "
"
- "" D_HOSTNAME " (%s)
";
+ "" D_HOSTNAME " (%s)
"
+ "" D_CORS_DOMAIN "
";
const char HTTP_FORM_LOG1[] PROGMEM =
"
"));
}
- WSContentSend_P(HTTP_FORM_LOG2, Settings.syslog_host, Settings.syslog_port, Settings.tele_period);
+ WSContentSend_P(HTTP_FORM_LOG2, SettingsText(SET_SYSLOG_HOST), Settings.syslog_port, Settings.tele_period);
WSContentSend_P(HTTP_FORM_END);
WSContentSpaceButton(BUTTON_CONFIGURATION);
WSContentStop();
@@ -1731,7 +1756,7 @@ void HandleLoggingConfiguration(void)
void LoggingSaveSettings(void)
{
- char tmp[sizeof(Settings.syslog_host)]; // Max length is currently 33
+ char tmp[100]; // Max length is currently 33
WebGetArg("l0", tmp, sizeof(tmp));
SetSeriallog((!strlen(tmp)) ? SERIAL_LOG_LEVEL : atoi(tmp));
@@ -1742,7 +1767,7 @@ void LoggingSaveSettings(void)
WebGetArg("l3", tmp, sizeof(tmp));
SetSyslog((!strlen(tmp)) ? SYS_LOG_LEVEL : atoi(tmp));
WebGetArg("lh", tmp, sizeof(tmp));
- strlcpy(Settings.syslog_host, (!strlen(tmp)) ? SYS_LOG_HOST : tmp, sizeof(Settings.syslog_host));
+ SettingsUpdateText(SET_SYSLOG_HOST, (!strlen(tmp)) ? SYS_LOG_HOST : tmp);
WebGetArg("lp", tmp, sizeof(tmp));
Settings.syslog_port = (!strlen(tmp)) ? SYS_LOG_PORT : atoi(tmp);
WebGetArg("lt", tmp, sizeof(tmp));
@@ -1751,7 +1776,7 @@ void LoggingSaveSettings(void)
Settings.tele_period = 10; // Do not allow periods < 10 seconds
}
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_LOG D_CMND_SERIALLOG " %d, " D_CMND_WEBLOG " %d, " D_CMND_MQTTLOG " %d, " D_CMND_SYSLOG " %d, " D_CMND_LOGHOST " %s, " D_CMND_LOGPORT " %d, " D_CMND_TELEPERIOD " %d"),
- Settings.seriallog_level, Settings.weblog_level, Settings.mqttlog_level, Settings.syslog_level, Settings.syslog_host, Settings.syslog_port, Settings.tele_period);
+ Settings.seriallog_level, Settings.weblog_level, Settings.mqttlog_level, Settings.syslog_level, SettingsText(SET_SYSLOG_HOST), Settings.syslog_port, Settings.tele_period);
}
/*-------------------------------------------------------------------------------------------*/
@@ -1787,7 +1812,7 @@ void HandleOtherConfiguration(void)
(i) ? stemp : "",
i,
(i) ? stemp : "",
- Settings.friendlyname[i]);
+ SettingsText(SET_FRIENDLYNAME1 + i));
}
#ifdef USE_EMULATION
@@ -1819,10 +1844,10 @@ void OtherSaveSettings(void)
{
char tmp[128];
char webindex[5];
- char friendlyname[sizeof(Settings.friendlyname[0])];
+ char friendlyname[TOPSZ];
WebGetArg("wp", tmp, sizeof(tmp));
- strlcpy(Settings.web_password, (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? Settings.web_password : tmp, sizeof(Settings.web_password));
+ SettingsUpdateText(SET_WEBPWD, (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? SettingsText(SET_WEBPWD) : tmp);
Settings.flag.mqtt_enabled = WebServer->hasArg("b1"); // SetOption3 - Enable MQTT
#ifdef USE_EMULATION
WebGetArg("b2", tmp, sizeof(tmp));
@@ -1833,8 +1858,8 @@ void OtherSaveSettings(void)
snprintf_P(webindex, sizeof(webindex), PSTR("a%d"), i);
WebGetArg(webindex, tmp, sizeof(tmp));
snprintf_P(friendlyname, sizeof(friendlyname), PSTR(FRIENDLY_NAME"%d"), i +1);
- strlcpy(Settings.friendlyname[i], (!strlen(tmp)) ? (i) ? friendlyname : FRIENDLY_NAME : tmp, sizeof(Settings.friendlyname[i]));
- snprintf_P(log_data, sizeof(log_data), PSTR("%s%s %s"), log_data, (i) ? "," : "", Settings.friendlyname[i]);
+ SettingsUpdateText(SET_FRIENDLYNAME1 +i, (!strlen(tmp)) ? (i) ? friendlyname : FRIENDLY_NAME : tmp);
+ snprintf_P(log_data, sizeof(log_data), PSTR("%s%s %s"), log_data, (i) ? "," : "", SettingsText(SET_FRIENDLYNAME1 +i));
}
AddLog(LOG_LEVEL_INFO);
WebGetArg("t1", tmp, sizeof(tmp));
@@ -1866,8 +1891,8 @@ void HandleBackupConfiguration(void)
char attachment[100];
-// char friendlyname[sizeof(Settings.friendlyname[0])];
-// snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=Config_%s_%s.dmp"), NoAlNumToUnderscore(friendlyname, Settings.friendlyname[0]), my_version);
+// char friendlyname[TOPSZ];
+// snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=Config_%s_%s.dmp"), NoAlNumToUnderscore(friendlyname, SettingsText(SET_FRIENDLYNAME1)), my_version);
char hostname[sizeof(my_hostname)];
snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=Config_%s_%s.dmp"), NoAlNumToUnderscore(hostname, my_hostname), my_version);
@@ -1967,11 +1992,17 @@ void HandleInformation(void)
if (IsModuleIfan()) { maxfn = 1; }
#endif // USE_SONOFF_IFAN
for (uint32_t i = 0; i < maxfn; i++) {
- WSContentSend_P(PSTR("}1" D_FRIENDLY_NAME " %d}2%s"), i +1, Settings.friendlyname[i]);
+ 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%%)"), Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WifiGetRssiAsQuality(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(WiFi.RSSI()), WiFi.RSSI());
WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), my_hostname, (Wifi.mdns_begun) ? ".local" : "");
+#if LWIP_IPV6
+ String ipv6_addr = WifiGetIPv6();
+ if(ipv6_addr != ""){
+ WSContentSend_P(PSTR("}1 IPv6 Address }2%s"), ipv6_addr.c_str());
+ }
+#endif
if (static_cast(WiFi.localIP()) != 0) {
WSContentSend_P(PSTR("}1" D_IP_ADDRESS "}2%s"), WiFi.localIP().toString().c_str());
WSContentSend_P(PSTR("}1" D_GATEWAY "}2%s"), IPAddress(Settings.ip_address[1]).toString().c_str());
@@ -1986,17 +2017,12 @@ void HandleInformation(void)
}
WSContentSend_P(PSTR("}1}2 ")); // Empty line
if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT
-#ifdef USE_MQTT_AWS_IOT
- WSContentSend_P(PSTR("}1" D_MQTT_HOST "}2%s%s"), Settings.mqtt_user, Settings.mqtt_host);
+ WSContentSend_P(PSTR("}1" D_MQTT_HOST "}2%s"), SettingsText(SET_MQTT_HOST));
WSContentSend_P(PSTR("}1" D_MQTT_PORT "}2%d"), Settings.mqtt_port);
-#else
- WSContentSend_P(PSTR("}1" D_MQTT_HOST "}2%s"), Settings.mqtt_host);
- WSContentSend_P(PSTR("}1" D_MQTT_PORT "}2%d"), Settings.mqtt_port);
- WSContentSend_P(PSTR("}1" D_MQTT_USER "}2%s"), Settings.mqtt_user);
-#endif
+ WSContentSend_P(PSTR("}1" D_MQTT_USER "}2%s"), SettingsText(SET_MQTT_USER));
WSContentSend_P(PSTR("}1" D_MQTT_CLIENT "}2%s"), mqtt_client);
- WSContentSend_P(PSTR("}1" D_MQTT_TOPIC "}2%s"), Settings.mqtt_topic);
-// WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC "}2%s"), Settings.mqtt_grptopic);
+ WSContentSend_P(PSTR("}1" D_MQTT_TOPIC "}2%s"), SettingsText(SET_MQTT_TOPIC));
+// WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC "}2%s"), SettingsText(SET_MQTT_GRP_TOPIC));
WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC "}2%s"), GetGroupTopic_P(stopic, ""));
WSContentSend_P(PSTR("}1" D_MQTT_FULL_TOPIC "}2%s"), GetTopic_P(stopic, CMND, mqtt_topic, ""));
WSContentSend_P(PSTR("}1" D_MQTT " " D_FALLBACK_TOPIC "}2%s"), GetFallbackTopic_P(stopic, ""));
@@ -2055,7 +2081,7 @@ void HandleUpgradeFirmware(void)
WSContentStart_P(S_FIRMWARE_UPGRADE);
WSContentSendStyle();
- WSContentSend_P(HTTP_FORM_UPG, Settings.ota_url);
+ WSContentSend_P(HTTP_FORM_UPG, SettingsText(SET_OTAURL));
WSContentSend_P(HTTP_FORM_RST_UPG, D_UPGRADE);
WSContentSpaceButton(BUTTON_MAIN);
WSContentStop();
@@ -2068,12 +2094,12 @@ void HandleUpgradeFirmwareStart(void)
{
if (!HttpCheckPriviledgedAccess()) { return; }
- char command[sizeof(Settings.ota_url) + 10]; // OtaUrl
+ char command[128]; // OtaUrl
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_UPGRADE_STARTED));
WifiConfigCounter();
- char otaurl[sizeof(Settings.ota_url)];
+ char otaurl[101];
WebGetArg("o", otaurl, sizeof(otaurl));
if (strlen(otaurl)) {
snprintf_P(command, sizeof(command), PSTR(D_CMND_OTAURL " %s"), otaurl);
@@ -2382,12 +2408,12 @@ void HandleHttpCommand(void)
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_COMMAND));
bool valid = true;
- if (Settings.web_password[0] != 0) {
- char tmp1[sizeof(Settings.web_password)];
+ if (strlen(SettingsText(SET_WEBPWD))) {
+ char tmp1[33];
WebGetArg("user", tmp1, sizeof(tmp1));
- char tmp2[sizeof(Settings.web_password)];
+ char tmp2[strlen(SettingsText(SET_WEBPWD)) +1];
WebGetArg("password", tmp2, sizeof(tmp2));
- if (!(!strcmp(tmp1, WEB_USERNAME) && !strcmp(tmp2, Settings.web_password))) { valid = false; }
+ if (!(!strcmp(tmp1, WEB_USERNAME) && !strcmp(tmp2, SettingsText(SET_WEBPWD)))) { valid = false; }
}
WSContentBegin(200, CT_JSON);
@@ -2698,7 +2724,7 @@ const char kWebCommands[] PROGMEM = "|" // No prefix
#ifdef USE_SENDMAIL
D_CMND_SENDMAIL "|"
#endif
- D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBREFRESH "|" D_CMND_WEBSEND "|" D_CMND_WEBCOLOR "|" D_CMND_WEBSENSOR;
+ D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBREFRESH "|" D_CMND_WEBSEND "|" D_CMND_WEBCOLOR "|" D_CMND_WEBSENSOR "|" D_CMND_CORS;
void (* const WebCommand[])(void) PROGMEM = {
#ifdef USE_EMULATION
@@ -2707,7 +2733,7 @@ void (* const WebCommand[])(void) PROGMEM = {
#ifdef USE_SENDMAIL
&CmndSendmail,
#endif
- &CmndWebServer, &CmndWebPassword, &CmndWeblog, &CmndWebRefresh, &CmndWebSend, &CmndWebColor, &CmndWebSensor };
+ &CmndWebServer, &CmndWebPassword, &CmndWeblog, &CmndWebRefresh, &CmndWebSend, &CmndWebColor, &CmndWebSensor, &CmndCors };
/*********************************************************************************************\
* Commands
@@ -2760,9 +2786,9 @@ void CmndWebServer(void)
void CmndWebPassword(void)
{
- if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.web_password))) {
- strlcpy(Settings.web_password, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? WEB_PASSWORD : XdrvMailbox.data, sizeof(Settings.web_password));
- ResponseCmndChar(Settings.web_password);
+ if (XdrvMailbox.data_len > 0) {
+ SettingsUpdateText(SET_WEBPWD, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? WEB_PASSWORD : XdrvMailbox.data);
+ ResponseCmndChar(SettingsText(SET_WEBPWD));
} else {
Response_P(S_JSON_COMMAND_ASTERISK, XdrvMailbox.command);
}
@@ -2828,6 +2854,14 @@ void CmndWebSensor(void)
ResponseJsonEnd();
}
+void CmndCors(void)
+{
+ if (XdrvMailbox.data_len > 0) {
+ SettingsUpdateText(SET_CORS, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? WEB_PASSWORD : XdrvMailbox.data);
+ }
+ ResponseCmndChar(SettingsText(SET_CORS));
+}
+
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino
index 49f35d579..47838e223 100644
--- a/tasmota/xdrv_02_mqtt.ino
+++ b/tasmota/xdrv_02_mqtt.ino
@@ -91,10 +91,6 @@ tls_dir_t tls_dir; // memory copy of tls_dir from flash
#endif // USE_MQTT_AWS_IOT
-// A typical AWS IoT endpoint is 50 characters long, it does not fit
-// in MqttHost field (32 chars). We need to concatenate both MqttUser and MqttHost
-char AWS_endpoint[65]; // aWS IOT endpoint, concatenation of user and host
-
// check whether the fingerprint is filled with a single value
// Filled with 0x00 = accept any fingerprint and learn it for next time
// Filled with 0xFF = accept any fingerpring forever
@@ -106,21 +102,6 @@ bool is_fingerprint_mono_value(uint8_t finger[20], uint8_t value) {
}
return true;
}
-
-#ifdef USE_MQTT_AWS_IOT
-void setLongMqttHost(const char *mqtt_host) {
- if (strlen(mqtt_host) <= sizeof(Settings.mqtt_host)) {
- strlcpy(Settings.mqtt_host, mqtt_host, sizeof(Settings.mqtt_host));
- Settings.mqtt_user[0] = 0;
- } else {
- // need to split in mqtt_user first then mqtt_host
- strlcpy(Settings.mqtt_user, mqtt_host, sizeof(Settings.mqtt_user));
- strlcpy(Settings.mqtt_host, &mqtt_host[sizeof(Settings.mqtt_user)-1], sizeof(Settings.mqtt_host));
- }
- strlcpy(AWS_endpoint, mqtt_host, sizeof(AWS_endpoint));
-}
-#endif // USE_MQTT_AWS_IOT
-
#endif // USE_MQTT_TLS
void MakeValidMqtt(uint32_t option, char* str)
@@ -165,10 +146,10 @@ void MqttDiscoverServer(void)
}
}
#endif // MDNS_HOSTNAME
- snprintf_P(Settings.mqtt_host, sizeof(Settings.mqtt_host), MDNS.IP(i).toString().c_str());
+ SettingsUpdateText(SET_MQTT_HOST, MDNS.IP(i).toString().c_str());
Settings.mqtt_port = MDNS.port(i);
- AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_MQTT_SERVICE_FOUND " %s, " D_IP_ADDRESS " %s, " D_PORT " %d"), MDNS.hostname(i).c_str(), Settings.mqtt_host, Settings.mqtt_port);
+ AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_MQTT_SERVICE_FOUND " %s, " D_IP_ADDRESS " %s, " D_PORT " %d"), MDNS.hostname(i).c_str(), SettingsText(SET_MQTT_HOST), Settings.mqtt_port);
}
}
#endif // MQTT_HOST_DISCOVERY
@@ -202,8 +183,6 @@ void MqttInit(void)
tlsClient = new BearSSL::WiFiClientSecure_light(1024,1024);
#ifdef USE_MQTT_AWS_IOT
- snprintf_P(AWS_endpoint, sizeof(AWS_endpoint), PSTR("%s%s"), Settings.mqtt_user, Settings.mqtt_host);
-
loadTlsDir(); // load key and certificate data from Flash
tlsClient->setClientECCert(AWS_IoT_Client_Certificate,
AWS_IoT_Private_Key,
@@ -261,8 +240,8 @@ void MqttDataHandler(char* mqtt_topic, uint8_t* mqtt_data, unsigned int data_len
if (data_len >= MQTT_MAX_PACKET_SIZE) { return; }
// Do not execute multiple times if Prefix1 equals Prefix2
- if (!strcmp(Settings.mqtt_prefix[0], Settings.mqtt_prefix[1])) {
- char *str = strstr(mqtt_topic, Settings.mqtt_prefix[0]);
+ if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2))) {
+ char *str = strstr(mqtt_topic, SettingsText(SET_MQTTPREFIX1));
if ((str == mqtt_topic) && mqtt_cmnd_publish) {
if (mqtt_cmnd_publish > 3) {
mqtt_cmnd_publish -= 3;
@@ -330,8 +309,8 @@ void MqttPublishLogging(const char *mxtime)
GetTopic_P(stopic, STAT, mqtt_topic, romram);
char *me;
- if (!strcmp(Settings.mqtt_prefix[0], Settings.mqtt_prefix[1])) {
- me = strstr(stopic, Settings.mqtt_prefix[0]);
+ if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2))) {
+ me = strstr(stopic, SettingsText(SET_MQTTPREFIX1));
if (me == stopic) {
mqtt_cmnd_publish += 3;
}
@@ -389,8 +368,8 @@ void MqttPublish(const char* topic, bool retained)
retained = false; // AWS IoT does not support retained, it will disconnect if received
#endif
- if (!strcmp(Settings.mqtt_prefix[0],Settings.mqtt_prefix[1])) {
- me = strstr(topic,Settings.mqtt_prefix[0]);
+ if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2))) {
+ me = strstr(topic, SettingsText(SET_MQTTPREFIX1));
if (me == topic) {
mqtt_cmnd_publish += 3;
}
@@ -505,11 +484,7 @@ void MqttDisconnected(int state)
MqttClient.disconnect();
-#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT)
- AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CONNECT_FAILED_TO " %s:%d, rc %d. " D_RETRY_IN " %d " D_UNIT_SECOND), AWS_endpoint, Settings.mqtt_port, state, Mqtt.retry_counter);
-#else
- AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CONNECT_FAILED_TO " %s:%d, rc %d. " D_RETRY_IN " %d " D_UNIT_SECOND), Settings.mqtt_host, Settings.mqtt_port, state, Mqtt.retry_counter);
-#endif
+ AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CONNECT_FAILED_TO " %s:%d, rc %d. " D_RETRY_IN " %d " D_UNIT_SECOND), SettingsText(SET_MQTT_HOST), Settings.mqtt_port, state, Mqtt.retry_counter);
rules_flag.mqtt_disconnected = 1;
}
@@ -533,7 +508,7 @@ void MqttConnected(void)
GetTopic_P(stopic, CMND, mqtt_topic, PSTR("#"));
MqttSubscribe(stopic);
- if (strstr_P(Settings.mqtt_fulltopic, MQTT_TOKEN_TOPIC) != nullptr) {
+ if (strstr_P(SettingsText(SET_MQTT_FULLTOPIC), MQTT_TOKEN_TOPIC) != nullptr) {
GetGroupTopic_P(stopic, PSTR("#")); // SetOption75 0: %prefix%/nothing/%topic% = cmnd/nothing//# or SetOption75 1: cmnd/
MqttSubscribe(stopic);
GetFallbackTopic_P(stopic, PSTR("#"));
@@ -550,12 +525,23 @@ void MqttConnected(void)
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "1"));
#ifdef USE_WEBSERVER
if (Settings.webserver) {
+#if LWIP_IPV6
+ Response_P(PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\",\"IPv6Address\":\"%s\"}"),
+ (2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str(),WifiGetIPv6().c_str());
+#else
Response_P(PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\"}"),
(2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str());
+#endif // LWIP_IPV6 = 1
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "2"));
}
#endif // USE_WEBSERVER
- Response_P(PSTR("{\"" D_JSON_RESTARTREASON "\":\"%s\"}"), GetResetReasonInfo().c_str());
+ Response_P(PSTR("{\"" D_JSON_RESTARTREASON "\":"));
+ if (ResetReason() == REASON_EXCEPTION_RST) {
+ CrashDump();
+ } else {
+ ResponseAppend_P(PSTR("\"%s\""), GetResetReason().c_str());
+ }
+ ResponseJsonEnd();
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "3"));
MqttPublishAllPowerState();
if (Settings.tele_period) {
@@ -583,7 +569,7 @@ void MqttReconnect(void)
MqttDiscoverServer();
#endif // MQTT_HOST_DISCOVERY
#endif // USE_DISCOVERY
- if (!strlen(Settings.mqtt_host) || !Settings.mqtt_port) {
+ if (!strlen(SettingsText(SET_MQTT_HOST)) || !Settings.mqtt_port) {
Mqtt.allowed = false;
}
#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT)
@@ -610,8 +596,12 @@ void MqttReconnect(void)
char *mqtt_user = nullptr;
char *mqtt_pwd = nullptr;
- if (strlen(Settings.mqtt_user) > 0) mqtt_user = Settings.mqtt_user;
- if (strlen(Settings.mqtt_pwd) > 0) mqtt_pwd = Settings.mqtt_pwd;
+ if (strlen(SettingsText(SET_MQTT_USER))) {
+ mqtt_user = SettingsText(SET_MQTT_USER);
+ }
+ if (strlen(SettingsText(SET_MQTT_PWD))) {
+ mqtt_pwd = SettingsText(SET_MQTT_PWD);
+ }
GetTopic_P(stopic, TELE, mqtt_topic, S_LWT);
Response_P(S_OFFLINE);
@@ -634,10 +624,8 @@ void MqttReconnect(void)
tlsClient->setClientECCert(AWS_IoT_Client_Certificate,
AWS_IoT_Private_Key,
0xFFFF /* all usages, don't care */, 0);
- MqttClient.setServer(AWS_endpoint, Settings.mqtt_port);
-#else
- MqttClient.setServer(Settings.mqtt_host, Settings.mqtt_port);
#endif
+ MqttClient.setServer(SettingsText(SET_MQTT_HOST), Settings.mqtt_port);
uint32_t mqtt_connect_time = millis();
#if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT)
@@ -651,7 +639,7 @@ void MqttReconnect(void)
tlsClient->setPubKeyFingerprint(Settings.mqtt_fingerprint[0], Settings.mqtt_fingerprint[1], allow_all_fingerprints);
#endif
#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT)
- AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "AWS IoT endpoint: %s"), AWS_endpoint);
+ AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "AWS IoT endpoint: %s"), SettingsText(SET_MQTT_HOST));
//if (MqttClient.connect(mqtt_client, nullptr, nullptr, nullptr, 0, false, nullptr)) {
if (MqttClient.connect(mqtt_client, nullptr, nullptr, stopic, 1, false, mqtt_data, MQTT_CLEAN_SESSION)) {
#else
@@ -711,7 +699,7 @@ void MqttCheck(void)
if (!Mqtt.retry_counter) {
#ifdef USE_DISCOVERY
#ifdef MQTT_HOST_DISCOVERY
- if (!strlen(Settings.mqtt_host) && !Wifi.mdns_begun) { return; }
+ if (!strlen(SettingsText(SET_MQTT_HOST)) && !Wifi.mdns_begun) { return; }
#endif // MQTT_HOST_DISCOVERY
#endif // USE_DISCOVERY
MqttReconnect();
@@ -752,18 +740,18 @@ void CmndMqttFingerprint(void)
#if !defined(USE_MQTT_TLS) || !defined(USE_MQTT_AWS_IOT) // user and password are disabled with AWS IoT
void CmndMqttUser(void)
{
- if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_user))) {
- strlcpy(Settings.mqtt_user, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_USER : XdrvMailbox.data, sizeof(Settings.mqtt_user));
+ if (XdrvMailbox.data_len > 0) {
+ SettingsUpdateText(SET_MQTT_USER, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_USER : XdrvMailbox.data);
restart_flag = 2;
}
- ResponseCmndChar(Settings.mqtt_user);
+ ResponseCmndChar(SettingsText(SET_MQTT_USER));
}
void CmndMqttPassword(void)
{
- if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_pwd))) {
- strlcpy(Settings.mqtt_pwd, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_PASS : XdrvMailbox.data, sizeof(Settings.mqtt_pwd));
- ResponseCmndChar(Settings.mqtt_pwd);
+ if (XdrvMailbox.data_len > 0) {
+ SettingsUpdateText(SET_MQTT_PWD, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_PASS : XdrvMailbox.data);
+ ResponseCmndChar(SettingsText(SET_MQTT_PWD));
restart_flag = 2;
} else {
Response_P(S_JSON_COMMAND_ASTERISK, XdrvMailbox.command);
@@ -781,19 +769,11 @@ void CmndMqttlog(void)
void CmndMqttHost(void)
{
-#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT)
- if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len <= sizeof(Settings.mqtt_host) + sizeof(Settings.mqtt_user) - 2)) {
- setLongMqttHost((SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_HOST : XdrvMailbox.data);
+ if (XdrvMailbox.data_len > 0) {
+ SettingsUpdateText(SET_MQTT_HOST, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_HOST : XdrvMailbox.data);
restart_flag = 2;
}
- ResponseCmndChar(AWS_endpoint);
-#else
- if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_host))) {
- strlcpy(Settings.mqtt_host, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_HOST : XdrvMailbox.data, sizeof(Settings.mqtt_host));
- restart_flag = 2;
- }
- ResponseCmndChar(Settings.mqtt_host);
-#endif
+ ResponseCmndChar(SettingsText(SET_MQTT_HOST));
}
void CmndMqttPort(void)
@@ -817,11 +797,11 @@ void CmndMqttRetry(void)
void CmndStateText(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) {
- if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.state_text[0]))) {
+ if (XdrvMailbox.data_len > 0) {
for (uint32_t i = 0; i <= XdrvMailbox.data_len; i++) {
if (XdrvMailbox.data[i] == ' ') XdrvMailbox.data[i] = '_';
}
- strlcpy(Settings.state_text[XdrvMailbox.index -1], XdrvMailbox.data, sizeof(Settings.state_text[0]));
+ SettingsUpdateText(SET_STATE_TXT1 + XdrvMailbox.index -1, XdrvMailbox.data);
}
ResponseCmndIdxChar(GetStateText(XdrvMailbox.index -1));
}
@@ -829,40 +809,41 @@ void CmndStateText(void)
void CmndMqttClient(void)
{
- if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_client))) {
- strlcpy(Settings.mqtt_client, (SC_DEFAULT == Shortcut()) ? MQTT_CLIENT_ID : XdrvMailbox.data, sizeof(Settings.mqtt_client));
+ if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) {
+ SettingsUpdateText(SET_MQTT_CLIENT, (SC_DEFAULT == Shortcut()) ? MQTT_CLIENT_ID : XdrvMailbox.data);
restart_flag = 2;
}
- ResponseCmndChar(Settings.mqtt_client);
+ ResponseCmndChar(SettingsText(SET_MQTT_CLIENT));
}
void CmndFullTopic(void)
{
- if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_fulltopic))) {
+ if (XdrvMailbox.data_len > 0) {
MakeValidMqtt(1, XdrvMailbox.data);
if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); }
char stemp1[TOPSZ];
strlcpy(stemp1, (SC_DEFAULT == Shortcut()) ? MQTT_FULLTOPIC : XdrvMailbox.data, sizeof(stemp1));
- if (strcmp(stemp1, Settings.mqtt_fulltopic)) {
+ if (strcmp(stemp1, SettingsText(SET_MQTT_FULLTOPIC))) {
Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); // SetOption10 - Control MQTT LWT message format
MqttPublishPrefixTopic_P(TELE, PSTR(D_LWT), true); // Offline or remove previous retained topic
- strlcpy(Settings.mqtt_fulltopic, stemp1, sizeof(Settings.mqtt_fulltopic));
+ SettingsUpdateText(SET_MQTT_FULLTOPIC, stemp1);
restart_flag = 2;
}
}
- ResponseCmndChar(Settings.mqtt_fulltopic);
+ ResponseCmndChar(SettingsText(SET_MQTT_FULLTOPIC));
}
void CmndPrefix(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) {
- if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_prefix[0]))) {
+
+ if (XdrvMailbox.data_len > 0) {
MakeValidMqtt(0, XdrvMailbox.data);
- strlcpy(Settings.mqtt_prefix[XdrvMailbox.index -1], (SC_DEFAULT == Shortcut()) ? (1==XdrvMailbox.index)?SUB_PREFIX:(2==XdrvMailbox.index)?PUB_PREFIX:PUB_PREFIX2 : XdrvMailbox.data, sizeof(Settings.mqtt_prefix[0]));
-// if (Settings.mqtt_prefix[XdrvMailbox.index -1][strlen(Settings.mqtt_prefix[XdrvMailbox.index -1])] == '/') Settings.mqtt_prefix[XdrvMailbox.index -1][strlen(Settings.mqtt_prefix[XdrvMailbox.index -1])] = 0;
+ SettingsUpdateText(SET_MQTTPREFIX1 + XdrvMailbox.index -1,
+ (SC_DEFAULT == Shortcut()) ? (1==XdrvMailbox.index) ? SUB_PREFIX : (2==XdrvMailbox.index) ? PUB_PREFIX : PUB_PREFIX2 : XdrvMailbox.data);
restart_flag = 2;
}
- ResponseCmndIdxChar(Settings.mqtt_prefix[XdrvMailbox.index -1]);
+ ResponseCmndIdxChar(SettingsText(SET_MQTTPREFIX1 + XdrvMailbox.index -1));
}
}
@@ -888,60 +869,60 @@ void CmndPublish(void)
void CmndGroupTopic(void)
{
- if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_grptopic))) {
+ if (XdrvMailbox.data_len > 0) {
MakeValidMqtt(0, XdrvMailbox.data);
if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); }
- strlcpy(Settings.mqtt_grptopic, (SC_DEFAULT == Shortcut()) ? MQTT_GRPTOPIC : XdrvMailbox.data, sizeof(Settings.mqtt_grptopic));
+ SettingsUpdateText(SET_MQTT_GRP_TOPIC, (SC_DEFAULT == Shortcut()) ? MQTT_GRPTOPIC : XdrvMailbox.data);
restart_flag = 2;
}
- ResponseCmndChar(Settings.mqtt_grptopic);
+ ResponseCmndChar(SettingsText(SET_MQTT_GRP_TOPIC));
}
void CmndTopic(void)
{
- if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_topic))) {
+ if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) {
MakeValidMqtt(0, XdrvMailbox.data);
if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); }
char stemp1[TOPSZ];
strlcpy(stemp1, (SC_DEFAULT == Shortcut()) ? MQTT_TOPIC : XdrvMailbox.data, sizeof(stemp1));
- if (strcmp(stemp1, Settings.mqtt_topic)) {
+ if (strcmp(stemp1, SettingsText(SET_MQTT_TOPIC))) {
Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); // SetOption10 - Control MQTT LWT message format
MqttPublishPrefixTopic_P(TELE, PSTR(D_LWT), true); // Offline or remove previous retained topic
- strlcpy(Settings.mqtt_topic, stemp1, sizeof(Settings.mqtt_topic));
+ SettingsUpdateText(SET_MQTT_TOPIC, stemp1);
restart_flag = 2;
}
}
- ResponseCmndChar(Settings.mqtt_topic);
+ ResponseCmndChar(SettingsText(SET_MQTT_TOPIC));
}
void CmndButtonTopic(void)
{
- if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.button_topic))) {
+ if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) {
MakeValidMqtt(0, XdrvMailbox.data);
if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); }
switch (Shortcut()) {
- case SC_CLEAR: strlcpy(Settings.button_topic, "", sizeof(Settings.button_topic)); break;
- case SC_DEFAULT: strlcpy(Settings.button_topic, mqtt_topic, sizeof(Settings.button_topic)); break;
- case SC_USER: strlcpy(Settings.button_topic, MQTT_BUTTON_TOPIC, sizeof(Settings.button_topic)); break;
- default: strlcpy(Settings.button_topic, XdrvMailbox.data, sizeof(Settings.button_topic));
+ case SC_CLEAR: SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, ""); break;
+ case SC_DEFAULT: SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, mqtt_topic); break;
+ case SC_USER: SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, MQTT_BUTTON_TOPIC); break;
+ default: SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, XdrvMailbox.data);
}
}
- ResponseCmndChar(Settings.button_topic);
+ ResponseCmndChar(SettingsText(SET_MQTT_BUTTON_TOPIC));
}
void CmndSwitchTopic(void)
{
- if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.switch_topic))) {
+ if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) {
MakeValidMqtt(0, XdrvMailbox.data);
if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); }
switch (Shortcut()) {
- case SC_CLEAR: strlcpy(Settings.switch_topic, "", sizeof(Settings.switch_topic)); break;
- case SC_DEFAULT: strlcpy(Settings.switch_topic, mqtt_topic, sizeof(Settings.switch_topic)); break;
- case SC_USER: strlcpy(Settings.switch_topic, MQTT_SWITCH_TOPIC, sizeof(Settings.switch_topic)); break;
- default: strlcpy(Settings.switch_topic, XdrvMailbox.data, sizeof(Settings.switch_topic));
+ case SC_CLEAR: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, ""); break;
+ case SC_DEFAULT: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, mqtt_topic); break;
+ case SC_USER: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, MQTT_SWITCH_TOPIC); break;
+ default: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, XdrvMailbox.data);
}
}
- ResponseCmndChar(Settings.switch_topic);
+ ResponseCmndChar(SettingsText(SET_MQTT_SWITCH_TOPIC));
}
void CmndButtonRetain(void)
@@ -1071,6 +1052,9 @@ void CmndTlsKey(void) {
}
memcpy_P(spi_buffer, tls_spi_start, tls_spi_len);
+ // remove any white space from the base64
+ RemoveAllSpaces(XdrvMailbox.data);
+
// allocate buffer for decoded base64
uint32_t bin_len = decode_base64_length((unsigned char*)XdrvMailbox.data);
uint8_t *bin_buf = nullptr;
@@ -1206,22 +1190,18 @@ void HandleMqttConfiguration(void)
return;
}
- char str[sizeof(Settings.mqtt_client)];
+ char str[33];
WSContentStart_P(S_CONFIGURE_MQTT);
WSContentSendStyle();
WSContentSend_P(HTTP_FORM_MQTT1,
-#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT)
- AWS_endpoint,
-#else
- Settings.mqtt_host,
-#endif
+ SettingsText(SET_MQTT_HOST),
Settings.mqtt_port,
- Format(str, MQTT_CLIENT_ID, sizeof(str)), MQTT_CLIENT_ID, Settings.mqtt_client);
+ Format(str, MQTT_CLIENT_ID, sizeof(str)), MQTT_CLIENT_ID, SettingsText(SET_MQTT_CLIENT));
WSContentSend_P(HTTP_FORM_MQTT2,
- (Settings.mqtt_user[0] == '\0') ? "0" : Settings.mqtt_user,
- Format(str, MQTT_TOPIC, sizeof(str)), MQTT_TOPIC, Settings.mqtt_topic,
- MQTT_FULLTOPIC, MQTT_FULLTOPIC, Settings.mqtt_fulltopic);
+ (!strlen(SettingsText(SET_MQTT_USER))) ? "0" : SettingsText(SET_MQTT_USER),
+ Format(str, MQTT_TOPIC, sizeof(str)), MQTT_TOPIC, SettingsText(SET_MQTT_TOPIC),
+ MQTT_FULLTOPIC, MQTT_FULLTOPIC, SettingsText(SET_MQTT_FULLTOPIC));
WSContentSend_P(HTTP_FORM_END);
WSContentSpaceButton(BUTTON_CONFIGURATION);
WSContentStop();
@@ -1239,32 +1219,28 @@ void MqttSaveSettings(void)
WebGetArg("mf", tmp, sizeof(tmp));
strlcpy(stemp2, (!strlen(tmp)) ? MQTT_FULLTOPIC : tmp, sizeof(stemp2));
MakeValidMqtt(1, stemp2);
- if ((strcmp(stemp, Settings.mqtt_topic)) || (strcmp(stemp2, Settings.mqtt_fulltopic))) {
+ if ((strcmp(stemp, SettingsText(SET_MQTT_TOPIC))) || (strcmp(stemp2, SettingsText(SET_MQTT_FULLTOPIC)))) {
Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); // SetOption10 - Control MQTT LWT message format
MqttPublishPrefixTopic_P(TELE, S_LWT, true); // Offline or remove previous retained topic
}
- strlcpy(Settings.mqtt_topic, stemp, sizeof(Settings.mqtt_topic));
- strlcpy(Settings.mqtt_fulltopic, stemp2, sizeof(Settings.mqtt_fulltopic));
+ SettingsUpdateText(SET_MQTT_TOPIC, stemp);
+ SettingsUpdateText(SET_MQTT_FULLTOPIC, stemp2);
WebGetArg("mh", tmp, sizeof(tmp));
-#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT)
- setLongMqttHost((!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp);
-#else
- strlcpy(Settings.mqtt_host, (!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_host));
-#endif
+ SettingsUpdateText(SET_MQTT_HOST, (!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp);
WebGetArg("ml", tmp, sizeof(tmp));
Settings.mqtt_port = (!strlen(tmp)) ? MQTT_PORT : atoi(tmp);
WebGetArg("mc", tmp, sizeof(tmp));
- strlcpy(Settings.mqtt_client, (!strlen(tmp)) ? MQTT_CLIENT_ID : tmp, sizeof(Settings.mqtt_client));
+ SettingsUpdateText(SET_MQTT_CLIENT, (!strlen(tmp)) ? MQTT_CLIENT_ID : tmp);
#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT)
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"),
- AWS_endpoint, Settings.mqtt_port, Settings.mqtt_client, Settings.mqtt_topic, Settings.mqtt_fulltopic);
+ SettingsText(SET_MQTT_HOST), Settings.mqtt_port, SettingsText(SET_MQTT_CLIENT), SettingsText(SET_MQTT_TOPIC), SettingsText(SET_MQTT_FULLTOPIC));
#else // USE_MQTT_AWS_IOT
WebGetArg("mu", tmp, sizeof(tmp));
- strlcpy(Settings.mqtt_user, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_user));
+ SettingsUpdateText(SET_MQTT_USER, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp);
WebGetArg("mp", tmp, sizeof(tmp));
- strlcpy(Settings.mqtt_pwd, (!strlen(tmp)) ? "" : (!strcmp(tmp, D_ASTERISK_PWD)) ? Settings.mqtt_pwd : tmp, sizeof(Settings.mqtt_pwd));
+ SettingsUpdateText(SET_MQTT_PWD, (!strlen(tmp)) ? "" : (!strcmp(tmp, D_ASTERISK_PWD)) ? SettingsText(SET_MQTT_PWD) : tmp);
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_MQTTUSER " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"),
- Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, Settings.mqtt_user, Settings.mqtt_topic, Settings.mqtt_fulltopic);
+ SettingsText(SET_MQTT_HOST), Settings.mqtt_port, SettingsText(SET_MQTT_CLIENT), SettingsText(SET_MQTT_USER), SettingsText(SET_MQTT_TOPIC), SettingsText(SET_MQTT_FULLTOPIC));
#endif
}
#endif // USE_WEBSERVER
diff --git a/tasmota/xdrv_09_timers.ino b/tasmota/xdrv_09_timers.ino
index a71960695..db1cde97e 100644
--- a/tasmota/xdrv_09_timers.ino
+++ b/tasmota/xdrv_09_timers.ino
@@ -554,10 +554,10 @@ const char HTTP_TIMER_SCRIPT2[] PROGMEM =
"o=qs('#ho');"
"e=o.childElementCount;"
"if(b==1){"
- "qs('#dr').disabled='';"
+ "qs('#dr').style.visibility='';"
"if(e>12){for(i=12;i<=23;i++){o.removeChild(o.lastElementChild);}}" // Create offset hours select options
"}else{"
- "qs('#dr').disabled='disabled';"
+ "qs('#dr').style.visibility='hidden';"
"if(e<23){for(i=12;i<=23;i++){ce(i,o);}}" // Create hours select options
"}"
"}";
@@ -583,7 +583,7 @@ const char HTTP_TIMER_SCRIPT3[] PROGMEM =
"if(m==0){s|=l;}" // Get time
#ifdef USE_SUNRISE
"if((m==1)||(m==2)){"
- "if(qs('#dr').selectedIndex>0){l+=720;}" // If negative offset, add 12h to given offset time
+ "if(qs('#dr').selectedIndex>0){if(l>0){l+=720;}}" // If negative offset and delta-time > 0, add 12h to given offset time
"s|=l&0x7FF;" // Save offset instead of time
"}"
#endif
diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino
index 4025ef5d4..6e1636518 100644
--- a/tasmota/xdrv_10_rules.ino
+++ b/tasmota/xdrv_10_rules.ino
@@ -217,7 +217,7 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule)
for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) {
snprintf_P(stemp, sizeof(stemp), PSTR("%%MEM%d%%"), i +1);
if (rule_param.startsWith(stemp)) {
- rule_param = Settings.mems[i];
+ rule_param = SettingsText(SET_MEM1 + i);
break;
}
}
@@ -438,7 +438,7 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved)
String ucommand = commands;
ucommand.toUpperCase();
// if (!ucommand.startsWith("BACKLOG")) { commands = "backlog " + commands; } // Always use Backlog to prevent power race exception
- if (ucommand.indexOf("EVENT ") != -1) { commands = "backlog " + commands; } // Always use Backlog with event to prevent rule event loop exception
+ if ((ucommand.indexOf("EVENT ") != -1) && (ucommand.indexOf("BACKLOG ") == -1)) { commands = "backlog " + commands; } // Always use Backlog with event to prevent rule event loop exception
RulesVarReplace(commands, F("%VALUE%"), Rules.event_value);
for (uint32_t i = 0; i < MAX_RULE_VARS; i++) {
@@ -447,11 +447,12 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved)
}
for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) {
snprintf_P(stemp, sizeof(stemp), PSTR("%%MEM%d%%"), i +1);
- RulesVarReplace(commands, stemp, Settings.mems[i]);
+ RulesVarReplace(commands, stemp, SettingsText(SET_MEM1 +i));
}
RulesVarReplace(commands, F("%TIME%"), String(MinutesPastMidnight()));
RulesVarReplace(commands, F("%UPTIME%"), String(MinutesUptime()));
RulesVarReplace(commands, F("%TIMESTAMP%"), GetDateAndTime(DT_LOCAL));
+ RulesVarReplace(commands, F("%TOPIC%"), SettingsText(SET_MQTT_TOPIC));
#if defined(USE_TIMERS) && defined(USE_SUNRISE)
RulesVarReplace(commands, F("%SUNRISE%"), String(SunMinutes(0)));
RulesVarReplace(commands, F("%SUNSET%"), String(SunMinutes(1)));
@@ -607,7 +608,7 @@ void RulesEvery50ms(void)
for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) {
if (bitRead(Rules.mems_event, i)) {
bitClear(Rules.mems_event, i);
- snprintf_P(json_event, sizeof(json_event), PSTR("{\"Mem%d\":{\"State\":%s}}"), i+1, Settings.mems[i]);
+ snprintf_P(json_event, sizeof(json_event), PSTR("{\"Mem%d\":{\"State\":%s}}"), i+1, SettingsText(SET_MEM1 +i));
RulesProcessEvent(json_event);
break;
}
@@ -1001,7 +1002,7 @@ bool findNextVariableValue(char * &pVarname, float &value)
} else if (sVarName.startsWith(F("MEM"))) {
int index = sVarName.substring(3).toInt();
if (index > 0 && index <= MAX_RULE_MEMS) {
- value = CharToFloat(Settings.mems[index -1]);
+ value = CharToFloat(SettingsText(SET_MEM1 + index -1));
}
} else if (sVarName.equals(F("TIME"))) {
value = MinutesPastMidnight();
@@ -1809,23 +1810,23 @@ void CmndMemory(void)
if (!XdrvMailbox.usridx) {
mqtt_data[0] = '\0';
for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) {
- ResponseAppend_P(PSTR("%c\"Mem%d\":\"%s\""), (i) ? ',' : '{', i +1, Settings.mems[i]);
+ ResponseAppend_P(PSTR("%c\"Mem%d\":\"%s\""), (i) ? ',' : '{', i +1, SettingsText(SET_MEM1 +i));
}
ResponseJsonEnd();
} else {
if (XdrvMailbox.data_len > 0) {
#ifdef USE_EXPRESSION
if (XdrvMailbox.data[0] == '=') { // Spaces already been skipped in data
- dtostrfd(evaluateExpression(XdrvMailbox.data + 1, XdrvMailbox.data_len - 1), Settings.flag2.calc_resolution, Settings.mems[XdrvMailbox.index -1]);
+ dtostrfd(evaluateExpression(XdrvMailbox.data + 1, XdrvMailbox.data_len - 1), Settings.flag2.calc_resolution, SettingsText(SET_MEM1 + XdrvMailbox.index -1));
} else {
- strlcpy(Settings.mems[XdrvMailbox.index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(Settings.mems[XdrvMailbox.index -1]));
+ SettingsUpdateText(SET_MEM1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data);
}
#else
- strlcpy(Settings.mems[XdrvMailbox.index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(Settings.mems[XdrvMailbox.index -1]));
+ SettingsUpdateText(SET_MEM1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data);
#endif // USE_EXPRESSION
bitSet(Rules.mems_event, XdrvMailbox.index -1);
}
- ResponseCmndIdxChar(Settings.mems[XdrvMailbox.index -1]);
+ ResponseCmndIdxChar(SettingsText(SET_MEM1 + XdrvMailbox.index -1));
}
}
}
diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino
index 0bab141d7..68df13984 100755
--- a/tasmota/xdrv_10_scripter.ino
+++ b/tasmota/xdrv_10_scripter.ino
@@ -1030,8 +1030,10 @@ char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,Jso
if ((*jo).is(vn)) {
if (!strncmp(str_value,"ON",2)) {
if (fp) *fp=1;
+ goto nexit;
} else if (!strncmp(str_value,"OFF",3)) {
if (fp) *fp=0;
+ goto nexit;
} else {
*vtype=STR_RES;
tind->bits.constant=1;
@@ -1039,6 +1041,7 @@ char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,Jso
if (sp) strlcpy(sp,str_value,SCRIPT_MAXSSIZE);
return lp+len;
}
+
} else {
if (fp) {
if (!strncmp(vn.c_str(),"Epoch",5)) {
@@ -1047,6 +1050,7 @@ char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,Jso
*fp=CharToFloat((char*)str_value);
}
}
+ nexit:
*vtype=NUM_RES;
tind->bits.constant=1;
tind->bits.is_string=0;
@@ -1366,7 +1370,7 @@ chknext:
goto exit;
}
if (!strncmp(vname,"gtopic",6)) {
- if (sp) strlcpy(sp,Settings.mqtt_grptopic,glob_script_mem.max_ssize);
+ if (sp) strlcpy(sp,SettingsText(SET_MQTT_GRP_TOPIC),glob_script_mem.max_ssize);
goto strexit;
}
break;
@@ -1523,15 +1527,15 @@ chknext:
goto exit;
}
if (!strncmp(vname,"prefix1",7)) {
- if (sp) strlcpy(sp,Settings.mqtt_prefix[0],glob_script_mem.max_ssize);
+ if (sp) strlcpy(sp,SettingsText(SET_MQTTPREFIX1),glob_script_mem.max_ssize);
goto strexit;
}
if (!strncmp(vname,"prefix2",7)) {
- if (sp) strlcpy(sp,Settings.mqtt_prefix[1],glob_script_mem.max_ssize);
+ if (sp) strlcpy(sp,SettingsText(SET_MQTTPREFIX2),glob_script_mem.max_ssize);
goto strexit;
}
if (!strncmp(vname,"prefix3",7)) {
- if (sp) strlcpy(sp,Settings.mqtt_prefix[2],glob_script_mem.max_ssize);
+ if (sp) strlcpy(sp,SettingsText(SET_MQTTPREFIX3),glob_script_mem.max_ssize);
goto strexit;
}
if (!strncmp(vname,"pow(",4)) {
@@ -1740,7 +1744,7 @@ chknext:
goto strexit;
}
if (!strncmp(vname,"topic",5)) {
- if (sp) strlcpy(sp,Settings.mqtt_topic,glob_script_mem.max_ssize);
+ if (sp) strlcpy(sp,SettingsText(SET_MQTT_TOPIC),glob_script_mem.max_ssize);
goto strexit;
}
#ifdef USE_DISPLAY
@@ -4843,6 +4847,12 @@ bool Xdrv10(uint8_t function)
result = ScriptCommand();
break;
case FUNC_SET_POWER:
+#ifdef SCRIPT_POWER_SECTION
+ if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">P",2,0);
+#else
+ if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">E",2,0);
+#endif
+ break;
case FUNC_RULES_PROCESS:
if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">E",2,mqtt_data);
break;
diff --git a/tasmota/xdrv_11_knx.ino b/tasmota/xdrv_11_knx.ino
index c848bddfe..b52c37e4d 100644
--- a/tasmota/xdrv_11_knx.ino
+++ b/tasmota/xdrv_11_knx.ino
@@ -499,6 +499,7 @@ void KNX_INIT(void)
if (GetUsedInModule(GPIO_DHT22, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; }
if (GetUsedInModule(GPIO_SI7021, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; }
+#if defined(USE_ENERGY_SENSOR)
// Any device with a Power Monitoring
if ( energy_flg != ENERGY_NONE ) {
device_param[KNX_ENERGY_POWER-1].show = true;
@@ -509,6 +510,7 @@ void KNX_INIT(void)
device_param[KNX_ENERGY_CURRENT-1].show = true;
device_param[KNX_ENERGY_POWERFACTOR-1].show = true;
}
+#endif
#ifdef USE_RULES
device_param[KNX_SLOT1-1].show = true;
diff --git a/tasmota/xdrv_12_home_assistant.ino b/tasmota/xdrv_12_home_assistant.ino
index 38c36ead1..58c266c61 100644
--- a/tasmota/xdrv_12_home_assistant.ino
+++ b/tasmota/xdrv_12_home_assistant.ino
@@ -46,7 +46,7 @@ const char HASS_DISCOVER_BUTTON_TOGGLE[] PROGMEM =
const char HASS_DISCOVER_SWITCH_TOGGLE[] PROGMEM =
",\"value_template\":\"{%%if is_state(entity_id,\\\"on\\\")-%%}OFF{%%-else-%%}ON{%%-endif%%}\""; // A switch must maintain his state until the next update
-
+
const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF[] PROGMEM =
",\"value_template\":\"{{value_json.%s}}\"," // STATE
"\"frc_upd\":true," // In ON/OFF case, enable force_update to make automations work
@@ -86,6 +86,7 @@ const char HASS_DISCOVER_SENSOR[] PROGMEM =
"{\"name\":\"%s\"," // dualr2 1 BTN
"\"stat_t\":\"%s\"," // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",")
"\"avty_t\":\"%s\"," // tele/dualr2/LWT
+ "\"frc_upd\":true," // force update for better graph representation
"\"pl_avail\":\"" D_ONLINE "\"," // Online
"\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline
@@ -238,9 +239,9 @@ void HAssAnnounceRelayLight(void)
char *availability_topic = stemp3;
if (i > MAX_FRIENDLYNAMES) {
- snprintf_P(name, sizeof(name), PSTR("%s %d"), Settings.friendlyname[0], i);
+ snprintf_P(name, sizeof(name), PSTR("%s %d"), SettingsText(SET_FRIENDLYNAME1), i);
} else {
- snprintf_P(name, sizeof(name), Settings.friendlyname[i -1]);
+ snprintf_P(name, sizeof(name), SettingsText(SET_FRIENDLYNAME1 +i -1));
}
GetPowerDevice(value_template, i, sizeof(value_template), Settings.flag.device_index_enable); // SetOption26 - Switch between POWER or POWER1
GetTopic_P(command_topic, CMND, mqtt_topic, value_template);
@@ -252,7 +253,7 @@ void HAssAnnounceRelayLight(void)
Shorten(&state_topic, prefix);
Shorten(&availability_topic, prefix);
- Response_P(HASS_DISCOVER_RELAY, name, command_topic, state_topic, value_template, Settings.state_text[0], Settings.state_text[1], availability_topic);
+ Response_P(HASS_DISCOVER_RELAY, name, command_topic, state_topic, value_template, SettingsText(SET_STATE_TXT1), SettingsText(SET_STATE_TXT2), availability_topic);
TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str());
TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix);
@@ -323,7 +324,7 @@ void HAssAnnounceButtonSwitch(uint8_t device, char* topic, uint8_t present, uint
char *availability_topic = stemp2;
char jsoname[8];
- snprintf_P(name, sizeof(name), PSTR("%s %s%d"), Settings.friendlyname[0], key?"Switch":"Button", device+1);
+ snprintf_P(name, sizeof(name), PSTR("%s %s%d"), SettingsText(SET_FRIENDLYNAME1), key?"Switch":"Button", device+1);
snprintf_P(jsoname, sizeof(jsoname), PSTR("%s%d"), key?"SWITCH":"BUTTON", device+1);
GetPowerDevice(value_template, device+1, sizeof(value_template),
key + Settings.flag.device_index_enable); // Force index for Switch 1, Index on Button1 is controlled by SetOption26 - Switch between POWER or POWER1
@@ -338,11 +339,11 @@ void HAssAnnounceButtonSwitch(uint8_t device, char* topic, uint8_t present, uint
TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str());
if (strlen(prefix) > 0 ) TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix);
if (toggle) {
- if (!key) {
- TryResponseAppend_P(HASS_DISCOVER_BUTTON_TOGGLE, PSTR(D_RSLT_STATE), Settings.state_text[toggle?2:1]);
+ if (!key) {
+ TryResponseAppend_P(HASS_DISCOVER_BUTTON_TOGGLE, PSTR(D_RSLT_STATE), SettingsText(SET_STATE_TXT1 + toggle?2:1));
} else {TryResponseAppend_P(HASS_DISCOVER_SWITCH_TOGGLE);}
}
- else TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_ONOFF, PSTR(D_RSLT_STATE), Settings.state_text[toggle?2:1], Settings.state_text[0]);
+ else TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_ONOFF, PSTR(D_RSLT_STATE), SettingsText(SET_STATE_TXT1 + toggle?2:1), SettingsText(SET_STATE_TXT1));
TryResponseAppend_P(PSTR("}"));
}
@@ -351,10 +352,10 @@ void HAssAnnounceButtonSwitch(uint8_t device, char* topic, uint8_t present, uint
void HAssAnnounceSwitches(void)
{
- char sw_topic[sizeof(Settings.switch_topic)];
+ char sw_topic[TOPSZ];
// Send info about buttons
- char *tmp = Settings.switch_topic;
+ char *tmp = SettingsText(SET_MQTT_SWITCH_TOPIC);
Format(sw_topic, tmp, sizeof(sw_topic));
if (!strcmp_P(sw_topic, "0") || strlen(sw_topic) == 0 ) {
for (uint32_t switch_index = 0; switch_index < MAX_SWITCHES; switch_index++) {
@@ -368,7 +369,7 @@ void HAssAnnounceSwitches(void)
// Check if MQTT message will be ON/OFF or TOGGLE
if (Settings.switchmode[switch_index] == FOLLOW || Settings.switchmode[switch_index] == FOLLOW_INV ||
Settings.flag3.button_switch_force_local || // SetOption61 - Force local operation when button/switch topic is set
- !strcmp(mqtt_topic, sw_topic) || !strcmp(Settings.mqtt_grptopic, sw_topic))
+ !strcmp(mqtt_topic, sw_topic) || !strcmp(SettingsText(SET_MQTT_GRP_TOPIC), sw_topic))
{
toggle = 0; // MQTT message will be ON/OFF
}
@@ -380,10 +381,10 @@ void HAssAnnounceSwitches(void)
void HAssAnnounceButtons(void)
{
- char key_topic[sizeof(Settings.button_topic)];
+ char key_topic[TOPSZ];
// Send info about buttons
- char *tmp = Settings.button_topic;
+ char *tmp = SettingsText(SET_MQTT_BUTTON_TOPIC);
Format(key_topic, tmp, sizeof(key_topic));
if (!strcmp_P(key_topic, "0") || strlen(key_topic) == 0 ) {
for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) {
@@ -400,7 +401,7 @@ void HAssAnnounceButtons(void)
// Check if MQTT message will be ON/OFF or TOGGLE
if (Settings.flag3.button_switch_force_local || // SetOption61 - Force local operation when button/switch topic is set
- !strcmp(mqtt_topic, key_topic) || !strcmp(Settings.mqtt_grptopic, key_topic))
+ !strcmp(mqtt_topic, key_topic) || !strcmp(SettingsText(SET_MQTT_GRP_TOPIC), key_topic))
{
toggle = 0; // MQTT message will be ON/OFF
}
@@ -444,7 +445,7 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype)
GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_SENSOR));
}
- snprintf_P(name, sizeof(name), PSTR("%s %s %s"), Settings.friendlyname[0], sensorname, subsensortype);
+ snprintf_P(name, sizeof(name), PSTR("%s %s %s"), SettingsText(SET_FRIENDLYNAME1), sensorname, subsensortype);
GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT);
FindPrefix(state_topic, availability_topic, prefix);
Shorten(&state_topic, prefix);
@@ -457,7 +458,7 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype)
TryResponseAppend_P(HASS_DISCOVER_SENSOR_TEMP, TempUnit(), sensorname);
} else if (!strcmp_P(subsensortype, PSTR(D_JSON_HUMIDITY))) {
TryResponseAppend_P(HASS_DISCOVER_SENSOR_HUM, sensorname);
- } else if (!strcmp_P(subsensortype, PSTR(D_JSON_PRESSURE))
+ } else if (!strcmp_P(subsensortype, PSTR(D_JSON_PRESSURE))
|| !strcmp_P(subsensortype, PSTR(D_JSON_PRESSUREATSEALEVEL))){
TryResponseAppend_P(HASS_DISCOVER_SENSOR_PRESS, PressureUnit().c_str(), sensorname, subsensortype);
} else if (!strcmp_P(subsensortype, PSTR(D_JSON_TOTAL))
@@ -547,7 +548,7 @@ void HAssAnnounceStatusSensor(void)
char *state_topic = stemp1;
char *availability_topic = stemp2;
- snprintf_P(name, sizeof(name), PSTR("%s status"), Settings.friendlyname[0]);
+ snprintf_P(name, sizeof(name), PSTR("%s status"), SettingsText(SET_FRIENDLYNAME1));
GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_HASS_STATE));
GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT);
FindPrefix(state_topic, availability_topic, prefix);
@@ -557,7 +558,7 @@ void HAssAnnounceStatusSensor(void)
Response_P(HASS_DISCOVER_SENSOR, name, state_topic, availability_topic);
TryResponseAppend_P(HASS_DISCOVER_SENSOR_HASS_STATUS, state_topic);
TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO, unique_id, ESP.getChipId(), WiFi.macAddress().c_str(),
- Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image);
+ SettingsText(SET_FRIENDLYNAME1), ModuleName().c_str(), my_version, my_image);
TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix);
TryResponseAppend_P(PSTR("}"));
}
@@ -587,8 +588,8 @@ void HAssDiscovery(void)
Settings.flag.decimal_text = 1; // SetOption17 - Switch between decimal or hexadecimal output - Respond with decimal color values
Settings.flag3.hass_tele_on_power = 1; // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT - send tele/STATE message as stat/RESULT
// Settings.light_scheme = 0; // To just control color it needs to be Scheme 0
- if (strcmp_P(Settings.mqtt_fulltopic, PSTR("%topic%/%prefix%/"))) {
- strncpy_P(Settings.mqtt_fulltopic, PSTR("%topic%/%prefix%/"), sizeof(Settings.mqtt_fulltopic));
+ if (strcmp_P(SettingsText(SET_MQTT_FULLTOPIC), PSTR("%topic%/%prefix%/"))) {
+ SettingsUpdateText(SET_MQTT_FULLTOPIC, "%topic%/%prefix%/");
restart_flag = 2;
return; // As full topic has changed do restart first before sending discovery data
}
diff --git a/tasmota/xdrv_13_display.ino b/tasmota/xdrv_13_display.ino
index 42bb9858b..b34b8ed27 100644
--- a/tasmota/xdrv_13_display.ino
+++ b/tasmota/xdrv_13_display.ino
@@ -1008,7 +1008,7 @@ void DisplayLogBufferInit(void)
snprintf_P(buffer, sizeof(buffer), PSTR(D_CMND_HOSTNAME " %s"), my_hostname);
DisplayLogBufferAdd(buffer);
- snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_SSID " %s"), Settings.sta_ssid[Settings.sta_active]);
+ snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_SSID " %s"), SettingsText(SET_STASSID1 + Settings.sta_active));
DisplayLogBufferAdd(buffer);
snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_MAC " %s"), WiFi.macAddress().c_str());
DisplayLogBufferAdd(buffer);
@@ -1196,7 +1196,7 @@ void DisplayMqttSubscribe(void)
char ntopic[TOPSZ];
ntopic[0] = '\0';
- strlcpy(stopic, Settings.mqtt_fulltopic, sizeof(stopic));
+ strlcpy(stopic, SettingsText(SET_MQTT_FULLTOPIC), sizeof(stopic));
char *tp = strtok(stopic, "/");
while (tp != nullptr) {
if (!strcmp_P(tp, MQTT_TOKEN_PREFIX)) {
@@ -1205,7 +1205,7 @@ void DisplayMqttSubscribe(void)
strncat_P(ntopic, PSTR("+/"), sizeof(ntopic) - strlen(ntopic) -1); // Add single-level wildcards
tp = strtok(nullptr, "/");
}
- strncat(ntopic, Settings.mqtt_prefix[2], sizeof(ntopic) - strlen(ntopic) -1); // Subscribe to tele messages
+ strncat(ntopic, SettingsText(SET_MQTTPREFIX3), sizeof(ntopic) - strlen(ntopic) -1); // Subscribe to tele messages
strncat_P(ntopic, PSTR("/#"), sizeof(ntopic) - strlen(ntopic) -1); // Add multi-level wildcard
MqttSubscribe(ntopic);
disp_subscribed = true;
@@ -1219,7 +1219,7 @@ bool DisplayMqttData(void)
if (disp_subscribed) {
char stopic[TOPSZ];
- snprintf_P(stopic, sizeof(stopic) , PSTR("%s/"), Settings.mqtt_prefix[2]); // tele/
+ snprintf_P(stopic, sizeof(stopic) , PSTR("%s/"), SettingsText(SET_MQTTPREFIX3)); // tele/
char *tp = strstr(XdrvMailbox.topic, stopic);
if (tp) { // tele/tasmota/SENSOR
if (Settings.display_mode &0x04) {
diff --git a/tasmota/xdrv_17_rcswitch.ino b/tasmota/xdrv_17_rcswitch.ino
index dfe5dc66a..156535876 100644
--- a/tasmota/xdrv_17_rcswitch.ino
+++ b/tasmota/xdrv_17_rcswitch.ino
@@ -85,6 +85,7 @@ void RfInit(void)
mySwitch.enableTransmit(pin[GPIO_RFSEND]);
}
if (pin[GPIO_RFRECV] < 99) {
+ pinMode( pin[GPIO_RFRECV], INPUT);
mySwitch.enableReceive(pin[GPIO_RFRECV]);
}
}
diff --git a/tasmota/xdrv_20_hue.ino b/tasmota/xdrv_20_hue.ino
index 254fa4d99..1d13ee263 100644
--- a/tasmota/xdrv_20_hue.ino
+++ b/tasmota/xdrv_20_hue.ino
@@ -365,17 +365,18 @@ void HueLightStatus1(uint8_t device, String *response)
// Any device whose friendly name start with "$" is considered hidden
bool HueActive(uint8_t device) {
if (device > MAX_FRIENDLYNAMES) { device = MAX_FRIENDLYNAMES; }
- return '$' != Settings.friendlyname[device-1][0];
+// return '$' != Settings.friendlyname[device-1][0];
+ return '$' != *SettingsText(SET_FRIENDLYNAME1 +device -1);
}
void HueLightStatus2(uint8_t device, String *response)
{
*response += FPSTR(HUE_LIGHTS_STATUS_JSON2);
if (device <= MAX_FRIENDLYNAMES) {
- response->replace("{j1", Settings.friendlyname[device-1]);
+ response->replace("{j1", SettingsText(SET_FRIENDLYNAME1 +device -1));
} else {
char fname[33];
- strcpy(fname, Settings.friendlyname[MAX_FRIENDLYNAMES-1]);
+ strcpy(fname, SettingsText(SET_FRIENDLYNAME1 + MAX_FRIENDLYNAMES -1));
uint32_t fname_len = strlen(fname);
if (fname_len > 30) { fname_len = 30; }
fname[fname_len++] = '-';
diff --git a/tasmota/xdrv_21_wemo.ino b/tasmota/xdrv_21_wemo.ino
index 4a50560e2..13e867ae6 100644
--- a/tasmota/xdrv_21_wemo.ino
+++ b/tasmota/xdrv_21_wemo.ino
@@ -241,7 +241,7 @@ void HandleUpnpSetupWemo(void)
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_SETUP));
String setup_xml = FPSTR(WEMO_SETUP_XML);
- setup_xml.replace("{x1", Settings.friendlyname[0]);
+ setup_xml.replace("{x1", SettingsText(SET_FRIENDLYNAME1));
setup_xml.replace("{x2", WemoUuid());
setup_xml.replace("{x3", WemoSerialnumber());
WSSend(200, CT_XML, setup_xml);
diff --git a/tasmota/xdrv_23_zigbee_0_constants.ino b/tasmota/xdrv_23_zigbee_0_constants.ino
index 996d877f8..0c74c9d8a 100644
--- a/tasmota/xdrv_23_zigbee_0_constants.ino
+++ b/tasmota/xdrv_23_zigbee_0_constants.ino
@@ -19,8 +19,6 @@
#ifdef USE_ZIGBEE
-#define ZIGBEE_VERBOSE // output versbose MQTT Zigbee logs. Will remain active for now
-
typedef uint64_t Z_IEEEAddress;
typedef uint16_t Z_ShortAddress;
diff --git a/tasmota/xdrv_23_zigbee_1_headers.ino b/tasmota/xdrv_23_zigbee_1_headers.ino
new file mode 100644
index 000000000..b017d8e2e
--- /dev/null
+++ b/tasmota/xdrv_23_zigbee_1_headers.ino
@@ -0,0 +1,26 @@
+/*
+ xdrv_23_zigbee_1_headers.ino - zigbee support for Tasmota
+
+ Copyright (C) 2019 Theo Arends and Stephan Hadinger
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ 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_ZIGBEE
+
+// contains some definitions for functions used before their declarations
+
+void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool disableDefResp = true, uint8_t transacId = 1);
+
+#endif // USE_ZIGBEE
diff --git a/tasmota/xdrv_23_zigbee_3_devices.ino b/tasmota/xdrv_23_zigbee_3_devices.ino
index f76c882c7..de13990c2 100644
--- a/tasmota/xdrv_23_zigbee_3_devices.ino
+++ b/tasmota/xdrv_23_zigbee_3_devices.ino
@@ -22,6 +22,9 @@
#include
#include