Merge pull request #9474 from pcdiem/pwm3

Add PWMD color/trigger on tap, SO88 led, DGR WITH_LOCAL flag
This commit is contained in:
Theo Arends 2020-10-06 10:26:03 +02:00 committed by GitHub
commit 08d79b6765
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 183 additions and 170 deletions

View File

@ -1999,7 +1999,7 @@ void CmndDevGroupSend(void)
{ {
uint8_t device_group_index = (XdrvMailbox.usridx ? XdrvMailbox.index - 1 : 0); uint8_t device_group_index = (XdrvMailbox.usridx ? XdrvMailbox.index - 1 : 0);
if (device_group_index < device_group_count) { if (device_group_index < device_group_count) {
if (!_SendDeviceGroupMessage(device_group_index, DGR_MSGTYPE_UPDATE_COMMAND)) { if (!_SendDeviceGroupMessage(device_group_index, (DevGroupMessageType)(DGR_MSGTYPE_UPDATE_COMMAND + DGR_MSGTYPFLAG_WITH_LOCAL))) {
ResponseCmndChar(XdrvMailbox.data); ResponseCmndChar(XdrvMailbox.data);
} }
} }

View File

@ -468,6 +468,10 @@ bool _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
// If the device group index is higher then the number of device groups, ignore this request. // If the device group index is higher then the number of device groups, ignore this request.
if (device_group_index >= device_group_count) return 0; if (device_group_index >= device_group_count) return 0;
// Extract the flags from the message type.
bool with_local = ((message_type & DGR_MSGTYPFLAG_WITH_LOCAL) != 0);
message_type = (DevGroupMessageType)(message_type & 0x7F);
// If we're currently processing a remote device message, ignore this request. // If we're currently processing a remote device message, ignore this request.
if (ignore_dgr_sends && message_type != DGR_MSGTYPE_UPDATE_COMMAND) return 0; if (ignore_dgr_sends && message_type != DGR_MSGTYPE_UPDATE_COMMAND) return 0;
@ -723,8 +727,8 @@ bool _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
SendReceiveDeviceGroupMessage(device_group, nullptr, device_group->message, device_group->message_length, false); SendReceiveDeviceGroupMessage(device_group, nullptr, device_group->message, device_group->message_length, false);
#ifdef USE_DEVICE_GROUPS_SEND #ifdef USE_DEVICE_GROUPS_SEND
// If this is the DevGroupSend command, also handle the update locally. // If requested, handle this updated locally as well.
if (message_type == DGR_MSGTYPE_UPDATE_COMMAND) { if (with_local) {
struct XDRVMAILBOX save_XdrvMailbox = XdrvMailbox; struct XDRVMAILBOX save_XdrvMailbox = XdrvMailbox;
SendReceiveDeviceGroupMessage(device_group, nullptr, device_group->message, device_group->message_length, true); SendReceiveDeviceGroupMessage(device_group, nullptr, device_group->message, device_group->message_length, true);
XdrvMailbox = save_XdrvMailbox; XdrvMailbox = save_XdrvMailbox;

View File

@ -308,7 +308,7 @@ enum SettingsTextIndex { SET_OTAURL,
#endif #endif
SET_MAX }; SET_MAX };
enum DevGroupMessageType { DGR_MSGTYP_FULL_STATUS, DGR_MSGTYP_PARTIAL_UPDATE, DGR_MSGTYP_UPDATE, DGR_MSGTYP_UPDATE_MORE_TO_COME, DGR_MSGTYP_UPDATE_DIRECT, DGR_MSGTYPE_UPDATE_COMMAND }; enum DevGroupMessageType { DGR_MSGTYP_FULL_STATUS, DGR_MSGTYP_PARTIAL_UPDATE, DGR_MSGTYP_UPDATE, DGR_MSGTYP_UPDATE_MORE_TO_COME, DGR_MSGTYP_UPDATE_DIRECT, DGR_MSGTYPE_UPDATE_COMMAND, DGR_MSGTYPFLAG_WITH_LOCAL = 128 };
enum DevGroupMessageFlag { DGR_FLAG_RESET = 1, DGR_FLAG_STATUS_REQUEST = 2, DGR_FLAG_FULL_STATUS = 4, DGR_FLAG_ACK = 8, DGR_FLAG_MORE_TO_COME = 16, DGR_FLAG_DIRECT = 32, DGR_FLAG_ANNOUNCEMENT = 64 }; enum DevGroupMessageFlag { DGR_FLAG_RESET = 1, DGR_FLAG_STATUS_REQUEST = 2, DGR_FLAG_FULL_STATUS = 4, DGR_FLAG_ACK = 8, DGR_FLAG_MORE_TO_COME = 16, DGR_FLAG_DIRECT = 32, DGR_FLAG_ANNOUNCEMENT = 64 };

View File

@ -572,7 +572,7 @@ class LightStateClass {
_briRGB = bri_rgb; _briRGB = bri_rgb;
if (bri_rgb > 0) { addRGBMode(); } if (bri_rgb > 0) { addRGBMode(); }
#ifdef USE_PWM_DIMMER #ifdef USE_PWM_DIMMER
if (PWM_DIMMER == my_module_type) PWMDimmerSetBrightnessLeds(0); if (PWM_DIMMER == my_module_type) PWMDimmerSetBrightnessLeds(-1);
#endif // USE_PWM_DIMMER #endif // USE_PWM_DIMMER
return prev_bri; return prev_bri;
} }
@ -583,7 +583,7 @@ class LightStateClass {
_briCT = bri_ct; _briCT = bri_ct;
if (bri_ct > 0) { addCTMode(); } if (bri_ct > 0) { addCTMode(); }
#ifdef USE_PWM_DIMMER #ifdef USE_PWM_DIMMER
if (PWM_DIMMER == my_module_type) PWMDimmerSetBrightnessLeds(0); if (PWM_DIMMER == my_module_type) PWMDimmerSetBrightnessLeds(-1);
#endif // USE_PWM_DIMMER #endif // USE_PWM_DIMMER
return prev_bri; return prev_bri;
} }
@ -2409,7 +2409,7 @@ void LightHandleDevGroupItem(void)
break; break;
} }
#endif // !USE_LIGHT_PALETTE #endif // !USE_LIGHT_PALETTE
value = value % MAX_FIXED_COLOR; value = value % MAX_FIXED_COLOR + 1;
if (value) { if (value) {
bool save_decimal_text = Settings.flag.decimal_text; bool save_decimal_text = Settings.flag.decimal_text;
char str[16]; char str[16];

View File

@ -58,18 +58,18 @@ struct remote_pwm_dimmer {
}; };
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
uint32_t last_button_press_time;
uint32_t button_hold_time[3]; uint32_t button_hold_time[3];
uint8_t led_timeout_seconds = 0; uint8_t led_timeout_seconds = 0;
uint8_t restore_powered_off_led_counter = 0; uint8_t restore_powered_off_led_counter = 0;
uint8_t power_button_index = 0; uint8_t power_button_index = 0;
uint8_t down_button_index = 1;
uint8_t buttons_pressed = 0; uint8_t buttons_pressed = 0;
uint8_t tap_count = 0; uint8_t local_fixed_color_index = 128;
bool ignore_power_button = false;
bool button_tapped = false;
bool down_button_tapped = false; bool down_button_tapped = false;
bool tap_handled = false;
bool power_button_increases_bri = true; bool power_button_increases_bri = true;
bool invert_power_button_bri_direction = false; bool invert_power_button_bri_direction = false;
bool restore_brightness_leds = false;
bool button_pressed[3] = { false, false, false }; bool button_pressed[3] = { false, false, false };
bool button_hold_sent[3]; bool button_hold_sent[3];
bool button_hold_processed[3]; bool button_hold_processed[3];
@ -127,6 +127,7 @@ void PWMModulePreInit(void)
active_remote_pwm_dimmer->bri_power_on = 128; active_remote_pwm_dimmer->bri_power_on = 128;
active_remote_pwm_dimmer->bri_preset_low = 10; active_remote_pwm_dimmer->bri_preset_low = 10;
active_remote_pwm_dimmer->bri_preset_high = 255; active_remote_pwm_dimmer->bri_preset_high = 255;
active_remote_pwm_dimmer->fixed_color_index = 128;
} }
} }
} }
@ -135,29 +136,30 @@ void PWMModulePreInit(void)
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
} }
// operation: 0 = normal, -1 = all off, 1 = all on // bri: -1 = set to current light bri, -2 = timeout, 0-255 = set to bri
void PWMDimmerSetBrightnessLeds(int32_t operation) void PWMDimmerSetBrightnessLeds(int32_t bri)
{ {
if (leds_present) { if (leds_present) {
uint32_t step = (!operation ? 256 / (leds_present + 1) : operation < 0 ? 256 : 0); led_timeout_seconds = 5;
uint32_t current_bri = (Light.power ? light_state.getBri() : 0); if (bri < 0) {
bri = ((bri == -2 && Settings.flag4.led_timeout) || !Light.power ? 0 : light_state.getBri());
if (!bri || !Settings.flag4.led_timeout) led_timeout_seconds = 0;
}
uint32_t step = 256 / (leds_present + 1);
uint32_t level = step; uint32_t level = step;
SetLedPowerIdx(0, current_bri >= level); SetLedPowerIdx(0, bri >= level);
if (leds_present > 1) { if (leds_present > 1) {
level += step; level += step;
SetLedPowerIdx(1, current_bri >= level); SetLedPowerIdx(1, bri >= level);
if (leds_present > 2) { if (leds_present > 2) {
level += step; level += step;
SetLedPowerIdx(2, current_bri >= level); SetLedPowerIdx(2, bri >= level);
if (leds_present > 3) { if (leds_present > 3) {
level += step; level += step;
SetLedPowerIdx(3, current_bri >= level); SetLedPowerIdx(3, bri >= level);
} }
} }
} }
// If enabled, set the LED timeout.
if (!operation) led_timeout_seconds = (current_bri && Settings.flag4.led_timeout ? 5 : 0);
} }
} }
@ -174,7 +176,7 @@ void PWMDimmerSetPoweredOffLed(void)
void PWMDimmerSetPower(void) void PWMDimmerSetPower(void)
{ {
DigitalWrite(GPIO_REL1, 0, bitRead(rel_inverted, 0) ? !power : power); DigitalWrite(GPIO_REL1, 0, bitRead(rel_inverted, 0) ? !power : power);
PWMDimmerSetBrightnessLeds(0); PWMDimmerSetBrightnessLeds(-1);
PWMDimmerSetPoweredOffLed(); PWMDimmerSetPoweredOffLed();
} }
@ -272,23 +274,17 @@ void PWMDimmerHandleButton(void)
* 3 1 2 * 3 1 2
*/ */
// If the button is not pressed and was not just released (the most common case), ... // If the button is not pressed and was not just released (the most common case), just return.
if (XdrvMailbox.payload && !button_pressed[XdrvMailbox.index]) { if (XdrvMailbox.payload && !button_pressed[XdrvMailbox.index]) return;
// If no buttons have been pressed for 400ms, reset the button press counts.
if (last_button_press_time && !buttons_pressed && millis() - last_button_press_time > 400) {
last_button_press_time = 0;
tap_count = 0;
}
return;
}
bool handle_tap = false;
bool state_updated = false; bool state_updated = false;
int32_t bri_offset = 0; int32_t bri_offset = 0;
uint8_t power_on_bri = 0; uint8_t power_on_bri = 0;
uint8_t dgr_item = 0; uint8_t dgr_item = 0;
uint8_t dgr_value = 0; uint8_t dgr_value = 0;
uint8_t dgr_more_to_come = false; uint8_t dgr_more_to_come = true;
uint8_t mqtt_trigger = 0;
uint32_t button_index = XdrvMailbox.index; uint32_t button_index = XdrvMailbox.index;
uint32_t now = millis(); uint32_t now = millis();
@ -300,7 +296,7 @@ void PWMDimmerHandleButton(void)
bool power_is_on = power; bool power_is_on = power;
bool is_power_button = !button_index; bool is_power_button = !button_index;
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
bool is_down_button = (button_index == down_button_index); bool is_down_button = (button_index == (power_button_index ? 0 : 1));
// If the button is pressed, ... // If the button is pressed, ...
if (!XdrvMailbox.payload) { if (!XdrvMailbox.payload) {
@ -308,10 +304,8 @@ void PWMDimmerHandleButton(void)
// If the button was just pressed, flag the button as pressed, clear the hold sent flag and // If the button was just pressed, flag the button as pressed, clear the hold sent flag and
// increment the buttons pressed count. // increment the buttons pressed count.
if (!button_pressed[button_index]) { if (!button_pressed[button_index]) {
last_button_press_time = now;
button_pressed[button_index] = true; button_pressed[button_index] = true;
button_hold_time[button_index] = now + Settings.param[P_HOLD_TIME] * 100; button_hold_time[button_index] = now + Settings.param[P_HOLD_TIME] * 100;
button_hold_sent[button_index] = false;
buttons_pressed++; buttons_pressed++;
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
@ -319,7 +313,6 @@ void PWMDimmerHandleButton(void)
// associated with this button the device we're going to control. // associated with this button the device we're going to control.
if (buttons_pressed == 1 && Settings.flag4.multiple_device_groups) { if (buttons_pressed == 1 && Settings.flag4.multiple_device_groups) {
power_button_index = button_index; power_button_index = button_index;
down_button_index = (button_index ? 0 : 1);
active_device_is_local = device_groups[power_button_index].local; active_device_is_local = device_groups[power_button_index].local;
if (!active_device_is_local) active_remote_pwm_dimmer = &remote_pwm_dimmers[power_button_index - 1]; if (!active_device_is_local) active_remote_pwm_dimmer = &remote_pwm_dimmers[power_button_index - 1];
} }
@ -331,9 +324,9 @@ void PWMDimmerHandleButton(void)
// If the button is being held, ... // If the button is being held, ...
if (button_hold_time[button_index] < now) { if (button_hold_time[button_index] < now) {
// If the power button is not also pressed and the button has been held for over 10 seconds, // If we're not in the middle of a power button plus up/down button sequence and the button
// execute the WiFiConfig 2 command. // has been held for over 10 seconds, execute the WiFiConfig 2 command.
if (!button_pressed[power_button_index] && now - button_hold_time[button_index] > 10000) { if (!ignore_power_button && now - button_hold_time[button_index] > 10000) {
button_hold_time[button_index] = now + 90000; button_hold_time[button_index] = now + 90000;
char scmnd[20]; char scmnd[20];
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WIFICONFIG " 2")); snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WIFICONFIG " 2"));
@ -345,16 +338,15 @@ void PWMDimmerHandleButton(void)
// rule), ignore the this button until it's released. // rule), ignore the this button until it's released.
if (!button_hold_sent[button_index]) { if (!button_hold_sent[button_index]) {
button_hold_sent[button_index] = true; button_hold_sent[button_index] = true;
button_hold_processed[button_index] = (!is_power_button && tap_count ? false : SendKey(KEY_BUTTON, button_index + 1, POWER_HOLD)); button_hold_processed[button_index] = (!is_power_button && button_tapped ? false : SendKey(KEY_BUTTON, button_index + 1, POWER_HOLD));
} }
if (!button_hold_processed[button_index]) { if (!button_hold_processed[button_index]) {
// If this is about the power button, ... // If this is about the power button, ...
if (is_power_button) { if (is_power_button) {
// If no other buttons are pressed and the up or down button was not tapped while holding // If we're not ignoring the power button and no other buttons are pressed, ...
// the power button before this, ... if (!ignore_power_button && buttons_pressed == 1) {
if (buttons_pressed == 1 && !tap_count) {
// If the power is on, adjust the brightness. Set the direction based on the current // If the power is on, adjust the brightness. Set the direction based on the current
// direction for the device and then invert the direction when the power button is // direction for the device and then invert the direction when the power button is
@ -385,73 +377,28 @@ void PWMDimmerHandleButton(void)
// If this is about the down or up buttons, ... // If this is about the down or up buttons, ...
else { else {
// If the power is on and the up or down button was not tapped while holding the power // If the power button is also pressed, ...
// button before this, adjust the brightness. Set the direction based on which button is if (button_pressed[power_button_index]) {
// pressed. The new brightness will be calculated below.
if (power_is_on && !tap_count) {
bri_offset = (is_down_button ? -1 : 1);
}
else {
uint8_t mqtt_trigger = 0;
// If the up or down button was tapped while holding the power button before this, // If the up or down button was tapped while holding the power button before this,
// handle the operation. // handle the operation below.
if (tap_count) { if (button_tapped) {
handle_tap = true;
// Send a device group update to select the previous/next fixed color. button_hold_time[button_index] = now + 500;
if (down_button_tapped) {
#ifdef USE_DEVICE_GROUPS
uint8_t uint8_value;
#ifdef USE_PWM_DIMMER_REMOTE
if (!active_device_is_local)
uint8_value = active_remote_pwm_dimmer->fixed_color_index;
else
#endif // USE_PWM_DIMMER_REMOTE
uint8_value = Light.fixed_color_index;
if (is_down_button)
uint8_value--;
else
uint8_value++;
#ifdef USE_PWM_DIMMER_REMOTE
if (!active_device_is_local)
active_remote_pwm_dimmer->fixed_color_index = uint8_value;
else
#endif // USE_PWM_DIMMER_REMOTE
Light.fixed_color_index = uint8_value;
dgr_item = DGR_ITEM_LIGHT_FIXED_COLOR;
dgr_value = uint8_value;
dgr_more_to_come = true;
#endif // USE_DEVICE_GROUPS
;
}
// Publish MQTT Event Trigger#.
else {
mqtt_trigger = (is_down_button ? 3 : 4);
}
} }
// If the power is not on, publish MQTT Event Trigger#. // Otherwise, publish MQTT Event Trigger#.
else if (!power_is_on) { else {
mqtt_trigger = (is_down_button ? 1 : 2); mqtt_trigger = (is_down_button ? 1 : 2);
button_hold_time[button_index] = now + 60000;
ignore_power_button = true;
} }
}
// If we need to publish an MQTT trigger, do it. // Otherwise, if the power is on, adjust the brightness. Set the direction based on which
if (mqtt_trigger) { // button is pressed. The new brightness will be calculated below.
char topic[TOPSZ]; else if (power_is_on && !button_tapped) {
sprintf_P(mqtt_data, PSTR("Trigger%u"), mqtt_trigger); bri_offset = (is_down_button ? -1 : 1);
#ifdef USE_PWM_DIMMER_REMOTE
if (!active_device_is_local) {
snprintf_P(topic, sizeof(topic), PSTR("cmnd/%s/Event"), device_groups[power_button_index].group_name);
MqttPublish(topic);
}
else
#endif // USE_PWM_DIMMER_REMOTE
MqttPublishPrefixTopic_P(CMND, PSTR("Event"));
}
button_hold_time[button_index] = now + 500;
} }
} }
} }
@ -461,16 +408,44 @@ void PWMDimmerHandleButton(void)
// If the button was just released, ... // If the button was just released, ...
else { else {
bool button_was_held = button_hold_sent[button_index]; bool button_was_held = button_hold_sent[button_index];
button_hold_sent[button_index] = false;
// If the button was not held, send a button toggle. If the button was held but not processes by // If the button was not held, send a button toggle. If the button was held but not processes by
// support_button or support_buttondoesn't process the toggle (is not handled by a rule), ... // support_button or support_buttondoesn't process the toggle (is not handled by a rule), ...
if (!(button_hold_sent[button_index] ? button_hold_processed[button_index] : SendKey(KEY_BUTTON, button_index + 1, POWER_TOGGLE))) { if (!(button_was_held ? button_hold_processed[button_index] : SendKey(KEY_BUTTON, button_index + 1, POWER_TOGGLE))) {
// If this is about the power button, ... // If this is about the power button, ...
if (is_power_button) { if (is_power_button) {
// If the power button was held, ... // If the up or down button was tapped while the power button was held and the up or
if (button_was_held) { // down buttons weren't tapped or held afterwards, handle the operation based on which
// button was tapped.
if (button_tapped) {
if (!tap_handled) {
#ifdef USE_PWM_DIMMER_REMOTE
if (active_device_is_local) {
#endif // USE_PWM_DIMMER_REMOTE
// Toggle the powered-off LED option.
if (down_button_tapped) {
Settings.flag4.led_timeout ^= 1;
if (Light.power) PWMDimmerSetBrightnessLeds(Settings.flag4.led_timeout ? 0 : -1);
}
// Toggle the LED timeout.
else {
Settings.flag4.powered_off_led ^= 1;
PWMDimmerSetPoweredOffLed();
}
#ifdef USE_PWM_DIMMER_REMOTE
}
#endif // USE_PWM_DIMMER_REMOTE
}
tap_handled = false;
}
// Otherwise, if the power button was held, ...
else if (button_was_held) {
// If the power button was held with no other buttons pressed, we changed the brightness // If the power button was held with no other buttons pressed, we changed the brightness
// so invert the bri direction for the next time and send a final update. // so invert the bri direction for the next time and send a final update.
@ -487,44 +462,11 @@ void PWMDimmerHandleButton(void)
state_updated = true; state_updated = true;
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
} }
// If the up or down button was tapped while the power button was held, ...
else if (tap_count) {
// If the button was tapped but not held, handle the operation based on which button was
// tapped.
if (!button_was_held) {
#ifdef USE_PWM_DIMMER_REMOTE
if (active_device_is_local) {
#endif // USE_PWM_DIMMER_REMOTE
// Toggle the powered-off LED option.
if (down_button_tapped) {
Settings.flag4.led_timeout ^= 1;
if (Light.power) PWMDimmerSetBrightnessLeds(Settings.flag4.led_timeout ? -1 : 0);
}
// Toggle the LED timeout.
else {
Settings.flag4.powered_off_led ^= 1;
PWMDimmerSetPoweredOffLed();
}
#ifdef USE_PWM_DIMMER_REMOTE
}
#endif // USE_PWM_DIMMER_REMOTE
}
// If the down button was tapped and held, we changed the fixed color. Send a final
// update.
else if (down_button_tapped) {
dgr_item = DGR_ITEM_FLAGS;
}
}
} }
// If the power button was not held, toggle the power. // If the power button was not held and we're not ignoring the next power button release,
else { // toggle the power.
else if (!ignore_power_button) {
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
if (!active_device_is_local) if (!active_device_is_local)
power_on_bri = active_remote_pwm_dimmer->bri_power_on; power_on_bri = active_remote_pwm_dimmer->bri_power_on;
@ -537,30 +479,34 @@ void PWMDimmerHandleButton(void)
// If this is about the up or down buttons, ... // If this is about the up or down buttons, ...
else { else {
if (restore_brightness_leds) { // If the power button is also pressed, set the flag to ignore the power button until it is
restore_brightness_leds = false; // released.
PWMDimmerSetBrightnessLeds(Settings.flag4.led_timeout ? -1 : 0); if (button_pressed[power_button_index]) {
ignore_power_button = true;
// If the button was tapped, handle it below.
if (button_tapped) {
handle_tap = true;
}
// Otherwise, if the button was not held, flag the tap.
else if (!button_was_held) {
button_tapped = true;
down_button_tapped = is_down_button;
}
} }
// If the button was not held and the power button is also pressed, increment the count of // If the power button is not also pressed, ...
// how many times the button has been tapped. else {
if (!button_was_held && button_pressed[power_button_index]) {
down_button_tapped = is_down_button;
tap_count++;
}
// If the button wasn't tapped while the power button was pressed, ...
if (!tap_count) {
// If the power is on, ... // If the power is on, ...
if (power_is_on) { if (power_is_on) {
// If the button was not held, adjust the brightness. Set the direction based on which // If the button was not held, adjust the brightness. Set the direction based on which
// button is pressed. The new brightness will be calculated below. // button is pressed. The new brightness will be calculated below.
if (button_hold_time[button_index] >= now) { if (!button_was_held) {
bri_offset = (is_down_button ? -1 : 1); bri_offset = (is_down_button ? -1 : 1);
dgr_item = DGR_ITEM_FLAGS; dgr_more_to_come = false;
state_updated = true;
} }
// If the button was held and the hold was not processed by a rule, we changed the // If the button was held and the hold was not processed by a rule, we changed the
@ -589,6 +535,10 @@ void PWMDimmerHandleButton(void)
// Flag the button as released. // Flag the button as released.
button_pressed[button_index] = false; button_pressed[button_index] = false;
buttons_pressed--; buttons_pressed--;
if (is_power_button) {
ignore_power_button = false;
button_tapped = false;
}
} }
// If we need to adjust the brightness, do it. // If we need to adjust the brightness, do it.
@ -610,11 +560,13 @@ void PWMDimmerHandleButton(void)
} }
if (new_bri != bri) { if (new_bri != bri) {
#ifdef USE_DEVICE_GROUPS #ifdef USE_DEVICE_GROUPS
SendDeviceGroupMessage(power_button_index, DGR_MSGTYP_UPDATE_MORE_TO_COME, DGR_ITEM_LIGHT_BRI, new_bri); SendDeviceGroupMessage(power_button_index, (dgr_more_to_come ? DGR_MSGTYP_UPDATE_MORE_TO_COME : DGR_MSGTYP_UPDATE), DGR_ITEM_LIGHT_BRI, new_bri);
#endif // USE_DEVICE_GROUPS #endif // USE_DEVICE_GROUPS
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
if (!active_device_is_local) if (!active_device_is_local) {
active_remote_pwm_dimmer->bri_power_on = active_remote_pwm_dimmer->bri = new_bri; active_remote_pwm_dimmer->bri_power_on = active_remote_pwm_dimmer->bri = new_bri;
PWMDimmerSetBrightnessLeds(new_bri);
}
else { else {
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
skip_light_fade = true; skip_light_fade = true;
@ -632,12 +584,15 @@ void PWMDimmerHandleButton(void)
} }
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
} }
else { #ifdef USE_PWM_DIMMER_REMOTE
PWMDimmerSetBrightnessLeds(0); else if (!active_device_is_local)
} PWMDimmerSetBrightnessLeds(new_bri);
#endif // USE_PWM_DIMMER_REMOTE
else
PWMDimmerSetBrightnessLeds(-1);
} }
// If we're supposed to toggle the power on, do it. // If we need to toggle the power on, do it.
else if (power_on_bri) { else if (power_on_bri) {
power_t new_power; power_t new_power;
#ifdef USE_DEVICE_GROUPS #ifdef USE_DEVICE_GROUPS
@ -645,6 +600,7 @@ void PWMDimmerHandleButton(void)
if (!active_device_is_local) { if (!active_device_is_local) {
active_remote_pwm_dimmer->power_on ^= 1; active_remote_pwm_dimmer->power_on ^= 1;
new_power = active_remote_pwm_dimmer->power_on; new_power = active_remote_pwm_dimmer->power_on;
PWMDimmerSetBrightnessLeds(new_power ? -power_on_bri : 0);
} }
else { else {
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
@ -664,18 +620,71 @@ void PWMDimmerHandleButton(void)
else { else {
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
light_state.setBri(power_on_bri); light_state.setBri(power_on_bri);
#ifdef USE_DEVICE_GROUPS
Light.devgrp_no_channels_out = true;
#endif // USE_DEVICE_GROUPS
ExecuteCommandPower(1, POWER_TOGGLE, SRC_RETRY); ExecuteCommandPower(1, POWER_TOGGLE, SRC_RETRY);
#ifdef USE_DEVICE_GROUPS
Light.devgrp_no_channels_out = false;
#endif // USE_DEVICE_GROUPS
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
} }
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
} }
// If the up or down button was tapped while holding the power button and the up or down button
// is being held or was just released after not being held, handle the operation.
if (handle_tap) {
ignore_power_button = tap_handled = true;
// If the down button was tapped while holding the power button, send a device group update to
// select the previous/next fixed color.
if (down_button_tapped) {
#ifdef USE_DEVICE_GROUPS
int8_t add_value = (is_down_button ? -1 : 1);
#ifdef USE_PWM_DIMMER_REMOTE
if (!active_device_is_local) {
active_remote_pwm_dimmer->fixed_color_index += add_value;
dgr_value = active_remote_pwm_dimmer->fixed_color_index;
}
else {
#endif // USE_PWM_DIMMER_REMOTE
local_fixed_color_index += add_value;
dgr_value = local_fixed_color_index;
#ifdef USE_PWM_DIMMER_REMOTE
}
#endif // USE_PWM_DIMMER_REMOTE
dgr_item = DGR_ITEM_LIGHT_FIXED_COLOR;
#endif // USE_DEVICE_GROUPS
;
}
// If the down button was tapped while holding the power button, publish an MQTT Event Trigger#.
else {
mqtt_trigger = (is_down_button ? 3 : 4);
}
}
// If we need to publish an MQTT trigger, do it.
if (mqtt_trigger) {
char topic[TOPSZ];
sprintf_P(mqtt_data, PSTR("Trigger%u"), mqtt_trigger);
#ifdef USE_PWM_DIMMER_REMOTE
if (!active_device_is_local) {
snprintf_P(topic, sizeof(topic), PSTR("cmnd/%s/Event"), device_groups[power_button_index].group_name);
MqttPublish(topic);
}
else
#endif // USE_PWM_DIMMER_REMOTE
MqttPublishPrefixTopic_P(CMND, PSTR("Event"));
}
// If we're not changing the brightness or toggling the power and we made changes, send a group // If we're not changing the brightness or toggling the power and we made changes, send a group
// update. // update.
if (dgr_item) { if (dgr_item) {
#ifdef USE_DEVICE_GROUPS #ifdef USE_DEVICE_GROUPS
AddLog_P2(LOG_LEVEL_ERROR, PSTR("PWMDimmer: sending DGR item %u"), dgr_item); DevGroupMessageType message_type = DGR_MSGTYP_UPDATE_DIRECT;
SendDeviceGroupMessage(power_button_index, (dgr_more_to_come ? DGR_MSGTYP_UPDATE_MORE_TO_COME : DGR_MSGTYP_UPDATE_DIRECT), dgr_item, dgr_value); if (handle_tap && active_device_is_local) message_type = (DevGroupMessageType)(message_type + DGR_MSGTYPFLAG_WITH_LOCAL);
SendDeviceGroupMessage(power_button_index, message_type, dgr_item, dgr_value);
#endif // USE_DEVICE_GROUPS #endif // USE_DEVICE_GROUPS
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
if (active_device_is_local) { if (active_device_is_local) {
@ -762,9 +771,9 @@ bool Xdrv35(uint8_t function)
switch (function) { switch (function) {
case FUNC_EVERY_SECOND: case FUNC_EVERY_SECOND:
// Turn off the brightness LED's if it's time. // Turn off/restore the brightness LED's if it's time.
if (led_timeout_seconds && !led_timeout_seconds--) { if (led_timeout_seconds && !--led_timeout_seconds) {
PWMDimmerSetBrightnessLeds(-1); PWMDimmerSetBrightnessLeds(-2);
} }
// The powered-off LED is also the LedLink LED. If we lose the WiFi or MQTT server connection, // The powered-off LED is also the LedLink LED. If we lose the WiFi or MQTT server connection,