Compare commits
169 Commits
v2024.12.2
...
latest
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
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
|
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -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
|
|
||||||
...
|
...
|
||||||
@@ -2,32 +2,22 @@
|
|||||||
##### 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 - Add-on - BLE Proxy #####
|
##### Purpose: ESPHome Core - Add-on - BLE Proxy (REMOVED) #####
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
##### Author: edwardtfn - https://github.com/edwardtfn - https://buymeacoffee.com/edwardfirmo #####
|
##### Author: edwardtfn - https://github.com/edwardtfn - https://buymeacoffee.com/edwardfirmo #####
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
##### NOTE: #####
|
##### REMOVAL NOTICE: #####
|
||||||
##### - Make changes ONLY if absolutely necessary and you have the required knowledge. #####
|
##### This package has been removed. Please update your configuration. #####
|
||||||
##### - For normal system use, modifications to this file are NOT required. #####
|
##### Add BLE proxy functionality directly in your YAML configuration instead: #####
|
||||||
|
##### bluetooth_proxy: #####
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
---
|
---
|
||||||
bluetooth_proxy:
|
# Trigger the error at compile time
|
||||||
|
|
||||||
esphome:
|
|
||||||
platformio_options:
|
|
||||||
build_flags:
|
|
||||||
- -D TX_ULTIMATE_EASY_ADDON_BLE_PROXY
|
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- id: !extend dump_config_list_packages
|
- id: force_compilation_error
|
||||||
then:
|
then:
|
||||||
- script.wait: dump_config
|
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
// Check for requirements
|
#error "The package TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml has been removed." \
|
||||||
#if !defined(TX_ULTIMATE_EASY_CORE)
|
"Please remove this package from your configuration and add" \
|
||||||
#error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required."
|
"'bluetooth_proxy:' directly to your YAML instead."
|
||||||
#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://github.com/edwardtfn/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,10 @@ 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
|
speed: 50
|
||||||
- pulse:
|
- pulse:
|
||||||
name: "Pulse"
|
name: "Pulse"
|
||||||
@@ -107,36 +143,118 @@ light:
|
|||||||
- id: light_full
|
- id: light_full
|
||||||
from: 0
|
from: 0
|
||||||
to: 27
|
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);
|
||||||
|
|
||||||
- id: light_us
|
- &light_partition_with_effects_us
|
||||||
name: Light
|
id: light_us
|
||||||
<<: *light_partition_with_effects
|
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
|
||||||
|
- pulse:
|
||||||
|
name: "Pulse"
|
||||||
|
transition_length: 1s
|
||||||
|
update_interval: 1s
|
||||||
|
- pulse:
|
||||||
|
name: "Pulse - Slow"
|
||||||
|
transition_length: 2s
|
||||||
|
update_interval: 2s
|
||||||
|
- addressable_scan:
|
||||||
|
name: "Scan"
|
||||||
|
move_interval: 100ms
|
||||||
|
scan_width: 3
|
||||||
|
- addressable_twinkle:
|
||||||
|
name: "Twinkle"
|
||||||
|
twinkle_probability: 5%
|
||||||
|
progress_interval: 4ms
|
||||||
|
- addressable_random_twinkle:
|
||||||
|
name: "Random Twinkle"
|
||||||
|
twinkle_probability: 20%
|
||||||
|
progress_interval: 32ms
|
||||||
|
- addressable_fireworks:
|
||||||
|
name: "Fireworks"
|
||||||
|
update_interval: 32ms
|
||||||
|
spark_probability: 10%
|
||||||
|
use_random_color: false
|
||||||
|
fade_out_rate: 120
|
||||||
|
- addressable_flicker:
|
||||||
|
name: "Flicker"
|
||||||
|
update_interval: 16ms
|
||||||
|
intensity: 5%
|
||||||
|
- random:
|
||||||
|
name: "Random"
|
||||||
segments:
|
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 +264,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 +324,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 +600,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
|
||||||
|
...
|
||||||
150
README.md
150
README.md
@@ -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:
|
|
||||||
- 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
|
||||||
|
|
||||||
|
|||||||
@@ -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.27
|
2025.10.1
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
version: 2024.12.27
|
version: 2025.10.1
|
||||||
|
|||||||
Reference in New Issue
Block a user