Sonoff TX Ultimate T5-3C-86 WIFI

Chip ESP32

Bardzo fajne przełącznik WIFI.
Wersja 3, 2, 1 kanałowe

Cechy:
Podświetlanie Neopixel
Wibracje.
Dźwięki w wersji oryginalnej Firmware.
Tryb Podświetlania w nocy.

Multi-Touch

Szybki dotyk palcem lub dłonią.
Przesunięcie całą dłonią w bok.
Przesunięcie 1 palcem w prawo lub lewo.
Wszystkie akcje, on_press on_release on_swipe_left on_swipe_right
on_full_touch_release on_long_touch_release

Wgrałem ESPHome, strona projektu https://github.com/SmartHome-yourself/sonoff-tx-ultimate-for-esphome

Wgrywałem też Tasmota ale aktualnie słabo to działa.


Aktualizacja: Można odtwarzać media/dźwięki.


Głośność nie poraża, ale jak ktoś chce dodać jakieś efekty to można to zrobić przez play media

2024-07-07T22:00:00Z


TX Ultimate inne ciekawe zastosowania.

Strona Autora ESPHome: https://github.com/PxPert/esphome

YT:
https://www.youtube.com/watch?v=AVS_tiUuSgQ

5 polubień

Niestety po aktualizacji esphome odtwarzanie dzwięków nie działa…

Prawdopodobnie w samym Esphome został wycięty mediaplayer, wiec nie działa.

Niby jest w nowej wersji ESPHome, ale korzysta z innych mechanizmów (speaker) i efekt jest taki że jeśli się zrobi dokładnie to co zaleca dokumentacja - brakuje RAM. Udało mi się w końcu skompilować działającą wersję ale musiałem wykorzystać pythona na PC z ESPhme w wersji ESPHome 2024.3.2

Z jakiego projektu Korzystasz? Jak możesz to wrzuć kod.

Tutaj inny projekt dla TXUltimate https://github.com/edwardtfn/TX-Ultimate-Easy niestety po któryś aktualizacjach ESPhome też miał problemy. Autor jest chyba w trakcie robienia poprawek. Różnica miedzy tym projektem powyżej jest taka że jest większa kontrola nad ustawieniami z poziomu HA bez modyfikowania kodu w ESP, kod jest podzielony na osobne pliki *.yam dla led, touch…

# NIE KOMPILOWAĆ, NIE WGRYWAĆ. dZIAŁA POPRAWNIE TYLKO Z ESP W WERSJI  ESPHome 2024.3.2 nie nowsza!!!!
# TUTAJ PLIK TYYLKO ZE WZGLĘDU NA UJAWNIENIE GO W BLOKU ESPHOMEBUILDER.
# KOMPILACJE REALIZOWAC NA PYTHONIE NA PC Z DOGRANYM ESP HOME
# AKTUALIZACJA FIRMWARE PRZEZ OTA LUB OTA NA WEBSERVER UWAGA NA HASŁA OTA

substitutions:
  name: "sonoff-ultimate-tx-1"  
  friendly_name: "Sonoff-Ultimate-TX-1" 

  relay_count: "2"

  toggle_relay_1_on_touch: "true"
  toggle_relay_2_on_touch: "true"
  toggle_relay_3_on_touch: "false"
  vibra_time: 150ms
  button_on_time: 5ms
  button_brightness: "0.7"
  button_color: "{0,0,100}"
  nightlight: "on"
  nightlight_brightness: "0.7"
  nightlight_color: "{80,70,0}"
  latitude: "51.203456°"
  longitude: "16.184321°"
  touch_brightness: "1"
  touch_color: "{0,100,100}"
  touch_effect: "Scan"
  long_press_brightness: "1"
  long_press_color: "{100,0,0}"
  long_press_effect: "Scan"

  multi_touch_brightness: "1"
  multi_touch_color: "{0,0,0}"
  multi_touch_effect: "Rainbow"

  swipe_left_brightness: "1"
  swipe_left_color: "{0,100,0}"
  swipe_left_effect: "Scan"

  swipe_right_brightness: "1"
  swipe_right_color: "{100,0,70}"
  swipe_right_effect: "Scan"

  relay_1_pin: GPIO18
  relay_2_pin: GPIO17
  relay_3_pin: GPIO27
  relay_4_pin: GPIO23

  vibra_motor_pin: GPIO21
  pa_power_pin: GPIO26

  led_pin: GPIO13
  status_led_pin: GPIO33

  uart_tx_pin: GPIO19
  uart_rx_pin: GPIO22
  audio_lrclk_pin: GPIO4
  audio_bclk_pin: GPIO2
  audio_sdata_pin: GPIO15
  touchpanel_power_pin: GPIO5

