diff --git a/components/tx_ultimate_easy/tx_ultimate_easy.cpp b/components/tx_ultimate_easy/tx_ultimate_easy.cpp deleted file mode 100644 index d820448..0000000 --- a/components/tx_ultimate_easy/tx_ultimate_easy.cpp +++ /dev/null @@ -1,250 +0,0 @@ -// tx_ultimate_easy.cpp - -#include "esphome/core/log.h" -#include "tx_ultimate_easy.h" -#include -#include - -namespace esphome { - namespace tx_ultimate_easy { - - void TxUltimateEasy::setup() { - ESP_LOGI(TAG, "TX Ultimate Easy is initialized"); - } - - void TxUltimateEasy::loop() { - bool found = false; - std::array uart_received_bytes{}; - int byte = -1; - int i = 0; - - while (this->available()) { - byte = this->read(); - if (byte == HEADER_BYTE_1) { - this->handle_touch(uart_received_bytes); - i = 0; - } - if (i < UART_RECEIVED_BYTES_SIZE) { - uart_received_bytes[i] = byte; - i++; - } - if (byte != 0x00) { - found = true; - } - } - if (found) this->handle_touch(uart_received_bytes); - } - - void TxUltimateEasy::handle_touch(const std::array &uart_received_bytes) { - ESP_LOGV(TAG, "------------"); - ESP_LOGV(TAG, "- UART-Log -"); - ESP_LOGV(TAG, "------------"); - for (int i = 0; i < UART_RECEIVED_BYTES_SIZE; i++) { - ESP_LOGV(TAG, "UART - Log - Byte[%i]: %i", i, uart_received_bytes[i]); - } - if (this->is_valid_data(uart_received_bytes)) { - this->send_touch_(this->get_touch_point(uart_received_bytes)); - } - } - - void TxUltimateEasy::dump_config() { - ESP_LOGCONFIG(TAG, "TX Ultimate Easy"); - ESP_LOGCONFIG(TAG, " Gang count: %" PRIu8, this->gang_count_); - } - - bool TxUltimateEasy::set_gang_count(const uint8_t gang_count) { - // Hardware supports maximum of 4 touch-sensitive buttons - if (gang_count < 1 or gang_count > 4) - return false; - this->gang_count_ = gang_count; - return true; - } - - uint8_t TxUltimateEasy::get_button_from_position(const uint8_t position) { - // Validate position bounds - if (position > TOUCH_MAX_POSITION) - return 0; - - // Special case for single gang (only one button exists) - if (this->gang_count_ == 1) - return 1; - - // Calculate button number Change to round up instead of truncate (integer division) - const uint8_t width = (TOUCH_MAX_POSITION + gang_count_) / this->gang_count_; // Width of each button region - if (width < 1) // Invalid width - and prevents division by zero - return 0; - const uint8_t button = std::min( - static_cast((position / width) + 1), // Convert position to button index - this->gang_count_ // Clamp to max gang count - ); - return button; - } - - void TxUltimateEasy::send_touch_(TouchPoint tp) { - this->trigger_touch_event_.trigger(tp); - switch (tp.state) { - case TOUCH_STATE_RELEASE: - if (tp.x >= 17) { - tp.x -= 16; - ESP_LOGV(TAG, "Long touch - Released (x=%d)", tp.x); - this->trigger_long_touch_release_.trigger(tp); - } else { - ESP_LOGV(TAG, "Touch - Released (x=%d)", tp.x); - this->trigger_release_.trigger(tp); - } - break; - - case TOUCH_STATE_PRESS: - ESP_LOGV(TAG, "Touch - Pressed (x=%d)", tp.x); - this->trigger_touch_.trigger(tp); - break; - - case TOUCH_STATE_SWIPE_LEFT: - ESP_LOGV(TAG, "Swipe - Left (x=%d)", tp.x); - this->trigger_swipe_left_.trigger(tp); - break; - - case TOUCH_STATE_SWIPE_RIGHT: - ESP_LOGV(TAG, "Swipe - Right (x=%d)", tp.x); - this->trigger_swipe_right_.trigger(tp); - break; - - case TOUCH_STATE_MULTI_TOUCH: - ESP_LOGV(TAG, "Multi touch - Released"); - this->trigger_multi_touch_release_.trigger(tp); - break; - - default: - break; - } - } - - bool TxUltimateEasy::is_valid_data(const std::array &uart_received_bytes) { - if (uart_received_bytes[0] != HEADER_BYTE_1 || - uart_received_bytes[1] != HEADER_BYTE_2 || - uart_received_bytes[2] != VALID_DATA_BYTE_2 || - uart_received_bytes[3] != VALID_DATA_BYTE_3) { - return false; - } - - int state = this->get_touch_state(uart_received_bytes); - return (state == TOUCH_STATE_PRESS || - state == TOUCH_STATE_RELEASE || - state == TOUCH_STATE_SWIPE_LEFT || - state == TOUCH_STATE_SWIPE_RIGHT || - state == TOUCH_STATE_MULTI_TOUCH) && - // Multi-touch events may have x < 0, all other events require valid x position - (uart_received_bytes[6] >= 0 || state == TOUCH_STATE_MULTI_TOUCH); - } - - int TxUltimateEasy::get_touch_position_x(const std::array &uart_received_bytes) { - switch (uart_received_bytes[4]) { - case TOUCH_STATE_RELEASE: - case TOUCH_STATE_MULTI_TOUCH: - return uart_received_bytes[5]; - - case TOUCH_STATE_SWIPE_LEFT: - case TOUCH_STATE_SWIPE_RIGHT: - // uart_received_bytes[5] indicates swipe direction: - // 12 = find last touch position (scan right to left) - // 13 = find first touch position (scan left to right) - // Bytes 6-7 contain a 10-bit bitmap of touch positions: - // Byte 7: bits 0-7 represent positions 1-8 - // Byte 6: bits 0-1 represent positions 9-10 - switch (uart_received_bytes[5]) { - case 12: - for (uint8_t i = 10; i > 0; i--) { - if (i > 8 - ? uart_received_bytes[6] & (1 << (i - 9)) - : uart_received_bytes[7] & (1 << (i - 1))) { - return i; - } - } - break; - case 13: - for (uint8_t i = 1; i <= 10; i++) { - if (i > 8 - ? uart_received_bytes[6] & (1 << (i - 9)) - : uart_received_bytes[7] & (1 << (i - 1))) { - return i; - } - } - break; - } - return uart_received_bytes[5]; - - default: - return uart_received_bytes[6]; - } - } - - int TxUltimateEasy::get_touch_state(const std::array &uart_received_bytes) { - int state = uart_received_bytes[4]; - if (state == TOUCH_STATE_PRESS && uart_received_bytes[5] != 0) - state = TOUCH_STATE_RELEASE; - if (state == TOUCH_STATE_RELEASE && uart_received_bytes[5] == TOUCH_STATE_MULTI_TOUCH) - state = TOUCH_STATE_MULTI_TOUCH; - if (state == TOUCH_STATE_SWIPE) { - state = (uart_received_bytes[5] == TOUCH_STATE_SWIPE_RIGHT) ? TOUCH_STATE_SWIPE_RIGHT : - (uart_received_bytes[5] == TOUCH_STATE_SWIPE_LEFT) ? TOUCH_STATE_SWIPE_LEFT : state; - } - return state; - } - - TouchPoint TxUltimateEasy::get_touch_point(const std::array &uart_received_bytes) { - TouchPoint tp; - tp.x = this->get_touch_position_x(uart_received_bytes); - if (tp.x >= 0) - tp.button = this->get_button_from_position(static_cast(tp.x)); - tp.state = this->get_touch_state(uart_received_bytes); - switch (tp.state) { - case TOUCH_STATE_RELEASE: - tp.state_str = "RELEASE"; - break; - case TOUCH_STATE_PRESS: - tp.state_str = "PRESS"; - break; - case TOUCH_STATE_SWIPE: - tp.state_str = "SWIPE"; - break; - case TOUCH_STATE_MULTI_TOUCH: - tp.state_str = "MULTI_TOUCH"; - break; - case TOUCH_STATE_SWIPE_RIGHT: - tp.state_str = "SWIPE_RIGHT"; - break; - case TOUCH_STATE_SWIPE_LEFT: - tp.state_str = "SWIPE_LEFT"; - break; - default: - tp.state_str = "Unknown"; - break; - } - return tp; - } - - // LightAttributes - - // Constant definitions - const LightAttributes LIGHT_ATTRS_DEFAULT = {100, 255, 255, 255}; - const uint32_t LIGHT_ATTRS_DEFAULT_PACKED = 0x64FFFFFF; - - // Function implementations - uint32_t pack_light_attributes(const LightAttributes& attr) { - return (uint32_t(attr.brightness) << 24) | - (uint32_t(attr.red) << 16) | - (uint32_t(attr.green) << 8) | - (uint32_t(attr.blue)); - } - - LightAttributes unpack_light_attributes(uint32_t packed) { - return { - .brightness = uint8_t((packed >> 24) & 0xFF), - .red = uint8_t((packed >> 16) & 0xFF), - .green = uint8_t((packed >> 8) & 0xFF), - .blue = uint8_t(packed & 0xFF) - }; - } - - } // namespace tx_ultimate_easy -} // namespace esphome diff --git a/components/tx_ultimate_easy/tx_ultimate_easy.h b/components/tx_ultimate_easy/tx_ultimate_easy.h deleted file mode 100644 index 5175398..0000000 --- a/components/tx_ultimate_easy/tx_ultimate_easy.h +++ /dev/null @@ -1,154 +0,0 @@ -// tx_ultimate_easy.h - -#pragma once - -#include "esphome/core/automation.h" -#include "esphome/core/component.h" -#include "esphome/components/uart/uart.h" -#include "esphome/components/uart/uart_component.h" -#include "esphome/components/binary_sensor/binary_sensor.h" -#include "esphome/components/switch/switch.h" -#include "esphome/components/light/addressable_light.h" -#include - -namespace esphome { - namespace tx_ultimate_easy { - // Touch Max Position - constexpr uint8_t TOUCH_MAX_POSITION = 10; - - // Touch State Constants - constexpr uint8_t TOUCH_STATE_RELEASE = 0x01; - constexpr uint8_t TOUCH_STATE_PRESS = 0x02; - constexpr uint8_t TOUCH_STATE_SWIPE = 0x03; - constexpr uint8_t TOUCH_STATE_MULTI_TOUCH = 0x0B; - constexpr uint8_t TOUCH_STATE_SWIPE_RIGHT = 0x0C; - constexpr uint8_t TOUCH_STATE_SWIPE_LEFT = 0x0D; - - // UART Constants - constexpr int UART_RECEIVED_BYTES_SIZE = 15; - constexpr int HEADER_BYTE_1 = 0xAA; - constexpr int HEADER_BYTE_2 = 0x55; - constexpr int VALID_DATA_BYTE_2 = 0x01; - constexpr int VALID_DATA_BYTE_3 = 0x02; - - // Log tag - static const char *TAG = "tx_ultimate_easy"; - - struct TouchPoint { - uint8_t button = 0; - int8_t x = -1; - int8_t state = -1; - std::string state_str = "Unknown"; - }; - - class TxUltimateEasy : public uart::UARTDevice, public Component { - public: - Trigger *get_trigger_touch_event() { return &this->trigger_touch_event_; } - Trigger *get_trigger_touch() { return &this->trigger_touch_; } - Trigger *get_trigger_release() { return &this->trigger_release_; } - Trigger *get_trigger_swipe_left() { return &this->trigger_swipe_left_; } - Trigger *get_trigger_swipe_right() { return &this->trigger_swipe_right_; } - Trigger *get_trigger_multi_touch_release() { return &this->trigger_multi_touch_release_; } - Trigger *get_trigger_long_touch_release() { return &this->trigger_long_touch_release_; } - - void set_uart_component(esphome::uart::UARTComponent *uart_component) { this->set_uart_parent(uart_component); } - - void setup() override; - void loop() override; - void dump_config() override; - - uint8_t get_gang_count() { return this->gang_count_; } - bool set_gang_count(const uint8_t gang_count); - uint8_t get_button_from_position(const uint8_t position); - - protected: - void send_touch_(TouchPoint tp); - void handle_touch(const std::array &bytes); - - TouchPoint get_touch_point(const std::array &bytes); - bool is_valid_data(const std::array &bytes); - int get_touch_position_x(const std::array &bytes); - int get_touch_state(const std::array &bytes); - - Trigger trigger_touch_event_; - Trigger trigger_touch_; - Trigger trigger_release_; - Trigger trigger_swipe_left_; - Trigger trigger_swipe_right_; - Trigger trigger_multi_touch_release_; - Trigger trigger_long_touch_release_; - - uint8_t gang_count_ = 1; - - }; // class TxUltimateEasy - - /** - * @brief Light attributes structure for storing color and brightness data. - * - * This structure represents the visual attributes of a light without the state (on/off). - * It's designed to be packed efficiently into a 32-bit integer for NVS storage. - * RGB components use the full 8-bit range (0-255) while brightness uses percentage (0-100). - */ - struct LightAttributes { - uint8_t brightness; ///< Light brightness percentage (0-100, where 100 = full brightness) - uint8_t red; ///< Red color component (0-255) - uint8_t green; ///< Green color component (0-255) - uint8_t blue; ///< Blue color component (0-255) - }; - - /** - * @brief Packs LightAttributes structure into a 32-bit integer for storage. - * - * Bit layout: [brightness(8)][red(8)][green(8)][blue(8)] - * This allows efficient storage in ESPHome globals with restore_value support. - * Note: Brightness values > 100 will be clamped to 100 during packing. - * - * @param attr The LightAttributes structure to pack - * @return uint32_t Packed representation suitable for NVS storage - * - * @example - * LightAttributes attrs = {75, 255, 128, 64}; - * uint32_t packed = pack_light_attributes(attrs); // Returns 0x4BFF8040 - */ - uint32_t pack_light_attributes(const LightAttributes& attr); - - /** - * @brief Unpacks a 32-bit integer back into LightAttributes structure. - * - * Reverses the packing operation to extract individual color and brightness values. - * Brightness values > 100 in the packed data will be clamped to 100. - * - * @param packed The packed 32-bit representation - * @return LightAttributes The unpacked structure with individual components - * - * @example - * uint32_t packed = 0x4BFF8040; - * LightAttributes attrs = unpack_light_attributes(packed); - * // attrs.brightness = 75, attrs.red = 255, attrs.green = 128, attrs.blue = 64 - */ - LightAttributes unpack_light_attributes(uint32_t packed); - - /** - * @brief Default light attributes for initialization. - * - * Provides sensible defaults for new lights: - * - Brightness: 100 (full brightness) - * - Red: 255 (full intensity) - * - Green: 255 (full intensity) - * - Blue: 255 (full intensity) - * Result: Pure white color at full brightness - */ - extern const LightAttributes LIGHT_ATTRS_DEFAULT; - - /** - * @brief Pre-packed version of DEFAULT_LIGHT_ATTRS for convenience. - * - * This constant contains LIGHT_ATTRS_DEFAULT already packed into uint32_t format, - * suitable for direct use in ESPHome YAML initial_value fields. - * - * Value: 0x64FFFFFF (brightness=100, RGB=255,255,255) - */ - extern const uint32_t LIGHT_ATTRS_DEFAULT_PACKED; - - } // namespace tx_ultimate_easy -} // namespace esphome