Compare commits
98 Commits
0.0.3
...
v2024.12.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5d941c460 | ||
|
|
9b134a786a | ||
|
|
be0fc353f6 | ||
|
|
fbc5cb79cc | ||
|
|
c65acc3298 | ||
|
|
4d8107faf2 | ||
|
|
65bbd901b1 | ||
|
|
8c610a406a | ||
|
|
696e3bf28d | ||
|
|
5ae4564e6a | ||
|
|
857c43940d | ||
|
|
8668fe8dc9 | ||
|
|
976a903118 | ||
|
|
35cc0c4a8e | ||
|
|
5c4581563e | ||
|
|
7f1c362a50 | ||
|
|
cf3018c95c | ||
|
|
360ae3123a | ||
|
|
6767b5e765 | ||
|
|
d5e5ebb3d6 | ||
|
|
46c04eb992 | ||
|
|
8558bc3650 | ||
|
|
f32e2eee4f | ||
|
|
5a993165cd | ||
|
|
d04c2aff2f | ||
|
|
2d79ee42c7 | ||
|
|
3f4fc7a505 | ||
|
|
be23a5a0fd | ||
|
|
a23a2db352 | ||
|
|
4e73a11528 | ||
|
|
3c98d81bb7 | ||
|
|
e63447984d | ||
|
|
1f1a8049e6 | ||
|
|
0dddc0747b | ||
|
|
86d1513c6a | ||
|
|
ac4d583b64 | ||
|
|
15830d4134 | ||
|
|
0c19ca1205 | ||
|
|
2d676036dc | ||
|
|
c8ffa9e224 | ||
|
|
1406ada53a | ||
|
|
f02f90c3fa | ||
|
|
f6169e3ea2 | ||
|
|
6774a1ac18 | ||
|
|
21720d8ba3 | ||
|
|
7727c968db | ||
|
|
dc9e19d43c | ||
|
|
737343e395 | ||
|
|
5569260f92 | ||
|
|
04ca752c3b | ||
|
|
23436428a4 | ||
|
|
26a244cbed | ||
|
|
ce8b4e700e | ||
|
|
35bf4bc0ec | ||
|
|
ee8ff66add | ||
|
|
96db05cc34 | ||
|
|
61a5d67082 | ||
|
|
ce9aefc7fe | ||
|
|
9bf6eff7d6 | ||
|
|
1d38ac282c | ||
|
|
9fbc499339 | ||
|
|
9646d5292a | ||
|
|
c01f8a4623 | ||
|
|
6f4d8ff611 | ||
|
|
82b6d8cb25 | ||
|
|
d0b8ba55ba | ||
|
|
8f4a2a9402 | ||
|
|
55cde35d31 | ||
|
|
e1b8469aa5 | ||
|
|
e0a5ea1cc8 | ||
|
|
2ae4d2abe8 | ||
|
|
da83c0749b | ||
|
|
ffe0d56576 | ||
|
|
b1b1a40d5e | ||
|
|
3543c0c088 | ||
|
|
0cc17b715f | ||
|
|
b1dbda4efe | ||
|
|
242325e556 | ||
|
|
cc5858be8b | ||
|
|
59da9bcb96 | ||
|
|
c62e7a689c | ||
|
|
62e4e3d511 | ||
|
|
e9890c937e | ||
|
|
81bf402e35 | ||
|
|
6d11d50e25 | ||
|
|
fa2c212efe | ||
|
|
3412e2389a | ||
|
|
a4eff7276a | ||
|
|
7c04d152a0 | ||
|
|
2e15149d3d | ||
|
|
818c6067e0 | ||
|
|
2f92e874b3 | ||
|
|
13722eccd0 | ||
|
|
51bf0dceab | ||
|
|
01293fd62d | ||
|
|
3f86f7dee9 | ||
|
|
b6d9ae5a96 | ||
|
|
7e46ecb1b3 |
8
.github/workflows/release_tag.yml
vendored
8
.github/workflows/release_tag.yml
vendored
@@ -1,3 +1,11 @@
|
|||||||
|
# This GitHub Actions workflow updates the "stable" and "latest" Git tags
|
||||||
|
# to point to the tag associated with a newly published release. It performs
|
||||||
|
# the following steps:
|
||||||
|
# 1. Checks out the repository code with full history.
|
||||||
|
# 2. Configures Git with a generic user for the action.
|
||||||
|
# 3. Moves and forcibly pushes the "stable" and "latest" tags to align with
|
||||||
|
# the tag of the newly published release.
|
||||||
|
# This ensures that "stable" and "latest" always point to the most recent release.
|
||||||
---
|
---
|
||||||
name: Update Tags
|
name: Update Tags
|
||||||
|
|
||||||
|
|||||||
30
.github/workflows/validate_esphome.yml
vendored
30
.github/workflows/validate_esphome.yml
vendored
@@ -3,24 +3,6 @@ name: Validate ESPHome
|
|||||||
|
|
||||||
# yamllint disable-line rule:truthy
|
# yamllint disable-line rule:truthy
|
||||||
on:
|
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:
|
workflow_dispatch:
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
@@ -56,10 +38,10 @@ jobs:
|
|||||||
- name: Build core
|
- name: Build core
|
||||||
uses: esphome/build-action@main
|
uses: esphome/build-action@main
|
||||||
with:
|
with:
|
||||||
yaml_file: ".test/esphome_ard_basic.yaml"
|
yaml-file: ".test/esphome_ard_basic.yaml"
|
||||||
|
|
||||||
build_bluetooth_proxy_4:
|
build_bluetooth_proxy_4:
|
||||||
name: Bluetooth Proxy (IDF v4)
|
name: Bluetooth Proxy (IDF)
|
||||||
needs: build_basic
|
needs: build_basic
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
@@ -67,10 +49,10 @@ jobs:
|
|||||||
- name: Build core
|
- name: Build core
|
||||||
uses: esphome/build-action@main
|
uses: esphome/build-action@main
|
||||||
with:
|
with:
|
||||||
yaml_file: ".test/esphome_idf_bluetooth_proxy.yaml"
|
yaml-file: ".test/esphome_idf_bluetooth_proxy.yaml"
|
||||||
|
|
||||||
build_bluetooth_proxy_5:
|
build_bluetooth_proxy_53:
|
||||||
name: Bluetooth Proxy (IDF v5)
|
name: Bluetooth Proxy (IDF v5.3)
|
||||||
needs: build_basic
|
needs: build_basic
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
@@ -78,5 +60,5 @@ jobs:
|
|||||||
- name: Build core
|
- name: Build core
|
||||||
uses: esphome/build-action@main
|
uses: esphome/build-action@main
|
||||||
with:
|
with:
|
||||||
yaml_file: ".test/esphome_idf5_bluetooth_proxy.yaml"
|
yaml-file: ".test/esphome_idf53_bluetooth_proxy.yaml"
|
||||||
...
|
...
|
||||||
|
|||||||
98
.github/workflows/validate_esphome_beta.yml
vendored
98
.github/workflows/validate_esphome_beta.yml
vendored
@@ -1,8 +1,25 @@
|
|||||||
---
|
---
|
||||||
name: Validate ESPHome (Beta)
|
name: Validate ESPHome (Beta)
|
||||||
|
|
||||||
# yamllint disable-line rule:truthy
|
on: # 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:
|
workflow_dispatch:
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
@@ -10,32 +27,9 @@ concurrency:
|
|||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
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:
|
code_scan:
|
||||||
name: Code scan (YAML)
|
name: Code scan (YAML)
|
||||||
runs-on: "ubuntu-latest"
|
runs-on: "ubuntu-latest"
|
||||||
needs: setup_dependencies
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Code
|
- name: Checkout Code
|
||||||
uses: actions/checkout@main
|
uses: actions/checkout@main
|
||||||
@@ -53,48 +47,38 @@ jobs:
|
|||||||
|
|
||||||
build_basic:
|
build_basic:
|
||||||
name: Basic
|
name: Basic
|
||||||
needs: [code_scan, setup_dependencies]
|
needs:
|
||||||
|
- code_scan
|
||||||
runs-on: ubuntu-latest
|
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:
|
steps:
|
||||||
- name: Checkout repository
|
- uses: actions/checkout@main
|
||||||
uses: actions/checkout@main
|
- name: Build core
|
||||||
|
|
||||||
- name: Firmware
|
|
||||||
if: steps.matrix.outputs.cache-hit != 'true'
|
|
||||||
uses: esphome/build-action@main
|
uses: esphome/build-action@main
|
||||||
with:
|
with:
|
||||||
yaml_file: ${{ matrix.yaml_file }}
|
yaml-file: ".test/esphome_ard_basic.yaml"
|
||||||
version: beta
|
version: beta
|
||||||
|
|
||||||
build_bluetooth_proxy:
|
build_bluetooth_proxy_4:
|
||||||
name: Bluetooth Proxy
|
name: Bluetooth Proxy (IDF)
|
||||||
needs: build_basic
|
needs: build_basic
|
||||||
runs-on: ubuntu-latest
|
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:
|
steps:
|
||||||
- name: Checkout repository
|
- uses: actions/checkout@main
|
||||||
uses: actions/checkout@main
|
- name: Build core
|
||||||
|
|
||||||
- name: Build Bluetooth Proxy Firmware
|
|
||||||
uses: esphome/build-action@main
|
uses: esphome/build-action@main
|
||||||
with:
|
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
|
version: beta
|
||||||
...
|
...
|
||||||
|
|||||||
42
.github/workflows/versioning.yml
vendored
Normal file
42
.github/workflows/versioning.yml
vendored
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# Workflow for managing versioning and tagging
|
||||||
|
---
|
||||||
|
name: Version Bump and Tag
|
||||||
|
|
||||||
|
on: # yamllint disable-line rule:truthy
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths-ignore:
|
||||||
|
- '**/VERSION'
|
||||||
|
- '**/VERSION_YAML'
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
update_stable:
|
||||||
|
description: "Update stable tag?"
|
||||||
|
required: true
|
||||||
|
default: "false"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
versioning:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: "actions/checkout@v4"
|
||||||
|
|
||||||
|
- name: Set up Git
|
||||||
|
run: |
|
||||||
|
git config user.name "GitHub Actions"
|
||||||
|
git config user.email "actions@github.com"
|
||||||
|
|
||||||
|
- name: Bump Version
|
||||||
|
run: |
|
||||||
|
chmod +x "./versioning/bump_version.sh"
|
||||||
|
"./versioning/bump_version.sh"
|
||||||
|
|
||||||
|
- name: Push Changes and Tags
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||||
|
run: |
|
||||||
|
git push "https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git" main
|
||||||
|
git push "https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git" --tags
|
||||||
|
...
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
packages:
|
packages:
|
||||||
basic_package: !include ../TX-Ultimate-Easy-ESPHome.yaml # Basic package
|
basic_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml # Basic package
|
||||||
|
|
||||||
esp32:
|
esp32:
|
||||||
framework:
|
framework:
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
---
|
---
|
||||||
packages:
|
packages:
|
||||||
basic_package: !include ../TX-Ultimate-Easy-ESPHome.yaml # Core package
|
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
||||||
addon_bluetooth_proxy: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml
|
addon_bluetooth_proxy: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml
|
||||||
|
|
||||||
esp32:
|
esp32:
|
||||||
framework:
|
framework:
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
version: 5.0.2
|
version: 5.3.1
|
||||||
platform_version: 6.3.2
|
platform_version: 6.9.0
|
||||||
...
|
...
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
packages:
|
packages:
|
||||||
basic_package: !include ../TX-Ultimate-Easy-ESPHome.yaml # Core package
|
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
||||||
addon_bluetooth_proxy: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml
|
addon_bluetooth_proxy: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml
|
||||||
...
|
...
|
||||||
|
|||||||
BIN
Assets/Logo.png
Normal file
BIN
Assets/Logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 165 KiB |
@@ -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:
|
bluetooth_proxy:
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
41
ESPHome/TX-Ultimate-Easy-ESPHome_core_api.yaml
Normal file
41
ESPHome/TX-Ultimate-Easy-ESPHome_core_api.yaml
Normal file
@@ -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();
|
||||||
|
...
|
||||||
277
ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml
Normal file
277
ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml
Normal file
@@ -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)"
|
||||||
|
|
||||||
|
BUTTON_CLICK_MIN_LENGTH: '50' # The minimum duration the click should last, in msec
|
||||||
|
BUTTON_CLICK_MAX_LENGTH: '350' # The maximum duration the click should last, in msec
|
||||||
|
BUTTON_MULTI_CLICK_DELAY: '250' # The time to wait for another click, in msec
|
||||||
|
BUTTON_PRESS_TIMEOUT: '10000' # Ignore if button is pressed for longer than this time, in msec
|
||||||
|
BUTTON_LONG_PRESS_DELAY: '800' # The time to wait to consider a long press, in msec
|
||||||
|
|
||||||
|
binary_sensor:
|
||||||
|
- &binary_sensor_button_base
|
||||||
|
id: bs_button_2
|
||||||
|
name: Button 2
|
||||||
|
icon: mdi:gesture-tap-box
|
||||||
|
platform: template
|
||||||
|
internal: true
|
||||||
|
|
||||||
|
- id: bs_button_3
|
||||||
|
name: Button 3
|
||||||
|
<<: *binary_sensor_button_base
|
||||||
|
|
||||||
|
- id: bs_button_4
|
||||||
|
name: Button 4
|
||||||
|
<<: *binary_sensor_button_base
|
||||||
|
|
||||||
|
- id: bs_button_1
|
||||||
|
name: Button 1
|
||||||
|
internal: false
|
||||||
|
<<: *binary_sensor_button_base
|
||||||
|
|
||||||
|
globals:
|
||||||
|
- id: button_press_button
|
||||||
|
type: uint8_t
|
||||||
|
restore_value: false
|
||||||
|
initial_value: '0'
|
||||||
|
|
||||||
|
- id: button_press_position
|
||||||
|
type: uint8_t
|
||||||
|
restore_value: false
|
||||||
|
initial_value: '0'
|
||||||
|
|
||||||
|
- id: button_press_start_time
|
||||||
|
type: uint32_t
|
||||||
|
restore_value: false
|
||||||
|
initial_value: '0'
|
||||||
|
|
||||||
|
- id: click_counter
|
||||||
|
type: uint8_t
|
||||||
|
restore_value: false
|
||||||
|
initial_value: '0'
|
||||||
|
|
||||||
|
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:
|
||||||
|
# Extended by:
|
||||||
|
# - core_api
|
||||||
|
- lambda: |-
|
||||||
|
ESP_LOGI("core_hw_buttons", "Button '%s' action: '%s'", component.c_str(), event.c_str());
|
||||||
|
id(button_press_button) = 0;
|
||||||
|
id(click_counter) = 0;
|
||||||
|
id(button_press_start_time) = 0;
|
||||||
|
buttons_release->execute();
|
||||||
|
|
||||||
|
- id: button_click_event
|
||||||
|
mode: restart
|
||||||
|
parameters:
|
||||||
|
button_id: uint8_t
|
||||||
|
click_count: uint8_t
|
||||||
|
then:
|
||||||
|
- delay:
|
||||||
|
milliseconds: ${BUTTON_MULTI_CLICK_DELAY}
|
||||||
|
- lambda: |-
|
||||||
|
const std::string button_name = "bs_button_" + std::to_string(button_id);
|
||||||
|
std::string event_name;
|
||||||
|
if (click_count == 1) event_name = "click";
|
||||||
|
else if (click_count == 2) event_name = "double_click";
|
||||||
|
else event_name = std::to_string(click_count) + "_click";
|
||||||
|
button_action->execute(button_name.c_str(), event_name.c_str());
|
||||||
|
|
||||||
|
- id: buttons_release
|
||||||
|
mode: restart
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
std::vector<binary_sensor::BinarySensor*> 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_position: !lambda return touch_position;
|
||||||
|
|
||||||
|
- id: touch_on_press_buttons
|
||||||
|
mode: restart
|
||||||
|
parameters:
|
||||||
|
touch_position: uint8_t
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
id(button_press_start_time) = millis();
|
||||||
|
id(button_press_position) = touch_position;
|
||||||
|
uint8_t button = 0;
|
||||||
|
auto model_index = sl_tx_model_gang->active_index();
|
||||||
|
if (model_index.has_value()) {
|
||||||
|
const uint8_t model_idx = model_index.value() + 1; // Increment for 1-based indexing
|
||||||
|
if (model_idx == 1) {
|
||||||
|
button = 1; // Single button, always 1
|
||||||
|
} else {
|
||||||
|
const uint8_t width = ${TOUCH_POSITION_MAX_VALUE} / model_idx; // Width of each button region
|
||||||
|
ESP_LOGV("core_hw_buttons", "Button regions: width=%" PRIu8 ", touch_position=%" PRIu8,
|
||||||
|
width, touch_position);
|
||||||
|
button = (touch_position / width) + 1; // Determine button region
|
||||||
|
if (button > model_idx)
|
||||||
|
button = model_idx; // Clamp to max button count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Update binary sensor
|
||||||
|
switch (button) {
|
||||||
|
case 1:
|
||||||
|
bs_button_1->publish_state(true);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
bs_button_2->publish_state(true);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
bs_button_3->publish_state(true);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
bs_button_4->publish_state(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Update counters
|
||||||
|
if (id(button_press_button) == button) {
|
||||||
|
id(click_counter)++;
|
||||||
|
} else {
|
||||||
|
id(click_counter) = 1;
|
||||||
|
id(button_press_button) = button;
|
||||||
|
}
|
||||||
|
|
||||||
|
- id: !extend touch_on_release
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
uint32_t current_time = millis();
|
||||||
|
buttons_release->execute();
|
||||||
|
if (id(button_press_start_time) > 0 and
|
||||||
|
id(button_press_start_time) < current_time) {
|
||||||
|
uint32_t press_duration = current_time - id(button_press_start_time);
|
||||||
|
// Handle overflow (optional, since it's unlikely to happen here)
|
||||||
|
ESP_LOGI("core_hw_buttons", "Button press duration: %" PRIu32 " ms", press_duration);
|
||||||
|
if (press_duration < ${BUTTON_CLICK_MIN_LENGTH}) {
|
||||||
|
ESP_LOGW("core_hw_buttons", "Ignoring button press (too short)");
|
||||||
|
} else if (press_duration >= ${BUTTON_CLICK_MIN_LENGTH} and
|
||||||
|
press_duration <= ${BUTTON_CLICK_MAX_LENGTH}) { // Short/normal click
|
||||||
|
button_click_event->execute(id(button_press_button), id(click_counter));
|
||||||
|
} else if (press_duration >= ${BUTTON_LONG_PRESS_DELAY} and press_duration <= ${BUTTON_PRESS_TIMEOUT}) {
|
||||||
|
button_action->execute(("bs_button_" + std::to_string(id(button_press_button))).c_str(), "long_click");
|
||||||
|
} else if (press_duration > ${BUTTON_PRESS_TIMEOUT}) { // Timeout or invalid
|
||||||
|
ESP_LOGW("core_hw_buttons", "Button press cancelled or timed out after ${BUTTON_PRESS_TIMEOUT} ms");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ESP_LOGW("core_hw_buttons", "Press event timestamp not recorded yet");
|
||||||
|
}
|
||||||
|
id(button_press_start_time) = 0;
|
||||||
|
|
||||||
|
- 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
|
||||||
|
...
|
||||||
905
ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml
Normal file
905
ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml
Normal file
@@ -0,0 +1,905 @@
|
|||||||
|
####################################################################################################
|
||||||
|
##### 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<light::LightState*>
|
||||||
|
restore_value: false
|
||||||
|
- id: gb_lights_2
|
||||||
|
type: std::vector<light::LightState*>
|
||||||
|
restore_value: false
|
||||||
|
|
||||||
|
light:
|
||||||
|
# These lights are controlling the LEDs on the device
|
||||||
|
- id: light_full
|
||||||
|
name: Light - All
|
||||||
|
internal: true
|
||||||
|
platform: neopixelbus
|
||||||
|
type: GRB
|
||||||
|
variant: WS2811
|
||||||
|
# method: esp32_rmt
|
||||||
|
num_leds: 32
|
||||||
|
pin: GPIO13
|
||||||
|
|
||||||
|
# Those lights are available based on the model selections
|
||||||
|
- &light_partition_with_effects
|
||||||
|
id: light_eu
|
||||||
|
name: Light
|
||||||
|
platform: partition
|
||||||
|
default_transition_length: ${default_transition_length}
|
||||||
|
internal: true
|
||||||
|
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"
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 0
|
||||||
|
to: 27
|
||||||
|
|
||||||
|
- id: light_us
|
||||||
|
name: Light
|
||||||
|
<<: *light_partition_with_effects
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 0
|
||||||
|
to: 31
|
||||||
|
|
||||||
|
- &light_partition_with_effects_disabled
|
||||||
|
id: light_eu_bottom
|
||||||
|
name: Light - Bottom
|
||||||
|
disabled_by_default: true
|
||||||
|
<<: *light_partition_with_effects
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 6
|
||||||
|
to: 12
|
||||||
|
reversed: true
|
||||||
|
- id: light_eu_left
|
||||||
|
name: Light - Left
|
||||||
|
<<: *light_partition_with_effects_disabled
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 13
|
||||||
|
to: 19
|
||||||
|
reversed: true
|
||||||
|
- id: light_eu_right
|
||||||
|
name: Light - Right
|
||||||
|
<<: *light_partition_with_effects_disabled
|
||||||
|
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
|
||||||
|
<<: *light_partition_with_effects_disabled
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 20
|
||||||
|
to: 26
|
||||||
|
reversed: false
|
||||||
|
- id: light_us_bottom
|
||||||
|
name: Light - Bottom
|
||||||
|
<<: *light_partition_with_effects_disabled
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 9
|
||||||
|
to: 14
|
||||||
|
reversed: true
|
||||||
|
- id: light_us_left
|
||||||
|
name: Light - Left
|
||||||
|
<<: *light_partition_with_effects_disabled
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 15
|
||||||
|
to: 24
|
||||||
|
reversed: true
|
||||||
|
- id: light_us_right
|
||||||
|
name: Light - Right
|
||||||
|
<<: *light_partition_with_effects_disabled
|
||||||
|
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
|
||||||
|
<<: *light_partition_with_effects_disabled
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 25
|
||||||
|
to: 30
|
||||||
|
reversed: false
|
||||||
|
|
||||||
|
- &light_partition_individual_led
|
||||||
|
id: light_00
|
||||||
|
name: Light - LED 00
|
||||||
|
platform: partition
|
||||||
|
disabled_by_default: true
|
||||||
|
default_transition_length: ${default_transition_length}
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 0
|
||||||
|
to: 0
|
||||||
|
- id: light_01
|
||||||
|
name: Light - LED 01
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 1
|
||||||
|
to: 1
|
||||||
|
- id: light_02
|
||||||
|
name: Light - LED 02
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 2
|
||||||
|
to: 2
|
||||||
|
- id: light_03
|
||||||
|
name: Light - LED 03
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 3
|
||||||
|
to: 3
|
||||||
|
- id: light_04
|
||||||
|
name: Light - LED 04
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 4
|
||||||
|
to: 4
|
||||||
|
- id: light_05
|
||||||
|
name: Light - LED 05
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 5
|
||||||
|
to: 5
|
||||||
|
- id: light_06
|
||||||
|
name: Light - LED 06
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 6
|
||||||
|
to: 6
|
||||||
|
- id: light_07
|
||||||
|
name: Light - LED 07
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 7
|
||||||
|
to: 7
|
||||||
|
- id: light_08
|
||||||
|
name: Light - LED 08
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 8
|
||||||
|
to: 8
|
||||||
|
- id: light_09
|
||||||
|
name: Light - LED 09
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 9
|
||||||
|
to: 9
|
||||||
|
- id: light_10
|
||||||
|
name: Light - LED 10
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 10
|
||||||
|
to: 10
|
||||||
|
- id: light_11
|
||||||
|
name: Light - LED 11
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 11
|
||||||
|
to: 11
|
||||||
|
- id: light_12
|
||||||
|
name: Light - LED 12
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 12
|
||||||
|
to: 12
|
||||||
|
- id: light_13
|
||||||
|
name: Light - LED 13
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 13
|
||||||
|
to: 13
|
||||||
|
- id: light_14
|
||||||
|
name: Light - LED 14
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 14
|
||||||
|
to: 14
|
||||||
|
- id: light_15
|
||||||
|
name: Light - LED 15
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 15
|
||||||
|
to: 15
|
||||||
|
- id: light_16
|
||||||
|
name: Light - LED 16
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 16
|
||||||
|
to: 16
|
||||||
|
- id: light_17
|
||||||
|
name: Light - LED 17
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 17
|
||||||
|
to: 17
|
||||||
|
- id: light_18
|
||||||
|
name: Light - LED 18
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 18
|
||||||
|
to: 18
|
||||||
|
- id: light_19
|
||||||
|
name: Light - LED 19
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 19
|
||||||
|
to: 19
|
||||||
|
- id: light_20
|
||||||
|
name: Light - LED 20
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 20
|
||||||
|
to: 20
|
||||||
|
- id: light_21
|
||||||
|
name: Light - LED 21
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 21
|
||||||
|
to: 21
|
||||||
|
- id: light_22
|
||||||
|
name: Light - LED 22
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 22
|
||||||
|
to: 22
|
||||||
|
- id: light_23
|
||||||
|
name: Light - LED 23
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 23
|
||||||
|
to: 23
|
||||||
|
- id: light_24
|
||||||
|
name: Light - LED 24
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 24
|
||||||
|
to: 24
|
||||||
|
- id: light_25
|
||||||
|
name: Light - LED 25
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 25
|
||||||
|
to: 25
|
||||||
|
- id: light_26
|
||||||
|
name: Light - LED 26
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 26
|
||||||
|
to: 26
|
||||||
|
- id: light_27
|
||||||
|
name: Light - LED 27
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 27
|
||||||
|
to: 27
|
||||||
|
- id: light_28 # US Model only
|
||||||
|
name: Light - LED 28
|
||||||
|
internal: true
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 28
|
||||||
|
to: 28
|
||||||
|
- id: light_29 # US Model only
|
||||||
|
name: Light - LED 29
|
||||||
|
internal: true
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 29
|
||||||
|
to: 29
|
||||||
|
- id: light_30 # US Model only
|
||||||
|
name: Light - LED 30
|
||||||
|
internal: true
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 30
|
||||||
|
to: 30
|
||||||
|
- id: light_31 # US Model only
|
||||||
|
name: Light - LED 31
|
||||||
|
internal: true
|
||||||
|
<<: *light_partition_individual_led
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 31
|
||||||
|
to: 31
|
||||||
|
|
||||||
|
# These lights are used to indicate relay's statuses
|
||||||
|
- &light_partition_relays
|
||||||
|
id: light_eu_rl_1_1_bottom
|
||||||
|
name: Light - Relay 1 of 1 (bottom)
|
||||||
|
platform: partition
|
||||||
|
internal: true
|
||||||
|
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)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 23
|
||||||
|
to: 23
|
||||||
|
- id: light_eu_rl_1_2_bottom
|
||||||
|
name: Light - Relay 1 of 2 (bottom)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 11
|
||||||
|
to: 11
|
||||||
|
- id: light_eu_rl_1_2_top
|
||||||
|
name: Light - Relay 1 of 2 (top)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 21
|
||||||
|
to: 21
|
||||||
|
- id: light_eu_rl_2_2_bottom
|
||||||
|
name: Light - Relay 2 of 2 (bottom)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 7
|
||||||
|
to: 7
|
||||||
|
- id: light_eu_rl_2_2_top
|
||||||
|
name: Light - Relay 2 of 2 (top)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 25
|
||||||
|
to: 25
|
||||||
|
- id: light_eu_rl_1_3_bottom
|
||||||
|
name: Light - Relay 1 of 3 (bottom)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 12
|
||||||
|
to: 12
|
||||||
|
- id: light_eu_rl_1_3_top
|
||||||
|
name: Light - Relay 1 of 3 (top)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 20
|
||||||
|
to: 20
|
||||||
|
- id: light_eu_rl_2_3_bottom
|
||||||
|
name: Light - Relay 2 of 3 (bottom)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 9
|
||||||
|
to: 9
|
||||||
|
- id: light_eu_rl_2_3_top
|
||||||
|
name: Light - Relay 2 of 3 (top)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 23
|
||||||
|
to: 23
|
||||||
|
- id: light_eu_rl_3_3_bottom
|
||||||
|
name: Light - Relay 3 of 3 (bottom)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 6
|
||||||
|
to: 6
|
||||||
|
- id: light_eu_rl_3_3_top
|
||||||
|
name: Light - Relay 3 of 3 (top)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 26
|
||||||
|
to: 26
|
||||||
|
- id: light_eu_rl_1_4_bottom
|
||||||
|
name: Light - Relay 1 of 4 (bottom)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 12
|
||||||
|
to: 12
|
||||||
|
- id: light_eu_rl_1_4_top
|
||||||
|
name: Light - Relay 1 of 4 (top)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 20
|
||||||
|
to: 20
|
||||||
|
- id: light_eu_rl_2_4_bottom
|
||||||
|
name: Light - Relay 2 of 4 (bottom)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 10
|
||||||
|
to: 10
|
||||||
|
- id: light_eu_rl_2_4_top
|
||||||
|
name: Light - Relay 2 of 4 (top)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 22
|
||||||
|
to: 22
|
||||||
|
- id: light_eu_rl_3_4_bottom
|
||||||
|
name: Light - Relay 3 of 4 (bottom)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 8
|
||||||
|
to: 8
|
||||||
|
- id: light_eu_rl_3_4_top
|
||||||
|
name: Light - Relay 3 of 4 (top)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 24
|
||||||
|
to: 24
|
||||||
|
- id: light_eu_rl_4_4_bottom
|
||||||
|
name: Light - Relay 4 of 4 (bottom)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 6
|
||||||
|
to: 6
|
||||||
|
- id: light_eu_rl_4_4_top
|
||||||
|
name: Light - Relay 4 of 4 (top)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 26
|
||||||
|
to: 26
|
||||||
|
- id: light_us_rl_1_1_left
|
||||||
|
name: Light - Relay 1 of 1 (left)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 15
|
||||||
|
to: 24
|
||||||
|
- id: light_us_rl_1_1_right
|
||||||
|
name: Light - Relay 1 of 1 (right)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
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)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 20
|
||||||
|
to: 24
|
||||||
|
- id: light_us_rl_1_2_right
|
||||||
|
name: Light - Relay 1 of 2 (right)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
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)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 15
|
||||||
|
to: 19
|
||||||
|
- id: light_us_rl_2_2_right
|
||||||
|
name: Light - Relay 2 of 2 (right)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 4
|
||||||
|
to: 8
|
||||||
|
- id: light_us_rl_1_3_left
|
||||||
|
name: Light - Relay 1 of 3 (left)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 22
|
||||||
|
to: 23
|
||||||
|
- id: light_us_rl_1_3_right
|
||||||
|
name: Light - Relay 1 of 3 (right)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 0
|
||||||
|
to: 1
|
||||||
|
- id: light_us_rl_2_3_left
|
||||||
|
name: Light - Relay 2 of 3 (left)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 19
|
||||||
|
to: 20
|
||||||
|
- id: light_us_rl_2_3_right
|
||||||
|
name: Light - Relay 2 of 3 (right)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 3
|
||||||
|
to: 4
|
||||||
|
- id: light_us_rl_3_3_left
|
||||||
|
name: Light - Relay 3 of 3 (left)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 17
|
||||||
|
to: 18
|
||||||
|
- id: light_us_rl_3_3_right
|
||||||
|
name: Light - Relay 3 of 3 (right)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 6
|
||||||
|
to: 7
|
||||||
|
- id: light_us_rl_1_4_left
|
||||||
|
name: Light - Relay 1 of 4 (left)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 12
|
||||||
|
to: 12
|
||||||
|
- id: light_us_rl_1_4_right
|
||||||
|
name: Light - Relay 1 of 4 (right)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 31
|
||||||
|
to: 31
|
||||||
|
- id: light_us_rl_2_4_left
|
||||||
|
name: Light - Relay 2 of 4 (left)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 24
|
||||||
|
to: 24
|
||||||
|
- id: light_us_rl_2_4_right
|
||||||
|
name: Light - Relay 2 of 4 (right)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 2
|
||||||
|
to: 2
|
||||||
|
- id: light_us_rl_3_4_left
|
||||||
|
name: Light - Relay 3 of 4 (left)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 21
|
||||||
|
to: 21
|
||||||
|
- id: light_us_rl_3_4_right
|
||||||
|
name: Light - Relay 3 of 4 (right)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 4
|
||||||
|
to: 4
|
||||||
|
- id: light_us_rl_4_4_left
|
||||||
|
name: Light - Relay 4 of 4 (left)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 19
|
||||||
|
to: 19
|
||||||
|
- id: light_us_rl_4_4_right
|
||||||
|
name: Light - Relay 4 of 4 (right)
|
||||||
|
<<: *light_partition_relays
|
||||||
|
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: // 4 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
|
||||||
|
...
|
||||||
283
ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml
Normal file
283
ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
####################################################################################################
|
||||||
|
##### 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. #####
|
||||||
|
####################################################################################################
|
||||||
|
---
|
||||||
|
globals:
|
||||||
|
- id: boot_initialization_relays
|
||||||
|
type: bool
|
||||||
|
restore_value: false
|
||||||
|
initial_value: 'false'
|
||||||
|
|
||||||
|
light:
|
||||||
|
# These lights are used for the physical relays to be shown as lights
|
||||||
|
- &light_binary_base
|
||||||
|
id: light_output_1
|
||||||
|
name: Light output 1
|
||||||
|
output: output_relay_1
|
||||||
|
platform: binary
|
||||||
|
internal: true
|
||||||
|
- id: light_output_2
|
||||||
|
name: Light output 2
|
||||||
|
output: output_relay_2
|
||||||
|
<<: *light_binary_base
|
||||||
|
- id: light_output_3
|
||||||
|
name: Light output 3
|
||||||
|
output: output_relay_3
|
||||||
|
<<: *light_binary_base
|
||||||
|
- id: light_output_4
|
||||||
|
name: Light output 4
|
||||||
|
output: output_relay_4
|
||||||
|
<<: *light_binary_base
|
||||||
|
|
||||||
|
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: !extend button_click_event
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
// Handle only single clicks
|
||||||
|
if (click_count != 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Ignore if other touch events are active
|
||||||
|
if (bs_multi_touch->state ||
|
||||||
|
bs_swipe_left->state ||
|
||||||
|
bs_swipe_down->state ||
|
||||||
|
bs_swipe_right->state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle relay if corresponding button action is enabled
|
||||||
|
switch (button_id) {
|
||||||
|
case 1:
|
||||||
|
if (sl_button_1_action->active_index().has_value() and
|
||||||
|
sl_button_1_action->active_index().value() == 1)
|
||||||
|
sw_relay_1->toggle();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (sl_button_2_action->active_index().has_value() and
|
||||||
|
sl_button_2_action->active_index().value() == 1)
|
||||||
|
sw_relay_2->toggle();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (sl_button_3_action->active_index().has_value() and
|
||||||
|
sl_button_3_action->active_index().value() == 1)
|
||||||
|
sw_relay_3->toggle();
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
if (sl_button_4_action->active_index().has_value() and
|
||||||
|
sl_button_4_action->active_index().value() == 1)
|
||||||
|
sw_relay_4->toggle();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
- 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
|
||||||
|
...
|
||||||
29
ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml
Normal file
29
ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml
Normal file
@@ -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
|
||||||
|
...
|
||||||
255
ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml
Normal file
255
ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
####################################################################################################
|
||||||
|
##### 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. #####
|
||||||
|
####################################################################################################
|
||||||
|
---
|
||||||
|
substitutions:
|
||||||
|
TOUCH_POSITION_MAX_VALUE: '10' # Maximum touch position value returned by the touch pad via uart
|
||||||
|
|
||||||
|
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: v${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_position: 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_long_touch_release:
|
||||||
|
- lambda: |-
|
||||||
|
const uint8_t touch_position = static_cast<uint8_t>(touch.x);
|
||||||
|
if (touch_position > ${TOUCH_POSITION_MAX_VALUE}) { // Check for valid range
|
||||||
|
ESP_LOGE("tx_ultimate_easy", "Invalid long-touch position: %" PRIu8, touch_position);
|
||||||
|
} else {
|
||||||
|
ESP_LOGI("tx_ultimate_easy", "Long-touch released at position %" PRIu8, touch_position);
|
||||||
|
}
|
||||||
|
|
||||||
|
on_multi_touch_release:
|
||||||
|
- lambda: ESP_LOGI("tx_ultimate_easy", "Multi-touch released");
|
||||||
|
- script.execute: touch_on_multi_touch_release
|
||||||
|
|
||||||
|
on_press:
|
||||||
|
- lambda: |-
|
||||||
|
const uint8_t touch_position = static_cast<uint8_t>(touch.x);
|
||||||
|
if (touch_position > ${TOUCH_POSITION_MAX_VALUE}) { // Check for valid range
|
||||||
|
ESP_LOGE("tx_ultimate_easy", "Invalid touch position: %" PRIu8, touch_position);
|
||||||
|
} else {
|
||||||
|
ESP_LOGI("tx_ultimate_easy", "Pressed at position %" PRIu8, touch_position);
|
||||||
|
touch_on_press->execute(touch_position);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
...
|
||||||
137
ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml
Normal file
137
ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml
Normal file
@@ -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
|
||||||
|
|
||||||
|
...
|
||||||
152
README.md
152
README.md
@@ -1,59 +1,139 @@
|
|||||||
# TX Ultimate Easy
|
# TX Ultimate Easy
|
||||||
|
|
||||||
|  | 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. |
|
<!-- 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 -->
|
||||||
|
|  | 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.
|
## Integration with Home Assistant
|
||||||
- **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.
|
|
||||||
|
|
||||||
## 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
|
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.
|
||||||
- Home Assistant installed
|
|
||||||
- ESPHome add-on installed in Home Assistant
|
|
||||||
|
|
||||||
### Installation
|
## Key Features
|
||||||
To be written.
|
|
||||||
|
|
||||||
### 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:**
|
## Hardware Support
|
||||||
All device settings can be managed through the Home Assistant interface. No need to edit YAML files directly.
|
|
||||||
|
|
||||||
- **Using Blueprints:**
|
- Compatible with all Sonoff TX Ultimate variants:
|
||||||
Import and use blueprints to quickly configure your device for common use cases.
|
- EU format (Square, T5-xC-86)
|
||||||
|
- US format (Rectangle, T5-xC-120)
|
||||||
|
- 1/2/3/4 gang versions
|
||||||
|
|
||||||
## Documentation
|
## Prerequisites
|
||||||
To be written.
|
|
||||||
|
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
|
## 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 `main`
|
||||||
|
3. Make your changes
|
||||||
|
4. Submit a pull request targeting the `main` branch
|
||||||
|
|
||||||
|
Please ensure your code follows our standards:
|
||||||
|
- Passes all lint checks (YAML, C++, Markdown)
|
||||||
|
- Includes appropriate documentation
|
||||||
|
- Follows existing code style
|
||||||
|
|
||||||
|
## 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)
|
||||||
|
|
||||||
|
[](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
|
## License
|
||||||
|
|
||||||
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
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:
|
|
||||||
|
|
||||||
[](https://www.buymeacoffee.com/edwardfirmo)
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- markdownlint-disable MD033 -->
|
||||||
<img src="Assets/Logo.webp" alt="TX Ultimate Easy Logo" width="100"/>
|
<img src="Assets/Logo.webp" alt="TX Ultimate Easy Logo" width="100"/>
|
||||||
|
<!-- markdownlint-enable MD033 -->
|
||||||
|
|||||||
@@ -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:
|
substitutions:
|
||||||
name: tx-ultimate-easy
|
name: tx-ultimate-easy
|
||||||
@@ -10,7 +16,7 @@ wifi:
|
|||||||
packages:
|
packages:
|
||||||
remote_package:
|
remote_package:
|
||||||
url: https://github.com/edwardtfn/TX-Ultimate-Easy
|
url: https://github.com/edwardtfn/TX-Ultimate-Easy
|
||||||
ref: dev
|
ref: latest
|
||||||
refresh: 30s
|
refresh: 30s
|
||||||
files:
|
files:
|
||||||
- ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
- ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ DEPENDENCIES = ['uart']
|
|||||||
CONF_TX_ULTIMATE_EASY = "tx_ultimate_easy"
|
CONF_TX_ULTIMATE_EASY = "tx_ultimate_easy"
|
||||||
|
|
||||||
CONF_UART = "uart"
|
CONF_UART = "uart"
|
||||||
|
CONF_GANG_COUNT = "gang_count"
|
||||||
|
|
||||||
CONF_ON_TOUCH_EVENT = "on_touch_event"
|
CONF_ON_TOUCH_EVENT = "on_touch_event"
|
||||||
CONF_ON_PRESS = "on_press"
|
CONF_ON_PRESS = "on_press"
|
||||||
@@ -33,6 +34,7 @@ CONFIG_SCHEMA = cv.Schema({
|
|||||||
cv.GenerateID(): cv.declare_id(TxUltimateTouch),
|
cv.GenerateID(): cv.declare_id(TxUltimateTouch),
|
||||||
|
|
||||||
cv.Required(CONF_UART): cv.use_id(uart),
|
cv.Required(CONF_UART): cv.use_id(uart),
|
||||||
|
cv.Optional(CONF_GANG_COUNT, default=1): cv.int_range(min=1, max=4),
|
||||||
|
|
||||||
cv.Optional(CONF_ON_TOUCH_EVENT): automation.validate_automation(single=True),
|
cv.Optional(CONF_ON_TOUCH_EVENT): automation.validate_automation(single=True),
|
||||||
cv.Optional(CONF_ON_PRESS): automation.validate_automation(single=True),
|
cv.Optional(CONF_ON_PRESS): automation.validate_automation(single=True),
|
||||||
@@ -49,6 +51,9 @@ async def register_tx_ultimate_easy(var, config):
|
|||||||
uart_component = await cg.get_variable(config[CONF_UART])
|
uart_component = await cg.get_variable(config[CONF_UART])
|
||||||
cg.add(var.set_uart_component(uart_component))
|
cg.add(var.set_uart_component(uart_component))
|
||||||
|
|
||||||
|
if CONF_GANG_COUNT in config:
|
||||||
|
cg.add(var.set_gang_count(config[CONF_GANG_COUNT]))
|
||||||
|
|
||||||
if CONF_ON_TOUCH_EVENT in config:
|
if CONF_ON_TOUCH_EVENT in config:
|
||||||
await automation.build_automation(
|
await automation.build_automation(
|
||||||
var.get_trigger_touch_event(),
|
var.get_trigger_touch_event(),
|
||||||
@@ -98,6 +103,7 @@ async def register_tx_ultimate_easy(var, config):
|
|||||||
config[CONF_ON_LONG_TOUCH_RELEASE],
|
config[CONF_ON_LONG_TOUCH_RELEASE],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def to_code(config):
|
async def to_code(config):
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
await cg.register_component(var, config)
|
await cg.register_component(var, config)
|
||||||
|
|||||||
@@ -48,6 +48,35 @@ namespace esphome {
|
|||||||
|
|
||||||
void TxUltimateEasy::dump_config() {
|
void TxUltimateEasy::dump_config() {
|
||||||
ESP_LOGCONFIG(TAG, "TX Ultimate Easy");
|
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
|
||||||
|
const uint8_t width = (TOUCH_MAX_POSITION + 1) / this->gang_count_; // Width of each button region
|
||||||
|
if (width < 1 or width > this->gang_count_) // Invalid width - and prevents division by zero
|
||||||
|
return 0;
|
||||||
|
const uint8_t button = std::min(
|
||||||
|
static_cast<uint8_t>((position / width) + 1), // Convert position to button index
|
||||||
|
this->gang_count_ // Clamp to max gang count
|
||||||
|
);
|
||||||
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TxUltimateEasy::send_touch_(TouchPoint tp) {
|
void TxUltimateEasy::send_touch_(TouchPoint tp) {
|
||||||
@@ -103,7 +132,8 @@ namespace esphome {
|
|||||||
state == TOUCH_STATE_SWIPE_LEFT ||
|
state == TOUCH_STATE_SWIPE_LEFT ||
|
||||||
state == TOUCH_STATE_SWIPE_RIGHT ||
|
state == TOUCH_STATE_SWIPE_RIGHT ||
|
||||||
state == TOUCH_STATE_MULTI_TOUCH) &&
|
state == TOUCH_STATE_MULTI_TOUCH) &&
|
||||||
(uart_received_bytes[6] >= 0 || 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<int, UART_RECEIVED_BYTES_SIZE> &uart_received_bytes) {
|
int TxUltimateEasy::get_touch_position_x(const std::array<int, UART_RECEIVED_BYTES_SIZE> &uart_received_bytes) {
|
||||||
@@ -133,6 +163,8 @@ namespace esphome {
|
|||||||
TouchPoint TxUltimateEasy::get_touch_point(const std::array<int, UART_RECEIVED_BYTES_SIZE> &uart_received_bytes) {
|
TouchPoint TxUltimateEasy::get_touch_point(const std::array<int, UART_RECEIVED_BYTES_SIZE> &uart_received_bytes) {
|
||||||
TouchPoint tp;
|
TouchPoint tp;
|
||||||
tp.x = this->get_touch_position_x(uart_received_bytes);
|
tp.x = this->get_touch_position_x(uart_received_bytes);
|
||||||
|
if (tp.x >= 0)
|
||||||
|
tp.button = this->get_button_from_position(static_cast<uint8_t>(tp.x));
|
||||||
tp.state = this->get_touch_state(uart_received_bytes);
|
tp.state = this->get_touch_state(uart_received_bytes);
|
||||||
switch (tp.state) {
|
switch (tp.state) {
|
||||||
case TOUCH_STATE_RELEASE:
|
case TOUCH_STATE_RELEASE:
|
||||||
|
|||||||
@@ -13,6 +13,9 @@
|
|||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace tx_ultimate_easy {
|
namespace tx_ultimate_easy {
|
||||||
|
// Touch Max Position
|
||||||
|
constexpr uint8_t TOUCH_MAX_POSITION = 10;
|
||||||
|
|
||||||
// Touch State Constants
|
// Touch State Constants
|
||||||
constexpr uint8_t TOUCH_STATE_RELEASE = 0x01;
|
constexpr uint8_t TOUCH_STATE_RELEASE = 0x01;
|
||||||
constexpr uint8_t TOUCH_STATE_PRESS = 0x02;
|
constexpr uint8_t TOUCH_STATE_PRESS = 0x02;
|
||||||
@@ -32,6 +35,7 @@ namespace esphome {
|
|||||||
static const char *TAG = "tx_ultimate_easy";
|
static const char *TAG = "tx_ultimate_easy";
|
||||||
|
|
||||||
struct TouchPoint {
|
struct TouchPoint {
|
||||||
|
uint8_t button = 0;
|
||||||
int8_t x = -1;
|
int8_t x = -1;
|
||||||
int8_t state = -1;
|
int8_t state = -1;
|
||||||
std::string state_str = "Unknown";
|
std::string state_str = "Unknown";
|
||||||
@@ -53,6 +57,10 @@ namespace esphome {
|
|||||||
void loop() override;
|
void loop() override;
|
||||||
void dump_config() 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:
|
protected:
|
||||||
void send_touch_(TouchPoint tp);
|
void send_touch_(TouchPoint tp);
|
||||||
void handle_touch(const std::array<int, UART_RECEIVED_BYTES_SIZE> &bytes);
|
void handle_touch(const std::array<int, UART_RECEIVED_BYTES_SIZE> &bytes);
|
||||||
@@ -70,6 +78,8 @@ namespace esphome {
|
|||||||
Trigger<TouchPoint> trigger_multi_touch_release_;
|
Trigger<TouchPoint> trigger_multi_touch_release_;
|
||||||
Trigger<TouchPoint> trigger_long_touch_release_;
|
Trigger<TouchPoint> trigger_long_touch_release_;
|
||||||
|
|
||||||
|
uint8_t gang_count_ = 1;
|
||||||
|
|
||||||
}; // class TxUltimateEasy
|
}; // class TxUltimateEasy
|
||||||
|
|
||||||
} // namespace tx_ultimate_easy
|
} // namespace tx_ultimate_easy
|
||||||
|
|||||||
76
versioning/README.md
Normal file
76
versioning/README.md
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
# Versioning
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
This project uses a time-based versioning scheme: `year.month.sequential_number`.
|
||||||
|
The system automates version updates and tagging to ensure consistent, conflict-free management of releases.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
- `2024.1.1` – First release of January 2024.
|
||||||
|
- `2024.12.2` – Second release of December 2024.
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
1. **Temporary Branch Creation**: A unique branch is created for each workflow run.
|
||||||
|
2. **Version Update**: The workflow updates the `VERSION` and `VERSION_YAML` files using the current date and release sequence.
|
||||||
|
3. **Commit with Marker**: Changes are committed with a `[skip-versioning]` marker to prevent triggering the workflow again.
|
||||||
|
4. **Merge into Main**: The temporary branch is merged into `main`.
|
||||||
|
5. **Branch Cleanup**: The temporary branch is deleted after merging.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Automated Workflow
|
||||||
|
The versioning process is fully automated:
|
||||||
|
- Developers submit their changes as usual.
|
||||||
|
- The workflow handles version updates, tagging, and integration into `main`.
|
||||||
|
- No manual intervention is needed for versioning.
|
||||||
|
|
||||||
|
### Accessing the Version in Code
|
||||||
|
The version is accessible in the ESPHome YAML configuration file (`TX-Ultimate-Easy-ESPHome_core.yaml`) using the following syntax:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
substitutions:
|
||||||
|
version: <<: !include ../versioning/VERSION
|
||||||
|
```
|
||||||
|
|
||||||
|
This ensures the correct version is dynamically included in the ESPHome setup.
|
||||||
|
|
||||||
|
## Benefits
|
||||||
|
- **Clarity**: Easily track when a release occurred with meaningful version numbers.
|
||||||
|
- **Automation**: Eliminates manual version management.
|
||||||
|
- **Scalability**: Supports frequent updates and concurrent workflows.
|
||||||
|
- **Traceability**: Maintains a clear history of changes through Git tags and version files.
|
||||||
|
|
||||||
|
## System Details
|
||||||
|
|
||||||
|
### Version Format
|
||||||
|
The format `year.month.sequential_number` includes:
|
||||||
|
- `year` (YYYY): A 4-digit number representing the year.
|
||||||
|
- `month` (M): A number from 1 to 12 (no leading zeros).
|
||||||
|
- `sequential_number`: A positive number incremented with each release in the same month.
|
||||||
|
|
||||||
|
### Validation Rules
|
||||||
|
The `bump_version.sh` script enforces strict validation:
|
||||||
|
- Year must be a 4-digit number.
|
||||||
|
- Month must be 1–12 without leading zeros.
|
||||||
|
- Sequence must be a positive number without leading zeros.
|
||||||
|
|
||||||
|
If validation fails, the workflow stops and provides an error message.
|
||||||
|
|
||||||
|
### GitHub Workflow
|
||||||
|
The workflow is triggered automatically when:
|
||||||
|
- Changes are pushed to `main`.
|
||||||
|
- Developers trigger it manually using the `workflow_dispatch` event.
|
||||||
|
|
||||||
|
The workflow avoids infinite loops by committing changes with the `[skip-versioning]` marker.
|
||||||
|
|
||||||
|
## Extending the System
|
||||||
|
Consider extending the system to:
|
||||||
|
- Automatically generate release notes or changelogs.
|
||||||
|
- Notify stakeholders when a new version is released.
|
||||||
|
- Integrate versioning information into deployment pipelines.
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
**Q: What happens if two workflows run concurrently?**
|
||||||
|
A: Each workflow operates in its own temporary branch, avoiding conflicts.
|
||||||
|
|
||||||
|
**Q: Can I manually update the version?**
|
||||||
|
A: Manual updates are not needed. The workflow ensures accurate, automated versioning.
|
||||||
1
versioning/VERSION
Normal file
1
versioning/VERSION
Normal file
@@ -0,0 +1 @@
|
|||||||
|
2024.12.4
|
||||||
1
versioning/VERSION_YAML
Normal file
1
versioning/VERSION_YAML
Normal file
@@ -0,0 +1 @@
|
|||||||
|
version: 2024.12.4
|
||||||
54
versioning/bump_version.sh
Normal file
54
versioning/bump_version.sh
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
VERSION_FILE="./versioning/VERSION"
|
||||||
|
VERSION_YAML_FILE="./versioning/VERSION_YAML"
|
||||||
|
|
||||||
|
# Read the current version
|
||||||
|
if [ -f "$VERSION_FILE" ]; then
|
||||||
|
CURRENT_VERSION=$(cat "$VERSION_FILE")
|
||||||
|
else
|
||||||
|
CURRENT_VERSION="0.0.0" # Default if file doesn't exist
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Validate the current version format
|
||||||
|
if ! [[ "$CURRENT_VERSION" =~ ^[0-9]{4}\.[0-9]{1,2}\.[0-9]+$ ]]; then
|
||||||
|
echo "Error: Invalid version format in $VERSION_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract components
|
||||||
|
CURRENT_YEAR=$(date +%Y)
|
||||||
|
CURRENT_MONTH=$(date +%-m) # Avoid leading zero for the month
|
||||||
|
CURRENT_SEQ=$(echo "$CURRENT_VERSION" | awk -F. '{print $3}')
|
||||||
|
|
||||||
|
VERSION_YEAR=$(echo "$CURRENT_VERSION" | awk -F. '{print $1}')
|
||||||
|
VERSION_MONTH=$(echo "$CURRENT_VERSION" | awk -F. '{print $2}')
|
||||||
|
|
||||||
|
# Determine new version
|
||||||
|
if [[ "$CURRENT_YEAR" == "$VERSION_YEAR" && "$CURRENT_MONTH" == "$VERSION_MONTH" ]]; then
|
||||||
|
NEXT_SEQ=$((CURRENT_SEQ + 1))
|
||||||
|
else
|
||||||
|
NEXT_SEQ=1 # Reset sequence for a new month
|
||||||
|
fi
|
||||||
|
|
||||||
|
NEW_VERSION="${CURRENT_YEAR}.${CURRENT_MONTH}.${NEXT_SEQ}"
|
||||||
|
|
||||||
|
# Update the plain text VERSION file
|
||||||
|
echo "$NEW_VERSION" > "$VERSION_FILE"
|
||||||
|
|
||||||
|
# Update the YAML VERSION_YAML file
|
||||||
|
echo "version: $NEW_VERSION" > "$VERSION_YAML_FILE"
|
||||||
|
|
||||||
|
# Commit and tag
|
||||||
|
if ! git add "$VERSION_FILE" "$VERSION_YAML_FILE"; then
|
||||||
|
echo "Error: Failed to stage version files"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! git commit -m "Bump version to $NEW_VERSION [skip-versioning]"; then
|
||||||
|
echo "Error: Failed to commit version bump"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! git tag "v$NEW_VERSION"; then
|
||||||
|
echo "Error: Failed to create version tag"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
Reference in New Issue
Block a user