esphome:
  name: ${name}
  friendly_name: ${friendly_name}
  project:
    name: smarthomeyourself.tx_ultimate
    version: "1.0"

  on_boot:
    priority: -100
    then:
      - binary_sensor.template.publish:
          id: touchfield_1
          state: OFF
      - binary_sensor.template.publish:
          id: touchfield_2
          state: OFF
      - binary_sensor.template.publish:
          id: touchfield_3
          state: OFF
      - binary_sensor.template.publish:
          id: multi_touch
          state: OFF
      - binary_sensor.template.publish:
          id: swipe_left
          state: OFF
      - binary_sensor.template.publish:
          id: swipe_right
          state: OFF
      - binary_sensor.template.publish:
          id: long_press
          state: OFF
      - script.execute: refresh_led_default
      - script.execute: refresh_nightlight

external_components:
  - source: github://esphome/esphome@2023.12.9
    components: [ i2s_audio, media_player, web_server ]
  - source: github://SmartHome-yourself/sonoff-tx-ultimate-for-esphome@main
    components: [ tx_ultimate_touch ]

esp32:
  board: esp32dev
  framework:
    type: arduino

logger:
  level: DEBUG
  logs:
    binary_sensor: INFO
    light: INFO
    script: INFO
    switch: INFO
    tx_ultimate_touch: INFO
    uart_debug: INFO

api:

web_server:
  port: 80
  version: 2

ota:

wifi:
  # Wpisz tutaj swoje dane, bez użycia !secrets
  ssid: "siec"
  password: "pass"
  
  manual_ip:
    static_ip: 192.168.999.999
    gateway: 192.168.1.1     
    subnet: 255.255.255.0
    dns1: 192.168.8.1

  ap:
    ssid: "Sonoff_fallback"
    password: "12345678"

improv_serial:

captive_portal:

globals:
  - id: nightlight_color
    type: int [3]
    restore_value: no
    initial_value: ${nightlight_color}
  - id: button_color
    type: int [3]
    restore_value: no
    initial_value: ${button_color}
  - id: long_press_color
    type: int [3]
    restore_value: no
    initial_value: ${long_press_color}
  - id: multi_touch_color
    type: int [3]
    restore_value: no
    initial_value: ${multi_touch_color}
  - id: swipe_left_color
    type: int [3]
    restore_value: no
    initial_value: ${swipe_left_color}
  - id: swipe_right_color
    type: int [3]
    restore_value: no
    initial_value: ${swipe_right_color}
  - id: touch_color
    type: int [3]
    restore_value: no
    initial_value: ${touch_color}    

