From a305f435e80934f3cc56b9094eec6ff4b45f1cbb Mon Sep 17 00:00:00 2001 From: George Date: Tue, 19 May 2020 15:15:39 +1000 Subject: [PATCH 01/20] First pass at led pwm settings * Added settings for ledpwm_on and ledpwm_off with defaults that mimic current digitalwrite function * Changed ledpoweridx from digitalwrite to analogwrite * Add commands to change new settings --- tasmota/i18n.h | 4 ++++ tasmota/settings.h | 4 +++- tasmota/settings.ino | 9 +++++++++ tasmota/support_command.ino | 28 ++++++++++++++++++++++++++-- tasmota/support_tasmota.ino | 8 +++++++- 5 files changed, 49 insertions(+), 4 deletions(-) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index e8286e585..18c073d0d 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -586,6 +586,10 @@ // Commands xsns_02_analog.ino #define D_CMND_ADCPARAM "AdcParam" +// Commands led pwm settings +#define D_CMND_SETLEDPWMOFF "SetLedPwmOff" +#define D_CMND_SETLEDPWMON "SetLedPwmOn" + /********************************************************************************************/ // Log message prefix diff --git a/tasmota/settings.h b/tasmota/settings.h index edd3de523..11546fea3 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -569,8 +569,10 @@ struct { uint16_t windmeter_pulse_debounce; // F3A int16_t windmeter_speed_factor; // F3C uint8_t windmeter_tele_pchange; // F3E + uint16_t ledpwm_on; // F3F + uint16_t ledpwm_off; // F41 - uint8_t free_f3f[121]; // F3F - Decrement if adding new Setting variables just above and below + uint8_t free_f42[117]; // F42 - Decrement if adding new Setting variables just above and below // Only 32 bit boundary variables below uint16_t pulse_counter_debounce_low; // FB8 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 5214add7a..7a6a27ac3 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1055,6 +1055,10 @@ void SettingsDefaultSet2(void) Settings.flag2 = flag2; Settings.flag3 = flag3; Settings.flag4 = flag4; + + // Led PWM + Settings.ledpwm_off = 0; + Settings.ledpwm_on = 1023; } /********************************************************************************************/ @@ -1419,4 +1423,9 @@ void SettingsDelta(void) Settings.version = VERSION; SettingsSave(1); } + // ledpwm + if (Settings.version < 0x080300002) { + Settings.ledpwm_off = 0; + Settings.ledpwm_on = 1023; + } } diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index f262b5fcb..5adcc708f 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -27,7 +27,7 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix 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_DEVICENAME "|" 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 "|" D_CMND_HUMOFFSET "|" - D_CMND_SPEEDUNIT "|" D_CMND_GLOBAL_TEMP "|" D_CMND_GLOBAL_HUM "|" + D_CMND_SPEEDUNIT "|" D_CMND_GLOBAL_TEMP "|" D_CMND_GLOBAL_HUM "|" D_CMND_SETLEDPWMON "|" D_CMND_SETLEDPWMOFF "|" #ifdef USE_I2C D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|" #endif @@ -50,7 +50,7 @@ void (* const TasmotaCommand[])(void) PROGMEM = { &CmndSerialDelimiter, &CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig, &CmndDevicename, &CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset, &CmndTime, &CmndTimezone, &CmndTimeStd, &CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndWifiPower, &CmndTempOffset, &CmndHumOffset, - &CmndSpeedUnit, &CmndGlobalTemp, &CmndGlobalHum, + &CmndSpeedUnit, &CmndGlobalTemp, &CmndGlobalHum, &CmndSetLedPwmOn, &CmndSetLedPwmOff, #ifdef USE_I2C &CmndI2cScan, CmndI2cDriver, #endif @@ -1890,3 +1890,27 @@ void CmndDriver(void) { XdrvCall(FUNC_COMMAND_DRIVER); } + +void CmndSetLedPwmOff(void) +{ + if ((XdrvMailbox.payload < 0) { + Settings.ledpwm_off = 0; + } else if (XdrvMailbox.payload > Settings.pwm_range) { + Settings.ledpwm_off = Settings.pwm_range; + } else { + Settings.ledpwm_off = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.ledpwm_off); +} + +void CmndSetLedPwmOn(void) +{ + if ((XdrvMailbox.payload < 0) { + Settings.ledpwm_on = 0; + } else if (XdrvMailbox.payload > Settings.pwm_range) { + Settings.ledpwm_on = Settings.pwm_range; + } else { + Settings.ledpwm_on = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.ledpwm_on); +} \ No newline at end of file diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 90df92a37..65d842686 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -351,7 +351,13 @@ void SetLedPowerIdx(uint32_t led, uint32_t state) } else { led_power &= (0xFF ^ mask); } - DigitalWrite(GPIO_LED1, led, bitRead(led_inverted, led) ? !state : state); + uint16_t led_pwm_set = 0; + if (bitRead(led_inverted, led)) { + led_pwm_set = state ? Settings.pwm_range - Settings.ledpwm_on : Settings.pwm_range - Settings.ledpwm_off; + } else { + led_pwm_set = state ? Settings.ledpwm_on : Settings.ledpwm_off; + } + analogWrite(led, led_pwm_set) } #ifdef USE_BUZZER if (led == 0) { From ce2696fef0066ee303423d89a40a0614d90df9a4 Mon Sep 17 00:00:00 2001 From: George Date: Tue, 19 May 2020 15:44:19 +1000 Subject: [PATCH 02/20] Fix compile errors Missing brackets and semicolons of course. Blame python. --- tasmota/support_command.ino | 6 +++--- tasmota/support_tasmota.ino | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 5adcc708f..b48723575 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -1893,7 +1893,7 @@ void CmndDriver(void) void CmndSetLedPwmOff(void) { - if ((XdrvMailbox.payload < 0) { + if (XdrvMailbox.payload < 0) { Settings.ledpwm_off = 0; } else if (XdrvMailbox.payload > Settings.pwm_range) { Settings.ledpwm_off = Settings.pwm_range; @@ -1905,7 +1905,7 @@ void CmndSetLedPwmOff(void) void CmndSetLedPwmOn(void) { - if ((XdrvMailbox.payload < 0) { + if (XdrvMailbox.payload < 0) { Settings.ledpwm_on = 0; } else if (XdrvMailbox.payload > Settings.pwm_range) { Settings.ledpwm_on = Settings.pwm_range; @@ -1913,4 +1913,4 @@ void CmndSetLedPwmOn(void) Settings.ledpwm_on = XdrvMailbox.payload; } ResponseCmndNumber(Settings.ledpwm_on); -} \ No newline at end of file +} diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 65d842686..2508566ea 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -357,7 +357,7 @@ void SetLedPowerIdx(uint32_t led, uint32_t state) } else { led_pwm_set = state ? Settings.ledpwm_on : Settings.ledpwm_off; } - analogWrite(led, led_pwm_set) + analogWrite(led, led_pwm_set); } #ifdef USE_BUZZER if (led == 0) { From bd33574ee7c4a50de1fa97c03c964148edff8fe5 Mon Sep 17 00:00:00 2001 From: George Date: Tue, 19 May 2020 16:38:21 +1000 Subject: [PATCH 03/20] Align new settings to 2B boundaries Attempting to fix settings not working correctly (might have mucked up the boundaries and compiler put a padding byte in). --- tasmota/settings.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index 11546fea3..10c28a2ca 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -569,12 +569,12 @@ struct { uint16_t windmeter_pulse_debounce; // F3A int16_t windmeter_speed_factor; // F3C uint8_t windmeter_tele_pchange; // F3E - uint16_t ledpwm_on; // F3F - uint16_t ledpwm_off; // F41 - uint8_t free_f42[117]; // F42 - Decrement if adding new Setting variables just above and below + uint8_t free_f3f[117]; // F3F - Decrement if adding new Setting variables just above and below // Only 32 bit boundary variables below + uint16_t ledpwm_on; // FB4 + uint16_t ledpwm_off; // FB6 uint16_t pulse_counter_debounce_low; // FB8 uint16_t pulse_counter_debounce_high; // FBA uint32_t keeloq_master_msb; // FBC From fb179c27aff44b90e037469dc7b2521fb6dae2db Mon Sep 17 00:00:00 2001 From: George Date: Tue, 19 May 2020 21:43:11 +1000 Subject: [PATCH 04/20] Fixes * Setting commands don't update if no data is sent * Didn't understand how pin mapping worked duh. Fixed. --- tasmota/support_command.ino | 21 ++++++++++++--------- tasmota/support_tasmota.ino | 14 +++++++++++--- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index b48723575..b5ce6d074 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -1893,24 +1893,27 @@ void CmndDriver(void) void CmndSetLedPwmOff(void) { - if (XdrvMailbox.payload < 0) { + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.payload < 0) { Settings.ledpwm_off = 0; - } else if (XdrvMailbox.payload > Settings.pwm_range) { + } else if (XdrvMailbox.payload > Settings.pwm_range) { Settings.ledpwm_off = Settings.pwm_range; - } else { - Settings.ledpwm_off = XdrvMailbox.payload; - } + } else { + Settings.ledpwm_off = XdrvMailbox.payload; + } ResponseCmndNumber(Settings.ledpwm_off); } void CmndSetLedPwmOn(void) { - if (XdrvMailbox.payload < 0) { + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.payload < 0) { Settings.ledpwm_on = 0; - } else if (XdrvMailbox.payload > Settings.pwm_range) { + } else if (XdrvMailbox.payload > Settings.pwm_range) { Settings.ledpwm_on = Settings.pwm_range; - } else { - Settings.ledpwm_on = XdrvMailbox.payload; + } else { + Settings.ledpwm_on = XdrvMailbox.payload; + } } ResponseCmndNumber(Settings.ledpwm_on); } diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 2508566ea..ba4b0fb1d 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -353,11 +353,19 @@ void SetLedPowerIdx(uint32_t led, uint32_t state) } uint16_t led_pwm_set = 0; if (bitRead(led_inverted, led)) { - led_pwm_set = state ? Settings.pwm_range - Settings.ledpwm_on : Settings.pwm_range - Settings.ledpwm_off; + if (state) { + led_pwm_set = Settings.pwm_range - Settings.ledpwm_on; + } else { + led_pwm_set = Settings.pwm_range - Settings.ledpwm_off; + } } else { - led_pwm_set = state ? Settings.ledpwm_on : Settings.ledpwm_off; + if (state) { + led_pwm_set = Settings.ledpwm_on; + } else { + led_pwm_set = Settings.ledpwm_off; + } } - analogWrite(led, led_pwm_set); + analogWrite(Pin(GPIO_LED1, led), led_pwm_set); } #ifdef USE_BUZZER if (led == 0) { From bea58f223fb68e42b300356663487f10cef37f40 Mon Sep 17 00:00:00 2001 From: George Date: Tue, 19 May 2020 22:01:40 +1000 Subject: [PATCH 05/20] Oops Compile error. Forgot bracket. --- tasmota/support_command.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index b5ce6d074..263f5f713 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -1901,6 +1901,7 @@ void CmndSetLedPwmOff(void) } else { Settings.ledpwm_off = XdrvMailbox.payload; } + } ResponseCmndNumber(Settings.ledpwm_off); } From e21cbfdc5d96a9acd3943b30a53d5f7492a13b7b Mon Sep 17 00:00:00 2001 From: George Date: Wed, 20 May 2020 11:25:32 +1000 Subject: [PATCH 06/20] More sensible behaviour * When setting PWM values, updates all the LEDs (instant response). Uses led_power values. * If LEDLINK not set, but LED1 is, LED1 is the status led. When turning on/off, setledlink uses digitalwrite (which does not respect the new pwm operation). In this case only, we will use the setledpoweridx instead of digitalwrite - costly (every 250ms this runs), but edge case / legacy. Allows more intuitive operation - if we blink an LED with the max and min PWM limits, we'd expect it to respect these. In this case, blink will also now update the led_power status, which keeps this accurate e.g. if ledpower 1 cmnd was sent, then blink occurred, led_state would read a 1 for that bit but the led would be off (but nothing was reading it for status so it didn't cause any trouble). Leaving digitalwrite when LEDLINK is defined as this is more efficient and the use case for pwm leds is to find buttons - link indicator would become more ambiguous for no benefit. --- tasmota/support_command.ino | 2 ++ tasmota/support_tasmota.ino | 13 +++++++++---- tasmota/tasmota.ino | 2 +- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 263f5f713..314097235 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -1901,6 +1901,7 @@ void CmndSetLedPwmOff(void) } else { Settings.ledpwm_off = XdrvMailbox.payload; } + UpdateLedPowerAll(); } ResponseCmndNumber(Settings.ledpwm_off); } @@ -1915,6 +1916,7 @@ void CmndSetLedPwmOn(void) } else { Settings.ledpwm_on = XdrvMailbox.payload; } + UpdateLedPowerAll(); } ResponseCmndNumber(Settings.ledpwm_on); } diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index ba4b0fb1d..5a28b76d6 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -336,6 +336,13 @@ void SetPowerOnState(void) blink_powersave = power; } +void UpdateLedPowerAll() +{ + for (uint32_t i = 0; i < leds_present; i++) { + SetLedPowerIdx(i, bitRead(led_power, i)); + } +} + void SetLedPowerIdx(uint32_t led, uint32_t state) { if (!PinUsed(GPIO_LEDLNK) && (0 == led)) { // Legacy - LED1 is link led only if LED2 is present @@ -400,10 +407,8 @@ void SetLedLink(uint32_t state) uint32_t led_pin = Pin(GPIO_LEDLNK); uint32_t led_inv = ledlnk_inverted; if (99 == led_pin) { // Legacy - LED1 is status - led_pin = Pin(GPIO_LED1); - led_inv = bitRead(led_inverted, 0); - } - if (led_pin < 99) { + SetLedPowerIdx(0, state); + } else if (led_pin < 99) { if (state) { state = 1; } digitalWrite(led_pin, (led_inv) ? !state : state); } diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index ecf1127ec..92e3169b2 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -1,4 +1,4 @@ -/* + /* tasmota.ino - Tasmota firmware for iTead Sonoff, Wemos and NodeMCU hardware Copyright (C) 2020 Theo Arends From 603b628f97cf41f1bdaf0285377cdc0274497f47 Mon Sep 17 00:00:00 2001 From: George Date: Wed, 20 May 2020 12:13:05 +1000 Subject: [PATCH 07/20] Add pwm mode masking * Extra setting & command to set - allows masking of pwm mode. Use case is for leds attached to buttons for seeing at night; this way user can combine both pwm and digital leds (i.e. pwm for the button leds but non-button status leds can stay on/off). --- tasmota/i18n.h | 1 + tasmota/settings.h | 3 ++- tasmota/settings.ino | 2 ++ tasmota/support_command.ino | 28 ++++++++++++++++++++++++++-- tasmota/support_tasmota.ino | 28 ++++++++++++++++------------ 5 files changed, 47 insertions(+), 15 deletions(-) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 18c073d0d..d2c232658 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -589,6 +589,7 @@ // Commands led pwm settings #define D_CMND_SETLEDPWMOFF "SetLedPwmOff" #define D_CMND_SETLEDPWMON "SetLedPwmOn" +#define D_CMND_SETLEDPWMMODE "SetLedPwmMode" /********************************************************************************************/ diff --git a/tasmota/settings.h b/tasmota/settings.h index 10c28a2ca..0cc171601 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -569,8 +569,9 @@ struct { uint16_t windmeter_pulse_debounce; // F3A int16_t windmeter_speed_factor; // F3C uint8_t windmeter_tele_pchange; // F3E + uint8_t ledpwm_mask; // F3F - uint8_t free_f3f[117]; // F3F - Decrement if adding new Setting variables just above and below + uint8_t free_f40[116]; // F40 - Decrement if adding new Setting variables just above and below // Only 32 bit boundary variables below uint16_t ledpwm_on; // FB4 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 7a6a27ac3..d9d913c0a 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1059,6 +1059,7 @@ void SettingsDefaultSet2(void) // Led PWM Settings.ledpwm_off = 0; Settings.ledpwm_on = 1023; + Settings.ledpwm_mask = 0; } /********************************************************************************************/ @@ -1427,5 +1428,6 @@ void SettingsDelta(void) if (Settings.version < 0x080300002) { Settings.ledpwm_off = 0; Settings.ledpwm_on = 1023; + Settings.ledpwm_mask = 0; } } diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 314097235..2f327b9a1 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -27,7 +27,7 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix 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_DEVICENAME "|" 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 "|" D_CMND_HUMOFFSET "|" - D_CMND_SPEEDUNIT "|" D_CMND_GLOBAL_TEMP "|" D_CMND_GLOBAL_HUM "|" D_CMND_SETLEDPWMON "|" D_CMND_SETLEDPWMOFF "|" + D_CMND_SPEEDUNIT "|" D_CMND_GLOBAL_TEMP "|" D_CMND_GLOBAL_HUM "|" D_CMND_SETLEDPWMON "|" D_CMND_SETLEDPWMOFF "|" D_CMND_SETLEDPWMMODE "|" #ifdef USE_I2C D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|" #endif @@ -50,7 +50,7 @@ void (* const TasmotaCommand[])(void) PROGMEM = { &CmndSerialDelimiter, &CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig, &CmndDevicename, &CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset, &CmndTime, &CmndTimezone, &CmndTimeStd, &CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndWifiPower, &CmndTempOffset, &CmndHumOffset, - &CmndSpeedUnit, &CmndGlobalTemp, &CmndGlobalHum, &CmndSetLedPwmOn, &CmndSetLedPwmOff, + &CmndSpeedUnit, &CmndGlobalTemp, &CmndGlobalHum, &CmndSetLedPwmOn, &CmndSetLedPwmOff, &CmndSetLedPwmMode, #ifdef USE_I2C &CmndI2cScan, CmndI2cDriver, #endif @@ -1920,3 +1920,27 @@ void CmndSetLedPwmOn(void) } ResponseCmndNumber(Settings.ledpwm_on); } + +void CmndSetLedPwmMode(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_LEDS)) { + if (!PinUsed(GPIO_LEDLNK)) { XdrvMailbox.index = 1; } + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { + uint32_t mask = 1 << (XdrvMailbox.index -1); // Led to configure + switch (XdrvMailbox.payload) { + case 0: // digital + Settings.ledpwm_mask &= (0xFF ^ mask); + break; + case 1: // pwm + Settings.ledpwm_mask |= mask; + break; + case 2: // toggle + Settings.ledpwm_mask ^= mask; + break; + } + UpdateLedPowerAll(); + } + bool state = bitRead(Settings.ledpwm_mask, XdrvMailbox.index -1); + ResponseCmndIdxChar(GetStateText(state)); + } +} diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 5a28b76d6..d96751e32 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -359,20 +359,24 @@ void SetLedPowerIdx(uint32_t led, uint32_t state) led_power &= (0xFF ^ mask); } uint16_t led_pwm_set = 0; - if (bitRead(led_inverted, led)) { - if (state) { - led_pwm_set = Settings.pwm_range - Settings.ledpwm_on; - } else { - led_pwm_set = Settings.pwm_range - Settings.ledpwm_off; - } + if (bitRead(Settings.ledpwm_mask, led)) { + if (bitRead(led_inverted, led)) { + if (state) { + led_pwm_set = Settings.pwm_range - Settings.ledpwm_on; + } else { + led_pwm_set = Settings.pwm_range - Settings.ledpwm_off; + } + } else { + if (state) { + led_pwm_set = Settings.ledpwm_on; + } else { + led_pwm_set = Settings.ledpwm_off; + } + } + analogWrite(Pin(GPIO_LED1, led), led_pwm_set); } else { - if (state) { - led_pwm_set = Settings.ledpwm_on; - } else { - led_pwm_set = Settings.ledpwm_off; - } + DigitalWrite(GPIO_LED1, led, bitRead(led_inverted, led) ? !state : state); } - analogWrite(Pin(GPIO_LED1, led), led_pwm_set); } #ifdef USE_BUZZER if (led == 0) { From 833d89203f643fac9db10f6409754892cfb7cef2 Mon Sep 17 00:00:00 2001 From: George Date: Wed, 20 May 2020 12:38:24 +1000 Subject: [PATCH 08/20] Fix settings delta fail bugfix - settings always default on boot *Moved block to right scope *Got version number right duh --- tasmota/settings.ino | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index d9d913c0a..85a205da2 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1416,6 +1416,13 @@ void SettingsDelta(void) if (Settings.rules[1][0] == 0) { Settings.rules[1][1] = 0; } if (Settings.rules[2][0] == 0) { Settings.rules[2][1] = 0; } } + + // ledpwm + if (Settings.version < 0x08030001) { + Settings.ledpwm_off = 0; + Settings.ledpwm_on = 1023; + Settings.ledpwm_mask = 0; + } if (Settings.version < 0x08030002) { SettingsUpdateText(SET_DEVICENAME, SettingsText(SET_FRIENDLYNAME1)); @@ -1424,10 +1431,5 @@ void SettingsDelta(void) Settings.version = VERSION; SettingsSave(1); } - // ledpwm - if (Settings.version < 0x080300002) { - Settings.ledpwm_off = 0; - Settings.ledpwm_on = 1023; - Settings.ledpwm_mask = 0; - } + } From 855e054db85400f0669a176064720e9949188385 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 22 May 2020 17:48:21 +0200 Subject: [PATCH 09/20] Change Energy JSON data - Bump version 8.3.1.2 - Change Energy JSON Total field from ``"Total":[33.736,11.717,16.978]`` to ``"Total":33.736,"TotalTariff":[11.717,16.978]`` - Change Energy JSON ExportActive field from ``"ExportActive":[33.736,11.717,16.978]`` to ``"ExportActive":33.736,"ExportActiveTariff":[11.717,16.978]`` - Add Three Phase Export Active Energy to SDM630 driver --- RELEASENOTES.md | 5 ++- tasmota/CHANGELOG.md | 6 +++ tasmota/tasmota_version.h | 2 +- tasmota/xdrv_03_energy.ino | 82 ++++++++++++++++++++++++------------- tasmota/xnrg_08_sdm120.ino | 2 +- tasmota/xnrg_09_dds2382.ino | 2 +- tasmota/xnrg_10_sdm630.ino | 56 +++++++++++++++++-------- tasmota/xnrg_11_ddsu666.ino | 2 +- 8 files changed, 107 insertions(+), 50 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index ab62c092f..4ff7a6b16 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -52,10 +52,13 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 8.3.1.1 +### Version 8.3.1.2 - Change IRremoteESP8266 library updated to v2.7.7 +- Change Energy JSON Total field from ``"Total":[33.736,11.717,16.978]`` to ``"Total":33.736,"TotalTariff":[11.717,16.978]`` +- Change Energy JSON ExportActive field from ``"ExportActive":[33.736,11.717,16.978]`` to ``"ExportActive":33.736,"ExportActiveTariff":[11.717,16.978]`` - Add command ``Rule0`` to change global rule parameters - Add more functionality to ``Switchmode`` 11 and 12 (#8450) - Add support for VEML6075 UVA/UVB/UVINDEX Sensor by device111 (#8432) - Add support for VEML7700 Ambient light intensity Sensor by device111 (#8432) +- Add Three Phase Export Active Energy to SDM630 driver diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 056a0edd6..09ddf8b4f 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,5 +1,11 @@ ## Unreleased (development) +### 8.3.1.2 20200522 + +- Change Energy JSON Total field from ``"Total":[33.736,11.717,16.978]`` to ``"Total":33.736,"TotalTariff":[11.717,16.978]`` +- Change Energy JSON ExportActive field from ``"ExportActive":[33.736,11.717,16.978]`` to ``"ExportActive":33.736,"ExportActiveTariff":[11.717,16.978]`` +- Add Three Phase Export Active Energy to SDM630 driver + ### 8.3.1.1 20200518 - Change IRremoteESP8266 library updated to v2.7.7 diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index af18e431f..1b21293b2 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,7 +20,7 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x08030101; +const uint32_t VERSION = 0x08030102; // Lowest compatible version const uint32_t VERSION_COMPATIBLE = 0x07010006; diff --git a/tasmota/xdrv_03_energy.ino b/tasmota/xdrv_03_energy.ino index 4210cea1c..7639fb2e8 100644 --- a/tasmota/xdrv_03_energy.ino +++ b/tasmota/xdrv_03_energy.ino @@ -80,10 +80,12 @@ struct ENERGY { float power_factor[3] = { NAN, NAN, NAN }; // 0.12 float frequency[3] = { NAN, NAN, NAN }; // 123.1 Hz +// float import_active[3] = { NAN, NAN, NAN }; // 123.123 kWh + float export_active[3] = { NAN, NAN, NAN }; // 123.123 kWh + float start_energy = 0; // 12345.12345 kWh total previous float daily = 0; // 123.123 kWh float total = 0; // 12345.12345 kWh total energy - float export_active = NAN; // 123.123 KWh unsigned long kWhtoday_delta = 0; // 1212312345 Wh 10^-5 (deca micro Watt hours) - Overflows to Energy.kWhtoday (HLW and CSE only) unsigned long kWhtoday_offset = 0; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily @@ -170,9 +172,18 @@ void EnergyUpdateToday(void) RtcSettings.energy_usage.last_usage_kWhtotal = (uint32_t)(Energy.total * 100000); uint32_t return_diff = 0; - if (!isnan(Energy.export_active)) { - return_diff = (uint32_t)(Energy.export_active * 100000) - RtcSettings.energy_usage.last_return_kWhtotal; - RtcSettings.energy_usage.last_return_kWhtotal = (uint32_t)(Energy.export_active * 100000); + if (!isnan(Energy.export_active[0])) { +// return_diff = (uint32_t)(Energy.export_active * 100000) - RtcSettings.energy_usage.last_return_kWhtotal; +// RtcSettings.energy_usage.last_return_kWhtotal = (uint32_t)(Energy.export_active * 100000); + + float export_active = 0.0; + for (uint32_t i = 0; i < Energy.phase_count; i++) { + if (!isnan(Energy.export_active[i])) { + export_active += Energy.export_active[i]; + } + } + return_diff = (uint32_t)(export_active * 100000) - RtcSettings.energy_usage.last_return_kWhtotal; + RtcSettings.energy_usage.last_return_kWhtotal = (uint32_t)(export_active * 100000); } if (EnergyTariff1Active()) { // Tarrif1 = Off-Peak @@ -466,13 +477,13 @@ void EnergyEverySecond(void) if (!isnan(Energy.reactive_power[i])) { Energy.reactive_power[i] = 0; } if (!isnan(Energy.frequency[i])) { Energy.frequency[i] = 0; } if (!isnan(Energy.power_factor[i])) { Energy.power_factor[i] = 0; } + if (!isnan(Energy.export_active[i])) { Energy.export_active[i] = 0; } data_valid--; } } } if (!data_valid) { - if (!isnan(Energy.export_active)) { Energy.export_active = 0; } Energy.start_energy = 0; XnrgCall(FUNC_ENERGY_RESET); @@ -948,29 +959,31 @@ void EnergyShow(bool json) char voltage_chr[Energy.phase_count][FLOATSZ]; char current_chr[Energy.phase_count][FLOATSZ]; char active_power_chr[Energy.phase_count][FLOATSZ]; + char export_active_chr[Energy.phase_count][FLOATSZ]; for (uint32_t i = 0; i < Energy.phase_count; i++) { dtostrfd(Energy.voltage[i], Settings.flag2.voltage_resolution, voltage_chr[i]); dtostrfd(Energy.current[i], Settings.flag2.current_resolution, current_chr[i]); dtostrfd(Energy.active_power[i], Settings.flag2.wattage_resolution, active_power_chr[i]); + dtostrfd(Energy.export_active[i], Settings.flag2.energy_resolution, export_active_chr[i]); } + char energy_total_chr[FLOATSZ]; + dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr); char energy_daily_chr[FLOATSZ]; dtostrfd(Energy.daily, Settings.flag2.energy_resolution, energy_daily_chr); char energy_yesterday_chr[FLOATSZ]; dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr); - char energy_total_chr[3][FLOATSZ]; - dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr[0]); - char export_active_chr[3][FLOATSZ]; - dtostrfd(Energy.export_active, Settings.flag2.energy_resolution, export_active_chr[0]); - uint8_t energy_total_fields = 1; + bool energy_tariff = false; + char energy_usage_chr[2][FLOATSZ]; + char energy_return_chr[2][FLOATSZ]; if (Settings.tariff[0][0] != Settings.tariff[1][0]) { - dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_total_chr[1]); // Tariff1 - dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_total_chr[2]); // Tariff2 - dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100000, Settings.flag2.energy_resolution, export_active_chr[1]); // Tariff1 - dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100000, Settings.flag2.energy_resolution, export_active_chr[2]); // Tariff2 - energy_total_fields = 3; + dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_usage_chr[0]); // Tariff1 + dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_usage_chr[1]); // Tariff2 + dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_return_chr[0]); // Tariff1 + dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_return_chr[1]); // Tariff2 + energy_tariff = true; } char value_chr[FLOATSZ *3]; // Used by EnergyFormatIndex @@ -980,15 +993,26 @@ void EnergyShow(bool json) if (json) { bool show_energy_period = (0 == tele_period); - ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL_START_TIME "\":\"%s\",\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s"), + ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL_START_TIME "\":\"%s\",\"" D_JSON_TOTAL "\":%s"), GetDateAndTime(DT_ENERGY).c_str(), - EnergyFormatIndex(value_chr, energy_total_chr[0], json, energy_total_fields), + energy_total_chr); + + if (energy_tariff) { + ResponseAppend_P(PSTR(",\"" D_JSON_TOTAL D_CMND_TARIFF "\":%s"), + EnergyFormatIndex(value_chr, energy_usage_chr[0], json, 2)); + } + + ResponseAppend_P(PSTR(",\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s"), energy_yesterday_chr, energy_daily_chr); - if (!isnan(Energy.export_active)) { + if (!isnan(Energy.export_active[0])) { ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT_ACTIVE "\":%s"), - EnergyFormatIndex(value_chr, export_active_chr[0], json, energy_total_fields)); + EnergyFormat(value_chr, export_active_chr[0], json)); + if (energy_tariff) { + ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT_ACTIVE D_CMND_TARIFF "\":%s"), + EnergyFormatIndex(value_chr, energy_return_chr[0], json, 2)); + } } if (show_energy_period) { @@ -1028,14 +1052,14 @@ void EnergyShow(bool json) #ifdef USE_DOMOTICZ if (show_energy_period) { // Only send if telemetry - dtostrfd(Energy.total * 1000, 1, energy_total_chr[0]); - DomoticzSensorPowerEnergy((int)Energy.active_power[0], energy_total_chr[0]); // PowerUsage, EnergyToday + dtostrfd(Energy.total * 1000, 1, energy_total_chr); + DomoticzSensorPowerEnergy((int)Energy.active_power[0], energy_total_chr); // PowerUsage, EnergyToday - dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100, 1, energy_total_chr[1]); // Tariff1 - dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100, 1, energy_total_chr[2]); // Tariff2 - dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100, 1, export_active_chr[1]); - dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100, 1, export_active_chr[2]); - DomoticzSensorP1SmartMeter(energy_total_chr[1], energy_total_chr[2], export_active_chr[1], export_active_chr[2], (int)Energy.active_power[0]); + dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100, 1, energy_usage_chr[0]); // Tariff1 + dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100, 1, energy_usage_chr[1]); // Tariff2 + dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100, 1, energy_return_chr[0]); + dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100, 1, energy_return_chr[1]); + DomoticzSensorP1SmartMeter(energy_usage_chr[0], energy_usage_chr[1], energy_return_chr[0], energy_return_chr[1], (int)Energy.active_power[0]); if (Energy.voltage_available) { DomoticzSensor(DZ_VOLTAGE, voltage_chr[0]); // Voltage @@ -1082,9 +1106,9 @@ void EnergyShow(bool json) EnergyFormat(value_chr, frequency_chr[0], json, Energy.voltage_common)); } } - WSContentSend_PD(HTTP_ENERGY_SNS2, energy_daily_chr, energy_yesterday_chr, energy_total_chr[0]); - if (!isnan(Energy.export_active)) { - WSContentSend_PD(HTTP_ENERGY_SNS3, export_active_chr[0]); + WSContentSend_PD(HTTP_ENERGY_SNS2, energy_daily_chr, energy_yesterday_chr, energy_total_chr); + if (!isnan(Energy.export_active[0])) { + WSContentSend_PD(HTTP_ENERGY_SNS3, EnergyFormat(value_chr, export_active_chr[0], json)); } XnrgCall(FUNC_WEB_SENSOR); diff --git a/tasmota/xnrg_08_sdm120.ino b/tasmota/xnrg_08_sdm120.ino index 93af326f8..8f764ad52 100644 --- a/tasmota/xnrg_08_sdm120.ino +++ b/tasmota/xnrg_08_sdm120.ino @@ -134,7 +134,7 @@ void SDM120Every250ms(void) break; case 9: - Energy.export_active = value; // 6.216 kWh + Energy.export_active[0] = value; // 6.216 kWh break; case 10: diff --git a/tasmota/xnrg_09_dds2382.ino b/tasmota/xnrg_09_dds2382.ino index a516ea4a8..7acb36f05 100644 --- a/tasmota/xnrg_09_dds2382.ino +++ b/tasmota/xnrg_09_dds2382.ino @@ -74,7 +74,7 @@ void Dds2382EverySecond(void) if (Settings.flag3.dds2382_model) { // SetOption71 - Select different Modbus registers for Active Energy (#6531) offset = 19; } - Energy.export_active = (float)((buffer[offset] << 24) + (buffer[offset +1] << 16) + (buffer[offset +2] << 8) + buffer[offset +3]) / 100.0; // 429496.729 kW + Energy.export_active[0] = (float)((buffer[offset] << 24) + (buffer[offset +1] << 16) + (buffer[offset +2] << 8) + buffer[offset +3]) / 100.0; // 429496.729 kW float import_active = (float)((buffer[offset +4] << 24) + (buffer[offset +5] << 16) + (buffer[offset +6] << 8) + buffer[offset +7]) / 100.0; // 429496.729 kW EnergyUpdateTotal(import_active, true); // 484.708 kWh diff --git a/tasmota/xnrg_10_sdm630.ino b/tasmota/xnrg_10_sdm630.ino index 4bfeecc96..026c3b4e8 100644 --- a/tasmota/xnrg_10_sdm630.ino +++ b/tasmota/xnrg_10_sdm630.ino @@ -40,22 +40,30 @@ TasmotaModbus *Sdm630Modbus; const uint16_t sdm630_start_addresses[] { - 0x0000, // L1 - SDM630_VOLTAGE [V] - 0x0002, // L2 - SDM630_VOLTAGE [V] - 0x0004, // L3 - SDM630_VOLTAGE [V] - 0x0006, // L1 - SDM630_CURRENT [A] - 0x0008, // L2 - SDM630_CURRENT [A] - 0x000A, // L3 - SDM630_CURRENT [A] - 0x000C, // L1 - SDM630_POWER [W] - 0x000E, // L2 - SDM630_POWER [W] - 0x0010, // L3 - SDM630_POWER [W] - 0x0018, // L1 - SDM630_REACTIVE_POWER [VAR] - 0x001A, // L2 - SDM630_REACTIVE_POWER [VAR] - 0x001C, // L3 - SDM630_REACTIVE_POWER [VAR] - 0x001E, // L1 - SDM630_POWER_FACTOR - 0x0020, // L2 - SDM630_POWER_FACTOR - 0x0022, // L3 - SDM630_POWER_FACTOR - 0x0156 // Total - SDM630_TOTAL_ACTIVE_ENERGY [Wh] + // 3P4 3P3 1P2 Unit Description + 0x0000, // + - + V Phase 1 line to neutral volts + 0x0002, // + - - V Phase 2 line to neutral volts + 0x0004, // + - - V Phase 3 line to neutral volts + 0x0006, // + + + A Phase 1 current + 0x0008, // + + - A Phase 2 current + 0x000A, // + + - A Phase 3 current + 0x000C, // + - + W Phase 1 power + 0x000E, // + - + W Phase 2 power + 0x0010, // + - - W Phase 3 power + 0x0018, // + - + VAr Phase 1 volt amps reactive + 0x001A, // + - - VAr Phase 2 volt amps reactive + 0x001C, // + - - VAr Phase 3 volt amps reactive + 0x001E, // + - + Phase 1 power factor + 0x0020, // + - - Phase 2 power factor + 0x0022, // + - - Phase 3 power factor + 0x0046, // + + + Hz Frequency of supply voltages + 0x0160, // + + + kWh Phase 1 export active energy + 0x0162, // + + + kWh Phase 2 export active energy + 0x0164, // + + + kWh Phase 3 export active energy +// 0x015A, // + + + kWh Phase 1 import active energy +// 0x015C, // + + + kWh Phase 2 import active energy +// 0x015E, // + + + kWh Phase 3 import active energy + 0x0156 // + + + kWh Total active energy }; struct SDM630 { @@ -153,6 +161,22 @@ void SDM630Every250ms(void) break; case 15: + Energy.frequency[0] = value; + break; + + case 16: + Energy.export_active[0] = value; + break; + + case 17: + Energy.export_active[1] = value; + break; + + case 18: + Energy.export_active[2] = value; + break; + + case 19: EnergyUpdateTotal(value, true); break; } diff --git a/tasmota/xnrg_11_ddsu666.ino b/tasmota/xnrg_11_ddsu666.ino index 87b585d84..f01ad50a5 100644 --- a/tasmota/xnrg_11_ddsu666.ino +++ b/tasmota/xnrg_11_ddsu666.ino @@ -110,7 +110,7 @@ void DDSU666Every250ms(void) break; case 7: - Energy.export_active = value; // 6.216 kWh + Energy.export_active[0] = value; // 6.216 kWh break; } From 93ca102391998e03dbe583cda2b64772e955eb01 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 22 May 2020 18:31:14 +0200 Subject: [PATCH 10/20] Change ExportActiveTariff to ExportTariff --- RELEASENOTES.md | 2 +- tasmota/CHANGELOG.md | 2 +- tasmota/i18n.h | 1 + tasmota/xdrv_03_energy.ino | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 4ff7a6b16..07406b54f 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -56,7 +56,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Change IRremoteESP8266 library updated to v2.7.7 - Change Energy JSON Total field from ``"Total":[33.736,11.717,16.978]`` to ``"Total":33.736,"TotalTariff":[11.717,16.978]`` -- Change Energy JSON ExportActive field from ``"ExportActive":[33.736,11.717,16.978]`` to ``"ExportActive":33.736,"ExportActiveTariff":[11.717,16.978]`` +- Change Energy JSON ExportActive field from ``"ExportActive":[33.736,11.717,16.978]`` to ``"ExportActive":33.736,"ExportTariff":[11.717,16.978]`` - Add command ``Rule0`` to change global rule parameters - Add more functionality to ``Switchmode`` 11 and 12 (#8450) - Add support for VEML6075 UVA/UVB/UVINDEX Sensor by device111 (#8432) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 09ddf8b4f..b4c77c4ab 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,7 +3,7 @@ ### 8.3.1.2 20200522 - Change Energy JSON Total field from ``"Total":[33.736,11.717,16.978]`` to ``"Total":33.736,"TotalTariff":[11.717,16.978]`` -- Change Energy JSON ExportActive field from ``"ExportActive":[33.736,11.717,16.978]`` to ``"ExportActive":33.736,"ExportActiveTariff":[11.717,16.978]`` +- Change Energy JSON ExportActive field from ``"ExportActive":[33.736,11.717,16.978]`` to ``"ExportActive":33.736,"ExportTariff":[11.717,16.978]`` - Add Three Phase Export Active Energy to SDM630 driver ### 8.3.1.1 20200518 diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 698192e99..b0b0cd666 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -65,6 +65,7 @@ #define D_JSON_ERROR "Error" #define D_JSON_EVENT "Event" #define D_JSON_EVERY "Every" +#define D_JSON_EXPORT "Export" #define D_JSON_EXPORT_ACTIVE "ExportActive" #define D_JSON_EXPORT_REACTIVE "ExportReactive" #define D_JSON_FAILED "Failed" diff --git a/tasmota/xdrv_03_energy.ino b/tasmota/xdrv_03_energy.ino index 7639fb2e8..2caaaa292 100644 --- a/tasmota/xdrv_03_energy.ino +++ b/tasmota/xdrv_03_energy.ino @@ -1010,7 +1010,7 @@ void EnergyShow(bool json) ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT_ACTIVE "\":%s"), EnergyFormat(value_chr, export_active_chr[0], json)); if (energy_tariff) { - ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT_ACTIVE D_CMND_TARIFF "\":%s"), + ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT D_CMND_TARIFF "\":%s"), EnergyFormatIndex(value_chr, energy_return_chr[0], json, 2)); } } From 7ee9b2d34d06a3d3e42c6c2871a73c642a7884ac Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 22 May 2020 22:14:17 +0200 Subject: [PATCH 11/20] Compressed string in Wemo emulation --- lib/Unishox-1.0-shadinger/src/unishox.cpp | 17 +++-- tasmota/support.ino | 34 +++++++++- tasmota/xdrv_10_rules.ino | 15 +---- tasmota/xdrv_21_wemo.ino | 82 +++++++++++++++++++++-- 4 files changed, 123 insertions(+), 25 deletions(-) diff --git a/lib/Unishox-1.0-shadinger/src/unishox.cpp b/lib/Unishox-1.0-shadinger/src/unishox.cpp index 743eed38c..286a16280 100644 --- a/lib/Unishox-1.0-shadinger/src/unishox.cpp +++ b/lib/Unishox-1.0-shadinger/src/unishox.cpp @@ -388,9 +388,9 @@ uint32_t Unishox::getNextBit(void) { in_eof = true; return 1; // return only 1s, which appends 'r' in worst case } - byte_in = in[byte_no++]; + byte_in = pgm_read_byte(&in[byte_no++]); if (ESCAPE_MARKER == byte_in) { - byte_in = in[byte_no++] - 1; // we shouldn't need to test if byte_no >= len, because it should not be possible to end with ESCAPE_MARKER + byte_in = pgm_read_byte(&in[byte_no++]) - 1; // we shouldn't need to test if byte_no >= len, because it should not be possible to end with ESCAPE_MARKER } bit_no = 0; } @@ -479,6 +479,9 @@ int32_t Unishox::unishox_decompress(const char *p_in, size_t p_len, char *p_out, out[ol] = 0; // while ((byte_no << 3) + bit_no - 8 < len) { while (!in_eof) { + if (ol >= len_out) { + break; + } int32_t h, v; char c = 0; byte is_upper = is_all_upper; @@ -564,11 +567,11 @@ int32_t Unishox::unishox_decompress(const char *p_in, size_t p_len, char *p_out, } } out[ol++] = c; - - if (ol >= len_out) { - return -1; // overflow - } } - return ol; + if (ol > len_out) { + return -1; // overflow + } else { + return ol; + } } diff --git a/tasmota/support.ino b/tasmota/support.ino index 271ad81fe..a053b6c34 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -1931,4 +1931,36 @@ String escapeJSONString(const char *str) { } return r; -} \ No newline at end of file +} + +/*********************************************************************************************\ + * Uncompress static PROGMEM strings +\*********************************************************************************************/ + +#if defined(USE_RULES_COMPRESSION) || defined(USE_SCRIPT_COMPRESSION) + +#include + +Unishox compressor; + +String decompress(const char * compressed, size_t uncompressed_size) { + String content(""); + + uncompressed_size += 2; // take a security margin + + // We use a nasty trick here. To avoid allocating twice the buffer, + // we first extend the buffer of the String object to the target size (maybe overshooting by 7 bytes) + // then we decompress in this buffer, + // and finally assign the raw string to the String, which happens to work: String uses memmove(), so overlapping works + content.reserve(uncompressed_size); + char * buffer = content.begin(); + + int32_t len = compressor.unishox_decompress(compressed, strlen_P(compressed), buffer, uncompressed_size); + if (len > 0) { + buffer[len] = 0; // terminate string with NULL + content = buffer; // copy in place + } + return content; +} + +#endif // defined(USE_RULES_COMPRESSION) || defined(USE_SCRIPT_COMPRESSION) \ No newline at end of file diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino index 25a62d288..7dcc90498 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/xdrv_10_rules.ino @@ -213,7 +213,7 @@ char rules_vars[MAX_RULE_VARS][33] = {{ 0 }}; #ifdef USE_RULES_COMPRESSION // Statically allocate one String per rule String k_rules[MAX_RULE_SETS] = { String(), String(), String() }; // Strings are created empty -Unishox compressor; // singleton +// Unishox compressor; // singleton #endif // USE_RULES_COMPRESSION // Returns whether the rule is uncompressed, which means the first byte is not NULL @@ -263,18 +263,7 @@ void GetRule_decompress(String &rule, const char *rule_head) { size_t buf_len = 1 + *rule_head * 8; // the first byte contains size of buffer for uncompressed rule / 8, buf_len may overshoot by 7 rule_head++; // advance to the actual compressed buffer - // We use a nasty trick here. To avoid allocating twice the buffer, - // we first extend the buffer of the String object to the target size (maybe overshooting by 7 bytes) - // then we decompress in this buffer, - // and finally assign the raw string to the String, which happens to work: String uses memmove(), so overlapping works - rule.reserve(buf_len); - char* buf = rule.begin(); - - int32_t len_decompressed = compressor.unishox_decompress(rule_head, strlen(rule_head), buf, buf_len); - buf[len_decompressed] = 0; // add NULL terminator - - // AddLog_P2(LOG_LEVEL_INFO, PSTR("RUL: Rawdecompressed: %d"), len_decompressed); - rule = buf; // assign the raw string to the String object (in reality re-writing the same data in the same place) + rule = decompress(rule_head, buf_len); } #endif // USE_RULES_COMPRESSION diff --git a/tasmota/xdrv_21_wemo.ino b/tasmota/xdrv_21_wemo.ino index fb123d4ab..20236df6e 100644 --- a/tasmota/xdrv_21_wemo.ino +++ b/tasmota/xdrv_21_wemo.ino @@ -85,6 +85,79 @@ void WemoRespondToMSearch(int echo_type) * Wemo web server additions \*********************************************************************************************/ +#if defined(USE_RULES_COMPRESSION) || defined(USE_SCRIPT_COMPRESSION) + +//SetBinaryStateBinaryStateBinaryStateinGetBinaryStateBinaryStateBinaryStateoutBinaryStatebool0levelstring0\r\n\r\n +//Successfully compressed from 779 to 249 bytes (-68%) +const size_t WEMO_EVENTSERVICE_XML_size = 779; +const char WEMO_EVENTSERVICE_XML[] PROGMEM = "\x3D\x3C\x18\xC1\x11\xB0\x68\x5D\xE3\xE1\xEC\x17\xFE\x3C\xC8\x73\x08\xD3\x78\xF3" + "\xF3\xF9\x9E\x86\xCE\xB3\x90\xEB\x67\xB0\xFC\x3D\x0A\xC3\xAD\xCE\x20\xB7\xD4\x08" + "\x72\x0F\xC3\xD3\xAC\x6B\x3F\x0B\xCE\x88\x76\xF5\xFC\xC8\xBD\x57\x4C\xF4\x3B\x3A" + "\xC6\xB3\xF0\xF4\xBF\x8F\x0B\x1A\xFA\x81\x0B\x0D\x04\x29\x47\xE1\xE9\xF7\x46\x76" + "\x11\xD8\x08\x58\xC0\x27\x62\xBF\x61\x5D\x31\x0B\xD5\x74\xC8\xCE\xFF\xB6\x38\x20" + "\x4A\xC1\x01\x42\xF1\xE8\x26\xFD\x82\x0E\xE7\xBC\x7A\x1D\x80\x8B\x28\xF4\x3B\x01" + "\x17\x59\x04\x48\xE0\x83\xB9\x1D\x80\x87\xC1\x20\x24\x70\x58\x43\xC0\xDA\xF8\x2C" + "\xC1\x74\x0C\x2F\x82\xD0\x42\x8A\x08\x34\x81\x0B\x92\x42\xF5\x5D\x32\xA0\x41\xCE" + "\x7C\x08\xFA\x42\xF3\xE1\x09\x99\xBE\xAF\x1F\x0F\x61\x93\xF1\xEC\x05\x5E\x0A\x44" + "\xBA\xB2\xA3\x21\x8C\xFC\x1D\x98\x11\xE8\x76\x02\x24\xB3\xD0\x46\x62\xC5\x85\x44" + "\x67\x61\x0B\x67\xE1\xC6\x7A\x1D\x84\x09\x13\x0F\x43\xB0\x12\x34\xC0\x60\x5A\xD8" + "\x4C\xCD\x84\x09\x9A\xAF\xAB\xFB\xC3\xC0\xC5\x75\x73\xB0\x13\xB8\x6A\x3B\x3C\x18" + "\xC1\x0F\xC9\xC2\x91\xBA\x70\xA4\x6E"; + +//10GetMetaInfoGetMetaInfoMetaInfoinMetaInfostring0\r\n\r\n +//Successfully compressed from 479 to 253 bytes (-47.2%) +const size_t WEMO_METASERVICE_XML_size = 479; +const char WEMO_METASERVICE_XML[] PROGMEM = "\x3D\x3C\x18\xC1\x11\xB0\x68\x5D\xE3\xE1\xEC\x17\xFE\x3C\xC8\x73\x08\xD3\x78\xF3" + "\xF3\xF9\x9E\x86\xCE\xB3\x90\xEB\x67\xB0\xFC\x3D\x0B\xC3\x18\x64\x66\xFF\xED\xCE" + "\x3F\x0F\x41\xB6\x6B\xCF\x9F\x87\x21\xE8\x76\x10\x20\xC5\x3D\x06\xEF\x67\xCF\xC3" + "\x8C\xF4\x3B\x08\x10\x62\x9E\x87\x60\x24\x61\x56\x1D\x6E\x71\x05\xBE\xA0\x43\x90" + "\x7E\x1E\x9D\x63\x59\xF8\x43\xCE\x88\x6B\xAB\x2D\xE3\x18\x7A\x1D\x9D\x63\x59\xF8" + "\x7A\x5F\xC7\x85\x8D\x7D\x40\x83\x85\x7D\xD1\x9D\x84\x8E\xC0\x55\xC3\x3E\xC2\xBA" + "\x62\x17\xAA\xE9\x91\x9D\xFF\x6C\x70\x4C\xFC\x04\x5C\x04\x14\x2D\x9E\x82\x6F\xD8" + "\x20\xEC\x9B\xC7\xA1\xD8\x08\xB2\x8F\x43\xB0\x12\x75\xB3\xB0\x10\xF8\x0A\x04\x28" + "\xA0\x83\x48\x10\xB8\x74\x2F\x55\xD3\x2A\x2B\x04\x1C\xB7\xC0\x8F\x9E\x2F\x3E\x10" + "\x99\x9B\xEA\xF1\xF0\xF6\x19\x3F\x1E\xC0\x42\xE0\x68\x12\xF8\x17\x12\xEA\xCA\x8C" + "\x86\x33\xF3\xD5\xFD\xE1\xE3\xD0\xEC\x04\x49\xA7\xA0\x8C\xC5\x8B\x0A\x88\xCE\xC2" + "\x16\xCF\xC3\x8C\xF4\x3B\x08\x12\x26\x1E\x87\x60\x24\x69\x67\xE1\xE8\x76\x02\x76" + "\xDC\x76\x78\x31\x82\x1F\x93\x85\x23\x74\xE1\x48\xDC"; + +//%d\r\n +//Successfully compressed from 282 to 161 bytes (-42.9%) +const size_t WEMO_RESPONSE_STATE_SOAP_size = 282; +const char WEMO_RESPONSE_STATE_SOAP[] PROGMEM = "\x3D\x3C\x79\x93\xE3\x36\x16\x0C\x68\xD8\x34\x2E\xF1\xE7\xE3\xE1\xEC\x15\x54\x30" + "\xF3\x3B\x0E\xCF\x06\x29\x8D\xBF\x1D\x0D\x83\x42\xF6\x58\xC3\xA6\x7C\x78\xEC\xF6" + "\x58\xC3\xB1\x82\x16\x1C\x76\x1E\xC5\xE3\xCD\xF0\x78\x26\xF0\xF1\x7A\x8C\x82\x60" + "\xBF\x8C\x02\x0E\x16\x76\x1E\xC3\xF0\xF4\xF1\xE6\x43\xB0\x43\x23\xF0\xF4\x16\x79" + "\x9F\x41\xBA\x21\xDB\xD7\xF3\x22\xF5\x5D\x32\xFB\xF0\xCC\xEF\x02\x1E\xDE\x2C\xF8" + "\x7B\x05\xFF\x8F\x32\x1C\xC2\x34\xDE\x3C\xFC\xFE\x67\xA1\xB3\xCC\x75\xFB\x43\x66" + "\x6F\xA8\xF3\x39\x0F\x61\xF8\x7A\x10\x23\x63\x67\xE1\xF4\x21\xE8\x76\x02\x3C\xC3" + "\xD0\xEC\x05\x4C\xFC\xFC\x3D\x0E\xC0\x43\xD8\xCE\xC0\x45\xE1\xA0\xFC\x9C\x29\x1B" + "\x8D"; + +//urn:Belkin:device:controllee:1{x1Belkin International Inc.Socket3.1415uuid:{x2{x30urn:Belkin:service:basicevent:1urn:Belkin:serviceId:basicevent1/upnp/control/basicevent1/upnp/event/basicevent1/eventservice.xmlurn:Belkin:service:metainfo:1urn:Belkin:serviceId:metainfo1/upnp/control/metainfo1/upnp/event/metainfo1/metainfoservice.xml\r\n +//Successfully compressed from 923 to 392 bytes (-57.5%) +const size_t WEMO_SETUP_XML_size = 923; +const char WEMO_SETUP_XML[] PROGMEM = "\x3D\x0E\xD1\xB0\x68\x48\xCD\xFF\xDB\x9C\x7C\x3D\x87\x21\xD1\x9E\xC3\xB4\x7E\x1E" + "\x85\xFC\xCA\x46\xC1\xA1\x77\x8F\x87\xB0\x5F\xF8\xF3\x21\xCC\x23\x4D\xE3\xCC\x46" + "\x67\xA1\xB3\xAC\xE4\x3A\xD9\xEC\x3F\x0F\x42\x04\x19\x20\x87\x10\xA8\xC8\x63\x3F" + "\x01\x33\x07\x3C\xC3\xCE\xAF\xE0\x41\x36\x79\x9C\x87\xA1\xD8\x40\x8D\x83\x9E\x86" + "\x3F\xAF\x84\x08\xC8\xBA\xC6\xB3\xF0\xF6\x9B\x0E\x43\xD0\xEC\x20\x48\x9C\x7A\x0D" + "\xBE\x16\x62\xC3\xA1\x7F\x7F\x3F\x01\x07\x31\x45\xBD\x4F\xFD\x75\xB9\xD6\x12\x2D" + "\xE0\xCE\x87\xA1\xD8\x09\x18\x21\xE8\x37\x04\x61\x17\x58\xD6\x7E\x17\xB0\x33\x47" + "\x47\xA1\xD8\x08\xB3\x81\x0A\xC8\xB1\xA3\x9F\xCF\xC3\x96\x74\x99\x34\x81\x0E\xD8" + "\x20\xD0\x3D\x08\x59\x08\x5C\x7E\x0B\x17\xA2\x1E\x67\xB4\xD8\x72\x8F\x43\xB0\x88" + "\x59\x08\x5C\x7E\x1E\x9E\x7F\xDB\x04\x3B\xA7\xB4\xD8\x72\xCF\x43\xB0\x81\x22\x71" + "\xE8\x3B\x7A\xFE\x64\x5E\xAB\xA6\x7E\x1C\x67\xA1\xD8\x40\x8F\x2C\xF4\xF3\xF9\x9E" + "\x86\xC8\x2D\xF5\x02\x24\x90\x44\x8A\x09\x7C\x46\x82\x15\x33\xCC\x75\xFB\x43\x66" + "\x6F\xA8\xF3\x39\x0F\x43\xB0\x81\x1F\x09\x04\x3C\x58\xB4\x40\x4E\xC5\x0B\x44\x04" + "\x6C\x58\x11\x71\x52\xD1\x0F\xC3\xD0\x10\xB8\xE0\x21\x65\xF2\x08\xFC\x3B\x05\x8C" + "\xE1\x87\x60\x21\x4D\x3B\x01\x23\x0D\x04\x6C\x08\xF4\x66\x6F\xA8\xBC\x2C\x70\x22" + "\xE1\xEC\xCD\xF5\x02\x4E\x1A\x08\xF8\x09\xE8\x45\xE0\xC6\x08\x2F\xE1\x11\xF8\x08" + "\x34\x81\x0B\x59\x3A\x1B\x06\x84\x7A\x1D\x80\x87\x5C\x11\x37\x2A\x01\x60\xBC\x34" + "\x0D\x75\x7B\xC6\x30\x18\x5F\x0C\xC0\x87\x8A\x03\x02\xE1\x90\x11\xB0\xB0\x5F\xE1" + "\x88\x11\xB0\xB0\x51\xE1\x80\x10\xEE\x82\xDF\x0C\x60\x87\x18\x10\x79\x7D\x04\x2E" + "\x83\xD1\xF8\x7A\x1D\x9F\xCC\xA3\xF2\x70\xA4\x6E"; +#else const char WEMO_EVENTSERVICE_XML[] PROGMEM = "" "" @@ -190,6 +263,7 @@ const char WEMO_SETUP_XML[] PROGMEM = "" "" "\r\n"; +#endif /********************************************************************************************/ @@ -219,7 +293,7 @@ void HandleUpnpEvent(void) } } - snprintf_P(event, sizeof(event), WEMO_RESPONSE_STATE_SOAP, state, bitRead(power, devices_present -1), state); + snprintf_P(event, sizeof(event), decompress(WEMO_RESPONSE_STATE_SOAP, WEMO_RESPONSE_STATE_SOAP_size).c_str(), state, bitRead(power, devices_present -1), state); WSSend(200, CT_XML, event); } @@ -227,21 +301,21 @@ void HandleUpnpService(void) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_EVENT_SERVICE)); - WSSend(200, CT_PLAIN, FPSTR(WEMO_EVENTSERVICE_XML)); + WSSend(200, CT_PLAIN, decompress(WEMO_EVENTSERVICE_XML, WEMO_EVENTSERVICE_XML_size)); } void HandleUpnpMetaService(void) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_META_SERVICE)); - WSSend(200, CT_PLAIN, FPSTR(WEMO_METASERVICE_XML)); + WSSend(200, CT_PLAIN, decompress(WEMO_METASERVICE_XML, WEMO_METASERVICE_XML_size)); } void HandleUpnpSetupWemo(void) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_SETUP)); - String setup_xml = FPSTR(WEMO_SETUP_XML); + String setup_xml = decompress(WEMO_SETUP_XML, WEMO_SETUP_XML_size); setup_xml.replace("{x1", SettingsText(SET_FRIENDLYNAME1)); setup_xml.replace("{x2", WemoUuid()); setup_xml.replace("{x3", WemoSerialnumber()); From 45b83a8c7729fa64bf9ae10ea14cfe9951582e48 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 22 May 2020 22:54:34 +0200 Subject: [PATCH 12/20] Compression candidates for Hue emulation --- tasmota/xdrv_20_hue.ino | 60 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/tasmota/xdrv_20_hue.ino b/tasmota/xdrv_20_hue.ino index 122166010..639f198bb 100644 --- a/tasmota/xdrv_20_hue.ino +++ b/tasmota/xdrv_20_hue.ino @@ -114,6 +114,29 @@ void HueRespondToMSearch(void) * Hue web server additions \*********************************************************************************************/ +//10http://{x1:80/urn:schemas-upnp-org:device:Basic:1Amazon-Echo-HA-Bridge ({x1)Royal Philips Electronicshttp://www.philips.comPhilips hue Personal Wireless LightingPhilips hue bridge 2012929000226503{x3uuid:{x2\r\n\r\n +//Successfully compressed from 625 to 391 bytes (-37.4%) +// const size_t HUE_DESCRIPTION_XML_size = 625; +// const char HUE_DESCRIPTION_XML[] PROGMEM = "\x3D\x0E\xD1\xB0\x68\x48\xCD\xFF\xDB\x9C\x7C\x3D\x87\x21\xD1\x9E\xC3\xB4\x7E\x1E" +// "\x85\xFC\xCA\x46\xC1\xA1\x77\x8F\x87\xB0\x5F\xF8\xF3\xF0\x62\x98\xDB\xF1\xD6\x2C" +// "\x67\x0C\x3A\xF3\xE3\xC7\x98\x8C\xCF\x43\x67\x59\xC8\x75\xB3\xD8\x7E\x1E\x85\xE1" +// "\x8C\x32\x33\x04\x1C\x78\xFC\x3D\x06\xD9\xAF\x3E\x7E\x1C\x87\xA1\xD8\x40\x83\x14" +// "\xF4\x1B\xBD\x9F\x3F\x0E\x33\xD0\xEC\x20\x41\x8A\x7A\x1D\x80\x91\x85\x10\xB2\xF9" +// "\x04\x43\xAF\xCC\xFC\x15\x54\x30\xF3\x3B\x0E\xC3\xDA\x6C\x39\x0F\x3F\xB3\xB0\xF4" +// "\x3B\x08\x10\xEA\x1E\x80\x83\xA2\x82\x1C\x42\xA3\x21\x8C\xFC\x05\x6D\xB4\xF3\x21" +// "\xD7\xED\x0C\xF3\x39\x0F\x43\xB0\x81\x1B\x0C\x3D\x0C\x7F\x5F\x08\x11\x91\x75\x8D" +// "\x67\xE1\x58\xDB\x36\xE7\x1D\x64\xC3\x15\x87\x59\x0A\x2B\x3A\xC8\x77\xF4\x41\xE6" +// "\x8E\xE9\xED\x36\x1C\x87\x78\xF4\x3B\x08\x12\x30\x63\xD0\x6D\xF0\xB3\x16\x1D\x0B" +// "\xFB\xF9\xF8\x5F\xC3\x2B\x09\x10\xC1\x5A\x16\x8C\xF2\x26\x13\x0E\xBF\x9D\xA1\xF8" +// "\xF4\x3B\x01\x23\x04\x04\x8C\x48\x85\x97\xC8\x20\x43\xE0\xDC\x7C\x7C\x7C\xE8\x30" +// "\x10\x71\xA3\xA0\x78\x34\x12\x71\x22\x16\x5F\x20\x8F\xC3\xD0\x6E\x08\xC2\x21\x1F" +// "\x83\xFE\x8C\xAD\xCE\x3F\x01\x0F\x49\x14\x2D\xA2\x18\xFF\xEC\xEB\x09\x10\xFE\xFD" +// "\x84\xFD\xE4\x41\x68\xF0\xAA\xDE\x1E\x3D\x0E\xC0\x4C\xC5\x41\x07\x27\x2E\xB1\xAC" +// "\x12\x32\x01\xC0\x83\xC2\x41\xCA\x72\x88\x10\xB1\x10\x42\xE1\x13\x04\x61\x17\x0B" +// "\x1A\x39\xFC\xFC\x38\xA9\x36\xEA\xBB\x5D\x90\x21\xE0\x20\x83\x58\xF4\xF3\xFE\xD8" +// "\x21\xCA\x3D\xA6\xC3\x96\x7A\x1D\x84\x09\x13\x8F\x42\x16\x42\x17\x1F\x82\xC5\xE8" +// "\x87\x99\xED\x36\x1C\xA3\xD0\xEC\x22\x16\x42\x17\x1F\x80\x87\xC7\x19\xF8\x7A\x1D" +// "\x9F\xCC\xA3\xF2\x70\xA4\x6E\x9C\x29\x1B\x8D"; const char HUE_DESCRIPTION_XML[] PROGMEM = "" "" @@ -137,22 +160,59 @@ const char HUE_DESCRIPTION_XML[] PROGMEM = "" "\r\n" "\r\n"; + +//%s"alert":"none","effect":"none","reachable":true} +//Successfully compressed from 50 to 34 bytes (-32%) +// const size_t HUE_LIGHTS_STATUS_JSON1_SUFFIX_size = 50; +// const char HUE_LIGHTS_STATUS_JSON1_SUFFIX[] PROGMEM = "\x3E\xBC\x7B\x2C\x27\xFA\x3D\x87\x99\xEC\xEC\xE6\x7B\x0E\xA3\xD8\xCC\x18\x61\x82" +// "\x34\xCF\xBB\x0C\x55\x8E\x09\x9E\xC3\xCE\xBE\x2D\x9E\xE3"; const char HUE_LIGHTS_STATUS_JSON1_SUFFIX[] PROGMEM = "%s\"alert\":\"none\"," "\"effect\":\"none\"," "\"reachable\":true}"; + +//,"type":"Extended color light","name":"%s","modelid":"%s","manufacturername":"%s","uniqueid":"%s"} +//Successfully compressed from 98 to 64 bytes (-34.7%) +// const size_t HUE_LIGHTS_STATUS_JSON2_size = 98; +// const char HUE_LIGHTS_STATUS_JSON2[] PROGMEM = "\x3A\x8F\x65\x19\x0C\x67\xB0\xF3\x3D\x84\xCD\x94\xF8\x46\x22\x0F\x02\xCF\xA0\xB4" +// "\x78\x55\x1E\xC3\xA8\xF6\x75\x8D\x67\xB0\xF3\x3D\x87\xD7\x8F\x61\xD4\x7B\x06\xE0" +// "\x8C\x2D\x10\x11\x25\xDF\x0B\x31\x61\xD0\xBF\xBF\x82\x3E\x06\x2F\xB4\xD4\x2D\x82" +// "\x1E\x08\x7B\x8D"; const char HUE_LIGHTS_STATUS_JSON2[] PROGMEM = ",\"type\":\"Extended color light\"," "\"name\":\"%s\"," "\"modelid\":\"%s\"," "\"manufacturername\":\"%s\"," "\"uniqueid\":\"%s\"}"; + +//{"name":"Group 0","lights":[{l1],"type":"LightGroup","action": +//Successfully compressed from 62 to 61 bytes (-1.6%) const char HUE_GROUP0_STATUS_JSON[] PROGMEM = "{\"name\":\"Group 0\"," "\"lights\":[{l1]," "\"type\":\"LightGroup\"," "\"action\":"; // "\"scene\":\"none\","; + +//{"name":"Philips hue","mac":"{ma","dhcp":true,"ipaddress":"{ip","netmask":"{ms","gateway":"{gw","proxyaddress":"none","proxyport":0,"bridgeid":"{br","UTC":"{dt","whitelist":{"{id":{"last use date":"{dt","create date":"{dt","name":"Remote"}},"swversion":"01041302","apiversion":"1.17.0","swupdate":{"updatestate":0,"url":"","text":"","notify": false},"linkbutton":false,"portalservices":false} +//Successfully compressed from 392 to 302 bytes (-23%) +// const size_t HueConfigResponse_JSON_size = 392; +// const char HueConfigResponse_JSON[] PROGMEM = "\x3D\xA7\xB3\xAC\x6B\x3D\x87\x99\xEC\x21\x82\xB4\x2D\x19\xE4\x28\x5B\x3D\x87\x51" +// "\xEC\x1B\x61\x9E\xC3\xCC\xF6\x1E\xD1\xB6\x7B\x0E\xA3\xD8\x20\xA0\xC6\x1E\xC3\xCE" +// "\xBE\x2D\x9D\x47\xB3\x46\x58\x82\x7D\xFB\xC7\xB0\xF3\x3D\x87\xB7\x46\x1E\xC3\xA8" +// "\xF6\x73\xA1\xB7\xE3\x43\xD8\x79\x9E\xC3\xDA\x37\xC7\xB0\xEA\x3D\x83\xD7\x4C\x7E" +// "\xCC\x8F\x61\xE6\x7B\x0F\x68\xF0\xF9\xEC\x3A\x8F\x60\xCF\xE1\xB0\xC8\x11\x71\x1E" +// "\xCE\x60\x87\x48\x66\x7E\x8F\x61\xE6\x71\x9D\x47\xB0\x87\x7F\x44\x1E\x7A\x21\xEC" +// "\x3C\xCF\x61\xED\x1D\xF3\xD8\x75\x1E\xC2\x16\x54\x41\x9E\xC3\xCC\xF6\x1E\xD1\x28" +// "\xF6\x1D\x47\xB0\x7C\x56\xD3\x0B\x7D\x47\xB0\xF3\x3D\xA7\xB0\xF6\xE8\x87\xB0\xF3" +// "\x3D\xA7\xB0\x2B\xF5\x21\x7E\x68\x4B\xA6\x08\x98\x30\x7F\x77\x40\x95\x40\x10\xB8" +// "\x3A\x2F\xB1\xB9\x4C\xF6\x1E\xE3\xDC\x75\x1E\xCF\x0F\x99\xBF\xFB\x73\x8F\x61\xE6" +// "\x7B\x0E\x38\xF2\x5B\xA3\xD8\x75\x1E\xC2\xB1\x9A\x08\xB5\x0E\x43\xA4\xF1\xD1\x9E" +// "\xC3\xA8\xF6\x17\x87\xC5\x8C\x04\x1C\xB0\xF6\x9E\xC0\x41\x8D\xEA\xBA\x67\xB0\xF3" +// "\x38\xCE\xA3\xD8\x42\xFE\x11\xEC\x3C\xCF\x61\xEC\x3A\x8F\x65\x33\x65\x02\x0C\x6E" +// "\xCA\xD3\x06\x47\xB0\xF3\x46\x2C\x2F\x33\xDC\x75\x1E\xC0\xB7\x8D\x07\x0B\xAA\xCE" +// "\x3D\x87\x99\x8B\x0B\xCC\xEA\x3D\x83\x33\xF5\x61\x79\xFC\xCF\x43\x7E\x04\x2A\x2B" +// "\x67\xB8"; const char HueConfigResponse_JSON[] PROGMEM = "{\"name\":\"Philips hue\"," "\"mac\":\"{ma\"," From 6154fd1015104dbdfbf885a5c9e3fe94384979fd Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 22 May 2020 23:05:55 +0200 Subject: [PATCH 13/20] Fixed compilation error --- tasmota/support.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/support.ino b/tasmota/support.ino index a053b6c34..f43a40569 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -1939,7 +1939,7 @@ String escapeJSONString(const char *str) { #if defined(USE_RULES_COMPRESSION) || defined(USE_SCRIPT_COMPRESSION) -#include +#include Unishox compressor; From e780f2528328cf3a10f032b618054cd7dc98ca18 Mon Sep 17 00:00:00 2001 From: George Date: Sat, 23 May 2020 17:13:04 +1000 Subject: [PATCH 14/20] Gamma correction Implement changes proposed by @s-hadinger review. * Use 0-255 range in settings * Apply gamma correction from xdrv_light & use changuintscale helper fn (as per pwm light routine) --- tasmota/settings.h | 8 ++++---- tasmota/settings.ino | 4 ++-- tasmota/support_command.ino | 8 ++++---- tasmota/support_tasmota.ino | 24 ++++++++---------------- 4 files changed, 18 insertions(+), 26 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index 0cc171601..e8bae5182 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -570,12 +570,12 @@ struct { int16_t windmeter_speed_factor; // F3C uint8_t windmeter_tele_pchange; // F3E uint8_t ledpwm_mask; // F3F - - uint8_t free_f40[116]; // F40 - Decrement if adding new Setting variables just above and below + uint8_t ledpwm_on; // F40 + uint8_t ledpwm_off; // F41 + + uint8_t free_f42[118]; // F42 - Decrement if adding new Setting variables just above and below // Only 32 bit boundary variables below - uint16_t ledpwm_on; // FB4 - uint16_t ledpwm_off; // FB6 uint16_t pulse_counter_debounce_low; // FB8 uint16_t pulse_counter_debounce_high; // FBA uint32_t keeloq_master_msb; // FBC diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 85a205da2..8d771a109 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1058,7 +1058,7 @@ void SettingsDefaultSet2(void) // Led PWM Settings.ledpwm_off = 0; - Settings.ledpwm_on = 1023; + Settings.ledpwm_on = 255; Settings.ledpwm_mask = 0; } @@ -1420,7 +1420,7 @@ void SettingsDelta(void) // ledpwm if (Settings.version < 0x08030001) { Settings.ledpwm_off = 0; - Settings.ledpwm_on = 1023; + Settings.ledpwm_on = 255; Settings.ledpwm_mask = 0; } diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 2f327b9a1..f52fb7ea5 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -1896,8 +1896,8 @@ void CmndSetLedPwmOff(void) if (XdrvMailbox.data_len > 0) { if (XdrvMailbox.payload < 0) { Settings.ledpwm_off = 0; - } else if (XdrvMailbox.payload > Settings.pwm_range) { - Settings.ledpwm_off = Settings.pwm_range; + } else if (XdrvMailbox.payload > 255) { + Settings.ledpwm_off = 255; } else { Settings.ledpwm_off = XdrvMailbox.payload; } @@ -1911,8 +1911,8 @@ void CmndSetLedPwmOn(void) if (XdrvMailbox.data_len > 0) { if (XdrvMailbox.payload < 0) { Settings.ledpwm_on = 0; - } else if (XdrvMailbox.payload > Settings.pwm_range) { - Settings.ledpwm_on = Settings.pwm_range; + } else if (XdrvMailbox.payload > 255) { + Settings.ledpwm_on = 255; } else { Settings.ledpwm_on = XdrvMailbox.payload; } diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index d96751e32..374cb6884 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -358,24 +358,16 @@ void SetLedPowerIdx(uint32_t led, uint32_t state) } else { led_power &= (0xFF ^ mask); } - uint16_t led_pwm_set = 0; + uint16_t pwm = 0; if (bitRead(Settings.ledpwm_mask, led)) { - if (bitRead(led_inverted, led)) { - if (state) { - led_pwm_set = Settings.pwm_range - Settings.ledpwm_on; - } else { - led_pwm_set = Settings.pwm_range - Settings.ledpwm_off; - } - } else { - if (state) { - led_pwm_set = Settings.ledpwm_on; - } else { - led_pwm_set = Settings.ledpwm_off; - } - } - analogWrite(Pin(GPIO_LED1, led), led_pwm_set); + #ifdef USE_LIGHT + pwm = changeUIntScale(ledGamma10(state ? Settings.ledpwm_on : Settings.ledpwm_off), 0, 1023, 0, Settings.pwm_range); // gamma corrected + #else //USE_LIGHT + pwm = changeUIntScale((uint16_t)(state ? Settings.ledpwm_on : Settings.ledpwm_off), 0, 255, 0, Settings.pwm_range); // linear + #endif //USE_LIGHT + analogWrite(Pin(GPIO_LED1, led), bitRead(led_inverted, led) ? Settings.pwm_range - pwm : pwm); } else { - DigitalWrite(GPIO_LED1, led, bitRead(led_inverted, led) ? !state : state); + DigitalWrite(GPIO_LED1, led, bitRead(led_inverted, led) ? !state : state); } } #ifdef USE_BUZZER From 02faa2ea492e56d2c66a40638070f3d93db91013 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sat, 23 May 2020 10:05:57 +0200 Subject: [PATCH 15/20] Fix style and compilation error when no compression --- tasmota/support.ino | 2 +- tasmota/xdrv_10_rules.ino | 2 +- tasmota/xdrv_21_wemo.ino | 32 ++++++++++++++++++++++++-------- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/tasmota/support.ino b/tasmota/support.ino index f43a40569..cecb5ffb2 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -1943,7 +1943,7 @@ String escapeJSONString(const char *str) { Unishox compressor; -String decompress(const char * compressed, size_t uncompressed_size) { +String Decompress(const char * compressed, size_t uncompressed_size) { String content(""); uncompressed_size += 2; // take a security margin diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino index 7dcc90498..912a32ae5 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/xdrv_10_rules.ino @@ -263,7 +263,7 @@ void GetRule_decompress(String &rule, const char *rule_head) { size_t buf_len = 1 + *rule_head * 8; // the first byte contains size of buffer for uncompressed rule / 8, buf_len may overshoot by 7 rule_head++; // advance to the actual compressed buffer - rule = decompress(rule_head, buf_len); + rule = Decompress(rule_head, buf_len); } #endif // USE_RULES_COMPRESSION diff --git a/tasmota/xdrv_21_wemo.ino b/tasmota/xdrv_21_wemo.ino index 20236df6e..86022b084 100644 --- a/tasmota/xdrv_21_wemo.ino +++ b/tasmota/xdrv_21_wemo.ino @@ -89,7 +89,7 @@ void WemoRespondToMSearch(int echo_type) //SetBinaryStateBinaryStateBinaryStateinGetBinaryStateBinaryStateBinaryStateoutBinaryStatebool0levelstring0\r\n\r\n //Successfully compressed from 779 to 249 bytes (-68%) -const size_t WEMO_EVENTSERVICE_XML_size = 779; +const size_t WEMO_EVENTSERVICE_XML_SIZE = 779; const char WEMO_EVENTSERVICE_XML[] PROGMEM = "\x3D\x3C\x18\xC1\x11\xB0\x68\x5D\xE3\xE1\xEC\x17\xFE\x3C\xC8\x73\x08\xD3\x78\xF3" "\xF3\xF9\x9E\x86\xCE\xB3\x90\xEB\x67\xB0\xFC\x3D\x0A\xC3\xAD\xCE\x20\xB7\xD4\x08" "\x72\x0F\xC3\xD3\xAC\x6B\x3F\x0B\xCE\x88\x76\xF5\xFC\xC8\xBD\x57\x4C\xF4\x3B\x3A" @@ -106,7 +106,7 @@ const char WEMO_EVENTSERVICE_XML[] PROGMEM = "\x3D\x3C\x18\xC1\x11\xB0\x68\x5D\x //10GetMetaInfoGetMetaInfoMetaInfoinMetaInfostring0\r\n\r\n //Successfully compressed from 479 to 253 bytes (-47.2%) -const size_t WEMO_METASERVICE_XML_size = 479; +const size_t WEMO_METASERVICE_XML_SIZE = 479; const char WEMO_METASERVICE_XML[] PROGMEM = "\x3D\x3C\x18\xC1\x11\xB0\x68\x5D\xE3\xE1\xEC\x17\xFE\x3C\xC8\x73\x08\xD3\x78\xF3" "\xF3\xF9\x9E\x86\xCE\xB3\x90\xEB\x67\xB0\xFC\x3D\x0B\xC3\x18\x64\x66\xFF\xED\xCE" "\x3F\x0F\x41\xB6\x6B\xCF\x9F\x87\x21\xE8\x76\x10\x20\xC5\x3D\x06\xEF\x67\xCF\xC3" @@ -123,7 +123,7 @@ const char WEMO_METASERVICE_XML[] PROGMEM = "\x3D\x3C\x18\xC1\x11\xB0\x68\x5D\xE //%d\r\n //Successfully compressed from 282 to 161 bytes (-42.9%) -const size_t WEMO_RESPONSE_STATE_SOAP_size = 282; +const size_t WEMO_RESPONSE_STATE_SOAP_SIZE = 282; const char WEMO_RESPONSE_STATE_SOAP[] PROGMEM = "\x3D\x3C\x79\x93\xE3\x36\x16\x0C\x68\xD8\x34\x2E\xF1\xE7\xE3\xE1\xEC\x15\x54\x30" "\xF3\x3B\x0E\xCF\x06\x29\x8D\xBF\x1D\x0D\x83\x42\xF6\x58\xC3\xA6\x7C\x78\xEC\xF6" "\x58\xC3\xB1\x82\x16\x1C\x76\x1E\xC5\xE3\xCD\xF0\x78\x26\xF0\xF1\x7A\x8C\x82\x60" @@ -136,7 +136,7 @@ const char WEMO_RESPONSE_STATE_SOAP[] PROGMEM = "\x3D\x3C\x79\x93\xE3\x36\x16\x0 //urn:Belkin:device:controllee:1{x1Belkin International Inc.Socket3.1415uuid:{x2{x30urn:Belkin:service:basicevent:1urn:Belkin:serviceId:basicevent1/upnp/control/basicevent1/upnp/event/basicevent1/eventservice.xmlurn:Belkin:service:metainfo:1urn:Belkin:serviceId:metainfo1/upnp/control/metainfo1/upnp/event/metainfo1/metainfoservice.xml\r\n //Successfully compressed from 923 to 392 bytes (-57.5%) -const size_t WEMO_SETUP_XML_size = 923; +const size_t WEMO_SETUP_XML_SIZE = 923; const char WEMO_SETUP_XML[] PROGMEM = "\x3D\x0E\xD1\xB0\x68\x48\xCD\xFF\xDB\x9C\x7C\x3D\x87\x21\xD1\x9E\xC3\xB4\x7E\x1E" "\x85\xFC\xCA\x46\xC1\xA1\x77\x8F\x87\xB0\x5F\xF8\xF3\x21\xCC\x23\x4D\xE3\xCC\x46" "\x67\xA1\xB3\xAC\xE4\x3A\xD9\xEC\x3F\x0F\x42\x04\x19\x20\x87\x10\xA8\xC8\x63\x3F" @@ -293,7 +293,11 @@ void HandleUpnpEvent(void) } } - snprintf_P(event, sizeof(event), decompress(WEMO_RESPONSE_STATE_SOAP, WEMO_RESPONSE_STATE_SOAP_size).c_str(), state, bitRead(power, devices_present -1), state); +#if defined(USE_RULES_COMPRESSION) || defined(USE_SCRIPT_COMPRESSION) + snprintf_P(event, sizeof(event), Decompress(WEMO_RESPONSE_STATE_SOAP, WEMO_RESPONSE_STATE_SOAP_SIZE).c_str(), state, bitRead(power, devices_present -1), state); +#else + snprintf_P(event, sizeof(event), WEMO_RESPONSE_STATE_SOAP, state, bitRead(power, devices_present -1), state); +#endif WSSend(200, CT_XML, event); } @@ -301,21 +305,33 @@ void HandleUpnpService(void) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_EVENT_SERVICE)); - WSSend(200, CT_PLAIN, decompress(WEMO_EVENTSERVICE_XML, WEMO_EVENTSERVICE_XML_size)); +#if defined(USE_RULES_COMPRESSION) || defined(USE_SCRIPT_COMPRESSION) + WSSend(200, CT_PLAIN, Decompress(WEMO_EVENTSERVICE_XML, WEMO_EVENTSERVICE_XML_SIZE)); +#else + WSSend(200, CT_PLAIN, FPSTR(WEMO_EVENTSERVICE_XML)); +#endif } void HandleUpnpMetaService(void) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_META_SERVICE)); - WSSend(200, CT_PLAIN, decompress(WEMO_METASERVICE_XML, WEMO_METASERVICE_XML_size)); +#if defined(USE_RULES_COMPRESSION) || defined(USE_SCRIPT_COMPRESSION) + WSSend(200, CT_PLAIN, Decompress(WEMO_METASERVICE_XML, WEMO_METASERVICE_XML_SIZE)); +#else + WSSend(200, CT_PLAIN, FPSTR(WEMO_METASERVICE_XML)); +#endif } void HandleUpnpSetupWemo(void) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_SETUP)); - String setup_xml = decompress(WEMO_SETUP_XML, WEMO_SETUP_XML_size); +#if defined(USE_RULES_COMPRESSION) || defined(USE_SCRIPT_COMPRESSION) + String setup_xml = Decompress(WEMO_SETUP_XML, WEMO_SETUP_XML_SIZE); +#else + String setup_xml = FPSTR(WEMO_SETUP_XML); +#endif setup_xml.replace("{x1", SettingsText(SET_FRIENDLYNAME1)); setup_xml.replace("{x2", WemoUuid()); setup_xml.replace("{x3", WemoSerialnumber()); From 584b3c2ef856babc4b8071cf70cfe61264439034 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Sat, 23 May 2020 10:24:08 +0200 Subject: [PATCH 16/20] scripter update add direct access to some energy registers and sml registers make google charts optional #define USE_GOOGLE_CHARTS --- tasmota/xdrv_10_scripter.ino | 458 +++++++++++++++++++++++++---------- tasmota/xsns_53_sml.ino | 9 +- 2 files changed, 335 insertions(+), 132 deletions(-) diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index eb0d00f29..199154644 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -1228,6 +1228,52 @@ chknext: fvar=UtcTime()-(uint32_t)EPOCH_OFFSET; goto exit; } +#ifdef USE_ENERGY_SENSOR + if (!strncmp(vname,"enrg[",5)) { + lp+=5; + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + while (*lp==' ') lp++; + switch ((uint32_t)fvar) { + case 0: + fvar=Energy.total; + break; + case 1: + fvar=Energy.voltage[0]; + break; + case 2: + fvar=Energy.voltage[1]; + break; + case 3: + fvar=Energy.voltage[2]; + break; + case 4: + fvar=Energy.current[0]; + break; + case 5: + fvar=Energy.current[1]; + break; + case 6: + fvar=Energy.current[2]; + break; + case 7: + fvar=Energy.active_power[0]; + break; + case 8: + fvar=Energy.active_power[1]; + break; + case 9: + fvar=Energy.active_power[2]; + break; + + default: + fvar=99999; + break; + } + len=0; + lp++; + goto exit; + } +#endif //USE_ENERGY_SENSOR break; case 'f': #ifdef USE_SCRIPT_FATFS @@ -1948,6 +1994,15 @@ chknext: } #endif #if defined(USE_SML_M) && defined (USE_SML_SCRIPT_CMD) + if (!strncmp(vname,"sml[",4)) { + lp+=4; + lp=GetNumericResult(lp,OPER_EQU,&fvar,0); + SCRIPT_SKIP_SPACES + fvar=SML_GetVal[fvar]; + lp++; + len=0; + goto exit; + } if (!strncmp(vname,"sml(",4)) { lp+=4; float fvar1; @@ -3948,6 +4003,12 @@ void ScriptSaveSettings(void) { strlcpy(glob_script_mem.script_ram,str.c_str(), glob_script_mem.script_size); + if (glob_script_mem.script_ram[0]!='>' && glob_script_mem.script_ram[1]!='D') { + AddLog_P2(LOG_LEVEL_INFO, PSTR("script error: must start with >D")); + bitWrite(Settings.rule_enabled, 0, 0); + } + + #if defined(USE_24C256) && !defined(USE_SCRIPT_FATFS) if (glob_script_mem.flags&1) { EEP_WRITE(0,EEP_SCRIPT_SIZE,glob_script_mem.script_ram); @@ -3983,9 +4044,9 @@ void ScriptSaveSettings(void) { #ifndef ESP32_SCRIPT_SIZE //AddLog_P2(LOG_LEVEL_INFO,PSTR("in string: %s len = %d"),glob_script_mem.script_ram,strlen(glob_script_mem.script_ram)); - uint32_t len_compressed = SCRIPT_COMPRESS(glob_script_mem.script_ram, strlen(glob_script_mem.script_ram)+1, Settings.rules[0], MAX_SCRIPT_SIZE-1); - Settings.rules[0][len_compressed] = 0; + uint32_t len_compressed = SCRIPT_COMPRESS(glob_script_mem.script_ram, strlen(glob_script_mem.script_ram), Settings.rules[0], MAX_SCRIPT_SIZE-1); if (len_compressed > 0) { + Settings.rules[0][len_compressed] = 0; AddLog_P2(LOG_LEVEL_INFO,PSTR("script compressed to %d %%"),len_compressed * 100 / strlen(glob_script_mem.script_ram)); } else { AddLog_P2(LOG_LEVEL_INFO, PSTR("script compress error: %d"), len_compressed); @@ -4899,12 +4960,20 @@ const char SCRIPT_MSG_TEXTINP[] PROGMEM = const char SCRIPT_MSG_NUMINP[] PROGMEM = "
"; + +#ifdef USE_GOOGLE_CHARTS const char SCRIPT_MSG_GTABLE[] PROGMEM = "" "" - "" - "" - ""; + "" + ""; + +const char SCRIPT_MSG_TABLE[] PROGMEM = + ""; +const char SCRIPT_MSG_GAUGE[] PROGMEM = + ""; +const char SCRIPT_MSG_TIMELINE[] PROGMEM = + ""; const char SCRIPT_MSG_GTABLEa[] PROGMEM = @@ -4913,9 +4982,15 @@ const char SCRIPT_MSG_GTABLEa[] PROGMEM = "var data=google.visualization.arrayToDataTable(["; +const char SCRIPT_MSG_GTABLEd[] PROGMEM = +"['Timeline','start','end'],"; + +//#define CHART_EXTRA_OPTIONS ",width:'640px',height:'480px'" +#define CHART_EXTRA_OPTIONS + const char SCRIPT_MSG_GTABLEb[] PROGMEM = "]);" - "var options={%s};" + "var options={%s" CHART_EXTRA_OPTIONS "};" "var chart=new google.visualization.%s(document.getElementById('chart%1d'));" "chart.draw(data,options);}" "google.charts.setOnLoadCallback(drawChart);"; @@ -4923,15 +4998,83 @@ const char SCRIPT_MSG_GTABLEb[] PROGMEM = const char SCRIPT_MSG_GOPT1[] PROGMEM = "title:'%s',isStacked:false"; -const char SCRIPT_MSG_GOPT3[] PROGMEM = -"title:'%s',vAxes:{0:{maxValue:%d},1:{maxValue:%d}},series:{0:{targetAxisIndex:0},1:{targetAxisIndex:1}}"; - - const char SCRIPT_MSG_GOPT2[] PROGMEM = "showRowNumber:true,sort:'disable',allowHtml:true,width:'100%%',height:'100%%',cssClassNames:cssc"; +const char SCRIPT_MSG_GOPT3[] PROGMEM = +"title:'%s',isStacked:false,vAxes:{0:{maxValue:%d},1:{maxValue:%d}},series:{0:{targetAxisIndex:0},1:{targetAxisIndex:1}}%s"; + +const char SCRIPT_MSG_GOPT4[] PROGMEM = +//"hAxis:{minValue:new Date(0,1,1,0,0),maxValue:new Date(0,1,2,0,0),format:'HH:mm'}"; +"hAxis:{minValue:new Date(0,1,1,0,0),maxValue:new Date(0,1,2,0,0),format:'HH:mm'},theme: 'maximized'"; + +const char SCRIPT_MSG_GOPT5[] PROGMEM = +"new Date(0,1,1,%d,%d)"; + const char SCRIPT_MSG_GTE1[] PROGMEM = "'%s'"; +#define GLIBS_MAIN 1<<0 +#define GLIBS_TABLE 1<<1 +#define GLIBS_GAUGE 1<<2 +#define GLIBS_TIMELINE 1<<3 + +#define MAX_GARRAY 4 + +char *gc_get_arrays(char *lp, float **arrays, uint8_t *ranum, uint8_t *rentries) { +struct T_INDEX ind; +uint8_t vtype; +uint8 entries=0; + + uint8_t anum=0; + while (anum> 2 %d\n",(uint32_t)*fa); + if (fa && len>=entries) { + if (!entries) {entries = len;} + // add array to list + arrays[anum]=fa; + anum++; + } + } + } else { + lp=lp1; + break; + } + } + } + *ranum=anum; + *rentries=entries; + return lp; +} + +char *gc_send_labels(char *lp,uint32_t anum) { + WSContentSend_PD("["); + for (uint32_t cnt=0; cnt> 2 %d\n",(uint32_t)*fa); - if (fa && len>=entries) { - if (!entries) {entries = len;} - // add array to list - arrays[anum]=fa; - anum++; - } - } - } else { - lp=lp1; - break; - } - } - } - //Serial.printf("arrays %d\n",anum); - //Serial.printf("entries %d\n",entries); - - if (!google_libs) { - WSContentSend_PD(SCRIPT_MSG_GTABLE); - google_libs=1; - } - - WSContentSend_PD(SCRIPT_MSG_GTABLEa); - - // we know how many arrays and the number of entries - // we need to fetch the labels now - WSContentSend_PD("["); - for (uint32_t cnt=0; cntnanum) { + goto nextwebline; + } + // we know how many arrays and the number of entries + //Serial.printf("arrays %d\n",anum); + //Serial.printf("entries %d\n",entries); + if (ctype=='T') { + if (anum && !(entries&1)) { + WSContentSend_PD(SCRIPT_MSG_GTABLEa); + WSContentSend_PD(SCRIPT_MSG_GTABLEd); + char label[SCRIPT_MAXSSIZE]; + lp=GetStringResult(lp,OPER_EQU,label,0); + SCRIPT_SKIP_SPACES + char *lblp=label; + for (uint32_t ind=0; ind0) glob_script_mem.script_ram[len_decompressed]=0; //AddLog_P2(LOG_LEVEL_INFO, PSTR("decompressed script len %d"),len_decompressed); #endif #endif @@ -5568,6 +5756,14 @@ bool Xdrv10(uint8_t function) glob_script_mem.flags=1; #endif + // a valid script MUST start with >D + if (glob_script_mem.script_ram[0]!='>' && glob_script_mem.script_ram[1]!='D') { + // clr all + memset(glob_script_mem.script_ram,0,glob_script_mem.script_size); + strcpy_P(glob_script_mem.script_ram, PSTR(">D\nscript error must start with >D")); + bitWrite(Settings.rule_enabled, 0, 0); + } + // assure permanent memory is 4 byte aligned { uint32_t ptr=(uint32_t)glob_script_mem.script_pram; ptr&=0xfffffffc; diff --git a/tasmota/xsns_53_sml.ino b/tasmota/xsns_53_sml.ino index c63478b48..3b4357b26 100755 --- a/tasmota/xsns_53_sml.ino +++ b/tasmota/xsns_53_sml.ino @@ -2151,6 +2151,7 @@ init10: #else #ifdef ESP32 meter_ss[meters] = new HardwareSerial(uart_index); + if (uart_index==0) { ClaimSerial(); } uart_index--; if (uart_index<0) uart_index=0; #else @@ -2216,7 +2217,13 @@ uint32_t SML_Write(uint32_t meter,char *hstr) { SML_Send_Seq(meter,hstr); return 1; } -#endif + +float SML_GetVal(uint32_t index) { + if (index<1 && index>SML_MAX_VARS) { index = 1;} + return meter_vars[index-1]; +} + +#endif // USE_SML_SCRIPT_CMD void SetDBGLed(uint8_t srcpin, uint8_t ledpin) { From 2eccc09086e24805e2b5db8f27085ba882c79723 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Sat, 23 May 2020 10:36:19 +0200 Subject: [PATCH 17/20] remove unishox def --- tasmota/xdrv_10_scripter.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index 199154644..cf148c97b 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -71,7 +71,7 @@ uint32_t DecodeLightId(uint32_t hue_id); #ifdef USE_SCRIPT_COMPRESSION #include -Unishox compressor; // singleton +//Unishox compressor; // singleton #define SCRIPT_COMPRESS compressor.unishox_compress #define SCRIPT_DECOMPRESS compressor.unishox_decompress #ifndef UNISHOXRSIZE From d0de78352f592aa611dc83348e0188b7be2d1990 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 23 May 2020 12:15:14 +0200 Subject: [PATCH 18/20] Fix Energy Frequency display --- tasmota/xdrv_03_energy.ino | 7 ++++--- tasmota/xnrg_07_ade7953.ino | 5 ++--- tasmota/xnrg_10_sdm630.ino | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/tasmota/xdrv_03_energy.ino b/tasmota/xdrv_03_energy.ino index 2caaaa292..f5e4a729d 100644 --- a/tasmota/xdrv_03_energy.ino +++ b/tasmota/xdrv_03_energy.ino @@ -97,7 +97,8 @@ struct ENERGY { uint8_t data_valid[3] = { 0, 0, 0 }; uint8_t phase_count = 1; // Number of phases active - bool voltage_common = false; // Use single voltage and frequency + bool voltage_common = false; // Use single voltage + bool frequency_common = false; // Use single frequency bool kWhtoday_offset_init = false; bool voltage_available = true; // Enable if voltage is measured @@ -1036,7 +1037,7 @@ void EnergyShow(bool json) } if (!isnan(Energy.frequency[0])) { ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":%s"), - EnergyFormat(value_chr, frequency_chr[0], json, Energy.voltage_common)); + EnergyFormat(value_chr, frequency_chr[0], json, Energy.frequency_common)); } } if (Energy.voltage_available) { @@ -1103,7 +1104,7 @@ void EnergyShow(bool json) } if (!isnan(Energy.frequency[0])) { WSContentSend_PD(PSTR("{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"), - EnergyFormat(value_chr, frequency_chr[0], json, Energy.voltage_common)); + EnergyFormat(value_chr, frequency_chr[0], json, Energy.frequency_common)); } } WSContentSend_PD(HTTP_ENERGY_SNS2, energy_daily_chr, energy_yesterday_chr, energy_total_chr); diff --git a/tasmota/xnrg_07_ade7953.ino b/tasmota/xnrg_07_ade7953.ino index 44bec2e59..3d7b405d5 100644 --- a/tasmota/xnrg_07_ade7953.ino +++ b/tasmota/xnrg_07_ade7953.ino @@ -209,10 +209,9 @@ void Ade7953DrvInit(void) } I2cSetActiveFound(ADE7953_ADDR, "ADE7953"); Ade7953.init_step = 2; - Energy.phase_count = 2; // Handle two channels as two phases - Energy.voltage_common = true; // Use common voltage and frequency - + Energy.voltage_common = true; // Use common voltage + Energy.frequency_common = true; // Use common frequency energy_flg = XNRG_07; } } diff --git a/tasmota/xnrg_10_sdm630.ino b/tasmota/xnrg_10_sdm630.ino index 026c3b4e8..d239c1c73 100644 --- a/tasmota/xnrg_10_sdm630.ino +++ b/tasmota/xnrg_10_sdm630.ino @@ -203,6 +203,7 @@ void Sdm630SnsInit(void) if (result) { if (2 == result) { ClaimSerial(); } Energy.phase_count = 3; + Energy.frequency_common = true; // Use common frequency } else { energy_flg = ENERGY_NONE; } From dc9ce428889470de66a435aee155bedd5d185c85 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 23 May 2020 13:04:17 +0200 Subject: [PATCH 19/20] Refactor LedPwm code --- tasmota/i18n.h | 8 +++----- tasmota/settings.h | 13 +++++-------- tasmota/settings.ino | 18 +++++------------- tasmota/support_command.ino | 34 ++++++++++++++++++---------------- 4 files changed, 31 insertions(+), 42 deletions(-) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index a2e9e16b0..98e20d9ac 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -295,6 +295,9 @@ #define D_CMND_LEDPOWER "LedPower" #define D_CMND_LEDSTATE "LedState" #define D_CMND_LEDMASK "LedMask" +#define D_CMND_LEDPWMOFF "LedPwmOff" +#define D_CMND_LEDPWMON "LedPwmOn" +#define D_CMND_LEDPWMMODE "LedPwmMode" #define D_CMND_WIFIPOWER "WifiPower" #define D_CMND_SPEEDUNIT "SpeedUnit" #define D_CMND_I2CSCAN "I2CScan" @@ -587,11 +590,6 @@ // Commands xsns_02_analog.ino #define D_CMND_ADCPARAM "AdcParam" -// Commands led pwm settings -#define D_CMND_SETLEDPWMOFF "LedPwmOff" -#define D_CMND_SETLEDPWMON "LedPwmOn" -#define D_CMND_SETLEDPWMMODE "LedPwmMode" - // xsns_70_veml6075.ino #define D_JSON_UVA_INTENSITY "UvaIntensity" #define D_JSON_UVB_INTENSITY "UvbItensity" diff --git a/tasmota/settings.h b/tasmota/settings.h index e8bae5182..6ff0c4213 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -515,9 +515,7 @@ struct { uint8_t ot_hot_water_setpoint; // E8C uint8_t ot_boiler_setpoint; // E8D uint8_t ot_flags; // E8E - - uint8_t free_e8f[1]; // E8F - + uint8_t ledpwm_mask; // F8F uint16_t dimmer_hw_min; // E90 uint16_t dimmer_hw_max; // E92 uint32_t deepsleep; // E94 @@ -569,11 +567,10 @@ struct { uint16_t windmeter_pulse_debounce; // F3A int16_t windmeter_speed_factor; // F3C uint8_t windmeter_tele_pchange; // F3E - uint8_t ledpwm_mask; // F3F - uint8_t ledpwm_on; // F40 - uint8_t ledpwm_off; // F41 - - uint8_t free_f42[118]; // F42 - Decrement if adding new Setting variables just above and below + uint8_t ledpwm_on; // F3F + uint8_t ledpwm_off; // F40 + + uint8_t free_f42[119]; // F41 - Decrement if adding new Setting variables just above and below // Only 32 bit boundary variables below uint16_t pulse_counter_debounce_low; // FB8 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 8d771a109..549799447 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -765,6 +765,9 @@ void SettingsDefaultSet2(void) Settings.blinkcount = APP_BLINKCOUNT; Settings.ledstate = APP_LEDSTATE; Settings.ledmask = APP_LEDMASK; +// Settings.ledpwm_off = 0; + Settings.ledpwm_on = 255; +// Settings.ledpwm_mask = 0; Settings.pulse_timer[0] = APP_PULSETIME; // for (uint32_t i = 1; i < MAX_PULSETIMERS; i++) { Settings.pulse_timer[i] = 0; } @@ -1055,11 +1058,6 @@ void SettingsDefaultSet2(void) Settings.flag2 = flag2; Settings.flag3 = flag3; Settings.flag4 = flag4; - - // Led PWM - Settings.ledpwm_off = 0; - Settings.ledpwm_on = 255; - Settings.ledpwm_mask = 0; } /********************************************************************************************/ @@ -1405,7 +1403,6 @@ void SettingsDelta(void) Settings.config_version = 1; // ESP32 #endif // ESP32 } - if (Settings.version < 0x08020006) { #ifdef ESP32 Settings.module = WEMOS; @@ -1416,18 +1413,13 @@ void SettingsDelta(void) if (Settings.rules[1][0] == 0) { Settings.rules[1][1] = 0; } if (Settings.rules[2][0] == 0) { Settings.rules[2][1] = 0; } } - - // ledpwm - if (Settings.version < 0x08030001) { + if (Settings.version < 0x08030002) { + SettingsUpdateText(SET_DEVICENAME, SettingsText(SET_FRIENDLYNAME1)); Settings.ledpwm_off = 0; Settings.ledpwm_on = 255; Settings.ledpwm_mask = 0; } - if (Settings.version < 0x08030002) { - SettingsUpdateText(SET_DEVICENAME, SettingsText(SET_FRIENDLYNAME1)); - } - Settings.version = VERSION; SettingsSave(1); } diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index f52fb7ea5..2ee5c17c4 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -27,7 +27,7 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix 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_DEVICENAME "|" 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 "|" D_CMND_HUMOFFSET "|" - D_CMND_SPEEDUNIT "|" D_CMND_GLOBAL_TEMP "|" D_CMND_GLOBAL_HUM "|" D_CMND_SETLEDPWMON "|" D_CMND_SETLEDPWMOFF "|" D_CMND_SETLEDPWMMODE "|" + D_CMND_SPEEDUNIT "|" D_CMND_GLOBAL_TEMP "|" D_CMND_GLOBAL_HUM "|" D_CMND_LEDPWMON "|" D_CMND_LEDPWMOFF "|" D_CMND_LEDPWMMODE "|" #ifdef USE_I2C D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|" #endif @@ -50,7 +50,7 @@ void (* const TasmotaCommand[])(void) PROGMEM = { &CmndSerialDelimiter, &CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig, &CmndDevicename, &CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset, &CmndTime, &CmndTimezone, &CmndTimeStd, &CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndWifiPower, &CmndTempOffset, &CmndHumOffset, - &CmndSpeedUnit, &CmndGlobalTemp, &CmndGlobalHum, &CmndSetLedPwmOn, &CmndSetLedPwmOff, &CmndSetLedPwmMode, + &CmndSpeedUnit, &CmndGlobalTemp, &CmndGlobalHum, &CmndLedPwmOn, &CmndLedPwmOff, &CmndLedPwmMode, #ifdef USE_I2C &CmndI2cScan, CmndI2cDriver, #endif @@ -1891,37 +1891,39 @@ void CmndDriver(void) XdrvCall(FUNC_COMMAND_DRIVER); } -void CmndSetLedPwmOff(void) +void CmndLedPwmOff(void) { if (XdrvMailbox.data_len > 0) { - if (XdrvMailbox.payload < 0) { - Settings.ledpwm_off = 0; - } else if (XdrvMailbox.payload > 255) { - Settings.ledpwm_off = 255; + if (XdrvMailbox.payload < 0) { + Settings.ledpwm_off = 0; + } + else if (XdrvMailbox.payload > 255) { + Settings.ledpwm_off = 255; } else { Settings.ledpwm_off = XdrvMailbox.payload; } - UpdateLedPowerAll(); + UpdateLedPowerAll(); } ResponseCmndNumber(Settings.ledpwm_off); } -void CmndSetLedPwmOn(void) +void CmndLedPwmOn(void) { if (XdrvMailbox.data_len > 0) { if (XdrvMailbox.payload < 0) { - Settings.ledpwm_on = 0; - } else if (XdrvMailbox.payload > 255) { - Settings.ledpwm_on = 255; - } else { - Settings.ledpwm_on = XdrvMailbox.payload; + Settings.ledpwm_on = 0; } - UpdateLedPowerAll(); + else if (XdrvMailbox.payload > 255) { + Settings.ledpwm_on = 255; + } else { + Settings.ledpwm_on = XdrvMailbox.payload; + } + UpdateLedPowerAll(); } ResponseCmndNumber(Settings.ledpwm_on); } -void CmndSetLedPwmMode(void) +void CmndLedPwmMode(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_LEDS)) { if (!PinUsed(GPIO_LEDLNK)) { XdrvMailbox.index = 1; } From aafa0862ab8246786628acf7339ef76ce69c5aec Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 23 May 2020 13:09:16 +0200 Subject: [PATCH 20/20] Refactor LedPwm code --- tasmota/support_tasmota.ino | 27 ++++++++++++++------------- tasmota/tasmota.ino | 2 +- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 374cb6884..08a2ac6ca 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -358,17 +358,17 @@ void SetLedPowerIdx(uint32_t led, uint32_t state) } else { led_power &= (0xFF ^ mask); } - uint16_t pwm = 0; - if (bitRead(Settings.ledpwm_mask, led)) { - #ifdef USE_LIGHT - pwm = changeUIntScale(ledGamma10(state ? Settings.ledpwm_on : Settings.ledpwm_off), 0, 1023, 0, Settings.pwm_range); // gamma corrected - #else //USE_LIGHT - pwm = changeUIntScale((uint16_t)(state ? Settings.ledpwm_on : Settings.ledpwm_off), 0, 255, 0, Settings.pwm_range); // linear - #endif //USE_LIGHT - analogWrite(Pin(GPIO_LED1, led), bitRead(led_inverted, led) ? Settings.pwm_range - pwm : pwm); - } else { - DigitalWrite(GPIO_LED1, led, bitRead(led_inverted, led) ? !state : state); - } + uint16_t pwm = 0; + if (bitRead(Settings.ledpwm_mask, led)) { +#ifdef USE_LIGHT + pwm = changeUIntScale(ledGamma10(state ? Settings.ledpwm_on : Settings.ledpwm_off), 0, 1023, 0, Settings.pwm_range); // gamma corrected +#else //USE_LIGHT + pwm = changeUIntScale((uint16_t)(state ? Settings.ledpwm_on : Settings.ledpwm_off), 0, 255, 0, Settings.pwm_range); // linear +#endif //USE_LIGHT + analogWrite(Pin(GPIO_LED1, led), bitRead(led_inverted, led) ? Settings.pwm_range - pwm : pwm); + } else { + DigitalWrite(GPIO_LED1, led, bitRead(led_inverted, led) ? !state : state); + } } #ifdef USE_BUZZER if (led == 0) { @@ -403,8 +403,9 @@ void SetLedLink(uint32_t state) uint32_t led_pin = Pin(GPIO_LEDLNK); uint32_t led_inv = ledlnk_inverted; if (99 == led_pin) { // Legacy - LED1 is status - SetLedPowerIdx(0, state); - } else if (led_pin < 99) { + SetLedPowerIdx(0, state); + } + else if (led_pin < 99) { if (state) { state = 1; } digitalWrite(led_pin, (led_inv) ? !state : state); } diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 92e3169b2..ecf1127ec 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -1,4 +1,4 @@ - /* +/* tasmota.ino - Tasmota firmware for iTead Sonoff, Wemos and NodeMCU hardware Copyright (C) 2020 Theo Arends