render.lines() zerlegt den zusammengefuehrten Zustand (status.json + control.json + SSID aus der Konfigurationsdatei) in Textzeilen, ohne Pillow und ohne Hardware zu brauchen - render.compose() importiert Pillow erst innerhalb der Funktion. epdconfig.py ist eine eigene GPIO/SPI-Schicht auf gpiozero/spidev, weil RPi.GPIO auf Debian 13 mit Python 3.13 nicht mehr traegt; epd2in13_V2.py/epd2in13_V3.py sind unveraendert aus dem Waveshare-Repository uebernommen (siehe HERKUNFT.md), nur der epdconfig-Import zeigt auf unser Modul. display.py laeuft als eigener systemd-Dienst (Wants=, Restart=on-failure), fehlendes Panel/SPI/Bibliothek beendet ihn sauber mit sys.exit(0) statt einer Neustartschleife - eine Migration darf davon nie abhaengen. Verdrahtung in setup_pi.sh/deploy.sh/ninlight-station folgt in einem eigenen Durchgang.
50 lines
2.1 KiB
Desktop File
50 lines
2.1 KiB
Desktop File
[Unit]
|
|
Description=ninlight E-Paper-Anzeige (Status der Migrations-/Rettungsstation)
|
|
# Nur eine Anzeige fuer den Hauptdienst - Wants=/After=, NICHT Requires=/BindsTo=: ein
|
|
# fehlendes oder abgestuerztes Panel darf server.py niemals mitreissen, und server.py
|
|
# darf umgekehrt starten, auch wenn dieser Dienst fehlt oder deaktiviert ist. Siehe
|
|
# display.py's Modul-Docstring: die Anzeige ist nirgends Voraussetzung fuer die
|
|
# Migration.
|
|
After=ninlight-station.service
|
|
Wants=ninlight-station.service
|
|
|
|
[Service]
|
|
Type=simple
|
|
# Reihenfolge wichtig: systemd wendet Environment=/EnvironmentFile= in der Reihenfolge
|
|
# an, in der sie hier stehen, und eine spaetere Zuweisung ueberschreibt eine gleichnamige
|
|
# fruehere. EPD_REVISION=V3 hier ist nur der Vorgabewert, falls die Konfigurationsdatei
|
|
# (unten, per EnvironmentFile=) den Schluessel (noch) nicht enthaelt - z.B. auf einem Pi,
|
|
# der vor Task 6 aufgesetzt wurde. Steht er dort, gewinnt er.
|
|
Environment=EPD_REVISION=V3
|
|
Environment=NINLIGHT_RUN_DIR=/run/ninlight-station
|
|
Environment=NINLIGHT_STATION_CONF=/etc/ninlight-station.conf
|
|
EnvironmentFile=/etc/ninlight-station.conf
|
|
ExecStart=/usr/bin/python3 /opt/ninlight-station/display/display.py
|
|
|
|
# display.py faengt ein fehlendes/abgestuerztes Panel als DisplayUnavailable ab,
|
|
# protokolliert eine Zeile und beendet sich mit sys.exit(0) - das ist also nie ein
|
|
# "Fehlschlag" im systemd-Sinne und loest kein Restart= aus. Restart=on-failure (nicht
|
|
# always) greift nur fuer echte Abstuerze (z.B. ein Python-Traceback aus einem
|
|
# Programmierfehler); ohne den Deckel wuerde ein dauerhaft fehlendes Panel sonst NICHT
|
|
# staendig neu versucht (gut so), waehrend ein echter Bug endlos neu starten wuerde und
|
|
# so das Journal fluten koennte.
|
|
Restart=on-failure
|
|
RestartSec=5
|
|
StartLimitIntervalSec=60
|
|
StartLimitBurst=5
|
|
|
|
NoNewPrivileges=yes
|
|
ProtectSystem=strict
|
|
ProtectHome=yes
|
|
PrivateTmp=yes
|
|
ReadOnlyPaths=/run/ninlight-station
|
|
RestrictAddressFamilies=AF_UNIX AF_NETLINK
|
|
MemoryMax=64M
|
|
|
|
# Fuer /dev/spidev0.0 und die GPIO-Zeichenleitung (per lgpio/gpiozero) noetig - laeuft
|
|
# deshalb nicht mit DynamicUser=, sondern als root wie der Hauptdienst.
|
|
SupplementaryGroups=spi gpio
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|