diff --git a/.github/workflows/validate_esphome.yml b/.github/workflows/validate_esphome.yml index 8224773..9aa4fb7 100644 --- a/.github/workflows/validate_esphome.yml +++ b/.github/workflows/validate_esphome.yml @@ -3,24 +3,6 @@ name: Validate ESPHome # yamllint disable-line rule:truthy on: - push: - paths: - - "*.yaml" - - "prebuilt/*.yaml" - - ".test/*.yaml" - - "*.h" - - "*.c" - - "*.cpp" - - "*.py" - pull_request: - paths: - - "*.yaml" - - "prebuilt/*.yaml" - - ".test/*.yaml" - - "*.h" - - "*.c" - - "*.cpp" - - "*.py" workflow_dispatch: concurrency: @@ -56,10 +38,10 @@ jobs: - name: Build core uses: esphome/build-action@main with: - yaml_file: ".test/esphome_ard_basic.yaml" + yaml-file: ".test/esphome_ard_basic.yaml" build_bluetooth_proxy_4: - name: Bluetooth Proxy (IDF v4) + name: Bluetooth Proxy (IDF) needs: build_basic runs-on: ubuntu-latest steps: @@ -67,10 +49,10 @@ jobs: - name: Build core uses: esphome/build-action@main with: - yaml_file: ".test/esphome_idf_bluetooth_proxy.yaml" + yaml-file: ".test/esphome_idf_bluetooth_proxy.yaml" - build_bluetooth_proxy_5: - name: Bluetooth Proxy (IDF v5) + build_bluetooth_proxy_53: + name: Bluetooth Proxy (IDF v5.3) needs: build_basic runs-on: ubuntu-latest steps: @@ -78,5 +60,5 @@ jobs: - name: Build core uses: esphome/build-action@main with: - yaml_file: ".test/esphome_idf5_bluetooth_proxy.yaml" + yaml-file: ".test/esphome_idf53_bluetooth_proxy.yaml" ... diff --git a/.github/workflows/validate_esphome_beta.yml b/.github/workflows/validate_esphome_beta.yml index 621e710..43d5f7e 100644 --- a/.github/workflows/validate_esphome_beta.yml +++ b/.github/workflows/validate_esphome_beta.yml @@ -3,6 +3,24 @@ name: Validate ESPHome (Beta) # yamllint disable-line rule:truthy on: + push: + paths: + - "*.yaml" + - "ESPHome/*.yaml" + - ".test/*.yaml" + - "*.h" + - "*.c" + - "*.cpp" + - "*.py" + pull_request: + paths: + - "*.yaml" + - "ESPHome/*.yaml" + - ".test/*.yaml" + - "*.h" + - "*.c" + - "*.cpp" + - "*.py" workflow_dispatch: concurrency: @@ -10,32 +28,9 @@ concurrency: cancel-in-progress: true jobs: - setup_dependencies: - name: Setup & Cache Dependencies - runs-on: ubuntu-latest - outputs: - cache-hit-arduino: ${{ steps.cache-arduino.outputs.cache-hit }} - - steps: - - name: Checkout repository - uses: actions/checkout@main - - - name: Cache Arduino Dependencies - id: cache-arduino - uses: actions/cache@main - with: - path: | - ~/.esphome/cache - ~/.platformio/packages - ~/.platformio/platforms - key: ${{ runner.os }}-arduino-${{ hashFiles('**/esphome_ard_basic.yaml') }} - restore-keys: | - ${{ runner.os }}-arduino- - code_scan: name: Code scan (YAML) runs-on: "ubuntu-latest" - needs: setup_dependencies steps: - name: Checkout Code uses: actions/checkout@main @@ -53,48 +48,38 @@ jobs: build_basic: name: Basic - needs: [code_scan, setup_dependencies] + needs: + - code_scan runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - include: - - id: ard - yaml_file: ".test/esphome_ard_basic.yaml" - cache-hit: ${{ needs.setup_dependencies.outputs.cache-hit-arduino }} - steps: - - name: Checkout repository - uses: actions/checkout@main - - - name: Firmware - if: steps.matrix.outputs.cache-hit != 'true' + - uses: actions/checkout@main + - name: Build core uses: esphome/build-action@main with: - yaml_file: ${{ matrix.yaml_file }} + yaml-file: ".test/esphome_ard_basic.yaml" version: beta - build_bluetooth_proxy: - name: Bluetooth Proxy + build_bluetooth_proxy_4: + name: Bluetooth Proxy (IDF) needs: build_basic runs-on: ubuntu-latest - strategy: - matrix: - include: - - id: idf_v4 - base: idf_v4 - yaml_file: ".test/esphome_idf_bluetooth_proxy.yaml" - - id: idf_v5 - base: idf_v5 - yaml_file: ".test/esphome_idf5_bluetooth_proxy.yaml" - steps: - - name: Checkout repository - uses: actions/checkout@main - - - name: Build Bluetooth Proxy Firmware + - uses: actions/checkout@main + - name: Build core uses: esphome/build-action@main with: - yaml_file: ${{ matrix.yaml_file }} + yaml-file: ".test/esphome_idf_bluetooth_proxy.yaml" + version: beta + + build_bluetooth_proxy_53: + name: Bluetooth Proxy (IDF v5.3) + needs: build_basic + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build core + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf53_bluetooth_proxy.yaml" version: beta ... diff --git a/.test/esphome_idf5_bluetooth_proxy.yaml b/.test/esphome_idf53_bluetooth_proxy.yaml similarity index 82% rename from .test/esphome_idf5_bluetooth_proxy.yaml rename to .test/esphome_idf53_bluetooth_proxy.yaml index 1ca452f..1e8643f 100644 --- a/.test/esphome_idf5_bluetooth_proxy.yaml +++ b/.test/esphome_idf53_bluetooth_proxy.yaml @@ -6,6 +6,6 @@ packages: esp32: framework: type: esp-idf - version: 5.0.2 - platform_version: 6.3.2 + version: 5.3.1 + platform_version: 6.9.0 ... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml index ad0ac37..331bda3 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml @@ -1,3 +1,15 @@ +#################################################################################################### +##### TX Ultimate Easy for ESPHome ##### +##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### +#################################################################################################### +##### Purpose: ESPHome Core - Add-on - BLE Proxy ##### +#################################################################################################### +##### 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. ##### +#################################################################################################### --- bluetooth_proxy: diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml index 31595ed..727af88 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml @@ -1,3 +1,15 @@ +#################################################################################################### +##### TX Ultimate Easy for ESPHome ##### +##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### +#################################################################################################### +##### Purpose: ESPHome Core ##### +#################################################################################################### +##### 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: name: tx-ultimate-easy @@ -6,178 +18,27 @@ substitutions: latitude: '0' longitude: '0' zone_home: 'zone.home' - default_transition_length: 500ms - invalid_cooldown: 100ms - version: '0.0.3' + version: '0.0.4' -api: - id: api_server - services: - - service: set_float - variables: - component: string - val: float - then: - - lambda: |- - if (!isnan(val)) { - if (component == "latitude") sun_entity->set_latitude(val); - else if (component == "longitude") sun_entity->set_longitude(val); - } + TX_MODEL_FORMAT_EU_TEXT: "EU (Square, T5-xC-86)" + TX_MODEL_FORMAT_US_TEXT: "US (Rectangle, T5-xC-120)" -binary_sensor: - - id: bs_vibrating - name: Vibrating - icon: mdi:vibrate - internal: false - platform: template - lambda: return sw_vibration_motor->state; + TX_MODEL_1_GANG_TEXT: "1 Gang" + TX_MODEL_2_GANG_TEXT: "2 Gang" + TX_MODEL_3_GANG_TEXT: "3 Gang" + TX_MODEL_4_GANG_TEXT: "4 Gang" - - id: bs_button_1 - name: Button 1 - icon: mdi:gesture-tap-box - internal: false - platform: template - on_click: - then: - - lambda: |- - if (sl_button_1_action->active_index().has_value() and - sl_button_1_action->active_index().value() == 1 and - !bs_multi_touch->state and - !bs_swipe_left->state and - !bs_swipe_down->state and - !bs_swipe_right->state) - sw_relay_1->toggle(); - send_event_to_ha->execute("bs_button_1", "click"); - on_double_click: - then: - - lambda: send_event_to_ha->execute("bs_button_1", "double_click"); - on_multi_click: - - timing: &long_click-timing - - ON for at least 0.8s - invalid_cooldown: ${invalid_cooldown} - then: - - lambda: send_event_to_ha->execute("bs_button_1", "long_click"); - - - id: bs_button_2 - name: Button 2 - icon: mdi:gesture-tap-box - internal: true - platform: template - on_click: - then: - - lambda: |- - if (sl_button_2_action->active_index().has_value() and - sl_button_2_action->active_index().value() == 1 and - !bs_multi_touch->state and - !bs_swipe_left->state and - !bs_swipe_down->state and - !bs_swipe_right->state) - sw_relay_2->toggle(); - send_event_to_ha->execute("bs_button_2", "click"); - on_double_click: - then: - - lambda: send_event_to_ha->execute("bs_button_2", "double_click"); - on_multi_click: - - timing: *long_click-timing - invalid_cooldown: ${invalid_cooldown} - then: - - lambda: send_event_to_ha->execute("bs_button_2", "long_click"); - - - id: bs_button_3 - name: Button 3 - icon: mdi:gesture-tap-box - internal: true - platform: template - on_click: - then: - - lambda: |- - if (sl_button_3_action->active_index().has_value() and - sl_button_3_action->active_index().value() == 1 and - !bs_multi_touch->state and - !bs_swipe_left->state and - !bs_swipe_down->state and - !bs_swipe_right->state) - sw_relay_3->toggle(); - send_event_to_ha->execute("bs_button_3", "click"); - on_double_click: - then: - - lambda: send_event_to_ha->execute("bs_button_3", "double_click"); - on_multi_click: - - timing: *long_click-timing - invalid_cooldown: ${invalid_cooldown} - then: - - lambda: send_event_to_ha->execute("bs_button_3", "long_click"); - - - id: bs_button_4 - name: Button 4 - icon: mdi:gesture-tap-box - internal: true - platform: template - on_click: - then: - - lambda: |- - if (sl_button_4_action->active_index().has_value() and - sl_button_4_action->active_index().value() == 1 and - !bs_multi_touch->state and - !bs_swipe_left->state and - !bs_swipe_down->state and - !bs_swipe_right->state) - sw_relay_4->toggle(); - send_event_to_ha->execute("bs_button_4", "click"); - on_double_click: - then: - - lambda: send_event_to_ha->execute("bs_button_4", "double_click"); - on_multi_click: - - timing: *long_click-timing - invalid_cooldown: ${invalid_cooldown} - then: - - lambda: send_event_to_ha->execute("bs_button_4", "long_click"); - - - id: bs_multi_touch - name: Multi-touch - icon: mdi:gesture-two-tap - internal: false - platform: template - on_click: - then: - - lambda: send_event_to_ha->execute("multi_touch", "multi_touch"); - - - id: bs_swipe_left - name: Swipe left - icon: mdi:gesture-swipe-left - internal: true - platform: template - on_click: - then: - - lambda: send_event_to_ha->execute("swipe", "left"); - - - id: bs_swipe_right - name: Swipe right - icon: mdi:gesture-swipe-right - internal: true - platform: template - on_click: - then: - - lambda: send_event_to_ha->execute("swipe", "right"); - - - id: bs_swipe_up - name: Swipe up - icon: mdi:gesture-swipe-up - internal: true - platform: template - on_click: - then: - - lambda: send_event_to_ha->execute("swipe", "up"); - - - id: bs_swipe_down - name: Swipe down - icon: mdi:gesture-swipe-down - internal: true - platform: template - on_click: - then: - - lambda: send_event_to_ha->execute("swipe", "down"); +packages: + # yamllint disable rule:colons + core_api: !include TX-Ultimate-Easy-ESPHome_core_api.yaml + core_hw_buttons: !include TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml + core_hw_leds: !include TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml + core_hw_relays: !include TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml + core_hw_speaker: !include TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml + core_hw_touch: !include TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml + core_hw_vibration: !include TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml + # yamllint enable rule:colons button: - id: bt_restart @@ -185,15 +46,6 @@ button: internal: false platform: restart - - id: bt_vibrate - name: Vibrate - icon: mdi:vibrate - internal: false - platform: template - on_press: - then: - - script.execute: vibrate - captive_portal: id: ap_captive_portal @@ -204,1409 +56,76 @@ esp32: esphome: name: ${name} friendly_name: ${friendly_name} + comment: TX Ultimate Easy platformio_options: build_flags: - -D TX_ULTIMATE_EASY_CORE + on_boot: - priority: 700 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 us_model = 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; - bs_button_1->publish_state(false); - bs_button_1->set_internal(num_gangs < 1); - sl_button_1_action->set_internal(num_gangs < 1); - bs_button_2->publish_state(false); - bs_button_2->set_internal(num_gangs < 2); - sl_button_2_action->set_internal(num_gangs < 2); - bs_button_3->publish_state(false); - bs_button_3->set_internal(num_gangs < 3); - sl_button_3_action->set_internal(num_gangs < 3); - bs_button_4->publish_state(false); - bs_button_4->set_internal(num_gangs < 4); - sl_button_4_action->set_internal(num_gangs < 4); - bs_multi_touch->publish_state(false); - bs_swipe_down->publish_state(false); - bs_swipe_down->set_internal(!us_model); - bs_swipe_left->publish_state(false); - bs_swipe_left->set_internal(us_model); - bs_swipe_right->publish_state(false); - bs_swipe_right->set_internal(us_model); - bs_swipe_up->publish_state(false); - bs_swipe_up->set_internal(!us_model); - light_28->set_internal(!us_model); - light_29->set_internal(!us_model); - light_30->set_internal(!us_model); - light_31->set_internal(!us_model); - light_eu->set_internal(us_model); - light_eu_bottom->set_internal(us_model); - light_eu_left->set_internal(us_model); - light_eu_right->set_internal(us_model); - light_eu_top->set_internal(us_model); - light_us->set_internal(!us_model); - light_us_bottom->set_internal(!us_model); - light_us_left->set_internal(!us_model); - light_us_right->set_internal(!us_model); - light_us_top->set_internal(!us_model); - sl_relay_1_mode->set_internal(num_gangs < 1); - sl_relay_1_light_mode_eu->set_internal(us_model or num_gangs < 1); - sl_relay_1_light_mode_us->set_internal(!us_model or num_gangs < 1); - sl_relay_2_mode->set_internal(num_gangs < 2); - sl_relay_2_light_mode_eu->set_internal(us_model or num_gangs < 2); - sl_relay_2_light_mode_us->set_internal(!us_model or num_gangs < 2); - sl_relay_3_mode->set_internal(num_gangs < 3); - sl_relay_3_light_mode_eu->set_internal(us_model or num_gangs < 3); - sl_relay_3_light_mode_us->set_internal(!us_model or num_gangs < 3); - sl_relay_4_mode->set_internal(num_gangs < 4); - sl_relay_4_light_mode_eu->set_internal(us_model or num_gangs < 4); - sl_relay_4_light_mode_us->set_internal(!us_model or num_gangs < 4); - auto relay_mode_index = sl_relay_1_mode->active_index(); - if (relay_mode_index.has_value()) { - ligth_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()) { - ligth_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()) { - ligth_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()) { - ligth_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); - } - switch (num_gangs) { - case 1: // 1 Gang - if (us_model) { - id(gb_lights_1) = { light_us_rl_1_1_left }; - id(gb_lights_2) = { light_us_rl_1_1_right }; - } else { - id(gb_lights_1) = { light_eu_rl_1_1_bottom }; - id(gb_lights_2) = { light_eu_rl_1_1_top }; - } - break; - case 2: // 2 Gang - if (us_model) { - id(gb_lights_1) = { light_us_rl_1_2_left, light_us_rl_2_2_left }; - id(gb_lights_2) = { light_us_rl_1_2_right, light_us_rl_2_2_right }; - } else { - id(gb_lights_1) = { light_eu_rl_1_2_bottom, light_eu_rl_2_2_bottom }; - id(gb_lights_2) = { light_eu_rl_1_2_top, light_eu_rl_2_2_top }; - } - break; - case 3: // 3 Gang - if (us_model) { - id(gb_lights_1) = { light_us_rl_1_3_left, light_us_rl_2_3_left, light_us_rl_3_3_left }; - id(gb_lights_2) = { light_us_rl_1_3_right, light_us_rl_2_3_right, light_us_rl_3_3_right }; - } else { - id(gb_lights_1) = { light_eu_rl_1_3_bottom, light_eu_rl_2_3_bottom, light_eu_rl_3_3_bottom }; - id(gb_lights_2) = { light_eu_rl_1_3_top, light_eu_rl_2_3_top, light_eu_rl_3_3_top }; - } - break; - case 4: // 3 Gang - if (us_model) { - id(gb_lights_1) = { light_us_rl_1_4_left, light_us_rl_2_4_left, light_us_rl_3_4_left, light_us_rl_4_4_left }; - id(gb_lights_2) = { light_us_rl_1_4_right, light_us_rl_2_4_right, light_us_rl_3_4_right, light_us_rl_4_4_right }; - } else { - id(gb_lights_1) = { light_eu_rl_1_4_bottom, light_eu_rl_2_4_bottom, light_eu_rl_3_4_bottom, light_eu_rl_4_4_bottom }; - id(gb_lights_2) = { light_eu_rl_1_4_top, light_eu_rl_2_4_top, light_eu_rl_3_4_top, light_eu_rl_4_4_top }; - } - break; - } + - script.execute: boot_initialize - priority: 600 # This is where most sensors are set up. then: - - lambda: |- - tx_fw_version->publish_state("${version}"); - tx_device_name->publish_state("${name}"); + - script.execute: boot_sequence + - priority: -100 # At this priority, pretty much everything should already be initialized. then: - - lambda: send_event_to_ha->execute("boot", "done"); - -external_components: - - source: github://edwardtfn/TX-Ultimate-Easy@dev # Change this before releasing - components: - - tx_ultimate_easy - -globals: - - id: gb_lights_1 - type: std::vector - restore_value: false - - id: gb_lights_2 - type: std::vector - restore_value: false - -i2s_audio: - id: if_i2s_audio - i2s_bclk_pin: GPIO2 - i2s_lrclk_pin: GPIO4 + - script.execute: boot_done improv_serial: id: serial_improv -light: - - id: ligth_output_1 - name: Light output 1 - internal: true - platform: binary - output: output_relay_1 - - id: ligth_output_2 - name: Light output 2 - internal: true - platform: binary - output: output_relay_2 - - id: ligth_output_3 - name: Light output 3 - internal: true - platform: binary - output: output_relay_3 - - id: ligth_output_4 - name: Light output 4 - internal: true - platform: binary - output: output_relay_4 - - - id: light_full - name: Light - All - internal: true - platform: neopixelbus - type: GRB - variant: WS2811 - num_leds: 32 - pin: GPIO13 - - - id: light_eu - name: Light - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 0 - to: 28 - effects: &light_effects_full - - addressable_rainbow: - - addressable_rainbow: - name: "Rainbow - Fast" - speed: 50 - - pulse: - - pulse: - name: "Pulse - Fast" - transition_length: 0.5s - update_interval: 0.5s - - pulse: - name: "Pulse - Slow" - update_interval: 2s - - addressable_scan: - - addressable_scan: - name: Scan Effect With Custom Values - move_interval: 100ms - scan_width: 3 - - addressable_twinkle: - - addressable_twinkle: - name: Twinkle Effect With Custom Values - twinkle_probability: 5% - progress_interval: 4ms - - addressable_random_twinkle: - - addressable_random_twinkle: - name: Random Twinkle Effect With Custom Values - twinkle_probability: 20% - progress_interval: 32ms - - addressable_fireworks: - - addressable_fireworks: - name: Fireworks Effect With Custom Values - update_interval: 32ms - spark_probability: 10% - use_random_color: false - fade_out_rate: 120 - - addressable_flicker: - - addressable_flicker: - name: Flicker Effect With Custom Values - update_interval: 16ms - intensity: 5% - - random: - - id: light_us - name: Light - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 0 - to: 31 - effects: *light_effects_full - - - id: light_eu_bottom - name: Light - Bottom - internal: true - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 6 - to: 12 - reversed: true - effects: *light_effects_full - - id: light_eu_left - name: Light - Left - internal: true - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 13 - to: 19 - reversed: true - effects: *light_effects_full - - id: light_eu_right - name: Light - Right - internal: true - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 27 - to: 27 - reversed: false - - id: light_full - from: 0 - to: 5 - reversed: false - effects: *light_effects_full - - id: light_eu_top - name: Light - Top - internal: true - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 20 - to: 26 - reversed: false - effects: *light_effects_full - - id: light_us_bottom - name: Light - Bottom - internal: true - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 10 - to: 15 - reversed: true - effects: *light_effects_full - - id: light_us_left - name: Light - Left - internal: true - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 15 - to: 24 - reversed: true - effects: *light_effects_full - - id: light_us_right - name: Light - Right - internal: true - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 31 - to: 31 - reversed: false - - id: light_full - from: 0 - to: 8 - reversed: false - effects: *light_effects_full - - id: light_us_top - name: Light - Top - internal: true - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 25 - to: 30 - reversed: false - effects: *light_effects_full - - - id: light_00 - name: Light - LED 00 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 0 - to: 0 - - id: light_01 - name: Light - LED 01 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 1 - to: 1 - - id: light_02 - name: Light - LED 02 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 2 - to: 2 - - id: light_03 - name: Light - LED 03 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 3 - to: 3 - - id: light_04 - name: Light - LED 04 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 4 - to: 4 - - id: light_05 - name: Light - LED 05 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 5 - to: 5 - - id: light_06 - name: Light - LED 06 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 6 - to: 6 - - id: light_07 - name: Light - LED 07 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 7 - to: 7 - - id: light_08 - name: Light - LED 08 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 8 - to: 8 - - id: light_09 - name: Light - LED 09 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 9 - to: 9 - - id: light_10 - name: Light - LED 10 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 10 - to: 10 - - id: light_11 - name: Light - LED 11 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 11 - to: 11 - - id: light_12 - name: Light - LED 12 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 12 - to: 12 - - id: light_13 - name: Light - LED 13 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 13 - to: 13 - - id: light_14 - name: Light - LED 14 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 14 - to: 14 - - id: light_15 - name: Light - LED 15 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 15 - to: 15 - - id: light_16 - name: Light - LED 16 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 16 - to: 16 - - id: light_17 - name: Light - LED 17 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 17 - to: 17 - - id: light_18 - name: Light - LED 18 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 18 - to: 18 - - id: light_19 - name: Light - LED 19 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 19 - to: 19 - - id: light_20 - name: Light - LED 20 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 20 - to: 20 - - id: light_21 - name: Light - LED 21 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 21 - to: 21 - - id: light_22 - name: Light - LED 22 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 22 - to: 22 - - id: light_23 - name: Light - LED 23 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 23 - to: 23 - - id: light_24 - name: Light - LED 24 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 24 - to: 24 - - id: light_25 - name: Light - LED 25 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 25 - to: 25 - - id: light_26 - name: Light - LED 26 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 26 - to: 26 - - id: light_27 - name: Light - LED 27 - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 27 - to: 27 - - id: light_28 - name: Light - LED 28 - internal: true - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 28 - to: 28 - - id: light_29 - name: Light - LED 29 - internal: true - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 29 - to: 29 - - id: light_30 - name: Light - LED 30 - internal: true - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 30 - to: 30 - - id: light_31 - name: Light - LED 31 - internal: true - disabled_by_default: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 31 - to: 31 - - - id: light_eu_rl_1_1_bottom - name: Light - Relay 1 of 1 (bottom) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 9 - to: 9 - - id: light_eu_rl_1_1_top - name: Light - Relay 1 of 1 (top) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 23 - to: 23 - - id: light_eu_rl_1_2_bottom - name: Light - Relay 1 of 2 (bottom) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 11 - to: 11 - - id: light_eu_rl_1_2_top - name: Light - Relay 1 of 2 (top) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 21 - to: 21 - - id: light_eu_rl_2_2_bottom - name: Light - Relay 2 of 2 (bottom) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 7 - to: 7 - - id: light_eu_rl_2_2_top - name: Light - Relay 2 of 2 (top) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 25 - to: 25 - - id: light_eu_rl_1_3_bottom - name: Light - Relay 1 of 3 (bottom) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 12 - to: 12 - - id: light_eu_rl_1_3_top - name: Light - Relay 1 of 3 (top) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 20 - to: 20 - - id: light_eu_rl_2_3_bottom - name: Light - Relay 2 of 3 (bottom) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 9 - to: 9 - - id: light_eu_rl_2_3_top - name: Light - Relay 2 of 3 (top) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 23 - to: 23 - - id: light_eu_rl_3_3_bottom - name: Light - Relay 3 of 3 (bottom) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 6 - to: 6 - - id: light_eu_rl_3_3_top - name: Light - Relay 3 of 3 (top) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 26 - to: 26 - - id: light_eu_rl_1_4_bottom - name: Light - Relay 1 of 4 (bottom) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 12 - to: 12 - - id: light_eu_rl_1_4_top - name: Light - Relay 1 of 4 (top) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 20 - to: 20 - - id: light_eu_rl_2_4_bottom - name: Light - Relay 2 of 4 (bottom) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 10 - to: 10 - - id: light_eu_rl_2_4_top - name: Light - Relay 2 of 4 (top) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 22 - to: 22 - - id: light_eu_rl_3_4_bottom - name: Light - Relay 3 of 4 (bottom) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 8 - to: 8 - - id: light_eu_rl_3_4_top - name: Light - Relay 3 of 4 (top) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 24 - to: 24 - - id: light_eu_rl_4_4_bottom - name: Light - Relay 4 of 4 (bottom) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 6 - to: 6 - - id: light_eu_rl_4_4_top - name: Light - Relay 4 of 4 (top) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 26 - to: 26 - - id: light_us_rl_1_1_left - name: Light - Relay 1 of 1 (left) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 15 - to: 24 - - id: light_us_rl_1_1_right - name: Light - Relay 1 of 1 (right) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 31 - to: 31 - - id: light_full - from: 0 - to: 8 - - id: light_us_rl_1_2_left - name: Light - Relay 1 of 2 (left) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 20 - to: 24 - - id: light_us_rl_1_2_right - name: Light - Relay 1 of 2 (right) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 31 - to: 31 - - id: light_full - from: 0 - to: 3 - - id: light_us_rl_2_2_left - name: Light - Relay 2 of 2 (left) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 15 - to: 19 - - id: light_us_rl_2_2_right - name: Light - Relay 2 of 2 (right) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 4 - to: 8 - - id: light_us_rl_1_3_left - name: Light - Relay 1 of 3 (left) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 22 - to: 23 - - id: light_us_rl_1_3_right - name: Light - Relay 1 of 3 (right) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 0 - to: 1 - - id: light_us_rl_2_3_left - name: Light - Relay 2 of 3 (left) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 19 - to: 20 - - id: light_us_rl_2_3_right - name: Light - Relay 2 of 3 (right) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 3 - to: 4 - - id: light_us_rl_3_3_left - name: Light - Relay 3 of 3 (left) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 17 - to: 18 - - id: light_us_rl_3_3_right - name: Light - Relay 3 of 3 (right) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 6 - to: 7 - - id: light_us_rl_1_4_left - name: Light - Relay 1 of 4 (left) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 12 - to: 12 - - id: light_us_rl_1_4_right - name: Light - Relay 1 of 4 (right) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 31 - to: 31 - - id: light_us_rl_2_4_left - name: Light - Relay 2 of 4 (left) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 24 - to: 24 - - id: light_us_rl_2_4_right - name: Light - Relay 2 of 4 (right) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 2 - to: 2 - - id: light_us_rl_3_4_left - name: Light - Relay 3 of 4 (left) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 21 - to: 21 - - id: light_us_rl_3_4_right - name: Light - Relay 3 of 4 (right) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 4 - to: 4 - - id: light_us_rl_4_4_left - name: Light - Relay 4 of 4 (left) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 19 - to: 19 - - id: light_us_rl_4_4_right - name: Light - Relay 4 of 4 (right) - internal: true - platform: partition - default_transition_length: ${default_transition_length} - segments: - - id: light_full - from: 7 - to: 7 - logger: - -media_player: - - id: mp_speaker - name: Speaker - platform: i2s_audio - i2s_dout_pin: GPIO15 - i2s_audio_id: if_i2s_audio - i2s_comm_fmt: lsb - dac_type: external - mode: mono - internal: false - -number: - - id: nr_vibrating_duration - name: Vibrate duration - icon: mdi:vibrate - unit_of_measurement: ms - # mode: box - internal: false - entity_category: config - platform: template - min_value: 1 - max_value: 500 - step: 1 - initial_value: 15 - optimistic: true - restore_value: true - - - id: nr_touch_duration - name: Touch duration - icon: mdi:timer-cog-outline - unit_of_measurement: ms - # mode: box - internal: false - entity_category: config - platform: template - min_value: 10 - max_value: 1500 - step: 1 - initial_value: 250 - optimistic: true - restore_value: true + level: INFO ota: platform: esphome -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 - psram: script: - - id: release_buttons + - id: boot_done + mode: restart + then: + - script.execute: + id: send_event_to_ha + component: boot + event: done + + - id: boot_initialize + mode: restart + then: + # Extended by: + # - HW Buttons + # - HW Relays + # - HW Touch + - script.execute: + id: send_event_to_ha + component: boot + event: start + + - id: boot_sequence + mode: restart + then: + - script.execute: publish_device_info + + - id: publish_device_info mode: restart then: - lambda: |- - if (bs_button_1->state) bs_button_1->publish_state(false); - if (bs_button_2->state) bs_button_2->publish_state(false); - if (bs_button_3->state) bs_button_3->publish_state(false); - if (bs_button_4->state) bs_button_4->publish_state(false); - - - id: send_event_to_ha - mode: queued - parameters: - component: string - event: string - then: - - lambda: |- - esphome::api::CustomAPIDevice ha_event; - ha_event.fire_homeassistant_event("esphome.tx_ultimate_easy", - { - {"device_name", tx_device_name->state.c_str()}, - {"firmware", "${version}"}, - {"component", component}, - {"event", event}, - }); - - - id: show_relay_status - mode: restart - then: - - lambda: |- - return; - show_relay_status->stop(); - auto model_format = sl_tx_model_format->active_index(); - std::vector relay_modes; - - if (model_format.has_value() and model_format.value() == 0) { - relay_modes = {sl_relay_1_light_mode_eu, sl_relay_2_light_mode_eu, sl_relay_3_light_mode_eu, sl_relay_4_light_mode_eu}; - } else { - relay_modes = {sl_relay_1_light_mode_us, sl_relay_2_light_mode_us, sl_relay_3_light_mode_us, sl_relay_4_light_mode_us}; - } - - std::vector switches = {sw_relay_1, sw_relay_2, sw_relay_3, sw_relay_4}; - for (int i = 0; i < relay_modes.size(); ++i) { - auto light_index = relay_modes[i]->active_index(); - if (light_index.has_value()) { - uint8_t light_idx = light_index.value(); - bool switch_state = switches[i]->state; - if (light_idx == 1 || light_idx == 3) { - if (switch_state) - id(gb_lights_1)[i]->turn_on().perform(); - else - id(gb_lights_1)[i]->turn_off().perform(); - } - if (light_idx == 2 || light_idx == 3) { - if (switch_state) - id(gb_lights_2)[i]->turn_on().perform(); - else - id(gb_lights_2)[i]->turn_off().perform(); - } - } - } - - - id: vibrate - mode: restart - then: - - switch.turn_on: sw_vibration_motor - - delay: !lambda return nr_vibrating_duration->state; - - switch.turn_off: sw_vibration_motor + tx_fw_version->publish_state("${version}"); + tx_device_name->publish_state(App.get_name().c_str()); select: - - id: sl_button_1_action - name: Button 1 action - platform: template - options: - - "None" - - "Relay 1 (toggle)" - 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: - - "None" - - "Relay 2 (toggle)" - optimistic: true - restore_value: true - internal: true - entity_category: config - disabled_by_default: false - icon: mdi:dip-switch - - - id: sl_button_3_action - name: Button 3 action - platform: template - options: - - "None" - - "Relay 3 (toggle)" - optimistic: true - restore_value: true - internal: true - entity_category: config - disabled_by_default: false - icon: mdi:dip-switch - - - id: sl_button_4_action - name: Button 4 action - platform: template - options: - - "None" - - "Relay 4 (toggle)" - optimistic: true - restore_value: true - internal: true - entity_category: config - disabled_by_default: false - icon: mdi:dip-switch - - - id: sl_relay_1_mode - name: Relay 1 mode - platform: template - options: - - "Relay" - - "Light" - - "Not in use" - 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 mode - platform: template - options: - - "Relay" - - "Light" - - "Not in use" - optimistic: true - restore_value: true - internal: true - entity_category: config - disabled_by_default: false - icon: mdi:dip-switch - - - id: sl_relay_3_mode - name: Relay 3 mode - platform: template - options: - - "Relay" - - "Light" - - "Not in use" - optimistic: true - restore_value: true - internal: true - entity_category: config - disabled_by_default: false - icon: mdi:dip-switch - - - id: sl_relay_4_mode - name: Relay 4 mode - platform: template - options: - - "Relay" - - "Light" - - "Not in use" - optimistic: true - restore_value: true - internal: true - entity_category: config - disabled_by_default: false - icon: mdi:dip-switch - - - id: sl_relay_1_light_mode_eu - name: Relay 1 light mode - platform: template - options: - - "Disabled" - - "Bottom" - - "Top" - - "Both" - initial_option: "Bottom" - optimistic: true - restore_value: true - internal: true - entity_category: config - disabled_by_default: false - icon: mdi:dots-square - - - id: sl_relay_2_light_mode_eu - name: Relay 2 light mode - platform: template - options: - - "Disabled" - - "Bottom" - - "Top" - - "Both" - initial_option: "Bottom" - optimistic: true - restore_value: true - internal: true - entity_category: config - disabled_by_default: false - icon: mdi:dots-square - - - id: sl_relay_3_light_mode_eu - name: Relay 3 light mode - platform: template - options: - - "Disabled" - - "Bottom" - - "Top" - - "Both" - initial_option: "Bottom" - optimistic: true - restore_value: true - internal: true - entity_category: config - disabled_by_default: false - icon: mdi:dots-square - - - id: sl_relay_4_light_mode_eu - name: Relay 4 light mode - platform: template - options: - - "Disabled" - - "Bottom" - - "Top" - - "Both" - initial_option: "Bottom" - optimistic: true - restore_value: true - internal: true - entity_category: config - disabled_by_default: false - icon: mdi:dots-square - - - id: sl_relay_1_light_mode_us - name: Relay 1 light mode - platform: template - options: - - "Disabled" - - "Left" - - "Right" - - "Both" - initial_option: "Right" - optimistic: true - restore_value: true - internal: true - entity_category: config - disabled_by_default: false - icon: mdi:dots-square - - - id: sl_relay_2_light_mode_us - name: Relay 2 light mode - platform: template - options: - - "Disabled" - - "Left" - - "Right" - - "Both" - initial_option: "Right" - optimistic: true - restore_value: true - internal: true - entity_category: config - disabled_by_default: false - icon: mdi:dots-square - - - id: sl_relay_3_light_mode_us - name: Relay 3 light mode - platform: template - options: - - "Disabled" - - "Left" - - "Right" - - "Both" - initial_option: "Right" - optimistic: true - restore_value: true - internal: true - entity_category: config - disabled_by_default: false - icon: mdi:dots-square - - - id: sl_relay_4_light_mode_us - name: Relay 4 light mode - platform: template - options: - - "Disabled" - - "Left" - - "Right" - - "Both" - initial_option: "Right" - optimistic: true - restore_value: true - internal: true - entity_category: config - disabled_by_default: false - icon: mdi:dots-square - - - id: sl_touch_vibration_feedback - name: Touch - Vibration feedback - platform: template - options: - - "Disabled" - - "On press" - - "On release" - - "Always" - initial_option: "Disabled" - optimistic: true - restore_value: true - internal: false - entity_category: config - disabled_by_default: false - icon: mdi:vibrate - - id: sl_tx_model_format name: Model (Format) platform: template options: - - "EU (Square, T5-xC-86)" - - "US (Rectangle, T5-xC-120)" - initial_option: "EU (Square, T5-xC-86)" + - "${TX_MODEL_FORMAT_EU_TEXT}" + - "${TX_MODEL_FORMAT_US_TEXT}" + initial_option: "${TX_MODEL_FORMAT_EU_TEXT}" optimistic: true restore_value: true internal: false @@ -1618,11 +137,11 @@ select: name: Model (Gang) platform: template options: - - "1 Gang" - - "2 Gang" - - "3 Gang" - - "4 Gang" - initial_option: "1 Gang" + - "${TX_MODEL_1_GANG_TEXT}" + - "${TX_MODEL_2_GANG_TEXT}" + - "${TX_MODEL_3_GANG_TEXT}" + - "${TX_MODEL_4_GANG_TEXT}" + initial_option: "${TX_MODEL_1_GANG_TEXT}" optimistic: true restore_value: true internal: false @@ -1630,110 +149,6 @@ select: disabled_by_default: false icon: mdi:dip-switch -sensor: - - id: sun_elevation - name: Sun Elevation - platform: sun - type: elevation - internal: true - - - id: zone_home_latitude - platform: homeassistant - entity_id: ${zone_home} - attribute: latitude - internal: false - on_value: - - lambda: if (!isnan(x)) sun_entity->set_latitude(x); - - - id: zone_home_longitude - platform: homeassistant - entity_id: ${zone_home} - attribute: longitude - internal: false - on_value: - - lambda: if (!isnan(x)) sun_entity->set_longitude(x); - -sun: - id: sun_entity - latitude: ${latitude} - longitude: ${longitude} - -switch: - - id: sw_relay_1 - name: Relay 1 - platform: output - output: output_relay_1 - restore_mode: RESTORE_DEFAULT_OFF - internal: true - on_turn_on: - then: - - script.execute: show_relay_status - on_turn_off: - then: - - script.execute: show_relay_status - - - id: sw_relay_2 - name: Relay 2 - platform: output - output: output_relay_2 - restore_mode: RESTORE_DEFAULT_OFF - internal: true - on_turn_on: - then: - - script.execute: show_relay_status - on_turn_off: - then: - - script.execute: show_relay_status - - - id: sw_relay_3 - name: Relay 3 - platform: output - output: output_relay_3 - restore_mode: RESTORE_DEFAULT_OFF - internal: true - on_turn_on: - then: - - script.execute: show_relay_status - on_turn_off: - then: - - script.execute: show_relay_status - - - id: sw_relay_4 - name: Relay 4 - platform: output - output: output_relay_4 - restore_mode: RESTORE_DEFAULT_OFF - internal: true - on_turn_on: - then: - - script.execute: show_relay_status - on_turn_off: - then: - - script.execute: show_relay_status - - - id: sw_touch_panel_power - name: Touch panel - Power - platform: gpio - pin: - number: GPIO5 - inverted: true - restore_mode: ALWAYS_ON - internal: false - entity_category: config - - - id: sw_vibration_motor - name: Vibration motor - platform: gpio - pin: GPIO21 - restore_mode: ALWAYS_OFF - internal: true - on_turn_on: - then: - - lambda: bs_vibrating->publish_state(true); - on_turn_off: - then: - - lambda: bs_vibrating->publish_state(false); - text_sensor: - id: tx_fw_version name: Firmware version @@ -1752,6 +167,7 @@ text_sensor: entity_category: diagnostic internal: false disabled_by_default: false + update_interval: never lambda: |- return {"${name}"}; filters: @@ -1774,82 +190,6 @@ time: - id: time_source platform: homeassistant -tx_ultimate_easy: - id: tx_ultimate - uart: uart_touch - - on_multi_touch_release: - - lambda: |- - if (sl_touch_vibration_feedback->state == "On press" or sl_touch_vibration_feedback->state == "Always") - vibrate->execute(); - bs_multi_touch->publish_state(true); - release_buttons->execute(); - - delay: !lambda return nr_touch_duration->state; - - lambda: bs_multi_touch->publish_state(false); - - on_press: - - lambda: |- - if (sl_touch_vibration_feedback->state == "On press" or sl_touch_vibration_feedback->state == "Always") - vibrate->execute(); - auto model_index = sl_tx_model_gang->active_index(); - if (model_index.has_value()) { - uint8_t model_idx = model_index.value() + 1; - switch (model_idx) { - case 1: // 1 Gang - bs_button_1->publish_state(true); - break; - case 2: // 2 Gang - if (touch.x <= 5) bs_button_1->publish_state(true); - else bs_button_2->publish_state(true); - break; - case 3: // 3 Gang - if (touch.x <= 3) bs_button_1->publish_state(true); - else if (touch.x <= 7) bs_button_2->publish_state(true); - else bs_button_3->publish_state(true); - break; - case 4: // 4 Gang - if (touch.x <= 2) bs_button_1->publish_state(true); - else if (touch.x <= 5) bs_button_2->publish_state(true); - else if (touch.x <= 8) bs_button_3->publish_state(true); - else bs_button_4->publish_state(true); - break; - } - } - - on_release: - - lambda: |- - if (sl_touch_vibration_feedback->state == "On release" or sl_touch_vibration_feedback->state == "Always") - vibrate->execute(); - release_buttons->execute(); - if (bs_swipe_left->state) bs_swipe_left->publish_state(false); - if (bs_swipe_right->state) bs_swipe_right->publish_state(false); - - on_swipe_left: - - lambda: |- - bs_swipe_left->publish_state(true); - release_buttons->execute(); - - delay: !lambda return nr_touch_duration->state; - - lambda: bs_swipe_left->publish_state(false); - - on_swipe_right: - - lambda: |- - bs_swipe_right->publish_state(true); - release_buttons->execute(); - - delay: !lambda return nr_touch_duration->state; - - lambda: bs_swipe_right->publish_state(false); - - on_touch_event: - - lambda: |- - ESP_LOGD("tx_ultimate_easy.on_touch_event", "Touch event:"); - ESP_LOGD("tx_ultimate_easy.on_touch_event", " State: %i (%s)", touch.state, touch.state_str.c_str()); - ESP_LOGD("tx_ultimate_easy.on_touch_event", " Position: %i", touch.x); - -uart: - id: uart_touch - tx_pin: GPIO19 - rx_pin: GPIO22 - baud_rate: 115200 - web_server: wifi: diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_api.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_api.yaml new file mode 100644 index 0000000..ff4bb80 --- /dev/null +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_api.yaml @@ -0,0 +1,41 @@ +#################################################################################################### +##### TX Ultimate Easy for ESPHome ##### +##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### +#################################################################################################### +##### Purpose: ESPHome Core - API ##### +#################################################################################################### +##### 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. ##### +#################################################################################################### +--- +api: + id: api_server + on_client_connected: + then: + - script.execute: publish_device_info + +script: + - id: !extend button_action + then: + - script.execute: + id: send_event_to_ha + component: !lambda return component.c_str(); + event: !lambda return event.c_str(); + + - id: send_event_to_ha + mode: queued + parameters: + component: string + event: string + then: + - homeassistant.event: + event: esphome.tx_ultimate_easy + data: + device_name: !lambda return tx_device_name->state.c_str(); + firmware: ${version} + component: !lambda return component.c_str(); + event: !lambda return event.c_str(); +... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml new file mode 100644 index 0000000..2e8a8a0 --- /dev/null +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml @@ -0,0 +1,277 @@ +#################################################################################################### +##### 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)" + +binary_sensor: + - id: bs_button_1 + name: Button 1 + icon: mdi:gesture-tap-box + internal: false + platform: template + on_click: + then: + - script.execute: + id: button_action + component: bs_button_1 + event: click + on_double_click: + then: + - script.execute: + id: button_action + component: bs_button_1 + event: double_click + on_multi_click: + - timing: &long_click-timing + - ON for at least 0.8s + invalid_cooldown: ${invalid_cooldown} + then: + - script.execute: + id: button_action + component: bs_button_1 + event: long_click + + - id: bs_button_2 + name: Button 2 + icon: mdi:gesture-tap-box + internal: true + platform: template + on_click: + then: + - script.execute: + id: button_action + component: bs_button_2 + event: click + on_double_click: + then: + - script.execute: + id: button_action + component: bs_button_2 + event: double_click + on_multi_click: + - timing: *long_click-timing + invalid_cooldown: ${invalid_cooldown} + then: + - script.execute: + id: button_action + component: bs_button_2 + event: long_click + + - id: bs_button_3 + name: Button 3 + icon: mdi:gesture-tap-box + internal: true + platform: template + on_click: + then: + - script.execute: + id: button_action + component: bs_button_3 + event: click + on_double_click: + then: + - script.execute: + id: button_action + component: bs_button_3 + event: double_click + on_multi_click: + - timing: *long_click-timing + invalid_cooldown: ${invalid_cooldown} + then: + - script.execute: + id: button_action + component: bs_button_3 + event: long_click + + - id: bs_button_4 + name: Button 4 + icon: mdi:gesture-tap-box + internal: true + platform: template + on_click: + then: + - script.execute: + id: button_action + component: bs_button_4 + event: click + on_double_click: + then: + - script.execute: + id: button_action + component: bs_button_4 + event: double_click + on_multi_click: + - timing: *long_click-timing + invalid_cooldown: ${invalid_cooldown} + then: + - script.execute: + id: button_action + component: bs_button_4 + event: long_click + +script: + - id: !extend boot_initialize + then: + - script.execute: boot_initialize_buttons + + - id: boot_initialize_buttons + mode: restart + then: + - wait_until: + condition: + - lambda: return sl_tx_model_gang->active_index().has_value(); + - lambda: |- + 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_buttons", "Invalid number of gangs: %" PRIu8, num_gangs); + return; + } + bs_button_1->publish_state(false); + bs_button_1->set_internal(num_gangs < 1); + sl_button_1_action->set_internal(num_gangs < 1); + bs_button_2->publish_state(false); + bs_button_2->set_internal(num_gangs < 2); + sl_button_2_action->set_internal(num_gangs < 2); + bs_button_3->publish_state(false); + bs_button_3->set_internal(num_gangs < 3); + sl_button_3_action->set_internal(num_gangs < 3); + bs_button_4->publish_state(false); + bs_button_4->set_internal(num_gangs < 4); + sl_button_4_action->set_internal(num_gangs < 4); + + - id: button_action + mode: parallel + parameters: + component: string + event: string + then: # There's nothing here so far + # Extended by: + # - core_api + + - id: buttons_release + mode: restart + then: + - lambda: |- + std::vector 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 + touch_x: !lambda return touch_x; + + - id: touch_on_press_buttons + mode: restart + parameters: + touch_x: uint8_t + then: + - lambda: |- + auto model_index = sl_tx_model_gang->active_index(); + if (model_index.has_value()) { + uint8_t model_idx = model_index.value() + 1; + switch (model_idx) { + case 1: // 1 Gang + bs_button_1->publish_state(true); + break; + case 2: // 2 Gang + if (touch_x <= 5) bs_button_1->publish_state(true); + else bs_button_2->publish_state(true); + break; + case 3: // 3 Gang + if (touch_x <= 3) bs_button_1->publish_state(true); + else if (touch_x <= 7) bs_button_2->publish_state(true); + else bs_button_3->publish_state(true); + break; + case 4: // 4 Gang + if (touch_x <= 2) bs_button_1->publish_state(true); + else if (touch_x <= 5) bs_button_2->publish_state(true); + else if (touch_x <= 8) bs_button_3->publish_state(true); + else bs_button_4->publish_state(true); + break; + } + } + + - id: !extend touch_on_release + then: + - script.execute: buttons_release + + - 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}" + 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}" + 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}" + 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}" + initial_option: "${BUTTON_4_ACTION_TEXT}" + <<: *button_select_action_base +... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml new file mode 100644 index 0000000..22374f6 --- /dev/null +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml @@ -0,0 +1,963 @@ +#################################################################################################### +##### TX Ultimate Easy for ESPHome ##### +##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### +#################################################################################################### +##### Purpose: ESPHome Core - Hardware - LEDs ##### +#################################################################################################### +##### 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: + default_transition_length: 500ms + + LIGHT_MODE_BOTH_TEXT: "Both" + LIGHT_MODE_DISABLED_TEXT: "Disabled" + LIGHT_MODE_LEFT_TEXT: "Left" + LIGHT_MODE_RIGHT_TEXT: "Right" + LIGHT_MODE_BOTTOM_TEXT: "Bottom" + LIGHT_MODE_TOP_TEXT: "Top" + + LIGHT_TRANSITION_TURN_ON: '0' # Transition time in msec + LIGHT_TRANSITION_TURN_OFF: '0' # Transition time in msec + LIGHT_BRIGHTNESS_TURN_ON: '0' # Brightness (1 to 100%, 0 to not set it) + +globals: + - id: gb_lights_1 + type: std::vector + restore_value: false + - id: gb_lights_2 + type: std::vector + restore_value: false + +light: + - id: light_output_1 + name: Light output 1 + internal: true + platform: binary + output: output_relay_1 + - id: light_output_2 + name: Light output 2 + internal: true + platform: binary + output: output_relay_2 + - id: light_output_3 + name: Light output 3 + internal: true + platform: binary + output: output_relay_3 + - id: light_output_4 + name: Light output 4 + internal: true + platform: binary + output: output_relay_4 + + - id: light_full + name: Light - All + internal: true + platform: neopixelbus + type: GRB + variant: WS2811 + # method: esp32_rmt + num_leds: 32 + pin: GPIO13 + + - id: light_eu + name: Light + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml + segments: + - id: light_full + from: 0 + to: 27 + + - id: light_us + name: Light + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml + segments: + - id: light_full + from: 0 + to: 31 + + # Those lights are available based on the model selections + - id: light_eu_bottom + name: Light - Bottom + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml + segments: + - id: light_full + from: 6 + to: 12 + reversed: true + - id: light_eu_left + name: Light - Left + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml + segments: + - id: light_full + from: 13 + to: 19 + reversed: true + - id: light_eu_right + name: Light - Right + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml + segments: + - id: light_full + from: 27 + to: 27 + reversed: false + - id: light_full + from: 0 + to: 5 + reversed: false + - id: light_eu_top + name: Light - Top + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml + segments: + - id: light_full + from: 20 + to: 26 + reversed: false + - id: light_us_bottom + name: Light - Bottom + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml + segments: + - id: light_full + from: 9 + to: 14 + reversed: true + - id: light_us_left + name: Light - Left + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml + segments: + - id: light_full + from: 15 + to: 24 + reversed: true + - id: light_us_right + name: Light - Right + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml + segments: + - id: light_full + from: 31 + to: 31 + reversed: false + - id: light_full + from: 0 + to: 8 + reversed: false + - id: light_us_top + name: Light - Top + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml + segments: + - id: light_full + from: 25 + to: 30 + reversed: false + + - id: light_00 + name: Light - LED 00 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 0 + to: 0 + - id: light_01 + name: Light - LED 01 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 1 + to: 1 + - id: light_02 + name: Light - LED 02 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 2 + to: 2 + - id: light_03 + name: Light - LED 03 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 3 + to: 3 + - id: light_04 + name: Light - LED 04 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 4 + to: 4 + - id: light_05 + name: Light - LED 05 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 5 + to: 5 + - id: light_06 + name: Light - LED 06 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 6 + to: 6 + - id: light_07 + name: Light - LED 07 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 7 + to: 7 + - id: light_08 + name: Light - LED 08 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 8 + to: 8 + - id: light_09 + name: Light - LED 09 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 9 + to: 9 + - id: light_10 + name: Light - LED 10 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 10 + to: 10 + - id: light_11 + name: Light - LED 11 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 11 + to: 11 + - id: light_12 + name: Light - LED 12 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 12 + to: 12 + - id: light_13 + name: Light - LED 13 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 13 + to: 13 + - id: light_14 + name: Light - LED 14 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 14 + to: 14 + - id: light_15 + name: Light - LED 15 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 15 + to: 15 + - id: light_16 + name: Light - LED 16 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 16 + to: 16 + - id: light_17 + name: Light - LED 17 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 17 + to: 17 + - id: light_18 + name: Light - LED 18 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 18 + to: 18 + - id: light_19 + name: Light - LED 19 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 19 + to: 19 + - id: light_20 + name: Light - LED 20 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 20 + to: 20 + - id: light_21 + name: Light - LED 21 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 21 + to: 21 + - id: light_22 + name: Light - LED 22 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 22 + to: 22 + - id: light_23 + name: Light - LED 23 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 23 + to: 23 + - id: light_24 + name: Light - LED 24 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 24 + to: 24 + - id: light_25 + name: Light - LED 25 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 25 + to: 25 + - id: light_26 + name: Light - LED 26 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 26 + to: 26 + - id: light_27 + name: Light - LED 27 + disabled_by_default: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 27 + to: 27 + - id: light_28 + name: Light - LED 28 + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 28 + to: 28 + - id: light_29 + name: Light - LED 29 + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 29 + to: 29 + - id: light_30 + name: Light - LED 30 + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 30 + to: 30 + - id: light_31 + name: Light - LED 31 + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 31 + to: 31 + + - id: light_eu_rl_1_1_bottom + name: Light - Relay 1 of 1 (bottom) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 9 + to: 9 + - id: light_eu_rl_1_1_top + name: Light - Relay 1 of 1 (top) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 23 + to: 23 + - id: light_eu_rl_1_2_bottom + name: Light - Relay 1 of 2 (bottom) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 11 + to: 11 + - id: light_eu_rl_1_2_top + name: Light - Relay 1 of 2 (top) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 21 + to: 21 + - id: light_eu_rl_2_2_bottom + name: Light - Relay 2 of 2 (bottom) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 7 + to: 7 + - id: light_eu_rl_2_2_top + name: Light - Relay 2 of 2 (top) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 25 + to: 25 + - id: light_eu_rl_1_3_bottom + name: Light - Relay 1 of 3 (bottom) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 12 + to: 12 + - id: light_eu_rl_1_3_top + name: Light - Relay 1 of 3 (top) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 20 + to: 20 + - id: light_eu_rl_2_3_bottom + name: Light - Relay 2 of 3 (bottom) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 9 + to: 9 + - id: light_eu_rl_2_3_top + name: Light - Relay 2 of 3 (top) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 23 + to: 23 + - id: light_eu_rl_3_3_bottom + name: Light - Relay 3 of 3 (bottom) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 6 + to: 6 + - id: light_eu_rl_3_3_top + name: Light - Relay 3 of 3 (top) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 26 + to: 26 + - id: light_eu_rl_1_4_bottom + name: Light - Relay 1 of 4 (bottom) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 12 + to: 12 + - id: light_eu_rl_1_4_top + name: Light - Relay 1 of 4 (top) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 20 + to: 20 + - id: light_eu_rl_2_4_bottom + name: Light - Relay 2 of 4 (bottom) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 10 + to: 10 + - id: light_eu_rl_2_4_top + name: Light - Relay 2 of 4 (top) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 22 + to: 22 + - id: light_eu_rl_3_4_bottom + name: Light - Relay 3 of 4 (bottom) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 8 + to: 8 + - id: light_eu_rl_3_4_top + name: Light - Relay 3 of 4 (top) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 24 + to: 24 + - id: light_eu_rl_4_4_bottom + name: Light - Relay 4 of 4 (bottom) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 6 + to: 6 + - id: light_eu_rl_4_4_top + name: Light - Relay 4 of 4 (top) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 26 + to: 26 + - id: light_us_rl_1_1_left + name: Light - Relay 1 of 1 (left) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 15 + to: 24 + - id: light_us_rl_1_1_right + name: Light - Relay 1 of 1 (right) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 31 + to: 31 + - id: light_full + from: 0 + to: 8 + - id: light_us_rl_1_2_left + name: Light - Relay 1 of 2 (left) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 20 + to: 24 + - id: light_us_rl_1_2_right + name: Light - Relay 1 of 2 (right) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 31 + to: 31 + - id: light_full + from: 0 + to: 3 + - id: light_us_rl_2_2_left + name: Light - Relay 2 of 2 (left) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 15 + to: 19 + - id: light_us_rl_2_2_right + name: Light - Relay 2 of 2 (right) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 4 + to: 8 + - id: light_us_rl_1_3_left + name: Light - Relay 1 of 3 (left) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 22 + to: 23 + - id: light_us_rl_1_3_right + name: Light - Relay 1 of 3 (right) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 0 + to: 1 + - id: light_us_rl_2_3_left + name: Light - Relay 2 of 3 (left) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 19 + to: 20 + - id: light_us_rl_2_3_right + name: Light - Relay 2 of 3 (right) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 3 + to: 4 + - id: light_us_rl_3_3_left + name: Light - Relay 3 of 3 (left) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 17 + to: 18 + - id: light_us_rl_3_3_right + name: Light - Relay 3 of 3 (right) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 6 + to: 7 + - id: light_us_rl_1_4_left + name: Light - Relay 1 of 4 (left) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 12 + to: 12 + - id: light_us_rl_1_4_right + name: Light - Relay 1 of 4 (right) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 31 + to: 31 + - id: light_us_rl_2_4_left + name: Light - Relay 2 of 4 (left) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 24 + to: 24 + - id: light_us_rl_2_4_right + name: Light - Relay 2 of 4 (right) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 2 + to: 2 + - id: light_us_rl_3_4_left + name: Light - Relay 3 of 4 (left) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 21 + to: 21 + - id: light_us_rl_3_4_right + name: Light - Relay 3 of 4 (right) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 4 + to: 4 + - id: light_us_rl_4_4_left + name: Light - Relay 4 of 4 (left) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 19 + to: 19 + - id: light_us_rl_4_4_right + name: Light - Relay 4 of 4 (right) + internal: true + <<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml + segments: + - id: light_full + from: 7 + to: 7 + +script: + - id: !extend boot_initialize + 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_leds", "Invalid number of gangs: %" PRIu8, num_gangs); + return; + } + light_28->set_internal(!is_model_us); + light_29->set_internal(!is_model_us); + light_30->set_internal(!is_model_us); + light_31->set_internal(!is_model_us); + light_eu->set_internal(is_model_us); + light_eu_bottom->set_internal(is_model_us); + light_eu_left->set_internal(is_model_us); + light_eu_right->set_internal(is_model_us); + light_eu_top->set_internal(is_model_us); + light_us->set_internal(!is_model_us); + light_us_bottom->set_internal(!is_model_us); + light_us_left->set_internal(!is_model_us); + light_us_right->set_internal(!is_model_us); + light_us_top->set_internal(!is_model_us); + switch (num_gangs) { + case 1: // 1 Gang + if (is_model_us) { + id(gb_lights_1) = { light_us_rl_1_1_left }; + id(gb_lights_2) = { light_us_rl_1_1_right }; + } else { + id(gb_lights_1) = { light_eu_rl_1_1_bottom }; + id(gb_lights_2) = { light_eu_rl_1_1_top }; + } + break; + case 2: // 2 Gang + if (is_model_us) { + id(gb_lights_1) = { light_us_rl_1_2_left, light_us_rl_2_2_left }; + id(gb_lights_2) = { light_us_rl_1_2_right, light_us_rl_2_2_right }; + } else { + id(gb_lights_1) = { light_eu_rl_1_2_bottom, light_eu_rl_2_2_bottom }; + id(gb_lights_2) = { light_eu_rl_1_2_top, light_eu_rl_2_2_top }; + } + break; + case 3: // 3 Gang + if (is_model_us) { + id(gb_lights_1) = { light_us_rl_1_3_left, light_us_rl_2_3_left, light_us_rl_3_3_left }; + id(gb_lights_2) = { light_us_rl_1_3_right, light_us_rl_2_3_right, light_us_rl_3_3_right }; + } else { + id(gb_lights_1) = { light_eu_rl_1_3_bottom, light_eu_rl_2_3_bottom, light_eu_rl_3_3_bottom }; + id(gb_lights_2) = { light_eu_rl_1_3_top, light_eu_rl_2_3_top, light_eu_rl_3_3_top }; + } + break; + case 4: // 3 Gang + if (is_model_us) { + id(gb_lights_1) = { light_us_rl_1_4_left, light_us_rl_2_4_left, + light_us_rl_3_4_left, light_us_rl_4_4_left }; + id(gb_lights_2) = { light_us_rl_1_4_right, light_us_rl_2_4_right, + light_us_rl_3_4_right, light_us_rl_4_4_right }; + } else { + id(gb_lights_1) = { light_eu_rl_1_4_bottom, light_eu_rl_2_4_bottom, + light_eu_rl_3_4_bottom, light_eu_rl_4_4_bottom }; + id(gb_lights_2) = { light_eu_rl_1_4_top, light_eu_rl_2_4_top, + light_eu_rl_3_4_top, light_eu_rl_4_4_top }; + } + break; + } + + - id: light_set_state + mode: parallel + parameters: + light_group: uint8_t + light_index: uint8_t + state: bool + then: + - lambda: |- + static const uint32_t LIGHT_TRANSITION_TURN_ON = ${LIGHT_TRANSITION_TURN_ON}; + static const uint32_t LIGHT_TRANSITION_TURN_OFF = ${LIGHT_TRANSITION_TURN_OFF}; + static const uint8_t LIGHT_BRIGHTNESS_TURN_ON = ${LIGHT_BRIGHTNESS_TURN_ON}; + + const bool is_model_us = sl_tx_model_format->active_index().has_value() and + sl_tx_model_format->active_index().value() == 1; + 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}"; + + switch (light_group) { + case 1: + if (light_index >= id(gb_lights_1).size()) { + ESP_LOGE("core_hw_leds", "Invalid set with %s light for Relay %" PRIu8, + light_mode_group_1.c_str(), light_index); + return; + } + if (state and !id(gb_lights_1)[light_index]->current_values.is_on()) { + ESP_LOGI("core_hw_leds", "Turn-on %s light for Relay %" PRIu8, + light_mode_group_1.c_str(), light_index); + auto call = id(gb_lights_1)[light_index]->turn_on(); + if (LIGHT_TRANSITION_TURN_ON > 0) + call.set_transition_length(LIGHT_TRANSITION_TURN_ON); // in ms + if (LIGHT_BRIGHTNESS_TURN_ON > 0 and LIGHT_BRIGHTNESS_TURN_ON <= 100) + call.set_brightness(LIGHT_BRIGHTNESS_TURN_ON / 100.0f); + call.perform(); + } else if (!state and id(gb_lights_1)[light_index]->current_values.is_on()) { + ESP_LOGI("core_hw_leds", "Turn-off %s light for Relay %" PRIu8, + light_mode_group_1.c_str(), light_index); + auto call = id(gb_lights_1)[light_index]->turn_off(); + if (LIGHT_TRANSITION_TURN_OFF > 0) + call.set_transition_length(LIGHT_TRANSITION_TURN_OFF); // in ms + call.perform(); + } + break; + case 2: + if (light_index >= id(gb_lights_2).size()) { + ESP_LOGE("core_hw_leds", "Invalid set with %s light for Relay %" PRIu8, + light_mode_group_2.c_str(), light_index); + return; + } + if (state and !id(gb_lights_2)[light_index]->current_values.is_on()) { + ESP_LOGI("core_hw_leds", "Turn-on %s light for Relay %" PRIu8, + light_mode_group_2.c_str(), light_index); + auto call = id(gb_lights_2)[light_index]->turn_on(); + if (LIGHT_TRANSITION_TURN_ON > 0) + call.set_transition_length(LIGHT_TRANSITION_TURN_ON); // in ms + if (LIGHT_BRIGHTNESS_TURN_ON > 0 and LIGHT_BRIGHTNESS_TURN_ON <= 100) + call.set_brightness(LIGHT_BRIGHTNESS_TURN_ON / 100.0f); + call.perform(); + } else if (!state and id(gb_lights_2)[light_index]->current_values.is_on()) { + ESP_LOGI("core_hw_leds", "Turn-off %s light for Relay %" PRIu8, + light_mode_group_2.c_str(), light_index); + auto call = id(gb_lights_2)[light_index]->turn_off(); + if (LIGHT_TRANSITION_TURN_OFF > 0) + call.set_transition_length(LIGHT_TRANSITION_TURN_OFF); // in ms + call.perform(); + } + break; + } + +select: + # EU relay light mode template + - &relay_light_mode_eu + id: sl_relay_1_light_mode_eu + name: Relay 1 light mode + platform: template + options: + - "${LIGHT_MODE_DISABLED_TEXT}" + - "${LIGHT_MODE_BOTTOM_TEXT}" + - "${LIGHT_MODE_TOP_TEXT}" + - "${LIGHT_MODE_BOTH_TEXT}" + initial_option: "${LIGHT_MODE_BOTTOM_TEXT}" + optimistic: true + restore_value: true + internal: true + entity_category: config + disabled_by_default: false + icon: mdi:dots-square + + - id: sl_relay_2_light_mode_eu + name: Relay 2 light mode + <<: *relay_light_mode_eu + + - id: sl_relay_3_light_mode_eu + name: Relay 3 light mode + <<: *relay_light_mode_eu + + - id: sl_relay_4_light_mode_eu + name: Relay 4 light mode + <<: *relay_light_mode_eu + + # US relay light mode template + - &relay_light_mode_us + id: sl_relay_1_light_mode_us + name: Relay 1 light mode + platform: template + options: + - "${LIGHT_MODE_DISABLED_TEXT}" + - "${LIGHT_MODE_LEFT_TEXT}" + - "${LIGHT_MODE_RIGHT_TEXT}" + - "${LIGHT_MODE_BOTH_TEXT}" + initial_option: "${LIGHT_MODE_RIGHT_TEXT}" + optimistic: true + restore_value: true + internal: true + entity_category: config + disabled_by_default: false + icon: mdi:dots-square + + - id: sl_relay_2_light_mode_us + name: Relay 2 light mode + <<: *relay_light_mode_us + + - id: sl_relay_3_light_mode_us + name: Relay 3 light mode + <<: *relay_light_mode_us + + - id: sl_relay_4_light_mode_us + name: Relay 4 light mode + <<: *relay_light_mode_us +... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml new file mode 100644 index 0000000..9430a37 --- /dev/null +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml @@ -0,0 +1,4 @@ +--- +platform: partition +default_transition_length: ${default_transition_length} +... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml new file mode 100644 index 0000000..dcdf7fb --- /dev/null +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml @@ -0,0 +1,40 @@ +--- +effects: + - addressable_rainbow: + name: "Rainbow" + - addressable_rainbow: + name: "Rainbow - Fast" + speed: 50 + - pulse: + name: "Pulse" + transition_length: 1s + update_interval: 1s + - pulse: + name: "Pulse - Slow" + transition_length: 2s + update_interval: 2s + - addressable_scan: + name: "Scan" + move_interval: 100ms + scan_width: 3 + - addressable_twinkle: + name: "Twinkle" + twinkle_probability: 5% + progress_interval: 4ms + - addressable_random_twinkle: + name: "Random Twinkle" + twinkle_probability: 20% + progress_interval: 32ms + - addressable_fireworks: + name: "Fireworks" + update_interval: 32ms + spark_probability: 10% + use_random_color: false + fade_out_rate: 120 + - addressable_flicker: + name: "Flicker" + update_interval: 16ms + intensity: 5% + - random: + name: "Random" +... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml new file mode 100644 index 0000000..42e596a --- /dev/null +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml @@ -0,0 +1,4 @@ +--- +internal: true +disabled_by_default: true +... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml new file mode 100644 index 0000000..e096d2a --- /dev/null +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml @@ -0,0 +1,272 @@ +#################################################################################################### +##### 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. ##### +#################################################################################################### +--- +binary_sensor: + - id: !extend bs_button_1 + on_click: + then: + - if: + condition: + - lambda: return sl_button_1_action->active_index().has_value(); + - lambda: return sl_button_1_action->active_index().value() == 1; + - and: &button_click_no_other_click + - lambda: return not bs_multi_touch->state; + - lambda: return not bs_swipe_left->state; + - lambda: return not bs_swipe_down->state; + - lambda: return not bs_swipe_right->state; + then: + - switch.toggle: sw_relay_1 + + - id: !extend bs_button_2 + on_click: + then: + - if: + condition: + - lambda: return sl_button_2_action->active_index().has_value(); + - lambda: return sl_button_2_action->active_index().value() == 1; + - and: *button_click_no_other_click + then: + - switch.toggle: sw_relay_2 + + - id: !extend bs_button_3 + on_click: + then: + - if: + condition: + - lambda: return sl_button_3_action->active_index().has_value(); + - lambda: return sl_button_3_action->active_index().value() == 1; + - and: *button_click_no_other_click + then: + - switch.toggle: sw_relay_3 + + - id: !extend bs_button_4 + on_click: + then: + - if: + condition: + - lambda: return sl_button_4_action->active_index().has_value(); + - lambda: return sl_button_4_action->active_index().value() == 1; + - and: *button_click_no_other_click + then: + - switch.toggle: sw_relay_4 + +globals: + - id: boot_initialization_relays + type: bool + restore_value: false + initial_value: 'false' + +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: 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 mode + platform: template + options: + - "Relay" + - "Light" + - "Not in use" + 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 mode + <<: *relay_select_mode_base + + - id: sl_relay_3_mode + name: Relay 3 mode + <<: *relay_select_mode_base + + - id: sl_relay_4_mode + name: Relay 4 mode + <<: *relay_select_mode_base + +switch: + - &relay_switch_base + id: sw_relay_1 + name: Relay 1 + platform: output + output: output_relay_1 + restore_mode: RESTORE_DEFAULT_OFF + internal: true + on_turn_on: + then: + - script.execute: show_relay_status + on_turn_off: + then: + - script.execute: show_relay_status + + - id: sw_relay_2 + name: Relay 2 + output: output_relay_2 + <<: *relay_switch_base + + - id: sw_relay_3 + name: Relay 3 + output: output_relay_3 + <<: *relay_switch_base + + - id: sw_relay_4 + name: Relay 4 + output: output_relay_4 + <<: *relay_switch_base +... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml new file mode 100644 index 0000000..11178ec --- /dev/null +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml @@ -0,0 +1,29 @@ +#################################################################################################### +##### TX Ultimate Easy for ESPHome ##### +##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### +#################################################################################################### +##### Purpose: ESPHome Core - Hardware - Speaker ##### +#################################################################################################### +##### 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. ##### +#################################################################################################### +--- +i2s_audio: + id: if_i2s_audio + i2s_bclk_pin: GPIO2 + i2s_lrclk_pin: GPIO4 + +media_player: + - id: mp_speaker + name: Speaker + platform: i2s_audio + i2s_dout_pin: GPIO15 + i2s_audio_id: if_i2s_audio + i2s_comm_fmt: lsb + dac_type: external + mode: mono + internal: false +... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml new file mode 100644 index 0000000..08c6490 --- /dev/null +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml @@ -0,0 +1,240 @@ +#################################################################################################### +##### TX Ultimate Easy for ESPHome ##### +##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### +#################################################################################################### +##### Purpose: ESPHome Core - Hardware - Touch panel ##### +#################################################################################################### +##### 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. ##### +#################################################################################################### +--- +binary_sensor: + - id: bs_multi_touch + name: Multi-touch + icon: mdi:gesture-two-tap + internal: false + platform: template + on_click: + then: + - lambda: send_event_to_ha->execute("multi_touch", "multi_touch"); + + - id: bs_swipe_left + name: Swipe left + icon: mdi:gesture-swipe-left + internal: true + platform: template + on_click: + then: + - lambda: send_event_to_ha->execute("swipe", "left"); + + - id: bs_swipe_right + name: Swipe right + icon: mdi:gesture-swipe-right + internal: true + platform: template + on_click: + then: + - lambda: send_event_to_ha->execute("swipe", "right"); + + - id: bs_swipe_up + name: Swipe up + icon: mdi:gesture-swipe-up + internal: true + platform: template + on_click: + then: + - lambda: send_event_to_ha->execute("swipe", "up"); + + - id: bs_swipe_down + name: Swipe down + icon: mdi:gesture-swipe-down + internal: true + platform: template + on_click: + then: + - lambda: send_event_to_ha->execute("swipe", "down"); + +external_components: + - source: + type: git + url: https://github.com/edwardtfn/TX-Ultimate-Easy + ref: ${version} + refresh: 1h + components: + - tx_ultimate_easy + +number: + - id: nr_touch_duration + name: Touch duration + icon: mdi:timer-cog-outline + unit_of_measurement: ms + # mode: box + internal: false + entity_category: config + platform: template + min_value: 10 + max_value: 1500 + step: 1 + initial_value: 250 + optimistic: true + restore_value: true + +script: + - id: !extend boot_initialize + then: + - script.execute: boot_initialize_touch + + - id: boot_initialize_touch + mode: restart + then: + - wait_until: + condition: + - lambda: return sl_tx_model_format->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; + bs_multi_touch->publish_state(false); + bs_swipe_down->publish_state(false); + bs_swipe_down->set_internal(!is_model_us); + bs_swipe_left->publish_state(false); + bs_swipe_left->set_internal(is_model_us); + bs_swipe_right->publish_state(false); + bs_swipe_right->set_internal(is_model_us); + bs_swipe_up->publish_state(false); + bs_swipe_up->set_internal(!is_model_us); + + - id: touch_on_multi_touch_release + mode: restart + then: + # Extended by: + # - HW Buttons + # - HW Vibration + - script.execute: touch_on_multi_touch_release_touch + + - id: touch_on_multi_touch_release_touch + mode: restart + then: + - lambda: bs_multi_touch->publish_state(true); + - delay: !lambda return nr_touch_duration->state; + - lambda: bs_multi_touch->publish_state(false); + + - id: touch_on_press + mode: restart + parameters: + touch_x: uint8_t + then: + # Extended by: + # - HW Buttons + # - HW Vibration + + - id: touch_on_release + mode: restart + then: + # Extended by: + # - HW Buttons + # - HW Vibration + - script.execute: touch_swipe_turn_off_binary_sensor + + - id: touch_swipe_left + mode: restart + then: + # Extended by: + # - HW Buttons + - script.execute: touch_swipe_left_touch + + - id: touch_swipe_left_touch + mode: restart + then: + - binary_sensor.template.publish: + id: bs_swipe_left + state: ON # yamllint disable-line rule:truthy + - delay: !lambda return nr_touch_duration->state; + - script.execute: touch_swipe_turn_off_binary_sensor + + - id: touch_swipe_right + mode: restart + then: + # Extended by: + # - HW Buttons + - script.execute: touch_swipe_right_touch + + - id: touch_swipe_right_touch + mode: restart + then: + - binary_sensor.template.publish: + id: bs_swipe_right + state: ON # yamllint disable-line rule:truthy + - delay: !lambda return nr_touch_duration->state; + - script.execute: touch_swipe_turn_off_binary_sensor + + - id: touch_swipe_turn_off_binary_sensor + mode: restart + then: + - if: + condition: + binary_sensor.is_on: bs_swipe_left + then: + - binary_sensor.template.publish: + id: bs_swipe_left + state: OFF # yamllint disable-line rule:truthy + - if: + condition: + binary_sensor.is_on: bs_swipe_right + then: + - binary_sensor.template.publish: + id: bs_swipe_right + state: OFF # yamllint disable-line rule:truthy + +switch: + - id: sw_touch_panel_power + name: Touch panel - Power + platform: gpio + pin: + number: GPIO5 + inverted: true + restore_mode: ALWAYS_ON + internal: false + entity_category: config + +tx_ultimate_easy: + id: tx_ultimate + uart: uart_touch + + on_multi_touch_release: + - lambda: ESP_LOGI("tx_ultimate_easy", "Multi-touch released"); + - script.execute: touch_on_multi_touch_release + + on_press: + - lambda: |- + ESP_LOGI("tx_ultimate_easy", "Pressed at position %" PRIu8, static_cast(touch.x)); + - script.execute: + id: touch_on_press + touch_x: !lambda return static_cast(touch.x); + + on_release: + - lambda: ESP_LOGI("tx_ultimate_easy", "Released"); + - script.execute: touch_on_release + + on_swipe_left: + - lambda: ESP_LOGI("tx_ultimate_easy", "Swipe left"); + - script.execute: touch_swipe_left + + on_swipe_right: + - lambda: ESP_LOGI("tx_ultimate_easy", "Swipe right"); + - script.execute: touch_swipe_right + + on_touch_event: + - lambda: |- + ESP_LOGD("tx_ultimate_easy", "Touch event:"); + ESP_LOGD("tx_ultimate_easy", " State: %i (%s)", touch.state, touch.state_str.c_str()); + ESP_LOGD("tx_ultimate_easy", " Position: %i", touch.x); + +uart: + id: uart_touch + tx_pin: GPIO19 + rx_pin: GPIO22 + baud_rate: 115200 +... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml new file mode 100644 index 0000000..67655c1 --- /dev/null +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml @@ -0,0 +1,137 @@ +#################################################################################################### +##### TX Ultimate Easy for ESPHome ##### +##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### +#################################################################################################### +##### Purpose: ESPHome Core - Hardware - Vibration system ##### +#################################################################################################### +##### 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: + vibration_max_duration: 2s + +binary_sensor: + - id: bs_vibrating + name: Vibrating + icon: mdi:vibrate + internal: false + platform: template + lambda: return sw_vibration_motor->state; + +button: + - id: bt_vibrate + name: Vibrate + icon: mdi:vibrate + internal: false + platform: template + on_press: + then: + - script.execute: vibrate + +number: + - id: nr_vibrating_duration + name: Vibrate duration + icon: mdi:vibrate + unit_of_measurement: ms + internal: false + entity_category: config + platform: template + min_value: 1 + max_value: 500 + step: 1 + initial_value: 15 + optimistic: true + restore_value: true + +ota: + on_state_change: + then: + - switch.turn_off: sw_vibration_motor + +script: + - id: !extend touch_on_multi_touch_release + then: + - script.execute: touch_on_multi_touch_release_vibration + + - id: touch_on_multi_touch_release_vibration + mode: restart + then: + - lambda: |- + if (sl_touch_vibration_feedback->state != "Disabled") + vibrate->execute(); + + - id: !extend touch_on_press + then: + - script.execute: touch_on_press_vibration + + - id: touch_on_press_vibration + mode: restart + then: + - lambda: |- + if (sl_touch_vibration_feedback->state == "On press" or sl_touch_vibration_feedback->state == "Always") + vibrate->execute(); + + - id: !extend touch_on_release + then: + - script.execute: touch_on_release_vibration + + - id: touch_on_release_vibration + mode: restart + then: + - lambda: |- + if (sl_touch_vibration_feedback->state == "On release" or sl_touch_vibration_feedback->state == "Always") + vibrate->execute(); + + - id: vibrate + mode: restart + then: + - switch.turn_on: sw_vibration_motor + - delay: !lambda return nr_vibrating_duration->state; + - switch.turn_off: sw_vibration_motor + +select: + - id: sl_touch_vibration_feedback + name: Touch - Vibration feedback + platform: template + options: + - "Disabled" + - "On press" + - "On release" + - "Always" + initial_option: "Disabled" + optimistic: true + restore_value: true + internal: false + entity_category: config + disabled_by_default: false + icon: mdi:vibrate + +switch: + - id: sw_vibration_motor + name: Vibration motor + platform: gpio + pin: GPIO21 + restore_mode: ALWAYS_OFF + internal: true + on_turn_on: + then: + - binary_sensor.template.publish: + id: bs_vibrating + state: ON # yamllint disable-line rule:truthy + - delay: ${vibration_max_duration} + - if: + condition: + switch.is_on: sw_vibration_motor + then: + - switch.turn_off: sw_vibration_motor + on_turn_off: + then: + - binary_sensor.template.publish: + id: bs_vibrating + state: OFF # yamllint disable-line rule:truthy + +... diff --git a/README.md b/README.md index 64ef6f6..a184ba5 100644 --- a/README.md +++ b/README.md @@ -1,59 +1,141 @@ # TX Ultimate Easy -|  ![TX Ultimate Easy Logo](Assets/Logo.webp) | Welcome to TX Ultimate Easy! This project aims to provide custom firmware for Sonoff TX Ultimate devices based on ESPHome, making it easy for even the least tech-savvy users to configure and use. Our goal is to have all the configurations manageable directly through the Home Assistant UI or via blueprints, eliminating the need to edit YAML files manually. | + +![GitHub Activity][commits-shield] +![License][license-shield] +![GitHub Last Commit][last-commit-shield] +![ESPHome][esphome-shield] +![Discord][discord-shield] +![Buy me an ice-cream][buymeacoffee-shield] + + + +|  ![TX Ultimate Easy Logo](Assets/Logo.webp) | TX Ultimate Easy provides custom ESPHome firmware for Sonoff TX Ultimate devices. Our project focuses on user-friendly configuration through the Home Assistant UI, eliminating the need for manual YAML editing. Whether you're new to home automation or an experienced user, TX Ultimate Easy makes it simple to manage your device. | | --- | :-- | + -## Features +[commits-shield]: https://img.shields.io/github/commit-activity/y/edwardtfn/TX-Ultimate-Easy +[commits]: https://github.com/edwardtfn/TX-Ultimate-Easy/commits/main +[license-shield]: https://img.shields.io/github/license/edwardtfn/TX-Ultimate-Easy +[license]: LICENSE +[last-commit-shield]: https://img.shields.io/github/last-commit/edwardtfn/TX-Ultimate-Easy +[esphome-shield]: https://img.shields.io/badge/powered%20by-ESPHome-blue +[esphome]: https://esphome.io/ +[discord-shield]: https://img.shields.io/discord/1243652421692031016?logo=discord +[discord]: https://discord.gg/Db6WJWzWuf +[buymeacoffee-shield]: https://img.shields.io/static/v1?label=Buy%20me%20an%20ice%20cream&message=❄&color=blue +[buymeacoffee]: https://www.buymeacoffee.com/edwardfirmo -- **Simple Setup:** Configure your Sonoff TX Ultimate through Home Assistant UI. -- **No YAML Editing:** All settings are adjustable without touching YAML files after the initial setup. -- **User-Friendly:** Designed for users of all technical levels. -- **Customizable:** Flexibility to adapt the firmware to your needs. -- **Seamless Integration:** Works flawlessly with Home Assistant. +## Integration with Home Assistant -## Getting Started +TX Ultimate Easy exposes your device's components (sensors, touch panel, relays, etc.) to Home Assistant, allowing you to: -### Prerequisites +- Monitor sensor states and values +- Control device components through the Home Assistant UI +- Use device triggers and states in your Home Assistant automations and scripts +- Configure device behavior through Home Assistant's service calls -- Sonoff TX Ultimate device -- Home Assistant installed -- ESPHome add-on installed in Home Assistant +All automation capabilities are handled through Home Assistant's native automation system - this project focuses on providing reliable device integration rather than implementing its own automation tools. -### Installation -To be written. +## Key Features -### Configuration +- **Home Assistant UI Configuration**: Manage all device settings directly through the Home Assistant interface +- **Zero YAML Knowledge Required**: After initial setup, no manual YAML editing needed +- **Flexible Light Control**: Customize LED behavior and effects +- **Touch Panel Support**: Full support for touch gestures and multi-touch capabilities +- **Advanced Automations**: Create complex automations using Home Assistant's powerful automation engine +- **BLE Proxy Support**: Optional Bluetooth Low Energy proxy functionality +- **Audio Feedback**: Built-in speaker support for audible feedback +- **Haptic Feedback**: Vibration motor support for tactile feedback -- **Via Home Assistant UI:** - All device settings can be managed through the Home Assistant interface. No need to edit YAML files directly. +## Hardware Support -- **Using Blueprints:** - Import and use blueprints to quickly configure your device for common use cases. +- Compatible with all Sonoff TX Ultimate variants: + - EU format (Square, T5-xC-86) + - US format (Rectangle, T5-xC-120) + - 1/2/3/4 gang versions -## Documentation -To be written. +## Prerequisites + +Before getting started, ensure you have: + +1. A Sonoff TX Ultimate device +2. Home Assistant installation +3. ESPHome add-on installed in Home Assistant +4. Basic knowledge of Home Assistant + +## Installation + +Detailed installation instructions coming soon. The process will include: + +1. Initial ESPHome setup +2. Device flashing +3. Home Assistant integration +4. Basic configuration + +## Usage + +After installation, you can: + +1. Configure your device through Home Assistant UI +2. Customize touch behaviors +3. Set up LED patterns and effects +4. Create automations +5. Enable optional features like BLE proxy + +## Configuration Options + +TX Ultimate Easy offers extensive configuration options: + +- Touch panel sensitivity and gestures +- LED colors, patterns, and behaviors +- Relay modes and functions +- Audio and haptic feedback settings +- Network and connectivity options ## Contributing -We welcome contributions from the community. If you have ideas for new features, improvements, or bug fixes, please open an issue or submit a pull request. +We welcome contributions from the community! Here's how you can help: + +1. Fork the repository +2. Create a feature branch from `dev` +3. Make your changes +4. Submit a pull request targeting the `dev` branch + +Please ensure your code follows our standards: +- Passes all lint checks (YAML, C++, Markdown) +- Includes appropriate documentation +- Follows existing code style + +All pull requests should be made against the `dev` branch. We don't accept pull requests directly to `main` as it's reserved for stable releases. + +## Support and Community + +Need help? Here are your options: + +- **Bug Reports & Feature Requests**: Use [GitHub Issues](https://github.com/edwardtfn/TX-Ultimate-Easy/issues) for all bug reports and feature requests +- **Community Chat**: Join our [Discord Server](https://discord.gg/Db6WJWzWuf) for discussions and community interaction +- **Support the Project**: Consider supporting through Buy Me a Coffee + +Note: For proper tracking and resolution, all bug reports and feature requests must be submitted through GitHub Issues, not Discord. The Issues page can be found at: [Issues · edwardtfn/TX-Ultimate-Easy](https://github.com/edwardtfn/TX-Ultimate-Easy/issues) + +[![Buy Me a Coffee](https://www.buymeacoffee.com/assets/img/custom_images/yellow_img.png)](https://www.buymeacoffee.com/edwardfirmo) + +## Acknowledgments + +This project builds upon the work of several amazing projects and contributors: + +- [SmartHome yourself - SONOFF TX Ultimate for ESPHome](https://github.com/SmartHome-yourself/sonoff-tx-ultimate-for-esphome) +- [Un loco y su tecnología - Sonoff TX Ultimate with ESPHome](https://www.youtube.com/watch?v=58v8oqSQgXQ) + +Special thanks to all contributors and community members who help make this project better. ## License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. -## Acknowledgments - -This project is highly inspired by these other projects: -- [SmartHome yourself - SONOFF TX Ultimate for ESPHome (Custom Component)](https://github.com/SmartHome-yourself/sonoff-tx-ultimate-for-esphome) -- [Un loco y su tecnología - Sonoff TX Ultimate with ESPHome | Absolute power](https://www.youtube.com/watch?v=58v8oqSQgXQ) - -Thanks a lot for sharing all your discoveries and ideas. - -## Support - -If you find this project helpful, consider supporting us through Buy Me a Coffee: - -[![Buy Me a Coffee](https://www.buymeacoffee.com/assets/img/custom_images/yellow_img.png)](https://www.buymeacoffee.com/edwardfirmo) - +--- + TX Ultimate Easy Logo + diff --git a/TX-Ultimate-Easy-ESPHome.yaml b/TX-Ultimate-Easy-ESPHome.yaml index f171b9a..3b95ea8 100644 --- a/TX-Ultimate-Easy-ESPHome.yaml +++ b/TX-Ultimate-Easy-ESPHome.yaml @@ -1,3 +1,9 @@ +#################################################################################################### +##### TX Ultimate Easy for ESPHome ##### +##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### +#################################################################################################### +##### Author: edwardtfn - https://github.com/edwardtfn - https://buymeacoffee.com/edwardfirmo ##### +#################################################################################################### --- substitutions: name: tx-ultimate-easy