Add DimmerRange command and support longer dimmer ranges. Fixes #6605

More and more serial dimmers are coming up with different dimming ranges, implemented DimmerRange command to make this setting generic and bring support for 2 byte dimming ranges which isn't supported by SetOptions.
This commit is contained in:
Shantur Rathore 2019-10-10 15:53:01 +01:00
parent 70ea4bedfa
commit 01f6df9161
10 changed files with 77 additions and 31 deletions

View File

@ -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)

View File

@ -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"

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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_

View File

@ -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;
}

View File

@ -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 };
@ -2057,6 +2057,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)) {

View File

@ -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;

View File

@ -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);