diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 0baecb42a..2ce866863 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -47,10 +47,23 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 7.1.2 Betty +### Version 7.1.2.4 -- 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) +- 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 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) 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 4bb5447ad..8f5954e66 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,15 +1,36 @@ ## Unreleased (development) +### 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) +- 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 -- Add command ``SerialConfig 0..23`` or ``SerialConfig 8N1`` to select Serial Config (#7108) +- 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 rule var ``%topic%`` (#5522) -- Add rule triggers ``tele_power1#state`` and multiple ``tele-wifi1#xxx`` (#7093) -- Add experimental support for stepper motor shutter control -- Add optional USE_MQTT_TLS to tasmota-minimal.bin (#7115) +- 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) ## Released diff --git a/tasmota/i18n.h b/tasmota/i18n.h index dfa998474..f4fde64b3 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" @@ -333,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" diff --git a/tasmota/language/bg-BG.h b/tasmota/language/bg-BG.h index 4bc5feebd..d39aba5f6 100644 --- a/tasmota/language/bg-BG.h +++ b/tasmota/language/bg-BG.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/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..236df351b 100644 --- a/tasmota/language/fr-FR.h +++ b/tasmota/language/fr-FR.h @@ -71,6 +71,7 @@ #define D_COLDLIGHT "Froid" #define D_COMMAND "Commande" #define D_CONNECTED "Connecté" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNT "Compte" #define D_COUNTER "Compteur" #define D_CURRENT "Courant" // As in Voltage and Current 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 f464a24cb..524a6ac19 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 @@ -433,12 +433,11 @@ 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 free_ea4[326]; // EA6 + uint8_t free_ec1[293]; // EC1 uint32_t i2c_drivers[3]; // FEC I2cDriver uint32_t cfg_timestamp; // FF8 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index f6113be46..cc6066c5a 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, @@ -718,6 +722,7 @@ void SettingsDefaultSet2(void) Settings.weblog_level = WEB_LOG_LEVEL; strlcpy(Settings.web_password, WEB_PASSWORD, sizeof(Settings.web_password)); Settings.flag3.mdns_enabled = MDNS_ENABLED; + strlcpy(Settings.cors_domain, CORS_DOMAIN, sizeof(Settings.cors_domain)); // Button // Settings.flag.button_restrict = 0; @@ -1176,6 +1181,13 @@ void SettingsDelta(void) 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; + } + } Settings.version = VERSION; SettingsSave(1); diff --git a/tasmota/support.ino b/tasmota/support.ino index f44d14eb7..3ecc9b179 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 \*********************************************************************************************/ @@ -383,6 +377,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; diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 070409566..ec8de9126 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -334,6 +334,9 @@ void CmndStatus(void) 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 @@ -369,7 +372,7 @@ void CmndStatus(void) 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, + 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")); } @@ -483,6 +489,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 @@ -564,6 +579,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(); 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_statistics.ino b/tasmota/support_statistics.ino new file mode 100644 index 000000000..3239c5b93 --- /dev/null +++ b/tasmota/support_statistics.ino @@ -0,0 +1,88 @@ +/* + 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 +\*********************************************************************************************/ + +struct STATS { +// uint32_t str_size = 1151; // Total number of characters reserved as char array in Settings + uint32_t str_len = 0; // Total number of characters used within char array + uint32_t str_char = 0; // Total number of character '|' within all char arrays +} Stats; + +void StatisticsChar(const char* text) +{ + uint32_t len = strlen(text); + Stats.str_len += len; + for (uint32_t i = 0; i < len; i++) { + if ('|' == text[i]) { // Text string separator as currently used in GetTextIndexed() + Stats.str_char++; + } + } +} + +String GetStatistics(void) +{ + for (uint32_t i = 0; i < 2; i++) { + StatisticsChar(Settings.sta_ssid[i]); + StatisticsChar(Settings.sta_pwd[i]); + } + for (uint32_t i = 0; i < 3; i++) { + StatisticsChar(Settings.mqtt_prefix[i]); + StatisticsChar(Settings.ntp_server[i]); + } + for (uint32_t i = 0; i < 4; i++) { + StatisticsChar(Settings.state_text[i]); + StatisticsChar(Settings.friendlyname[i]); + } + for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { + StatisticsChar(Settings.mems[i]); + } + StatisticsChar(Settings.ota_url); + StatisticsChar(Settings.hostname); + StatisticsChar(Settings.syslog_host); + StatisticsChar(Settings.mqtt_host); + StatisticsChar(Settings.mqtt_client); + StatisticsChar(Settings.mqtt_user); + StatisticsChar(Settings.mqtt_pwd); + StatisticsChar(Settings.mqtt_topic); + StatisticsChar(Settings.button_topic); + StatisticsChar(Settings.switch_topic); + StatisticsChar(Settings.mqtt_grptopic); + StatisticsChar(Settings.web_password); + StatisticsChar(Settings.mqtt_fulltopic); + StatisticsChar(Settings.cors_domain); + + char data[40]; + snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/1151/%d\""), Stats.str_len, Stats.str_char); // 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 2f54cec7d..34ce9f5dc 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -565,7 +565,7 @@ void MqttShowState(void) if (i == LightDevice()) { LightState(1); } // call it only once } else { #endif - ResponseAppend_P(PSTR(",\"%s\":{\"STATE\":\"%s\"}"), GetPowerDevice(stemp1, i, sizeof(stemp1), Settings.flag.device_index_enable), // SetOption26 - Switch between POWER or POWER1 + ResponseAppend_P(PSTR(",\"%s\":\"%s\""), GetPowerDevice(stemp1, i, sizeof(stemp1), Settings.flag.device_index_enable), // SetOption26 - Switch between POWER or POWER1 GetStateText(bitRead(power, i-1))); #ifdef USE_SONOFF_IFAN if (IsModuleIfan()) { @@ -583,8 +583,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, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), + WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.RSSI(), WifiLinkCount(), WifiDowntime().c_str()); } void MqttPublishTeleState(void) @@ -609,7 +610,7 @@ bool MqttShowSensor(void) if (pin[GPIO_SWT1 +i] < 99) { #endif // USE_TM1638 bool swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i])); - ResponseAppend_P(PSTR(",\"" D_JSON_SWITCH "%d\":{\"STATE\":\"%s\"}"), i +1, GetStateText(swm ^ SwitchLastState(i))); + ResponseAppend_P(PSTR(",\"" D_JSON_SWITCH "%d\":\"%s\""), i +1, GetStateText(swm ^ SwitchLastState(i))); } } XsnsCall(FUNC_JSON_APPEND); @@ -1285,15 +1286,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..06d922b26 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -617,6 +617,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..c31bfad83 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 diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index 929924840..a0cbe1e41 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 = 0x07010202; +const uint32_t VERSION = 0x07010204; #endif // _TASMOTA_VERSION_H_ diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 48e2cd26a..0a72da399 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 = "
 " D_LOGGING_PARAMETERS " " @@ -673,8 +674,8 @@ bool HttpCheckPriviledgedAccess(bool autorequestauth = true) void HttpHeaderCors(void) { - if (Settings.flag3.cors_enabled) { // SetOption73 - Enable HTTP CORS - WebServer->sendHeader(F("Access-Control-Allow-Origin"), F("*")); + if (Settings.cors_domain[0] != 0) { + WebServer->sendHeader(F("Access-Control-Allow-Origin"), Settings.cors_domain); } } @@ -1106,6 +1107,21 @@ void HandleRoot(void) } else { #endif // USE_SONOFF_IFAN for (uint32_t idx = 1; idx <= devices_present; idx++) { +#ifdef USE_SHUTTER + if (Settings.flag3.shutter_mode) { // SetOption80 - Enable shutter support + bool shutter_used = false; + for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { + if (Settings.shutter_startrelay[i] == (((idx -1) & 0xFFFFFFFE) +1)) { + shutter_used = true; + break; + } + } + if (shutter_used) { + WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, (idx % 2) ? "▲" : "▼" , ""); + continue; + } + } +#endif // USE_SHUTTER snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx); WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, (devices_present < 5) ? D_BUTTON_TOGGLE : "", (devices_present > 1) ? stemp : ""); } @@ -1638,11 +1654,11 @@ void HandleWifiConfiguration(void) int quality = WifiGetRssiAsQuality(WiFi.RSSI(indices[i])); int auth = WiFi.encryptionType(indices[i]); char encryption[20]; - WSContentSend_P(PSTR("
