mirror of
https://github.com/randybb/esphome-configs.git
synced 2026-10-14 08:35:12 +02:00
Compare commits
73
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3374ed6ad8 | ||
|
|
e5f9c5813e | ||
|
|
2b66f1a60d | ||
|
|
05060756e3 | ||
|
|
7cc90187d1 | ||
|
|
26a09b37bc | ||
|
|
4c45ebdc4a | ||
|
|
2ad74b9d05 | ||
|
|
b1b57818df | ||
|
|
1a83052d90 | ||
|
|
8eae480253 | ||
|
|
5fdacb82df | ||
|
|
9eb5cd9155 | ||
|
|
b8f8649833 | ||
|
|
5fdea643a7 | ||
|
|
4bbf26fc87 | ||
|
|
427e9ac136 | ||
|
|
005c9903bf | ||
|
|
db57574497 | ||
|
|
fd7a4c98b5 | ||
|
|
2e8b678072 | ||
|
|
3f9a8c3117 | ||
|
|
38ede7fab6 | ||
|
|
ad9aeea346 | ||
|
|
3a397cfb4b | ||
|
|
6fd5ee1fa7 | ||
|
|
eb25302e9b | ||
|
|
34929a38c7 | ||
|
|
0536e91fd1 | ||
|
|
7374ddf4d6 | ||
|
|
a005b940b2 | ||
|
|
46cf3b1fe8 | ||
|
|
bb76912023 | ||
|
|
831d88689d | ||
|
|
170fd69274 | ||
|
|
89763817f6 | ||
|
|
03ca4e98b5 | ||
|
|
fb66547dd1 | ||
|
|
725c400de6 | ||
|
|
7517c301ac | ||
|
|
422b334582 | ||
|
|
2f5e438424 | ||
|
|
6a3002d9b7 | ||
|
|
6845679bc0 | ||
|
|
a3950d9f17 | ||
|
|
0d6aa6e3d7 | ||
|
|
271a5a5a54 | ||
|
|
c5ab280725 | ||
|
|
1a2aec5d01 | ||
|
|
882428e491 | ||
|
|
20f6db5a70 | ||
|
|
b8738b39e0 | ||
|
|
7ee975875a | ||
|
|
dd508aec99 | ||
|
|
e13be73596 | ||
|
|
b523963944 | ||
|
|
6ca813fb64 | ||
|
|
d80abdbb90 | ||
|
|
29b375df68 | ||
|
|
5db5987405 | ||
|
|
dec5e5de0a | ||
|
|
88e1214058 | ||
|
|
61032ad248 | ||
|
|
148c51c4df | ||
|
|
cc2ab4c467 | ||
|
|
504aa06d10 | ||
|
|
4b6544adfa | ||
|
|
6a51099789 | ||
|
|
369578a63a | ||
|
|
bdf49db1c2 | ||
|
|
349f699572 | ||
|
|
329830e553 | ||
|
|
d813717d2c |
No files matched your search
@@ -10,35 +10,42 @@ jobs:
|
|||||||
name: YAML lint
|
name: YAML lint
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v7
|
||||||
|
|
||||||
- name: Get changed YAML files
|
- name: Get changed YAML files
|
||||||
id: changed
|
id: changed
|
||||||
uses: tj-actions/changed-files@v46
|
uses: tj-actions/changed-files@v47
|
||||||
with:
|
with:
|
||||||
files: "**/*.yaml"
|
files: "**/*.yaml"
|
||||||
|
|
||||||
- uses: ibiqlik/action-yamllint@v3
|
# yamllint straight from pip: Gitea's runner image doesn't ship it like GitHub's does
|
||||||
|
- name: Lint changed YAML files
|
||||||
if: steps.changed.outputs.any_changed == 'true'
|
if: steps.changed.outputs.any_changed == 'true'
|
||||||
with:
|
env:
|
||||||
config_file: .yamllint.yml
|
PIP_BREAK_SYSTEM_PACKAGES: "1"
|
||||||
file_or_dir: ${{ steps.changed.outputs.all_changed_files }}
|
run: |
|
||||||
|
pip install --ignore-installed yamllint
|
||||||
|
yamllint -c .yamllint.yml -f parsable ${{ steps.changed.outputs.all_changed_files }}
|
||||||
|
|
||||||
validate:
|
validate:
|
||||||
name: ESPHome config validation
|
name: ESPHome config validation
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v7
|
||||||
|
|
||||||
- name: Get changed device configs
|
- name: Get changed device configs
|
||||||
id: changed
|
id: changed
|
||||||
uses: tj-actions/changed-files@v46
|
uses: tj-actions/changed-files@v47
|
||||||
with:
|
with:
|
||||||
files: "mcu-*.yaml"
|
files: "mcu-*.yaml"
|
||||||
|
|
||||||
- name: Install ESPHome (dev)
|
- name: Install ESPHome (dev)
|
||||||
if: steps.changed.outputs.any_changed == 'true'
|
if: steps.changed.outputs.any_changed == 'true'
|
||||||
run: pip install git+https://github.com/esphome/esphome.git@dev
|
# Gitea's runner image marks the system Python as externally managed (PEP 668)
|
||||||
|
# and has Debian packages pip can't uninstall (pyparsing), so don't touch them
|
||||||
|
env:
|
||||||
|
PIP_BREAK_SYSTEM_PACKAGES: "1"
|
||||||
|
run: pip install --ignore-installed git+https://github.com/esphome/esphome.git@dev
|
||||||
|
|
||||||
- name: Prepare secrets
|
- name: Prepare secrets
|
||||||
if: steps.changed.outputs.any_changed == 'true'
|
if: steps.changed.outputs.any_changed == 'true'
|
||||||
@@ -48,6 +55,8 @@ jobs:
|
|||||||
if: steps.changed.outputs.any_changed == 'true'
|
if: steps.changed.outputs.any_changed == 'true'
|
||||||
run: |
|
run: |
|
||||||
for f in ${{ steps.changed.outputs.all_changed_files }}; do
|
for f in ${{ steps.changed.outputs.all_changed_files }}; do
|
||||||
|
# zephyr: needs the esphomeplatformzephyr fork, upstream doesn't know it yet
|
||||||
|
if grep -q '^zephyr:' "$f"; then echo "Skipping $f (zephyr fork)"; continue; fi
|
||||||
echo "Validating $f..."
|
echo "Validating $f..."
|
||||||
esphome config "$f"
|
esphome config "$f"
|
||||||
done
|
done
|
||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
# This is an example and may include too much for your use-case.
|
# This is an example and may include too much for your use-case.
|
||||||
# You can modify this file to suit your needs.
|
# You can modify this file to suit your needs.
|
||||||
/.claude/
|
/.claude/
|
||||||
/.esphome/
|
.esphome/
|
||||||
/secrets.yaml
|
/secrets.yaml
|
||||||
/archive/
|
/archive/
|
||||||
/trash/
|
/trash/
|
||||||
|
|||||||
@@ -25,3 +25,7 @@ rules:
|
|||||||
|
|
||||||
comments:
|
comments:
|
||||||
require-starting-space: false
|
require-starting-space: false
|
||||||
|
|
||||||
|
# Aligned values (e.g. the bedroom lamp presets) are intentional
|
||||||
|
colons:
|
||||||
|
max-spaces-after: -1
|
||||||
+28781
File diff suppressed because it is too large.
Load diff
+86576
File diff suppressed because it is too large.
Load diff
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1194" height="240" fill="none" viewBox="0 0 1194 240"><g clip-path="url(#clip0_2_63)"><path fill="#18BCF2" d="M240 219C240 227.24 233.24 234 225 234H15C6.76 234 0 227.24 0 219V129C0 120.76 4.78 109.22 10.6 103.4L109.4 4.61999C115.24 -1.22001 124.78 -1.22001 130.62 4.61999L229.4 103.4C235.24 109.24 240 120.76 240 129V219Z"/><path fill="#F2F4F9" d="M160 78.66H80C76.68 78.66 74 81.34 74 84.66V234H86V90.66H154V102.66H104C100.68 102.66 98 105.34 98 108.66V132.66C98 135.98 100.68 138.66 104 138.66H154V150.66H104C100.68 150.66 98 153.34 98 156.66V180.66C98 183.98 100.68 186.66 104 186.66H154V198.66H104C100.68 198.66 98 201.34 98 204.66C98 207.98 100.68 210.66 104 210.66H160C163.32 210.66 166 207.98 166 204.66V180.66C166 177.34 163.32 174.66 160 174.66H110V162.66H160C163.32 162.66 166 159.98 166 156.66V132.66C166 129.34 163.32 126.66 160 126.66H110V114.66H160C163.32 114.66 166 111.98 166 108.66V84.66C166 81.34 163.32 78.66 160 78.66Z"/><path fill="#F2F4F9" d="M423 167.61V190.11H336V49.95H423V72.63H359.82V108.91H416.26V130.01H359.82V167.61H423Z"/><path fill="#F2F4F9" d="M491.08 47.41C503.9 47.41 514.54 50.53 523.04 56.79C531.54 63.03 536.76 71.39 538.7 81.83L516.3 87.93C515.04 81.93 512.12 77.31 507.54 74.05C502.94 70.81 497.28 69.17 490.52 69.17C483.26 69.17 477.52 70.91 473.28 74.37C469.02 77.83 466.9 82.45 466.9 88.19C466.9 97.25 472.52 103.13 483.78 105.81L506.66 111.53C518.48 114.59 527.32 119.45 533.2 126.11C539.08 132.77 542.02 140.97 542.02 150.71C542.02 163.21 537.48 173.31 528.42 181.03C519.36 188.75 507.24 192.61 492.04 192.61C478.36 192.61 466.78 189.39 457.36 182.95C448.04 176.27 442.54 167.45 440.86 156.51L463.26 150.69C464.08 156.87 467.16 161.73 472.5 165.23C477.84 168.73 484.64 170.47 492.9 170.47C501.16 170.47 507.08 168.79 511.6 165.45C516.14 162.11 518.4 157.57 518.4 151.81C518.4 142.81 512.78 136.87 501.52 133.99L478.64 128.45C466.88 125.77 458.06 120.99 452.16 114.15C446.26 107.31 443.3 98.95 443.3 89.07C443.3 76.69 447.7 66.65 456.48 58.93C465.26 51.21 476.8 47.35 491.12 47.35L491.08 47.41Z"/><path fill="#F2F4F9" d="M666.1 95.61C666.1 109.37 661.92 120.49 653.58 128.99C645.24 137.49 634 141.75 619.88 141.75H588.38V190.13H564.56V49.95H620.06C634.3 49.95 645.54 54.07 653.76 62.27C661.98 70.49 666.08 81.59 666.08 95.59L666.1 95.61ZM641.16 95.05C641.16 87.99 638.96 82.25 634.56 77.85C630.16 73.45 623.92 71.25 615.86 71.25H588.4V120.85H615.5C623.74 120.85 630.1 118.51 634.54 113.81C638.98 109.13 641.2 102.87 641.2 95.05H641.16Z"/><path fill="#F2F4F9" d="M687.38 49.95H711.2V108.55L772.98 108.73V49.95H796.98V190.11H772.98V129.83L711.2 129.65V190.11H687.38V49.95Z"/><path fill="#F2F4F9" d="M868.6 92.79C883.1 92.79 894.92 97.45 904.04 106.75C913.16 116.07 917.72 128.03 917.72 142.65C917.72 157.27 913.16 169.15 904.04 178.47C894.92 187.79 883.1 192.43 868.6 192.43C854.1 192.43 842.1 187.77 832.98 178.47C823.86 169.15 819.3 157.23 819.3 142.65C819.3 128.07 823.86 115.97 832.98 106.69C842.1 97.41 853.98 92.77 868.6 92.77V92.79ZM868.6 172.01C876.34 172.01 882.64 169.27 887.5 163.81C892.34 158.35 894.76 151.23 894.76 142.49C894.76 133.75 892.34 126.67 887.5 121.25C882.66 115.85 876.36 113.15 868.6 113.15C860.84 113.15 854.26 115.85 849.38 121.25C844.5 126.65 842.06 133.73 842.06 142.49C842.06 151.25 844.5 158.35 849.38 163.81C854.26 169.27 860.66 172.01 868.6 172.01Z"/><path fill="#F2F4F9" d="M1081.6 129.83V190.11H1059.56V133.29C1059.56 126.73 1057.88 121.61 1054.5 117.91C1051.12 114.23 1046.54 112.37 1040.72 112.37C1034.54 112.37 1029.6 114.39 1025.9 118.41C1022.22 122.45 1020.36 128.09 1020.36 135.33V190.09H998.04V133.27C998.04 126.71 996.4 121.59 993.12 117.89C989.84 114.21 985.3 112.35 979.48 112.35C973.3 112.35 968.32 114.37 964.58 118.39C960.84 122.41 958.96 128.07 958.96 135.31V190.07H936.28V95.39H957.38L958.14 104.49C963.64 96.43 972.6 92.39 985.04 92.39C992.28 92.39 998.58 93.89 1003.88 96.89C1009.2 99.89 1013.22 104.27 1015.98 110.01C1018.3 104.51 1022.12 100.19 1027.46 97.07C1032.8 93.95 1039.16 92.39 1046.54 92.39C1057.28 92.39 1065.82 95.71 1072.14 102.33C1078.46 108.95 1081.6 118.11 1081.6 129.79V129.83Z"/><path fill="#F2F4F9" d="M1193.54 151.11H1120.98C1121.74 158.23 1124.42 163.67 1129.04 167.43C1133.66 171.19 1139.54 173.05 1146.66 173.05C1158.22 173.05 1166.32 168.23 1170.94 158.61L1189.88 166.11C1186.32 174.43 1180.7 180.93 1173.06 185.61C1165.4 190.29 1156.6 192.65 1146.66 192.65C1132.66 192.65 1121.3 188.07 1112.58 178.91C1103.86 169.75 1099.5 157.73 1099.5 142.87C1099.5 128.01 1103.9 115.91 1112.68 106.59C1121.46 97.27 1132.94 92.63 1147.14 92.63C1161.34 92.63 1172.3 97.23 1180.8 106.41C1189.3 115.59 1193.56 127.69 1193.56 142.69V151.13L1193.54 151.11ZM1121.36 135.17H1170.48C1170.04 127.49 1167.72 121.63 1163.5 117.59C1159.28 113.55 1153.6 111.55 1146.48 111.55C1139.36 111.55 1133.66 113.59 1129.24 117.69C1124.8 121.79 1122.18 127.61 1121.36 135.17Z"/></g><defs><clipPath id="clip0_2_63"><rect width="1193.56" height="240" fill="#fff"/></cliLine truncated
|
|
||||||
|
Before Width: | Height: | Size: 4.9 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_2" data-name="Layer 2" viewBox="0 0 681.98 201.98"><defs><style>.cls-1{fill:none;stroke:#1d2126;stroke-miterlimit:10;stroke-width:1.01px}.cls-2{fill:#1d2126}.cls-2,.cls-3,.cls-4{stroke-width:0}.cls-3{fill:#f2f4f9}.cls-4{fill:#18bcf2}</style></defs><g id="Layer_1-2" data-name="Layer 1"><g><g><rect width="680.97" height="200.97" x=".51" y=".51" class="cls-3" rx="40.48" ry="40.48"/><rect width="680.97" height="200.97" x=".51" y=".51" class="cls-1" rx="40.48" ry="40.48"/></g><g><path d="M236.13,43.11v26.53h-5.29v-14.5l-5.68,14.5h-5.08l-5.61-14.4v14.4h-5.12v-26.53h5.12l8.16,20.27,8.21-20.27h5.29Z" class="cls-4"/><path d="M259.54,63.84h-9.04l-2.02,5.8h-5.59l9.51-26.53h5.33l9.47,26.53h-5.7l-1.97-5.8ZM258,59.34l-2.95-8.7-2.99,8.7h5.94Z" class="cls-4"/><path d="M296.93,56.42c.02,1.89-.3,3.66-.98,5.31s-1.61,3.06-2.8,4.22-2.61,2.07-4.26,2.73-3.4.98-5.26.96h-9.65v-26.53h9.65c2.43-.04,4.66.52,6.71,1.68s3.67,2.76,4.86,4.82,1.78,4.33,1.74,6.81ZM291.25,56.42c0-2.46-.71-4.46-2.12-5.99s-3.27-2.29-5.58-2.29h-4.22v16.52h4.22c2.34,0,4.21-.75,5.61-2.26s2.09-3.5,2.09-5.99Z" class="cls-4"/><path d="M321.38,64.59v5.04h-16.7v-26.53h16.7v5.1h-11.34v5.66h10.07v4.75h-10.07v5.98h11.34Z" class="cls-4"/><path d="M348.35,48.17v6.1h9.58l-.04,4.82h-9.54v10.55h-5.36v-26.53h16.73l-.04,5.06h-11.34Z" class="cls-4"/><path d="M378.62,42.64c1.9,0,3.66.34,5.27,1.03s2.99,1.63,4.11,2.84,2,2.66,2.63,4.35.94,3.52.94,5.49c.02,1.95-.28,3.77-.91,5.48s-1.52,3.17-2.65,4.39-2.52,2.17-4.15,2.86-3.39,1.03-5.27,1c-2.5.04-4.74-.54-6.72-1.72s-3.52-2.82-4.6-4.92-1.6-4.45-1.56-7.05c-.02-1.95.28-3.77.91-5.48s1.51-3.18,2.65-4.39,2.51-2.17,4.13-2.87,3.37-1.03,5.23-1ZM378.65,64.82c2.24,0,4.01-.76,5.32-2.28s1.96-3.58,1.96-6.2-.65-4.71-1.95-6.22-3.08-2.27-5.33-2.27-4.03.76-5.33,2.27-1.95,3.59-1.95,6.22.65,4.71,1.95,6.21,3.08,2.26,5.33,2.26Z" class="cls-4"/><path d="M419.5,69.64h-6.01l-4.08-9.58h-4.89v9.58h-5.36v-26.53h10.21c3.28.01,5.76.74,7.44,2.19s2.51,3.55,2.51,6.3c0,1.79-.39,3.34-1.17,4.65s-1.89,2.28-3.33,2.91l4.68,10.48ZM413.63,51.6c0-1.15-.36-2.05-1.07-2.72s-1.78-.99-3.18-.99h-4.85v7.49h4.85c1.41,0,2.47-.34,3.18-1.01s1.07-1.6,1.07-2.77Z" class="cls-4"/></g><g><path d="M251.92,146.83v11.25h-43.5v-70.08h43.5v11.34h-31.59v18.14h28.22v10.55h-28.22v18.8h31.59Z" class="cls-2"/><path d="M285,86.74c6.41,0,11.73,1.56,15.98,4.69,4.25,3.12,6.86,7.3,7.83,12.52l-11.2,3.05c-.62-3-2.09-5.31-4.38-6.94-2.3-1.62-5.13-2.44-8.51-2.44-3.62,0-6.5.87-8.62,2.6s-3.19,4.04-3.19,6.91c0,4.53,2.81,7.47,8.44,8.81l11.44,2.86c5.91,1.53,10.33,3.96,13.27,7.29s4.41,7.43,4.41,12.3c0,6.25-2.27,11.3-6.8,15.16-4.53,3.86-10.59,5.79-18.19,5.79-6.84,0-12.62-1.61-17.34-4.83-4.66-3.34-7.41-7.75-8.25-13.22l11.2-2.91c.41,3.09,1.95,5.52,4.62,7.27,2.67,1.75,6.07,2.62,10.2,2.62s7.09-.84,9.35-2.51c2.27-1.67,3.4-3.94,3.4-6.82,0-4.5-2.81-7.47-8.44-8.91l-11.44-2.77c-5.88-1.34-10.29-3.73-13.24-7.15s-4.43-7.6-4.43-12.54c0-6.19,2.2-11.21,6.59-15.07,4.39-3.86,10.16-5.79,17.32-5.79Z" class="cls-2"/><path d="M371.55,110.83c0,6.88-2.09,12.44-6.26,16.69-4.17,4.25-9.79,6.38-16.85,6.38h-15.75v24.19h-11.91v-70.08h27.75c7.12,0,12.74,2.06,16.85,6.16,4.11,4.11,6.16,9.66,6.16,16.66ZM359.08,110.55c0-3.53-1.1-6.4-3.3-8.6s-5.32-3.3-9.35-3.3h-13.73v24.8h13.55c4.12,0,7.3-1.17,9.52-3.52s3.33-5.47,3.33-9.38Z" class="cls-2"/><path d="M381.23,88h11.91v29.3l30.89.09v-29.39h12v70.08h-12v-30.14l-30.89-.09v30.23h-11.91v-70.08Z" class="cls-2"/><path d="M470.88,109.43c7.25,0,13.16,2.33,17.72,6.98,4.56,4.66,6.84,10.64,6.84,17.95s-2.28,13.25-6.84,17.91c-4.56,4.66-10.47,6.98-17.72,6.98s-13.25-2.33-17.81-6.98c-4.56-4.66-6.84-10.62-6.84-17.91s2.28-13.34,6.84-17.98,10.5-6.96,17.81-6.96ZM470.88,149.04c3.88,0,7.02-1.37,9.45-4.1,2.42-2.73,3.63-6.29,3.63-10.66s-1.21-7.91-3.63-10.62c-2.42-2.7-5.57-4.05-9.45-4.05s-7.17,1.35-9.61,4.05c-2.44,2.7-3.66,6.24-3.66,10.62s1.22,7.93,3.66,10.66c2.44,2.73,5.64,4.1,9.61,4.1Z" class="cls-2"/><path d="M576.42,127.94v30.14h-11.02v-28.41c0-3.28-.84-5.84-2.53-7.69-1.69-1.84-3.98-2.77-6.89-2.77-3.09,0-5.56,1.01-7.41,3.02s-2.77,4.84-2.77,8.46v27.38h-11.16v-28.41c0-3.28-.82-5.84-2.46-7.69-1.64-1.84-3.91-2.77-6.82-2.77-3.09,0-5.58,1.01-7.45,3.02s-2.81,4.84-2.81,8.46v27.38h-11.34v-47.34h10.55l.38,4.55c2.75-4.03,7.23-6.05,13.45-6.05,3.62,0,6.77.75,9.42,2.25s4.67,3.69,6.05,6.56c1.16-2.75,3.07-4.91,5.74-6.47,2.67-1.56,5.85-2.34,9.54-2.34,5.38,0,9.64,1.66,12.8,4.97,3.16,3.31,4.73,7.89,4.73,13.73Z" class="cls-2"/><path d="M631.43,138.58h-36.28c.38,3.56,1.72,6.28,4.03,8.16s5.25,2.81,8.81,2.81c5.78,0,9.83-2.41,12.14-7.22l9.47,3.75c-1.78,4.16-4.59,7.41-8.41,9.75s-8.23,3.52-13.2,3.52c-7,0-12.68-2.29-17.04-6.87-4.36-4.58-6.54-10.59-6.54-18.02s2.2-13.48,6.59-18.14c4.39-4.66,10.13-6.98,17.23-6.98s12.58,2.3,16.83,6.89,6.38,10.64,6.38,18.14v4.22ZM595.34,130.61h24.56c-.22-3.84-1.38-6.77-3.49-8.79s-4.95-3.02-8.51-3.02-6.41,1.02-8.62,3.07c-2.22,2.05-3.53,4.96-3.94,8.74Z" class="cls-2"/></g><g><path d="M170.55,153.49c0,4.12-3.38,7.5-7.5,7.5H58.05c-4.12,0-7.5-3.38-7.5-7.5v-45c0-4.12,2.39-9.89,5.3-12Line truncated
|
||||||
|
After Width: | Height: | Size: 5.3 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_2" data-name="Layer 2" viewBox="0 0 681.98 201.98"><defs><style>.cls-1{fill:#1d2126}.cls-1,.cls-2,.cls-3{stroke-width:0}.cls-2{fill:#f2f4f9}.cls-3{fill:#18bcf2}.cls-4{fill:none;stroke:#f2f4f9;stroke-miterlimit:10;stroke-width:1.01px}</style></defs><g id="Layer_1-2" data-name="Layer 1"><g><g><rect width="680.97" height="200.97" x=".51" y=".51" class="cls-1" rx="40.48" ry="40.48"/><rect width="680.97" height="200.97" x=".51" y=".51" class="cls-4" rx="40.48" ry="40.48"/></g><g><path d="M236.13,43.11v26.53h-5.29v-14.5l-5.68,14.5h-5.08l-5.61-14.4v14.4h-5.12v-26.53h5.12l8.16,20.27,8.21-20.27h5.29Z" class="cls-3"/><path d="M259.54,63.84h-9.04l-2.02,5.8h-5.59l9.51-26.53h5.33l9.47,26.53h-5.7l-1.97-5.8ZM258,59.34l-2.95-8.7-2.99,8.7h5.94Z" class="cls-3"/><path d="M296.93,56.42c.02,1.89-.3,3.66-.98,5.31s-1.61,3.06-2.8,4.22-2.61,2.07-4.26,2.73-3.4.98-5.26.96h-9.65v-26.53h9.65c2.43-.04,4.66.52,6.71,1.68s3.67,2.76,4.86,4.82,1.78,4.33,1.74,6.81ZM291.25,56.42c0-2.46-.71-4.46-2.12-5.99s-3.27-2.29-5.58-2.29h-4.22v16.52h4.22c2.34,0,4.21-.75,5.61-2.26s2.09-3.5,2.09-5.99Z" class="cls-3"/><path d="M321.38,64.59v5.04h-16.7v-26.53h16.7v5.1h-11.34v5.66h10.07v4.75h-10.07v5.98h11.34Z" class="cls-3"/><path d="M348.35,48.17v6.1h9.58l-.04,4.82h-9.54v10.55h-5.36v-26.53h16.73l-.04,5.06h-11.34Z" class="cls-3"/><path d="M378.62,42.64c1.9,0,3.66.34,5.27,1.03s2.99,1.63,4.11,2.84,2,2.66,2.63,4.35.94,3.52.94,5.49c.02,1.95-.28,3.77-.91,5.48s-1.52,3.17-2.65,4.39-2.52,2.17-4.15,2.86-3.39,1.03-5.27,1c-2.5.04-4.74-.54-6.72-1.72s-3.52-2.82-4.6-4.92-1.6-4.45-1.56-7.05c-.02-1.95.28-3.77.91-5.48s1.51-3.18,2.65-4.39,2.51-2.17,4.13-2.87,3.37-1.03,5.23-1ZM378.65,64.82c2.24,0,4.01-.76,5.32-2.28s1.96-3.58,1.96-6.2-.65-4.71-1.95-6.22-3.08-2.27-5.33-2.27-4.03.76-5.33,2.27-1.95,3.59-1.95,6.22.65,4.71,1.95,6.21,3.08,2.26,5.33,2.26Z" class="cls-3"/><path d="M419.5,69.64h-6.01l-4.08-9.58h-4.89v9.58h-5.36v-26.53h10.21c3.28.01,5.76.74,7.44,2.19s2.51,3.55,2.51,6.3c0,1.79-.39,3.34-1.17,4.65s-1.89,2.28-3.33,2.91l4.68,10.48ZM413.63,51.6c0-1.15-.36-2.05-1.07-2.72s-1.78-.99-3.18-.99h-4.85v7.49h4.85c1.41,0,2.47-.34,3.18-1.01s1.07-1.6,1.07-2.77Z" class="cls-3"/></g><g><path d="M251.92,146.83v11.25h-43.5v-70.08h43.5v11.34h-31.59v18.14h28.22v10.55h-28.22v18.8h31.59Z" class="cls-2"/><path d="M285,86.74c6.41,0,11.73,1.56,15.98,4.69,4.25,3.12,6.86,7.3,7.83,12.52l-11.2,3.05c-.62-3-2.09-5.31-4.38-6.94-2.3-1.62-5.13-2.44-8.51-2.44-3.62,0-6.5.87-8.62,2.6s-3.19,4.04-3.19,6.91c0,4.53,2.81,7.47,8.44,8.81l11.44,2.86c5.91,1.53,10.33,3.96,13.27,7.29s4.41,7.43,4.41,12.3c0,6.25-2.27,11.3-6.8,15.16-4.53,3.86-10.59,5.79-18.19,5.79-6.84,0-12.62-1.61-17.34-4.83-4.66-3.34-7.41-7.75-8.25-13.22l11.2-2.91c.41,3.09,1.95,5.52,4.62,7.27,2.67,1.75,6.07,2.62,10.2,2.62s7.09-.84,9.35-2.51c2.27-1.67,3.4-3.94,3.4-6.82,0-4.5-2.81-7.47-8.44-8.91l-11.44-2.77c-5.88-1.34-10.29-3.73-13.24-7.15s-4.43-7.6-4.43-12.54c0-6.19,2.2-11.21,6.59-15.07,4.39-3.86,10.16-5.79,17.32-5.79Z" class="cls-2"/><path d="M371.55,110.83c0,6.88-2.09,12.44-6.26,16.69-4.17,4.25-9.79,6.38-16.85,6.38h-15.75v24.19h-11.91v-70.08h27.75c7.12,0,12.74,2.06,16.85,6.16,4.11,4.11,6.16,9.66,6.16,16.66ZM359.08,110.55c0-3.53-1.1-6.4-3.3-8.6s-5.32-3.3-9.35-3.3h-13.73v24.8h13.55c4.12,0,7.3-1.17,9.52-3.52s3.33-5.47,3.33-9.38Z" class="cls-2"/><path d="M381.23,88h11.91v29.3l30.89.09v-29.39h12v70.08h-12v-30.14l-30.89-.09v30.23h-11.91v-70.08Z" class="cls-2"/><path d="M470.88,109.43c7.25,0,13.16,2.33,17.72,6.98,4.56,4.66,6.84,10.64,6.84,17.95s-2.28,13.25-6.84,17.91c-4.56,4.66-10.47,6.98-17.72,6.98s-13.25-2.33-17.81-6.98c-4.56-4.66-6.84-10.62-6.84-17.91s2.28-13.34,6.84-17.98,10.5-6.96,17.81-6.96ZM470.88,149.04c3.88,0,7.02-1.37,9.45-4.1,2.42-2.73,3.63-6.29,3.63-10.66s-1.21-7.91-3.63-10.62c-2.42-2.7-5.57-4.05-9.45-4.05s-7.17,1.35-9.61,4.05c-2.44,2.7-3.66,6.24-3.66,10.62s1.22,7.93,3.66,10.66c2.44,2.73,5.64,4.1,9.61,4.1Z" class="cls-2"/><path d="M576.42,127.94v30.14h-11.02v-28.41c0-3.28-.84-5.84-2.53-7.69-1.69-1.84-3.98-2.77-6.89-2.77-3.09,0-5.56,1.01-7.41,3.02s-2.77,4.84-2.77,8.46v27.38h-11.16v-28.41c0-3.28-.82-5.84-2.46-7.69-1.64-1.84-3.91-2.77-6.82-2.77-3.09,0-5.58,1.01-7.45,3.02s-2.81,4.84-2.81,8.46v27.38h-11.34v-47.34h10.55l.38,4.55c2.75-4.03,7.23-6.05,13.45-6.05,3.62,0,6.77.75,9.42,2.25s4.67,3.69,6.05,6.56c1.16-2.75,3.07-4.91,5.74-6.47,2.67-1.56,5.85-2.34,9.54-2.34,5.38,0,9.64,1.66,12.8,4.97,3.16,3.31,4.73,7.89,4.73,13.73Z" class="cls-2"/><path d="M631.43,138.58h-36.28c.38,3.56,1.72,6.28,4.03,8.16s5.25,2.81,8.81,2.81c5.78,0,9.83-2.41,12.14-7.22l9.47,3.75c-1.78,4.16-4.59,7.41-8.41,9.75s-8.23,3.52-13.2,3.52c-7,0-12.68-2.29-17.04-6.87-4.36-4.58-6.54-10.59-6.54-18.02s2.2-13.48,6.59-18.14c4.39-4.66,10.13-6.98,17.23-6.98s12.58,2.3,16.83,6.89,6.38,10.64,6.38,18.14v4.22ZM595.34,130.61h24.56c-.22-3.84-1.38-6.77-3.49-8.79s-4.95-3.02-8.51-3.02-6.41,1.02-8.62,3.07c-2.22,2.05-3.53,4.96-3.94,8.74Z" class="cls-2"/></g><g><path d="M170.55,153.49c0,4.12-3.38,7.5-7.5,7.5H58.05c-4.12,0-7.5-3.38-7.5-7.5v-45c0-4.12,2.39-9.89,5.3-12Line truncated
|
||||||
|
After Width: | Height: | Size: 5.3 KiB |
Submodule common/.esphome/external_components/b7dc7eea deleted from 16571e8a90.
+2
-2
@@ -24,8 +24,8 @@ text_sensor:
|
|||||||
# - <<: !include text_sensor/uptime.yaml
|
# - <<: !include text_sensor/uptime.yaml
|
||||||
- <<: !include text_sensor/wifi_info.yaml
|
- <<: !include text_sensor/wifi_info.yaml
|
||||||
|
|
||||||
# time:
|
time:
|
||||||
#. - <<: !include time/homeassistant.yaml
|
- <<: !include time/homeassistant.yaml
|
||||||
|
|
||||||
network:
|
network:
|
||||||
enable_ipv6: true
|
enable_ipv6: true
|
||||||
@@ -24,5 +24,8 @@ text_sensor:
|
|||||||
- <<: !include text_sensor/version.yaml
|
- <<: !include text_sensor/version.yaml
|
||||||
- <<: !include text_sensor/wifi_info.yaml
|
- <<: !include text_sensor/wifi_info.yaml
|
||||||
|
|
||||||
|
time:
|
||||||
|
- <<: !include time/homeassistant.yaml
|
||||||
|
|
||||||
network:
|
network:
|
||||||
enable_ipv6: true
|
enable_ipv6: true
|
||||||
@@ -23,5 +23,8 @@ text_sensor:
|
|||||||
- <<: !include text_sensor/version.yaml
|
- <<: !include text_sensor/version.yaml
|
||||||
- <<: !include text_sensor/wifi_info.yaml
|
- <<: !include text_sensor/wifi_info.yaml
|
||||||
|
|
||||||
|
time:
|
||||||
|
- <<: !include time/homeassistant.yaml
|
||||||
|
|
||||||
network:
|
network:
|
||||||
enable_ipv6: true
|
enable_ipv6: true
|
||||||
@@ -21,5 +21,8 @@ text_sensor:
|
|||||||
- <<: !include text_sensor/version.yaml
|
- <<: !include text_sensor/version.yaml
|
||||||
- <<: !include text_sensor/ethernet_info.yaml
|
- <<: !include text_sensor/ethernet_info.yaml
|
||||||
|
|
||||||
|
time:
|
||||||
|
- <<: !include time/homeassistant.yaml
|
||||||
|
|
||||||
network:
|
network:
|
||||||
enable_ipv6: true
|
enable_ipv6: true
|
||||||
@@ -27,3 +27,6 @@ text_sensor:
|
|||||||
- <<: !include text_sensor/git_ref.yaml
|
- <<: !include text_sensor/git_ref.yaml
|
||||||
- <<: !include text_sensor/version.yaml
|
- <<: !include text_sensor/version.yaml
|
||||||
- <<: !include text_sensor/wifi_info.yaml
|
- <<: !include text_sensor/wifi_info.yaml
|
||||||
|
|
||||||
|
time:
|
||||||
|
- <<: !include time/homeassistant.yaml
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
# ESP8266 core with LEAmDNS announcing the IPv6 addresses (AAAA, ff02::fb) from
|
||||||
|
# randybb/Arduino@mdns-ipv6-aaaa (esp8266/Arduino#9068); add next to common_esp8266.yaml.
|
||||||
|
# The device must not set 'toolchain: arduino' (no custom framework source there).
|
||||||
|
# Drop once it's upstream and in an ESPHome release.
|
||||||
|
esp8266:
|
||||||
|
toolchain: platformio
|
||||||
|
framework:
|
||||||
|
version: 3.1.2
|
||||||
|
source: https://github.com/randybb/Arduino.git#mdns-ipv6-aaaa
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
# IPv6-only IoT network (SLAAC, no DHCPv4); add next to a common package:
|
||||||
|
# packages:
|
||||||
|
# common: !include common/common.yaml
|
||||||
|
# ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
# Ethernet devices use common/ipv6_only_eth.yaml (this without the WiFi part)
|
||||||
|
packages:
|
||||||
|
base: !include ipv6_only_eth.yaml
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
networks:
|
||||||
|
- id: !extend wifi_iot
|
||||||
|
ssid: !secret wifi_ssid_ipv6
|
||||||
|
password: !secret wifi_password_ipv6
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
# IPv6-only IoT network (SLAAC, no DHCPv4) for ethernet devices; add next to a common package:
|
||||||
|
# packages:
|
||||||
|
# common_eth: !include common/common_eth.yaml
|
||||||
|
# ipv6_only: !include common/ipv6_only_eth.yaml
|
||||||
|
# WiFi devices use common/ipv6_only.yaml (this + the IPv6 SSID)
|
||||||
|
external_components:
|
||||||
|
# network enable_ipv4 + audio HTTP reader over IPv6 (esphome/esphome#19750), drop once merged
|
||||||
|
- source: github://pr#19750
|
||||||
|
components: [const, network, wifi, ethernet, audio]
|
||||||
|
refresh: 1h
|
||||||
|
|
||||||
|
esp32:
|
||||||
|
framework:
|
||||||
|
components:
|
||||||
|
# mdns 1.14.0: no "A 0.0.0.0" without IPv4 + IPv6 on ETH-only builds (espressif/esp-protocols#1156, #1161),
|
||||||
|
# drop once on ESPHome 2026.10.0 (esphome/esphome#20383 bumps the pin from 1.12.0)
|
||||||
|
- name: espressif/mdns
|
||||||
|
ref: 1.14.0
|
||||||
|
# IDF v5.5.5 lwip + .local resolution over IPv6 (espressif/esp-lwip#94), drop once in IDF
|
||||||
|
- name: lwip
|
||||||
|
source: https://github.com/randybb/esp-lwip.git
|
||||||
|
ref: idf-v5.5.5-lwip-component
|
||||||
|
path: lwip
|
||||||
|
|
||||||
|
network:
|
||||||
|
enable_ipv6: true
|
||||||
|
enable_ipv4: false
|
||||||
|
min_ipv6_addr_count: 1
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
---
|
||||||
|
# Sonoff NSPanel with the native Lovelace UI (randybb/esphome-nspanel-lovelace-native).
|
||||||
|
# The device file adds the cards, buttons and relays:
|
||||||
|
# packages:
|
||||||
|
# common: !include common/common.yaml
|
||||||
|
# nspanel: !include
|
||||||
|
# file: common/nspanel.yaml
|
||||||
|
# vars:
|
||||||
|
# temperature_entity: sensor.zigbee_bedroom_temperature
|
||||||
|
# nspanel_lovelace:
|
||||||
|
# cards: [...]
|
||||||
|
defaults:
|
||||||
|
temperature_name: Temperature
|
||||||
|
ntc_reference_temperature: 25°C
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
on_boot:
|
||||||
|
then:
|
||||||
|
- switch.turn_off: screen_power
|
||||||
|
- delay: 1s
|
||||||
|
- switch.turn_on: screen_power
|
||||||
|
- delay: 2s
|
||||||
|
- lambda: 'id(nspanel_id).set_display_dim(5, 80);'
|
||||||
|
|
||||||
|
esp32:
|
||||||
|
variant: esp32
|
||||||
|
toolchain: esp-idf
|
||||||
|
framework:
|
||||||
|
type: esp-idf
|
||||||
|
advanced:
|
||||||
|
flash_chip: generic
|
||||||
|
minimum_chip_revision: 3.0
|
||||||
|
sram1_as_iram: true
|
||||||
|
|
||||||
|
packages:
|
||||||
|
popup: !include nspanel_popup.yaml
|
||||||
|
|
||||||
|
external_components:
|
||||||
|
- source:
|
||||||
|
type: git
|
||||||
|
url: https://github.com/randybb/esphome-nspanel-lovelace-native
|
||||||
|
ref: devices
|
||||||
|
refresh: 0s
|
||||||
|
components: [nspanel_lovelace]
|
||||||
|
|
||||||
|
api:
|
||||||
|
homeassistant_services: true
|
||||||
|
homeassistant_states: true
|
||||||
|
actions:
|
||||||
|
- action: play_rtttl
|
||||||
|
variables:
|
||||||
|
song: string
|
||||||
|
then:
|
||||||
|
- rtttl.play:
|
||||||
|
rtttl: !lambda 'return song;'
|
||||||
|
|
||||||
|
- action: notify
|
||||||
|
variables:
|
||||||
|
heading: string
|
||||||
|
message: string
|
||||||
|
song: string
|
||||||
|
then:
|
||||||
|
- lambda: 'id(nspanel_id).notify_on_screensaver(heading, message, 10000);'
|
||||||
|
- rtttl.play:
|
||||||
|
rtttl: !lambda 'return song;'
|
||||||
|
|
||||||
|
- action: notify_fullscreen
|
||||||
|
variables:
|
||||||
|
title: string
|
||||||
|
description: string
|
||||||
|
button1: string
|
||||||
|
button2: string
|
||||||
|
timeout: int
|
||||||
|
icon: string
|
||||||
|
then:
|
||||||
|
- lambda: 'id(nspanel_id).notify_on_screensaver(title, description, timeout);'
|
||||||
|
- rtttl.play: "scale_up:d=32,o=5,b=100:c,c#,d#,e,f#,g#,a#,b"
|
||||||
|
|
||||||
|
uart:
|
||||||
|
id: display_uart
|
||||||
|
tx_pin: 16
|
||||||
|
rx_pin: 17
|
||||||
|
baud_rate: 115200
|
||||||
|
|
||||||
|
nspanel_lovelace:
|
||||||
|
id: nspanel_id
|
||||||
|
sleep_timeout: 10
|
||||||
|
experimental_vertical_ui: true
|
||||||
|
locale:
|
||||||
|
language: sk
|
||||||
|
temperature_unit: celcius
|
||||||
|
screensaver:
|
||||||
|
time_id: ha_time
|
||||||
|
time_format: '%H:%M'
|
||||||
|
date_format: '%A, %d. %b. %Y'
|
||||||
|
weather:
|
||||||
|
entity_id: sensor.weather_forecast_daily
|
||||||
|
icon_color: [255, 255, 255]
|
||||||
|
entities:
|
||||||
|
- entity_id: ${temperature_entity}
|
||||||
|
icon:
|
||||||
|
value: home-thermometer-outline
|
||||||
|
color: [255, 255, 255]
|
||||||
|
precision: 1
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: ledc
|
||||||
|
id: buzzer_out
|
||||||
|
pin:
|
||||||
|
number: 21
|
||||||
|
|
||||||
|
switch:
|
||||||
|
- platform: gpio
|
||||||
|
name: Screen Power
|
||||||
|
id: screen_power
|
||||||
|
entity_category: config
|
||||||
|
pin:
|
||||||
|
number: 4
|
||||||
|
inverted: true
|
||||||
|
restore_mode: ALWAYS_ON
|
||||||
|
|
||||||
|
rtttl:
|
||||||
|
id: buzzer
|
||||||
|
output: buzzer_out
|
||||||
|
|
||||||
|
sensor:
|
||||||
|
- platform: adc
|
||||||
|
id: ntc_source
|
||||||
|
pin: 38
|
||||||
|
update_interval: 5min
|
||||||
|
attenuation: 12db
|
||||||
|
|
||||||
|
- platform: resistance
|
||||||
|
id: resistance_sensor
|
||||||
|
sensor: ntc_source
|
||||||
|
configuration: DOWNSTREAM
|
||||||
|
resistor: 11.2kOhm
|
||||||
|
|
||||||
|
- platform: ntc
|
||||||
|
name: ${temperature_name}
|
||||||
|
id: temperature
|
||||||
|
sensor: resistance_sensor
|
||||||
|
calibration:
|
||||||
|
b_constant: 3950
|
||||||
|
reference_temperature: ${ntc_reference_temperature}
|
||||||
|
reference_resistance: 10kOhm
|
||||||
|
|
||||||
|
text_sensor:
|
||||||
|
- platform: homeassistant
|
||||||
|
id: name_day
|
||||||
|
entity_id: sensor.nameday_sk
|
||||||
|
on_value:
|
||||||
|
- lambda: |-
|
||||||
|
id(nspanel_id).set_time_format("%H:%M~" + x);
|
||||||
|
id(nspanel_id).update_time();
|
||||||
|
|
||||||
|
# HMI protocol version reported by the TFT on startup (52/53 for this UI)
|
||||||
|
- platform: template
|
||||||
|
name: TFT Version
|
||||||
|
entity_category: diagnostic
|
||||||
|
update_interval: 60s
|
||||||
|
lambda: |-
|
||||||
|
using esphome::nspanel_lovelace::Configuration;
|
||||||
|
const auto ver = Configuration::get_version();
|
||||||
|
if (ver == 0) return {"unknown"};
|
||||||
|
return {std::to_string(ver) + " (" + Configuration::get_model_str() + ")"};
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
---
|
||||||
|
# NSPanel popups (popupNotify page), without changes to nspanel_lovelace:
|
||||||
|
# - OTA progress
|
||||||
|
# - device info (version, IPs) via the show_info API action
|
||||||
|
# Needs nspanel_lovelace (id nspanel_id), its uart (id display_uart) and the
|
||||||
|
# ota id ota_esphome (common/ota_esp32.yaml).
|
||||||
|
# The component doesn't track these popups; the panel either reboots (OTA)
|
||||||
|
# or goes back to the default page afterwards.
|
||||||
|
api:
|
||||||
|
actions:
|
||||||
|
- action: show_info
|
||||||
|
then:
|
||||||
|
- script.execute: info_popup
|
||||||
|
|
||||||
|
script:
|
||||||
|
- id: info_popup
|
||||||
|
mode: restart
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
char build[Application::BUILD_TIME_STR_SIZE];
|
||||||
|
App.get_build_time_string(build);
|
||||||
|
std::string msg = "ESPHome " ESPHOME_VERSION "\r\n";
|
||||||
|
msg += build;
|
||||||
|
// global/ULA first, link-local last
|
||||||
|
std::vector<std::string> ips;
|
||||||
|
for (int pass = 0; pass < 2; pass++) {
|
||||||
|
for (auto &ip : wifi::global_wifi_component->wifi_sta_ip_addresses()) {
|
||||||
|
if (!ip.is_set()) continue;
|
||||||
|
char buf[network::IP_ADDRESS_BUFFER_SIZE];
|
||||||
|
ip.str_to(buf);
|
||||||
|
bool ll = strncmp(buf, "fe80", 4) == 0;
|
||||||
|
if (ll == (pass == 1)) ips.emplace_back(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto &ip : ips) msg += "\r\n" + ip;
|
||||||
|
id(nspanel_id).send_display_command("pageType~popupNotify");
|
||||||
|
id(nspanel_id).send_display_command(
|
||||||
|
"entityUpdateDetail~info~" + App.get_friendly_name() + "~65535~~65535~~65535~" + msg + "~65535~15");
|
||||||
|
- delay: 15s
|
||||||
|
- lambda: 'id(nspanel_id).render_default_page();'
|
||||||
|
|
||||||
|
# OTA blocks the main loop, and nspanel_lovelace only sends its queued
|
||||||
|
# commands from loop(), so these frames go straight to the uart in the
|
||||||
|
# component's format: 55 BB, length (LE), command, CRC16 (LE).
|
||||||
|
- id: ota_popup
|
||||||
|
parameters:
|
||||||
|
message: string
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
auto send = [](const std::string &cmd) {
|
||||||
|
uint8_t hdr[4] = {0x55, 0xBB, uint8_t(cmd.size() & 0xFF), uint8_t(cmd.size() >> 8)};
|
||||||
|
uint16_t crc = crc16(hdr, 4);
|
||||||
|
crc = crc16(reinterpret_cast<const uint8_t *>(cmd.data()), cmd.size(), crc);
|
||||||
|
uint8_t tail[2] = {uint8_t(crc & 0xFF), uint8_t(crc >> 8)};
|
||||||
|
id(display_uart).write_array(hdr, 4);
|
||||||
|
id(display_uart).write_array(reinterpret_cast<const uint8_t *>(cmd.data()), cmd.size());
|
||||||
|
id(display_uart).write_array(tail, 2);
|
||||||
|
id(display_uart).flush();
|
||||||
|
};
|
||||||
|
send("dimmode~100~100");
|
||||||
|
send("pageType~popupNotify");
|
||||||
|
send("entityUpdateDetail~ota~Aktualizácia firmvéru~65535~~65535~~65535~" + message + "~65535~0");
|
||||||
|
|
||||||
|
ota:
|
||||||
|
- id: !extend ota_esphome
|
||||||
|
on_begin:
|
||||||
|
- script.execute:
|
||||||
|
id: ota_popup
|
||||||
|
message: Nahrávam…
|
||||||
|
on_progress:
|
||||||
|
- lambda: |-
|
||||||
|
static int last = -1;
|
||||||
|
int pct = (int) x / 10 * 10;
|
||||||
|
if (pct != last) {
|
||||||
|
last = pct;
|
||||||
|
id(ota_popup)->execute("Nahrávam… " + std::to_string(pct) + " %");
|
||||||
|
}
|
||||||
|
on_end:
|
||||||
|
- script.execute:
|
||||||
|
id: ota_popup
|
||||||
|
message: Hotovo, reštartujem
|
||||||
|
on_error:
|
||||||
|
- script.execute:
|
||||||
|
id: ota_popup
|
||||||
|
message: Aktualizácia zlyhala
|
||||||
|
- delay: 5s
|
||||||
|
- lambda: |-
|
||||||
|
id(nspanel_id).set_display_dim(5, 80);
|
||||||
|
id(nspanel_id).render_default_page();
|
||||||
|
|
||||||
|
button:
|
||||||
|
# put button.<device>_info on a card: the panel presses it through HA
|
||||||
|
- platform: template
|
||||||
|
name: Info
|
||||||
|
id: info_button
|
||||||
|
entity_category: diagnostic
|
||||||
|
on_press:
|
||||||
|
- script.execute: info_popup
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
---
|
||||||
|
# NSPanel screensaver dims to 0 at night (sun below -6°), unless the room lights are on.
|
||||||
|
# packages:
|
||||||
|
# sleep_dim: !include
|
||||||
|
# file: common/nspanel_sleep_dim.yaml
|
||||||
|
# vars:
|
||||||
|
# sleep_override_entity: light.bedroom_lights
|
||||||
|
script:
|
||||||
|
- id: apply_sleep_dim
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
uint8_t dim;
|
||||||
|
if (id(sleep_override).state) dim = 5; // sleepOverride
|
||||||
|
else if (id(sun_id).is_above_horizon(-6)) dim = 5; // day
|
||||||
|
else dim = 0; // night
|
||||||
|
id(nspanel_id).set_display_inactive_dim(dim);
|
||||||
|
|
||||||
|
time:
|
||||||
|
- id: !extend ha_time
|
||||||
|
on_time_sync:
|
||||||
|
- script.execute: apply_sleep_dim
|
||||||
|
|
||||||
|
binary_sensor:
|
||||||
|
- platform: homeassistant # sleepOverride
|
||||||
|
id: sleep_override
|
||||||
|
entity_id: ${sleep_override_entity}
|
||||||
|
on_state:
|
||||||
|
- script.execute: apply_sleep_dim
|
||||||
|
|
||||||
|
sun:
|
||||||
|
id: sun_id
|
||||||
|
time_id: ha_time
|
||||||
|
latitude: 48.15°
|
||||||
|
longitude: 17.11°
|
||||||
|
on_sunrise:
|
||||||
|
- elevation: -6°
|
||||||
|
then:
|
||||||
|
- script.execute: apply_sleep_dim
|
||||||
|
on_sunset:
|
||||||
|
- elevation: -6°
|
||||||
|
then:
|
||||||
|
- script.execute: apply_sleep_dim
|
||||||
@@ -2,3 +2,7 @@
|
|||||||
ota:
|
ota:
|
||||||
- platform: esphome
|
- platform: esphome
|
||||||
password: !secret ota_password
|
password: !secret ota_password
|
||||||
|
# migration to encrypted OTA (api key): once every device encrypts,
|
||||||
|
# remove allow_plaintext_upload together with the password
|
||||||
|
encryption:
|
||||||
|
allow_plaintext_upload: true
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
---
|
---
|
||||||
ota:
|
ota:
|
||||||
- platform: esphome
|
- platform: esphome
|
||||||
|
id: ota_esphome
|
||||||
password: !secret ota_password
|
password: !secret ota_password
|
||||||
|
# migration to encrypted OTA (api key): once every device encrypts,
|
||||||
|
# remove allow_plaintext_upload together with the password
|
||||||
|
encryption:
|
||||||
|
allow_plaintext_upload: true
|
||||||
allow_partition_access: true
|
allow_partition_access: true
|
||||||
@@ -7,4 +7,3 @@ accuracy_decimals: 2
|
|||||||
update_interval: 60s
|
update_interval: 60s
|
||||||
filters:
|
filters:
|
||||||
- lambda: return x / 86400;
|
- lambda: return x / 86400;
|
||||||
|
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
---
|
||||||
|
# Status on a visible RGB light, which stays a normal light otherwise:
|
||||||
|
# network down red, slow blink
|
||||||
|
# no API client (HA) orange, slow blink
|
||||||
|
# component error purple, steady (only with show_errors: "true", for a dedicated status LED)
|
||||||
|
# OTA blue, fast blink; green when done, 3 red blinks on error
|
||||||
|
# back to normal green for 1 s, then the light goes back to how it was
|
||||||
|
# packages:
|
||||||
|
# status_led: !include
|
||||||
|
# file: common/status_led.yaml
|
||||||
|
# vars:
|
||||||
|
# light_id: led_light
|
||||||
|
# Needs the ota id ota_esphome (common/ota_esp32.yaml).
|
||||||
|
defaults:
|
||||||
|
brightness: "0.3"
|
||||||
|
show_errors: "false" # a failed component would take over a display or a shared light for good
|
||||||
|
|
||||||
|
globals:
|
||||||
|
- id: status_led_active
|
||||||
|
type: bool
|
||||||
|
initial_value: "false"
|
||||||
|
- id: status_led_saved
|
||||||
|
type: light::LightColorValues
|
||||||
|
- id: status_led_last
|
||||||
|
type: uint32_t
|
||||||
|
initial_value: "0xFFFFFFFF"
|
||||||
|
|
||||||
|
script:
|
||||||
|
- id: status_led_show
|
||||||
|
parameters:
|
||||||
|
r: float
|
||||||
|
g: float
|
||||||
|
b: float
|
||||||
|
lit: bool
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
auto *l = id(${light_id});
|
||||||
|
uint32_t key = (lit << 24) | (uint32_t(r * 255) << 16) | (uint32_t(g * 255) << 8) | uint32_t(b * 255);
|
||||||
|
if (!id(status_led_active)) {
|
||||||
|
id(status_led_saved) = l->remote_values;
|
||||||
|
id(status_led_active) = true;
|
||||||
|
} else if (key == id(status_led_last)) {
|
||||||
|
return; // unchanged: don't flood Home Assistant with the same state
|
||||||
|
}
|
||||||
|
id(status_led_last) = key;
|
||||||
|
if (lit) {
|
||||||
|
l->turn_on().set_rgb(r, g, b).set_brightness(${brightness}).set_transition_length(0).set_effect("None").perform();
|
||||||
|
} else {
|
||||||
|
l->turn_off().set_transition_length(0).perform();
|
||||||
|
}
|
||||||
|
l->loop(); // write now: OTA blocks the main loop
|
||||||
|
- id: status_led_restore
|
||||||
|
parameters:
|
||||||
|
confirm: bool
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
if (id(status_led_active) && confirm) id(status_led_show)->execute(0.0f, 1.0f, 0.0f, true);
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
lambda: 'return id(status_led_active) && confirm;'
|
||||||
|
then:
|
||||||
|
- delay: 1s # green: back to normal
|
||||||
|
- lambda: |-
|
||||||
|
if (!id(status_led_active)) return;
|
||||||
|
id(status_led_active) = false;
|
||||||
|
id(status_led_last) = 0xFFFFFFFF;
|
||||||
|
id(${light_id})->make_call().from_light_color_values(id(status_led_saved)).set_transition_length(0).perform();
|
||||||
|
|
||||||
|
interval:
|
||||||
|
- interval: 500ms
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
static uint8_t tick = 0;
|
||||||
|
tick++;
|
||||||
|
bool slow = (tick / 2) % 2 == 0; // 1 s on, 1 s off
|
||||||
|
bool error = ${show_errors} && (App.get_app_state() & STATUS_LED_ERROR);
|
||||||
|
bool problem = !network::is_connected() || !api::global_api_server->is_connected() || error;
|
||||||
|
if (problem) id(status_led_restore)->stop();
|
||||||
|
if (!network::is_connected()) {
|
||||||
|
id(status_led_show)->execute(1.0f, 0.0f, 0.0f, slow);
|
||||||
|
} else if (!api::global_api_server->is_connected()) {
|
||||||
|
id(status_led_show)->execute(1.0f, 0.4f, 0.0f, slow);
|
||||||
|
} else if (error) {
|
||||||
|
id(status_led_show)->execute(0.6f, 0.0f, 1.0f, true);
|
||||||
|
} else if (id(status_led_active) && !id(status_led_restore)->is_running()) {
|
||||||
|
id(status_led_restore)->execute(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
ota:
|
||||||
|
- id: !extend ota_esphome
|
||||||
|
on_begin:
|
||||||
|
- script.execute:
|
||||||
|
id: status_led_show
|
||||||
|
r: 0.0
|
||||||
|
g: 0.0
|
||||||
|
b: 1.0
|
||||||
|
lit: true
|
||||||
|
on_progress:
|
||||||
|
- lambda: 'id(status_led_show)->execute(0.0f, 0.0f, 1.0f, (millis() / 250) % 2 == 0);'
|
||||||
|
on_end:
|
||||||
|
- script.execute:
|
||||||
|
id: status_led_show
|
||||||
|
r: 0.0
|
||||||
|
g: 1.0
|
||||||
|
b: 0.0
|
||||||
|
lit: true
|
||||||
|
on_error:
|
||||||
|
- repeat:
|
||||||
|
count: 3
|
||||||
|
then:
|
||||||
|
- script.execute:
|
||||||
|
id: status_led_show
|
||||||
|
r: 1.0
|
||||||
|
g: 0.0
|
||||||
|
b: 0.0
|
||||||
|
lit: true
|
||||||
|
- delay: 250ms
|
||||||
|
- script.execute:
|
||||||
|
id: status_led_show
|
||||||
|
r: 1.0
|
||||||
|
g: 0.0
|
||||||
|
b: 0.0
|
||||||
|
lit: false
|
||||||
|
- delay: 250ms
|
||||||
|
- script.execute:
|
||||||
|
id: status_led_restore
|
||||||
|
confirm: false
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
# Status LED on the M5Stack ATOM Lite's own RGB LED (G27), see common/status_led.yaml
|
||||||
|
packages:
|
||||||
|
status_led: !include
|
||||||
|
file: status_led.yaml
|
||||||
|
vars:
|
||||||
|
light_id: atom_led
|
||||||
|
show_errors: "true" # dedicated status LED
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: esp32_rmt_led_strip
|
||||||
|
id: atom_led
|
||||||
|
internal: true
|
||||||
|
pin: 27
|
||||||
|
num_leds: 1
|
||||||
|
rmt_symbols: 64 # 1 LED is 24 bits; leave RMT memory for remote_transmitter/receiver
|
||||||
|
chipset: ws2812
|
||||||
|
channel_colors: GRB
|
||||||
|
restore_mode: ALWAYS_OFF
|
||||||
@@ -5,4 +5,4 @@ id: git_ref_sensor
|
|||||||
long: true
|
long: true
|
||||||
all: true
|
all: true
|
||||||
abbrev: 16
|
abbrev: 16
|
||||||
dirty: "-dirty"
|
dirty: "-dirty"
|
||||||
@@ -2,6 +2,8 @@ esp32:
|
|||||||
variant: esp32
|
variant: esp32
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: gd # ESP32-PICO-D4, like every other ATOM Lite
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
external_components:
|
external_components:
|
||||||
|
|||||||
+4
-1
@@ -2,8 +2,11 @@
|
|||||||
wifi:
|
wifi:
|
||||||
# reboot_timeout: 0s
|
# reboot_timeout: 0s
|
||||||
networks:
|
networks:
|
||||||
- ssid: !secret wifi_ssid
|
# id lets devices override the network with '!extend wifi_iot'
|
||||||
|
- id: wifi_iot
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
password: !secret wifi_password
|
password: !secret wifi_password
|
||||||
enable_btm: true
|
enable_btm: true
|
||||||
enable_rrm: true
|
enable_rrm: true
|
||||||
min_auth_mode: WPA3
|
min_auth_mode: WPA3
|
||||||
|
power_save_mode: none
|
||||||
@@ -7,4 +7,4 @@ wifi:
|
|||||||
# enable_rrm: true
|
# enable_rrm: true
|
||||||
ap:
|
ap:
|
||||||
ssid: TEST
|
ssid: TEST
|
||||||
password: testtest
|
password: testtest
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
#pragma once
|
||||||
|
// Upcoming calendar events for mcu-m5paper: parsed from the calendar.get_events
|
||||||
|
// response and kept in flash (NVS), so they survive the power-off between RTC wake-ups.
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "esphome/components/json/json_util.h"
|
||||||
|
#include "esphome/core/preferences.h"
|
||||||
|
#include "esphome/core/time.h"
|
||||||
|
|
||||||
|
namespace m5paper_calendar {
|
||||||
|
|
||||||
|
static constexpr uint8_t MAX_EVENTS = 32;
|
||||||
|
static constexpr size_t SUMMARY_LEN = 44;
|
||||||
|
static constexpr uint16_t ALL_DAY = 0xFFFF;
|
||||||
|
static constexpr uint32_t PREF_HASH = 0x6D35C41A;
|
||||||
|
|
||||||
|
enum Kind : uint8_t { BIRTHDAY = 0, WASTE };
|
||||||
|
|
||||||
|
struct Event {
|
||||||
|
uint16_t day; // local date, days since 1970-01-01
|
||||||
|
uint16_t minute; // local start time in minutes after midnight, ALL_DAY if none
|
||||||
|
uint8_t kind;
|
||||||
|
char summary[SUMMARY_LEN + 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Events {
|
||||||
|
uint32_t fetched_at{0}; // UTC epoch of the download
|
||||||
|
uint8_t count{0};
|
||||||
|
Event items[MAX_EVENTS]{};
|
||||||
|
|
||||||
|
bool valid() const { return this->fetched_at != 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// the events in RAM, loaded from flash at boot
|
||||||
|
inline Events &events() {
|
||||||
|
static Events ev;
|
||||||
|
return ev;
|
||||||
|
}
|
||||||
|
|
||||||
|
// days since 1970-01-01 for a proleptic Gregorian date (H. Hinnant's algorithm)
|
||||||
|
inline int32_t days_from_civil(int y, int m, int d) {
|
||||||
|
y -= m <= 2;
|
||||||
|
const int era = (y >= 0 ? y : y - 399) / 400;
|
||||||
|
const int yoe = y - era * 400;
|
||||||
|
const int doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1;
|
||||||
|
const int doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
|
||||||
|
return era * 146097 + doe - 719468;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int32_t local_day(const esphome::ESPTime &t) { return days_from_civil(t.year, t.month, t.day_of_month); }
|
||||||
|
|
||||||
|
// 0 = Monday
|
||||||
|
inline int weekday(int32_t day) { return (day + 3) % 7; }
|
||||||
|
|
||||||
|
// "2026-10-01" (all-day) or "2026-10-01T10:00:00+02:00" -> local day and minute; false on error
|
||||||
|
inline bool parse_start(const char *s, uint16_t &day, uint16_t &minute) {
|
||||||
|
int y, mo, d, h, mi, sec = 0, oh = 0, om = 0;
|
||||||
|
char sign = '+';
|
||||||
|
int n = sscanf(s, "%d-%d-%dT%d:%d:%d%c%d:%d", &y, &mo, &d, &h, &mi, &sec, &sign, &oh, &om);
|
||||||
|
if (n < 3)
|
||||||
|
return false;
|
||||||
|
if (n < 5) {
|
||||||
|
day = days_from_civil(y, mo, d);
|
||||||
|
minute = ALL_DAY;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
int64_t ts = int64_t(days_from_civil(y, mo, d)) * 86400 + h * 3600 + mi * 60 + sec;
|
||||||
|
if (n >= 8 && (sign == '+' || sign == '-')) {
|
||||||
|
int64_t offset = oh * 3600 + om * 60;
|
||||||
|
ts += sign == '+' ? -offset : offset;
|
||||||
|
}
|
||||||
|
if (ts <= 0)
|
||||||
|
return false;
|
||||||
|
const auto t = esphome::ESPTime::from_epoch_local(ts);
|
||||||
|
day = local_day(t);
|
||||||
|
minute = t.hour * 60 + t.minute;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy at most SUMMARY_LEN bytes without cutting a UTF-8 sequence
|
||||||
|
inline void copy_summary(char *dst, const char *src) {
|
||||||
|
size_t n = strnlen(src, SUMMARY_LEN + 1);
|
||||||
|
if (n > SUMMARY_LEN) {
|
||||||
|
n = SUMMARY_LEN;
|
||||||
|
while (n > 0 && (uint8_t(src[n]) & 0xC0) == 0x80)
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
memcpy(dst, src, n);
|
||||||
|
dst[n] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the calendar.get_events response; Home Assistant wraps the action response as
|
||||||
|
// {"response": {"calendar.x": {"events": [...]}, ...}}; every calendar other than the waste one holds birthdays
|
||||||
|
inline bool parse(ArduinoJson::JsonObjectConst response, const char *waste, uint32_t now, Events &ev) {
|
||||||
|
ArduinoJson::JsonObjectConst root = response["response"].is<ArduinoJson::JsonObjectConst>()
|
||||||
|
? response["response"].as<ArduinoJson::JsonObjectConst>()
|
||||||
|
: response;
|
||||||
|
if (root.size() == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Events out;
|
||||||
|
for (ArduinoJson::JsonPairConst cal : root) {
|
||||||
|
const uint8_t kind = strcmp(cal.key().c_str(), waste) == 0 ? WASTE : BIRTHDAY;
|
||||||
|
for (ArduinoJson::JsonObjectConst item : cal.value()["events"].as<ArduinoJson::JsonArrayConst>()) {
|
||||||
|
Event e;
|
||||||
|
if (!parse_start(item["start"] | "", e.day, e.minute))
|
||||||
|
continue;
|
||||||
|
e.kind = kind;
|
||||||
|
copy_summary(e.summary, item["summary"] | "");
|
||||||
|
// the same birthday in the contacts and the manual calendar
|
||||||
|
if (std::any_of(out.items, out.items + out.count,
|
||||||
|
[&e](const Event &o) { return o.day == e.day && strcmp(o.summary, e.summary) == 0; }))
|
||||||
|
continue;
|
||||||
|
if (out.count < MAX_EVENTS) {
|
||||||
|
out.items[out.count++] = e;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// full: keep the nearest events
|
||||||
|
Event *last = std::max_element(out.items, out.items + out.count,
|
||||||
|
[](const Event &a, const Event &b) { return a.day < b.day; });
|
||||||
|
if (e.day < last->day)
|
||||||
|
*last = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::sort(out.items, out.items + out.count, [](const Event &a, const Event &b) {
|
||||||
|
// all-day (0xFFFF wraps to 0) first
|
||||||
|
return a.day != b.day ? a.day < b.day : uint16_t(a.minute + 1) < uint16_t(b.minute + 1);
|
||||||
|
});
|
||||||
|
out.fetched_at = now;
|
||||||
|
ev = out;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// battery cycle: refreshed once a day, after midnight
|
||||||
|
inline bool stale(const esphome::ESPTime &now) {
|
||||||
|
const auto &ev = events();
|
||||||
|
return !ev.valid() || !now.is_valid() || now.timestamp - ev.fetched_at >= 20 * 3600;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline esphome::ESPPreferenceObject &pref() {
|
||||||
|
static esphome::ESPPreferenceObject p = esphome::global_preferences->make_preference<Events>(PREF_HASH, true);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool load(Events &ev) {
|
||||||
|
if (!pref().load(&ev)) {
|
||||||
|
ev = Events{};
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ev.count = std::min(ev.count, MAX_EVENTS);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// written to flash right away: the board may power off before the next preferences flush
|
||||||
|
inline bool save(const Events &ev) { return pref().save(&ev) && esphome::global_preferences->sync(); }
|
||||||
|
|
||||||
|
} // namespace m5paper_calendar
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
#pragma once
|
||||||
|
// Moonraker client for mcu-cnc-pendant on its own FreeRTOS task: esp_http_client blocks
|
||||||
|
// (DNS is not bounded by timeout_ms), so the main loop only queues commands and reads
|
||||||
|
// the last polled status. An unreachable Klipper shows as "offline" instead of starving
|
||||||
|
// the loop into the task watchdog.
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "esp_http_client.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
|
||||||
|
#include "esphome/components/json/json_util.h"
|
||||||
|
#include "esphome/core/hal.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace moonraker {
|
||||||
|
|
||||||
|
struct Status {
|
||||||
|
float pos[3]{};
|
||||||
|
std::string homed;
|
||||||
|
std::string state{"offline"};
|
||||||
|
};
|
||||||
|
|
||||||
|
class Client {
|
||||||
|
public:
|
||||||
|
void start(const char *base) {
|
||||||
|
this->base_ = base;
|
||||||
|
xTaskCreate(task, "moonraker", 6144, this, 1, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run G-code; dropped when Klipper is not keeping up.
|
||||||
|
void gcode(const std::string &script) {
|
||||||
|
JsonDocument doc;
|
||||||
|
doc["script"] = script;
|
||||||
|
std::string body;
|
||||||
|
serializeJson(doc, body);
|
||||||
|
this->post("/printer/gcode/script", body);
|
||||||
|
}
|
||||||
|
|
||||||
|
// urgent: throw away everything queued and send this first (emergency stop)
|
||||||
|
void post(const std::string &path, const std::string &body = "", bool urgent = false) {
|
||||||
|
std::lock_guard<std::mutex> lock(this->mutex_);
|
||||||
|
if (urgent) {
|
||||||
|
this->queue_.clear();
|
||||||
|
} else if (this->queue_.size() >= MAX_QUEUE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->queue_.emplace_back(path, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status status() {
|
||||||
|
std::lock_guard<std::mutex> lock(this->mutex_);
|
||||||
|
return this->status_;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static constexpr size_t MAX_QUEUE = 8;
|
||||||
|
static constexpr uint32_t POLL_MS = 250;
|
||||||
|
static constexpr int TIMEOUT_MS = 1000;
|
||||||
|
|
||||||
|
static void task(void *arg) {
|
||||||
|
auto *self = static_cast<Client *>(arg);
|
||||||
|
uint32_t last_poll = 0;
|
||||||
|
for (;;) {
|
||||||
|
std::pair<std::string, std::string> cmd;
|
||||||
|
bool have_cmd = false;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(self->mutex_);
|
||||||
|
if (!self->queue_.empty()) {
|
||||||
|
cmd = std::move(self->queue_.front());
|
||||||
|
self->queue_.pop_front();
|
||||||
|
have_cmd = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (have_cmd) {
|
||||||
|
int code = self->request(cmd.first, &cmd.second, nullptr);
|
||||||
|
if (code != 200)
|
||||||
|
ESP_LOGW("moonraker", "POST %s failed (%d): %s", cmd.first.c_str(), code, cmd.second.c_str());
|
||||||
|
continue; // drain commands before the next poll
|
||||||
|
}
|
||||||
|
if (esphome::millis() - last_poll >= POLL_MS) {
|
||||||
|
last_poll = esphome::millis();
|
||||||
|
self->poll();
|
||||||
|
}
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void poll() {
|
||||||
|
std::string body;
|
||||||
|
Status s;
|
||||||
|
if (this->request("/printer/objects/query?gcode_move=gcode_position&toolhead=homed_axes&print_stats=state",
|
||||||
|
nullptr, &body) == 200) {
|
||||||
|
auto doc = esphome::json::parse_json(body);
|
||||||
|
JsonObject st = doc["result"]["status"];
|
||||||
|
JsonArray p = st["gcode_move"]["gcode_position"];
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
s.pos[i] = p[i];
|
||||||
|
s.homed = st["toolhead"]["homed_axes"].as<std::string>();
|
||||||
|
s.state = st["print_stats"]["state"].as<std::string>();
|
||||||
|
} else {
|
||||||
|
std::lock_guard<std::mutex> lock(this->mutex_);
|
||||||
|
s.pos[0] = this->status_.pos[0]; // keep the last position, only flag offline
|
||||||
|
s.pos[1] = this->status_.pos[1];
|
||||||
|
s.pos[2] = this->status_.pos[2];
|
||||||
|
}
|
||||||
|
std::lock_guard<std::mutex> lock(this->mutex_);
|
||||||
|
this->status_ = std::move(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST when body is set, GET otherwise; returns the HTTP status or -1
|
||||||
|
int request(const std::string &path, const std::string *body, std::string *out) {
|
||||||
|
std::string url = this->base_ + path;
|
||||||
|
esp_http_client_config_t cfg{};
|
||||||
|
cfg.url = url.c_str();
|
||||||
|
cfg.timeout_ms = TIMEOUT_MS;
|
||||||
|
cfg.method = body ? HTTP_METHOD_POST : HTTP_METHOD_GET;
|
||||||
|
esp_http_client_handle_t c = esp_http_client_init(&cfg);
|
||||||
|
if (c == nullptr)
|
||||||
|
return -1;
|
||||||
|
int code = -1;
|
||||||
|
int len = body ? body->size() : 0;
|
||||||
|
if (len > 0)
|
||||||
|
esp_http_client_set_header(c, "Content-Type", "application/json");
|
||||||
|
if (esp_http_client_open(c, len) == ESP_OK && (len == 0 || esp_http_client_write(c, body->data(), len) == len)) {
|
||||||
|
esp_http_client_fetch_headers(c);
|
||||||
|
code = esp_http_client_get_status_code(c);
|
||||||
|
char buf[256];
|
||||||
|
int n;
|
||||||
|
while (out != nullptr && (n = esp_http_client_read(c, buf, sizeof(buf))) > 0)
|
||||||
|
out->append(buf, n);
|
||||||
|
}
|
||||||
|
esp_http_client_cleanup(c);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string base_;
|
||||||
|
std::mutex mutex_;
|
||||||
|
std::deque<std::pair<std::string, std::string>> queue_;
|
||||||
|
Status status_;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline Client client;
|
||||||
|
|
||||||
|
} // namespace moonraker
|
||||||
+17
-10
@@ -1,4 +1,12 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: IKEA VINDRIKTNING (modded) + M5Stack M5Stamp Pico
|
||||||
|
# Pinout:
|
||||||
|
# GPIO21 PM1006 UART -> particle_uart (uart tx_pin)
|
||||||
|
# GPIO22 PM1006 UART -> particle_uart (uart rx_pin)
|
||||||
|
# GPIO25 TZT 8-bit WS2812 5050 stick (8 LEDs, 7 visible outside) -> NEO [neo] (light esp32_rmt_led_strip), also status
|
||||||
|
# GPIO27 Onboard RGB LED (1x WS2812, inside), unused
|
||||||
|
# GPIO32 Grove SDA -> i2c (i2c sda)
|
||||||
|
# GPIO33 Grove SCL -> i2c (i2c scl)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: air-office-r
|
device: air-office-r
|
||||||
name: Office R Air
|
name: Office R Air
|
||||||
@@ -16,10 +24,16 @@ esp32:
|
|||||||
variant: esp32
|
variant: esp32
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: gd
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
status_led: !include
|
||||||
|
file: common/status_led.yaml
|
||||||
|
vars:
|
||||||
|
light_id: neo
|
||||||
|
|
||||||
i2c:
|
i2c:
|
||||||
# - id: i2c0
|
# - id: i2c0
|
||||||
@@ -46,20 +60,13 @@ uart:
|
|||||||
# inverted: true
|
# inverted: true
|
||||||
|
|
||||||
light:
|
light:
|
||||||
- platform: esp32_rmt_led_strip
|
# also the status light (common/status_led.yaml): back to its previous state when all is fine
|
||||||
# name: LED
|
|
||||||
id: neo
|
|
||||||
channel_colors: GRB
|
|
||||||
pin: 27
|
|
||||||
num_leds: 1
|
|
||||||
chipset: ws2812
|
|
||||||
restore_mode: ALWAYS_OFF
|
|
||||||
- platform: esp32_rmt_led_strip
|
- platform: esp32_rmt_led_strip
|
||||||
name: NEO
|
name: NEO
|
||||||
id: neo_strip
|
id: neo
|
||||||
channel_colors: GRB
|
channel_colors: GRB
|
||||||
pin: 25
|
pin: 25
|
||||||
num_leds: 7
|
num_leds: 7 # 8 on the stick, the 8th one is hidden
|
||||||
chipset: ws2812
|
chipset: ws2812
|
||||||
restore_mode: ALWAYS_OFF
|
restore_mode: ALWAYS_OFF
|
||||||
effects:
|
effects:
|
||||||
|
|||||||
+13
-1
@@ -1,4 +1,14 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Apollo Automation ESK-1 ESPHome Starter Kit
|
||||||
|
# Pinout:
|
||||||
|
# GPIO0 -> i2c_1 (i2c scl)
|
||||||
|
# GPIO1 -> i2c_1 (i2c sda)
|
||||||
|
# GPIO4 -> Accessory Power (switch gpio)
|
||||||
|
# GPIO5 -> Onboard RGB LED (light esp32_rmt_led_strip)
|
||||||
|
# GPIO14 -> RGB LEDs (light esp32_rmt_led_strip)
|
||||||
|
# GPIO18 -> buzzer_output (output ledc)
|
||||||
|
# I2C:
|
||||||
|
# 0x38 aht20 (sensor aht10)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: apollo-dev #test
|
device: apollo-dev #test
|
||||||
name: Apollo DEV #test
|
name: Apollo DEV #test
|
||||||
@@ -16,6 +26,8 @@ esp32:
|
|||||||
flash_size: 8MB
|
flash_size: 8MB
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: generic
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
@@ -30,7 +42,7 @@ api:
|
|||||||
then:
|
then:
|
||||||
- rtttl.play:
|
- rtttl.play:
|
||||||
rtttl: !lambda 'return song;'
|
rtttl: !lambda 'return song;'
|
||||||
|
|
||||||
switch:
|
switch:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
id: accessory_power
|
id: accessory_power
|
||||||
|
|||||||
+60
-5
@@ -1,4 +1,23 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack AtomS3
|
||||||
|
# Pinout:
|
||||||
|
# GPIO1 Grove SCL -> motor_in1 (output gpio)
|
||||||
|
# GPIO2 Grove SDA -> motor_in2 (output gpio)
|
||||||
|
# GPIO5 -> canbus/esp32_can (canbus esp32_can tx_pin)
|
||||||
|
# GPIO6 -> canbus/esp32_can (canbus esp32_can rx_pin)
|
||||||
|
# GPIO15 -> display_tft (display mipi_spi cs_pin)
|
||||||
|
# GPIO16 -> gpio_tft_backlight (output ledc)
|
||||||
|
# GPIO17 -> spi (spi clk_pin)
|
||||||
|
# GPIO21 -> spi (spi mosi_pin)
|
||||||
|
# GPIO33 -> display_tft (display mipi_spi dc_pin)
|
||||||
|
# GPIO34 -> display_tft (display mipi_spi reset_pin)
|
||||||
|
# GPIO38 -> i2c_main (i2c sda)
|
||||||
|
# GPIO39 -> i2c_main (i2c scl)
|
||||||
|
# GPIO41 -> Button (binary_sensor gpio) (inverted)
|
||||||
|
# I2C:
|
||||||
|
# 0x21 pcf8574_hub (pcf8574)
|
||||||
|
# 0x26 m5stack_relay_1 (m5stack_4relay)
|
||||||
|
# 0x3C lcd (display ssd1306_i2c)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: atoms3
|
device: atoms3
|
||||||
name: AtomS3
|
name: AtomS3
|
||||||
@@ -23,6 +42,8 @@ esp32:
|
|||||||
flash_size: 8MB
|
flash_size: 8MB
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: gd
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
ota:
|
ota:
|
||||||
@@ -33,12 +54,14 @@ pcf8574:
|
|||||||
address: 0x21
|
address: 0x21
|
||||||
pcf8575: true
|
pcf8575: true
|
||||||
|
|
||||||
animation:
|
image:
|
||||||
- file: "assets/images/blinky.gif"
|
- platform: animation
|
||||||
|
file: "assets/images/blinky.gif"
|
||||||
id: blinky
|
id: blinky
|
||||||
resize: 128x128
|
resize: 128x128
|
||||||
type: RGB565
|
type: RGB565
|
||||||
- file: "assets/images/vault_boy_walking.gif"
|
- platform: animation
|
||||||
|
file: "assets/images/vault_boy_walking.gif"
|
||||||
id: vaultboy
|
id: vaultboy
|
||||||
resize: 168x121
|
resize: 168x121
|
||||||
type: RGB565
|
type: RGB565
|
||||||
@@ -108,6 +131,11 @@ external_components:
|
|||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
status_led: !include
|
||||||
|
file: common/status_led.yaml
|
||||||
|
vars:
|
||||||
|
light_id: status_frame
|
||||||
# common: !include common/common_wo_debug.yaml
|
# common: !include common/common_wo_debug.yaml
|
||||||
# common: !include common/common_dev.yaml
|
# common: !include common/common_dev.yaml
|
||||||
|
|
||||||
@@ -211,12 +239,32 @@ output:
|
|||||||
- platform: ledc
|
- platform: ledc
|
||||||
pin: 16
|
pin: 16
|
||||||
id: gpio_tft_backlight
|
id: gpio_tft_backlight
|
||||||
|
# virtual RGB light for common/status_led.yaml, shown full screen on the display
|
||||||
|
- platform: template
|
||||||
|
id: status_frame_r
|
||||||
|
type: float
|
||||||
|
write_action: []
|
||||||
|
- platform: template
|
||||||
|
id: status_frame_g
|
||||||
|
type: float
|
||||||
|
write_action: []
|
||||||
|
- platform: template
|
||||||
|
id: status_frame_b
|
||||||
|
type: float
|
||||||
|
write_action: []
|
||||||
|
|
||||||
light:
|
light:
|
||||||
- platform: monochromatic
|
- platform: monochromatic
|
||||||
id: display_tft_backlight
|
id: display_tft_backlight
|
||||||
output: gpio_tft_backlight
|
output: gpio_tft_backlight
|
||||||
restore_mode: ALWAYS_ON
|
restore_mode: ALWAYS_ON
|
||||||
|
- platform: rgb
|
||||||
|
id: status_frame
|
||||||
|
internal: true
|
||||||
|
red: status_frame_r
|
||||||
|
green: status_frame_g
|
||||||
|
blue: status_frame_b
|
||||||
|
restore_mode: ALWAYS_OFF
|
||||||
|
|
||||||
switch:
|
switch:
|
||||||
- platform: template
|
- platform: template
|
||||||
@@ -372,6 +420,7 @@ display:
|
|||||||
- platform: mipi_spi
|
- platform: mipi_spi
|
||||||
model: ST7789V
|
model: ST7789V
|
||||||
id: display_tft
|
id: display_tft
|
||||||
|
byte_order: little_endian # colours were byte-swapped (purple showed as green)
|
||||||
dimensions:
|
dimensions:
|
||||||
height: 128
|
height: 128
|
||||||
width: 128
|
width: 128
|
||||||
@@ -384,11 +433,18 @@ display:
|
|||||||
# eightbitcolor: true
|
# eightbitcolor: true
|
||||||
update_interval: 1s
|
update_interval: 1s
|
||||||
lambda: |-
|
lambda: |-
|
||||||
|
// status screen (common/status_led.yaml): the whole display in the status colour
|
||||||
|
auto &sv = id(status_frame)->current_values;
|
||||||
|
if (sv.is_on()) {
|
||||||
|
it.fill(Color(sv.get_red() * 255, sv.get_green() * 255, sv.get_blue() * 255));
|
||||||
|
return;
|
||||||
|
}
|
||||||
//Ingress shown animation Frame.
|
//Ingress shown animation Frame.
|
||||||
id(blinky).next_frame();
|
id(blinky).next_frame();
|
||||||
// Draw the animation my_animation at position [x=0,y=0]
|
// Draw the animation my_animation at position [x=0,y=0]
|
||||||
it.image(0, 0, id(blinky), COLOR_ON, COLOR_OFF);
|
it.image(0, 0, id(blinky), COLOR_ON, COLOR_OFF);
|
||||||
|
|
||||||
|
|
||||||
// // it.print(0, 0, id(font_default), "Hello World!");
|
// // it.print(0, 0, id(font_default), "Hello World!");
|
||||||
// // it.strftime(0, 0, id(font_default), TextAlign::TOP_LEFT, "%H:%M", id(ha_time).now());
|
// // it.strftime(0, 0, id(font_default), TextAlign::TOP_LEFT, "%H:%M", id(ha_time).now());
|
||||||
// it.rectangle(0, 0, it.get_width(), it.get_height(), id(my_blue));
|
// it.rectangle(0, 0, it.get_width(), it.get_height(), id(my_blue));
|
||||||
@@ -491,8 +547,7 @@ sensor:
|
|||||||
# name: Dallas Temp 4
|
# name: Dallas Temp 4
|
||||||
# one_wire_id: hub_1
|
# one_wire_id: hub_1
|
||||||
|
|
||||||
time:
|
# time:
|
||||||
- !include common/time/homeassistant.yaml
|
|
||||||
# - platform: sntp
|
# - platform: sntp
|
||||||
# id: sntp_time
|
# id: sntp_time
|
||||||
# timezone: Europe/Bratislava
|
# timezone: Europe/Bratislava
|
||||||
|
|||||||
+9
-8
@@ -1,4 +1,12 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Sonoff Dual R2
|
||||||
|
# Pinout:
|
||||||
|
# GPIO0 Pin "button 0" on expansion header
|
||||||
|
# GPIO5 Relay #2 and green color on LED -> relay_2 (output gpio)
|
||||||
|
# GPIO9 Pin "button 1" on expansion header
|
||||||
|
# GPIO10 Push Button
|
||||||
|
# GPIO12 Relay #1 and red color on LED -> relay_1 (output gpio)
|
||||||
|
# GPIO13 Blue Status LED -> status_led (status_led) (inverted)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: basement-2
|
device: basement-2
|
||||||
name_short: Basement
|
name_short: Basement
|
||||||
@@ -17,14 +25,7 @@ esp8266:
|
|||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common_esp8266.yaml
|
common: !include common/common_esp8266.yaml
|
||||||
|
mdns_ipv6: !include common/esp8266_mdns_ipv6.yaml
|
||||||
# Sonoff Dual R2
|
|
||||||
# GPIO10 Push Button
|
|
||||||
# GPIO00 Pin "button 0" on expansion header
|
|
||||||
# GPIO09 Pin "button 1" on expansion header
|
|
||||||
# GPIO12 Relay #1 and red color on LED
|
|
||||||
# GPIO05 Relay #2 and green color on LED
|
|
||||||
# GPIO13 Blue Status LED
|
|
||||||
|
|
||||||
status_led:
|
status_led:
|
||||||
pin:
|
pin:
|
||||||
|
|||||||
+10
-11
@@ -1,4 +1,12 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Sonoff Dual R2
|
||||||
|
# Pinout:
|
||||||
|
# GPIO0 Pin "button 0" on expansion header -> Light Switch (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO5 Relay #2 and green color on LED -> Socket 1 (switch gpio)
|
||||||
|
# GPIO9 Pin "button 1" on expansion header -> Door (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO10 Push Button -> Socket 1 Switch (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO12 Relay #1 and red color on LED -> Sewage Treatment Aerator Pump [relay_1] (switch gpio)
|
||||||
|
# GPIO13 Blue Status LED -> status_led (status_led) (inverted)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: basement
|
device: basement
|
||||||
name: Basement
|
name: Basement
|
||||||
@@ -16,15 +24,7 @@ esp8266:
|
|||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common_esp8266.yaml
|
common: !include common/common_esp8266.yaml
|
||||||
|
mdns_ipv6: !include common/esp8266_mdns_ipv6.yaml
|
||||||
# Sonoff Dual R2
|
|
||||||
# Pin Function
|
|
||||||
# GPIO10 Push Button
|
|
||||||
# GPIO00 Pin "button 0" on expansion header
|
|
||||||
# GPIO09 Pin "button 1" on expansion header
|
|
||||||
# GPIO12 Relay #1 and red color on LED
|
|
||||||
# GPIO05 Relay #2 and green color on LED
|
|
||||||
# GPIO13 Blue Status LED
|
|
||||||
|
|
||||||
globals:
|
globals:
|
||||||
- id: aerator_auto
|
- id: aerator_auto
|
||||||
@@ -139,8 +139,7 @@ switch:
|
|||||||
id: relay_2
|
id: relay_2
|
||||||
|
|
||||||
time:
|
time:
|
||||||
- platform: homeassistant
|
- id: !extend ha_time
|
||||||
timezone: Europe/Bratislava
|
|
||||||
on_time:
|
on_time:
|
||||||
- seconds: 0
|
- seconds: 0
|
||||||
minutes: /15
|
minutes: /15
|
||||||
|
|||||||
+24
-10
@@ -1,4 +1,23 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Xiaomi Mi Bedside Lamp 2 (ESP-WROOM-32D, single core; RGBW LEDs)
|
||||||
|
# Pinout (github.com/mmakaay/esphome-xiaomi_bslamp2, doc/technical_details.md):
|
||||||
|
# GPIO1 Debug pad TX
|
||||||
|
# GPIO2 Debug pad, free I/O
|
||||||
|
# GPIO3 Debug pad RX
|
||||||
|
# GPIO4 LEDs master switch 2
|
||||||
|
# GPIO5 LEDs blue PWM
|
||||||
|
# GPIO12 LEDs white PWM
|
||||||
|
# GPIO13 LEDs red PWM
|
||||||
|
# GPIO14 LEDs green PWM
|
||||||
|
# GPIO16 Front panel interrupt
|
||||||
|
# GPIO17 EEPROM I2C SDA
|
||||||
|
# GPIO18 EEPROM I2C SCL
|
||||||
|
# GPIO19 Front panel I2C SCL -> front_panel_i2c (i2c scl)
|
||||||
|
# GPIO21 Front panel I2C SDA -> front_panel_i2c (i2c sda)
|
||||||
|
# GPIO33 LEDs master switch 1
|
||||||
|
# I2C:
|
||||||
|
# 0x10 EEPROM-like IC on its own bus (GPIO17/18), not configured
|
||||||
|
# 0x2C Front panel
|
||||||
substitutions:
|
substitutions:
|
||||||
device: bedroom-lamp-left
|
device: bedroom-lamp-left
|
||||||
name: Bedroom Lamp Left
|
name: Bedroom Lamp Left
|
||||||
@@ -20,26 +39,21 @@ esp32:
|
|||||||
sdkconfig_options:
|
sdkconfig_options:
|
||||||
CONFIG_FREERTOS_UNICORE: y
|
CONFIG_FREERTOS_UNICORE: y
|
||||||
advanced:
|
advanced:
|
||||||
|
flash_chip: generic
|
||||||
ignore_efuse_custom_mac: true
|
ignore_efuse_custom_mac: true
|
||||||
ignore_efuse_mac_crc: true
|
ignore_efuse_mac_crc: true
|
||||||
|
|
||||||
external_components:
|
external_components:
|
||||||
- source:
|
- source:
|
||||||
type: git
|
type: git
|
||||||
url: https://github.com/mmakaay/esphome-xiaomi_bslamp2
|
# fork: fix for ESPHome 2026.10 (restore_mode -> restore_state), back to mmakaay once merged
|
||||||
ref: dev
|
url: https://github.com/randybb/esphome-xiaomi_bslamp2
|
||||||
|
ref: fix-light-restore-state
|
||||||
refresh: 1h
|
refresh: 1h
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
# Mi Desk Lamp
|
|
||||||
# Pin Function (Name)
|
|
||||||
# GPIO02: Button (GPIO_KEY1)
|
|
||||||
# GPIO04: Cold White (GPIO_PWM1)
|
|
||||||
# GPIO05: Warm White (GPIO_PWM2)
|
|
||||||
# GPIO12: Rotary switch A pin (GPIO_ROT_A)
|
|
||||||
# GPIO13: Rotary switch B pin (GPIO_ROT_B)
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------
|
# ------------------------------------------------------------------------
|
||||||
# Behavior: default
|
# Behavior: default
|
||||||
|
|||||||
+24
-10
@@ -1,4 +1,23 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Xiaomi Mi Bedside Lamp 2 (ESP-WROOM-32D, single core; RGBW LEDs)
|
||||||
|
# Pinout (github.com/mmakaay/esphome-xiaomi_bslamp2, doc/technical_details.md):
|
||||||
|
# GPIO1 Debug pad TX
|
||||||
|
# GPIO2 Debug pad, free I/O
|
||||||
|
# GPIO3 Debug pad RX
|
||||||
|
# GPIO4 LEDs master switch 2
|
||||||
|
# GPIO5 LEDs blue PWM
|
||||||
|
# GPIO12 LEDs white PWM
|
||||||
|
# GPIO13 LEDs red PWM
|
||||||
|
# GPIO14 LEDs green PWM
|
||||||
|
# GPIO16 Front panel interrupt
|
||||||
|
# GPIO17 EEPROM I2C SDA
|
||||||
|
# GPIO18 EEPROM I2C SCL
|
||||||
|
# GPIO19 Front panel I2C SCL -> front_panel_i2c (i2c scl)
|
||||||
|
# GPIO21 Front panel I2C SDA -> front_panel_i2c (i2c sda)
|
||||||
|
# GPIO33 LEDs master switch 1
|
||||||
|
# I2C:
|
||||||
|
# 0x10 EEPROM-like IC on its own bus (GPIO17/18), not configured
|
||||||
|
# 0x2C Front panel
|
||||||
substitutions:
|
substitutions:
|
||||||
device: bedroom-lamp-right
|
device: bedroom-lamp-right
|
||||||
name: Bedroom Lamp Right
|
name: Bedroom Lamp Right
|
||||||
@@ -20,26 +39,21 @@ esp32:
|
|||||||
sdkconfig_options:
|
sdkconfig_options:
|
||||||
CONFIG_FREERTOS_UNICORE: y
|
CONFIG_FREERTOS_UNICORE: y
|
||||||
advanced:
|
advanced:
|
||||||
|
flash_chip: generic
|
||||||
ignore_efuse_custom_mac: true
|
ignore_efuse_custom_mac: true
|
||||||
ignore_efuse_mac_crc: true
|
ignore_efuse_mac_crc: true
|
||||||
|
|
||||||
external_components:
|
external_components:
|
||||||
- source:
|
- source:
|
||||||
type: git
|
type: git
|
||||||
url: https://github.com/mmakaay/esphome-xiaomi_bslamp2
|
# fork: fix for ESPHome 2026.10 (restore_mode -> restore_state), back to mmakaay once merged
|
||||||
ref: dev
|
url: https://github.com/randybb/esphome-xiaomi_bslamp2
|
||||||
|
ref: fix-light-restore-state
|
||||||
refresh: 60s
|
refresh: 60s
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
# Mi Desk Lamp
|
|
||||||
# Pin Function (Name)
|
|
||||||
# GPIO02: Button (GPIO_KEY1)
|
|
||||||
# GPIO04: Cold White (GPIO_PWM1)
|
|
||||||
# GPIO05: Warm White (GPIO_PWM2)
|
|
||||||
# GPIO12: Rotary switch A pin (GPIO_ROT_A)
|
|
||||||
# GPIO13: Rotary switch B pin (GPIO_ROT_B)
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------
|
# ------------------------------------------------------------------------
|
||||||
# Behavior: default
|
# Behavior: default
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Espressif ESP32-C6-DevKitC-1
|
||||||
|
# Pinout:
|
||||||
|
# GPIO8 -> LED (light esp32_rmt_led_strip)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: c6-test-1
|
device: c6-test-1
|
||||||
name: C6 TEST 1
|
name: C6 TEST 1
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Espressif ESP32-C6-DevKitC-1
|
||||||
|
# Pinout:
|
||||||
|
# GPIO8 -> LED (light esp32_rmt_led_strip)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: c6-test-2
|
device: c6-test-2
|
||||||
name: C6 TEST 2
|
name: C6 TEST 2
|
||||||
|
|||||||
@@ -1,4 +1,21 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: ESP32-CAM (AI-Thinker style, runs hot)
|
||||||
|
# Pinout:
|
||||||
|
# GPIO0 -> Camera (esp32_camera)
|
||||||
|
# GPIO5 -> Camera (esp32_camera data_pins)
|
||||||
|
# GPIO18 -> Camera (esp32_camera data_pins)
|
||||||
|
# GPIO19 -> Camera (esp32_camera data_pins)
|
||||||
|
# GPIO21 -> Camera (esp32_camera data_pins)
|
||||||
|
# GPIO22 -> Camera (esp32_camera pixel_clock_pin)
|
||||||
|
# GPIO23 -> Camera (esp32_camera href_pin)
|
||||||
|
# GPIO25 -> Camera (esp32_camera vsync_pin)
|
||||||
|
# GPIO26 -> i2c_bus (i2c sda)
|
||||||
|
# GPIO27 -> i2c_bus (i2c scl)
|
||||||
|
# GPIO32 -> Enable (switch gpio)
|
||||||
|
# GPIO34 -> Camera (esp32_camera data_pins)
|
||||||
|
# GPIO35 -> Camera (esp32_camera data_pins)
|
||||||
|
# GPIO36 -> Camera (esp32_camera data_pins)
|
||||||
|
# GPIO39 -> Camera (esp32_camera data_pins)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: cam-1
|
device: cam-1
|
||||||
name: Cam 1
|
name: Cam 1
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: ESP32 DevKit
|
||||||
|
# Pinout:
|
||||||
|
# GPIO0 -> Boot (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO2 -> LED (switch gpio)
|
||||||
|
# GPIO22 -> can_bus (canbus esp32_can rx_pin)
|
||||||
|
# GPIO23 -> can_bus (canbus esp32_can tx_pin)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: can-node-1
|
device: can-node-1
|
||||||
name: CAN Node 1
|
name: CAN Node 1
|
||||||
|
|||||||
@@ -1,4 +1,13 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: ESP32 DevKit
|
||||||
|
# Pinout:
|
||||||
|
# GPIO17 -> i2c (i2c sda)
|
||||||
|
# GPIO18 -> i2c (i2c scl)
|
||||||
|
# GPIO19 -> as3935_i2c (as3935_i2c irq_pin)
|
||||||
|
# GPIO22 -> can_bus (canbus esp32_can rx_pin)
|
||||||
|
# GPIO23 -> can_bus (canbus esp32_can tx_pin)
|
||||||
|
# I2C:
|
||||||
|
# 0x03 as3935_i2c (as3935_i2c)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: can-node-2
|
device: can-node-2
|
||||||
name: CAN Node 2
|
name: CAN Node 2
|
||||||
|
|||||||
+11
-5
@@ -1,4 +1,13 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack M5Stamp Pico
|
||||||
|
# Pinout:
|
||||||
|
# GPIO22 -> uart_distance (uart rx_pin)
|
||||||
|
# GPIO25 -> uart_distance (uart tx_pin)
|
||||||
|
# GPIO26 -> hdmi_cec (hdmi_cec)
|
||||||
|
# GPIO27 -> LED (light esp32_rmt_led_strip)
|
||||||
|
# GPIO32 Grove SDA -> i2c (i2c sda)
|
||||||
|
# GPIO33 Grove SCL -> i2c (i2c scl)
|
||||||
|
# GPIO39 -> Bedroom TV Button (binary_sensor gpio) (inverted)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: cec-bedroom
|
device: cec-bedroom
|
||||||
name: Bedroom TV
|
name: Bedroom TV
|
||||||
@@ -15,6 +24,8 @@ esp32:
|
|||||||
variant: esp32
|
variant: esp32
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: gd # ESP32-PICO-D4, like the other M5Stamp Pico (not read from the device)
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
external_components:
|
external_components:
|
||||||
@@ -31,11 +42,6 @@ packages:
|
|||||||
|
|
||||||
debug:
|
debug:
|
||||||
|
|
||||||
time:
|
|
||||||
- platform: homeassistant
|
|
||||||
id: ha_time
|
|
||||||
timezone: Europe/Bratislava
|
|
||||||
|
|
||||||
i2c:
|
i2c:
|
||||||
# - id: i2c0
|
# - id: i2c0
|
||||||
sda: 32
|
sda: 32
|
||||||
|
|||||||
+17
-20
@@ -1,4 +1,18 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack M5Stamp C3
|
||||||
|
# Pinout:
|
||||||
|
# GPIO0 I2C SCL
|
||||||
|
# GPIO1 I2C SDA, BUTTON
|
||||||
|
# GPIO2 RGB
|
||||||
|
# GPIO4 DISPLAY CLOCK -> tm1637_display (display tm1637 clk_pin)
|
||||||
|
# GPIO5 DISPLAY DIO -> tm1637_display (display tm1637 dio_pin)
|
||||||
|
# GPIO6 GPIO
|
||||||
|
# GPIO7 GPIO
|
||||||
|
# GPIO8 GPIO
|
||||||
|
# GPIO9 GPIO (BUZZER?) -> rtttl_out (output ledc)
|
||||||
|
# GPIO10 GPIO
|
||||||
|
# GPIO20 UART RX
|
||||||
|
# GPIO21 UART TX
|
||||||
substitutions:
|
substitutions:
|
||||||
device: clock-1
|
device: clock-1
|
||||||
name: Clock 1
|
name: Clock 1
|
||||||
@@ -17,27 +31,15 @@ esp32:
|
|||||||
variant: esp32c3
|
variant: esp32c3
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: generic
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
# version: 5.4.2
|
# version: 5.4.2
|
||||||
# platform_version: 54.03.21
|
# platform_version: 54.03.21
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
# GPIO21 UART TX
|
|
||||||
# GPIO20 UART RX
|
|
||||||
# GPIO0 I2C SCL
|
|
||||||
# GPIO1 I2C SDA
|
|
||||||
# GPIO2 RGB
|
|
||||||
# GPIO1 BUTTON
|
|
||||||
# GPIO4 DISPLAY CLOCK
|
|
||||||
# GPIO5 DISPLAY DIO
|
|
||||||
# GPIO6 GPIO
|
|
||||||
# GPIO7 GPIO
|
|
||||||
# GPIO8 GPIO
|
|
||||||
# GPIO10 GPIO
|
|
||||||
#
|
|
||||||
# GPIO9 GPIO (BUZZER?)
|
|
||||||
|
|
||||||
# https://github.com/granadaxronos/120-SONG_NOKIA_RTTTL_RINGTONE_PLAYER_FOR_ARDUINO_UNO/blob/master/RTTTL_PLAYER/songs.h
|
# https://github.com/granadaxronos/120-SONG_NOKIA_RTTTL_RINGTONE_PLAYER_FOR_ARDUINO_UNO/blob/master/RTTTL_PLAYER/songs.h
|
||||||
api:
|
api:
|
||||||
@@ -109,11 +111,6 @@ globals:
|
|||||||
restore_value: no
|
restore_value: no
|
||||||
initial_value: "false"
|
initial_value: "false"
|
||||||
|
|
||||||
time:
|
|
||||||
- platform: homeassistant
|
|
||||||
id: ha_time
|
|
||||||
timezone: Europe/Bratislava
|
|
||||||
|
|
||||||
display:
|
display:
|
||||||
- platform: tm1637
|
- platform: tm1637
|
||||||
id: tm1637_display
|
id: tm1637_display
|
||||||
|
|||||||
@@ -1,4 +1,13 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack M5Stamp Pico
|
||||||
|
# Pinout:
|
||||||
|
# GPIO25 -> rtttl_out (output ledc)
|
||||||
|
# GPIO27 -> LED (light esp32_rmt_led_strip)
|
||||||
|
# GPIO32 Grove SDA -> i2c_main (i2c sda)
|
||||||
|
# GPIO33 Grove SCL -> i2c_main (i2c scl)
|
||||||
|
# GPIO39 -> Button (binary_sensor gpio) (inverted)
|
||||||
|
# I2C:
|
||||||
|
# 0x24 tm1650_display (display tm1650)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: clock-living-room
|
device: clock-living-room
|
||||||
name: Living room Clock
|
name: Living room Clock
|
||||||
@@ -15,6 +24,8 @@ esp32:
|
|||||||
variant: esp32
|
variant: esp32
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: gd # ESP32-PICO-D4, like the other M5Stamp Pico (not read from the device)
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
external_components:
|
external_components:
|
||||||
@@ -51,11 +62,6 @@ globals:
|
|||||||
restore_value: no
|
restore_value: no
|
||||||
initial_value: "false"
|
initial_value: "false"
|
||||||
|
|
||||||
time:
|
|
||||||
- platform: homeassistant
|
|
||||||
id: ha_time
|
|
||||||
timezone: Europe/Bratislava
|
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
name: Button
|
name: Button
|
||||||
|
|||||||
@@ -0,0 +1,235 @@
|
|||||||
|
---
|
||||||
|
# Hardware: M5Stack M5Stamp S3 in the ESPendant case (github.com/positron96/ESP32_CNC_Pendant),
|
||||||
|
# talks to Klipper over Moonraker HTTP API
|
||||||
|
# Pinout:
|
||||||
|
# GPIO0 Stamp button (boot) -> stamp_button (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO1 Handwheel A -> handwheel (sensor rotary_encoder pin_a)
|
||||||
|
# GPIO2 Handwheel B -> handwheel (sensor rotary_encoder pin_b)
|
||||||
|
# GPIO4 Axis encoder A -> axis_encoder (sensor rotary_encoder pin_a)
|
||||||
|
# GPIO5 Axis encoder B -> axis_encoder (sensor rotary_encoder pin_b)
|
||||||
|
# GPIO6 Axis encoder push -> axis_button (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO7 Step encoder A -> step_encoder (sensor rotary_encoder pin_a)
|
||||||
|
# GPIO8 Step encoder B -> step_encoder (sensor rotary_encoder pin_b)
|
||||||
|
# GPIO9 Step encoder push -> step_button (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO10 BT1 -> bt1 (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO11 BT2 -> bt2 (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO12 BT3 -> bt3 (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO13 LCD E (SCK) -> spi (spi clk_pin)
|
||||||
|
# GPIO14 LCD R/W (MOSI) -> spi (spi mosi_pin)
|
||||||
|
# GPIO15 LCD RS (CS) -> lcd (display st7920 cs_pin)
|
||||||
|
# GPIO21 RGB LED -> status_rgb (light esp32_rmt_led_strip)
|
||||||
|
# GPIO39-44 free (BT4-BT6 later)
|
||||||
|
# LCD RST: RC to 3.3 V, PSB to GND (serial mode)
|
||||||
|
substitutions:
|
||||||
|
device: cnc-pendant
|
||||||
|
name: CNC Pendant
|
||||||
|
area: Workshop
|
||||||
|
comment: Klipper CNC pendant
|
||||||
|
moonraker: http://klipper.local:7125
|
||||||
|
max_feed: "3000" # mm/min, handwheel jog feed cap
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: mcu-${device}
|
||||||
|
friendly_name: ${name}
|
||||||
|
area: ${area}
|
||||||
|
comment: ${comment}
|
||||||
|
includes:
|
||||||
|
- include/moonraker.h
|
||||||
|
on_boot:
|
||||||
|
- lambda: 'moonraker::client.start("${moonraker}");'
|
||||||
|
|
||||||
|
esp32:
|
||||||
|
variant: esp32s3
|
||||||
|
flash_size: 8MB
|
||||||
|
toolchain: esp-idf
|
||||||
|
framework:
|
||||||
|
type: esp-idf
|
||||||
|
|
||||||
|
packages:
|
||||||
|
common: !include common/common.yaml
|
||||||
|
# ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
status_led: !include
|
||||||
|
file: common/status_led.yaml
|
||||||
|
vars:
|
||||||
|
light_id: status_rgb
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: esp32_rmt_led_strip
|
||||||
|
id: status_rgb
|
||||||
|
name: LED
|
||||||
|
pin: 21
|
||||||
|
num_leds: 1
|
||||||
|
chipset: ws2812
|
||||||
|
rgb_order: GRB
|
||||||
|
restore_mode: ALWAYS_OFF
|
||||||
|
|
||||||
|
# only links esp_http_client for include/moonraker.h, which runs requests on its own task
|
||||||
|
http_request:
|
||||||
|
|
||||||
|
globals:
|
||||||
|
- id: axis
|
||||||
|
type: int
|
||||||
|
initial_value: "0" # 0 X, 1 Y, 2 Z
|
||||||
|
- id: step
|
||||||
|
type: int
|
||||||
|
initial_value: "1" # index into steps[] in the jog interval
|
||||||
|
- id: wheel_sent
|
||||||
|
type: float
|
||||||
|
initial_value: "0"
|
||||||
|
|
||||||
|
interval:
|
||||||
|
# handwheel: send the counts since the last jog as one relative move
|
||||||
|
- interval: 100ms
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
static const float steps[] = {0.01f, 0.1f, 1.0f};
|
||||||
|
float delta = id(handwheel).state - id(wheel_sent);
|
||||||
|
if (delta == 0 || std::isnan(delta)) return;
|
||||||
|
id(wheel_sent) = id(handwheel).state;
|
||||||
|
float dist = delta * steps[id(step)];
|
||||||
|
// feed so the move takes ~100 ms, i.e. about one interval
|
||||||
|
// ponytail: capped feed lets fast spins queue moves that keep running after the wheel stops; drop excess counts if that bites
|
||||||
|
float feed = std::min(std::max(std::fabs(dist) * 600.0f, 60.0f), ${max_feed}.0f);
|
||||||
|
moonraker::client.gcode(str_sprintf("G91\nG1 %c%.3f F%.0f\nG90", "XYZ"[id(axis)], dist, feed));
|
||||||
|
|
||||||
|
sensor:
|
||||||
|
- platform: rotary_encoder
|
||||||
|
id: handwheel
|
||||||
|
pin_a:
|
||||||
|
number: 1
|
||||||
|
mode: INPUT_PULLUP
|
||||||
|
pin_b:
|
||||||
|
number: 2
|
||||||
|
mode: INPUT_PULLUP
|
||||||
|
resolution: 1 # calibration: counts per detent, flip pin_a/pin_b if direction is wrong
|
||||||
|
- platform: rotary_encoder
|
||||||
|
id: axis_encoder
|
||||||
|
pin_a:
|
||||||
|
number: 4
|
||||||
|
mode: INPUT_PULLUP
|
||||||
|
pin_b:
|
||||||
|
number: 5
|
||||||
|
mode: INPUT_PULLUP
|
||||||
|
on_clockwise:
|
||||||
|
- lambda: 'id(axis) = std::min(id(axis) + 1, 2);'
|
||||||
|
on_anticlockwise:
|
||||||
|
- lambda: 'id(axis) = std::max(id(axis) - 1, 0);'
|
||||||
|
- platform: rotary_encoder
|
||||||
|
id: step_encoder
|
||||||
|
pin_a:
|
||||||
|
number: 7
|
||||||
|
mode: INPUT_PULLUP
|
||||||
|
pin_b:
|
||||||
|
number: 8
|
||||||
|
mode: INPUT_PULLUP
|
||||||
|
on_clockwise:
|
||||||
|
- lambda: 'id(step) = std::min(id(step) + 1, 2);'
|
||||||
|
on_anticlockwise:
|
||||||
|
- lambda: 'id(step) = std::max(id(step) - 1, 0);'
|
||||||
|
|
||||||
|
binary_sensor:
|
||||||
|
- platform: gpio
|
||||||
|
id: stamp_button
|
||||||
|
name: Stamp Button
|
||||||
|
pin:
|
||||||
|
number: 0
|
||||||
|
inverted: true
|
||||||
|
# axis push: zero the selected axis in work coordinates
|
||||||
|
- platform: gpio
|
||||||
|
id: axis_button
|
||||||
|
name: Axis Button
|
||||||
|
pin:
|
||||||
|
number: 6
|
||||||
|
mode: INPUT_PULLUP
|
||||||
|
inverted: true
|
||||||
|
filters:
|
||||||
|
- delayed_on_off: 20ms
|
||||||
|
on_press:
|
||||||
|
- lambda: 'moonraker::client.gcode(str_sprintf("G92 %c0", "XYZ"[id(axis)]));'
|
||||||
|
- platform: gpio
|
||||||
|
id: step_button
|
||||||
|
name: Step Button
|
||||||
|
pin:
|
||||||
|
number: 9
|
||||||
|
mode: INPUT_PULLUP
|
||||||
|
inverted: true
|
||||||
|
filters:
|
||||||
|
- delayed_on_off: 20ms
|
||||||
|
# BT1: home all
|
||||||
|
- platform: gpio
|
||||||
|
id: bt1
|
||||||
|
name: BT1
|
||||||
|
pin:
|
||||||
|
number: 10
|
||||||
|
mode: INPUT_PULLUP
|
||||||
|
inverted: true
|
||||||
|
filters:
|
||||||
|
- delayed_on_off: 20ms
|
||||||
|
on_press:
|
||||||
|
- lambda: 'moonraker::client.gcode("G28");'
|
||||||
|
# BT2: pause / resume
|
||||||
|
- platform: gpio
|
||||||
|
id: bt2
|
||||||
|
name: BT2
|
||||||
|
pin:
|
||||||
|
number: 11
|
||||||
|
mode: INPUT_PULLUP
|
||||||
|
inverted: true
|
||||||
|
filters:
|
||||||
|
- delayed_on_off: 20ms
|
||||||
|
on_press:
|
||||||
|
- lambda: 'moonraker::client.post(moonraker::client.status().state == "paused" ? "/printer/print/resume" : "/printer/print/pause");'
|
||||||
|
# BT3: hold 1 s for emergency stop (Klipper needs FIRMWARE_RESTART afterwards)
|
||||||
|
- platform: gpio
|
||||||
|
id: bt3
|
||||||
|
name: BT3
|
||||||
|
pin:
|
||||||
|
number: 12
|
||||||
|
mode: INPUT_PULLUP
|
||||||
|
inverted: true
|
||||||
|
filters:
|
||||||
|
- delayed_on_off: 20ms
|
||||||
|
on_multi_click:
|
||||||
|
- timing:
|
||||||
|
- ON for at least 1s
|
||||||
|
then:
|
||||||
|
- lambda: 'moonraker::client.post("/printer/emergency_stop", "", true);'
|
||||||
|
|
||||||
|
font:
|
||||||
|
# X11 misc-fixed bitmap fonts (as in u8g2 / Marlin), 6 px wide: axis letter + "-123.456" fits 64 px
|
||||||
|
- file: assets/fonts/6x13.bdf
|
||||||
|
id: font_big
|
||||||
|
- file: assets/fonts/6x10.bdf
|
||||||
|
id: font_small
|
||||||
|
|
||||||
|
spi:
|
||||||
|
clk_pin: 13
|
||||||
|
mosi_pin: 14
|
||||||
|
|
||||||
|
display:
|
||||||
|
- platform: st7920
|
||||||
|
id: lcd
|
||||||
|
cs_pin:
|
||||||
|
number: 15
|
||||||
|
inverted: true # ST7920 RS/CS is active high
|
||||||
|
data_rate: 1MHz # default 200kHz takes ~220 ms per frame; drop back if the picture garbles
|
||||||
|
width: 128
|
||||||
|
height: 64
|
||||||
|
rotation: 90 # mounted portrait, 270 if upside down
|
||||||
|
update_interval: 200ms
|
||||||
|
lambda: |-
|
||||||
|
static const char *steps[] = {"0.01", "0.1", "1"};
|
||||||
|
auto s = moonraker::client.status();
|
||||||
|
it.printf(0, 0, id(font_small), "%s", s.state.c_str());
|
||||||
|
it.printf(0, 10, id(font_small), "H:%s", s.homed.empty() ? "-" : s.homed.c_str());
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
int y = 22 + i * 14;
|
||||||
|
Color c = COLOR_ON;
|
||||||
|
if (i == id(axis)) {
|
||||||
|
it.filled_rectangle(0, y, 64, 13);
|
||||||
|
c = COLOR_OFF;
|
||||||
|
}
|
||||||
|
it.printf(1, y + 1, id(font_big), c, "%c", "XYZ"[i]);
|
||||||
|
it.printf(63, y + 1, id(font_big), c, TextAlign::TOP_RIGHT, "%.3f", s.pos[i]);
|
||||||
|
}
|
||||||
|
it.printf(0, 118, id(font_small), "%s mm", steps[id(step)]);
|
||||||
+10
-8
@@ -1,4 +1,11 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Xiaomi Mi Desk Lamp, brain transplant: M5Stack M5Stamp Pico (originally ESP8266)
|
||||||
|
# Pinout:
|
||||||
|
# GPIO18 Warm White (GPIO_PWM2) -> warm_white (output ledc)
|
||||||
|
# GPIO19 Cold White (GPIO_PWM1) -> cold_white (output ledc)
|
||||||
|
# GPIO21 Rotary switch A pin (GPIO_ROT_A) -> rotary (sensor rotary_encoder pin_a)
|
||||||
|
# GPIO26 Rotary switch B pin (GPIO_ROT_B) -> rotary (sensor rotary_encoder pin_b)
|
||||||
|
# GPIO36 Button (GPIO_KEY1) -> rotary_button (binary_sensor gpio) (inverted)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: desk-lamp
|
device: desk-lamp
|
||||||
name: Desk Lamp
|
name: Desk Lamp
|
||||||
@@ -15,18 +22,13 @@ esp32:
|
|||||||
variant: esp32
|
variant: esp32
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: gd
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
# Mi Desk Lamp
|
|
||||||
# Pin Function (Name)
|
|
||||||
# GPIO18: Warm White (GPIO_PWM2)
|
|
||||||
# GPIO19: Cold White (GPIO_PWM1)
|
|
||||||
# GPIO21: Rotary switch A pin (GPIO_ROT_A)
|
|
||||||
# GPIO26: Rotary switch B pin (GPIO_ROT_B)
|
|
||||||
# GPIO36: Button (GPIO_KEY1)
|
|
||||||
|
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
|
|||||||
@@ -1,4 +1,11 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack M5Stamp Pico
|
||||||
|
# Pinout:
|
||||||
|
# GPIO22 -> dimmer1 (output ac_dimmer gate_pin)
|
||||||
|
# GPIO25 -> dimmer1 (output ac_dimmer zero_cross_pin) (inverted)
|
||||||
|
# GPIO27 -> LED (light esp32_rmt_led_strip)
|
||||||
|
# GPIO32 Grove SDA
|
||||||
|
# GPIO33 Grove SCL
|
||||||
substitutions:
|
substitutions:
|
||||||
device: dimmer
|
device: dimmer
|
||||||
name: Dimmer
|
name: Dimmer
|
||||||
@@ -30,10 +37,13 @@ esp32:
|
|||||||
variant: esp32
|
variant: esp32
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: gd
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
|
||||||
# fan:
|
# fan:
|
||||||
# - platform: speed
|
# - platform: speed
|
||||||
|
|||||||
+19
-2
@@ -1,4 +1,14 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack ATOM Echo
|
||||||
|
# Pinout:
|
||||||
|
# GPIO19 -> speaker_bus (i2s_audio i2s_bclk_pin)
|
||||||
|
# GPIO22 -> speaker_id (speaker i2s_audio i2s_dout_pin)
|
||||||
|
# GPIO23 -> echo_microphone (microphone i2s_audio i2s_din_pin)
|
||||||
|
# GPIO26 Grove SDA
|
||||||
|
# GPIO27 ATOM RGB LED -> LED [neo_buildin] (light esp32_rmt_led_strip), also status
|
||||||
|
# GPIO32 Grove SCL
|
||||||
|
# GPIO33 -> speaker_bus (i2s_audio i2s_lrclk_pin)
|
||||||
|
# GPIO39 -> Button (binary_sensor gpio) (inverted)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: echo-1
|
device: echo-1
|
||||||
name: Echo 1
|
name: Echo 1
|
||||||
@@ -15,10 +25,17 @@ esphome:
|
|||||||
esp32:
|
esp32:
|
||||||
variant: esp32
|
variant: esp32
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: gd
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
status_led: !include
|
||||||
|
file: common/status_led.yaml
|
||||||
|
vars:
|
||||||
|
light_id: neo_buildin
|
||||||
|
|
||||||
api:
|
api:
|
||||||
actions:
|
actions:
|
||||||
@@ -131,10 +148,10 @@ media_player:
|
|||||||
buffer_size: 14000
|
buffer_size: 14000
|
||||||
media_pipeline:
|
media_pipeline:
|
||||||
speaker: media_spk_resampling_input
|
speaker: media_spk_resampling_input
|
||||||
format: NONE
|
format: WAV # no PSRAM: HA transcodes to WAV, decoding MP3/FLAC here runs the heap out
|
||||||
announcement_pipeline:
|
announcement_pipeline:
|
||||||
speaker: announcement_spk_resampling_input
|
speaker: announcement_spk_resampling_input
|
||||||
format: NONE
|
format: WAV # no PSRAM: HA transcodes to WAV, decoding MP3/FLAC here runs the heap out
|
||||||
|
|
||||||
rtttl:
|
rtttl:
|
||||||
id: my_rtttl
|
id: my_rtttl
|
||||||
|
|||||||
+22
-11
@@ -1,4 +1,16 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Xiaomi Mijia Gateway, brain transplant: M5Stack ATOM Echo (kept the speaker, LEDs and PSU)
|
||||||
|
# Pinout:
|
||||||
|
# GPIO12 -> Button (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO19 -> speaker_bus (i2s_audio i2s_bclk_pin)
|
||||||
|
# GPIO21 Gateway LED ring red -> led_red (output ledc)
|
||||||
|
# GPIO22 -> speaker_id (speaker i2s_audio i2s_dout_pin)
|
||||||
|
# GPIO23 Gateway LED ring blue -> led_blue (output ledc)
|
||||||
|
# GPIO25 Gateway LED ring green -> led_green (output ledc)
|
||||||
|
# GPIO26 Grove SDA -> i2c (i2c sda)
|
||||||
|
# GPIO27 ATOM onboard RGB LED (inside, not visible)
|
||||||
|
# GPIO32 Grove SCL -> i2c (i2c scl)
|
||||||
|
# GPIO33 -> speaker_bus (i2s_audio i2s_lrclk_pin)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: echo
|
device: echo
|
||||||
name: Echo
|
name: Echo
|
||||||
@@ -16,10 +28,17 @@ esp32:
|
|||||||
variant: esp32
|
variant: esp32
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: gd
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
status_led: !include
|
||||||
|
file: common/status_led.yaml
|
||||||
|
vars:
|
||||||
|
light_id: led_light
|
||||||
|
|
||||||
api:
|
api:
|
||||||
actions:
|
actions:
|
||||||
@@ -71,11 +90,6 @@ light:
|
|||||||
red: led_red
|
red: led_red
|
||||||
green: led_green
|
green: led_green
|
||||||
blue: led_blue
|
blue: led_blue
|
||||||
- platform: status_led
|
|
||||||
id: led_status
|
|
||||||
pin:
|
|
||||||
number: 23
|
|
||||||
allow_other_uses: true
|
|
||||||
|
|
||||||
output:
|
output:
|
||||||
- platform: ledc
|
- platform: ledc
|
||||||
@@ -86,9 +100,7 @@ output:
|
|||||||
pin: 25
|
pin: 25
|
||||||
- platform: ledc
|
- platform: ledc
|
||||||
id: led_blue
|
id: led_blue
|
||||||
pin:
|
pin: 23
|
||||||
number: 23
|
|
||||||
allow_other_uses: true
|
|
||||||
|
|
||||||
i2s_audio:
|
i2s_audio:
|
||||||
- id: speaker_bus
|
- id: speaker_bus
|
||||||
@@ -127,16 +139,15 @@ media_player:
|
|||||||
- platform: speaker
|
- platform: speaker
|
||||||
id: media_out
|
id: media_out
|
||||||
name: Player
|
name: Player
|
||||||
codec_support_enabled: false
|
|
||||||
buffer_size: 14000
|
buffer_size: 14000
|
||||||
media_pipeline:
|
media_pipeline:
|
||||||
speaker: media_spk_resampling_input
|
speaker: media_spk_resampling_input
|
||||||
# format: WAV
|
format: WAV # only the WAV decoder is built (was codec_support_enabled: false)
|
||||||
# num_channels: 1
|
# num_channels: 1
|
||||||
# sample_rate: 8000 # Lower sample rate
|
# sample_rate: 8000 # Lower sample rate
|
||||||
announcement_pipeline:
|
announcement_pipeline:
|
||||||
speaker: announcement_spk_resampling_input
|
speaker: announcement_spk_resampling_input
|
||||||
# format: WAV
|
format: WAV
|
||||||
# num_channels: 1
|
# num_channels: 1
|
||||||
# sample_rate: 8000 # Lower sample rate
|
# sample_rate: 8000 # Lower sample rate
|
||||||
on_play:
|
on_play:
|
||||||
|
|||||||
+18
-22
@@ -1,4 +1,22 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack M5Stamp C3
|
||||||
|
# Pinout:
|
||||||
|
# GPIO0 I2C SCL -> i2c_grove (i2c scl)
|
||||||
|
# GPIO1 I2C SDA, BUTTON -> i2c_grove (i2c sda)
|
||||||
|
# GPIO2 RGB
|
||||||
|
# GPIO4 GPIO
|
||||||
|
# GPIO5 GPIO
|
||||||
|
# GPIO6 GPIO
|
||||||
|
# GPIO7 GPIO
|
||||||
|
# GPIO8 GPIO
|
||||||
|
# GPIO9 GPIO
|
||||||
|
# GPIO10 GPIO
|
||||||
|
# GPIO18 UART RX -> uart_hdmi_switch (uart rx_pin)
|
||||||
|
# GPIO19 UART TX -> uart_hdmi_switch (uart tx_pin)
|
||||||
|
# GPIO20 UART RX, LOGGER -> uart_log (uart rx_pin)
|
||||||
|
# GPIO21 UART TX, LOGGER -> uart_log (uart tx_pin)
|
||||||
|
# I2C:
|
||||||
|
# 0x20 pcf8574_hub (pcf8574)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: eworkbench
|
device: eworkbench
|
||||||
name: Electronics Workbench
|
name: Electronics Workbench
|
||||||
@@ -22,23 +40,6 @@ esp32:
|
|||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
|
||||||
# GPIO20 UART RX, LOGGER
|
|
||||||
# GPIO21 UART TX, LOGGER
|
|
||||||
# GPIO9 GPIO
|
|
||||||
#
|
|
||||||
# GPIO0 I2C SCL
|
|
||||||
# GPIO1 I2C SDA
|
|
||||||
# GPIO2 RGB
|
|
||||||
# GPIO1 BUTTON
|
|
||||||
# GPIO4 GPIO
|
|
||||||
# GPIO5 GPIO
|
|
||||||
# GPIO6 GPIO
|
|
||||||
# GPIO7 GPIO
|
|
||||||
# GPIO8 GPIO
|
|
||||||
# GPIO10 GPIO
|
|
||||||
# GPIO18 UART RX
|
|
||||||
# GPIO19 UART TX
|
|
||||||
|
|
||||||
i2c:
|
i2c:
|
||||||
- id: i2c_grove
|
- id: i2c_grove
|
||||||
sda: 1
|
sda: 1
|
||||||
@@ -242,11 +243,6 @@ binary_sensor:
|
|||||||
# on_clockwise:
|
# on_clockwise:
|
||||||
# - display_menu.down:
|
# - display_menu.down:
|
||||||
|
|
||||||
time:
|
|
||||||
- platform: homeassistant
|
|
||||||
id: ha_time
|
|
||||||
timezone: Europe/Bratislava
|
|
||||||
|
|
||||||
# display:
|
# display:
|
||||||
# - platform: tm1637
|
# - platform: tm1637
|
||||||
# id: tm1637_display
|
# id: tm1637_display
|
||||||
|
|||||||
+30
-68
@@ -1,4 +1,22 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack ATOM Lite + ATOM Hub Switch
|
||||||
|
# Pinout:
|
||||||
|
# GPIO1 UART0 TX
|
||||||
|
# GPIO3 UART0 RX
|
||||||
|
# GPIO12 IR
|
||||||
|
# GPIO19 Relay2
|
||||||
|
# GPIO21 I2C1 SCL -> i2c (i2c scl)
|
||||||
|
# GPIO22 Relay1
|
||||||
|
# GPIO23 RS485 Tx
|
||||||
|
# GPIO25 I2C1 SDA - red -> i2c (i2c sda)
|
||||||
|
# GPIO26 I2C0 SDA - white
|
||||||
|
# GPIO27 NEO 1x -> atom_led (status LED, common/status_led_atom.yaml)
|
||||||
|
# GPIO32 I2C0 SCL
|
||||||
|
# GPIO33 RS485 Rx
|
||||||
|
# GPIO39 BUTTON -> Status Button (binary_sensor gpio)
|
||||||
|
# I2C:
|
||||||
|
# 0x18 one_wire_bus (one_wire ds2482)
|
||||||
|
# 0x27 pca9554_module (pca9554)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: fireplace
|
device: fireplace
|
||||||
name: Heating Fireplace
|
name: Heating Fireplace
|
||||||
@@ -15,76 +33,30 @@ esp32:
|
|||||||
variant: esp32
|
variant: esp32
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: gd
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
external_components:
|
|
||||||
# - source: github://pr#12717
|
|
||||||
# components: [ds248x]
|
|
||||||
# refresh: 1h
|
|
||||||
- source: github://pr#13534
|
|
||||||
components: [ds2482, ds2484, ds248x_base]
|
|
||||||
refresh: 1h
|
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
status_led: !include common/status_led_atom.yaml
|
||||||
# PINOUTS: M5ATOM+Atom Hub Switch
|
|
||||||
# IR G12
|
|
||||||
# NEO G27 1x
|
|
||||||
# BUTTON G39
|
|
||||||
# I2C0 SDA G26 - white
|
|
||||||
# I2C0 SCL G32
|
|
||||||
# I2C1 SDA G25 - red
|
|
||||||
# I2C1 SCL G21
|
|
||||||
# UART0 RX G3
|
|
||||||
# UART0 TX G1
|
|
||||||
# RS485 Rx G33
|
|
||||||
# RS485 Tx G23
|
|
||||||
# Relay1 G22
|
|
||||||
# Relay2 G19
|
|
||||||
|
|
||||||
time:
|
|
||||||
- platform: homeassistant
|
|
||||||
id: ha_time
|
|
||||||
timezone: Europe/Bratislava
|
|
||||||
|
|
||||||
i2c:
|
i2c:
|
||||||
# - id: i2c0
|
|
||||||
# sda: 26
|
|
||||||
# scl: 32
|
|
||||||
# scan: true #false
|
|
||||||
# - id: i2c1
|
|
||||||
sda: 25
|
sda: 25
|
||||||
scl: 21
|
scl: 21
|
||||||
scan: true #false
|
scan: true #false
|
||||||
|
|
||||||
# ds248x:
|
ds248x:
|
||||||
# # i2c_id: i2c_main
|
id: ds2484_module
|
||||||
# address: 0x18 # should be the default
|
type: ds2482-100
|
||||||
# # sleep_pin: 32 # remove if not needed, if set the ds248x sleeps when no transaction is in progress
|
address: 0x18
|
||||||
# active_pullup: true # adds a active pullup which should improve signal integrity
|
active_pullup: true
|
||||||
# strong_pullup: false # enables a strong pullup used to provide the needed current for temperature reading without vcc connected
|
|
||||||
# bus_sleep: true # power down the bus when no transaction is in progres
|
|
||||||
|
|
||||||
# one_wire:
|
|
||||||
# id: one_wire_bus
|
|
||||||
# platform: ds2484
|
|
||||||
# active_pullup: true
|
|
||||||
|
|
||||||
# ds248x:
|
|
||||||
# id: ds2484_module
|
|
||||||
# address: 0x18
|
|
||||||
|
|
||||||
# one_wire:
|
|
||||||
# - platform: ds248x
|
|
||||||
# ds248x_id: ds2484_module
|
|
||||||
# id: one_wire_bus
|
|
||||||
|
|
||||||
one_wire:
|
one_wire:
|
||||||
id: one_wire_bus
|
- platform: ds248x
|
||||||
platform: ds2482
|
ds248x_id: ds2484_module
|
||||||
active_pullup: true
|
id: one_wire_bus
|
||||||
|
|
||||||
pca9554:
|
pca9554:
|
||||||
- id: pca9554_module
|
- id: pca9554_module
|
||||||
@@ -131,16 +103,6 @@ sensor:
|
|||||||
# index: 0
|
# index: 0
|
||||||
name: Temperature
|
name: Temperature
|
||||||
id: 'heating_fireplace_temperature'
|
id: 'heating_fireplace_temperature'
|
||||||
# - platform: dht
|
|
||||||
# pin: 14
|
|
||||||
# temperature:
|
|
||||||
# name: "Kitchen Temperature"
|
|
||||||
# id: 'kitchen_temperature'
|
|
||||||
# humidity:
|
|
||||||
# name: "Kitchen Humidity"
|
|
||||||
# id: 'kitchen_humidity'
|
|
||||||
# update_interval: 60s
|
|
||||||
# model: si7021
|
|
||||||
|
|
||||||
bluetooth_proxy:
|
bluetooth_proxy:
|
||||||
active: true
|
active: true
|
||||||
+19
-15
@@ -1,4 +1,19 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack ATOM Lite + ATOM Hub Switch
|
||||||
|
# Pinout:
|
||||||
|
# GPIO1 UART0 TX
|
||||||
|
# GPIO3 UART0 RX
|
||||||
|
# GPIO12 IR
|
||||||
|
# GPIO19 RELAY-2 -> relay_2 (output gpio)
|
||||||
|
# GPIO21 I2C1 SCL
|
||||||
|
# GPIO22 RELAY-1 -> relay_1 (output gpio)
|
||||||
|
# GPIO23 RS485 TX
|
||||||
|
# GPIO25 I2C1 SDA red
|
||||||
|
# GPIO26 I2C0 SDA white
|
||||||
|
# GPIO27 NEO -> atom_led (status LED, common/status_led_atom.yaml)
|
||||||
|
# GPIO32 I2C0 SCL -> gate_ogi_state (binary_sensor gpio) (inverted); gate_ogi_blink (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO33 RS485 RX
|
||||||
|
# GPIO39 BUTTON
|
||||||
substitutions:
|
substitutions:
|
||||||
device: gate
|
device: gate
|
||||||
name: Gate
|
name: Gate
|
||||||
@@ -15,25 +30,14 @@ esp32:
|
|||||||
variant: esp32
|
variant: esp32
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: gd
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
# PINOUTS: M5ATOM
|
status_led: !include common/status_led_atom.yaml
|
||||||
# IR G12
|
|
||||||
# NEO G27
|
|
||||||
# BUTTON G39
|
|
||||||
# I2C0 SDA G26 white
|
|
||||||
# I2C0 SCL G32
|
|
||||||
# I2C1 SDA G25 red
|
|
||||||
# I2C1 SCL G21
|
|
||||||
# UART0 RX G3
|
|
||||||
# UART0 TX G1
|
|
||||||
# RS485 RX G33
|
|
||||||
# RS485 TX G23
|
|
||||||
# RELAY-1 G22
|
|
||||||
# RELAY-2 G19
|
|
||||||
|
|
||||||
button:
|
button:
|
||||||
- platform: output
|
- platform: output
|
||||||
|
|||||||
+29
-16
@@ -1,4 +1,31 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Olimex ESP32-POE-ISO
|
||||||
|
# Pinout:
|
||||||
|
# # UEXT
|
||||||
|
# 3V3 1 2 GND
|
||||||
|
# GPIO4 3 4 GPIO36 U1TXD/U1RXD
|
||||||
|
# GPIO16 5 6 GPIO13 I2C-SCL/I2C-SDA
|
||||||
|
# GPIO15 7 8 GPIO2 HS2_CMD/HS2_DATA0
|
||||||
|
# GPIO14 9 10 GPIO5 HS2_CLK/SPI_CS
|
||||||
|
#
|
||||||
|
# SD/MMC; shared with UEXT, no CS!!!
|
||||||
|
# GPIO15 HS2_CMD
|
||||||
|
# GPIO14 HS2_CLK
|
||||||
|
# GPIO2 HS2_DATA0
|
||||||
|
#
|
||||||
|
# GPIO34 BUT1
|
||||||
|
# GPIO35 Battery Measurment ADC
|
||||||
|
# GPIO39 Ext Power Sense ADC
|
||||||
|
# Used:
|
||||||
|
# GPIO4 uart_modbus (uart tx_pin)
|
||||||
|
# GPIO12 ethernet (ethernet power_pin)
|
||||||
|
# GPIO13 i2c (i2c sda)
|
||||||
|
# GPIO16 i2c (i2c scl)
|
||||||
|
# GPIO17 ethernet (ethernet)
|
||||||
|
# GPIO18 ethernet (ethernet mdio_pin)
|
||||||
|
# GPIO23 ethernet (ethernet mdc_pin)
|
||||||
|
# GPIO34 user_button (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO36 uart_modbus (uart rx_pin)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: gateway
|
device: gateway
|
||||||
name: Gateway
|
name: Gateway
|
||||||
@@ -17,6 +44,7 @@ esp32:
|
|||||||
framework:
|
framework:
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
advanced:
|
advanced:
|
||||||
|
flash_chip: generic
|
||||||
minimum_chip_revision: 3.0
|
minimum_chip_revision: 3.0
|
||||||
sram1_as_iram: true
|
sram1_as_iram: true
|
||||||
|
|
||||||
@@ -32,22 +60,7 @@ external_components:
|
|||||||
packages:
|
packages:
|
||||||
# common: !include common/common.yaml
|
# common: !include common/common.yaml
|
||||||
common_eth: !include common/common_eth.yaml
|
common_eth: !include common/common_eth.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only_eth.yaml
|
||||||
## UEXT
|
|
||||||
# 3V3 1 2 GND
|
|
||||||
# GPIO4 3 4 GPIO36 U1TXD/U1RXD
|
|
||||||
# GPIO16 5 6 GPIO13 I2C-SCL/I2C-SDA
|
|
||||||
# GPIO15 7 8 GPIO2 HS2_CMD/HS2_DATA0
|
|
||||||
# GPIO14 9 10 GPIO5 HS2_CLK/SPI_CS
|
|
||||||
#
|
|
||||||
# SD/MMC; shared with UEXT, no CS!!!
|
|
||||||
# GPIO15 HS2_CMD
|
|
||||||
# GPIO14 HS2_CLK
|
|
||||||
# GPIO2 HS2_DATA0
|
|
||||||
|
|
||||||
# GPIO34 BUT1
|
|
||||||
# GPIO35 Battery Measurment ADC
|
|
||||||
# GPIO39 Ext Power Sense ADC
|
|
||||||
|
|
||||||
i2c:
|
i2c:
|
||||||
sda: 13
|
sda: 13
|
||||||
|
|||||||
+32
-56
@@ -1,4 +1,22 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack ATOM Lite + ATOM Hub Switch
|
||||||
|
# Pinout:
|
||||||
|
# GPIO1 UART0 TX
|
||||||
|
# GPIO3 UART0 RX
|
||||||
|
# GPIO12 IR
|
||||||
|
# GPIO19 NC -> Demand [heating_demand] (switch gpio)
|
||||||
|
# GPIO21 I2C1 SCL -> i2c (i2c scl)
|
||||||
|
# GPIO22 1-WIRE -> Demand [hot_water_demand] (switch gpio)
|
||||||
|
# GPIO23 UART1 RX -> uart_modbus (uart rx_pin)
|
||||||
|
# GPIO25 I2C1 SDA -> i2c (i2c sda)
|
||||||
|
# GPIO26 I2C0 SDA
|
||||||
|
# GPIO27 NEO -> atom_led (status LED, common/status_led_atom.yaml)
|
||||||
|
# GPIO32 I2C0 SCL
|
||||||
|
# GPIO33 UART1 TX -> uart_modbus (uart tx_pin)
|
||||||
|
# GPIO39 BUTTON
|
||||||
|
# I2C:
|
||||||
|
# 0x18 one_wire_bus (one_wire ds2482)
|
||||||
|
# 0x27 pca9554_module (pca9554)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: heater
|
device: heater
|
||||||
name: Heater
|
name: Heater
|
||||||
@@ -25,40 +43,14 @@ esp32:
|
|||||||
variant: esp32
|
variant: esp32
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: gd
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
external_components:
|
|
||||||
# - source: github://pr#12717
|
|
||||||
# components: [ds248x]
|
|
||||||
# refresh: 1h
|
|
||||||
- source: github://pr#13534
|
|
||||||
components: [ds2482, ds2484, ds248x_base]
|
|
||||||
refresh: 1h
|
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
# PINOUTS: M5ATOM
|
status_led: !include common/status_led_atom.yaml
|
||||||
# IR G12
|
|
||||||
# NEO G27
|
|
||||||
# BUTTON G39
|
|
||||||
# I2C0 SDA G26
|
|
||||||
# I2C0 SCL G32
|
|
||||||
# I2C1 SDA G25
|
|
||||||
# I2C1 SCL G21
|
|
||||||
# UART0 RX G3
|
|
||||||
# UART0 TX G1
|
|
||||||
# UART1 RX G23
|
|
||||||
# UART1 TX G33
|
|
||||||
# 1-WIRE G22
|
|
||||||
# NC G19
|
|
||||||
|
|
||||||
#logger:
|
|
||||||
# level: VERBOSE
|
|
||||||
# logs:
|
|
||||||
# dallas.component: ERROR
|
|
||||||
# uart.component: ERROR
|
|
||||||
# i2c.component: VERBOSE
|
|
||||||
|
|
||||||
# Heating / Hot water Controller
|
# Heating / Hot water Controller
|
||||||
# temp_1: Solar Collector
|
# temp_1: Solar Collector
|
||||||
@@ -129,9 +121,7 @@ globals:
|
|||||||
initial_value: '20.5'
|
initial_value: '20.5'
|
||||||
|
|
||||||
time:
|
time:
|
||||||
- platform: homeassistant
|
- id: !extend ha_time
|
||||||
id: ha_time
|
|
||||||
timezone: Europe/Bratislava
|
|
||||||
on_time:
|
on_time:
|
||||||
- seconds: 0
|
- seconds: 0
|
||||||
minutes: /1
|
minutes: /1
|
||||||
@@ -165,36 +155,22 @@ climate:
|
|||||||
default_target_temperature_high: 40 °C
|
default_target_temperature_high: 40 °C
|
||||||
|
|
||||||
i2c:
|
i2c:
|
||||||
# - id: i2c0
|
|
||||||
# sda: 26
|
|
||||||
# scl: 32
|
|
||||||
# scan: true #false
|
|
||||||
# - id: i2c1
|
|
||||||
sda: 25
|
sda: 25
|
||||||
scl: 21
|
scl: 21
|
||||||
scan: true #false
|
scan: true #false
|
||||||
|
|
||||||
# one_wire:
|
|
||||||
# id: one_wire_bus
|
|
||||||
# # i2c_id: i2c_main
|
|
||||||
# platform: ds2484
|
|
||||||
# active_pullup: true
|
|
||||||
|
|
||||||
# ds248x:
|
ds248x:
|
||||||
# id: ds2484_module
|
id: ds2482_module
|
||||||
# address: 0x18
|
type: ds2482-100
|
||||||
# active_pullup: true
|
address: 0x18
|
||||||
|
active_pullup: true
|
||||||
# one_wire:
|
|
||||||
# - platform: ds248x
|
|
||||||
# ds248x_id: ds2484_module
|
|
||||||
# id: one_wire_bus
|
|
||||||
|
|
||||||
one_wire:
|
one_wire:
|
||||||
id: one_wire_bus
|
- platform: ds248x
|
||||||
# i2c_id: i2c_main
|
ds248x_id: ds2482_module
|
||||||
platform: ds2482
|
id: one_wire_bus
|
||||||
active_pullup: true
|
|
||||||
|
|
||||||
modbus:
|
modbus:
|
||||||
uart_id: uart_modbus
|
uart_id: uart_modbus
|
||||||
|
|||||||
+23
-22
@@ -1,4 +1,21 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack ATOM Lite + ATOM Hub Switch
|
||||||
|
# Pinout:
|
||||||
|
# GPIO1 UART0 TX
|
||||||
|
# GPIO3 UART0 RX
|
||||||
|
# GPIO12 IR
|
||||||
|
# GPIO19 Relay2
|
||||||
|
# GPIO21 I2C1 SCL -> i2c (i2c scl)
|
||||||
|
# GPIO22 Relay1 -> power_supply1 (power_supply)
|
||||||
|
# GPIO23 RS485 Tx
|
||||||
|
# GPIO25 I2C1 SDA - red -> i2c (i2c sda)
|
||||||
|
# GPIO26 I2C0 SDA - white
|
||||||
|
# GPIO27 NEO 1x -> atom_led (status LED, common/status_led_atom.yaml)
|
||||||
|
# GPIO32 I2C0 SCL
|
||||||
|
# GPIO33 RS485 Rx
|
||||||
|
# GPIO39 BUTTON -> Status Button (binary_sensor gpio)
|
||||||
|
# I2C:
|
||||||
|
# 0x40 pca9685_hub1 (pca9685)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: kitchen
|
device: kitchen
|
||||||
name: Kitchen
|
name: Kitchen
|
||||||
@@ -32,33 +49,17 @@ esp32:
|
|||||||
variant: esp32
|
variant: esp32
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: gd
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
status_led: !include common/status_led_atom.yaml
|
||||||
|
|
||||||
api:
|
# api:
|
||||||
reboot_timeout: 300s
|
# reboot_timeout: 300s
|
||||||
|
|
||||||
# PINOUTS: M5ATOM+Atom Hub Switch
|
|
||||||
# IR G12
|
|
||||||
# NEO G27 1x
|
|
||||||
# BUTTON G39
|
|
||||||
# I2C0 SDA G26 - white
|
|
||||||
# I2C0 SCL G32
|
|
||||||
# I2C1 SDA G25 - red
|
|
||||||
# I2C1 SCL G21
|
|
||||||
# UART0 RX G3
|
|
||||||
# UART0 TX G1
|
|
||||||
# RS485 Rx G33
|
|
||||||
# RS485 Tx G23
|
|
||||||
# Relay1 G22
|
|
||||||
# Relay2 G19
|
|
||||||
|
|
||||||
time:
|
|
||||||
- platform: homeassistant
|
|
||||||
id: ha_time
|
|
||||||
timezone: Europe/Bratislava
|
|
||||||
|
|
||||||
i2c:
|
i2c:
|
||||||
# - id: i2c0
|
# - id: i2c0
|
||||||
|
|||||||
@@ -1,4 +1,14 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack M5Stamp Pico
|
||||||
|
# Pinout:
|
||||||
|
# GPIO22 -> i2c (i2c scl)
|
||||||
|
# GPIO25 -> i2c (i2c sda)
|
||||||
|
# GPIO26 -> as3935_i2c (as3935_i2c irq_pin)
|
||||||
|
# GPIO27 -> neo (light esp32_rmt_led_strip)
|
||||||
|
# GPIO32 Grove SDA
|
||||||
|
# GPIO33 Grove SCL
|
||||||
|
# I2C:
|
||||||
|
# 0x03 as3935_i2c (as3935_i2c)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: lightening
|
device: lightening
|
||||||
name: Lightening detector
|
name: Lightening detector
|
||||||
@@ -16,6 +26,8 @@ esp32:
|
|||||||
variant: esp32
|
variant: esp32
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: gd # ESP32-PICO-D4, like the other M5Stamp Pico (not read from the device)
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|||||||
@@ -0,0 +1,337 @@
|
|||||||
|
---
|
||||||
|
# Hardware: Guition ESP32-S3-4848S040
|
||||||
|
# Pinout:
|
||||||
|
# # Display (RGB, pins in the mipi_rgb model)
|
||||||
|
# CS 39
|
||||||
|
# SCK 48 ST7701S init (3-wire SPI)
|
||||||
|
# SDA 47
|
||||||
|
# DE 18
|
||||||
|
# HSYNC 16
|
||||||
|
# VSYNC 17
|
||||||
|
# PCLK 21
|
||||||
|
# BL 38
|
||||||
|
# # Capacitive Touch (GT911)
|
||||||
|
# TP_SDA 19
|
||||||
|
# TP_SCL 45
|
||||||
|
# # Relays (86 box variant)
|
||||||
|
# RELAY1 40
|
||||||
|
# RELAY2 2
|
||||||
|
# RELAY3 1
|
||||||
|
# Used:
|
||||||
|
# GPIO0 main_display (display mipi_rgb data_pins.red)
|
||||||
|
# GPIO3 main_display (display mipi_rgb data_pins.green)
|
||||||
|
# GPIO4 main_display (display mipi_rgb data_pins.blue)
|
||||||
|
# GPIO5 main_display (display mipi_rgb data_pins.blue)
|
||||||
|
# GPIO6 main_display (display mipi_rgb data_pins.blue)
|
||||||
|
# GPIO7 main_display (display mipi_rgb data_pins.blue)
|
||||||
|
# GPIO8 main_display (display mipi_rgb data_pins.green)
|
||||||
|
# GPIO9 main_display (display mipi_rgb data_pins.green)
|
||||||
|
# GPIO10 main_display (display mipi_rgb data_pins.green)
|
||||||
|
# GPIO11 main_display (display mipi_rgb data_pins.red)
|
||||||
|
# GPIO12 main_display (display mipi_rgb data_pins.red)
|
||||||
|
# GPIO13 main_display (display mipi_rgb data_pins.red)
|
||||||
|
# GPIO14 main_display (display mipi_rgb data_pins.red)
|
||||||
|
# GPIO15 main_display (display mipi_rgb data_pins.blue)
|
||||||
|
# GPIO16 main_display (display mipi_rgb hsync_pin)
|
||||||
|
# GPIO17 main_display (display mipi_rgb vsync_pin)
|
||||||
|
# GPIO18 main_display (display mipi_rgb de_pin)
|
||||||
|
# GPIO19 i2c_main (i2c sda)
|
||||||
|
# GPIO20 main_display (display mipi_rgb data_pins.green)
|
||||||
|
# GPIO21 main_display (display mipi_rgb pclk_pin)
|
||||||
|
# GPIO38 gpio_backlight_pwm (output ledc)
|
||||||
|
# GPIO39 main_display (display mipi_rgb cs_pin)
|
||||||
|
# GPIO45 i2c_main (i2c scl)
|
||||||
|
# GPIO46 main_display (display mipi_rgb data_pins.green)
|
||||||
|
# GPIO47 lcd_spi (spi mosi_pin)
|
||||||
|
# GPIO48 lcd_spi (spi clk_pin)
|
||||||
|
# I2C:
|
||||||
|
# 0x5D main_touch (touchscreen gt911)
|
||||||
|
substitutions:
|
||||||
|
device: lvgl-4848s040
|
||||||
|
name: LVGL 4848S040
|
||||||
|
area: DEV
|
||||||
|
comment: "${area} | Guition ESP32-S3-4848S040"
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: mcu-${device}
|
||||||
|
friendly_name: ${name}
|
||||||
|
area: ${area}
|
||||||
|
comment: ${comment}
|
||||||
|
on_boot:
|
||||||
|
- priority: -100
|
||||||
|
then:
|
||||||
|
- lvgl.page.show: status_page
|
||||||
|
|
||||||
|
esp32:
|
||||||
|
variant: esp32s3
|
||||||
|
flash_size: 16MB
|
||||||
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: boya
|
||||||
|
type: esp-idf
|
||||||
|
# PSRAM bandwidth for the RGB panel (not set by ESPHome); without it the
|
||||||
|
# image shifts during flash/WiFi activity
|
||||||
|
sdkconfig_options:
|
||||||
|
CONFIG_ESP32S3_DATA_CACHE_64KB: y
|
||||||
|
CONFIG_SPIRAM_FETCH_INSTRUCTIONS: y
|
||||||
|
CONFIG_SPIRAM_RODATA: y
|
||||||
|
|
||||||
|
psram:
|
||||||
|
mode: octal
|
||||||
|
speed: 80MHz
|
||||||
|
|
||||||
|
packages:
|
||||||
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
|
||||||
|
api:
|
||||||
|
# status page until Home Assistant connects (log viewers don't subscribe to states)
|
||||||
|
on_client_connected:
|
||||||
|
- delay: 2s
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
api.connected:
|
||||||
|
state_subscription_only: true
|
||||||
|
then:
|
||||||
|
- lvgl.page.show: main_page
|
||||||
|
on_client_disconnected:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
not:
|
||||||
|
api.connected:
|
||||||
|
state_subscription_only: true
|
||||||
|
then:
|
||||||
|
- lvgl.page.show: status_page
|
||||||
|
|
||||||
|
i2c:
|
||||||
|
- id: i2c_main
|
||||||
|
sda: 19
|
||||||
|
scl: 45
|
||||||
|
scan: true
|
||||||
|
|
||||||
|
spi:
|
||||||
|
- id: lcd_spi
|
||||||
|
clk_pin: 48
|
||||||
|
mosi_pin: 47
|
||||||
|
|
||||||
|
display:
|
||||||
|
- platform: mipi_rgb
|
||||||
|
model: GUITION-4848S040
|
||||||
|
id: main_display
|
||||||
|
spi_id: lcd_spi
|
||||||
|
update_interval: never
|
||||||
|
auto_clear_enabled: false
|
||||||
|
|
||||||
|
touchscreen:
|
||||||
|
- platform: gt911
|
||||||
|
id: main_touch
|
||||||
|
display: main_display
|
||||||
|
i2c_id: i2c_main
|
||||||
|
# the mipi_rgb model mirrors the image on both axes, touch has to follow
|
||||||
|
transform:
|
||||||
|
mirror_x: true
|
||||||
|
mirror_y: true
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: ledc
|
||||||
|
id: gpio_backlight_pwm
|
||||||
|
pin: 38
|
||||||
|
frequency: 1220
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: monochromatic
|
||||||
|
id: back_light
|
||||||
|
name: Backlight
|
||||||
|
output: gpio_backlight_pwm
|
||||||
|
restore_mode: ALWAYS_ON
|
||||||
|
|
||||||
|
script:
|
||||||
|
- id: update_status
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
// same colors as the other status screens: ok green, waiting orange, details gray
|
||||||
|
static const uint32_t OK = 0x4DD966, WAIT = 0xFFB300;
|
||||||
|
auto set = [](lv_obj_t *label, const std::string &text, uint32_t color) {
|
||||||
|
lv_label_set_text(label, text.c_str());
|
||||||
|
lv_obj_set_style_text_color(label, lv_color_hex(color), LV_PART_MAIN);
|
||||||
|
};
|
||||||
|
|
||||||
|
const bool wifi_ok = wifi::global_wifi_component->is_connected();
|
||||||
|
set(id(status_wifi),
|
||||||
|
wifi_ok ? str_sprintf("WiFi: connected (%d dBm)", wifi::global_wifi_component->wifi_rssi())
|
||||||
|
: std::string("WiFi: connecting..."),
|
||||||
|
wifi_ok ? OK : WAIT);
|
||||||
|
|
||||||
|
// IPv6 first (skip link-local), then IPv4
|
||||||
|
std::string ips;
|
||||||
|
if (wifi_ok) {
|
||||||
|
char buf[network::IP_ADDRESS_BUFFER_SIZE];
|
||||||
|
for (bool v6 : {true, false}) {
|
||||||
|
for (auto &ip : wifi::global_wifi_component->get_ip_addresses()) {
|
||||||
|
if (!ip.is_set() || ip.is_ip6() != v6)
|
||||||
|
continue;
|
||||||
|
ip.str_to(buf);
|
||||||
|
if (v6 && strncmp(buf, "fe80", 4) == 0)
|
||||||
|
continue;
|
||||||
|
if (!ips.empty())
|
||||||
|
ips += "\n";
|
||||||
|
ips += buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lv_label_set_text(id(status_ips), ips.c_str());
|
||||||
|
if (ips.empty())
|
||||||
|
lv_obj_add_flag(id(status_ips), LV_OBJ_FLAG_HIDDEN);
|
||||||
|
else
|
||||||
|
lv_obj_remove_flag(id(status_ips), LV_OBJ_FLAG_HIDDEN);
|
||||||
|
|
||||||
|
const bool api_ok = api::global_api_server->is_connected();
|
||||||
|
set(id(status_ha), api_ok ? "Home Assistant: connected" : "Home Assistant: waiting...",
|
||||||
|
api_ok ? OK : WAIT);
|
||||||
|
|
||||||
|
const uint32_t up = millis() / 1000;
|
||||||
|
lv_label_set_text(id(status_footer),
|
||||||
|
str_sprintf("ESPHome %s · up %ud %02u:%02u:%02u", ESPHOME_VERSION, up / 86400,
|
||||||
|
(up / 3600) % 24, (up / 60) % 60, up % 60).c_str());
|
||||||
|
|
||||||
|
interval:
|
||||||
|
- interval: 1s
|
||||||
|
then:
|
||||||
|
- lvgl.label.update:
|
||||||
|
id: clock_label
|
||||||
|
text: !lambda |-
|
||||||
|
auto now = id(ha_time).now();
|
||||||
|
if (!now.is_valid())
|
||||||
|
return std::string("--:--");
|
||||||
|
return now.strftime("%H:%M");
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
lvgl.page.is_showing: status_page
|
||||||
|
then:
|
||||||
|
- script.execute: update_status
|
||||||
|
|
||||||
|
image:
|
||||||
|
- platform: file
|
||||||
|
file: assets/images/made-for-esphome-white-on-black.svg
|
||||||
|
id: esphome_logo
|
||||||
|
resize: 320x95
|
||||||
|
type: RGB565
|
||||||
|
transparency: alpha_channel
|
||||||
|
|
||||||
|
font:
|
||||||
|
- file: "gfonts://Roboto@500"
|
||||||
|
id: font_clock
|
||||||
|
size: 150
|
||||||
|
glyphs: "0123456789:-"
|
||||||
|
- file: "gfonts://Roboto"
|
||||||
|
id: font_title
|
||||||
|
size: 32
|
||||||
|
- file: "gfonts://Roboto"
|
||||||
|
id: font_status
|
||||||
|
size: 20
|
||||||
|
glyphs: "·"
|
||||||
|
glyphsets: [GF_Latin_Kernel]
|
||||||
|
|
||||||
|
lvgl:
|
||||||
|
log_level: WARN
|
||||||
|
color_depth: 16
|
||||||
|
bg_color: 0x000000
|
||||||
|
text_color: 0xFFFFFF
|
||||||
|
theme:
|
||||||
|
buttonmatrix:
|
||||||
|
bg_opa: TRANSP
|
||||||
|
border_width: 0
|
||||||
|
items:
|
||||||
|
bg_color: 0x2B2F36
|
||||||
|
text_color: 0xFFFFFF
|
||||||
|
radius: 12
|
||||||
|
checked:
|
||||||
|
bg_color: 0xE08A00
|
||||||
|
top_layer:
|
||||||
|
widgets:
|
||||||
|
# same navigation bar as on mcu-lvgl-trainer
|
||||||
|
- buttonmatrix:
|
||||||
|
id: nav_bar
|
||||||
|
align: bottom_mid
|
||||||
|
width: 100%
|
||||||
|
height: 60
|
||||||
|
pad_all: 4
|
||||||
|
pad_column: 6
|
||||||
|
items:
|
||||||
|
text_font: montserrat_28
|
||||||
|
rows:
|
||||||
|
- buttons:
|
||||||
|
- id: page_prev
|
||||||
|
text: ""
|
||||||
|
on_press:
|
||||||
|
then:
|
||||||
|
lvgl.page.previous:
|
||||||
|
- id: page_home
|
||||||
|
text: ""
|
||||||
|
on_press:
|
||||||
|
then:
|
||||||
|
lvgl.page.show: main_page
|
||||||
|
- id: page_next
|
||||||
|
text: ""
|
||||||
|
on_press:
|
||||||
|
then:
|
||||||
|
lvgl.page.next:
|
||||||
|
pages:
|
||||||
|
# 1: clock
|
||||||
|
- id: main_page
|
||||||
|
widgets:
|
||||||
|
- label:
|
||||||
|
id: clock_label
|
||||||
|
align: CENTER
|
||||||
|
y: -30
|
||||||
|
text_font: font_clock
|
||||||
|
text: "--:--"
|
||||||
|
|
||||||
|
# 2: status (shown until Home Assistant connects)
|
||||||
|
- id: status_page
|
||||||
|
on_load:
|
||||||
|
- script.execute: update_status
|
||||||
|
widgets:
|
||||||
|
- image:
|
||||||
|
src: esphome_logo
|
||||||
|
align: TOP_MID
|
||||||
|
y: 16
|
||||||
|
- label:
|
||||||
|
align: TOP_MID
|
||||||
|
y: 120
|
||||||
|
text_font: font_title
|
||||||
|
text: "${name}"
|
||||||
|
- obj:
|
||||||
|
id: status_lines
|
||||||
|
x: 24
|
||||||
|
y: 170
|
||||||
|
width: 440
|
||||||
|
height: SIZE_CONTENT
|
||||||
|
bg_opa: TRANSP
|
||||||
|
border_width: 0
|
||||||
|
pad_all: 0
|
||||||
|
scrollbar_mode: "OFF"
|
||||||
|
layout:
|
||||||
|
type: flex
|
||||||
|
flex_flow: column
|
||||||
|
pad_row: 6
|
||||||
|
widgets:
|
||||||
|
- label:
|
||||||
|
id: status_wifi
|
||||||
|
text_font: font_status
|
||||||
|
text: ""
|
||||||
|
- label:
|
||||||
|
id: status_ips
|
||||||
|
text_font: font_status
|
||||||
|
text_color: 0x8C8C8C
|
||||||
|
pad_left: 20
|
||||||
|
text: ""
|
||||||
|
- label:
|
||||||
|
id: status_ha
|
||||||
|
text_font: font_status
|
||||||
|
text: ""
|
||||||
|
- label:
|
||||||
|
id: status_footer
|
||||||
|
text_font: font_status
|
||||||
|
text_color: 0x8C8C8C
|
||||||
|
text: ""
|
||||||
@@ -1,4 +1,17 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Guition JC3248W535
|
||||||
|
# Pinout:
|
||||||
|
# GPIO1 -> main_backlight (power_supply)
|
||||||
|
# GPIO4 -> touchscreen_bus (i2c sda)
|
||||||
|
# GPIO8 -> touchscreen_bus (i2c scl)
|
||||||
|
# GPIO21 -> display_qspi (spi data_pins)
|
||||||
|
# GPIO39 -> display_qspi (spi data_pins)
|
||||||
|
# GPIO40 -> display_qspi (spi data_pins)
|
||||||
|
# GPIO45 -> main_display (display mipi_spi cs_pin)
|
||||||
|
# GPIO47 -> display_qspi (spi clk_pin)
|
||||||
|
# GPIO48 -> display_qspi (spi data_pins)
|
||||||
|
# I2C:
|
||||||
|
# 0x3B main_touch (touchscreen axs15231)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: lvgl-eworkbench
|
device: lvgl-eworkbench
|
||||||
name: Electronics Workbench Display
|
name: Electronics Workbench Display
|
||||||
@@ -16,6 +29,8 @@ esp32:
|
|||||||
flash_size: 16MB
|
flash_size: 16MB
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: generic # same board as lvgl-trainer (not read from the device)
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|||||||
+628
-150
@@ -1,9 +1,31 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Guition JC3248W535
|
||||||
|
# Pinout:
|
||||||
|
# GPIO1 -> gpio_backlight_pwm (output ledc)
|
||||||
|
# GPIO4 -> touchscreen_bus (i2c sda)
|
||||||
|
# GPIO8 -> touchscreen_bus (i2c scl)
|
||||||
|
# GPIO21 -> display_qspi (spi data_pins)
|
||||||
|
# GPIO39 -> display_qspi (spi data_pins)
|
||||||
|
# GPIO40 -> display_qspi (spi data_pins)
|
||||||
|
# GPIO43 -> ext_uart (uart tx_pin)
|
||||||
|
# GPIO44 -> ext_uart (uart rx_pin)
|
||||||
|
# GPIO45 -> main_display (display mipi_spi cs_pin)
|
||||||
|
# GPIO47 -> display_qspi (spi clk_pin)
|
||||||
|
# GPIO48 -> display_qspi (spi data_pins)
|
||||||
|
# I2C:
|
||||||
|
# 0x3B main_touch (touchscreen axs15231)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: lvgl-trainer
|
device: lvgl-trainer
|
||||||
name: Trainer Display
|
name: Trainer Display
|
||||||
area: Basement
|
area: Basement
|
||||||
comment: "${area} | Pain Cave"
|
comment: "${area} | Pain Cave"
|
||||||
|
light_basement: light.mcu_basement_2_light
|
||||||
|
light_workbench: light.mcu_basement_2_workbench_light
|
||||||
|
light_exercise: light.exercise_room
|
||||||
|
fan: light.mcu_dimmer_exercise_room_fan
|
||||||
|
|
||||||
|
# Pages (480x320, navigation bar at the bottom):
|
||||||
|
# clock, lights, training, fan, stopwatch, status
|
||||||
|
|
||||||
esphome:
|
esphome:
|
||||||
name: mcu-${device}
|
name: mcu-${device}
|
||||||
@@ -15,11 +37,13 @@ esp32:
|
|||||||
variant: esp32s3
|
variant: esp32s3
|
||||||
flash_size: 16MB
|
flash_size: 16MB
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: generic
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
|
||||||
i2c:
|
i2c:
|
||||||
- id: touchscreen_bus
|
- id: touchscreen_bus
|
||||||
@@ -36,71 +60,17 @@ spi:
|
|||||||
clk_pin: 47
|
clk_pin: 47
|
||||||
data_pins: [21, 48, 40, 39]
|
data_pins: [21, 48, 40, 39]
|
||||||
|
|
||||||
color:
|
|
||||||
- id: my_red
|
|
||||||
red: 100%
|
|
||||||
green: 0%
|
|
||||||
blue: 0%
|
|
||||||
- id: my_orange
|
|
||||||
red: 100%
|
|
||||||
green: 50%
|
|
||||||
blue: 0%
|
|
||||||
- id: my_yellow
|
|
||||||
red: 100%
|
|
||||||
green: 100%
|
|
||||||
blue: 0%
|
|
||||||
- id: my_green
|
|
||||||
red: 0%
|
|
||||||
green: 100%
|
|
||||||
blue: 0%
|
|
||||||
- id: my_blue
|
|
||||||
red: 0%
|
|
||||||
green: 0%
|
|
||||||
blue: 100%
|
|
||||||
- id: my_teal
|
|
||||||
red: 0%
|
|
||||||
green: 100%
|
|
||||||
blue: 100%
|
|
||||||
- id: my_gray
|
|
||||||
red: 70%
|
|
||||||
green: 70%
|
|
||||||
blue: 70%
|
|
||||||
- id: my_white
|
|
||||||
red: 100%
|
|
||||||
green: 100%
|
|
||||||
blue: 100%
|
|
||||||
|
|
||||||
font:
|
|
||||||
- file: "gfonts://Roboto"
|
|
||||||
id: Roboto_48
|
|
||||||
size: 48
|
|
||||||
- file: "gfonts://Roboto"
|
|
||||||
id: Roboto_36
|
|
||||||
size: 36
|
|
||||||
- file: "gfonts://Roboto"
|
|
||||||
id: Roboto_24
|
|
||||||
size: 24
|
|
||||||
- file: "gfonts://Roboto"
|
|
||||||
id: Roboto_12
|
|
||||||
size: 12
|
|
||||||
- file: "gfonts://Roboto"
|
|
||||||
id: font_std
|
|
||||||
size: 40
|
|
||||||
glyphs: "!\"%()+=,-_.:°0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz/\\[]|&@#'"
|
|
||||||
- file: "gfonts://Roboto@700"
|
|
||||||
id: font_title
|
|
||||||
size: 40
|
|
||||||
glyphs: "!\"%()+=,-_.:°0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz/\\[]|&@#'"
|
|
||||||
|
|
||||||
globals:
|
globals:
|
||||||
- id: bgcolor
|
# stopwatch: accumulated time of finished runs + start of the current run
|
||||||
type: Color
|
- id: sw_running
|
||||||
initial_value: "Color::random_color()"
|
type: bool
|
||||||
|
initial_value: 'false'
|
||||||
# power_supply:
|
- id: sw_start
|
||||||
# id: main_backlight
|
type: uint32_t
|
||||||
# pin: 1
|
initial_value: '0'
|
||||||
# enable_on_boot: true
|
- id: sw_accum
|
||||||
|
type: uint32_t
|
||||||
|
initial_value: '0'
|
||||||
|
|
||||||
output:
|
output:
|
||||||
- platform: ledc
|
- platform: ledc
|
||||||
@@ -119,7 +89,6 @@ display:
|
|||||||
- platform: mipi_spi
|
- platform: mipi_spi
|
||||||
model: AXS15231
|
model: AXS15231
|
||||||
data_rate: 40MHz #20mhz is default
|
data_rate: 40MHz #20mhz is default
|
||||||
#spi_mode: MODE2
|
|
||||||
id: main_display
|
id: main_display
|
||||||
spi_id: display_qspi
|
spi_id: display_qspi
|
||||||
dimensions:
|
dimensions:
|
||||||
@@ -127,11 +96,6 @@ display:
|
|||||||
width: 320
|
width: 320
|
||||||
cs_pin: 45
|
cs_pin: 45
|
||||||
auto_clear_enabled: false
|
auto_clear_enabled: false
|
||||||
# show_test_card: true
|
|
||||||
# lambda: |-
|
|
||||||
# it.fill(id(bgcolor));
|
|
||||||
# it.print(it.get_width()/2, it.get_height()/2-20, id(font_title), TextAlign::CENTER, "ESPHome");
|
|
||||||
# it.print(it.get_width()/2, it.get_height()/2+20, id(font_std), TextAlign::CENTER, "@UTBDK");
|
|
||||||
|
|
||||||
touchscreen:
|
touchscreen:
|
||||||
- platform: axs15231
|
- platform: axs15231
|
||||||
@@ -142,27 +106,8 @@ touchscreen:
|
|||||||
# interrupt_pin:
|
# interrupt_pin:
|
||||||
# number: 3
|
# number: 3
|
||||||
# ignore_strapping_warning: true
|
# ignore_strapping_warning: true
|
||||||
calibration:
|
# no calibration/transform: the driver defaults to the native 320x480 panel and
|
||||||
x_min: 0
|
# LVGL applies its own rotation to touch points
|
||||||
x_max: 479
|
|
||||||
y_min: 0
|
|
||||||
y_max: 319
|
|
||||||
transform:
|
|
||||||
swap_xy: true
|
|
||||||
mirror_x: false
|
|
||||||
mirror_y: true
|
|
||||||
# on_touch:
|
|
||||||
# - lambda: |-
|
|
||||||
# Color newColor;
|
|
||||||
# do { newColor = Color::random_color(); } while (newColor == id(bgcolor));
|
|
||||||
# id(bgcolor) = newColor;
|
|
||||||
|
|
||||||
# ESP_LOGI("cal", "x=%d, y=%d, x_raw=%d, y_raw=%0d",
|
|
||||||
# touch.x,
|
|
||||||
# touch.y,
|
|
||||||
# touch.x_raw,
|
|
||||||
# touch.y_raw
|
|
||||||
# );
|
|
||||||
on_release:
|
on_release:
|
||||||
- if:
|
- if:
|
||||||
condition: lvgl.is_paused
|
condition: lvgl.is_paused
|
||||||
@@ -183,107 +128,640 @@ uart:
|
|||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: homeassistant
|
- platform: homeassistant
|
||||||
id: exercise_room_light
|
id: basement_light
|
||||||
entity_id: light.exercise_room
|
entity_id: ${light_basement}
|
||||||
trigger_on_initial_state: true
|
trigger_on_initial_state: true
|
||||||
on_state:
|
on_state:
|
||||||
then:
|
- lvgl.widget.update:
|
||||||
lvgl.widget.update:
|
id: basement_light_btn
|
||||||
id: exercise_room_light_btn
|
|
||||||
state:
|
state:
|
||||||
checked: !lambda return x;
|
checked: !lambda return x;
|
||||||
- platform: homeassistant
|
- platform: homeassistant
|
||||||
id: exercise_room_fan
|
id: workbench_light
|
||||||
entity_id: light.mcu_dimmer_exercise_room_fan
|
entity_id: ${light_workbench}
|
||||||
trigger_on_initial_state: true
|
trigger_on_initial_state: true
|
||||||
on_state:
|
on_state:
|
||||||
then:
|
- lvgl.widget.update:
|
||||||
lvgl.widget.update:
|
id: workbench_light_btn
|
||||||
id: exercise_room_fan_btn
|
|
||||||
state:
|
state:
|
||||||
checked: !lambda return x;
|
checked: !lambda return x;
|
||||||
|
- platform: homeassistant
|
||||||
|
id: exercise_light
|
||||||
|
entity_id: ${light_exercise}
|
||||||
|
trigger_on_initial_state: true
|
||||||
|
on_state:
|
||||||
|
- lvgl.widget.update:
|
||||||
|
id: exercise_light_btn
|
||||||
|
state:
|
||||||
|
checked: !lambda return x;
|
||||||
|
# brightness and color temperature only make sense while the light is on
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
lambda: return x;
|
||||||
|
then:
|
||||||
|
- lvgl.widget.show: exercise_controls
|
||||||
|
else:
|
||||||
|
- lvgl.widget.hide: exercise_controls
|
||||||
|
- platform: homeassistant
|
||||||
|
id: fan_on
|
||||||
|
entity_id: ${fan}
|
||||||
|
trigger_on_initial_state: true
|
||||||
|
on_state:
|
||||||
|
- script.execute: update_fan_buttons
|
||||||
|
|
||||||
|
sensor:
|
||||||
|
- platform: homeassistant
|
||||||
|
id: fan_brightness
|
||||||
|
entity_id: ${fan}
|
||||||
|
attribute: brightness
|
||||||
|
on_value:
|
||||||
|
- script.execute: update_fan_buttons
|
||||||
|
|
||||||
|
text_sensor:
|
||||||
|
# light attributes read as text: they are 'None' while the light is off
|
||||||
|
- platform: homeassistant
|
||||||
|
id: exercise_brightness
|
||||||
|
entity_id: ${light_exercise}
|
||||||
|
attribute: brightness
|
||||||
|
on_value:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
lambda: return parse_number<float>(x).has_value();
|
||||||
|
then:
|
||||||
|
- lvgl.slider.update:
|
||||||
|
id: exercise_brightness_slider
|
||||||
|
value: !lambda return roundf(*parse_number<float>(x) * 100.0f / 255.0f);
|
||||||
|
- platform: homeassistant
|
||||||
|
id: exercise_color_temp
|
||||||
|
entity_id: ${light_exercise}
|
||||||
|
attribute: color_temp_kelvin
|
||||||
|
on_value:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
lambda: return parse_number<float>(x).has_value();
|
||||||
|
then:
|
||||||
|
- lvgl.slider.update:
|
||||||
|
id: exercise_color_temp_slider
|
||||||
|
value: !lambda return *parse_number<float>(x);
|
||||||
|
# a running automation (e.g. its delay) has current > 0
|
||||||
|
- platform: homeassistant
|
||||||
|
id: training_start_running
|
||||||
|
entity_id: automation.zwift_enable_fan
|
||||||
|
attribute: current
|
||||||
|
on_value:
|
||||||
|
- script.execute: update_training_status
|
||||||
|
- platform: homeassistant
|
||||||
|
id: training_stop_running
|
||||||
|
entity_id: automation.zwift_disable_fan
|
||||||
|
attribute: current
|
||||||
|
on_value:
|
||||||
|
- script.execute: update_training_status
|
||||||
|
|
||||||
|
script:
|
||||||
|
- id: update_fan_buttons
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
// fan level rounded to the 10 % steps of the buttons, 0 = off
|
||||||
|
int pct = 0;
|
||||||
|
if (id(fan_on).state && !std::isnan(id(fan_brightness).state))
|
||||||
|
pct = (int) roundf(id(fan_brightness).state * 10.0f / 255.0f) * 10;
|
||||||
|
const int levels[] = {0, 50, 60, 70, 80, 90, 100};
|
||||||
|
lv_obj_t *matrix = id(fan_matrix)->obj;
|
||||||
|
for (int i = 0; i < 7; i++) {
|
||||||
|
if (levels[i] == pct)
|
||||||
|
lv_buttonmatrix_set_button_ctrl(matrix, i, LV_BUTTONMATRIX_CTRL_CHECKED);
|
||||||
|
else
|
||||||
|
lv_buttonmatrix_clear_button_ctrl(matrix, i, LV_BUTTONMATRIX_CTRL_CHECKED);
|
||||||
|
}
|
||||||
|
- lvgl.label.update:
|
||||||
|
id: fan_status_label
|
||||||
|
text: !lambda |-
|
||||||
|
if (!id(fan_on).state)
|
||||||
|
return std::string("Ventilátor vypnutý");
|
||||||
|
if (std::isnan(id(fan_brightness).state))
|
||||||
|
return std::string("Ventilátor zapnutý");
|
||||||
|
return str_sprintf("Ventilátor %.0f %%", id(fan_brightness).state * 100.0f / 255.0f);
|
||||||
|
|
||||||
|
- id: update_training_status
|
||||||
|
then:
|
||||||
|
- lvgl.label.update:
|
||||||
|
id: training_status_label
|
||||||
|
text: !lambda |-
|
||||||
|
if (id(training_start_running).state != "0" && !id(training_start_running).state.empty())
|
||||||
|
return std::string("Tréning sa spúšťa, ventilátor sa zapne o 10 min");
|
||||||
|
if (id(training_stop_running).state != "0" && !id(training_stop_running).state.empty())
|
||||||
|
return std::string("Tréning sa ukončuje, ventilátor sa vypne o 2 min");
|
||||||
|
return std::string("");
|
||||||
|
|
||||||
|
- id: update_stopwatch
|
||||||
|
then:
|
||||||
|
- lvgl.label.update:
|
||||||
|
id: stopwatch_label
|
||||||
|
text: !lambda |-
|
||||||
|
const unsigned ms = id(sw_accum) + (id(sw_running) ? millis() - id(sw_start) : 0);
|
||||||
|
const unsigned s = ms / 1000;
|
||||||
|
if (s >= 3600)
|
||||||
|
return str_sprintf("%u:%02u:%02u", s / 3600, (s / 60) % 60, s % 60);
|
||||||
|
return str_sprintf("%02u:%02u.%u", s / 60, s % 60, (ms / 100) % 10);
|
||||||
|
- lvgl.label.update:
|
||||||
|
id: stopwatch_start_label
|
||||||
|
text: !lambda |-
|
||||||
|
return std::string(id(sw_running) ? "Stop" : "Štart");
|
||||||
|
|
||||||
|
- id: update_status
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
// same colors as the other status screens: ok green, waiting orange, details gray
|
||||||
|
static const uint32_t OK = 0x4DD966, WAIT = 0xFFB300;
|
||||||
|
auto set = [](lv_obj_t *label, const std::string &text, uint32_t color) {
|
||||||
|
lv_label_set_text(label, text.c_str());
|
||||||
|
lv_obj_set_style_text_color(label, lv_color_hex(color), LV_PART_MAIN);
|
||||||
|
};
|
||||||
|
|
||||||
|
const bool wifi_ok = wifi::global_wifi_component->is_connected();
|
||||||
|
set(id(status_wifi),
|
||||||
|
wifi_ok ? str_sprintf("WiFi: connected (%d dBm)", wifi::global_wifi_component->wifi_rssi())
|
||||||
|
: std::string("WiFi: connecting..."),
|
||||||
|
wifi_ok ? OK : WAIT);
|
||||||
|
|
||||||
|
// IPv6 first (skip link-local), then IPv4
|
||||||
|
std::string ips;
|
||||||
|
if (wifi_ok) {
|
||||||
|
char buf[network::IP_ADDRESS_BUFFER_SIZE];
|
||||||
|
for (bool v6 : {true, false}) {
|
||||||
|
for (auto &ip : wifi::global_wifi_component->get_ip_addresses()) {
|
||||||
|
if (!ip.is_set() || ip.is_ip6() != v6)
|
||||||
|
continue;
|
||||||
|
ip.str_to(buf);
|
||||||
|
if (v6 && strncmp(buf, "fe80", 4) == 0)
|
||||||
|
continue;
|
||||||
|
if (!ips.empty())
|
||||||
|
ips += "\n";
|
||||||
|
ips += buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lv_label_set_text(id(status_ips), ips.c_str());
|
||||||
|
if (ips.empty())
|
||||||
|
lv_obj_add_flag(id(status_ips), LV_OBJ_FLAG_HIDDEN);
|
||||||
|
else
|
||||||
|
lv_obj_remove_flag(id(status_ips), LV_OBJ_FLAG_HIDDEN);
|
||||||
|
|
||||||
|
const bool api_ok = api::global_api_server->is_connected();
|
||||||
|
set(id(status_ha), api_ok ? "Home Assistant: connected" : "Home Assistant: waiting...",
|
||||||
|
api_ok ? OK : WAIT);
|
||||||
|
|
||||||
|
const uint32_t up = millis() / 1000;
|
||||||
|
lv_label_set_text(id(status_footer),
|
||||||
|
str_sprintf("ESPHome %s · up %ud %02u:%02u:%02u", ESPHOME_VERSION, up / 86400,
|
||||||
|
(up / 3600) % 24, (up / 60) % 60, up % 60).c_str());
|
||||||
|
interval:
|
||||||
|
- interval: 1s
|
||||||
|
then:
|
||||||
|
- lvgl.label.update:
|
||||||
|
id: clock_label
|
||||||
|
text: !lambda |-
|
||||||
|
auto now = id(ha_time).now();
|
||||||
|
if (!now.is_valid())
|
||||||
|
return std::string("--:--:--");
|
||||||
|
return now.strftime("%H:%M:%S");
|
||||||
|
- interval: 100ms
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
and:
|
||||||
|
- lambda: return id(sw_running);
|
||||||
|
- lvgl.page.is_showing: stopwatch_page
|
||||||
|
then:
|
||||||
|
- script.execute: update_stopwatch
|
||||||
|
- interval: 2s
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
lvgl.page.is_showing: status_page
|
||||||
|
then:
|
||||||
|
- script.execute: update_status
|
||||||
|
|
||||||
|
image:
|
||||||
|
- platform: file
|
||||||
|
file: assets/images/made-for-esphome-white-on-black.svg
|
||||||
|
id: esphome_logo
|
||||||
|
resize: 280x83
|
||||||
|
type: RGB565
|
||||||
|
transparency: alpha_channel
|
||||||
|
|
||||||
|
font:
|
||||||
|
- file: "gfonts://Roboto@500"
|
||||||
|
id: font_digits
|
||||||
|
size: 110
|
||||||
|
glyphs: "0123456789:.-"
|
||||||
|
- file: "gfonts://Roboto"
|
||||||
|
id: font_ui
|
||||||
|
size: 24
|
||||||
|
glyphs: &sk_glyphs "ÁÄČĎÉÍĹĽŇÓÔŔŠŤÚÝŽáäčďéíĺľňóôŕšťúýž°·"
|
||||||
|
glyphsets: [GF_Latin_Kernel]
|
||||||
|
- file: "gfonts://Roboto@500"
|
||||||
|
id: font_button
|
||||||
|
size: 34
|
||||||
|
glyphs: *sk_glyphs
|
||||||
|
glyphsets: [GF_Latin_Kernel]
|
||||||
|
- file: "gfonts://Roboto"
|
||||||
|
id: font_small
|
||||||
|
size: 18
|
||||||
|
glyphs: *sk_glyphs
|
||||||
|
glyphsets: [GF_Latin_Kernel]
|
||||||
|
|
||||||
lvgl:
|
lvgl:
|
||||||
rotation: 90
|
rotation: 90
|
||||||
buffer_size: 100%
|
buffer_size: 100%
|
||||||
log_level: WARN
|
log_level: WARN
|
||||||
color_depth: 16
|
color_depth: 16
|
||||||
default_font: montserrat_18
|
default_font: font_ui
|
||||||
# on_idle:
|
bg_color: 0x000000
|
||||||
# - timeout: !lambda "return (id(display_timeout).state * 1000);"
|
text_color: 0xFFFFFF
|
||||||
# then:
|
theme:
|
||||||
# - logger.log: "LVGL is idle"
|
button:
|
||||||
# - light.turn_off:
|
bg_color: 0x2B2F36
|
||||||
# id: display_backlight
|
radius: 12
|
||||||
# transition_length: 2500ms
|
checked:
|
||||||
# - lvgl.pause:
|
bg_color: 0xE08A00
|
||||||
|
buttonmatrix:
|
||||||
|
bg_opa: TRANSP
|
||||||
|
border_width: 0
|
||||||
|
items:
|
||||||
|
bg_color: 0x2B2F36
|
||||||
|
text_color: 0xFFFFFF
|
||||||
|
radius: 12
|
||||||
|
checked:
|
||||||
|
bg_color: 0xE08A00
|
||||||
|
slider:
|
||||||
|
bg_color: 0x2B2F36
|
||||||
|
indicator:
|
||||||
|
bg_color: 0xE08A00
|
||||||
|
knob:
|
||||||
|
bg_color: 0xFFFFFF
|
||||||
top_layer:
|
top_layer:
|
||||||
widgets:
|
widgets:
|
||||||
- buttonmatrix:
|
- buttonmatrix:
|
||||||
|
id: nav_bar
|
||||||
align: bottom_mid
|
align: bottom_mid
|
||||||
# styles: header_footer
|
width: 100%
|
||||||
pad_all: 0
|
height: 56
|
||||||
outline_width: 0
|
pad_all: 4
|
||||||
id: top_layer
|
pad_column: 6
|
||||||
# items:
|
items:
|
||||||
# styles: header_footer
|
text_font: montserrat_28
|
||||||
rows:
|
rows:
|
||||||
- buttons:
|
- buttons:
|
||||||
- id: page_prev
|
- id: page_prev
|
||||||
text: "\uF053"
|
text: ""
|
||||||
on_press:
|
on_press:
|
||||||
then:
|
then:
|
||||||
lvgl.page.previous:
|
lvgl.page.previous:
|
||||||
- id: page_home
|
- id: page_home
|
||||||
text: "\uF015"
|
text: ""
|
||||||
on_press:
|
on_press:
|
||||||
then:
|
then:
|
||||||
lvgl.page.show: main_page
|
lvgl.page.show: clock_page
|
||||||
- id: page_next
|
- id: page_next
|
||||||
text: "\uF054"
|
text: ""
|
||||||
on_press:
|
on_press:
|
||||||
then:
|
then:
|
||||||
lvgl.page.next:
|
lvgl.page.next:
|
||||||
pages:
|
pages:
|
||||||
- id: main_page
|
# 1: clock (default after boot)
|
||||||
|
- id: clock_page
|
||||||
widgets:
|
widgets:
|
||||||
- label:
|
- label:
|
||||||
text: "ESPHome LVGL Display"
|
id: clock_label
|
||||||
align: CENTER
|
align: CENTER
|
||||||
text_align: CENTER
|
y: -28
|
||||||
text_color: 0xFFFFFF
|
text_font: font_digits
|
||||||
- id: excercise_page
|
text: "--:--:--"
|
||||||
|
|
||||||
|
# 2: basement lights
|
||||||
|
- id: lights_page
|
||||||
|
pad_all: 10
|
||||||
widgets:
|
widgets:
|
||||||
- label:
|
|
||||||
align: CENTER
|
|
||||||
text: 'Hello World!'
|
|
||||||
- button:
|
- button:
|
||||||
id: exercise_room_light_btn
|
id: basement_light_btn
|
||||||
align: TOP_LEFT
|
align: TOP_LEFT
|
||||||
width: 100
|
width: 148
|
||||||
height: 70
|
height: 80
|
||||||
checkable: true
|
checkable: true
|
||||||
widgets:
|
widgets:
|
||||||
- label:
|
- label:
|
||||||
align: CENTER
|
align: CENTER
|
||||||
text: 'Light'
|
text: "Pivnica"
|
||||||
on_click:
|
on_click:
|
||||||
- homeassistant.action:
|
- homeassistant.action:
|
||||||
action: light.toggle
|
action: light.toggle
|
||||||
data:
|
data:
|
||||||
entity_id: light.exercise_room
|
entity_id: ${light_basement}
|
||||||
- button:
|
- button:
|
||||||
id: exercise_room_fan_btn
|
id: workbench_light_btn
|
||||||
align: TOP_RIGHT
|
align: TOP_MID
|
||||||
width: 100
|
width: 148
|
||||||
height: 70
|
height: 80
|
||||||
checkable: true
|
checkable: true
|
||||||
widgets:
|
widgets:
|
||||||
- label:
|
- label:
|
||||||
align: CENTER
|
align: CENTER
|
||||||
text: 'Fan'
|
text: "Pracovný stôl"
|
||||||
on_click:
|
on_click:
|
||||||
- homeassistant.action:
|
- homeassistant.action:
|
||||||
action: light.toggle
|
action: light.toggle
|
||||||
data:
|
data:
|
||||||
entity_id: light.mcu_dimmer_exercise_room_fan
|
entity_id: ${light_workbench}
|
||||||
|
- button:
|
||||||
|
id: exercise_light_btn
|
||||||
|
align: TOP_RIGHT
|
||||||
|
width: 148
|
||||||
|
height: 80
|
||||||
|
checkable: true
|
||||||
|
widgets:
|
||||||
|
- label:
|
||||||
|
align: CENTER
|
||||||
|
text: "Posilka"
|
||||||
|
on_click:
|
||||||
|
- homeassistant.action:
|
||||||
|
action: light.toggle
|
||||||
|
data:
|
||||||
|
entity_id: ${light_exercise}
|
||||||
|
- obj:
|
||||||
|
id: exercise_controls
|
||||||
|
hidden: true
|
||||||
|
y: 110
|
||||||
|
width: 460
|
||||||
|
height: 120
|
||||||
|
pad_all: 0
|
||||||
|
bg_opa: TRANSP
|
||||||
|
border_width: 0
|
||||||
|
scrollbar_mode: "OFF"
|
||||||
|
widgets:
|
||||||
|
- label:
|
||||||
|
x: 4
|
||||||
|
y: 0
|
||||||
|
text_font: font_small
|
||||||
|
text: "Posilka jas"
|
||||||
|
- slider:
|
||||||
|
id: exercise_brightness_slider
|
||||||
|
x: 14
|
||||||
|
y: 32
|
||||||
|
width: 430
|
||||||
|
height: 16
|
||||||
|
min_value: 1
|
||||||
|
max_value: 100
|
||||||
|
value: 100
|
||||||
|
on_release:
|
||||||
|
- homeassistant.action:
|
||||||
|
action: light.turn_on
|
||||||
|
data:
|
||||||
|
entity_id: ${light_exercise}
|
||||||
|
brightness_pct: !lambda return (int) x;
|
||||||
|
- label:
|
||||||
|
x: 4
|
||||||
|
y: 62
|
||||||
|
text_font: font_small
|
||||||
|
text: "Posilka teplota (2700 – 6500 K)"
|
||||||
|
- slider:
|
||||||
|
id: exercise_color_temp_slider
|
||||||
|
x: 14
|
||||||
|
y: 94
|
||||||
|
width: 430
|
||||||
|
height: 16
|
||||||
|
min_value: 2700
|
||||||
|
max_value: 6500
|
||||||
|
value: 2700
|
||||||
|
on_release:
|
||||||
|
- homeassistant.action:
|
||||||
|
action: light.turn_on
|
||||||
|
data:
|
||||||
|
entity_id: ${light_exercise}
|
||||||
|
color_temp_kelvin: !lambda return (int) x;
|
||||||
|
|
||||||
|
# 3: training start / stop
|
||||||
|
- id: training_page
|
||||||
|
pad_all: 10
|
||||||
|
widgets:
|
||||||
|
- button:
|
||||||
|
align: TOP_LEFT
|
||||||
|
y: 10
|
||||||
|
width: 222
|
||||||
|
height: 150
|
||||||
|
bg_color: 0x1E7D32
|
||||||
|
widgets:
|
||||||
|
- label:
|
||||||
|
align: CENTER
|
||||||
|
text_font: font_button
|
||||||
|
text: "Štart"
|
||||||
|
on_click:
|
||||||
|
- homeassistant.action:
|
||||||
|
action: automation.trigger
|
||||||
|
data:
|
||||||
|
entity_id: automation.zwift_enable_fan
|
||||||
|
- button:
|
||||||
|
align: TOP_RIGHT
|
||||||
|
y: 10
|
||||||
|
width: 222
|
||||||
|
height: 150
|
||||||
|
bg_color: 0xB71C1C
|
||||||
|
widgets:
|
||||||
|
- label:
|
||||||
|
align: CENTER
|
||||||
|
text_font: font_button
|
||||||
|
text: "Stop"
|
||||||
|
on_click:
|
||||||
|
- homeassistant.action:
|
||||||
|
action: automation.trigger
|
||||||
|
data:
|
||||||
|
entity_id: automation.zwift_disable_fan
|
||||||
|
- label:
|
||||||
|
id: training_status_label
|
||||||
|
align: TOP_MID
|
||||||
|
y: 185
|
||||||
|
width: 440
|
||||||
|
text_align: CENTER
|
||||||
|
text_font: font_small
|
||||||
|
text: ""
|
||||||
|
|
||||||
|
# 4: fan
|
||||||
|
- id: fan_page
|
||||||
|
pad_all: 10
|
||||||
|
widgets:
|
||||||
|
- buttonmatrix:
|
||||||
|
id: fan_matrix
|
||||||
|
align: TOP_MID
|
||||||
|
width: 460
|
||||||
|
height: 180
|
||||||
|
pad_row: 8
|
||||||
|
pad_column: 8
|
||||||
|
one_checked: true
|
||||||
|
items:
|
||||||
|
text_font: font_button
|
||||||
|
rows:
|
||||||
|
- buttons:
|
||||||
|
- text: "Vyp"
|
||||||
|
control:
|
||||||
|
checkable: true
|
||||||
|
on_press:
|
||||||
|
- homeassistant.action:
|
||||||
|
action: light.turn_off
|
||||||
|
data:
|
||||||
|
entity_id: ${fan}
|
||||||
|
- text: "50"
|
||||||
|
control:
|
||||||
|
checkable: true
|
||||||
|
on_press:
|
||||||
|
- homeassistant.action:
|
||||||
|
action: light.turn_on
|
||||||
|
data:
|
||||||
|
entity_id: ${fan}
|
||||||
|
brightness_pct: "50"
|
||||||
|
- text: "60"
|
||||||
|
control:
|
||||||
|
checkable: true
|
||||||
|
on_press:
|
||||||
|
- homeassistant.action:
|
||||||
|
action: light.turn_on
|
||||||
|
data:
|
||||||
|
entity_id: ${fan}
|
||||||
|
brightness_pct: "60"
|
||||||
|
- text: "70"
|
||||||
|
control:
|
||||||
|
checkable: true
|
||||||
|
on_press:
|
||||||
|
- homeassistant.action:
|
||||||
|
action: light.turn_on
|
||||||
|
data:
|
||||||
|
entity_id: ${fan}
|
||||||
|
brightness_pct: "70"
|
||||||
|
- buttons:
|
||||||
|
- text: "80"
|
||||||
|
control:
|
||||||
|
checkable: true
|
||||||
|
on_press:
|
||||||
|
- homeassistant.action:
|
||||||
|
action: light.turn_on
|
||||||
|
data:
|
||||||
|
entity_id: ${fan}
|
||||||
|
brightness_pct: "80"
|
||||||
|
- text: "90"
|
||||||
|
control:
|
||||||
|
checkable: true
|
||||||
|
on_press:
|
||||||
|
- homeassistant.action:
|
||||||
|
action: light.turn_on
|
||||||
|
data:
|
||||||
|
entity_id: ${fan}
|
||||||
|
brightness_pct: "90"
|
||||||
|
- text: "100"
|
||||||
|
control:
|
||||||
|
checkable: true
|
||||||
|
on_press:
|
||||||
|
- homeassistant.action:
|
||||||
|
action: light.turn_on
|
||||||
|
data:
|
||||||
|
entity_id: ${fan}
|
||||||
|
brightness_pct: "100"
|
||||||
|
- label:
|
||||||
|
id: fan_status_label
|
||||||
|
align: TOP_MID
|
||||||
|
y: 200
|
||||||
|
text_font: font_small
|
||||||
|
text: ""
|
||||||
|
|
||||||
|
# 5: stopwatch
|
||||||
|
- id: stopwatch_page
|
||||||
|
pad_all: 10
|
||||||
|
widgets:
|
||||||
|
- label:
|
||||||
|
id: stopwatch_label
|
||||||
|
align: TOP_MID
|
||||||
|
y: 10
|
||||||
|
text_font: font_digits
|
||||||
|
text: "00:00.0"
|
||||||
|
- button:
|
||||||
|
align: TOP_LEFT
|
||||||
|
y: 150
|
||||||
|
width: 222
|
||||||
|
height: 90
|
||||||
|
widgets:
|
||||||
|
- label:
|
||||||
|
id: stopwatch_start_label
|
||||||
|
align: CENTER
|
||||||
|
text_font: font_button
|
||||||
|
text: "Štart"
|
||||||
|
on_click:
|
||||||
|
- lambda: |-
|
||||||
|
if (id(sw_running)) {
|
||||||
|
id(sw_accum) += millis() - id(sw_start);
|
||||||
|
id(sw_running) = false;
|
||||||
|
} else {
|
||||||
|
id(sw_start) = millis();
|
||||||
|
id(sw_running) = true;
|
||||||
|
}
|
||||||
|
- script.execute: update_stopwatch
|
||||||
|
- button:
|
||||||
|
align: TOP_RIGHT
|
||||||
|
y: 150
|
||||||
|
width: 222
|
||||||
|
height: 90
|
||||||
|
widgets:
|
||||||
|
- label:
|
||||||
|
align: CENTER
|
||||||
|
text_font: font_button
|
||||||
|
text: "Reset"
|
||||||
|
on_click:
|
||||||
|
- lambda: |-
|
||||||
|
id(sw_accum) = 0;
|
||||||
|
id(sw_start) = millis();
|
||||||
|
- script.execute: update_stopwatch
|
||||||
|
|
||||||
|
# 6: status
|
||||||
|
- id: status_page
|
||||||
|
on_load:
|
||||||
|
- script.execute: update_status
|
||||||
|
widgets:
|
||||||
|
- image:
|
||||||
|
src: esphome_logo
|
||||||
|
align: TOP_MID
|
||||||
|
y: 8
|
||||||
|
- label:
|
||||||
|
align: TOP_MID
|
||||||
|
y: 96
|
||||||
|
text: "${name}"
|
||||||
|
- obj:
|
||||||
|
id: status_lines
|
||||||
|
x: 20
|
||||||
|
y: 126
|
||||||
|
width: 440
|
||||||
|
height: SIZE_CONTENT
|
||||||
|
bg_opa: TRANSP
|
||||||
|
border_width: 0
|
||||||
|
pad_all: 0
|
||||||
|
scrollbar_mode: "OFF"
|
||||||
|
layout:
|
||||||
|
type: flex
|
||||||
|
flex_flow: column
|
||||||
|
pad_row: 4
|
||||||
|
widgets:
|
||||||
|
- label:
|
||||||
|
id: status_wifi
|
||||||
|
text_font: font_small
|
||||||
|
text: ""
|
||||||
|
- label:
|
||||||
|
id: status_ips
|
||||||
|
text_font: font_small
|
||||||
|
text_color: 0x8C8C8C
|
||||||
|
pad_left: 16
|
||||||
|
text: ""
|
||||||
|
- label:
|
||||||
|
id: status_ha
|
||||||
|
text_font: font_small
|
||||||
|
text: ""
|
||||||
|
- label:
|
||||||
|
id: status_footer
|
||||||
|
text_font: font_small
|
||||||
|
text_color: 0x8C8C8C
|
||||||
|
text: ""
|
||||||
+302
-600
@@ -1,4 +1,88 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Sunton ESP32-8048S043 (CYD 4.3", 800x480, capacitive touch)
|
||||||
|
# Pinout:
|
||||||
|
# # Display
|
||||||
|
# R0 GND
|
||||||
|
# R1 GND
|
||||||
|
# R2 GND
|
||||||
|
# R3 45
|
||||||
|
# R4 48
|
||||||
|
# R5 47
|
||||||
|
# R6 21
|
||||||
|
# R7 14
|
||||||
|
# G0 GND
|
||||||
|
# G1 GND
|
||||||
|
# G2 5
|
||||||
|
# G3 6
|
||||||
|
# G4 7
|
||||||
|
# G5 15
|
||||||
|
# G6 16
|
||||||
|
# G7 4
|
||||||
|
# B0 GND
|
||||||
|
# B1 GND
|
||||||
|
# B2 GND
|
||||||
|
# B3 8
|
||||||
|
# B4 3
|
||||||
|
# B5 46
|
||||||
|
# B6 9
|
||||||
|
# B7 1
|
||||||
|
# DCLK 42
|
||||||
|
# HSYNC 39
|
||||||
|
# VSYNC 41
|
||||||
|
# DE 40
|
||||||
|
# BL 2
|
||||||
|
# # Capacitive Touch
|
||||||
|
# TP_INT
|
||||||
|
# TP_RST 38
|
||||||
|
# TP_SDA 19
|
||||||
|
# TP_SCL 20
|
||||||
|
# # SDCARD
|
||||||
|
# TF_CS 10
|
||||||
|
# SPI_MOSI 11
|
||||||
|
# SPI_CLK 12
|
||||||
|
# SPI_MISO 13
|
||||||
|
# # SPI Conector (HC1.25-4)
|
||||||
|
# SPI_CS 19
|
||||||
|
# SPI_MOSI 11
|
||||||
|
# SPI_CLK 12
|
||||||
|
# SPI_MISO 13
|
||||||
|
# # UART1 (SH1.0-4)
|
||||||
|
# 1 GND
|
||||||
|
# 2 3V3-ESP
|
||||||
|
# 3 17
|
||||||
|
# 4 18
|
||||||
|
# # UART1, USB Connector (Resistive) / I2C (Capacitive) (HC1.25-4)
|
||||||
|
# 1 17
|
||||||
|
# 2 18
|
||||||
|
# 3 19 TP_SDA
|
||||||
|
# 4 20 TP_SCL
|
||||||
|
# Used:
|
||||||
|
# GPIO1 main_display (display mipi_rgb data_pins.blue)
|
||||||
|
# GPIO2 gpio_backlight_pwm (output ledc)
|
||||||
|
# GPIO3 main_display (display mipi_rgb data_pins.blue)
|
||||||
|
# GPIO4 main_display (display mipi_rgb data_pins.green)
|
||||||
|
# GPIO5 main_display (display mipi_rgb data_pins.green)
|
||||||
|
# GPIO6 main_display (display mipi_rgb data_pins.green)
|
||||||
|
# GPIO7 main_display (display mipi_rgb data_pins.green)
|
||||||
|
# GPIO8 main_display (display mipi_rgb data_pins.blue)
|
||||||
|
# GPIO9 main_display (display mipi_rgb data_pins.blue)
|
||||||
|
# GPIO14 main_display (display mipi_rgb data_pins.red)
|
||||||
|
# GPIO15 main_display (display mipi_rgb data_pins.green)
|
||||||
|
# GPIO16 main_display (display mipi_rgb data_pins.green)
|
||||||
|
# GPIO19 i2c_main (i2c sda)
|
||||||
|
# GPIO20 i2c_main (i2c scl)
|
||||||
|
# GPIO21 main_display (display mipi_rgb data_pins.red)
|
||||||
|
# GPIO38 main_touch (touchscreen gt911 reset_pin)
|
||||||
|
# GPIO39 main_display (display mipi_rgb hsync_pin)
|
||||||
|
# GPIO40 main_display (display mipi_rgb de_pin)
|
||||||
|
# GPIO41 main_display (display mipi_rgb vsync_pin)
|
||||||
|
# GPIO42 main_display (display mipi_rgb pclk_pin)
|
||||||
|
# GPIO45 main_display (display mipi_rgb data_pins.red)
|
||||||
|
# GPIO46 main_display (display mipi_rgb data_pins.blue)
|
||||||
|
# GPIO47 main_display (display mipi_rgb data_pins.red)
|
||||||
|
# GPIO48 main_display (display mipi_rgb data_pins.red)
|
||||||
|
# I2C:
|
||||||
|
# 0x5D main_touch (touchscreen gt911)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: lvgl
|
device: lvgl
|
||||||
name: LVGL
|
name: LVGL
|
||||||
@@ -10,18 +94,22 @@ esphome:
|
|||||||
friendly_name: ${name}
|
friendly_name: ${name}
|
||||||
area: ${area}
|
area: ${area}
|
||||||
comment: ${comment}
|
comment: ${comment}
|
||||||
platformio_options:
|
on_boot:
|
||||||
board_build.flash_mode: dio
|
- priority: -100
|
||||||
|
then:
|
||||||
|
- lvgl.page.show: status_page
|
||||||
|
|
||||||
esp32:
|
esp32:
|
||||||
variant: esp32s3
|
variant: esp32s3
|
||||||
flash_size: 16MB
|
flash_size: 16MB
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: gd
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
# Required to achieve sufficient PSRAM bandwidth
|
# PSRAM bandwidth for the RGB panel (not set by ESPHome); without it the
|
||||||
|
# image shifts during flash/WiFi activity
|
||||||
sdkconfig_options:
|
sdkconfig_options:
|
||||||
CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240: y
|
|
||||||
CONFIG_ESP32S3_DATA_CACHE_64KB: y
|
CONFIG_ESP32S3_DATA_CACHE_64KB: y
|
||||||
CONFIG_SPIRAM_FETCH_INSTRUCTIONS: y
|
CONFIG_SPIRAM_FETCH_INSTRUCTIONS: y
|
||||||
CONFIG_SPIRAM_RODATA: y
|
CONFIG_SPIRAM_RODATA: y
|
||||||
@@ -32,62 +120,26 @@ psram:
|
|||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
|
||||||
# PINOUTS: ESP32 Cheap Yellow Display, 4.3", IPS, Capacitive
|
api:
|
||||||
## Display
|
# status page until Home Assistant connects (log viewers don't subscribe to states)
|
||||||
# R0 GND
|
on_client_connected:
|
||||||
# R1 GND
|
- delay: 2s
|
||||||
# R2 GND
|
- if:
|
||||||
# R3 45
|
condition:
|
||||||
# R4 48
|
api.connected:
|
||||||
# R5 47
|
state_subscription_only: true
|
||||||
# R6 21
|
then:
|
||||||
# R7 14
|
- lvgl.page.show: main_page
|
||||||
# G0 GND
|
on_client_disconnected:
|
||||||
# G1 GND
|
- if:
|
||||||
# G2 5
|
condition:
|
||||||
# G3 6
|
not:
|
||||||
# G4 7
|
api.connected:
|
||||||
# G5 15
|
state_subscription_only: true
|
||||||
# G6 16
|
then:
|
||||||
# G7 4
|
- lvgl.page.show: status_page
|
||||||
# B0 GND
|
|
||||||
# B1 GND
|
|
||||||
# B2 GND
|
|
||||||
# B3 8
|
|
||||||
# B4 3
|
|
||||||
# B5 46
|
|
||||||
# B6 9
|
|
||||||
# B7 1
|
|
||||||
# DCLK 42
|
|
||||||
# HSYNC 39
|
|
||||||
# VSYNC 41
|
|
||||||
# DE 40
|
|
||||||
## Capacitive Touch
|
|
||||||
# TP_INT
|
|
||||||
# TP_RST 38
|
|
||||||
# TP_SDA 19
|
|
||||||
# TP_SCL 20
|
|
||||||
## SDCARD
|
|
||||||
# TF_CS 10
|
|
||||||
# SPI_MOSI 11
|
|
||||||
# SPI_CLK 12
|
|
||||||
# SPI_MISO 13
|
|
||||||
## SPI Conector (HC1.25-4)
|
|
||||||
# SPI_CS 19
|
|
||||||
# SPI_MOSI 11
|
|
||||||
# SPI_CLK 12
|
|
||||||
# SPI_MISO 13
|
|
||||||
## UART1 (SH1.0-4)
|
|
||||||
# 1 GND
|
|
||||||
# 2 3V3-ESP
|
|
||||||
# 3 17
|
|
||||||
# 4 18
|
|
||||||
## UART1, USB Connector (Resistive) / I2C (Capacitive) (HC1.25-4)
|
|
||||||
# 1 17
|
|
||||||
# 2 18
|
|
||||||
# 3 19 TP_SDA
|
|
||||||
# 4 20 TP_SCL
|
|
||||||
|
|
||||||
i2c:
|
i2c:
|
||||||
- id: i2c_main
|
- id: i2c_main
|
||||||
@@ -95,573 +147,223 @@ i2c:
|
|||||||
scl: 20
|
scl: 20
|
||||||
scan: true
|
scan: true
|
||||||
|
|
||||||
|
# same pins and timing as the 5" Sunton board, pclk lowered for the 4.3" panel
|
||||||
display:
|
display:
|
||||||
- platform: rpi_dpi_rgb
|
- platform: mipi_rgb
|
||||||
|
model: ESP32-8048S050
|
||||||
id: main_display
|
id: main_display
|
||||||
color_order: RGB
|
color_order: RGB
|
||||||
invert_colors: true
|
invert_colors: true
|
||||||
|
pclk_frequency: 12.5MHz
|
||||||
update_interval: never
|
update_interval: never
|
||||||
auto_clear_enabled: false # takes 2.8 seconds to clear the display
|
auto_clear_enabled: false # takes 2.8 seconds to clear the display
|
||||||
dimensions:
|
|
||||||
width: 800
|
|
||||||
height: 480
|
|
||||||
de_pin: 40
|
|
||||||
hsync_pin: 39
|
|
||||||
vsync_pin: 41
|
|
||||||
pclk_pin: 42
|
|
||||||
pclk_frequency: 12.5MHz
|
|
||||||
hsync_pulse_width: 4
|
|
||||||
hsync_front_porch: 8
|
|
||||||
hsync_back_porch: 8
|
|
||||||
vsync_pulse_width: 4
|
|
||||||
vsync_front_porch: 8
|
|
||||||
vsync_back_porch: 8
|
|
||||||
data_pins:
|
|
||||||
red:
|
|
||||||
- 45 # R1
|
|
||||||
- 48 # R2
|
|
||||||
- 47 # R3
|
|
||||||
- 21 # R4
|
|
||||||
- 14 # R5
|
|
||||||
green:
|
|
||||||
- 5 # G0
|
|
||||||
- 6 # G1
|
|
||||||
- 7 # G2
|
|
||||||
- 15 # G3
|
|
||||||
- 16 # G4
|
|
||||||
- 4 # G5
|
|
||||||
blue:
|
|
||||||
- 8 # B1
|
|
||||||
- 3 # B2
|
|
||||||
- 46 # B3
|
|
||||||
- 9 # B4
|
|
||||||
- 1 # B5
|
|
||||||
|
|
||||||
|
touchscreen:
|
||||||
|
- platform: gt911
|
||||||
|
id: main_touch
|
||||||
|
display: main_display
|
||||||
|
i2c_id: i2c_main
|
||||||
|
reset_pin: 38
|
||||||
|
|
||||||
# Define a PWM output on the ESP32
|
|
||||||
output:
|
output:
|
||||||
- platform: ledc
|
- platform: ledc
|
||||||
|
id: gpio_backlight_pwm
|
||||||
pin: 2
|
pin: 2
|
||||||
frequency: 1220
|
frequency: 1220
|
||||||
id: gpio_backlight_pwm
|
|
||||||
|
|
||||||
light:
|
light:
|
||||||
- platform: monochromatic
|
- platform: monochromatic
|
||||||
output: gpio_backlight_pwm
|
|
||||||
id: back_light
|
id: back_light
|
||||||
|
name: Backlight
|
||||||
|
output: gpio_backlight_pwm
|
||||||
restore_mode: ALWAYS_ON
|
restore_mode: ALWAYS_ON
|
||||||
|
|
||||||
text_sensor:
|
|
||||||
- platform: template
|
|
||||||
# name: Uptime Human Readable
|
|
||||||
id: uptime_human
|
|
||||||
icon: mdi:clock-start
|
|
||||||
internal: True
|
|
||||||
|
|
||||||
time:
|
|
||||||
- platform: homeassistant
|
|
||||||
id: time_comp
|
|
||||||
|
|
||||||
number:
|
|
||||||
- platform: template
|
|
||||||
initial_value: 0
|
|
||||||
id: counting_number
|
|
||||||
internal: True
|
|
||||||
min_value: -10
|
|
||||||
max_value: 10
|
|
||||||
step: 1
|
|
||||||
optimistic: True
|
|
||||||
|
|
||||||
# debug:
|
|
||||||
# update_interval: 5s
|
|
||||||
|
|
||||||
sensor:
|
|
||||||
- platform: uptime
|
|
||||||
id: uptime_counter
|
|
||||||
update_interval: 1s
|
|
||||||
accuracy_decimals: 0
|
|
||||||
on_raw_value:
|
|
||||||
then:
|
|
||||||
- light.turn_on:
|
|
||||||
id: back_light
|
|
||||||
brightness: 90%
|
|
||||||
- number.increment:
|
|
||||||
id: counting_number
|
|
||||||
cycle: True
|
|
||||||
- script.execute: update_display
|
|
||||||
# - platform: debug
|
|
||||||
# free:
|
|
||||||
# name: "${name} Heap Free"
|
|
||||||
# block:
|
|
||||||
# name: "${name} Heap Max Block"
|
|
||||||
# loop_time:
|
|
||||||
# name: "${name} Loop Time"
|
|
||||||
# psram:
|
|
||||||
# name: "${name} Free PSRAM"
|
|
||||||
- platform: uptime
|
|
||||||
# name: Uptime Sensor
|
|
||||||
internal: True
|
|
||||||
id: uptime_sensor
|
|
||||||
update_interval: 1s
|
|
||||||
on_raw_value:
|
|
||||||
then:
|
|
||||||
- text_sensor.template.publish:
|
|
||||||
id: uptime_human
|
|
||||||
state: !lambda |-
|
|
||||||
int seconds = round(id(uptime_sensor).raw_state);
|
|
||||||
int days = seconds / (24 * 3600);
|
|
||||||
seconds = seconds % (24 * 3600);
|
|
||||||
int hours = seconds / 3600;
|
|
||||||
seconds = seconds % 3600;
|
|
||||||
int minutes = seconds / 60;
|
|
||||||
seconds = seconds % 60;
|
|
||||||
return (
|
|
||||||
("Uptime ") +
|
|
||||||
(days ? to_string(days) + "d " : "") +
|
|
||||||
(hours ? to_string(hours) + "h " : "") +
|
|
||||||
(minutes ? to_string(minutes) + "m " : "") +
|
|
||||||
(to_string(seconds) + "s")
|
|
||||||
).c_str();
|
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- id: update_display
|
- id: update_status
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
// same colors as the other status screens: ok green, waiting orange, details gray
|
||||||
|
static const uint32_t OK = 0x4DD966, WAIT = 0xFFB300;
|
||||||
|
auto set = [](lv_obj_t *label, const std::string &text, uint32_t color) {
|
||||||
|
lv_label_set_text(label, text.c_str());
|
||||||
|
lv_obj_set_style_text_color(label, lv_color_hex(color), LV_PART_MAIN);
|
||||||
|
};
|
||||||
|
|
||||||
|
const bool wifi_ok = wifi::global_wifi_component->is_connected();
|
||||||
|
set(id(status_wifi),
|
||||||
|
wifi_ok ? str_sprintf("WiFi: connected (%d dBm)", wifi::global_wifi_component->wifi_rssi())
|
||||||
|
: std::string("WiFi: connecting..."),
|
||||||
|
wifi_ok ? OK : WAIT);
|
||||||
|
|
||||||
|
// IPv6 first (skip link-local), then IPv4
|
||||||
|
std::string ips;
|
||||||
|
if (wifi_ok) {
|
||||||
|
char buf[network::IP_ADDRESS_BUFFER_SIZE];
|
||||||
|
for (bool v6 : {true, false}) {
|
||||||
|
for (auto &ip : wifi::global_wifi_component->get_ip_addresses()) {
|
||||||
|
if (!ip.is_set() || ip.is_ip6() != v6)
|
||||||
|
continue;
|
||||||
|
ip.str_to(buf);
|
||||||
|
if (v6 && strncmp(buf, "fe80", 4) == 0)
|
||||||
|
continue;
|
||||||
|
if (!ips.empty())
|
||||||
|
ips += "\n";
|
||||||
|
ips += buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lv_label_set_text(id(status_ips), ips.c_str());
|
||||||
|
if (ips.empty())
|
||||||
|
lv_obj_add_flag(id(status_ips), LV_OBJ_FLAG_HIDDEN);
|
||||||
|
else
|
||||||
|
lv_obj_remove_flag(id(status_ips), LV_OBJ_FLAG_HIDDEN);
|
||||||
|
|
||||||
|
const bool api_ok = api::global_api_server->is_connected();
|
||||||
|
set(id(status_ha), api_ok ? "Home Assistant: connected" : "Home Assistant: waiting...",
|
||||||
|
api_ok ? OK : WAIT);
|
||||||
|
|
||||||
|
const uint32_t up = millis() / 1000;
|
||||||
|
lv_label_set_text(id(status_footer),
|
||||||
|
str_sprintf("ESPHome %s · up %ud %02u:%02u:%02u", ESPHOME_VERSION, up / 86400,
|
||||||
|
(up / 3600) % 24, (up / 60) % 60, up % 60).c_str());
|
||||||
|
interval:
|
||||||
|
- interval: 1s
|
||||||
then:
|
then:
|
||||||
# - lvgl.indicator.line.update:
|
|
||||||
# id: power_meter_input
|
|
||||||
# value: !lambda return id(counting_number).state;
|
|
||||||
- lvgl.label.update:
|
- lvgl.label.update:
|
||||||
id: battery_kw
|
id: clock_label
|
||||||
text: !lambda |-
|
text: !lambda |-
|
||||||
static char buf[8];
|
auto now = id(ha_time).now();
|
||||||
snprintf(buf, sizeof(buf), "%.1fkW", id(counting_number).state);
|
if (!now.is_valid())
|
||||||
return buf;
|
return std::string("--:--");
|
||||||
- lvgl.label.update:
|
return now.strftime("%H:%M");
|
||||||
id: battery_status
|
- if:
|
||||||
text_color: 0xFF0000
|
condition:
|
||||||
#text: "charging"
|
lvgl.page.is_showing: status_page
|
||||||
text: "discharging"
|
then:
|
||||||
- lvgl.label.update:
|
- script.execute: update_status
|
||||||
id: battery_soc
|
|
||||||
text: !lambda |-
|
|
||||||
static char buf[8];
|
|
||||||
snprintf(buf, sizeof(buf), "%.1f%%", id(counting_number).state);
|
|
||||||
return buf;
|
|
||||||
- lvgl.label.update:
|
|
||||||
id: solar_kw
|
|
||||||
text: !lambda |-
|
|
||||||
static char buf[8];
|
|
||||||
snprintf(buf, sizeof(buf), "%.1fkW", id(counting_number).state);
|
|
||||||
return buf;
|
|
||||||
# - lvgl.img.update:
|
|
||||||
# id: img_solar_power
|
|
||||||
# src: solar_power_icon
|
|
||||||
# img_recolor: 0xFFF000 #mixes this color with the base image
|
|
||||||
# #img_recolor_opa: 100% #opacity defaults to 0% = must set this for recolor to take effect
|
|
||||||
# #bg_color: 0xFFFFFF
|
|
||||||
# # - lvgl.indicator.line.update:
|
|
||||||
# # id: power_meter_input2
|
|
||||||
# # value: !lambda return id(counting_number).state;
|
|
||||||
- lvgl.label.update:
|
|
||||||
id: battery_kw2
|
|
||||||
text: !lambda |-
|
|
||||||
static char buf[8];
|
|
||||||
snprintf(buf, sizeof(buf), "%.1fkW", id(counting_number).state);
|
|
||||||
return buf;
|
|
||||||
- lvgl.label.update:
|
|
||||||
id: battery_status2
|
|
||||||
text_color: 0xFF0000
|
|
||||||
#text: "charging"
|
|
||||||
text: "discharging"
|
|
||||||
- lvgl.label.update:
|
|
||||||
id: battery_soc2
|
|
||||||
text: !lambda |-
|
|
||||||
static char buf[8];
|
|
||||||
snprintf(buf, sizeof(buf), "%.1f%%", id(counting_number).state);
|
|
||||||
return buf;
|
|
||||||
- lvgl.label.update:
|
|
||||||
id: solar_kw2
|
|
||||||
text: !lambda |-
|
|
||||||
static char buf[8];
|
|
||||||
snprintf(buf, sizeof(buf), "%.1fkW", id(counting_number).state);
|
|
||||||
return buf;
|
|
||||||
# - lvgl.img.update:
|
|
||||||
# id: img_solar_power2
|
|
||||||
# src: solar_power_icon
|
|
||||||
# img_recolor: 0xFFF000 #mixes this color with the base image
|
|
||||||
# #img_recolor_opa: 100% #opacity defaults to 0% = must set this for recolor to take effect
|
|
||||||
# #bg_color: 0xFFFFFF
|
|
||||||
|
|
||||||
image:
|
image:
|
||||||
- file: mdi:sun-wireless-outline
|
- platform: file
|
||||||
#"solar-power-invert.png"
|
file: assets/images/made-for-esphome-white-on-black.svg
|
||||||
# mdi:solar-power
|
id: esphome_logo
|
||||||
# mdi:battery-charging-outline
|
resize: 400x118
|
||||||
# mdi:battery-arrow-up-outline
|
type: RGB565
|
||||||
# mdi:battery-arrow-down-outline
|
transparency: alpha_channel
|
||||||
id: solar_power_icon
|
|
||||||
resize: 50x50
|
|
||||||
type: BINARY
|
|
||||||
|
|
||||||
- file: mdi:battery-arrow-down-outline
|
font:
|
||||||
id: home_battery_icon
|
- file: "gfonts://Roboto@500"
|
||||||
resize: 30x30
|
id: font_clock
|
||||||
type: BINARY
|
size: 200
|
||||||
|
glyphs: "0123456789:-"
|
||||||
|
- file: "gfonts://Roboto"
|
||||||
|
id: font_title
|
||||||
|
size: 40
|
||||||
|
- file: "gfonts://Roboto"
|
||||||
|
id: font_status
|
||||||
|
size: 26
|
||||||
|
glyphs: "·"
|
||||||
|
glyphsets: [GF_Latin_Kernel]
|
||||||
|
|
||||||
lvgl:
|
lvgl:
|
||||||
log_level: INFO
|
log_level: WARN
|
||||||
color_depth: 16
|
color_depth: 16
|
||||||
#buffer_size: 25%
|
bg_color: 0x000000
|
||||||
bg_color: 0
|
text_color: 0xFFFFFF
|
||||||
border_width: 0
|
theme:
|
||||||
outline_width: 0
|
buttonmatrix:
|
||||||
shadow_width: 0
|
|
||||||
text_font: unscii_16
|
|
||||||
align: center
|
|
||||||
style_definitions:
|
|
||||||
- id: meter_style
|
|
||||||
text_font: unscii_8
|
|
||||||
#state_default: null
|
|
||||||
- id: font_style
|
|
||||||
text_font: MONTSERRAT_24
|
|
||||||
#text_font: unscii_16
|
|
||||||
align: center
|
|
||||||
text_color: 0xFFFFFF
|
|
||||||
#bg_opa: cover
|
|
||||||
bg_opa: TRANSP
|
bg_opa: TRANSP
|
||||||
bg_color: 0
|
border_width: 0
|
||||||
radius: 4
|
items:
|
||||||
pad_all: 2
|
bg_color: 0x2B2F36
|
||||||
- id: details_style
|
text_color: 0xFFFFFF
|
||||||
text_font: MONTSERRAT_18
|
radius: 12
|
||||||
align: center
|
checked:
|
||||||
text_color: 0xFFFFFF
|
bg_color: 0xE08A00
|
||||||
#bg_opa: cover
|
top_layer:
|
||||||
bg_opa: TRANSP
|
widgets:
|
||||||
bg_color: 0
|
# same navigation bar as on mcu-lvgl-trainer
|
||||||
radius: 4
|
- buttonmatrix:
|
||||||
pad_all: 2
|
id: nav_bar
|
||||||
widgets:
|
align: bottom_mid
|
||||||
- obj: # Meter
|
width: 100%
|
||||||
height: 240
|
height: 64
|
||||||
width: 240
|
pad_all: 4
|
||||||
#bg_opa: TRANSP
|
pad_column: 6
|
||||||
bg_color: 0
|
items:
|
||||||
border_width: 0
|
text_font: montserrat_28
|
||||||
outline_width: 0
|
rows:
|
||||||
shadow_width: 0
|
- buttons:
|
||||||
pad_all: 4
|
- id: page_prev
|
||||||
align: TOP_LEFT
|
text: "\uF053"
|
||||||
#scrollbar_mode: "off"
|
on_press:
|
||||||
widgets:
|
then:
|
||||||
- meter: # Gradient color arc
|
lvgl.page.previous:
|
||||||
height: 100%
|
- id: page_home
|
||||||
width: 100%
|
text: "\uF015"
|
||||||
border_width: 0
|
on_press:
|
||||||
outline_width: 0
|
then:
|
||||||
align: center
|
lvgl.page.show: main_page
|
||||||
bg_color: 0
|
- id: page_next
|
||||||
styles: meter_style
|
text: "\uF054"
|
||||||
#bg_opa: TRANSP
|
on_press:
|
||||||
scales:
|
then:
|
||||||
angle_range: 180 # sets the total angle to 180 = starts mid left and ends mid right
|
lvgl.page.next:
|
||||||
range_to: 10
|
pages:
|
||||||
range_from: -10
|
# 1: clock
|
||||||
ticks:
|
- id: main_page
|
||||||
count: 0
|
widgets:
|
||||||
indicators:
|
- label:
|
||||||
- line:
|
id: clock_label
|
||||||
id: power_meter_input
|
align: CENTER
|
||||||
width: 8
|
y: -32
|
||||||
color: 0xFFFFFF
|
text_font: font_clock
|
||||||
r_mod: 12 #sets line length by this much difference from the scale default radius
|
text: "--:--"
|
||||||
value: 50
|
|
||||||
# - image:
|
# 2: status (shown until Home Assistant connects)
|
||||||
# id: power_meter_input_img
|
- id: status_page
|
||||||
- arc:
|
on_load:
|
||||||
color: 0xFF3000
|
- script.execute: update_status
|
||||||
r_mod: 10 #radius difference from the scale default radius
|
widgets:
|
||||||
width: 20
|
- image:
|
||||||
start_value: -10
|
src: esphome_logo
|
||||||
end_value: 0
|
align: TOP_MID
|
||||||
- arc:
|
y: 16
|
||||||
color: 0x00FF00
|
- label:
|
||||||
r_mod: 10 #radius difference from the scale default radius
|
align: TOP_MID
|
||||||
width: 20
|
y: 140
|
||||||
start_value: 0
|
text_font: font_title
|
||||||
end_value: 10
|
text: "${name}"
|
||||||
#- canvas:
|
- obj:
|
||||||
- arc: # black arc to erase middle part of meter indicator line
|
id: status_lines
|
||||||
height: 160
|
x: 60
|
||||||
width: 160
|
y: 196
|
||||||
align: center
|
width: 700
|
||||||
arc_color: 0x000000 # background color
|
height: SIZE_CONTENT
|
||||||
arc_width: 150
|
bg_opa: TRANSP
|
||||||
start_angle: 0
|
border_width: 0
|
||||||
end_angle: 360
|
pad_all: 0
|
||||||
indicator:
|
scrollbar_mode: "OFF"
|
||||||
arc_width: 150
|
layout:
|
||||||
arc_color: 0x000000
|
type: flex
|
||||||
- label: # gauge lower and higher range indicators
|
flex_flow: column
|
||||||
styles: font_style
|
pad_row: 8
|
||||||
text_font: MONTSERRAT_18 # override font size
|
widgets:
|
||||||
y: 8 #negative = higher
|
- label:
|
||||||
x: -99
|
id: status_wifi
|
||||||
text: "-10"
|
text_font: font_status
|
||||||
- label:
|
text: ""
|
||||||
styles: font_style
|
- label:
|
||||||
text_font: MONTSERRAT_18 # override font size
|
id: status_ips
|
||||||
y: 8 #negative = higher
|
text_font: font_status
|
||||||
x: 99
|
text_color: 0x8C8C8C
|
||||||
text: "+10"
|
pad_left: 30
|
||||||
- label:
|
text: ""
|
||||||
styles: font_style
|
- label:
|
||||||
id: battery_status
|
id: status_ha
|
||||||
y: -35 #negative = higher
|
text_font: font_status
|
||||||
- label:
|
text: ""
|
||||||
styles: font_style
|
- label:
|
||||||
id: battery_kw
|
id: status_footer
|
||||||
y: -60
|
text_font: font_status
|
||||||
- label:
|
text_color: 0x8C8C8C
|
||||||
styles: font_style
|
text: ""
|
||||||
text_font: MONTSERRAT_40 # override font size
|
|
||||||
id: battery_soc
|
|
||||||
y: 0
|
|
||||||
- label:
|
|
||||||
styles: font_style
|
|
||||||
id: solar_kw
|
|
||||||
text_color: 0xFFFF00
|
|
||||||
y: 90
|
|
||||||
#- img:
|
|
||||||
# src: home_battery_icon
|
|
||||||
#id: img_solar_power
|
|
||||||
#align: center
|
|
||||||
#img_recolor: 0xFFFFFF
|
|
||||||
#img_recolor_opa: 100% #opacity defaults to 0% = must set this for recolor to take effect
|
|
||||||
#bg_color: 0xFFFFFF
|
|
||||||
#y: -35
|
|
||||||
#x: -60
|
|
||||||
- image:
|
|
||||||
src: solar_power_icon
|
|
||||||
id: img_solar_power
|
|
||||||
align: center
|
|
||||||
image_recolor: 0xFFFF00
|
|
||||||
image_recolor_opa: 100% #opacity defaults to 0% = must set this for recolor to take effect
|
|
||||||
#bg_color: 0xFFFFFF
|
|
||||||
y: 50
|
|
||||||
#x: -60
|
|
||||||
- obj: # Meter
|
|
||||||
height: 240
|
|
||||||
width: 240
|
|
||||||
#bg_opa: TRANSP
|
|
||||||
bg_color: 0
|
|
||||||
border_width: 0
|
|
||||||
outline_width: 0
|
|
||||||
shadow_width: 0
|
|
||||||
pad_all: 4
|
|
||||||
align: TOP_MID
|
|
||||||
#scrollbar_mode: "off"
|
|
||||||
widgets:
|
|
||||||
- meter: # Gradient color arc
|
|
||||||
height: 100%
|
|
||||||
width: 100%
|
|
||||||
border_width: 0
|
|
||||||
outline_width: 0
|
|
||||||
align: center
|
|
||||||
bg_color: 0
|
|
||||||
styles: meter_style
|
|
||||||
#bg_opa: TRANSP
|
|
||||||
scales:
|
|
||||||
angle_range: 180 # sets the total angle to 180 = starts mid left and ends mid right
|
|
||||||
range_to: 10
|
|
||||||
range_from: -10
|
|
||||||
ticks:
|
|
||||||
count: 0
|
|
||||||
indicators:
|
|
||||||
- line:
|
|
||||||
id: power_meter_input2
|
|
||||||
width: 8
|
|
||||||
color: 0xFFFFFF
|
|
||||||
r_mod: 12 #sets line length by this much difference from the scale default radius
|
|
||||||
value: 50
|
|
||||||
# - image:
|
|
||||||
# id: power_meter_input_img2
|
|
||||||
- arc:
|
|
||||||
color: 0xFF3000
|
|
||||||
r_mod: 10 #radius difference from the scale default radius
|
|
||||||
width: 20
|
|
||||||
start_value: -10
|
|
||||||
end_value: 0
|
|
||||||
- arc:
|
|
||||||
color: 0x00FF00
|
|
||||||
r_mod: 10 #radius difference from the scale default radius
|
|
||||||
width: 20
|
|
||||||
start_value: 0
|
|
||||||
end_value: 10
|
|
||||||
#- canvas:
|
|
||||||
- arc: # black arc to erase middle part of meter indicator line
|
|
||||||
height: 160
|
|
||||||
width: 160
|
|
||||||
align: center
|
|
||||||
arc_color: 0x000000 # background color
|
|
||||||
arc_width: 150
|
|
||||||
start_angle: 0
|
|
||||||
end_angle: 360
|
|
||||||
indicator:
|
|
||||||
arc_width: 150
|
|
||||||
arc_color: 0x000000
|
|
||||||
- label: # gauge lower and higher range indicators
|
|
||||||
styles: font_style
|
|
||||||
text_font: MONTSERRAT_18 # override font size
|
|
||||||
y: 8 #negative = higher
|
|
||||||
x: -99
|
|
||||||
text: "-10"
|
|
||||||
- label:
|
|
||||||
styles: font_style
|
|
||||||
text_font: MONTSERRAT_18 # override font size
|
|
||||||
y: 8 #negative = higher
|
|
||||||
x: 99
|
|
||||||
text: "+10"
|
|
||||||
- label:
|
|
||||||
styles: font_style
|
|
||||||
id: battery_status2
|
|
||||||
y: -35 #negative = higher
|
|
||||||
- label:
|
|
||||||
styles: font_style
|
|
||||||
id: battery_kw2
|
|
||||||
y: -60
|
|
||||||
- label:
|
|
||||||
styles: font_style
|
|
||||||
text_font: MONTSERRAT_40 # override font size
|
|
||||||
id: battery_soc2
|
|
||||||
y: 0
|
|
||||||
- label:
|
|
||||||
styles: font_style
|
|
||||||
id: solar_kw2
|
|
||||||
text_color: 0xFFFF00
|
|
||||||
y: 90
|
|
||||||
#- img:
|
|
||||||
# src: home_battery_icon
|
|
||||||
#id: img_solar_power
|
|
||||||
#align: center
|
|
||||||
#img_recolor: 0xFFFFFF
|
|
||||||
#img_recolor_opa: 100% #opacity defaults to 0% = must set this for recolor to take effect
|
|
||||||
#bg_color: 0xFFFFFF
|
|
||||||
#y: -35
|
|
||||||
#x: -60
|
|
||||||
- image:
|
|
||||||
src: solar_power_icon
|
|
||||||
id: img_solar_power2
|
|
||||||
align: center
|
|
||||||
image_recolor: 0xFFFF00
|
|
||||||
image_recolor_opa: 100% #opacity defaults to 0% = must set this for recolor to take effect
|
|
||||||
#bg_color: 0xFFFFFF
|
|
||||||
y: 50
|
|
||||||
#x: -60
|
|
||||||
- obj: # Meter
|
|
||||||
height: 240
|
|
||||||
width: 240
|
|
||||||
#bg_opa: TRANSP
|
|
||||||
bg_color: 0
|
|
||||||
border_width: 0
|
|
||||||
outline_width: 0
|
|
||||||
shadow_width: 0
|
|
||||||
pad_all: 4
|
|
||||||
align: BOTTOM_LEFT
|
|
||||||
#scrollbar_mode: "off"
|
|
||||||
widgets:
|
|
||||||
- meter: # Gradient color arc
|
|
||||||
height: 100%
|
|
||||||
width: 100%
|
|
||||||
border_width: 0
|
|
||||||
outline_width: 0
|
|
||||||
align: center
|
|
||||||
bg_color: 0
|
|
||||||
styles: meter_style
|
|
||||||
#bg_opa: TRANSP
|
|
||||||
scales:
|
|
||||||
angle_range: 180 # sets the total angle to 180 = starts mid left and ends mid right
|
|
||||||
range_to: 10
|
|
||||||
range_from: -10
|
|
||||||
ticks:
|
|
||||||
count: 0
|
|
||||||
indicators:
|
|
||||||
- line:
|
|
||||||
id: power_meter_input3
|
|
||||||
width: 8
|
|
||||||
color: 0xFFFFFF
|
|
||||||
r_mod: 12 #sets line length by this much difference from the scale default radius
|
|
||||||
value: 50
|
|
||||||
# - image:
|
|
||||||
# id: power_meter_input_img3
|
|
||||||
- arc:
|
|
||||||
color: 0xFF3000
|
|
||||||
r_mod: 10 #radius difference from the scale default radius
|
|
||||||
width: 20
|
|
||||||
start_value: -10
|
|
||||||
end_value: 0
|
|
||||||
- arc:
|
|
||||||
color: 0x00FF00
|
|
||||||
r_mod: 10 #radius difference from the scale default radius
|
|
||||||
width: 20
|
|
||||||
start_value: 0
|
|
||||||
end_value: 10
|
|
||||||
#- canvas:
|
|
||||||
- arc: # black arc to erase middle part of meter indicator line
|
|
||||||
height: 160
|
|
||||||
width: 160
|
|
||||||
align: center
|
|
||||||
arc_color: 0x000000 # background color
|
|
||||||
arc_width: 150
|
|
||||||
start_angle: 0
|
|
||||||
end_angle: 360
|
|
||||||
indicator:
|
|
||||||
arc_width: 150
|
|
||||||
arc_color: 0x000000
|
|
||||||
- label: # gauge lower and higher range indicators
|
|
||||||
styles: font_style
|
|
||||||
text_font: MONTSERRAT_18 # override font size
|
|
||||||
y: 8 #negative = higher
|
|
||||||
x: -99
|
|
||||||
text: "-10"
|
|
||||||
- label:
|
|
||||||
styles: font_style
|
|
||||||
text_font: MONTSERRAT_18 # override font size
|
|
||||||
y: 8 #negative = higher
|
|
||||||
x: 99
|
|
||||||
text: "+10"
|
|
||||||
- label:
|
|
||||||
styles: font_style
|
|
||||||
id: battery_status3
|
|
||||||
y: -35 #negative = higher
|
|
||||||
- label:
|
|
||||||
styles: font_style
|
|
||||||
id: battery_kw3
|
|
||||||
y: -60
|
|
||||||
- label:
|
|
||||||
styles: font_style
|
|
||||||
text_font: MONTSERRAT_40 # override font size
|
|
||||||
id: battery_soc3
|
|
||||||
y: 0
|
|
||||||
- label:
|
|
||||||
styles: font_style
|
|
||||||
id: solar_kw3
|
|
||||||
text_color: 0xFFFF00
|
|
||||||
y: 90
|
|
||||||
#- img:
|
|
||||||
# src: home_battery_icon
|
|
||||||
#id: img_solar_power
|
|
||||||
#align: center
|
|
||||||
#img_recolor: 0xFFFFFF
|
|
||||||
#img_recolor_opa: 100% #opacity defaults to 0% = must set this for recolor to take effect
|
|
||||||
#bg_color: 0xFFFFFF
|
|
||||||
#y: -35
|
|
||||||
#x: -60
|
|
||||||
- image:
|
|
||||||
src: solar_power_icon
|
|
||||||
id: img_solar_power3
|
|
||||||
align: center
|
|
||||||
image_recolor: 0xFFFF00
|
|
||||||
image_recolor_opa: 100% #opacity defaults to 0% = must set this for recolor to take effect
|
|
||||||
#bg_color: 0xFFFFFF
|
|
||||||
y: 50
|
|
||||||
#x: -60
|
|
||||||
+600
-77
@@ -1,97 +1,404 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack M5Paper
|
||||||
|
# Pinout:
|
||||||
|
# GPIO2 -> main_power (switch gpio)
|
||||||
|
# GPIO5 -> ext_power (switch gpio)
|
||||||
|
# GPIO12 -> spi (spi mosi_pin)
|
||||||
|
# GPIO13 -> spi (spi miso_pin)
|
||||||
|
# GPIO14 -> spi (spi clk_pin)
|
||||||
|
# GPIO15 -> m5paper_display (display it8951 cs_pin)
|
||||||
|
# GPIO21 -> i2c_main (i2c sda)
|
||||||
|
# GPIO22 -> i2c_main (i2c scl)
|
||||||
|
# GPIO23 -> m5paper_display (display it8951 reset_pin)
|
||||||
|
# GPIO27 -> m5paper_display (display it8951 busy_pin)
|
||||||
|
# GPIO35 -> Battery Voltage (sensor adc)
|
||||||
|
# GPIO36 -> gt911_touchscreen (touchscreen gt911 interrupt_pin)
|
||||||
|
# GPIO37 -> M5Paper Button UP (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO38 -> M5Paper Button Press (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO39 -> M5Paper Button Down (binary_sensor gpio) (inverted)
|
||||||
|
# I2C:
|
||||||
|
# 0x44 sensor sht3xd (sensor sht3xd)
|
||||||
|
# 0x51 rtc_time (time bm8563)
|
||||||
|
# 0x5D gt911_touchscreen (touchscreen gt911)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: m5paper
|
device: m5paper
|
||||||
name: M5Paper
|
name: M5Paper
|
||||||
area: DEV
|
area: DEV
|
||||||
comment: M5Paper
|
comment: M5Paper
|
||||||
|
waste_calendar: calendar.https_www_hviezdoslavov_sk_kalendar_icalfeed_category_0_ongoing_1
|
||||||
|
# contacts + manual
|
||||||
|
birthday_calendars: calendar.birthdays, calendar.narodeniny
|
||||||
|
|
||||||
|
# Power modes
|
||||||
|
# - USB: always on, WiFi + API, events refreshed and redrawn after midnight
|
||||||
|
# - battery: RTC wakes the board at 00:05, it refreshes the events, draws them and powers
|
||||||
|
# itself off; the RTC timer lasts at most 255 min, so the wake-ups on the way to
|
||||||
|
# midnight only re-arm it
|
||||||
|
# The power button (and USB) also connects to WiFi: the events are refreshed on every
|
||||||
|
# Home Assistant connection outside the battery cycle.
|
||||||
|
# Screens: status (after power-on, until Home Assistant connects) and calendar
|
||||||
|
# The mode is detected by trying to power off: on USB the board keeps running.
|
||||||
|
|
||||||
esphome:
|
esphome:
|
||||||
name: mcu-${device}
|
name: mcu-${device}
|
||||||
friendly_name: ${name}
|
friendly_name: ${name}
|
||||||
area: ${area}
|
area: ${area}
|
||||||
comment: ${comment}
|
comment: ${comment}
|
||||||
|
includes:
|
||||||
|
- include/m5paper_calendar.h
|
||||||
|
on_boot:
|
||||||
|
- priority: 600
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
// BM8563 CONTROL_STATUS_2: TF (bit 2) is set when the timer woke us up
|
||||||
|
const uint8_t reg = 0x01;
|
||||||
|
uint8_t status = 0;
|
||||||
|
if (id(i2c_main)->write_readv(0x51, ®, 1, &status, 1) == i2c::ERROR_OK) {
|
||||||
|
id(rtc_wake) = status & 0x04;
|
||||||
|
// clear TF and TIE so the RTC releases the power latch
|
||||||
|
const uint8_t clear[2] = {reg, uint8_t(status & ~0x05)};
|
||||||
|
id(i2c_main)->write(0x51, clear, 2);
|
||||||
|
}
|
||||||
|
m5paper_calendar::load(m5paper_calendar::events());
|
||||||
|
ESP_LOGI("m5paper", "Wake-up: %s, events: %u", id(rtc_wake) ? "RTC" : "power-on", m5paper_calendar::events().count);
|
||||||
|
- priority: -100
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
lambda: return id(rtc_wake);
|
||||||
|
then:
|
||||||
|
- script.execute: battery_cycle
|
||||||
|
else:
|
||||||
|
# power button / USB: stay awake for a while (logs, OTA), then decide the mode
|
||||||
|
- wifi.enable:
|
||||||
|
# IT8951 init runs asynchronously after setup
|
||||||
|
- delay: 3s
|
||||||
|
- component.update: m5paper_display
|
||||||
|
- delay: 2min
|
||||||
|
- script.execute: battery_cycle
|
||||||
|
|
||||||
esp32:
|
esp32:
|
||||||
variant: esp32
|
variant: esp32
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
advanced:
|
||||||
|
flash_chip: generic
|
||||||
|
minimum_chip_revision: 3.0
|
||||||
|
sram1_as_iram: true
|
||||||
|
|
||||||
psram:
|
psram:
|
||||||
|
|
||||||
external_components:
|
|
||||||
- source: github://Passific/m5paper_esphome
|
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
|
||||||
time:
|
globals:
|
||||||
- platform: homeassistant
|
- id: show_status
|
||||||
id: ha_time
|
type: bool
|
||||||
timezone: Europe/Bratislava
|
initial_value: 'true'
|
||||||
on_time_sync:
|
- id: usb_mode
|
||||||
- bm8563.write_time
|
type: bool
|
||||||
- platform: bm8563
|
initial_value: 'false'
|
||||||
id: rtc_time
|
- id: rtc_wake
|
||||||
sleep_duration: 3600000ms
|
type: bool
|
||||||
|
initial_value: 'false'
|
||||||
|
# battery cycle running: calendar screen regardless of the connection state
|
||||||
|
- id: calendar_page
|
||||||
|
type: bool
|
||||||
|
initial_value: 'false'
|
||||||
|
- id: fetch_done
|
||||||
|
type: bool
|
||||||
|
initial_value: 'false'
|
||||||
|
- id: sleep_s
|
||||||
|
type: int
|
||||||
|
initial_value: '900'
|
||||||
|
|
||||||
m5paper:
|
wifi:
|
||||||
battery_power_pin: GPIO5
|
enable_on_boot: false
|
||||||
main_power_pin: GPIO2
|
on_connect:
|
||||||
# update_interval: 10s
|
- if:
|
||||||
# battery_voltage:
|
condition:
|
||||||
# name: "${name} Battery"
|
lambda: return id(show_status) && !id(calendar_page);
|
||||||
|
then:
|
||||||
|
- component.update: m5paper_display
|
||||||
|
|
||||||
|
api:
|
||||||
|
# status screen until Home Assistant connects (log viewers don't subscribe to states)
|
||||||
|
on_client_connected:
|
||||||
|
- delay: 2s
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
api.connected:
|
||||||
|
state_subscription_only: true
|
||||||
|
then:
|
||||||
|
- lambda: id(show_status) = false;
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
lambda: return !id(calendar_page);
|
||||||
|
then:
|
||||||
|
- component.update: m5paper_display
|
||||||
|
# outside the battery cycle (power button, USB) WiFi is up anyway: always refresh
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
and:
|
||||||
|
- lambda: return !id(calendar_page);
|
||||||
|
- api.connected:
|
||||||
|
state_subscription_only: true
|
||||||
|
then:
|
||||||
|
- script.execute: fetch_events
|
||||||
|
on_client_disconnected:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
not:
|
||||||
|
api.connected:
|
||||||
|
state_subscription_only: true
|
||||||
|
then:
|
||||||
|
- lambda: id(show_status) = true;
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
lambda: return !id(calendar_page);
|
||||||
|
then:
|
||||||
|
- component.update: m5paper_display
|
||||||
|
|
||||||
|
# I2C devices (i2c_main)
|
||||||
# 0x44 SHT30
|
# 0x44 SHT30
|
||||||
# 0x50
|
# 0x50 FM24C02 EEPROM (unused)
|
||||||
# 0x51
|
# 0x51 BM8563 RTC
|
||||||
# 0x5D GT911
|
# 0x5D GT911 touch (docs say 0x14; the driver tries 0x5D, then 0x14)
|
||||||
|
|
||||||
i2c:
|
i2c:
|
||||||
- id: i2c_main
|
- id: i2c_main
|
||||||
sda: 21
|
sda: 21
|
||||||
scl: 22
|
scl: 22
|
||||||
scan: true #false
|
scan: true
|
||||||
|
# Port A
|
||||||
# - id: i2c_a
|
# - id: i2c_a
|
||||||
# sda: 25
|
# sda: 25
|
||||||
# scl: 32
|
# scl: 32
|
||||||
# scan: true #false
|
# Port B
|
||||||
# - id: i2c_b
|
# - id: i2c_b
|
||||||
# sda: 26
|
# sda: 26
|
||||||
# scl: 33
|
# scl: 33
|
||||||
# scan: true #false
|
# Port C
|
||||||
# - id: i2c_c
|
# - id: i2c_c
|
||||||
# sda: 18
|
# sda: 18
|
||||||
# scl: 19
|
# scl: 19
|
||||||
# scan: true #false
|
|
||||||
|
|
||||||
spi:
|
spi:
|
||||||
clk_pin: 14
|
clk_pin: 14
|
||||||
miso_pin: 13
|
miso_pin: 13
|
||||||
mosi_pin: 12
|
mosi_pin: 12
|
||||||
|
|
||||||
|
switch:
|
||||||
|
# Power control MOS (no PMU on M5Paper); on battery the device powers off when this goes low
|
||||||
|
- platform: gpio
|
||||||
|
id: main_power
|
||||||
|
pin:
|
||||||
|
number: GPIO2
|
||||||
|
ignore_strapping_warning: true
|
||||||
|
restore_mode: ALWAYS_ON
|
||||||
|
internal: true
|
||||||
|
# External power (Grove ports)
|
||||||
|
- platform: gpio
|
||||||
|
id: ext_power
|
||||||
|
pin:
|
||||||
|
number: GPIO5
|
||||||
|
ignore_strapping_warning: true
|
||||||
|
restore_mode: ALWAYS_ON
|
||||||
|
internal: true
|
||||||
|
|
||||||
|
script:
|
||||||
|
# One wake-up on battery: refresh the events if they are old, draw them, power off
|
||||||
|
- id: battery_cycle
|
||||||
|
mode: single
|
||||||
|
then:
|
||||||
|
- lambda: id(calendar_page) = true;
|
||||||
|
- wait_until:
|
||||||
|
condition:
|
||||||
|
lambda: return id(rtc_time).now().is_valid();
|
||||||
|
timeout: 10s
|
||||||
|
- if:
|
||||||
|
# RTC wake-up on the way to midnight: nothing to draw
|
||||||
|
condition:
|
||||||
|
lambda: |-
|
||||||
|
const auto now = id(rtc_time).now();
|
||||||
|
return id(rtc_wake) && now.is_valid() && now.hour != 0;
|
||||||
|
then:
|
||||||
|
- script.execute: try_sleep
|
||||||
|
else:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
lambda: return m5paper_calendar::stale(id(rtc_time).now());
|
||||||
|
then:
|
||||||
|
- wifi.enable:
|
||||||
|
- wait_until:
|
||||||
|
condition:
|
||||||
|
api.connected:
|
||||||
|
state_subscription_only: true
|
||||||
|
timeout: 45s
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
api.connected:
|
||||||
|
state_subscription_only: true
|
||||||
|
then:
|
||||||
|
- script.execute: fetch_events
|
||||||
|
- wait_until:
|
||||||
|
condition:
|
||||||
|
lambda: return id(fetch_done);
|
||||||
|
timeout: 15s
|
||||||
|
- component.update: m5paper_display
|
||||||
|
# let the e-paper refresh finish before cutting power
|
||||||
|
- delay: 4s
|
||||||
|
- script.execute: try_sleep
|
||||||
|
|
||||||
|
# today and the next 31 days (the month grid and the list)
|
||||||
|
- id: fetch_events
|
||||||
|
mode: single
|
||||||
|
then:
|
||||||
|
- lambda: id(fetch_done) = false;
|
||||||
|
- homeassistant.action:
|
||||||
|
action: calendar.get_events
|
||||||
|
data:
|
||||||
|
entity_id: ${waste_calendar}, ${birthday_calendars}
|
||||||
|
start_date_time: !lambda return id(rtc_time).now().strftime("%Y-%m-%d 00:00:00");
|
||||||
|
duration: "744:00:00"
|
||||||
|
capture_response: true
|
||||||
|
on_success:
|
||||||
|
- lambda: |-
|
||||||
|
auto &ev = m5paper_calendar::events();
|
||||||
|
if (m5paper_calendar::parse(response, "${waste_calendar}", id(rtc_time).now().timestamp, ev)) {
|
||||||
|
const bool saved = m5paper_calendar::save(ev);
|
||||||
|
ESP_LOGI("m5paper", "Events: %u%s", ev.count, saved ? "" : " (flash write failed)");
|
||||||
|
} else {
|
||||||
|
ESP_LOGW("m5paper", "Events: unexpected response");
|
||||||
|
}
|
||||||
|
id(fetch_done) = true;
|
||||||
|
# the battery cycle draws on its own
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
lambda: return !id(calendar_page);
|
||||||
|
then:
|
||||||
|
- component.update: m5paper_display
|
||||||
|
on_error:
|
||||||
|
- lambda: |-
|
||||||
|
ESP_LOGW("m5paper", "Events: %s", error.c_str());
|
||||||
|
id(fetch_done) = true;
|
||||||
|
|
||||||
|
# Arm the RTC and cut power; if we are still running afterwards, we are on USB
|
||||||
|
- id: try_sleep
|
||||||
|
mode: single
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
// next 00:05; the timer lasts at most 255 min, so get there in steps
|
||||||
|
const int MAX = 255 * 60;
|
||||||
|
int duration = MAX;
|
||||||
|
const auto now = id(rtc_time).now();
|
||||||
|
if (now.is_valid()) {
|
||||||
|
const int sod = now.hour * 3600 + now.minute * 60 + now.second;
|
||||||
|
int left = (86400 + 300 - sod) % 86400;
|
||||||
|
if (left < 600) // just drawn: the 1/60 Hz RTC timer may wake us up to a minute early
|
||||||
|
left += 86400;
|
||||||
|
// leave at least 20 min for the last step, so it cannot fall into the case above
|
||||||
|
duration = left > MAX ? std::min(MAX, left - 1200) : left;
|
||||||
|
}
|
||||||
|
if (duration > 255) // longer timers count whole minutes
|
||||||
|
duration = (duration + 59) / 60 * 60;
|
||||||
|
id(sleep_s) = std::min(duration, MAX);
|
||||||
|
ESP_LOGI("m5paper", "Powering off for %d s", id(sleep_s));
|
||||||
|
- bm8563.start_timer:
|
||||||
|
duration: !lambda return id(sleep_s);
|
||||||
|
# a battery wake-up is shorter than boot_is_good_after: confirm the OTA image
|
||||||
|
# before cutting power, otherwise the bootloader rolls back
|
||||||
|
- safe_mode.mark_successful:
|
||||||
|
- delay: 200ms
|
||||||
|
- switch.turn_off: main_power
|
||||||
|
- delay: 2s
|
||||||
|
# still alive -> USB power
|
||||||
|
- switch.turn_on: main_power
|
||||||
|
- lambda: |-
|
||||||
|
ESP_LOGI("m5paper", "Still running, USB power");
|
||||||
|
id(usb_mode) = true;
|
||||||
|
id(rtc_wake) = false;
|
||||||
|
id(calendar_page) = false;
|
||||||
|
id(show_status) = !api::global_api_server->is_connected_with_state_subscription();
|
||||||
|
- wifi.enable:
|
||||||
|
- component.update: m5paper_display
|
||||||
|
|
||||||
|
interval:
|
||||||
|
# USB mode: the battery voltage drops once USB is unplugged -> go to battery mode
|
||||||
|
- interval: 5min
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
lambda: |-
|
||||||
|
static float last = NAN;
|
||||||
|
const float v = id(battery_voltage).state;
|
||||||
|
const bool dropped = id(usb_mode) && !std::isnan(last) && last - v > 0.03f;
|
||||||
|
last = v;
|
||||||
|
return dropped;
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
ESP_LOGI("m5paper", "Battery voltage dropping, checking USB");
|
||||||
|
id(usb_mode) = false;
|
||||||
|
- script.execute: battery_cycle
|
||||||
|
|
||||||
|
time:
|
||||||
|
- id: !extend ha_time
|
||||||
|
on_time_sync:
|
||||||
|
- bm8563.write_time
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
lambda: return !id(calendar_page);
|
||||||
|
then:
|
||||||
|
- component.update: m5paper_display
|
||||||
|
on_time:
|
||||||
|
# new day
|
||||||
|
- seconds: 0
|
||||||
|
minutes: 0
|
||||||
|
hours: 0
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
lambda: return !id(show_status) && !id(calendar_page);
|
||||||
|
then:
|
||||||
|
- component.update: m5paper_display
|
||||||
|
# USB mode: keep the stored events fresh for battery mode
|
||||||
|
- seconds: 0
|
||||||
|
minutes: 5
|
||||||
|
hours: 0
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
and:
|
||||||
|
- lambda: return id(usb_mode);
|
||||||
|
- api.connected:
|
||||||
|
state_subscription_only: true
|
||||||
|
then:
|
||||||
|
- script.execute: fetch_events
|
||||||
|
- platform: bm8563
|
||||||
|
id: rtc_time
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
name: ${name} Button UP
|
name: ${name} Button UP
|
||||||
id: button_up
|
id: button_up
|
||||||
pin:
|
pin:
|
||||||
number: 37
|
number: GPIO37
|
||||||
inverted: true
|
inverted: true
|
||||||
on_press:
|
on_press:
|
||||||
- component.update: m5paper_display
|
- component.update: m5paper_display
|
||||||
on_release:
|
|
||||||
- component.update: m5paper_display
|
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
name: ${name} Button Press
|
name: ${name} Button Press
|
||||||
id: button_press
|
id: button_press
|
||||||
pin:
|
pin:
|
||||||
number: 38
|
number: GPIO38
|
||||||
inverted: true
|
inverted: true
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
name: ${name} Button Down
|
name: ${name} Button Down
|
||||||
id: button_down
|
id: button_down
|
||||||
pin:
|
pin:
|
||||||
number: 39
|
number: GPIO39
|
||||||
inverted: true
|
inverted: true
|
||||||
- platform: touchscreen
|
- platform: touchscreen
|
||||||
name: ${name} Top Left Touch Button
|
name: ${name} Top Left Touch Button
|
||||||
@@ -103,51 +410,19 @@ binary_sensor:
|
|||||||
y_min: 0
|
y_min: 0
|
||||||
y_max: 100
|
y_max: 100
|
||||||
on_press:
|
on_press:
|
||||||
# Example of applying the sleep duration and shutting down to the lowest power mode
|
- script.execute: battery_cycle
|
||||||
- bm8563.apply_sleep_duration
|
|
||||||
- delay: 1s
|
|
||||||
- m5paper.shutdown_main_power
|
|
||||||
|
|
||||||
font:
|
button:
|
||||||
- file: "gfonts://Roboto"
|
- platform: template
|
||||||
id: font_default
|
name: Refresh Display
|
||||||
size: 20
|
entity_category: config
|
||||||
- file: "gfonts://Roboto"
|
on_press:
|
||||||
id: roboto_32
|
- component.update: m5paper_display
|
||||||
size: 32
|
- platform: template
|
||||||
- file: "gfonts://Roboto"
|
name: Refresh Calendar
|
||||||
id: roboto_24
|
entity_category: config
|
||||||
size: 24
|
on_press:
|
||||||
- file: "gfonts://Roboto"
|
- script.execute: fetch_events
|
||||||
id: roboto_12
|
|
||||||
size: 12
|
|
||||||
|
|
||||||
display:
|
|
||||||
- platform: it8951e
|
|
||||||
id: m5paper_display
|
|
||||||
cs_pin: GPIO15
|
|
||||||
reset_pin: GPIO23
|
|
||||||
busy_pin: GPIO27
|
|
||||||
rotation: 90
|
|
||||||
reversed: False
|
|
||||||
update_interval: "never"
|
|
||||||
lambda: |-
|
|
||||||
it.printf(25, 25, id(roboto_32), "%.1f°", id(current_temperature).state);
|
|
||||||
it.strftime(350, 25, id(roboto_32), "%H:%M:%S", id(rtc_time).now());
|
|
||||||
|
|
||||||
touchscreen:
|
|
||||||
- platform: gt911
|
|
||||||
display: m5paper_display
|
|
||||||
id: gt911_touchscreen
|
|
||||||
interrupt_pin: GPIO36
|
|
||||||
|
|
||||||
# display:
|
|
||||||
# - platform: waveshare_epaper
|
|
||||||
# cs_pin: 15
|
|
||||||
# model: 2.90in
|
|
||||||
# full_update_every: 30
|
|
||||||
# lambda: |-
|
|
||||||
# it.print(0, 0, id(font1), "Hello World!");
|
|
||||||
|
|
||||||
sensor:
|
sensor:
|
||||||
- platform: sht3xd
|
- platform: sht3xd
|
||||||
@@ -156,9 +431,257 @@ sensor:
|
|||||||
id: current_temperature
|
id: current_temperature
|
||||||
humidity:
|
humidity:
|
||||||
name: Humidity
|
name: Humidity
|
||||||
|
id: current_humidity
|
||||||
address: 0x44
|
address: 0x44
|
||||||
update_interval: 60s
|
update_interval: 60s
|
||||||
|
- platform: adc
|
||||||
|
id: battery_voltage
|
||||||
|
name: Battery Voltage
|
||||||
|
pin: GPIO35
|
||||||
|
attenuation: 12db
|
||||||
|
samples: 16
|
||||||
|
update_interval: 60s
|
||||||
|
entity_category: diagnostic
|
||||||
|
filters:
|
||||||
|
- multiply: 2.0 # 1:2 voltage divider
|
||||||
|
- platform: copy
|
||||||
|
source_id: battery_voltage
|
||||||
|
id: battery_level
|
||||||
|
name: Battery
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
device_class: battery
|
||||||
|
accuracy_decimals: 0
|
||||||
|
filters:
|
||||||
|
- calibrate_linear:
|
||||||
|
- 3.3 -> 0.0
|
||||||
|
- 4.15 -> 100.0
|
||||||
|
- clamp:
|
||||||
|
min_value: 0
|
||||||
|
max_value: 100
|
||||||
|
|
||||||
# touchscreen:
|
.image_defaults:
|
||||||
# - platform: gt911
|
icon: &icon {platform: file, type: BINARY, transparency: chroma_key}
|
||||||
# interrupt_pin: 36
|
|
||||||
|
image:
|
||||||
|
- platform: file
|
||||||
|
file: assets/images/made-for-esphome-white-on-black.svg
|
||||||
|
id: esphome_logo
|
||||||
|
resize: 460x136
|
||||||
|
type: GRAYSCALE
|
||||||
|
transparency: alpha_channel
|
||||||
|
# same order as m5paper_calendar::Kind
|
||||||
|
- {<<: *icon, file: "mdi:cake-variant", id: icon_birthday, resize: 32x32}
|
||||||
|
- {<<: *icon, file: "mdi:trash-can", id: icon_waste, resize: 32x32}
|
||||||
|
- {<<: *icon, file: "mdi:cake-variant", id: mark_birthday, resize: 18x18}
|
||||||
|
- {<<: *icon, file: "mdi:trash-can", id: mark_waste, resize: 18x18}
|
||||||
|
|
||||||
|
font:
|
||||||
|
- file: "gfonts://Roboto"
|
||||||
|
id: font_title
|
||||||
|
size: 48
|
||||||
|
- file: "gfonts://Roboto"
|
||||||
|
id: font_status
|
||||||
|
size: 28
|
||||||
|
glyphs: &sk_glyphs "ÁÄČĎÉÍĹĽŇÓÔŔŠŤÚÝŽáäčďéíĺľňóôŕšťúýž°·"
|
||||||
|
glyphsets: [GF_Latin_Kernel]
|
||||||
|
- file: "gfonts://Roboto"
|
||||||
|
id: font_small
|
||||||
|
size: 24
|
||||||
|
glyphs: *sk_glyphs
|
||||||
|
glyphsets: [GF_Latin_Kernel]
|
||||||
|
- file: "gfonts://Roboto"
|
||||||
|
id: font_footer
|
||||||
|
size: 18
|
||||||
|
glyphs: "0123456789abcdef:. "
|
||||||
|
- file: "gfonts://Roboto@500"
|
||||||
|
id: font_date
|
||||||
|
size: 34
|
||||||
|
glyphs: *sk_glyphs
|
||||||
|
glyphsets: [GF_Latin_Kernel]
|
||||||
|
|
||||||
|
color:
|
||||||
|
- id: ink
|
||||||
|
red: 0%
|
||||||
|
green: 0%
|
||||||
|
blue: 0%
|
||||||
|
- id: paper
|
||||||
|
red: 100%
|
||||||
|
green: 100%
|
||||||
|
blue: 100%
|
||||||
|
|
||||||
|
display:
|
||||||
|
- platform: it8951
|
||||||
|
id: m5paper_display
|
||||||
|
model: m5stack-m5paper
|
||||||
|
rotation: 270
|
||||||
|
update_interval: never
|
||||||
|
# 1bpp: updates use the fast DU waveform, full GC16 refresh every 30 updates
|
||||||
|
grayscale: false
|
||||||
|
dithering: false
|
||||||
|
lambda: |-
|
||||||
|
// 540x960 portrait
|
||||||
|
it.fill(id(paper));
|
||||||
|
const int w = it.get_width();
|
||||||
|
const int cx = w / 2;
|
||||||
|
const float batt = id(battery_level).state;
|
||||||
|
|
||||||
|
// status screen after power-on, until Home Assistant connects
|
||||||
|
if (id(show_status) && !id(calendar_page)) {
|
||||||
|
it.image(cx, 200, id(esphome_logo), ImageAlign::CENTER);
|
||||||
|
it.print(cx, 320, id(font_title), id(ink), TextAlign::CENTER, "${name}");
|
||||||
|
|
||||||
|
const bool wifi_ok = wifi::global_wifi_component->is_connected();
|
||||||
|
if (wifi_ok) {
|
||||||
|
it.printf(40, 440, id(font_status), id(ink), "WiFi: connected (%d dBm)", wifi::global_wifi_component->wifi_rssi());
|
||||||
|
// IPv6 first (skip link-local), then IPv4
|
||||||
|
int y = 484;
|
||||||
|
char buf[network::IP_ADDRESS_BUFFER_SIZE];
|
||||||
|
for (bool v6 : {true, false}) {
|
||||||
|
for (auto &ip : wifi::global_wifi_component->get_ip_addresses()) {
|
||||||
|
if (!ip.is_set() || ip.is_ip6() != v6 || y > 590)
|
||||||
|
continue;
|
||||||
|
ip.str_to(buf);
|
||||||
|
if (v6 && strncmp(buf, "fe80", 4) == 0)
|
||||||
|
continue;
|
||||||
|
it.print(60, y, id(font_small), id(ink), buf);
|
||||||
|
y += 34;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
it.print(40, 440, id(font_status), id(ink), "WiFi: connecting...");
|
||||||
|
}
|
||||||
|
const bool api_ok = api::global_api_server->is_connected_with_state_subscription();
|
||||||
|
it.print(40, 620, id(font_status), id(ink),
|
||||||
|
api_ok ? "Home Assistant: connected" : "Home Assistant: waiting...");
|
||||||
|
if (!std::isnan(batt))
|
||||||
|
it.printf(40, 670, id(font_status), id(ink), "Battery: %.0f%% (%.2f V)", batt, id(battery_voltage).state);
|
||||||
|
it.printf(40, 720, id(font_status), id(ink), "Calendar: %u events stored", m5paper_calendar::events().count);
|
||||||
|
it.printf(40, 900, id(font_small), id(ink), "ESPHome %s", ESPHOME_VERSION);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calendar screen
|
||||||
|
using namespace m5paper_calendar;
|
||||||
|
image::Image *icons[] = {id(icon_birthday), id(icon_waste)};
|
||||||
|
image::Image *marks[] = {id(mark_birthday), id(mark_waste)};
|
||||||
|
static const char *const DAYS[] = {"Pondelok", "Utorok", "Streda", "Štvrtok", "Piatok", "Sobota", "Nedeľa"};
|
||||||
|
static const char *const DAYS_SHORT[] = {"Po", "Ut", "St", "Št", "Pi", "So", "Ne"};
|
||||||
|
static const char *const MONTHS[] = {"Január", "Február", "Marec", "Apríl", "Máj", "Jún",
|
||||||
|
"Júl", "August", "September", "Október", "November", "December"};
|
||||||
|
|
||||||
|
const auto &ev = m5paper_calendar::events();
|
||||||
|
const auto now = id(rtc_time).now();
|
||||||
|
if (!now.is_valid()) {
|
||||||
|
it.print(cx, 400, id(font_status), id(ink), TextAlign::CENTER, "Čas nie je k dispozícii");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const int32_t today = local_day(now);
|
||||||
|
|
||||||
|
// header: date, battery
|
||||||
|
it.printf(24, 16, id(font_date), id(ink), "%s %d. %d.", DAYS[weekday(today)], now.day_of_month, now.month);
|
||||||
|
if (!std::isnan(batt))
|
||||||
|
it.printf(w - 24, 22, id(font_small), id(ink), TextAlign::TOP_RIGHT, "%.0f %%", batt);
|
||||||
|
|
||||||
|
// month grid; days with events get the icons of their kinds
|
||||||
|
const int32_t first = days_from_civil(now.year, now.month, 1);
|
||||||
|
const int32_t next = now.month == 12 ? days_from_civil(now.year + 1, 1, 1) : days_from_civil(now.year, now.month + 1, 1);
|
||||||
|
const int dim = next - first, lead = weekday(first);
|
||||||
|
uint8_t kinds[32] = {};
|
||||||
|
for (int i = 0; i < ev.count; i++) {
|
||||||
|
if (ev.items[i].day >= first && ev.items[i].day < next)
|
||||||
|
kinds[ev.items[i].day - first + 1] |= 1 << ev.items[i].kind;
|
||||||
|
}
|
||||||
|
const int col_w = 70, row_h = 54, gx = (w - 7 * col_w) / 2, gy = 150;
|
||||||
|
it.printf(cx, 70, id(font_status), id(ink), TextAlign::TOP_CENTER, "%s %d", MONTHS[now.month - 1], now.year);
|
||||||
|
for (int c = 0; c < 7; c++)
|
||||||
|
it.print(gx + c * col_w + col_w / 2, 116, id(font_small), id(ink), TextAlign::TOP_CENTER, DAYS_SHORT[c]);
|
||||||
|
for (int d = 1; d <= dim; d++) {
|
||||||
|
const int cell = lead + d - 1;
|
||||||
|
const int x = gx + (cell % 7) * col_w, y = gy + (cell / 7) * row_h;
|
||||||
|
const bool is_today = first + d - 1 == today;
|
||||||
|
if (is_today)
|
||||||
|
it.filled_rectangle(x + 3, y + 1, col_w - 6, row_h - 2, id(ink));
|
||||||
|
const Color fg = is_today ? id(paper) : id(ink);
|
||||||
|
it.printf(x + col_w / 2, y + 4, id(font_small), fg, TextAlign::TOP_CENTER, "%d", d);
|
||||||
|
const int n = __builtin_popcount(kinds[d]);
|
||||||
|
int mx = x + (col_w - n * 20) / 2;
|
||||||
|
for (int k = 0; k < 2; k++) {
|
||||||
|
if (kinds[d] & (1 << k)) {
|
||||||
|
it.image(mx, y + 32, marks[k], fg);
|
||||||
|
mx += 20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// next 14 days; waste collection today or tomorrow is inverted: put the bin out
|
||||||
|
const int top = 490, list_h = 50, max_rows = 8;
|
||||||
|
it.horizontal_line(24, top - 12, w - 48, id(ink));
|
||||||
|
int rows = 0, more = 0;
|
||||||
|
for (int i = 0; i < ev.count; i++) {
|
||||||
|
const Event &e = ev.items[i];
|
||||||
|
if (e.day < today || e.day >= today + 14)
|
||||||
|
continue;
|
||||||
|
if (rows == max_rows) {
|
||||||
|
more++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const int y = top + rows++ * list_h;
|
||||||
|
const bool urgent = e.kind == WASTE && e.day <= today + 1;
|
||||||
|
if (urgent)
|
||||||
|
it.filled_rectangle(16, y, w - 32, list_h - 4, id(ink));
|
||||||
|
const Color fg = urgent ? id(paper) : id(ink);
|
||||||
|
const int ty = y + (list_h - 4) / 2;
|
||||||
|
if (e.day == today)
|
||||||
|
it.print(28, ty, id(font_small), fg, TextAlign::CENTER_LEFT, "Dnes");
|
||||||
|
else if (e.day == today + 1)
|
||||||
|
it.print(28, ty, id(font_small), fg, TextAlign::CENTER_LEFT, "Zajtra");
|
||||||
|
else {
|
||||||
|
const auto t = ESPTime::from_epoch_local(uint32_t(e.day) * 86400 + 43200);
|
||||||
|
it.printf(28, ty, id(font_small), fg, TextAlign::CENTER_LEFT, "%s %d. %d.", DAYS_SHORT[weekday(e.day)],
|
||||||
|
t.day_of_month, t.month);
|
||||||
|
}
|
||||||
|
if (e.kind < 2)
|
||||||
|
it.image(150, ty - 16, icons[e.kind], fg);
|
||||||
|
it.start_clipping(194, y, w - 28, y + list_h);
|
||||||
|
if (e.minute == ALL_DAY)
|
||||||
|
it.print(194, ty, id(font_small), fg, TextAlign::CENTER_LEFT, e.summary);
|
||||||
|
else
|
||||||
|
it.printf(194, ty, id(font_small), fg, TextAlign::CENTER_LEFT, "%02d:%02d %s", e.minute / 60, e.minute % 60,
|
||||||
|
e.summary);
|
||||||
|
it.end_clipping();
|
||||||
|
}
|
||||||
|
if (!ev.valid())
|
||||||
|
it.print(cx, top + 20, id(font_small), id(ink), TextAlign::TOP_CENTER, "Kalendár nie je k dispozícii");
|
||||||
|
else if (rows == 0)
|
||||||
|
it.print(cx, top + 20, id(font_small), id(ink), TextAlign::TOP_CENTER, "Žiadne udalosti v najbližších 14 dňoch");
|
||||||
|
else if (more > 0)
|
||||||
|
it.printf(w - 28, top + rows * list_h, id(font_small), id(ink), TextAlign::TOP_RIGHT, "+%d ďalšie", more);
|
||||||
|
|
||||||
|
// footer: IPv6 address (only while WiFi is up), last download
|
||||||
|
it.horizontal_line(24, 910, w - 48, id(ink));
|
||||||
|
char buf[network::IP_ADDRESS_BUFFER_SIZE];
|
||||||
|
for (auto &ip : wifi::global_wifi_component->get_ip_addresses()) {
|
||||||
|
if (!ip.is_set() || !ip.is_ip6())
|
||||||
|
continue;
|
||||||
|
ip.str_to(buf);
|
||||||
|
if (strncmp(buf, "fe80", 4) != 0) {
|
||||||
|
it.print(24, 944, id(font_footer), id(ink), TextAlign::BOTTOM_LEFT, buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ev.valid()) {
|
||||||
|
const auto f = ESPTime::from_epoch_local(ev.fetched_at);
|
||||||
|
it.printf(w - 24, 944, id(font_footer), id(ink), TextAlign::BOTTOM_RIGHT, "%d. %d. %02d:%02d", f.day_of_month,
|
||||||
|
f.month, f.hour, f.minute);
|
||||||
|
}
|
||||||
|
|
||||||
|
touchscreen:
|
||||||
|
- platform: gt911
|
||||||
|
id: gt911_touchscreen
|
||||||
|
display: m5paper_display
|
||||||
|
# GPIO36 is input-only; INT is only driven as output when reset_pin is set
|
||||||
|
interrupt_pin:
|
||||||
|
number: GPIO36
|
||||||
|
mode:
|
||||||
|
input: true
|
||||||
|
output: false
|
||||||
+20
-18
@@ -1,4 +1,19 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack ATOM Lite
|
||||||
|
# Pinout:
|
||||||
|
# GPIO1 UART0 TX
|
||||||
|
# GPIO3 UART0 RX
|
||||||
|
# GPIO12 IR
|
||||||
|
# GPIO19 NC
|
||||||
|
# GPIO21 I2C1 SCL
|
||||||
|
# GPIO22 1-WIRE
|
||||||
|
# GPIO23 UART1 RX
|
||||||
|
# GPIO25 I2C1 SDA
|
||||||
|
# GPIO26 I2C0 SDA -> uart_modbus (uart rx_pin)
|
||||||
|
# GPIO27 NEO -> atom_led (status LED, common/status_led_atom.yaml)
|
||||||
|
# GPIO32 I2C0 SCL -> uart_modbus (uart tx_pin)
|
||||||
|
# GPIO33 UART1 TX
|
||||||
|
# GPIO39 BUTTON
|
||||||
substitutions:
|
substitutions:
|
||||||
device: mains-power
|
device: mains-power
|
||||||
name: Mains Power
|
name: Mains Power
|
||||||
@@ -22,25 +37,14 @@ esp32:
|
|||||||
variant: esp32
|
variant: esp32
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: gd
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
# PINOUTS: M5ATOM
|
status_led: !include common/status_led_atom.yaml
|
||||||
# IR G12
|
|
||||||
# NEO G27
|
|
||||||
# BUTTON G39
|
|
||||||
# I2C0 SDA G26
|
|
||||||
# I2C0 SCL G32
|
|
||||||
# I2C1 SDA G25
|
|
||||||
# I2C1 SCL G21
|
|
||||||
# UART0 RX G3
|
|
||||||
# UART0 TX G1
|
|
||||||
# UART1 RX G23
|
|
||||||
# UART1 TX G33
|
|
||||||
# 1-WIRE G22
|
|
||||||
# NC G19
|
|
||||||
|
|
||||||
modbus:
|
modbus:
|
||||||
uart_id: uart_modbus
|
uart_id: uart_modbus
|
||||||
@@ -228,9 +232,7 @@ button:
|
|||||||
- pzemac.reset_energy: pzemac_l3
|
- pzemac.reset_energy: pzemac_l3
|
||||||
|
|
||||||
time:
|
time:
|
||||||
- platform: homeassistant
|
- id: !extend ha_time
|
||||||
id: ha_time
|
|
||||||
timezone: Europe/Bratislava
|
|
||||||
on_time:
|
on_time:
|
||||||
- cron: '0 0 0 * * *'
|
- cron: '0 0 0 * * *'
|
||||||
then:
|
then:
|
||||||
|
|||||||
@@ -0,0 +1,185 @@
|
|||||||
|
---
|
||||||
|
# Hardware: Nordic nRF52840 DK
|
||||||
|
# Pinout:
|
||||||
|
# P0.06 UART0 TX -> logger (J-Link VCOM)
|
||||||
|
# P0.13 LED 1 (active low) -> ANT+ Connected (a configured device is received)
|
||||||
|
# P0.14 LED 2 (active low) -> ANT+ Unknown Device (an unconfigured one is in range)
|
||||||
|
# P1.01 UART1 RX <- mcu-nrf-dk UART1 TX (P1.02), packet_transport
|
||||||
|
# P1.02 UART1 TX -> mcu-nrf-dk UART1 RX (P1.01), packet_transport; plus GND
|
||||||
|
# Radio: ANT+ receiver (RadiANT), no network of its own; values go to mcu-nrf-dk
|
||||||
|
# ANT+ devices:
|
||||||
|
# 655730 Garmin HRM-Pro heart rate
|
||||||
|
# 498521 Concept2 PM5 (rower) fitness equipment (FE-C)
|
||||||
|
# 1044953 Garmin Tempe environment (temperature)
|
||||||
|
# 604693 Garmin Varia RTL515 bike radar, battery only
|
||||||
|
# 136052 Garmin HRM-Dual heart rate (pain cave)
|
||||||
|
# 334424 Garmin HRM-Tri heart rate (bike)
|
||||||
|
# 886796 Garmin Rally RS200 power + cadence
|
||||||
|
# 343922 Garmin Speed Sensor 2 speed
|
||||||
|
# 42898 SRAM Force AXS shifting (Cube Litening C:68X), battery only
|
||||||
|
esphome:
|
||||||
|
name: mcu-nrf-ant
|
||||||
|
friendly_name: nRF ANT+
|
||||||
|
|
||||||
|
# needs the esphomeplatformzephyr fork (esphome-zephyr); RadiANT needs NCS
|
||||||
|
zephyr:
|
||||||
|
variant: NRF52
|
||||||
|
board: nrf52840dk/nrf52840
|
||||||
|
framework:
|
||||||
|
type: ncs
|
||||||
|
|
||||||
|
logger:
|
||||||
|
hardware_uart: UART0
|
||||||
|
|
||||||
|
external_components:
|
||||||
|
- source: github://randybb/esphome-components
|
||||||
|
components: [ant_plus]
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: gpio
|
||||||
|
id: led_known
|
||||||
|
pin: {number: P0.13, inverted: true}
|
||||||
|
- platform: gpio
|
||||||
|
id: led_unknown
|
||||||
|
pin: {number: P0.14, inverted: true}
|
||||||
|
|
||||||
|
ant_plus:
|
||||||
|
network_key: !secret ant_plus_network_key
|
||||||
|
connected:
|
||||||
|
id: ant_connected
|
||||||
|
name: ANT+ Connected
|
||||||
|
on_press: {output.turn_on: led_known}
|
||||||
|
on_release: {output.turn_off: led_known}
|
||||||
|
unknown_device:
|
||||||
|
id: ant_unknown_device
|
||||||
|
name: ANT+ Unknown Device
|
||||||
|
on_press: {output.turn_on: led_unknown}
|
||||||
|
on_release: {output.turn_off: led_unknown}
|
||||||
|
devices:
|
||||||
|
- type: heart_rate # Garmin HRM-Pro
|
||||||
|
device_number: 655730
|
||||||
|
heart_rate:
|
||||||
|
id: hrm_pro_heart_rate
|
||||||
|
name: Garmin HRM-Pro Heart Rate
|
||||||
|
battery_level:
|
||||||
|
id: hrm_pro_battery
|
||||||
|
name: Garmin HRM-Pro Battery
|
||||||
|
- type: fitness_equipment # Concept2 PM5 (rower)
|
||||||
|
device_number: 498521
|
||||||
|
power:
|
||||||
|
id: pm5_power
|
||||||
|
name: Concept2 PM5 Power
|
||||||
|
cadence:
|
||||||
|
id: pm5_stroke_rate
|
||||||
|
name: Concept2 PM5 Stroke Rate
|
||||||
|
in_use:
|
||||||
|
id: pm5_in_use
|
||||||
|
name: Concept2 PM5 In Use
|
||||||
|
- type: temperature # Garmin Tempe
|
||||||
|
device_number: 1044953
|
||||||
|
temperature:
|
||||||
|
id: tempe_temperature
|
||||||
|
name: Garmin Tempe Temperature
|
||||||
|
temperature_min:
|
||||||
|
id: tempe_temperature_min
|
||||||
|
name: Garmin Tempe Temperature 24h Min
|
||||||
|
temperature_max:
|
||||||
|
id: tempe_temperature_max
|
||||||
|
name: Garmin Tempe Temperature 24h Max
|
||||||
|
battery_voltage:
|
||||||
|
id: tempe_battery
|
||||||
|
name: Garmin Tempe Battery
|
||||||
|
battery_low:
|
||||||
|
id: tempe_battery_low
|
||||||
|
name: Garmin Tempe Battery Low
|
||||||
|
- type: bike_radar # Garmin Varia RTL515
|
||||||
|
device_number: 604693
|
||||||
|
battery_voltage:
|
||||||
|
id: varia_battery
|
||||||
|
name: Garmin Varia RTL515 Battery
|
||||||
|
battery_low:
|
||||||
|
id: varia_battery_low
|
||||||
|
name: Garmin Varia RTL515 Battery Low
|
||||||
|
- type: heart_rate # Garmin HRM-Dual
|
||||||
|
device_number: 136052
|
||||||
|
heart_rate:
|
||||||
|
id: hrm_dual_heart_rate
|
||||||
|
name: Garmin HRM-Dual Heart Rate
|
||||||
|
battery_level:
|
||||||
|
id: hrm_dual_battery
|
||||||
|
name: Garmin HRM-Dual Battery
|
||||||
|
- type: heart_rate # Garmin HRM-Tri
|
||||||
|
device_number: 334424
|
||||||
|
heart_rate:
|
||||||
|
id: hrm_tri_heart_rate
|
||||||
|
name: Garmin HRM-Tri Heart Rate
|
||||||
|
battery_level:
|
||||||
|
id: hrm_tri_battery
|
||||||
|
name: Garmin HRM-Tri Battery
|
||||||
|
- type: power # Garmin Rally RS200 (a battery in each pedal)
|
||||||
|
device_number: 886796
|
||||||
|
power:
|
||||||
|
id: rally_power
|
||||||
|
name: Garmin Rally RS200 Power
|
||||||
|
cadence:
|
||||||
|
id: rally_cadence
|
||||||
|
name: Garmin Rally RS200 Cadence
|
||||||
|
battery_low:
|
||||||
|
id: rally_battery_low
|
||||||
|
name: Garmin Rally RS200 Battery Low
|
||||||
|
- type: speed # Garmin Speed Sensor 2
|
||||||
|
device_number: 343922
|
||||||
|
speed:
|
||||||
|
id: speed2_speed
|
||||||
|
name: Garmin Speed Sensor 2 Speed
|
||||||
|
battery_voltage:
|
||||||
|
id: speed2_battery
|
||||||
|
name: Garmin Speed Sensor 2 Battery
|
||||||
|
battery_low:
|
||||||
|
id: speed2_battery_low
|
||||||
|
name: Garmin Speed Sensor 2 Battery Low
|
||||||
|
- type: shifting # SRAM Force AXS (Cube Litening C:68X)
|
||||||
|
device_number: 42898
|
||||||
|
battery_low:
|
||||||
|
id: sram_battery_low
|
||||||
|
name: SRAM Force AXS Battery Low
|
||||||
|
|
||||||
|
uart:
|
||||||
|
id: link
|
||||||
|
port: UART1
|
||||||
|
# the DK's default UART1 pins, same on both boards, wires crossed
|
||||||
|
tx_pin: P1.02
|
||||||
|
rx_pin: P1.01
|
||||||
|
baud_rate: 115200
|
||||||
|
|
||||||
|
packet_transport:
|
||||||
|
- platform: uart
|
||||||
|
uart_id: link
|
||||||
|
update_interval: 1s
|
||||||
|
sensors:
|
||||||
|
- hrm_pro_heart_rate
|
||||||
|
- hrm_pro_battery
|
||||||
|
- pm5_power
|
||||||
|
- pm5_stroke_rate
|
||||||
|
- tempe_temperature
|
||||||
|
- tempe_temperature_min
|
||||||
|
- tempe_temperature_max
|
||||||
|
- tempe_battery
|
||||||
|
- varia_battery
|
||||||
|
- hrm_dual_heart_rate
|
||||||
|
- hrm_dual_battery
|
||||||
|
- hrm_tri_heart_rate
|
||||||
|
- hrm_tri_battery
|
||||||
|
- rally_power
|
||||||
|
- rally_cadence
|
||||||
|
- speed2_speed
|
||||||
|
- speed2_battery
|
||||||
|
binary_sensors:
|
||||||
|
- ant_connected
|
||||||
|
- ant_unknown_device
|
||||||
|
- pm5_in_use
|
||||||
|
- tempe_battery_low
|
||||||
|
- varia_battery_low
|
||||||
|
- rally_battery_low
|
||||||
|
- speed2_battery_low
|
||||||
|
- sram_battery_low
|
||||||
+290
-5
@@ -1,11 +1,296 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Nordic nRF52840 DK
|
||||||
|
# Pinout:
|
||||||
|
# P0.11 Button 1 (active low) -> Button 1 (binary_sensor gpio)
|
||||||
|
# P0.12 Button 2 (active low) -> Button 2 (binary_sensor gpio)
|
||||||
|
# P0.13 LED 1 (active low) -> LED 1 (light binary)
|
||||||
|
# P0.14 LED 2 (active low) -> LED 2 (light binary)
|
||||||
|
# P0.15 LED 3 (active low) -> LED 3 (light binary)
|
||||||
|
# P0.16 LED 4 (active low) -> LED 4 (light binary)
|
||||||
|
# P0.24 Button 3 (active low) -> Button 3 (binary_sensor gpio)
|
||||||
|
# P0.25 Button 4 (active low) -> Button 4 (binary_sensor gpio)
|
||||||
|
# P1.01 UART1 RX <- mcu-nrf-ant UART1 TX (P1.02), packet_transport; plus GND
|
||||||
|
# P1.02 UART1 TX -> mcu-nrf-ant UART1 RX (P1.01), packet_transport
|
||||||
|
# ANT+ values (Garmin HRM-Pro, Concept2 PM5, Garmin Tempe, Garmin Varia RTL515) come from mcu-nrf-ant
|
||||||
esphome:
|
esphome:
|
||||||
name: mcu-nrf-dk
|
name: mcu-nrf-dk
|
||||||
friendly_name: mcu-nrf-dk
|
friendly_name: nRF DK
|
||||||
|
|
||||||
nrf52:
|
# needs the esphomeplatformzephyr fork (esphome-zephyr), upstream has no zephyr: platform yet
|
||||||
board: nrf52840_dk
|
zephyr:
|
||||||
bootloader: adafruit_nrf52_sd140_v7
|
variant: NRF52
|
||||||
|
board: nrf52840dk/nrf52840
|
||||||
|
framework:
|
||||||
|
type: zephyr
|
||||||
|
|
||||||
# Enable logging
|
|
||||||
logger:
|
logger:
|
||||||
|
|
||||||
|
network:
|
||||||
|
enable_ipv6: true
|
||||||
|
|
||||||
|
# Active dataset of the Thread network (HA: Settings > Thread > ... > dataset TLV)
|
||||||
|
openthread:
|
||||||
|
tlv: !secret thread_tlv
|
||||||
|
# end device, doesn't route for others; saves flash (FTD fills the MCUboot slot)
|
||||||
|
device_type: MTD
|
||||||
|
|
||||||
|
api:
|
||||||
|
encryption:
|
||||||
|
key: !secret api_key
|
||||||
|
|
||||||
|
# ANT+ values from mcu-nrf-ant (second nRF52840 DK) over UART
|
||||||
|
uart:
|
||||||
|
id: ant_link
|
||||||
|
port: UART1
|
||||||
|
# the DK's default UART1 pins, same on both boards, wires crossed
|
||||||
|
rx_pin: P1.01
|
||||||
|
tx_pin: P1.02
|
||||||
|
baud_rate: 115200
|
||||||
|
|
||||||
|
packet_transport:
|
||||||
|
- platform: uart
|
||||||
|
uart_id: ant_link
|
||||||
|
providers:
|
||||||
|
- name: mcu-nrf-ant
|
||||||
|
|
||||||
|
sensor:
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: hrm_pro_heart_rate
|
||||||
|
name: Garmin HRM-Pro Heart Rate
|
||||||
|
internal: false
|
||||||
|
unit_of_measurement: bpm
|
||||||
|
icon: mdi:heart-pulse
|
||||||
|
filters:
|
||||||
|
- throttle: 1s
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: hrm_pro_battery
|
||||||
|
name: Garmin HRM-Pro Battery
|
||||||
|
internal: false
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
device_class: battery
|
||||||
|
entity_category: diagnostic
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: pm5_power
|
||||||
|
name: Concept2 PM5 Power
|
||||||
|
internal: false
|
||||||
|
unit_of_measurement: W
|
||||||
|
device_class: power
|
||||||
|
filters:
|
||||||
|
- throttle: 1s
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: pm5_stroke_rate
|
||||||
|
name: Concept2 PM5 Stroke Rate
|
||||||
|
internal: false
|
||||||
|
unit_of_measurement: spm
|
||||||
|
icon: mdi:rowing
|
||||||
|
filters:
|
||||||
|
- throttle: 1s
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: tempe_temperature
|
||||||
|
name: Garmin Tempe Temperature
|
||||||
|
internal: false
|
||||||
|
unit_of_measurement: °C
|
||||||
|
device_class: temperature
|
||||||
|
accuracy_decimals: 1
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: tempe_temperature_min
|
||||||
|
name: Garmin Tempe Temperature 24h Min
|
||||||
|
internal: false
|
||||||
|
unit_of_measurement: °C
|
||||||
|
device_class: temperature
|
||||||
|
accuracy_decimals: 1
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: tempe_temperature_max
|
||||||
|
name: Garmin Tempe Temperature 24h Max
|
||||||
|
internal: false
|
||||||
|
unit_of_measurement: °C
|
||||||
|
device_class: temperature
|
||||||
|
accuracy_decimals: 1
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: tempe_battery
|
||||||
|
name: Garmin Tempe Battery
|
||||||
|
internal: false
|
||||||
|
unit_of_measurement: V
|
||||||
|
device_class: voltage
|
||||||
|
accuracy_decimals: 2
|
||||||
|
entity_category: diagnostic
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: varia_battery
|
||||||
|
name: Garmin Varia RTL515 Battery
|
||||||
|
internal: false
|
||||||
|
unit_of_measurement: V
|
||||||
|
device_class: voltage
|
||||||
|
accuracy_decimals: 2
|
||||||
|
entity_category: diagnostic
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: hrm_dual_heart_rate
|
||||||
|
name: Garmin HRM-Dual Heart Rate
|
||||||
|
internal: false
|
||||||
|
unit_of_measurement: bpm
|
||||||
|
icon: mdi:heart-pulse
|
||||||
|
filters:
|
||||||
|
- throttle: 1s
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: hrm_dual_battery
|
||||||
|
name: Garmin HRM-Dual Battery
|
||||||
|
internal: false
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
device_class: battery
|
||||||
|
entity_category: diagnostic
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: hrm_tri_heart_rate
|
||||||
|
name: Garmin HRM-Tri Heart Rate
|
||||||
|
internal: false
|
||||||
|
unit_of_measurement: bpm
|
||||||
|
icon: mdi:heart-pulse
|
||||||
|
filters:
|
||||||
|
- throttle: 1s
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: hrm_tri_battery
|
||||||
|
name: Garmin HRM-Tri Battery
|
||||||
|
internal: false
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
device_class: battery
|
||||||
|
entity_category: diagnostic
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: rally_power
|
||||||
|
name: Garmin Rally RS200 Power
|
||||||
|
internal: false
|
||||||
|
unit_of_measurement: W
|
||||||
|
device_class: power
|
||||||
|
filters:
|
||||||
|
- throttle: 1s
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: rally_cadence
|
||||||
|
name: Garmin Rally RS200 Cadence
|
||||||
|
internal: false
|
||||||
|
unit_of_measurement: rpm
|
||||||
|
icon: mdi:rotate-right
|
||||||
|
filters:
|
||||||
|
- throttle: 1s
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: speed2_speed
|
||||||
|
name: Garmin Speed Sensor 2 Speed
|
||||||
|
internal: false
|
||||||
|
unit_of_measurement: m/s
|
||||||
|
device_class: speed
|
||||||
|
accuracy_decimals: 2
|
||||||
|
filters:
|
||||||
|
- throttle: 1s
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: speed2_battery
|
||||||
|
name: Garmin Speed Sensor 2 Battery
|
||||||
|
internal: false
|
||||||
|
unit_of_measurement: V
|
||||||
|
device_class: voltage
|
||||||
|
accuracy_decimals: 2
|
||||||
|
entity_category: diagnostic
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: gpio
|
||||||
|
id: led_1_out
|
||||||
|
pin: {number: P0.13, inverted: true}
|
||||||
|
- platform: gpio
|
||||||
|
id: led_2_out
|
||||||
|
pin: {number: P0.14, inverted: true}
|
||||||
|
- platform: gpio
|
||||||
|
id: led_3_out
|
||||||
|
pin: {number: P0.15, inverted: true}
|
||||||
|
- platform: gpio
|
||||||
|
id: led_4_out
|
||||||
|
pin: {number: P0.16, inverted: true}
|
||||||
|
|
||||||
|
light:
|
||||||
|
- {platform: binary, name: LED 1, id: led_1, output: led_1_out}
|
||||||
|
- {platform: binary, name: LED 2, id: led_2, output: led_2_out}
|
||||||
|
- {platform: binary, name: LED 3, id: led_3, output: led_3_out}
|
||||||
|
- {platform: binary, name: LED 4, id: led_4, output: led_4_out}
|
||||||
|
|
||||||
|
# each button toggles its LED locally and is visible in HA
|
||||||
|
binary_sensor:
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: ant_connected
|
||||||
|
name: ANT+ Connected
|
||||||
|
internal: false
|
||||||
|
device_class: connectivity
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: ant_unknown_device
|
||||||
|
name: ANT+ Unknown Device
|
||||||
|
internal: false
|
||||||
|
icon: mdi:access-point
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: pm5_in_use
|
||||||
|
name: Concept2 PM5 In Use
|
||||||
|
internal: false
|
||||||
|
device_class: running
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: tempe_battery_low
|
||||||
|
name: Garmin Tempe Battery Low
|
||||||
|
internal: false
|
||||||
|
device_class: battery
|
||||||
|
entity_category: diagnostic
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: varia_battery_low
|
||||||
|
name: Garmin Varia RTL515 Battery Low
|
||||||
|
internal: false
|
||||||
|
device_class: battery
|
||||||
|
entity_category: diagnostic
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: rally_battery_low
|
||||||
|
name: Garmin Rally RS200 Battery Low
|
||||||
|
internal: false
|
||||||
|
device_class: battery
|
||||||
|
entity_category: diagnostic
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: speed2_battery_low
|
||||||
|
name: Garmin Speed Sensor 2 Battery Low
|
||||||
|
internal: false
|
||||||
|
device_class: battery
|
||||||
|
entity_category: diagnostic
|
||||||
|
- platform: packet_transport
|
||||||
|
provider: mcu-nrf-ant
|
||||||
|
remote_id: sram_battery_low
|
||||||
|
name: SRAM Force AXS Battery Low
|
||||||
|
internal: false
|
||||||
|
device_class: battery
|
||||||
|
entity_category: diagnostic
|
||||||
|
- platform: gpio
|
||||||
|
name: Button 1
|
||||||
|
pin: {number: P0.11, inverted: true, mode: {input: true, pullup: true}}
|
||||||
|
on_press: {light.toggle: led_1}
|
||||||
|
- platform: gpio
|
||||||
|
name: Button 2
|
||||||
|
pin: {number: P0.12, inverted: true, mode: {input: true, pullup: true}}
|
||||||
|
on_press: {light.toggle: led_2}
|
||||||
|
- platform: gpio
|
||||||
|
name: Button 3
|
||||||
|
pin: {number: P0.24, inverted: true, mode: {input: true, pullup: true}}
|
||||||
|
on_press: {light.toggle: led_3}
|
||||||
|
- platform: gpio
|
||||||
|
name: Button 4
|
||||||
|
pin: {number: P0.25, inverted: true, mode: {input: true, pullup: true}}
|
||||||
|
on_press: {light.toggle: led_4}
|
||||||
+29
-167
@@ -1,4 +1,18 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Sonoff NSPanel (EU)
|
||||||
|
# Pinout:
|
||||||
|
# GPIO2 IO2
|
||||||
|
# GPIO4 Screen power -> Screen Power (switch gpio) (inverted)
|
||||||
|
# GPIO14 Left button -> Left Button (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO16 Display UART TX -> display_uart (uart tx_pin)
|
||||||
|
# GPIO17 Display UART RX -> display_uart (uart rx_pin)
|
||||||
|
# GPIO19 Relay 2
|
||||||
|
# GPIO21 Buzzer -> buzzer_out (output ledc)
|
||||||
|
# GPIO22 Relay 1 -> relay_1 (output gpio)
|
||||||
|
# GPIO23 Relay 3 (no relay, connector)
|
||||||
|
# GPIO27 Right button -> Right Button (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO37 ALS (light sensor)
|
||||||
|
# GPIO38 NTC temperature (ADC) -> ntc_source (sensor adc)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: nspanel-bedroom
|
device: nspanel-bedroom
|
||||||
name: Bedroom NSPanel
|
name: Bedroom NSPanel
|
||||||
@@ -11,103 +25,20 @@ esphome:
|
|||||||
friendly_name: ${name}
|
friendly_name: ${name}
|
||||||
area: ${area}
|
area: ${area}
|
||||||
comment: ${comment}
|
comment: ${comment}
|
||||||
on_boot:
|
|
||||||
then:
|
|
||||||
- switch.turn_off: screen_power
|
|
||||||
- delay: 1s
|
|
||||||
- switch.turn_on: screen_power
|
|
||||||
- delay: 2s
|
|
||||||
- lambda: 'id(nspanel_id).set_display_dim(5, 80);'
|
|
||||||
|
|
||||||
esp32:
|
|
||||||
variant: esp32
|
|
||||||
toolchain: esp-idf
|
|
||||||
framework:
|
|
||||||
type: esp-idf
|
|
||||||
advanced:
|
|
||||||
minimum_chip_revision: 3.0
|
|
||||||
sram1_as_iram: true
|
|
||||||
|
|
||||||
external_components:
|
|
||||||
- source:
|
|
||||||
type: git
|
|
||||||
url: https://github.com/randybb/esphome-nspanel-lovelace-native
|
|
||||||
ref: devices
|
|
||||||
refresh: 0s
|
|
||||||
components: [nspanel_lovelace]
|
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
script:
|
nspanel: !include
|
||||||
- id: apply_sleep_dim
|
file: common/nspanel.yaml
|
||||||
then:
|
vars:
|
||||||
- lambda: |-
|
temperature_entity: sensor.zigbee_bedroom_temperature
|
||||||
uint8_t dim;
|
sleep_dim: !include
|
||||||
if (id(bedroom_lights).state) dim = 5; // sleepOverride
|
file: common/nspanel_sleep_dim.yaml
|
||||||
else if (id(sun_id).is_above_horizon(-6)) dim = 5; // day
|
vars:
|
||||||
else dim = 0; // night
|
sleep_override_entity: light.bedroom_lights
|
||||||
id(nspanel_id).set_display_inactive_dim(dim);
|
|
||||||
|
|
||||||
api:
|
|
||||||
homeassistant_services: true
|
|
||||||
homeassistant_states: true
|
|
||||||
actions:
|
|
||||||
- action: play_rtttl
|
|
||||||
variables:
|
|
||||||
song: string
|
|
||||||
then:
|
|
||||||
- rtttl.play:
|
|
||||||
rtttl: !lambda 'return song;'
|
|
||||||
|
|
||||||
- action: notify
|
|
||||||
variables:
|
|
||||||
heading: string
|
|
||||||
message: string
|
|
||||||
song: string
|
|
||||||
then:
|
|
||||||
- lambda: 'id(nspanel_id).notify_on_screensaver(heading, message, 10000);'
|
|
||||||
- rtttl.play:
|
|
||||||
rtttl: !lambda 'return song;'
|
|
||||||
|
|
||||||
- action: notify_fullscreen
|
|
||||||
variables:
|
|
||||||
title: string
|
|
||||||
description: string
|
|
||||||
button1: string
|
|
||||||
button2: string
|
|
||||||
timeout: int
|
|
||||||
icon: string
|
|
||||||
then:
|
|
||||||
- lambda: 'id(nspanel_id).notify_on_screensaver(title, description, timeout);'
|
|
||||||
- rtttl.play: "scale_up:d=32,o=5,b=100:c,c#,d#,e,f#,g#,a#,b"
|
|
||||||
|
|
||||||
uart:
|
|
||||||
id: display_uart
|
|
||||||
tx_pin: 16
|
|
||||||
rx_pin: 17
|
|
||||||
baud_rate: 115200
|
|
||||||
|
|
||||||
nspanel_lovelace:
|
nspanel_lovelace:
|
||||||
id: nspanel_id
|
|
||||||
sleep_timeout: 10
|
|
||||||
experimental_vertical_ui: true
|
|
||||||
locale:
|
|
||||||
language: sk
|
|
||||||
temperature_unit: celcius
|
|
||||||
screensaver:
|
|
||||||
time_id: ha_time
|
|
||||||
time_format: '%H:%M'
|
|
||||||
date_format: '%A, %d. %b. %Y'
|
|
||||||
weather:
|
|
||||||
entity_id: sensor.weather_forecast_daily
|
|
||||||
icon_color: [255, 255, 255]
|
|
||||||
entities:
|
|
||||||
- entity_id: sensor.zigbee_bedroom_temperature
|
|
||||||
icon:
|
|
||||||
value: home-thermometer-outline
|
|
||||||
color: [255, 255, 255]
|
|
||||||
precision: 1
|
|
||||||
cards:
|
cards:
|
||||||
- type: cardGrid
|
- type: cardGrid
|
||||||
title: Spálňa
|
title: Spálňa
|
||||||
@@ -135,12 +66,12 @@ nspanel_lovelace:
|
|||||||
title: Kúrenie
|
title: Kúrenie
|
||||||
thermo_entity_id: climate.bt_trv_bedroom
|
thermo_entity_id: climate.bt_trv_bedroom
|
||||||
|
|
||||||
time:
|
- type: cardEntities
|
||||||
- platform: homeassistant
|
title: Info
|
||||||
id: ha_time
|
entities:
|
||||||
timezone: Europe/Bratislava
|
- name: Zariadenie
|
||||||
on_time_sync:
|
entity_id: button.bedroom_nspanel_info
|
||||||
- script.execute: apply_sleep_dim
|
icon: information-outline
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
@@ -166,12 +97,6 @@ binary_sensor:
|
|||||||
entity_id: light.bedroom_lamps
|
entity_id: light.bedroom_lamps
|
||||||
- lambda: 'id(nspanel_id).render_default_page();'
|
- lambda: 'id(nspanel_id).render_default_page();'
|
||||||
|
|
||||||
- platform: homeassistant # sleepOverride
|
|
||||||
id: bedroom_lights
|
|
||||||
entity_id: light.bedroom_lights
|
|
||||||
on_state:
|
|
||||||
- script.execute: apply_sleep_dim
|
|
||||||
|
|
||||||
light:
|
light:
|
||||||
- platform: binary
|
- platform: binary
|
||||||
name: Light
|
name: Light
|
||||||
@@ -179,10 +104,6 @@ light:
|
|||||||
output: relay_1
|
output: relay_1
|
||||||
|
|
||||||
output:
|
output:
|
||||||
- platform: ledc
|
|
||||||
id: buzzer_out
|
|
||||||
pin:
|
|
||||||
number: 21
|
|
||||||
- id: relay_1
|
- id: relay_1
|
||||||
platform: gpio
|
platform: gpio
|
||||||
pin:
|
pin:
|
||||||
@@ -191,62 +112,3 @@ output:
|
|||||||
# platform: gpio
|
# platform: gpio
|
||||||
# pin:
|
# pin:
|
||||||
# number: 19
|
# number: 19
|
||||||
|
|
||||||
sun:
|
|
||||||
id: sun_id
|
|
||||||
time_id: ha_time
|
|
||||||
latitude: 48.15°
|
|
||||||
longitude: 17.11°
|
|
||||||
on_sunrise:
|
|
||||||
- elevation: -6°
|
|
||||||
then:
|
|
||||||
- script.execute: apply_sleep_dim
|
|
||||||
on_sunset:
|
|
||||||
- elevation: -6°
|
|
||||||
then:
|
|
||||||
- script.execute: apply_sleep_dim
|
|
||||||
|
|
||||||
switch:
|
|
||||||
- platform: gpio
|
|
||||||
name: Screen Power
|
|
||||||
id: screen_power
|
|
||||||
entity_category: config
|
|
||||||
pin:
|
|
||||||
number: 4
|
|
||||||
inverted: true
|
|
||||||
restore_mode: ALWAYS_ON
|
|
||||||
|
|
||||||
rtttl:
|
|
||||||
id: buzzer
|
|
||||||
output: buzzer_out
|
|
||||||
|
|
||||||
sensor:
|
|
||||||
- platform: adc
|
|
||||||
id: ntc_source
|
|
||||||
pin: 38
|
|
||||||
update_interval: 5min
|
|
||||||
attenuation: 12db
|
|
||||||
|
|
||||||
- platform: resistance
|
|
||||||
id: resistance_sensor
|
|
||||||
sensor: ntc_source
|
|
||||||
configuration: DOWNSTREAM
|
|
||||||
resistor: 11.2kOhm
|
|
||||||
|
|
||||||
- platform: ntc
|
|
||||||
name: Temperature
|
|
||||||
id: temperature
|
|
||||||
sensor: resistance_sensor
|
|
||||||
calibration:
|
|
||||||
b_constant: 3950
|
|
||||||
reference_temperature: 25°C
|
|
||||||
reference_resistance: 10kOhm
|
|
||||||
|
|
||||||
text_sensor:
|
|
||||||
- platform: homeassistant
|
|
||||||
id: name_day
|
|
||||||
entity_id: sensor.nameday_sk
|
|
||||||
on_value:
|
|
||||||
- lambda: |-
|
|
||||||
id(nspanel_id).set_time_format("%H:%M~" + x);
|
|
||||||
id(nspanel_id).update_time();
|
|
||||||
+24
-5
@@ -1,4 +1,18 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Sonoff NSPanel (EU)
|
||||||
|
# Pinout:
|
||||||
|
# GPIO2 IO2
|
||||||
|
# GPIO4 Screen power -> Screen Power (switch gpio) (inverted)
|
||||||
|
# GPIO14 Left button -> Left Button (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO16 Display UART TX -> display_uart (uart tx_pin)
|
||||||
|
# GPIO17 Display UART RX -> display_uart (uart rx_pin)
|
||||||
|
# GPIO19 Relay 2 -> Relay 2 (switch gpio)
|
||||||
|
# GPIO21 Buzzer -> buzzer_out (output ledc)
|
||||||
|
# GPIO22 Relay 1 -> Relay 1 (switch gpio)
|
||||||
|
# GPIO23 Relay 3 (no relay, connector)
|
||||||
|
# GPIO27 Right button -> Right Button (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO37 ALS (light sensor)
|
||||||
|
# GPIO38 NTC temperature (ADC) -> ntc_source (sensor adc)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: nspanel-dev
|
device: nspanel-dev
|
||||||
name: NSPanel DEV
|
name: NSPanel DEV
|
||||||
@@ -37,6 +51,7 @@ esp32:
|
|||||||
framework:
|
framework:
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
advanced:
|
advanced:
|
||||||
|
flash_chip: generic
|
||||||
minimum_chip_revision: 3.0
|
minimum_chip_revision: 3.0
|
||||||
sram1_as_iram: true
|
sram1_as_iram: true
|
||||||
|
|
||||||
@@ -59,6 +74,8 @@ external_components:
|
|||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
nspanel_popup: !include common/nspanel_popup.yaml
|
||||||
# common: !include common/common_dev.yaml
|
# common: !include common/common_dev.yaml
|
||||||
|
|
||||||
# web_server:
|
# web_server:
|
||||||
@@ -440,6 +457,13 @@ nspanel_lovelace:
|
|||||||
- name: Rast trávy
|
- name: Rast trávy
|
||||||
entity_id: automation.irrigation_grow_grass
|
entity_id: automation.irrigation_grow_grass
|
||||||
|
|
||||||
|
- type: cardEntities
|
||||||
|
title: Info
|
||||||
|
entities:
|
||||||
|
- name: Zariadenie
|
||||||
|
entity_id: button.nspanel_dev_info
|
||||||
|
icon: information-outline
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
name: Left Button
|
name: Left Button
|
||||||
@@ -540,11 +564,6 @@ sensor:
|
|||||||
- platform: template
|
- platform: template
|
||||||
id: room_temperature_id
|
id: room_temperature_id
|
||||||
|
|
||||||
time:
|
|
||||||
platform: homeassistant
|
|
||||||
id: ha_time
|
|
||||||
timezone: Europe/Bratislava
|
|
||||||
|
|
||||||
text_sensor:
|
text_sensor:
|
||||||
- platform: homeassistant
|
- platform: homeassistant
|
||||||
id: name_day
|
id: name_day
|
||||||
|
|||||||
+26
-135
@@ -1,4 +1,18 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Sonoff NSPanel (EU)
|
||||||
|
# Pinout:
|
||||||
|
# GPIO2 IO2
|
||||||
|
# GPIO4 Screen power -> Screen Power (switch gpio) (inverted)
|
||||||
|
# GPIO14 Left button -> Left Button (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO16 Display UART TX -> display_uart (uart tx_pin)
|
||||||
|
# GPIO17 Display UART RX -> display_uart (uart rx_pin)
|
||||||
|
# GPIO19 Relay 2 -> Dining Table Light MAIN (switch gpio)
|
||||||
|
# GPIO21 Buzzer -> buzzer_out (output ledc)
|
||||||
|
# GPIO22 Relay 1 -> Kitchen Worktop Light (switch gpio)
|
||||||
|
# GPIO23 Relay 3 (no relay, connector)
|
||||||
|
# GPIO27 Right button -> Right Button (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO37 ALS (light sensor)
|
||||||
|
# GPIO38 NTC temperature (ADC) -> ntc_source (sensor adc)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: nspanel-fireplace
|
device: nspanel-fireplace
|
||||||
name: Fireplace NSPanel
|
name: Fireplace NSPanel
|
||||||
@@ -10,93 +24,17 @@ esphome:
|
|||||||
friendly_name: ${name}
|
friendly_name: ${name}
|
||||||
area: ${area}
|
area: ${area}
|
||||||
comment: ${comment}
|
comment: ${comment}
|
||||||
on_boot:
|
|
||||||
then:
|
|
||||||
- switch.turn_off: screen_power
|
|
||||||
- delay: 1s
|
|
||||||
- switch.turn_on: screen_power
|
|
||||||
- delay: 2s
|
|
||||||
- lambda: 'id(nspanel_id).set_display_dim(5, 80);'
|
|
||||||
|
|
||||||
esp32:
|
|
||||||
variant: esp32
|
|
||||||
toolchain: esp-idf
|
|
||||||
framework:
|
|
||||||
type: esp-idf
|
|
||||||
advanced:
|
|
||||||
minimum_chip_revision: 3.0
|
|
||||||
sram1_as_iram: true
|
|
||||||
|
|
||||||
external_components:
|
|
||||||
- source:
|
|
||||||
type: git
|
|
||||||
url: https://github.com/randybb/esphome-nspanel-lovelace-native
|
|
||||||
ref: devices
|
|
||||||
refresh: 0s
|
|
||||||
components: [nspanel_lovelace]
|
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
api:
|
nspanel: !include
|
||||||
homeassistant_services: true
|
file: common/nspanel.yaml
|
||||||
homeassistant_states: true
|
vars:
|
||||||
actions:
|
temperature_entity: sensor.zigbee_living_room_kitchen_temperature
|
||||||
- action: play_rtttl
|
temperature_name: Living Room Temperature
|
||||||
variables:
|
|
||||||
song: string
|
|
||||||
then:
|
|
||||||
- rtttl.play:
|
|
||||||
rtttl: !lambda 'return song;'
|
|
||||||
|
|
||||||
- action: notify
|
|
||||||
variables:
|
|
||||||
heading: string
|
|
||||||
message: string
|
|
||||||
song: string
|
|
||||||
then:
|
|
||||||
- lambda: 'id(nspanel_id).notify_on_screensaver(heading, message, 10000);'
|
|
||||||
- rtttl.play:
|
|
||||||
rtttl: !lambda 'return song;'
|
|
||||||
|
|
||||||
- action: notify_fullscreen
|
|
||||||
variables:
|
|
||||||
title: string
|
|
||||||
description: string
|
|
||||||
button1: string
|
|
||||||
button2: string
|
|
||||||
timeout: int
|
|
||||||
icon: string
|
|
||||||
then:
|
|
||||||
- lambda: 'id(nspanel_id).notify_on_screensaver(title, description, timeout);'
|
|
||||||
- rtttl.play: "scale_up:d=32,o=5,b=100:c,c#,d#,e,f#,g#,a#,b"
|
|
||||||
|
|
||||||
uart:
|
|
||||||
id: display_uart
|
|
||||||
tx_pin: 16
|
|
||||||
rx_pin: 17
|
|
||||||
baud_rate: 115200
|
|
||||||
|
|
||||||
nspanel_lovelace:
|
nspanel_lovelace:
|
||||||
id: nspanel_id
|
|
||||||
sleep_timeout: 10
|
|
||||||
experimental_vertical_ui: true
|
|
||||||
locale:
|
|
||||||
language: sk
|
|
||||||
temperature_unit: celcius
|
|
||||||
screensaver:
|
|
||||||
time_id: ha_time
|
|
||||||
time_format: '%H:%M'
|
|
||||||
date_format: '%A, %d. %b. %Y'
|
|
||||||
weather:
|
|
||||||
entity_id: sensor.weather_forecast_daily
|
|
||||||
icon_color: [255, 255, 255]
|
|
||||||
entities:
|
|
||||||
- entity_id: sensor.zigbee_living_room_kitchen_temperature
|
|
||||||
icon:
|
|
||||||
value: home-thermometer-outline
|
|
||||||
color: [255, 255, 255]
|
|
||||||
precision: 1
|
|
||||||
cards:
|
cards:
|
||||||
- type: cardGrid
|
- type: cardGrid
|
||||||
title: Kuchyňa / Obývačka
|
title: Kuchyňa / Obývačka
|
||||||
@@ -185,10 +123,12 @@ nspanel_lovelace:
|
|||||||
- name: Auto-zatváranie
|
- name: Auto-zatváranie
|
||||||
entity_id: switch.gate_auto_close
|
entity_id: switch.gate_auto_close
|
||||||
|
|
||||||
time:
|
- type: cardEntities
|
||||||
- platform: homeassistant
|
title: Info
|
||||||
id: ha_time
|
entities:
|
||||||
timezone: Europe/Bratislava
|
- name: Zariadenie
|
||||||
|
entity_id: button.fireplace_nspanel_info
|
||||||
|
icon: information-outline
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
@@ -240,11 +180,6 @@ binary_sensor:
|
|||||||
entity_id: light.mcu_kitchen_stove
|
entity_id: light.mcu_kitchen_stove
|
||||||
- lambda: 'id(nspanel_id).render_default_page();'
|
- lambda: 'id(nspanel_id).render_default_page();'
|
||||||
- lambda: 'id(nspanel_id).render_next_page();'
|
- lambda: 'id(nspanel_id).render_next_page();'
|
||||||
output:
|
|
||||||
- platform: ledc
|
|
||||||
id: buzzer_out
|
|
||||||
pin:
|
|
||||||
number: 21
|
|
||||||
|
|
||||||
switch:
|
switch:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
@@ -259,47 +194,3 @@ switch:
|
|||||||
entity_category: config
|
entity_category: config
|
||||||
pin:
|
pin:
|
||||||
number: 19
|
number: 19
|
||||||
|
|
||||||
- platform: gpio
|
|
||||||
name: Screen Power
|
|
||||||
id: screen_power
|
|
||||||
entity_category: config
|
|
||||||
pin:
|
|
||||||
number: 4
|
|
||||||
inverted: true
|
|
||||||
restore_mode: ALWAYS_ON
|
|
||||||
|
|
||||||
rtttl:
|
|
||||||
id: buzzer
|
|
||||||
output: buzzer_out
|
|
||||||
|
|
||||||
sensor:
|
|
||||||
- platform: adc
|
|
||||||
id: ntc_source
|
|
||||||
pin: 38
|
|
||||||
update_interval: 5min
|
|
||||||
attenuation: 12db
|
|
||||||
|
|
||||||
- platform: resistance
|
|
||||||
id: resistance_sensor
|
|
||||||
sensor: ntc_source
|
|
||||||
configuration: DOWNSTREAM
|
|
||||||
resistor: 11.2kOhm
|
|
||||||
|
|
||||||
- platform: ntc
|
|
||||||
name: "Living Room Temperature"
|
|
||||||
id: temperature
|
|
||||||
sensor: resistance_sensor
|
|
||||||
calibration:
|
|
||||||
b_constant: 3950
|
|
||||||
reference_temperature: 25°C
|
|
||||||
reference_resistance: 10kOhm
|
|
||||||
|
|
||||||
text_sensor:
|
|
||||||
- platform: homeassistant
|
|
||||||
id: name_day
|
|
||||||
entity_id: sensor.nameday_sk
|
|
||||||
on_value:
|
|
||||||
- lambda: |-
|
|
||||||
id(nspanel_id).set_time_format("%H:%M~" + x);
|
|
||||||
id(nspanel_id).update_time();
|
|
||||||
+30
-136
@@ -1,4 +1,18 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Sonoff NSPanel (EU)
|
||||||
|
# Pinout:
|
||||||
|
# GPIO2 IO2
|
||||||
|
# GPIO4 Screen power -> Screen Power (switch gpio) (inverted)
|
||||||
|
# GPIO14 Left button -> Left Button (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO16 Display UART TX -> display_uart (uart tx_pin)
|
||||||
|
# GPIO17 Display UART RX -> display_uart (uart rx_pin)
|
||||||
|
# GPIO19 Relay 2
|
||||||
|
# GPIO21 Buzzer -> buzzer_out (output ledc)
|
||||||
|
# GPIO22 Relay 1 -> relay_1 (output gpio)
|
||||||
|
# GPIO23 Relay 3 (no relay, connector)
|
||||||
|
# GPIO27 Right button -> Right Button (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO37 ALS (light sensor)
|
||||||
|
# GPIO38 NTC temperature (ADC) -> ntc_source (sensor adc)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: nspanel-office-j
|
device: nspanel-office-j
|
||||||
name: Office J NSPanel
|
name: Office J NSPanel
|
||||||
@@ -10,93 +24,21 @@ esphome:
|
|||||||
friendly_name: ${name}
|
friendly_name: ${name}
|
||||||
area: ${area}
|
area: ${area}
|
||||||
comment: ${comment}
|
comment: ${comment}
|
||||||
on_boot:
|
|
||||||
then:
|
|
||||||
- switch.turn_off: screen_power
|
|
||||||
- delay: 1s
|
|
||||||
- switch.turn_on: screen_power
|
|
||||||
- delay: 2s
|
|
||||||
- lambda: 'id(nspanel_id).set_display_dim(5, 80);'
|
|
||||||
|
|
||||||
esp32:
|
|
||||||
variant: esp32
|
|
||||||
toolchain: esp-idf
|
|
||||||
framework:
|
|
||||||
type: esp-idf
|
|
||||||
advanced:
|
|
||||||
minimum_chip_revision: 3.0
|
|
||||||
sram1_as_iram: true
|
|
||||||
|
|
||||||
external_components:
|
|
||||||
- source:
|
|
||||||
type: git
|
|
||||||
url: https://github.com/randybb/esphome-nspanel-lovelace-native
|
|
||||||
ref: devices
|
|
||||||
refresh: 0s
|
|
||||||
components: [nspanel_lovelace]
|
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
api:
|
nspanel: !include
|
||||||
homeassistant_services: true
|
file: common/nspanel.yaml
|
||||||
homeassistant_states: true
|
vars:
|
||||||
actions:
|
temperature_entity: sensor.zigbee_office_j_temperature
|
||||||
- action: play_rtttl
|
ntc_reference_temperature: 22°C
|
||||||
variables:
|
sleep_dim: !include
|
||||||
song: string
|
file: common/nspanel_sleep_dim.yaml
|
||||||
then:
|
vars:
|
||||||
- rtttl.play:
|
sleep_override_entity: light.office_j_lights
|
||||||
rtttl: !lambda 'return song;'
|
|
||||||
|
|
||||||
- action: notify
|
|
||||||
variables:
|
|
||||||
heading: string
|
|
||||||
message: string
|
|
||||||
song: string
|
|
||||||
then:
|
|
||||||
- lambda: 'id(nspanel_id).notify_on_screensaver(heading, message, 10000);'
|
|
||||||
- rtttl.play:
|
|
||||||
rtttl: !lambda 'return song;'
|
|
||||||
|
|
||||||
- action: notify_fullscreen
|
|
||||||
variables:
|
|
||||||
title: string
|
|
||||||
description: string
|
|
||||||
button1: string
|
|
||||||
button2: string
|
|
||||||
timeout: int
|
|
||||||
icon: string
|
|
||||||
then:
|
|
||||||
- lambda: 'id(nspanel_id).notify_on_screensaver(title, description, timeout);'
|
|
||||||
- rtttl.play: "scale_up:d=32,o=5,b=100:c,c#,d#,e,f#,g#,a#,b"
|
|
||||||
|
|
||||||
uart:
|
|
||||||
id: display_uart
|
|
||||||
tx_pin: 16
|
|
||||||
rx_pin: 17
|
|
||||||
baud_rate: 115200
|
|
||||||
|
|
||||||
nspanel_lovelace:
|
nspanel_lovelace:
|
||||||
id: nspanel_id
|
|
||||||
sleep_timeout: 10
|
|
||||||
experimental_vertical_ui: true
|
|
||||||
locale:
|
|
||||||
language: sk
|
|
||||||
temperature_unit: celcius
|
|
||||||
screensaver:
|
|
||||||
time_id: ha_time
|
|
||||||
time_format: '%H:%M'
|
|
||||||
date_format: '%A, %d. %b. %Y'
|
|
||||||
weather:
|
|
||||||
entity_id: sensor.weather_forecast_daily
|
|
||||||
icon_color: [255, 255, 255]
|
|
||||||
entities:
|
|
||||||
- entity_id: sensor.zigbee_office_j_temperature
|
|
||||||
icon:
|
|
||||||
value: home-thermometer-outline
|
|
||||||
color: [255, 255, 255]
|
|
||||||
precision: 1
|
|
||||||
cards:
|
cards:
|
||||||
- type: cardGrid
|
- type: cardGrid
|
||||||
title: Janko
|
title: Janko
|
||||||
@@ -134,10 +76,12 @@ nspanel_lovelace:
|
|||||||
- name: Auto-zatváranie
|
- name: Auto-zatváranie
|
||||||
entity_id: switch.gate_auto_close
|
entity_id: switch.gate_auto_close
|
||||||
|
|
||||||
time:
|
- type: cardEntities
|
||||||
- platform: homeassistant
|
title: Info
|
||||||
id: ha_time
|
entities:
|
||||||
timezone: Europe/Bratislava
|
- name: Zariadenie
|
||||||
|
entity_id: button.office_j_nspanel_info
|
||||||
|
icon: information-outline
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
@@ -162,11 +106,6 @@ binary_sensor:
|
|||||||
- lambda: 'id(nspanel_id).render_default_page();'
|
- lambda: 'id(nspanel_id).render_default_page();'
|
||||||
|
|
||||||
output:
|
output:
|
||||||
- platform: ledc
|
|
||||||
id: buzzer_out
|
|
||||||
pin:
|
|
||||||
number: 21
|
|
||||||
|
|
||||||
- id: relay_1
|
- id: relay_1
|
||||||
platform: gpio
|
platform: gpio
|
||||||
pin:
|
pin:
|
||||||
@@ -185,48 +124,3 @@ light:
|
|||||||
# # - platform: binary
|
# # - platform: binary
|
||||||
# # name: Relay 2
|
# # name: Relay 2
|
||||||
# # output: relay_2
|
# # output: relay_2
|
||||||
|
|
||||||
switch:
|
|
||||||
- platform: gpio
|
|
||||||
name: Screen Power
|
|
||||||
id: screen_power
|
|
||||||
entity_category: config
|
|
||||||
pin:
|
|
||||||
number: 4
|
|
||||||
inverted: true
|
|
||||||
restore_mode: ALWAYS_ON
|
|
||||||
|
|
||||||
rtttl:
|
|
||||||
id: buzzer
|
|
||||||
output: buzzer_out
|
|
||||||
|
|
||||||
sensor:
|
|
||||||
- platform: adc
|
|
||||||
id: ntc_source
|
|
||||||
pin: 38
|
|
||||||
update_interval: 5min
|
|
||||||
attenuation: 12db
|
|
||||||
|
|
||||||
- platform: resistance
|
|
||||||
id: resistance_sensor
|
|
||||||
sensor: ntc_source
|
|
||||||
configuration: DOWNSTREAM
|
|
||||||
resistor: 11.2kOhm
|
|
||||||
|
|
||||||
- platform: ntc
|
|
||||||
name: Temperature
|
|
||||||
id: temperature
|
|
||||||
sensor: resistance_sensor
|
|
||||||
calibration:
|
|
||||||
b_constant: 3950
|
|
||||||
reference_temperature: 22°C
|
|
||||||
reference_resistance: 10kOhm
|
|
||||||
|
|
||||||
text_sensor:
|
|
||||||
- platform: homeassistant
|
|
||||||
id: name_day
|
|
||||||
entity_id: sensor.nameday_sk
|
|
||||||
on_value:
|
|
||||||
- lambda: |-
|
|
||||||
id(nspanel_id).set_time_format("%H:%M~" + x);
|
|
||||||
id(nspanel_id).update_time();
|
|
||||||
+27
-134
@@ -1,4 +1,18 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Sonoff NSPanel (EU)
|
||||||
|
# Pinout:
|
||||||
|
# GPIO2 IO2
|
||||||
|
# GPIO4 Screen power -> Screen Power (switch gpio) (inverted)
|
||||||
|
# GPIO14 Left button -> Left Button (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO16 Display UART TX -> display_uart (uart tx_pin)
|
||||||
|
# GPIO17 Display UART RX -> display_uart (uart rx_pin)
|
||||||
|
# GPIO19 Relay 2 -> relay_2 (switch gpio)
|
||||||
|
# GPIO21 Buzzer -> buzzer_out (output ledc)
|
||||||
|
# GPIO22 Relay 1 -> relay_1 (output gpio)
|
||||||
|
# GPIO23 Relay 3 (no relay, connector) -> Presence Light (light esp32_rmt_led_strip)
|
||||||
|
# GPIO27 Right button -> Right Button (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO37 ALS (light sensor)
|
||||||
|
# GPIO38 NTC temperature (ADC) -> ntc_source (sensor adc)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: nspanel-office-r
|
device: nspanel-office-r
|
||||||
name: Office R NSPanel
|
name: Office R NSPanel
|
||||||
@@ -10,33 +24,15 @@ esphome:
|
|||||||
friendly_name: ${name}
|
friendly_name: ${name}
|
||||||
area: ${area}
|
area: ${area}
|
||||||
comment: ${comment}
|
comment: ${comment}
|
||||||
on_boot:
|
|
||||||
then:
|
|
||||||
- switch.turn_off: screen_power
|
|
||||||
- delay: 1s
|
|
||||||
- switch.turn_on: screen_power
|
|
||||||
- delay: 2s
|
|
||||||
- lambda: 'id(nspanel_id).set_display_dim(5, 80);'
|
|
||||||
|
|
||||||
esp32:
|
|
||||||
variant: esp32
|
|
||||||
toolchain: esp-idf
|
|
||||||
framework:
|
|
||||||
type: esp-idf
|
|
||||||
advanced:
|
|
||||||
minimum_chip_revision: 3.0
|
|
||||||
sram1_as_iram: true
|
|
||||||
|
|
||||||
external_components:
|
|
||||||
- source:
|
|
||||||
type: git
|
|
||||||
url: https://github.com/randybb/esphome-nspanel-lovelace-native
|
|
||||||
ref: devices
|
|
||||||
refresh: 0s
|
|
||||||
components: [nspanel_lovelace]
|
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
nspanel: !include
|
||||||
|
file: common/nspanel.yaml
|
||||||
|
vars:
|
||||||
|
temperature_entity: sensor.zigbee_office_r_temperature
|
||||||
|
ntc_reference_temperature: 22°C
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- id: geiger_click
|
- id: geiger_click
|
||||||
@@ -55,65 +51,7 @@ script:
|
|||||||
return esphome::random_uint32() % 450 + 50;
|
return esphome::random_uint32() % 450 + 50;
|
||||||
- script.execute: geiger_click
|
- script.execute: geiger_click
|
||||||
|
|
||||||
api:
|
|
||||||
homeassistant_services: true
|
|
||||||
homeassistant_states: true
|
|
||||||
actions:
|
|
||||||
- action: play_rtttl
|
|
||||||
variables:
|
|
||||||
song: string
|
|
||||||
then:
|
|
||||||
- rtttl.play:
|
|
||||||
rtttl: !lambda 'return song;'
|
|
||||||
|
|
||||||
- action: notify
|
|
||||||
variables:
|
|
||||||
heading: string
|
|
||||||
message: string
|
|
||||||
song: string
|
|
||||||
then:
|
|
||||||
- lambda: 'id(nspanel_id).notify_on_screensaver(heading, message, 10000);'
|
|
||||||
- rtttl.play:
|
|
||||||
rtttl: !lambda 'return song;'
|
|
||||||
|
|
||||||
- action: notify_fullscreen
|
|
||||||
variables:
|
|
||||||
title: string
|
|
||||||
description: string
|
|
||||||
button1: string
|
|
||||||
button2: string
|
|
||||||
timeout: int
|
|
||||||
icon: string
|
|
||||||
then:
|
|
||||||
- lambda: 'id(nspanel_id).notify_on_screensaver(title, description, timeout);'
|
|
||||||
- rtttl.play: "scale_up:d=32,o=5,b=100:c,c#,d#,e,f#,g#,a#,b"
|
|
||||||
|
|
||||||
uart:
|
|
||||||
id: display_uart
|
|
||||||
tx_pin: 16
|
|
||||||
rx_pin: 17
|
|
||||||
baud_rate: 115200
|
|
||||||
|
|
||||||
nspanel_lovelace:
|
nspanel_lovelace:
|
||||||
id: nspanel_id
|
|
||||||
sleep_timeout: 10
|
|
||||||
experimental_vertical_ui: true
|
|
||||||
locale:
|
|
||||||
language: sk
|
|
||||||
temperature_unit: celcius
|
|
||||||
screensaver:
|
|
||||||
time_id: ha_time
|
|
||||||
time_format: '%H:%M'
|
|
||||||
date_format: '%A, %d. %b. %Y'
|
|
||||||
weather:
|
|
||||||
entity_id: sensor.weather_forecast_daily
|
|
||||||
icon_color: [255, 255, 255]
|
|
||||||
entities:
|
|
||||||
- entity_id: sensor.zigbee_office_r_temperature
|
|
||||||
icon:
|
|
||||||
value: home-thermometer-outline
|
|
||||||
color: [255, 255, 255]
|
|
||||||
precision: 1
|
|
||||||
cards:
|
cards:
|
||||||
- type: cardGrid
|
- type: cardGrid
|
||||||
title: Romanko
|
title: Romanko
|
||||||
@@ -158,10 +96,12 @@ nspanel_lovelace:
|
|||||||
- name: Auto-zatváranie
|
- name: Auto-zatváranie
|
||||||
entity_id: switch.gate_auto_close
|
entity_id: switch.gate_auto_close
|
||||||
|
|
||||||
time:
|
- type: cardEntities
|
||||||
- platform: homeassistant
|
title: Info
|
||||||
id: ha_time
|
entities:
|
||||||
timezone: Europe/Bratislava
|
- name: Zariadenie
|
||||||
|
entity_id: button.office_r_nspanel_info
|
||||||
|
icon: information-outline
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
@@ -175,7 +115,7 @@ binary_sensor:
|
|||||||
data:
|
data:
|
||||||
entity_id: light.office_r_desk_strip
|
entity_id: light.office_r_desk_strip
|
||||||
- lambda: 'id(nspanel_id).render_default_page();'
|
- lambda: 'id(nspanel_id).render_default_page();'
|
||||||
|
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
name: Right Button
|
name: Right Button
|
||||||
pin:
|
pin:
|
||||||
@@ -186,10 +126,6 @@ binary_sensor:
|
|||||||
- lambda: 'id(nspanel_id).render_default_page();'
|
- lambda: 'id(nspanel_id).render_default_page();'
|
||||||
|
|
||||||
output:
|
output:
|
||||||
- platform: ledc
|
|
||||||
id: buzzer_out
|
|
||||||
pin:
|
|
||||||
number: 21
|
|
||||||
- id: relay_1
|
- id: relay_1
|
||||||
platform: gpio
|
platform: gpio
|
||||||
pin:
|
pin:
|
||||||
@@ -229,14 +165,6 @@ switch:
|
|||||||
id: relay_2
|
id: relay_2
|
||||||
pin:
|
pin:
|
||||||
number: 19
|
number: 19
|
||||||
- platform: gpio
|
|
||||||
name: Screen Power
|
|
||||||
id: screen_power
|
|
||||||
entity_category: config
|
|
||||||
pin:
|
|
||||||
number: 4
|
|
||||||
inverted: true
|
|
||||||
restore_mode: ALWAYS_ON
|
|
||||||
- platform: template
|
- platform: template
|
||||||
name: "Geiger Counter"
|
name: "Geiger Counter"
|
||||||
optimistic: True
|
optimistic: True
|
||||||
@@ -244,38 +172,3 @@ switch:
|
|||||||
- script.execute: geiger_click
|
- script.execute: geiger_click
|
||||||
turn_off_action:
|
turn_off_action:
|
||||||
- script.stop: geiger_click
|
- script.stop: geiger_click
|
||||||
|
|
||||||
rtttl:
|
|
||||||
id: buzzer
|
|
||||||
output: buzzer_out
|
|
||||||
|
|
||||||
sensor:
|
|
||||||
- platform: adc
|
|
||||||
id: ntc_source
|
|
||||||
pin: 38
|
|
||||||
update_interval: 5min
|
|
||||||
attenuation: 12db
|
|
||||||
|
|
||||||
- platform: resistance
|
|
||||||
id: resistance_sensor
|
|
||||||
sensor: ntc_source
|
|
||||||
configuration: DOWNSTREAM
|
|
||||||
resistor: 11.2kOhm
|
|
||||||
|
|
||||||
- platform: ntc
|
|
||||||
name: Temperature
|
|
||||||
id: temperature
|
|
||||||
sensor: resistance_sensor
|
|
||||||
calibration:
|
|
||||||
b_constant: 3950
|
|
||||||
reference_temperature: 22°C
|
|
||||||
reference_resistance: 10kOhm
|
|
||||||
|
|
||||||
text_sensor:
|
|
||||||
- platform: homeassistant
|
|
||||||
id: name_day
|
|
||||||
entity_id: sensor.nameday_sk
|
|
||||||
on_value:
|
|
||||||
- lambda: |-
|
|
||||||
id(nspanel_id).set_time_format("%H:%M~" + x);
|
|
||||||
id(nspanel_id).update_time();
|
|
||||||
+45
-140
@@ -1,4 +1,18 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Sonoff NSPanel (EU)
|
||||||
|
# Pinout:
|
||||||
|
# GPIO2 IO2
|
||||||
|
# GPIO4 Screen power -> Screen Power (switch gpio) (inverted)
|
||||||
|
# GPIO14 Left button -> Left Button (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO16 Display UART TX -> display_uart (uart tx_pin)
|
||||||
|
# GPIO17 Display UART RX -> display_uart (uart rx_pin)
|
||||||
|
# GPIO19 Relay 2 -> Light MAIN (switch gpio)
|
||||||
|
# GPIO21 Buzzer -> buzzer_out (output ledc)
|
||||||
|
# GPIO22 Relay 1 -> Outside Light Back (switch gpio)
|
||||||
|
# GPIO23 Relay 3 (no relay, connector)
|
||||||
|
# GPIO27 Right button -> Right Button (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO37 ALS (light sensor)
|
||||||
|
# GPIO38 NTC temperature (ADC) -> ntc_source (sensor adc)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: nspanel-patio
|
device: nspanel-patio
|
||||||
name: Patio NSPanel
|
name: Patio NSPanel
|
||||||
@@ -10,96 +24,21 @@ esphome:
|
|||||||
friendly_name: ${name}
|
friendly_name: ${name}
|
||||||
area: ${area}
|
area: ${area}
|
||||||
comment: ${comment}
|
comment: ${comment}
|
||||||
on_boot:
|
|
||||||
then:
|
|
||||||
- switch.turn_off: screen_power
|
|
||||||
- delay: 1s
|
|
||||||
- switch.turn_on: screen_power
|
|
||||||
- delay: 2s
|
|
||||||
- lambda: 'id(nspanel_id).set_display_dim(5, 80);'
|
|
||||||
|
|
||||||
esp32:
|
|
||||||
variant: esp32
|
|
||||||
toolchain: esp-idf
|
|
||||||
framework:
|
|
||||||
type: esp-idf
|
|
||||||
advanced:
|
|
||||||
minimum_chip_revision: 3.0
|
|
||||||
sram1_as_iram: true
|
|
||||||
|
|
||||||
external_components:
|
|
||||||
- source:
|
|
||||||
type: git
|
|
||||||
url: https://github.com/randybb/esphome-nspanel-lovelace-native
|
|
||||||
ref: devices
|
|
||||||
refresh: 0s
|
|
||||||
components: [nspanel_lovelace]
|
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
api:
|
nspanel: !include
|
||||||
homeassistant_services: true
|
file: common/nspanel.yaml
|
||||||
homeassistant_states: true
|
vars:
|
||||||
actions:
|
temperature_entity: sensor.zigbee_living_room_kitchen_temperature
|
||||||
- action: play_rtttl
|
temperature_name: Living Room Temperature
|
||||||
variables:
|
|
||||||
song: string
|
|
||||||
then:
|
|
||||||
- rtttl.play:
|
|
||||||
rtttl: !lambda 'return song;'
|
|
||||||
|
|
||||||
- action: notify
|
|
||||||
variables:
|
|
||||||
heading: string
|
|
||||||
message: string
|
|
||||||
song: string
|
|
||||||
then:
|
|
||||||
- lambda: 'id(nspanel_id).notify_on_screensaver(heading, message, 10000);'
|
|
||||||
- rtttl.play:
|
|
||||||
rtttl: !lambda 'return song;'
|
|
||||||
|
|
||||||
- action: notify_fullscreen
|
|
||||||
variables:
|
|
||||||
title: string
|
|
||||||
description: string
|
|
||||||
button1: string
|
|
||||||
button2: string
|
|
||||||
timeout: int
|
|
||||||
icon: string
|
|
||||||
then:
|
|
||||||
- lambda: 'id(nspanel_id).notify_on_screensaver(title, description, timeout);'
|
|
||||||
- rtttl.play: "scale_up:d=32,o=5,b=100:c,c#,d#,e,f#,g#,a#,b"
|
|
||||||
|
|
||||||
uart:
|
|
||||||
id: display_uart
|
|
||||||
tx_pin: 16
|
|
||||||
rx_pin: 17
|
|
||||||
baud_rate: 115200
|
|
||||||
|
|
||||||
nspanel_lovelace:
|
nspanel_lovelace:
|
||||||
id: nspanel_id
|
|
||||||
sleep_timeout: 10
|
|
||||||
experimental_vertical_ui: true
|
|
||||||
locale:
|
|
||||||
language: sk
|
|
||||||
temperature_unit: celcius
|
|
||||||
screensaver:
|
|
||||||
time_id: ha_time
|
|
||||||
time_format: '%H:%M'
|
|
||||||
date_format: '%A, %d. %b. %Y'
|
|
||||||
weather:
|
|
||||||
entity_id: sensor.weather_forecast_daily
|
|
||||||
icon_color: [255, 255, 255]
|
|
||||||
entities:
|
|
||||||
- entity_id: sensor.zigbee_living_room_kitchen_temperature
|
|
||||||
icon:
|
|
||||||
value: home-thermometer-outline
|
|
||||||
color: [255, 255, 255]
|
|
||||||
precision: 1
|
|
||||||
cards:
|
cards:
|
||||||
- type: cardGrid
|
- type: cardGrid
|
||||||
title: Kuchyňa / Obývačka
|
title: Kuchyňa / Obývačka
|
||||||
|
id: card_home
|
||||||
entities:
|
entities:
|
||||||
- name: Kuchyňa / Obývačka
|
- name: Kuchyňa / Obývačka
|
||||||
entity_id: light.kitchen
|
entity_id: light.kitchen
|
||||||
@@ -132,6 +71,7 @@ nspanel_lovelace:
|
|||||||
|
|
||||||
- type: cardGrid
|
- type: cardGrid
|
||||||
title: Von
|
title: Von
|
||||||
|
id: card_outside
|
||||||
entities:
|
entities:
|
||||||
- name: Terasa
|
- name: Terasa
|
||||||
entity_id: light.patio_lights
|
entity_id: light.patio_lights
|
||||||
@@ -214,10 +154,12 @@ nspanel_lovelace:
|
|||||||
- name: Rast trávy
|
- name: Rast trávy
|
||||||
entity_id: automation.irrigation_grow_grass
|
entity_id: automation.irrigation_grow_grass
|
||||||
|
|
||||||
time:
|
- type: cardEntities
|
||||||
- platform: homeassistant
|
title: Info
|
||||||
id: ha_time
|
entities:
|
||||||
timezone: Europe/Bratislava
|
- name: Zariadenie
|
||||||
|
entity_id: button.patio_nspanel_info
|
||||||
|
icon: information-outline
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
@@ -227,9 +169,7 @@ binary_sensor:
|
|||||||
inverted: true
|
inverted: true
|
||||||
on_click:
|
on_click:
|
||||||
- switch.toggle: relay_1
|
- switch.toggle: relay_1
|
||||||
- lambda: 'id(nspanel_id).render_default_page();'
|
- script.execute: show_outside_card
|
||||||
- lambda: 'id(nspanel_id).render_next_page();'
|
|
||||||
- lambda: 'id(nspanel_id).render_next_page();'
|
|
||||||
|
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
name: Right Button
|
name: Right Button
|
||||||
@@ -238,24 +178,23 @@ binary_sensor:
|
|||||||
inverted: true
|
inverted: true
|
||||||
on_click:
|
on_click:
|
||||||
if:
|
if:
|
||||||
|
# mcu-patio online -> toggle its lights; otherwise (no API or relay_2 cut its power) the relay
|
||||||
condition:
|
condition:
|
||||||
api.connected:
|
and:
|
||||||
|
- api.connected:
|
||||||
|
- binary_sensor.is_on: patio_status
|
||||||
then:
|
then:
|
||||||
- homeassistant.action:
|
- homeassistant.action:
|
||||||
action: light.toggle
|
action: light.toggle
|
||||||
data:
|
data:
|
||||||
entity_id: light.patio_lights
|
entity_id: light.patio_lights
|
||||||
- lambda: 'id(nspanel_id).render_default_page();'
|
- script.execute: show_outside_card
|
||||||
- lambda: 'id(nspanel_id).render_next_page();'
|
|
||||||
- lambda: 'id(nspanel_id).render_next_page();'
|
|
||||||
else:
|
else:
|
||||||
- switch.toggle: relay_2
|
- switch.toggle: relay_2
|
||||||
|
|
||||||
output:
|
- platform: homeassistant
|
||||||
- platform: ledc
|
id: patio_status
|
||||||
id: buzzer_out
|
entity_id: binary_sensor.mcu_patio_status
|
||||||
pin:
|
|
||||||
number: 21
|
|
||||||
|
|
||||||
switch:
|
switch:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
@@ -272,46 +211,12 @@ switch:
|
|||||||
pin:
|
pin:
|
||||||
number: 19
|
number: 19
|
||||||
|
|
||||||
- platform: gpio
|
script:
|
||||||
name: Screen Power
|
# jump straight to the "Von" card (one render instead of home + next + next):
|
||||||
id: screen_power
|
# make it the default page for a moment, render it, restore the home card
|
||||||
entity_category: config
|
- id: show_outside_card
|
||||||
pin:
|
then:
|
||||||
number: 4
|
|
||||||
inverted: true
|
|
||||||
restore_mode: ALWAYS_ON
|
|
||||||
|
|
||||||
rtttl:
|
|
||||||
id: buzzer
|
|
||||||
output: buzzer_out
|
|
||||||
|
|
||||||
sensor:
|
|
||||||
- platform: adc
|
|
||||||
id: ntc_source
|
|
||||||
pin: 38
|
|
||||||
update_interval: 5min
|
|
||||||
attenuation: 12db
|
|
||||||
|
|
||||||
- platform: resistance
|
|
||||||
id: resistance_sensor
|
|
||||||
sensor: ntc_source
|
|
||||||
configuration: DOWNSTREAM
|
|
||||||
resistor: 11.2kOhm
|
|
||||||
|
|
||||||
- platform: ntc
|
|
||||||
name: Living Room Temperature
|
|
||||||
id: temperature
|
|
||||||
sensor: resistance_sensor
|
|
||||||
calibration:
|
|
||||||
b_constant: 3950
|
|
||||||
reference_temperature: 25°C
|
|
||||||
reference_resistance: 10kOhm
|
|
||||||
|
|
||||||
text_sensor:
|
|
||||||
- platform: homeassistant
|
|
||||||
id: name_day
|
|
||||||
entity_id: sensor.nameday_sk
|
|
||||||
on_value:
|
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
id(nspanel_id).set_time_format("%H:%M~" + x);
|
id(nspanel_id).set_default_page("card_outside");
|
||||||
id(nspanel_id).update_time();
|
id(nspanel_id).render_default_page();
|
||||||
|
id(nspanel_id).set_default_page("card_home");
|
||||||
+14
-7
@@ -1,4 +1,15 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack M5Stamp C3
|
||||||
|
# Pinout:
|
||||||
|
# GPIO0 I2C SDA
|
||||||
|
# GPIO1 I2C SCL
|
||||||
|
# GPIO2 NEO
|
||||||
|
# GPIO3 BUTTON
|
||||||
|
# GPIO4 -> led_red (output ledc)
|
||||||
|
# GPIO5 -> led_green (output ledc)
|
||||||
|
# GPIO6 -> led_blue (output ledc)
|
||||||
|
# GPIO20 UART RX
|
||||||
|
# GPIO21 UART TX
|
||||||
substitutions:
|
substitutions:
|
||||||
device: office-r
|
device: office-r
|
||||||
name: Office R
|
name: Office R
|
||||||
@@ -18,17 +29,13 @@ esp32:
|
|||||||
variant: esp32c3
|
variant: esp32c3
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: generic
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
# GPIO21 UART TX
|
|
||||||
# GPIO20 UART RX
|
|
||||||
# GPIO0 I2C SDA
|
|
||||||
# GPIO1 I2C SCL
|
|
||||||
# GPIO2 NEO
|
|
||||||
# GPIO3 BUTTON
|
|
||||||
|
|
||||||
light:
|
light:
|
||||||
- platform: rgb
|
- platform: rgb
|
||||||
|
|||||||
+21
-20
@@ -1,4 +1,21 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack ATOM Lite + ATOM Hub Switch
|
||||||
|
# Pinout:
|
||||||
|
# GPIO1 UART0 TX
|
||||||
|
# GPIO3 UART0 RX
|
||||||
|
# GPIO12 IR
|
||||||
|
# GPIO19 Relay2 -> Relay (switch gpio)
|
||||||
|
# GPIO21 I2C1 SCL -> i2c (i2c scl)
|
||||||
|
# GPIO22 Relay1 -> power_supply1 (power_supply)
|
||||||
|
# GPIO23 RS485 Tx
|
||||||
|
# GPIO25 I2C1 SDA - red -> i2c (i2c sda)
|
||||||
|
# GPIO26 I2C0 SDA - white
|
||||||
|
# GPIO27 NEO 1x -> atom_led (status LED, common/status_led_atom.yaml)
|
||||||
|
# GPIO32 I2C0 SCL
|
||||||
|
# GPIO33 RS485 Rx
|
||||||
|
# GPIO39 BUTTON -> Status Button (binary_sensor gpio)
|
||||||
|
# I2C:
|
||||||
|
# 0x40 pca9685_hub1 (pca9685)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: patio
|
device: patio
|
||||||
name: Patio
|
name: Patio
|
||||||
@@ -33,32 +50,16 @@ esp32:
|
|||||||
variant: esp32
|
variant: esp32
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: gd
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
status_led: !include common/status_led_atom.yaml
|
||||||
|
|
||||||
|
|
||||||
# PINOUTS: M5ATOM+Atom Hub Switch
|
|
||||||
# IR G12
|
|
||||||
# NEO G27 1x
|
|
||||||
# BUTTON G39
|
|
||||||
# I2C0 SDA G26 - white
|
|
||||||
# I2C0 SCL G32
|
|
||||||
# I2C1 SDA G25 - red
|
|
||||||
# I2C1 SCL G21
|
|
||||||
# UART0 RX G3
|
|
||||||
# UART0 TX G1
|
|
||||||
# RS485 Rx G33
|
|
||||||
# RS485 Tx G23
|
|
||||||
# Relay1 G22
|
|
||||||
# Relay2 G19
|
|
||||||
|
|
||||||
time:
|
|
||||||
- platform: homeassistant
|
|
||||||
id: ha_time
|
|
||||||
timezone: Europe/Bratislava
|
|
||||||
|
|
||||||
i2c:
|
i2c:
|
||||||
# - id: i2c0
|
# - id: i2c0
|
||||||
# sda: 26
|
# sda: 26
|
||||||
|
|||||||
+14
-3
@@ -1,4 +1,16 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Sonoff POW Elite
|
||||||
|
# Pinout:
|
||||||
|
# GPIO0 -> reset (binary_sensor gpio)
|
||||||
|
# GPIO2 -> relay_on (switch gpio)
|
||||||
|
# GPIO4 -> relay_off (switch gpio)
|
||||||
|
# GPIO5 -> wifi_status_led (light status_led) (inverted)
|
||||||
|
# GPIO14 -> tm1621_display (display tm1621 data_pin)
|
||||||
|
# GPIO16 -> cse7766_uart (uart rx_pin)
|
||||||
|
# GPIO18 -> led (output ledc) (inverted)
|
||||||
|
# GPIO25 -> tm1621_display (display tm1621 cs_pin)
|
||||||
|
# GPIO26 -> tm1621_display (display tm1621 read_pin)
|
||||||
|
# GPIO27 -> tm1621_display (display tm1621 write_pin)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: pow-dishwasher
|
device: pow-dishwasher
|
||||||
name: Dishwasher POW
|
name: Dishwasher POW
|
||||||
@@ -18,11 +30,13 @@ esp32:
|
|||||||
framework:
|
framework:
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
advanced:
|
advanced:
|
||||||
|
flash_chip: gd
|
||||||
minimum_chip_revision: 3.1
|
minimum_chip_revision: 3.1
|
||||||
sram1_as_iram: true
|
sram1_as_iram: true
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
|
||||||
uart:
|
uart:
|
||||||
- id: cse7766_uart
|
- id: cse7766_uart
|
||||||
@@ -186,6 +200,3 @@ switch:
|
|||||||
- delay: 500ms
|
- delay: 500ms
|
||||||
- switch.turn_off: relay_off # bi-stable relay so no need to keep on
|
- switch.turn_off: relay_off # bi-stable relay so no need to keep on
|
||||||
interlock: [relay_on]
|
interlock: [relay_on]
|
||||||
|
|
||||||
time:
|
|
||||||
- !include common/time/homeassistant.yaml
|
|
||||||
+14
-4
@@ -1,8 +1,20 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Sonoff POW Elite
|
||||||
|
# Pinout:
|
||||||
|
# GPIO0 -> reset (binary_sensor gpio)
|
||||||
|
# GPIO2 -> relay_on (switch gpio)
|
||||||
|
# GPIO4 -> relay_off (switch gpio)
|
||||||
|
# GPIO5 -> wifi_status_led (light status_led) (inverted)
|
||||||
|
# GPIO14 -> tm1621_display (display tm1621 data_pin)
|
||||||
|
# GPIO16 -> cse7766_uart (uart rx_pin)
|
||||||
|
# GPIO18 -> led (output ledc) (inverted)
|
||||||
|
# GPIO25 -> tm1621_display (display tm1621 cs_pin)
|
||||||
|
# GPIO26 -> tm1621_display (display tm1621 read_pin)
|
||||||
|
# GPIO27 -> tm1621_display (display tm1621 write_pin)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: pow-washer
|
device: pow-washer
|
||||||
name: Washer POW
|
name: Washer POW
|
||||||
comment:
|
comment: "spare"
|
||||||
area: Washroom
|
area: Washroom
|
||||||
update_interval: 10s
|
update_interval: 10s
|
||||||
|
|
||||||
@@ -18,6 +30,7 @@ esp32:
|
|||||||
framework:
|
framework:
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
advanced:
|
advanced:
|
||||||
|
flash_chip: gd # same device as pow-dishwasher (not read from the device)
|
||||||
minimum_chip_revision: 3.1
|
minimum_chip_revision: 3.1
|
||||||
sram1_as_iram: true
|
sram1_as_iram: true
|
||||||
|
|
||||||
@@ -186,6 +199,3 @@ switch:
|
|||||||
- delay: 500ms
|
- delay: 500ms
|
||||||
- switch.turn_off: relay_off # bi-stable relay so no need to keep on
|
- switch.turn_off: relay_off # bi-stable relay so no need to keep on
|
||||||
interlock: [relay_on]
|
interlock: [relay_on]
|
||||||
|
|
||||||
time:
|
|
||||||
- !include common/time/homeassistant.yaml
|
|
||||||
+18
-3
@@ -1,4 +1,15 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack ATOM Lite
|
||||||
|
# Pinout:
|
||||||
|
# GPIO19 -> spi (spi mosi_pin)
|
||||||
|
# GPIO21 -> rf_tx (remote_transmitter)
|
||||||
|
# GPIO22 -> spi (spi miso_pin)
|
||||||
|
# GPIO23 -> spi (spi clk_pin)
|
||||||
|
# GPIO25 -> rf_rx (remote_receiver)
|
||||||
|
# GPIO26 Grove SDA
|
||||||
|
# GPIO27 NEO (ATOM RGB LED) -> atom_led (status LED, common/status_led_atom.yaml)
|
||||||
|
# GPIO32 Grove SCL
|
||||||
|
# GPIO33 -> cc1101 (cc1101 cs_pin)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: rf
|
device: rf
|
||||||
name: RF Bridge
|
name: RF Bridge
|
||||||
@@ -15,16 +26,20 @@ esp32:
|
|||||||
variant: esp32
|
variant: esp32
|
||||||
flash_size: 4MB
|
flash_size: 4MB
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: gd
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
status_led: !include common/status_led_atom.yaml
|
||||||
|
|
||||||
spi:
|
spi:
|
||||||
clk_pin: 23
|
clk_pin: 23
|
||||||
mosi_pin: 19
|
mosi_pin: 19
|
||||||
miso_pin: 22
|
miso_pin: 22
|
||||||
|
|
||||||
cc1101:
|
cc1101:
|
||||||
cs_pin: 33
|
cs_pin: 33
|
||||||
frequency: 433.92MHz
|
frequency: 433.92MHz
|
||||||
@@ -40,7 +55,7 @@ radio_frequency:
|
|||||||
id: rf_proxy_rx
|
id: rf_proxy_rx
|
||||||
remote_receiver_id: rf_rx
|
remote_receiver_id: rf_rx
|
||||||
frequency: 433.92MHz
|
frequency: 433.92MHz
|
||||||
|
|
||||||
remote_receiver:
|
remote_receiver:
|
||||||
- id: rf_rx
|
- id: rf_rx
|
||||||
pin: 25
|
pin: 25
|
||||||
@@ -55,4 +70,4 @@ remote_transmitter:
|
|||||||
- cc1101.begin_tx
|
- cc1101.begin_tx
|
||||||
on_complete:
|
on_complete:
|
||||||
then:
|
then:
|
||||||
- cc1101.begin_rx
|
- cc1101.begin_rx
|
||||||
@@ -1,4 +1,9 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Sonoff RF Bridge (obsolete)
|
||||||
|
# Pinout:
|
||||||
|
# GPIO4 -> remote_receiver (remote_receiver)
|
||||||
|
# GPIO5 -> remote_transmitter (remote_transmitter)
|
||||||
|
# GPIO13 -> status_led (status_led) (inverted)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: rf433
|
device: rf433
|
||||||
name: RF433 Bridge
|
name: RF433 Bridge
|
||||||
@@ -16,6 +21,7 @@ esp8266:
|
|||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common_esp8266.yaml
|
common: !include common/common_esp8266.yaml
|
||||||
|
mdns_ipv6: !include common/esp8266_mdns_ipv6.yaml
|
||||||
|
|
||||||
remote_receiver:
|
remote_receiver:
|
||||||
pin: 4
|
pin: 4
|
||||||
|
|||||||
@@ -0,0 +1,285 @@
|
|||||||
|
---
|
||||||
|
# Hardware: M5Stack M5Stamp S3 + PN5180 module (5 V and 3.3 V both needed)
|
||||||
|
# Pinout:
|
||||||
|
# GPIO0 Button
|
||||||
|
# GPIO3 (external RFID LED, not fitted yet; notify_led uses the onboard RGB for now)
|
||||||
|
# GPIO4 Buzzer -> buzzer (output ledc)
|
||||||
|
# GPIO5 -> spi (spi miso_pin) PN5180 MISO
|
||||||
|
# GPIO6 -> spi (spi mosi_pin) PN5180 MOSI
|
||||||
|
# GPIO7 -> spi (spi clk_pin) PN5180 SCK
|
||||||
|
# GPIO8 -> pn5180 (cs_pin) PN5180 NSS
|
||||||
|
# GPIO9 -> pn5180 (busy_pin) PN5180 BUSY
|
||||||
|
# GPIO10 -> pn5180 (reset_pin) PN5180 RST
|
||||||
|
# GPIO11 -> pn5180 (irq_pin) PN5180 IRQ
|
||||||
|
# GPIO19 U-
|
||||||
|
# GPIO20 U+
|
||||||
|
# GPIO21 RGB -> notify_led (light esp32_rmt_led_strip), also status_led
|
||||||
|
# PN5180 REQ, AUX, GPIO left open (REQ high at reset = firmware download mode)
|
||||||
|
substitutions:
|
||||||
|
device: rfid-openprinttag
|
||||||
|
name: OpenPrintTag
|
||||||
|
area: DEV
|
||||||
|
comment: Filament spool reader (OpenPrintTag, Creality CFS)
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: mcu-${device}
|
||||||
|
friendly_name: ${name}
|
||||||
|
area: ${area}
|
||||||
|
comment: ${comment}
|
||||||
|
|
||||||
|
esp32:
|
||||||
|
variant: esp32s3
|
||||||
|
toolchain: esp-idf
|
||||||
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: gd
|
||||||
|
type: esp-idf
|
||||||
|
|
||||||
|
packages:
|
||||||
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
status_led: !include
|
||||||
|
file: common/status_led.yaml
|
||||||
|
vars:
|
||||||
|
light_id: notify_led
|
||||||
|
show_errors: "true"
|
||||||
|
|
||||||
|
external_components:
|
||||||
|
- source: github://randybb/esphome-components
|
||||||
|
components: [pn5180, openprinttag, creality_cfs]
|
||||||
|
refresh: 1h
|
||||||
|
|
||||||
|
# Called by the OpenPrintTag integration (openprinttag.update) to update the aux region
|
||||||
|
api:
|
||||||
|
actions:
|
||||||
|
- action: openprinttag_write_aux
|
||||||
|
variables:
|
||||||
|
uid: string
|
||||||
|
aux: string
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
switch.is_on: led_enabled
|
||||||
|
then:
|
||||||
|
- light.turn_on:
|
||||||
|
id: notify_led
|
||||||
|
brightness: 100%
|
||||||
|
red: 100%
|
||||||
|
green: 0%
|
||||||
|
blue: 0%
|
||||||
|
flash_length: 500ms
|
||||||
|
- lambda: id(spool).write_aux(uid, aux);
|
||||||
|
# Writes a Creality CFS record (48 characters, optionally 48 more for sector 2) to the
|
||||||
|
# Creality tag on the reader
|
||||||
|
- action: creality_cfs_write
|
||||||
|
variables:
|
||||||
|
uid: string
|
||||||
|
data: string
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
switch.is_on: led_enabled
|
||||||
|
then:
|
||||||
|
- light.turn_on:
|
||||||
|
id: notify_led
|
||||||
|
brightness: 100%
|
||||||
|
red: 100%
|
||||||
|
green: 0%
|
||||||
|
blue: 0%
|
||||||
|
flash_length: 500ms
|
||||||
|
- lambda: id(creality).write(uid, data);
|
||||||
|
|
||||||
|
spi:
|
||||||
|
clk_pin: GPIO7
|
||||||
|
mosi_pin: GPIO6
|
||||||
|
miso_pin: GPIO5
|
||||||
|
|
||||||
|
pn5180:
|
||||||
|
id: pn5180_reader
|
||||||
|
cs_pin: GPIO8
|
||||||
|
busy_pin: GPIO9
|
||||||
|
reset_pin: GPIO10
|
||||||
|
irq_pin: GPIO11
|
||||||
|
on_tag:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
switch.is_on: led_enabled
|
||||||
|
then:
|
||||||
|
- light.turn_on:
|
||||||
|
id: notify_led
|
||||||
|
brightness: 100%
|
||||||
|
red: 0%
|
||||||
|
green: 100%
|
||||||
|
blue: 0%
|
||||||
|
flash_length: 500ms
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
switch.is_on: buzzer_enabled
|
||||||
|
then:
|
||||||
|
- rtttl.play: "success:d=32,o=5,b=100:c,g,b"
|
||||||
|
- homeassistant.tag_scanned: !lambda return x;
|
||||||
|
on_tag_removed:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
switch.is_on: buzzer_enabled
|
||||||
|
then:
|
||||||
|
- rtttl.play: "removed:d=16,o=5,b=100:b"
|
||||||
|
|
||||||
|
openprinttag:
|
||||||
|
id: spool
|
||||||
|
# Raw tag record for the OpenPrintTag integration (randybb/ha-openprinttag), empty when removed
|
||||||
|
on_openprinttag:
|
||||||
|
- homeassistant.event:
|
||||||
|
event: esphome.openprinttag
|
||||||
|
data:
|
||||||
|
uid: !lambda return uid;
|
||||||
|
payload: !lambda return payload;
|
||||||
|
|
||||||
|
creality_cfs:
|
||||||
|
id: creality
|
||||||
|
# The Creality record (ASCII) for Home Assistant, empty when removed
|
||||||
|
on_creality:
|
||||||
|
- homeassistant.event:
|
||||||
|
event: esphome.creality_cfs
|
||||||
|
data:
|
||||||
|
uid: !lambda return uid;
|
||||||
|
data: !lambda return data;
|
||||||
|
|
||||||
|
sensor:
|
||||||
|
- platform: creality_cfs
|
||||||
|
name: Creality length
|
||||||
|
- platform: openprinttag
|
||||||
|
type: remaining_weight
|
||||||
|
name: Remaining weight
|
||||||
|
- platform: openprinttag
|
||||||
|
type: consumed_weight
|
||||||
|
name: Consumed weight
|
||||||
|
- platform: openprinttag
|
||||||
|
type: actual_weight
|
||||||
|
name: Full weight
|
||||||
|
- platform: openprinttag
|
||||||
|
type: min_print_temperature
|
||||||
|
name: Min print temperature
|
||||||
|
- platform: openprinttag
|
||||||
|
type: max_print_temperature
|
||||||
|
name: Max print temperature
|
||||||
|
- platform: openprinttag
|
||||||
|
type: max_bed_temperature
|
||||||
|
name: Max bed temperature
|
||||||
|
- platform: openprinttag
|
||||||
|
type: drying_temperature
|
||||||
|
name: Drying temperature
|
||||||
|
- platform: openprinttag
|
||||||
|
type: drying_time
|
||||||
|
name: Drying time
|
||||||
|
|
||||||
|
text_sensor:
|
||||||
|
- platform: pn5180
|
||||||
|
name: Tag UID
|
||||||
|
- platform: creality_cfs
|
||||||
|
type: material_id
|
||||||
|
name: Creality material ID
|
||||||
|
- platform: creality_cfs
|
||||||
|
type: color
|
||||||
|
name: Creality color
|
||||||
|
id: creality_color
|
||||||
|
on_value:
|
||||||
|
- script.execute: show_filament_color
|
||||||
|
- platform: creality_cfs
|
||||||
|
type: serial
|
||||||
|
name: Creality serial
|
||||||
|
- platform: openprinttag
|
||||||
|
type: material_type
|
||||||
|
name: Material
|
||||||
|
- platform: openprinttag
|
||||||
|
type: material_name
|
||||||
|
name: Material name
|
||||||
|
- platform: openprinttag
|
||||||
|
type: brand_name
|
||||||
|
name: Brand
|
||||||
|
- platform: openprinttag
|
||||||
|
type: primary_color
|
||||||
|
name: Color
|
||||||
|
id: openprinttag_color
|
||||||
|
on_value:
|
||||||
|
- script.execute: show_filament_color
|
||||||
|
|
||||||
|
script:
|
||||||
|
# The filament color on the filament_color light: the OpenPrintTag's, else the Creality tag's
|
||||||
|
- id: show_filament_color
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
std::string x = id(openprinttag_color).state;
|
||||||
|
if (x.size() < 7)
|
||||||
|
x = id(creality_color).state;
|
||||||
|
if (x.size() < 7) {
|
||||||
|
id(filament_color).turn_off().set_transition_length(0).perform();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint32_t c = strtoul(x.c_str() + 1, nullptr, 16);
|
||||||
|
if (x.size() > 7)
|
||||||
|
c >>= 8; // #rrggbbaa
|
||||||
|
// ESPHome scales the strongest channel to 100 %, the darkness goes to the brightness
|
||||||
|
const float r = ((c >> 16) & 0xFF) / 255.0f, g = ((c >> 8) & 0xFF) / 255.0f, b = (c & 0xFF) / 255.0f;
|
||||||
|
const float m = std::max({r, g, b});
|
||||||
|
if (m == 0.0f) {
|
||||||
|
id(filament_color).turn_off().set_transition_length(0).perform(); // black
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
id(filament_color).turn_on()
|
||||||
|
.set_rgb(r, g, b)
|
||||||
|
.set_brightness(m)
|
||||||
|
.set_transition_length(0)
|
||||||
|
.perform();
|
||||||
|
|
||||||
|
light:
|
||||||
|
# Onboard RGB for now: tag feedback and status. With the external LED fitted, move
|
||||||
|
# notify_led to pin 3 and give the onboard one back to status_led (as on mcu-rfid-reader)
|
||||||
|
- platform: esp32_rmt_led_strip
|
||||||
|
id: notify_led
|
||||||
|
name: Notify LED
|
||||||
|
channel_colors: GRB
|
||||||
|
pin: 21
|
||||||
|
num_leds: 1
|
||||||
|
chipset: ws2812
|
||||||
|
restore_mode: ALWAYS_OFF
|
||||||
|
rmt_symbols: 96
|
||||||
|
|
||||||
|
# Shows the filament color in Home Assistant; drives nothing, the next tag read overwrites it
|
||||||
|
- platform: rgb
|
||||||
|
id: filament_color
|
||||||
|
name: Filament color
|
||||||
|
icon: mdi:printer-3d-nozzle
|
||||||
|
red: color_none
|
||||||
|
green: color_none
|
||||||
|
blue: color_none
|
||||||
|
restore_mode: ALWAYS_OFF
|
||||||
|
default_transition_length: 0s
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: ledc
|
||||||
|
pin: 4
|
||||||
|
id: buzzer
|
||||||
|
- platform: template
|
||||||
|
id: color_none
|
||||||
|
type: float
|
||||||
|
write_action: []
|
||||||
|
|
||||||
|
rtttl:
|
||||||
|
output: buzzer
|
||||||
|
|
||||||
|
switch:
|
||||||
|
- platform: template
|
||||||
|
name: Buzzer Enabled
|
||||||
|
id: buzzer_enabled
|
||||||
|
icon: mdi:volume-high
|
||||||
|
optimistic: true
|
||||||
|
restore_mode: RESTORE_DEFAULT_ON
|
||||||
|
entity_category: config
|
||||||
|
- platform: template
|
||||||
|
name: LED enabled
|
||||||
|
id: led_enabled
|
||||||
|
icon: mdi:alarm-light-outline
|
||||||
|
optimistic: true
|
||||||
|
restore_mode: RESTORE_DEFAULT_ON
|
||||||
|
entity_category: config
|
||||||
+27
-21
@@ -1,4 +1,16 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack M5Stamp S3
|
||||||
|
# Pinout:
|
||||||
|
# GPIO0 Button
|
||||||
|
# GPIO1 I2C SDA -> i2c_rfid (i2c sda)
|
||||||
|
# GPIO2 I2C SDA, Notify LED -> i2c_rfid (i2c scl)
|
||||||
|
# GPIO3 -> notify_led (light esp32_rmt_led_strip)
|
||||||
|
# GPIO4 Buzzer -> buzzer (output ledc)
|
||||||
|
# GPIO19 U-
|
||||||
|
# GPIO20 U+
|
||||||
|
# GPIO21 RGB -> status_led (light esp32_rmt_led_strip)
|
||||||
|
# I2C:
|
||||||
|
# 0x24 pn532_module (pn532_i2c)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: rfid-reader
|
device: rfid-reader
|
||||||
name: RFID Reader
|
name: RFID Reader
|
||||||
@@ -16,7 +28,7 @@ esphome:
|
|||||||
# - wait_until:
|
# - wait_until:
|
||||||
# api.connected:
|
# api.connected:
|
||||||
# - logger.log: API is connected!
|
# - logger.log: API is connected!
|
||||||
# - rtttl.play: "success:d=24,o=5,b=100:c,g,b"
|
# - rtttl.play: "success:d=32,o=5,b=100:c,g,b"
|
||||||
# - light.turn_on:
|
# - light.turn_on:
|
||||||
# id: notify_led
|
# id: notify_led
|
||||||
# brightness: 100%
|
# brightness: 100%
|
||||||
@@ -31,6 +43,8 @@ esp32:
|
|||||||
variant: esp32s3
|
variant: esp32s3
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: gd
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
# external_components:
|
# external_components:
|
||||||
@@ -40,19 +54,11 @@ esp32:
|
|||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
|
||||||
# logger:
|
# logger:
|
||||||
# hardware_uart: UART0
|
# hardware_uart: UART0
|
||||||
|
|
||||||
# GPIO20 U+
|
|
||||||
# GPIO19 U-
|
|
||||||
# GPIO0 Button
|
|
||||||
# GPIO1 I2C SDA
|
|
||||||
# GPIO2 I2C SDA
|
|
||||||
# GPIO2 Notify LED
|
|
||||||
# GPIO4 Buzzer
|
|
||||||
# GPIO21 RGB
|
|
||||||
|
|
||||||
api:
|
api:
|
||||||
actions:
|
actions:
|
||||||
- action: rfidreader_tag_ok
|
- action: rfidreader_tag_ok
|
||||||
@@ -85,13 +91,13 @@ api:
|
|||||||
uri += tag_id;
|
uri += tag_id;
|
||||||
message->add_uri_record(uri);
|
message->add_uri_record(uri);
|
||||||
id(pn532_module).write_mode(message);
|
id(pn532_module).write_mode(message);
|
||||||
- rtttl.play: "write:d=24,o=5,b=100:b"
|
- rtttl.play: "write:d=32,o=5,b=100:b"
|
||||||
- wait_until:
|
- wait_until:
|
||||||
not:
|
not:
|
||||||
pn532.is_writing:
|
pn532.is_writing:
|
||||||
- light.turn_off:
|
- light.turn_off:
|
||||||
id: notify_led
|
id: notify_led
|
||||||
- rtttl.play: "write:d=24,o=5,b=100:b,b"
|
- rtttl.play: "write:d=32,o=5,b=100:b,b"
|
||||||
|
|
||||||
- action: write_music_tag
|
- action: write_music_tag
|
||||||
variables:
|
variables:
|
||||||
@@ -117,13 +123,13 @@ api:
|
|||||||
message->add_text_record(text);
|
message->add_text_record(text);
|
||||||
}
|
}
|
||||||
id(pn532_module).write_mode(message);
|
id(pn532_module).write_mode(message);
|
||||||
- rtttl.play: "write:d=24,o=5,b=100:b"
|
- rtttl.play: "write:d=32,o=5,b=100:b"
|
||||||
- wait_until:
|
- wait_until:
|
||||||
not:
|
not:
|
||||||
pn532.is_writing:
|
pn532.is_writing:
|
||||||
- light.turn_off:
|
- light.turn_off:
|
||||||
id: notify_led
|
id: notify_led
|
||||||
- rtttl.play: "write:d=24,o=5,b=100:b,b"
|
- rtttl.play: "write:d=32,o=5,b=100:b,b"
|
||||||
|
|
||||||
globals:
|
globals:
|
||||||
- id: source
|
- id: source
|
||||||
@@ -165,7 +171,7 @@ pn532_i2c:
|
|||||||
id(info)="";
|
id(info)="";
|
||||||
if (tag.has_ndef_message()) {
|
if (tag.has_ndef_message()) {
|
||||||
auto message = tag.get_ndef_message();
|
auto message = tag.get_ndef_message();
|
||||||
auto records = message->get_records();
|
const auto &records = message->get_records();
|
||||||
for (auto &record : records) {
|
for (auto &record : records) {
|
||||||
std::string payload = record->get_payload();
|
std::string payload = record->get_payload();
|
||||||
std::string type = record->get_type();
|
std::string type = record->get_type();
|
||||||
@@ -265,7 +271,7 @@ pn532_i2c:
|
|||||||
condition:
|
condition:
|
||||||
switch.is_on: buzzer_enabled
|
switch.is_on: buzzer_enabled
|
||||||
then:
|
then:
|
||||||
- rtttl.play: "success:d=24,o=5,b=100:c,g,b"
|
- rtttl.play: "success:d=32,o=5,b=100:c,g,b"
|
||||||
on_tag_removed:
|
on_tag_removed:
|
||||||
then:
|
then:
|
||||||
- homeassistant.event:
|
- homeassistant.event:
|
||||||
@@ -307,13 +313,13 @@ button:
|
|||||||
message->add_uri_record(uri);
|
message->add_uri_record(uri);
|
||||||
ESP_LOGD("tagreader", "Writing payload: %s", uri.c_str());
|
ESP_LOGD("tagreader", "Writing payload: %s", uri.c_str());
|
||||||
id(pn532_module).write_mode(message);
|
id(pn532_module).write_mode(message);
|
||||||
- rtttl.play: "write:d=24,o=5,b=100:b"
|
- rtttl.play: "write:d=32,o=5,b=100:b"
|
||||||
- wait_until:
|
- wait_until:
|
||||||
not:
|
not:
|
||||||
pn532.is_writing:
|
pn532.is_writing:
|
||||||
- light.turn_off:
|
- light.turn_off:
|
||||||
id: notify_led
|
id: notify_led
|
||||||
- rtttl.play: "write:d=24,o=5,b=100:b,b"
|
- rtttl.play: "write:d=32,o=5,b=100:b,b"
|
||||||
- platform: template
|
- platform: template
|
||||||
name: Clean Tag
|
name: Clean Tag
|
||||||
id: clean_tag
|
id: clean_tag
|
||||||
@@ -327,13 +333,13 @@ button:
|
|||||||
green: 64.7%
|
green: 64.7%
|
||||||
blue: 0%
|
blue: 0%
|
||||||
- lambda: 'id(pn532_module).clean_mode();'
|
- lambda: 'id(pn532_module).clean_mode();'
|
||||||
- rtttl.play: "write:d=24,o=5,b=100:b"
|
- rtttl.play: "write:d=32,o=5,b=100:b"
|
||||||
- wait_until:
|
- wait_until:
|
||||||
not:
|
not:
|
||||||
pn532.is_writing:
|
pn532.is_writing:
|
||||||
- light.turn_off:
|
- light.turn_off:
|
||||||
id: notify_led
|
id: notify_led
|
||||||
- rtttl.play: "write:d=24,o=5,b=100:b,b"
|
- rtttl.play: "write:d=32,o=5,b=100:b,b"
|
||||||
- platform: template
|
- platform: template
|
||||||
name: Cancel writing
|
name: Cancel writing
|
||||||
id: cancel_writing
|
id: cancel_writing
|
||||||
@@ -343,7 +349,7 @@ button:
|
|||||||
- lambda: 'id(pn532_module).read_mode();'
|
- lambda: 'id(pn532_module).read_mode();'
|
||||||
- light.turn_off:
|
- light.turn_off:
|
||||||
id: notify_led
|
id: notify_led
|
||||||
- rtttl.play: "write:d=24,o=5,b=100:b,b"
|
- rtttl.play: "write:d=32,o=5,b=100:b,b"
|
||||||
|
|
||||||
light:
|
light:
|
||||||
- platform: esp32_rmt_led_strip
|
- platform: esp32_rmt_led_strip
|
||||||
|
|||||||
+15
-3
@@ -1,4 +1,15 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack ATOM Lite + ATOM Hub Switch
|
||||||
|
# Pinout:
|
||||||
|
# GPIO19 -> Light (switch gpio)
|
||||||
|
# GPIO21 -> i2c (i2c scl)
|
||||||
|
# GPIO22 -> Garden Light (switch gpio)
|
||||||
|
# GPIO25 -> i2c (i2c sda)
|
||||||
|
# GPIO26 Grove SDA
|
||||||
|
# GPIO27 NEO (ATOM RGB LED) -> atom_led (status LED, common/status_led_atom.yaml)
|
||||||
|
# GPIO32 Grove SCL
|
||||||
|
# I2C:
|
||||||
|
# 0x27 pca9554_module (pca9554)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: shed
|
device: shed
|
||||||
name: Shed
|
name: Shed
|
||||||
@@ -15,12 +26,16 @@ esp32:
|
|||||||
variant: esp32
|
variant: esp32
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: gd
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
# version: 5.4.2
|
# version: 5.4.2
|
||||||
# platform_version: 54.03.21
|
# platform_version: 54.03.21
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
status_led: !include common/status_led_atom.yaml
|
||||||
|
|
||||||
i2c:
|
i2c:
|
||||||
sda: 25
|
sda: 25
|
||||||
@@ -108,6 +123,3 @@ switch:
|
|||||||
pin:
|
pin:
|
||||||
number: 19
|
number: 19
|
||||||
mode: OUTPUT
|
mode: OUTPUT
|
||||||
|
|
||||||
time:
|
|
||||||
- !include common/time/homeassistant.yaml
|
|
||||||
+13
-14
@@ -1,4 +1,15 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: BlitzWolf BW-SHP2/SHP6
|
||||||
|
# Pinout:
|
||||||
|
# GPIO0 GPIO_LED1_INV Red LED (inverted), Power Status -> led_red (output gpio)
|
||||||
|
# GPIO1 GPIO_USER RXD, Optional sensor
|
||||||
|
# GPIO2 GPIO_LEDLNK_INV Blue LED (inverted), Link Status -> led_blue (output gpio)
|
||||||
|
# GPIO3 GPIO_USER TXD, Optional sensor
|
||||||
|
# GPIO5 GPIO_HJL_CF BL0937 or HJL-01 CF power -> sensor/hlw8012 (sensor hlw8012 cf_pin)
|
||||||
|
# GPIO12 GPIO_NRG_SEL_INV BL0937 or HJL-01 Sel output (0 = Voltage) -> sensor/hlw8012 (sensor hlw8012 sel_pin) (inverted)
|
||||||
|
# GPIO13 GPIO_KEY1 Button -> Button (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO14 GPIO_NRG_CF1 BL0937 or HJL-01 CF1 current / voltage -> sensor/hlw8012 (sensor hlw8012 cf1_pin)
|
||||||
|
# GPIO15 GPIO_REL1 Relay -> Relay (switch gpio)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: socket-01
|
device: socket-01
|
||||||
name: Socket 01
|
name: Socket 01
|
||||||
@@ -18,18 +29,7 @@ esp8266:
|
|||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common_esp8266.yaml
|
common: !include common/common_esp8266.yaml
|
||||||
|
mdns_ipv6: !include common/esp8266_mdns_ipv6.yaml
|
||||||
# BlitzWolf BW-SHP2 and BW-SHP6 (ESP8285 - BL0937 or HJL-01 Energy Monitoring)
|
|
||||||
# Pin Name Function
|
|
||||||
# GPIO15 GPIO_REL1 Relay
|
|
||||||
# GPIO13 GPIO_KEY1 Button
|
|
||||||
# GPIO00 GPIO_LED1_INV Red LED (inverted), Power Status
|
|
||||||
# GPIO02 GPIO_LEDLNK_INV Blue LED (inverted), Link Status
|
|
||||||
# GPIO05 GPIO_HJL_CF BL0937 or HJL-01 CF power
|
|
||||||
# GPIO12 GPIO_NRG_SEL_INV BL0937 or HJL-01 Sel output (0 = Voltage)
|
|
||||||
# GPIO14 GPIO_NRG_CF1 BL0937 or HJL-01 CF1 current / voltage
|
|
||||||
# GPIO01 GPIO_USER RXD, Optional sensor
|
|
||||||
# GPIO03 GPIO_USER TXD, Optional sensor
|
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
@@ -121,8 +121,7 @@ switch:
|
|||||||
# number: GPIO00
|
# number: GPIO00
|
||||||
# inverted: True
|
# inverted: True
|
||||||
|
|
||||||
time:
|
# time:
|
||||||
- !include common/time/homeassistant.yaml
|
|
||||||
# - platform: homeassistant
|
# - platform: homeassistant
|
||||||
# timezone: Europe/Bratislava
|
# timezone: Europe/Bratislava
|
||||||
# on_time:
|
# on_time:
|
||||||
|
|||||||
+13
-14
@@ -1,4 +1,15 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: BlitzWolf BW-SHP2/SHP6
|
||||||
|
# Pinout:
|
||||||
|
# GPIO0 GPIO_LED1_INV Red LED (inverted), Power Status -> led_red (output gpio)
|
||||||
|
# GPIO1 GPIO_USER RXD, Optional sensor
|
||||||
|
# GPIO2 GPIO_LEDLNK_INV Blue LED (inverted), Link Status -> led_blue (output gpio)
|
||||||
|
# GPIO3 GPIO_USER TXD, Optional sensor
|
||||||
|
# GPIO5 GPIO_HJL_CF BL0937 or HJL-01 CF power -> sensor/hlw8012 (sensor hlw8012 cf_pin)
|
||||||
|
# GPIO12 GPIO_NRG_SEL_INV BL0937 or HJL-01 Sel output (0 = Voltage) -> sensor/hlw8012 (sensor hlw8012 sel_pin) (inverted)
|
||||||
|
# GPIO13 GPIO_KEY1 Button -> Button (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO14 GPIO_NRG_CF1 BL0937 or HJL-01 CF1 current / voltage -> sensor/hlw8012 (sensor hlw8012 cf1_pin)
|
||||||
|
# GPIO15 GPIO_REL1 Relay -> Relay (switch gpio)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: socket-02
|
device: socket-02
|
||||||
name: Socket 02
|
name: Socket 02
|
||||||
@@ -18,18 +29,7 @@ esp8266:
|
|||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common_esp8266.yaml
|
common: !include common/common_esp8266.yaml
|
||||||
|
mdns_ipv6: !include common/esp8266_mdns_ipv6.yaml
|
||||||
# BlitzWolf BW-SHP2 and BW-SHP6 (ESP8285 - BL0937 or HJL-01 Energy Monitoring)
|
|
||||||
# Pin Name Function
|
|
||||||
# GPIO15 GPIO_REL1 Relay
|
|
||||||
# GPIO13 GPIO_KEY1 Button
|
|
||||||
# GPIO00 GPIO_LED1_INV Red LED (inverted), Power Status
|
|
||||||
# GPIO02 GPIO_LEDLNK_INV Blue LED (inverted), Link Status
|
|
||||||
# GPIO05 GPIO_HJL_CF BL0937 or HJL-01 CF power
|
|
||||||
# GPIO12 GPIO_NRG_SEL_INV BL0937 or HJL-01 Sel output (0 = Voltage)
|
|
||||||
# GPIO14 GPIO_NRG_CF1 BL0937 or HJL-01 CF1 current / voltage
|
|
||||||
# GPIO01 GPIO_USER RXD, Optional sensor
|
|
||||||
# GPIO03 GPIO_USER TXD, Optional sensor
|
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
@@ -122,8 +122,7 @@ switch:
|
|||||||
on_turn_off:
|
on_turn_off:
|
||||||
- light.turn_off: light_red
|
- light.turn_off: light_red
|
||||||
|
|
||||||
time:
|
# time:
|
||||||
- !include common/time/homeassistant.yaml
|
|
||||||
# - platform: homeassistant
|
# - platform: homeassistant
|
||||||
# timezone: Europe/Bratislava
|
# timezone: Europe/Bratislava
|
||||||
# on_time:
|
# on_time:
|
||||||
|
|||||||
+14
-14
@@ -1,4 +1,15 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: BlitzWolf BW-SHP2/SHP6
|
||||||
|
# Pinout:
|
||||||
|
# GPIO0 GPIO_LED1_INV Red LED (inverted), Power Status -> led_red (output gpio)
|
||||||
|
# GPIO1 GPIO_USER RXD, Optional sensor
|
||||||
|
# GPIO2 GPIO_LEDLNK_INV Blue LED (inverted), Link Status -> led_blue (output gpio)
|
||||||
|
# GPIO3 GPIO_USER TXD, Optional sensor
|
||||||
|
# GPIO5 GPIO_HJL_CF BL0937 or HJL-01 CF power -> sensor/hlw8012 (sensor hlw8012 cf_pin)
|
||||||
|
# GPIO12 GPIO_NRG_SEL_INV BL0937 or HJL-01 Sel output (0 = Voltage) -> sensor/hlw8012 (sensor hlw8012 sel_pin) (inverted)
|
||||||
|
# GPIO13 GPIO_KEY1 Button -> Button (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO14 GPIO_NRG_CF1 BL0937 or HJL-01 CF1 current / voltage -> sensor/hlw8012 (sensor hlw8012 cf1_pin)
|
||||||
|
# GPIO15 GPIO_REL1 Relay -> Relay (switch gpio)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: socket-03
|
device: socket-03
|
||||||
name: Socket 03
|
name: Socket 03
|
||||||
@@ -19,23 +30,13 @@ esphome:
|
|||||||
friendly_name: ${name}
|
friendly_name: ${name}
|
||||||
area: ${area}
|
area: ${area}
|
||||||
comment: ${comment}
|
comment: ${comment}
|
||||||
|
|
||||||
esp8266:
|
esp8266:
|
||||||
board: esp01_1m
|
board: esp01_1m
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common_esp8266.yaml
|
common: !include common/common_esp8266.yaml
|
||||||
|
mdns_ipv6: !include common/esp8266_mdns_ipv6.yaml
|
||||||
# BlitzWolf BW-SHP2 and BW-SHP6 (ESP8285 - BL0937 or HJL-01 Energy Monitoring)
|
|
||||||
# Pin Name Function
|
|
||||||
# GPIO15 GPIO_REL1 Relay
|
|
||||||
# GPIO13 GPIO_KEY1 Button
|
|
||||||
# GPIO00 GPIO_LED1_INV Red LED (inverted), Power Status
|
|
||||||
# GPIO02 GPIO_LEDLNK_INV Blue LED (inverted), Link Status
|
|
||||||
# GPIO05 GPIO_HJL_CF BL0937 or HJL-01 CF power
|
|
||||||
# GPIO12 GPIO_NRG_SEL_INV BL0937 or HJL-01 Sel output (0 = Voltage)
|
|
||||||
# GPIO14 GPIO_NRG_CF1 BL0937 or HJL-01 CF1 current / voltage
|
|
||||||
# GPIO01 GPIO_USER RXD, Optional sensor
|
|
||||||
# GPIO03 GPIO_USER TXD, Optional sensor
|
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
@@ -144,8 +145,7 @@ switch:
|
|||||||
# number: GPIO00
|
# number: GPIO00
|
||||||
# inverted: True
|
# inverted: True
|
||||||
|
|
||||||
time:
|
# time:
|
||||||
- !include common/time/homeassistant.yaml
|
|
||||||
# - platform: homeassistant
|
# - platform: homeassistant
|
||||||
# timezone: Europe/Bratislava
|
# timezone: Europe/Bratislava
|
||||||
# on_time:
|
# on_time:
|
||||||
|
|||||||
+68
-11
@@ -1,3 +1,43 @@
|
|||||||
|
# Hardware: M5Stack CoreS3 + Stack-chan kit
|
||||||
|
# Pinout:
|
||||||
|
# GPIO0 -> i2s_bus (i2s_audio i2s_mclk_pin)
|
||||||
|
# GPIO2 -> Camera (esp32_camera)
|
||||||
|
# GPIO3 -> display_tft (display mipi_spi cs_pin)
|
||||||
|
# GPIO5 -> ir_tx (remote_transmitter)
|
||||||
|
# GPIO6 -> uart_servo (uart tx_pin)
|
||||||
|
# GPIO7 -> uart_servo (uart rx_pin)
|
||||||
|
# GPIO10 -> ir_rx (remote_receiver)
|
||||||
|
# GPIO11 -> i2c_bsp (i2c scl)
|
||||||
|
# GPIO12 -> i2c_bsp (i2c sda)
|
||||||
|
# GPIO13 -> speaker_id (speaker i2s_audio i2s_dout_pin)
|
||||||
|
# GPIO14 -> stackchan_microphone (microphone i2s_audio i2s_din_pin)
|
||||||
|
# GPIO15 -> Camera (esp32_camera data_pins)
|
||||||
|
# GPIO16 -> Camera (esp32_camera data_pins)
|
||||||
|
# GPIO33 -> i2s_bus (i2s_audio i2s_lrclk_pin)
|
||||||
|
# GPIO34 -> i2s_bus (i2s_audio i2s_bclk_pin)
|
||||||
|
# GPIO35 -> display_tft (display mipi_spi dc_pin)
|
||||||
|
# GPIO36 -> spi_bus (spi clk_pin)
|
||||||
|
# GPIO37 -> spi_bus (spi mosi_pin)
|
||||||
|
# GPIO38 -> Camera (esp32_camera href_pin)
|
||||||
|
# GPIO39 -> Camera (esp32_camera data_pins)
|
||||||
|
# GPIO40 -> Camera (esp32_camera data_pins)
|
||||||
|
# GPIO41 -> Camera (esp32_camera data_pins)
|
||||||
|
# GPIO42 -> Camera (esp32_camera data_pins)
|
||||||
|
# GPIO45 -> Camera (esp32_camera pixel_clock_pin)
|
||||||
|
# GPIO46 -> Camera (esp32_camera vsync_pin)
|
||||||
|
# GPIO47 -> Camera (esp32_camera data_pins)
|
||||||
|
# GPIO48 -> Camera (esp32_camera data_pins)
|
||||||
|
# I2C:
|
||||||
|
# 0x23 sensor ltr_als_ps (sensor ltr_als_ps)
|
||||||
|
# 0x34 axp2101_pmu (axp2101)
|
||||||
|
# 0x36 aw88298_dac (audio_dac aw88298)
|
||||||
|
# 0x38 touch_lcd (touchscreen ft63x6)
|
||||||
|
# 0x40 es7210_adc (audio_adc es7210)
|
||||||
|
# 0x41 sensor ina226 (sensor ina226)
|
||||||
|
# 0x51 rtc_time (time bm8563)
|
||||||
|
# 0x58 aw9523b_hub (aw9523b)
|
||||||
|
# 0x68 touch_hub (si12t)
|
||||||
|
# 0x6F m5ioe1_hub (m5ioe1)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: stackchan
|
device: stackchan
|
||||||
name: StackChan
|
name: StackChan
|
||||||
@@ -23,8 +63,11 @@ esphome:
|
|||||||
esp32:
|
esp32:
|
||||||
variant: esp32s3
|
variant: esp32s3
|
||||||
flash_size: 16MB
|
flash_size: 16MB
|
||||||
|
flash_frequency: 40MHz # the IDF 5.5.5 bootloader reads garbage from this flash (mfr 0x46) at 80MHz
|
||||||
toolchain: esp-idf
|
toolchain: esp-idf
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: generic
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
psram:
|
psram:
|
||||||
@@ -33,6 +76,7 @@ psram:
|
|||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
|
||||||
external_components:
|
external_components:
|
||||||
- source: github://m5stack/esphome-yaml/components
|
- source: github://m5stack/esphome-yaml/components
|
||||||
@@ -40,7 +84,7 @@ external_components:
|
|||||||
refresh: 0s
|
refresh: 0s
|
||||||
- source: github://randybb/esphome-components
|
- source: github://randybb/esphome-components
|
||||||
components: [audio_spectrum]
|
components: [audio_spectrum]
|
||||||
refresh: 1d
|
refresh: 1h
|
||||||
|
|
||||||
globals:
|
globals:
|
||||||
- id: in_love
|
- id: in_love
|
||||||
@@ -464,9 +508,9 @@ spi:
|
|||||||
|
|
||||||
image:
|
image:
|
||||||
- platform: file
|
- platform: file
|
||||||
file: assets/images/esphome-logo-text-on-dark.svg
|
file: assets/images/made-for-esphome-white-on-black.svg
|
||||||
id: esphome_logo
|
id: esphome_logo
|
||||||
resize: 280x56
|
resize: 230x68
|
||||||
type: RGB565
|
type: RGB565
|
||||||
transparency: alpha_channel
|
transparency: alpha_channel
|
||||||
- platform: file
|
- platform: file
|
||||||
@@ -545,22 +589,36 @@ display:
|
|||||||
if (id(show_status)) {
|
if (id(show_status)) {
|
||||||
first_draw = true;
|
first_draw = true;
|
||||||
it.fill(id(face_bg));
|
it.fill(id(face_bg));
|
||||||
it.image(160, 45, id(esphome_logo), ImageAlign::CENTER);
|
it.image(160, 46, id(esphome_logo), ImageAlign::CENTER);
|
||||||
it.print(160, 95, id(font_title), id(face_fg), TextAlign::CENTER, "${name}");
|
it.print(160, 95, id(font_title), id(face_fg), TextAlign::CENTER, "${name}");
|
||||||
|
|
||||||
if (wifi_ok) {
|
if (wifi_ok) {
|
||||||
it.printf(20, 135, id(font_status), id(status_ok), "WiFi: %s (%d dBm)",
|
it.printf(20, 114, id(font_status), id(status_ok), "WiFi: connected (%d dBm)", rssi);
|
||||||
id(ip_address_sensor).state.c_str(), rssi);
|
// one global IPv6 (skip link-local) and one IPv4 address
|
||||||
|
int y = 133;
|
||||||
|
char buf[network::IP_ADDRESS_BUFFER_SIZE];
|
||||||
|
for (bool v6 : {true, false}) {
|
||||||
|
for (auto &ip : wifi::global_wifi_component->get_ip_addresses()) {
|
||||||
|
if (!ip.is_set() || ip.is_ip6() != v6)
|
||||||
|
continue;
|
||||||
|
ip.str_to(buf);
|
||||||
|
if (v6 && strncmp(buf, "fe80", 4) == 0)
|
||||||
|
continue;
|
||||||
|
it.print(30, y, id(font_status), id(status_dim), buf);
|
||||||
|
y += 19;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
it.print(20, 135, id(font_status), id(status_wait), "WiFi: connecting...");
|
it.print(20, 114, id(font_status), id(status_wait), "WiFi: connecting...");
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool api_ok = api::global_api_server->is_connected();
|
const bool api_ok = api::global_api_server->is_connected();
|
||||||
it.print(20, 162, id(font_status), api_ok ? id(status_ok) : id(status_wait),
|
it.print(20, 172, id(font_status), api_ok ? id(status_ok) : id(status_wait),
|
||||||
api_ok ? "Home Assistant: connected" : "Home Assistant: waiting...");
|
api_ok ? "Home Assistant: connected" : "Home Assistant: waiting...");
|
||||||
|
|
||||||
if (batt >= 0) {
|
if (batt >= 0) {
|
||||||
it.printf(20, 189, id(font_status), batt <= 20 && !charging ? id(status_low) : id(status_dim),
|
it.printf(20, 191, id(font_status), batt <= 20 && !charging ? id(status_low) : id(status_dim),
|
||||||
"Battery: %d%%%s", batt, charging ? " (charging)" : "");
|
"Battery: %d%%%s", batt, charging ? " (charging)" : "");
|
||||||
}
|
}
|
||||||
it.printf(20, 212, id(font_status), id(status_dim), "ESPHome %s", ESPHOME_VERSION);
|
it.printf(20, 212, id(font_status), id(status_dim), "ESPHome %s", ESPHOME_VERSION);
|
||||||
@@ -867,7 +925,7 @@ light:
|
|||||||
name: LCD Backlight
|
name: LCD Backlight
|
||||||
output: lcd_backlight_output
|
output: lcd_backlight_output
|
||||||
restore_mode: ALWAYS_ON
|
restore_mode: ALWAYS_ON
|
||||||
|
|
||||||
remote_transmitter:
|
remote_transmitter:
|
||||||
id: ir_tx
|
id: ir_tx
|
||||||
pin: 5
|
pin: 5
|
||||||
@@ -883,4 +941,3 @@ time:
|
|||||||
id: rtc_time
|
id: rtc_time
|
||||||
i2c_id: i2c_bsp
|
i2c_id: i2c_bsp
|
||||||
update_interval: never
|
update_interval: never
|
||||||
- !include common/time/homeassistant.yaml
|
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Sonoff Mini
|
||||||
|
# Pinout:
|
||||||
|
# GPIO12 -> relay (output gpio)
|
||||||
|
# GPIO13 -> led_blue (output gpio)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: staircase-light
|
device: staircase-light
|
||||||
name: Staircase
|
name: Staircase
|
||||||
@@ -16,6 +20,7 @@ esp8266:
|
|||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common_esp8266.yaml
|
common: !include common/common_esp8266.yaml
|
||||||
|
mdns_ipv6: !include common/esp8266_mdns_ipv6.yaml
|
||||||
|
|
||||||
# wifi:
|
# wifi:
|
||||||
# use_address: mcu-mini-04.local
|
# use_address: mcu-mini-04.local
|
||||||
@@ -49,8 +54,18 @@ binary_sensor:
|
|||||||
entity_id: binary_sensor.zigbee_staircase_pir_occupancy
|
entity_id: binary_sensor.zigbee_staircase_pir_occupancy
|
||||||
on_state:
|
on_state:
|
||||||
if:
|
if:
|
||||||
condition:
|
condition: &no_motion
|
||||||
binary_sensor.is_off: motion
|
and:
|
||||||
|
- binary_sensor.is_off: motion
|
||||||
|
- binary_sensor.is_off: motion_2
|
||||||
|
then:
|
||||||
|
- light.turn_off: light_relay
|
||||||
|
- platform: homeassistant
|
||||||
|
id: motion_2
|
||||||
|
entity_id: binary_sensor.zigbee_staircase_2_pir_occupancy
|
||||||
|
on_state:
|
||||||
|
if:
|
||||||
|
condition: *no_motion
|
||||||
then:
|
then:
|
||||||
- light.turn_off: light_relay
|
- light.turn_off: light_relay
|
||||||
|
|
||||||
|
|||||||
+243
-79
@@ -1,4 +1,14 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack M5Stamp C3
|
||||||
|
# Pinout:
|
||||||
|
# GPIO0 Grove SCL -> touchscreen/xpt2046 (touchscreen xpt2046 cs_pin)
|
||||||
|
# GPIO1 Grove SDA -> touchscreen/xpt2046 (touchscreen xpt2046 interrupt_pin)
|
||||||
|
# GPIO4 -> spi (spi clk_pin)
|
||||||
|
# GPIO5 -> spi (spi mosi_pin)
|
||||||
|
# GPIO6 -> spi (spi miso_pin)
|
||||||
|
# GPIO7 -> main_display (display mipi_spi cs_pin)
|
||||||
|
# GPIO8 -> main_display (display mipi_spi dc_pin)
|
||||||
|
# GPIO10 -> main_display (display mipi_spi reset_pin)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: tft
|
device: tft
|
||||||
name: TFT
|
name: TFT
|
||||||
@@ -10,104 +20,258 @@ esphome:
|
|||||||
friendly_name: ${name}
|
friendly_name: ${name}
|
||||||
area: ${area}
|
area: ${area}
|
||||||
comment: ${comment}
|
comment: ${comment}
|
||||||
platformio_options:
|
on_boot:
|
||||||
board_build.flash_mode: dio
|
- priority: -100
|
||||||
|
then:
|
||||||
|
- lvgl.page.show: status_page
|
||||||
|
|
||||||
esp32:
|
esp32:
|
||||||
variant: esp32c3
|
variant: esp32c3
|
||||||
framework:
|
framework:
|
||||||
|
advanced:
|
||||||
|
flash_chip: generic
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
|
||||||
logger:
|
api:
|
||||||
logs:
|
# status page until Home Assistant connects (log viewers don't subscribe to states)
|
||||||
component: ERROR
|
on_client_connected:
|
||||||
|
- delay: 2s
|
||||||
# GPIO1 UART TX
|
- if:
|
||||||
# GPIO3 UART RX
|
condition:
|
||||||
# GPIO4 I2C SDA
|
api.connected:
|
||||||
# GPIO5 I2C SCL
|
state_subscription_only: true
|
||||||
# GPIO12 DISPLAY DIO
|
then:
|
||||||
# GPIO12 DISPLAY CLOCK
|
- lvgl.page.show: main_page
|
||||||
# GPIO14 BUZZER
|
on_client_disconnected:
|
||||||
# GPIO16 RGB
|
- if:
|
||||||
|
condition:
|
||||||
|
not:
|
||||||
|
api.connected:
|
||||||
|
state_subscription_only: true
|
||||||
|
then:
|
||||||
|
- lvgl.page.show: status_page
|
||||||
|
|
||||||
spi:
|
spi:
|
||||||
clk_pin: 4
|
clk_pin: 4
|
||||||
mosi_pin: 5
|
mosi_pin: 5
|
||||||
miso_pin: 6
|
miso_pin: 6
|
||||||
|
|
||||||
color:
|
|
||||||
- id: my_green
|
|
||||||
hex: 00ff00
|
|
||||||
- id: my_magenta
|
|
||||||
hex: ff00ff
|
|
||||||
- id: my_red
|
|
||||||
hex: ff0000
|
|
||||||
- id: my_white
|
|
||||||
hex: ffffff
|
|
||||||
|
|
||||||
font:
|
|
||||||
- file: "gfonts://Roboto"
|
|
||||||
id: font_default
|
|
||||||
size: 20
|
|
||||||
- file: "gfonts://B612"
|
|
||||||
id: b612_24
|
|
||||||
size: 24
|
|
||||||
- file: "gfonts://B612"
|
|
||||||
id: b612_16
|
|
||||||
size: 16
|
|
||||||
- file: "gfonts://B612"
|
|
||||||
id: b612_12
|
|
||||||
size: 12
|
|
||||||
- file: "gfonts://B612 Mono"
|
|
||||||
id: b612_24_mono
|
|
||||||
size: 24
|
|
||||||
- file: "gfonts://B612 Mono"
|
|
||||||
id: b612_16_mono
|
|
||||||
size: 16
|
|
||||||
- file: "gfonts://B612 Mono"
|
|
||||||
id: b612_12_mono
|
|
||||||
size: 12
|
|
||||||
- file: "gfonts://Roboto"
|
|
||||||
id: roboto_32
|
|
||||||
size: 32
|
|
||||||
- file: "gfonts://Roboto"
|
|
||||||
id: roboto_24
|
|
||||||
size: 24
|
|
||||||
- file: "gfonts://Roboto"
|
|
||||||
id: roboto_16
|
|
||||||
size: 16
|
|
||||||
- file: "gfonts://Roboto"
|
|
||||||
id: roboto_12
|
|
||||||
size: 12
|
|
||||||
- file: "gfonts://Roboto Mono"
|
|
||||||
id: roboto_32_mono
|
|
||||||
size: 32
|
|
||||||
- file: "gfonts://Roboto Mono"
|
|
||||||
id: roboto_24_mono
|
|
||||||
size: 24
|
|
||||||
- file: "gfonts://Roboto Mono"
|
|
||||||
id: roboto_16_mono
|
|
||||||
size: 16
|
|
||||||
- file: "gfonts://Roboto Mono"
|
|
||||||
id: roboto_12_mono
|
|
||||||
size: 12
|
|
||||||
|
|
||||||
|
|
||||||
display:
|
display:
|
||||||
- platform: mipi_spi
|
- platform: mipi_spi
|
||||||
|
id: main_display
|
||||||
model: ILI9341
|
model: ILI9341
|
||||||
cs_pin: 7
|
cs_pin: 7
|
||||||
dc_pin: 8
|
dc_pin: 8
|
||||||
reset_pin: 10
|
reset_pin: 10
|
||||||
invert_colors: false
|
invert_colors: false
|
||||||
lambda: |-
|
data_rate: 40MHz
|
||||||
it.fill(Color::BLACK);
|
update_interval: never
|
||||||
it.print(0, 0, id(b612_12), id(my_white), TextAlign::TOP_LEFT, "HELLO WORLD!");
|
auto_clear_enabled: false
|
||||||
it.print(0, 14, id(b612_12), id(my_green), TextAlign::TOP_LEFT, "HELLO WORLD!");
|
|
||||||
it.print(0, 28, id(b612_12), id(my_magenta), TextAlign::TOP_LEFT, "HELLO WORLD!");
|
touchscreen:
|
||||||
it.print(0, 42, id(b612_12), id(my_red), TextAlign::TOP_LEFT, "HELLO WORLD!");
|
- platform: xpt2046
|
||||||
|
display: main_display
|
||||||
|
cs_pin: 0
|
||||||
|
interrupt_pin: 1
|
||||||
|
transform:
|
||||||
|
mirror_x: true
|
||||||
|
calibration:
|
||||||
|
x_min: 330
|
||||||
|
x_max: 3620
|
||||||
|
y_min: 230
|
||||||
|
y_max: 3680
|
||||||
|
|
||||||
|
script:
|
||||||
|
- id: update_status
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
// same colors as the other status screens: ok green, waiting orange, details gray
|
||||||
|
static const uint32_t OK = 0x4DD966, WAIT = 0xFFB300;
|
||||||
|
auto set = [](lv_obj_t *label, const std::string &text, uint32_t color) {
|
||||||
|
lv_label_set_text(label, text.c_str());
|
||||||
|
lv_obj_set_style_text_color(label, lv_color_hex(color), LV_PART_MAIN);
|
||||||
|
};
|
||||||
|
|
||||||
|
const bool wifi_ok = wifi::global_wifi_component->is_connected();
|
||||||
|
set(id(status_wifi),
|
||||||
|
wifi_ok ? str_sprintf("WiFi: connected (%d dBm)", wifi::global_wifi_component->wifi_rssi())
|
||||||
|
: std::string("WiFi: connecting..."),
|
||||||
|
wifi_ok ? OK : WAIT);
|
||||||
|
|
||||||
|
// IPv6 first (skip link-local), then IPv4
|
||||||
|
std::string ips;
|
||||||
|
if (wifi_ok) {
|
||||||
|
char buf[network::IP_ADDRESS_BUFFER_SIZE];
|
||||||
|
for (bool v6 : {true, false}) {
|
||||||
|
for (auto &ip : wifi::global_wifi_component->get_ip_addresses()) {
|
||||||
|
if (!ip.is_set() || ip.is_ip6() != v6)
|
||||||
|
continue;
|
||||||
|
ip.str_to(buf);
|
||||||
|
if (v6 && strncmp(buf, "fe80", 4) == 0)
|
||||||
|
continue;
|
||||||
|
if (!ips.empty())
|
||||||
|
ips += "\n";
|
||||||
|
ips += buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lv_label_set_text(id(status_ips), ips.c_str());
|
||||||
|
if (ips.empty())
|
||||||
|
lv_obj_add_flag(id(status_ips), LV_OBJ_FLAG_HIDDEN);
|
||||||
|
else
|
||||||
|
lv_obj_remove_flag(id(status_ips), LV_OBJ_FLAG_HIDDEN);
|
||||||
|
|
||||||
|
const bool api_ok = api::global_api_server->is_connected();
|
||||||
|
set(id(status_ha), api_ok ? "Home Assistant: connected" : "Home Assistant: waiting...",
|
||||||
|
api_ok ? OK : WAIT);
|
||||||
|
|
||||||
|
const uint32_t up = millis() / 1000;
|
||||||
|
lv_label_set_text(id(status_footer),
|
||||||
|
str_sprintf("ESPHome %s\nup %ud %02u:%02u:%02u", ESPHOME_VERSION, up / 86400,
|
||||||
|
(up / 3600) % 24, (up / 60) % 60, up % 60).c_str());
|
||||||
|
interval:
|
||||||
|
- interval: 1s
|
||||||
|
then:
|
||||||
|
- lvgl.label.update:
|
||||||
|
id: clock_label
|
||||||
|
text: !lambda |-
|
||||||
|
auto now = id(ha_time).now();
|
||||||
|
if (!now.is_valid())
|
||||||
|
return std::string("--:--");
|
||||||
|
return now.strftime("%H:%M");
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
lvgl.page.is_showing: status_page
|
||||||
|
then:
|
||||||
|
- script.execute: update_status
|
||||||
|
|
||||||
|
image:
|
||||||
|
- platform: file
|
||||||
|
file: assets/images/made-for-esphome-white-on-black.svg
|
||||||
|
id: esphome_logo
|
||||||
|
resize: 220x65
|
||||||
|
type: RGB565
|
||||||
|
transparency: alpha_channel
|
||||||
|
|
||||||
|
font:
|
||||||
|
- file: "gfonts://Roboto@500"
|
||||||
|
id: font_clock
|
||||||
|
size: 80
|
||||||
|
glyphs: "0123456789:-"
|
||||||
|
- file: "gfonts://Roboto"
|
||||||
|
id: font_title
|
||||||
|
size: 24
|
||||||
|
- file: "gfonts://Roboto"
|
||||||
|
id: font_status
|
||||||
|
size: 14
|
||||||
|
|
||||||
|
lvgl:
|
||||||
|
log_level: WARN
|
||||||
|
color_depth: 16
|
||||||
|
bg_color: 0x000000
|
||||||
|
text_color: 0xFFFFFF
|
||||||
|
theme:
|
||||||
|
button:
|
||||||
|
bg_color: 0x2B2F36
|
||||||
|
radius: 12
|
||||||
|
checked:
|
||||||
|
bg_color: 0xE08A00
|
||||||
|
buttonmatrix:
|
||||||
|
bg_opa: TRANSP
|
||||||
|
border_width: 0
|
||||||
|
items:
|
||||||
|
bg_color: 0x2B2F36
|
||||||
|
text_color: 0xFFFFFF
|
||||||
|
radius: 12
|
||||||
|
checked:
|
||||||
|
bg_color: 0xE08A00
|
||||||
|
top_layer:
|
||||||
|
widgets:
|
||||||
|
# same navigation bar as on the other LVGL displays
|
||||||
|
- buttonmatrix:
|
||||||
|
id: nav_bar
|
||||||
|
align: bottom_mid
|
||||||
|
width: 100%
|
||||||
|
height: 48
|
||||||
|
pad_all: 4
|
||||||
|
pad_column: 6
|
||||||
|
items:
|
||||||
|
text_font: montserrat_20
|
||||||
|
rows:
|
||||||
|
- buttons:
|
||||||
|
- id: page_prev
|
||||||
|
text: ""
|
||||||
|
on_press:
|
||||||
|
then:
|
||||||
|
lvgl.page.previous:
|
||||||
|
- id: page_home
|
||||||
|
text: ""
|
||||||
|
on_press:
|
||||||
|
then:
|
||||||
|
lvgl.page.show: main_page
|
||||||
|
- id: page_next
|
||||||
|
text: ""
|
||||||
|
on_press:
|
||||||
|
then:
|
||||||
|
lvgl.page.next:
|
||||||
|
pages:
|
||||||
|
# 1: clock
|
||||||
|
- id: main_page
|
||||||
|
widgets:
|
||||||
|
- label:
|
||||||
|
id: clock_label
|
||||||
|
align: CENTER
|
||||||
|
y: -24
|
||||||
|
text_font: font_clock
|
||||||
|
text: "--:--"
|
||||||
|
|
||||||
|
# 2: status (shown until Home Assistant connects)
|
||||||
|
- id: status_page
|
||||||
|
on_load:
|
||||||
|
- script.execute: update_status
|
||||||
|
widgets:
|
||||||
|
- image:
|
||||||
|
src: esphome_logo
|
||||||
|
align: TOP_MID
|
||||||
|
y: 8
|
||||||
|
- label:
|
||||||
|
align: TOP_MID
|
||||||
|
y: 78
|
||||||
|
text_font: font_title
|
||||||
|
text: "${name}"
|
||||||
|
- obj:
|
||||||
|
x: 8
|
||||||
|
y: 116
|
||||||
|
width: 224
|
||||||
|
height: SIZE_CONTENT
|
||||||
|
bg_opa: TRANSP
|
||||||
|
border_width: 0
|
||||||
|
pad_all: 0
|
||||||
|
scrollbar_mode: "OFF"
|
||||||
|
layout:
|
||||||
|
type: flex
|
||||||
|
flex_flow: column
|
||||||
|
pad_row: 6
|
||||||
|
widgets:
|
||||||
|
- label:
|
||||||
|
id: status_wifi
|
||||||
|
text_font: font_status
|
||||||
|
text: ""
|
||||||
|
- label:
|
||||||
|
id: status_ips
|
||||||
|
text_font: font_status
|
||||||
|
text_color: 0x8C8C8C
|
||||||
|
text: ""
|
||||||
|
- label:
|
||||||
|
id: status_ha
|
||||||
|
text_font: font_status
|
||||||
|
text: ""
|
||||||
|
- label:
|
||||||
|
id: status_footer
|
||||||
|
text_font: font_status
|
||||||
|
text_color: 0x8C8C8C
|
||||||
|
text: ""
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: LilyGO T-PCIE
|
||||||
substitutions:
|
substitutions:
|
||||||
device: tracker
|
device: tracker
|
||||||
name: Tracker
|
name: Tracker
|
||||||
|
|||||||
+19
-10
@@ -1,4 +1,22 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Huacanxing H801
|
||||||
|
# Pinout:
|
||||||
|
# # H801 LED module
|
||||||
|
# Function Pin Channel
|
||||||
|
# R GPIO15 PWM1
|
||||||
|
# G GPIO13 PWM2
|
||||||
|
# B GPIO12 PWM3
|
||||||
|
# W1 GPIO14 PWM4
|
||||||
|
# W2 GPIO04 PWM5
|
||||||
|
# LED D1 R GPIO05
|
||||||
|
# LED D2 G GPIO01
|
||||||
|
# Used:
|
||||||
|
# GPIO4 pwm_warm_white (output esp8266_pwm)
|
||||||
|
# GPIO5 status_led_id (light status_led)
|
||||||
|
# GPIO12 pwm_blue (output esp8266_pwm)
|
||||||
|
# GPIO13 pwm_green (output esp8266_pwm)
|
||||||
|
# GPIO14 pwm_cold_white (output esp8266_pwm)
|
||||||
|
# GPIO15 pwm_red (output esp8266_pwm)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: tv-light
|
device: tv-light
|
||||||
name: TV Light
|
name: TV Light
|
||||||
@@ -16,16 +34,7 @@ esp8266:
|
|||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common_esp8266.yaml
|
common: !include common/common_esp8266.yaml
|
||||||
|
mdns_ipv6: !include common/esp8266_mdns_ipv6.yaml
|
||||||
## H801 LED module
|
|
||||||
# Function Pin Channel
|
|
||||||
# R GPIO15 PWM1
|
|
||||||
# G GPIO13 PWM2
|
|
||||||
# B GPIO12 PWM3
|
|
||||||
# W1 GPIO14 PWM4
|
|
||||||
# W2 GPIO04 PWM5
|
|
||||||
# LED D1 R GPIO05
|
|
||||||
# LED D2 G GPIO01
|
|
||||||
|
|
||||||
light:
|
light:
|
||||||
- platform: status_led
|
- platform: status_led
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack ATOM Lite
|
||||||
|
# Pinout: see common/vehicle_base.yaml
|
||||||
substitutions:
|
substitutions:
|
||||||
device: vehicle-honda-pcx125
|
device: vehicle-honda-pcx125
|
||||||
name: Vehicle Honda PCX125
|
name: Vehicle Honda PCX125
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack ATOM Lite
|
||||||
|
# Pinout: see common/vehicle_base.yaml
|
||||||
substitutions:
|
substitutions:
|
||||||
device: vehicle-suzuki-dl650
|
device: vehicle-suzuki-dl650
|
||||||
name: Vehicle Suzuki DL650
|
name: Vehicle Suzuki DL650
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack ATOM Lite
|
||||||
|
# Pinout: see common/vehicle_base.yaml
|
||||||
substitutions:
|
substitutions:
|
||||||
device: vehicle-toyota-auris-ts
|
device: vehicle-toyota-auris-ts
|
||||||
name: Vehicle Toyota Auris TS
|
name: Vehicle Toyota Auris TS
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack ATOM Lite
|
||||||
|
# Pinout: see common/vehicle_base.yaml
|
||||||
substitutions:
|
substitutions:
|
||||||
device: vehicle-toyota-yaris-cross
|
device: vehicle-toyota-yaris-cross
|
||||||
name: Vehicle Toyota Yaris Cross
|
name: Vehicle Toyota Yaris Cross
|
||||||
|
|||||||
@@ -1,4 +1,11 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: Sonoff Basic R2
|
||||||
|
# Pinout:
|
||||||
|
# GPIO0 BUTTON -> Button (binary_sensor gpio) (inverted)
|
||||||
|
# GPIO1 TX PIN
|
||||||
|
# GPIO3 RX PIN
|
||||||
|
# GPIO12 RELAY -> Relay (switch gpio)
|
||||||
|
# GPIO13 LED1 -> led (output gpio)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: waterproof-socket
|
device: waterproof-socket
|
||||||
name: Waterproof Socket
|
name: Waterproof Socket
|
||||||
@@ -16,13 +23,7 @@ esp8266:
|
|||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common_esp8266.yaml
|
common: !include common/common_esp8266.yaml
|
||||||
|
mdns_ipv6: !include common/esp8266_mdns_ipv6.yaml
|
||||||
# Sonoff Basic R2
|
|
||||||
# GPIO00 - BUTTON
|
|
||||||
# GPIO12 - RELAY
|
|
||||||
# GPIO13 - LED1
|
|
||||||
# GPIO03 - RX PIN
|
|
||||||
# GPIO01 - TX PIN
|
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
|
|||||||
+14
-3
@@ -1,4 +1,15 @@
|
|||||||
---
|
---
|
||||||
|
# Hardware: M5Stack ATOM Lite + ATOM Hub Switch
|
||||||
|
# Pinout:
|
||||||
|
# GPIO21 -> i2c (i2c scl)
|
||||||
|
# GPIO23 -> modbus_uart (uart tx_pin)
|
||||||
|
# GPIO25 -> i2c (i2c sda)
|
||||||
|
# GPIO26 Grove SDA
|
||||||
|
# GPIO27 NEO (ATOM RGB LED) -> atom_led (status LED, common/status_led_atom.yaml)
|
||||||
|
# GPIO32 Grove SCL
|
||||||
|
# GPIO33 -> modbus_uart (uart rx_pin)
|
||||||
|
# I2C:
|
||||||
|
# 0x27 relay_module (pca9554)
|
||||||
substitutions:
|
substitutions:
|
||||||
device: well
|
device: well
|
||||||
name: Well
|
name: Well
|
||||||
@@ -30,10 +41,13 @@ esp32:
|
|||||||
framework:
|
framework:
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
advanced:
|
advanced:
|
||||||
|
flash_chip: gd
|
||||||
sram1_as_iram: true
|
sram1_as_iram: true
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
common: !include common/common.yaml
|
common: !include common/common.yaml
|
||||||
|
ipv6_only: !include common/ipv6_only.yaml
|
||||||
|
status_led: !include common/status_led_atom.yaml
|
||||||
|
|
||||||
api:
|
api:
|
||||||
actions:
|
actions:
|
||||||
@@ -357,6 +371,3 @@ valve:
|
|||||||
- switch.turn_on: irrigation_relay_8
|
- switch.turn_on: irrigation_relay_8
|
||||||
close_action:
|
close_action:
|
||||||
- switch.turn_off: irrigation_relay_8
|
- switch.turn_off: irrigation_relay_8
|
||||||
|
|
||||||
time:
|
|
||||||
- !include common/time/homeassistant.yaml
|
|
||||||
+10
-1
@@ -1,6 +1,9 @@
|
|||||||
wifi_ssid: "ssid"
|
wifi_ssid: "ssid"
|
||||||
wifi_password: "password"
|
wifi_password: "password"
|
||||||
|
|
||||||
|
wifi_ssid_ipv6: "ssid"
|
||||||
|
wifi_password_ipv6: "password"
|
||||||
|
|
||||||
api_password: "password"
|
api_password: "password"
|
||||||
api_key: "oSsCFxRUqIJLpT98cQwSwNxYoC7zbUh0YBHczAWRyBI="
|
api_key: "oSsCFxRUqIJLpT98cQwSwNxYoC7zbUh0YBHczAWRyBI="
|
||||||
|
|
||||||
@@ -25,4 +28,10 @@ ble_beacon_toyota_auris_major: 10167
|
|||||||
ble_beacon_toyota_auris_minor: 61958
|
ble_beacon_toyota_auris_minor: 61958
|
||||||
ble_beacon_toyota_yaris_uuid: "00000000-0000-0000-0000-000000000000"
|
ble_beacon_toyota_yaris_uuid: "00000000-0000-0000-0000-000000000000"
|
||||||
ble_beacon_toyota_yaris_honda_major: 10167
|
ble_beacon_toyota_yaris_honda_major: 10167
|
||||||
ble_beacon_toyota_yaris_honda_minor: 61958
|
ble_beacon_toyota_yaris_honda_minor: 61958
|
||||||
|
|
||||||
|
# Thread active dataset (hex TLV) from Home Assistant
|
||||||
|
thread_tlv: "0E080000000000010000"
|
||||||
|
|
||||||
|
# ANT+ network key (8 bytes hex), from thisisant.com
|
||||||
|
ant_plus_network_key: "0000000000000000"
|
||||||
Reference in new issue
Block a user