binary_sensor:
  - platform: template
    name: "Touchfield 1"
    id: touchfield_1
    on_press:
      if:
        condition:
          lambda: "return ${toggle_relay_1_on_touch};"
        then:
          - switch.toggle: relay_1
          - delay: ${button_on_time}
          - binary_sensor.template.publish: { id: touchfield_1, state: OFF }
          - script.execute: refresh_led_default

  - platform: template
    name: "Touchfield 2"
    id: touchfield_2
    on_press:
      if:
        condition:
          lambda: "return ${toggle_relay_2_on_touch};"
        then:
          - switch.toggle: relay_2
          - delay: ${button_on_time}
          - binary_sensor.template.publish: { id: touchfield_2, state: OFF }
          - script.execute: refresh_led_default

  - platform: template
    name: "Touchfield 3"
    id: touchfield_3
    on_press:
      if:
        condition:
          lambda: "return ${toggle_relay_3_on_touch};"
        then:
          - switch.toggle: relay_3
          - delay: ${button_on_time}
          - binary_sensor.template.publish: { id: touchfield_3, state: OFF }
          - script.execute: refresh_led_default

  - platform: template
    name: "Swipe left"
    id: swipe_left
    on_press:
      - delay: ${button_on_time}
      - binary_sensor.template.publish: { id: swipe_left, state: OFF }
      - script.execute: refresh_led_default

  - platform: template
    name: "Swipe_right"
    id: swipe_right
    on_press:
      - delay: ${button_on_time}
      - binary_sensor.template.publish: { id: swipe_right, state: OFF }
      - script.execute: refresh_led_default

  - platform: template
    name: "Multi Touch"
    id: multi_touch
    on_press:
      - delay: ${button_on_time}
      - binary_sensor.template.publish: { id: multi_touch, state: OFF }
      - script.execute: refresh_led_default

  - platform: template
    name: "Long Press"
    id: long_press
    on_press:
      - delay: ${button_on_time}
      - binary_sensor.template.publish: { id: long_press, state: OFF }
      - script.execute: refresh_led_default

switch:
  - platform: gpio
    id: relay_1
    name: "${friendly_name} L1"
    pin: ${relay_1_pin}
    restore_mode: RESTORE_DEFAULT_OFF
    on_turn_on:
      then:
        - script.execute: refresh_led_default
    on_turn_off:
      then:
        - script.execute: refresh_led_default

  - platform: gpio
    id: relay_2
    name: "${friendly_name} L2"
    pin: ${relay_2_pin}
    restore_mode: RESTORE_DEFAULT_OFF
    on_turn_on:
      then:
        - script.execute: refresh_led_default
    on_turn_off:
      then:
        - script.execute: refresh_led_default

  - platform: gpio
    id: relay_3
    name: "${friendly_name} L3"
    pin: ${relay_3_pin}
    restore_mode: RESTORE_DEFAULT_OFF
    on_turn_on:
      then:
        - script.execute: refresh_led_default
    on_turn_off:
      then:
        - script.execute: refresh_led_default

  - platform: gpio
    id: vibra
    pin: ${vibra_motor_pin}
    name: "${friendly_name} Vibration"
    restore_mode: ALWAYS_OFF
    on_turn_on:
      - delay: ${vibra_time}
      - switch.turn_off: vibra

  - platform: gpio
    id: pa_power
    pin: ${pa_power_pin}
    name: "PA Power"
    internal: true
    restore_mode: ALWAYS_ON

  - platform: gpio
    name: "touch panel power"
    pin:
      number: ${touchpanel_power_pin}
      inverted: true
    id: touch_power
    internal: true
    restore_mode: RESTORE_DEFAULT_ON

  - platform: template
    name: "Nightlight"
    id: nightlight
    internal: true
    optimistic: true
    restore_mode: RESTORE_DEFAULT_OFF
    on_turn_on:
      then:
        - script.execute: refresh_led_default
    on_turn_off:
      then:
        - script.execute: refresh_led_default

  - platform: template
    name: "Nightlight"
    id: nightlight_active
    optimistic: true
    restore_mode: RESTORE_DEFAULT_OFF
    on_turn_on:
      then:
        - script.execute: refresh_led_default
    on_turn_off:
      then:
        - script.execute: refresh_led_default

  - platform: restart
    name: "${friendly_name} Restart"

