Add PWM Dimmer multi-press and ledmask support

This commit is contained in:
Paul C Diem 2020-10-19 20:12:41 -05:00
parent 32648da9b6
commit f075a89d6b
8 changed files with 365 additions and 340 deletions

View File

@ -465,8 +465,8 @@
#define DEVICE_GROUPS_ADDRESS 239,255,250,250 // Device groups multicast address #define DEVICE_GROUPS_ADDRESS 239,255,250,250 // Device groups multicast address
#define DEVICE_GROUPS_PORT 4447 // Device groups multicast port #define DEVICE_GROUPS_PORT 4447 // Device groups multicast port
#define USE_DEVICE_GROUPS_SEND // Add support for the DevGroupSend command (+0k6 code) #define USE_DEVICE_GROUPS_SEND // Add support for the DevGroupSend command (+0k6 code)
#define USE_PWM_DIMMER // Add support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+2k2 code, DGR=0k4) #define USE_PWM_DIMMER // Add support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+2k3 code, DGR=0k7)
#define USE_PWM_DIMMER_REMOTE // Add support for remote switches to PWM Dimmer (requires USE_DEVICE_GROUPS) (+0k9 code) #define USE_PWM_DIMMER_REMOTE // Add support for remote switches to PWM Dimmer (requires USE_DEVICE_GROUPS) (+0k6 code)
//#define USE_KEELOQ // Add support for Jarolift rollers by Keeloq algorithm (+4k5 code) //#define USE_KEELOQ // Add support for Jarolift rollers by Keeloq algorithm (+4k5 code)
#define USE_SONOFF_D1 // Add support for Sonoff D1 Dimmer (+0k7 code) #define USE_SONOFF_D1 // Add support for Sonoff D1 Dimmer (+0k7 code)

View File

