fix(station): V2/V3-Panelkapselung, wiedereintrittsfaehiges module_init, Unit-Fixes
Fixrunde 1 zu Task 6a: epd2in13_V2.init() braucht ein Pflichtargument und dessen displayPartial() setzt selbst keine LUT (neue Panel-Klasse in display.py kapselt das statt es zu verstreuen); epdconfig.module_init() war nicht wiedereintrittsfaehig und ein zu breites except tarnte GPIOPinInUse als "Panel fehlt" (jetzt idempotent, gezielter except); ninlight-display.service hatte ReadOnlyPaths=/run/ninlight-station (verhindert den Start, wenn die Station regulaer aus ist), StartLimit* in der falschen Sektion und SupplementaryGroups=spi gpio (harter Fehler auf reinem Debian ohne diese Gruppen); ein fehlendes Pillow fuehrte zu ModuleNotFoundError statt zum vorgesehenen stillen Exit 0. Dazu: Panel schlaeft nach jedem Zeichnen (Alterung), Modus-Vorrang liegt jetzt bei RUN_DIR/mode statt bei status.json, export-Praefix in der Konfigurationsdatei wird erkannt, MAX_COLS auf das mit Pillow nachgemessene Mass korrigiert, und build_state() hat jetzt eigene Tests.
This commit is contained in:
@@ -90,10 +90,23 @@ def spi_writebyte2(data) -> None:
|
||||
|
||||
|
||||
def module_init() -> int:
|
||||
"""Oeffnet GPIO-Pins und SPI-Geraet. Wirft DisplayUnavailable statt irgendeiner
|
||||
Bibliotheksausnahme, damit display.py genau eine Ausnahmeklasse abfangen muss."""
|
||||
"""Oeffnet GPIO-Pins und SPI-Geraet. Wirft DisplayUnavailable statt einer rohen
|
||||
Bibliotheksausnahme, damit display.py genau eine Ausnahmeklasse abfangen muss.
|
||||
|
||||
Idempotent: ein zweiter Aufruf, waehrend die Pins/das SPI-Geraet noch offen sind (die
|
||||
Panel-Treiber rufen dies bei JEDEM epd.init() erneut auf - Vollaufbau bei Moduswechsel
|
||||
oder alle 30 Minuten loest also ohne diese Absicherung einen zweiten, unnoetigen
|
||||
Oeffnungsversuch aus), kehrt sofort zurueck statt gpiozero.DigitalOutputDevice(17)
|
||||
ein zweites Mal anzulegen. Das wuerde mit GPIOPinInUse scheitern - vom breiten
|
||||
except unten (Fixrunde 1, C2) frueher faelschlich als "Panel fehlt" verschluckt,
|
||||
obwohl es ein Programmierfehler in der Aufrufreihenfolge ist. Nach module_exit()
|
||||
(z.B. durch epd.sleep()) ist _spi wieder None, ein echter Neuaufbau laeuft dann
|
||||
normal."""
|
||||
global _rst_pin, _dc_pin, _busy_pin, _spi
|
||||
|
||||
if _spi is not None:
|
||||
return 0
|
||||
|
||||
if gpiozero is None or spidev is None:
|
||||
raise DisplayUnavailable("gpiozero/spidev nicht installiert")
|
||||
|
||||
@@ -101,6 +114,14 @@ def module_init() -> int:
|
||||
if not os.path.exists(spi_path):
|
||||
raise DisplayUnavailable(f"{spi_path} fehlt - ist SPI aktiviert (raspi-config)?")
|
||||
|
||||
# Nur Fehler, die tatsaechlich von einer fehlenden/blockierten Hardware kommen, werden
|
||||
# zu DisplayUnavailable - alles andere (ein echter Programmierfehler an anderer
|
||||
# Stelle) soll weiterhin als das erkennbar bleiben, was es ist, statt hier als
|
||||
# "Panel fehlt" getarnt zu werden (Fixrunde 1, C2, zweiter Teil).
|
||||
hardware_errors: tuple[type[BaseException], ...] = (OSError, ImportError)
|
||||
if gpiozero is not None:
|
||||
hardware_errors = hardware_errors + (gpiozero.GPIODeviceError,)
|
||||
|
||||
try:
|
||||
_rst_pin = gpiozero.DigitalOutputDevice(RST_PIN)
|
||||
_dc_pin = gpiozero.DigitalOutputDevice(DC_PIN)
|
||||
@@ -110,7 +131,7 @@ def module_init() -> int:
|
||||
_spi.open(_SPI_BUS, _SPI_DEVICE)
|
||||
_spi.max_speed_hz = _SPI_HZ
|
||||
_spi.mode = 0b00
|
||||
except Exception as e: # noqa: BLE001 - alles hier wird zu DisplayUnavailable
|
||||
except hardware_errors as e:
|
||||
module_exit()
|
||||
raise DisplayUnavailable(f"GPIO/SPI-Initialisierung fehlgeschlagen: {e}") from e
|
||||
|
||||
|
||||
Reference in New Issue
Block a user