light:
  - platform: neopixelbus
    type: GRB
    variant: WS2811
    pin: ${led_pin}
    num_leds: 28
    name: "NeoPixel Light"
    id: leds
    default_transition_length: 0s
    effects:
      - addressable_rainbow:
          name: "Rainbow"
          speed: 30
          width: 8
      - pulse:
          name: "Pulse"
          transition_length: 1.4s
          update_interval: 1s

    on_turn_off:
      then:
        - script.execute: refresh_led_default

  - platform: partition
    name: "LEDs Button right"
    id: leds_button_right
    internal: true
    segments:
      - id: leds
        from: 7
        to: 7
  - platform: partition
    name: "LEDs Button middle"
    id: leds_button_middle
    internal: true
    segments:
      - id: leds
        from: 9
        to: 9
  - platform: partition
    name: "LEDs Button left"
    id: leds_button_left
    internal: true
    segments:
      - id: leds
        from: 11
        to: 11

  - platform: partition
    name: "LEDs Nightlight"
    id: leds_nightlight
    internal: true
    segments:
      - id: leds
        from: 0
        to: 6
      - id: leds
        from: 8
        to: 8
      - id: leds
        from: 10
        to: 10
      - id: leds
        from: 12
        to: 19
      - id: leds
        from: 27
        to: 27
      - id: leds_top
        from: 0
        to: 6

  - platform: partition
    name: "LEDs Top"
    id: leds_top
    internal: true
    segments:
      - id: leds
        from: 20
        to: 26
    effects:
      - addressable_scan:
          name: "Scan"
      - addressable_rainbow:
          name: "Rainbow"
          speed: 10
          width: 20

i2s_audio:
  id: audio_i2s
  i2s_lrclk_pin: GPIO4
  i2s_bclk_pin: GPIO2

# Stara, stabilna definicja media_player:
media_player:
  - platform: i2s_audio
    name: "Głośnik Łazienka Dół"
    i2s_audio_id: audio_i2s
    i2s_dout_pin: GPIO15
    dac_type: external
    i2s_comm_fmt: lsb
    mode: mono
    #buffer_duration wywalamy stąd, bo w starej wersji to nie istnieje!

uart:
  tx_pin: ${uart_tx_pin}
  rx_pin: ${uart_rx_pin}
  id: my_uart
  baud_rate: 115200
  data_bits: 8
  stop_bits: 1
  parity: NONE
  debug:
    direction: RX
    dummy_receiver: false
    after:
      timeout: 2s
      bytes: 2048
    sequence:
      - lambda: UARTDebug::log_hex(direction, bytes, ' ');

tx_ultimate_touch:
  id: tx_touch
  uart: my_uart

  on_press:
    - script.execute: led_on_touch
    - lambda: >
        ESP_LOGD("tx_ultimate_touch.on_press", "Touch Position: %d / State: %d", touch.x, touch.state);
  on_release:
    - script.execute:
        id: handle_release
        pos: !lambda "return touch.x;"
    - switch.turn_on: vibra
    - lambda: >
        ESP_LOGD("tx_ultimate_touch.on_release", "Release Position: %d / State: %d", touch.x, touch.state);
  on_swipe_left:
    - script.execute: led_on_swipe_left
    - switch.turn_on: vibra
    - binary_sensor.template.publish:
        id: swipe_left
        state: ON
    - lambda: >
        ESP_LOGD("tx_ultimate_touch.on_swipe_left", "Swipe Left Position: %d / State: %d", touch.x, touch.state);
  on_swipe_right:
    - script.execute: led_on_swipe_right
    - switch.turn_on: vibra
    - binary_sensor.template.publish:
        id: swipe_right
        state: ON
    - lambda: >
        ESP_LOGD("tx_ultimate_touch.on_swipe_right", "Swipe Right Position: %d / State: %d", touch.x, touch.state);
  on_full_touch_release:
    - script.execute: led_on_full_touch
    - switch.turn_on: vibra
    - binary_sensor.template.publish:
        id: multi_touch
        state: ON
    - lambda: >
        ESP_LOGD("tx_ultimate_touch.on_full_touch_release", "Full Touch Release Position: %d / State: %d", touch.x, touch.state);
  on_long_touch_release:
    - script.execute: led_on_long_touch
    - switch.turn_on: vibra
    - binary_sensor.template.publish:
        id: long_press
        state: ON
    - lambda: >
        ESP_LOGD("tx_ultimate_touch.on_long_touch_release", "Long Touch Release Position: %d / State: %d", touch.x, touch.state);

