Compare commits

...

84 Commits

Author SHA1 Message Date
GitHub Actions
bbbaeeb0d4 Bump version to 2024.12.7 [skip-versioning] 2024-12-22 23:02:49 +00:00
Edward Firmo
a9f82d958f Merge pull request #54 from edwardtfn/event-based-automation-docs
Event based automation docs
2024-12-23 00:02:40 +01:00
Edward Firmo
c07e4f195a CodeRabbitAI 2024-12-22 23:55:18 +01:00
Edward Firmo
f1f545198b CodeRabbitAI 2024-12-22 23:47:03 +01:00
Edward Firmo
d87b86bfca CodeRabbitAI 2024-12-22 23:41:02 +01:00
Edward Firmo
f11840d2bc markdownlint 2024-12-22 23:23:22 +01:00
Edward Firmo
42afe71365 Add event based automation overview
Helps with #51
2024-12-22 23:20:39 +01:00
GitHub Actions
09e9d340fc Bump version to 2024.12.6 [skip-versioning] 2024-12-22 16:41:40 +00:00
Edward Firmo
7850d16aeb Push tag before setting latest and stable 2024-12-22 17:40:45 +01:00
Edward Firmo
1f2e60e7db Merge pull request #53 from edwardtfn/use-main-as-ref
Use `main` as reference for remote package
2024-12-22 17:23:39 +01:00
Edward Firmo
dd25e5dbba Use bump_version.sh from folder versioning 2024-12-22 17:19:59 +01:00
Edward Firmo
75f4245fe1 No need another versioning action 2024-12-22 17:16:09 +01:00
Edward Firmo
3b7f811876 Tag latest and stable only after versioning 2024-12-22 17:04:52 +01:00
Edward Firmo
d403bc2aa9 CodeRabbitAI - Remove duplicated badge reference 2024-12-22 16:41:21 +01:00
Edward Firmo
5d780f162e Add version badge 2024-12-22 16:37:05 +01:00
Edward Firmo
0e53dfd3cd CodeRabbitAI 2024-12-22 16:26:49 +01:00
Edward Firmo
23b633cdcb Run all tests in parallel
Let's see if this saves some time.
2024-12-22 16:20:51 +01:00
Edward Firmo
b1187332fb Ensure latest and stable tags are updated on push to main 2024-12-22 16:17:07 +01:00
Edward Firmo
669cc2f2c2 Use main as reference for remote package 2024-12-22 16:03:39 +01:00
GitHub Actions
e5d941c460 Bump version to 2024.12.4 [skip-versioning] 2024-12-22 01:12:50 +00:00
Edward Firmo
9b134a786a Merge pull request #50 from edwardtfn/swipe-priority
Rebuild Button click engine
2024-12-22 02:12:39 +01:00
Edward Firmo
be0fc353f6 Simplify relay handler 2024-12-22 02:03:35 +01:00
Edward Firmo
fbc5cb79cc Reduce BUTTON_MULTI_CLICK_DELAY to 250ms 2024-12-22 01:46:28 +01:00
Edward Firmo
c65acc3298 Pass parameters to button_click_event 2024-12-22 01:37:07 +01:00
Edward Firmo
4d8107faf2 Remove relay from binary sensor 2024-12-22 01:15:26 +01:00
Edward Firmo
65bbd901b1 Clean-up get_button_from_position 2024-12-21 23:32:15 +01:00
Edward Firmo
8c610a406a Log long-press from component
If this works fine, it could replace this part on the new implementation.
2024-12-21 23:17:42 +01:00
Edward Firmo
696e3bf28d Component to provide button number 2024-12-21 23:10:16 +01:00
Edward Firmo
5ae4564e6a CodeRabbitAI Nitpick 2 2024-12-21 22:08:19 +01:00
Edward Firmo
857c43940d CodeRabbitAI Nitpick 2024-12-21 21:54:54 +01:00
Edward Firmo
8668fe8dc9 Fix another bad reference 2024-12-21 21:29:05 +01:00
Edward Firmo
976a903118 Fix references 2024-12-21 21:25:29 +01:00
Edward Firmo
35cc0c4a8e Reorganize scripts for better clarity 2024-12-21 21:18:54 +01:00
Edward Firmo
5c4581563e Rebuild Button click engine
The native engine from ESPHome cannot be used here as a button press event is triggered on touch, which would trigger the click even on swipe.
Other projects solved this by tracking only single click and only at release, so we decided to implement this in a different way, so we can handle multiple or long-clicks also.
This should finally solve #14, but some test is required to ensure nothing else was broken.
2024-12-21 21:14:41 +01:00
GitHub Actions
7f1c362a50 Bump version to 2024.12.3 [skip-versioning] 2024-12-21 17:09:47 +00:00
Edward Firmo
cf3018c95c Merge pull request #49 from edwardtfn/new-versioning-03
Fix verison validation
2024-12-21 18:09:37 +01:00
Edward Firmo
360ae3123a Update bump_version.sh 2024-12-21 18:06:00 +01:00
Edward Firmo
6767b5e765 Fix version validation 2024-12-21 18:00:46 +01:00
Edward Firmo
d5e5ebb3d6 Fix version format 2024-12-21 17:52:33 +01:00
Edward Firmo
46c04eb992 Merge pull request #46 from edwardtfn/new-versioning-03
Rollback to the last working point
2024-12-21 17:50:34 +01:00
Edward Firmo
8558bc3650 Merge branch 'main' into new-versioning-03 2024-12-21 17:49:58 +01:00
Edward Firmo
f32e2eee4f Add quotes around file path in cat command
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2024-12-21 17:14:00 +01:00
Edward Firmo
5a993165cd Rollback to the last working point 2024-12-21 14:54:47 +01:00
Edward Firmo
d04c2aff2f Merge pull request #45 from edwardtfn/new-versioning-02
Use an automation branch
2024-12-21 14:14:00 +01:00
Edward Firmo
2d79ee42c7 Quote variables and url 2024-12-21 14:05:37 +01:00
Edward Firmo
3f4fc7a505 Quote GitHub token in push command
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2024-12-21 13:55:26 +01:00
Edward Firmo
be23a5a0fd Quote variables in temporary branch creation
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2024-12-21 13:54:51 +01:00
Edward Firmo
a23a2db352 Fix invalid YAML structure in push trigger
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2024-12-21 13:35:12 +01:00
Edward Firmo
4e73a11528 Use an automation branch 2024-12-21 13:27:58 +01:00
Edward Firmo
3c98d81bb7 Merge pull request #44 from edwardtfn/new-versioning-01
No leading zero on versions
2024-12-21 12:31:30 +01:00
Edward Firmo
e63447984d Remove duplicated version validation 2024-12-21 12:26:05 +01:00
Edward Firmo
1f1a8049e6 No leading zero on versions 2024-12-21 12:23:32 +01:00
Edward Firmo
0dddc0747b Merge pull request #43 from edwardtfn/test-new-versioning-04
Describe file
2024-12-21 11:55:06 +01:00
Edward Firmo
86d1513c6a Describe file 2024-12-21 11:54:42 +01:00
GitHub Actions
ac4d583b64 Bump version to 2024.12.01 2024-12-21 10:37:03 +00:00
Edward Firmo
15830d4134 Merge pull request #42 from edwardtfn/test-new-versioning-03
Fix repo name
2024-12-21 11:27:19 +01:00
Edward Firmo
0c19ca1205 Fix repo name 2024-12-21 11:26:57 +01:00
Edward Firmo
2d676036dc Merge pull request #41 from edwardtfn/test-new-versioning-02
New approach to GitHub tokens
2024-12-21 11:20:35 +01:00
Edward Firmo
c8ffa9e224 New approach to GitHub tokens 2024-12-21 11:20:13 +01:00
Edward Firmo
1406ada53a Merge pull request #40 from edwardtfn/test-new-versioning
Testing new versioning
2024-12-21 11:13:58 +01:00
Edward Firmo
f02f90c3fa Testing new versioning 2024-12-21 11:05:40 +01:00
Edward Firmo
f6169e3ea2 Merge branch 'main' of https://github.com/edwardtfn/TX-Ultimate-Easy 2024-12-21 11:01:47 +01:00
Edward Firmo
6774a1ac18 Set initial version number 2024-12-21 11:01:01 +01:00
Edward Firmo
21720d8ba3 Merge pull request #39 from edwardtfn/dev
New versioning
2024-12-21 10:58:41 +01:00
Edward Firmo
7727c968db Merge branch 'dev' of https://github.com/edwardtfn/TX-Ultimate-Easy into dev 2024-12-21 10:33:54 +01:00
Edward Firmo
dc9e19d43c Add section about version validation 2024-12-21 10:33:36 +01:00
Edward Firmo
737343e395 Add fetch-depth: 0 to checkout action
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2024-12-21 10:31:23 +01:00
Edward Firmo
5569260f92 Update checkout action version
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2024-12-21 10:30:28 +01:00
Edward Firmo
04ca752c3b Add error handling for git operations
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2024-12-21 10:29:46 +01:00
Edward Firmo
23436428a4 Add error handling for invalid version format
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2024-12-21 10:29:12 +01:00
Edward Firmo
26a244cbed Fix potential overflow in sequence number
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2024-12-21 10:28:14 +01:00
Edward Firmo
ce8b4e700e Merge pull request #38 from edwardtfn/0.0.5
Clean up LED files & new versioning
2024-12-21 10:18:49 +01:00
Edward Firmo
35bf4bc0ec New versioning 2024-12-21 10:17:32 +01:00
Edward Firmo
ee8ff66add Removed LED auxiliary files
Using YAML anchors instead.
It makes it cleaner and easier to understand.
2024-12-21 08:54:41 +01:00
Edward Firmo
96db05cc34 Fix typo 2024-12-21 00:24:02 +01:00
Edward Firmo
61a5d67082 Merge pull request #36 from edwardtfn/dev
v0.0.4 - Bug fixes
2024-12-21 00:17:12 +01:00
Edward Firmo
ce9aefc7fe Merge pull request #37 from edwardtfn/0.0.4
CodeRabbitAI
2024-12-21 00:08:47 +01:00
Edward Firmo
1d38ac282c Merge pull request #35 from edwardtfn/0.0.4
Wrap-up
2024-12-20 23:37:50 +01:00
Edward Firmo
2ae4d2abe8 Merge pull request #34 from edwardtfn/0.0.4
Rebuilt relay status indicator engine
2024-12-20 19:41:14 +01:00
Edward Firmo
3543c0c088 Merge pull request #33 from edwardtfn/0.0.4
Remove references to Blueprint in the README
2024-12-20 02:36:46 +01:00
Edward Firmo
242325e556 Merge pull request #32 from edwardtfn/0.0.4
v0.0.4 - Bug fixes
2024-12-20 02:18:34 +01:00
Edward Firmo
f65f3a930c Merge pull request #26 from edwardtfn/dev
Fix toggle with swipe
2024-07-26 08:35:46 +02:00
Edward Firmo
0bf52a28c0 Merge pull request #25 from edwardtfn/dev
Support ESPHome v2024.6.0
2024-06-20 00:29:03 +02:00
Edward Firmo
976814eb58 Merge pull request #11 from edwardtfn/dev
First workable version
2024-05-29 22:23:15 +02:00
25 changed files with 717 additions and 501 deletions

