Files
grossanzeige/main.py
T
admin 142a621066 Dauerbetrieb: Autostart (main.py) und Watchdog
MicroPython fuehrt main.py nach jedem Reset selbst aus -- nach Stromausfall oder
Watchdog-Neustart laeuft die Anzeige damit ohne Notebook wieder an. Bisher gab es
die Datei bewusst nicht, weil am Aufbau gearbeitet wurde.

**Das Abbruchfenster ist kein Komfort, sondern die Notbremse.** Ohne es waere ein
Geraet, dessen Programm beim Start haengt, nur noch durch Neuflashen erreichbar:
Die Endlosschleife belegt die REPL sofort nach dem Reset. main.py wartet deshalb
erst AUTOSTART_DELAY (3 s), in denen Ctrl-C zurueck an die REPL fuehrt -- dann
laeuft auch kein Watchdog.

Watchdog (WDT_TIMEOUT = 120 s): startet das Geraet neu, wenn die Poll-Schleife
stehenbleibt. Gefuettert wird zu Beginn *jedes* Durchlaufs, auch nach einem
Fehler -- "KEIN LINK" ist kein Stillstand, die Schleife laeuft ja weiter. Der
Wert muss ueber allem liegen, was regulaer blockieren darf (WLAN 20 s,
Montierung 3 s, dazu ein MQTT-Versuch); knapper waere er eine Neustart-Schleife.

Ein gestarteter Watchdog laesst sich nicht mehr abschalten. Deshalb legt ihn nur
main.py an -- im Handbetrieb ueber die REPL startete das Geraet sonst neu,
waehrend man nachdenkt.

Weiteres:
- Nach einem Watchdog-Neustart meldet main.py das beim Start
  (machine.reset_cause()), sonst saehe er aus wie ein Stromausfall.
- Eine Ausnahme faengt main.py ab und startet nach RESTART_DELAY (10 s) neu,
  statt in die REPL zu fallen und die Anzeige einzufrieren. Die Pause verhindert
  eine Neustart-Schleife im Sekundentakt.
- Autostart faehrt mit Helligkeitsregelung (with_ldr=True, Nutzerentscheidung).

Am Geraet bestaetigt: Autostart nach Reset laeuft durch (Watchdog aktiv, WLAN,
MQTT), ein absichtlich herbeigefuehrter Stillstand loest den Watchdog aus und das
Geraet kommt von allein wieder hoch -- mit der Meldung "Vorheriger Lauf wurde vom
Watchdog beendet". Ctrl-C im Startfenster gibt die REPL frei.

Beim Geraetetest aufgefallen: make_watchdog wurde ohne log aufgerufen, im
Startprotokoll stand also nichts vom Watchdog. Behoben und durch einen Test
festgehalten. 178 Tests gruen (neu: test_main.py).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-27 18:41:33 +02:00

88 lines
2.9 KiB
Python

"""Autostart auf dem ESP32-C3.
MicroPython fuehrt diese Datei nach boot.py bei jedem Reset selbst aus. Damit
laeuft die Anzeige nach Stromausfall oder Watchdog-Neustart von allein wieder an,
ohne dass jemand ein Notebook anschliessen muss.
**Das Abbruchfenster ist kein Komfort, sondern die Notbremse.** Ohne es waere ein
Geraet, dessen Programm beim Start haengt oder abstuerzt, nur noch durch
Neuflashen erreichbar -- die Endlosschleife belegt die REPL sofort nach dem
Reset. Deshalb wartet main.py erst config.AUTOSTART_DELAY Sekunden, in denen
Ctrl-C zurueck an die REPL fuehrt:
mpremote repl dann Ctrl-C druecken, solange "startet in ..." steht
Danach:
- Der **Watchdog** startet das Geraet neu, wenn die Poll-Schleife stehenbleibt
(siehe run_esp32.make_watchdog). Das faengt Haenger, die keine Ausnahme werfen.
- Eine **Ausnahme** faengt der Block unten ab und startet nach
config.RESTART_DELAY neu, statt in die REPL zu fallen und die Anzeige
einzufrieren.
"""
import sys
import time
import config
def _startbar():
"""Wartet das Abbruchfenster ab. False, wenn abgebrochen wurde."""
print("Grossanzeige startet in %.0f s -- Ctrl-C bricht ab."
% config.AUTOSTART_DELAY)
try:
time.sleep(config.AUTOSTART_DELAY)
except KeyboardInterrupt:
print("Autostart abgebrochen, REPL ist frei.")
return False
return True
def _neustart(grund):
"""Nach einem Absturz neu starten -- mit Pause und Abbruchmoeglichkeit."""
print("%s -- Neustart in %.0f s (Ctrl-C bricht ab)"
% (grund, config.RESTART_DELAY))
try:
time.sleep(config.RESTART_DELAY)
except KeyboardInterrupt:
print("Neustart abgebrochen, REPL ist frei.")
return
try:
import machine
machine.reset()
except ImportError:
sys.exit()
def start():
if not _startbar():
return
import run_esp32
# Nach einem Watchdog-Neustart ist das der einzige Hinweis darauf, dass
# ueberhaupt etwas gehangen hat -- ohne ihn sieht ein Neustart aus wie ein
# gewoehnlicher Stromausfall.
try:
import machine
if machine.reset_cause() == machine.WDT_RESET:
print("Vorheriger Lauf wurde vom Watchdog beendet.")
except (ImportError, AttributeError):
pass
# log=print, damit im Startprotokoll steht, dass der Watchdog laeuft --
# sonst bliebe unsichtbar, ob er ueberhaupt angelegt wurde.
feed = run_esp32.make_watchdog(log=print)
try:
run_esp32.main(with_ldr=True, feed=feed)
except KeyboardInterrupt:
# Von Hand beendet: nicht neu starten, sondern die REPL freigeben.
# Der Watchdog laeuft allerdings weiter und startet das Geraet in
# config.WDT_TIMEOUT Sekunden neu -- er laesst sich nicht abschalten.
print("\nbeendet (Watchdog startet in %.0f s neu)" % config.WDT_TIMEOUT)
except Exception as e:
_neustart("Absturz: %s" % e)
start()