Compare commits

..
21 Commits
Author SHA1 Message Date
randy eea872b930 mcu-stackchan: spectrum analyzer, head touch gestures, status bar
- Winamp style spectrum analyzer instead of the face while music plays,
  using audio_spectrum from randybb/esphome-components
- head touch: tap starts the assistant, stroking shows an in-love face;
  SI12T sensitivity raised so the pads actually trigger
- battery (AXP2101) and wifi indicators, ear icon while listening
2026-09-27 15:19:07 +02:00
randy 39e744900d mcu-stackchan: add M5Stack StackChan config
Voice assistant satellite with animated face on the CoreS3 display:
- power rails, IO expander resets and servo power as in the M5 BSP
- mic and speaker share one I2S bus, so the mic is released before playback
- AW88298 volume limited to the audible range (0.5-1.0)
- partial display redraws, status screen until Home Assistant connects
- battery and wifi indicators, listening icon
- camera converted to JPEG on demand, no periodic frames
2026-09-27 14:02:40 +02:00
randy 6348e6bbb6 mcu-nspanel-*: migrate to native nspanel_lovelace component
CI / ESPHome config validation (push) Failing after 14s
CI / YAML lint (push) Failing after 32s
Switch all NSPanels from the MQTT + AppDaemon based
esphome-nspanel-lovelace-ui to the native component
(randybb/esphome-nspanel-lovelace-native, ref: devices).
Cards and screensaver are now configured directly in ESPHome,
removing the dependency on MQTT and AppDaemon.
2026-09-26 19:31:16 +02:00
randy 6a40e65a4b mcu-nspanel: drop local sk.json, use built-in sk translation from fork 2026-09-26 18:05:23 +02:00
randy a6605fe5e4 Add CLAUDE.md: no Claude attribution in commits/PRs 2026-09-25 23:14:35 +02:00
randyandClaude Sonnet 5 0daecc2fb9 mcu-lvgl-trainer, mcu-lvgl-eworkbench: migrate display to mipi_spi
CI / ESPHome config validation (push) Failing after 8s
CI / YAML lint (push) Failing after 52s
qspi_dbi is deprecated in favor of mipi_spi. Also fixes
mcu-lvgl-trainer's LVGL rotation (must be set on the lvgl component,
not the display, when LVGL is in use) and its deprecated
publish_initial_state -> trigger_on_initial_state. brightness is
dropped since mipi_spi only supports it for AMOLED panels and both
devices already control backlight separately.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 22:56:01 +02:00
randyandClaude Sonnet 5 c9358e7bd6 Rename deprecated light rgb_order to channel_colors
ESPHome renamed the esp32_rmt_led_strip platform's rgb_order option to
channel_colors; update the remaining devices using it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 22:16:30 +02:00
randyandClaude Sonnet 5 173514f73e mcu-echo-1: migrate to speaker-based media_player with mixer
The i2s_audio media_player platform was removed; rebuild the audio
pipeline like mcu-echo.yaml with an i2s_audio speaker feeding a
mixer, so media playback, TTS announcements, and rtttl beeps all
share the one physical DAC output without conflicting. Also uses
format: NONE instead of the deprecated codec_support_enabled.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 22:16:11 +02:00
randyandClaude Sonnet 5 b818b5291b mcu-gate: split OGI detection into steady-state and blink sensors
The single on_multi_click FSM mixed an unbounded "at least 1500ms"
pattern with two bounded blink patterns, which made Open detection
unreliable. Split into two binary_sensor entries sharing the same
pin: a filter-based one for steady Open/Closed, and a dedicated
on_multi_click for the Opening/Closing blink patterns.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 22:09:06 +02:00
randyandClaude Sonnet 5 ab08e9a0af mcu-gateway: migrate modbus_controller off deprecated register_count
register_count is derived from value_type now; drop the now-redundant
register_count: 1 on the temp/humidity sensors, and replace the
Solar Pressure sensor's register_count: 2 (its device always returns
2 registers per read) with a hidden padding sensor on the next
register using reuse_previous_range: true, per the new
modbus_controller range-grouping mechanism.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 21:52:03 +02:00
randyandClaude Sonnet 5 5f966ffba6 mcu-tft: migrate display from deprecated ili9xxx to mipi_spi
ili9xxx is being phased out in favor of the unified mipi_spi driver;
model TFT 2.4 maps to the ILI9341 chip it was already using.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 21:43:14 +02:00
randyandClaude Sonnet 5 cd78449995 mcu-tft: comment out pinned esp-idf/platform version
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 21:39:02 +02:00
randyandClaude Sonnet 5 aaa6418edc mcu-well: add Modbus support for n4dig08 relay module
Adds a UART-based Modbus link plus scripts to toggle channel 1 on the
n4dig08 relay module, and calls relay_module.setup() before each
irrigation switch action.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 21:35:44 +02:00
randyandClaude Sonnet 5 a36dd4447d mcu-well: enable sram1_as_iram to use bootloader's extra 40KB IRAM
Fixes bootloader warning:
[W][app:198]: Bootloader supports SRAM1 as IRAM (+40KB). Set sram1_as_iram: true under esp32 > framework > advanced

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 21:35:38 +02:00
randyandClaude Sonnet 5 f9656a8e4c mcu-well: rename deprecated api services/service to actions/action
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 21:35:14 +02:00
randyandClaude Sonnet 5 c0309c5418 mcu-apollo-dev: explicitly set esp-idf toolchain
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 21:25:38 +02:00
randyandClaude Sonnet 5 c895c821ea mcu-rf: rework RF pin wiring and unify transmit/receive frequency
Move rx/tx off the shared gdo0 pin (21) onto dedicated pins, drop the
now-unneeded allow_other_uses/gdo0_pin workarounds, and align tx/rx
frequency to 433.92MHz.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 21:25:32 +02:00
randyandClaude Sonnet 5 13a5bf04cc mcu-basement: rename sewage treatment blower to aerator pump
Reflects what the device actually controls; renames the entity/id
(blower_auto -> aerator_auto) and display names accordingly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 21:25:22 +02:00
randyandClaude Sonnet 5 176b875bef Rename deprecated light rgb_order to channel_colors
ESPHome renamed the esp32_rmt_led_strip platform's rgb_order option to
channel_colors; update all devices using it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 21:24:58 +02:00
randyandClaude Sonnet 5 56db2c2087 Rename deprecated api services/service to actions/action
ESPHome renamed the api component's services/service keys to
actions/action; update all devices using the old names.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 21:24:36 +02:00
randyandClaude Sonnet 5 468e813958 Stop tracking .device-builder.json state file
It's generated/local state from ESPHome Device Builder that changes
constantly and doesn't belong in version control.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 21:22:20 +02:00
35 changed files with 1754 additions and 1035 deletions

No files matched your search

-5
View File
@@ -1,5 +0,0 @@
{
"_preferences": {
"editor_layout": "both"
}
}
-1
View File
@@ -6,5 +6,4 @@
/secrets.yaml
/archive/
/trash/
.device-builder.yaml
.device-builder.json
+8
View File
@@ -0,0 +1,8 @@
# Git commit attribution
Do not add any Claude/Anthropic attribution to git commits or pull requests in
this repository — no `Co-Authored-By: Claude ...` line, no mention of Claude
anywhere in the commit message or PR description. Commits should look like
they were written entirely by the human author.
This overrides any default Claude Code attribution instructions.
@@ -0,0 +1 @@
<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

After

Width:  |  Height:  |  Size: 4.9 KiB