View File

@@ -1,32 +0,0 @@
---
name: Update Tags
# yamllint disable-line rule:truthy
on:
release:
types: [published]
jobs:
update-tags:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@main
with:
fetch-depth: '0'
- name: Set up Git
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
- name: Move and push stable tag
run: |
git tag -f stable ${{ github.event.release.tag_name }}
git push -f origin stable
- name: Move and push latest tag
run: |
git tag -f latest ${{ github.event.release.tag_name }}
git push -f origin latest
...

View File

@@ -30,8 +30,6 @@ jobs:
build_basic:
name: Basic
needs:
- code_scan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@main
@@ -42,7 +40,6 @@ jobs:
build_bluetooth_proxy_4:
name: Bluetooth Proxy (IDF)
needs: build_basic
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@main
@@ -53,7 +50,6 @@ jobs:
build_bluetooth_proxy_53:
name: Bluetooth Proxy (IDF v5.3)
needs: build_basic
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@main

View File

@@ -1,8 +1,7 @@
---
name: Validate ESPHome (Beta)
# yamllint disable-line rule:truthy
on:
on: # yamllint disable-line rule:truthy
push:
paths:
- "*.yaml"
@@ -48,8 +47,6 @@ jobs:
build_basic:
name: Basic
needs:
- code_scan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@main
@@ -61,7 +58,6 @@ jobs:
build_bluetooth_proxy_4:
name: Bluetooth Proxy (IDF)
needs: build_basic
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@main
@@ -73,7 +69,6 @@ jobs:
build_bluetooth_proxy_53:
name: Bluetooth Proxy (IDF v5.3)
needs: build_basic
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@main

