Files
TX-Ultimate-Easy/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml
Edward Firmo 403cdce2b5 Expose relay-indicator LEDs
The lights will be available on Home Assistant, so users will be able to set it's color and brightness, then this will be used when the relay turn on-off as the indicator for the relay status.
Resolves #57
2024-12-24 23:31:50 +01:00

326 lines
11 KiB
YAML

####################################################################################################
##### TX Ultimate Easy for ESPHome #####
##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy #####
####################################################################################################
##### Purpose: ESPHome Core - Hardware - Buttons #####
####################################################################################################
##### Author: edwardtfn - https://github.com/edwardtfn - https://buymeacoffee.com/edwardfirmo #####
####################################################################################################
##### NOTE: #####
##### - Make changes ONLY if absolutely necessary and you have the required knowledge. #####
##### - For normal system use, modifications to this file are NOT required. #####
####################################################################################################
---
substitutions:
invalid_cooldown: 100ms
BUTTON_ACTION_NONE_TEXT: "None"
BUTTON_1_ACTION_TEXT: "Relay 1 (toggle)"
BUTTON_2_ACTION_TEXT: "Relay 2 (toggle)"
BUTTON_3_ACTION_TEXT: "Relay 3 (toggle)"
BUTTON_4_ACTION_TEXT: "Relay 4 (toggle)"
BUTTON_1_ACTION_FAILSAFE_TEXT: "Relay 1 (API failsafe only)"
BUTTON_2_ACTION_FAILSAFE_TEXT: "Relay 2 (API failsafe only)"
BUTTON_3_ACTION_FAILSAFE_TEXT: "Relay 3 (API failsafe only)"
BUTTON_4_ACTION_FAILSAFE_TEXT: "Relay 4 (API failsafe only)"
BUTTON_CLICK_MIN_LENGTH: '50' # The minimum duration the click should last, in msec
BUTTON_CLICK_MAX_LENGTH: '350' # The maximum duration the click should last, in msec
BUTTON_MULTI_CLICK_DELAY: '250' # The time to wait for another click, in msec
BUTTON_PRESS_TIMEOUT: '10000' # Ignore if button is pressed for longer than this time, in msec
BUTTON_LONG_PRESS_DELAY: '800' # The time to wait to consider a long press, in msec
# Button numbers constants
BUTTON_1_ID: '1'
BUTTON_2_ID: '2'
BUTTON_3_ID: '3'
BUTTON_4_ID: '4'
binary_sensor:
- &binary_sensor_button_base
id: bs_button_2
name: Button 2
icon: mdi:gesture-tap-box
platform: template
internal: true
- id: bs_button_3
name: Button 3
<<: *binary_sensor_button_base
- id: bs_button_4
name: Button 4
<<: *binary_sensor_button_base
- id: bs_button_1
name: Button 1
internal: false
<<: *binary_sensor_button_base
globals:
- id: button_press_button
type: uint8_t
restore_value: false
initial_value: '0'
- id: button_press_position
type: uint8_t
restore_value: false
initial_value: '0'
- id: button_press_start_time
type: uint32_t
restore_value: false
initial_value: '0'
- id: click_counter
type: uint8_t
restore_value: false
initial_value: '0'
script:
- id: !extend boot_initialize
then:
- script.execute: boot_initialize_buttons
- id: boot_initialize_buttons
mode: restart
then:
- lambda: |-
bs_button_1->publish_state(false);
bs_button_1->set_internal(id(gang_count) < 1);
sl_button_1_action->set_internal(id(gang_count) < 1);
bs_button_2->publish_state(false);
bs_button_2->set_internal(id(gang_count) < 2);
sl_button_2_action->set_internal(id(gang_count) < 2);
bs_button_3->publish_state(false);
bs_button_3->set_internal(id(gang_count) < 3);
sl_button_3_action->set_internal(id(gang_count) < 3);
bs_button_4->publish_state(false);
bs_button_4->set_internal(id(gang_count) < 4);
sl_button_4_action->set_internal(id(gang_count) < 4);
- id: button_action
mode: parallel
parameters:
button: uint8_t
action: string
count: uint8_t
then:
- homeassistant.event:
event: esphome.tx_ultimate_easy
data:
device_name: !lambda return tx_device_name->state.c_str();
firmware: ${version}
domain: touch
type: button
action: !lambda return action.c_str();
button_id: !lambda return button;
count: !lambda return count;
position: !lambda return id(button_press_position);
- lambda: |-
ESP_LOGI("core_hw_buttons", "Button %" PRIu8 " action: '%s'", button, action.c_str());
if (action == "click") {
switch (button) {
case ${BUTTON_1_ID}:
bs_button_1_click_event->publish_state(true);
break;
case ${BUTTON_2_ID}:
bs_button_2_click_event->publish_state(true);
break;
case ${BUTTON_3_ID}:
bs_button_3_click_event->publish_state(true);
break;
case ${BUTTON_4_ID}:
bs_button_4_click_event->publish_state(true);
break;
}
} else if (action == "double_click") {
switch (button) {
case ${BUTTON_1_ID}:
bs_button_1_double_click_event->publish_state(true);
break;
case ${BUTTON_2_ID}:
bs_button_2_double_click_event->publish_state(true);
break;
case ${BUTTON_3_ID}:
bs_button_3_double_click_event->publish_state(true);
break;
case ${BUTTON_4_ID}:
bs_button_4_double_click_event->publish_state(true);
break;
}
} else if (action == "long_press") {
switch (button) {
case ${BUTTON_1_ID}:
bs_button_1_long_press_event->publish_state(true);
break;
case ${BUTTON_2_ID}:
bs_button_2_long_press_event->publish_state(true);
break;
case ${BUTTON_3_ID}:
bs_button_3_long_press_event->publish_state(true);
break;
case ${BUTTON_4_ID}:
bs_button_4_long_press_event->publish_state(true);
break;
}
}
id(button_press_button) = 0;
id(button_press_position) = 0;
id(button_press_start_time) = 0;
id(click_counter) = 0;
buttons_release->execute();
- id: button_click_event
mode: restart
parameters:
button: uint8_t
click_count: uint8_t
then:
- delay:
milliseconds: ${BUTTON_MULTI_CLICK_DELAY}
- lambda: |-
std::string event_name;
if (click_count == 1) event_name = "click";
else if (click_count == 2) event_name = "double_click";
else event_name = "multiple_click";
button_action->execute(button, event_name.c_str(), click_count);
- id: buttons_release
mode: restart
then:
- lambda: |-
std::vector<binary_sensor::BinarySensor*> buttons = {
bs_button_1, bs_button_2, bs_button_3, bs_button_4
};
for (auto* button : buttons) {
if (button->state) {
button->publish_state(false);
}
}
- id: !extend touch_on_multi_touch_release
then:
- script.execute: buttons_release
- id: !extend touch_on_press
then:
- script.execute:
id: touch_on_press_buttons
button: !lambda return button;
position: !lambda return position;
- id: touch_on_press_buttons
mode: restart
parameters:
button: uint8_t
position: uint8_t
then:
- lambda: |-
id(button_press_start_time) = millis();
id(button_press_button) = button;
// Update counters
if (id(button_press_position) == position) {
id(click_counter)++;
} else {
id(click_counter) = 1;
id(button_press_position) = position;
}
// Update binary sensor
switch (button) {
case 1:
bs_button_1->publish_state(true);
break;
case 2:
bs_button_2->publish_state(true);
break;
case 3:
bs_button_3->publish_state(true);
break;
case 4:
bs_button_4->publish_state(true);
break;
}
- id: !extend touch_on_release
then:
- lambda: |-
uint32_t current_time = millis();
buttons_release->execute();
if (id(button_press_start_time) > 0 and
id(button_press_start_time) < current_time) {
uint32_t press_duration = current_time - id(button_press_start_time);
// Handle overflow (optional, since it's unlikely to happen here)
ESP_LOGI("core_hw_buttons", "Button press duration: %" PRIu32 " ms", press_duration);
if (press_duration < ${BUTTON_CLICK_MIN_LENGTH}) {
ESP_LOGW("core_hw_buttons", "Ignoring button press (too short)");
} else if (press_duration >= ${BUTTON_CLICK_MIN_LENGTH} and
press_duration <= ${BUTTON_CLICK_MAX_LENGTH}) { // Short/normal click
button_click_event->execute(id(button_press_button), id(click_counter));
} else if (press_duration >= ${BUTTON_LONG_PRESS_DELAY} and press_duration <= ${BUTTON_PRESS_TIMEOUT}) {
button_action->execute(id(button_press_button), "long_press", 1);
} else if (press_duration > ${BUTTON_PRESS_TIMEOUT}) { // Timeout or invalid
ESP_LOGW("core_hw_buttons", "Button press cancelled or timed out after ${BUTTON_PRESS_TIMEOUT} ms");
}
} else {
ESP_LOGW("core_hw_buttons", "Press event timestamp not recorded yet");
}
id(button_press_start_time) = 0;
- id: !extend touch_swipe_left
then:
- script.execute: buttons_release
- id: !extend touch_swipe_right
then:
- script.execute: buttons_release
select:
- &button_select_action_base
id: sl_button_1_action
name: Button 1 action
platform: template
options:
- "${BUTTON_ACTION_NONE_TEXT}"
- "${BUTTON_1_ACTION_TEXT}"
- "${BUTTON_1_ACTION_FAILSAFE_TEXT}"
initial_option: "${BUTTON_1_ACTION_TEXT}"
optimistic: true
restore_value: true
internal: true
entity_category: config
disabled_by_default: false
icon: mdi:dip-switch
- id: sl_button_2_action
name: Button 2 action
platform: template
options:
- "${BUTTON_ACTION_NONE_TEXT}"
- "${BUTTON_2_ACTION_TEXT}"
- "${BUTTON_2_ACTION_FAILSAFE_TEXT}"
initial_option: "${BUTTON_2_ACTION_TEXT}"
<<: *button_select_action_base
- id: sl_button_3_action
name: Button 3 action
platform: template
options:
- "${BUTTON_ACTION_NONE_TEXT}"
- "${BUTTON_3_ACTION_TEXT}"
- "${BUTTON_3_ACTION_FAILSAFE_TEXT}"
initial_option: "${BUTTON_3_ACTION_TEXT}"
<<: *button_select_action_base
- id: sl_button_4_action
name: Button 4 action
platform: template
options:
- "${BUTTON_ACTION_NONE_TEXT}"
- "${BUTTON_4_ACTION_TEXT}"
- "${BUTTON_4_ACTION_FAILSAFE_TEXT}"
initial_option: "${BUTTON_4_ACTION_TEXT}"
<<: *button_select_action_base
...