Rolladensteuerung mit ESPHome, virtuelle Schalter für die Home Assistant Oberfläche

Die 4-fach-Relaissteuerungplatine mit ESP Wroom kann nach dem letzten Beitrag installiert werden und ist über die Hardwareschalter an der Rolladensteuerung bedienbar. Smart Home ist das aber noch nicht. Dafür fehlt die Bedienbarkeit über das Netzwerk, bzw. über Home Assistant. Hier setzt dieser vorerst letzte Beitrag der Reihe an.

Für die Steuerung der Relais auf der Karte benötigt man Schalter. Per Hardwareanbindung von Schaltkontakt zu GPIO-Anschluss ist das schon realisiert. Für die Bedienung in der Home Assistant Oberfläche benötigen wir keine Hardware, sondern nur Schaltersymbole und virtuelle Schalter. In ESPHome werden diese virtuellen Schalter „Templates“ genannt. Diese Templates sehen genauso aus, wie die Schalter, die schon vorher benutzt wurden und sie werden auch genauso benutzt, – abgesehen davon, dass eine andere Plattformbezeichnung „template“  gewählt wird:

- platform: template
name: "VFen_Up"
id: vfen_up
optimistic: true

turn_on_action:
then:

Es gibt für die Template-Schalter zwei Aktionen, …

turn_on_action: 
then:
.
.
.
turn_off_action:
then:
.
.
.

… die jeweils bei der Bedienung in der GUI ausgeführt werden. Die Zeile „optimistic: true“ wird benötigt, damit der Schalter in der GUI von Hand schaltbar bleibt. Ohne diese Zeile wird er nämlich einfach nach einer Sekunde zurückgesetzt.

Die durchzuführenden Aktionen sind in unserem Fall die gleichen, wie bei der Betätigung des jeweils zugehörigen Hardwareschalters. Diese Tatsache führt aber dazu, dass man sich Gedanken darüber machen sollte, ob man den auszuführenden Code zweimal schreibt,  obwohl er doch an beiden Stellen identisch ist.

Damit sind wir dann auch schon bei den Scripten. Die kann man sich ähnlich vorstellen wie Unterprogramme, sofern man mal etwas mit Programmieren zu tun hatte. Ein immer wieder zu verwendender Code wird einmalig aufgeschrieben und dann von verschiedenen Stellen aufgerufen. Genauso läuft es hier:

script:
- id: do_fen_up
then:
- switch.turn_off: fenpowrel1
- switch.turn_off: fendirrel2
- delay: 100ms
- switch.turn_on: fenpowrel1
- delay: 15s
- script.execute: end_fen
- switch.turn_off: vfen_up

Der Codeschnipsel sollte aus dem letzten Beitrag bekannt vorkommen. Die beiden letzten Zeilen sind allerdings neu.

script.execute: end_fen“ ruft ebenfalls ein Script auf, nämlich das, das jeweils die zwei Relais stromlos macht. Der Aufruf eines Scripts erfolgt immer mit script.execute: gefolgt vom Namen des Scriptes.

switch.turn_off: vfen_up“ sorgt dafür, dass der Schalter in der GUI nach Ausführung der Aktionen wieder zurückgestellt wird. 

An diversen Stellen werden Delays, also Verzögerungen, durchgeführt. Sinnvoll wäre es, wenn man die benötigten Werte zentral pflegen könnte. Der Ansatz ist also ähnlich wie bei den Scripten.

Ein mögliches Konstrukt hierfür sind „Global Variables„. Der Einsatz ist aber speziell in Verbindung mit delay etwas trickreich und ich muss zugeben, dass ich da recht lang nach einer Lösung suchen musste. Ich habe die Schreibweise zunächst auch einfach mal hingenommen ohne genau die Hintergründe zu kennen. Schon öfters kam in der Dokumentation der Begriff Lambda vor. Genau das kommt jetzt zum Einsatz.

Definition der globalen Variablen ist ja noch recht einfach:

globals:
# Fahrzeit Fenster-Rollade
- id: timer_fen
type: int
restore_value: False
initial_value: '15'