106
.github/workflows/versioning.yml vendored Normal file
View File

@@ -0,0 +1,106 @@
# This GitHub Actions workflow handles version bumping and tag updates.
# It can be triggered either by:
# 1. Pushing to main branch - automatically bumps version and updates tags
# 2. Manual dispatch - allows independent control over stable and latest tags
---
name: Version and Tags
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
type: boolean
update_latest:
description: "Update latest tag?"
required: true
default: false
type: boolean
jobs:
version-and-tag:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- 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 origin main
git push origin --tags --force
- name: Update stable tag
if: |
success() && (
github.event_name == 'workflow_dispatch' && inputs.update_stable ||
github.event_name == 'push'
)
run: |
# Verify version bump was successful
if [ ! -f "./versioning/VERSION" ]; then
echo "Error: VERSION file not found. Version bump may have failed."
exit 1
fi
# Backup existing tag
if git rev-parse --verify stable >/dev/null 2>&1; then
OLD_STABLE=$(git rev-parse stable)
echo "Backing up current stable tag ($OLD_STABLE)"
fi
# Update tag
NEW_VERSION=$(cat ./versioning/VERSION)
echo "Updating stable tag to $NEW_VERSION"
git tag -fa stable -m "Update stable tag"
git push origin stable --force
- name: Update latest tag
if: |
success() && (
github.event_name == 'workflow_dispatch' && inputs.update_latest ||
github.event_name == 'push'
)
run: |
# Verify version bump was successful
if [ ! -f "./versioning/VERSION" ]; then
echo "Error: VERSION file not found. Version bump may have failed."
exit 1
fi
# Backup existing tag
if git rev-parse --verify latest >/dev/null 2>&1; then
OLD_LATEST=$(git rev-parse latest)
echo "Backing up current latest tag ($OLD_LATEST)"
fi
# Update tag
NEW_VERSION=$(cat ./versioning/VERSION)
echo "Updating latest tag to $NEW_VERSION"
git tag -fa latest -m "Update latest tag"
git push origin latest --force
...

