Add DimmerRange command and support longer dimmer ranges. Fixes

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