Schwieriger ist schon die Nutzung. Man muss dazu auch wissen, dass speziell in diesem Fall die übergebenen Werte immer als Millisekunden erwartet werden, deshalb auch der nachfolgende Multiplikator von 1000:

delay: !lambda 'return id(timer_fen) * 1000;'

Hier wird also 15000ms übergeben.

Wenn das dann alles so codiert wird und durch den Compiler gelaufen ist, kann man in der Home Assistant GUI die neuen Schalter unter Geräte/Entitäten sehen:

Mit diesen Entitäten kann dann in einem eigenen Dashboard in Home Assistant die Steuerung der Rolladen nach eigenem Empfinden und Vorlieben entworfen werden.

Die Anschlüsse sind wie auf dem folgenden Bild vorzunehmen. Natürlich muss darüberhinaus noch der Nullleiter und die Erdleitung mit jedem Motor verbunden werden und die Platine selbst ist ebenfalls mit Netzstrom zu versorgen, wie es bereits im ersten Beitrag erklärt wurde.

Zum Schluss noch der gesamte Code. Falls noch Fragen offen bleiben, schreibt mich gerne an oder hinterlasst einen Kommentar.

esphome:
name: esphome-web-0a9aa0
friendly_name: ESP32 4fach Relais 2 0a9aa0
min_version: 2024.11.0
name_add_mac_suffix: false

esp32:
board: esp32dev
framework:
type: esp-idf

globals:
# Fahrzeit Fenster-Rollade
- id: timer_fen
type: int
restore_value: False
initial_value: '15'

# Fahrzeit Tür-Rollade
- id: timer_tuer
type: int
restore_value: False
initial_value: '25'

# Delay für sichere Schaltzustände
- id: switch_time
type: int
restore_value: False
initial_value: '100'




# Status LED
light:
- platform: status_led
name: RelayBoard Led
restore_mode: ALWAYS_ON
pin:
number: GPIO23

# 4 relay outputs, exposed as switches in Home Assistant

# NO -> im Ruhezustand open, connect to Motor down bei DirRelay
# NC -> im Ruhezustand closed, connect to Motor up bei DirRelay
# COM DirRelay connect to NO PowRelay

switch:
- platform: gpio
pin: GPIO32
name: FenPowRel1
id: fenpowrel1
- platform: gpio
pin: GPIO33
name: FenDirRel2
id: fendirrel2
- platform: gpio
pin: GPIO25
name: TuePowRel3
id: tuepowrel3
- platform: gpio
pin: GPIO26
name: TueDirRel4
id: tuedirrel4

# virtuelle Switches für die Oberfläche
# machen das Gleiche wie die Hardware-Switches
- platform: template
name: "VFen_Up"
id: vfen_up
optimistic: true

turn_on_action:
then:
- script.execute: do_fen_up

turn_off_action:
then:
- script.execute: end_fen

- platform: template
name: "VFen_Dn"
id: vfen_dn
optimistic: true

turn_on_action:
then:
- script.execute: do_fen_dn

turn_off_action:
then:
- script.execute: end_fen

- platform: template
name: "VTuer_Up"
id: vtuer_up
optimistic: true

turn_on_action:
then:
- script.execute: do_tuer_up

turn_off_action:
then:
- script.execute: end_tuer

- platform: template
name: "VTuer_Dn"
id: vtuer_dn
optimistic: true

turn_on_action:
then:
- script.execute: do_tuer_dn

turn_off_action:
then:
- script.execute: end_tuer


# GPIOs als Eingang eines Hardwareschalters
binary_sensor:

# Fenster fährt 15sec
# Tür fahrt 25sec
# 27 -> Fenster down
# 1. Stromzufuhr powrel off
# 2. Richtung dirrel on/off
# 3. Sicherheitsdelay 100ms für definierten Schaltzustand des DirRelais
# 4. Stromzufuhr powrel on
# 5. Timer
# 6. Stromzufuhr powrel off
# 7. Richtung dirrel off
# nach dem Schaltvorgang sollen alle Relais stromlos sein