View File

@@ -1,6 +1,6 @@
---
packages:
basic_package: !include ../TX-Ultimate-Easy-ESPHome.yaml # Basic package
basic_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml # Basic package
esp32:
framework:

View File

@@ -1,6 +1,6 @@
---
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
esp32:

View File

@@ -1,5 +1,5 @@
---
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
...

BIN
Assets/Logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

View File

@@ -15,11 +15,7 @@ substitutions:
name: tx-ultimate-easy
friendly_name: TX Ultimate Easy
latitude: '0'
longitude: '0'
zone_home: 'zone.home'
version: '0.0.4'
<<: !include ../versioning/VERSION_YAML
TX_MODEL_FORMAT_EU_TEXT: "EU (Square, T5-xC-86)"
TX_MODEL_FORMAT_US_TEXT: "US (Rectangle, T5-xC-120)"
@@ -78,7 +74,7 @@ improv_serial:
id: serial_improv
logger:
level: INFO
level: DEBUG
ota:
platform: esphome

View File

@@ -20,111 +20,53 @@ substitutions:
BUTTON_3_ACTION_TEXT: "Relay 3 (toggle)"
BUTTON_4_ACTION_TEXT: "Relay 4 (toggle)"
binary_sensor:
- id: bs_button_1
name: Button 1
icon: mdi:gesture-tap-box
internal: false
platform: template
on_click:
then:
- script.execute:
id: button_action
component: bs_button_1
event: click
on_double_click:
then:
- script.execute:
id: button_action
component: bs_button_1
event: double_click
on_multi_click:
- timing: &long_click-timing
- ON for at least 0.8s
invalid_cooldown: ${invalid_cooldown}
then:
- script.execute:
id: button_action
component: bs_button_1
event: long_click
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
- id: bs_button_2
binary_sensor:
- &binary_sensor_button_base
id: bs_button_2
name: Button 2
icon: mdi:gesture-tap-box
internal: true
platform: template
on_click:
then:
- script.execute:
id: button_action
component: bs_button_2
event: click
on_double_click:
then:
- script.execute:
id: button_action
component: bs_button_2
event: double_click
on_multi_click:
- timing: *long_click-timing
invalid_cooldown: ${invalid_cooldown}
then:
- script.execute:
id: button_action
component: bs_button_2
event: long_click
internal: true
- id: bs_button_3
name: Button 3
icon: mdi:gesture-tap-box
internal: true
platform: template
on_click:
then:
- script.execute:
id: button_action
component: bs_button_3
event: click
on_double_click:
then:
- script.execute:
id: button_action
component: bs_button_3
event: double_click
on_multi_click:
- timing: *long_click-timing
invalid_cooldown: ${invalid_cooldown}
then:
- script.execute:
id: button_action
component: bs_button_3
event: long_click
<<: *binary_sensor_button_base
- id: bs_button_4
name: Button 4
icon: mdi:gesture-tap-box
internal: true
platform: template
on_click:
then:
- script.execute:
id: button_action
component: bs_button_4
event: click
on_double_click:
then:
- script.execute:
id: button_action
component: bs_button_4
event: double_click
on_multi_click:
- timing: *long_click-timing
invalid_cooldown: ${invalid_cooldown}
then:
- script.execute:
id: button_action
component: bs_button_4
event: long_click
<<: *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
@@ -162,9 +104,31 @@ script:
parameters:
component: string
event: string
then: # There's nothing here so far
# Extended by:
# - core_api
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
@@ -187,42 +151,78 @@ script:
then:
- script.execute:
id: touch_on_press_buttons
touch_x: !lambda return touch_x;
touch_position: !lambda return touch_position;
- id: touch_on_press_buttons
mode: restart
parameters:
touch_x: uint8_t
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()) {
uint8_t model_idx = model_index.value() + 1;
switch (model_idx) {
case 1: // 1 Gang
bs_button_1->publish_state(true);
break;
case 2: // 2 Gang
if (touch_x <= 5) bs_button_1->publish_state(true);
else bs_button_2->publish_state(true);
break;
case 3: // 3 Gang
if (touch_x <= 3) bs_button_1->publish_state(true);
else if (touch_x <= 7) bs_button_2->publish_state(true);
else bs_button_3->publish_state(true);
break;
case 4: // 4 Gang
if (touch_x <= 2) bs_button_1->publish_state(true);
else if (touch_x <= 5) bs_button_2->publish_state(true);
else if (touch_x <= 8) bs_button_3->publish_state(true);
else bs_button_4->publish_state(true);
break;
}
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:
- script.execute: buttons_release
- 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:

View File

@@ -21,9 +21,9 @@ substitutions:
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)
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
@@ -34,27 +34,7 @@ globals:
restore_value: false
light:
- id: light_output_1
name: Light output 1
internal: true
platform: binary
output: output_relay_1
- id: light_output_2
name: Light output 2
internal: true
platform: binary
output: output_relay_2
- id: light_output_3
name: Light output 3
internal: true
platform: binary
output: output_relay_3
- id: light_output_4
name: Light output 4
internal: true
platform: binary
output: output_relay_4
# These lights are controlling the LEDs on the device
- id: light_full
name: Light - All
internal: true
@@ -65,11 +45,51 @@ light:
num_leds: 32
pin: GPIO13
- id: light_eu
# 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
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml
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
@@ -77,20 +97,17 @@ light:
- id: light_us
name: Light
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml
<<: *light_partition_with_effects
segments:
- id: light_full
from: 0
to: 31
# Those lights are available based on the model selections
- id: light_eu_bottom
- &light_partition_with_effects_disabled
id: light_eu_bottom
name: Light - Bottom
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml
disabled_by_default: true
<<: *light_partition_with_effects
segments:
- id: light_full
from: 6
@@ -98,9 +115,7 @@ light:
reversed: true
- id: light_eu_left
name: Light - Left
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml
<<: *light_partition_with_effects_disabled
segments:
- id: light_full
from: 13
@@ -108,9 +123,7 @@ light:
reversed: true
- id: light_eu_right
name: Light - Right
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml
<<: *light_partition_with_effects_disabled
segments:
- id: light_full
from: 27
@@ -122,9 +135,7 @@ light:
reversed: false
- id: light_eu_top
name: Light - Top
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml
<<: *light_partition_with_effects_disabled
segments:
- id: light_full
from: 20
@@ -132,9 +143,7 @@ light:
reversed: false
- id: light_us_bottom
name: Light - Bottom
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml
<<: *light_partition_with_effects_disabled
segments:
- id: light_full
from: 9
@@ -142,9 +151,7 @@ light:
reversed: true
- id: light_us_left
name: Light - Left
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml
<<: *light_partition_with_effects_disabled
segments:
- id: light_full
from: 15
@@ -152,9 +159,7 @@ light:
reversed: true
- id: light_us_right
name: Light - Right
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml
<<: *light_partition_with_effects_disabled
segments:
- id: light_full
from: 31
@@ -166,444 +171,399 @@ light:
reversed: false
- id: light_us_top
name: Light - Top
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_effects.yaml
<<: *light_partition_with_effects_disabled
segments:
- id: light_full
from: 25
to: 30
reversed: false
- id: light_00
- &light_partition_individual_led
id: light_00
name: Light - LED 00
platform: partition
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
default_transition_length: ${default_transition_length}
segments:
- id: light_full
from: 0
to: 0
- id: light_01
name: Light - LED 01
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 1
to: 1
- id: light_02
name: Light - LED 02
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 2
to: 2
- id: light_03
name: Light - LED 03
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 3
to: 3
- id: light_04
name: Light - LED 04
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 4
to: 4
- id: light_05
name: Light - LED 05
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 5
to: 5
- id: light_06
name: Light - LED 06
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 6
to: 6
- id: light_07
name: Light - LED 07
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 7
to: 7
- id: light_08
name: Light - LED 08
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 8
to: 8
- id: light_09
name: Light - LED 09
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 9
to: 9
- id: light_10
name: Light - LED 10
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 10
to: 10
- id: light_11
name: Light - LED 11
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 11
to: 11
- id: light_12
name: Light - LED 12
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 12
to: 12
- id: light_13
name: Light - LED 13
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 13
to: 13
- id: light_14
name: Light - LED 14
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 14
to: 14
- id: light_15
name: Light - LED 15
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 15
to: 15
- id: light_16
name: Light - LED 16
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 16
to: 16
- id: light_17
name: Light - LED 17
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 17
to: 17
- id: light_18
name: Light - LED 18
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 18
to: 18
- id: light_19
name: Light - LED 19
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 19
to: 19
- id: light_20
name: Light - LED 20
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 20
to: 20
- id: light_21
name: Light - LED 21
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 21
to: 21
- id: light_22
name: Light - LED 22
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 22
to: 22
- id: light_23
name: Light - LED 23
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 23
to: 23
- id: light_24
name: Light - LED 24
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 24
to: 24
- id: light_25
name: Light - LED 25
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 25
to: 25
- id: light_26
name: Light - LED 26
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 26
to: 26
- id: light_27
name: Light - LED 27
disabled_by_default: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_individual_led
segments:
- id: light_full
from: 27
to: 27
- id: light_28
- id: light_28 # US Model only
name: Light - LED 28
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
internal: true
<<: *light_partition_individual_led
segments:
- id: light_full
from: 28
to: 28
- id: light_29
- id: light_29 # US Model only
name: Light - LED 29
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
internal: true
<<: *light_partition_individual_led
segments:
- id: light_full
from: 29
to: 29
- id: light_30
- id: light_30 # US Model only
name: Light - LED 30
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
internal: true
<<: *light_partition_individual_led
segments:
- id: light_full
from: 30
to: 30
- id: light_31
- id: light_31 # US Model only
name: Light - LED 31
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_internal.yaml
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
internal: true
<<: *light_partition_individual_led
segments:
- id: light_full
from: 31
to: 31
- id: light_eu_rl_1_1_bottom
# 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
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_relays
segments:
- id: light_full
from: 31
@@ -613,16 +573,14 @@ light:
to: 8
- id: light_us_rl_1_2_left
name: Light - Relay 1 of 2 (left)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_relays
segments:
- id: light_full
from: 31
@@ -632,128 +590,112 @@ light:
to: 3
- id: light_us_rl_2_2_left
name: Light - Relay 2 of 2 (left)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *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)
internal: true
<<: !include TX-Ultimate-Easy-ESPHome_core_hw_leds_light_base.yaml
<<: *light_partition_relays
segments:
- id: light_full
from: 7
@@ -817,7 +759,7 @@ script:
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: // 3 Gang
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 };

