- Alle AIDA-Referenzen durch "Zeiterfassung" ersetzt - Modulare Zeiterfassung dokumentiert (CSV + REST API) - Azure-Einrichtung auf Webbasierte Auth aktualisiert - Verweis auf detaillierte Azure-Anleitung - Projektstruktur und Installer ergaenzt Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Busylight WLED Controller
Web-Anwendung zur Steuerung von WLED-Busylights basierend auf Microsoft Teams Presence-Status, Zeiterfassung und Telefonanlage (Webhook).
Jedes WLED-Geraet verfuegt ueber zwei Segmente (oben/unten), die jeweils einem Benutzer zugeordnet werden. Die Farbe des Segments wird automatisch anhand des Anwesenheitsstatus, des Teams-Status und des Telefonstatus gesetzt.
Features
- Dashboard mit Echtzeit-Uebersicht aller Busylights (Zeiterfassungs-, Teams- und Telefon-Status als Badges)
- Benutzer-Verwaltung mit automatischem Sync aus Microsoft Entra ID (Azure AD)
- WLED-Geraete hinzufuegen, bearbeiten, entfernen mit automatischem Status-Check (online/offline, LED-Anzahl, Firmware)
- Zuordnung von Benutzern zu WLED-Segmenten per Dropdown
- Farb-Regeln mit Color-Picker fuer jeden Status
- Telefon-Webhook fuer Telefonanlage (callstart/callend auf Port 8081)
- Modulare Zeiterfassung per CSV oder REST API - kompatibel mit jeder Zeiterfassung
- Webbasierte Azure-Authentifizierung direkt im Browser (kein Terminal noetig)
- Einstellungen fuer Azure, Polling-Intervall und Zeiterfassung
- Protokoll der letzten Statusaenderungen
Funktionsweise
| Quelle | Beschreibung | Auswirkung auf WLED |
|---|---|---|
| Zeiterfassung | Anwesend / Abwesend / Homeoffice | Grundfarbe (gruen / aus / gelb) |
| Microsoft Teams | Verfuegbar / Beschaeftigt / Nicht stoeren / etc. | Farbe wenn anwesend |
| Telefonanlage (Webhook) | Telefoniert / Frei | Rot wenn aktiv, danach zurueck auf Zeiterfassungs-Status |
Prioritaet: Telefon > Teams > Zeiterfassung. Die WLED-Farbe wird nur gesetzt wenn der Mitarbeiter laut Zeiterfassung anwesend oder im Homeoffice ist.
Voraussetzungen
- Linux-Server (Debian 13+ empfohlen)
- Python 3.10+
- Netzwerkzugriff auf die WLED-Geraete (HTTP Port 80)
- Microsoft Entra ID App-Registrierung (siehe Azure-Einrichtung)
- Optional: Zeiterfassung per CSV oder REST API
- Optional: Telefonanlage mit Webhook-Unterstuetzung (z.B. Starface)
Installation
Schnellinstallation (Debian 13)
curl -s https://git.cynfo.net/christian/busylight_modular/raw/branch/master/install.sh | bash
Manuelle Installation
# Repository klonen
git clone https://git.cynfo.net/christian/busylight_modular.git /opt/busylight
cd /opt/busylight
# Python Virtual Environment erstellen
python3 -m venv venv
source venv/bin/activate
# Abhaengigkeiten installieren
pip install -r requirements.txt
Einrichtung
1. Azure verbinden
Detaillierte Anleitung: docs/azure-einrichtung.md
Kurzfassung:
- App-Registrierung in Azure erstellen
- Oeffentliche Clientflows aktivieren
- API-Berechtigungen setzen (User.Read.All, Presence.Read.All)
- Im Web-Interface unter Einstellungen die IDs eintragen
- Auf "Mit Azure verbinden" klicken und im Browser anmelden
2. Benutzer synchronisieren
Unter Benutzer auf "Aus Azure synchronisieren" klicken. Anschliessend:
- Benutzer aktivieren/deaktivieren (nur aktive Benutzer werden abgefragt)
- Personalnummer zuordnen (fuer Zeiterfassung)
- Telefon-Durchwahl zuordnen (fuer Starface-Webhook)
3. WLED-Geraete anlegen
Unter Tuerschilder die Hostnamen/IP-Adressen der WLED-Busylights eintragen. Der Status (online/offline, LEDs, Firmware) wird automatisch alle 4 Minuten geprueft.
4. Zuordnungen erstellen
Unter Zuordnungen jeden aktiven Benutzer einem WLED-Geraet und Segment zuweisen:
- Segment 0 = unten
- Segment 1 = oben
5. Farben anpassen
Unter Farb-Regeln die Farben fuer jeden Status per Color-Picker anpassen:
| Status | Beschreibung |
|---|---|
abwesend |
Benutzer nicht anwesend |
homeoffice |
Benutzer im Homeoffice |
phone_active |
Benutzer telefoniert (Webhook) |
teams_available |
Teams: Verfuegbar |
teams_busy |
Teams: Beschaeftigt |
teams_donotdisturb |
Teams: Nicht stoeren |
teams_inacall |
Teams: In einem Anruf |
teams_inameeting |
Teams: In einer Besprechung |
teams_presenting |
Teams: Praesentiert |
teams_away |
Teams: Abwesend |
teams_offline |
Teams: Offline |
teams_outofoffice |
Teams: Abwesend (ganztaegig) |
teams_inactive |
Teams: Inaktiv |
teams_offwork |
Teams: Nicht bei der Arbeit |
Zeiterfassung
Die Zeiterfassung ist modular - es gibt zwei Wege den Anwesenheitsstatus zu liefern:
Option A: CSV-Datei
Eine CSV-Datei mit dem Anwesenheitsstatus wird periodisch gelesen. Das Format:
~~00100~~,~~1~~
~~00101~~,~~0~~
~~00102~~,~~2~~
Status-Codes (konfigurierbar in den Einstellungen):
~~0~~= Abwesend~~1~~= Anwesend~~2~~= Homeoffice
Die CSV kann von jedem Zeiterfassungssystem per Script erzeugt werden. In den Einstellungen den Pfad zur CSV eintragen.
Option B: REST API
Externe Systeme koennen den Status direkt per API setzen (Port 8081):
# Status setzen
curl -X POST -H "Content-Type: application/json" \
-d '{"status":"anwesend"}' \
http://SERVER:8081/api/attendance/00100
# Alle Status abfragen
curl http://SERVER:8081/api/attendance
Beide Optionen koennen parallel genutzt werden.
Telefonanlage (Webhook)
Die Anwendung startet automatisch einen Webhook-Server auf Port 8081 fuer die Anbindung einer Telefonanlage (z.B. Starface).
Webhook-Endpoints
GET/POST http://SERVER:8081/{durchwahl}/callstart - Anruf gestartet (WLED -> Rot)
GET/POST http://SERVER:8081/{durchwahl}/callend - Anruf beendet (WLED -> zurueck auf Zeiterfassungs-Status)
Einrichtung
- Unter Benutzer im Web-Interface die Durchwahl pro User eintragen (z.B.
123) - In der Telefonanlage den Webhook konfigurieren:
- Anrufbeginn:
http://SERVER-IP:8081/123/callstart - Anrufende:
http://SERVER-IP:8081/123/callend
- Anrufbeginn:
Verhalten
callstart: Setzt WLED auf Telefon-Farbe (Standard: Rot), aber nur wenn der Mitarbeiter laut Zeiterfassung anwesend oder im Homeoffice istcallend: Setzt WLED zurueck auf den Zeiterfassungs-Status. Der Teams-Status wird beim naechsten Polling-Zyklus (15s) automatisch aktualisiert- Waehrend eines aktiven Telefonats ueberschreibt das Teams-Polling die Farbe nicht
- Die Telefon-Farbe (
phone_active) ist unter Farb-Regeln konfigurierbar
Starten
Manuell (zum Testen)
cd /opt/busylight
source venv/bin/activate
python app.py
Dabei werden zwei Server gestartet:
- Port 8080: Web-Oberflaeche
- Port 8081: Webhook-Server (Telefonanlage + Zeiterfassungs-API)
Als systemd-Service (Produktivbetrieb)
# Service installieren (bei manueller Installation)
sudo cp busylight.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now busylight
# Status pruefen
sudo systemctl status busylight
# Logs anzeigen
sudo journalctl -u busylight -f
# Update
cd /opt/busylight && git pull
sudo systemctl restart busylight
Dashboard
Das Dashboard zeigt alle Busylights mit dem aktuellen Status in Echtzeit an und aktualisiert sich automatisch alle 10 Sekunden. Pro Benutzer werden drei Status-Badges angezeigt:
- Zeiterfassung: Anwesend (gruen) / Abwesend (grau) / Homeoffice (gelb)
- Teams: Verfuegbar / Beschaeftigt / Nicht stoeren / Offline / etc.
- Telefon: Telefoniert (rot) / Frei (grau)
Hintergrund-Jobs
| Job | Intervall | Beschreibung |
|---|---|---|
| Status-Polling | 15 Sekunden (konfigurierbar) | Teams-Presence und Zeiterfassungs-Status abfragen, WLED aktualisieren |
| Device-Check | 240 Sekunden | Alle WLED-Geraete auf Erreichbarkeit pruefen |
Projektstruktur
busylight/
├── app.py # FastAPI Web-Anwendung + Azure Auth + Startup
├── webhook.py # Webhook-Server + Zeiterfassungs-API (Port 8081)
├── database.py # SQLite Datenbank-Schema und Hilfsfunktionen
├── graph_client.py # Microsoft Graph API Client
├── wled_client.py # WLED HTTP API Client
├── scheduler.py # Hintergrund-Jobs (Polling + Device-Check)
├── install.sh # Installer fuer Debian 13
├── requirements.txt # Python-Abhaengigkeiten
├── busylight.service # systemd Service-Datei
├── docs/ # Dokumentation
├── static/
│ └── style.css # CSS Styles
└── templates/ # Jinja2 HTML-Templates
Ports und Firewall
| Port | Richtung | Zweck |
|---|---|---|
| 8080/tcp | Eingehend | Web-Oberflaeche |
| 8081/tcp | Eingehend | Webhook-API (Telefon + Zeiterfassung) |
| 80/tcp | Ausgehend | WLED HTTP API |
| 443/tcp | Ausgehend | Microsoft Graph API |
Troubleshooting
Dashboard zeigt nur graue Segmente
- Zeiterfassung pruefen (CSV-Pfad oder API-Status)
- Benutzer muessen aktiviert sein UND eine Personalnummer haben
- Zuordnung Benutzer -> WLED-Geraet + Segment muss vorhanden sein
Teams-Status wird nicht angezeigt
- Azure-Authentifizierung pruefen (Sidebar zeigt "Azure verbunden")
- API-Berechtigungen in Azure pruefen (Presence.Read.All)
Telefon-Webhook reagiert nicht
- Port 8081 erreichbar?
curl http://SERVER:8081/ - Durchwahl beim Benutzer eingetragen?
- Benutzer muss laut Zeiterfassung anwesend oder im Homeoffice sein
Azure Auth schlaegt fehl
- "Oeffentliche Clientflows zulassen" muss in der Azure App aktiviert sein
- Siehe docs/azure-einrichtung.md fuer Details
WLED-Geraete offline
- Unter Tuerschilder den Status pruefen ("Alle jetzt pruefen")
- Netzwerkverbindung pruefen:
curl http://HOSTNAME/json/info
Nach git pull aendert sich nichts
- Service neustarten:
sudo systemctl restart busylight