diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 249c87014..b9ea7ff21 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ /*********************************************************************************************\ + * 6.6.0.18 20191010 + * Add command DimmerRange in Light module to support 2 byte dimming ranges from Tuya + * * 6.6.0.17 20191009 * Add command SetOption34 0..255 to set backlog delay. Default value is 200 (mSeconds) (#6562) * Add command Gpio 255 to show physical GPIO configuration of all non-flash pins (#6407) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 0d7cdf0a9..d57c3f1a2 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -366,6 +366,7 @@ #define D_CMND_COLOR "Color" #define D_CMND_COLORTEMPERATURE "CT" #define D_CMND_DIMMER "Dimmer" +#define D_CMND_DIMMER_RANGE "DimmerRange" #define D_CMND_HSBCOLOR "HSBColor" #define D_CMND_LED "Led" #define D_CMND_LEDTABLE "LedTable" diff --git a/sonoff/settings.h b/sonoff/settings.h index 938102cc6..d4ebfda01 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -79,10 +79,10 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t no_power_feedback : 1; // bit 13 (v6.5.0.9) - SetOption63 - Don't scan relay power state at restart uint32_t use_underscore : 1; // bit 14 (v6.5.0.12) - SetOption64 - Enable "_" instead of "-" as sensor index separator uint32_t ex_tuya_disable_dimmer : 1; // bit 15 (v6.5.0.15) - SetOption65 - (Enable or Disable Tuya Serial Dimmer control) - free since 6.6.0.10 - uint32_t tuya_dimmer_range_255 : 1; // bit 16 (v6.6.0.1) - SetOption66 - Enable or Disable Dimmer range 255 slider control + uint32_t ex_tuya_dimmer_range_255 : 1; // bit 16 (v6.6.0.1) - SetOption66 - Enable or Disable Dimmer range 255 slider control uint32_t buzzer_enable : 1; // bit 17 (v6.6.0.1) - SetOption67 - Enable buzzer when available uint32_t pwm_multi_channels : 1; // bit 18 (v6.6.0.3) - SetOption68 - Enable multi-channels PWM instead of Color PWM - uint32_t tuya_dimmer_min_limit : 1; // bit 19 (v6.6.0.5) - SetOption69 - Limits Tuya dimmers to minimum of 10% (25) when enabled. + uint32_t ex_tuya_dimmer_min_limit : 1; // bit 19 (v6.6.0.5) - SetOption69 - Limits Tuya dimmers to minimum of 10% (25) when enabled. 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 / Disable hardware energy total counter as reference (#6561) @@ -384,8 +384,10 @@ struct SYSCFG { uint8_t shutter_position[MAX_SHUTTERS]; // E80 uint8_t shutter_startrelay[MAX_SHUTTERS]; // E84 uint8_t pcf8574_config[MAX_PCF8574]; // E88 + uint16_t dimmer_hw_min; // E8A + uint16_t dimmer_hw_max; // E8C - uint8_t free_e90[360]; // E90 + uint8_t free_e90[356]; // E90 uint32_t cfg_timestamp; // FF8 uint32_t cfg_crc32; // FFC diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 12647de97..faf17ff54 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -128,6 +128,11 @@ #ifndef DEFAULT_DIMMER_MAX #define DEFAULT_DIMMER_MAX 100 #endif +#ifndef DEFAULT_DIMMER_MIN +#define DEFAULT_DIMMER_MIN 10 +#endif + + enum WebColors { COL_TEXT, COL_BACKGROUND, COL_FORM, @@ -776,7 +781,8 @@ void SettingsDefaultSet2(void) // Settings.light_rotation = 0; SettingsDefaultSet_5_8_1(); // Clock color - Settings.param[P_DIMMER_MAX] = DEFAULT_DIMMER_MAX; + Settings.dimmer_hw_max = DEFAULT_DIMMER_MAX; + Settings.dimmer_hw_min = DEFAULT_DIMMER_MIN; // Display SettingsDefaultSet_5_10_1(); // Display settings @@ -1085,10 +1091,10 @@ void SettingsDelta(void) } if (Settings.version < 0x06060008) { // Move current tuya dimmer range to the new param. - if (Settings.flag3.tuya_dimmer_range_255) { - Settings.param[P_DIMMER_MAX] = 100; + if (Settings.flag3.ex_tuya_dimmer_range_255) { + Settings.param[P_ex_DIMMER_MAX] = 100; } else { - Settings.param[P_DIMMER_MAX] = 255; + Settings.param[P_ex_DIMMER_MAX] = 255; } } if (Settings.version < 0x06060009) { @@ -1141,6 +1147,18 @@ void SettingsDelta(void) Settings.param[P_BACKLOG_DELAY] = MIN_BACKLOG_DELAY; } + if (Settings.version < 0x06060012) { + Settings.dimmer_hw_max = Settings.param[P_ex_DIMMER_MAX]; + Settings.dimmer_hw_min = DEFAULT_DIMMER_MIN; + if (TUYA_DIMMER == Settings.module) { + if (Settings.flag3.ex_tuya_dimmer_min_limit) { + Settings.dimmer_hw_min = 25; + } else { + Settings.dimmer_hw_min = 1; + } + } + } + Settings.version = VERSION; SettingsSave(1); } diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 500933374..a075cef0f 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -247,7 +247,7 @@ enum Shortcuts { SC_CLEAR, SC_DEFAULT, SC_USER }; enum SettingsParamIndex { P_HOLD_TIME, P_MAX_POWER_RETRY, P_BACKLOG_DELAY, P_MDNS_DELAYED_START, P_BOOT_LOOP_OFFSET, P_RGB_REMAP, P_IR_UNKNOW_THRESHOLD, // SetOption32 .. SetOption38 P_CSE7766_INVALID_POWER, P_HOLD_IGNORE, P_ex_TUYA_RELAYS, P_OVER_TEMP, // SetOption39 .. SetOption42 - P_DIMMER_MAX, + P_ex_DIMMER_MAX, P_ex_TUYA_VOLTAGE_ID, P_ex_TUYA_CURRENT_ID, P_ex_TUYA_POWER_ID, // SetOption43 .. SetOption46 P_ex_ENERGY_TARIFF1, P_ex_ENERGY_TARIFF2, // SetOption47 .. SetOption48 P_MAX_PARAM8 }; // Max is PARAM8_SIZE (18) - SetOption32 until SetOption49 diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index bba6b708c..3f9afcc0e 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,6 +20,6 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -const uint32_t VERSION = 0x06060011; +const uint32_t VERSION = 0x06060012; #endif // _SONOFF_VERSION_H_ diff --git a/sonoff/support_command.ino b/sonoff/support_command.ino index 1d0872d79..781bd5769 100644 --- a/sonoff/support_command.ino +++ b/sonoff/support_command.ino @@ -711,7 +711,7 @@ void CmndSetoption(void) IrReceiveUpdateThreshold(); break; #endif - case P_DIMMER_MAX: + case P_ex_DIMMER_MAX: restart_flag = 2; // Need a restart to update GUI break; } diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 154024428..f64e021a0 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -129,12 +129,12 @@ enum LightSchemes { LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_M const uint8_t LIGHT_COLOR_SIZE = 25; // Char array scolor size const char kLightCommands[] PROGMEM = "|" // No prefix - D_CMND_COLOR "|" D_CMND_COLORTEMPERATURE "|" D_CMND_DIMMER "|" D_CMND_LEDTABLE "|" D_CMND_FADE "|" + D_CMND_COLOR "|" D_CMND_COLORTEMPERATURE "|" D_CMND_DIMMER "|" D_CMND_DIMMER_RANGE "|" D_CMND_LEDTABLE "|" D_CMND_FADE "|" D_CMND_RGBWWTABLE "|" D_CMND_SCHEME "|" D_CMND_SPEED "|" D_CMND_WAKEUP "|" D_CMND_WAKEUPDURATION "|" D_CMND_WHITE "|" D_CMND_CHANNEL "|" D_CMND_HSBCOLOR "|UNDOCA" ; void (* const LightCommand[])(void) PROGMEM = { - &CmndColor, &CmndColorTemperature, &CmndDimmer, &CmndLedTable, &CmndFade, + &CmndColor, &CmndColorTemperature, &CmndDimmer, &CmndDimmerRange, &CmndLedTable, &CmndFade, &CmndRgbwwTable, &CmndScheme, &CmndSpeed, &CmndWakeup, &CmndWakeupDuration, &CmndWhite, &CmndChannel, &CmndHsbColor, &CmndUndocA }; @@ -2058,6 +2058,29 @@ void CmndDimmer(void) } } +void CmndDimmerRange(void) +{ + if (XdrvMailbox.data_len > 0) { + char *p; + uint8_t i = 0; + uint16_t parm[2] = { 0 }; + for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 2; str = strtok_r(nullptr, ", ", &p)) { + parm[i] = strtoul(str, nullptr, 0); + i++; + } + + if (parm[0] < parm[1]) { + Settings.dimmer_hw_min = parm[0]; + Settings.dimmer_hw_max = parm[1]; + restart_flag = 2; + } else { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("Light: Dimmer minimum %d should be less than maximum %d"), parm[0], parm[1]); + } + } + + Response_P(PSTR("{" D_CMND_DIMMER_RANGE ":{\"min\":%d, \"max\":%d}}"), Settings.dimmer_hw_min, Settings.dimmer_hw_max); +} + void CmndLedTable(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { diff --git a/sonoff/xdrv_16_tuyamcu.ino b/sonoff/xdrv_16_tuyamcu.ino index 3ba681e8a..61d01daa8 100644 --- a/sonoff/xdrv_16_tuyamcu.ino +++ b/sonoff/xdrv_16_tuyamcu.ino @@ -47,7 +47,7 @@ TasmotaSerial *TuyaSerial = nullptr; struct TUYA { - uint8_t new_dim = 0; // Tuya dimmer value temp + uint16_t new_dim = 0; // Tuya dimmer value temp bool ignore_dim = false; // Flag to skip serial send to prevent looping when processing inbound states from the faceplate interaction uint8_t cmd_status = 0; // Current status of serial-read uint8_t cmd_checksum = 0; // Checksum of tuya command @@ -124,7 +124,7 @@ void CmndTuyaMcu(void) { } - Response_P(PSTR("[")); + Response_P(PSTR("{" D_CMND_TUYA_MCU ":[")); bool added = false; for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { if (Settings.tuya_fnid_map[i].fnid != 0) { @@ -135,7 +135,7 @@ void CmndTuyaMcu(void) { added = true; } } - ResponseAppend_P(PSTR("]")); + ResponseAppend_P(PSTR("]}")); } /*********************************************************************************************\ @@ -290,21 +290,19 @@ bool TuyaSetChannels(void) return true; } -void LightSerialDuty(uint8_t duty) +void LightSerialDuty(uint16_t duty) { uint8_t dpid = TuyaGetDpId(TUYA_MCU_FUNC_DIMMER); if (duty > 0 && !Tuya.ignore_dim && TuyaSerial && dpid > 0) { - if (Settings.flag3.tuya_dimmer_min_limit) { // Enable dimming limit SetOption69: Enabled by default - if (duty < 25) { duty = 25; } // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself - } - duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_DIMMER_MAX]); + if (duty < Settings.dimmer_hw_min) { duty = Settings.dimmer_hw_min; } // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself + duty = changeUIntScale(duty, 0, 255, 0, Settings.dimmer_hw_max); if (Tuya.new_dim != duty) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim value=%d (id=%d)"), duty, dpid); TuyaSendValue(dpid, duty); } } else if (dpid > 0) { Tuya.ignore_dim = false; // reset flag - duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_DIMMER_MAX]); + duty = changeUIntScale(duty, 0, 255, 0, Settings.dimmer_hw_max); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim skipped value=%d"), duty); // due to 0 or already set } else { AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Cannot set dimmer. Dimmer Id unknown")); // @@ -373,9 +371,10 @@ void TuyaPacketProcess(void) } else if (Tuya.buffer[5] == 8) { // Long value packet bool tuya_energy_enabled = (XNRG_16 == energy_flg); + uint16_t packetValue = Tuya.buffer[12] << 8 | Tuya.buffer[13]; if (fnId == TUYA_MCU_FUNC_DIMMER) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), Tuya.buffer[13]); - Tuya.new_dim = changeUIntScale((uint8_t) Tuya.buffer[13], 0, Settings.param[P_DIMMER_MAX], 0, 100); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), packetValue); + Tuya.new_dim = changeUIntScale(packetValue, 0, Settings.dimmer_hw_max, 0, 100); if ((power || Settings.flag3.tuya_apply_o20) && (Tuya.new_dim > 0) && (abs(Tuya.new_dim - Settings.light_dimmer) > 1)) { Tuya.ignore_dim = true; @@ -386,14 +385,14 @@ void TuyaPacketProcess(void) #ifdef USE_ENERGY_SENSOR else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_VOLTAGE) { - Energy.voltage[0] = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 10; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Voltage=%d"), Tuya.buffer[6], (Tuya.buffer[12] << 8 | Tuya.buffer[13])); + Energy.voltage[0] = (float)packetValue / 10; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Voltage=%d"), Tuya.buffer[6], packetValue); } else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_CURRENT) { - Energy.current[0] = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 1000; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Current=%d"), Tuya.buffer[6], (Tuya.buffer[12] << 8 | Tuya.buffer[13])); + Energy.current[0] = (float)packetValue / 1000; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Current=%d"), Tuya.buffer[6], packetValue); } else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_POWER) { - Energy.active_power[0] = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 10; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Active_Power=%d"), Tuya.buffer[6], (Tuya.buffer[12] << 8 | Tuya.buffer[13])); + Energy.active_power[0] = (float)packetValue / 10; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Active_Power=%d"), Tuya.buffer[6], packetValue); if (Tuya.lastPowerCheckTime != 0 && Energy.active_power[0] > 0) { Energy.kWhtoday += (float)Energy.active_power[0] * (Rtc.utc_time - Tuya.lastPowerCheckTime) / 36; diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index 01e837dc6..67771aa48 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -82,8 +82,8 @@ void PS16DZSerialSendUpdateCommand(void) { uint8_t light_state_dimmer = light_state.getDimmer(); // Dimming acts odd below 10% - this mirrors the threshold set on the faceplate itself - light_state_dimmer = (light_state_dimmer < 10) ? 10 : light_state_dimmer; - light_state_dimmer = (light_state_dimmer > Settings.param[P_DIMMER_MAX]) ? Settings.param[P_DIMMER_MAX] : light_state_dimmer; + light_state_dimmer = (light_state_dimmer < Settings.dimmer_hw_min) ? Settings.dimmer_hw_min : light_state_dimmer; + light_state_dimmer = (light_state_dimmer > Settings.dimmer_hw_max) ? Settings.dimmer_hw_max : light_state_dimmer; snprintf_P(Ps16dz.tx_buffer, PS16DZ_BUFFER_SIZE, PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"bright\":%d"), LocalTime(), millis()%1000, power?"on":"off", light_state_dimmer);