View File

@@ -1,4 +0,0 @@
---
platform: partition
default_transition_length: ${default_transition_length}
...

View File

@@ -1,40 +0,0 @@
---
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"
...

View File

@@ -1,4 +0,0 @@
---
internal: true
disabled_by_default: true
...

View File

@@ -11,61 +11,33 @@
##### - For normal system use, modifications to this file are NOT required. #####
####################################################################################################
---
binary_sensor:
- id: !extend bs_button_1
on_click:
then:
- if:
condition:
- lambda: return sl_button_1_action->active_index().has_value();
- lambda: return sl_button_1_action->active_index().value() == 1;
- and: &button_click_no_other_click
- lambda: return not bs_multi_touch->state;
- lambda: return not bs_swipe_left->state;
- lambda: return not bs_swipe_down->state;
- lambda: return not bs_swipe_right->state;
then:
- switch.toggle: sw_relay_1
- id: !extend bs_button_2
on_click:
then:
- if:
condition:
- lambda: return sl_button_2_action->active_index().has_value();
- lambda: return sl_button_2_action->active_index().value() == 1;
- and: *button_click_no_other_click
then:
- switch.toggle: sw_relay_2
- id: !extend bs_button_3
on_click:
then:
- if:
condition:
- lambda: return sl_button_3_action->active_index().has_value();
- lambda: return sl_button_3_action->active_index().value() == 1;
- and: *button_click_no_other_click
then:
- switch.toggle: sw_relay_3
- id: !extend bs_button_4
on_click:
then:
- if:
condition:
- lambda: return sl_button_4_action->active_index().has_value();
- lambda: return sl_button_4_action->active_index().value() == 1;
- and: *button_click_no_other_click
then:
- switch.toggle: sw_relay_4
globals:
- id: boot_initialization_relays
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
@@ -138,6 +110,45 @@ script:
}
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:

View File

@@ -11,6 +11,9 @@
##### - 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
@@ -61,7 +64,7 @@ external_components:
- source:
type: git
url: https://github.com/edwardtfn/TX-Ultimate-Easy
ref: ${version}
ref: v${version}
refresh: 1h
components:
- tx_ultimate_easy
@@ -124,7 +127,7 @@ script:
- id: touch_on_press
mode: restart
parameters:
touch_x: uint8_t
touch_position: uint8_t
then:
# Extended by:
# - HW Buttons
@@ -203,16 +206,28 @@ 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: |-
ESP_LOGI("tx_ultimate_easy", "Pressed at position %" PRIu8, static_cast<uint8_t>(touch.x));
- script.execute:
id: touch_on_press
touch_x: !lambda return static_cast<uint8_t>(touch.x);
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");
@@ -233,8 +248,8 @@ tx_ultimate_easy:
ESP_LOGD("tx_ultimate_easy", " Position: %i", touch.x);
uart:
id: uart_touch
tx_pin: GPIO19
rx_pin: GPIO22
baud_rate: 115200
- id: uart_touch
tx_pin: GPIO19
rx_pin: GPIO22
baud_rate: 115200
...

View File

@@ -1,19 +1,20 @@
# TX Ultimate Easy
<!-- markdownlint-disable MD033 -->
<a href="https://github.com/edwardtfn/TX-Ultimate-Easy/commits/main" target="_blank">![GitHub Activity][commits-shield]</a>
<a href="LICENSE" target="_blank">![License][license-shield]</a>
<a href="https://github.com/edwardtfn/TX-Ultimate-Easy/commits/main" target="_blank">![GitHub Last Commit][last-commit-shield]</a>
<a href="https://esphome.io/" target="_blank">![ESPHome][esphome-shield]</a>
<a href="https://discord.gg/Db6WJWzWuf" target="_blank">![Discord][discord-shield]</a>
<a href="https://www.buymeacoffee.com/edwardfirmo" target="_blank">![Buy me an ice-cream][buymeacoffee-shield]</a>
<!-- markdownlint-enable MD033 -->
[![Version][version-shield]](https://github.com/edwardtfn/TX-Ultimate-Easy/tags)
[![GitHub Activity][commits-shield]](https://github.com/edwardtfn/TX-Ultimate-Easy/commits/main)
[![License][license-shield]](LICENSE)
[![GitHub Last Commit][last-commit-shield]](https://github.com/edwardtfn/TX-Ultimate-Easy/commits/main)
[![ESPHome][esphome-shield]](https://esphome.io/)
[![Discord][discord-shield]](https://discord.gg/Db6WJWzWuf)
[![Buy me an ice-cream][buymeacoffee-shield]](https://www.buymeacoffee.com/edwardfirmo)
<!-- markdownlint-disable MD013 -->
| &nbsp;![TX Ultimate Easy Logo](Assets/Logo.webp) | TX Ultimate Easy provides custom ESPHome firmware for Sonoff TX Ultimate devices. Our project focuses on user-friendly configuration through the Home Assistant UI, eliminating the need for manual YAML editing. Whether you're new to home automation or an experienced user, TX Ultimate Easy makes it simple to manage your device. |
| --- | :-- |
<!-- markdownlint-enable MD013 -->
[version-shield]: https://img.shields.io/github/v/tag/edwardtfn/TX-Ultimate-Easy?label=version
[version]: https://github.com/edwardtfn/TX-Ultimate-Easy/tags
[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
@@ -35,7 +36,60 @@ TX Ultimate Easy exposes your device's components (sensors, touch panel, relays,
- Use device triggers and states in your Home Assistant automations and scripts
- Configure device behavior through Home Assistant's service calls
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.
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.
### Event-Based Automation
TX Ultimate Easy uses Home Assistant's native Events system for reliable automation triggers.
While sensors show the current state (e.g., button pressed/not pressed), events capture-specific actions like clicks, swipes, and long presses.
To view available events:
1. Go to Developer Tools in Home Assistant
2. Select the "Events" tab
3. Enter `esphome.tx_ultimate_easy` in the "Event to subscribe to" field
4. Click "Start listening"
5. Interact with your device to see events in real-time
Example event trigger in automation (YAML):
```yaml
triggers:
- platform: event
event_type: esphome.tx_ultimate_easy
event_data:
device_name: your_device_name # Replace with your specific device name
component: bs_button_1 # Button identifier (e.g., bs_button_1, bs_button_2, bs_button_3 or bs_button_4)
event: click
actions:
- action: light.toggle
target:
entity_id: light.living_room
```
**Common event types**:
- `click`: Single press and release
- `double_click`: Two quick presses
- `long_press`: Press and hold
- `swipe_left`: Left swipe gesture
- `swipe_right`: Right swipe gesture
You can also create event-based automations through the Home Assistant UI by selecting "Event" as the trigger type and filtering by your device.
### Device Configuration
#### Relay Modes
- **Light Mode**: Exposes the relay as a light entity with brightness controls (if supported)
- **Switch Mode**: Exposes the relay as a simple on/off switch entity
#### Button Actions
- **None**: Allows using button events for custom automations
Example: Trigger scenes or complex automations through Home Assistant
- **Relay Toggle**: Direct control of the associated relay
Example: Toggle relay state with each press, independent of Home Assistant
#### Automation
All device behaviors can be customized through Home Assistant automations without relying on local device triggers.
## Key Features
@@ -98,17 +152,16 @@ TX Ultimate Easy offers extensive configuration options:
We welcome contributions from the community! Here's how you can help:
1. Fork the repository
2. Create a feature branch from `dev`
2. Create a feature branch from `main`
3. Make your changes
4. Submit a pull request targeting the `dev` branch
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
All pull requests should be made against the `dev` branch. We don't accept pull requests directly to `main` as it's reserved for stable releases.
## Support and Community
Need help? Here are your options:
@@ -117,7 +170,9 @@ Need help? Here are your options:
- **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)
Note: For proper tracking and resolution:
- All bug reports and feature requests must be submitted through GitHub Issues, not Discord
- Submit issues here: [Issues · edwardtfn/TX-Ultimate-Easy](https://github.com/edwardtfn/TX-Ultimate-Easy/issues)
[![Buy Me a Coffee](https://www.buymeacoffee.com/assets/img/custom_images/yellow_img.png)](https://www.buymeacoffee.com/edwardfirmo)

View File

@@ -16,7 +16,7 @@ wifi:
packages:
remote_package:
url: https://github.com/edwardtfn/TX-Ultimate-Easy
ref: dev
ref: main
refresh: 30s
files:
- ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml

View File

@@ -13,6 +13,7 @@ DEPENDENCIES = ['uart']
CONF_TX_ULTIMATE_EASY = "tx_ultimate_easy"
CONF_UART = "uart"
CONF_GANG_COUNT = "gang_count"
CONF_ON_TOUCH_EVENT = "on_touch_event"
CONF_ON_PRESS = "on_press"
@@ -33,6 +34,7 @@ CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_id(TxUltimateTouch),
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_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])
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:
await automation.build_automation(
var.get_trigger_touch_event(),
@@ -98,6 +103,7 @@ async def register_tx_ultimate_easy(var, config):
config[CONF_ON_LONG_TOUCH_RELEASE],
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)

View File

@@ -48,6 +48,35 @@ namespace esphome {
void TxUltimateEasy::dump_config() {
ESP_LOGCONFIG(TAG, "TX Ultimate Easy");
ESP_LOGCONFIG(TAG, " Gang count: %" PRIu8, this->gang_count_);
}
bool TxUltimateEasy::set_gang_count(const uint8_t gang_count) {
// Hardware supports maximum of 4 touch-sensitive buttons
if (gang_count < 1 or gang_count > 4)
return false;
this->gang_count_ = gang_count;
return true;
}
uint8_t TxUltimateEasy::get_button_from_position(const uint8_t position) {
// Validate position bounds
if (position > TOUCH_MAX_POSITION)
return 0;
// Special case for single gang (only one button exists)
if (this->gang_count_ == 1)
return 1;
// Calculate button number
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) {
@@ -103,7 +132,8 @@ namespace esphome {
state == TOUCH_STATE_SWIPE_LEFT ||
state == TOUCH_STATE_SWIPE_RIGHT ||
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) {
@@ -133,6 +163,8 @@ namespace esphome {
TouchPoint TxUltimateEasy::get_touch_point(const std::array<int, UART_RECEIVED_BYTES_SIZE> &uart_received_bytes) {
TouchPoint tp;
tp.x = this->get_touch_position_x(uart_received_bytes);
if (tp.x >= 0)
tp.button = this->get_button_from_position(static_cast<uint8_t>(tp.x));
tp.state = this->get_touch_state(uart_received_bytes);
switch (tp.state) {
case TOUCH_STATE_RELEASE:

View File

@@ -13,6 +13,9 @@
namespace esphome {
namespace tx_ultimate_easy {
// Touch Max Position
constexpr uint8_t TOUCH_MAX_POSITION = 10;
// Touch State Constants
constexpr uint8_t TOUCH_STATE_RELEASE = 0x01;
constexpr uint8_t TOUCH_STATE_PRESS = 0x02;
@@ -32,6 +35,7 @@ namespace esphome {
static const char *TAG = "tx_ultimate_easy";
struct TouchPoint {
uint8_t button = 0;
int8_t x = -1;
int8_t state = -1;
std::string state_str = "Unknown";
@@ -53,6 +57,10 @@ namespace esphome {
void loop() override;
void dump_config() override;
uint8_t get_gang_count() { return this->gang_count_; }
bool set_gang_count(const uint8_t gang_count);
uint8_t get_button_from_position(const uint8_t position);
protected:
void send_touch_(TouchPoint tp);
void handle_touch(const std::array<int, UART_RECEIVED_BYTES_SIZE> &bytes);
@@ -70,6 +78,8 @@ namespace esphome {
Trigger<TouchPoint> trigger_multi_touch_release_;
Trigger<TouchPoint> trigger_long_touch_release_;
uint8_t gang_count_ = 1;
}; // class TxUltimateEasy
} // namespace tx_ultimate_easy

76
versioning/README.md Normal file
View 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 112 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
View File

@@ -0,0 +1 @@
2024.12.7

1
versioning/VERSION_YAML Normal file
View File

@@ -0,0 +1 @@
version: 2024.12.7

View 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