busylight_modular/README.md
Christian Mueller 6e6edd91db docs: README komplett ueberarbeitet - AIDA entfernt, modular
- 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>
2026-05-03 11:50:55 +02:00

279 lines
9.6 KiB
Markdown

# 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](docs/azure-einrichtung.md))
- Optional: Zeiterfassung per CSV oder REST API
- Optional: Telefonanlage mit Webhook-Unterstuetzung (z.B. Starface)
## Installation
### Schnellinstallation (Debian 13)
```bash
curl -s https://git.cynfo.net/christian/busylight_modular/raw/branch/master/install.sh | bash
```
### Manuelle Installation
```bash
# 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](docs/azure-einrichtung.md)
Kurzfassung:
1. App-Registrierung in Azure erstellen
2. Oeffentliche Clientflows aktivieren
3. API-Berechtigungen setzen (User.Read.All, Presence.Read.All)
4. Im Web-Interface unter **Einstellungen** die IDs eintragen
5. 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):
```bash
# 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
1. Unter **Benutzer** im Web-Interface die **Durchwahl** pro User eintragen (z.B. `123`)
2. In der Telefonanlage den Webhook konfigurieren:
- Anrufbeginn: `http://SERVER-IP:8081/123/callstart`
- Anrufende: `http://SERVER-IP:8081/123/callend`
### Verhalten
- `callstart`: Setzt WLED auf Telefon-Farbe (Standard: Rot), aber **nur** wenn der Mitarbeiter laut Zeiterfassung anwesend oder im Homeoffice ist
- `callend`: 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)
```bash
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)
```bash
# 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](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`