@ -1885,7 +1885,13 @@ void CmndLedState(void) {
void CmndLedMask(void) { void CmndLedMask(void) {
if (XdrvMailbox.data_len > 0) { if (XdrvMailbox.data_len > 0) {
#ifdef USE_PWM_DIMMER
PWMDimmerSetBrightnessLeds(0);
#endif // USE_PWM_DIMMER
Settings.ledmask = XdrvMailbox.payload; Settings.ledmask = XdrvMailbox.payload;
#ifdef USE_PWM_DIMMER
PWMDimmerSetBrightnessLeds(-1);
#endif // USE_PWM_DIMMER
} }
char stemp1[TOPSZ]; char stemp1[TOPSZ];
snprintf_P(stemp1, sizeof(stemp1), PSTR("%d (0x%04X)"), Settings.ledmask, Settings.ledmask); snprintf_P(stemp1, sizeof(stemp1), PSTR("%d (0x%04X)"), Settings.ledmask, Settings.ledmask);

View File

@ -48,7 +48,6 @@ struct device_group {
uint16_t ack_check_interval; uint16_t ack_check_interval;
uint8_t message_header_length; uint8_t message_header_length;
uint8_t initial_status_requests_remaining; uint8_t initial_status_requests_remaining;
bool local;
char group_name[TOPSZ]; char group_name[TOPSZ];
uint8_t message[128]; uint8_t message[128];
struct device_group_member * device_group_members; struct device_group_member * device_group_members;
@ -157,8 +156,6 @@ void DeviceGroupsInit(void)
device_group->last_full_status_sequence = -1; device_group->last_full_status_sequence = -1;
} }
device_groups[0].local = true;
// If both in and out shared items masks are 0, assume they're unitialized and initialize them. // If both in and out shared items masks are 0, assume they're unitialized and initialize them.
if (!Settings.device_group_share_in && !Settings.device_group_share_out) { if (!Settings.device_group_share_in && !Settings.device_group_share_out) {
Settings.device_group_share_in = Settings.device_group_share_out = 0xffffffff; Settings.device_group_share_in = Settings.device_group_share_out = 0xffffffff;
@ -296,6 +293,7 @@ void SendReceiveDeviceGroupMessage(struct device_group * device_group, struct de
*/ */
XdrvMailbox.command = nullptr; // Indicates the source is a device group update XdrvMailbox.command = nullptr; // Indicates the source is a device group update
XdrvMailbox.index = flags | message_sequence << 16; XdrvMailbox.index = flags | message_sequence << 16;
if (device_group_index == 0 && first_device_group_is_local) XdrvMailbox.index |= DGR_FLAG_LOCAL;
XdrvMailbox.topic = (char *)&device_group_index; XdrvMailbox.topic = (char *)&device_group_index;
if (flags & (DGR_FLAG_MORE_TO_COME | DGR_FLAG_DIRECT)) skip_light_fade = true; if (flags & (DGR_FLAG_MORE_TO_COME | DGR_FLAG_DIRECT)) skip_light_fade = true;
@ -388,10 +386,12 @@ void SendReceiveDeviceGroupMessage(struct device_group * device_group, struct de
switch (item) { switch (item) {
case DGR_ITEM_POWER: case DGR_ITEM_POWER:
if (Settings.flag4.multiple_device_groups) { // SetOption88 - Enable relays in separate device groups if (Settings.flag4.multiple_device_groups) { // SetOption88 - Enable relays in separate device groups
if (device_group_index < devices_present) {
bool on = (value & 1); bool on = (value & 1);
if (on != (power & (1 << device_group_index))) ExecuteCommandPower(device_group_index + 1, (on ? POWER_ON : POWER_OFF), SRC_REMOTE); if (on != (power & (1 << device_group_index))) ExecuteCommandPower(device_group_index + 1, (on ? POWER_ON : POWER_OFF), SRC_REMOTE);
} }
else if (device_group->local) { }
else if (XdrvMailbox.index & DGR_FLAG_LOCAL) {
uint8_t mask_devices = value >> 24; uint8_t mask_devices = value >> 24;
if (mask_devices > devices_present) mask_devices = devices_present; if (mask_devices > devices_present) mask_devices = devices_present;
for (uint32_t i = 0; i < mask_devices; i++) { for (uint32_t i = 0; i < mask_devices; i++) {
@ -505,10 +505,9 @@ bool _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
building_status_message = true; building_status_message = true;
// Call the drivers to build the status update. // Call the drivers to build the status update.
if (device_group->local || Settings.flag4.multiple_device_groups) { // SetOption88 - Enable relays in separate device groups
SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_POWER, power); SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_POWER, power);
} XdrvMailbox.index = 0;
XdrvMailbox.index = device_group_index << 16; if (device_group_index == 0 && first_device_group_is_local) XdrvMailbox.index = DGR_FLAG_LOCAL;
XdrvMailbox.command_code = DGR_ITEM_STATUS; XdrvMailbox.command_code = DGR_ITEM_STATUS;
XdrvMailbox.topic = (char *)&device_group_index; XdrvMailbox.topic = (char *)&device_group_index;
XdrvCall(FUNC_DEVICE_GROUP_ITEM); XdrvCall(FUNC_DEVICE_GROUP_ITEM);
@ -680,7 +679,7 @@ bool _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
*message_ptr++ = value & 0xff; *message_ptr++ = value & 0xff;
value >>= 8; value >>= 8;
// For the power item, the device count is overlayed onto the highest 8 bits. // For the power item, the device count is overlayed onto the highest 8 bits.
if (item == DGR_ITEM_POWER && !value) value = (device_group_index == 0 ? devices_present : 1); if (item == DGR_ITEM_POWER && !value) value = (device_group_index == 0 && first_device_group_is_local ? devices_present : 1);
*message_ptr++ = value; *message_ptr++ = value;
} }
} }

View File

@ -492,6 +492,9 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state)
XdrvMailbox.payload = device_save << 24 | key << 16 | state << 8 | device; XdrvMailbox.payload = device_save << 24 | key << 16 | state << 8 | device;
XdrvCall(FUNC_ANY_KEY); XdrvCall(FUNC_ANY_KEY);
XdrvMailbox.payload = payload_save; XdrvMailbox.payload = payload_save;
#ifdef USE_PWM_DIMMER
if (PWM_DIMMER == my_module_type) result = true;
#endif // USE_PWM_DIMMER
return result; return result;
} }

View File

@ -310,7 +310,7 @@ enum SettingsTextIndex { SET_OTAURL,
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 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, DGR_FLAG_LOCAL = 128 };
enum DevGroupItem { DGR_ITEM_EOL, DGR_ITEM_STATUS, DGR_ITEM_FLAGS, enum DevGroupItem { DGR_ITEM_EOL, DGR_ITEM_STATUS, DGR_ITEM_FLAGS,
DGR_ITEM_LIGHT_FADE, DGR_ITEM_LIGHT_SPEED, DGR_ITEM_LIGHT_BRI, DGR_ITEM_LIGHT_SCHEME, DGR_ITEM_LIGHT_FIXED_COLOR, DGR_ITEM_LIGHT_FADE, DGR_ITEM_LIGHT_SPEED, DGR_ITEM_LIGHT_BRI, DGR_ITEM_LIGHT_SCHEME, DGR_ITEM_LIGHT_FIXED_COLOR,

View File

@ -391,6 +391,7 @@ const char kWebColors[] PROGMEM =
#define SendDeviceGroupMessage(DEVICE_INDEX, REQUEST_TYPE, ...) _SendDeviceGroupMessage(DEVICE_INDEX, REQUEST_TYPE, __VA_ARGS__, 0) #define SendDeviceGroupMessage(DEVICE_INDEX, REQUEST_TYPE, ...) _SendDeviceGroupMessage(DEVICE_INDEX, REQUEST_TYPE, __VA_ARGS__, 0)
#define SendLocalDeviceGroupMessage(REQUEST_TYPE, ...) _SendDeviceGroupMessage(0, REQUEST_TYPE, __VA_ARGS__, 0) #define SendLocalDeviceGroupMessage(REQUEST_TYPE, ...) _SendDeviceGroupMessage(0, REQUEST_TYPE, __VA_ARGS__, 0)
uint8_t device_group_count = 0; uint8_t device_group_count = 0;
bool first_device_group_is_local = true;
#endif // USE_DEVICE_GROUPS #endif // USE_DEVICE_GROUPS
#ifdef DEBUG_TASMOTA_CORE #ifdef DEBUG_TASMOTA_CORE

View File

@ -2336,11 +2336,12 @@ void LightHandleDevGroupItem(void)
{ {
static bool send_state = false; static bool send_state = false;
static bool restore_power = false; static bool restore_power = false;
#ifdef USE_PWM_DIMMER_REMOTE
if (!(XdrvMailbox.index & DGR_FLAG_LOCAL)) return;
#endif // USE_PWM_DIMMER_REMOTE
bool more_to_come; bool more_to_come;
uint32_t value = XdrvMailbox.payload; uint32_t value = XdrvMailbox.payload;
#ifdef USE_PWM_DIMMER_REMOTE
if (*XdrvMailbox.topic) return; // Ignore updates from other device groups
#endif // USE_PWM_DIMMER_REMOTE
switch (XdrvMailbox.command_code) { switch (XdrvMailbox.command_code) {
case DGR_ITEM_EOL: case DGR_ITEM_EOL:
more_to_come = (XdrvMailbox.index & DGR_FLAG_MORE_TO_COME); more_to_come = (XdrvMailbox.index & DGR_FLAG_MORE_TO_COME);

View File

@ -31,6 +31,7 @@
\*********************************************************************************************/ \*********************************************************************************************/
#define XDRV_35 35 #define XDRV_35 35
#define MAX_PWM_DIMMER_KEYS 3
const char kPWMDimmerCommands[] PROGMEM = "|" // No prefix const char kPWMDimmerCommands[] PROGMEM = "|" // No prefix
D_CMND_BRI_PRESET D_CMND_BRI_PRESET
@ -58,26 +59,26 @@ struct remote_pwm_dimmer {
}; };
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
uint32_t ignore_any_key_time = 0;
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 local_fixed_color_index = 128; uint8_t local_fixed_color_index = 128;
bool ignore_power_button = false;
bool button_tapped = false; bool button_tapped = false;
bool down_button_tapped = false; bool down_button_tapped = false;
bool tap_handled = false; bool ignore_power_button = false;
bool multibutton_in_progress = false;
bool power_button_increases_bri = true; bool power_button_increases_bri = true;
bool tap_handled = false;
bool invert_power_button_bri_direction = false; bool invert_power_button_bri_direction = false;
bool button_pressed[3] = { false, false, false }; bool button_pressed[3] = { false, false, false };
bool button_hold_sent[3]; bool button_held[3];
bool button_hold_processed[3];
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
struct remote_pwm_dimmer * remote_pwm_dimmers; struct remote_pwm_dimmer remote_pwm_dimmers[MAX_PWM_DIMMER_KEYS];
struct remote_pwm_dimmer * active_remote_pwm_dimmer; struct remote_pwm_dimmer * active_remote_pwm_dimmer;
uint8_t remote_pwm_dimmer_count;
bool active_device_is_local;
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
void PWMModulePreInit(void) void PWMModulePreInit(void)
@ -89,9 +90,14 @@ void PWMModulePreInit(void)
// If the module was just changed to PWM Dimmer, set the defaults. // If the module was just changed to PWM Dimmer, set the defaults.
if (Settings.last_module != Settings.module) { if (Settings.last_module != Settings.module) {
Settings.flag.pwm_control = true; // SetOption15 - Switch between commands PWM or COLOR/DIMMER/CT/CHANNEL Settings.flag.pwm_control = true; // SetOption15 - Switch between commands PWM or COLOR/DIMMER/CT/CHANNEL
Settings.param[P_HOLD_TIME] = 5; // SetOption32 - Button held for factor times longer
Settings.bri_power_on = Settings.bri_preset_low = Settings.bri_preset_high = 0; Settings.bri_power_on = Settings.bri_preset_low = Settings.bri_preset_high = 0;
Settings.last_module = Settings.module; Settings.last_module = Settings.module;
// Previous versions of PWM Dimmer used SetOption32 - Button held for factor times longer as the
// hold time. The hold time is now fixed and SetOption32 is used as normal including to
// determine how long a button is held before a reset command is executed. If SetOption32 is
// still 5, change it to 40 (the default).
if (Settings.param[P_HOLD_TIME] == 5) Settings.param[P_HOLD_TIME] = 40;
} }
// Make sure the brightness level settings are sensible. // Make sure the brightness level settings are sensible.
@ -111,18 +117,20 @@ void PWMModulePreInit(void)
Settings.flag4.device_groups_enabled = true; Settings.flag4.device_groups_enabled = true;
device_group_count = 0; device_group_count = 0;
for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) { for (uint32_t button_index = 0; button_index < MAX_PWM_DIMMER_KEYS; button_index++) {
if (PinUsed(GPIO_KEY1, button_index)) device_group_count++; if (PinUsed(GPIO_KEY1, button_index)) device_group_count++;
} }
remote_pwm_dimmer_count = device_group_count - 1; // If no relay or PWM is defined, all buttons control remote devices.
if (remote_pwm_dimmer_count) { if (!PinUsed(GPIO_REL1) && !PinUsed(GPIO_PWM1)) {
if ((remote_pwm_dimmers = (struct remote_pwm_dimmer *) calloc(remote_pwm_dimmer_count, sizeof(struct remote_pwm_dimmer))) == nullptr) { first_device_group_is_local = false;
AddLog_P2(LOG_LEVEL_ERROR, PSTR("PWMDimmer: error allocating PWM dimmer array"));
Settings.flag4.multiple_device_groups = false; // Back out the changes made in the light module under the assumtion we have a relay or PWM.
devices_present--;
light_type = 0;
} }
else {
for (uint8_t i = 0; i < remote_pwm_dimmer_count; i++) { for (uint8_t i = 0; i < MAX_PWM_DIMMER_KEYS; i++) {
active_remote_pwm_dimmer = &remote_pwm_dimmers[i]; active_remote_pwm_dimmer = &remote_pwm_dimmers[i];
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;
@ -130,35 +138,44 @@ void PWMModulePreInit(void)
active_remote_pwm_dimmer->fixed_color_index = 128; active_remote_pwm_dimmer->fixed_color_index = 128;
} }
} }
}
}
active_device_is_local = true;
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
} }
// bri: -1 = set to current light bri, -2 = timeout, 0-255 = set to bri // bri: -1 = set to current light bri, -2 = timeout, 0-255 = set to bri
void PWMDimmerSetBrightnessLeds(int32_t bri) void PWMDimmerSetBrightnessLeds(int32_t bri)
{ {
if (leds_present) { // Find out how many of the LEDs have their ledmask bit set.
uint32_t leds = 0;
uint32_t mask = 1;
int32_t led;
for (led = 0; led < leds_present; led++) {
if (Settings.ledmask & mask) leds++;
mask <<= 1;
}
// If we found at least one LED, get the brightness to show and calculate the brightness level
// difference between each LED.
if (leds) {
led_timeout_seconds = 5; led_timeout_seconds = 5;
if (bri < 0) { if (bri < 0) {
bri = ((bri == -2 && Settings.flag4.led_timeout) || !Light.power ? 0 : light_state.getBri()); bri = ((bri == -2 && Settings.flag4.led_timeout) || !Light.power ? 0 : light_state.getBri());
if (!bri || !Settings.flag4.led_timeout) led_timeout_seconds = 0; if (!bri || !Settings.flag4.led_timeout) led_timeout_seconds = 0;
} }
uint32_t step = 256 / (leds_present + 1); uint32_t step = 256 / (leds + 1);
uint32_t level = step;
SetLedPowerIdx(0, bri >= level); // Turn the LED's on/off.
if (leds_present > 1) { uint32_t level = 0;
led = -1;
mask = 0;
for (uint32_t count = 0; count < leds; count++) {
level += step; level += step;
SetLedPowerIdx(1, bri >= level); for (;;) {
if (leds_present > 2) { led++;
level += step; mask <<= 1;
SetLedPowerIdx(2, bri >= level); if (!mask) mask = 1;
if (leds_present > 3) { if (Settings.ledmask & mask) break;
level += step;
SetLedPowerIdx(3, bri >= level);
}
} }
SetLedPowerIdx(led, bri >= level);
} }
} }
} }
@ -183,63 +200,57 @@ void PWMDimmerSetPower(void)
#ifdef USE_DEVICE_GROUPS #ifdef USE_DEVICE_GROUPS
void PWMDimmerHandleDevGroupItem(void) void PWMDimmerHandleDevGroupItem(void)
{ {
uint32_t value = XdrvMailbox.payload;
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
uint8_t device_group_index = *(uint8_t *)XdrvMailbox.topic; uint8_t device_group_index = *(uint8_t *)XdrvMailbox.topic;
if (device_group_index > remote_pwm_dimmer_count) return; bool is_local = ((XdrvMailbox.index & DGR_FLAG_LOCAL) != 0);
bool device_is_local = device_groups[device_group_index].local; if (device_group_index > MAX_PWM_DIMMER_KEYS) return;
struct remote_pwm_dimmer * remote_pwm_dimmer = &remote_pwm_dimmers[device_group_index - 1]; struct remote_pwm_dimmer * remote_pwm_dimmer = &remote_pwm_dimmers[device_group_index];
#else // USE_PWM_DIMMER_REMOTE #else // USE_PWM_DIMMER_REMOTE
if (*(uint8_t *)XdrvMailbox.topic) return; if (!(XdrvMailbox.index & DGR_FLAG_LOCAL)) return;
#endif // !USE_PWM_DIMMER_REMOTE #endif // !USE_PWM_DIMMER_REMOTE
uint32_t value = XdrvMailbox.payload;
switch (XdrvMailbox.command_code) { switch (XdrvMailbox.command_code) {
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
case DGR_ITEM_LIGHT_BRI: case DGR_ITEM_LIGHT_BRI:
if (!device_is_local) remote_pwm_dimmer->bri = value; remote_pwm_dimmer->bri = value;
break; break;
case DGR_ITEM_POWER: case DGR_ITEM_POWER:
if (!device_is_local) {
remote_pwm_dimmer->power_on = value & 1; remote_pwm_dimmer->power_on = value & 1;
remote_pwm_dimmer->power_button_increases_bri = (remote_pwm_dimmer->bri < 128); remote_pwm_dimmer->power_button_increases_bri = (remote_pwm_dimmer->bri < 128);
}
break; break;
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
case DGR_ITEM_LIGHT_FIXED_COLOR: case DGR_ITEM_LIGHT_FIXED_COLOR:
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
if (!device_is_local)
remote_pwm_dimmer->fixed_color_index = value; remote_pwm_dimmer->fixed_color_index = value;
else if (is_local)
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
local_fixed_color_index = value; local_fixed_color_index = value;
break; break;
case DGR_ITEM_BRI_POWER_ON: case DGR_ITEM_BRI_POWER_ON:
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
if (!device_is_local)
remote_pwm_dimmer->bri_power_on = value; remote_pwm_dimmer->bri_power_on = value;
else if (is_local)
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
Settings.bri_power_on = value; Settings.bri_power_on = value;
break; break;
case DGR_ITEM_BRI_PRESET_LOW: case DGR_ITEM_BRI_PRESET_LOW:
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
if (!device_is_local)
remote_pwm_dimmer->bri_preset_low = value; remote_pwm_dimmer->bri_preset_low = value;
else if (is_local)
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
Settings.bri_preset_low = value; Settings.bri_preset_low = value;
break; break;
case DGR_ITEM_BRI_PRESET_HIGH: case DGR_ITEM_BRI_PRESET_HIGH:
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
if (!device_is_local)
remote_pwm_dimmer->bri_preset_high = value; remote_pwm_dimmer->bri_preset_high = value;
else if (is_local)
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
Settings.bri_preset_high = value; Settings.bri_preset_high = value;
break; break;
case DGR_ITEM_STATUS: case DGR_ITEM_STATUS:
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
if (device_is_local) if (is_local)
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_BRI_POWER_ON, Settings.bri_power_on, SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_BRI_POWER_ON, Settings.bri_power_on,
DGR_ITEM_BRI_PRESET_LOW, Settings.bri_preset_low, DGR_ITEM_BRI_PRESET_HIGH, Settings.bri_preset_high); DGR_ITEM_BRI_PRESET_LOW, Settings.bri_preset_low, DGR_ITEM_BRI_PRESET_HIGH, Settings.bri_preset_high);
@ -248,40 +259,8 @@ void PWMDimmerHandleDevGroupItem(void)
} }
#endif // USE_DEVICE_GROUPS #endif // USE_DEVICE_GROUPS
void PWMDimmerHandleButton(void) void PWMDimmerHandleButton(uint32_t button_index, bool pressed)
{ {
/*
* Power Button Up/Down Buttons State Remote Mode Action
* -------------------- ---------------------- ----- ------------ ----------------------------
* Press & release Released Any Any Toggle power
* Hold for hold time Released On Any Brighter/dimmer while held
* then reverse direction
* Hold for hold time Released Off Any Power on at bri preset low
* Hold while Press & release up Any Any Toggle/change options
* Hold while Press & release down Any Any Toggle/change options
* Hold while Press up On Yes Brighter
* Hold while Press down On Yes Dimmer
* Released Hold up On No Brigther
* Released Hold down On No Dimmer
* Released Press & release up Off No Power on at bri preset low
* Released Press & release down Off No Power on at bri preset high
*
* Holding any button for over 10 seconds executes the WiFiConfig 2 command.
*
* In remote mode, whichever button is pressed first becomes the power button and any buttons
* pressed while it is held affect the device associated with it. The up and down buttons change
* depeneding on which button is the current power button:
*
* Power Down Up
* ----- ---- --
* 1 2 3
* 2 1 3
* 3 1 2
*/
// If the button is not pressed and was not just released (the most common case), just return.
if (XdrvMailbox.payload && !button_pressed[XdrvMailbox.index]) return;
bool handle_tap = false; bool handle_tap = false;
bool state_updated = false; bool state_updated = false;
int32_t bri_offset = 0; int32_t bri_offset = 0;
@ -290,62 +269,21 @@ void PWMDimmerHandleButton(void)
uint8_t dgr_value = 0; uint8_t dgr_value = 0;
uint8_t dgr_more_to_come = true; uint8_t dgr_more_to_come = true;
uint8_t mqtt_trigger = 0; uint8_t mqtt_trigger = 0;
uint32_t button_index = XdrvMailbox.index;
uint32_t now = millis();
// Initialize some variables. // Initialize some variables.
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
bool power_is_on = (!active_device_is_local ? active_remote_pwm_dimmer->power_on : power); bool power_is_on = (active_remote_pwm_dimmer ? active_remote_pwm_dimmer->power_on : power);
bool is_power_button = (button_index == power_button_index); bool is_power_button = (button_index == power_button_index);
bool is_down_button = (button_index == down_button_index);
#else // USE_PWM_DIMMER_REMOTE #else // USE_PWM_DIMMER_REMOTE
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
bool is_down_button = (button_index == (power_button_index ? 0 : 1)); bool is_down_button = (button_index == (power_button_index ? 0 : 1));
// If the button is pressed, ...
if (!XdrvMailbox.payload) {
// If the button was just pressed, flag the button as pressed, clear the hold sent flag and
// increment the buttons pressed count.
if (!button_pressed[button_index]) {
button_pressed[button_index] = true;
button_hold_time[button_index] = now + Settings.param[P_HOLD_TIME] * 100;
buttons_pressed++;
#ifdef USE_PWM_DIMMER_REMOTE
// If there are no other buttons pressed right now and remote mode is enabled, make the device
// associated with this button the device we're going to control.
if (buttons_pressed == 1 && Settings.flag4.multiple_device_groups) {
power_button_index = button_index;
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];
}
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
return;
}
// If the button is being held, ... // If the button is being held, ...
if (button_hold_time[button_index] < now) { if (pressed) {
uint32_t now = millis();
// If we're not in the middle of a power button plus up/down button sequence and the button
// has been held for over 10 seconds, execute the WiFiConfig 2 command.
if (!ignore_power_button && now - button_hold_time[button_index] > 10000) {
button_hold_time[button_index] = now + 90000;
char scmnd[20];
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WIFICONFIG " 2"));
ExecuteCommand(scmnd, SRC_BUTTON);
return;
}
// Send a button hold if we haven't already. If it is handled (by the button topic or by a
// rule), ignore the this button until it's released.
if (!button_hold_sent[button_index]) {
button_hold_sent[button_index] = true;
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 this is about the power button, ... // If this is about the power button, ...
if (is_power_button) { if (is_power_button) {
@ -354,22 +292,22 @@ void PWMDimmerHandleButton(void)
if (!ignore_power_button && buttons_pressed == 1) { if (!ignore_power_button && buttons_pressed == 1) {
// 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 released.
// released. The new brightness will be calculated below. // The new brightness will be calculated below.
if (power_is_on) { if (power_is_on) {
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
bri_offset = (!active_device_is_local ? (active_remote_pwm_dimmer->power_button_increases_bri ? 1 : -1) : (power_button_increases_bri ? 1 : -1)); bri_offset = (active_remote_pwm_dimmer ? (active_remote_pwm_dimmer->power_button_increases_bri ? 1 : -1) : (power_button_increases_bri ? 1 : -1));
#else // USE_PWM_DIMMER_REMOTE #else // USE_PWM_DIMMER_REMOTE
bri_offset = (power_button_increases_bri ? 1 : -1); bri_offset = (power_button_increases_bri ? 1 : -1);
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
invert_power_button_bri_direction = true; invert_power_button_bri_direction = true;
} }
// If the power is not on, turn it on using an initial brightness of bri_preset_low and // If the power is not on, turn it on using an initial brightness of bri_preset_low and set
// set the power button hold time to delay before we start increasing the brightness. // the power button hold time to delay before we start increasing the brightness.
else { else {
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
if (!active_device_is_local) if (active_remote_pwm_dimmer)
power_on_bri = active_remote_pwm_dimmer->bri = active_remote_pwm_dimmer->bri_preset_low; power_on_bri = active_remote_pwm_dimmer->bri = active_remote_pwm_dimmer->bri_preset_low;
else else
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
@ -385,13 +323,19 @@ void PWMDimmerHandleButton(void)
// If the power button is also pressed, ... // If the power button is also pressed, ...
if (button_pressed[power_button_index]) { if (button_pressed[power_button_index]) {
// 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
// handle the operation below. // the operation below.
if (button_tapped) { if (button_tapped) {
handle_tap = true; handle_tap = true;
button_hold_time[button_index] = now + 500; button_hold_time[button_index] = now + 500;
} }
// Otherwise, if the power is on and remote mode is enabled, adjust the brightness. Set the
// direction based on which button is pressed. The new brightness will be calculated below.
else if (power_is_on && Settings.flag4.multiple_device_groups) {
bri_offset = (is_down_button ? -1 : 1);
}
// Otherwise, publish MQTT Event Trigger#. // Otherwise, publish MQTT Event Trigger#.
else { else {
mqtt_trigger = (is_down_button ? 1 : 2); mqtt_trigger = (is_down_button ? 1 : 2);
@ -407,28 +351,21 @@ 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_held[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
// support_button or support_buttondoesn't process the toggle (is not handled by a rule), ...
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 up or down button was tapped while the power button was held and the up or // If the up or down button was tapped while the power button was held and the up or down
// down buttons weren't tapped or held afterwards, handle the operation based on which // buttons weren't tapped or held afterwards, handle the operation based on which button was
// button was tapped. // tapped.
if (button_tapped) { if (button_tapped) {
if (!tap_handled) { if (!tap_handled) {
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
if (active_device_is_local) { if (!active_remote_pwm_dimmer) {
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
// Toggle the powered-off LED option. // Toggle the powered-off LED option.
@ -457,7 +394,7 @@ void PWMDimmerHandleButton(void)
if (invert_power_button_bri_direction) { if (invert_power_button_bri_direction) {
invert_power_button_bri_direction = false; invert_power_button_bri_direction = false;
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
if (!active_device_is_local) if (active_remote_pwm_dimmer)
active_remote_pwm_dimmer->power_button_increases_bri ^= 1; active_remote_pwm_dimmer->power_button_increases_bri ^= 1;
else else
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
@ -473,7 +410,7 @@ void PWMDimmerHandleButton(void)
// toggle the power. // toggle the power.
else if (!ignore_power_button) { else if (!ignore_power_button) {
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
if (!active_device_is_local) if (active_remote_pwm_dimmer)
power_on_bri = active_remote_pwm_dimmer->bri_power_on; power_on_bri = active_remote_pwm_dimmer->bri_power_on;
else else
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
@ -510,15 +447,14 @@ void PWMDimmerHandleButton(void)
// 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_was_held) { if (!button_was_held) {
bri_offset = (is_down_button ? -1 : 1); bri_offset = (is_down_button ? -5 : 5);
dgr_more_to_come = false; dgr_more_to_come = false;
state_updated = true; 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, we changed the brightness and sent updates with the
// brightness and sent updates with the more-to-come message type while the button was // more-to-come message type while the button was held. Send a final update.
// held. Send a final update. else {
else if (!button_hold_processed[button_index]) {
dgr_item = DGR_ITEM_FLAGS; dgr_item = DGR_ITEM_FLAGS;
state_updated = true; state_updated = true;
} }
@ -528,7 +464,7 @@ void PWMDimmerHandleButton(void)
// down button is pressed or bri_preset_low if the up button is pressed. // down button is pressed or bri_preset_low if the up button is pressed.
else { else {
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
if (!active_device_is_local) if (active_remote_pwm_dimmer)
power_on_bri = active_remote_pwm_dimmer->bri = (is_down_button ? active_remote_pwm_dimmer->bri_preset_low : active_remote_pwm_dimmer->bri_preset_high); power_on_bri = active_remote_pwm_dimmer->bri = (is_down_button ? active_remote_pwm_dimmer->bri_preset_low : active_remote_pwm_dimmer->bri_preset_high);
else else
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
@ -538,20 +474,11 @@ void PWMDimmerHandleButton(void)
} }
} }
// Flag the button as released.
button_pressed[button_index] = false;
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.
if (bri_offset) { if (bri_offset) {
int32_t bri; int32_t bri;
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
if (!active_device_is_local) if (active_remote_pwm_dimmer)
bri = active_remote_pwm_dimmer->bri; bri = active_remote_pwm_dimmer->bri;
else else
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
@ -569,7 +496,7 @@ void PWMDimmerHandleButton(void)
SendDeviceGroupMessage(power_button_index, (dgr_more_to_come ? DGR_MSGTYP_UPDATE_MORE_TO_COME : DGR_MSGTYP_UPDATE), 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_remote_pwm_dimmer) {
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); PWMDimmerSetBrightnessLeds(new_bri);
} }
@ -591,7 +518,7 @@ void PWMDimmerHandleButton(void)
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
} }
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
else if (!active_device_is_local) else if (active_remote_pwm_dimmer)
PWMDimmerSetBrightnessLeds(new_bri); PWMDimmerSetBrightnessLeds(new_bri);
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
else else
@ -603,7 +530,7 @@ void PWMDimmerHandleButton(void)
power_t new_power; power_t new_power;
#ifdef USE_DEVICE_GROUPS #ifdef USE_DEVICE_GROUPS
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
if (!active_device_is_local) { if (active_remote_pwm_dimmer) {
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); PWMDimmerSetBrightnessLeds(new_power ? -power_on_bri : 0);
@ -621,7 +548,7 @@ void PWMDimmerHandleButton(void)
#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_remote_pwm_dimmer)
active_remote_pwm_dimmer->power_button_increases_bri = (power_on_bri < 128); active_remote_pwm_dimmer->power_button_increases_bri = (power_on_bri < 128);
else { else {
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
@ -649,7 +576,7 @@ void PWMDimmerHandleButton(void)
#ifdef USE_DEVICE_GROUPS #ifdef USE_DEVICE_GROUPS
int8_t add_value = (is_down_button ? -1 : 1); int8_t add_value = (is_down_button ? -1 : 1);
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
if (!active_device_is_local) { if (active_remote_pwm_dimmer) {
active_remote_pwm_dimmer->fixed_color_index += add_value; active_remote_pwm_dimmer->fixed_color_index += add_value;
dgr_value = active_remote_pwm_dimmer->fixed_color_index; dgr_value = active_remote_pwm_dimmer->fixed_color_index;
} }
@ -675,36 +602,40 @@ void PWMDimmerHandleButton(void)
char topic[TOPSZ]; char topic[TOPSZ];
sprintf_P(mqtt_data, PSTR("Trigger%u"), mqtt_trigger); sprintf_P(mqtt_data, PSTR("Trigger%u"), mqtt_trigger);
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
if (!active_device_is_local) { if (active_remote_pwm_dimmer) {
snprintf_P(topic, sizeof(topic), PSTR("cmnd/%s/Event"), device_groups[power_button_index].group_name); snprintf_P(topic, sizeof(topic), PSTR("cmnd/%s/EVENT"), device_groups[power_button_index].group_name);
MqttPublish(topic); MqttPublish(topic);
} }
else else
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
MqttPublishPrefixTopic_P(CMND, PSTR("Event")); 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 need to send a device group update, do it.
// update.
if (dgr_item) { if (dgr_item) {
#ifdef USE_DEVICE_GROUPS #ifdef USE_DEVICE_GROUPS
DevGroupMessageType message_type = DGR_MSGTYP_UPDATE_DIRECT; DevGroupMessageType message_type = DGR_MSGTYP_UPDATE_DIRECT;
if (handle_tap && active_device_is_local) message_type = (DevGroupMessageType)(message_type + DGR_MSGTYPFLAG_WITH_LOCAL); #ifdef USE_PWM_DIMMER_REMOTE
if (handle_tap && !active_remote_pwm_dimmer)
#else // USE_PWM_DIMMER_REMOTE
if (handle_tap)
#endif // USE_PWM_DIMMER_REMOTE
message_type = (DevGroupMessageType)(message_type + DGR_MSGTYPFLAG_WITH_LOCAL);
SendDeviceGroupMessage(power_button_index, message_type, dgr_item, dgr_value); 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_remote_pwm_dimmer)
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
light_controller.saveSettings(); light_controller.saveSettings();
} }
if (state_updated) if (state_updated && Settings.flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT
#ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER_REMOTE
if (active_device_is_local) if (!active_remote_pwm_dimmer)
#endif // USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER_REMOTE
if (Settings.flag3.hass_tele_on_power) // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT
MqttPublishTeleState(); MqttPublishTeleState();
} }
}
/*********************************************************************************************\ /*********************************************************************************************\
* Commands * Commands
@ -796,8 +727,92 @@ bool Xdrv35(uint8_t function)
break; break;
case FUNC_BUTTON_PRESSED: case FUNC_BUTTON_PRESSED:
PWMDimmerHandleButton(); // If the button is pressed or was just released, ...
if (!XdrvMailbox.payload || button_pressed[XdrvMailbox.index]) {
uint32_t button_index = XdrvMailbox.index;
uint32_t now = millis();
// If the button is pressed, ...
if (!XdrvMailbox.payload) {
// If the button was just pressed, flag the button as pressed, set the hold time and
// increment the buttons pressed count.
if (!button_pressed[button_index]) {
button_pressed[button_index] = true;
button_hold_time[button_index] = now + (button_index == power_button_index ? 500 : 250);
buttons_pressed++;
if (buttons_pressed > 1) multibutton_in_progress = true;
#ifdef USE_PWM_DIMMER_REMOTE
// If there are no other buttons pressed right now and remote mode is enabled, make the
// device associated with this button the device we're going to control. In remote mode,
// whichever button is pressed first becomes the power button and any buttons pressed
// while it is held affect the device associated with it. The up and down buttons change
// depeneding on which button is the current power button and are based on the GPIOs
// used on the MJ-SD01 type dimmers.
//
// Power Down Up
// Position GPIO Button GPIO GPIO
// -------- ---- ------ ---- ----
// Top 0 1 1 0
// Middle 1 2 15 0
// Bottom 15 3 15 1
if (buttons_pressed == 1 && Settings.flag4.multiple_device_groups) {
power_button_index = button_index;
down_button_index = (Pin(GPIO_KEY1, power_button_index) == 15 ? gpio_pin[1] : gpio_pin[15]) - 32;
active_remote_pwm_dimmer = nullptr;
if (power_button_index || !first_device_group_is_local)
active_remote_pwm_dimmer = &remote_pwm_dimmers[power_button_index];
}
#endif // USE_PWM_DIMMER_REMOTE
}
// If hold time has arrived, handle it.
else if (button_hold_time[button_index] <= now) {
PWMDimmerHandleButton(button_index, true);
button_held[button_index] = true;
}
}
// If the button was just released, flag the button as released and decrement the buttons
// pressed count.
else {
button_pressed[button_index] = false;
buttons_pressed--;
// If this is a multibutton press or the button was held, handle it.
if (multibutton_in_progress || button_held[button_index]) {
PWMDimmerHandleButton(button_index, false);
// Set a timer so FUNC_ANY_KEY ignores the button if support_button winds up sending a
// key because of this.
ignore_any_key_time = now + 500;
}
// If the power button was just released, clear the flags associated with it.
if (button_index == power_button_index) {
if (ignore_power_button) ignore_any_key_time = now + 500;
ignore_power_button = false;
button_tapped = false;
}
button_held[button_index] = false;
}
// If a multi-button operation is in progress, tell support_button that we've handled it.
if (multibutton_in_progress) {
result = true; result = true;
if (buttons_pressed == 0) multibutton_in_progress = false;
}
}
break;
case FUNC_ANY_KEY:
{
uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; // 0 = Off, 1 = On, 2 = Toggle, 3 = Hold, 10,11,12,13 and 14 for Button Multipress
if ((state == 2 || state == 10) && ignore_any_key_time < millis()) {
PWMDimmerHandleButton((XdrvMailbox.payload & 0xFF) - 1, false);
}
}
break; break;
#ifdef USE_DEVICE_GROUPS #ifdef USE_DEVICE_GROUPS