Merge pull request #35 from edwardtfn/0.0.4

Wrap-up
This commit is contained in:
Edward Firmo
2024-12-20 23:37:50 +01:00
committed by GitHub
7 changed files with 214 additions and 141 deletions

View File

@@ -78,7 +78,7 @@ improv_serial:
id: serial_improv
logger:
level: DEBUG
level: INFO
ota:
platform: esphome
@@ -89,22 +89,34 @@ script:
- id: boot_done
mode: restart
then:
- lambda: send_event_to_ha->execute("boot", "done");
- script.execute:
id: send_event_to_ha
component: boot
event: done
- id: boot_initialize
mode: restart
then: # There's nothing here so far
# Extended by:
# - HW Buttons
# - HW Relays
# - HW Touch
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: |-
tx_fw_version->publish_state("${version}");
tx_device_name->publish_state("${name}");
tx_device_name->publish_state(App.get_name().c_str());
select:
- id: sl_tx_model_format
@@ -137,34 +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}
text_sensor:
- id: tx_fw_version
name: Firmware version
@@ -183,6 +167,7 @@ text_sensor:
entity_category: diagnostic
internal: false
disabled_by_default: false
update_interval: never
lambda: |-
return {"${name}"};
filters:

View File

@@ -13,23 +13,9 @@
---
api:
id: api_server
actions:
- action: set_float
variables:
component: string
val: float
then:
- lambda: |-
ESP_LOGD("core_api", "Set float:");
ESP_LOGD("core_api", " Component: %s", component.c_str());
ESP_LOGD("core_api", " Value: %f", val);
if (!isnan(val)) {
if (component == "latitude" && val >= -90 && val <= 90) {
sun_entity->set_latitude(val);
} else if (component == "longitude" && val >= -180 && val <= 180) {
sun_entity->set_longitude(val);
}
}
on_client_connected:
then:
- script.execute: publish_device_info
script:
- id: !extend button_action
@@ -45,14 +31,11 @@ script:
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},
});
- 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();
...

View File

@@ -14,6 +14,12 @@
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
@@ -232,8 +238,9 @@ select:
name: Button 1 action
platform: template
options:
- "None"
- "Relay 1 (toggle)"
- "${BUTTON_ACTION_NONE_TEXT}"
- "${BUTTON_1_ACTION_TEXT}"
initial_option: "${BUTTON_1_ACTION_TEXT}"
optimistic: true
restore_value: true
internal: true
@@ -245,23 +252,26 @@ select:
name: Button 2 action
platform: template
options:
- "None"
- "Relay 2 (toggle)"
- "${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:
- "None"
- "Relay 3 (toggle)"
- "${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:
- "None"
- "Relay 4 (toggle)"
- "${BUTTON_ACTION_NONE_TEXT}"
- "${BUTTON_4_ACTION_TEXT}"
initial_option: "${BUTTON_4_ACTION_TEXT}"
<<: *button_select_action_base
...

View File

@@ -844,16 +844,21 @@ script:
static const uint32_t LIGHT_TRANSITION_TURN_OFF = ${LIGHT_TRANSITION_TURN_OFF};
static const uint8_t LIGHT_BRIGHTNESS_TURN_ON = ${LIGHT_BRIGHTNESS_TURN_ON};
ESP_LOGI("core_hw_leds.light_set_state", "Setting light group %d, index %d to state %s",
light_group, light_index, state ? "ON" : "OFF");
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("light_set_state", "Invalid light_index %d for group 1", light_index);
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
@@ -861,6 +866,8 @@ script:
call.set_brightness(LIGHT_TRANSITION_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
@@ -869,10 +876,13 @@ script:
break;
case 2:
if (light_index >= id(gb_lights_2).size()) {
ESP_LOGE("light_set_state", "Invalid light_index %d for group 2", light_index);
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
@@ -880,6 +890,8 @@ script:
call.set_brightness(LIGHT_TRANSITION_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

View File

@@ -15,50 +15,50 @@ binary_sensor:
- id: !extend bs_button_1
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();
- 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:
- 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();
- 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:
- 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();
- 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:
- 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();
- 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

View File

@@ -208,7 +208,8 @@ tx_ultimate_easy:
- script.execute: touch_on_multi_touch_release
on_press:
- lambda: ESP_LOGI("tx_ultimate_easy", "Pressed");
- lambda: |-
ESP_LOGI("tx_ultimate_easy", "Pressed at position %" PRIu8, static_cast<uint8_t>(touch.x));
- script.execute:
id: touch_on_press
touch_x: !lambda return static_cast<uint8_t>(touch.x);

148
README.md
View File

@@ -1,58 +1,140 @@
# TX Ultimate Easy
<!-- markdownlint-disable MD033 -->
<a href="https://github.com/edwardtfn/TX-Ultimate-Easy/commits/main" target="_blank">![GitHub Activity][commits-shield]</a>
<a href="LICENSE" target="_blank">![License][license-shield]</a>
<a href="https://github.com/edwardtfn/TX-Ultimate-Easy/commits/main" target="_blank">![GitHub Last Commit][last-commit-shield]</a>
<a href="https://esphome.io/" target="_blank">![ESPHome][esphome-shield]</a>
<a href="https://discord.gg/Db6WJWzWuf" target="_blank">![Discord][discord-shield]</a>
<a href="https://www.buymeacoffee.com/edwardfirmo" target="_blank">![Buy me an ice-cream][buymeacoffee-shield]</a>
<!-- markdownlint-enable MD033 -->
<!-- markdownlint-disable MD013 -->
| &nbsp;![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, eliminating the need to edit YAML files manually. |
| &nbsp;![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. |
| --- | :-- |
<!-- markdownlint-enable MD013 -->
## 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
## Documentation
To be written.
- 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
## 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)
---
<!-- markdownlint-disable MD033 -->
<img src="Assets/Logo.webp" alt="TX Ultimate Easy Logo" width="100"/>