# GPIO27 -> Fenster up
- platform: gpio
pin:
number: GPIO27
inverted: true
mode:
input: true
pullup: true
name: "Fen_Up"
filters:
- delayed_off: !lambda 'return id(switch_time);'
- delayed_on: !lambda 'return id(switch_time);'

on_press:
then:
- script.execute: do_fen_up

on_release:
then:
- script.execute: end_fen


# GPIO14 -> Fenster down
- platform: gpio
pin:
number: GPIO14
inverted: true
mode:
input: true
pullup: true
name: "Fen_Dn"
filters:
- delayed_off: !lambda 'return id(switch_time);'
- delayed_on: !lambda 'return id(switch_time);'

on_press:
then:
- script.execute: do_fen_dn

on_release:
then:
- script.execute: end_fen


# GPIO13 -> Tür up
- platform: gpio
pin:
number: GPIO13
inverted: true
mode:
input: true
pullup: true
name: "Tuer_Up"
filters:
- delayed_off: !lambda 'return id(switch_time);'
- delayed_on: !lambda 'return id(switch_time);'

on_press:
then:
- script.execute: do_tuer_up

on_release:
then:
- script.execute: end_tuer


# GPIO12 -> Tür down
- platform: gpio
pin:
number: GPIO12
inverted: true
mode:
input: true
pullup: true
name: "Tuer_Dn"
filters:
- delayed_off: !lambda 'return id(switch_time);'
- delayed_on: !lambda 'return id(switch_time);'

on_press:
then:
- script.execute: do_tuer_dn

on_release:
then:
- script.execute: end_tuer


i2c:
sda: GPIO21
scl: GPIO22
scan: true

sensor:
- platform: bme280_i2c
temperature:
name: "BME280 Temperature"
pressure:
name: "BME280 Pressure"
humidity:
name: "BME280 Humidity"

script:
- id: do_fen_up
then:
- switch.turn_off: fenpowrel1
- switch.turn_off: fendirrel2
- delay: !lambda 'return id(switch_time);'
- switch.turn_on: fenpowrel1
- delay: !lambda 'return id(timer_fen) * 1000;'
- script.execute: end_fen
- switch.turn_off: vfen_up

- id: do_fen_dn
then:
- switch.turn_off: fenpowrel1
- switch.turn_on: fendirrel2
- delay: !lambda 'return id(switch_time);'
- switch.turn_on: fenpowrel1
- delay: !lambda 'return id(timer_fen) * 1000;'
- script.execute: end_fen
- switch.turn_off: vfen_dn

- id: do_tuer_up
then:
- switch.turn_off: tuepowrel3
- switch.turn_off: tuedirrel4
- delay: !lambda 'return id(switch_time);'
- switch.turn_on: tuepowrel3
- delay: !lambda 'return id(timer_tuer) * 1000;'
- script.execute: end_tuer
- switch.turn_off: vtuer_up

- id: do_tuer_dn
then:
- switch.turn_off: tuepowrel3
- switch.turn_on: tuedirrel4
- delay: !lambda 'return id(switch_time);'
- switch.turn_on: tuepowrel3
- delay: !lambda 'return id(timer_tuer) * 1000;'
- script.execute: end_tuer
- switch.turn_off: vtuer_dn

- id: end_fen
then:
- switch.turn_off: fenpowrel1
- delay: !lambda 'return id(switch_time);'
- switch.turn_off: fendirrel2

- id: end_tuer
then:
- switch.turn_off: tuepowrel3
- delay: !lambda 'return id(switch_time);'
- switch.turn_off: tuedirrel4



# Enable logging
logger:

# Enable Home Assistant API
api:

# Allow Over-The-Air updates
ota:
- platform: esphome

wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password

manual_ip:
static_ip: 192.168.xxx.xxx
gateway: 192.168.xxx.xxx
subnet: 255.255.255.0

# Enable fallback hotspot (captive portal) in case wifi connection fails
# no ssid sets device name
ap:
password: "fürchterlich geheim"
ap_timeout: 10min

captive_portal:

# die echten Zugangsdaten stehen in der secrets.yaml
0 0 votes
Article Rating
Abonnieren
Benachrichtige mich bei
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments