Compare commits
18
Commits
302bc3a924
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe14c3c723 | ||
|
|
9a800b3732 | ||
|
|
330cf7569f | ||
|
|
a1e3ca23b8 | ||
|
|
976045a2eb | ||
|
|
cf4837f121 | ||
|
|
163d95a8de | ||
|
|
777a1870ea | ||
|
|
1fb90a6144 | ||
|
|
afaaa9f4eb | ||
|
|
d508c3c6f2 | ||
|
|
bb1f514fee | ||
|
|
08b6b6bc07 | ||
|
|
230126248d | ||
|
|
ce7704c628 | ||
|
|
333484a89a | ||
|
|
ef2047e268 | ||
|
|
dc6cf4d1af |
+1
-1
@@ -1 +1 @@
|
|||||||
2026.7.4
|
2026.9.2
|
||||||
+43
-9
@@ -70,8 +70,9 @@
|
|||||||
action: light.turn_off
|
action: light.turn_off
|
||||||
mode: single
|
mode: single
|
||||||
- id: '1623673821789'
|
- id: '1623673821789'
|
||||||
alias: Gute Nacht!
|
alias: Schlafen gehen
|
||||||
description: Schalte alles (außer Schlafzimmer) aus, sobald das Schlaftracking startet.
|
description: Schalte alles (außer Schlafzimmer) aus und schließ die Wohnungstür,
|
||||||
|
sobald das Schlaftracking startet.
|
||||||
triggers:
|
triggers:
|
||||||
- trigger: state
|
- trigger: state
|
||||||
entity_id:
|
entity_id:
|
||||||
@@ -95,6 +96,11 @@
|
|||||||
device_id: 6d1be741876624a70ab5b01b54c6fd6f
|
device_id: 6d1be741876624a70ab5b01b54c6fd6f
|
||||||
entity_id: switch.kuche_musik
|
entity_id: switch.kuche_musik
|
||||||
domain: switch
|
domain: switch
|
||||||
|
- action: lock.lock
|
||||||
|
metadata: {}
|
||||||
|
target:
|
||||||
|
entity_id: lock.flur_wohnungstur
|
||||||
|
data: {}
|
||||||
- data:
|
- data:
|
||||||
message: Gute Nacht!
|
message: Gute Nacht!
|
||||||
action: notify.mobile_app_le2123
|
action: notify.mobile_app_le2123
|
||||||
@@ -251,7 +257,7 @@
|
|||||||
action: tts.speak
|
action: tts.speak
|
||||||
mode: single
|
mode: single
|
||||||
- id: '1623954512941'
|
- id: '1623954512941'
|
||||||
alias: Licht im Schlafzimmer zum Aufwachen einschalten
|
alias: Aufwachen
|
||||||
description: Nach der Alarmquittierung
|
description: Nach der Alarmquittierung
|
||||||
triggers:
|
triggers:
|
||||||
- trigger: state
|
- trigger: state
|
||||||
@@ -273,6 +279,11 @@
|
|||||||
device_id: 68868390eda35e969ec60a13020f2407
|
device_id: 68868390eda35e969ec60a13020f2407
|
||||||
data: {}
|
data: {}
|
||||||
action: light.turn_on
|
action: light.turn_on
|
||||||
|
- action: lock.unlock
|
||||||
|
metadata: {}
|
||||||
|
target:
|
||||||
|
entity_id: lock.flur_wohnungstur
|
||||||
|
data: {}
|
||||||
mode: single
|
mode: single
|
||||||
- id: '1624820688449'
|
- id: '1624820688449'
|
||||||
alias: 'Anruf: Beim Klingeln grün blinken'
|
alias: 'Anruf: Beim Klingeln grün blinken'
|
||||||
@@ -439,7 +450,7 @@
|
|||||||
action: light.turn_on
|
action: light.turn_on
|
||||||
mode: single
|
mode: single
|
||||||
- id: '1630914505161'
|
- id: '1630914505161'
|
||||||
alias: Beim Verlassen der Wohnung alles abschalten
|
alias: Wohnung verlassen
|
||||||
description: ''
|
description: ''
|
||||||
triggers:
|
triggers:
|
||||||
- entity_id: person.marcus_scholz
|
- entity_id: person.marcus_scholz
|
||||||
@@ -475,6 +486,11 @@
|
|||||||
device_id:
|
device_id:
|
||||||
- 231cd7ec37e32690faf126105b03ee02
|
- 231cd7ec37e32690faf126105b03ee02
|
||||||
- a6d24e7d93c114723bf525e9eac1c2df
|
- a6d24e7d93c114723bf525e9eac1c2df
|
||||||
|
- action: lock.lock
|
||||||
|
metadata: {}
|
||||||
|
target:
|
||||||
|
entity_id: lock.flur_wohnungstur
|
||||||
|
data: {}
|
||||||
- type: turn_off
|
- type: turn_off
|
||||||
device_id: c4ead7f6227e2ee4c43c4b0df829cd84
|
device_id: c4ead7f6227e2ee4c43c4b0df829cd84
|
||||||
entity_id: 7f7284b11f2bf50ae2f0ebeeb35411c0
|
entity_id: 7f7284b11f2bf50ae2f0ebeeb35411c0
|
||||||
@@ -1438,7 +1454,6 @@
|
|||||||
device_id: 6d1be741876624a70ab5b01b54c6fd6f
|
device_id: 6d1be741876624a70ab5b01b54c6fd6f
|
||||||
entity_id: 621e4377a089b7f5d92c7c9f2cc171a1
|
entity_id: 621e4377a089b7f5d92c7c9f2cc171a1
|
||||||
domain: switch
|
domain: switch
|
||||||
|
|
||||||
- id: epaper_daily_demotivational_quote
|
- id: epaper_daily_demotivational_quote
|
||||||
alias: Epaper tägliches Demotivationszitat
|
alias: Epaper tägliches Demotivationszitat
|
||||||
description: Wählt täglich ein festes Zitat aus der lokalen Zitatbibliothek aus.
|
description: Wählt täglich ein festes Zitat aus der lokalen Zitatbibliothek aus.
|
||||||
@@ -1446,14 +1461,33 @@
|
|||||||
- trigger: homeassistant
|
- trigger: homeassistant
|
||||||
event: start
|
event: start
|
||||||
- trigger: time
|
- trigger: time
|
||||||
at: "00:00:00"
|
at: 00:00:00
|
||||||
conditions: []
|
conditions: []
|
||||||
actions:
|
actions:
|
||||||
- action: input_select.select_option
|
- action: input_select.select_option
|
||||||
target:
|
target:
|
||||||
entity_id: input_select.epaper_demotivationszitat
|
entity_id: input_select.epaper_demotivationszitat
|
||||||
data:
|
data:
|
||||||
option: >-
|
option: '{% set quotes = state_attr(''input_select.epaper_demotivationszitat'',
|
||||||
{% set quotes = state_attr('input_select.epaper_demotivationszitat', 'options') %}
|
''options'') %} {{ quotes[(now().strftime(''%j'') | int - 1) % (quotes | count)]
|
||||||
{{ quotes[(now().strftime('%j') | int - 1) % (quotes | count)] }}
|
}}'
|
||||||
|
mode: single
|
||||||
|
- id: '1785863986502'
|
||||||
|
alias: SmartMirror neu laden
|
||||||
|
description: ''
|
||||||
|
triggers:
|
||||||
|
- trigger: time
|
||||||
|
at: 00:00:10
|
||||||
|
conditions: []
|
||||||
|
actions:
|
||||||
|
- action: button.press
|
||||||
|
metadata: {}
|
||||||
|
target:
|
||||||
|
entity_id: button.touchkio_smartmirror_refresh
|
||||||
|
data: {}
|
||||||
|
- action: button.press
|
||||||
|
metadata: {}
|
||||||
|
target:
|
||||||
|
entity_id: button.touchkio_raspberrypi_refresh
|
||||||
|
data: {}
|
||||||
mode: single
|
mode: single
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
# Configure a default setup of Home Assistant (frontend, api, etc)
|
# Configure a default setup of Home Assistant (frontend, api, etc)
|
||||||
default_config:
|
default_config:
|
||||||
|
|
||||||
# Enable SSL/TLS
|
|
||||||
http:
|
|
||||||
server_port: 443
|
|
||||||
ssl_certificate: /ssl/fullchain.pem
|
|
||||||
ssl_key: /ssl/privkey.pem
|
|
||||||
|
|
||||||
# Text to speech
|
# Text to speech
|
||||||
tts:
|
tts:
|
||||||
- platform: picotts_remote
|
- platform: picotts_remote
|
||||||
@@ -91,5 +85,3 @@ frontend:
|
|||||||
|
|
||||||
freedns:
|
freedns:
|
||||||
url: !secret freedns6_url
|
url: !secret freedns6_url
|
||||||
# - name: IPv4
|
|
||||||
# url: !secret freedns4_url
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ substitutions:
|
|||||||
external_components_source: github://syssi/esphome-atorch-dl24@main
|
external_components_source: github://syssi/esphome-atorch-dl24@main
|
||||||
dl24_mac_address: !secret dl24_mac_address
|
dl24_mac_address: !secret dl24_mac_address
|
||||||
project_version: 2.1.0
|
project_version: 2.1.0
|
||||||
device_description: "Monitor and control a Atorch meter via bluetooth BLE"
|
device_description: "ESP32-S3 BLE client to monitor and control an Atorch DL24 programmable DC load"
|
||||||
|
|
||||||
esphome:
|
esphome:
|
||||||
name: ${name}
|
name: ${name}
|
||||||
@@ -36,7 +36,7 @@ api:
|
|||||||
# Enable over-the-air updates
|
# Enable over-the-air updates
|
||||||
ota:
|
ota:
|
||||||
platform: esphome
|
platform: esphome
|
||||||
password: !secret ota
|
encryption:
|
||||||
|
|
||||||
network:
|
network:
|
||||||
enable_ipv6: true
|
enable_ipv6: true
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
name: "aussensensor"
|
name: "aussensensor"
|
||||||
friendly_name: "Außensensor"
|
friendly_name: "Außensensor"
|
||||||
|
device_description: "NodeMCU-32S outdoor temperature and humidity sensor using a DHT22"
|
||||||
|
|
||||||
esphome:
|
esphome:
|
||||||
name: ${name}
|
name: ${name}
|
||||||
friendly_name: ${friendly_name}
|
friendly_name: ${friendly_name}
|
||||||
|
comment: ${device_description}
|
||||||
name_add_mac_suffix: false
|
name_add_mac_suffix: false
|
||||||
project:
|
project:
|
||||||
name: sensor.outdoor
|
name: sensor.outdoor
|
||||||
@@ -40,7 +42,7 @@ api:
|
|||||||
|
|
||||||
ota:
|
ota:
|
||||||
platform: esphome
|
platform: esphome
|
||||||
password: !secret ota
|
encryption:
|
||||||
|
|
||||||
# DHT22 sensor
|
# DHT22 sensor
|
||||||
sensor:
|
sensor:
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ api:
|
|||||||
|
|
||||||
ota:
|
ota:
|
||||||
platform: esphome
|
platform: esphome
|
||||||
password: !secret ota
|
encryption:
|
||||||
|
|
||||||
wifi:
|
wifi:
|
||||||
ssid: "Voltage-legacy"
|
ssid: "Voltage-legacy"
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ api:
|
|||||||
|
|
||||||
ota:
|
ota:
|
||||||
platform: esphome
|
platform: esphome
|
||||||
password: !secret ota
|
encryption:
|
||||||
|
|
||||||
wifi:
|
wifi:
|
||||||
ssid: "Voltage-legacy"
|
ssid: "Voltage-legacy"
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
name: "raspiaudio-muse-luxe"
|
name: "raspiaudio-muse-luxe"
|
||||||
friendly_name: "RaspiAudio Muse Luxe"
|
friendly_name: "RaspiAudio Muse Luxe"
|
||||||
|
device_description: "RaspiAudio Muse Luxe ESP32 voice assistant and media player with local wake-word detection, ES8388 audio codec and battery monitoring"
|
||||||
#States
|
#States
|
||||||
P_starting: "0"
|
P_starting: "0"
|
||||||
P_waiting: "1"
|
P_waiting: "1"
|
||||||
@@ -18,7 +19,7 @@ api:
|
|||||||
ota:
|
ota:
|
||||||
- platform: esphome
|
- platform: esphome
|
||||||
id: ota_esphome
|
id: ota_esphome
|
||||||
password: !secret ota
|
encryption:
|
||||||
|
|
||||||
external_components:
|
external_components:
|
||||||
- source: github://RASPIAUDIO/esphomeLuxe@main
|
- source: github://RASPIAUDIO/esphomeLuxe@main
|
||||||
@@ -43,6 +44,7 @@ wifi:
|
|||||||
esphome:
|
esphome:
|
||||||
name: ${name}
|
name: ${name}
|
||||||
friendly_name: ${friendly_name}
|
friendly_name: ${friendly_name}
|
||||||
|
comment: ${device_description}
|
||||||
min_version: 2025.2.0
|
min_version: 2025.2.0
|
||||||
name_add_mac_suffix: false
|
name_add_mac_suffix: false
|
||||||
platformio_options:
|
platformio_options:
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
name: "sleepingroom"
|
name: "sleepingroom"
|
||||||
friendly_name: "Luftqualität Schlafzimmer"
|
friendly_name: "Luftqualität Schlafzimmer"
|
||||||
|
device_description: "NodeMCU-32S bedroom air-quality monitor with SCD30 CO2, temperature and humidity, PM1006 particulate sensing, RGB status LED and IR receiver/transmitter"
|
||||||
|
|
||||||
esphome:
|
esphome:
|
||||||
name: ${name}
|
name: ${name}
|
||||||
friendly_name: ${friendly_name}
|
friendly_name: ${friendly_name}
|
||||||
|
comment: ${device_description}
|
||||||
name_add_mac_suffix: false
|
name_add_mac_suffix: false
|
||||||
project:
|
project:
|
||||||
name: sensor.${name}
|
name: sensor.${name}
|
||||||
@@ -80,7 +82,7 @@ api:
|
|||||||
# Enable over-the-air updates
|
# Enable over-the-air updates
|
||||||
ota:
|
ota:
|
||||||
platform: esphome
|
platform: esphome
|
||||||
password: !secret ota
|
encryption:
|
||||||
|
|
||||||
# Initialize I²C
|
# Initialize I²C
|
||||||
i2c:
|
i2c:
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
|
device_description: "ESP32-C3 bathroom temperature and humidity monitor with DHT22 and SHT3x sensors"
|
||||||
name: "bathroom"
|
name: "bathroom"
|
||||||
friendly_name: "Bad"
|
friendly_name: "Bad"
|
||||||
|
|
||||||
esphome:
|
esphome:
|
||||||
|
comment: ${device_description}
|
||||||
name: ${name}
|
name: ${name}
|
||||||
friendly_name: ${friendly_name}
|
friendly_name: ${friendly_name}
|
||||||
name_add_mac_suffix: false
|
name_add_mac_suffix: false
|
||||||
@@ -44,7 +46,7 @@ api:
|
|||||||
|
|
||||||
ota:
|
ota:
|
||||||
platform: esphome
|
platform: esphome
|
||||||
password: !secret ota
|
encryption:
|
||||||
|
|
||||||
# Initialize I²C
|
# Initialize I²C
|
||||||
i2c:
|
i2c:
|
||||||
|
|||||||
+413
-22
@@ -1,8 +1,12 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
|
device_description: "M5Stack Core energy dashboard for Home Assistant grid, solar and consumer usage, with analog/digital clock and WireGuard"
|
||||||
name: "energymonitor"
|
name: "energymonitor"
|
||||||
friendly_name: "Energy Monitor"
|
friendly_name: "Energy Monitor"
|
||||||
|
grid_power_gauge_max_w: "5000.0"
|
||||||
|
balcony_solar_gauge_max_w: "800.0"
|
||||||
|
|
||||||
esphome:
|
esphome:
|
||||||
|
comment: ${device_description}
|
||||||
name: ${name}
|
name: ${name}
|
||||||
friendly_name: ${friendly_name}
|
friendly_name: ${friendly_name}
|
||||||
name_add_mac_suffix: false
|
name_add_mac_suffix: false
|
||||||
@@ -17,6 +21,9 @@ esp32:
|
|||||||
board: m5stack-core-esp32
|
board: m5stack-core-esp32
|
||||||
framework:
|
framework:
|
||||||
type: esp-idf
|
type: esp-idf
|
||||||
|
advanced:
|
||||||
|
minimum_chip_revision: "3.1"
|
||||||
|
sram1_as_iram: true
|
||||||
|
|
||||||
network:
|
network:
|
||||||
enable_ipv6: true
|
enable_ipv6: true
|
||||||
@@ -29,6 +36,9 @@ wifi:
|
|||||||
- ssid: "Moppelkotze"
|
- ssid: "Moppelkotze"
|
||||||
password: !secret moppelkotze_psk
|
password: !secret moppelkotze_psk
|
||||||
priority: 5
|
priority: 5
|
||||||
|
- ssid: "TKRZ"
|
||||||
|
password: !secret tkrz_psk
|
||||||
|
priority: 4
|
||||||
use_address: 192.168.126.250
|
use_address: 192.168.126.250
|
||||||
on_connect:
|
on_connect:
|
||||||
- lambda: id(wifi_connected) = true;
|
- lambda: id(wifi_connected) = true;
|
||||||
@@ -67,12 +77,13 @@ wireguard:
|
|||||||
logger:
|
logger:
|
||||||
|
|
||||||
api:
|
api:
|
||||||
|
id: api_server
|
||||||
encryption:
|
encryption:
|
||||||
key: !secret apikey
|
key: !secret apikey
|
||||||
|
|
||||||
ota:
|
ota:
|
||||||
platform: esphome
|
platform: esphome
|
||||||
password: !secret ota
|
encryption:
|
||||||
|
|
||||||
spi:
|
spi:
|
||||||
clk_pin: GPIO18
|
clk_pin: GPIO18
|
||||||
@@ -109,11 +120,18 @@ font:
|
|||||||
glyphsets:
|
glyphsets:
|
||||||
- GF_Latin_Kernel
|
- GF_Latin_Kernel
|
||||||
glyphs: ["äöüÄÖÜß"]
|
glyphs: ["äöüÄÖÜß"]
|
||||||
|
- file: "fonts/Roboto-Regular.ttf"
|
||||||
|
id: font_device
|
||||||
|
size: 13
|
||||||
|
glyphsets:
|
||||||
|
- GF_Latin_Kernel
|
||||||
|
glyphs: ["äöüÄÖÜß"]
|
||||||
- file: "fonts/materialdesignicons-webfont.ttf"
|
- file: "fonts/materialdesignicons-webfont.ttf"
|
||||||
id: font_icon
|
id: font_icon
|
||||||
size: 24
|
size: 24
|
||||||
glyphs:
|
glyphs:
|
||||||
- "\U000F0306" # mdi:key
|
- "\U000F0306" # mdi:key
|
||||||
|
- "\U000F07D0" # mdi:home-assistant
|
||||||
- "\U000F091F" # mdi:wifi-strength-1
|
- "\U000F091F" # mdi:wifi-strength-1
|
||||||
- "\U000F0922" # mdi:wifi-strength-2
|
- "\U000F0922" # mdi:wifi-strength-2
|
||||||
- "\U000F0925" # mdi:wifi-strength-3
|
- "\U000F0925" # mdi:wifi-strength-3
|
||||||
@@ -129,13 +147,25 @@ globals:
|
|||||||
type: bool
|
type: bool
|
||||||
restore_value: false
|
restore_value: false
|
||||||
initial_value: 'false'
|
initial_value: 'false'
|
||||||
|
- id: page_one_gauge_view
|
||||||
|
type: bool
|
||||||
|
restore_value: true
|
||||||
|
initial_value: 'false'
|
||||||
|
- id: clock_digital_view
|
||||||
|
type: bool
|
||||||
|
restore_value: true
|
||||||
|
initial_value: 'false'
|
||||||
|
- id: device_usage_view
|
||||||
|
type: int
|
||||||
|
restore_value: true
|
||||||
|
initial_value: '0'
|
||||||
|
|
||||||
sensor:
|
sensor:
|
||||||
# WiFi signal strength
|
# WiFi signal strength
|
||||||
- platform: wifi_signal
|
- platform: wifi_signal
|
||||||
name: "WiFi Signalstärke"
|
name: "WiFi Signalstärke"
|
||||||
id: wifisignal
|
id: wifisignal
|
||||||
update_interval: 60s
|
update_interval: 10s
|
||||||
- platform: homeassistant
|
- platform: homeassistant
|
||||||
id: grid_power
|
id: grid_power
|
||||||
entity_id: sensor.netzleistung
|
entity_id: sensor.netzleistung
|
||||||
@@ -144,10 +174,132 @@ sensor:
|
|||||||
id: balcony_solar_power
|
id: balcony_solar_power
|
||||||
entity_id: sensor.balkonkraftwerk_power
|
entity_id: sensor.balkonkraftwerk_power
|
||||||
internal: true
|
internal: true
|
||||||
|
- platform: homeassistant
|
||||||
|
id: solar_energy_daily
|
||||||
|
entity_id: sensor.energy_solar_daily
|
||||||
|
internal: true
|
||||||
|
- platform: homeassistant
|
||||||
|
id: grid_import_energy_daily
|
||||||
|
entity_id: sensor.energy_import_daily
|
||||||
|
internal: true
|
||||||
|
- platform: homeassistant
|
||||||
|
id: grid_export_energy_daily
|
||||||
|
entity_id: sensor.energy_export_daily
|
||||||
|
internal: true
|
||||||
|
- platform: homeassistant
|
||||||
|
id: hallway_fragrance_power
|
||||||
|
entity_id: sensor.flur_raumduft_power
|
||||||
|
internal: true
|
||||||
|
- platform: homeassistant
|
||||||
|
id: cellar_power
|
||||||
|
entity_id: sensor.keller_power
|
||||||
|
internal: true
|
||||||
|
- platform: homeassistant
|
||||||
|
id: sideboard_power
|
||||||
|
entity_id: sensor.kuche_anrichte_power
|
||||||
|
internal: true
|
||||||
|
- platform: homeassistant
|
||||||
|
id: kitchen_music_power
|
||||||
|
entity_id: sensor.kuche_musik_power
|
||||||
|
internal: true
|
||||||
|
- platform: homeassistant
|
||||||
|
id: bedroom_bed_power
|
||||||
|
entity_id: sensor.schlafzimmer_bett_power
|
||||||
|
internal: true
|
||||||
|
- platform: homeassistant
|
||||||
|
id: bedroom_cinema_power
|
||||||
|
entity_id: sensor.schlafzimmer_heimkino_power
|
||||||
|
internal: true
|
||||||
|
- platform: homeassistant
|
||||||
|
id: desk_decoration_power
|
||||||
|
entity_id: sensor.schreibtisch_deko_power
|
||||||
|
internal: true
|
||||||
|
- platform: homeassistant
|
||||||
|
id: desk_power
|
||||||
|
entity_id: sensor.schreibtisch_power
|
||||||
|
internal: true
|
||||||
|
- platform: homeassistant
|
||||||
|
id: server_room_power
|
||||||
|
entity_id: sensor.serverraum_power
|
||||||
|
internal: true
|
||||||
|
- platform: homeassistant
|
||||||
|
id: living_room_cinema_power
|
||||||
|
entity_id: sensor.wohnzimmer_heimkino_power
|
||||||
|
internal: true
|
||||||
|
- platform: homeassistant
|
||||||
|
id: games_cabinet_power
|
||||||
|
entity_id: sensor.wohnzimmer_spieleschrank_power
|
||||||
|
internal: true
|
||||||
|
- platform: homeassistant
|
||||||
|
id: refrigerator_power
|
||||||
|
entity_id: sensor.tz3000_ww6drja5_ts011f_leistung
|
||||||
|
internal: true
|
||||||
|
- platform: homeassistant
|
||||||
|
id: coffee_machine_power
|
||||||
|
entity_id: sensor.kaffeemaschine_leistung_2
|
||||||
|
internal: true
|
||||||
|
- platform: homeassistant
|
||||||
|
id: dryer_power
|
||||||
|
entity_id: sensor.ikea_of_sweden_inspelning_smart_plug_leistung
|
||||||
|
internal: true
|
||||||
|
- platform: homeassistant
|
||||||
|
id: washing_machine_power
|
||||||
|
entity_id: sensor.waschmaschine_leistung
|
||||||
|
internal: true
|
||||||
|
- platform: homeassistant
|
||||||
|
id: arcade_power
|
||||||
|
entity_id: sensor.arcade_automat_leistung
|
||||||
|
internal: true
|
||||||
|
- platform: homeassistant
|
||||||
|
id: dishwasher_power
|
||||||
|
entity_id: sensor.spulmaschine_leistung
|
||||||
|
internal: true
|
||||||
|
- platform: homeassistant
|
||||||
|
id: microwave_power
|
||||||
|
entity_id: sensor.waschetrockner_leistung
|
||||||
|
internal: true
|
||||||
- platform: wireguard
|
- platform: wireguard
|
||||||
latest_handshake:
|
latest_handshake:
|
||||||
name: 'WireGuard Latest Handshake'
|
name: 'WireGuard Latest Handshake'
|
||||||
|
|
||||||
|
script:
|
||||||
|
- id: show_previous_page
|
||||||
|
then:
|
||||||
|
- lambda: id(page_index) = (id(page_index) + 3 - 1) % 3;
|
||||||
|
- component.update: tft
|
||||||
|
- id: toggle_page_mode
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
if (id(page_index) == 0) {
|
||||||
|
id(page_one_gauge_view) = !id(page_one_gauge_view);
|
||||||
|
} else if (id(page_index) == 1) {
|
||||||
|
id(device_usage_view) = (id(device_usage_view) + 1) % 2;
|
||||||
|
} else {
|
||||||
|
id(clock_digital_view) = !id(clock_digital_view);
|
||||||
|
}
|
||||||
|
- component.update: tft
|
||||||
|
- id: show_next_page
|
||||||
|
then:
|
||||||
|
- lambda: id(page_index) = (id(page_index) + 1) % 3;
|
||||||
|
- component.update: tft
|
||||||
|
|
||||||
|
button:
|
||||||
|
- platform: template
|
||||||
|
name: "Zurück"
|
||||||
|
icon: mdi:arrow-left
|
||||||
|
on_press:
|
||||||
|
- script.execute: show_previous_page
|
||||||
|
- platform: template
|
||||||
|
name: "Modus"
|
||||||
|
icon: mdi:view-dashboard-outline
|
||||||
|
on_press:
|
||||||
|
- script.execute: toggle_page_mode
|
||||||
|
- platform: template
|
||||||
|
name: "Weiter"
|
||||||
|
icon: mdi:arrow-right
|
||||||
|
on_press:
|
||||||
|
- script.execute: show_next_page
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: wireguard
|
- platform: wireguard
|
||||||
status:
|
status:
|
||||||
@@ -155,6 +307,16 @@ binary_sensor:
|
|||||||
- platform: wireguard
|
- platform: wireguard
|
||||||
enabled:
|
enabled:
|
||||||
name: 'WireGuard Enabled'
|
name: 'WireGuard Enabled'
|
||||||
|
# M5Stack Core button B (middle) switches the current page's view.
|
||||||
|
- platform: gpio
|
||||||
|
pin:
|
||||||
|
number: GPIO38
|
||||||
|
mode: INPUT
|
||||||
|
inverted: true
|
||||||
|
id: button_middle
|
||||||
|
on_press:
|
||||||
|
- script.execute: toggle_page_mode
|
||||||
|
|
||||||
# M5Stack Core button A (left). GPIO39 is input-only and has an external pull-up.
|
# M5Stack Core button A (left). GPIO39 is input-only and has an external pull-up.
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
pin:
|
pin:
|
||||||
@@ -163,10 +325,7 @@ binary_sensor:
|
|||||||
inverted: true
|
inverted: true
|
||||||
id: button_left
|
id: button_left
|
||||||
on_press:
|
on_press:
|
||||||
then:
|
- script.execute: show_previous_page
|
||||||
- lambda: |-
|
|
||||||
id(page_index) = (id(page_index) + 2 - 1) % 2;
|
|
||||||
- component.update: tft
|
|
||||||
# M5Stack Core button C (right). GPIO37 is input-only and has an external pull-up.
|
# M5Stack Core button C (right). GPIO37 is input-only and has an external pull-up.
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
pin:
|
pin:
|
||||||
@@ -175,10 +334,7 @@ binary_sensor:
|
|||||||
inverted: true
|
inverted: true
|
||||||
id: button_right
|
id: button_right
|
||||||
on_press:
|
on_press:
|
||||||
then:
|
- script.execute: show_next_page
|
||||||
- lambda: |-
|
|
||||||
id(page_index) = (id(page_index) + 1) % 2;
|
|
||||||
- component.update: tft
|
|
||||||
|
|
||||||
text_sensor:
|
text_sensor:
|
||||||
- platform: wireguard
|
- platform: wireguard
|
||||||
@@ -199,12 +355,17 @@ display:
|
|||||||
it.fill(Color::BLACK);
|
it.fill(Color::BLACK);
|
||||||
|
|
||||||
if (id(sntp_time).now().is_valid()) {
|
if (id(sntp_time).now().is_valid()) {
|
||||||
it.strftime(260, 10, id(font_small), Color::WHITE, TextAlign::TOP_RIGHT,
|
it.strftime(234, 10, id(font_small), Color::WHITE, TextAlign::TOP_RIGHT,
|
||||||
"%H:%M", id(sntp_time).now());
|
"%H:%M", id(sntp_time).now());
|
||||||
} else {
|
} else {
|
||||||
it.printf(260, 10, id(font_small), Color::WHITE, TextAlign::TOP_RIGHT, "--:--");
|
it.printf(234, 10, id(font_small), Color::WHITE, TextAlign::TOP_RIGHT, "--:--");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Native API connectivity; Home Assistant is normally the connected client.
|
||||||
|
const bool home_assistant_online = id(api_server).is_connected();
|
||||||
|
const Color home_assistant_color = home_assistant_online ? Color(64, 255, 64) : Color(255, 80, 80);
|
||||||
|
it.printf(260, 8, id(font_icon), home_assistant_color, TextAlign::TOP_RIGHT, "\U000F07D0");
|
||||||
|
|
||||||
// Green means the WireGuard peer is online; red means it is offline.
|
// Green means the WireGuard peer is online; red means it is offline.
|
||||||
const bool wireguard_online = id(energymonitor_wireguard).is_peer_up();
|
const bool wireguard_online = id(energymonitor_wireguard).is_peer_up();
|
||||||
const Color wireguard_color = wireguard_online ? Color(64, 255, 64) : Color(255, 80, 80);
|
const Color wireguard_color = wireguard_online ? Color(64, 255, 64) : Color(255, 80, 80);
|
||||||
@@ -225,29 +386,251 @@ display:
|
|||||||
}
|
}
|
||||||
it.printf(312, 8, id(font_icon), wifi_color, TextAlign::TOP_RIGHT, "%s", wifi_icon);
|
it.printf(312, 8, id(font_icon), wifi_color, TextAlign::TOP_RIGHT, "%s", wifi_icon);
|
||||||
|
|
||||||
if (id(page_index) == 0) {
|
if (id(page_index) == 0 && !id(page_one_gauge_view)) {
|
||||||
it.printf(12, 12, id(font_small), Color::WHITE, "Netzleistung");
|
it.printf(12, 12, id(font_small), Color::WHITE, "Netzleistung");
|
||||||
if (id(grid_power).has_state()) {
|
if (id(grid_power).has_state()) {
|
||||||
it.printf(308, 32, id(font_value), Color::WHITE, TextAlign::TOP_RIGHT,
|
const Color grid_power_color = id(grid_power).state >= 0
|
||||||
|
? Color(143, 190, 223) // #8FBEDF: positive grid power
|
||||||
|
: Color(150, 110, 217); // #966ED9: negative grid power
|
||||||
|
it.printf(308, 32, id(font_value), grid_power_color, TextAlign::TOP_RIGHT,
|
||||||
"%+.0f W", id(grid_power).state);
|
"%+.0f W", id(grid_power).state);
|
||||||
} else {
|
} else {
|
||||||
it.printf(308, 42, id(font_value), Color::WHITE, TextAlign::TOP_RIGHT,
|
it.printf(308, 42, id(font_value), Color::WHITE, TextAlign::TOP_RIGHT,
|
||||||
"-- W");
|
"-- W");
|
||||||
}
|
}
|
||||||
|
|
||||||
it.printf(12, 99, id(font_small), Color::WHITE, "Balkonkraftwerk");
|
|
||||||
|
if (id(grid_import_energy_daily).has_state()) {
|
||||||
|
it.printf(12, 96, id(font_small), Color::WHITE, "Bezug: %.2f kWh",
|
||||||
|
id(grid_import_energy_daily).state);
|
||||||
|
} else {
|
||||||
|
it.printf(12, 96, id(font_small), Color::WHITE, "Bezug: -- kWh");
|
||||||
|
}
|
||||||
|
if (id(grid_export_energy_daily).has_state()) {
|
||||||
|
it.printf(12, 116, id(font_small), Color::WHITE, "Einspeisung: %.2f kWh",
|
||||||
|
id(grid_export_energy_daily).state);
|
||||||
|
} else {
|
||||||
|
it.printf(12, 116, id(font_small), Color::WHITE, "Einspeisung: -- kWh");
|
||||||
|
}
|
||||||
|
|
||||||
|
it.printf(12, 138, id(font_small), Color::WHITE, "Balkonkraftwerk");
|
||||||
|
// Daily solar energy is aligned to the left of the current solar-power reading.
|
||||||
|
if (id(solar_energy_daily).has_state()) {
|
||||||
|
it.printf(12, 180, id(font_small), Color(255, 170, 40), "Solar: %.2f kWh",
|
||||||
|
id(solar_energy_daily).state);
|
||||||
|
} else {
|
||||||
|
it.printf(12, 180, id(font_small), Color(255, 170, 40), "Solar: -- kWh");
|
||||||
|
}
|
||||||
if (id(balcony_solar_power).has_state()) {
|
if (id(balcony_solar_power).has_state()) {
|
||||||
it.printf(308, 119, id(font_value), Color(255, 215, 0), TextAlign::TOP_RIGHT,
|
it.printf(308, 158, id(font_value), Color(255, 170, 40), TextAlign::TOP_RIGHT,
|
||||||
"%.0f W", id(balcony_solar_power).state);
|
"%.0f W", id(balcony_solar_power).state);
|
||||||
} else {
|
} else {
|
||||||
it.printf(308, 129, id(font_value), Color(255, 215, 0), TextAlign::TOP_RIGHT,
|
it.printf(308, 168, id(font_value), Color(255, 170, 40), TextAlign::TOP_RIGHT,
|
||||||
"-- W");
|
"-- W");
|
||||||
}
|
}
|
||||||
|
} else if (id(page_index) == 0) {
|
||||||
|
// One shared gauge with two parallel curved bars: grid on the outside, solar inside.
|
||||||
|
const Color gauge_background = Color(42, 42, 42);
|
||||||
|
const int gauge_center_x = 160;
|
||||||
|
const int gauge_center_y = 188;
|
||||||
|
|
||||||
|
// The outer band represents the absolute grid-power value with its signed color.
|
||||||
|
float grid_power_value = id(grid_power).has_state() ? id(grid_power).state : 0.0f;
|
||||||
|
float grid_power_magnitude = grid_power_value < 0.0f ? -grid_power_value : grid_power_value;
|
||||||
|
int grid_gauge_percent = static_cast<int>(grid_power_magnitude * 100.0f / ${grid_power_gauge_max_w});
|
||||||
|
if (grid_gauge_percent > 100) grid_gauge_percent = 100;
|
||||||
|
const Color grid_gauge_color = grid_power_value >= 0.0f
|
||||||
|
? Color(143, 190, 223) // #8FBEDF
|
||||||
|
: Color(150, 110, 217); // #966ED9
|
||||||
|
it.filled_gauge(gauge_center_x, gauge_center_y, 140, 122, 100, gauge_background);
|
||||||
|
it.filled_gauge(gauge_center_x, gauge_center_y, 140, 122, grid_gauge_percent, grid_gauge_color);
|
||||||
|
|
||||||
|
// The inner band is solar power, normalized against the 800 W inverter maximum.
|
||||||
|
float solar_power_value = id(balcony_solar_power).has_state() ? id(balcony_solar_power).state : 0.0f;
|
||||||
|
int solar_gauge_percent = static_cast<int>(solar_power_value * 100.0f / ${balcony_solar_gauge_max_w});
|
||||||
|
if (solar_gauge_percent < 0) solar_gauge_percent = 0;
|
||||||
|
if (solar_gauge_percent > 100) solar_gauge_percent = 100;
|
||||||
|
const Color solar_gauge_color = Color(255, 170, 40); // #FFAA28
|
||||||
|
it.filled_gauge(gauge_center_x, gauge_center_y, 116, 98, 100, gauge_background);
|
||||||
|
it.filled_gauge(gauge_center_x, gauge_center_y, 116, 98, solar_gauge_percent, solar_gauge_color);
|
||||||
|
|
||||||
|
it.printf(gauge_center_x, 102, id(font_small), Color::WHITE, TextAlign::TOP_CENTER,
|
||||||
|
"Netzleistung");
|
||||||
|
if (id(grid_power).has_state()) {
|
||||||
|
it.printf(gauge_center_x, 120, id(font_title), grid_gauge_color, TextAlign::TOP_CENTER,
|
||||||
|
"%+.0f W", grid_power_value);
|
||||||
} else {
|
} else {
|
||||||
it.printf(160, 45, id(font_title), Color::WHITE, TextAlign::TOP_CENTER,
|
it.printf(gauge_center_x, 120, id(font_title), Color::WHITE, TextAlign::TOP_CENTER, "-- W");
|
||||||
"Weitere Seite");
|
}
|
||||||
it.printf(160, 95, id(font_small), Color::WHITE, TextAlign::TOP_CENTER,
|
it.printf(gauge_center_x, 151, id(font_small), Color::WHITE, TextAlign::TOP_CENTER,
|
||||||
"Für zusätzliche Werte vorbereitet");
|
"Balkonkraftwerk");
|
||||||
|
if (id(balcony_solar_power).has_state()) {
|
||||||
|
it.printf(gauge_center_x, 169, id(font_title), solar_gauge_color, TextAlign::TOP_CENTER,
|
||||||
|
"%.0f W", solar_power_value);
|
||||||
|
} else {
|
||||||
|
it.printf(gauge_center_x, 169, id(font_title), solar_gauge_color, TextAlign::TOP_CENTER, "-- W");
|
||||||
|
}
|
||||||
|
} else if (id(page_index) == 1) {
|
||||||
|
// Page 2 lists nine consumers at once in two columns; button B changes group.
|
||||||
|
const int device_count = 18;
|
||||||
|
const int usage_group = id(device_usage_view);
|
||||||
|
const int page_start = usage_group * 9;
|
||||||
|
const char *device_names[device_count] = {
|
||||||
|
"Raumduft", "Keller", "Anrichte", "Musik", "Bett", "HK Schlafzimmer",
|
||||||
|
"Deko", "Schreibtisch", "Serverraum", "HK Wohnzimmer", "Spieleschrank",
|
||||||
|
"Kühlschrank", "Kaffeemaschine", "Wäschetrockner", "Waschmaschine", "Arcade",
|
||||||
|
"Spülmaschine", "Mikrowelle"};
|
||||||
|
float device_values[device_count] = {
|
||||||
|
id(hallway_fragrance_power).state, id(cellar_power).state, id(sideboard_power).state,
|
||||||
|
id(kitchen_music_power).state, id(bedroom_bed_power).state, id(bedroom_cinema_power).state,
|
||||||
|
id(desk_decoration_power).state, id(desk_power).state, id(server_room_power).state,
|
||||||
|
id(living_room_cinema_power).state, id(games_cabinet_power).state, id(refrigerator_power).state,
|
||||||
|
id(coffee_machine_power).state, id(dryer_power).state, id(washing_machine_power).state,
|
||||||
|
id(arcade_power).state, id(dishwasher_power).state, id(microwave_power).state};
|
||||||
|
bool device_has_state[device_count] = {
|
||||||
|
id(hallway_fragrance_power).has_state(), id(cellar_power).has_state(), id(sideboard_power).has_state(),
|
||||||
|
id(kitchen_music_power).has_state(), id(bedroom_bed_power).has_state(), id(bedroom_cinema_power).has_state(),
|
||||||
|
id(desk_decoration_power).has_state(), id(desk_power).has_state(), id(server_room_power).has_state(),
|
||||||
|
id(living_room_cinema_power).has_state(), id(games_cabinet_power).has_state(), id(refrigerator_power).has_state(),
|
||||||
|
id(coffee_machine_power).has_state(), id(dryer_power).has_state(), id(washing_machine_power).has_state(),
|
||||||
|
id(arcade_power).has_state(), id(dishwasher_power).has_state(), id(microwave_power).has_state()};
|
||||||
|
Color device_colors[device_count] = {
|
||||||
|
Color(255, 170, 40), Color(69, 189, 255), Color(170, 116, 217), Color(93, 207, 140),
|
||||||
|
Color(238, 112, 112), Color(107, 139, 255), Color(255, 130, 180), Color(122, 204, 174),
|
||||||
|
Color(240, 195, 90), Color(151, 120, 220), Color(91, 189, 193), Color(212, 132, 82),
|
||||||
|
Color(143, 190, 223), Color(233, 106, 142), Color(132, 205, 92), Color(255, 181, 80),
|
||||||
|
Color(111, 167, 229), Color(190, 137, 226)};
|
||||||
|
|
||||||
|
// The title uses the free area to the left of the status indicators.
|
||||||
|
it.printf(12, 10, id(font_device), Color::WHITE, "Geräteverbrauch");
|
||||||
|
for (int display_index = 0; display_index < 9; display_index++) {
|
||||||
|
const int index = page_start + display_index;
|
||||||
|
const int column = display_index % 2;
|
||||||
|
const int row = display_index / 2;
|
||||||
|
const int x = column == 0 ? 12 : 166;
|
||||||
|
const int y = 43 + row * 25;
|
||||||
|
if (device_has_state[index]) {
|
||||||
|
it.printf(x, y, id(font_device), device_colors[index], "%s: %.0f W",
|
||||||
|
device_names[index], device_values[index]);
|
||||||
|
} else {
|
||||||
|
it.printf(x, y, id(font_device), device_colors[index], "%s: -- W", device_names[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The stacked bar always represents all 18 consumer devices, not only this view's rows.
|
||||||
|
const int bar_x = 12;
|
||||||
|
const int bar_y = 180;
|
||||||
|
const int bar_width = 296;
|
||||||
|
const int bar_height = 18;
|
||||||
|
float usage_sum = 0.0f;
|
||||||
|
int last_active = -1;
|
||||||
|
for (int index = 0; index < device_count; index++) {
|
||||||
|
if (device_has_state[index] && device_values[index] > 0.0f) {
|
||||||
|
usage_sum += device_values[index];
|
||||||
|
last_active = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
it.filled_rectangle(bar_x, bar_y, bar_width, bar_height, Color(42, 42, 42));
|
||||||
|
if (usage_sum > 0.0f) {
|
||||||
|
int cursor_x = bar_x;
|
||||||
|
for (int index = 0; index < device_count; index++) {
|
||||||
|
if (!device_has_state[index] || device_values[index] <= 0.0f) continue;
|
||||||
|
const int segment_width = index == last_active
|
||||||
|
? bar_x + bar_width - cursor_x
|
||||||
|
: static_cast<int>(device_values[index] * bar_width / usage_sum);
|
||||||
|
if (segment_width > 0) {
|
||||||
|
it.filled_rectangle(cursor_x, bar_y, segment_width, bar_height, device_colors[index]);
|
||||||
|
cursor_x += segment_width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id(page_index) == 2) {
|
||||||
|
const auto now = id(sntp_time).now();
|
||||||
|
const Color accent(143, 190, 223);
|
||||||
|
const Color gold(255, 170, 40);
|
||||||
|
const Color muted(55, 65, 80);
|
||||||
|
it.print(12, 10, id(font_device), accent, "Uhr · Berlin");
|
||||||
|
if (!now.is_valid()) {
|
||||||
|
it.print(160, 100, id(font_title), accent, TextAlign::TOP_CENTER, "--:--:--");
|
||||||
|
it.print(160, 190, id(font_small), Color::WHITE, TextAlign::TOP_CENTER,
|
||||||
|
"Warte auf Zeitsynchronisation");
|
||||||
|
} else {
|
||||||
|
if (!id(clock_digital_view)) {
|
||||||
|
const int cx = 160, cy = 111, radius = 74;
|
||||||
|
const float tau = 6.28318530718f;
|
||||||
|
it.filled_circle(cx, cy, radius, Color(12, 18, 28));
|
||||||
|
it.circle(cx, cy, radius, accent);
|
||||||
|
it.circle(cx, cy, radius - 3, muted);
|
||||||
|
for (int tick = 0; tick < 60; tick++) {
|
||||||
|
const float angle = tick * tau / 60.0f;
|
||||||
|
const int inner = tick % 5 == 0 ? radius - 13 : radius - 8;
|
||||||
|
it.line(cx + lroundf(sinf(angle) * inner), cy - lroundf(cosf(angle) * inner),
|
||||||
|
cx + lroundf(sinf(angle) * (radius - 5)),
|
||||||
|
cy - lroundf(cosf(angle) * (radius - 5)),
|
||||||
|
tick % 5 == 0 ? accent : muted);
|
||||||
|
}
|
||||||
|
it.print(cx, cy - 49, id(font_device), Color::WHITE, TextAlign::CENTER, "12");
|
||||||
|
it.print(cx + 50, cy, id(font_device), Color::WHITE, TextAlign::CENTER, "3");
|
||||||
|
it.print(cx, cy + 49, id(font_device), Color::WHITE, TextAlign::CENTER, "6");
|
||||||
|
it.print(cx - 50, cy, id(font_device), Color::WHITE, TextAlign::CENTER, "9");
|
||||||
|
// Round-ended hands; minutes and hours advance with the seconds.
|
||||||
|
auto hand = [&](float turns, int length, int thickness, Color color) {
|
||||||
|
const float angle = turns * tau;
|
||||||
|
for (int r = 0; r <= length; r++) {
|
||||||
|
it.filled_circle(cx + lroundf(sinf(angle) * r),
|
||||||
|
cy - lroundf(cosf(angle) * r), thickness, color);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
hand((now.hour % 12 + now.minute / 60.0f + now.second / 3600.0f) / 12.0f,
|
||||||
|
34, 3, Color::WHITE);
|
||||||
|
hand((now.minute + now.second / 60.0f) / 60.0f, 51, 2, accent);
|
||||||
|
const float second_angle = now.second * tau / 60.0f;
|
||||||
|
it.line(cx - lroundf(sinf(second_angle) * 12), cy + lroundf(cosf(second_angle) * 12),
|
||||||
|
cx + lroundf(sinf(second_angle) * 60), cy - lroundf(cosf(second_angle) * 60), gold);
|
||||||
|
it.filled_circle(cx, cy, 4, gold);
|
||||||
|
it.filled_circle(cx, cy, 1, Color::BLACK);
|
||||||
|
} else {
|
||||||
|
// Draw seven-segment digits directly, avoiding an extra font dependency.
|
||||||
|
const uint8_t masks[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66,
|
||||||
|
0x6D, 0x7D, 0x07, 0x7F, 0x6F};
|
||||||
|
const int digits[6] = {now.hour / 10, now.hour % 10, now.minute / 10,
|
||||||
|
now.minute % 10, now.second / 10, now.second % 10};
|
||||||
|
const int positions[6] = {17, 61, 121, 165, 225, 269};
|
||||||
|
const int y = 77;
|
||||||
|
for (int digit = 0; digit < 6; digit++) {
|
||||||
|
const int x = positions[digit];
|
||||||
|
const Color lit = digit < 4 ? accent : gold;
|
||||||
|
for (int segment = 0; segment < 7; segment++) {
|
||||||
|
const Color color = (masks[digits[digit]] & (1 << segment))
|
||||||
|
? lit : Color(20, 27, 36);
|
||||||
|
const bool horizontal = segment == 0 || segment == 3 || segment == 6;
|
||||||
|
const int sx = horizontal ? x + 6 : x + ((segment == 1 || segment == 2) ? 30 : 0);
|
||||||
|
const int sy = y + (segment == 0 ? 0 : segment == 3 ? 72 : segment == 6 ? 36
|
||||||
|
: (segment == 1 || segment == 5) ? 6 : 42);
|
||||||
|
// Taper each segment's ends for the classic LED clock shape.
|
||||||
|
for (int stripe = 0; stripe < 6; stripe++) {
|
||||||
|
const int inset = stripe < 3 ? 2 - stripe : stripe - 3;
|
||||||
|
if (horizontal)
|
||||||
|
it.line(sx + inset, sy + stripe, sx + 23 - inset, sy + stripe, color);
|
||||||
|
else
|
||||||
|
it.line(sx + stripe, sy + inset, sx + stripe, sy + 29 - inset, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int x : {109, 213}) {
|
||||||
|
it.filled_circle(x, y + 24, 3, accent);
|
||||||
|
it.filled_circle(x, y + 54, 3, accent);
|
||||||
|
}
|
||||||
|
it.line(40, 172, 280, 172, muted);
|
||||||
|
}
|
||||||
|
const char *weekdays[] = {"Sonntag", "Montag", "Dienstag", "Mittwoch",
|
||||||
|
"Donnerstag", "Freitag", "Samstag"};
|
||||||
|
it.printf(160, 190, id(font_small), Color::WHITE, TextAlign::TOP_CENTER,
|
||||||
|
"%s, %02d.%02d.%04d", weekdays[now.day_of_week - 1],
|
||||||
|
now.day_of_month, now.month, now.year);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Labels correspond to the left (A) and right (C) hardware buttons.
|
// Labels correspond to the left (A) and right (C) hardware buttons.
|
||||||
@@ -255,5 +638,13 @@ display:
|
|||||||
"< Zurück");
|
"< Zurück");
|
||||||
it.printf(312, 239, id(font_small), Color::WHITE, TextAlign::BOTTOM_RIGHT,
|
it.printf(312, 239, id(font_small), Color::WHITE, TextAlign::BOTTOM_RIGHT,
|
||||||
"Weiter >");
|
"Weiter >");
|
||||||
|
if (id(page_index) == 0) {
|
||||||
it.printf(160, 239, id(font_small), Color::WHITE, TextAlign::BOTTOM_CENTER,
|
it.printf(160, 239, id(font_small), Color::WHITE, TextAlign::BOTTOM_CENTER,
|
||||||
"%d / 2", id(page_index) + 1);
|
"Ansicht · 1 / 3");
|
||||||
|
} else if (id(page_index) == 1) {
|
||||||
|
it.printf(160, 239, id(font_small), Color::WHITE, TextAlign::BOTTOM_CENTER,
|
||||||
|
"Geräte %d / 2", id(device_usage_view) + 1);
|
||||||
|
} else {
|
||||||
|
it.printf(160, 239, id(font_small), Color::WHITE, TextAlign::BOTTOM_CENTER,
|
||||||
|
"%s · 3 / 3", id(clock_digital_view) ? "Analog" : "Digital");
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
# Device identity shared by ESPHome and Home Assistant.
|
# Device identity shared by ESPHome and Home Assistant.
|
||||||
substitutions:
|
substitutions:
|
||||||
|
device_description: "ESP32 e-paper Home Assistant dashboard for indoor climate, energy and calendar events, with button-controlled pages"
|
||||||
name: epaperframe
|
name: epaperframe
|
||||||
friendly_name: "Info-Dashboard"
|
friendly_name: "Info-Dashboard"
|
||||||
|
|
||||||
# Startup selects the default page only after Home Assistant has had time to
|
# Startup selects the default page only after Home Assistant has had time to
|
||||||
# provide the sensor states needed by its display lambda.
|
# provide the sensor states needed by its display lambda.
|
||||||
esphome:
|
esphome:
|
||||||
|
comment: ${device_description}
|
||||||
name: ${name}
|
name: ${name}
|
||||||
friendly_name: ${friendly_name}
|
friendly_name: ${friendly_name}
|
||||||
name_add_mac_suffix: false
|
name_add_mac_suffix: false
|
||||||
@@ -65,7 +67,7 @@ globals:
|
|||||||
|
|
||||||
ota:
|
ota:
|
||||||
platform: esphome
|
platform: esphome
|
||||||
password: !secret ota
|
encryption:
|
||||||
|
|
||||||
# Power key of li-ion charger
|
# Power key of li-ion charger
|
||||||
output:
|
output:
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
|
device_description: "ESP32 Geiger counter with radiation dose rate, accumulated dose and MAX7219 seven-segment display"
|
||||||
name: "geigercounter"
|
name: "geigercounter"
|
||||||
friendly_name: "Geigerzähler"
|
friendly_name: "Geigerzähler"
|
||||||
|
|
||||||
esphome:
|
esphome:
|
||||||
|
comment: ${device_description}
|
||||||
name: ${name}
|
name: ${name}
|
||||||
friendly_name: ${friendly_name}
|
friendly_name: ${friendly_name}
|
||||||
name_add_mac_suffix: false
|
name_add_mac_suffix: false
|
||||||
@@ -44,7 +46,7 @@ api:
|
|||||||
|
|
||||||
ota:
|
ota:
|
||||||
platform: esphome
|
platform: esphome
|
||||||
password: !secret ota
|
encryption:
|
||||||
|
|
||||||
spi:
|
spi:
|
||||||
clk_pin: 18
|
clk_pin: 18
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
|
device_description: "Home Assistant Voice PE voice assistant with microphone and speaker."
|
||||||
name: home-assistant-voice-09c0e7
|
name: home-assistant-voice-09c0e7
|
||||||
friendly_name: Home Assistant Voice Küche
|
friendly_name: Home Assistant Voice Küche
|
||||||
packages:
|
packages:
|
||||||
Nabu Casa.Home Assistant Voice PE: github://esphome/home-assistant-voice-pe/home-assistant-voice.yaml
|
Nabu Casa.Home Assistant Voice PE: github://esphome/home-assistant-voice-pe/home-assistant-voice.yaml
|
||||||
esphome:
|
esphome:
|
||||||
|
comment: ${device_description}
|
||||||
name: ${name}
|
name: ${name}
|
||||||
name_add_mac_suffix: false
|
name_add_mac_suffix: false
|
||||||
friendly_name: ${friendly_name}
|
friendly_name: ${friendly_name}
|
||||||
@@ -28,7 +30,7 @@ api:
|
|||||||
|
|
||||||
ota:
|
ota:
|
||||||
platform: esphome
|
platform: esphome
|
||||||
password: !secret ota
|
encryption:
|
||||||
|
|
||||||
http_request:
|
http_request:
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
|
device_description: "Home Assistant Voice PE voice assistant with microphone and speaker."
|
||||||
name: home-assistant-voice-0a7c6b
|
name: home-assistant-voice-0a7c6b
|
||||||
friendly_name: Home Assistant Voice Wohnzimmer
|
friendly_name: Home Assistant Voice Wohnzimmer
|
||||||
packages:
|
packages:
|
||||||
Nabu Casa.Home Assistant Voice PE: github://esphome/home-assistant-voice-pe/home-assistant-voice.yaml
|
Nabu Casa.Home Assistant Voice PE: github://esphome/home-assistant-voice-pe/home-assistant-voice.yaml
|
||||||
esphome:
|
esphome:
|
||||||
|
comment: ${device_description}
|
||||||
name: ${name}
|
name: ${name}
|
||||||
name_add_mac_suffix: false
|
name_add_mac_suffix: false
|
||||||
friendly_name: ${friendly_name}
|
friendly_name: ${friendly_name}
|
||||||
@@ -28,7 +30,7 @@ api:
|
|||||||
|
|
||||||
ota:
|
ota:
|
||||||
platform: esphome
|
platform: esphome
|
||||||
password: !secret ota
|
encryption:
|
||||||
|
|
||||||
http_request:
|
http_request:
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
name: kamera-balkon
|
name: kamera-balkon
|
||||||
friendly_name: Kamera Balkon
|
friendly_name: Kamera Balkon
|
||||||
|
device_description: "Balcony ESP32-CAM with HTTP stream and snapshots, flash LED, and SHT3x temperature and humidity sensing."
|
||||||
|
|
||||||
esphome:
|
esphome:
|
||||||
|
comment: ${device_description}
|
||||||
name: ${name}
|
name: ${name}
|
||||||
friendly_name: ${friendly_name}
|
friendly_name: ${friendly_name}
|
||||||
name_add_mac_suffix: false
|
name_add_mac_suffix: false
|
||||||
@@ -43,7 +45,7 @@ api:
|
|||||||
|
|
||||||
ota:
|
ota:
|
||||||
platform: esphome
|
platform: esphome
|
||||||
password: !secret ota
|
encryption:
|
||||||
|
|
||||||
# Initialize I²C
|
# Initialize I²C
|
||||||
i2c:
|
i2c:
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
name: kamera-wohnzimmer
|
name: kamera-wohnzimmer
|
||||||
friendly_name: Kamera Wohnzimmer
|
friendly_name: Kamera Wohnzimmer
|
||||||
|
device_description: "Living-room ESP32 camera with HTTP stream and snapshots and a controllable flash LED."
|
||||||
|
|
||||||
esphome:
|
esphome:
|
||||||
|
comment: ${device_description}
|
||||||
name: ${name}
|
name: ${name}
|
||||||
friendly_name: ${friendly_name}
|
friendly_name: ${friendly_name}
|
||||||
name_add_mac_suffix: false
|
name_add_mac_suffix: false
|
||||||
@@ -43,7 +45,7 @@ api:
|
|||||||
|
|
||||||
ota:
|
ota:
|
||||||
platform: esphome
|
platform: esphome
|
||||||
password: !secret ota
|
encryption:
|
||||||
|
|
||||||
# Initialize I²C
|
# Initialize I²C
|
||||||
i2c:
|
i2c:
|
||||||
|
|||||||
@@ -27,10 +27,16 @@ esphome:
|
|||||||
includes:
|
includes:
|
||||||
- lab-ble-proxy.h
|
- lab-ble-proxy.h
|
||||||
on_boot:
|
on_boot:
|
||||||
priority: 850
|
- priority: 850
|
||||||
then:
|
then:
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
owon_b35t::core2_axp192_init(id(core2_i2c));
|
owon_b35t::core2_axp192_init(id(core2_i2c));
|
||||||
|
# Start the normal dimming/off cycle after a cold boot as well. The
|
||||||
|
# light component is initialized by this priority, while BLE callbacks
|
||||||
|
# and touch events can still restart the script through wake_backlight.
|
||||||
|
- priority: 600
|
||||||
|
then:
|
||||||
|
- script.execute: backlight_idle
|
||||||
project:
|
project:
|
||||||
name: "custom.lab-ble-proxy-m5stack-core2"
|
name: "custom.lab-ble-proxy-m5stack-core2"
|
||||||
version: "1.0"
|
version: "1.0"
|
||||||
@@ -61,7 +67,7 @@ api:
|
|||||||
|
|
||||||
ota:
|
ota:
|
||||||
platform: esphome
|
platform: esphome
|
||||||
password: !secret ota
|
encryption:
|
||||||
|
|
||||||
network:
|
network:
|
||||||
enable_ipv6: true
|
enable_ipv6: true
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
|
device_description: "ESP32 living-room air quality monitor with SCD30 CO2, temperature and humidity, PM2.5 sensing and RGB status LED"
|
||||||
name: "livingroom"
|
name: "livingroom"
|
||||||
friendly_name: "Luftqualität Wohnzimmer"
|
friendly_name: "Luftqualität Wohnzimmer"
|
||||||
|
|
||||||
esphome:
|
esphome:
|
||||||
|
comment: ${device_description}
|
||||||
name: ${name}
|
name: ${name}
|
||||||
friendly_name: ${friendly_name}
|
friendly_name: ${friendly_name}
|
||||||
name_add_mac_suffix: false
|
name_add_mac_suffix: false
|
||||||
@@ -86,7 +88,7 @@ api:
|
|||||||
# Enable over-the-air updates
|
# Enable over-the-air updates
|
||||||
ota:
|
ota:
|
||||||
platform: esphome
|
platform: esphome
|
||||||
password: !secret ota
|
encryption:
|
||||||
|
|
||||||
# Initialize I²C
|
# Initialize I²C
|
||||||
i2c:
|
i2c:
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
name: m5stack-atom-echo
|
name: m5stack-atom-echo
|
||||||
friendly_name: M5Stack Atom Echo
|
friendly_name: M5Stack Atom Echo
|
||||||
|
device_description: "M5Stack Atom Echo ESP32 voice assistant with on-device or Home Assistant wake-word detection and timer announcements."
|
||||||
|
|
||||||
esphome:
|
esphome:
|
||||||
|
comment: ${device_description}
|
||||||
name: ${name}
|
name: ${name}
|
||||||
name_add_mac_suffix: false
|
name_add_mac_suffix: false
|
||||||
friendly_name: ${friendly_name}
|
friendly_name: ${friendly_name}
|
||||||
@@ -26,7 +28,7 @@ api:
|
|||||||
ota:
|
ota:
|
||||||
- platform: esphome
|
- platform: esphome
|
||||||
id: ota_esphome
|
id: ota_esphome
|
||||||
password: !secret ota
|
encryption:
|
||||||
|
|
||||||
network:
|
network:
|
||||||
enable_ipv6: true
|
enable_ipv6: true
|
||||||
@@ -232,7 +234,7 @@ light:
|
|||||||
default_transition_length: 0s
|
default_transition_length: 0s
|
||||||
chipset: SK6812
|
chipset: SK6812
|
||||||
num_leds: 1
|
num_leds: 1
|
||||||
rgb_order: grb
|
channel_colors: GRB
|
||||||
effects:
|
effects:
|
||||||
- pulse:
|
- pulse:
|
||||||
name: "Slow Pulse"
|
name: "Slow Pulse"
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ api:
|
|||||||
|
|
||||||
ota:
|
ota:
|
||||||
platform: esphome
|
platform: esphome
|
||||||
password: !secret ota
|
encryption:
|
||||||
|
|
||||||
# Enable status LED
|
# Enable status LED
|
||||||
status_led:
|
status_led:
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ api:
|
|||||||
|
|
||||||
ota:
|
ota:
|
||||||
platform: esphome
|
platform: esphome
|
||||||
password: !secret ota
|
encryption:
|
||||||
|
|
||||||
# Enable status LED
|
# Enable status LED
|
||||||
status_led:
|
status_led:
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
|
device_description: "ESP32-C3 server-room temperature and atmospheric pressure monitor with BMP280 sensor"
|
||||||
name: "serverroom"
|
name: "serverroom"
|
||||||
friendly_name: "Serverraum Luft"
|
friendly_name: "Serverraum Luft"
|
||||||
|
|
||||||
esphome:
|
esphome:
|
||||||
|
comment: ${device_description}
|
||||||
name: ${name}
|
name: ${name}
|
||||||
friendly_name: ${friendly_name}
|
friendly_name: ${friendly_name}
|
||||||
name_add_mac_suffix: false
|
name_add_mac_suffix: false
|
||||||
@@ -44,7 +46,7 @@ api:
|
|||||||
|
|
||||||
ota:
|
ota:
|
||||||
platform: esphome
|
platform: esphome
|
||||||
password: !secret ota
|
encryption:
|
||||||
|
|
||||||
# Initialize I²C
|
# Initialize I²C
|
||||||
i2c:
|
i2c:
|
||||||
|
|||||||
+4
-2
@@ -11,7 +11,8 @@
|
|||||||
host: !secret router_ip
|
host: !secret router_ip
|
||||||
community: !secret router_community
|
community: !secret router_community
|
||||||
# baseoid: .1.3.6.1.2.1.31.1.1.1.6.511
|
# baseoid: .1.3.6.1.2.1.31.1.1.1.6.511
|
||||||
baseoid: .1.3.6.1.2.1.2.2.1.10.12
|
# baseoid: .1.3.6.1.2.1.2.2.1.10.12
|
||||||
|
baseoid: .1.3.6.1.2.1.31.1.1.1.6.12 # IF-MIB::ifHCInOctets.12
|
||||||
version: 2c
|
version: 2c
|
||||||
unit_of_measurement: "Octets"
|
unit_of_measurement: "Octets"
|
||||||
- platform: snmp
|
- platform: snmp
|
||||||
@@ -20,7 +21,8 @@
|
|||||||
host: !secret router_ip
|
host: !secret router_ip
|
||||||
community: !secret router_community
|
community: !secret router_community
|
||||||
# baseoid: .1.3.6.1.2.1.31.1.1.1.10.511
|
# baseoid: .1.3.6.1.2.1.31.1.1.1.10.511
|
||||||
baseoid: .1.3.6.1.2.1.2.2.1.16.12
|
# baseoid: .1.3.6.1.2.1.2.2.1.16.12
|
||||||
|
baseoid: .1.3.6.1.2.1.31.1.1.1.10.12 # IF-MIB::ifHCOutOctets.12
|
||||||
version: 2c
|
version: 2c
|
||||||
unit_of_measurement: "Octets"
|
unit_of_measurement: "Octets"
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -78,7 +78,8 @@
|
|||||||
{% set waschmaschine = states('sensor.waschmaschine_leistung') | float %}
|
{% set waschmaschine = states('sensor.waschmaschine_leistung') | float %}
|
||||||
{% set arcade = states('sensor.arcade_automat_leistung') | float %}
|
{% set arcade = states('sensor.arcade_automat_leistung') | float %}
|
||||||
{% set spuelmaschine = states('sensor.spulmaschine_leistung') | float %}
|
{% set spuelmaschine = states('sensor.spulmaschine_leistung') | float %}
|
||||||
{{ (total + solar - raumduft - keller - musik - bett - heimkino_sz - deko - schreibtisch - serverraum - heimkino_wz - spieleschrank - kuehlschrank - kaffeemaschine - waeschetrockner - waschmaschine - arcade - spuelmaschine) | round(1) }}
|
{% set mikrowelle = states('sensor.waschetrockner_leistung') | float %}
|
||||||
|
{{ (total + solar - raumduft - keller - musik - bett - heimkino_sz - deko - schreibtisch - serverraum - heimkino_wz - spieleschrank - kuehlschrank - kaffeemaschine - waeschetrockner - waschmaschine - arcade - spuelmaschine - mikrowelle) | round(1) }}
|
||||||
device_class: power
|
device_class: power
|
||||||
state_class: measurement
|
state_class: measurement
|
||||||
attributes:
|
attributes:
|
||||||
|
|||||||
Reference in New Issue
Block a user