diff --git a/tasmota/support_rotary.ino b/tasmota/support_rotary.ino index 3367b70d4..d58ebd560 100644 --- a/tasmota/support_rotary.ino +++ b/tasmota/support_rotary.ino @@ -34,207 +34,98 @@ \*********************************************************************************************/ #ifndef ROTARY_MAX_STEPS -#define ROTARY_MAX_STEPS 10 // Rotary step boundary +#define ROTARY_MAX_STEPS 10 // Rotary step boundary #endif -//#define ROTARY_OPTION1 // Up to 4 interrupts and pulses per step -//#define ROTARY_OPTION2 // Up to 4 interrupts but 1 pulse per step -#define ROTARY_OPTION3 // 1 interrupt and pulse per step - -#ifdef ROTARY_OPTION1 -// up to 4 pulses per step -const uint8_t rotary_dimmer_increment = 100 / (ROTARY_MAX_STEPS * 3); // Dimmer 1..100 = 100 -const uint8_t rotary_ct_increment = 350 / (ROTARY_MAX_STEPS * 3); // Ct 153..500 = 347 -const uint8_t rotary_color_increment = 360 / (ROTARY_MAX_STEPS * 3); // Hue 0..359 = 360 -#endif // ROTARY_OPTION1 - -#ifdef ROTARY_OPTION2 // 1 pulse per step -const uint8_t rotary_dimmer_increment = 100 / ROTARY_MAX_STEPS; // Dimmer 1..100 = 100 -const uint8_t rotary_ct_increment = 350 / ROTARY_MAX_STEPS; // Ct 153..500 = 347 -const uint8_t rotary_color_increment = 360 / ROTARY_MAX_STEPS; // Hue 0..359 = 360 -#endif // ROTARY_OPTION2 +const uint8_t rotary_dimmer_increment = 100 / ROTARY_MAX_STEPS; // Dimmer 1..100 = 100 +const uint8_t rotary_ct_increment = 350 / ROTARY_MAX_STEPS; // Ct 153..500 = 347 +const uint8_t rotary_color_increment = 360 / ROTARY_MAX_STEPS; // Hue 0..359 = 360 -#ifdef ROTARY_OPTION3 -// 1 pulse per step -const uint8_t rotary_dimmer_increment = 100 / ROTARY_MAX_STEPS; // Dimmer 1..100 = 100 -const uint8_t rotary_ct_increment = 350 / ROTARY_MAX_STEPS; // Ct 153..500 = 347 -const uint8_t rotary_color_increment = 360 / ROTARY_MAX_STEPS; // Hue 0..359 = 360 -#endif // ROTARY_OPTION3 - -const uint8_t ROTARY_TIMEOUT = 10; // 10 * RotaryHandler() call which is usually 10 * 0.05 seconds +const uint8_t ROTARY_TIMEOUT = 10; // 10 * RotaryHandler() call which is usually 10 * 0.05 seconds struct ROTARY { -#ifdef ROTARY_OPTION1 - uint8_t state = 0; -#endif // ROTARY_OPTION1 -#ifdef ROTARY_OPTION2 - uint16_t store; - uint8_t prev_next_code; -#endif // ROTARY_OPTION2 -#ifdef ROTARY_OPTION3 + bool present = false; +} Rotary; + +struct ENCODER { uint32_t debounce = 0; -#endif // ROTARY_OPTION3 int8_t abs_position1 = 0; int8_t abs_position2 = 0; - int8_t direction = 0; // Control consistent direction - uint8_t present = 0; + int8_t direction = 0; // Control consistent direction + int8_t pin = -1; uint8_t position = 128; uint8_t last_position = 128; - uint8_t timeout = 0; // Disallow direction change within 0.5 second + uint8_t timeout = 0; // Disallow direction change within 0.5 second bool changed = false; bool busy = false; -} Rotary; +} Encoder[MAX_ROTARIES]; /********************************************************************************************/ -void update_rotary(void) ICACHE_RAM_ATTR; -void update_rotary(void) { - if (Rotary.busy) { return; } +void ICACHE_RAM_ATTR RotaryIsr(uint32_t index) { + if (Encoder[index].busy) { return; } -#ifdef ROTARY_OPTION1 - // https://github.com/PaulStoffregen/Encoder/blob/master/Encoder.h -/* - uint8_t p1val = digitalRead(Pin(GPIO_ROT1A)); - uint8_t p2val = digitalRead(Pin(GPIO_ROT1B)); - uint8_t state = Rotary.state & 3; - if (p1val) { state |= 4; } - if (p2val) { state |= 8; } - Rotary.state = (state >> 2); - switch (state) { - case 1: case 7: case 8: case 14: - Rotary.position++; - return; - case 2: case 4: case 11: case 13: - Rotary.position--; - return; - case 3: case 12: - Rotary.position += 2; - return; - case 6: case 9: - Rotary.position -= 2; - return; - } -*/ - uint8_t p1val = digitalRead(Pin(GPIO_ROT1A)); - uint8_t p2val = digitalRead(Pin(GPIO_ROT1B)); - uint8_t state = Rotary.state & 3; - if (p1val) { state |= 4; } - if (p2val) { state |= 8; } - Rotary.state = (state >> 2); - int direction = 0; - int multiply = 1; - switch (state) { - case 3: case 12: - multiply = 2; - case 1: case 7: case 8: case 14: - direction = 1; - break; - case 6: case 9: - multiply = 2; - case 2: case 4: case 11: case 13: - direction = -1; - break; - } - if ((0 == Rotary.direction) || (direction == Rotary.direction)) { - Rotary.position += (direction * multiply); - Rotary.direction = direction; - } -#endif // ROTARY_OPTION1 - -#ifdef ROTARY_OPTION2 - // https://github.com/FrankBoesing/EncoderBounce/blob/master/EncoderBounce.h -/* - const uint16_t rot_enc = 0b0110100110010110; - - uint8_t p1val = digitalRead(Pin(GPIO_ROT1B)); - uint8_t p2val = digitalRead(Pin(GPIO_ROT1A)); - uint8_t t = Rotary.prev_next_code; - t <<= 2; - if (p1val) { t |= 0x02; } - if (p2val) { t |= 0x01; } - t &= 0x0f; - Rotary.prev_next_code = t; - - // If valid then store as 16 bit data. - if (rot_enc & (1 << t)) { - Rotary.store = (Rotary.store << 4) | Rotary.prev_next_code; - if (Rotary.store == 0xd42b) { Rotary.position++; } - else if (Rotary.store == 0xe817) { Rotary.position--; } - else if ((Rotary.store & 0xff) == 0x2b) { Rotary.position--; } - else if ((Rotary.store & 0xff) == 0x17) { Rotary.position++; } - } -*/ - const uint16_t rot_enc = 0b0110100110010110; - - uint8_t p1val = digitalRead(Pin(GPIO_ROT1B)); - uint8_t p2val = digitalRead(Pin(GPIO_ROT1A)); - uint8_t t = Rotary.prev_next_code; - t <<= 2; - if (p1val) { t |= 0x02; } - if (p2val) { t |= 0x01; } - t &= 0x0f; - Rotary.prev_next_code = t; - - // If valid then store as 16 bit data. - if (rot_enc & (1 << t)) { - Rotary.store = (Rotary.store << 4) | Rotary.prev_next_code; - int direction = 0; - if (Rotary.store == 0xd42b) { direction = 1; } - else if (Rotary.store == 0xe817) { direction = -1; } - else if ((Rotary.store & 0xff) == 0x2b) { direction = -1; } - else if ((Rotary.store & 0xff) == 0x17) { direction = 1; } - if ((0 == Rotary.direction) || (direction == Rotary.direction)) { - Rotary.position += direction; - Rotary.direction = direction; - } - } -#endif // ROTARY_OPTION2 - -#ifdef ROTARY_OPTION3 - // Theo Arends uint32_t time = micros(); - if (Rotary.debounce < time) { - int direction = (digitalRead(Pin(GPIO_ROT1B))) ? 1 : -1; - if ((0 == Rotary.direction) || (direction == Rotary.direction)) { - Rotary.position += direction; - Rotary.direction = direction; + if (Encoder[index].debounce < time) { + int direction = (digitalRead(Encoder[index].pin)) ? -1 : 1; + if ((0 == Encoder[index].direction) || (direction == Encoder[index].direction)) { + Encoder[index].position += direction; + Encoder[index].direction = direction; } - Rotary.debounce = time +20; // Experimental debounce + Encoder[index].debounce = time +50; // Experimental debounce in microseconds } -#endif // ROTARY_OPTION3 } -//bool RotaryButtonPressed(void) { +void ICACHE_RAM_ATTR RotaryIsr1(void) { + RotaryIsr(0); +} + +void ICACHE_RAM_ATTR RotaryIsr2(void) { + RotaryIsr(1); +} + bool RotaryButtonPressed(uint32_t button_index) { if (!Rotary.present) { return false; } - if (0 != button_index) { return false; } - bool powered_on = (power); + for (uint32_t index = 0; index < MAX_ROTARIES; index++) { + if (-1 == Encoder[index].pin) { continue; } + if (index != button_index) { continue; } + + bool powered_on = (power); #ifdef USE_LIGHT - if (!Settings.flag4.rotary_uses_rules) { // SetOption98 - Use rules instead of light control - powered_on = LightPower(); - } + if (!Settings.flag4.rotary_uses_rules) { // SetOption98 - Use rules instead of light control + powered_on = LightPower(); + } #endif // USE_LIGHT - if (Rotary.changed && powered_on) { - Rotary.changed = false; // Color (temp) changed, no need to turn of the light - return true; + if (Encoder[index].changed && powered_on) { + Encoder[index].changed = false; // Color (temp) changed, no need to turn of the light + return true; + } + return false; } return false; } void RotaryInit(void) { - Rotary.present = 0; - if (PinUsed(GPIO_ROT1A) && PinUsed(GPIO_ROT1B)) { - Rotary.present++; - pinMode(Pin(GPIO_ROT1A), INPUT_PULLUP); - pinMode(Pin(GPIO_ROT1B), INPUT_PULLUP); -#ifdef ROTARY_OPTION3 - attachInterrupt(Pin(GPIO_ROT1A), update_rotary, RISING); -#else - attachInterrupt(Pin(GPIO_ROT1A), update_rotary, CHANGE); - attachInterrupt(Pin(GPIO_ROT1B), update_rotary, CHANGE); -#endif + Rotary.present = false; + for (uint32_t index = 0; index < MAX_ROTARIES; index++) { +#ifdef ESP8266 + uint32_t idx = index *2; +#else // ESP32 + uint32_t idx = index; +#endif // ESP8266 or ESP32 + if (PinUsed(GPIO_ROT1A, idx) && PinUsed(GPIO_ROT1B, idx)) { + Encoder[index].pin = Pin(GPIO_ROT1B, idx); + pinMode(Encoder[index].pin, INPUT_PULLUP); + pinMode(Pin(GPIO_ROT1A, idx), INPUT_PULLUP); + if (0 == index) { + attachInterrupt(Pin(GPIO_ROT1A, idx), RotaryIsr1, FALLING); + } else { + attachInterrupt(Pin(GPIO_ROT1A, idx), RotaryIsr2, FALLING); + } + } + Rotary.present |= (Encoder[index].pin > -1); } } @@ -245,63 +136,80 @@ void RotaryInit(void) { void RotaryHandler(void) { if (!Rotary.present) { return; } - if (Rotary.timeout) { - Rotary.timeout--; - if (!Rotary.timeout) { - Rotary.direction = 0; + for (uint32_t index = 0; index < MAX_ROTARIES; index++) { + if (-1 == Encoder[index].pin) { continue; } + + if (Encoder[index].timeout) { + Encoder[index].timeout--; + if (!Encoder[index].timeout) { #ifdef USE_LIGHT - if (!Settings.flag4.rotary_uses_rules) { // SetOption98 - Use rules instead of light control - LightState(0); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_DIMMER)); - XdrvRulesProcess(); - } + if (!Settings.flag4.rotary_uses_rules) { // SetOption98 - Use rules instead of light control + ResponseLightState(0); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_STATE)); + XdrvRulesProcess(); + } #endif // USE_LIGHT + Encoder[index].direction = 0; + } } - } - if (Rotary.last_position == Rotary.position) { return; } - Rotary.busy = true; + if (Encoder[index].last_position == Encoder[index].position) { continue; } + Encoder[index].busy = true; - Rotary.timeout = ROTARY_TIMEOUT; // Prevent fast direction changes within 0.5 second + Encoder[index].timeout = ROTARY_TIMEOUT; // Prevent fast direction changes within 0.5 second - int rotary_position = Rotary.position - Rotary.last_position; + int rotary_position = Encoder[index].position - Encoder[index].last_position; - if (Settings.save_data && (save_data_counter < 2)) { - save_data_counter = 2; // Postpone flash writes while rotary is turned - } + if (Settings.save_data && (save_data_counter < 2)) { + save_data_counter = 2; // Postpone flash writes while rotary is turned + } - bool button_pressed = (Button.hold_timer[0]); // Button1 is pressed: set color temperature - if (button_pressed) { Rotary.changed = true; } -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ROT: Button1 %d, Position %d"), button_pressed, rotary_position); + bool button_pressed = (Button.hold_timer[index]); // Button is pressed: set color temperature + if (button_pressed) { Encoder[index].changed = true; } +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ROT: Button1 %d, Position %d"), button_pressed, rotary_position); #ifdef USE_LIGHT - if (!Settings.flag4.rotary_uses_rules) { // SetOption98 - Use rules instead of light control - if (button_pressed) { - if (!LightColorTempOffset(rotary_position * rotary_ct_increment)) { - LightColorOffset(rotary_position * rotary_color_increment); + if (!Settings.flag4.rotary_uses_rules) { // SetOption98 - Use rules instead of light control + bool second_rotary = (Encoder[1].pin > -1); + if (0 == index) { // Rotary1 + if (button_pressed) { + if (second_rotary) { // Color RGB + LightColorOffset(rotary_position * rotary_color_increment); + } else { // Color Temperature or Color RGB + if (!LightColorTempOffset(rotary_position * rotary_ct_increment)) { + LightColorOffset(rotary_position * rotary_color_increment); + } + } + } else { // Dimmer RGBCW or RGB only if second rotary + LightDimmerOffset(second_rotary ? 1 : 0, rotary_position * rotary_dimmer_increment); + } + } else { // Rotary2 + if (button_pressed) { // Color Temperature + LightColorTempOffset(rotary_position * rotary_ct_increment); + } else { // Dimmer CW + LightDimmerOffset(2, rotary_position * rotary_dimmer_increment); + } } } else { - LightDimmerOffset(rotary_position * rotary_dimmer_increment); - } - } else { #endif // USE_LIGHT - if (button_pressed) { - Rotary.abs_position2 += rotary_position; - if (Rotary.abs_position2 < 0) { Rotary.abs_position2 = 0; } - if (Rotary.abs_position2 > ROTARY_MAX_STEPS) { Rotary.abs_position2 = ROTARY_MAX_STEPS; } - } else { - Rotary.abs_position1 += rotary_position; - if (Rotary.abs_position1 < 0) { Rotary.abs_position1 = 0; } - if (Rotary.abs_position1 > ROTARY_MAX_STEPS) { Rotary.abs_position1 = ROTARY_MAX_STEPS; } - } - Response_P(PSTR("{\"Rotary1\":{\"Pos1\":%d,\"Pos2\":%d}}"), Rotary.abs_position1, Rotary.abs_position2); - XdrvRulesProcess(); + if (button_pressed) { + Encoder[index].abs_position2 += rotary_position; + if (Encoder[index].abs_position2 < 0) { Encoder[index].abs_position2 = 0; } + if (Encoder[index].abs_position2 > ROTARY_MAX_STEPS) { Encoder[index].abs_position2 = ROTARY_MAX_STEPS; } + } else { + Encoder[index].abs_position1 += rotary_position; + if (Encoder[index].abs_position1 < 0) { Encoder[index].abs_position1 = 0; } + if (Encoder[index].abs_position1 > ROTARY_MAX_STEPS) { Encoder[index].abs_position1 = ROTARY_MAX_STEPS; } + } + Response_P(PSTR("{\"Rotary%d\":{\"Pos1\":%d,\"Pos2\":%d}}"), index +1, Encoder[index].abs_position1, Encoder[index].abs_position2); + XdrvRulesProcess(); #ifdef USE_LIGHT - } + } #endif // USE_LIGHT - Rotary.last_position = 128; - Rotary.position = 128; - Rotary.busy = false; + Encoder[index].last_position = 128; + Encoder[index].position = 128; + Encoder[index].busy = false; + } } #endif // ROTARY_V1 diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 68edd6a7a..70d7f66af 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -663,7 +663,7 @@ void MqttShowState(void) for (uint32_t i = 1; i <= devices_present; i++) { #ifdef USE_LIGHT if ((LightDevice()) && (i >= LightDevice())) { - if (i == LightDevice()) { LightState(1); } // call it only once + if (i == LightDevice()) { ResponseLightState(1); } // call it only once } else { #endif ResponseAppend_P(PSTR(",\"%s\":\"%s\""), GetPowerDevice(stemp1, i, sizeof(stemp1), Settings.flag.device_index_enable), // SetOption26 - Switch between POWER or POWER1 diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index 4eceddb5c..21a7b5b00 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -84,6 +84,7 @@ const uint8_t MAX_GROUP_TOPICS = 4; // Max number of Group Topics const uint8_t MAX_DEV_GROUP_NAMES = 4; // Max number of Device Group names const uint8_t MAX_HUE_DEVICES = 15; // Max number of Philips Hue device per emulation +const uint8_t MAX_ROTARIES = 2; // Max number of Rotary Encoders const char MQTT_TOKEN_PREFIX[] PROGMEM = "%prefix%"; // To be substituted by mqtt_prefix[x] const char MQTT_TOKEN_TOPIC[] PROGMEM = "%topic%"; // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index bd1c009de..d287d7e01 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -373,6 +373,12 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_SWT7_NP, GPIO_SWT8, GPIO_SWT8_NP, +#ifdef ROTARY_V1 + GPIO_ROT1A, // Rotary switch1 A Pin + GPIO_ROT1B, // Rotary switch1 B Pin + GPIO_ROT2A, // Rotary switch2 A Pin + GPIO_ROT2B, // Rotary switch2 B Pin +#endif GPIO_REL1, // Relays GPIO_REL1_INV, GPIO_REL2, @@ -665,12 +671,6 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_MAX31855CLK, // MAX31855 Serial interface GPIO_MAX31855DO, // MAX31855 Serial interface #endif -#ifdef ROTARY_V1 - GPIO_ROT1A, // Rotary switch1 A Pin - GPIO_ROT1B, // Rotary switch1 B Pin - GPIO_ROT2A, // Rotary switch2 A Pin - GPIO_ROT2B, // Rotary switch2 B Pin -#endif #ifdef USE_HRE GPIO_HRE_CLOCK, GPIO_HRE_DATA, diff --git a/tasmota/tasmota_template_ESP32.h b/tasmota/tasmota_template_ESP32.h index e5b30a5b1..72c72e48b 100644 --- a/tasmota/tasmota_template_ESP32.h +++ b/tasmota/tasmota_template_ESP32.h @@ -88,7 +88,10 @@ enum UserSelectablePins { GPIO_CSE7766_TX, GPIO_CSE7766_RX, // CSE7766 Serial interface (S31 and Pow R2) GPIO_ARIRFRCV, GPIO_ARIRFSEL, // Arilux RF Receive input GPIO_TXD, GPIO_RXD, // Serial interface - GPIO_ROT1A, GPIO_ROT1B, GPIO_ROT2A, GPIO_ROT2B, // Rotary switch + GPIO_ROT1A, GPIO_ROT1B, // Rotary switch + + GPIO_SPARE1, GPIO_SPARE2, // Spare GPIOs + GPIO_HRE_CLOCK, GPIO_HRE_DATA, // HR-E Water Meter GPIO_ADE7953_IRQ, // ADE7953 IRQ GPIO_SOLAXX1_TX, GPIO_SOLAXX1_RX, // Solax Inverter Serial interface @@ -188,7 +191,10 @@ const char kSensorNames[] PROGMEM = D_SENSOR_CSE7766_TX "|" D_SENSOR_CSE7766_RX "|" D_SENSOR_ARIRFRCV "|" D_SENSOR_ARIRFSEL "|" D_SENSOR_TXD "|" D_SENSOR_RXD "|" - D_SENSOR_ROTARY "_1a|" D_SENSOR_ROTARY "_1b|" D_SENSOR_ROTARY "_2a|" D_SENSOR_ROTARY "_2b|" + D_SENSOR_ROTARY "_a|" D_SENSOR_ROTARY "_b|" + + "Spare1|Spare2|" + D_SENSOR_HRE_CLOCK "|" D_SENSOR_HRE_DATA "|" D_SENSOR_ADE7953_IRQ "|" D_SENSOR_SOLAXX1_TX "|" D_SENSOR_SOLAXX1_RX "|" @@ -245,6 +251,10 @@ const uint16_t kGpioNiceList[] PROGMEM = { AGPIO(GPIO_KEY1_TC) + MAX_KEYS, // Touch button AGPIO(GPIO_SWT1) + MAX_SWITCHES, // User connected external switches AGPIO(GPIO_SWT1_NP) + MAX_SWITCHES, +#ifdef ROTARY_V1 + AGPIO(GPIO_ROT1A) + MAX_ROTARIES, // Rotary A Pin + AGPIO(GPIO_ROT1B) + MAX_ROTARIES, // Rotary B Pin +#endif AGPIO(GPIO_REL1) + MAX_RELAYS, // Relays AGPIO(GPIO_REL1_INV) + MAX_RELAYS, AGPIO(GPIO_LED1) + MAX_LEDS, // Leds @@ -508,12 +518,6 @@ const uint16_t kGpioNiceList[] PROGMEM = { AGPIO(GPIO_MAX31855CLK), // MAX31855 Serial interface AGPIO(GPIO_MAX31855DO), // MAX31855 Serial interface #endif -#ifdef ROTARY_V1 - AGPIO(GPIO_ROT1A), // Rotary switch1 A Pin - AGPIO(GPIO_ROT1B), // Rotary switch1 B Pin - AGPIO(GPIO_ROT2A), // Rotary switch2 A Pin - AGPIO(GPIO_ROT2B), // Rotary switch2 B Pin -#endif #ifdef USE_HRE AGPIO(GPIO_HRE_CLOCK), AGPIO(GPIO_HRE_DATA), diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 86293c2b2..d284e71fe 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -314,16 +314,6 @@ power_t LightPower(void) return Light.power; // Make external } -// IRAM variant for rotary -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 // Fix core 2.5.x ISR not in IRAM Exception -power_t LightPowerIRAM(void) ICACHE_RAM_ATTR; -#endif // ARDUINO_ESP8266_RELEASE_2_3_0 - -power_t LightPowerIRAM(void) -{ - return Light.power; // Make external -} - uint8_t LightDevice(void) { return Light.device; // Make external @@ -1568,7 +1558,7 @@ void LightPowerOn(void) } } -void LightState(uint8_t append) +void ResponseLightState(uint8_t append) { char scolor[LIGHT_COLOR_SIZE]; char scommand[33]; @@ -1718,7 +1708,7 @@ void LightPreparePower(power_t channels = 0xFFFFFFFF) { // 1 = only RGB, 2 = AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower End power=%d Light.power=%d", power, Light.power); #endif Light.power = power >> (Light.device - 1); // reset next state, works also with unlinked RGB/CT - LightState(0); + ResponseLightState(0); } #ifdef USE_LIGHT_PALETTE @@ -1886,7 +1876,7 @@ void LightAnimate(void) MqttPublishPrefixTopic_P(TELE, PSTR(D_CMND_WAKEUP)); */ Response_P(PSTR("{\"" D_CMND_WAKEUP "\":\"" D_JSON_DONE "\"")); - LightState(1); + ResponseLightState(1); ResponseJsonEnd(); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_WAKEUP)); XdrvRulesProcess(); @@ -2689,7 +2679,7 @@ void CmndHsbColor(void) light_controller.changeHSB(HSB[0], HSB[1], HSB[2]); LightPreparePower(1); } else { - LightState(0); + ResponseLightState(0); } } } @@ -2774,12 +2764,12 @@ void CmndColorTemperature(void) } } -void LightDimmerOffset(int32_t offset) { - int32_t dimmer = light_state.getDimmer() + offset; - if (dimmer < 1) { dimmer = 1; } +void LightDimmerOffset(uint32_t index, int32_t offset) { + int32_t dimmer = light_state.getDimmer(index) + offset; + if (dimmer < 1) { dimmer = Settings.flag3.slider_dimmer_stay_on; } // SetOption77 - Do not power off if slider moved to far left if (dimmer > 100) { dimmer = 100; } - XdrvMailbox.index = 0; + XdrvMailbox.index = index; XdrvMailbox.payload = dimmer; CmndDimmer(); }