light: | |
- platform: neopixelbus | |
type: GRB | |
variant: WS2812 | |
pin: GPIO1 | |
num_leds: 1 | |
name: "NeoPixel 1" | |
internal: true | |
- platform: neopixelbus | |
type: GRB | |
variant: WS2812 | |
pin: GPIO3 | |
num_leds: 1 | |
name: "NeoPixel 3" | |
internal: true | |
- platform: neopixelbus | |
type: GRB | |
variant: WS2812 | |
pin: GPIO5 | |
num_leds: 1 | |
name: "NeoPixel 5" | |
internal: true | |
- platform: neopixelbus | |
type: GRB | |
variant: WS2812 | |
pin: GPIO13 | |
num_leds: 1 | |
name: "NeoPixel 13" | |
internal: true | |
- platform: neopixelbus | |
type: GRB | |
variant: WS2812 | |
pin: GPIO32 | |
num_leds: 1 | |
name: "NeoPixel 32" | |
internal: true | |
- platform: neopixelbus | |
type: GRB | |
variant: WS2812 | |
# pin: GPIO20 | |
pin: GPIO33 | |
num_leds: 28 | |
name: "Ambience Nightlight" | |
id: rgb_light | |
effects: | |
- addressable_twinkle: | |
- addressable_random_twinkle: | |
- addressable_rainbow: | |
name: 'rainbow slow' | |
speed: 5 | |
- addressable_rainbow: | |
name: 'rainbow fast' | |
speed: 50 | |
- addressable_rainbow: | |
name: 'rainbow superfast' | |
speed: 100 | |
restore_mode: RESTORE_DEFAULT_OFF | |
# - platform: partition | |
# id: light_left_top | |
# name: "light left top" | |
# segments: | |
# - id: rgb_light | |
# from: 20 | |
# to: 20 | |
# - platform: partition | |
# id: light_middle_top | |
# name: "light middle top" | |
# segments: | |
# - id: rgb_light | |
# from: 23 | |
# to: 23 | |
# - platform: partition | |
# id: light_right_top | |
# name: "light right top" | |
# segments: | |
# - id: rgb_light | |
# from: 26 | |
# to: 27 | |
# - platform: partition | |
# id: light_left_bottom | |
# name: "light left bottom" | |
# segments: | |
# - id: rgb_light | |
# from: 6 | |
# to: 7 | |
# - platform: partition | |
# id: light_middle_bottom | |
# name: "light middle bottom" | |
# segments: | |
# - id: rgb_light | |
# from: 8 | |
# to: 10 | |
# - platform: partition | |
# id: light_right_bottom | |
# name: "light right bottom" | |
# segments: | |
# - id: rgb_light | |
# from: 11 | |
# to: 12 | |
- platform: partition | |
restore_mode: RESTORE_DEFAULT_OFF | |
id: light_left_both | |
name: "light left both" | |
segments: | |
- id: rgb_light | |
from: 11 | |
to: 21 | |
effects: | |
- addressable_twinkle: | |
- addressable_random_twinkle: | |
- addressable_rainbow: | |
speed: 5 | |
- platform: partition | |
restore_mode: RESTORE_DEFAULT_OFF | |
id: light_middle_both | |
name: "light middle both" | |
segments: | |
- id: rgb_light | |
from: 22 | |
to: 24 | |
- id: rgb_light | |
from: 8 | |
to: 10 | |
effects: | |
- addressable_twinkle: | |
- addressable_random_twinkle: | |
- addressable_rainbow: | |
speed: 5 | |
- platform: partition | |
restore_mode: RESTORE_DEFAULT_OFF | |
id: light_right_both | |
name: "light right both" | |
segments: | |
- id: rgb_light | |
from: 0 | |
to: 7 | |
- id: rgb_light | |
from: 25 | |
to: 27 | |
effects: | |
- addressable_twinkle: | |
- addressable_random_twinkle: | |
- addressable_rainbow: | |
speed: 5 | |
- platform: partition | |
restore_mode: RESTORE_DEFAULT_OFF | |
id: light_right | |
name: "light right" | |
segments: | |
- id: rgb_light | |
from: 0 | |
to: 5 | |
# - platform: partition | |
# id: light_bottom | |
# name: "light bottom" | |
# segments: | |
# - id: rgb_light | |
# from: 6 | |
# to: 12 | |
- platform: partition | |
restore_mode: RESTORE_DEFAULT_OFF | |
id: light_left | |
name: "light left" | |
segments: | |
- id: rgb_light | |
from: 13 | |
to: 19 | |
# - platform: partition | |
# id: light_top | |
# name: "light top" | |
# segments: | |
# - id: rgb_light | |
# from: 20 | |
# to: 26 |
condition: | |
switch.is_on: ${switch} | |
then: | |
- light.turn_on: | |
id: ${light} | |
brightness: ${on_brightness} | |
red: ${on_red} | |
green: ${on_green} | |
blue: ${on_blue} | |
transition_length: 500ms | |
else: | |
- if: | |
condition: | |
and: | |
- lambda: |- | |
return id(htime).now().hour < ${nightlight_on_hour}; | |
- lambda: |- | |
return id(htime).now().hour > ${nightlight_off_hour}; | |
then: | |
- light.turn_off: | |
id: ${light} | |
transition_length: 500ms | |
else: | |
- light.turn_on: | |
id: ${light} | |
brightness: ${nightlight_brightness} | |
red: ${nightlight_red} | |
green: ${nightlight_green} | |
blue: ${nightlight_blue} | |
transition_length: 500ms |
substitutions: | |
name: 'sonoff_tx_ultimate_00' | |
on_brightness: 50% | |
on_red: 100% | |
on_green: 40% | |
on_blue: 0% | |
nightlight_brightness: 20% | |
nightlight_red: 100% | |
nightlight_green: 40% | |
nightlight_blue: 0% | |
nightlight_on_hour: '19' # turn on at 7 in the evening | |
nightlight_off_hour: '9' # turn off at 9 in the morning | |
esphome: | |
name: $name | |
platform: ESP32 | |
board: esp32dev | |
on_boot: | |
priority: -100.0 | |
then: | |
- script.execute: light_relays | |
includes: | |
- touch_panel.hpp | |
- touch_panel.cpp | |
uart: | |
id: uart_bus | |
tx_pin: GPIO19 | |
rx_pin: GPIO22 | |
baud_rate: 115200 | |
script: | |
- id: light_relays | |
then: | |
- if: !include | |
file: relays_light.yaml | |
vars: | |
switch: relay1 | |
light: light_left_both | |
- if: !include | |
file: relays_light.yaml | |
vars: | |
switch: relay2 | |
light: light_middle_both | |
- if: !include | |
file: relays_light.yaml | |
vars: | |
switch: relay3 | |
light: light_right_both | |
binary_sensor: | |
- platform: custom | |
lambda: |- | |
auto touch_panel = new touch_panel::TouchPanel(id(uart_bus)); | |
App.register_component(touch_panel); | |
return { | |
touch_panel->left, | |
touch_panel->middle, | |
touch_panel->right, | |
touch_panel->two_finger, | |
touch_panel->dragged_ltr, | |
touch_panel->dragged_rtl, | |
}; | |
binary_sensors: | |
- id: button_left | |
name: "Left Button" | |
on_press: | |
- switch.toggle: relay1 | |
- switch.turn_on: haptics | |
- id: button_middle | |
name: "Middle Button" | |
on_press: | |
- switch.toggle: relay2 | |
- switch.turn_on: haptics | |
- id: button_right | |
name: "Right Button" | |
on_press: | |
- switch.toggle: relay3 | |
- switch.turn_on: haptics | |
- id: button_two_finger | |
name: "Two Fingers" | |
- id: button_dragged_ltr | |
name: "Dragged Left to Right" | |
- id: button_dragged_rtl | |
name: "Dragged Right to Left" |
switch: | |
- platform: gpio | |
name: "relay left" | |
pin: GPIO18 | |
id: relay1 | |
on_turn_on: | |
script.execute: light_relays | |
on_turn_off: | |
script.execute: light_relays | |
- platform: gpio | |
name: "relay middle" | |
pin: GPIO17 | |
id: relay2 | |
on_turn_on: | |
script.execute: light_relays | |
on_turn_off: | |
script.execute: light_relays | |
- platform: gpio | |
name: "relay right" | |
pin: GPIO27 | |
id: relay3 | |
on_turn_on: | |
script.execute: light_relays | |
on_turn_off: | |
script.execute: light_relays | |
- platform: gpio | |
name: "relay right" | |
pin: GPIO23 | |
id: relay4 | |
on_turn_on: | |
script.execute: light_relays | |
on_turn_off: | |
script.execute: light_relays | |
- platform: gpio | |
name: "sound amplifier power" | |
pin: GPIO26 | |
id: pa_sw | |
- platform: gpio | |
name: "touch panel power" | |
pin: | |
number: GPIO5 | |
inverted: true | |
id: ca51_pow | |
restore_mode: ALWAYS_ON | |
- platform: gpio | |
pin: GPIO21 | |
name: "Haptics" | |
id: "haptics" | |
restore_mode: ALWAYS_OFF | |
on_turn_on: | |
- delay: 300ms | |
- switch.turn_off: haptics |
#include "touch_panel.hpp" | |
#include <stdio.h> | |
namespace esphome | |
{ | |
namespace touch_panel | |
{ | |
#define MIN(a, b) (((a) < (b)) ? (a) : (b)) | |
#define MAX(a, b) (((a) > (b)) ? (a) : (b)) | |
const uint8_t PREFIX[] = {0xAA, 0x55, 0x01, 0x02}; | |
const unsigned int PREFIX_LENGTH = sizeof(PREFIX) / sizeof(PREFIX[0]); | |
// Messages consist of a prefix, a type of action and a position. | |
// There's probably other stuff but that's not relevant for us | |
const unsigned int MESSAGE_SIZE = PREFIX_LENGTH + 4; | |
const unsigned int BUFFER_SIZE = 32; | |
TouchPanel::TouchPanel(uart::UARTComponent *parent) : uart::UARTDevice(parent) {} | |
void TouchPanel::setup() | |
{ | |
for (int i = 0; i < button_map.size(); i++) | |
button_map[i]->publish_state(i < TwoFinger); | |
} | |
void TouchPanel::loop() | |
{ | |
static uint8_t buffer[BUFFER_SIZE]; | |
while (available() >= MESSAGE_SIZE) | |
{ | |
read_array(buffer, MIN(available(), BUFFER_SIZE)); | |
bool match = true; | |
if (memcmp(buffer, PREFIX, PREFIX_LENGTH) != 0) | |
{ | |
continue; | |
} | |
if (match) | |
{ | |
TouchEvent event = static_cast<TouchEvent>(buffer[4]); | |
uint8_t released_position = buffer[5]; | |
uint8_t pressed_position = buffer[6]; | |
if (event == Pressed) | |
{ | |
// ESP_LOGD("custom", "Pressed: %d", pressed_position); | |
button_map[pressed_position]->publish_state(true); | |
// Always trigger the two-fingered and drag events since we can only detect when they are released | |
two_finger->publish_state(true); | |
dragged_ltr->publish_state(true); | |
dragged_rtl->publish_state(true); | |
} | |
else if (event == Released || event == Dragged) | |
{ | |
// Make sure to reset all buttons | |
for (int i = 0; i < TwoFinger; i++) | |
button_map[i]->publish_state(false); | |
button_map[released_position]->publish_state(false); | |
} | |
else | |
{ | |
ESP_LOGD("custom", "Unknown event: %d", event); | |
} | |
} | |
} | |
} | |
} // namespace touch_panel | |
} // namespace esphome |
#pragma once | |
#include "esphome/core/component.h" | |
#include "esphome/components/uart/uart.h" | |
#include "esphome/components/binary_sensor/binary_sensor.h" | |
#include <vector> | |
namespace esphome | |
{ | |
namespace touch_panel | |
{ | |
enum TouchEvent | |
{ | |
Released = 1, | |
Pressed = 2, | |
Dragged = 3 | |
}; | |
enum TouchPosition | |
{ | |
Left = 1, | |
Middle = 4, | |
Right = 7, | |
TwoFinger = 11, | |
DraggedLTR = 12, | |
DraggedRTL = 13 | |
}; | |
class TouchPanel : public Component, public uart::UARTDevice | |
{ | |
public: | |
TouchPanel(uart::UARTComponent *parent); | |
void setup() override; | |
void loop() override; | |
float get_setup_priority() const override { return esphome::setup_priority::BUS; } | |
binary_sensor::BinarySensor *left = new binary_sensor::BinarySensor(); | |
binary_sensor::BinarySensor *middle = new binary_sensor::BinarySensor(); | |
binary_sensor::BinarySensor *right = new binary_sensor::BinarySensor(); | |
binary_sensor::BinarySensor *two_finger = new binary_sensor::BinarySensor(); | |
binary_sensor::BinarySensor *dragged_ltr = new binary_sensor::BinarySensor(); | |
binary_sensor::BinarySensor *dragged_rtl = new binary_sensor::BinarySensor(); | |
protected: | |
// For positional tracking | |
std::vector<binary_sensor::BinarySensor *> button_map = { | |
left, // 0 never occurs but is here for completeness | |
left, // 1-3 is left | |
left, | |
left, | |
middle, // 4-6 is middle | |
middle, | |
middle, | |
right, // 7-10 is right | |
right, | |
right, | |
right, | |
two_finger, // 11 is two fingers (released only) | |
dragged_ltr, // 12 is drag left to right | |
dragged_rtl, // 13 is drag right to left | |
}; | |
}; | |
} // namespace adalight | |
} // namespace esphome |
@wolph Mind giving me a hint on how to actually backup the stock firmware? I tried the read_flash
command of esptool
but it keeps throwing me the same error, even though I made sure that I'm in boot mode:
$ esptool.py -p /dev/cu.usbserial-210 -b 460800 read_flash 0 ALL tx-ultimate-stock.bin
esptool.py v4.8.1
Serial port /dev/cu.usbserial-210
Connecting.....
Detecting chip type... Unsupported detection protocol, switching and trying again...
Connecting...
Detecting chip type... ESP32
Chip is ESP32-D0WDR2-V3 (revision v3.1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: fe:b4:67:b8:f6:11
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
Configuring flash size...
Detected flash size: 8MB
A fatal error occurred: Invalid head of packet (0x7F): Possible serial noise or corruption.
@0xAhmed You can try lowering the baud rate, I've found that 460800 (or higher) only works with short high quality USB cables and even in those cases it's not guaranteed to work.
Try it with 115200 and see if you still get the error.
Alternatively... it could be that the flash size is detected incorrectly, but I think I remember the tx ultimate having 8MB so it should be correct.
You can read the flash size with this command:
esptool.py -p /dev/cu.usbserial-210 flash_id
[Edit]
I just remember another potential issue with these... they draw quite a bit of power so it could be that you need an extra/external 5v power supply. I can't get the tx ultimate to work reliably off my usb2serial adapter alone.
Thank you so much @wolph. I completed overlooked the fact that the baud rate might be the problem. I just tried with an ESP32-WROOM chip (was getting the same error message on it) and it worked fine. Shall try with another TX Ultimate switch later.
Anybody ever get the sound to be as loud as the stock firmware. mine works but its very , very low.
media_player:
- platform: i2s_audio
id: media_out
name: ${friendly_name} Player
dac_type: external
i2s_dout_pin: ${audio_sdata_pin}
i2s_audio_id: audio_i2s
i2s_comm_fmt: lsb
mode: mono
@MantasGSXR sorry to tell you but that backup won't help you. The firmwares are locked to the mac address so the backup won't work on your device unless it was made by your device