+2 -2
View File
@@ -49,7 +49,7 @@ light:
- platform: esp32_rmt_led_strip
# name: LED
id: neo
rgb_order: GRB
channel_colors: GRB
pin: 27
num_leds: 1
chipset: ws2812
@@ -57,7 +57,7 @@ light:
- platform: esp32_rmt_led_strip
name: NEO
id: neo_strip
rgb_order: GRB
channel_colors: GRB
pin: 25
num_leds: 7
chipset: ws2812
+5 -4
View File
@@ -14,6 +14,7 @@ esphome:
esp32:
variant: esp32c6
flash_size: 8MB
toolchain: esp-idf
framework:
type: esp-idf
@@ -22,8 +23,8 @@ packages:
api:
# https://github.com/granadaxronos/120-SONG_NOKIA_RTTTL_RINGTONE_PLAYER_FOR_ARDUINO_UNO/blob/master/RTTTL_PLAYER/songs.h
services:
- service: play_rtttl
actions:
- action: play_rtttl
variables:
song: string
then:
@@ -49,7 +50,7 @@ light:
id: rgb_leds
chipset: WS2812
num_leds: 10
rgb_order: GRB
channel_colors: GRB
rmt_symbols: 48
effects:
# Use default parameters:
@@ -76,7 +77,7 @@ light:
id: onboard_rgb_led
chipset: WS2812
num_leds: 1
rgb_order: GRB
channel_colors: GRB
rmt_symbols: 48
output:
+17 -17
View File
@@ -27,7 +27,7 @@ packages:
# GPIO13 Blue Status LED
globals:
- id: blower_auto
- id: aerator_auto
type: bool
restore_value: true
initial_value: "true"
@@ -44,15 +44,15 @@ binary_sensor:
- min_length: 50ms
max_length: 350ms
then:
- homeassistant.service:
service: light.toggle
- homeassistant.action:
action: light.toggle
data:
entity_id: light.mcu_basement_2_light
- min_length: 351ms
max_length: 1000ms
then:
- homeassistant.service:
service: light.toggle
- homeassistant.action:
action: light.toggle
data:
entity_id: light.exercise_room
- min_length: 1001ms
@@ -62,12 +62,12 @@ binary_sensor:
# service: light.turn_off
# data:
# entity_id: light.basement_light
- homeassistant.service:
service: light.turn_off
- homeassistant.action:
action: light.turn_off
data:
entity_id: light.exercise_room
- homeassistant.service:
service: light.turn_off
- homeassistant.action:
action: light.turn_off
data:
entity_id: light.exercise_room_fan
- platform: gpio
@@ -88,14 +88,14 @@ binary_sensor:
filters:
invert:
on_press:
- homeassistant.service:
service: light.turn_on
- homeassistant.action:
action: light.turn_on
data:
entity_id: light.mcu_basement_2_light
select:
- platform: template
name: Sewage Treatment Blower
name: Sewage Treatment Aerator Pump
icon: mdi:hair-dryer-outline
optimistic: true
options:
@@ -109,14 +109,14 @@ select:
- lambda: |-
switch (i) {
case 0: {
id(blower_auto) = false;
id(aerator_auto) = false;
id(relay_1).turn_on();
} break;
case 1: {
id(blower_auto) = true;
id(aerator_auto) = true;
} break;
case 2:
id(blower_auto) = false;
id(aerator_auto) = false;
id(relay_1).turn_off();
}
@@ -127,7 +127,7 @@ status_led:
switch:
- platform: gpio
name: Sewage Treatment Blower
name: Sewage Treatment Aerator Pump
icon: mdi:hair-dryer-outline
pin: 12
id: relay_1
@@ -147,7 +147,7 @@ time:
then:
- if:
condition:
lambda: 'return id(blower_auto);'
lambda: 'return id(aerator_auto);'
then:
- switch.turn_on: relay_1
- delay: 12min
+4 -4
View File
@@ -114,8 +114,8 @@ script:
# make use of the following service.
api:
reboot_timeout: 0s
services:
- service: activate_preset
actions:
- action: activate_preset
variables:
my_group: string
my_preset: string
@@ -279,8 +279,8 @@ sensor:
lambda: |-
return id(group_control);
then:
- homeassistant.service:
service: light.turn_on
- homeassistant.action:
action: light.turn_on
data:
light_name: bedroom_lamp
brightness: !lambda return x;
+2 -2
View File
@@ -111,8 +111,8 @@ script:
# make use of the following service.
api:
reboot_timeout: 0s
services:
- service: activate_preset
actions:
- action: activate_preset
variables:
my_group: string
my_preset: string
+1 -1
View File
@@ -56,7 +56,7 @@ light:
- platform: esp32_rmt_led_strip
name: LED
id: led
rgb_order: GRB
channel_colors: GRB
pin: 8
num_leds: 1
# rmt_channel: 0
+1 -1
View File
@@ -56,7 +56,7 @@ light:
- platform: esp32_rmt_led_strip
name: LED
id: led
rgb_order: GRB
channel_colors: GRB
pin: 8
num_leds: 1
# rmt_channel: 0
+1 -1
View File
@@ -71,7 +71,7 @@ light:
- platform: esp32_rmt_led_strip
name: LED
id: led
rgb_order: GRB
channel_colors: GRB
pin: 27
num_leds: 1
chipset: ws2812
+2 -2
View File
@@ -41,8 +41,8 @@ packages:
# https://github.com/granadaxronos/120-SONG_NOKIA_RTTTL_RINGTONE_PLAYER_FOR_ARDUINO_UNO/blob/master/RTTTL_PLAYER/songs.h
api:
services:
- service: play_rtttl
actions:
- action: play_rtttl
variables:
song: string
then:
+3 -3
View File
@@ -30,8 +30,8 @@ packages:
# https://github.com/granadaxronos/120-SONG_NOKIA_RTTTL_RINGTONE_PLAYER_FOR_ARDUINO_UNO/blob/master/RTTTL_PLAYER/songs.h
api:
services:
- service: play_rtttl
actions:
- action: play_rtttl
variables:
song: string
then:
@@ -96,7 +96,7 @@ light:
- platform: esp32_rmt_led_strip
name: LED
id: led
rgb_order: GRB
channel_colors: GRB
pin: 27
num_leds: 1
chipset: ws2812
+1 -1
View File
@@ -123,7 +123,7 @@ light:
- platform: esp32_rmt_led_strip
name: LED
id: led
rgb_order: GRB
channel_colors: GRB
pin: 27
num_leds: 1
# rmt_channel: 0
+43 -38
View File
@@ -15,33 +15,15 @@ esphome:
esp32:
variant: esp32
framework:
type: arduino
# version: 2.0.14
# platform_version: 6.5.0
# type: esp-idf
# version: 5.1.2
# platform_version: 6.5.0
external_components:
- source: components
# - source:
# type: git
# url: https://github.com/nielsnl68/esphome
# ref: nvds-RTTTL_I2S
# components: [ speaker, rtttl ]
# refresh: 0s
- source: github://pr#5177
components: [rtttl]
refresh: 0s
type: esp-idf
packages:
common: !include common/common_esp8266.yaml # this profile is without fancy features that are not supported by arduino
common: !include common/common.yaml
api:
services:
actions:
# https://github.com/granadaxronos/120-SONG_NOKIA_RTTTL_RINGTONE_PLAYER_FOR_ARDUINO_UNO/blob/master/RTTTL_PLAYER/songs.h
- service: play_rtttl
- action: play_rtttl
variables:
song: string
then:
@@ -81,7 +63,7 @@ light:
- platform: esp32_rmt_led_strip
name: LED
id: neo_buildin
rgb_order: GRB
channel_colors: GRB
pin: 27
num_leds: 1
chipset: ws2812
@@ -110,35 +92,58 @@ light:
# # brightness: 30%
i2s_audio:
- id: speaker_bus
i2s_lrclk_pin: 33
i2s_bclk_pin: 19
media_player:
- platform: i2s_audio
id: media_out
name: ${name} Player
dac_type: external
i2s_dout_pin:
number: 22
allow_other_uses: true
mode: mono
speaker:
- platform: i2s_audio
id: echo_speaker
id: speaker_id
i2s_audio_id: speaker_bus
dac_type: external
i2s_dout_pin:
number: 22
allow_other_uses: true
i2s_dout_pin: 22
channel: mono
sample_rate: 16000
buffer_duration: 100ms
- platform: mixer
id: mixer_speaker_id
output_speaker: speaker_id
num_channels: 1
task_stack_in_psram: false
source_speakers:
- id: announcement_spk_mixer_input
- id: media_spk_mixer_input
- id: rtttl_spk_mixer_input
- platform: resampler
id: media_spk_resampling_input
output_speaker: media_spk_mixer_input
- platform: resampler
id: announcement_spk_resampling_input
output_speaker: announcement_spk_mixer_input
- platform: resampler
id: rtttl_spk_resampling_input
output_speaker: rtttl_spk_mixer_input
media_player:
- platform: speaker
id: media_out
name: ${name} Player
buffer_size: 14000
media_pipeline:
speaker: media_spk_resampling_input
format: NONE
announcement_pipeline:
speaker: announcement_spk_resampling_input
format: NONE
rtttl:
id: my_rtttl
speaker: echo_speaker
speaker: rtttl_spk_resampling_input
microphone:
- platform: i2s_audio
id: echo_microphone
i2s_audio_id: speaker_bus
i2s_din_pin: 23
adc_type: external
pdm: true
+2 -2
View File
@@ -22,9 +22,9 @@ packages:
common: !include common/common.yaml
api:
services:
actions:
# https://github.com/granadaxronos/120-SONG_NOKIA_RTTTL_RINGTONE_PLAYER_FOR_ARDUINO_UNO/blob/master/RTTTL_PLAYER/songs.h
- service: play_rtttl
- action: play_rtttl
variables:
song: string
then:
+24 -17
View File
@@ -136,32 +136,39 @@ binary_sensor:
on_press: !include {file: common/gate_beacon_open.yaml, vars: {enable_id: enable_dl650}}
on_release: !include {file: common/gate_beacon_close.yaml, vars: {enable_id: enable_dl650}}
- platform: gpio
id: gate_ogi
id: gate_ogi_state
pin:
number: 32
inverted: true
allow_other_uses: true
mode:
input: true
filters:
- delayed_on_off: 10ms
- delayed_on_off: 1500ms
entity_category: diagnostic
on_press:
- select.set:
id: gate_state
option: Open
- logger.log: "OGI ON (steady) => GATE OPEN"
on_release:
- select.set:
id: gate_state
option: Closed
- logger.log: "OGI OFF (steady) => GATE CLOSED"
- platform: gpio
id: gate_ogi_blink
pin:
number: 32
inverted: true
allow_other_uses: true
mode:
input: true
filters:
- delayed_on_off: 10ms
entity_category: diagnostic
on_multi_click:
- timing:
- OFF for at least 1500ms
then:
- select.set:
id: gate_state
option: Closed
- logger.log: "OGI OFF => GATE CLOSED"
invalid_cooldown: 100ms
- timing:
- ON for at least 1500ms
then:
- select.set:
id: gate_state
option: Open
- logger.log: "OGI ON => GATE OPEN"
invalid_cooldown: 100ms
- timing:
- ON for 400ms to 500ms
- OFF for 400ms to 500ms
+8 -3
View File
@@ -129,7 +129,6 @@ sensor:
register_type: read
value_type: U_WORD
accuracy_decimals: 1
register_count: 1
filters:
- multiply: 0.1
- platform: modbus_controller
@@ -152,7 +151,6 @@ sensor:
register_type: read
value_type: U_WORD
accuracy_decimals: 1
register_count: 1
filters:
- multiply: 0.1
- platform: modbus_controller
@@ -192,11 +190,18 @@ sensor:
register_type: holding
value_type: U_WORD
accuracy_decimals: 1
register_count: 2
filters:
- calibrate_linear:
- 50 -> 0
- 450 -> 5
- platform: modbus_controller
modbus_controller_id: modbus_adc_1
id: adc_1_1_padding
internal: true
address: 1
register_type: holding
value_type: U_WORD
reuse_previous_range: true
switch:
- platform: modbus_controller
+1 -1
View File
@@ -49,7 +49,7 @@ light:
- platform: esp32_rmt_led_strip
# name: LED
id: neo
rgb_order: GRB
channel_colors: GRB
pin: 27
num_leds: 1
chipset: ws2812
+2 -3
View File
@@ -105,8 +105,8 @@ power_supply:
enable_on_boot: true
display:
- platform: qspi_dbi
model: axs15231
- platform: mipi_spi
model: AXS15231
data_rate: 40MHz #20mhz is default
#spi_mode: MODE2
id: main_display
@@ -115,7 +115,6 @@ display:
height: 480
width: 320
cs_pin: 45
brightness: 50
rotation: 90
auto_clear_enabled: false
show_test_card: true
+5 -6
View File
@@ -116,8 +116,8 @@ light:
default_transition_length: 500ms
display:
- platform: qspi_dbi
model: axs15231
- platform: mipi_spi
model: AXS15231
data_rate: 40MHz #20mhz is default
#spi_mode: MODE2
id: main_display
@@ -126,8 +126,6 @@ display:
height: 480
width: 320
cs_pin: 45
brightness: 50
rotation: 90
auto_clear_enabled: false
# show_test_card: true
# lambda: |-
@@ -187,7 +185,7 @@ binary_sensor:
- platform: homeassistant
id: exercise_room_light
entity_id: light.exercise_room
publish_initial_state: true
trigger_on_initial_state: true
on_state:
then:
lvgl.widget.update:
@@ -197,7 +195,7 @@ binary_sensor:
- platform: homeassistant
id: exercise_room_fan
entity_id: light.mcu_dimmer_exercise_room_fan
publish_initial_state: true
trigger_on_initial_state: true
on_state:
then:
lvgl.widget.update:
@@ -206,6 +204,7 @@ binary_sensor:
checked: !lambda return x;
lvgl:
rotation: 90
buffer_size: 100%
log_level: WARN
color_depth: 16
+104 -129
View File
@@ -5,10 +5,6 @@ substitutions:
name_short: Bedroom
area: Bedroom
comment: NSPanel
panel_recv_topic: "tele/${device}/RESULT"
panel_send_topic: "cmnd/${device}/CustomSend"
tft_url: !secret tft_url
esphome:
name: mcu-${device}
@@ -20,6 +16,8 @@ esphome:
- 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
@@ -33,133 +31,55 @@ esp32:
external_components:
- source:
type: git
url: https://github.com/sairon/esphome-nspanel-lovelace-ui
ref: dev
url: https://github.com/randybb/esphome-nspanel-lovelace-native
ref: devices
refresh: 0s
components: [nspanel_lovelace]
packages:
common: !include common/common.yaml
script:
- id: apply_sleep_dim
then:
- lambda: |-
uint8_t dim;
if (id(bedroom_lights).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);
api:
# https://github.com/granadaxronos/120-SONG_NOKIA_RTTTL_RINGTONE_PLAYER_FOR_ARDUINO_UNO/blob/master/RTTTL_PLAYER/songs.h
services:
- service: play_rtttl
homeassistant_services: true
homeassistant_states: true
actions:
- action: play_rtttl
variables:
song: string
then:
- rtttl.play:
rtttl: !lambda 'return song;'
- service: notify
- action: notify
variables:
heading: string
message: string
song: string
then:
- lambda: 'id(nspanel_id).send_custom_command("notify~" + heading + "~" + message);'
- lambda: 'id(nspanel_id).notify_on_screensaver(heading, message, 10000);'
- rtttl.play:
rtttl: !lambda 'return song;'
- delay: 10s
- lambda: 'id(nspanel_id).send_custom_command("notify~~");'
- service: update_tft
then:
- lambda: |-
id(nspanel_id).upload_tft("${tft_url}");
- service: upload_tft
variables:
url: string
then:
- lambda: |-
id(nspanel_id).upload_tft(url);
# Service to send a command directly to the display. Useful for testing
- service: send_command
variables:
cmd: string
then:
- lambda: "id(nspanel_id).send_custom_command(cmd.c_str());"
# Service to pusblish to mqtt used for refreshin the panel
- service: publish_to_recv_topic
variables:
cmd: string
then:
- mqtt.publish:
topic: $panel_recv_topic
payload: !lambda "return cmd;"
# Service to send a command wake the screen
- service: wake
then:
- lambda: 'id(nspanel_id).send_custom_command("wake");'
# Service to send a command to show screensaver (some of the values are hardcoded)
- service: show_screensaver
then:
- mqtt.publish:
topic: $panel_recv_topic
payload: '{"CustomRecv":"event,sleepReached,cardGrid"}'
# Service to navigate to screen
- service: navigate_to_page
variables:
page: string
then:
- mqtt.publish_json:
topic: $panel_recv_topic
payload: |-
root["CustomRecv"] = "event,buttonPress2,navigate." + page + ",button";
# Service to send a command disable screensaver
- service: disable_screensaver
then:
- lambda: 'id(nspanel_id).send_custom_command("timeout~0");'
# Service to send a command enabled screensaver
- service: enable_screensaver
then:
- lambda: 'id(nspanel_id).send_custom_command("timeout~20");'
# Service to send a command wake the screen
- service: dim_0_to_100
variables:
intensity: string
then:
- lambda: 'id(nspanel_id).send_custom_command("dimmode~"+intensity+"~100");'
# Service to send a command To show the screen of a specific like
- service: show_entity
variables:
entity: string
title: string
then:
- lambda: 'id(nspanel_id).send_custom_command("pageType~popupLight~" + title + "~" + entity);'
# Service to send a command To show the screen of a specific like
- service: notify_on_screensaver
variables:
line1: string
line2: string
then:
- lambda: 'id(nspanel_id).send_custom_command("notify~" + line1 + "~" + line2);'
- rtttl.play: "short:d=4,o=5,b=100:16e6"
# Service to send a command To show the screen of a specific like
# interaction of the buttons are on implemented yet
- service: notify_fullscreen
- action: notify_fullscreen
variables:
title: string
description: string
button1: string
button2: string
time_secs: string
timeout: int
icon: string
then:
# show notification screen
- lambda: 'id(nspanel_id).send_custom_command("pageType~popupNotify");'
# set values on notification screen
# color defined as number created in binary and converted to decimal (rrrrggggbbbbaaaa)
- lambda: 'id(nspanel_id).send_custom_command("entityUpdateDetail~id~"+ title + "~65535~" + button1 +"~3840~" + button2 + "~61440~" + description + "~65535~" + time_secs);'
- 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:
@@ -168,24 +88,59 @@ uart:
rx_pin: 17
baud_rate: 115200
mqtt:
id: mqtt_client
broker: !secret mqtt_ip
username: !secret mqtt_username
password: !secret mqtt_password
discovery: false
idf_send_async: true
reboot_timeout: 0s
nspanel_lovelace:
id: nspanel_id
mqtt_recv_topic: $panel_recv_topic
mqtt_send_topic: $panel_send_topic
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:
- type: cardGrid
title: Spálňa
entities:
- name: TV
entity_id: switch.mcu_socket_01_relay
icon: television-classic
- name: Raid
entity_id: switch.mcu_socket_02_relay
icon: emoticon-dead
- name: ""
entity_id: switch.mcu_socket_03_relay
icon: power-socket-fr
- name: Svetlo
entity_id: light.mcu_nspanel_bedroom_light
icon: wall-sconce-flat
- name: Nočná lampa J
entity_id: light.mcu_bedroom_lamp_right_light
icon: lamp
- name: Nočná lampa R
entity_id: light.mcu_bedroom_lamp_left_light
icon: lamp
- type: cardThermo
title: Kúrenie
thermo_entity_id: climate.bt_trv_bedroom
time:
- platform: homeassistant
id: ha_time
timezone: Europe/Bratislava
on_time_sync:
- script.execute: apply_sleep_dim
binary_sensor:
- platform: gpio
@@ -195,10 +150,7 @@ binary_sensor:
inverted: true
on_click:
- light.toggle: light_1
- mqtt.publish_json:
topic: $panel_recv_topic
payload: |-
root["CustomRecv"] = "event,buttonPress2,navigate.cardGrid_main,button";
- lambda: 'id(nspanel_id).render_default_page();'
- platform: gpio
name: Right Button
@@ -208,14 +160,17 @@ binary_sensor:
# on_click:
# - switch.toggle: relay_2
on_click:
- homeassistant.service:
service: light.toggle
- homeassistant.action:
action: light.toggle
data:
entity_id: light.bedroom_lamps
- mqtt.publish_json:
topic: $panel_recv_topic
payload: |-
root["CustomRecv"] = "event,buttonPress2,navigate.cardGrid_main,button";
- 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:
- platform: binary
@@ -237,6 +192,20 @@ output:
# pin:
# 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
@@ -265,13 +234,19 @@ sensor:
resistor: 11.2kOhm
- platform: ntc
name: Temperature
id: temperature
sensor: resistance_sensor
calibration:
b_constant: 3950
reference_temperature: 25°C
reference_resistance: 10kOhm
name: Temperature
- platform: template
id: room_temperature_id
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();
+58 -35
View File
@@ -39,8 +39,6 @@ esp32:
advanced:
minimum_chip_revision: 3.0
sram1_as_iram: true
include_builtin_idf_components:
- esp_http_client
external_components:
# - source:
@@ -51,8 +49,10 @@ external_components:
# components: [nspanel_lovelace]
- source:
type: git
url: https://github.com/olicooper/esphome-nspanel-lovelace-native
ref: dev
# url: https://github.com/olicooper/esphome-nspanel-lovelace-native
# ref: dev
url: https://github.com/randybb/esphome-nspanel-lovelace-native
ref: devices
refresh: 0s
components: [nspanel_lovelace]
# - source: components
@@ -68,23 +68,22 @@ packages:
api:
homeassistant_services: true
homeassistant_states: true
services:
actions:
# https://github.com/granadaxronos/120-SONG_NOKIA_RTTTL_RINGTONE_PLAYER_FOR_ARDUINO_UNO/blob/master/RTTTL_PLAYER/songs.h
- service: play_rtttl
- action: play_rtttl
variables:
song: string
then:
- rtttl.play:
rtttl: !lambda 'return song;'
- service: notify
- action: notify
variables:
heading: string
message: string
song: string
then:
- lambda: 'id(nspanel_id).notify_on_screensaver(heading, message, 10000);'
# - lambda: 'id(nspanel_id).send_custom_command("notify~" + heading + "~" + message);'
- rtttl.play:
rtttl: !lambda 'return song;'
# - delay: 10s
@@ -177,7 +176,7 @@ api:
# Service to send a command To show the screen of a specific like
# interaction of the buttons are on implemented yet
- service: notify_fullscreen
- action: notify_fullscreen
variables:
title: string
description: string
@@ -203,15 +202,37 @@ uart:
nspanel_lovelace:
id: nspanel_id
sleep_timeout: 10
experimental_vertical_ui: true
locale:
language: nspanel/sk.json
language: sk
temperature_unit: celcius
screensaver:
time_id: ha_time
time_format: '%H:%M~$name_day'
time_format: '%H:%M'
date_format: '%A, %d. %b. %Y'
weather:
entity_id: sensor.weather_forecast_daily
# entity_id: weather.openweathermap
# forecast_method: service
icon_color: [255, 255, 255]
entities:
- entity_id: sensor.zigbee_office_r_temperature
icon:
value: home-thermometer-outline
color: [255, 255, 255]
precision: 1
# type: screensaver2
## Custom entities, filled into the layout slots in order after the weather items.
## Use 'entity_id: delete' to leave a slot empty.
## screensaver: weather main + 4 forecast items, 1 extra entity switches to the alternative layout (max 6 items)
## screensaver2: weather main only, then 3 left + 6 bottom + 5 indicator icons (max 15 items)
# entities:
# - entity_id: sensor.outside_humidity
# name: Humidity
# icon: water-percent
# - entity_id: delete
# - entity_id: binary_sensor.front_door
# type: screensaver2
# statusIcon1:
# entity: switch.office_r_light
@@ -281,7 +302,7 @@ nspanel_lovelace:
entity_id: light.living_room
icon: ceiling-light
- name: TV
entity_id: light.tv_light
entity_id: light.mcu_tv_light_light
icon: led-strip-variant
- name: (Stôl)
entity_id: light.dining_table_ambilight
@@ -293,7 +314,7 @@ nspanel_lovelace:
title: Romanko
entities:
- name: Svetlo
entity_id: switch.office_r_light
entity_id: light.mcu_nspanel_office_r_light
icon: wall-sconce-flat
- name: LED pásik
entity_id: light.office_r_desk_strip
@@ -305,40 +326,38 @@ nspanel_lovelace:
- name: (Monitor)
entity_id: light.office_r_display_lamp_ambilight
icon: monitor-star
- name: Whitebox
entity_id: switch.whitebox
- type: cardGrid
title: Von
entities:
- name: Terasa
entity_id: light.patio_light
entity_id: light.patio_lights
icon: lightbulb-group
- name: Terasa
entity_id: switch.patio_relay
entity_id: switch.mcu_patio_relay
icon: power-socket-fr
- name: Vzadu
entity_id: switch.outside_light_back
entity_id: switch.mcu_nspanel_patio_outside_light_back
icon: light-flood-down
- name: Z. domček
entity_id: switch.shed_light
entity_id: switch.mcu_shed_light
icon: wall-sconce-flat
# state_template: '{{ is_state("binary_sensor.shed_status", "off") }}'
- name: Z. domček
entity_id: switch.shed_socket
entity_id: switch.mcu_shed_socket
icon: power-socket-fr
# state_template: '{{ is_state("binary_sensor.shed_status", "off") }}'
- name: Záhrada
entity_id: switch.garden_light
entity_id: switch.mcu_shed_garden_light
icon: light-flood-down
# state_template: '{{ is_state("binary_sensor.shed_status", "off") }}'
- type: cardGrid
title: Brána
entities:
- name: Otvoriť
entity_id: button.gate_open
entity_id: button.mcu_gate_open
icon: gate-open
- name: Zatvoriť
entity_id: button.gate_close
entity_id: button.mcu_gate_close
icon: gate
- name: Automatizácia
entity_id: navigate.card_gate_automation
@@ -346,19 +365,19 @@ nspanel_lovelace:
title: Závlaha
entities:
- name: A1
entity_id: switch.irrigation_valve_a1
entity_id: switch.mcu_well_irrigation_valve_a1
icon: valve
- name: A2
entity_id: switch.irrigation_valve_a2
entity_id: switch.mcu_well_irrigation_valve_a2
icon: valve
- name: A3
entity_id: switch.irrigation_valve_a3
entity_id: switch.mcu_well_irrigation_valve_a3
icon: valve
- name: A4
entity_id: switch.irrigation_valve_a4
entity_id: switch.mcu_well_irrigation_valve_a4
icon: valve
- name: A5
entity_id: switch.irrigation_valve_a5
entity_id: switch.mcu_well_irrigation_valve_a5
icon: valve
- name: Automatizácia
entity_id: navigate.card_irrigation_automation
@@ -381,13 +400,13 @@ nspanel_lovelace:
title: Zwift
entities:
- name: Svetlo
entity_id: light.basement_light
entity_id: light.mcu_basement_light
icon: lightbulb-multiple
- name: LED
entity_id: light.exercise_room
icon: led-strip-variant
- name: Ventilátor
entity_id: light.exercise_room_fan
entity_id: light.mcu_dimmer_exercise_room_fan
icon: fan
- name: Automatizácia
entity_id: navigate.card_exercise_automation
@@ -421,11 +440,6 @@ nspanel_lovelace:
- name: Rast trávy
entity_id: automation.irrigation_grow_grass
time:
- platform: homeassistant
id: ha_time
timezone: Europe/Bratislava
binary_sensor:
- platform: gpio
name: Left Button
@@ -526,10 +540,19 @@ sensor:
- platform: template
id: room_temperature_id
time:
platform: homeassistant
id: ha_time
timezone: Europe/Bratislava
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();
# esp32_ble_tracker:
# scan_parameters:
+143 -142
View File
@@ -4,9 +4,6 @@ substitutions:
name: Fireplace NSPanel
area: Living Room & Kitchen
comment: NSPanel
panel_recv_topic: "tele/${device}/RESULT"
panel_send_topic: "cmnd/${device}/CustomSend"
tft_url: !secret tft_url
esphome:
name: mcu-${device}
@@ -18,6 +15,8 @@ esphome:
- 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
@@ -31,133 +30,45 @@ esp32:
external_components:
- source:
type: git
url: https://github.com/sairon/esphome-nspanel-lovelace-ui
ref: dev
url: https://github.com/randybb/esphome-nspanel-lovelace-native
ref: devices
refresh: 0s
components: [nspanel_lovelace]
packages:
common: !include common/common.yaml
api:
# https://github.com/granadaxronos/120-SONG_NOKIA_RTTTL_RINGTONE_PLAYER_FOR_ARDUINO_UNO/blob/master/RTTTL_PLAYER/songs.h
services:
- service: play_rtttl
homeassistant_services: true
homeassistant_states: true
actions:
- action: play_rtttl
variables:
song: string
then:
- rtttl.play:
rtttl: !lambda 'return song;'
- service: notify
- action: notify
variables:
heading: string
message: string
song: string
then:
- lambda: 'id(nspanel_id).send_custom_command("notify~" + heading + "~" + message);'
- lambda: 'id(nspanel_id).notify_on_screensaver(heading, message, 10000);'
- rtttl.play:
rtttl: !lambda 'return song;'
- delay: 10s
- lambda: 'id(nspanel_id).send_custom_command("notify~~");'
- service: update_tft
then:
- lambda: |-
id(nspanel_id).upload_tft("${tft_url}");
- service: upload_tft
variables:
url: string
then:
- lambda: |-
id(nspanel_id).upload_tft(url);
# Service to send a command directly to the display. Useful for testing
- service: send_command
variables:
cmd: string
then:
- lambda: "id(nspanel_id).send_custom_command(cmd.c_str());"
# Service to pusblish to mqtt used for refreshin the panel
- service: publish_to_recv_topic
variables:
cmd: string
then:
- mqtt.publish:
topic: $panel_recv_topic
payload: !lambda "return cmd;"
# Service to send a command wake the screen
- service: wake
then:
- lambda: 'id(nspanel_id).send_custom_command("wake");'
# Service to send a command to show screensaver (some of the values are hardcoded)
- service: show_screensaver
then:
- mqtt.publish:
topic: $panel_recv_topic
payload: '{"CustomRecv":"event,sleepReached,cardGrid"}'
# Service to navigate to screen
- service: navigate_to_page
variables:
page: string
then:
- mqtt.publish_json:
topic: $panel_recv_topic
payload: |-
root["CustomRecv"] = "event,buttonPress2,navigate." + page + ",button";
# Service to send a command disable screensaver
- service: disable_screensaver
then:
- lambda: 'id(nspanel_id).send_custom_command("timeout~0");'
# Service to send a command enabled screensaver
- service: enable_screensaver
then:
- lambda: 'id(nspanel_id).send_custom_command("timeout~20");'
# Service to send a command wake the screen
- service: dim_0_to_100
variables:
intensity: string
then:
- lambda: 'id(nspanel_id).send_custom_command("dimmode~"+intensity+"~100");'
# Service to send a command To show the screen of a specific like
- service: show_entity
variables:
entity: string
title: string
then:
- lambda: 'id(nspanel_id).send_custom_command("pageType~popupLight~" + title + "~" + entity);'
# Service to send a command To show the screen of a specific like
- service: notify_on_screensaver
variables:
line1: string
line2: string
then:
- lambda: 'id(nspanel_id).send_custom_command("notify~" + line1 + "~" + line2);'
- rtttl.play: "short:d=4,o=5,b=100:16e6"
# Service to send a command To show the screen of a specific like
# interaction of the buttons are on implemented yet
- service: notify_fullscreen
- action: notify_fullscreen
variables:
title: string
description: string
button1: string
button2: string
time_secs: string
timeout: int
icon: string
then:
# show notification screen
- lambda: 'id(nspanel_id).send_custom_command("pageType~popupNotify");'
# set values on notification screen
# color defined as number created in binary and converted to decimal (rrrrggggbbbbaaaa)
- lambda: 'id(nspanel_id).send_custom_command("entityUpdateDetail~id~"+ title + "~65535~" + button1 +"~3840~" + button2 + "~61440~" + description + "~65535~" + time_secs);'
- 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:
@@ -166,19 +77,113 @@ uart:
rx_pin: 17
baud_rate: 115200
mqtt:
id: mqtt_client
broker: !secret mqtt_ip
username: !secret mqtt_username
password: !secret mqtt_password
discovery: false
idf_send_async: true
reboot_timeout: 0s
nspanel_lovelace:
id: nspanel_id
mqtt_recv_topic: $panel_recv_topic
mqtt_send_topic: $panel_send_topic
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:
- type: cardGrid
title: Kuchyňa / Obývačka
entities:
- name: Kuchyňa / Obývačka
entity_id: light.kitchen
icon: ceiling-light
- name: Stôl
entity_id: light.dining_table
icon: ceiling-light
- name: Gauč
entity_id: light.living_room
icon: ceiling-light
- name: TV
entity_id: light.mcu_tv_light_strip
icon: led-strip-variant
- name: (Stôl)
entity_id: light.dining_table_ambilight
icon: ceiling-light-multiple-outline
- name: (Gauč)
entity_id: light.living_room_ambilight
icon: ceiling-light-multiple-outline
- type: cardGrid
title: Kuchyňa
entities:
- name: Linka
entity_id: light.worktop_lights
icon: countertop
- name: Sporák
entity_id: light.mcu_kitchen_stove
icon: stove
- type: cardGrid
title: Von
entities:
- name: Terasa
entity_id: light.patio_lights
icon: lightbulb-group
- name: Terasa
entity_id: switch.mcu_patio_relay
icon: power-socket-fr
- name: Vzadu
entity_id: switch.mcu_nspanel_patio_outside_light_back
icon: light-flood-down
- name: Z. domček
entity_id: switch.mcu_shed_light
icon: wall-sconce-flat
# state_template: '{{ is_state("binary_sensor.shed_status", "off") }}'
- name: Z. domček
entity_id: switch.mcu_shed_socket
icon: power-socket-fr
# state_template: '{{ is_state("binary_sensor.shed_status", "off") }}'
- name: Záhrada
entity_id: switch.mcu_shed_garden_light
icon: light-flood-down
# state_template: '{{ is_state("binary_sensor.shed_status", "off") }}'
- type: cardGrid
title: Brána
entities:
- name: Otvoriť
entity_id: button.mcu_gate_open
icon: gate-open
- name: Zatvoriť
entity_id: button.mcu_gate_close
icon: gate
- name: Automatizácia
entity_id: navigate.card_gate_automation
- type: cardThermo
title: Kúrenie
thermo_entity_id: climate.bt_trv_living_room_kitchen
- type: cardThermo
title: Kúrenie - Izba
thermo_entity_id: climate.bt_trv_room
- type: cardEntities
title: Automatizácia
id: card_gate_automation
hidden: true
entities:
- name: Auto-otváranie
entity_id: switch.gate_auto_open
- name: Auto-zatváranie
entity_id: switch.gate_auto_close
time:
- platform: homeassistant
@@ -196,25 +201,20 @@ binary_sensor:
- min_length: 50ms
max_length: 350ms
then:
- homeassistant.service:
service: light.toggle
- homeassistant.action:
action: light.toggle
data:
entity_id: light.living_room
- mqtt.publish_json:
topic: $panel_recv_topic
payload: |-
root["CustomRecv"] = "event,buttonPress2,navigate.cardGrid_main,button";
- lambda: 'id(nspanel_id).render_default_page();'
- min_length: 500ms
max_length: 2000ms
then:
- homeassistant.service:
service: light.toggle
- homeassistant.action:
action: light.toggle
data:
entity_id: light.worktop_lights
- mqtt.publish_json:
topic: $panel_recv_topic
payload: |-
root["CustomRecv"] = "event,buttonPress2,navigate.cardGrid_kitchen,button";
- lambda: 'id(nspanel_id).render_default_page();'
- lambda: 'id(nspanel_id).render_next_page();'
- platform: gpio
name: Right Button
@@ -226,25 +226,20 @@ binary_sensor:
- min_length: 50ms
max_length: 350ms
then:
- homeassistant.service:
service: light.toggle
- homeassistant.action:
action: light.toggle
data:
entity_id: light.dining_table
- mqtt.publish_json:
topic: $panel_recv_topic
payload: |-
root["CustomRecv"] = "event,buttonPress2,navigate.cardGrid_main,button";
- lambda: 'id(nspanel_id).render_default_page();'
- min_length: 500ms
max_length: 2000ms
then:
- homeassistant.service:
service: light.toggle
- homeassistant.action:
action: light.toggle
data:
entity_id: light.mcu_kitchen_stove
- mqtt.publish_json:
topic: $panel_recv_topic
payload: |-
root["CustomRecv"] = "event,buttonPress2,navigate.cardGrid_kitchen,button";
- lambda: 'id(nspanel_id).render_default_page();'
- lambda: 'id(nspanel_id).render_next_page();'
output:
- platform: ledc
id: buzzer_out
@@ -292,13 +287,19 @@ sensor:
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
name: "Living Room Temperature"
- platform: template
id: room_temperature_id
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();
+85 -163
View File
@@ -4,10 +4,6 @@ substitutions:
name: Office J NSPanel
area: Office J
comment: NSPanel
panel_recv_topic: "tele/${device}/RESULT"
panel_send_topic: "cmnd/${device}/CustomSend"
tft_url: !secret tft_url
esphome:
name: mcu-${device}
@@ -19,6 +15,8 @@ esphome:
- 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
@@ -32,138 +30,45 @@ esp32:
external_components:
- source:
type: git
url: https://github.com/sairon/esphome-nspanel-lovelace-ui
ref: dev
url: https://github.com/randybb/esphome-nspanel-lovelace-native
ref: devices
refresh: 0s
components: [nspanel_lovelace]
packages:
common: !include common/common.yaml
api:
# https://github.com/granadaxronos/120-SONG_NOKIA_RTTTL_RINGTONE_PLAYER_FOR_ARDUINO_UNO/blob/master/RTTTL_PLAYER/songs.h
#
# stupnovane:d=4,o=6,b=180:c,e,g
# help:d=4,o=6,b=100:f,8p,f,8p,f,8p,f,8p,f,8p,f,8p,f,8p,f,8p,f,8p,f
# gate_opening:d=16,o=5,b=160:a, 8p, a
# fireplace_attention:d=16,o=5,b=160:a, 8p, g, 16p, c
services:
- service: play_rtttl
homeassistant_services: true
homeassistant_states: true
actions:
- action: play_rtttl
variables:
song: string
then:
- rtttl.play:
rtttl: !lambda 'return song;'
- service: notify
- action: notify
variables:
heading: string
message: string
song: string
then:
- lambda: 'id(nspanel_id).send_custom_command("notify~" + heading + "~" + message);'
- lambda: 'id(nspanel_id).notify_on_screensaver(heading, message, 10000);'
- rtttl.play:
rtttl: !lambda 'return song;'
- delay: 10s
- lambda: 'id(nspanel_id).send_custom_command("notify~~");'
- service: update_tft
then:
- lambda: |-
id(nspanel_id).upload_tft("${tft_url}");
- service: upload_tft
variables:
url: string
then:
- lambda: |-
id(nspanel_id).upload_tft(url);
# Service to send a command directly to the display. Useful for testing
- service: send_command
variables:
cmd: string
then:
- lambda: "id(nspanel_id).send_custom_command(cmd.c_str());"
# Service to pusblish to mqtt used for refreshin the panel
- service: publish_to_recv_topic
variables:
cmd: string
then:
- mqtt.publish:
topic: $panel_recv_topic
payload: !lambda "return cmd;"
# Service to send a command wake the screen
- service: wake
then:
- lambda: 'id(nspanel_id).send_custom_command("wake");'
# Service to send a command to show screensaver (some of the values are hardcoded)
- service: show_screensaver
then:
- mqtt.publish:
topic: $panel_recv_topic
payload: '{"CustomRecv":"event,sleepReached,cardGrid"}'
# Service to navigate to screen
- service: navigate_to_page
variables:
page: string
then:
- mqtt.publish_json:
topic: $panel_recv_topic
payload: |-
root["CustomRecv"] = "event,buttonPress2,navigate." + page + ",button";
# Service to send a command disable screensaver
- service: disable_screensaver
then:
- lambda: 'id(nspanel_id).send_custom_command("timeout~0");'
# Service to send a command enabled screensaver
- service: enable_screensaver
then:
- lambda: 'id(nspanel_id).send_custom_command("timeout~20");'
# Service to send a command wake the screen
- service: dim_0_to_100
variables:
intensity: string
then:
- lambda: 'id(nspanel_id).send_custom_command("dimmode~"+intensity+"~100");'
# Service to send a command To show the screen of a specific like
- service: show_entity
variables:
entity: string
title: string
then:
- lambda: 'id(nspanel_id).send_custom_command("pageType~popupLight~" + title + "~" + entity);'
# Service to send a command To show the screen of a specific like
- service: notify_on_screensaver
variables:
line1: string
line2: string
then:
- lambda: 'id(nspanel_id).send_custom_command("notify~" + line1 + "~" + line2);'
- rtttl.play: "short:d=4,o=5,b=100:16e6"
# Service to send a command To show the screen of a specific like
# interaction of the buttons are on implemented yet
- service: notify_fullscreen
- action: notify_fullscreen
variables:
title: string
description: string
button1: string
button2: string
time_secs: string
timeout: int
icon: string
then:
# show notification screen
- lambda: 'id(nspanel_id).send_custom_command("pageType~popupNotify");'
# set values on notification screen
# color defined as number created in binary and converted to decimal (rrrrggggbbbbaaaa)
- lambda: 'id(nspanel_id).send_custom_command("entityUpdateDetail~id~"+ title + "~65535~" + button1 +"~3840~" + button2 + "~61440~" + description + "~65535~" + time_secs);'
- 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:
@@ -172,19 +77,62 @@ uart:
rx_pin: 17
baud_rate: 115200
mqtt:
id: mqtt_client
broker: !secret mqtt_ip
username: !secret mqtt_username
password: !secret mqtt_password
discovery: false
idf_send_async: true
reboot_timeout: 0s
nspanel_lovelace:
id: nspanel_id
mqtt_recv_topic: $panel_recv_topic
mqtt_send_topic: $panel_send_topic
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:
- type: cardGrid
title: Janko
entities:
- name: Svetlo
entity_id: light.mcu_nspanel_office_j_light
icon: wall-sconce-flat
- name: Nočná lampa
entity_id: light.bedside_left
icon: lamp
- type: cardGrid
title: Brána
entities:
- name: Otvoriť
entity_id: button.mcu_gate_open
icon: gate-open
- name: Zatvoriť
entity_id: button.mcu_gate_close
icon: gate
- name: Automatizácia
entity_id: navigate.card_gate_automation
- type: cardThermo
title: Kúrenie
thermo_entity_id: climate.bt_trv_office_j
- type: cardEntities
title: Automatizácia
id: card_gate_automation
hidden: true
entities:
- name: Auto-otváranie
entity_id: switch.gate_auto_open
- name: Auto-zatváranie
entity_id: switch.gate_auto_close
time:
- platform: homeassistant
@@ -192,26 +140,6 @@ time:
timezone: Europe/Bratislava
binary_sensor:
# - platform: gpio
# name: Left Button
# pin:
# number: 14
# inverted: true
# on_click:
# - switch.toggle: relay_1
# - platform: gpio
# name: Right Button
# pin:
# number: 27
# inverted: true
# # on_click:
# # - switch.toggle: relay_2
# on_click:
# - homeassistant.service:
# service: light.toggle
# data:
# entity_id: light.office_r_desk_strip
- platform: gpio
name: Left Button
pin:
@@ -219,10 +147,7 @@ binary_sensor:
inverted: true
on_click:
- light.toggle: light_1
- mqtt.publish_json:
topic: $panel_recv_topic
payload: |-
root["CustomRecv"] = "event,buttonPress2,navigate.cardGrid_main,button";
- lambda: 'id(nspanel_id).render_default_page();'
- platform: gpio
name: Right Button
@@ -230,20 +155,18 @@ binary_sensor:
number: 27
inverted: true
on_click:
- homeassistant.service:
service: light.toggle
- homeassistant.action:
action: light.toggle
data:
entity_id: light.bedside_left
- mqtt.publish_json:
topic: $panel_recv_topic
payload: |-
root["CustomRecv"] = "event,buttonPress2,navigate.cardGrid_main,button";
- lambda: 'id(nspanel_id).render_default_page();'
output:
- platform: ledc
id: buzzer_out
pin:
number: 21
- id: relay_1
platform: gpio
pin:
@@ -283,28 +206,27 @@ sensor:
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
name: Temperature
- platform: template
id: room_temperature_id
# esp32_ble_tracker:
# text_sensor:
# - platform: ble_scanner
# name: BLE Scanner
# esp32_ble_beacon:
# type: iBeacon
# uuid: '6d68252f-2e6f-b5b9-965f-43c0a3713880'
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();
+93 -178
View File
@@ -4,10 +4,6 @@ substitutions:
name: Office R NSPanel
area: Office R
comment: NSPanel
panel_recv_topic: "tele/${device}/RESULT"
panel_send_topic: "cmnd/${device}/CustomSend"
tft_url: !secret tft_url
esphome:
name: mcu-${device}
@@ -19,6 +15,8 @@ esphome:
- 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
@@ -26,15 +24,15 @@ esp32:
framework:
type: esp-idf
advanced:
enable_lwip_mdns_queries: true
minimum_chip_revision: 3.0
sram1_as_iram: true
external_components:
- source:
type: git
url: https://github.com/sairon/esphome-nspanel-lovelace-ui
ref: dev
url: https://github.com/randybb/esphome-nspanel-lovelace-native
ref: devices
refresh: 0s
components: [nspanel_lovelace]
packages:
@@ -58,131 +56,36 @@ script:
- script.execute: geiger_click
api:
# https://github.com/granadaxronos/120-SONG_NOKIA_RTTTL_RINGTONE_PLAYER_FOR_ARDUINO_UNO/blob/master/RTTTL_PLAYER/songs.h
#
# stupnovane:d=4,o=6,b=180:c,e,g
# help:d=4,o=6,b=100:f,8p,f,8p,f,8p,f,8p,f,8p,f,8p,f,8p,f,8p,f,8p,f
# gate_opening:d=16,o=5,b=160:a, 8p, a
# fireplace_attention:d=16,o=5,b=160:a, 8p, g, 16p, c
services:
- service: play_rtttl
homeassistant_services: true
homeassistant_states: true
actions:
- action: play_rtttl
variables:
song: string
then:
- rtttl.play:
rtttl: !lambda 'return song;'
- service: notify
- action: notify
variables:
heading: string
message: string
song: string
then:
- lambda: 'id(nspanel_id).send_custom_command("notify~" + heading + "~" + message);'
- lambda: 'id(nspanel_id).notify_on_screensaver(heading, message, 10000);'
- rtttl.play:
rtttl: !lambda 'return song;'
- delay: 10s
- lambda: 'id(nspanel_id).send_custom_command("notify~~");'
- service: update_tft
then:
- logger.log: "tft updating from: ${tft_url}"
- lambda: |-
id(nspanel_id).upload_tft("${tft_url}");
- service: upload_tft
variables:
url: string
then:
- lambda: |-
id(nspanel_id).upload_tft(url);
# Service to send a command directly to the display. Useful for testing
- service: send_command
variables:
cmd: string
then:
- lambda: "id(nspanel_id).send_custom_command(cmd.c_str());"
# Service to pusblish to mqtt used for refreshin the panel
- service: publish_to_recv_topic
variables:
cmd: string
then:
- mqtt.publish:
topic: $panel_recv_topic
payload: !lambda "return cmd;"
# Service to send a command wake the screen
- service: wake
then:
- lambda: 'id(nspanel_id).send_custom_command("wake");'
# Service to send a command to show screensaver (some of the values are hardcoded)
- service: show_screensaver
then:
- mqtt.publish:
topic: $panel_recv_topic
payload: '{"CustomRecv":"event,sleepReached,cardGrid"}'
# Service to navigate to screen
- service: navigate_to_page
variables:
page: string
then:
- mqtt.publish_json:
topic: $panel_recv_topic
payload: |-
root["CustomRecv"] = "event,buttonPress2,navigate." + page + ",button";
# Service to send a command disable screensaver
- service: disable_screensaver
then:
- lambda: 'id(nspanel_id).send_custom_command("timeout~0");'
# Service to send a command enabled screensaver
- service: enable_screensaver
then:
- lambda: 'id(nspanel_id).send_custom_command("timeout~20");'
# Service to send a command wake the screen
- service: dim_0_to_100
variables:
intensity: string
then:
- lambda: 'id(nspanel_id).send_custom_command("dimmode~"+intensity+"~100");'
# Service to send a command To show the screen of a specific like
- service: show_entity
variables:
entity: string
title: string
then:
- lambda: 'id(nspanel_id).send_custom_command("pageType~popupLight~" + title + "~" + entity);'
# Service to send a command To show the screen of a specific like
- service: notify_on_screensaver
variables:
line1: string
line2: string
then:
- lambda: 'id(nspanel_id).send_custom_command("notify~" + line1 + "~" + line2);'
- rtttl.play: "short:d=4,o=5,b=100:16e6"
# Service to send a command To show the screen of a specific like
# interaction of the buttons are on implemented yet
- service: notify_fullscreen
- action: notify_fullscreen
variables:
title: string
description: string
button1: string
button2: string
time_secs: string
timeout: int
icon: string
then:
# show notification screen
- lambda: 'id(nspanel_id).send_custom_command("pageType~popupNotify");'
# set values on notification screen
# color defined as number created in binary and converted to decimal (rrrrggggbbbbaaaa)
- lambda: 'id(nspanel_id).send_custom_command("entityUpdateDetail~id~"+ title + "~65535~" + button1 +"~3840~" + button2 + "~61440~" + description + "~65535~" + time_secs);'
- 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:
@@ -191,19 +94,69 @@ uart:
rx_pin: 17
baud_rate: 115200
mqtt:
id: mqtt_client
broker: !secret mqtt_ip
username: !secret mqtt_username
password: !secret mqtt_password
discovery: false
idf_send_async: true
reboot_timeout: 0s
nspanel_lovelace:
id: nspanel_id
mqtt_recv_topic: $panel_recv_topic
mqtt_send_topic: $panel_send_topic
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:
- type: cardGrid
title: Romanko
entities:
- name: Svetlo
entity_id: light.mcu_nspanel_office_r_light
icon: wall-sconce-flat
- name: LED pásik
entity_id: light.office_r_desk_strip
icon: led-strip-variant
- entity_id: delete
- name: Monitor
entity_id: light.office_r_display_lamp
icon: monitor-star
- name: (Monitor)
entity_id: light.office_r_display_lamp_ambilight
icon: monitor-star
- type: cardGrid
title: Brána
entities:
- name: Otvoriť
entity_id: button.mcu_gate_open
icon: gate-open
- name: Zatvoriť
entity_id: button.mcu_gate_close
icon: gate
- name: Automatizácia
entity_id: navigate.card_gate_automation
- type: cardThermo
title: Kúrenie
thermo_entity_id: climate.bt_trv_office_r
- type: cardEntities
title: Automatizácia
id: card_gate_automation
hidden: true
entities:
- name: Auto-otváranie
entity_id: switch.gate_auto_open
- name: Auto-zatváranie
entity_id: switch.gate_auto_close
time:
- platform: homeassistant
@@ -211,42 +164,18 @@ time:
timezone: Europe/Bratislava
binary_sensor:
# - platform: gpio
# name: Left Button
# pin:
# number: 14
# inverted: true
# on_click:
# - switch.toggle: relay_1
# - platform: gpio
# name: Right Button
# pin:
# number: 27
# inverted: true
# # on_click:
# # - switch.toggle: relay_2
# on_click:
# - homeassistant.service:
# service: light.toggle
# data:
# entity_id: light.office_r_desk_strip
- platform: gpio
name: Left Button
pin:
number: 14
inverted: true
on_click:
- homeassistant.service:
service: light.toggle
- homeassistant.action:
action: light.toggle
data:
entity_id: light.office_r_desk_strip
- mqtt.publish_json:
topic: $panel_recv_topic
payload: |-
root["CustomRecv"] = "event,buttonPress1,navigate.cardGrid_main,button";
# - lambda: 'id(nspanel_id).send_custom_command("event,buttonPress1,navigate.cardGrid_main,button");'
- lambda: 'id(nspanel_id).render_default_page();'
- platform: gpio
name: Right Button
pin:
@@ -254,11 +183,7 @@ binary_sensor:
inverted: true
on_click:
- light.toggle: light_1
- mqtt.publish_json:
topic: $panel_recv_topic
payload: |-
root["CustomRecv"] = "event,buttonPress2,navigate.cardGrid_main,button";
# - lambda: 'id(nspanel_id).send_custom_command("event,buttonPress2,navigate.cardGrid_main,button");'
- lambda: 'id(nspanel_id).render_default_page();'
output:
- platform: ledc
@@ -278,10 +203,9 @@ light:
- platform: esp32_rmt_led_strip
name: Presence Light
id: neo
rgb_order: GRB
channel_colors: GRB
pin: 23
num_leds: 3
# rmt_channel: 0
chipset: SK6812
effects:
- pulse:
@@ -298,16 +222,8 @@ light:
id: light_1
output: relay_1
restore_mode: RESTORE_DEFAULT_OFF
# # - platform: binary
# # name: Relay 2
# # output: relay_2
switch:
# - platform: gpio
# name: Light
# id: relay_1
# pin:
# number: 22
- platform: gpio
# name: Relay 2
id: relay_2
@@ -339,28 +255,27 @@ sensor:
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
name: Temperature
- platform: template
id: room_temperature_id
# esp32_ble_tracker:
# text_sensor:
# - platform: ble_scanner
# name: BLE Scanner
# esp32_ble_beacon:
# type: iBeacon
# uuid: '6d68252f-2e6f-b5b9-965f-43c0a3713880'
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();
+166 -128
View File
@@ -4,9 +4,6 @@ substitutions:
name: Patio NSPanel
area: Living Room & Kitchen
comment: ${area}, Patio | NSPanel
panel_recv_topic: "tele/${device}/RESULT"
panel_send_topic: "cmnd/${device}/CustomSend"
tft_url: !secret tft_url
esphome:
name: mcu-${device}
@@ -18,6 +15,8 @@ esphome:
- 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
@@ -31,133 +30,45 @@ esp32:
external_components:
- source:
type: git
url: https://github.com/sairon/esphome-nspanel-lovelace-ui
ref: dev
url: https://github.com/randybb/esphome-nspanel-lovelace-native
ref: devices
refresh: 0s
components: [nspanel_lovelace]
packages:
common: !include common/common.yaml
api:
# https://github.com/granadaxronos/120-SONG_NOKIA_RTTTL_RINGTONE_PLAYER_FOR_ARDUINO_UNO/blob/master/RTTTL_PLAYER/songs.h
services:
- service: play_rtttl
homeassistant_services: true
homeassistant_states: true
actions:
- action: play_rtttl
variables:
song: string
then:
- rtttl.play:
rtttl: !lambda 'return song;'
- service: notify
- action: notify
variables:
heading: string
message: string
song: string
then:
- lambda: 'id(nspanel_id).send_custom_command("notify~" + heading + "~" + message);'
- lambda: 'id(nspanel_id).notify_on_screensaver(heading, message, 10000);'
- rtttl.play:
rtttl: !lambda 'return song;'
- delay: 10s
- lambda: 'id(nspanel_id).send_custom_command("notify~~");'
- service: update_tft
then:
- lambda: |-
id(nspanel_id).upload_tft("${tft_url}");
- service: upload_tft
variables:
url: string
then:
- lambda: |-
id(nspanel_id).upload_tft(url);
# Service to send a command directly to the display. Useful for testing
- service: send_command
variables:
cmd: string
then:
- lambda: "id(nspanel_id).send_custom_command(cmd.c_str());"
# Service to pusblish to mqtt used for refreshin the panel
- service: publish_to_recv_topic
variables:
cmd: string
then:
- mqtt.publish:
topic: $panel_recv_topic
payload: !lambda "return cmd;"
# Service to send a command wake the screen
- service: wake
then:
- lambda: 'id(nspanel_id).send_custom_command("wake");'
# Service to send a command to show screensaver (some of the values are hardcoded)
- service: show_screensaver
then:
- mqtt.publish:
topic: $panel_recv_topic
payload: '{"CustomRecv":"event,sleepReached,cardGrid"}'
# Service to navigate to screen
- service: navigate_to_page
variables:
page: string
then:
- mqtt.publish_json:
topic: $panel_recv_topic
payload: |-
root["CustomRecv"] = "event,buttonPress2,navigate." + page + ",button";
# Service to send a command disable screensaver
- service: disable_screensaver
then:
- lambda: 'id(nspanel_id).send_custom_command("timeout~0");'
# Service to send a command enabled screensaver
- service: enable_screensaver
then:
- lambda: 'id(nspanel_id).send_custom_command("timeout~20");'
# Service to send a command wake the screen
- service: dim_0_to_100
variables:
intensity: string
then:
- lambda: 'id(nspanel_id).send_custom_command("dimmode~"+intensity+"~100");'
# Service to send a command To show the screen of a specific like
- service: show_entity
variables:
entity: string
title: string
then:
- lambda: 'id(nspanel_id).send_custom_command("pageType~popupLight~" + title + "~" + entity);'
# Service to send a command To show the screen of a specific like
- service: notify_on_screensaver
variables:
line1: string
line2: string
then:
- lambda: 'id(nspanel_id).send_custom_command("notify~" + line1 + "~" + line2);'
- rtttl.play: "short:d=4,o=5,b=100:16e6"
# Service to send a command To show the screen of a specific like
# interaction of the buttons are on implemented yet
- service: notify_fullscreen
- action: notify_fullscreen
variables:
title: string
description: string
button1: string
button2: string
time_secs: string
timeout: int
icon: string
then:
# show notification screen
- lambda: 'id(nspanel_id).send_custom_command("pageType~popupNotify");'
# set values on notification screen
# color defined as number created in binary and converted to decimal (rrrrggggbbbbaaaa)
- lambda: 'id(nspanel_id).send_custom_command("entityUpdateDetail~id~"+ title + "~65535~" + button1 +"~3840~" + button2 + "~61440~" + description + "~65535~" + time_secs);'
- 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:
@@ -166,19 +77,142 @@ uart:
rx_pin: 17
baud_rate: 115200
mqtt:
id: mqtt_client
broker: !secret mqtt_ip
username: !secret mqtt_username
password: !secret mqtt_password
discovery: false
idf_send_async: true
reboot_timeout: 0s
nspanel_lovelace:
id: nspanel_id
mqtt_recv_topic: $panel_recv_topic
mqtt_send_topic: $panel_send_topic
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:
- type: cardGrid
title: Kuchyňa / Obývačka
entities:
- name: Kuchyňa / Obývačka
entity_id: light.kitchen
icon: ceiling-light
- name: Stôl
entity_id: light.dining_table
icon: ceiling-light
- name: Gauč
entity_id: light.living_room
icon: ceiling-light
- name: TV
entity_id: light.mcu_tv_light_strip
icon: led-strip-variant
- name: (Stôl)
entity_id: light.dining_table_ambilight
icon: ceiling-light-multiple-outline
- name: (Gauč)
entity_id: light.living_room_ambilight
icon: ceiling-light-multiple-outline
- type: cardGrid
title: Kuchyňa
entities:
- name: Linka
entity_id: light.worktop_lights
icon: countertop
- name: Sporák
entity_id: light.mcu_kitchen_stove
icon: stove
- type: cardGrid
title: Von
entities:
- name: Terasa
entity_id: light.patio_lights
icon: lightbulb-group
- name: Terasa
entity_id: switch.mcu_patio_relay
icon: power-socket-fr
- name: Vzadu
entity_id: switch.mcu_nspanel_patio_outside_light_back
icon: light-flood-down
- name: Z. domček
entity_id: switch.mcu_shed_light
icon: wall-sconce-flat
# state_template: '{{ is_state("binary_sensor.shed_status", "off") }}'
- name: Z. domček
entity_id: switch.mcu_shed_socket
icon: power-socket-fr
# state_template: '{{ is_state("binary_sensor.shed_status", "off") }}'
- name: Záhrada
entity_id: switch.mcu_shed_garden_light
icon: light-flood-down
# state_template: '{{ is_state("binary_sensor.shed_status", "off") }}'
- type: cardGrid
title: Závlaha
entities:
- name: A1
entity_id: switch.mcu_well_irrigation_valve_a1
icon: valve
- name: A2
entity_id: switch.mcu_well_irrigation_valve_a2
icon: valve
- name: A3
entity_id: switch.mcu_well_irrigation_valve_a3
icon: valve
- name: A4
entity_id: switch.mcu_well_irrigation_valve_a4
icon: valve
- name: A5
entity_id: switch.mcu_well_irrigation_valve_a5
icon: valve
- name: Automatizácia
entity_id: navigate.card_irrigation_automation
- type: cardGrid
title: Brána
entities:
- name: Otvoriť
entity_id: button.mcu_gate_open
icon: gate-open
- name: Zatvoriť
entity_id: button.mcu_gate_close
icon: gate
- name: Automatizácia
entity_id: navigate.card_gate_automation
- type: cardThermo
title: Kúrenie
thermo_entity_id: climate.bt_trv_living_room_kitchen
- type: cardEntities
title: Automatizácia
id: card_gate_automation
hidden: true
entities:
- name: Auto-otváranie
entity_id: switch.gate_auto_open
- name: Auto-zatváranie
entity_id: switch.gate_auto_close
- type: cardEntities
title: Automatizácia
id: card_irrigation_automation
hidden: true
entities:
- name: Ráno
entity_id: automation.irrigation_morning
- name: Terasa
entity_id: automation.irrigation_patio
- name: Rast trávy
entity_id: automation.irrigation_grow_grass
time:
- platform: homeassistant
@@ -193,10 +227,9 @@ binary_sensor:
inverted: true
on_click:
- switch.toggle: relay_1
- mqtt.publish_json:
topic: $panel_recv_topic
payload: |-
root["CustomRecv"] = "event,buttonPress2,navigate.cardGrid_main,button";
- lambda: 'id(nspanel_id).render_default_page();'
- lambda: 'id(nspanel_id).render_next_page();'
- lambda: 'id(nspanel_id).render_next_page();'
- platform: gpio
name: Right Button
@@ -208,14 +241,13 @@ binary_sensor:
condition:
api.connected:
then:
- homeassistant.service:
service: light.toggle
- homeassistant.action:
action: light.toggle
data:
entity_id: light.patio_lights
- mqtt.publish_json:
topic: $panel_recv_topic
payload: |-
root["CustomRecv"] = "event,buttonPress2,navigate.cardGrid_main,button";
- lambda: 'id(nspanel_id).render_default_page();'
- lambda: 'id(nspanel_id).render_next_page();'
- lambda: 'id(nspanel_id).render_next_page();'
else:
- switch.toggle: relay_2
@@ -267,13 +299,19 @@ sensor:
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
name: Living Room Temperature
- platform: template
id: room_temperature_id
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();
+6 -13
View File
@@ -21,41 +21,34 @@ packages:
common: !include common/common.yaml
spi:
clk_pin: 25
clk_pin: 23
mosi_pin: 19
miso_pin: 22
cc1101:
cs_pin: 33
frequency: 433.92MHz
gdo0_pin:
number: 21
allow_other_uses: true
infrared:
radio_frequency:
- platform: ir_rf_proxy
name: RF Proxy Transmitter
id: rf_proxy_tx
remote_transmitter_id: rf_tx
frequency: 433MHz
frequency: 433.92MHz
- platform: ir_rf_proxy
name: RF Proxy Receiver
id: rf_proxy_rx
remote_receiver_id: rf_rx
receiver_frequency: 433MHz
frequency: 433.92MHz
remote_receiver:
- id: rf_rx
pin:
number: 21
allow_other_uses: true
pin: 25
dump: all
remote_transmitter:
- id: rf_tx
pin:
number: 21
allow_other_uses: true
pin: 21
carrier_duty_percent: 100%
on_transmit:
then:
+8 -8
View File
@@ -54,22 +54,22 @@ packages:
# GPIO21 RGB
api:
services:
- service: rfidreader_tag_ok
actions:
- action: rfidreader_tag_ok
then:
- rtttl.play: "beep:d=16,o=5,b=100:b"
- service: rfidreader_tag_ko
- action: rfidreader_tag_ko
then:
- rtttl.play: "beep:d=8,o=5,b=100:b"
- service: play_rtttl
- action: play_rtttl
variables:
song_str: string
then:
- rtttl.play: !lambda 'return song_str;'
- service: write_tag_id
- action: write_tag_id
variables:
tag_id: string
then:
@@ -93,7 +93,7 @@ api:
id: notify_led
- rtttl.play: "write:d=24,o=5,b=100:b,b"
- service: write_music_tag
- action: write_music_tag
variables:
music_url: string
music_info: string
@@ -348,7 +348,7 @@ button:
light:
- platform: esp32_rmt_led_strip
id: notify_led
rgb_order: GRB
channel_colors: GRB
pin: 3
num_leds: 1
chipset: ws2812
@@ -356,7 +356,7 @@ light:
rmt_symbols: 96
- platform: esp32_rmt_led_strip
id: status_led
rgb_order: GRB
channel_colors: GRB
pin: 21
num_leds: 1
chipset: ws2812
+2 -2
View File
@@ -106,8 +106,8 @@ sensor:
then:
- light.turn_off: light_red
- switch.turn_off: relay
- homeassistant.service:
service: persistent_notification.create
- homeassistant.action:
action: persistent_notification.create
data:
title: Message from ${name}
data_template:
+886
View File
@@ -0,0 +1,886 @@
substitutions:
device: stackchan
name: StackChan
area: DEV
comment: StackChan
esphome:
name: mcu-${device}
friendly_name: ${name}
area: ${area}
comment: ${comment}
on_boot:
- priority: -100
then:
- light.turn_on:
id: light_bar
brightness: 20%
red: 0%
green: 0%
blue: 100%
- component.update: display_tft
esp32:
variant: esp32s3
flash_size: 16MB
toolchain: esp-idf
framework:
type: esp-idf
psram:
mode: quad
speed: 80MHz
packages:
common: !include common/common.yaml
external_components:
- source: github://m5stack/esphome-yaml/components
components: [axp2101, aw88298, aw9523b, si12t, m5ioe1, ftservo, scs9009]
refresh: 0s
- source: github://randybb/esphome-components
components: [audio_spectrum]
refresh: 1d
globals:
- id: in_love
type: bool
initial_value: 'false'
- id: show_status
type: bool
initial_value: 'true'
- id: mouth_open
type: float
initial_value: '0.0'
- id: eyes_open
type: bool
initial_value: 'true'
- id: speaking
type: bool
initial_value: 'false'
- id: listening
type: bool
initial_value: 'false'
- id: gaze_x
type: int
initial_value: '0'
- id: gaze_y
type: int
initial_value: '0'
i2c:
- id: i2c_bsp
sda: 12
scl: 11
frequency: 100kHz
axp2101:
id: axp2101_pmu
i2c_id: i2c_bsp
aw9523b:
id: aw9523b_hub
i2c_id: i2c_bsp
p0_drive_mode: PUSH_PULL
m5ioe1:
id: m5ioe1_hub
i2c_id: i2c_bsp
reset: true
output:
- platform: axp2101
id: lcd_backlight_output
type: range
channel: DLDO1
min_voltage: 2600
max_voltage: 3300
- platform: axp2101
channel: ALDO1
voltage: 1800
- platform: axp2101
channel: ALDO2
voltage: 3300
- platform: axp2101
channel: ALDO3
voltage: 3300
- platform: axp2101
channel: ALDO4
voltage: 3300
- platform: axp2101
channel: BLDO1
voltage: 2800
- platform: axp2101
channel: BLDO2
voltage: 1500
- platform: axp2101
channel: DCDC1
voltage: 3300
- platform: axp2101
channel: DCDC4
voltage: 1800
- platform: axp2101
channel: DCDC3
voltage: 3300
- platform: axp2101
channel: DCDC5
voltage: 3300
switch:
- platform: gpio
id: boost_en
name: Boost
entity_category: config
pin:
aw9523b_id: aw9523b_hub
number: 15
restore_mode: RESTORE_DEFAULT_ON
- platform: gpio
id: usb_otg_en
name: USB OTG
entity_category: config
pin:
aw9523b_id: aw9523b_hub
number: 5
restore_mode: RESTORE_DEFAULT_OFF
- platform: gpio
id: bus_out_en
name: BUS Out
entity_category: config
pin:
aw9523b_id: aw9523b_hub
number: 1
restore_mode: RESTORE_DEFAULT_ON
- platform: gpio
id: light_bar_en
internal: true
pin:
m5ioe1_id: m5ioe1_hub
number: 13
mode:
output: true
pullup: true
restore_mode: ALWAYS_ON
- platform: gpio
id: aw_rst
internal: true
pin:
aw9523b_id: aw9523b_hub
number: 2
restore_mode: ALWAYS_ON
- platform: gpio
id: cam_rst
internal: true
pin:
aw9523b_id: aw9523b_hub
number: 8
restore_mode: ALWAYS_ON
- platform: gpio
id: servo_power
internal: true
pin:
m5ioe1_id: m5ioe1_hub
number: 0
mode:
output: true
pullup: true
restore_mode: ALWAYS_ON
i2s_audio:
- id: i2s_bus
i2s_lrclk_pin: 33
i2s_bclk_pin: 34
i2s_mclk_pin:
number: 0
ignore_strapping_warning: true
audio_adc:
- platform: es7210
id: es7210_adc
i2c_id: i2c_bsp
bits_per_sample: 16bit
sample_rate: 16000
mic_gain: 36
audio_dac:
- platform: aw88298
id: aw88298_dac
i2c_id: i2c_bsp
sample_rate: 48000
microphone:
- platform: i2s_audio
id: stackchan_microphone
i2s_audio_id: i2s_bus
i2s_din_pin: 14
adc_type: external
sample_rate: 16000
bits_per_sample: 16bit
speaker:
- platform: i2s_audio
id: speaker_id
i2s_audio_id: i2s_bus
dac_type: external
i2s_dout_pin: 13
audio_dac: aw88298_dac
sample_rate: 48000
buffer_duration: 100ms
# pass-through that computes the spectrum shown on the display while music plays
- platform: audio_spectrum
id: spectrum
output_speaker: speaker_id
bands: 20
- platform: mixer
id: mixer_speaker_id
output_speaker: spectrum
num_channels: 1
source_speakers:
- id: announcement_spk_mixer_input
- id: media_spk_mixer_input
- platform: resampler
id: media_spk_resampling_input
output_speaker: media_spk_mixer_input
- platform: resampler
id: announcement_spk_resampling_input
output_speaker: announcement_spk_mixer_input
media_player:
- platform: speaker
id: media_out
name: Player
buffer_size: 14000
# AW88298 maps volume linearly to -96..0 dB, the lower half is inaudible
volume_min: 0.5
volume_max: 1.0
media_pipeline:
speaker: media_spk_resampling_input
format: NONE
announcement_pipeline:
speaker: announcement_spk_resampling_input
format: NONE
on_announcement:
- script.execute: release_i2s_bus
on_play:
- script.execute: release_i2s_bus
on_idle:
- if:
condition:
not:
voice_assistant.is_running:
then:
- micro_wake_word.start:
micro_wake_word:
id: mww
microphone: stackchan_microphone
models:
- model: okay_nabu
on_wake_word_detected:
- voice_assistant.start:
wake_word: !lambda return wake_word;
voice_assistant:
id: va
microphone: stackchan_microphone
media_player: media_out
micro_wake_word: mww
noise_suppression_level: 2
auto_gain: 31dBFS
on_client_connected:
- micro_wake_word.start:
- delay: 2s
- lambda: id(show_status) = false;
- component.update: display_tft
on_client_disconnected:
- micro_wake_word.stop:
- lambda: id(show_status) = true;
- component.update: display_tft
on_listening:
- lambda: |-
id(listening) = true;
id(gaze_x) = 0;
id(gaze_y) = 0;
- component.update: display_tft
- light.turn_on: {id: light_bar, brightness: 60%, red: 0%, green: 60%, blue: 100%}
on_stt_end:
- lambda: id(listening) = false;
- component.update: display_tft
- light.turn_on: {id: light_bar, brightness: 40%, red: 80%, green: 50%, blue: 0%}
on_tts_start:
- lambda: id(speaking) = true;
- light.turn_on: {id: light_bar, brightness: 60%, red: 0%, green: 100%, blue: 20%}
on_end:
- wait_until:
not:
media_player.is_announcing: media_out
- lambda: |-
id(speaking) = false;
id(listening) = false;
id(mouth_open) = 0.0f;
- component.update: display_tft
- light.turn_on: {id: light_bar, brightness: 20%, red: 0%, green: 0%, blue: 100%}
- wait_until:
not: voice_assistant.is_running
- micro_wake_word.start:
on_error:
- light.turn_on: {id: light_bar, brightness: 60%, red: 100%, green: 0%, blue: 0%}
script:
# short tap on the head starts the assistant
- id: head_tap
then:
- if:
condition:
not: voice_assistant.is_running
then:
- voice_assistant.start:
# stroking the head shows the in-love face for a while
- id: head_stroke
mode: restart
then:
- lambda: id(in_love) = true;
- component.update: display_tft
- delay: 5s
- lambda: id(in_love) = false;
- component.update: display_tft
# mic and speaker share one I2S bus - the mic must be released before playback
- id: release_i2s_bus
mode: single
then:
- if:
condition:
microphone.is_capturing:
then:
- micro_wake_word.stop:
# stop VA only while it is listening (e.g. continued conversation), not during its own response
- if:
condition:
lambda: return id(listening);
then:
- voice_assistant.stop:
- wait_until:
condition:
not:
microphone.is_capturing:
timeout: 2s
interval:
- interval: 80ms # spectrum analyzer frame rate while music plays
then:
- if:
condition:
and:
- media_player.is_playing: media_out
- not: voice_assistant.is_running
then:
- component.update: display_tft
# head touch gestures: a touch episode ends after 250 ms without contact;
# tap = short episode, stroke = longer episode that reaches the pads one after another
- interval: 50ms
then:
- lambda: |-
static bool active = false;
static uint32_t start = 0, last_on = 0;
static uint32_t first_on[3];
const bool on[3] = {id(head_touch_1).state != "No touch", id(head_touch_2).state != "No touch",
id(head_touch_3).state != "No touch"};
const uint32_t now = millis();
if (on[0] || on[1] || on[2]) {
if (!active) {
active = true;
start = now;
first_on[0] = first_on[1] = first_on[2] = 0;
}
for (int i = 0; i < 3; i++)
if (on[i] && first_on[i] == 0)
first_on[i] = now;
last_on = now;
return;
}
if (!active || now - last_on < 250)
return;
active = false;
const uint32_t duration = last_on - start;
int pads = 0;
uint32_t earliest = UINT32_MAX, latest = 0;
for (int i = 0; i < 3; i++) {
if (first_on[i] == 0)
continue;
pads++;
earliest = std::min(earliest, first_on[i]);
latest = std::max(latest, first_on[i]);
}
const uint32_t spread = latest - earliest;
ESP_LOGD("head_touch", "duration %u ms, pads %d, spread %u ms, order 1:%d 2:%d 3:%d", (unsigned) duration,
pads, (unsigned) spread, first_on[0] ? (int) (first_on[0] - earliest) : -1,
first_on[1] ? (int) (first_on[1] - earliest) : -1, first_on[2] ? (int) (first_on[2] - earliest) : -1);
if (pads >= 2 && spread >= 150 && duration >= 400) {
id(head_stroke).execute();
} else if (duration <= 600) {
id(head_tap).execute();
}
- interval: 1s # status screen refresh until Home Assistant connects
then:
- if:
condition:
lambda: return id(show_status);
then:
- component.update: display_tft
- interval: 90ms
then:
- lambda: |-
if (id(speaking)) {
id(mouth_open) = 0.15f + (esp_random() % 85) / 100.0f;
id(display_tft).update();
} else if (id(mouth_open) > 0) {
id(mouth_open) = 0;
id(display_tft).update();
}
- interval: 3s # blinking
then:
- delay: !lambda return esp_random() % 3000;
- lambda: id(eyes_open) = false;
- component.update: display_tft
- delay: 150ms
- lambda: id(eyes_open) = true;
- component.update: display_tft
- interval: 7s # looking around while idle
then:
- lambda: |-
if (!id(speaking) && !id(listening)) {
id(gaze_x) = (int) (esp_random() % 21) - 10;
id(gaze_y) = (int) (esp_random() % 11) - 5;
id(display_tft).update();
}
spi:
- id: spi_bus
clk_pin: 36
mosi_pin: 37
image:
- platform: file
file: assets/images/esphome-logo-text-on-dark.svg
id: esphome_logo
resize: 280x56
type: RGB565
transparency: alpha_channel
- platform: file
file: mdi:ear-hearing
id: icon_listening
resize: 28x28
type: BINARY
font:
- file: "gfonts://Roboto"
id: font_title
size: 24
- file: "gfonts://Roboto"
id: font_status
size: 16
color:
- id: status_ok
red: 30%
green: 85%
blue: 40%
- id: status_wait
red: 100%
green: 70%
blue: 0%
- id: love_red
red: 100%
green: 25%
blue: 45%
- id: status_low
red: 100%
green: 20%
blue: 20%
- id: status_dim
red: 55%
green: 55%
blue: 55%
- id: face_fg
red: 100%
green: 100%
blue: 100%
- id: face_bg
red: 0%
green: 0%
blue: 0%
display:
- platform: mipi_spi
id: display_tft
model: M5CORE
dc_pin: 35
reset_pin:
aw9523b_id: aw9523b_hub
number: 9
cs_pin:
number: 3
ignore_strapping_warning: true
data_rate: 40MHz
invert_colors: true
update_interval: never
auto_clear_enabled: false
lambda: |-
static bool first_draw = true;
static bool dot_shown = false;
static bool bar_drawn = false;
static int last_bars = -1, last_batt = -2;
static bool last_charging = false;
const bool wifi_ok = wifi::global_wifi_component->is_connected();
const int8_t rssi = wifi_ok ? wifi::global_wifi_component->wifi_rssi() : -127;
const int wifi_bars = !wifi_ok ? 0 : rssi > -55 ? 4 : rssi > -65 ? 3 : rssi > -75 ? 2 : 1;
const int batt = std::isnan(id(battery_level).state) ? -1 : (int) roundf(id(battery_level).state);
const bool charging = id(battery_charging).state;
// status screen until Home Assistant connects
if (id(show_status)) {
first_draw = true;
it.fill(id(face_bg));
it.image(160, 45, id(esphome_logo), ImageAlign::CENTER);
it.print(160, 95, id(font_title), id(face_fg), TextAlign::CENTER, "${name}");
if (wifi_ok) {
it.printf(20, 135, id(font_status), id(status_ok), "WiFi: %s (%d dBm)",
id(ip_address_sensor).state.c_str(), rssi);
} else {
it.print(20, 135, id(font_status), id(status_wait), "WiFi: connecting...");
}
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),
api_ok ? "Home Assistant: connected" : "Home Assistant: waiting...");
if (batt >= 0) {
it.printf(20, 189, id(font_status), batt <= 20 && !charging ? id(status_low) : id(status_dim),
"Battery: %d%%%s", batt, charging ? " (charging)" : "");
}
it.printf(20, 212, id(font_status), id(status_dim), "ESPHome %s", ESPHOME_VERSION);
it.printf(300, 212, id(font_status), id(status_dim), TextAlign::TOP_RIGHT, "up %us",
(unsigned) (millis() / 1000));
return;
}
// stack-chan face: 2 eyes + mouth, 320x240
// the whole screen is cleared only once, then just the face areas, so that only the
// changed region is sent over SPI instead of the whole 150 kB buffer
const bool love = id(in_love);
const bool music = id(media_out).state == media_player::MEDIA_PLAYER_STATE_PLAYING && !id(va).is_running();
// switching between face, in-love face and spectrum repaints everything
static int last_mode = -1;
const int mode = music ? 2 : love ? 1 : 0;
if (mode != last_mode) {
last_mode = mode;
first_draw = true;
}
// the in-love face is drawn outside the partially cleared areas, so it always repaints everything
static bool spectrum_reset = true;
if (first_draw || love) {
it.fill(id(face_bg));
first_draw = false;
bar_drawn = false;
spectrum_reset = true;
} else if (!music) {
it.filled_rectangle(70, 78, 181, 31, id(face_bg)); // eyes including gaze range
it.filled_rectangle(105, 130, 111, 38, id(face_bg)); // mouth
if (dot_shown && !id(listening)) {
it.filled_rectangle(254, 2, 28, 28, id(face_bg));
}
}
dot_shown = id(listening);
// status bar (battery top-left, wifi top-right), redrawn only when something changes
if (!bar_drawn || wifi_bars != last_bars || batt != last_batt || charging != last_charging) {
bar_drawn = true;
last_bars = wifi_bars;
last_batt = batt;
last_charging = charging;
it.filled_rectangle(4, 4, 90, 22, id(face_bg));
it.filled_rectangle(288, 4, 28, 22, id(face_bg));
// battery: outline, terminal nub and fill proportional to the charge
if (batt >= 0) {
const Color c = charging ? id(status_ok) : batt <= 20 ? id(status_low) : id(status_dim);
it.rectangle(8, 8, 26, 13, c);
it.filled_rectangle(34, 12, 2, 5, c);
it.filled_rectangle(10, 10, 22 * batt / 100, 9, c);
it.printf(40, 6, id(font_status), c, "%d%%", batt);
}
// wifi: 4 bars, unused ones dimmed; red when disconnected
for (int i = 0; i < 4; i++) {
const int h = 4 + 3 * i;
const Color c = !wifi_ok ? id(status_low) : i < wifi_bars ? id(status_dim) : Color(40, 40, 40);
it.filled_rectangle(290 + i * 6, 21 - h, 4, h, c);
}
}
// Winamp style spectrum analyzer instead of the face while music plays.
// Only the segments that changed since the last frame are drawn or cleared, which keeps both the
// pixel work and the SPI transfer small.
if (music) {
static float peak[32];
static uint32_t peak_time[32];
static int prev_segs[32], prev_cap[32];
const uint32_t now = millis();
const int bands = std::min<int>(id(spectrum).get_bands(), 32);
const int x0 = 12, x1 = 308, top = 40, bottom = 228;
const int slot = (x1 - x0) / bands, bar_w = slot - 3;
const int seg_h = 5; // 4 px LED segment + 1 px gap
const int max_segs = (bottom - top) / seg_h;
if (spectrum_reset) {
spectrum_reset = false;
for (int b = 0; b < 32; b++) {
peak[b] = 0.0f;
prev_segs[b] = 0;
prev_cap[b] = -1;
}
}
auto seg_y = [&](int s) { return bottom - (s + 1) * seg_h + 1; };
for (int b = 0; b < bands; b++) {
const float level = id(spectrum).get_level(b);
const int x = x0 + b * slot + 1;
const int segs = std::min(max_segs, (int) (level * max_segs));
// peak caps hold for a moment, then fall slowly
if (level >= peak[b]) {
peak[b] = level;
peak_time[b] = now;
} else if (now - peak_time[b] > 400) {
peak[b] = std::max(0.0f, peak[b] - 0.03f);
}
const int cap = peak[b] > 0.0f ? std::min(max_segs - 1, std::max(segs, (int) (peak[b] * max_segs))) : -1;
// the old cap is cleared first; bar segments drawn below repaint anything it overlapped
if (prev_cap[b] >= 0 && prev_cap[b] != cap)
it.filled_rectangle(x, seg_y(prev_cap[b]), bar_w, seg_h - 1, id(face_bg));
if (segs > prev_segs[b]) {
for (int s = prev_segs[b]; s < segs; s++) {
// green at the bottom, through yellow to red at the top
const float f = float(s) / float(max_segs - 1);
const Color c = f < 0.5f ? Color((uint8_t) (510 * f), 230, 0) : Color(255, (uint8_t) (460 * (1.0f - f)), 0);
it.filled_rectangle(x, seg_y(s), bar_w, seg_h - 1, c);
}
} else if (segs < prev_segs[b]) {
it.filled_rectangle(x, seg_y(prev_segs[b] - 1), bar_w, (prev_segs[b] - segs) * seg_h, id(face_bg));
}
prev_segs[b] = segs;
if (cap >= segs && cap >= 0 && (cap != prev_cap[b] || cap == segs)) {
const int cy = seg_y(cap) + seg_h - 3;
it.filled_rectangle(x, cy, bar_w, 2, id(status_dim));
}
prev_cap[b] = cap;
}
return;
}
const int ex = id(gaze_x), ey = id(gaze_y);
const int eye_y = 93 + ey, eye_r = 8;
const int lx = 90 + ex, rx = 230 + ex;
if (love) {
// heart eyes, blush and a wide smile
for (int cx : {lx, rx}) {
it.filled_circle(cx - 6, eye_y - 3, 7, id(love_red));
it.filled_circle(cx + 6, eye_y - 3, 7, id(love_red));
it.filled_triangle(cx - 13, eye_y - 1, cx + 13, eye_y - 1, cx, eye_y + 14, id(love_red));
}
it.filled_circle(60 + ex, 130 + ey, 12, Color(90, 20, 40));
it.filled_circle(260 + ex, 130 + ey, 12, Color(90, 20, 40));
if (!id(speaking)) {
it.filled_circle(160 + ex / 2, 132 + ey / 2, 30, id(face_fg));
it.filled_circle(160 + ex / 2, 122 + ey / 2, 30, id(face_bg));
}
} else if (id(eyes_open)) {
it.filled_circle(lx, eye_y, eye_r, id(face_fg));
it.filled_circle(rx, eye_y, eye_r, id(face_fg));
} else {
it.filled_rectangle(lx - eye_r, eye_y - 2, eye_r * 2, 4, id(face_fg));
it.filled_rectangle(rx - eye_r, eye_y - 2, eye_r * 2, 4, id(face_fg));
}
const float m = id(mouth_open);
if (!love || id(speaking)) {
const int mw = 90 - (int) (40 * m);
const int mh = 4 + (int) (26 * m);
it.filled_rectangle(160 - mw / 2 + ex / 2, 148 - mh / 2 + ey / 2, mw, mh, id(face_fg));
}
if (id(listening)) {
it.image(254, 2, id(icon_listening), id(face_fg), id(face_bg)); // left of the wifi bars
}
touchscreen:
- platform: ft63x6
id: touch_lcd
i2c_id: i2c_bsp
reset_pin:
aw9523b_id: aw9523b_hub
number: 0
on_touch:
- voice_assistant.start:
esp32_camera:
id: camera_id
name: Camera
i2c_id: i2c_bsp
setup_priority: -200 # after power rails and IO expanders
pixel_format: RGB565
max_framerate: 15 fps
frame_buffer_count: 1
# GC0308 has no JPEG, convert RGB565 -> JPEG for HA (as in BSP); runs in the main loop, so no periodic frames
jpeg_quality: 12
idle_framerate: 0 fps
vsync_pin:
number: 46
ignore_strapping_warning: true
href_pin: 38
external_clock:
pin: 2
frequency: 20MHz
pixel_clock_pin:
number: 45
ignore_strapping_warning: true
data_pins: [39, 40, 41, 42, 15, 16, 48, 47]
resolution: 320x240
frame_buffer_location: PSRAM
sensor:
- platform: axp2101
id: axp2101_sensor
battery_level:
id: battery_level
name: Battery Level
filters:
- delta: 1.0
on_value:
- component.update: display_tft
battery_charging:
id: battery_charging
name: Battery Charging
on_state:
- component.update: display_tft
- platform: ltr_als_ps
i2c_id: i2c_bsp
address: 0x23
type: ALS_PS
ambient_light:
id: ambient_light
name: Ambient Light
ps_counts:
id: proximity_counts
name: Proximity Counts
- platform: ina226
i2c_id: i2c_bsp
address: 0x41
shunt_resistance: 0.01 ohm
max_current: 3.2A
current:
id: ina226_current
name: Current
power:
id: ina226_power
name: Power
bus_voltage:
id: ina226_bus_voltage
name: Bus Voltage
si12t:
id: touch_hub
i2c_id: i2c_bsp
# report low-strength touches too, not only medium/high
intr_level: OUTPUT_ALL
text_sensor:
- platform: si12t
id: head_touch_1
name: Head Touch 1
channel: CH_1
# lower level = lower touch threshold: SENS_LEVEL_1 = 0.7 % capacitance change (default level 3 is 1.2 %),
# SENS_LEVEL_0 made neighbouring pads trigger together
sensitivity: SENS_LEVEL_1
extend_threshold: false
update_interval: 100ms
internal: true
- platform: si12t
id: head_touch_2
name: Head Touch 2
channel: CH_2
sensitivity: SENS_LEVEL_1
extend_threshold: false
update_interval: 100ms
internal: true
- platform: si12t
id: head_touch_3
name: Head Touch 3
channel: CH_3
sensitivity: SENS_LEVEL_1
extend_threshold: false
update_interval: 100ms
internal: true
uart:
- id: uart_servo
tx_pin: 6
rx_pin: 7
baud_rate: 1000000
scs9009:
ftservo:
- platform: scs9009
id: x_servo
address: 1
- platform: scs9009
id: y_servo
address: 2
number:
- platform: ftservo
ftservo_id: x_servo
angle:
id: servo_x_angle
name: Servo X Angle
min_value: -164
max_value: 164
use_raw_angle: false
angle_offset: 164
step: 5
light:
- platform: m5ioe1
id: light_bar
name: Light Bar
num_led: 12
- platform: monochromatic
id: lcd_backlight
name: LCD Backlight
output: lcd_backlight_output
restore_mode: ALWAYS_ON
remote_transmitter:
id: ir_tx
pin: 5
carrier_duty_percent: 50%
non_blocking: true
remote_receiver:
id: ir_rx
pin: 10
time:
- platform: bm8563
id: rtc_time
i2c_id: i2c_bsp
update_interval: never
- !include common/time/homeassistant.yaml
+2 -11
View File
@@ -18,19 +18,10 @@ esp32:
variant: esp32c3
framework:
type: esp-idf
version: 5.3.2
platform_version: 53.03.11
packages:
common: !include common/common.yaml
# external_components:
# - source:
# type: git
# url: https://github.com/clydebarrow/esphome
# ref: fd15094c0860df23d532881df36cfd16c7da1091 #previous commit - wont be needed in the future
# components: [ lvgl ]
logger:
logs:
component: ERROR
@@ -108,8 +99,8 @@ font:
display:
- platform: ili9xxx
model: TFT 2.4
- platform: mipi_spi
model: ILI9341
cs_pin: 7
dc_pin: 8
reset_pin: 10
+68 -4
View File
@@ -29,55 +29,93 @@ esp32:
toolchain: esp-idf
framework:
type: esp-idf
advanced:
sram1_as_iram: true
packages:
common: !include common/common.yaml
api:
services:
- service: irrigation_morning
actions:
- action: irrigation_morning
then:
- lambda: |-
id(relay_module).setup();
- switch.turn_on: irrigation_relay_1
- delay: 4minutes
- switch.turn_off: irrigation_relay_1
- delay: 2minutes
- lambda: |-
id(relay_module).setup();
- switch.turn_on: irrigation_relay_1
- delay: 4minutes
- switch.turn_off: irrigation_relay_1
- delay: 2minutes
- lambda: |-
id(relay_module).setup();
- switch.turn_on: irrigation_relay_2
- delay: 4minutes
- switch.turn_off: irrigation_relay_2
- delay: 2minutes
- lambda: |-
id(relay_module).setup();
- switch.turn_on: irrigation_relay_2
- delay: 4minutes
- switch.turn_off: irrigation_relay_2
- delay: 2minutes
- lambda: |-
id(relay_module).setup();
- switch.turn_on: irrigation_relay_3
- delay: 4minutes
- switch.turn_off: irrigation_relay_3
# - switch.turn_on: irrigation_relay_4
# - delay: 40minutes
# - switch.turn_off: irrigation_relay_4
- service: irrigation_grass
- action: irrigation_grass
then:
- lambda: |-
id(relay_module).setup();
- switch.turn_on: irrigation_relay_1
- delay: 5minutes
- switch.turn_off: irrigation_relay_1
- delay: 2minutes
- lambda: |-
id(relay_module).setup();
- switch.turn_on: irrigation_relay_2
- delay: 5minutes
- switch.turn_off: irrigation_relay_2
- delay: 2minutes
- lambda: |-
id(relay_module).setup();
- switch.turn_on: irrigation_relay_3
- delay: 2minutes
- switch.turn_off: irrigation_relay_3
- service: irrigation_patio
- action: irrigation_patio
then:
- lambda: |-
id(relay_module).setup();
- switch.turn_on: irrigation_relay_5
- delay: 30sec
- switch.turn_off: irrigation_relay_5
script:
- id: modbus_turn_on_ch1
mode: single
then:
- lambda: |-
ESP_LOGD("modbus", "Sending Channel 0 ON command as byte array");
// Channel 0 open command: [0x01, 0x05, 0x00, 0x00, 0xFF, 0x00, 0x8C, 0x3A]
uint8_t data[8] = {0x01, 0x06, 0x00, 0x01, 0x01, 0x00, 0xD9, 0x9A};
id(modbus_uart).write_array(data, 8);
- id: modbus_turn_off_ch1
mode: single
then:
- lambda: |-
ESP_LOGD("modbus", "Sending Channel 0 OFF command as byte array");
// Channel 0 close command: [0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0xCD, 0xCA]
uint8_t data[8] = {0x01, 0x06, 0x00, 0x01, 0x02, 0x00, 0xD9, 0x6A};
id(modbus_uart).write_array(data, 8);
i2c:
sda: 25
scl: 21
@@ -87,6 +125,32 @@ pca9554:
- id: relay_module
address: 0x27
uart:
id: modbus_uart
tx_pin: 23
rx_pin: 33
baud_rate: 9600
data_bits: 8
parity: NONE
stop_bits: 1
rx_buffer_size: 256
modbus:
id: modbus_hub
uart_id: modbus_uart
modbus_controller:
- id: n4dig08
address: 0x01
modbus_id: modbus_hub
setup_priority: -10
logger:
level: DEBUG # Alebo VERY_VERBOSE, ak chceš vidieť úplne všetko
logs:
modbus: DEBUG
modbus_controller: DEBUG
sprinkler:
- id: lawn_sprinkler_ctrlr
main_switch: "Irrigation A"
-108
View File
@@ -1,108 +0,0 @@
{
"none": "Žiady",
"unknown": "Neznámy",
"preset_mode": "Prednastavený režim",
"swing_mode": "Režim oscilácie",
"fan_mode": "Režim ventilátora",
"activity": "Aktivita",
"away": "Preč",
"boost": "Boost",
"comfort": "Komfort",
"eco": "Eko",
"home": "Domov",
"sleep": "Spánok",
"cool": "Chladenie",
"cooling": "Chladí",
"dry": "Sušenie",
"drying": "Suší",
"fan": "Ventilátor",
"heat": "Kúrenie",
"heating": "Kúri",
"heat_cool": "Kúrenie/Chladenie",
"idle": "V kľude",
"auto": "Automatický",
"fan_only": "Len ventilátor",
"on": "Zapnuté",
"off": "Vypnuté",
"currently": "Aktuálne",
"state": "Stav",
"action": "Akcia",
"lock": "Zamknúť",
"unlock": "Odomknúť",
"paused": "Pozastavené",
"active": "Aktívne",
"activate": "Aktivovať",
"press": "Stlačiť",
"run": "Spustiť",
"speed": "Rýchlosť",
"brightness": "Jas",
"color": "Farba",
"color_temp": "Teplota farby",
"above_horizon": "Nad horizontom",
"below_horizon": "Pod horizontom",
"position": "Pozícia",
"tilt_position": "Náklon",
"start": "Štart",
"pause": "Pauza",
"cancel": "Zrušiť",
"finish": "Dokončiť",
"arm_home": "Arm (doma)",
"arm_away": "Arm (mimo domov)",
"arm_night": "Arm (noc)",
"arm_vacation": "Arm (dovolenka)",
"arm_custom_bypass": "Arm (bypass)",
"disarm": "Vypnúť zabezpečenie",
"disarming": "Vypínanie zabezpečenia",
"disarmed": "Zabezpečenie vypnuté",
"arming": "Zabezpečuje sa",
"pending": "Čekanie",
"triggered": "Poplach",
"armed_away": "Zabezpečené (mimo domov)",
"armed_home": "Zabezpečené (doma)",
"armed_night": "Zabezpečené (noc)",
"armed_vacation": "Zabezpečené (dovolenka)",
"armed_custom_bypass": "Zabezpečené (bypass)",
"not_home": "Mimo domov",
"start_cleaning": "Začať upratovať",
"return_to_base": "Späť na základňu",
"docked": "Zaparkované",
"turn_on": "Zapnúť",
"turn_off": "Vypnúť",
"month_january": "Január",
"month_jan": "Jan",
"month_february": "Február",
"month_feb": "Feb",
"month_march": "Marec",
"month_mar": "Mar",
"month_april": "Apríl",
"month_apr": "Apr",
"month_may": "Máj",
"month_june": "Jún",
"month_jun": "Jun",
"month_july": "Júl",
"month_jul": "Jul",
"month_august": "August",
"month_aug": "Aug",
"month_september": "September",
"month_sep": "Sep",
"month_october": "Október",
"month_oct": "Okt",
"month_november": "November",
"month_nov": "Nov",
"month_december": "December",
"month_dec": "Dec",
"dow_sunday": "Nedela",
"dow_sun": "Ne",
"dow_monday": "Pondelok",
"dow_mon": "Po",
"dow_tuesday": "Utorok",
"dow_tue": "Ut",
"dow_wednesday": "Streda",
"dow_wed": "St",
"dow_thursday": "Štvrtok",
"dow_thu": "Št",
"dow_friday": "Piatok",
"dow_fri": "Pi",
"dow_saturday": "Sobota",
"dow_sat": "So"
}