time:
  - platform: homeassistant
  - platform: sntp
    on_time:
      - seconds: 0
        minutes: /5
        then:
          - script.execute: refresh_nightlight

sun:
  latitude: ${latitude}
  longitude: ${longitude}

script:
  - id: refresh_nightlight
    mode: restart
    then:
      - if:
          condition:
            lambda: 'return "${nightlight}" == "on";'
          then:
            - if:
                condition:
                  - sun.is_below_horizon:
                then:
                  - switch.turn_on: nightlight
                else:
                  - switch.turn_off: nightlight

  - id: refresh_led_default
    mode: restart
    then:
      - light.turn_off: leds_top

      - if:
          condition:
            lambda: "return (${relay_count}>1 && id(relay_1).state) ;"
          then:
            - script.execute: led_on_button_left
          else:
            - script.execute: led_off_button_left

      - if:
          condition:
            lambda: "return (${relay_count}==3 && id(relay_2).state) || (${relay_count}==1 && id(relay_1).state);"
          then:
            - script.execute: led_on_button_middle
          else:
            - script.execute: led_off_button_middle

      - if:
          condition:
            lambda: "return (${relay_count}==2 && id(relay_2).state) || (${relay_count}==3 && id(relay_3).state);"
          then:
            - script.execute: led_on_button_right
          else:
            - script.execute: led_off_button_right

      - if:
          condition:
            lambda: "return id(nightlight).state || id(nightlight_active).state;"
          then:
            - script.execute: led_on_nightlight
          else:
            - light.turn_off: leds_nightlight

  - id: led_on_button_left
    mode: restart
    then:
      - light.turn_on:
          id: leds_button_left
          brightness: ${button_brightness}
          red: !lambda "return id(button_color)[0]/100.0;"
          green: !lambda "return id(button_color)[1]/100.0;"
          blue:  !lambda "return id(button_color)[2]/100.0;"

  - id: led_on_button_middle
    mode: restart
    then:
      - light.turn_on:
          id: leds_button_middle
          brightness: ${button_brightness}
          red: !lambda "return id(button_color)[0]/100.0;"
          green: !lambda "return id(button_color)[1]/100.0;"
          blue:  !lambda "return id(button_color)[2]/100.0;"

  - id: led_on_button_right
    mode: restart
    then:
      - light.turn_on:
          id: leds_button_right
          brightness: ${button_brightness}
          red: !lambda "return id(button_color)[0]/100.0;"
          green: !lambda "return id(button_color)[1]/100.0;"
          blue:  !lambda "return id(button_color)[2]/100.0;"

  - id: led_off_button_left
    mode: restart
    then:
      - if:
          condition:
            lambda: "return id(nightlight).state || id(nightlight_active).state;"
          then:
            - light.turn_on:
                id: leds_button_left
                brightness: ${nightlight_brightness}
                red: !lambda "return id(nightlight_color)[0]/100.0;"
                green: !lambda "return id(nightlight_color)[1]/100.0;"
                blue:  !lambda "return id(nightlight_color)[2]/100.0;"
          else:
            - light.turn_off:
                id: leds_button_left

  - id: led_off_button_middle
    mode: restart
    then:
      - if:
          condition:
            lambda: "return id(nightlight).state || id(nightlight_active).state;"
          then:
            - light.turn_on:
                id: leds_button_middle
                brightness: ${nightlight_brightness}
                red: !lambda "return id(nightlight_color)[0]/100.0;"
                green: !lambda "return id(nightlight_color)[1]/100.0;"
                blue:  !lambda "return id(nightlight_color)[2]/100.0;"
          else:
            - light.turn_off:
                id: leds_button_middle

  - id: led_off_button_right
    mode: restart
    then:
      - if:
          condition:
            lambda: "return id(nightlight).state || id(nightlight_active).state;"
          then:
            - light.turn_on:
                id: leds_button_right
                brightness: ${nightlight_brightness}
                red: !lambda "return id(nightlight_color)[0]/100.0;"
                green: !lambda "return id(nightlight_color)[1]/100.0;"
                blue:  !lambda "return id(nightlight_color)[2]/100.0;"
          else:
            - light.turn_off:
                id: leds_button_right

  - id: led_on_nightlight
    mode: restart
    then:
      - light.turn_on:
          id: leds_nightlight
          brightness: ${nightlight_brightness}
          red: !lambda "return id(nightlight_color)[0]/100.0;"
          green: !lambda "return id(nightlight_color)[1]/100.0;"
          blue:  !lambda "return id(nightlight_color)[2]/100.0;"

  - id: led_on_release
    mode: restart
    then:
      - light.turn_off:
          id: leds_top

  - id: led_on_touch
    mode: restart
    then:
      - light.turn_on:
          id: leds_top
          brightness: ${touch_brightness}
          red: !lambda "return id(touch_color)[0]/100.0;"
          green: !lambda "return id(touch_color)[1]/100.0;"
          blue:  !lambda "return id(touch_color)[2]/100.0;"
          effect: ${touch_effect}
      - delay: 6s
      - script.execute: refresh_led_default

  - id: led_on_swipe_left
    mode: restart
    then:
      - light.turn_on:
          id: leds_top
          brightness: ${swipe_left_brightness}
          red: !lambda "return id(swipe_left_color)[0]/100.0;"
          green: !lambda "return id(swipe_left_color)[1]/100.0;"
          blue:  !lambda "return id(swipe_left_color)[2]/100.0;"
          effect: ${swipe_left_effect}

  - id: led_on_swipe_right
    mode: restart
    then:
      - light.turn_on:
          id: leds_top
          brightness: ${swipe_right_brightness}
          red: !lambda "return id(swipe_right_color)[0]/100.0;"
          green: !lambda "return id(swipe_right_color)[1]/100.0;"
          blue:  !lambda "return id(swipe_right_color)[2]/100.0;"
          effect: ${swipe_right_effect}

  - id: led_on_full_touch
    mode: restart
    then:
      - light.turn_on:
          id: leds_top
          brightness: ${multi_touch_brightness}
          red: !lambda "return id(multi_touch_color)[0]/100.0;"
          green: !lambda "return id(multi_touch_color)[1]/100.0;"
          blue:  !lambda "return id(multi_touch_color)[2]/100.0;"
          effect: ${multi_touch_effect}

  - id: led_on_long_touch
    mode: restart
    then:
      - light.turn_on:
          id: leds_top
          brightness: ${long_press_brightness}
          red: !lambda "return id(long_press_color)[0]/100.0;"
          green: !lambda "return id(long_press_color)[1]/100.0;"
          blue:  !lambda "return id(long_press_color)[2]/100.0;"
          effect: ${long_press_effect}

  - id: handle_release
    mode: restart
    parameters:
      pos: int
    then:
      - if:
          condition:
            lambda: "return ${relay_count}==1;"
          then:
            - binary_sensor.template.publish:
                id: touchfield_1
                state: ON

      - if:
          condition:
            lambda: "return ${relay_count}==2;"
          then:
            - if:
                condition:
                  lambda: "return pos <= 5;"
                then:
                  - binary_sensor.template.publish:
                      id: touchfield_1
                      state: ON
                else:
                  - binary_sensor.template.publish:
                      id: touchfield_2
                      state: ON

      - if:
          condition:
            lambda: "return ${relay_count}==3;"
          then:
            - if:
                condition:
                  lambda: "return pos <= 3;"
                then:
                  - binary_sensor.template.publish:
                      id: touchfield_1
                      state: ON
                else:
                  - if:
                      condition:
                        lambda: "return pos <= 7;"
                      then:
                        - binary_sensor.template.publish:
                            id: touchfield_2
                            state: ON
                      else:
                        - binary_sensor.template.publish:
                            id: touchfield_3
                            state: ON


1 polubienie