#################################################################################################### ##### TX Ultimate Easy for ESPHome ##### ##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### #################################################################################################### ##### Purpose: ESPHome Core - Hardware - Relays ##### #################################################################################################### ##### 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: RELAY_MODE_TEXT_SWITCH: "Switch" RELAY_MODE_TEXT_LIGHT: "Light" RELAY_MODE_TEXT_NOT_USED: "Not in use" globals: - id: boot_initialization_relays type: bool restore_value: false initial_value: 'false' light: # These lights are used for the physical relays to be shown as lights - id: light_output_1 name: Light output 1 output: output_relay_1 platform: binary internal: true on_turn_on: then: - if: condition: - switch.is_off: sw_relay_1 then: - switch.turn_on: sw_relay_1 on_turn_off: then: - if: condition: - switch.is_on: sw_relay_1 then: - switch.turn_off: sw_relay_1 - id: light_output_2 name: Light output 2 output: output_relay_2 platform: binary internal: true on_turn_on: then: - if: condition: - switch.is_off: sw_relay_2 then: - switch.turn_on: sw_relay_2 on_turn_off: then: - if: condition: - switch.is_on: sw_relay_2 then: - switch.turn_off: sw_relay_2 - id: light_output_3 name: Light output 3 output: output_relay_3 platform: binary internal: true on_turn_on: then: - if: condition: - switch.is_off: sw_relay_3 then: - switch.turn_on: sw_relay_3 on_turn_off: then: - if: condition: - switch.is_on: sw_relay_3 then: - switch.turn_off: sw_relay_3 - id: light_output_4 name: Light output 4 output: output_relay_4 platform: binary internal: true on_turn_on: then: - if: condition: - switch.is_off: sw_relay_4 then: - switch.turn_on: sw_relay_4 on_turn_off: then: - if: condition: - switch.is_on: sw_relay_4 then: - switch.turn_off: sw_relay_4 output: - id: output_relay_1 platform: gpio pin: GPIO18 - id: output_relay_2 platform: gpio pin: GPIO17 - id: output_relay_3 platform: gpio pin: GPIO27 - id: output_relay_4 platform: gpio pin: GPIO23 script: - id: !extend boot_initialize then: - script.execute: boot_initialize_relays - id: boot_initialize_relays mode: restart then: - wait_until: condition: - lambda: return sl_tx_model_format->active_index().has_value(); - lambda: return sl_tx_model_gang->active_index().has_value(); - lambda: |- const bool is_model_us = sl_tx_model_format->active_index().has_value() and sl_tx_model_format->active_index().value() == 1; const uint8_t num_gangs = (sl_tx_model_gang->active_index().has_value()) ? (sl_tx_model_gang->active_index().value() + 1) : 0; if (num_gangs < 1 || num_gangs > 4) { ESP_LOGE("core_hw_relays", "Invalid number of gangs: %" PRIu8, num_gangs); return; } sl_relay_1_mode->set_internal(num_gangs < 1); sl_relay_1_light_mode_eu->set_internal(is_model_us or num_gangs < 1); sl_relay_1_light_mode_us->set_internal(!is_model_us or num_gangs < 1); sl_relay_2_mode->set_internal(num_gangs < 2); sl_relay_2_light_mode_eu->set_internal(is_model_us or num_gangs < 2); sl_relay_2_light_mode_us->set_internal(!is_model_us or num_gangs < 2); sl_relay_3_mode->set_internal(num_gangs < 3); sl_relay_3_light_mode_eu->set_internal(is_model_us or num_gangs < 3); sl_relay_3_light_mode_us->set_internal(!is_model_us or num_gangs < 3); sl_relay_4_mode->set_internal(num_gangs < 4); sl_relay_4_light_mode_eu->set_internal(is_model_us or num_gangs < 4); sl_relay_4_light_mode_us->set_internal(!is_model_us or num_gangs < 4); auto relay_mode_index = sl_relay_1_mode->active_index(); if (relay_mode_index.has_value()) { light_output_1->set_internal(false or relay_mode_index.value() != 1); sw_relay_1->set_internal(false or relay_mode_index.value() != 0); } relay_mode_index = sl_relay_2_mode->active_index(); if (relay_mode_index.has_value()) { light_output_2->set_internal(num_gangs < 2 or relay_mode_index.value() != 1); sw_relay_2->set_internal(num_gangs < 2 or relay_mode_index.value() != 0); } relay_mode_index = sl_relay_3_mode->active_index(); if (relay_mode_index.has_value()) { light_output_3->set_internal(num_gangs < 3 or relay_mode_index.value() != 1); sw_relay_3->set_internal(num_gangs < 3 or relay_mode_index.value() != 0); } relay_mode_index = sl_relay_4_mode->active_index(); if (relay_mode_index.has_value()) { light_output_4->set_internal(num_gangs < 4 or relay_mode_index.value() != 1); sw_relay_4->set_internal(num_gangs < 4 or relay_mode_index.value() != 0); } id(boot_initialization_relays) = true; - id: !extend button_click_event then: - lambda: |- // Handle only single clicks if (click_count != 1) return; // Ignore if other touch events are active if (bs_multi_touch->state || bs_swipe_left->state || bs_swipe_down->state || bs_swipe_right->state) { return; } // Toggle relay if corresponding button action is enabled switch (button_id) { case ${BUTTON_1_ID}: if (sl_button_1_action->state != "${RELAY_MODE_TEXT_NOT_USED}") sw_relay_1->toggle(); break; case ${BUTTON_2_ID}: if (sl_button_2_action->state != "${RELAY_MODE_TEXT_NOT_USED}") sw_relay_2->toggle(); break; case ${BUTTON_3_ID}: if (sl_button_3_action->state != "${RELAY_MODE_TEXT_NOT_USED}") sw_relay_3->toggle(); break; case ${BUTTON_4_ID}: if (sl_button_4_action->state != "${RELAY_MODE_TEXT_NOT_USED}") sw_relay_4->toggle(); break; } - id: show_relay_status mode: restart then: - script.wait: boot_initialize_relays - wait_until: condition: - lambda: return id(boot_initialization_relays); - lambda: |- const bool is_model_us = sl_tx_model_format->active_index().has_value() and sl_tx_model_format->active_index().value() == 1; const uint8_t num_gangs = (sl_tx_model_gang->active_index().has_value()) ? (sl_tx_model_gang->active_index().value() + 1) : 0; if (num_gangs < 1 || num_gangs > 4) { ESP_LOGE("core_hw_relays", "Invalid number of gangs: %" PRIu8, num_gangs); return; } for (uint8_t i = 0; i < num_gangs; i++) { bool relay_state = false; std::string light_mode; const std::string light_mode_group_1 = is_model_us ? "${LIGHT_MODE_LEFT_TEXT}" : "${LIGHT_MODE_BOTTOM_TEXT}"; const std::string light_mode_group_2 = is_model_us ? "${LIGHT_MODE_RIGHT_TEXT}" : "${LIGHT_MODE_TOP_TEXT}"; // Determine relay state and light mode switch (i) { case 0: relay_state = id(sw_relay_1).state; light_mode = is_model_us ? id(sl_relay_1_light_mode_us)->state : id(sl_relay_1_light_mode_eu)->state; break; case 1: relay_state = id(sw_relay_2).state; light_mode = is_model_us ? id(sl_relay_2_light_mode_us)->state : id(sl_relay_2_light_mode_eu)->state; break; case 2: relay_state = id(sw_relay_3).state; light_mode = is_model_us ? id(sl_relay_3_light_mode_us)->state : id(sl_relay_3_light_mode_eu)->state; break; case 3: relay_state = id(sw_relay_4).state; light_mode = is_model_us ? id(sl_relay_4_light_mode_us)->state : id(sl_relay_4_light_mode_eu)->state; break; } ESP_LOGV("core_hw_relays", "Relay %" PRIu8 " is %s", i + 1, relay_state ? "ON" : "OFF"); ESP_LOGV("core_hw_relays", "Light Mode for Relay %" PRIu8 ": %s", i + 1, light_mode.c_str()); // Use light_set_state for light updates if (relay_state) { if (light_mode == light_mode_group_1 || light_mode == "${LIGHT_MODE_BOTH_TEXT}") { light_set_state->execute(1, i, true); // Left/bottom light } if (light_mode == light_mode_group_2 || light_mode == "${LIGHT_MODE_BOTH_TEXT}") { light_set_state->execute(2, i, true); // Right/top light } } else { light_set_state->execute(1, i, false); // Turn off left/bottom light light_set_state->execute(2, i, false); // Turn off right/top light } } select: - &relay_select_mode_base id: sl_relay_1_mode name: Relay 1 display mode platform: template options: - "${RELAY_MODE_TEXT_SWITCH}" - "${RELAY_MODE_TEXT_LIGHT}" - "${RELAY_MODE_TEXT_NOT_USED}" initial_option: "${RELAY_MODE_TEXT_SWITCH}" optimistic: true restore_value: true internal: true entity_category: config disabled_by_default: false icon: mdi:dip-switch - id: sl_relay_2_mode name: Relay 2 display mode <<: *relay_select_mode_base - id: sl_relay_3_mode name: Relay 3 display mode <<: *relay_select_mode_base - id: sl_relay_4_mode name: Relay 4 display mode <<: *relay_select_mode_base switch: - id: sw_relay_1 name: Relay 1 output: output_relay_1 platform: output restore_mode: RESTORE_DEFAULT_OFF internal: true on_turn_on: then: - script.execute: show_relay_status - if: condition: - light.is_off: light_output_1 then: light.turn_on: light_output_1 on_turn_off: then: - script.execute: show_relay_status - if: condition: - light.is_on: light_output_1 then: - light.turn_off: light_output_1 - id: sw_relay_2 name: Relay 2 output: output_relay_2 platform: output restore_mode: RESTORE_DEFAULT_OFF internal: true on_turn_on: then: - script.execute: show_relay_status - if: condition: - light.is_off: light_output_2 then: light.turn_on: light_output_2 on_turn_off: then: - script.execute: show_relay_status - if: condition: - light.is_on: light_output_2 then: - light.turn_off: light_output_2 - id: sw_relay_3 name: Relay 3 output: output_relay_3 platform: output restore_mode: RESTORE_DEFAULT_OFF internal: true on_turn_on: then: - script.execute: show_relay_status - if: condition: - light.is_off: light_output_3 then: - light.turn_on: light_output_3 on_turn_off: then: - script.execute: show_relay_status - if: condition: - light.is_on: light_output_3 then: - light.turn_off: light_output_3 - id: sw_relay_4 name: Relay 4 output: output_relay_4 platform: output restore_mode: RESTORE_DEFAULT_OFF internal: true on_turn_on: then: - script.execute: show_relay_status - if: condition: - light.is_off: light_output_4 then: - light.turn_on: light_output_4 on_turn_off: then: - script.execute: show_relay_status - if: condition: - light.is_on: light_output_4 then: - light.turn_off: light_output_4 ...