%s (%d) %s %d%%
"), + WSContentSend_P(PSTR("
%s (%d) %s %d%% (%d dBm)
"), HtmlEscape(WiFi.SSID(indices[i])).c_str(), WiFi.channel(indices[i]), GetTextIndexed(encryption, sizeof(encryption), auth +1, kEncryptionType), - quality + quality, WiFi.RSSI() ); delay(0); @@ -1654,7 +1670,7 @@ void HandleWifiConfiguration(void) } // As WIFI_HOSTNAME may contain %s-%04d it cannot be part of HTTP_FORM_WIFI where it will exception - WSContentSend_P(HTTP_FORM_WIFI, Settings.sta_ssid[0], Settings.sta_ssid[1], WIFI_HOSTNAME, WIFI_HOSTNAME, Settings.hostname); + WSContentSend_P(HTTP_FORM_WIFI, Settings.sta_ssid[0], Settings.sta_ssid[1], WIFI_HOSTNAME, WIFI_HOSTNAME, Settings.hostname, Settings.cors_domain); WSContentSend_P(HTTP_FORM_END); } @@ -1678,6 +1694,8 @@ void WifiSaveSettings(void) if (strstr(Settings.hostname, "%") != nullptr) { strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); } + WebGetArg("c", tmp, sizeof(tmp)); + strlcpy(Settings.cors_domain, (!strlen(tmp)) ? CORS_DOMAIN : tmp, sizeof(Settings.cors_domain)); WebGetArg("s1", tmp, sizeof(tmp)); strlcpy(Settings.sta_ssid[0], (!strlen(tmp)) ? STA_SSID1 : tmp, sizeof(Settings.sta_ssid[0])); WebGetArg("s2", tmp, sizeof(tmp)); @@ -1686,7 +1704,7 @@ void WifiSaveSettings(void) strlcpy(Settings.sta_pwd[0], (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? Settings.sta_pwd[0] : tmp, sizeof(Settings.sta_pwd[0])); WebGetArg("p2", tmp, sizeof(tmp)); strlcpy(Settings.sta_pwd[1], (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? Settings.sta_pwd[1] : tmp, sizeof(Settings.sta_pwd[1])); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s"), Settings.hostname, Settings.sta_ssid[0], Settings.sta_ssid[1]); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s, " D_CMND_CORS " %s"), Settings.hostname, Settings.sta_ssid[0], Settings.sta_ssid[1], Settings.cors_domain); } /*-------------------------------------------------------------------------------------------*/ @@ -1970,7 +1988,7 @@ void HandleInformation(void) WSContentSend_P(PSTR("}1" D_FRIENDLY_NAME " %d}2%s"), i +1, Settings.friendlyname[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, Settings.sta_ssid[Settings.sta_active], WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.RSSI()); WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), my_hostname, (Wifi.mdns_begun) ? ".local" : ""); if (static_cast(WiFi.localIP()) != 0) { WSContentSend_P(PSTR("}1" D_IP_ADDRESS "}2%s"), WiFi.localIP().toString().c_str()); @@ -2698,7 +2716,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 +2725,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 @@ -2828,6 +2846,14 @@ void CmndWebSensor(void) ResponseJsonEnd(); } +void CmndCors(void) +{ + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.cors_domain))) { + strlcpy(Settings.cors_domain, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? WEB_PASSWORD : XdrvMailbox.data, sizeof(Settings.cors_domain)); + } + ResponseCmndChar(Settings.cors_domain); +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/ diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 49f35d579..6d68a346e 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -555,7 +555,13 @@ void MqttConnected(void) 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) { @@ -1071,6 +1077,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; 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 441722662..ac771f0d7 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/xdrv_10_rules.ino @@ -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++) { diff --git a/tasmota/xdrv_12_home_assistant.ino b/tasmota/xdrv_12_home_assistant.ino index 38c36ead1..22c0e370e 100644 --- a/tasmota/xdrv_12_home_assistant.ino +++ b/tasmota/xdrv_12_home_assistant.ino @@ -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 diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index f47b53376..c97318c5f 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -194,10 +194,10 @@ void ShutterInit(void) } } else { Shutter.mode = SHT_OFF_ON__OPEN_CLOSE; - if (pin[GPIO_PWM1 ]+i < 99) { + if (pin[GPIO_PWM1+i] < 99) { Shutter.pwm_frequency = 0; analogWriteFreq(Shutter.pwm_frequency); - analogWrite(pin[GPIO_PWM1]+i, 50); + analogWrite(pin[GPIO_PWM1+i], 50); } } @@ -257,11 +257,11 @@ void ShutterUpdatePosition(void) // Counter should be initiated to 0 to count movement. // 0..1000 in step 100 = 10 steps with 0.05 sec = 0.5sec total ramp time from start to // full speed. - if (pin[GPIO_PWM1]+i < 99 && Shutter.pwm_frequency != Shutter.max_pwm_frequency) { + if (pin[GPIO_PWM1+i] < 99 && Shutter.pwm_frequency != Shutter.max_pwm_frequency) { Shutter.pwm_frequency += Shutter.max_pwm_frequency/20; Shutter.pwm_frequency = (Shutter.pwm_frequency > Shutter.max_pwm_frequency ? Shutter.max_pwm_frequency : Shutter.pwm_frequency); analogWriteFreq(Shutter.pwm_frequency); - analogWrite(pin[GPIO_PWM1]+i, 50); + analogWrite(pin[GPIO_PWM1+i], 50); } Shutter.real_position[i] = Shutter.start_position[i] + ( (Shutter.time[i] - Shutter.motordelay[i]) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); @@ -287,21 +287,21 @@ void ShutterUpdatePosition(void) // This is a failsafe configuration. Relay1 ON/OFF Relay2 -1/1 direction // Only allow PWM microstepping if PWM and COUNTER are defined. // see wiki to connect PWM and COUNTER - if (pin[GPIO_PWM1 ]+i < 99 && pin[GPIO_CNTR1 ]+i < 99 ) { + if (pin[GPIO_PWM1+i] < 99 && pin[GPIO_CNTR1+i] < 99 ) { int16_t missing_steps = ((Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) - RtcSettings.pulse_counter[i]; Shutter.pwm_frequency = 0; //slow down for acurate position analogWriteFreq(500); - analogWrite(pin[GPIO_PWM1]+i, 50); + analogWrite(pin[GPIO_PWM1+i], 50); //prepare for stop PWM Shutter.motordelay[i] = -2 + Shutter.motordelay[i] + missing_steps/(Shutter.max_pwm_frequency/20); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Missing steps %d, adjust motordelay %d, counter %d, temp realpos %d"), missing_steps, Shutter.motordelay[i],RtcSettings.pulse_counter[i] ,Shutter.real_position[i]); - Settings.shutter_motordelay[i]=Shutter.motordelay[i]; + Settings.shutter_motordelay[i]=(missing_steps > 0 ? Shutter.motordelay[i] : 0); analogWriteFreq(0); while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) { delay(1); } - analogWrite(pin[GPIO_PWM1]+i, 0); + analogWrite(pin[GPIO_PWM1+i], 0); Shutter.real_position[i] = ((int32_t)RtcSettings.pulse_counter[i]*Shutter.direction[i]*2000 / Shutter.max_pwm_frequency)+Shutter.start_position[i]; //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:Realpos %d, pulsecount %d, startpos %d, int32 %d"), Shutter.real_position[i],RtcSettings.pulse_counter[i], Shutter.start_position[i], ((int32_t)RtcSettings.pulse_counter[i]*Shutter.direction[i]*2000 / Shutter.max_pwm_frequency)); @@ -357,12 +357,12 @@ void ShutterStartInit(uint8_t index, uint8_t direction, int32_t target_pos) Shutter.target_position[index] = target_pos; Shutter.start_position[index] = Shutter.real_position[index]; Shutter.time[index] = 0; - if (pin[GPIO_PWM1]+index < 99) { + if (pin[GPIO_PWM1+index] < 99) { Shutter.pwm_frequency = 0; analogWriteFreq(Shutter.pwm_frequency); - analogWrite(pin[GPIO_PWM1]+index, 0); + analogWrite(pin[GPIO_PWM1+index], 0); // can be operated without counter, but then not that acurate. - if (pin[GPIO_CNTR1]+index < 99) { + if (pin[GPIO_CNTR1+index] < 99) { RtcSettings.pulse_counter[index] = 0; } } @@ -459,6 +459,10 @@ void ShutterSetPosition(uint8_t device, uint8_t position) void CmndShutterOpen(void) { + //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Payload close: %d, index %d"), XdrvMailbox.payload, XdrvMailbox.index); + if ( XdrvMailbox.index == 1 && XdrvMailbox.payload != -99) { + XdrvMailbox.index = XdrvMailbox.payload; + } XdrvMailbox.payload = 100; last_source = SRC_WEBGUI; CmndShutterPosition(); @@ -466,6 +470,10 @@ void CmndShutterOpen(void) void CmndShutterClose(void) { + //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Payload open: %d, index %d"), XdrvMailbox.payload, XdrvMailbox.index); + if ( XdrvMailbox.index == 1 && XdrvMailbox.payload != -99) { + XdrvMailbox.index = XdrvMailbox.payload; + } XdrvMailbox.payload = 0; XdrvMailbox.data_len = 0; last_source = SRC_WEBGUI; @@ -475,6 +483,9 @@ void CmndShutterClose(void) void CmndShutterStop(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ( XdrvMailbox.index == 1 && XdrvMailbox.payload != -99) { + XdrvMailbox.index = XdrvMailbox.payload; + } uint32_t index = XdrvMailbox.index -1; if (Shutter.direction[index] != 0) { diff --git a/tasmota/xsns_06_dht.ino b/tasmota/xsns_06_dht.ino index c4e877de9..6ef7055ac 100644 --- a/tasmota/xsns_06_dht.ino +++ b/tasmota/xsns_06_dht.ino @@ -28,7 +28,7 @@ #define XSNS_06 6 -#define DHT_MAX_SENSORS 3 +#define DHT_MAX_SENSORS 4 #define DHT_MAX_RETRY 8 uint32_t dht_max_cycles; diff --git a/tasmota/xsns_32_mpu6050.ino b/tasmota/xsns_32_mpu6050.ino index 48cd201bc..bcec100b0 100644 --- a/tasmota/xsns_32_mpu6050.ino +++ b/tasmota/xsns_32_mpu6050.ino @@ -57,6 +57,7 @@ int16_t MPU_6050_temperature = 0; VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements VectorFloat gravity; // [x, y, z] gravity vector float euler[3]; // [psi, theta, phi] Euler angle container + float yawPitchRoll[3]; // [yaw, pitch roll] Yaw-pitch-roll container } MPU6050_DMP; MPU6050_DMP MPU6050_dmp; @@ -68,7 +69,7 @@ MPU6050 mpu6050; void MPU_6050PerformReading(void) { #ifdef USE_MPU6050_DMP - mpu6050.resetFIFO(); // with a default dampling rate of 200Hz, we create a delay of approx. 5ms with a complete read cycle + mpu6050.resetFIFO(); // with a default sampling rate of 200Hz, we create a delay of approx. 5ms with a complete read cycle MPU6050_dmp.fifoCount = mpu6050.getFIFOCount(); while (MPU6050_dmp.fifoCount < MPU6050_dmp.packetSize) MPU6050_dmp.fifoCount = mpu6050.getFIFOCount(); mpu6050.getFIFOBytes(MPU6050_dmp.fifoBuffer, MPU6050_dmp.packetSize); @@ -79,6 +80,7 @@ void MPU_6050PerformReading(void) mpu6050.dmpGetAccel(&MPU6050_dmp.aa, MPU6050_dmp.fifoBuffer); mpu6050.dmpGetGravity(&MPU6050_dmp.gravity, &MPU6050_dmp.q); mpu6050.dmpGetLinearAccel(&MPU6050_dmp.aaReal, &MPU6050_dmp.aa, &MPU6050_dmp.gravity); + mpu6050.dmpGetYawPitchRoll(MPU6050_dmp.yawPitchRoll, &MPU6050_dmp.q, &MPU6050_dmp.gravity); MPU_6050_gx = MPU6050_dmp.euler[0] * 180/M_PI; MPU_6050_gy = MPU6050_dmp.euler[1] * 180/M_PI; MPU_6050_gz = MPU6050_dmp.euler[2] * 180/M_PI; @@ -145,6 +147,10 @@ void MPU_6050Detect(void) } } +#define D_YAW "Yaw" +#define D_PITCH "Pitch" +#define D_ROLL "Roll" + #ifdef USE_WEBSERVER const char HTTP_SNS_AXIS[] PROGMEM = "{s}" D_SENSOR_MPU6050 " " D_AX_AXIS "{m}%s{e}" // {s} = , {m} = , {e} = @@ -153,6 +159,12 @@ const char HTTP_SNS_AXIS[] PROGMEM = "{s}" D_SENSOR_MPU6050 " " D_GX_AXIS "{m}%s{e}" // {s} = , {m} = , {e} = "{s}" D_SENSOR_MPU6050 " " D_GY_AXIS "{m}%s{e}" // {s} = , {m} = , {e} = "{s}" D_SENSOR_MPU6050 " " D_GZ_AXIS "{m}%s{e}"; // {s} = , {m} = , {e} = +#ifdef USE_MPU6050_DMP +const char HTTP_SNS_YPR[] PROGMEM = + "{s}" D_SENSOR_MPU6050 " " D_YAW "{m}%s{e}" // {s} = , {m} = , {e} = + "{s}" D_SENSOR_MPU6050 " " D_PITCH "{m}%s{e}" // {s} = , {m} = , {e} = + "{s}" D_SENSOR_MPU6050 " " D_ROLL "{m}%s{e}"; // {s} = , {m} = , {e} = +#endif // USE_MPU6050_DMP #endif // USE_WEBSERVER #define D_JSON_AXIS_AX "AccelXAxis" @@ -161,6 +173,9 @@ const char HTTP_SNS_AXIS[] PROGMEM = #define D_JSON_AXIS_GX "GyroXAxis" #define D_JSON_AXIS_GY "GyroYAxis" #define D_JSON_AXIS_GZ "GyroZAxis" +#define D_JSON_YAW "Yaw" +#define D_JSON_PITCH "Pitch" +#define D_JSON_ROLL "Roll" void MPU_6050Show(bool json) { @@ -181,6 +196,14 @@ void MPU_6050Show(bool json) dtostrfd(MPU_6050_gy, Settings.flag2.axis_resolution, axis_gy); char axis_gz[33]; dtostrfd(MPU_6050_gz, Settings.flag2.axis_resolution, axis_gz); +#ifdef USE_MPU6050_DMP + char axis_yaw[33]; + dtostrfd(MPU6050_dmp.yawPitchRoll[0] / PI * 180.0, Settings.flag2.axis_resolution, axis_yaw); + char axis_pitch[33]; + dtostrfd(MPU6050_dmp.yawPitchRoll[1] / PI * 180.0, Settings.flag2.axis_resolution, axis_pitch); + char axis_roll[33]; + dtostrfd(MPU6050_dmp.yawPitchRoll[2] / PI * 180.0, Settings.flag2.axis_resolution, axis_roll); +#endif // USE_MPU6050_DMP if (json) { char json_axis_ax[25]; @@ -195,8 +218,20 @@ void MPU_6050Show(bool json) snprintf_P(json_axis_gy, sizeof(json_axis_gy), PSTR(",\"" D_JSON_AXIS_GY "\":%s"), axis_gy); char json_axis_gz[25]; snprintf_P(json_axis_gz, sizeof(json_axis_gz), PSTR(",\"" D_JSON_AXIS_GZ "\":%s"), axis_gz); +#ifdef USE_MPU6050_DMP + char json_ypr_y[25]; + snprintf_P(json_ypr_y, sizeof(json_ypr_y), PSTR(",\"" D_JSON_YAW "\":%s"), axis_yaw); + char json_ypr_p[25]; + snprintf_P(json_ypr_p, sizeof(json_ypr_p), PSTR(",\"" D_JSON_PITCH "\":%s"), axis_pitch); + char json_ypr_r[25]; + snprintf_P(json_ypr_r, sizeof(json_ypr_r), PSTR(",\"" D_JSON_ROLL "\":%s"), axis_roll); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s%s%s%s}"), + D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz, + json_ypr_y, json_ypr_p, json_ypr_r); +#else ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s}"), D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz); +#endif // USE_MPU6050_DMP #ifdef USE_DOMOTICZ DomoticzSensor(DZ_TEMP, temperature); #endif // USE_DOMOTICZ @@ -204,6 +239,9 @@ void MPU_6050Show(bool json) } else { WSContentSend_PD(HTTP_SNS_TEMP, D_SENSOR_MPU6050, temperature, TempUnit()); WSContentSend_PD(HTTP_SNS_AXIS, axis_ax, axis_ay, axis_az, axis_gx, axis_gy, axis_gz); +#ifdef USE_MPU6050_DMP + WSContentSend_PD(HTTP_SNS_YPR, axis_yaw, axis_pitch, axis_roll); +#endif // USE_MPU6050_DMP #endif // USE_WEBSERVER } } diff --git a/tasmota/xsns_34_hx711.ino b/tasmota/xsns_34_hx711.ino index d9076f61d..469a5bb68 100644 --- a/tasmota/xsns_34_hx711.ino +++ b/tasmota/xsns_34_hx711.ino @@ -57,6 +57,7 @@ #define D_JSON_WEIGHT_MAX "WeightMax" #define D_JSON_WEIGHT_ITEM "WeightItem" #define D_JSON_WEIGHT_CHANGE "WeightChange" +#define D_JSON_WEIGHT_RAW "WeightRaw" enum HxCalibrationSteps { HX_CAL_END, HX_CAL_LIMBO, HX_CAL_FINISH, HX_CAL_FAIL, HX_CAL_DONE, HX_CAL_FIRST, HX_CAL_RESET, HX_CAL_START }; @@ -64,8 +65,10 @@ const char kHxCalibrationStates[] PROGMEM = D_HX_CAL_FAIL "|" D_HX_CAL_DONE "|" struct HX { long weight = 0; + long raw = 0; long last_weight = 0; long sum_weight = 0; + long sum_raw = 0; long offset = 0; long scale = 1; long weight_diff = 0; @@ -272,13 +275,17 @@ void HxInit(void) void HxEvery100mSecond(void) { - Hx.sum_weight += HxRead(); + long raw = HxRead(); + Hx.sum_raw += raw; + Hx.sum_weight += raw; Hx.sample_count++; if (HX_SAMPLES == Hx.sample_count) { long average = Hx.sum_weight / Hx.sample_count; // grams + long raw_average = Hx.sum_raw / Hx.sample_count; // grams long value = average - Hx.offset; // grams Hx.weight = value / Hx.scale; // grams + Hx.raw = raw_average / Hx.scale; if (Hx.weight < 0) { if (Settings.energy_frequency_calibration) { long difference = Settings.energy_frequency_calibration + Hx.weight; @@ -367,6 +374,7 @@ void HxEvery100mSecond(void) } Hx.sum_weight = 0; + Hx.sum_raw = 0; Hx.sample_count = 0; } } @@ -405,7 +413,7 @@ void HxShow(bool json) dtostrfd(weight, Settings.flag2.weight_resolution, weight_chr); if (json) { - ResponseAppend_P(PSTR(",\"HX711\":{\"" D_JSON_WEIGHT "\":%s%s}"), weight_chr, scount); + ResponseAppend_P(PSTR(",\"HX711\":{\"" D_JSON_WEIGHT "\":%s%s, \"" D_JSON_WEIGHT_RAW "\":%d}"), weight_chr, scount, Hx.raw); #ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_HX711_WEIGHT, weight_chr); @@ -565,4 +573,4 @@ bool Xsns34(uint8_t function) return result; } -#endif // USE_HX711 \ No newline at end of file +#endif // USE_HX711