Compare commits
181 Commits
v2024.12.2
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 76cecb268a | |||
| 69f3985d59 | |||
| 1a73150368 | |||
|
|
cd39fee788 | ||
|
|
d9f361b404 | ||
|
|
6ffa73b321 | ||
|
|
e2b4fa4186 | ||
|
|
63c98fcc68 | ||
|
|
8943dc7ea9 | ||
|
|
15c7ddc4b4 | ||
|
|
22a99017fa | ||
|
|
67d1c2cdce | ||
|
|
65d08194aa | ||
|
|
0690ae14d8 | ||
|
|
0b430a7ce0 | ||
|
|
03e0004e8c | ||
|
|
6d2de0d32b | ||
|
|
8af692e82d | ||
|
|
fc135875c5 | ||
|
|
aae3eaa204 | ||
|
|
fe745c0132 | ||
|
|
5757714b31 | ||
|
|
6520b8050e | ||
|
|
a10edb3d06 | ||
|
|
1df58e162f | ||
|
|
d905b69ad2 | ||
|
|
462b131cb6 | ||
|
|
cf8590b460 | ||
|
|
eca54c01ed | ||
|
|
0d0de08e19 | ||
|
|
3557c847b2 | ||
|
|
dbbbc4040d | ||
|
|
1bb444e008 | ||
|
|
00d70efc3b | ||
|
|
3c53b21fbe | ||
|
|
0fb4b5fe09 | ||
|
|
4634b650d9 | ||
|
|
6a1a5d5ae2 | ||
|
|
271aa74f99 | ||
|
|
ce54db0f6d | ||
|
|
93120a8b51 | ||
|
|
91f24db3b1 | ||
|
|
fa2e8f3b62 | ||
|
|
c9a85504f1 | ||
|
|
33bbad6adb | ||
|
|
bda597f748 | ||
|
|
1552aaec6c | ||
|
|
250b22562d | ||
|
|
243a18bdf2 | ||
|
|
07de172188 | ||
|
|
c1f1b5a7e7 | ||
|
|
1d8b4fee1a | ||
|
|
6d16d7d645 | ||
|
|
42ae160217 | ||
|
|
ecfc64d2f3 | ||
|
|
db83050d7b | ||
|
|
d7dcc05506 | ||
|
|
b6dc915469 | ||
|
|
dcc68f7077 | ||
|
|
23d28a32a3 | ||
|
|
ba8f19060f | ||
|
|
c36af8a220 | ||
|
|
6fad9d7074 | ||
|
|
f79ed28364 | ||
|
|
11807ce892 | ||
|
|
526b257ad6 | ||
|
|
0a95a7f8d0 | ||
|
|
6687c5c6a5 | ||
|
|
ad92799035 | ||
|
|
8e4bbda412 | ||
|
|
8eaa60b5c0 | ||
|
|
334932c6c8 | ||
|
|
0480f2ddf3 | ||
|
|
720cf3ab36 | ||
|
|
9edd43079b | ||
|
|
a67f3dfd4a | ||
|
|
796eb7620c | ||
|
|
e53334ac18 | ||
|
|
7d2080cd8d | ||
|
|
efd44fab02 | ||
|
|
8422168837 | ||
|
|
0b7f83ebca | ||
|
|
5aecb343f6 | ||
|
|
a4340da836 | ||
|
|
912607d1ec | ||
|
|
ba041a9d50 | ||
|
|
b99a6b8c54 | ||
|
|
29b292bf45 | ||
|
|
4c0a83851e | ||
|
|
9663f295d5 | ||
|
|
4707506c74 | ||
|
|
5b77f44ae2 | ||
|
|
efd4eaa6bb | ||
|
|
bc0b775df2 | ||
|
|
ddfd4b3220 | ||
|
|
54ac959abb | ||
|
|
9fdfd52ad4 | ||
|
|
e326f03502 | ||
|
|
754ad9cffe | ||
|
|
637f47583a | ||
|
|
bd86371453 | ||
|
|
54c9119a63 | ||
|
|
2d1ef49ca9 | ||
|
|
1190802ccd | ||
|
|
2cc8199593 | ||
|
|
669a78a427 | ||
|
|
78d820d91e | ||
|
|
a8277e5b88 | ||
|
|
458273206d | ||
|
|
982c64c1c1 | ||
|
|
66d1b27c0d | ||
|
|
f9da912777 | ||
|
|
6d663323e5 | ||
|
|
122cfff8db | ||
|
|
70a054616c | ||
|
|
5957e277b7 | ||
|
|
7e070617ae | ||
|
|
50a11f61ff | ||
|
|
97b193d7c3 | ||
|
|
644ba8e711 | ||
|
|
36b28a2475 | ||
|
|
1bd51f304d | ||
|
|
680042a428 | ||
|
|
0a3ceb97f5 | ||
|
|
daaffdb6ca | ||
|
|
ffdb3a22b5 | ||
|
|
b426bdd5dc | ||
|
|
3cdd9f87af | ||
|
|
ddb26cd833 | ||
|
|
5ea4f2015b | ||
|
|
ddb5e0f783 | ||
|
|
ab078f597a | ||
|
|
5eb42082db | ||
|
|
b1a978b3f3 | ||
|
|
4ec44e611f | ||
|
|
4d7895a2e9 | ||
|
|
be76ebd603 | ||
|
|
49a0f088e7 | ||
|
|
ace945a4ea | ||
|
|
e944cd2c21 | ||
|
|
1cf6f60c78 | ||
|
|
58ba5e0136 | ||
|
|
b0b19fee45 | ||
|
|
fe222ffe32 | ||
|
|
bb09d7f7f7 | ||
|
|
b6e3f41952 | ||
|
|
ba3fc89032 | ||
|
|
fcbc92aaec | ||
|
|
a59f667e7d | ||
|
|
ff3bf05ed1 | ||
|
|
8a4009dd7e | ||
|
|
6bdf6e97b7 | ||
|
|
acb602c4ca | ||
|
|
9bae016573 | ||
|
|
e47726dc47 | ||
|
|
5988681132 | ||
|
|
5d80ce1117 | ||
|
|
036e62b277 | ||
|
|
56c613a70f | ||
|
|
12fd2d3747 | ||
|
|
81f0420987 | ||
|
|
e89adca5cb | ||
|
|
a64c45b37b | ||
|
|
95291c0381 | ||
|
|
39cf0f2b10 | ||
|
|
8d03105caf | ||
|
|
e911482deb | ||
|
|
ef4f412223 | ||
|
|
9d64b099a4 | ||
|
|
037801e961 | ||
|
|
79b57304c7 | ||
|
|
48ddfbf8b0 | ||
|
|
2e43160acb | ||
|
|
8656d0c4ca | ||
|
|
133d571874 | ||
|
|
1489bc5237 | ||
|
|
11b21de8a9 | ||
|
|
e8346e4436 | ||
|
|
e3abc6c6d5 | ||
|
|
3e847bbd4a | ||
|
|
ba69b43688 |
484
.github/workflows/validate_esphome.yml
vendored
484
.github/workflows/validate_esphome.yml
vendored
@@ -1,12 +1,36 @@
|
|||||||
---
|
---
|
||||||
name: Validate ESPHome (Latest)
|
name: Validate ESPHome
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
pull-requests: read
|
pull-requests: read
|
||||||
|
|
||||||
on: # yamllint disable-line rule:truthy
|
on: # yamllint disable-line rule:truthy
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- "**/*.yml"
|
||||||
|
- "**/*.yaml"
|
||||||
|
- "**/*.h"
|
||||||
|
- "**/*.cpp"
|
||||||
|
- "**/*.c"
|
||||||
|
- "**/*.py"
|
||||||
|
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- "**/*.yml"
|
||||||
|
- "**/*.yaml"
|
||||||
|
- "**/*.h"
|
||||||
|
- "**/*.cpp"
|
||||||
|
- "**/*.c"
|
||||||
|
- "**/*.py"
|
||||||
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
skip_dev:
|
||||||
|
description: 'Skip dev testing (test only on latest)'
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
type: boolean
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||||
@@ -15,250 +39,416 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
code_scan:
|
code_scan:
|
||||||
name: Code scan (YAML)
|
name: Code scan (YAML)
|
||||||
runs-on: "ubuntu-latest"
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Code
|
- name: Checkout Code
|
||||||
uses: actions/checkout@main
|
uses: actions/checkout@main
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@main
|
uses: actions/setup-python@main
|
||||||
with:
|
with:
|
||||||
python-version: '3.8'
|
python-version: '3.11'
|
||||||
|
|
||||||
- name: Install Yamllint
|
- name: Install Yamllint
|
||||||
run: pip install yamllint
|
run: pip install yamllint
|
||||||
|
|
||||||
- name: Validate YAML files
|
- name: Validate YAML files
|
||||||
run: find . -name "*.yaml" -exec yamllint -c ./.rules/yamllint.yml {} +
|
run: find . -name "*.yaml" -exec yamllint -c ./.rules/yamllint.yml {} +
|
||||||
|
|
||||||
|
# Arduino Framework - Foundation (latest)
|
||||||
build_ard_core:
|
build_ard_core:
|
||||||
name: Core (Arduino)
|
name: "🏗️ Arduino Core (latest)"
|
||||||
needs: code_scan
|
needs: code_scan
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@main
|
- uses: actions/checkout@main
|
||||||
- name: Build Core (Arduino)
|
- name: Build Arduino Core - latest
|
||||||
uses: esphome/build-action@main
|
uses: esphome/build-action@main
|
||||||
with:
|
with:
|
||||||
yaml-file: ".test/esphome_ard_core.yaml"
|
yaml-file: ".test/esphome_ard_core.yaml"
|
||||||
version: latest
|
version: latest
|
||||||
|
|
||||||
build_idf_core:
|
build_ard_core_dev:
|
||||||
name: Core (IDF)
|
name: "🏗️ Arduino Core (dev)"
|
||||||
needs: code_scan
|
needs: code_scan
|
||||||
|
if: ${{ success() && (github.event_name != 'workflow_dispatch' || github.event.inputs.skip_dev != 'true') }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@main
|
- uses: actions/checkout@main
|
||||||
- name: Build Core (IDF)
|
- name: Build Arduino Core - dev
|
||||||
uses: esphome/build-action@main
|
uses: esphome/build-action@main
|
||||||
with:
|
with:
|
||||||
yaml-file: ".test/esphome_idf_core.yaml"
|
yaml-file: ".test/esphome_ard_core.yaml"
|
||||||
version: latest
|
version: dev
|
||||||
|
|
||||||
build_idf53_core:
|
|
||||||
name: Core (IDF v5.3)
|
|
||||||
needs: code_scan
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build Core (IDF v5.3)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_idf53_core.yaml"
|
|
||||||
version: latest
|
|
||||||
|
|
||||||
build_ard_basic:
|
build_ard_basic:
|
||||||
name: Basic (Arduino)
|
name: "📦 Arduino Basic (latest)"
|
||||||
needs: build_ard_core
|
needs: build_ard_core
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@main
|
- uses: actions/checkout@main
|
||||||
- name: Build Basic (Arduino)
|
- name: Build Arduino Basic - latest
|
||||||
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"
|
||||||
version: latest
|
version: latest
|
||||||
|
|
||||||
build_idf_basic:
|
build_ard_basic_dev:
|
||||||
name: Basic (IDF)
|
name: "📦 Arduino Basic (dev)"
|
||||||
needs: build_idf_core
|
needs: build_ard_core_dev
|
||||||
|
if: ${{ success() && (github.event_name != 'workflow_dispatch' || github.event.inputs.skip_dev != 'true') }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@main
|
- uses: actions/checkout@main
|
||||||
- name: Build Basic (IDF)
|
- name: Build Arduino Basic - dev
|
||||||
uses: esphome/build-action@main
|
uses: esphome/build-action@main
|
||||||
with:
|
with:
|
||||||
yaml-file: ".test/esphome_idf_basic.yaml"
|
yaml-file: ".test/esphome_ard_basic.yaml"
|
||||||
version: latest
|
version: dev
|
||||||
|
|
||||||
build_idf53_basic:
|
|
||||||
name: Basic (IDF v5.3)
|
|
||||||
needs: build_idf53_core
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build Basic (IDF v5.3)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_idf53_basic.yaml"
|
|
||||||
version: latest
|
|
||||||
|
|
||||||
build_ard_hw_relays:
|
build_ard_hw_relays:
|
||||||
name: HW Relays (Arduino)
|
name: "🔌 Arduino HW Relays (latest)"
|
||||||
needs: build_ard_core
|
needs: build_ard_basic
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@main
|
- uses: actions/checkout@main
|
||||||
- name: Build HW Relays (Arduino)
|
- name: Build Arduino HW Relays - latest
|
||||||
uses: esphome/build-action@main
|
uses: esphome/build-action@main
|
||||||
with:
|
with:
|
||||||
yaml-file: ".test/esphome_ard_hw_relays.yaml"
|
yaml-file: ".test/esphome_ard_hw_relays.yaml"
|
||||||
version: latest
|
version: latest
|
||||||
|
|
||||||
build_idf_hw_relays:
|
|
||||||
name: HW Relays (IDF)
|
|
||||||
needs: build_idf_core
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build HW Relays (IDF)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_idf_hw_relays.yaml"
|
|
||||||
version: latest
|
|
||||||
|
|
||||||
build_idf53_hw_relays:
|
|
||||||
name: HW Relays (IDF v5.3)
|
|
||||||
needs: build_idf53_core
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build HW Relays (IDF v5.3)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_idf53_hw_relays.yaml"
|
|
||||||
version: latest
|
|
||||||
|
|
||||||
build_ard_hw_speaker:
|
build_ard_hw_speaker:
|
||||||
name: HW Speaker (Arduino)
|
name: "🔌 Arduino HW Speaker (latest)"
|
||||||
needs: build_ard_core
|
needs: build_ard_basic
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@main
|
- uses: actions/checkout@main
|
||||||
- name: Build HW Speaker (Arduino)
|
- name: Build Arduino HW Speaker - latest
|
||||||
uses: esphome/build-action@main
|
uses: esphome/build-action@main
|
||||||
with:
|
with:
|
||||||
yaml-file: ".test/esphome_ard_hw_speaker.yaml"
|
yaml-file: ".test/esphome_ard_hw_speaker.yaml"
|
||||||
version: latest
|
version: latest
|
||||||
|
|
||||||
build_idf_hw_speaker:
|
|
||||||
name: HW Speaker (IDF)
|
|
||||||
needs: build_idf_core
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build HW Speaker (IDF)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_idf_hw_speaker.yaml"
|
|
||||||
version: latest
|
|
||||||
|
|
||||||
build_idf53_hw_speaker:
|
|
||||||
name: HW Speaker (IDF v5.3)
|
|
||||||
needs: build_idf53_core
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build HW Speaker (IDF v5.3)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_idf53_hw_speaker.yaml"
|
|
||||||
version: latest
|
|
||||||
|
|
||||||
build_ard_hw_vibration:
|
build_ard_hw_vibration:
|
||||||
name: HW Vibration (Arduino)
|
name: "🔌 Arduino HW Vibration (latest)"
|
||||||
needs: build_ard_core
|
needs: build_ard_basic
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@main
|
- uses: actions/checkout@main
|
||||||
- name: Build HW Vibration (Arduino)
|
- name: Build Arduino HW Vibration - latest
|
||||||
uses: esphome/build-action@main
|
uses: esphome/build-action@main
|
||||||
with:
|
with:
|
||||||
yaml-file: ".test/esphome_ard_hw_vibration.yaml"
|
yaml-file: ".test/esphome_ard_hw_vibration.yaml"
|
||||||
version: latest
|
version: latest
|
||||||
|
|
||||||
build_idf_hw_vibration:
|
build_ard_ble_proxy_latest:
|
||||||
name: HW Vibration (IDF)
|
name: "⚡ Arduino BLE Proxy (latest)"
|
||||||
needs: build_idf_core
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build HW Vibration (IDF)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_idf_hw_vibration.yaml"
|
|
||||||
version: latest
|
|
||||||
|
|
||||||
build_idf53_hw_vibration:
|
|
||||||
name: HW Vibration (IDF v5.3)
|
|
||||||
needs: build_idf53_core
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build HW Vibration (IDF v5.3)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_idf53_hw_vibration.yaml"
|
|
||||||
version: latest
|
|
||||||
|
|
||||||
build_ard_ble_proxy:
|
|
||||||
name: Bluetooth Proxy (Ard)
|
|
||||||
needs: build_ard_basic
|
needs: build_ard_basic
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@main
|
- uses: actions/checkout@main
|
||||||
- name: Build BLE Proxy (Ard)
|
- name: Build Arduino BLE Proxy - latest
|
||||||
uses: esphome/build-action@main
|
uses: esphome/build-action@main
|
||||||
with:
|
with:
|
||||||
yaml-file: ".test/esphome_ard_ble_proxy.yaml"
|
yaml-file: ".test/esphome_ard_ble_proxy.yaml"
|
||||||
version: latest
|
version: latest
|
||||||
|
|
||||||
build_idf_ble_proxy:
|
build_ard_ble_proxy_dev:
|
||||||
name: Bluetooth Proxy (IDF)
|
name: "⚡ Arduino BLE Proxy (dev)"
|
||||||
|
needs: build_ard_basic_dev
|
||||||
|
if: ${{ success() && (github.event_name != 'workflow_dispatch' || github.event.inputs.skip_dev != 'true') }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@main
|
||||||
|
- name: Build Arduino BLE Proxy - dev
|
||||||
|
uses: esphome/build-action@main
|
||||||
|
with:
|
||||||
|
yaml-file: ".test/esphome_ard_ble_proxy.yaml"
|
||||||
|
version: dev
|
||||||
|
|
||||||
|
# IDF Framework - Foundation (latest)
|
||||||
|
build_idf_core:
|
||||||
|
name: "🏗️ IDF Core (latest)"
|
||||||
|
needs: code_scan
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@main
|
||||||
|
- name: Build IDF Core - latest
|
||||||
|
uses: esphome/build-action@main
|
||||||
|
with:
|
||||||
|
yaml-file: ".test/esphome_idf_core.yaml"
|
||||||
|
version: latest
|
||||||
|
|
||||||
|
build_idf_core_dev:
|
||||||
|
name: "🏗️ IDF Core (dev)"
|
||||||
|
needs: code_scan
|
||||||
|
if: ${{ success() && (github.event_name != 'workflow_dispatch' || github.event.inputs.skip_dev != 'true') }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@main
|
||||||
|
- name: Build IDF Core - dev
|
||||||
|
uses: esphome/build-action@main
|
||||||
|
with:
|
||||||
|
yaml-file: ".test/esphome_idf_core.yaml"
|
||||||
|
version: dev
|
||||||
|
|
||||||
|
build_idf_basic:
|
||||||
|
name: "📦 IDF Basic (latest)"
|
||||||
|
needs: build_idf_core
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@main
|
||||||
|
- name: Build IDF Basic - latest
|
||||||
|
uses: esphome/build-action@main
|
||||||
|
with:
|
||||||
|
yaml-file: ".test/esphome_idf_basic.yaml"
|
||||||
|
version: latest
|
||||||
|
|
||||||
|
build_idf_basic_dev:
|
||||||
|
name: "📦 IDF Basic (dev)"
|
||||||
|
needs: build_idf_core_dev
|
||||||
|
if: ${{ success() && (github.event_name != 'workflow_dispatch' || github.event.inputs.skip_dev != 'true') }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@main
|
||||||
|
- name: Build IDF Basic - dev
|
||||||
|
uses: esphome/build-action@main
|
||||||
|
with:
|
||||||
|
yaml-file: ".test/esphome_idf_basic.yaml"
|
||||||
|
version: dev
|
||||||
|
|
||||||
|
build_idf_hw_relays:
|
||||||
|
name: "🔌 IDF HW Relays (latest)"
|
||||||
needs: build_idf_basic
|
needs: build_idf_basic
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@main
|
- uses: actions/checkout@main
|
||||||
- name: Build BLE Proxy (IDF)
|
- name: Build IDF HW Relays - latest
|
||||||
|
uses: esphome/build-action@main
|
||||||
|
with:
|
||||||
|
yaml-file: ".test/esphome_idf_hw_relays.yaml"
|
||||||
|
version: latest
|
||||||
|
|
||||||
|
build_idf_hw_speaker:
|
||||||
|
name: "🔌 IDF HW Speaker (latest)"
|
||||||
|
needs: build_idf_basic
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@main
|
||||||
|
- name: Build IDF HW Speaker - latest
|
||||||
|
uses: esphome/build-action@main
|
||||||
|
with:
|
||||||
|
yaml-file: ".test/esphome_idf_hw_speaker.yaml"
|
||||||
|
version: latest
|
||||||
|
|
||||||
|
build_idf_hw_vibration:
|
||||||
|
name: "🔌 IDF HW Vibration (latest)"
|
||||||
|
needs: build_idf_basic
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@main
|
||||||
|
- name: Build IDF HW Vibration - latest
|
||||||
|
uses: esphome/build-action@main
|
||||||
|
with:
|
||||||
|
yaml-file: ".test/esphome_idf_hw_vibration.yaml"
|
||||||
|
version: latest
|
||||||
|
|
||||||
|
build_idf_ble_proxy_latest:
|
||||||
|
name: "⚡ IDF BLE Proxy (latest)"
|
||||||
|
needs: build_idf_basic
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@main
|
||||||
|
- name: Build IDF BLE Proxy - latest
|
||||||
uses: esphome/build-action@main
|
uses: esphome/build-action@main
|
||||||
with:
|
with:
|
||||||
yaml-file: ".test/esphome_idf_ble_proxy.yaml"
|
yaml-file: ".test/esphome_idf_ble_proxy.yaml"
|
||||||
version: latest
|
version: latest
|
||||||
|
|
||||||
build_idf53_ble_proxy:
|
build_idf_ble_proxy_dev:
|
||||||
name: Bluetooth Proxy (IDF v5.3)
|
name: "⚡ IDF BLE Proxy (dev)"
|
||||||
needs: build_idf53_basic
|
needs: build_idf_basic_dev
|
||||||
|
if: ${{ success() && (github.event_name != 'workflow_dispatch' || github.event.inputs.skip_dev != 'true') }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@main
|
- uses: actions/checkout@main
|
||||||
- name: Build BLE Proxy (IDF v5.3)
|
- name: Build IDF BLE Proxy - dev
|
||||||
uses: esphome/build-action@main
|
uses: esphome/build-action@main
|
||||||
with:
|
with:
|
||||||
yaml-file: ".test/esphome_idf53_ble_proxy.yaml"
|
yaml-file: ".test/esphome_idf_ble_proxy.yaml"
|
||||||
version: latest
|
version: dev
|
||||||
|
|
||||||
build_ard_media_player:
|
# Summary Jobs - Grouped by framework and environment
|
||||||
name: Media Player (Ard)
|
summary_arduino:
|
||||||
|
name: "📊 Arduino Framework"
|
||||||
needs:
|
needs:
|
||||||
|
- build_ard_core
|
||||||
|
- build_ard_core_dev
|
||||||
|
- build_ard_basic
|
||||||
|
- build_ard_basic_dev
|
||||||
|
- build_ard_hw_relays
|
||||||
|
- build_ard_hw_speaker
|
||||||
|
- build_ard_hw_vibration
|
||||||
|
- build_ard_ble_proxy_latest
|
||||||
|
- build_ard_ble_proxy_dev
|
||||||
|
if: always()
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Arduino Framework Results
|
||||||
|
run: |
|
||||||
|
SUCCESS=0
|
||||||
|
TOTAL=0
|
||||||
|
|
||||||
|
# Count latest builds (always run)
|
||||||
|
[ "${{ needs.build_ard_core.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_ard_basic.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_ard_hw_relays.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_ard_hw_speaker.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_ard_hw_vibration.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_ard_ble_proxy_latest.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
TOTAL=$((TOTAL + 6))
|
||||||
|
|
||||||
|
# Count dev builds (if not skipped)
|
||||||
|
if [ "${{ github.event.inputs.skip_dev }}" != "true" ]; then
|
||||||
|
[ "${{ needs.build_ard_core_dev.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_ard_basic_dev.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_ard_ble_proxy_dev.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
TOTAL=$((TOTAL + 3))
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "🤖 Arduino Framework: $SUCCESS/$TOTAL builds passed"
|
||||||
|
|
||||||
|
if [ "$SUCCESS" -eq "$TOTAL" ]; then
|
||||||
|
echo "✅ All Arduino builds successful!"
|
||||||
|
else
|
||||||
|
echo "❌ Some Arduino builds failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
summary_idf:
|
||||||
|
name: "📊 ESP-IDF Framework"
|
||||||
|
needs:
|
||||||
|
- build_idf_core
|
||||||
|
- build_idf_core_dev
|
||||||
|
- build_idf_basic
|
||||||
|
- build_idf_basic_dev
|
||||||
|
- build_idf_hw_relays
|
||||||
|
- build_idf_hw_speaker
|
||||||
|
- build_idf_hw_vibration
|
||||||
|
- build_idf_ble_proxy_latest
|
||||||
|
- build_idf_ble_proxy_dev
|
||||||
|
if: always()
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: ESP-IDF Framework Results
|
||||||
|
run: |
|
||||||
|
SUCCESS=0
|
||||||
|
TOTAL=0
|
||||||
|
|
||||||
|
# Count latest builds (always run)
|
||||||
|
[ "${{ needs.build_idf_core.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_idf_basic.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_idf_hw_relays.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_idf_hw_speaker.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_idf_hw_vibration.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_idf_ble_proxy_latest.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
TOTAL=$((TOTAL + 6))
|
||||||
|
|
||||||
|
# Count dev builds (if not skipped)
|
||||||
|
if [ "${{ github.event.inputs.skip_dev }}" != "true" ]; then
|
||||||
|
[ "${{ needs.build_idf_core_dev.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_idf_basic_dev.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_idf_ble_proxy_dev.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
TOTAL=$((TOTAL + 3))
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "🔧 ESP-IDF Framework: $SUCCESS/$TOTAL builds passed"
|
||||||
|
|
||||||
|
if [ "$SUCCESS" -eq "$TOTAL" ]; then
|
||||||
|
echo "✅ All ESP-IDF builds successful!"
|
||||||
|
else
|
||||||
|
echo "❌ Some ESP-IDF builds failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
summary_latest:
|
||||||
|
name: "📊 ESPHome (Latest)"
|
||||||
|
needs:
|
||||||
|
- build_ard_core
|
||||||
- build_ard_basic
|
- build_ard_basic
|
||||||
- build_ard_hw_relays
|
- build_ard_hw_relays
|
||||||
|
- build_ard_hw_speaker
|
||||||
- build_ard_hw_vibration
|
- build_ard_hw_vibration
|
||||||
|
- build_ard_ble_proxy_latest
|
||||||
|
- build_idf_core
|
||||||
|
- build_idf_basic
|
||||||
|
- build_idf_hw_relays
|
||||||
|
- build_idf_hw_speaker
|
||||||
|
- build_idf_hw_vibration
|
||||||
|
- build_idf_ble_proxy_latest
|
||||||
|
if: always()
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@main
|
- name: Latest ESPHome Results
|
||||||
- name: Build Media Player (Ard)
|
run: |
|
||||||
uses: esphome/build-action@main
|
SUCCESS=0
|
||||||
with:
|
TOTAL=12
|
||||||
yaml-file: ".test/esphome_ard_media_player.yaml"
|
|
||||||
version: latest
|
# Arduino Latest builds
|
||||||
|
[ "${{ needs.build_ard_core.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_ard_basic.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_ard_hw_relays.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_ard_hw_speaker.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_ard_hw_vibration.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_ard_ble_proxy_latest.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
|
||||||
|
# ESP-IDF Latest builds
|
||||||
|
[ "${{ needs.build_idf_core.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_idf_basic.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_idf_hw_relays.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_idf_hw_speaker.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_idf_hw_vibration.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_idf_ble_proxy_latest.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
|
||||||
|
echo "📋 ESPHome (Latest): $SUCCESS/$TOTAL builds passed"
|
||||||
|
|
||||||
|
if [ "$SUCCESS" -eq "$TOTAL" ]; then
|
||||||
|
echo "✅ All builds on latest ESPHome successful!"
|
||||||
|
else
|
||||||
|
echo "❌ Some builds on latest ESPHome failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
summary_dev:
|
||||||
|
name: "📊 ESPHome (Dev)"
|
||||||
|
needs:
|
||||||
|
- build_ard_core_dev
|
||||||
|
- build_ard_basic_dev
|
||||||
|
- build_ard_ble_proxy_dev
|
||||||
|
- build_idf_core_dev
|
||||||
|
- build_idf_basic_dev
|
||||||
|
- build_idf_ble_proxy_dev
|
||||||
|
if: ${{ always() && (github.event_name != 'workflow_dispatch' || github.event.inputs.skip_dev != 'true') }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Dev ESPHome Results
|
||||||
|
run: |
|
||||||
|
SUCCESS=0
|
||||||
|
TOTAL=6
|
||||||
|
|
||||||
|
# Arduino Dev builds
|
||||||
|
[ "${{ needs.build_ard_core_dev.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_ard_basic_dev.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_ard_ble_proxy_dev.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
|
||||||
|
# ESP-IDF Dev builds
|
||||||
|
[ "${{ needs.build_idf_core_dev.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_idf_basic_dev.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
[ "${{ needs.build_idf_ble_proxy_dev.result }}" == "success" ] && SUCCESS=$((SUCCESS + 1))
|
||||||
|
|
||||||
|
echo "🚀 ESPHome (Dev): $SUCCESS/$TOTAL builds passed"
|
||||||
|
|
||||||
|
if [ "$SUCCESS" -eq "$TOTAL" ]; then
|
||||||
|
echo "✅ All builds on dev ESPHome successful!"
|
||||||
|
else
|
||||||
|
echo "❌ Some builds on dev ESPHome failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
...
|
...
|
||||||
|
|||||||
270
.github/workflows/validate_esphome_beta.yml
vendored
270
.github/workflows/validate_esphome_beta.yml
vendored
@@ -1,270 +0,0 @@
|
|||||||
---
|
|
||||||
name: Validate ESPHome (Beta)
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: read
|
|
||||||
|
|
||||||
on: # yamllint disable-line rule:truthy
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- "**/*.{yml,yaml,h,cpp,c,py}" # Match any file with the extensions in any directory
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- "**/*.{yml,yaml,h,cpp,c,py}" # Match any file with the extensions in any directory
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
code_scan:
|
|
||||||
name: Code scan (YAML)
|
|
||||||
runs-on: "ubuntu-latest"
|
|
||||||
steps:
|
|
||||||
- name: Checkout Code
|
|
||||||
uses: actions/checkout@main
|
|
||||||
|
|
||||||
- name: Setup Python
|
|
||||||
uses: actions/setup-python@main
|
|
||||||
with:
|
|
||||||
python-version: '3.8'
|
|
||||||
|
|
||||||
- name: Install Yamllint
|
|
||||||
run: pip install yamllint
|
|
||||||
|
|
||||||
- name: Validate YAML files
|
|
||||||
run: find . -name "*.yaml" -exec yamllint -c ./.rules/yamllint.yml {} +
|
|
||||||
|
|
||||||
build_ard_core:
|
|
||||||
name: Core (Arduino)
|
|
||||||
needs: code_scan
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build Core (Arduino)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_ard_core.yaml"
|
|
||||||
version: beta
|
|
||||||
|
|
||||||
build_idf_core:
|
|
||||||
name: Core (IDF)
|
|
||||||
needs: code_scan
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build Core (IDF)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_idf_core.yaml"
|
|
||||||
version: beta
|
|
||||||
|
|
||||||
build_idf53_core:
|
|
||||||
name: Core (IDF v5.3)
|
|
||||||
needs: code_scan
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build Core (IDF v5.3)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_idf53_core.yaml"
|
|
||||||
version: beta
|
|
||||||
|
|
||||||
build_ard_basic:
|
|
||||||
name: Basic (Arduino)
|
|
||||||
needs: build_ard_core
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build Basic (Arduino)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_ard_basic.yaml"
|
|
||||||
version: beta
|
|
||||||
|
|
||||||
build_idf_basic:
|
|
||||||
name: Basic (IDF)
|
|
||||||
needs: build_idf_core
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build Basic (IDF)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_idf_basic.yaml"
|
|
||||||
version: beta
|
|
||||||
|
|
||||||
build_idf53_basic:
|
|
||||||
name: Basic (IDF v5.3)
|
|
||||||
needs: build_idf53_core
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build Basic (IDF v5.3)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_idf53_basic.yaml"
|
|
||||||
version: beta
|
|
||||||
|
|
||||||
build_ard_hw_relays:
|
|
||||||
name: HW Relays (Arduino)
|
|
||||||
needs: build_ard_core
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build HW Relays (Arduino)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_ard_hw_relays.yaml"
|
|
||||||
version: beta
|
|
||||||
|
|
||||||
build_idf_hw_relays:
|
|
||||||
name: HW Relays (IDF)
|
|
||||||
needs: build_idf_core
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build HW Relays (IDF)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_idf_hw_relays.yaml"
|
|
||||||
version: beta
|
|
||||||
|
|
||||||
build_idf53_hw_relays:
|
|
||||||
name: HW Relays (IDF v5.3)
|
|
||||||
needs: build_idf53_core
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build HW Relays (IDF v5.3)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_idf53_hw_relays.yaml"
|
|
||||||
version: beta
|
|
||||||
|
|
||||||
build_ard_hw_speaker:
|
|
||||||
name: HW Speaker (Arduino)
|
|
||||||
needs: build_ard_core
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build HW Speaker (Arduino)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_ard_hw_speaker.yaml"
|
|
||||||
version: beta
|
|
||||||
|
|
||||||
build_idf_hw_speaker:
|
|
||||||
name: HW Speaker (IDF)
|
|
||||||
needs: build_idf_core
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build HW Speaker (IDF)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_idf_hw_speaker.yaml"
|
|
||||||
version: beta
|
|
||||||
|
|
||||||
build_idf53_hw_speaker:
|
|
||||||
name: HW Speaker (IDF v5.3)
|
|
||||||
needs: build_idf53_core
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build HW Speaker (IDF v5.3)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_idf53_hw_speaker.yaml"
|
|
||||||
version: beta
|
|
||||||
|
|
||||||
build_ard_hw_vibration:
|
|
||||||
name: HW Vibration (Arduino)
|
|
||||||
needs: build_ard_core
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build HW Vibration (Arduino)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_ard_hw_vibration.yaml"
|
|
||||||
version: beta
|
|
||||||
|
|
||||||
build_idf_hw_vibration:
|
|
||||||
name: HW Vibration (IDF)
|
|
||||||
needs: build_idf_core
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build HW Vibration (IDF)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_idf_hw_vibration.yaml"
|
|
||||||
version: beta
|
|
||||||
|
|
||||||
build_idf53_hw_vibration:
|
|
||||||
name: HW Vibration (IDF v5.3)
|
|
||||||
needs: build_idf53_core
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build HW Vibration (IDF v5.3)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_idf53_hw_vibration.yaml"
|
|
||||||
version: beta
|
|
||||||
|
|
||||||
build_ard_ble_proxy:
|
|
||||||
name: Bluetooth Proxy (Ard)
|
|
||||||
needs: build_ard_basic
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build BLE Proxy (Ard)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_ard_ble_proxy.yaml"
|
|
||||||
version: beta
|
|
||||||
|
|
||||||
build_idf_ble_proxy:
|
|
||||||
name: Bluetooth Proxy (IDF)
|
|
||||||
needs: build_idf_basic
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build BLE Proxy (IDF)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_idf_ble_proxy.yaml"
|
|
||||||
version: beta
|
|
||||||
|
|
||||||
build_idf53_ble_proxy:
|
|
||||||
name: Bluetooth Proxy (IDF v5.3)
|
|
||||||
needs: build_idf53_basic
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build BLE Proxy (IDF v5.3)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_idf53_ble_proxy.yaml"
|
|
||||||
version: beta
|
|
||||||
|
|
||||||
build_ard_media_player:
|
|
||||||
name: Media Player (Ard)
|
|
||||||
needs:
|
|
||||||
- build_ard_basic
|
|
||||||
- build_ard_hw_relays
|
|
||||||
- build_ard_hw_vibration
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@main
|
|
||||||
- name: Build Media Player (Ard)
|
|
||||||
uses: esphome/build-action@main
|
|
||||||
with:
|
|
||||||
yaml-file: ".test/esphome_ard_media_player.yaml"
|
|
||||||
version: beta
|
|
||||||
...
|
|
||||||
45
.github/workflows/validate_markdown.yml
vendored
45
.github/workflows/validate_markdown.yml
vendored
@@ -17,23 +17,28 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@main
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: '0'
|
fetch-depth: 0 # Ensures full commit history for diff
|
||||||
|
|
||||||
# https://github.com/marketplace/actions/markdownlint-cli2-action
|
|
||||||
- name: Identify changed files
|
- name: Identify changed files
|
||||||
uses: tj-actions/changed-files@v41
|
|
||||||
id: changed-files
|
id: changed-files
|
||||||
with:
|
run: |
|
||||||
files: '**/*.md'
|
BASE=${{ github.event.before }}
|
||||||
separator: ","
|
HEAD=${{ github.sha }}
|
||||||
# https://github.com/marketplace/actions/markdownlint-cli2-action
|
FILES=$(git diff --name-only $BASE $HEAD -- '**/*.md' | tr '\n' ',')
|
||||||
|
echo "changed_files=$FILES" >> $GITHUB_ENV
|
||||||
|
if [[ -n "$FILES" ]]; then
|
||||||
|
echo "any_changed=true" >> $GITHUB_ENV
|
||||||
|
else
|
||||||
|
echo "any_changed=false" >> $GITHUB_ENV
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Markdown Lint
|
- name: Markdown Lint
|
||||||
uses: DavidAnson/markdownlint-cli2-action@v14
|
uses: DavidAnson/markdownlint-cli2-action@v14
|
||||||
if: steps.changed-files.outputs.any_changed == 'true'
|
if: env.any_changed == 'true'
|
||||||
with:
|
with:
|
||||||
globs: ${{ steps.changed-files.outputs.all_changed_files }}
|
globs: ${{ env.changed_files }}
|
||||||
separator: ","
|
separator: ","
|
||||||
config: '.rules/.markdownlint.jsonc'
|
config: '.rules/.markdownlint.jsonc'
|
||||||
fix: true
|
fix: true
|
||||||
@@ -43,15 +48,27 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@main
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: '0'
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Identify changed files
|
||||||
|
id: changed-files
|
||||||
|
run: |
|
||||||
|
BASE=${{ github.event.before }}
|
||||||
|
HEAD=${{ github.sha }}
|
||||||
|
FILES=$(git diff --name-only $BASE $HEAD -- '**/*.md' | tr '\n' ',')
|
||||||
|
echo "changed_files=$FILES" >> $GITHUB_ENV
|
||||||
|
if [[ -n "$FILES" ]]; then
|
||||||
|
echo "any_changed=true" >> $GITHUB_ENV
|
||||||
|
else
|
||||||
|
echo "any_changed=false" >> $GITHUB_ENV
|
||||||
|
fi
|
||||||
|
|
||||||
# https://github.com/gaurav-nelson/github-action-markdown-link-check
|
|
||||||
- name: Markdown links
|
- name: Markdown links
|
||||||
uses: gaurav-nelson/github-action-markdown-link-check@v1
|
uses: gaurav-nelson/github-action-markdown-link-check@v1
|
||||||
|
if: env.any_changed == 'true'
|
||||||
with:
|
with:
|
||||||
# yamllint disable-line rule:truthy
|
|
||||||
check-modified-files-only: yes
|
check-modified-files-only: yes
|
||||||
config-file: '.rules/mlc_config.json'
|
config-file: '.rules/mlc_config.json'
|
||||||
base-branch: 'main'
|
base-branch: 'main'
|
||||||
|
|||||||
25
.github/workflows/validate_yamllint.yml
vendored
25
.github/workflows/validate_yamllint.yml
vendored
@@ -19,24 +19,29 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@main
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: '0'
|
fetch-depth: 0 # Ensures full commit history for diff
|
||||||
|
|
||||||
- name: Identify changed files
|
- name: Identify changed files
|
||||||
uses: tj-actions/changed-files@v41
|
|
||||||
id: changed-files
|
id: changed-files
|
||||||
with:
|
run: |
|
||||||
files: '**/*.y*ml'
|
BASE=${{ github.event.before }}
|
||||||
separator: ","
|
HEAD=${{ github.sha }}
|
||||||
|
FILES=$(git diff --name-only $BASE $HEAD -- '**/*.yml' '**/*.yaml' | tr '\n' ',')
|
||||||
|
echo "changed_files=$FILES" >> $GITHUB_ENV
|
||||||
|
if [[ -n "$FILES" ]]; then
|
||||||
|
echo "any_changed=true" >> $GITHUB_ENV
|
||||||
|
else
|
||||||
|
echo "any_changed=false" >> $GITHUB_ENV
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Validate YAML
|
- name: Validate YAML
|
||||||
if: steps.changed-files.outputs.any_changed == 'true'
|
if: env.any_changed == 'true'
|
||||||
run: |
|
run: |
|
||||||
IFS=',' read -ra FILES <<< "${{ steps.changed-files.outputs.all_changed_files }}"
|
IFS=',' read -ra FILES <<< "${{ env.changed_files }}"
|
||||||
for file in "${FILES[@]}"; do
|
for file in "${FILES[@]}"; do
|
||||||
if [[ "$file" =~ ^*\.yaml$ ]] || \
|
if [[ "$file" =~ ^.*\.yaml$ ]] || [[ "$file" =~ ^ESPHome/.*\.yaml$ ]]; then
|
||||||
[[ "$file" =~ ^ESPHome/*\.yaml$ ]]; then
|
|
||||||
echo "Skipping $file"
|
echo "Skipping $file"
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|||||||
88
.github/workflows/versioning.yml
vendored
88
.github/workflows/versioning.yml
vendored
@@ -4,7 +4,6 @@
|
|||||||
# 2. Manual dispatch - allows independent control over stable and latest tags
|
# 2. Manual dispatch - allows independent control over stable and latest tags
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
name: Version and Tags
|
name: Version and Tags
|
||||||
|
|
||||||
on: # yamllint disable-line rule:truthy
|
on: # yamllint disable-line rule:truthy
|
||||||
@@ -42,11 +41,84 @@ jobs:
|
|||||||
git config user.name "GitHub Actions"
|
git config user.name "GitHub Actions"
|
||||||
git config user.email "actions@github.com"
|
git config user.email "actions@github.com"
|
||||||
|
|
||||||
|
- name: Get PR information
|
||||||
|
id: pr_info
|
||||||
|
if: github.event_name == 'push'
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
try {
|
||||||
|
// Use GitHub's reliable API to find PRs associated with this commit
|
||||||
|
const { data: associatedPRs } = await github.rest.repos.listPullRequestsAssociatedWithCommit({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
commit_sha: context.sha
|
||||||
|
});
|
||||||
|
|
||||||
|
if (associatedPRs.length > 0) {
|
||||||
|
// Get the most recent merged PR
|
||||||
|
const pr = associatedPRs.find(pr => pr.state === 'closed' && pr.merged_at) || associatedPRs[0];
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: pr.title,
|
||||||
|
body: pr.body || 'No description provided',
|
||||||
|
number: pr.number,
|
||||||
|
found: true
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// Fallback for direct pushes or when no PR is found
|
||||||
|
const commit = await github.rest.repos.getCommit({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
ref: context.sha
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: 'Direct push to main',
|
||||||
|
body: commit.data.commit.message,
|
||||||
|
number: null,
|
||||||
|
found: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Could not get PR info:', error.message);
|
||||||
|
return {
|
||||||
|
title: 'Version update',
|
||||||
|
body: 'Automated version bump',
|
||||||
|
number: null,
|
||||||
|
found: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
- name: Bump version
|
- name: Bump version
|
||||||
run: |
|
run: |
|
||||||
chmod +x ./versioning/bump_version.sh
|
chmod +x ./versioning/bump_version.sh
|
||||||
./versioning/bump_version.sh
|
./versioning/bump_version.sh
|
||||||
|
|
||||||
|
- name: Create tag message
|
||||||
|
id: tag_message
|
||||||
|
run: |
|
||||||
|
NEW_VERSION=$(cat ./versioning/VERSION)
|
||||||
|
|
||||||
|
if [ "${{ github.event_name }}" == "push" ] && [ "${{ steps.pr_info.outcome }}" == "success" ]; then
|
||||||
|
# Use PR information directly in heredoc to avoid quoting issues
|
||||||
|
cat > tag_message.txt << EOF
|
||||||
|
# v${NEW_VERSION} - ${{ fromJson(steps.pr_info.outputs.result).title }}
|
||||||
|
|
||||||
|
${{ fromJson(steps.pr_info.outputs.result).body }}
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
# Manual dispatch or PR info unavailable - simpler message
|
||||||
|
cat > tag_message.txt << EOF
|
||||||
|
# v${NEW_VERSION} - Manual tag update
|
||||||
|
|
||||||
|
Tag updated via manual workflow dispatch.
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Store the message for use in subsequent steps
|
||||||
|
echo "TAG_MESSAGE_FILE=tag_message.txt" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Push Changes and Tags
|
- name: Push Changes and Tags
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -73,10 +145,10 @@ jobs:
|
|||||||
echo "Backing up current stable tag ($OLD_STABLE)"
|
echo "Backing up current stable tag ($OLD_STABLE)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Update tag
|
# Update tag with detailed message
|
||||||
NEW_VERSION=$(cat ./versioning/VERSION)
|
NEW_VERSION=$(cat ./versioning/VERSION)
|
||||||
echo "Updating stable tag to $NEW_VERSION"
|
echo "Updating stable tag to $NEW_VERSION"
|
||||||
git tag -fa stable -m "Update stable tag"
|
git tag -fa stable -F "$TAG_MESSAGE_FILE"
|
||||||
git push origin stable --force
|
git push origin stable --force
|
||||||
|
|
||||||
- name: Update latest tag
|
- name: Update latest tag
|
||||||
@@ -98,9 +170,15 @@ jobs:
|
|||||||
echo "Backing up current latest tag ($OLD_LATEST)"
|
echo "Backing up current latest tag ($OLD_LATEST)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Update tag
|
# Update tag with detailed message
|
||||||
NEW_VERSION=$(cat ./versioning/VERSION)
|
NEW_VERSION=$(cat ./versioning/VERSION)
|
||||||
echo "Updating latest tag to $NEW_VERSION"
|
echo "Updating latest tag to $NEW_VERSION"
|
||||||
git tag -fa latest -m "Update latest tag"
|
git tag -fa latest -F "$TAG_MESSAGE_FILE"
|
||||||
git push origin latest --force
|
git push origin latest --force
|
||||||
|
|
||||||
|
- name: Cleanup
|
||||||
|
if: always()
|
||||||
|
run: |
|
||||||
|
# Clean up temporary files
|
||||||
|
[ -f tag_message.txt ] && rm tag_message.txt || true
|
||||||
...
|
...
|
||||||
|
|||||||
5
.test/common.yaml
Normal file
5
.test/common.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
...
|
||||||
8
.test/common_ard.yaml
Normal file
8
.test/common_ard.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
packages:
|
||||||
|
common: !include common.yaml
|
||||||
|
|
||||||
|
esp32:
|
||||||
|
framework:
|
||||||
|
type: arduino
|
||||||
|
...
|
||||||
8
.test/common_idf.yaml
Normal file
8
.test/common_idf.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
packages:
|
||||||
|
common: !include common.yaml
|
||||||
|
|
||||||
|
esp32:
|
||||||
|
framework:
|
||||||
|
type: esp-idf
|
||||||
|
...
|
||||||
@@ -1,13 +1,6 @@
|
|||||||
---
|
---
|
||||||
packages:
|
packages:
|
||||||
|
common_arduino: !include common_ard.yaml
|
||||||
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
||||||
standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml
|
standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml
|
||||||
|
|
||||||
esp32:
|
|
||||||
framework:
|
|
||||||
type: arduino
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -1,14 +1,8 @@
|
|||||||
---
|
---
|
||||||
packages:
|
packages:
|
||||||
|
common_arduino: !include common_ard.yaml
|
||||||
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
||||||
standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml
|
standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml
|
||||||
addon_bluetooth_proxy: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml
|
|
||||||
|
|
||||||
esp32:
|
bluetooth_proxy:
|
||||||
framework:
|
|
||||||
type: arduino
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -1,12 +1,5 @@
|
|||||||
---
|
---
|
||||||
packages:
|
packages:
|
||||||
|
common_arduino: !include common_ard.yaml
|
||||||
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
||||||
|
|
||||||
esp32:
|
|
||||||
framework:
|
|
||||||
type: arduino
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -1,13 +1,6 @@
|
|||||||
---
|
---
|
||||||
packages:
|
packages:
|
||||||
|
common_arduino: !include common_ard.yaml
|
||||||
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
||||||
standard_hw_relays_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml
|
standard_hw_relays_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml
|
||||||
|
|
||||||
esp32:
|
|
||||||
framework:
|
|
||||||
type: arduino
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -1,13 +1,6 @@
|
|||||||
---
|
---
|
||||||
packages:
|
packages:
|
||||||
|
common_arduino: !include common_ard.yaml
|
||||||
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
||||||
standard_hw_speaker_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml
|
standard_hw_speaker_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml
|
||||||
|
|
||||||
esp32:
|
|
||||||
framework:
|
|
||||||
type: arduino
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -1,13 +1,6 @@
|
|||||||
---
|
---
|
||||||
packages:
|
packages:
|
||||||
|
common_arduino: !include common_ard.yaml
|
||||||
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
||||||
standard_hw_vibration_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml
|
standard_hw_vibration_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml
|
||||||
|
|
||||||
esp32:
|
|
||||||
framework:
|
|
||||||
type: arduino
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
packages:
|
|
||||||
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
|
||||||
standard_hw_relays_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml
|
|
||||||
standard_hw_vibration_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml
|
|
||||||
addon_media_player: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml
|
|
||||||
|
|
||||||
esp32:
|
|
||||||
framework:
|
|
||||||
type: arduino
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
...
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
packages:
|
|
||||||
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
|
||||||
standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml
|
|
||||||
|
|
||||||
esp32:
|
|
||||||
framework:
|
|
||||||
type: esp-idf
|
|
||||||
version: 5.3.1
|
|
||||||
platform_version: 6.9.0
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
...
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
---
|
|
||||||
packages:
|
|
||||||
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
|
||||||
standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml
|
|
||||||
addon_bluetooth_proxy: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml
|
|
||||||
|
|
||||||
esp32:
|
|
||||||
framework:
|
|
||||||
type: esp-idf
|
|
||||||
version: 5.3.1
|
|
||||||
platform_version: 6.9.0
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
...
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
---
|
|
||||||
packages:
|
|
||||||
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
|
||||||
|
|
||||||
esp32:
|
|
||||||
framework:
|
|
||||||
type: esp-idf
|
|
||||||
version: 5.3.1
|
|
||||||
platform_version: 6.9.0
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
...
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
packages:
|
|
||||||
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
|
||||||
standard_hw_relays_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml
|
|
||||||
|
|
||||||
esp32:
|
|
||||||
framework:
|
|
||||||
type: esp-idf
|
|
||||||
version: 5.3.1
|
|
||||||
platform_version: 6.9.0
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
...
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
packages:
|
|
||||||
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
|
||||||
standard_hw_speaker_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml
|
|
||||||
|
|
||||||
esp32:
|
|
||||||
framework:
|
|
||||||
type: esp-idf
|
|
||||||
version: 5.3.1
|
|
||||||
platform_version: 6.9.0
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
...
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
packages:
|
|
||||||
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
|
||||||
standard_hw_vibration_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml
|
|
||||||
|
|
||||||
esp32:
|
|
||||||
framework:
|
|
||||||
type: esp-idf
|
|
||||||
version: 5.3.1
|
|
||||||
platform_version: 6.9.0
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
...
|
|
||||||
@@ -1,13 +1,6 @@
|
|||||||
---
|
---
|
||||||
packages:
|
packages:
|
||||||
|
common_idf: !include common_idf.yaml
|
||||||
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
||||||
standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml
|
standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml
|
||||||
|
|
||||||
esp32:
|
|
||||||
framework:
|
|
||||||
type: esp-idf
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -1,14 +1,8 @@
|
|||||||
---
|
---
|
||||||
packages:
|
packages:
|
||||||
|
common: !include common.yaml
|
||||||
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
||||||
standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml
|
standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml
|
||||||
addon_bluetooth_proxy: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml
|
|
||||||
|
|
||||||
esp32:
|
bluetooth_proxy:
|
||||||
framework:
|
|
||||||
type: esp-idf
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -1,12 +1,5 @@
|
|||||||
---
|
---
|
||||||
packages:
|
packages:
|
||||||
|
common_idf: !include common_idf.yaml
|
||||||
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
||||||
|
|
||||||
esp32:
|
|
||||||
framework:
|
|
||||||
type: esp-idf
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -1,13 +1,6 @@
|
|||||||
---
|
---
|
||||||
packages:
|
packages:
|
||||||
|
common_idf: !include common_idf.yaml
|
||||||
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
||||||
standard_hw_relays_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml
|
standard_hw_relays_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml
|
||||||
|
|
||||||
esp32:
|
|
||||||
framework:
|
|
||||||
type: esp-idf
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -1,13 +1,6 @@
|
|||||||
---
|
---
|
||||||
packages:
|
packages:
|
||||||
|
common_idf: !include common_idf.yaml
|
||||||
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
||||||
standard_hw_speaker_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml
|
standard_hw_speaker_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml
|
||||||
|
|
||||||
esp32:
|
|
||||||
framework:
|
|
||||||
type: esp-idf
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -1,13 +1,6 @@
|
|||||||
---
|
---
|
||||||
packages:
|
packages:
|
||||||
|
common_idf: !include common_idf.yaml
|
||||||
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml
|
||||||
standard_hw_vibration_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml
|
standard_hw_vibration_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml
|
||||||
|
|
||||||
esp32:
|
|
||||||
framework:
|
|
||||||
type: esp-idf
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
...
|
...
|
||||||
|
|||||||
BIN
Assets/Logo_dark.png
Normal file
BIN
Assets/Logo_dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 165 KiB |
BIN
Assets/Logo_dark.webp
Normal file
BIN
Assets/Logo_dark.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 261 KiB |
BIN
Assets/Logo_light.png
Normal file
BIN
Assets/Logo_light.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 107 KiB |
@@ -2,7 +2,7 @@
|
|||||||
##### TX Ultimate Easy for ESPHome #####
|
##### TX Ultimate Easy for ESPHome #####
|
||||||
##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy #####
|
##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy #####
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
##### Purpose: ESPHome Core - Hardware - Media player #####
|
##### Purpose: ESPHome Basic (includes core plus non-essential, but recommended packages) #####
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
##### Author: edwardtfn - https://github.com/edwardtfn - https://buymeacoffee.com/edwardfirmo #####
|
##### Author: edwardtfn - https://github.com/edwardtfn - https://buymeacoffee.com/edwardfirmo #####
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
@@ -11,19 +11,9 @@
|
|||||||
##### - For normal system use, modifications to this file are NOT required. #####
|
##### - For normal system use, modifications to this file are NOT required. #####
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
---
|
---
|
||||||
i2s_audio:
|
packages:
|
||||||
id: if_i2s_audio
|
# yamllint disable rule:colons
|
||||||
i2s_bclk_pin: GPIO2
|
core: !include TX-Ultimate-Easy-ESPHome_core.yaml
|
||||||
i2s_lrclk_pin: GPIO4
|
standard: !include TX-Ultimate-Easy-ESPHome_standard.yaml
|
||||||
|
# yamllint enable rule:colons
|
||||||
media_player:
|
|
||||||
- id: mp_media_player
|
|
||||||
name: Media Player
|
|
||||||
internal: false
|
|
||||||
platform: i2s_audio
|
|
||||||
i2s_dout_pin: GPIO15
|
|
||||||
i2s_audio_id: if_i2s_audio
|
|
||||||
i2s_comm_fmt: msb # Experimental - It was 'lsb' until v2024.12.12
|
|
||||||
dac_type: external
|
|
||||||
mode: mono
|
|
||||||
...
|
...
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
####################################################################################################
|
|
||||||
##### 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:
|
|
||||||
|
|
||||||
esphome:
|
|
||||||
platformio_options:
|
|
||||||
build_flags:
|
|
||||||
- -D TX_ULTIMATE_EASY_ADDON_BLE_PROXY
|
|
||||||
|
|
||||||
script:
|
|
||||||
- id: !extend dump_config_list_packages
|
|
||||||
then:
|
|
||||||
- script.wait: dump_config
|
|
||||||
- lambda: |-
|
|
||||||
// Check for requirements
|
|
||||||
#if !defined(TX_ULTIMATE_EASY_CORE)
|
|
||||||
#error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Identify itself
|
|
||||||
ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Add-on - BLE Proxy");
|
|
||||||
...
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
####################################################################################################
|
|
||||||
##### TX Ultimate Easy for ESPHome #####
|
|
||||||
##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy #####
|
|
||||||
####################################################################################################
|
|
||||||
##### Purpose: ESPHome - Add-on - Media player #####
|
|
||||||
####################################################################################################
|
|
||||||
##### 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. #####
|
|
||||||
####################################################################################################
|
|
||||||
---
|
|
||||||
packages:
|
|
||||||
standard_hw_audio: !include TX-Ultimate-Easy-ESPHome_standard_hw_audio.yaml
|
|
||||||
|
|
||||||
esp32:
|
|
||||||
framework:
|
|
||||||
type: arduino
|
|
||||||
|
|
||||||
esphome:
|
|
||||||
platformio_options:
|
|
||||||
build_flags:
|
|
||||||
- -D TX_ULTIMATE_EASY_ADDON_MEDIA_PLAYER
|
|
||||||
|
|
||||||
media_player:
|
|
||||||
- id: mp_media_player
|
|
||||||
name: Media Player
|
|
||||||
internal: false
|
|
||||||
platform: i2s_audio
|
|
||||||
i2s_dout_pin: GPIO15
|
|
||||||
i2s_audio_id: if_i2s_audio
|
|
||||||
i2s_comm_fmt: msb
|
|
||||||
dac_type: external
|
|
||||||
mode: mono
|
|
||||||
mute_pin:
|
|
||||||
number: GPIO26
|
|
||||||
inverted: true
|
|
||||||
allow_other_uses: true
|
|
||||||
|
|
||||||
script:
|
|
||||||
- id: !extend dump_config_list_packages
|
|
||||||
then:
|
|
||||||
- script.wait: dump_config
|
|
||||||
- lambda: |-
|
|
||||||
// Check for requirements
|
|
||||||
#if !defined(TX_ULTIMATE_EASY_CORE)
|
|
||||||
#error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required."
|
|
||||||
#endif
|
|
||||||
#if !defined(TX_ULTIMATE_EASY_STANDARD_HW_AUDIO)
|
|
||||||
#error "The package TX-Ultimate-Easy-ESPHome_standard_hw_audio.yaml is required."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Identify itself
|
|
||||||
ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Add-on - Media Player");
|
|
||||||
|
|
||||||
switch:
|
|
||||||
- id: sw_speaker_amplifier
|
|
||||||
name: Speaker - Amplifier
|
|
||||||
platform: gpio
|
|
||||||
pin:
|
|
||||||
number: GPIO26
|
|
||||||
inverted: true
|
|
||||||
allow_other_uses: true
|
|
||||||
restore_mode: RESTORE_DEFAULT_ON
|
|
||||||
internal: true
|
|
||||||
entity_category: config
|
|
||||||
...
|
|
||||||
@@ -11,312 +11,11 @@
|
|||||||
##### - For normal system use, modifications to this file are NOT required. #####
|
##### - For normal system use, modifications to this file are NOT required. #####
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
---
|
---
|
||||||
substitutions:
|
|
||||||
name: tx-ultimate-easy
|
|
||||||
friendly_name: TX Ultimate Easy
|
|
||||||
|
|
||||||
<<: !include ../versioning/VERSION_YAML
|
|
||||||
|
|
||||||
TX_MODEL_FORMAT_EU_TEXT: "EU (Square, T5-xC-86)"
|
|
||||||
TX_MODEL_FORMAT_US_TEXT: "US (Rectangle, T5-xC-120)"
|
|
||||||
|
|
||||||
TX_MODEL_1_GANG_TEXT: "1 Gang"
|
|
||||||
TX_MODEL_2_GANG_TEXT: "2 Gang"
|
|
||||||
TX_MODEL_3_GANG_TEXT: "3 Gang"
|
|
||||||
TX_MODEL_4_GANG_TEXT: "4 Gang"
|
|
||||||
|
|
||||||
DUMP_CONFIG_CALLER_DELAY: 10s # Delay to dump config after requested
|
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
# yamllint disable rule:colons
|
# yamllint disable rule:colons
|
||||||
|
core_common: !include TX-Ultimate-Easy-ESPHome_core_common.yaml
|
||||||
core_hw_buttons: !include TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml
|
core_hw_buttons: !include TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml
|
||||||
core_hw_leds: !include TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml
|
core_hw_leds: !include TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml
|
||||||
core_hw_touch: !include TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml
|
core_hw_touch: !include TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml
|
||||||
# yamllint enable rule:colons
|
# yamllint enable rule:colons
|
||||||
|
|
||||||
api:
|
|
||||||
id: api_server
|
|
||||||
on_client_connected:
|
|
||||||
then:
|
|
||||||
- script.execute: dump_config_caller
|
|
||||||
- script.execute: publish_device_info
|
|
||||||
|
|
||||||
binary_sensor:
|
|
||||||
- id: bs_pending_restart
|
|
||||||
name: Pending Restart Status
|
|
||||||
internal: false
|
|
||||||
disabled_by_default: false
|
|
||||||
platform: template
|
|
||||||
entity_category: diagnostic
|
|
||||||
device_class: problem
|
|
||||||
on_state:
|
|
||||||
then:
|
|
||||||
- lambda: |-
|
|
||||||
if (x)
|
|
||||||
ESP_LOGW("core", "Pending restart: YES");
|
|
||||||
else
|
|
||||||
ESP_LOGCONFIG("core", "Pending restart: No");
|
|
||||||
- script.execute: dump_config_caller
|
|
||||||
|
|
||||||
esp32:
|
|
||||||
board: esp32dev # adafruit_feather_esp32_v2 # esp32dev
|
|
||||||
flash_size: 8MB
|
|
||||||
framework:
|
|
||||||
type: esp-idf
|
|
||||||
|
|
||||||
esphome:
|
|
||||||
name: ${name}
|
|
||||||
friendly_name: ${friendly_name}
|
|
||||||
comment: TX Ultimate Easy
|
|
||||||
project:
|
|
||||||
name: "edwardtfn.tx_ultimate_easy"
|
|
||||||
version: ${version}
|
|
||||||
platformio_options:
|
|
||||||
build_flags:
|
|
||||||
- -D TX_ULTIMATE_EASY_CORE
|
|
||||||
|
|
||||||
on_boot:
|
|
||||||
- priority: 700
|
|
||||||
then:
|
|
||||||
- script.execute: boot_initialize
|
|
||||||
|
|
||||||
- priority: 600 # This is where most sensors are set up.
|
|
||||||
then:
|
|
||||||
- script.execute: boot_sequence
|
|
||||||
|
|
||||||
- priority: -100 # At this priority, pretty much everything should already be initialized.
|
|
||||||
then:
|
|
||||||
- script.execute: boot_done
|
|
||||||
|
|
||||||
globals:
|
|
||||||
- id: is_us_model
|
|
||||||
type: bool
|
|
||||||
restore_value: true
|
|
||||||
initial_value: 'false'
|
|
||||||
|
|
||||||
- id: gang_count
|
|
||||||
type: uint8_t
|
|
||||||
restore_value: true
|
|
||||||
initial_value: '0'
|
|
||||||
|
|
||||||
- id: gang_count_plural_suffix
|
|
||||||
type: std::string
|
|
||||||
restore_value: true
|
|
||||||
max_restore_data_length: 3
|
|
||||||
# initial_value: "''"
|
|
||||||
|
|
||||||
logger:
|
|
||||||
level: DEBUG
|
|
||||||
|
|
||||||
ota:
|
|
||||||
platform: esphome
|
|
||||||
|
|
||||||
psram:
|
|
||||||
mode: octal
|
|
||||||
speed: 80MHz
|
|
||||||
|
|
||||||
script:
|
|
||||||
- id: api_send_ha_event_boot
|
|
||||||
mode: queued
|
|
||||||
parameters:
|
|
||||||
type: string
|
|
||||||
then:
|
|
||||||
- homeassistant.event:
|
|
||||||
event: esphome.tx_ultimate_easy
|
|
||||||
data:
|
|
||||||
device_name: !lambda return tx_device_name->state.c_str();
|
|
||||||
firmware: ${version}
|
|
||||||
domain: boot
|
|
||||||
type: !lambda return type.c_str();
|
|
||||||
|
|
||||||
- id: boot_done
|
|
||||||
mode: restart
|
|
||||||
then:
|
|
||||||
- script.execute:
|
|
||||||
id: api_send_ha_event_boot
|
|
||||||
type: done
|
|
||||||
|
|
||||||
- id: boot_initialize
|
|
||||||
mode: restart
|
|
||||||
then:
|
|
||||||
# Extended by:
|
|
||||||
# - HW Buttons
|
|
||||||
# - HW Relays
|
|
||||||
# - HW Touch
|
|
||||||
- script.execute:
|
|
||||||
id: api_send_ha_event_boot
|
|
||||||
type: start
|
|
||||||
- wait_until:
|
|
||||||
condition:
|
|
||||||
- lambda: return sl_tx_model_format->active_index().has_value();
|
|
||||||
- lambda: return sl_tx_model_gang->active_index().has_value();
|
|
||||||
- lambda: |-
|
|
||||||
id(is_us_model) = (sl_tx_model_format->state == "${TX_MODEL_FORMAT_US_TEXT}");
|
|
||||||
id(gang_count) = sl_tx_model_gang->active_index().value() + 1;
|
|
||||||
if (id(gang_count) < 1 || id(gang_count) > 4) {
|
|
||||||
ESP_LOGE("core_hw_leds", "Invalid number of gangs: %" PRIu8, id(gang_count));
|
|
||||||
}
|
|
||||||
id(gang_count_plural_suffix) = id(gang_count) > 1 ? "s" : "";
|
|
||||||
|
|
||||||
- id: boot_sequence
|
|
||||||
mode: restart
|
|
||||||
then:
|
|
||||||
- script.execute: publish_device_info
|
|
||||||
- binary_sensor.template.publish:
|
|
||||||
id: bs_pending_restart
|
|
||||||
state: false
|
|
||||||
|
|
||||||
- id: dump_config
|
|
||||||
mode: restart
|
|
||||||
then:
|
|
||||||
# Extended by all modules
|
|
||||||
- lambda: |-
|
|
||||||
// Device identification
|
|
||||||
ESP_LOGCONFIG("core", "Device friendly name: ${friendly_name}");
|
|
||||||
ESP_LOGCONFIG("core", "Device name: ${name}");
|
|
||||||
ESP_LOGCONFIG("core", "Device name (HA): %s", tx_device_name->state.c_str());
|
|
||||||
ESP_LOGCONFIG("core", "Device hostname: %s", App.get_name().c_str());
|
|
||||||
|
|
||||||
dump_config_versions->execute();
|
|
||||||
|
|
||||||
// Framework detection
|
|
||||||
#ifdef USE_ARDUINO
|
|
||||||
ESP_LOGCONFIG("core", "Framework: Arduino");
|
|
||||||
#elif defined(USE_ESP_IDF)
|
|
||||||
ESP_LOGCONFIG("core", "Framework: ESP-IDF");
|
|
||||||
#else
|
|
||||||
ESP_LOGW("core", "Framework: UNKNOWN");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Model configuration
|
|
||||||
ESP_LOGCONFIG("core", "Model format (selected): %s", sl_tx_model_format->state.c_str());
|
|
||||||
ESP_LOGCONFIG("core", "Model format (detected): %s", id(is_us_model) ? "US" : "EU");
|
|
||||||
ESP_LOGCONFIG("core", "Gangs (selected): %s", sl_tx_model_gang->state.c_str());
|
|
||||||
ESP_LOGCONFIG("core", "Gangs (detected): %" PRIu8 "-Gang%s", id(gang_count), id(gang_count_plural_suffix).c_str());
|
|
||||||
|
|
||||||
// System state
|
|
||||||
if (bs_pending_restart->state)
|
|
||||||
ESP_LOGW("core", "Pending restart: YES");
|
|
||||||
else
|
|
||||||
ESP_LOGCONFIG("core", "Pending restart: No");
|
|
||||||
|
|
||||||
- id: dump_config_caller
|
|
||||||
mode: restart
|
|
||||||
then:
|
|
||||||
- delay: ${DUMP_CONFIG_CALLER_DELAY}
|
|
||||||
- script.execute: dump_config
|
|
||||||
- script.wait: dump_config
|
|
||||||
- script.execute: dump_config_list_packages
|
|
||||||
|
|
||||||
- id: dump_config_list_packages
|
|
||||||
mode: restart
|
|
||||||
then:
|
|
||||||
- script.wait: dump_config
|
|
||||||
- lambda: |-
|
|
||||||
ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, "Installed packages:");
|
|
||||||
|
|
||||||
// Identify itself
|
|
||||||
ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Core");
|
|
||||||
|
|
||||||
- id: dump_config_versions
|
|
||||||
mode: restart
|
|
||||||
then:
|
|
||||||
- lambda: |-
|
|
||||||
// Version information
|
|
||||||
ESP_LOGCONFIG("core", "TX Ultimate firmware version: ${version}");
|
|
||||||
|
|
||||||
- id: publish_device_info
|
|
||||||
mode: restart
|
|
||||||
then:
|
|
||||||
- lambda: |-
|
|
||||||
tx_fw_version->publish_state("${version}");
|
|
||||||
tx_device_name->publish_state(App.get_name().c_str());
|
|
||||||
|
|
||||||
select:
|
|
||||||
- id: sl_tx_model_format
|
|
||||||
name: Model (Format)
|
|
||||||
platform: template
|
|
||||||
options:
|
|
||||||
- "${TX_MODEL_FORMAT_EU_TEXT}"
|
|
||||||
- "${TX_MODEL_FORMAT_US_TEXT}"
|
|
||||||
initial_option: "${TX_MODEL_FORMAT_EU_TEXT}"
|
|
||||||
optimistic: true
|
|
||||||
restore_value: true
|
|
||||||
internal: false
|
|
||||||
entity_category: config
|
|
||||||
disabled_by_default: false
|
|
||||||
icon: mdi:tablet-cellphone
|
|
||||||
on_value:
|
|
||||||
then:
|
|
||||||
- binary_sensor.template.publish:
|
|
||||||
id: bs_pending_restart
|
|
||||||
state: true
|
|
||||||
- lambda: |-
|
|
||||||
id(is_us_model) = (x == "${TX_MODEL_FORMAT_US_TEXT}");
|
|
||||||
ESP_LOGI("core", "New model selected: %s", id(is_us_model) ? "US" : "EU");
|
|
||||||
|
|
||||||
- id: sl_tx_model_gang
|
|
||||||
name: Model (Gang)
|
|
||||||
platform: template
|
|
||||||
options:
|
|
||||||
- "${TX_MODEL_1_GANG_TEXT}"
|
|
||||||
- "${TX_MODEL_2_GANG_TEXT}"
|
|
||||||
- "${TX_MODEL_3_GANG_TEXT}"
|
|
||||||
- "${TX_MODEL_4_GANG_TEXT}"
|
|
||||||
initial_option: "${TX_MODEL_1_GANG_TEXT}"
|
|
||||||
optimistic: true
|
|
||||||
restore_value: true
|
|
||||||
internal: false
|
|
||||||
entity_category: config
|
|
||||||
disabled_by_default: false
|
|
||||||
icon: mdi:dip-switch
|
|
||||||
on_value:
|
|
||||||
then:
|
|
||||||
- binary_sensor.template.publish:
|
|
||||||
id: bs_pending_restart
|
|
||||||
state: true
|
|
||||||
- lambda: |-
|
|
||||||
id(gang_count) = static_cast<uint8_t>(i) + 1;
|
|
||||||
ESP_LOGI("core", "New model selected: %" PRIu8 "-%s", id(gang_count), id(gang_count) > 1 ? "Gangs" : "Gang");
|
|
||||||
tx_ultimate->set_gang_count(id(gang_count));
|
|
||||||
|
|
||||||
text_sensor:
|
|
||||||
- id: tx_fw_version
|
|
||||||
name: TX Ultimate Easy Firmware Version
|
|
||||||
platform: template
|
|
||||||
entity_category: diagnostic
|
|
||||||
icon: mdi:tag-text-outline
|
|
||||||
internal: false
|
|
||||||
update_interval: never
|
|
||||||
lambda: |-
|
|
||||||
return {"${version}"};
|
|
||||||
|
|
||||||
- id: tx_device_name
|
|
||||||
name: Device Name
|
|
||||||
platform: template
|
|
||||||
icon: mdi:identifier
|
|
||||||
entity_category: diagnostic
|
|
||||||
internal: false
|
|
||||||
disabled_by_default: false
|
|
||||||
update_interval: never
|
|
||||||
lambda: |-
|
|
||||||
return {"${name}"};
|
|
||||||
filters:
|
|
||||||
- lambda: |-
|
|
||||||
const std::string raw_name = x;
|
|
||||||
std::string result;
|
|
||||||
bool last_was_underscore = false;
|
|
||||||
for (const char& c : raw_name) {
|
|
||||||
if (isalnum(c)) {
|
|
||||||
result += tolower(c); // Add alphanumeric characters as lowercase
|
|
||||||
last_was_underscore = false;
|
|
||||||
} else if (!last_was_underscore) { // Replace non-alphanumeric with '_' but avoid consecutive '_'
|
|
||||||
result += '_';
|
|
||||||
last_was_underscore = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
id: wifi_component
|
|
||||||
...
|
...
|
||||||
|
|||||||
378
ESPHome/TX-Ultimate-Easy-ESPHome_core_common.yaml
Normal file
378
ESPHome/TX-Ultimate-Easy-ESPHome_core_common.yaml
Normal file
@@ -0,0 +1,378 @@
|
|||||||
|
####################################################################################################
|
||||||
|
##### TX Ultimate Easy for ESPHome #####
|
||||||
|
##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy #####
|
||||||
|
####################################################################################################
|
||||||
|
##### Purpose: ESPHome Core - Common #####
|
||||||
|
####################################################################################################
|
||||||
|
##### 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:
|
||||||
|
name: tx-ultimate-easy
|
||||||
|
friendly_name: TX Ultimate Easy
|
||||||
|
|
||||||
|
<<: !include ../versioning/VERSION_YAML
|
||||||
|
|
||||||
|
EVENT_NAME: esphome.tx_ultimate_easy
|
||||||
|
|
||||||
|
TX_MODEL_FORMAT_EU_TEXT: "EU (Square, T5-xC-86)"
|
||||||
|
TX_MODEL_FORMAT_US_TEXT: "US (Rectangle, T5-xC-120)"
|
||||||
|
|
||||||
|
TX_MODEL_1_GANG_TEXT: "1 Gang"
|
||||||
|
TX_MODEL_2_GANG_TEXT: "2 Gang"
|
||||||
|
TX_MODEL_3_GANG_TEXT: "3 Gang"
|
||||||
|
TX_MODEL_4_GANG_TEXT: "4 Gang"
|
||||||
|
|
||||||
|
DUMP_CONFIG_CALLER_DELAY: 5s # Delay to dump config after requested
|
||||||
|
|
||||||
|
TAG_CORE_COMMON: core.common
|
||||||
|
|
||||||
|
api:
|
||||||
|
id: api_server
|
||||||
|
on_client_connected:
|
||||||
|
then:
|
||||||
|
- script.execute: dump_config_caller
|
||||||
|
- script.execute: publish_device_info
|
||||||
|
|
||||||
|
binary_sensor:
|
||||||
|
- id: bs_pending_restart
|
||||||
|
name: Pending Restart Status
|
||||||
|
internal: false
|
||||||
|
disabled_by_default: false
|
||||||
|
platform: template
|
||||||
|
entity_category: diagnostic
|
||||||
|
device_class: problem
|
||||||
|
on_state:
|
||||||
|
then:
|
||||||
|
- script.execute: dump_config_caller
|
||||||
|
|
||||||
|
- id: bs_boot_completed
|
||||||
|
name: Boot Completed
|
||||||
|
internal: false
|
||||||
|
disabled_by_default: false
|
||||||
|
platform: template
|
||||||
|
entity_category: diagnostic
|
||||||
|
device_class: connectivity
|
||||||
|
icon: mdi:rocket-launch
|
||||||
|
on_state:
|
||||||
|
then:
|
||||||
|
- script.execute: dump_config_caller
|
||||||
|
|
||||||
|
button:
|
||||||
|
- id: bt_restart
|
||||||
|
name: Restart
|
||||||
|
internal: false
|
||||||
|
platform: restart
|
||||||
|
|
||||||
|
esp32:
|
||||||
|
board: esp32dev
|
||||||
|
flash_size: 8MB
|
||||||
|
framework:
|
||||||
|
type: esp-idf
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: ${name}
|
||||||
|
friendly_name: ${friendly_name}
|
||||||
|
comment: TX Ultimate Easy
|
||||||
|
min_version: 2025.8.0
|
||||||
|
project:
|
||||||
|
name: "edwardtfn.tx_ultimate_easy"
|
||||||
|
version: ${version}
|
||||||
|
platformio_options:
|
||||||
|
build_flags:
|
||||||
|
- -D TX_ULTIMATE_EASY_CORE_COMMON
|
||||||
|
|
||||||
|
on_boot:
|
||||||
|
- priority: 1000 # Very early in boot process
|
||||||
|
then:
|
||||||
|
- binary_sensor.template.publish:
|
||||||
|
id: bs_boot_completed
|
||||||
|
state: OFF # yamllint disable-line rule:truthy
|
||||||
|
|
||||||
|
- priority: 750
|
||||||
|
then:
|
||||||
|
- script.execute: restore_from_nvs
|
||||||
|
|
||||||
|
- priority: 700
|
||||||
|
then:
|
||||||
|
- script.execute: boot_initialize
|
||||||
|
|
||||||
|
- priority: 600 # This is where most sensors are set up.
|
||||||
|
then:
|
||||||
|
- script.execute: boot_sequence
|
||||||
|
|
||||||
|
- priority: -100 # At this priority, pretty much everything should already be initialized.
|
||||||
|
then:
|
||||||
|
- script.execute: boot_done
|
||||||
|
|
||||||
|
external_components:
|
||||||
|
- source:
|
||||||
|
type: git
|
||||||
|
url: https://git.andrejka.at/oneil1987/TX-Ultimate-Easy
|
||||||
|
ref: v${version}
|
||||||
|
refresh: 1h
|
||||||
|
components:
|
||||||
|
- tx_ultimate_easy
|
||||||
|
|
||||||
|
globals:
|
||||||
|
- id: gang_count
|
||||||
|
type: uint8_t
|
||||||
|
restore_value: true
|
||||||
|
initial_value: '0'
|
||||||
|
|
||||||
|
- id: is_us_model
|
||||||
|
type: bool
|
||||||
|
restore_value: true
|
||||||
|
initial_value: 'false'
|
||||||
|
|
||||||
|
logger:
|
||||||
|
level: DEBUG
|
||||||
|
|
||||||
|
ota:
|
||||||
|
platform: esphome
|
||||||
|
|
||||||
|
psram:
|
||||||
|
|
||||||
|
script:
|
||||||
|
- id: api_send_ha_event_boot
|
||||||
|
mode: queued
|
||||||
|
parameters:
|
||||||
|
type: string
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
// Send event to Home Assistant
|
||||||
|
esphome::api::CustomAPIDevice ha_event;
|
||||||
|
ha_event.fire_homeassistant_event("${EVENT_NAME}", {
|
||||||
|
{"device_name", id(tx_device_name).state.c_str()},
|
||||||
|
{"firmware", "${version}"},
|
||||||
|
{"domain", "boot"},
|
||||||
|
{"type", type.c_str()}
|
||||||
|
});
|
||||||
|
|
||||||
|
- id: boot_done
|
||||||
|
mode: restart
|
||||||
|
then:
|
||||||
|
- script.wait: restore_from_nvs
|
||||||
|
- script.wait: boot_initialize
|
||||||
|
- script.wait: boot_sequence
|
||||||
|
- script.execute:
|
||||||
|
id: api_send_ha_event_boot
|
||||||
|
type: done
|
||||||
|
- script.wait: api_send_ha_event_boot
|
||||||
|
- binary_sensor.template.publish:
|
||||||
|
id: bs_boot_completed
|
||||||
|
state: ON # yamllint disable-line rule:truthy
|
||||||
|
|
||||||
|
- id: boot_initialize
|
||||||
|
mode: restart
|
||||||
|
then:
|
||||||
|
# Extended by:
|
||||||
|
# - HW Buttons
|
||||||
|
# - HW Relays
|
||||||
|
# - HW Touch
|
||||||
|
- script.execute:
|
||||||
|
id: api_send_ha_event_boot
|
||||||
|
type: start
|
||||||
|
- wait_until:
|
||||||
|
condition:
|
||||||
|
- lambda: return sl_tx_model_format->active_index().has_value();
|
||||||
|
- lambda: return sl_tx_model_gang->active_index().has_value();
|
||||||
|
- lambda: |-
|
||||||
|
id(is_us_model) = (sl_tx_model_format->state == "${TX_MODEL_FORMAT_US_TEXT}");
|
||||||
|
id(gang_count) = sl_tx_model_gang->active_index().value() + 1;
|
||||||
|
if (id(gang_count) < 1 || id(gang_count) > 4) {
|
||||||
|
ESP_LOGE("${TAG_CORE_COMMON}", "Invalid number of gangs: %" PRIu8, id(gang_count));
|
||||||
|
}
|
||||||
|
|
||||||
|
- id: boot_sequence
|
||||||
|
mode: restart
|
||||||
|
then:
|
||||||
|
- script.execute: publish_device_info
|
||||||
|
- binary_sensor.template.publish:
|
||||||
|
id: bs_pending_restart
|
||||||
|
state: false
|
||||||
|
|
||||||
|
- id: dump_config
|
||||||
|
mode: restart
|
||||||
|
then:
|
||||||
|
# Extended by all modules
|
||||||
|
- lambda: |-
|
||||||
|
// Device identification
|
||||||
|
ESP_LOGCONFIG("${TAG_CORE_COMMON}", "Device friendly name: ${friendly_name}");
|
||||||
|
ESP_LOGCONFIG("${TAG_CORE_COMMON}", "Device name: ${name}");
|
||||||
|
ESP_LOGCONFIG("${TAG_CORE_COMMON}", "Device name (HA): %s", tx_device_name->state.c_str());
|
||||||
|
ESP_LOGCONFIG("${TAG_CORE_COMMON}", "Device hostname: %s", App.get_name().c_str());
|
||||||
|
|
||||||
|
dump_config_versions->execute();
|
||||||
|
|
||||||
|
// Framework detection
|
||||||
|
#ifdef USE_ARDUINO
|
||||||
|
ESP_LOGCONFIG("${TAG_CORE_COMMON}", "Framework: Arduino");
|
||||||
|
#elif defined(USE_ESP_IDF)
|
||||||
|
ESP_LOGCONFIG("${TAG_CORE_COMMON}", "Framework: ESP-IDF");
|
||||||
|
#else
|
||||||
|
ESP_LOGW("${TAG_CORE_COMMON}", "Framework: UNKNOWN");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Model configuration
|
||||||
|
ESP_LOGCONFIG("${TAG_CORE_COMMON}", "Model format (selected): %s",
|
||||||
|
sl_tx_model_format->state.c_str());
|
||||||
|
ESP_LOGCONFIG("${TAG_CORE_COMMON}", "Model format (detected): %s",
|
||||||
|
id(is_us_model) ? "US" : "EU");
|
||||||
|
ESP_LOGCONFIG("${TAG_CORE_COMMON}", "Gangs (selected): %s",
|
||||||
|
sl_tx_model_gang->state.c_str());
|
||||||
|
ESP_LOGCONFIG("${TAG_CORE_COMMON}", "Gangs (detected): %" PRIu8 "-Gang%s",
|
||||||
|
id(gang_count), id(gang_count) > 1 ? "s" : "");
|
||||||
|
|
||||||
|
// Boot completion status
|
||||||
|
if (bs_boot_completed->state)
|
||||||
|
ESP_LOGCONFIG("${TAG_CORE_COMMON}", "Boot completed: Yes");
|
||||||
|
else
|
||||||
|
ESP_LOGW("${TAG_CORE_COMMON}", "Boot completed: NO");
|
||||||
|
|
||||||
|
// System state
|
||||||
|
if (bs_pending_restart->state)
|
||||||
|
ESP_LOGW("${TAG_CORE_COMMON}", "Pending restart: YES");
|
||||||
|
else
|
||||||
|
ESP_LOGCONFIG("${TAG_CORE_COMMON}", "Pending restart: No");
|
||||||
|
|
||||||
|
- id: dump_config_caller
|
||||||
|
mode: restart
|
||||||
|
then:
|
||||||
|
- delay: ${DUMP_CONFIG_CALLER_DELAY}
|
||||||
|
- script.execute: dump_config
|
||||||
|
- script.wait: dump_config
|
||||||
|
- script.execute: dump_config_list_packages
|
||||||
|
|
||||||
|
- id: dump_config_list_packages
|
||||||
|
mode: restart
|
||||||
|
then:
|
||||||
|
- script.wait: dump_config
|
||||||
|
- lambda: |-
|
||||||
|
ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, "Installed packages:");
|
||||||
|
|
||||||
|
// Identify itself
|
||||||
|
ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Core");
|
||||||
|
|
||||||
|
- id: dump_config_versions
|
||||||
|
mode: restart
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
// Version information
|
||||||
|
ESP_LOGCONFIG("${TAG_CORE_COMMON}", "TX Ultimate firmware version: ${version}");
|
||||||
|
// ESPHome builder information
|
||||||
|
ESP_LOGCONFIG("${TAG_CORE_COMMON}", "ESPHome builder: " ESPHOME_VERSION);
|
||||||
|
ESP_LOGCONFIG("${TAG_CORE_COMMON}", "ESPHome build timestamp: %s", App.get_compilation_time().c_str());
|
||||||
|
|
||||||
|
- id: publish_device_info
|
||||||
|
mode: restart
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
tx_fw_version->publish_state("${version}");
|
||||||
|
tx_device_name->publish_state(App.get_name().c_str());
|
||||||
|
|
||||||
|
- id: restore_from_nvs
|
||||||
|
mode: single
|
||||||
|
then:
|
||||||
|
- select.set_index:
|
||||||
|
id: sl_tx_model_format
|
||||||
|
index: !lambda if (id(is_us_model)) return 1; else return 0;
|
||||||
|
- select.set_index:
|
||||||
|
id: sl_tx_model_gang
|
||||||
|
index: !lambda |-
|
||||||
|
if (id(gang_count) < 1 || id(gang_count) > 4) return 0; // default to 1-Gang
|
||||||
|
return static_cast<uint8_t>(id(gang_count)) - 1;
|
||||||
|
|
||||||
|
select:
|
||||||
|
- id: sl_tx_model_format
|
||||||
|
name: Model (Format)
|
||||||
|
platform: template
|
||||||
|
options:
|
||||||
|
- "${TX_MODEL_FORMAT_EU_TEXT}"
|
||||||
|
- "${TX_MODEL_FORMAT_US_TEXT}"
|
||||||
|
initial_option: "${TX_MODEL_FORMAT_EU_TEXT}"
|
||||||
|
optimistic: true
|
||||||
|
restore_value: false
|
||||||
|
internal: false
|
||||||
|
entity_category: config
|
||||||
|
disabled_by_default: false
|
||||||
|
icon: mdi:tablet-cellphone
|
||||||
|
on_value:
|
||||||
|
then:
|
||||||
|
- binary_sensor.template.publish:
|
||||||
|
id: bs_pending_restart
|
||||||
|
state: true
|
||||||
|
- lambda: |-
|
||||||
|
id(is_us_model) = (x == "${TX_MODEL_FORMAT_US_TEXT}");
|
||||||
|
|
||||||
|
- id: sl_tx_model_gang
|
||||||
|
name: Model (Gang)
|
||||||
|
platform: template
|
||||||
|
options:
|
||||||
|
- "${TX_MODEL_1_GANG_TEXT}"
|
||||||
|
- "${TX_MODEL_2_GANG_TEXT}"
|
||||||
|
- "${TX_MODEL_3_GANG_TEXT}"
|
||||||
|
- "${TX_MODEL_4_GANG_TEXT}"
|
||||||
|
initial_option: "${TX_MODEL_1_GANG_TEXT}"
|
||||||
|
optimistic: true
|
||||||
|
restore_value: false
|
||||||
|
internal: false
|
||||||
|
entity_category: config
|
||||||
|
disabled_by_default: false
|
||||||
|
icon: mdi:dip-switch
|
||||||
|
on_value:
|
||||||
|
then:
|
||||||
|
- binary_sensor.template.publish:
|
||||||
|
id: bs_pending_restart
|
||||||
|
state: true
|
||||||
|
- lambda: |-
|
||||||
|
id(gang_count) = static_cast<uint8_t>(i) + 1;
|
||||||
|
tx_ultimate->set_gang_count(id(gang_count));
|
||||||
|
|
||||||
|
text_sensor:
|
||||||
|
- id: tx_fw_version
|
||||||
|
name: TX Ultimate Easy Firmware Version
|
||||||
|
platform: template
|
||||||
|
entity_category: diagnostic
|
||||||
|
icon: mdi:tag-text-outline
|
||||||
|
internal: false
|
||||||
|
update_interval: never
|
||||||
|
lambda: |-
|
||||||
|
return {"${version}"};
|
||||||
|
|
||||||
|
- id: tx_device_name
|
||||||
|
name: Device Name
|
||||||
|
platform: template
|
||||||
|
icon: mdi:identifier
|
||||||
|
entity_category: diagnostic
|
||||||
|
internal: false
|
||||||
|
disabled_by_default: false
|
||||||
|
update_interval: never
|
||||||
|
lambda: |-
|
||||||
|
return {"${name}"};
|
||||||
|
filters:
|
||||||
|
- lambda: |-
|
||||||
|
const std::string raw_name = x;
|
||||||
|
std::string result;
|
||||||
|
bool last_was_underscore = false;
|
||||||
|
for (const char& c : raw_name) {
|
||||||
|
if (isalnum(c)) {
|
||||||
|
result += tolower(c); // Add alphanumeric characters as lowercase
|
||||||
|
last_was_underscore = false;
|
||||||
|
} else if (!last_was_underscore) { // Replace non-alphanumeric with '_' but avoid consecutive '_'
|
||||||
|
result += '_';
|
||||||
|
last_was_underscore = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
|
||||||
|
tx_ultimate_easy:
|
||||||
|
id: tx_ultimate
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
id: wifi_component
|
||||||
|
...
|
||||||
@@ -36,6 +36,8 @@ substitutions:
|
|||||||
BUTTON_3_ID: '3'
|
BUTTON_3_ID: '3'
|
||||||
BUTTON_4_ID: '4'
|
BUTTON_4_ID: '4'
|
||||||
|
|
||||||
|
TAG_CORE_HW_BUTTONS: core.hw.buttons
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- &binary_sensor_button_base
|
- &binary_sensor_button_base
|
||||||
id: bs_button_2
|
id: bs_button_2
|
||||||
@@ -63,6 +65,14 @@ esphome:
|
|||||||
- -D TX_ULTIMATE_EASY_CORE_HW_BUTTONS
|
- -D TX_ULTIMATE_EASY_CORE_HW_BUTTONS
|
||||||
|
|
||||||
globals:
|
globals:
|
||||||
|
# Packed button actions - replaces 4 separate selects
|
||||||
|
- id: button_actions_packed
|
||||||
|
type: uint16_t
|
||||||
|
restore_value: true
|
||||||
|
initial_value: '4369' # Binary: 0001000100010001 = all buttons set to option 1 (default action)
|
||||||
|
# Bit layout: [button4(4)][button3(4)][button2(4)][button1(4)]
|
||||||
|
# Each button uses 4 bits: 0=None, 1=Toggle, 2=Failsafe, 3-15=Reserved for future options
|
||||||
|
|
||||||
- id: button_press_button
|
- id: button_press_button
|
||||||
type: uint8_t
|
type: uint8_t
|
||||||
restore_value: false
|
restore_value: false
|
||||||
@@ -112,19 +122,20 @@ script:
|
|||||||
action: string
|
action: string
|
||||||
count: uint8_t
|
count: uint8_t
|
||||||
then:
|
then:
|
||||||
- homeassistant.event:
|
|
||||||
event: esphome.tx_ultimate_easy
|
|
||||||
data:
|
|
||||||
device_name: !lambda return tx_device_name->state.c_str();
|
|
||||||
firmware: ${version}
|
|
||||||
domain: touch
|
|
||||||
type: button
|
|
||||||
action: !lambda return action.c_str();
|
|
||||||
button_id: !lambda return button;
|
|
||||||
count: !lambda return count;
|
|
||||||
position: !lambda return id(button_press_position);
|
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
ESP_LOGI("core_hw_buttons", "Button %" PRIu8 " action: '%s'", button, action.c_str());
|
// Send event to Home Assistant
|
||||||
|
esphome::api::CustomAPIDevice ha_event;
|
||||||
|
ha_event.fire_homeassistant_event("${EVENT_NAME}", {
|
||||||
|
{"device_name", id(tx_device_name).state.c_str()},
|
||||||
|
{"firmware", "${version}"},
|
||||||
|
{"domain", "touch"},
|
||||||
|
{"type", "button"},
|
||||||
|
{"action", action.c_str()},
|
||||||
|
{"button_id", std::to_string(button)},
|
||||||
|
{"count", std::to_string(count)},
|
||||||
|
{"position", std::to_string(id(button_press_position))}
|
||||||
|
});
|
||||||
|
ESP_LOGI("${TAG_CORE_HW_BUTTONS}", "Button %" PRIu8 " action: '%s'", button, action.c_str());
|
||||||
if (action == "click") {
|
if (action == "click") {
|
||||||
switch (button) {
|
switch (button) {
|
||||||
case ${BUTTON_1_ID}:
|
case ${BUTTON_1_ID}:
|
||||||
@@ -208,38 +219,50 @@ script:
|
|||||||
- id: !extend dump_config
|
- id: !extend dump_config
|
||||||
then:
|
then:
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
|
std::string gang_count_plural_suffix = id(gang_count) > 1 ? "s" : "";
|
||||||
// Button's actions
|
// Button's actions
|
||||||
ESP_LOGCONFIG("core_hw_buttons", "Button%s action%s:",
|
ESP_LOGCONFIG("${TAG_CORE_HW_BUTTONS}", "Button%s action%s:",
|
||||||
id(gang_count_plural_suffix).c_str(),
|
gang_count_plural_suffix.c_str(),
|
||||||
id(gang_count_plural_suffix).c_str());
|
gang_count_plural_suffix.c_str());
|
||||||
ESP_LOGCONFIG("core_hw_buttons", " Relay 1: %s", sl_button_1_action->has_state()
|
ESP_LOGCONFIG("${TAG_CORE_HW_BUTTONS}", " Relay 1: %s", sl_button_1_action->has_state() ?
|
||||||
? sl_button_1_action->state.c_str()
|
sl_button_1_action->state.c_str() : "Unknown");
|
||||||
: "Unknown");
|
|
||||||
if (id(gang_count) >= 2)
|
if (id(gang_count) >= 2)
|
||||||
ESP_LOGCONFIG("core_hw_buttons", " Relay 2: %s", sl_button_2_action->has_state()
|
ESP_LOGCONFIG("${TAG_CORE_HW_BUTTONS}", " Relay 2: %s", sl_button_2_action->has_state() ?
|
||||||
? sl_button_2_action->state.c_str()
|
sl_button_2_action->state.c_str() : "Unknown");
|
||||||
: "Unknown");
|
|
||||||
if (id(gang_count) >= 3)
|
if (id(gang_count) >= 3)
|
||||||
ESP_LOGCONFIG("core_hw_buttons", " Relay 3: %s", sl_button_3_action->has_state()
|
ESP_LOGCONFIG("${TAG_CORE_HW_BUTTONS}", " Relay 3: %s", sl_button_3_action->has_state() ?
|
||||||
? sl_button_3_action->state.c_str()
|
sl_button_3_action->state.c_str() : "Unknown");
|
||||||
: "Unknown");
|
|
||||||
if (id(gang_count) >= 4)
|
if (id(gang_count) >= 4)
|
||||||
ESP_LOGCONFIG("core_hw_buttons", " Relay 4: %s", sl_button_4_action->has_state()
|
ESP_LOGCONFIG("${TAG_CORE_HW_BUTTONS}", " Relay 4: %s", sl_button_4_action->has_state() ?
|
||||||
? sl_button_4_action->state.c_str()
|
sl_button_4_action->state.c_str() : "Unknown");
|
||||||
: "Unknown");
|
|
||||||
|
|
||||||
- id: !extend dump_config_list_packages
|
- id: !extend dump_config_list_packages
|
||||||
then:
|
then:
|
||||||
- script.wait: dump_config
|
- script.wait: dump_config
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
// Check for requirements
|
// Check for requirements
|
||||||
#if !defined(TX_ULTIMATE_EASY_CORE)
|
#if !defined(TX_ULTIMATE_EASY_CORE_COMMON)
|
||||||
#error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required."
|
#error "The package TX-Ultimate-Easy-ESPHome_core_common.yaml is required."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Identify itself
|
// Identify itself
|
||||||
ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Core - Hardware - Buttons");
|
ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Core - Hardware - Buttons");
|
||||||
|
|
||||||
|
- id: !extend restore_from_nvs
|
||||||
|
then:
|
||||||
|
- select.set_index:
|
||||||
|
id: sl_button_1_action
|
||||||
|
index: !lambda return std::min((uint8_t)(id(button_actions_packed) & 0x0F), (uint8_t)2);
|
||||||
|
- select.set_index:
|
||||||
|
id: sl_button_2_action
|
||||||
|
index: !lambda return std::min((uint8_t)((id(button_actions_packed) >> 4) & 0x0F), (uint8_t)2);
|
||||||
|
- select.set_index:
|
||||||
|
id: sl_button_3_action
|
||||||
|
index: !lambda return std::min((uint8_t)((id(button_actions_packed) >> 8) & 0x0F), (uint8_t)2);
|
||||||
|
- select.set_index:
|
||||||
|
id: sl_button_4_action
|
||||||
|
index: !lambda return std::min((uint8_t)((id(button_actions_packed) >> 12) & 0x0F), (uint8_t)2);
|
||||||
|
|
||||||
- id: !extend touch_on_multi_touch_release
|
- id: !extend touch_on_multi_touch_release
|
||||||
then:
|
then:
|
||||||
- script.execute: buttons_release
|
- script.execute: buttons_release
|
||||||
@@ -292,19 +315,20 @@ script:
|
|||||||
id(button_press_start_time) < current_time) {
|
id(button_press_start_time) < current_time) {
|
||||||
uint32_t press_duration = current_time - id(button_press_start_time);
|
uint32_t press_duration = current_time - id(button_press_start_time);
|
||||||
// Handle overflow (optional, since it's unlikely to happen here)
|
// Handle overflow (optional, since it's unlikely to happen here)
|
||||||
ESP_LOGI("core_hw_buttons", "Button press duration: %" PRIu32 " ms", press_duration);
|
ESP_LOGI("${TAG_CORE_HW_BUTTONS}", "Button press duration: %" PRIu32 " ms", press_duration);
|
||||||
if (press_duration < ${BUTTON_CLICK_MIN_LENGTH}) {
|
if (press_duration < ${BUTTON_CLICK_MIN_LENGTH}) {
|
||||||
ESP_LOGW("core_hw_buttons", "Ignoring button press (too short)");
|
ESP_LOGW("${TAG_CORE_HW_BUTTONS}", "Ignoring button press (too short)");
|
||||||
} else if (press_duration >= ${BUTTON_CLICK_MIN_LENGTH} and
|
} else if (press_duration >= ${BUTTON_CLICK_MIN_LENGTH} and
|
||||||
press_duration <= ${BUTTON_CLICK_MAX_LENGTH}) { // Short/normal click
|
press_duration <= ${BUTTON_CLICK_MAX_LENGTH}) { // Short/normal click
|
||||||
button_click_event->execute(id(button_press_button), id(click_counter));
|
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}) {
|
} else if (press_duration >= ${BUTTON_LONG_PRESS_DELAY} and press_duration <= ${BUTTON_PRESS_TIMEOUT}) {
|
||||||
button_action->execute(id(button_press_button), "long_press", 1);
|
button_action->execute(id(button_press_button), "long_press", 1);
|
||||||
} else if (press_duration > ${BUTTON_PRESS_TIMEOUT}) { // Timeout or invalid
|
} 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");
|
ESP_LOGW("${TAG_CORE_HW_BUTTONS}",
|
||||||
|
"Button press cancelled or timed out after ${BUTTON_PRESS_TIMEOUT} ms");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGW("core_hw_buttons", "Press event timestamp not recorded yet");
|
ESP_LOGW("${TAG_CORE_HW_BUTTONS}", "Press event timestamp not recorded yet");
|
||||||
}
|
}
|
||||||
id(button_press_start_time) = 0;
|
id(button_press_start_time) = 0;
|
||||||
|
|
||||||
@@ -327,11 +351,16 @@ select:
|
|||||||
- "${BUTTON_1_ACTION_FAILSAFE_TEXT}"
|
- "${BUTTON_1_ACTION_FAILSAFE_TEXT}"
|
||||||
initial_option: "${BUTTON_1_ACTION_TEXT}"
|
initial_option: "${BUTTON_1_ACTION_TEXT}"
|
||||||
optimistic: true
|
optimistic: true
|
||||||
restore_value: true
|
restore_value: false
|
||||||
internal: true
|
internal: true
|
||||||
entity_category: config
|
entity_category: config
|
||||||
disabled_by_default: false
|
disabled_by_default: false
|
||||||
icon: mdi:dip-switch
|
icon: mdi:dip-switch
|
||||||
|
on_value:
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
id(button_actions_packed) = (id(button_actions_packed) & ~(0x0F << 0)) |
|
||||||
|
((id(sl_button_1_action).active_index().value_or(1) & 0x0F) << 0);
|
||||||
|
|
||||||
- id: sl_button_2_action
|
- id: sl_button_2_action
|
||||||
name: Button 2 action
|
name: Button 2 action
|
||||||
@@ -342,6 +371,11 @@ select:
|
|||||||
- "${BUTTON_2_ACTION_FAILSAFE_TEXT}"
|
- "${BUTTON_2_ACTION_FAILSAFE_TEXT}"
|
||||||
initial_option: "${BUTTON_2_ACTION_TEXT}"
|
initial_option: "${BUTTON_2_ACTION_TEXT}"
|
||||||
<<: *button_select_action_base
|
<<: *button_select_action_base
|
||||||
|
on_value:
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
id(button_actions_packed) = (id(button_actions_packed) & ~(0x0F << 4)) |
|
||||||
|
((id(sl_button_2_action).active_index().value_or(1) & 0x0F) << 4);
|
||||||
|
|
||||||
- id: sl_button_3_action
|
- id: sl_button_3_action
|
||||||
name: Button 3 action
|
name: Button 3 action
|
||||||
@@ -352,6 +386,11 @@ select:
|
|||||||
- "${BUTTON_3_ACTION_FAILSAFE_TEXT}"
|
- "${BUTTON_3_ACTION_FAILSAFE_TEXT}"
|
||||||
initial_option: "${BUTTON_3_ACTION_TEXT}"
|
initial_option: "${BUTTON_3_ACTION_TEXT}"
|
||||||
<<: *button_select_action_base
|
<<: *button_select_action_base
|
||||||
|
on_value:
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
id(button_actions_packed) = (id(button_actions_packed) & ~(0x0F << 8)) |
|
||||||
|
((id(sl_button_3_action).active_index().value_or(1) & 0x0F) << 8);
|
||||||
|
|
||||||
- id: sl_button_4_action
|
- id: sl_button_4_action
|
||||||
name: Button 4 action
|
name: Button 4 action
|
||||||
@@ -362,4 +401,9 @@ select:
|
|||||||
- "${BUTTON_4_ACTION_FAILSAFE_TEXT}"
|
- "${BUTTON_4_ACTION_FAILSAFE_TEXT}"
|
||||||
initial_option: "${BUTTON_4_ACTION_TEXT}"
|
initial_option: "${BUTTON_4_ACTION_TEXT}"
|
||||||
<<: *button_select_action_base
|
<<: *button_select_action_base
|
||||||
|
on_value:
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
id(button_actions_packed) = (id(button_actions_packed) & ~(0x0F << 12)) |
|
||||||
|
((id(sl_button_4_action).active_index().value_or(1) & 0x0F) << 12);
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -25,9 +25,14 @@ substitutions:
|
|||||||
LIGHT_TRANSITION_TURN_OFF: '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_BRIGHTNESS_TURN_ON: '0' # Brightness (1 to 100%, 0 to not set it)
|
||||||
|
|
||||||
LIGHT_FULL_RESTORE_MODE: RESTORE_DEFAULT_OFF
|
LIGHT_FULL_RESTORE_MODE: ALWAYS_OFF
|
||||||
LIGHT_SIDES_RESTORE_MODE: RESTORE_DEFAULT_OFF
|
LIGHT_SIDES_RESTORE_MODE: ALWAYS_OFF
|
||||||
LIGHT_INDIVIDUAL_RESTORE_MODE: RESTORE_DEFAULT_OFF
|
LIGHT_INDIVIDUAL_RESTORE_MODE: ALWAYS_OFF
|
||||||
|
|
||||||
|
LIGHT_ATTRS_DEFAULT: '0x64FFFFFF' # brightness=100, RGB=255,255,255
|
||||||
|
LIGHT_DUAL_ATTRS_DEFAULT: '0x64FFFFFF64FFFFFF' # Both lights: brightness=100, RGB=255,255,255
|
||||||
|
|
||||||
|
TAG_CORE_HW_LEDS: core.hw.leds
|
||||||
|
|
||||||
esphome:
|
esphome:
|
||||||
platformio_options:
|
platformio_options:
|
||||||
@@ -35,32 +40,61 @@ esphome:
|
|||||||
- -D TX_ULTIMATE_EASY_CORE_HW_LEDS
|
- -D TX_ULTIMATE_EASY_CORE_HW_LEDS
|
||||||
|
|
||||||
globals:
|
globals:
|
||||||
- id: gb_lights_1
|
# light_full with effect support
|
||||||
type: std::vector<light::LightState*>
|
- id: led_full_attrs
|
||||||
restore_value: false
|
type: uint32_t
|
||||||
- id: gb_lights_2
|
restore_value: true
|
||||||
type: std::vector<light::LightState*>
|
initial_value: '${LIGHT_ATTRS_DEFAULT}'
|
||||||
restore_value: false
|
# Basic attributes: brightness + RGB
|
||||||
|
|
||||||
|
# For light_full effects
|
||||||
|
- id: led_full_effect_packed
|
||||||
|
type: uint32_t
|
||||||
|
restore_value: true
|
||||||
|
initial_value: '0x00000000'
|
||||||
|
# Stores: effect_index(16 bits) + effect_speed(8 bits) + reserved(8 bits)
|
||||||
|
# 0 = no effect/solid color, 1-10 = effect indices
|
||||||
|
|
||||||
|
- id: led_main_packed_attrs
|
||||||
|
type: uint64_t
|
||||||
|
restore_value: true
|
||||||
|
initial_value: '${LIGHT_DUAL_ATTRS_DEFAULT}'
|
||||||
|
# light_eu(group1) + light_us(group2) - the main effect lights
|
||||||
|
|
||||||
|
- id: led_main_packed_effect
|
||||||
|
type: uint32_t
|
||||||
|
restore_value: true
|
||||||
|
initial_value: '0x00000000'
|
||||||
|
# Shared between light_eu and light_us
|
||||||
|
|
||||||
|
# Main user-facing LED lights only
|
||||||
|
- id: led_sides_packed_attrs
|
||||||
|
type: uint64_t
|
||||||
|
restore_value: true
|
||||||
|
initial_value: '${LIGHT_DUAL_ATTRS_DEFAULT}'
|
||||||
|
# EU: bottom(group1) + top(group2) OR US: left(group1) + right(group2)
|
||||||
|
|
||||||
light:
|
light:
|
||||||
# These lights are controlling the LEDs on the device
|
# These lights are controlling the LEDs on the device
|
||||||
- id: light_full
|
- id: light_full
|
||||||
name: Light - All
|
name: Light - All
|
||||||
internal: true
|
internal: true
|
||||||
platform: esp32_rmt_led_strip
|
|
||||||
rgb_order: GRB
|
|
||||||
rmt_channel: 1
|
|
||||||
chipset: ws2812
|
|
||||||
num_leds: 32
|
num_leds: 32
|
||||||
pin: GPIO13
|
pin: GPIO13
|
||||||
restore_mode: ${LIGHT_FULL_RESTORE_MODE}
|
restore_mode: ${LIGHT_FULL_RESTORE_MODE}
|
||||||
|
platform: esp32_rmt_led_strip
|
||||||
|
rgb_order: GRB
|
||||||
|
chipset: ws2812
|
||||||
max_refresh_rate: 33ms
|
max_refresh_rate: 33ms
|
||||||
use_psram: true
|
use_psram: false
|
||||||
|
# platform: neopixelbus
|
||||||
|
# type: GRB
|
||||||
|
# variant: WS2811
|
||||||
|
|
||||||
# Those lights are available based on the model selections
|
# Those lights are available based on the model selections
|
||||||
- &light_partition_with_effects
|
- &light_partition_with_effects_eu
|
||||||
id: light_eu
|
id: light_eu
|
||||||
name: Light
|
name: Light EU
|
||||||
platform: partition
|
platform: partition
|
||||||
default_transition_length: ${default_transition_length}
|
default_transition_length: ${default_transition_length}
|
||||||
internal: true
|
internal: true
|
||||||
@@ -68,8 +102,76 @@ light:
|
|||||||
effects:
|
effects:
|
||||||
- addressable_rainbow:
|
- addressable_rainbow:
|
||||||
name: "Rainbow"
|
name: "Rainbow"
|
||||||
|
width: 28
|
||||||
- addressable_rainbow:
|
- addressable_rainbow:
|
||||||
name: "Rainbow - Fast"
|
name: "Rainbow - Fast"
|
||||||
|
width: 28
|
||||||
|
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%
|
||||||
|
- addressable_nachtlicht:
|
||||||
|
name: "Nachtlicht"
|
||||||
|
intensity: 25%
|
||||||
|
- random:
|
||||||
|
name: "Random"
|
||||||
|
segments:
|
||||||
|
- id: light_full
|
||||||
|
from: 0
|
||||||
|
to: 27
|
||||||
|
on_state:
|
||||||
|
then:
|
||||||
|
- script.execute:
|
||||||
|
id: light_attributes_save_dual
|
||||||
|
light_ptr: !lambda return id(light_eu);
|
||||||
|
attr_global_ptr: !lambda return &id(led_main_packed_attrs);
|
||||||
|
group_index: 1
|
||||||
|
- script.execute:
|
||||||
|
id: light_effect_save
|
||||||
|
light_ptr: !lambda return id(light_eu);
|
||||||
|
effect_global_ptr: !lambda return &id(led_main_packed_effect);
|
||||||
|
|
||||||
|
- &light_partition_with_effects_us
|
||||||
|
id: light_us
|
||||||
|
name: Light US
|
||||||
|
platform: partition
|
||||||
|
default_transition_length: ${default_transition_length}
|
||||||
|
internal: true
|
||||||
|
restore_mode: ${LIGHT_SIDES_RESTORE_MODE}
|
||||||
|
effects:
|
||||||
|
- addressable_rainbow:
|
||||||
|
name: "Rainbow"
|
||||||
|
width: 32
|
||||||
|
- addressable_rainbow:
|
||||||
|
name: "Rainbow - Fast"
|
||||||
|
width: 32
|
||||||
speed: 50
|
speed: 50
|
||||||
- pulse:
|
- pulse:
|
||||||
name: "Pulse"
|
name: "Pulse"
|
||||||
@@ -103,40 +205,59 @@ light:
|
|||||||
intensity: 5%
|
intensity: 5%
|
||||||
- random:
|
- random:
|
||||||
name: "Random"
|
name: "Random"
|
||||||
segments:
|
|
||||||
- id: light_full
|
|
||||||
from: 0
|
|
||||||
to: 27
|
|
||||||
|
|
||||||
- id: light_us
|
|
||||||
name: Light
|
|
||||||
<<: *light_partition_with_effects
|
|
||||||
segments:
|
segments:
|
||||||
- id: light_full
|
- id: light_full
|
||||||
from: 0
|
from: 0
|
||||||
to: 31
|
to: 31
|
||||||
|
on_state:
|
||||||
|
then:
|
||||||
|
- script.execute:
|
||||||
|
id: light_attributes_save_dual
|
||||||
|
light_ptr: !lambda return id(light_us);
|
||||||
|
attr_global_ptr: !lambda return &id(led_main_packed_attrs);
|
||||||
|
group_index: 2
|
||||||
|
- script.execute:
|
||||||
|
id: light_effect_save
|
||||||
|
light_ptr: !lambda return id(light_us);
|
||||||
|
effect_global_ptr: !lambda return &id(led_main_packed_effect);
|
||||||
|
|
||||||
- &light_partition_with_effects_disabled
|
- &light_partition_no_effects_disabled
|
||||||
id: light_eu_bottom
|
id: light_eu_bottom
|
||||||
name: Light - Bottom
|
name: Light - Bottom EU
|
||||||
|
platform: partition
|
||||||
disabled_by_default: true
|
disabled_by_default: true
|
||||||
<<: *light_partition_with_effects
|
default_transition_length: ${default_transition_length}
|
||||||
|
restore_mode: ${LIGHT_SIDES_RESTORE_MODE}
|
||||||
|
internal: true
|
||||||
segments:
|
segments:
|
||||||
- id: light_full
|
- id: light_full
|
||||||
from: 6
|
from: 6
|
||||||
to: 12
|
to: 12
|
||||||
reversed: true
|
reversed: true
|
||||||
|
on_state:
|
||||||
|
- script.execute:
|
||||||
|
id: light_attributes_save_dual
|
||||||
|
light_ptr: !lambda return id(light_eu_bottom);
|
||||||
|
attr_global_ptr: !lambda return &id(led_sides_packed_attrs);
|
||||||
|
group_index: 1
|
||||||
|
|
||||||
- id: light_eu_left
|
- id: light_eu_left
|
||||||
name: Light - Left
|
name: Light - Left EU
|
||||||
<<: *light_partition_with_effects_disabled
|
<<: *light_partition_no_effects_disabled
|
||||||
segments:
|
segments:
|
||||||
- id: light_full
|
- id: light_full
|
||||||
from: 13
|
from: 13
|
||||||
to: 19
|
to: 19
|
||||||
reversed: true
|
reversed: true
|
||||||
|
on_state:
|
||||||
|
- script.execute:
|
||||||
|
id: light_attributes_save_dual
|
||||||
|
light_ptr: !lambda return id(light_eu_left);
|
||||||
|
attr_global_ptr: !lambda return &id(led_sides_packed_attrs);
|
||||||
|
group_index: 1
|
||||||
- id: light_eu_right
|
- id: light_eu_right
|
||||||
name: Light - Right
|
name: Light - Right EU
|
||||||
<<: *light_partition_with_effects_disabled
|
<<: *light_partition_no_effects_disabled
|
||||||
segments:
|
segments:
|
||||||
- id: light_full
|
- id: light_full
|
||||||
from: 27
|
from: 27
|
||||||
@@ -146,33 +267,57 @@ light:
|
|||||||
from: 0
|
from: 0
|
||||||
to: 5
|
to: 5
|
||||||
reversed: false
|
reversed: false
|
||||||
|
on_state:
|
||||||
|
- script.execute:
|
||||||
|
id: light_attributes_save_dual
|
||||||
|
light_ptr: !lambda return id(light_eu_right);
|
||||||
|
attr_global_ptr: !lambda return &id(led_sides_packed_attrs);
|
||||||
|
group_index: 2
|
||||||
- id: light_eu_top
|
- id: light_eu_top
|
||||||
name: Light - Top
|
name: Light - Top EU
|
||||||
<<: *light_partition_with_effects_disabled
|
<<: *light_partition_no_effects_disabled
|
||||||
segments:
|
segments:
|
||||||
- id: light_full
|
- id: light_full
|
||||||
from: 20
|
from: 20
|
||||||
to: 26
|
to: 26
|
||||||
reversed: false
|
reversed: false
|
||||||
|
on_state:
|
||||||
|
- script.execute:
|
||||||
|
id: light_attributes_save_dual
|
||||||
|
light_ptr: !lambda return id(light_eu_top);
|
||||||
|
attr_global_ptr: !lambda return &id(led_sides_packed_attrs);
|
||||||
|
group_index: 2
|
||||||
- id: light_us_bottom
|
- id: light_us_bottom
|
||||||
name: Light - Bottom
|
name: Light - Bottom US
|
||||||
<<: *light_partition_with_effects_disabled
|
<<: *light_partition_no_effects_disabled
|
||||||
segments:
|
segments:
|
||||||
- id: light_full
|
- id: light_full
|
||||||
from: 9
|
from: 9
|
||||||
to: 14
|
to: 14
|
||||||
reversed: true
|
reversed: true
|
||||||
|
on_state:
|
||||||
|
- script.execute:
|
||||||
|
id: light_attributes_save_dual
|
||||||
|
light_ptr: !lambda return id(light_us_bottom);
|
||||||
|
attr_global_ptr: !lambda return &id(led_sides_packed_attrs);
|
||||||
|
group_index: 1
|
||||||
- id: light_us_left
|
- id: light_us_left
|
||||||
name: Light - Left
|
name: Light - Left US
|
||||||
<<: *light_partition_with_effects_disabled
|
<<: *light_partition_no_effects_disabled
|
||||||
segments:
|
segments:
|
||||||
- id: light_full
|
- id: light_full
|
||||||
from: 15
|
from: 15
|
||||||
to: 24
|
to: 24
|
||||||
reversed: true
|
reversed: true
|
||||||
|
on_state:
|
||||||
|
- script.execute:
|
||||||
|
id: light_attributes_save_dual
|
||||||
|
light_ptr: !lambda return id(light_us_left);
|
||||||
|
attr_global_ptr: !lambda return &id(led_sides_packed_attrs);
|
||||||
|
group_index: 1
|
||||||
- id: light_us_right
|
- id: light_us_right
|
||||||
name: Light - Right
|
name: Light - Right US
|
||||||
<<: *light_partition_with_effects_disabled
|
<<: *light_partition_no_effects_disabled
|
||||||
segments:
|
segments:
|
||||||
- id: light_full
|
- id: light_full
|
||||||
from: 31
|
from: 31
|
||||||
@@ -182,14 +327,26 @@ light:
|
|||||||
from: 0
|
from: 0
|
||||||
to: 8
|
to: 8
|
||||||
reversed: false
|
reversed: false
|
||||||
|
on_state:
|
||||||
|
- script.execute:
|
||||||
|
id: light_attributes_save_dual
|
||||||
|
light_ptr: !lambda return id(light_us_right);
|
||||||
|
attr_global_ptr: !lambda return &id(led_sides_packed_attrs);
|
||||||
|
group_index: 2
|
||||||
- id: light_us_top
|
- id: light_us_top
|
||||||
name: Light - Top
|
name: Light - Top US
|
||||||
<<: *light_partition_with_effects_disabled
|
<<: *light_partition_no_effects_disabled
|
||||||
segments:
|
segments:
|
||||||
- id: light_full
|
- id: light_full
|
||||||
from: 25
|
from: 25
|
||||||
to: 30
|
to: 30
|
||||||
reversed: false
|
reversed: false
|
||||||
|
on_state:
|
||||||
|
- script.execute:
|
||||||
|
id: light_attributes_save_dual
|
||||||
|
light_ptr: !lambda return id(light_us_top);
|
||||||
|
attr_global_ptr: !lambda return &id(led_sides_packed_attrs);
|
||||||
|
group_index: 2
|
||||||
|
|
||||||
- &light_partition_individual_led
|
- &light_partition_individual_led
|
||||||
id: light_00
|
id: light_00
|
||||||
@@ -446,178 +603,246 @@ script:
|
|||||||
- id: !extend dump_config
|
- id: !extend dump_config
|
||||||
then:
|
then:
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
// Relay's LEDs modes
|
|
||||||
ESP_LOGCONFIG("core_hw_leds", "Relay%s LEDs mode%s:",
|
|
||||||
id(gang_count_plural_suffix).c_str(),
|
|
||||||
id(gang_count_plural_suffix).c_str());
|
|
||||||
ESP_LOGCONFIG("core_hw_leds", " Relay 1: %s", id(is_us_model)
|
|
||||||
? sl_relay_1_light_mode_us->state.c_str()
|
|
||||||
: sl_relay_1_light_mode_eu->state.c_str());
|
|
||||||
if (id(gang_count) >= 2)
|
|
||||||
ESP_LOGCONFIG("core_hw_leds", " Relay 2: %s", id(is_us_model)
|
|
||||||
? sl_relay_2_light_mode_us->state.c_str()
|
|
||||||
: sl_relay_2_light_mode_eu->state.c_str());
|
|
||||||
if (id(gang_count) >= 3)
|
|
||||||
ESP_LOGCONFIG("core_hw_leds", " Relay 3: %s", id(is_us_model)
|
|
||||||
? sl_relay_3_light_mode_us->state.c_str()
|
|
||||||
: sl_relay_3_light_mode_eu->state.c_str());
|
|
||||||
if (id(gang_count) >= 4)
|
|
||||||
ESP_LOGCONFIG("core_hw_leds", " Relay 4: %s", id(is_us_model)
|
|
||||||
? sl_relay_4_light_mode_us->state.c_str()
|
|
||||||
: sl_relay_4_light_mode_eu->state.c_str());
|
|
||||||
|
|
||||||
// Transition times
|
// Transition times
|
||||||
ESP_LOGCONFIG("core_hw_leds", "Transition times:");
|
ESP_LOGCONFIG("${TAG_CORE_HW_LEDS}", "Transition times:");
|
||||||
ESP_LOGCONFIG("core_hw_leds", " Default: ${default_transition_length}");
|
ESP_LOGCONFIG("${TAG_CORE_HW_LEDS}", " Default: ${default_transition_length}");
|
||||||
if (${LIGHT_TRANSITION_TURN_ON} > 0)
|
if (${LIGHT_TRANSITION_TURN_ON} > 0)
|
||||||
ESP_LOGCONFIG("core_hw_leds", " Turning on: ${LIGHT_TRANSITION_TURN_ON}ms");
|
ESP_LOGCONFIG("${TAG_CORE_HW_LEDS}", " Turning on: ${LIGHT_TRANSITION_TURN_ON}ms");
|
||||||
else
|
else
|
||||||
ESP_LOGCONFIG("core_hw_leds", " Turning on: Disabled");
|
ESP_LOGCONFIG("${TAG_CORE_HW_LEDS}", " Turning on: Disabled");
|
||||||
if (${LIGHT_TRANSITION_TURN_OFF} > 0)
|
if (${LIGHT_TRANSITION_TURN_OFF} > 0)
|
||||||
ESP_LOGCONFIG("core_hw_leds", " Turning off: ${LIGHT_TRANSITION_TURN_OFF}ms");
|
ESP_LOGCONFIG("${TAG_CORE_HW_LEDS}", " Turning off: ${LIGHT_TRANSITION_TURN_OFF}ms");
|
||||||
else
|
else
|
||||||
ESP_LOGCONFIG("core_hw_leds", " Turning off: Disabled");
|
ESP_LOGCONFIG("${TAG_CORE_HW_LEDS}", " Turning off: Disabled");
|
||||||
|
|
||||||
// Restore modes
|
// Restore modes
|
||||||
ESP_LOGCONFIG("core_hw_leds", "LED restore modes:");
|
ESP_LOGCONFIG("${TAG_CORE_HW_LEDS}", "LED restore modes:");
|
||||||
ESP_LOGCONFIG("core_hw_leds", " Light - All: ${LIGHT_FULL_RESTORE_MODE}");
|
ESP_LOGCONFIG("${TAG_CORE_HW_LEDS}", " Light - All: ${LIGHT_FULL_RESTORE_MODE}");
|
||||||
ESP_LOGCONFIG("core_hw_leds", " Sides: ${LIGHT_SIDES_RESTORE_MODE}");
|
ESP_LOGCONFIG("${TAG_CORE_HW_LEDS}", " Sides: ${LIGHT_SIDES_RESTORE_MODE}");
|
||||||
ESP_LOGCONFIG("core_hw_leds", " Individual: ${LIGHT_INDIVIDUAL_RESTORE_MODE}");
|
ESP_LOGCONFIG("${TAG_CORE_HW_LEDS}", " Individual: ${LIGHT_INDIVIDUAL_RESTORE_MODE}");
|
||||||
|
|
||||||
- id: !extend dump_config_list_packages
|
- id: !extend dump_config_list_packages
|
||||||
then:
|
then:
|
||||||
- script.wait: dump_config
|
- script.wait: dump_config
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
// Check for requirements
|
// Check for requirements
|
||||||
#if !defined(TX_ULTIMATE_EASY_CORE)
|
#if !defined(TX_ULTIMATE_EASY_CORE_COMMON)
|
||||||
#error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required."
|
#error "The package TX-Ultimate-Easy-ESPHome_core_common.yaml is required."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Identify itself
|
// Identify itself
|
||||||
ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Core - Hardware - LEDs");
|
ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Core - Hardware - LEDs");
|
||||||
|
|
||||||
- id: light_set_state
|
- id: light_attributes_restore
|
||||||
mode: parallel
|
mode: parallel
|
||||||
parameters:
|
parameters:
|
||||||
light_group: uint8_t
|
light_ptr: light::LightState*
|
||||||
light_index: uint8_t
|
attr_global_ptr: uint32_t*
|
||||||
state: bool
|
|
||||||
then:
|
then:
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
static const uint32_t LIGHT_TRANSITION_TURN_ON = ${LIGHT_TRANSITION_TURN_ON};
|
if (!light_ptr) {
|
||||||
static const uint32_t LIGHT_TRANSITION_TURN_OFF = ${LIGHT_TRANSITION_TURN_OFF};
|
ESP_LOGE("${TAG_CORE_HW_LEDS}", "Invalid light pointer");
|
||||||
static const uint8_t LIGHT_BRIGHTNESS_TURN_ON = ${LIGHT_BRIGHTNESS_TURN_ON};
|
return;
|
||||||
|
}
|
||||||
|
if (!attr_global_ptr) {
|
||||||
|
ESP_LOGE("${TAG_CORE_HW_LEDS}", "Invalid attributes pointer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tx_ultimate_easy::LightAttributes attrs = tx_ultimate_easy::unpack_light_attributes(*attr_global_ptr);
|
||||||
|
auto call = light_ptr->make_call();
|
||||||
|
call.set_brightness(attrs.brightness / 100.0f);
|
||||||
|
call.set_rgb(attrs.red / 255.0f, attrs.green / 255.0f, attrs.blue / 255.0f);
|
||||||
|
call.perform();
|
||||||
|
ESP_LOGI("${TAG_CORE_HW_LEDS}", "Restored light attributes: brightness=%d%%, RGB=(%d,%d,%d)",
|
||||||
|
attrs.brightness, attrs.red, attrs.green, attrs.blue);
|
||||||
|
|
||||||
const std::string light_mode_group_1 = id(is_us_model)
|
- id: light_attributes_restore_dual
|
||||||
? "${LIGHT_MODE_LEFT_TEXT}"
|
mode: parallel
|
||||||
: "${LIGHT_MODE_BOTTOM_TEXT}";
|
parameters:
|
||||||
const std::string light_mode_group_2 = id(is_us_model)
|
light_ptr: light::LightState*
|
||||||
? "${LIGHT_MODE_RIGHT_TEXT}"
|
attr_global_ptr: uint64_t*
|
||||||
: "${LIGHT_MODE_TOP_TEXT}";
|
group_index: uint8_t # 1 or 2
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
if (!light_ptr) {
|
||||||
|
ESP_LOGE("${TAG_CORE_HW_LEDS}", "Invalid light pointer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!attr_global_ptr) {
|
||||||
|
ESP_LOGE("${TAG_CORE_HW_LEDS}", "Invalid attributes pointer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (group_index != 1 && group_index != 2) {
|
||||||
|
ESP_LOGE("${TAG_CORE_HW_LEDS}", "Invalid group_index=%d (expected 1 or 2)", group_index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto attrs_pair = tx_ultimate_easy::unpack_dual_light_attributes(*attr_global_ptr);
|
||||||
|
tx_ultimate_easy::LightAttributes attrs = (group_index == 1) ? attrs_pair.first : attrs_pair.second;
|
||||||
|
|
||||||
switch (light_group) {
|
auto call = light_ptr->make_call();
|
||||||
case 1:
|
call.set_brightness(attrs.brightness / 100.0f);
|
||||||
if (light_index >= id(gb_lights_1).size()) {
|
call.set_rgb(attrs.red / 255.0f, attrs.green / 255.0f, attrs.blue / 255.0f);
|
||||||
ESP_LOGE("core_hw_leds", "Invalid set with %s light for Relay %" PRIu8,
|
call.perform();
|
||||||
light_mode_group_1.c_str(), light_index+1);
|
ESP_LOGI("${TAG_CORE_HW_LEDS}", "Restored (group=%d) attributes: brightness=%d%%, RGB=(%d,%d,%d)",
|
||||||
return;
|
group_index, attrs.brightness, attrs.red, attrs.green, attrs.blue);
|
||||||
}
|
|
||||||
if (state and !id(gb_lights_1)[light_index]->current_values.is_on()) {
|
- id: light_attributes_save
|
||||||
ESP_LOGI("core_hw_leds", "Turn-on %s light for Relay %" PRIu8,
|
mode: parallel
|
||||||
light_mode_group_1.c_str(), light_index+1);
|
parameters:
|
||||||
auto call = id(gb_lights_1)[light_index]->turn_on();
|
light_ptr: light::LightState*
|
||||||
if (LIGHT_TRANSITION_TURN_ON > 0)
|
attr_global_ptr: uint32_t*
|
||||||
call.set_transition_length(LIGHT_TRANSITION_TURN_ON); // in ms
|
then:
|
||||||
if (LIGHT_BRIGHTNESS_TURN_ON > 0 and LIGHT_BRIGHTNESS_TURN_ON <= 100)
|
- lambda: |-
|
||||||
call.set_brightness(LIGHT_BRIGHTNESS_TURN_ON / 100.0f);
|
if (!light_ptr) {
|
||||||
call.perform();
|
ESP_LOGE("${TAG_CORE_HW_LEDS}", "Invalid light pointer");
|
||||||
} else if (!state and id(gb_lights_1)[light_index]->current_values.is_on()) {
|
return;
|
||||||
ESP_LOGI("core_hw_leds", "Turn-off %s light for Relay %" PRIu8,
|
}
|
||||||
light_mode_group_1.c_str(), light_index+1);
|
if (!attr_global_ptr) {
|
||||||
auto call = id(gb_lights_1)[light_index]->turn_off();
|
ESP_LOGE("${TAG_CORE_HW_LEDS}", "Invalid attributes pointer");
|
||||||
if (LIGHT_TRANSITION_TURN_OFF > 0)
|
return;
|
||||||
call.set_transition_length(LIGHT_TRANSITION_TURN_OFF); // in ms
|
}
|
||||||
call.perform();
|
auto current = light_ptr->current_values;
|
||||||
}
|
tx_ultimate_easy::LightAttributes attrs = {
|
||||||
break;
|
.brightness = uint8_t(current.get_brightness() * 100.0f),
|
||||||
case 2:
|
.red = uint8_t(current.get_red() * 255.0f),
|
||||||
if (light_index >= id(gb_lights_2).size()) {
|
.green = uint8_t(current.get_green() * 255.0f),
|
||||||
ESP_LOGE("core_hw_leds", "Invalid set with %s light for Relay %" PRIu8,
|
.blue = uint8_t(current.get_blue() * 255.0f)
|
||||||
light_mode_group_2.c_str(), light_index+1);
|
};
|
||||||
return;
|
|
||||||
}
|
*attr_global_ptr = tx_ultimate_easy::pack_light_attributes(attrs);
|
||||||
if (state and !id(gb_lights_2)[light_index]->current_values.is_on()) {
|
ESP_LOGD("${TAG_CORE_HW_LEDS}", "Saved light attributes: brightness=%d%%, RGB=(%d,%d,%d)",
|
||||||
ESP_LOGI("core_hw_leds", "Turn-on %s light for Relay %" PRIu8,
|
attrs.brightness, attrs.red, attrs.green, attrs.blue);
|
||||||
light_mode_group_2.c_str(), light_index+1);
|
|
||||||
auto call = id(gb_lights_2)[light_index]->turn_on();
|
- id: light_attributes_save_dual
|
||||||
if (LIGHT_TRANSITION_TURN_ON > 0)
|
mode: queued # To prevent two instances trying to change the same global
|
||||||
call.set_transition_length(LIGHT_TRANSITION_TURN_ON); // in ms
|
parameters:
|
||||||
if (LIGHT_BRIGHTNESS_TURN_ON > 0 and LIGHT_BRIGHTNESS_TURN_ON <= 100)
|
light_ptr: light::LightState*
|
||||||
call.set_brightness(LIGHT_BRIGHTNESS_TURN_ON / 100.0f);
|
attr_global_ptr: uint64_t*
|
||||||
call.perform();
|
group_index: uint8_t # 1 or 2 (which group within the dual pack)
|
||||||
} else if (!state and id(gb_lights_2)[light_index]->current_values.is_on()) {
|
then:
|
||||||
ESP_LOGI("core_hw_leds", "Turn-off %s light for Relay %" PRIu8,
|
- lambda: |-
|
||||||
light_mode_group_2.c_str(), light_index+1);
|
if (!light_ptr) {
|
||||||
auto call = id(gb_lights_2)[light_index]->turn_off();
|
ESP_LOGE("${TAG_CORE_HW_LEDS}", "Invalid light pointer");
|
||||||
if (LIGHT_TRANSITION_TURN_OFF > 0)
|
return;
|
||||||
call.set_transition_length(LIGHT_TRANSITION_TURN_OFF); // in ms
|
}
|
||||||
call.perform();
|
if (!attr_global_ptr) {
|
||||||
}
|
ESP_LOGE("${TAG_CORE_HW_LEDS}", "Invalid attributes pointer");
|
||||||
break;
|
return;
|
||||||
|
}
|
||||||
|
if (group_index != 1 && group_index != 2) {
|
||||||
|
ESP_LOGE("${TAG_CORE_HW_LEDS}", "Invalid group_index=%d (expected 1 or 2)", group_index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto current = light_ptr->current_values;
|
||||||
|
tx_ultimate_easy::LightAttributes new_attrs = {
|
||||||
|
.brightness = uint8_t(current.get_brightness() * 100.0f),
|
||||||
|
.red = uint8_t(current.get_red() * 255.0f),
|
||||||
|
.green = uint8_t(current.get_green() * 255.0f),
|
||||||
|
.blue = uint8_t(current.get_blue() * 255.0f)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Unpack existing dual attributes
|
||||||
|
auto existing = tx_ultimate_easy::unpack_dual_light_attributes(*attr_global_ptr);
|
||||||
|
|
||||||
|
// Update the appropriate group
|
||||||
|
if (group_index == 1) {
|
||||||
|
*attr_global_ptr = tx_ultimate_easy::pack_dual_light_attributes(new_attrs, existing.second);
|
||||||
|
} else {
|
||||||
|
*attr_global_ptr = tx_ultimate_easy::pack_dual_light_attributes(existing.first, new_attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
select:
|
- id: light_effect_save
|
||||||
# EU relay light mode template
|
mode: queued
|
||||||
- &relay_light_mode_eu
|
parameters:
|
||||||
id: sl_relay_1_light_mode_eu
|
light_ptr: light::LightState*
|
||||||
name: Relay 1 light mode
|
effect_global_ptr: uint32_t*
|
||||||
platform: template
|
then:
|
||||||
options:
|
- lambda: |-
|
||||||
- "${LIGHT_MODE_DISABLED_TEXT}"
|
if (!light_ptr || !effect_global_ptr) return;
|
||||||
- "${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
|
uint32_t effect_index = light_ptr->get_current_effect_index();
|
||||||
- &relay_light_mode_us
|
// Store effect index (16 bits) + reserved space for future use
|
||||||
id: sl_relay_1_light_mode_us
|
*effect_global_ptr = effect_index & 0xFFFF;
|
||||||
name: Relay 1 light mode
|
|
||||||
platform: template
|
ESP_LOGD("${TAG_CORE_HW_LEDS}", "Saved effect index: %d", effect_index);
|
||||||
options:
|
|
||||||
- "${LIGHT_MODE_DISABLED_TEXT}"
|
- id: light_effect_restore
|
||||||
- "${LIGHT_MODE_LEFT_TEXT}"
|
mode: parallel
|
||||||
- "${LIGHT_MODE_RIGHT_TEXT}"
|
parameters:
|
||||||
- "${LIGHT_MODE_BOTH_TEXT}"
|
light_ptr: light::LightState*
|
||||||
initial_option: "${LIGHT_MODE_RIGHT_TEXT}"
|
effect_global_ptr: uint32_t*
|
||||||
optimistic: true
|
then:
|
||||||
restore_value: true
|
- lambda: |-
|
||||||
internal: true
|
if (!light_ptr || !effect_global_ptr) return;
|
||||||
entity_category: config
|
|
||||||
disabled_by_default: false
|
uint32_t effect_index = *effect_global_ptr & 0xFFFF;
|
||||||
icon: mdi:dots-square
|
|
||||||
- id: sl_relay_2_light_mode_us
|
if (effect_index == 0) return; // No effect
|
||||||
name: Relay 2 light mode
|
if (effect_index > light_ptr->get_effect_count()) {
|
||||||
<<: *relay_light_mode_us
|
ESP_LOGW("${TAG_CORE_HW_LEDS}", "Invalid effect index: %d (max: %d)",
|
||||||
- id: sl_relay_3_light_mode_us
|
effect_index, light_ptr->get_effect_count());
|
||||||
name: Relay 3 light mode
|
return;
|
||||||
<<: *relay_light_mode_us
|
}
|
||||||
- id: sl_relay_4_light_mode_us
|
|
||||||
name: Relay 4 light mode
|
auto call = light_ptr->make_call();
|
||||||
<<: *relay_light_mode_us
|
call.set_effect(effect_index);
|
||||||
|
call.perform();
|
||||||
|
|
||||||
|
ESP_LOGI("${TAG_CORE_HW_LEDS}", "Restored effect: %s (index=%d)",
|
||||||
|
light_ptr->get_effect_name_by_index(effect_index).c_str(), effect_index);
|
||||||
|
|
||||||
|
- id: !extend restore_from_nvs
|
||||||
|
then:
|
||||||
|
# LED restoration
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
lambda: return id(is_us_model);
|
||||||
|
then:
|
||||||
|
# US model restoration
|
||||||
|
- script.execute:
|
||||||
|
id: light_attributes_restore_dual
|
||||||
|
light_ptr: !lambda return id(light_us);
|
||||||
|
attr_global_ptr: !lambda return &id(led_main_packed_attrs);
|
||||||
|
group_index: 2
|
||||||
|
- script.execute:
|
||||||
|
id: light_effect_restore
|
||||||
|
light_ptr: !lambda return id(light_us);
|
||||||
|
effect_global_ptr: !lambda return &id(led_main_packed_effect);
|
||||||
|
- script.execute:
|
||||||
|
id: light_attributes_restore_dual
|
||||||
|
light_ptr: !lambda return id(light_us_left);
|
||||||
|
attr_global_ptr: !lambda return &id(led_sides_packed_attrs);
|
||||||
|
group_index: 1
|
||||||
|
- script.execute:
|
||||||
|
id: light_attributes_restore_dual
|
||||||
|
light_ptr: !lambda return id(light_us_right);
|
||||||
|
attr_global_ptr: !lambda return &id(led_sides_packed_attrs);
|
||||||
|
group_index: 2
|
||||||
|
else:
|
||||||
|
# EU model restoration
|
||||||
|
- script.execute:
|
||||||
|
id: light_attributes_restore_dual
|
||||||
|
light_ptr: !lambda return id(light_eu);
|
||||||
|
attr_global_ptr: !lambda return &id(led_main_packed_attrs);
|
||||||
|
group_index: 1
|
||||||
|
- script.execute:
|
||||||
|
id: light_effect_restore
|
||||||
|
light_ptr: !lambda return id(light_eu);
|
||||||
|
effect_global_ptr: !lambda return &id(led_main_packed_effect);
|
||||||
|
- script.execute:
|
||||||
|
id: light_attributes_restore_dual
|
||||||
|
light_ptr: !lambda return id(light_eu_bottom);
|
||||||
|
attr_global_ptr: !lambda return &id(led_sides_packed_attrs);
|
||||||
|
group_index: 1
|
||||||
|
- script.execute:
|
||||||
|
id: light_attributes_restore_dual
|
||||||
|
light_ptr: !lambda return id(light_eu_top);
|
||||||
|
attr_global_ptr: !lambda return &id(led_sides_packed_attrs);
|
||||||
|
group_index: 2
|
||||||
|
|
||||||
|
# Light full restoration
|
||||||
|
- script.execute:
|
||||||
|
id: light_attributes_restore
|
||||||
|
light_ptr: !lambda return id(light_full);
|
||||||
|
attr_global_ptr: !lambda return &id(led_full_attrs);
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
TOUCH_POSITION_MAX_VALUE: '10' # Maximum touch position value returned by the touch pad via uart
|
TOUCH_POSITION_MAX_VALUE: '10' # Maximum touch position value returned by the touch pad via uart
|
||||||
|
|
||||||
|
TAG_CORE_HW_TOUCH: core.hw.touch
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- &bs_button_event_template
|
- &bs_button_event_template
|
||||||
id: bs_button_event_template
|
id: bs_button_event_template
|
||||||
@@ -203,15 +205,6 @@ esphome:
|
|||||||
build_flags:
|
build_flags:
|
||||||
- -D TX_ULTIMATE_EASY_CORE_HW_TOUCH
|
- -D TX_ULTIMATE_EASY_CORE_HW_TOUCH
|
||||||
|
|
||||||
external_components:
|
|
||||||
- source:
|
|
||||||
type: git
|
|
||||||
url: https://github.com/edwardtfn/TX-Ultimate-Easy
|
|
||||||
ref: v${version}
|
|
||||||
refresh: 1h
|
|
||||||
components:
|
|
||||||
- tx_ultimate_easy
|
|
||||||
|
|
||||||
number:
|
number:
|
||||||
- id: nr_touch_duration
|
- id: nr_touch_duration
|
||||||
name: Touch event duration
|
name: Touch event duration
|
||||||
@@ -293,18 +286,18 @@ script:
|
|||||||
- lambda: |-
|
- lambda: |-
|
||||||
// Touch panel's state
|
// Touch panel's state
|
||||||
if (sw_touch_panel_power->state)
|
if (sw_touch_panel_power->state)
|
||||||
ESP_LOGCONFIG("core_hw_touch", "Touch panel - Power: On");
|
ESP_LOGCONFIG("${TAG_CORE_HW_TOUCH}", "Touch panel - Power: On");
|
||||||
else
|
else
|
||||||
ESP_LOGW("core_hw_touch", "Touch panel - Power: OFF");
|
ESP_LOGW("${TAG_CORE_HW_TOUCH}", "Touch panel - Power: OFF");
|
||||||
ESP_LOGCONFIG("core_hw_touch", "Touch event duration: %.0fms", nr_touch_duration->state);
|
ESP_LOGCONFIG("${TAG_CORE_HW_TOUCH}", "Touch event duration: %.0fms", nr_touch_duration->state);
|
||||||
|
|
||||||
- id: !extend dump_config_list_packages
|
- id: !extend dump_config_list_packages
|
||||||
then:
|
then:
|
||||||
- script.wait: dump_config
|
- script.wait: dump_config
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
// Check for requirements
|
// Check for requirements
|
||||||
#if !defined(TX_ULTIMATE_EASY_CORE)
|
#if !defined(TX_ULTIMATE_EASY_CORE_COMMON)
|
||||||
#error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required."
|
#error "The package TX-Ultimate-Easy-ESPHome_core_common.yaml is required."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Identify itself
|
// Identify itself
|
||||||
@@ -318,7 +311,7 @@ script:
|
|||||||
# - HW Vibration
|
# - HW Vibration
|
||||||
- binary_sensor.template.publish:
|
- binary_sensor.template.publish:
|
||||||
id: bs_multi_touch
|
id: bs_multi_touch
|
||||||
state: OFF # yamllint disable-line rule:truthy
|
state: ON # yamllint disable-line rule:truthy
|
||||||
|
|
||||||
- id: touch_on_press
|
- id: touch_on_press
|
||||||
mode: restart
|
mode: restart
|
||||||
@@ -373,88 +366,104 @@ switch:
|
|||||||
entity_category: config
|
entity_category: config
|
||||||
|
|
||||||
tx_ultimate_easy:
|
tx_ultimate_easy:
|
||||||
id: tx_ultimate
|
|
||||||
uart: uart_touch
|
uart: uart_touch
|
||||||
|
|
||||||
on_long_touch_release:
|
on_long_touch_release:
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
const uint8_t touch_position = 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
|
if (touch_position > ${TOUCH_POSITION_MAX_VALUE}) { // Check for valid range
|
||||||
ESP_LOGE("core_hw_touch", "Invalid long-touch position: %" PRIu8, touch_position);
|
ESP_LOGE("${TAG_CORE_HW_TOUCH}", "Invalid long-touch position: %" PRIu8, touch_position);
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGI("core_hw_touch", "Long-touch released at position %" PRIu8, touch_position);
|
ESP_LOGI("${TAG_CORE_HW_TOUCH}", "Long-touch released at position %" PRIu8, touch_position);
|
||||||
}
|
}
|
||||||
|
|
||||||
on_multi_touch_release:
|
on_multi_touch_release:
|
||||||
- homeassistant.event:
|
then:
|
||||||
event: esphome.tx_ultimate_easy
|
- homeassistant.event:
|
||||||
data:
|
event: ${EVENT_NAME}
|
||||||
device_name: !lambda return tx_device_name->state.c_str();
|
data:
|
||||||
firmware: ${version}
|
device_name: !lambda return id(tx_device_name).state.c_str();
|
||||||
domain: touch
|
firmware: ${version}
|
||||||
type: multi_touch
|
domain: touch
|
||||||
action: release
|
type: multi_touch
|
||||||
position: !lambda return touch.x;
|
action: release
|
||||||
- lambda: ESP_LOGI("core_hw_touch", "Multi-touch released");
|
position: !lambda return std::to_string(touch.x);
|
||||||
- script.execute: touch_on_multi_touch_release
|
- lambda: |-
|
||||||
|
ESP_LOGI("${TAG_CORE_HW_TOUCH}", "Multi-touch released");
|
||||||
|
touch_on_multi_touch_release->execute();
|
||||||
|
|
||||||
on_press:
|
on_press:
|
||||||
- lambda: |-
|
then:
|
||||||
const uint8_t position = static_cast<uint8_t>(touch.x);
|
- lambda: |-
|
||||||
if (position > ${TOUCH_POSITION_MAX_VALUE}) { // Check for valid range
|
const uint8_t position = static_cast<uint8_t>(touch.x);
|
||||||
ESP_LOGE("core_hw_touch", "Invalid touch position: %" PRIu8, position);
|
if (position > ${TOUCH_POSITION_MAX_VALUE}) { // Check for valid range
|
||||||
} else {
|
ESP_LOGE("${TAG_CORE_HW_TOUCH}", "Invalid touch position: %" PRIu8, position);
|
||||||
ESP_LOGI("core_hw_touch", "Pressed at position %" PRIu8, position);
|
} else {
|
||||||
touch_on_press->execute(static_cast<uint8_t>(touch.button), position);
|
ESP_LOGI("${TAG_CORE_HW_TOUCH}", "Pressed at position %" PRIu8, position);
|
||||||
}
|
touch_on_press->execute(static_cast<uint8_t>(touch.button), position);
|
||||||
|
}
|
||||||
|
|
||||||
on_release:
|
on_release:
|
||||||
- lambda: ESP_LOGI("core_hw_touch", "Released");
|
then:
|
||||||
- script.execute: touch_on_release
|
- lambda: |-
|
||||||
|
ESP_LOGI("${TAG_CORE_HW_TOUCH}", "Released");
|
||||||
|
- script.execute: touch_on_release
|
||||||
|
|
||||||
on_swipe_left:
|
on_swipe_left:
|
||||||
- homeassistant.event:
|
then:
|
||||||
event: esphome.tx_ultimate_easy
|
- homeassistant.event:
|
||||||
data:
|
event: ${EVENT_NAME}
|
||||||
device_name: !lambda return tx_device_name->state.c_str();
|
data:
|
||||||
firmware: ${version}
|
device_name: !lambda return id(tx_device_name).state.c_str();
|
||||||
domain: touch
|
firmware: ${version}
|
||||||
type: swipe
|
domain: touch
|
||||||
action: !lambda |-
|
type: swipe
|
||||||
return sl_tx_model_format->state == "${TX_MODEL_FORMAT_EU_TEXT}" ? "left" : "down";
|
action: !lambda |-
|
||||||
swipe-direction: !lambda |-
|
if (sl_tx_model_format->state == "${TX_MODEL_FORMAT_EU_TEXT}")
|
||||||
return sl_tx_model_format->state == "${TX_MODEL_FORMAT_EU_TEXT}" ? "left" : "down";
|
return "left";
|
||||||
position: !lambda return touch.x;
|
else
|
||||||
- lambda: |-
|
return "down";
|
||||||
ESP_LOGI("core_hw_touch", "Swipe %s", sl_tx_model_format->state == "${TX_MODEL_FORMAT_EU_TEXT}"
|
swipe-direction: !lambda |-
|
||||||
? "left"
|
if (sl_tx_model_format->state == "${TX_MODEL_FORMAT_EU_TEXT}")
|
||||||
: "down");
|
return "left";
|
||||||
- script.execute: touch_swipe_left
|
else
|
||||||
|
return "down";
|
||||||
|
position: !lambda return std::to_string(touch.x);
|
||||||
|
- lambda: |-
|
||||||
|
ESP_LOGI("${TAG_CORE_HW_TOUCH}", "Swipe %s",
|
||||||
|
(sl_tx_model_format->state == "${TX_MODEL_FORMAT_EU_TEXT}") ? "left" : "down");
|
||||||
|
touch_swipe_left->execute();
|
||||||
|
|
||||||
on_swipe_right:
|
on_swipe_right:
|
||||||
- homeassistant.event:
|
then:
|
||||||
event: esphome.tx_ultimate_easy
|
- homeassistant.event:
|
||||||
data:
|
event: ${EVENT_NAME}
|
||||||
device_name: !lambda return tx_device_name->state.c_str();
|
data:
|
||||||
firmware: ${version}
|
device_name: !lambda return id(tx_device_name).state.c_str();
|
||||||
domain: touch
|
firmware: ${version}
|
||||||
type: swipe
|
domain: touch
|
||||||
action: !lambda |-
|
type: swipe
|
||||||
return sl_tx_model_format->state == "${TX_MODEL_FORMAT_EU_TEXT}" ? "right" : "up";
|
action: !lambda |-
|
||||||
swipe-direction: !lambda |-
|
if (sl_tx_model_format->state == "${TX_MODEL_FORMAT_EU_TEXT}")
|
||||||
return sl_tx_model_format->state == "${TX_MODEL_FORMAT_EU_TEXT}" ? "right" : "up";
|
return "right";
|
||||||
position: !lambda return touch.x;
|
else
|
||||||
- lambda: |-
|
return "up";
|
||||||
ESP_LOGI("core_hw_touch", "Swipe %s", sl_tx_model_format->state == "${TX_MODEL_FORMAT_EU_TEXT}"
|
swipe-direction: !lambda |-
|
||||||
? "right"
|
if (sl_tx_model_format->state == "${TX_MODEL_FORMAT_EU_TEXT}")
|
||||||
: "up");
|
return "right";
|
||||||
- script.execute: touch_swipe_right
|
else
|
||||||
|
return "up";
|
||||||
|
position: !lambda return std::to_string(touch.x);
|
||||||
|
- lambda: |-
|
||||||
|
ESP_LOGI("${TAG_CORE_HW_TOUCH}", "Swipe %s",
|
||||||
|
(sl_tx_model_format->state == "${TX_MODEL_FORMAT_EU_TEXT}") ? "right" : "up");
|
||||||
|
touch_swipe_right->execute();
|
||||||
|
|
||||||
on_touch_event:
|
on_touch_event:
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
ESP_LOGD("core_hw_touch", "Touch event:");
|
ESP_LOGD("${TAG_CORE_HW_TOUCH}", "Touch event:");
|
||||||
ESP_LOGD("core_hw_touch", " State: %i (%s)", touch.state, touch.state_str.c_str());
|
ESP_LOGD("${TAG_CORE_HW_TOUCH}", " State: %i (%s)", touch.state, touch.state_str.c_str());
|
||||||
ESP_LOGD("core_hw_touch", " Position: %i", touch.x);
|
ESP_LOGD("${TAG_CORE_HW_TOUCH}", " Position: %i", touch.x);
|
||||||
|
|
||||||
uart:
|
uart:
|
||||||
- id: uart_touch
|
- id: uart_touch
|
||||||
|
|||||||
@@ -13,60 +13,8 @@
|
|||||||
---
|
---
|
||||||
packages:
|
packages:
|
||||||
# yamllint disable rule:colons
|
# yamllint disable rule:colons
|
||||||
core_hw_relays: !include TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml
|
standard_hw_relays: !include TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml
|
||||||
core_hw_speaker: !include TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml
|
standard_hw_vibration: !include TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml
|
||||||
core_hw_vibration: !include TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml
|
standard_media_player: !include TX-Ultimate-Easy-ESPHome_standard_media_player.yaml
|
||||||
# yamllint enable rule:colons
|
# yamllint enable rule:colons
|
||||||
|
|
||||||
button:
|
|
||||||
- id: bt_restart
|
|
||||||
name: Restart
|
|
||||||
internal: false
|
|
||||||
platform: restart
|
|
||||||
|
|
||||||
captive_portal:
|
|
||||||
id: ap_captive_portal
|
|
||||||
|
|
||||||
esphome:
|
|
||||||
platformio_options:
|
|
||||||
build_flags:
|
|
||||||
- -D TX_ULTIMATE_EASY_STANDARD
|
|
||||||
|
|
||||||
script:
|
|
||||||
- id: !extend dump_config_list_packages
|
|
||||||
then:
|
|
||||||
- script.wait: dump_config
|
|
||||||
- lambda: |-
|
|
||||||
// Check for requirements
|
|
||||||
#if !defined(TX_ULTIMATE_EASY_CORE)
|
|
||||||
#error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Identify itself
|
|
||||||
ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Standard");
|
|
||||||
|
|
||||||
- id: !extend dump_config_versions
|
|
||||||
then:
|
|
||||||
- lambda: |-
|
|
||||||
// Version information
|
|
||||||
ESP_LOGCONFIG("standard", "ESPHome builder: %s", esphome_fw_version->state.c_str());
|
|
||||||
|
|
||||||
improv_serial:
|
|
||||||
id: serial_improv
|
|
||||||
|
|
||||||
text_sensor:
|
|
||||||
- id: esphome_fw_version
|
|
||||||
name: ESPHome Version
|
|
||||||
platform: version
|
|
||||||
entity_category: diagnostic
|
|
||||||
internal: false
|
|
||||||
|
|
||||||
time:
|
|
||||||
- id: time_source
|
|
||||||
platform: homeassistant
|
|
||||||
|
|
||||||
web_server:
|
|
||||||
|
|
||||||
wifi:
|
|
||||||
ap:
|
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -11,15 +11,20 @@
|
|||||||
##### - For normal system use, modifications to this file are NOT required. #####
|
##### - For normal system use, modifications to this file are NOT required. #####
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
---
|
---
|
||||||
|
substitutions:
|
||||||
|
SWITCH_AUDIO_AMPLIFIER_RESTORE_MODE: RESTORE_DEFAULT_ON
|
||||||
|
|
||||||
|
TAG_STD_HW_AUDIO: std.hw.audio
|
||||||
|
|
||||||
esphome:
|
esphome:
|
||||||
platformio_options:
|
platformio_options:
|
||||||
build_flags:
|
build_flags:
|
||||||
- -D TX_ULTIMATE_EASY_STANDARD_HW_AUDIO
|
- -D TX_ULTIMATE_EASY_STANDARD_HW_AUDIO
|
||||||
|
|
||||||
i2s_audio:
|
i2s_audio:
|
||||||
id: if_i2s_audio
|
- id: if_i2s_audio
|
||||||
i2s_bclk_pin: GPIO2
|
i2s_bclk_pin: GPIO2
|
||||||
i2s_lrclk_pin: GPIO4
|
i2s_lrclk_pin: GPIO4
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- id: !extend dump_config_list_packages
|
- id: !extend dump_config_list_packages
|
||||||
@@ -27,10 +32,21 @@ script:
|
|||||||
- script.wait: dump_config
|
- script.wait: dump_config
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
// Check for requirements
|
// Check for requirements
|
||||||
#if !defined(TX_ULTIMATE_EASY_CORE)
|
#if !defined(TX_ULTIMATE_EASY_CORE_COMMON)
|
||||||
#error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required."
|
#error "The package TX-Ultimate-Easy-ESPHome_core_common.yaml is required."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Identify itself
|
// Identify itself
|
||||||
ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Standard - Hardware - Audio");
|
ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Standard - Hardware - Audio");
|
||||||
|
|
||||||
|
switch:
|
||||||
|
- id: sw_audio_amplifier
|
||||||
|
name: Audio Amplifier
|
||||||
|
platform: gpio
|
||||||
|
pin:
|
||||||
|
number: GPIO26
|
||||||
|
inverted: false
|
||||||
|
restore_mode: ${SWITCH_AUDIO_AMPLIFIER_RESTORE_MODE}
|
||||||
|
internal: true
|
||||||
|
entity_category: config
|
||||||
...
|
...
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,8 @@ substitutions:
|
|||||||
# d=32 (32nd note), o=5 (octave 5), b=100 (tempo 100)
|
# d=32 (32nd note), o=5 (octave 5), b=100 (tempo 100)
|
||||||
tone_volume_change: "scale_up:d=32,o=5,b=100:c,c#,d#,e,f#,g#,a#,b" # Use "none" to disable sound
|
tone_volume_change: "scale_up:d=32,o=5,b=100:c,c#,d#,e,f#,g#,a#,b" # Use "none" to disable sound
|
||||||
|
|
||||||
|
TAG_STD_HW_SPEAKER: std.hw.speaker
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
standard_hw_audio: !include TX-Ultimate-Easy-ESPHome_standard_hw_audio.yaml
|
standard_hw_audio: !include TX-Ultimate-Easy-ESPHome_standard_hw_audio.yaml
|
||||||
|
|
||||||
@@ -31,18 +33,18 @@ api:
|
|||||||
- lambda: |-
|
- lambda: |-
|
||||||
rtttl_speaker->stop();
|
rtttl_speaker->stop();
|
||||||
if (speaker_volume->state > 0) {
|
if (speaker_volume->state > 0) {
|
||||||
ESP_LOGI("standard_speaker", "Play tone: '%s'", tone.c_str());
|
ESP_LOGI("${TAG_STD_HW_SPEAKER}", "Play tone: '%s'", tone.c_str());
|
||||||
rtttl_speaker->play(tone.c_str());
|
rtttl_speaker->play(tone.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
esphome:
|
esphome:
|
||||||
platformio_options:
|
platformio_options:
|
||||||
build_flags:
|
build_flags:
|
||||||
- -D TX_ULTIMATE_EASY_STANDARD_SPEAKER
|
- -D TX_ULTIMATE_EASY_STANDARD_HW_SPEAKER
|
||||||
|
|
||||||
number:
|
number:
|
||||||
- id: speaker_volume
|
- id: speaker_volume
|
||||||
name: Sound - Volume
|
name: Speaker Volume
|
||||||
platform: template
|
platform: template
|
||||||
max_value: 100
|
max_value: 100
|
||||||
min_value: 0
|
min_value: 0
|
||||||
@@ -76,8 +78,8 @@ script:
|
|||||||
- script.wait: dump_config
|
- script.wait: dump_config
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
// Check for requirements
|
// Check for requirements
|
||||||
#if !defined(TX_ULTIMATE_EASY_CORE)
|
#if !defined(TX_ULTIMATE_EASY_CORE_COMMON)
|
||||||
#error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required."
|
#error "The package TX-Ultimate-Easy-ESPHome_core_common.yaml is required."
|
||||||
#endif
|
#endif
|
||||||
#if !defined(TX_ULTIMATE_EASY_STANDARD_HW_AUDIO)
|
#if !defined(TX_ULTIMATE_EASY_STANDARD_HW_AUDIO)
|
||||||
#error "The package TX-Ultimate-Easy-ESPHome_standard_hw_audio.yaml is required."
|
#error "The package TX-Ultimate-Easy-ESPHome_standard_hw_audio.yaml is required."
|
||||||
@@ -179,4 +181,8 @@ speaker:
|
|||||||
i2s_audio_id: if_i2s_audio
|
i2s_audio_id: if_i2s_audio
|
||||||
i2s_comm_fmt: stand_msb
|
i2s_comm_fmt: stand_msb
|
||||||
channel: mono
|
channel: mono
|
||||||
|
timeout: never
|
||||||
|
bits_per_sample: 16bit
|
||||||
|
sample_rate: 48000
|
||||||
|
buffer_duration: 500ms
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
vibration_max_duration: 2s
|
vibration_max_duration: 2s
|
||||||
|
|
||||||
|
TAG_STD_HW_VIBRATION: std.hw.vibration
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- id: bs_vibrating
|
- id: bs_vibrating
|
||||||
name: Vibrating
|
name: Vibrating
|
||||||
@@ -62,24 +64,24 @@ script:
|
|||||||
then:
|
then:
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
// Configuration
|
// Configuration
|
||||||
ESP_LOGCONFIG("standard_hw_vibration", "Touch - Vibration feedback: %s",
|
ESP_LOGCONFIG("${TAG_STD_HW_VIBRATION}", "Touch - Vibration feedback: %s",
|
||||||
sl_touch_vibration_feedback->state.c_str());
|
sl_touch_vibration_feedback->state.c_str());
|
||||||
ESP_LOGCONFIG("standard_hw_vibration", "Vibrate duration: %.0fms", nr_vibrating_duration->state);
|
ESP_LOGCONFIG("${TAG_STD_HW_VIBRATION}", "Vibrate duration: %.0fms", nr_vibrating_duration->state);
|
||||||
ESP_LOGCONFIG("standard_hw_vibration", "Vibrate max duration: ${vibration_max_duration}");
|
ESP_LOGCONFIG("${TAG_STD_HW_VIBRATION}", "Vibrate max duration: ${vibration_max_duration}");
|
||||||
|
|
||||||
// State
|
// State
|
||||||
if (bs_vibrating->state)
|
if (bs_vibrating->state)
|
||||||
ESP_LOGW("standard_hw_vibration", "Vibrating now: YES");
|
ESP_LOGW("${TAG_STD_HW_VIBRATION}", "Vibrating now: YES");
|
||||||
else
|
else
|
||||||
ESP_LOGCONFIG("standard_hw_vibration", "Vibrating now: No");
|
ESP_LOGCONFIG("${TAG_STD_HW_VIBRATION}", "Vibrating now: No");
|
||||||
|
|
||||||
- id: !extend dump_config_list_packages
|
- id: !extend dump_config_list_packages
|
||||||
then:
|
then:
|
||||||
- script.wait: dump_config
|
- script.wait: dump_config
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
// Check for requirements
|
// Check for requirements
|
||||||
#if !defined(TX_ULTIMATE_EASY_CORE)
|
#if !defined(TX_ULTIMATE_EASY_CORE_COMMON)
|
||||||
#error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required."
|
#error "The package TX-Ultimate-Easy-ESPHome_core_common.yaml is required."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Identify itself
|
// Identify itself
|
||||||
@@ -149,20 +151,17 @@ switch:
|
|||||||
pin: GPIO21
|
pin: GPIO21
|
||||||
restore_mode: ALWAYS_OFF
|
restore_mode: ALWAYS_OFF
|
||||||
internal: true
|
internal: true
|
||||||
on_turn_on:
|
on_state:
|
||||||
then:
|
then:
|
||||||
- binary_sensor.template.publish:
|
- binary_sensor.template.publish:
|
||||||
id: bs_vibrating
|
id: bs_vibrating
|
||||||
state: ON # yamllint disable-line rule:truthy
|
state: !lambda return x;
|
||||||
|
on_turn_on:
|
||||||
|
then:
|
||||||
- delay: ${vibration_max_duration}
|
- delay: ${vibration_max_duration}
|
||||||
- if:
|
- if:
|
||||||
condition:
|
condition:
|
||||||
switch.is_on: sw_vibration_motor
|
switch.is_on: sw_vibration_motor
|
||||||
then:
|
then:
|
||||||
- switch.turn_off: sw_vibration_motor
|
- switch.turn_off: sw_vibration_motor
|
||||||
on_turn_off:
|
|
||||||
then:
|
|
||||||
- binary_sensor.template.publish:
|
|
||||||
id: bs_vibrating
|
|
||||||
state: OFF # yamllint disable-line rule:truthy
|
|
||||||
...
|
...
|
||||||
|
|||||||
118
ESPHome/TX-Ultimate-Easy-ESPHome_standard_media_player.yaml
Normal file
118
ESPHome/TX-Ultimate-Easy-ESPHome_standard_media_player.yaml
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
####################################################################################################
|
||||||
|
##### TX Ultimate Easy for ESPHome #####
|
||||||
|
##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy #####
|
||||||
|
####################################################################################################
|
||||||
|
##### Purpose: ESPHome - Add-on - Media player #####
|
||||||
|
####################################################################################################
|
||||||
|
##### 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:
|
||||||
|
TAG_STD_MEDIA_PLAYER: "std.media-player"
|
||||||
|
|
||||||
|
packages:
|
||||||
|
standard_hw_speaker: !include TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
platformio_options:
|
||||||
|
build_flags:
|
||||||
|
- -D TX_ULTIMATE_EASY_STANDARD_MEDIA_PLAYER
|
||||||
|
|
||||||
|
globals:
|
||||||
|
- id: last_media_player_volume
|
||||||
|
type: uint8_t
|
||||||
|
restore_value: false
|
||||||
|
initial_value: '100'
|
||||||
|
- id: persistent_media_player_volume
|
||||||
|
type: uint8_t
|
||||||
|
restore_value: true
|
||||||
|
initial_value: '100'
|
||||||
|
|
||||||
|
media_player:
|
||||||
|
- id: mp_media_player
|
||||||
|
name: Media Player
|
||||||
|
internal: false
|
||||||
|
platform: speaker
|
||||||
|
codec_support_enabled: true
|
||||||
|
buffer_size: 250000
|
||||||
|
task_stack_in_psram: false
|
||||||
|
announcement_pipeline:
|
||||||
|
speaker: announcement_spk_resampling_input
|
||||||
|
format: WAV
|
||||||
|
num_channels: 1
|
||||||
|
sample_rate: 48000
|
||||||
|
media_pipeline:
|
||||||
|
speaker: media_spk_resampling_input
|
||||||
|
format: FLAC
|
||||||
|
num_channels: 1
|
||||||
|
sample_rate: 48000
|
||||||
|
on_state:
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
// Check if volume has changed and update number entity
|
||||||
|
id(persistent_media_player_volume) = static_cast<uint8_t>(mp_media_player->volume * 100.0f);
|
||||||
|
if (id(persistent_media_player_volume) != id(last_media_player_volume)) {
|
||||||
|
id(last_media_player_volume) = id(persistent_media_player_volume);
|
||||||
|
ESP_LOGD("${TAG_STD_MEDIA_PLAYER}", "Media player volume changed to %" PRIu8 "%%, updating number entity",
|
||||||
|
id(persistent_media_player_volume));
|
||||||
|
}
|
||||||
|
|
||||||
|
script:
|
||||||
|
- id: !extend boot_sequence
|
||||||
|
then:
|
||||||
|
- script.execute: sync_initial_volume
|
||||||
|
|
||||||
|
- id: !extend dump_config
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
// Volume sync configuration
|
||||||
|
ESP_LOGCONFIG("${TAG_STD_MEDIA_PLAYER}", "Media Player Volume Sync:");
|
||||||
|
ESP_LOGCONFIG("${TAG_STD_MEDIA_PLAYER}", " Persistent volume: %" PRIu8 "%",
|
||||||
|
id(persistent_media_player_volume));
|
||||||
|
ESP_LOGCONFIG("${TAG_STD_MEDIA_PLAYER}", " Current volume: %.1f%%", mp_media_player->volume * 100.0f);
|
||||||
|
|
||||||
|
- id: !extend dump_config_list_packages
|
||||||
|
then:
|
||||||
|
- script.wait: dump_config
|
||||||
|
- lambda: |-
|
||||||
|
// Check for requirements
|
||||||
|
#if !defined(TX_ULTIMATE_EASY_CORE_COMMON)
|
||||||
|
#error "The package TX-Ultimate-Easy-ESPHome_core_common.yaml is required."
|
||||||
|
#endif // TX_ULTIMATE_EASY_CORE
|
||||||
|
#if !defined(TX_ULTIMATE_EASY_STANDARD_HW_SPEAKER)
|
||||||
|
#error "The package TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml is required."
|
||||||
|
#endif // TX_ULTIMATE_EASY_STANDARD_HW_SPEAKER
|
||||||
|
|
||||||
|
// Identify itself
|
||||||
|
ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Standard - Media Player");
|
||||||
|
|
||||||
|
- id: sync_initial_volume
|
||||||
|
mode: restart
|
||||||
|
then:
|
||||||
|
- delay: 2s # Wait for media player to initialize
|
||||||
|
- media_player.volume_set: # Sync initial volume from persisted number entity to media player
|
||||||
|
id: mp_media_player
|
||||||
|
volume: !lambda return id(persistent_media_player_volume) / 100.0f;
|
||||||
|
- lambda: |-
|
||||||
|
id(last_media_player_volume) = id(persistent_media_player_volume);
|
||||||
|
ESP_LOGI("${TAG_STD_MEDIA_PLAYER}", "Initial volume sync: %.1f%% (restored from persistence)",
|
||||||
|
id(persistent_media_player_volume));
|
||||||
|
|
||||||
|
speaker:
|
||||||
|
- platform: mixer
|
||||||
|
id: mixer_speaker_embedded
|
||||||
|
output_speaker: speaker_embedded
|
||||||
|
source_speakers:
|
||||||
|
- id: announcement_speaker_embedded
|
||||||
|
- id: media_speaker_embedded
|
||||||
|
- platform: resampler
|
||||||
|
id: announcement_spk_resampling_input
|
||||||
|
output_speaker: announcement_speaker_embedded
|
||||||
|
- platform: resampler
|
||||||
|
id: media_spk_resampling_input
|
||||||
|
output_speaker: media_speaker_embedded
|
||||||
|
...
|
||||||
160
README.md
160
README.md
@@ -8,10 +8,10 @@
|
|||||||
[![Discord][discord-shield]](https://discord.gg/Db6WJWzWuf)
|
[![Discord][discord-shield]](https://discord.gg/Db6WJWzWuf)
|
||||||
[![Buy me an ice-cream][buymeacoffee-shield]](https://www.buymeacoffee.com/edwardfirmo)
|
[![Buy me an ice-cream][buymeacoffee-shield]](https://www.buymeacoffee.com/edwardfirmo)
|
||||||
|
|
||||||
<!-- markdownlint-disable MD013 -->
|
<!-- markdownlint-disable MD013 MD033 -->
|
||||||
|  | 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. |
|
| <picture><source media="(prefers-color-scheme: dark)" srcset="Assets/Logo_dark.png"><source media="(prefers-color-scheme: light)" srcset="Assets/Logo_light.png"><img alt="TX Ultimate Easy Logo" src="Assets/Logo_light.png"></picture> | 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 -->
|
<!-- markdownlint-enable MD013 MD033 -->
|
||||||
|
|
||||||
[version-shield]: https://img.shields.io/github/v/tag/edwardtfn/TX-Ultimate-Easy?label=version
|
[version-shield]: https://img.shields.io/github/v/tag/edwardtfn/TX-Ultimate-Easy?label=version
|
||||||
[version]: https://github.com/edwardtfn/TX-Ultimate-Easy/tags
|
[version]: https://github.com/edwardtfn/TX-Ultimate-Easy/tags
|
||||||
@@ -27,6 +27,48 @@
|
|||||||
[buymeacoffee-shield]: https://img.shields.io/static/v1?label=Buy%20me%20an%20ice%20cream&message=❄&color=blue
|
[buymeacoffee-shield]: https://img.shields.io/static/v1?label=Buy%20me%20an%20ice%20cream&message=❄&color=blue
|
||||||
[buymeacoffee]: https://www.buymeacoffee.com/edwardfirmo
|
[buymeacoffee]: https://www.buymeacoffee.com/edwardfirmo
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> ESPHome builder v2025.8.0+ is required
|
||||||
|
|
||||||
|
## Framework Migration to ESP-IDF
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> **ESP-IDF Framework Migration**
|
||||||
|
>
|
||||||
|
> Starting with version **2025.8.0**, TX Ultimate Easy will use **ESP-IDF** as the default framework, following ESPHome's direction towards ESP-IDF for better performance, stability, and feature support.
|
||||||
|
>
|
||||||
|
> **What this means for you:**
|
||||||
|
> - **New installations**: Will automatically use ESP-IDF (no action required)
|
||||||
|
> - **Existing Arduino users**: Can continue using Arduino but with limited support
|
||||||
|
> - **Migration recommended**: For better performance and full feature support
|
||||||
|
>
|
||||||
|
> **Arduino Framework Support:**
|
||||||
|
> - Still functional but **no longer actively tested**
|
||||||
|
> - **Limited support** will be provided for Arduino-specific issues
|
||||||
|
> - May miss out on new features optimized for ESP-IDF
|
||||||
|
|
||||||
|
### Migration Guidelines
|
||||||
|
|
||||||
|
#### For New Users
|
||||||
|
No action required - ESP-IDF will be used automatically.
|
||||||
|
|
||||||
|
#### For Existing Arduino Users
|
||||||
|
|
||||||
|
**Option 1: Migrate to ESP-IDF (Recommended)**
|
||||||
|
1. **Best practice**: Flash via serial/USB to ensure proper partition setup
|
||||||
|
2. **Alternative**: If serial flashing isn't possible, flash OTA twice consecutively to improve success rate
|
||||||
|
|
||||||
|
**Option 2: Continue with Arduino**
|
||||||
|
Add this to your YAML configuration to force Arduino framework:
|
||||||
|
```yaml
|
||||||
|
esp32:
|
||||||
|
framework:
|
||||||
|
type: arduino
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> **Migration via OTA:** When switching frameworks via OTA, the partition table may not update correctly. Flash twice in succession to ensure both firmware partitions contain the latest firmware and prevent boot failures.
|
||||||
|
|
||||||
## Integration with Home Assistant
|
## Integration with Home Assistant
|
||||||
|
|
||||||
TX Ultimate Easy exposes your device's components (sensors, touch panel, relays, etc.) to Home Assistant,
|
TX Ultimate Easy exposes your device's components (sensors, touch panel, relays, etc.) to Home Assistant,
|
||||||
@@ -70,9 +112,10 @@ All device behaviors can be customized through Home Assistant automations withou
|
|||||||
- **Flexible Light Control**: Customize LED behavior and effects
|
- **Flexible Light Control**: Customize LED behavior and effects
|
||||||
- **Touch Panel Support**: Full support for touch gestures and multi-touch capabilities
|
- **Touch Panel Support**: Full support for touch gestures and multi-touch capabilities
|
||||||
- **Advanced Automations**: Create complex automations using Home Assistant's powerful automation engine
|
- **Advanced Automations**: Create complex automations using Home Assistant's powerful automation engine
|
||||||
- **BLE Proxy Support**: Optional Bluetooth Low Energy proxy functionality
|
- **Bluetooth Proxy Support**: Compatible with ESPHome's bluetooth_proxy component for BLE device integration
|
||||||
- **Audio Feedback**: Built-in speaker support for audible feedback
|
- **Audio Feedback**: Built-in speaker support for audible feedback
|
||||||
- **Haptic Feedback**: Vibration motor support for tactile feedback
|
- **Haptic Feedback**: Vibration motor support for tactile feedback
|
||||||
|
- **ESP-IDF Framework**: Enhanced performance and stability with ESP-IDF support
|
||||||
|
|
||||||
## Hardware Support
|
## Hardware Support
|
||||||
|
|
||||||
@@ -111,28 +154,104 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome.
|
|||||||
4. Copy this basic configuration to your new device:
|
4. Copy this basic configuration to your new device:
|
||||||
```yaml
|
```yaml
|
||||||
substitutions:
|
substitutions:
|
||||||
name: tx-ultimate-easy # Change this to your device name
|
name: tx-ultimate-easy
|
||||||
friendly_name: TX Ultimate Easy
|
friendly_name: TX Ultimate Easy
|
||||||
|
|
||||||
packages:
|
|
||||||
remote_package:
|
|
||||||
url: https://github.com/edwardtfn/TX-Ultimate-Easy
|
|
||||||
ref: main # For latest stable release
|
|
||||||
files:
|
|
||||||
- ESPHome/TX-Ultimate-Easy-ESPHome.yaml
|
|
||||||
|
|
||||||
wifi:
|
wifi:
|
||||||
ssid: !secret wifi_ssid
|
ssid: !secret wifi_ssid
|
||||||
password: !secret wifi_password
|
password: !secret wifi_password
|
||||||
```
|
|
||||||
|
|
||||||
|
packages:
|
||||||
|
remote_package:
|
||||||
|
url: https://github.com/edwardtfn/TX-Ultimate-Easy
|
||||||
|
ref: main # Or you can specify a version, like `ref: v2024.12.6` or `ref: latest`
|
||||||
|
refresh: 5min
|
||||||
|
files:
|
||||||
|
- ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml # Core (essential) packages
|
||||||
|
- ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml # Non-essential, but recommended packages
|
||||||
|
```
|
||||||
You can also use a specific version tag for better control over updates:
|
You can also use a specific version tag for better control over updates:
|
||||||
```yaml
|
```yaml
|
||||||
ref: v2024.12.2 # Using specific version for controlled updates
|
ref: v2024.12.2 # Using specific version for controlled updates
|
||||||
```
|
```
|
||||||
**Note:** [Click here](https://github.com/edwardtfn/TX-Ultimate-Easy/tags) for a full list of versions available.
|
**Notes:**
|
||||||
|
- [Click here](https://github.com/edwardtfn/TX-Ultimate-Easy/tags) for a full list of versions available.
|
||||||
|
- [Click here](TX-Ultimate-Easy-ESPHome.yaml)
|
||||||
|
for the latest version of this yaml.
|
||||||
5. Click "Save" and then "Install"
|
5. Click "Save" and then "Install"
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> Starting from version 2025.1.0, non-essential components like `web_server`, `captive_portal`, and `wifi`
|
||||||
|
> are no longer included in the core package. If you need these components,
|
||||||
|
> you must add them manually to your local configuration file.
|
||||||
|
> For example:
|
||||||
|
> ```yaml
|
||||||
|
> # Add these to your configuration if needed
|
||||||
|
> web_server:
|
||||||
|
> captive_portal:
|
||||||
|
> wifi:
|
||||||
|
> ap: # Access point configuration
|
||||||
|
> ```
|
||||||
|
|
||||||
|
### Optional Features
|
||||||
|
|
||||||
|
#### Bluetooth Proxy
|
||||||
|
TX Ultimate Easy is fully compatible with ESPHome's `bluetooth_proxy` component.
|
||||||
|
To enable Bluetooth proxy functionality, add the following to your device configuration:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
bluetooth_proxy:
|
||||||
|
# Optional: Configure specific settings
|
||||||
|
# active: true
|
||||||
|
```
|
||||||
|
|
||||||
|
**Requirements for Bluetooth Proxy:**
|
||||||
|
- ESP-IDF framework (default framework, not recommended with Arduino framework)
|
||||||
|
- Sufficient memory (TX Ultimate Easy components are compatible,
|
||||||
|
but adding additional custom components may require memory optimization)
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Bluetooth proxy functionality is provided by ESPHome's native component.
|
||||||
|
> TX Ultimate Easy ensures compatibility but does not include it by default to maintain optimal memory usage.
|
||||||
|
|
||||||
|
### Advanced Settings
|
||||||
|
For more granular control over components,
|
||||||
|
you can use our [advanced configuration template](TX-Ultimate-Easy-ESPHome_advanced.yaml).
|
||||||
|
This template allows you to selectively include specific packages, which can be useful for:
|
||||||
|
|
||||||
|
- Troubleshooting specific components
|
||||||
|
- Reducing memory usage by excluding unused features
|
||||||
|
- Customizing functionality for specific use cases
|
||||||
|
|
||||||
|
Here's an example of the advanced configuration:
|
||||||
|
```yaml
|
||||||
|
packages:
|
||||||
|
remote_package:
|
||||||
|
url: https://github.com/edwardtfn/TX-Ultimate-Easy
|
||||||
|
ref: main # Or you can specify a version, like `ref: v2024.12.6` or `ref: latest`
|
||||||
|
refresh: 5min
|
||||||
|
files:
|
||||||
|
# Core (essential) packages
|
||||||
|
- ESPHome/TX-Ultimate-Easy-ESPHome_core_common.yaml # Basic shared settings
|
||||||
|
- ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml # Button logic
|
||||||
|
- ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml # LED configuration
|
||||||
|
- ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml # Touch panel support
|
||||||
|
|
||||||
|
# Optional but recommended packages
|
||||||
|
- ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml # Relay control
|
||||||
|
- ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml # Haptic feedback
|
||||||
|
|
||||||
|
# Audio options (use none or choose only one - using both will fail)
|
||||||
|
- ESPHome/TX-Ultimate-Easy-ESPHome_standard_media_player.yaml # Media player (Recommended for most users)
|
||||||
|
# - ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml # Basic speaker
|
||||||
|
|
||||||
|
# Optional: Add Bluetooth proxy support
|
||||||
|
bluetooth_proxy:
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Use the advanced configuration with caution. Excluding core packages may cause instability or reduced functionality.
|
||||||
|
|
||||||
### Device Flashing
|
### Device Flashing
|
||||||
|
|
||||||
Initial flashing must be done via serial connection.
|
Initial flashing must be done via serial connection.
|
||||||
@@ -232,7 +351,7 @@ If the device isn't discovered automatically:
|
|||||||
- Button actions
|
- Button actions
|
||||||
3. Optional: Configure advanced features
|
3. Optional: Configure advanced features
|
||||||
- LED behaviors
|
- LED behaviors
|
||||||
- Touch sensitivity
|
- Touch duration
|
||||||
- Haptic feedback
|
- Haptic feedback
|
||||||
- Audio feedback
|
- Audio feedback
|
||||||
4. Test your configuration:
|
4. Test your configuration:
|
||||||
@@ -252,17 +371,18 @@ After installation, you can:
|
|||||||
2. Customize touch behaviors
|
2. Customize touch behaviors
|
||||||
3. Set up LED patterns and effects
|
3. Set up LED patterns and effects
|
||||||
4. Create automations
|
4. Create automations
|
||||||
5. Enable optional features like BLE proxy
|
5. Enable optional features like Bluetooth proxy
|
||||||
|
|
||||||
## Configuration Options
|
## Configuration Options
|
||||||
|
|
||||||
TX Ultimate Easy offers extensive configuration options:
|
TX Ultimate Easy offers extensive configuration options:
|
||||||
|
|
||||||
- Touch panel sensitivity and gestures
|
- Touch panel gestures
|
||||||
- LED colors, patterns, and behaviors
|
- LED colors, patterns, and behaviors
|
||||||
- Relay modes and functions
|
- Relay modes and functions
|
||||||
- Audio and haptic feedback settings
|
- Audio and haptic feedback settings
|
||||||
- Network and connectivity options
|
- Network and connectivity options
|
||||||
|
- Optional Bluetooth proxy functionality
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
@@ -314,5 +434,9 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
|
|||||||
---
|
---
|
||||||
|
|
||||||
<!-- markdownlint-disable MD033 -->
|
<!-- markdownlint-disable MD033 -->
|
||||||
<img src="Assets/Logo.webp" alt="TX Ultimate Easy Logo" width="100"/>
|
<picture>
|
||||||
|
<source media="(prefers-color-scheme: dark)" srcset="Assets/Logo_dark.png">
|
||||||
|
<source media="(prefers-color-scheme: light)" srcset="Assets/Logo_light.png">
|
||||||
|
<img alt="TX Ultimate Easy Logo" src="Assets/Logo_light.png" width="100">
|
||||||
|
</picture>
|
||||||
<!-- markdownlint-enable MD033 -->
|
<!-- markdownlint-enable MD033 -->
|
||||||
|
|||||||
@@ -16,11 +16,10 @@ wifi:
|
|||||||
packages:
|
packages:
|
||||||
remote_package:
|
remote_package:
|
||||||
url: https://github.com/edwardtfn/TX-Ultimate-Easy
|
url: https://github.com/edwardtfn/TX-Ultimate-Easy
|
||||||
ref: latest # Or you can specify a version, like `ref: v2024.12.6`
|
ref: stable # Or you can specify a version, like `ref: v2024.12.6` or `ref: latest` to the latest non-stable
|
||||||
refresh: 5min
|
refresh: 5min
|
||||||
files:
|
files:
|
||||||
- ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml # Core (essential) packages
|
- ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml # Core (essential) packages
|
||||||
- ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml # Non-essential, but recommended packages
|
- ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml # Non-essential, but recommended packages
|
||||||
# - ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml # Adds BLE proxy support
|
# - ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml # Adds BLE proxy support
|
||||||
# - ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml # Adds experimental Media Player (limited)
|
|
||||||
...
|
...
|
||||||
|
|||||||
38
TX-Ultimate-Easy-ESPHome_advanced.yaml
Normal file
38
TX-Ultimate-Easy-ESPHome_advanced.yaml
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
####################################################################################################
|
||||||
|
##### TX Ultimate Easy for ESPHome #####
|
||||||
|
##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy #####
|
||||||
|
####################################################################################################
|
||||||
|
##### Author: edwardtfn - https://github.com/edwardtfn - https://buymeacoffee.com/edwardfirmo #####
|
||||||
|
####################################################################################################
|
||||||
|
##### WARNING: This is an advanced configuration template. Use with caution as improper #####
|
||||||
|
##### configuration may lead to reduced functionality or system instability. #####
|
||||||
|
####################################################################################################
|
||||||
|
---
|
||||||
|
substitutions:
|
||||||
|
name: tx-ultimate-easy-adv
|
||||||
|
friendly_name: TX Ultimate Easy Advanced
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
|
||||||
|
packages:
|
||||||
|
remote_package:
|
||||||
|
url: https://github.com/edwardtfn/TX-Ultimate-Easy
|
||||||
|
ref: stable # Or you can specify a version, like `ref: v2024.12.6` or `ref: latest` to the latest non-stable
|
||||||
|
refresh: 5min
|
||||||
|
files:
|
||||||
|
# Core (essential) packages - Do not disable these unless you know what you're doing
|
||||||
|
- ESPHome/TX-Ultimate-Easy-ESPHome_core_common.yaml # Basic shared settings
|
||||||
|
- ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml # Button logic
|
||||||
|
- ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml # LED configuration
|
||||||
|
- ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml # Touch panel support
|
||||||
|
|
||||||
|
# Optional functionality - Can be enabled/disabled as needed
|
||||||
|
- ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml # Relay control
|
||||||
|
- ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml # Haptic feedback
|
||||||
|
|
||||||
|
# Audio options (use none or choose only one - using both will fail)
|
||||||
|
- ESPHome/TX-Ultimate-Easy-ESPHome_standard_media_player.yaml # Media player (Recommended for most users)
|
||||||
|
# - ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml # Basic speaker
|
||||||
|
...
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
|
from esphome import automation
|
||||||
from esphome.components import uart
|
from esphome.components import uart
|
||||||
|
from esphome.components.esp32 import add_idf_sdkconfig_option
|
||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
CONF_ID,
|
CONF_ID,
|
||||||
)
|
)
|
||||||
|
from esphome.core import CORE
|
||||||
from esphome import automation
|
|
||||||
|
|
||||||
CODEOWNERS = ["@edwardtfn"]
|
CODEOWNERS = ["@edwardtfn"]
|
||||||
DEPENDENCIES = ['uart']
|
DEPENDENCIES = ['uart']
|
||||||
@@ -109,3 +110,17 @@ async def to_code(config):
|
|||||||
await cg.register_component(var, config)
|
await cg.register_component(var, config)
|
||||||
await uart.register_uart_device(var, config)
|
await uart.register_uart_device(var, config)
|
||||||
await register_tx_ultimate_easy(var, config)
|
await register_tx_ultimate_easy(var, config)
|
||||||
|
|
||||||
|
if CORE.using_esp_idf:
|
||||||
|
add_idf_sdkconfig_option("CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST", True)
|
||||||
|
add_idf_sdkconfig_option("CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY", True)
|
||||||
|
add_idf_sdkconfig_option("CONFIG_ESP32_REV_MIN_3", True)
|
||||||
|
add_idf_sdkconfig_option("CONFIG_MBEDTLS_DYNAMIC_BUFFER", True)
|
||||||
|
add_idf_sdkconfig_option("CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT", True)
|
||||||
|
add_idf_sdkconfig_option("CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA", True)
|
||||||
|
add_idf_sdkconfig_option("CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC", True)
|
||||||
|
add_idf_sdkconfig_option("CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY", True)
|
||||||
|
add_idf_sdkconfig_option("CONFIG_SPIRAM_RODATA", True)
|
||||||
|
add_idf_sdkconfig_option("CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP", True)
|
||||||
|
|
||||||
|
cg.add_define("USE_TX_ULTIMATE_EASY")
|
||||||
|
|||||||
58
components/tx_ultimate_easy/tx_ultimate_easy_light.cpp
Normal file
58
components/tx_ultimate_easy/tx_ultimate_easy_light.cpp
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
// tx_ultimate_easy_light.cpp
|
||||||
|
|
||||||
|
#ifdef TX_ULTIMATE_EASY_CORE_HW_LEDS
|
||||||
|
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
#include "tx_ultimate_easy_light.h"
|
||||||
|
#include <cinttypes>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace tx_ultimate_easy {
|
||||||
|
|
||||||
|
// Log tag
|
||||||
|
static const char *TAG = "tx_ultimate_easy.light";
|
||||||
|
|
||||||
|
// Constant definitions
|
||||||
|
const LightAttributes LIGHT_ATTRS_DEFAULT = {100, 255, 255, 255};
|
||||||
|
const uint32_t LIGHT_ATTRS_DEFAULT_PACKED = 0x64FFFFFF;
|
||||||
|
const uint64_t DEFAULT_DUAL_LIGHT_ATTRS_PACKED = 0x64FFFFFF64FFFFFF;
|
||||||
|
|
||||||
|
// Function implementations
|
||||||
|
uint32_t pack_light_attributes(const LightAttributes& attr) {
|
||||||
|
return (uint32_t(std::min(attr.brightness, uint8_t(100))) << 24) |
|
||||||
|
(uint32_t(attr.red) << 16) |
|
||||||
|
(uint32_t(attr.green) << 8) |
|
||||||
|
(uint32_t(attr.blue));
|
||||||
|
}
|
||||||
|
|
||||||
|
LightAttributes unpack_light_attributes(uint32_t packed) {
|
||||||
|
return {
|
||||||
|
.brightness = std::min(uint8_t((packed >> 24) & 0xFF), uint8_t(100)),
|
||||||
|
.red = uint8_t((packed >> 16) & 0xFF),
|
||||||
|
.green = uint8_t((packed >> 8) & 0xFF),
|
||||||
|
.blue = uint8_t(packed & 0xFF)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t pack_dual_light_attributes(const LightAttributes& group1_attrs, const LightAttributes& group2_attrs) {
|
||||||
|
uint32_t group1_packed = pack_light_attributes(group1_attrs);
|
||||||
|
uint32_t group2_packed = pack_light_attributes(group2_attrs);
|
||||||
|
|
||||||
|
return (uint64_t(group2_packed) << 32) | uint64_t(group1_packed);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<LightAttributes, LightAttributes> unpack_dual_light_attributes(uint64_t packed) {
|
||||||
|
uint32_t group1_packed = uint32_t(packed & 0xFFFFFFFF); // Lower 32 bits
|
||||||
|
uint32_t group2_packed = uint32_t((packed >> 32) & 0xFFFFFFFF); // Upper 32 bits
|
||||||
|
|
||||||
|
return std::make_pair(
|
||||||
|
unpack_light_attributes(group1_packed),
|
||||||
|
unpack_light_attributes(group2_packed)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace tx_ultimate_easy
|
||||||
|
} // namespace esphome
|
||||||
|
|
||||||
|
#endif // TX_ULTIMATE_EASY_CORE_HW_LEDS
|
||||||
116
components/tx_ultimate_easy/tx_ultimate_easy_light.h
Normal file
116
components/tx_ultimate_easy/tx_ultimate_easy_light.h
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
// tx_ultimate_easy_light.h
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef TX_ULTIMATE_EASY_CORE_HW_LEDS
|
||||||
|
|
||||||
|
#include "esphome/core/automation.h"
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/components/uart/uart.h"
|
||||||
|
#include "esphome/components/uart/uart_component.h"
|
||||||
|
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||||
|
#include "esphome/components/switch/switch.h"
|
||||||
|
#include "esphome/components/light/addressable_light.h"
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace tx_ultimate_easy {
|
||||||
|
/**
|
||||||
|
* @brief Light attributes structure for storing color and brightness data.
|
||||||
|
*
|
||||||
|
* This structure represents the visual attributes of a light without the state (on/off).
|
||||||
|
* It's designed to be packed efficiently into a 32-bit integer for NVS storage.
|
||||||
|
* RGB components use the full 8-bit range (0-255) while brightness uses percentage (0-100).
|
||||||
|
*/
|
||||||
|
struct LightAttributes {
|
||||||
|
uint8_t brightness; ///< Light brightness percentage (0-100, where 100 = full brightness)
|
||||||
|
uint8_t red; ///< Red color component (0-255)
|
||||||
|
uint8_t green; ///< Green color component (0-255)
|
||||||
|
uint8_t blue; ///< Blue color component (0-255)
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Packs LightAttributes structure into a 32-bit integer for storage.
|
||||||
|
*
|
||||||
|
* Bit layout: [brightness(8)][red(8)][green(8)][blue(8)]
|
||||||
|
* This allows efficient storage in ESPHome globals with restore_value support.
|
||||||
|
* Note: Brightness values > 100 will be clamped to 100 during packing.
|
||||||
|
*
|
||||||
|
* @param attr The LightAttributes structure to pack
|
||||||
|
* @return uint32_t Packed representation suitable for NVS storage
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* LightAttributes attrs = {75, 255, 128, 64};
|
||||||
|
* uint32_t packed = pack_light_attributes(attrs); // Returns 0x4BFF8040
|
||||||
|
*/
|
||||||
|
uint32_t pack_light_attributes(const LightAttributes& attr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unpacks a 32-bit integer back into LightAttributes structure.
|
||||||
|
*
|
||||||
|
* Reverses the packing operation to extract individual color and brightness values.
|
||||||
|
* Brightness values > 100 in the packed data will be clamped to 100.
|
||||||
|
*
|
||||||
|
* @param packed The packed 32-bit representation
|
||||||
|
* @return LightAttributes The unpacked structure with individual components
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* uint32_t packed = 0x4BFF8040;
|
||||||
|
* LightAttributes attrs = unpack_light_attributes(packed);
|
||||||
|
* // attrs.brightness = 75, attrs.red = 255, attrs.green = 128, attrs.blue = 64
|
||||||
|
*/
|
||||||
|
LightAttributes unpack_light_attributes(uint32_t packed);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Default light attributes for initialization.
|
||||||
|
*
|
||||||
|
* Provides sensible defaults for new lights:
|
||||||
|
* - Brightness: 100 (full brightness)
|
||||||
|
* - Red: 255 (full intensity)
|
||||||
|
* - Green: 255 (full intensity)
|
||||||
|
* - Blue: 255 (full intensity)
|
||||||
|
* Result: Pure white color at full brightness
|
||||||
|
*/
|
||||||
|
extern const LightAttributes LIGHT_ATTRS_DEFAULT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pre-packed version of DEFAULT_LIGHT_ATTRS for convenience.
|
||||||
|
*
|
||||||
|
* This constant contains LIGHT_ATTRS_DEFAULT already packed into uint32_t format,
|
||||||
|
* suitable for direct use in ESPHome YAML initial_value fields.
|
||||||
|
*
|
||||||
|
* Value: 0x64FFFFFF (brightness=100, RGB=255,255,255)
|
||||||
|
*/
|
||||||
|
extern const uint32_t LIGHT_ATTRS_DEFAULT_PACKED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Packs two LightAttributes into a single uint64_t for dual light storage.
|
||||||
|
*
|
||||||
|
* Bit layout: [group2_light(32)][group1_light(32)]
|
||||||
|
* Each light uses 32 bits: [brightness(8)][red(8)][green(8)][blue(8)]
|
||||||
|
*
|
||||||
|
* @param group1_attrs First light attributes (stored in lower 32 bits)
|
||||||
|
* @param group2_attrs Second light attributes (stored in upper 32 bits)
|
||||||
|
* @return uint64_t Packed representation suitable for NVS storage
|
||||||
|
*/
|
||||||
|
uint64_t pack_dual_light_attributes(const LightAttributes& group1_attrs, const LightAttributes& group2_attrs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unpacks uint64_t back into two LightAttributes structures.
|
||||||
|
*
|
||||||
|
* @param packed The packed 64-bit representation
|
||||||
|
* @return std::pair<LightAttributes, LightAttributes> Pair of (group1, group2) attributes
|
||||||
|
*/
|
||||||
|
std::pair<LightAttributes, LightAttributes> unpack_dual_light_attributes(uint64_t packed);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pre-packed version of dual default attributes for convenience.
|
||||||
|
*
|
||||||
|
* Value: 0x64FFFFFF64FFFFFF (both lights: brightness=100, RGB=255,255,255)
|
||||||
|
*/
|
||||||
|
extern const uint64_t DEFAULT_DUAL_LIGHT_ATTRS_PACKED;
|
||||||
|
|
||||||
|
} // namespace tx_ultimate_easy
|
||||||
|
} // namespace esphome
|
||||||
|
|
||||||
|
#endif // TX_ULTIMATE_EASY_CORE_HW_LEDS
|
||||||
@@ -1,13 +1,18 @@
|
|||||||
// tx_ultimate_easy.cpp
|
// tx_ultimate_easy_touch.cpp
|
||||||
|
|
||||||
|
#ifdef TX_ULTIMATE_EASY_CORE_HW_TOUCH
|
||||||
|
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
#include "tx_ultimate_easy.h"
|
#include "tx_ultimate_easy_touch.h"
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace tx_ultimate_easy {
|
namespace tx_ultimate_easy {
|
||||||
|
|
||||||
|
// Log tag
|
||||||
|
static const char *TAG = "tx_ultimate_easy.touch";
|
||||||
|
|
||||||
void TxUltimateEasy::setup() {
|
void TxUltimateEasy::setup() {
|
||||||
ESP_LOGI(TAG, "TX Ultimate Easy is initialized");
|
ESP_LOGI(TAG, "TX Ultimate Easy is initialized");
|
||||||
}
|
}
|
||||||
@@ -69,9 +74,10 @@ namespace esphome {
|
|||||||
if (this->gang_count_ == 1)
|
if (this->gang_count_ == 1)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
//Calculate button number Change to round up insted of truncate (integer division)
|
// Calculate button width (rounds up to ensure full coverage)
|
||||||
const uint8_t width = (TOUCH_MAX_POSITION + gang_count_) / this->gang_count_; // Width of each button region
|
const uint8_t width =
|
||||||
if (width < 1) // Invalid width - and prevents division by zero removed "width > gang_count_" issue with 2 gang
|
(TOUCH_MAX_POSITION + this->gang_count_) / this->gang_count_; // Width of each button region
|
||||||
|
if (width < 1) // Invalid width - and prevents division by zero
|
||||||
return 0;
|
return 0;
|
||||||
const uint8_t button = std::min(
|
const uint8_t button = std::min(
|
||||||
static_cast<uint8_t>((position / width) + 1), // Convert position to button index
|
static_cast<uint8_t>((position / width) + 1), // Convert position to button index
|
||||||
@@ -141,8 +147,36 @@ namespace esphome {
|
|||||||
switch (uart_received_bytes[4]) {
|
switch (uart_received_bytes[4]) {
|
||||||
case TOUCH_STATE_RELEASE:
|
case TOUCH_STATE_RELEASE:
|
||||||
case TOUCH_STATE_MULTI_TOUCH:
|
case TOUCH_STATE_MULTI_TOUCH:
|
||||||
|
return uart_received_bytes[5];
|
||||||
|
|
||||||
case TOUCH_STATE_SWIPE_LEFT:
|
case TOUCH_STATE_SWIPE_LEFT:
|
||||||
case TOUCH_STATE_SWIPE_RIGHT:
|
case TOUCH_STATE_SWIPE_RIGHT:
|
||||||
|
// uart_received_bytes[5] indicates swipe direction:
|
||||||
|
// 12 = find last touch position (scan right to left)
|
||||||
|
// 13 = find first touch position (scan left to right)
|
||||||
|
// Bytes 6-7 contain a 10-bit bitmap of touch positions:
|
||||||
|
// Byte 7: bits 0-7 represent positions 1-8
|
||||||
|
// Byte 6: bits 0-1 represent positions 9-10
|
||||||
|
switch (uart_received_bytes[5]) {
|
||||||
|
case 12:
|
||||||
|
for (uint8_t i = 10; i > 0; i--) {
|
||||||
|
if (i > 8
|
||||||
|
? uart_received_bytes[6] & (1 << (i - 9))
|
||||||
|
: uart_received_bytes[7] & (1 << (i - 1))) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
for (uint8_t i = 1; i <= 10; i++) {
|
||||||
|
if (i > 8
|
||||||
|
? uart_received_bytes[6] & (1 << (i - 9))
|
||||||
|
: uart_received_bytes[7] & (1 << (i - 1))) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
return uart_received_bytes[5];
|
return uart_received_bytes[5];
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -152,8 +186,10 @@ namespace esphome {
|
|||||||
|
|
||||||
int TxUltimateEasy::get_touch_state(const std::array<int, UART_RECEIVED_BYTES_SIZE> &uart_received_bytes) {
|
int TxUltimateEasy::get_touch_state(const std::array<int, UART_RECEIVED_BYTES_SIZE> &uart_received_bytes) {
|
||||||
int state = uart_received_bytes[4];
|
int state = uart_received_bytes[4];
|
||||||
if (state == TOUCH_STATE_PRESS && uart_received_bytes[5] != 0) state = TOUCH_STATE_RELEASE;
|
if (state == TOUCH_STATE_PRESS && uart_received_bytes[5] != 0)
|
||||||
if (state == TOUCH_STATE_RELEASE && uart_received_bytes[5] == TOUCH_STATE_MULTI_TOUCH) state = TOUCH_STATE_MULTI_TOUCH;
|
state = TOUCH_STATE_RELEASE;
|
||||||
|
if (state == TOUCH_STATE_RELEASE && uart_received_bytes[5] == TOUCH_STATE_MULTI_TOUCH)
|
||||||
|
state = TOUCH_STATE_MULTI_TOUCH;
|
||||||
if (state == TOUCH_STATE_SWIPE) {
|
if (state == TOUCH_STATE_SWIPE) {
|
||||||
state = (uart_received_bytes[5] == TOUCH_STATE_SWIPE_RIGHT) ? TOUCH_STATE_SWIPE_RIGHT :
|
state = (uart_received_bytes[5] == TOUCH_STATE_SWIPE_RIGHT) ? TOUCH_STATE_SWIPE_RIGHT :
|
||||||
(uart_received_bytes[5] == TOUCH_STATE_SWIPE_LEFT) ? TOUCH_STATE_SWIPE_LEFT : state;
|
(uart_received_bytes[5] == TOUCH_STATE_SWIPE_LEFT) ? TOUCH_STATE_SWIPE_LEFT : state;
|
||||||
@@ -195,3 +231,5 @@ namespace esphome {
|
|||||||
|
|
||||||
} // namespace tx_ultimate_easy
|
} // namespace tx_ultimate_easy
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
||||||
|
#endif // TX_ULTIMATE_EASY_CORE_HW_TOUCH
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
// tx_ultimate_easy.h
|
// tx_ultimate_easy_touch.h
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef TX_ULTIMATE_EASY_CORE_HW_TOUCH
|
||||||
|
|
||||||
#include "esphome/core/automation.h"
|
#include "esphome/core/automation.h"
|
||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/components/uart/uart.h"
|
#include "esphome/components/uart/uart.h"
|
||||||
@@ -31,9 +33,6 @@ namespace esphome {
|
|||||||
constexpr int VALID_DATA_BYTE_2 = 0x01;
|
constexpr int VALID_DATA_BYTE_2 = 0x01;
|
||||||
constexpr int VALID_DATA_BYTE_3 = 0x02;
|
constexpr int VALID_DATA_BYTE_3 = 0x02;
|
||||||
|
|
||||||
// Log tag
|
|
||||||
static const char *TAG = "tx_ultimate_easy";
|
|
||||||
|
|
||||||
struct TouchPoint {
|
struct TouchPoint {
|
||||||
uint8_t button = 0;
|
uint8_t button = 0;
|
||||||
int8_t x = -1;
|
int8_t x = -1;
|
||||||
@@ -84,3 +83,5 @@ namespace esphome {
|
|||||||
|
|
||||||
} // namespace tx_ultimate_easy
|
} // namespace tx_ultimate_easy
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
||||||
|
#endif // TX_ULTIMATE_EASY_CORE_HW_TOUCH
|
||||||
@@ -1 +1 @@
|
|||||||
2024.12.25
|
2025.10.1
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
version: 2024.12.25
|
version: 2025.10.1
|
||||||
|
|||||||
Reference in New Issue
Block a user