E-Paper behaelt sein Bild dauerhaft, auch stromlos. Faehrt der Pi herunter, wird der Anzeigedienst mit abgeraeumt und das zuletzt gezeichnete Bild bleibt fuer immer stehen - bei der Abnahme stand dort die Rueckfrage des Tastermenues, und der ausgeschaltete Pi sah aus, als warte er noch auf eine Eingabe. Zwei neue Units, ninlight-poweroff.service (WantedBy=poweroff.target) und ninlight-reboot.service (WantedBy=reboot.target). Sie haengen am System, nicht am Tasterdienst: so greifen sie bei jedem Herunterfahren - Menue, "poweroff" per SSH, "reboot" - und nicht nur auf einem von drei Wegen. Zwei Units statt einer Fallunterscheidung, weil systemd einem ExecStart nicht sagt, wohin die Reise geht. Die Texte unterscheiden sich: "AUSGESCHALTET / Strom kann getrennt werden" gegen "NEUSTART / Strom NICHT trennen!" samt Hinweis auf die rund zwei Minuten, die der Zero W bis zum Anzeigedienst braucht. An diesem Pi hat ein Stromzug in genau dieser Wartezeit schon eine SD-Karte gekostet. Reihenfolge: die Units ordnen sich per After=ninlight-display.service hinter dessen Stop ein, und "ninlight-station display final <kind>" wartet zusaetzlich, bis systemctl is-active nicht mehr anschlaegt - dasselbe Muster wie display_handover(), nur ohne Wiederanfahren. Gibt der Dienst die Leitungen nicht frei, wird nicht gezeichnet (GPIO busy), sondern gewarnt: ein Anzeigefehler haelt das Herunterfahren nie auf. Nebenbei behoben: display_run() reichte nur "$1" an display.py weiter und haette "--final poweroff" halbiert.
43 lines
2.3 KiB
Desktop File
43 lines
2.3 KiB
Desktop File
[Unit]
|
|
Description=ninlight-Station: "Ausgeschaltet"-Bild aufs E-Paper
|
|
Documentation=file:/opt/ninlight-station/README.md
|
|
# E-Paper ist bistabil: das zuletzt gezeichnete Bild bleibt fuer immer stehen, auch
|
|
# stromlos. Faehrt der Pi herunter, wird der Anzeigedienst mit abgeraeumt - ohne diese
|
|
# Unit behauptet das Panel danach dauerhaft den Zustand von vorher. Bei der Abnahme stand
|
|
# dort die Rueckfrage des Tastermenues, und der ausgeschaltete Pi sah aus, als warte er
|
|
# noch auf eine Eingabe.
|
|
#
|
|
# Sie haengt am SYSTEM, nicht am Tasterdienst: so greift sie bei jedem Herunterfahren -
|
|
# ueber das Tastermenue (systemctl poweroff), ueber "poweroff" per SSH, ueber jeden
|
|
# anderen Weg nach poweroff.target. Am Taster allein haetten wir die Anzeige nur auf
|
|
# einem von drei Wegen.
|
|
#
|
|
# Die Gegenstueck-Unit ninlight-reboot.service macht dasselbe fuer den Neustart, mit
|
|
# ANDEREM Text: beim Neustart darf man den Stecker gerade nicht ziehen.
|
|
DefaultDependencies=no
|
|
# Erst zeichnen, wenn der Anzeigedienst die GPIO-/SPI-Leitungen losgelassen hat: zwei
|
|
# Prozesse darauf enden in "lgpio.error: 'GPIO busy'" (in diesem Projekt schon zweimal
|
|
# passiert). "After=" auf eine Unit, die gerade gestoppt wird, ordnet deren Stop VOR den
|
|
# Start dieser hier - genau die gesuchte Reihenfolge. Das CLI wartet zusaetzlich, bis
|
|
# "systemctl is-active ninlight-display" nicht mehr anschlaegt (display_final()).
|
|
After=ninlight-display.service ninlight-button.service
|
|
# ... und noch BEVOR das System die Leitungen verliert: nach umount.target gibt es weder
|
|
# /opt/ninlight-station noch die Schriftdateien, aus denen das Bild entsteht.
|
|
Before=umount.target shutdown.target final.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
# Das Bild entsteht ueber das vorhandene CLI, nicht durch nachgebaute Logik: nur dort
|
|
# stehen EPD_REVISION aus /etc/ninlight-station.conf, die Uebergabe der GPIO-Leitungen
|
|
# und die Zusage "ein Fehler an der Anzeige haelt das Herunterfahren nie auf" (das CLI
|
|
# beendet sich hier immer mit 0).
|
|
ExecStart=/usr/local/bin/ninlight-station display final poweroff
|
|
# Ein Bildaufbau auf diesem Panel dauert Sekunden, nicht Minuten; dazu die Wartezeit auf
|
|
# die Freigabe der Leitungen. Der Deckel ist da, damit ein haengendes Panel das
|
|
# Herunterfahren nicht dauerhaft aufhaelt - systemds Vorgabe von 90 s waere hier eine
|
|
# sehr lange Zeit vor einem dunklen Geraet.
|
|
TimeoutStartSec=30
|
|
|
|
[Install]
|
|
WantedBy=poweroff.target
|