Betrieb & Installation

Cron & Mail-Verarbeitung

Der Cron ist das Herz der Automatisierung. Er ruft regelmäßig /cron.php auf, prüft das Mail-Postfach, parst neue Alarm-Mails und legt daraus Einsätze an.

Was im Cron passiert

Bei jedem Aufruf:

  1. Token-Check — passt der ?token=…-Parameter zum konfigurierten cron_token? Wenn nein: 403.
  2. Mail-Postfach abfragen — neue Mails seit dem letzten Lauf.
  3. Subject-Filter — passt das Betreff zu den konfigurierten Pattern (mail_subject_alarm / mail_subject_unwetter)?
  4. Pro passender Mail:
    • Parser extrahiert Felder (Stichwort, Adresse, Sachverhalt, EMs, Melder)
    • Geocoding löst die Adresse zu Koordinaten auf (mit Cache)
    • Einsatz anlegen via EinsatzService::create()
    • Auto-Zuweisung zum Schwerpunkt, falls der Ort zu einem aktiven Schwerpunkt im Modus „Orte" passt
    • Telegram-Push in den Alarm-Chat
  5. Heartbeat schreiben in logs/last-cron-beat.txt
  6. Statistik im Cron-Log (logs/cron-YYYYMMDD.log)

Crontab-Eintrag

Empfohlen: alle 2 Minuten. Mehr belastet das Postfach unnötig, weniger verzögert Alarme zu spürbar.

*/2 * * * * curl -fsS "https://etb.example.de/cron.php?token=DEIN_TOKEN" >/dev/null

Den Token findest Du unter /admin/config.php (Setting cron_token) oder im Setup-Wizard, der ihn beim Erst-Setup generiert.

⚠️ Achtung: Der Token ist ein gemeinsames Geheimnis — wer ihn kennt, kann beliebig oft /cron.php triggern. Schütze die Crontab-Datei mit den üblichen Unix-Permissions (chmod 600) und rotiere den Token, wenn er versehentlich nach außen gelangt.

Alternativen zum Crontab

  • systemd-Timer: Wenn Dein System systemd hat, ist das die modernere Variante. Erstelle etb-cron.service und etb-cron.timer.
  • Externer Scheduler: Cron-Jobs aus der Cloud (z. B. cron-job.org) können die URL stündlich abfragen — taugt aber nur als Notnagel, weil ein guter Alarm-Push minutengenau sein soll.

Mail-Parser im Detail

Der Parser extrahiert aus dem Mail-Body diese Felder:

Feld Wo es im Mail-Body steht (typisch)
Stichwort „Stichwort: …"
Adresse „Straße: …", „Ort: …", „Hausnummer: …"
Sachverhalt „Sachverhalt: …" (mehrzeilig)
Einsatzmittel „Alarmiert: …" (komma-separiert)
Melder „Melder: Name, Telefon"
Alarmzeit „Eingegangen: …"
Zusatz-Info „Bemerkung: …"

Die Erkennungsmuster sind in MailParser.php definiert und auf das Format einer konkreten Leitstelle zugeschnitten (das der Referenz-Installation). Wenn Deine Leitstelle ein anderes Format schickt, musst Du den Parser anpassen — das ist ein eigenes Projekt, eine reine Konfiguration reicht da nicht. Sprich uns an.

ℹ️ Auch der Mail-Parser nutzt den Stichwort-Katalog. Passt das Mail-Stichwort auf einen Katalog-Eintrag, wird dessen Anzeige-Variante gespeichert; passt keiner, bleibt das volle Stichwort der Mail stehen. Siehe Einsatz anlegen & bearbeiten und Stammdaten.

Geocoding

Adressen werden gegen den Nominatim-Server von OpenStreetMap aufgelöst. Damit Deine lokale „Hauptstraße 5" nicht in einem anderen Bundesland landet, wird der konfigurierte geocode_suffix an die Adresse angehängt (z. B. „12345 Musterstadt").

Cache: Jede aufgelöste Adresse landet in der DB-Tabelle geo_cache. Beim nächsten Treffer wird der Cache genutzt — schont Nominatim und bringt sub-second Response. Unter /geocode-admin.php siehst Du den Cache und kannst einzelne Einträge löschen oder neu auflösen.

Heartbeat

Der Cron schreibt alle 6 Stunden einen Heartbeat-Eintrag und der tägliche Heartbeat (separater Cron-Job auf /api/heartbeat.php?token=…) schickt eine ausführliche Status-Mail an den Telegram-Status-Chat:

🟢 Alarmpush-Heartbeat
Letzte 24 Stunden:
• 📋 Verarbeitete Alarme: 7
• 📑 Log-Einträge: 142
• ⚠️ Warnungen: 0
• ❌ Fehler: 0

Seit letztem ETB-Reset:
• 🚒 Einsätze gesamt: 23

Der Counter „Verarbeitete Alarme" zählt echte Einsätze aus der einsaetze-Tabelle (24 h bzw. seit ETB-Reset) — nicht die Cron-Aufrufe selbst. So bleibt der Zähler aussagekräftig, auch wenn der Cron alle 30 Sekunden läuft und 99 % der Aufrufe leer sind.

ℹ️ Der „Seit letztem ETB-Reset"-Counter setzt sich automatisch zurück, wenn der ETB-Reset (manuell oder morgendlich) läuft — kein zusätzlicher Counter-State nötig.

Was wenn der Cron nicht läuft?

  1. Manuell aufrufen: curl "https://etb.example.de/cron.php?token=…" — siehst Du die JSON-Response? Wenn nein, ist es ein Webserver-/PHP-Problem.
  2. Crontab prüfen: crontab -l -u www-data (oder der User, unter dem Dein Cron läuft).
  3. Cron-Logs: /var/log/syslog | grep CRON zeigt, ob der Job überhaupt getriggert wurde.
  4. System-Status öffnen (/admin/system-status.php) — zeigt das Alter des letzten Cron-Laufs.

Mehr in FAQ und Diagnose.

Was als nächstes?