Thema: Tools zur Steuerung eines HMDI-Monitors an einem abgesetzten Dashboard (nur linux, nicht android)
-–—
Hallo zusammen,
da ich in meinem Zuhause fest installierte Touch-Monitore mit einem Raspi zur Anzeige von Dashboards verwende (z.B. ein 27.9inch Monitor im Flur als Zentrale Steuerungseinheit), habe ich nach einer Möglichkeit gesucht, die Monitore über HA sinnvoll anzusteuern. Ich finde es persönlich angenehmer, wenn ich am Dashboard vorbei laufe, dass der Monitor bereits an ist und ich nicht erst auf den Touch tippen muss um etwas anzuzeigen. Wenn aber niemand da ist soll der Monitor im Standby sein (Stromverbrauch des Raspi’s lassen wir hier mal außen vor, der ist über PoE gepowered, da kommt der Strom aus dem Netzwerkkabel
).
Das Problem ist ja, dass man mit Automationen nicht auf den entfernten Rechner zugreifen kann um da was zu machen. Also musste eine Lösung her, die universell ist und im Kontext der HA shell-integration funktioniert. Nach ein paar Experimenten habe ich dann einen Ansatz mit UDP Telegrammen gefunden, der auch im Umfeld der shell-integration funktioniert.
Im Grunde sind das 2 Python-scripte, eines läuft als Service auf dem entfernten Rechner, das andere wird bei Bedarf im HA mit Hilfe der shell-integration ausgeführt. Bei mir sind da noch 2 Präsenzmelder mit im Spiel, die im Flur installiert sind und so jede Person “entdecken”, die den Flur betritt (und damit ggf. am Dashboard vorbei läuft.
Ich habe jetzt einfach eine Automation erstellt, die von den Person-Erkannt Sensoren der Melder getriggert wird und den Befehl zum Einschalten des Monitors triggert. Im Dashboard gibt es in der Navbar einen Button, mit dem man den Monitor sofort wieder ausschalten kann. Eine zweite Automation wird dann getriggert, wenn niemand mehr im Flur erkannt wird (sind ja Präsenzmelder, deren Haltezeit ist mit 2 Minuten recht kurz eingestellt) und die dann den Befehl zum Ausschalten des Monitors triggen. Außerdem ist der Bildschirm Timeout auch noch vorhanden, falls der Ausschaltbefehl von HA aus irgend einem Grund nicht erfolgt. Das Timeout schlägt allerdings erst nach 30 Minuten zu.
Soweit zu meinem Aufbau. Für alle, die das evtl. auch so umsetzen möchten, hier jetzt eine Schritt-für-Schritt-Anleitung, wie man das bei sich einbauen kann:
Zunächst benötigt ihr eine Möglichkeit um eigene Dateien im HA-Dateisystem anzulegen und zu ändern. Ich verwende dafür das Add-On “File editor”. Ihr könnt natürlich auch SSH und NANO verwenden, oder per SCP kopieren. Der Weg ist egal, das Ergebnis muss nachher passen. In dieser Anleitung beziehe ich mich auf den Weg per “File editor” Add-On. Alle Arbeiten auf entfernten Rechnern mache ich per SSH - auch hier bezieht sich meine Anleitung auf diesen Weg. Ihr könnt euch natürlich auch direkt an den entfernten Rechner setzen und dort arbeiten (falls Tastatur und ggf. Maus vorhanden ist).
Als erstes müsst ihr auf dem entfernten System die DPMS-Funktion überprüfen. Diese ist zwingend notwendig, damit mein Tool funktionieren kann.
Zum Überprüfen der Funktion loggt ihr euch per SSH auf dem entfernten System ein.
Gebt zunächst mal folgenden Befehl ein, um zu gucken ob das ‘xset’ Utility installiert ist:
whereis xset
Als Ausgabe liefert whereis bei Erfolg den Pfad:
xset: /usr/bin/xset /usr/share/man/man1/xset.1.gz
Falls das Programm nicht gefunden werden konnte seht ihr nur:
xset:
In diesem Fall müsst Ihr dann zusehen, warum das so ist. Ohne ‘xset’ funktioniert es nicht.
Als nächstes müssen wir noch den Status der DPMS-Unterstützung überprüfen.
Dazu gebt ihr die folgenden 2 Befehle ein:
export DISPLAY=:0
xset q
Ihr solltet eine umfangreiche Ausgabe erhalten, die ungefähr wie folgt aussieht:
Keyboard Control:
auto repeat: on key click percent: 0 LED mask: 00000000
XKB indicators:
00: Caps Lock: off 01: Num Lock: off 02: Scroll Lock: off
03: Compose: off 04: Kana: off 05: Sleep: off
06: Suspend: off 07: Mute: off 08: Misc: off
09: Mail: off 10: Charging: off 11: Shift Lock: off
12: Group 2: off 13: Mouse Keys: off
auto repeat delay: 660 repeat rate: 25
auto repeating keys: 00ffffffdffffbbf
fadfffefffedffff
9fffffffffffffff
fff7ffffffffffff
bell percent: 50 bell pitch: 400 bell duration: 100
Pointer Control:
acceleration: 2/1 threshold: 4
Screen Saver:
prefer blanking: no allow exposures: yes
timeout: 0 cycle: 600
Colors:
default colormap: 0x20 BlackPixel: 0x0 WhitePixel: 0xffffff
Font Path:
/usr/share/fonts/X11/misc,/usr/share/fonts/X11/100dpi/:unscaled,/usr/share/fonts/X11/75dpi/:unscaled,/usr/share/fonts/X11/Type1,/usr/share/fonts/X11/100dpi,/usr/share/fonts/X11/75dpi,built-ins
DPMS (Energy Star):
Standby: 120 Suspend: 130 Off: 140
DPMS is Enabled
Monitor is Off
Interessant ist der Abschnitt “DPMS (Energy Star):” (ganz am Ende).
Dort muss “DPMS is Enabled” stehen, sonst funktioniert das nicht.
Prüft nun mit dem folgenden Befehl, ob ihr den Monitor mittels ‘xset’ wirklich ein- und ausschalten könnt:
xset dpms force off
xset dpms force on
xset dpms 120 150 165
Der erste Befehl sollte den Monitor ausschalten. Dabei sollte der Monitor wirklich in den Standby gehen und nicht nur schwarz werden. Ihr könnt das jederzeit mit
xset q
überprüfen, im DPMS-Abschnitt muss dann “Monitor if Off” bzw. “Monitor is On” stehen, je nach Zustand.
Der zweite Befehl sollte den Monitor wieder einschalten.
Mit dem dritten Befehl werden die Timeouts für Standby, Suspend und Off geändert. Auch die Werte werden mit
xset q
angezeigt. Überprüft ob alles einwandfrei funktioniert, den der Daemon schaltet den Monitor ein und aus und passt dabei auch die Timeouts an.
Ist das alles in Ordnung kommt jetzt die Installation und Einrichtung des Systemdienstes.
Als erstes müssen wir das Python Script für den Daemon ablegen. Ich habe dafür im Ordner meines Hauptbenutzers ‘pi’ einen Unterordner mit dem Namen ‘display_power_daemon’ angelegt:
mkdir ~/display_power_daemon
Wechselt nun in diesen Ordner und erstellt eine leere Datei:
cd ~/display_power_daemon
touch display_power_daemon.py
Wie Ordner und Datei benannt werden bleibt euch überlassen, ihr braucht diese Angaben gleich im Unit-File. Öffnet nun den Editor eurer Wahl (ich benutze nur NANO) und ruft die soeben erstellte .py-Datei auf:
nano display_power_daemon.py
Fügt nun den folgenden Scriptcode in diese Datei ein:
import argparse
from socket import *
from subprocess import run
from os import environ
parser = argparse.ArgumentParser()
parser.add_argument("-p", "--port",
help="Set port number for daemon. Defaults to 5001",
default=5001,
type=int
)
parser.add_argument("-v", "--verbose",
help="Enable verbose output",
action="store_true"
)
args = parser.parse_args()
def debug(text, newline = True):
if args.verbose:
if not newline:
print(text, end = '')
else:
print(text)
debug("DISPLAY-Power-Daemon")
debug("====================")
# First get actual environment variables
debug("Loading environment ... ", newline = False)
myenv = environ
debug("DONE")
# Now we add a DISPLAY variable and set to id of the display.
# This is required to use xset. Check and change if required.
debug("Setting up Display ... ", newline = False)
myenv['DISPLAY'] = ':0'
debug("DONE")
# Now we create a UDP Broadcast receiver socket and bind it to its
# designated port (taken from --port parameter viaq args.port)
debug(f"Initialising UDP Socket, bind to Port {args.port}...", newline = False)
udpsocket = socket(AF_INET, SOCK_DGRAM)
udpsocket.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
udpsocket.bind(('', args.port))
debug("DONE")
debug("Initialisation finished")
debug("Starting main loop")
# Now we start listening for UDP telegrams and handle them.
while True:
debug(">> Awaiting UDP command telegram")
# recvfrom return a pair as (bytes, address) - we only need the bytes
msg = udpsocket.recvfrom(1024)[0]
debug(">> UDP command telegram received")
match msg[0]:
case 48 | 70 | 102: # '0', 'F', 'f'
debug("<< 'OFF'-CMD: Set Timeout to 60s and switch OFF display")
run(['xset', 'dpms', '60', '60', '60']) # Timeout/Blank/Off to 60s
run(['xset', 'dpms', 'force', 'off'])
case 49 | 84 | 116: # '1', 'T', 't'
debug("<< 'ON'-CMD: Set Timeout to 15m and switch ON display")
run(['xset', 'dpms', '900', '900', '900']) # Timeout/Blank/Off to 10m
run(['xset', 'dpms', 'force', 'on'])
case _:
debug(f"<< Unknown data received: {msg}")
debug("DISPLAY-Power-Daemon exited")
Speichert alles mit Strg+O (Dateiname mit Enter bestätigen) und schließt den Editor dann mit Strg+X.
Jetzt müssen wir noch das Unit-File für den Systemdienst erstellen.
Dazu wechselt ihr jetzt in den Ordner “/etc/systemd/system” und erstellt dort, mit Root-Rechten, eine leere Datei mit Namen “display-power-daemon.serivce”:
cd /etc/systemd/system
sudo touch display-power-daemon.service
Öffnet nun die eben erstellte Datei im Editor und fügt den folgenden Code dort ein:
[Unit]
Description=Python based Service for DPMI Power Mode settings via UDP packets.
After=multi-user.target
[Service]
User=pi
Type=idle
ExecStart=/usr/bin/python3 /home/pi/display_power_daemon/display_power_daemon.py --port=5001
[Install]
WantedBy=multi-user.target
Diese .service-Dateii beschreibt einen Systemdienst, der von systemd verwaltet und gesteuert wird.
Diese Unit Definition setzt voraus dass:
1.) Der User ‘pi’ heißt
2.) Das Programm im Ordner “/home/pi/display_power_daemon” liegt
und
3.) Das Programm den Namen “display_power_daemon.py” hatGgf. müssen Pfade und Dateinamen angepasst werden!
Der abschließende Parameter “–port=5001” legt den Port fest, auf dem der Daemon lauscht. Ihr könnt den Parameter auch weglassen, wenn der Defaultport 5001 für euch OK ist. Wollt ihr einen anderen Port gebt ihn hier an. Dieser Port wird später auch auf dem HA-Server benötigt, um die UDP-Telegrammee an den richtigen Empfänger zu senden.
Zum Schluss müssen wir den eben erstellen Service noch aktivieren (damit er beim Systemstart automatisch ausgeführt wird) und dann starten, damit wir die Funktion anschließend gleich testen können. Dazu jetzt die folgenden Befehle eingeben:
sudo systemctl daemon-reload
sudo systemctl enable display-power_daemon.service
sudo systemctl start display-power-daemon.service
Der erste Befehl macht die neue Unit-Dateii im System bekannt.
Der zweite Befehl aktiviert (enable) den neuen Service, damit er bei einem Neustart automatisch mit gestartet wird.
Der dritte Befehl startet schließlich den neuen Service sofort.
Überprüft nun mittels
systemctl status display-power-daemon.service
ob alles geklappt hat.
Ihr solltet eine Ausgabe ähnlich dieser erhalten:
● display-power-daemon.service - Python based Service for DPMI Power Mode settings via UDP packets.
Loaded: loaded (/etc/systemd/system/display-power-daemon.service; enabled; preset: enabled)
Active: active (running) since Thu 2026-01-08 23:17:51 CET; 56min ago
Main PID: 19828 (python3)
Tasks: 1 (limit: 4689)
CPU: 45ms
CGroup: /system.slice/display-power-daemon.service
└─19828 /usr/bin/python3 /home/pi/display_power_daemon/display_power_daemon.py --port=5001
Jan 08 23:17:51 fullpageos systemd[1]: Started display-power-daemon.service - Python based Service for DPMI Power Mode settings via UDP packets..
Wichtig ist die Zeile mit “Active:”. Dort muss “active (running)” stehen. Steht dort etwas anderes habt ihr irgendwo einen Fehler gemacht oder ein anderes Problem, dass ihr zunächst lösen müsst.
Hat alles geklappt ist das abgesetzte System fertig.
Weiter geht es jetzt mit den Anpassungen am HA Server:
Wir benötigen einen kleinen Python-Helfer, um UDP Pakete versenden zu können.
Öffnet dazu den File editor in der HA Oberfläche.
Klickt nun auf “Browse Filesystem” (das Ordner-Symbol oben links).
Ihr solltet nun im Ordner “homeassistant/” sein.
Ich habe alle Shellscripte in einem Unterordner “shellscripts”, damit der Ordner “homeassistant/” nicht so voll und unübersichtlich wird.
Wechselt also jetzt in den Ordner “shellscripts” (könnt ihr auch anders benennen oder ganz weg lassen) und klickt auf “New File” (oben links im Browse Filesystem).
Es öffnet sich ein Dialog und fragt nach dem Dateinamen.
Tragt dort bitte “send_udp_packet.py” ein und bestätigt das mit “OK”.
Die neue Datei ist jetzt im Browser zu finden - sucht sie und klickt einmal drauf, damit sie im Editor geöffnet wird (in der Titelzeile oberhalb des Editors sollte dann
“/homeassistant/schellscripts/send_udp_packet.py”
stehen. Klickt jetzt einmal in den Editor-Bereich, der Browser wird geschlossen und ihr könnt jetzt den Inhalt der Datei bearbeiten.
In diese Datei muss das folgende Python Script eingefügt werden:
from socket import socket, AF_INET, SOCK_DGRAM
from sys import argv
cmd = argv[1]
host argv[2]
port = int(argv[3])
s = socket(AF_INET, SOCK_DGRAM)
s.sendto(bytes(cmd, "utf-8"), (host, port))
Klickt jetzt auf die rot hinterlegte Diskette oben rechts um die Änderung zu speichern.
Nun öffnet ihr wieder den Dateibrowser und öffnet die “configuration.yaml”, die im Verzeichnis “homeassistant/” zu finden ist.
Mit dem Pfeil nach links, der neben dem Namen des aktuellen Verzeichnisses angezeigt wird, kommt ihr eine Ebene nach oben.
Klickt dann auf den Editor um den Browser zu schließen.
Falls ihr bereits die shell-integration konfiguriert habt sucht den Block “shell command:” und fügt dort die Definition für die beiden neuen shell commands “monitor_on” und “monitor_off” ein.
Falls ihr bisher noch keine shell-commands habt fügt den gesamten folgenden Block ein:
shell command:
monitor_on: python /config/shellscripts/send_udp_packet.py 1 {host} {port}
monitor_off: python /config/shellscripts/send_udp_packet.py 0 {host} {port}
{host} müsst ihr natürlich mit dem Hostnamen des entfernten Rechners ersetzten und
- ganz wichtig - {port} gemäß der Einstellung in der Service Unit anpassen (Default ist 5001).
Dies stellt euch dann 2 neue shell-Befehle zur verfügung (hier “monitor_on” und “monitor_off”).
Falls ihr euch über den Pfad wundert: Im Dateisystem des HA Servers ist der Ordner “homeassistant” nur ein Link auf den Ordner “config”, der im Wurzelverzeichnis der entsprechenden Partition liegt. Somit funktioniert für die shell-integration der Pfad mit “/config/…” entsprechend. Wenn ihr, wie ich, einen Unterordner angelegt habt, muss der nach “/config” folgen, dann kommt auch schon der Name des Python-scripts. “python” ist der Shell-Befehl, den HA ausführt und der Pfad und Parameter übergeben bekommt.
Die Namen der Aktions “monitor_on" und “monitor_off” könnt ihr frei wählen.
Für jedes entferntem System, dass ihr steuern möchtet, benötigt ihr diese 2 Zeilen mit entsprechenden Hostnamen und Portnummern.
Dies ist alles, was am HA Server angepasst werden muss. Abschließend müsst ihr HA neu starten, damit die shell-commands aktiv werden.
Nach dem Neustart könnt ihr die Developer Tools öffnen und in den Bereich “Aktionen” gehen.
Wenn ihr im “Aktion”-Wähler nun eure Shell-commands sucht bzw. auswählt und dann auf “Aktion ausführen” klickt, sollte der Monitor des entfernten Rechners ein bzw. aus geschaltet werden (je nach dem welche Aktion ihr ausgeführt habt).
Viel Spaß damit die Monitore eurer entfernten Rechner per Automation ein und aus zu schalten.
Ist übrigens auch Prima geeignet um dem Partner einen keinen Streich zu spielen ![]()
Wünsche gutes gelingen. Falls noch Fragen aufkommen, immer her damit.
VG Thorsten