From b336bf35737a1b5094e10727413bf1aa8dc2dd3c Mon Sep 17 00:00:00 2001 From: Christian Mueller Date: Fri, 24 Apr 2026 23:03:29 +0200 Subject: [PATCH] docs: rewrite Starface module guide as step-by-step new build --- docs/starface-modul-anleitung.md | 379 ++++++++++++++++++++++++------- 1 file changed, 297 insertions(+), 82 deletions(-) diff --git a/docs/starface-modul-anleitung.md b/docs/starface-modul-anleitung.md index 045bee4..c6a27cc 100644 --- a/docs/starface-modul-anleitung.md +++ b/docs/starface-modul-anleitung.md @@ -1,130 +1,345 @@ -# Starface Modulcreator – Busylight Integration +# Starface Modul – Busylight Webhook (Neuaufbau) ## Übersicht -Dieses Modul sendet bei jedem Anruf-Event einen HTTP-Request an den Busylight-Server, -damit die Türschilder automatisch den Telefonstatus anzeigen. +Dieses Modul sendet bei jedem Anruf-Event einen HTTP-Request an den Busylight-Server. +Damit zeigen die Türschilder automatisch den Telefonstatus an. + +**Ablauf:** Anruf startet → Starface → HTTP GET → Busylight-Server → WLED wird rot +**Ablauf:** Anruf endet → Starface → HTTP GET → Busylight-Server → WLED zurück auf Normal ## Voraussetzungen -- Starface Telefonanlage mit Modulcreator-Lizenz -- Busylight-Server erreichbar unter `http://BUSYLIGHT-IP:8081` -- Durchwahlen der Mitarbeiter im Busylight-Portal eingetragen +- Starface mit Modulcreator-Lizenz +- Busylight-Server erreichbar unter `http://100.95.224.14:8081` +- Durchwahlen im Busylight-Portal bei den Benutzern eingetragen -## Modul im Modulcreator erstellen +--- -### Schritt 1: Neues Modul anlegen +## Neues Modul erstellen -1. Starface Admin-Oberfläche öffnen -2. **Admin** → **Modulcreator** (oder **Module** → **Modulcreator**) -3. **Neues Modul erstellen** -4. Modulinformationen: - - **Name**: `Busylight` - - **Beschreibung**: `Sendet Telefonstatus an Busylight Türschilder` +### Schritt 1: Modul anlegen + +1. Starface Admin → **Module** → **Modulcreator** +2. **Neues Modul erstellen** +3. Tab **Module Settings**: + - **Name**: `Busylight Webhook` + - **Version**: `1` - **Vendor**: `cynfo GmbH` - - **Version**: `1.0.0` -### Schritt 2: Modulkonfiguration (Instanz-Variablen) +--- -Unter **Modulkonfiguration** folgende Variablen anlegen: +### Schritt 2: GUI-Tab – Einstellungen definieren -| Variable | Typ | Standardwert | Beschreibung | -|----------|-----|-------------|-------------| -| `busylight_url` | String | `http://100.95.224.14:8081` | URL des Busylight Webhook-Servers | +1. Tab **GUI** öffnen +2. Ein neues Textfeld anlegen: + - **Variable-Name**: `GUI_WEBHOOK_URL` + - **Typ**: String + - **Standardwert**: `http://100.95.224.14:8081` + - **Label/Beschreibung**: `Busylight Webhook URL` -### Schritt 3: Trigger konfigurieren +Das ist die einzige Einstellung die der Admin später pro Instanz konfiguriert. -1. **Trigger hinzufügen**: `Anruf-Trigger` (Call Trigger) -2. **Trigger-Typ**: `Bei jedem Anruf` oder `Call State Changed` -3. **Richtung**: Eingehend + Ausgehend (beide) +--- -### Schritt 4: Funktionsablauf erstellen +### Schritt 3: Funktion "CallWebhook" erstellen -Der Ablauf hat zwei Zweige: +Diese Funktion baut die URL zusammen und sendet den HTTP-Request. -#### Zweig A: Anruf beginnt (callstart) +1. Tab **Development** +2. Links unter **Functions** auf **+** klicken → Name: `CallWebhook` +3. **Function Settings** klicken → **Input-Variablen** anlegen: -1. **Bedingung**: Anrufstatus = `CONNECTED` (Anruf angenommen) -2. **Aktion**: HTTP Request - - **Methode**: GET - - **URL**: `{busylight_url}/{called_number}/callstart` - - `{called_number}` = Die Durchwahl des angerufenen Benutzers +| Name | Typ | Beschreibung | +|------|-----|-------------| +| `loginId` | String | Durchwahl des Benutzers | +| `action` | String | `callstart` oder `callend` | -#### Zweig B: Anruf endet (callend) +4. Zurück zu **Edit** wechseln -1. **Bedingung**: Anrufstatus = `HANGUP` (Anruf beendet) -2. **Aktion**: HTTP Request - - **Methode**: GET - - **URL**: `{busylight_url}/{called_number}/callend` +5. Folgende 4 Bausteine nacheinander aus der **Components**-Sidebar (rechts) in den Edit-Bereich ziehen: -### Schritt 5: Variablen-Mapping +--- -Die Starface-Variablen müssen auf die URL gemappt werden: +#### Baustein 1: Append (URL zusammenbauen) -| Starface-Variable | Beschreibung | Verwendung | -|-------------------|-------------|-----------| -| `${call.calledNumber}` | Durchwahl des Angerufenen | In URL als Durchwahl | -| `${call.callingNumber}` | Nummer des Anrufers | Optional für Logging | -| `${call.state}` | Aktueller Anrufstatus | Für Bedingung | +**Wo:** Components → **String** → **Append** -**Hinweis:** Die genauen Variablennamen können je nach Starface-Version variieren. -Im Modulcreator werden die verfügbaren Variablen als Dropdown angeboten. +In den Edit-Bereich ziehen. Dann konfigurieren: -### Schritt 6: Modul speichern und aktivieren +- Input **"Strings"** (Klick auf das Feld, dann mehrere Werte hinzufügen): -1. **Speichern** klicken -2. **Modul exportieren** als `.sfm` Datei (für Backup) -3. Unter **Module** → **Modulinstanzen** eine neue Instanz anlegen -4. `busylight_url` auf die IP des Busylight-Servers setzen: `http://100.95.224.14:8081` -5. **Aktivieren** +| Nr | Wert | By Reference | +|----|------|-------------| +| 1 | `GUI_WEBHOOK_URL` | ✅ Ja (Referenz auf die Modul-Variable) | +| 2 | `/` | ❌ Nein (fester Text) | +| 3 | `loginId` | ✅ Ja (Referenz auf Input-Variable) | +| 4 | `/` | ❌ Nein (fester Text) | +| 5 | `action` | ✅ Ja (Referenz auf Input-Variable) | + +- Output **"result"** → wird automatisch erzeugt, z.B. `http://100.95.224.14:8081/222/callstart` + +--- + +#### Baustein 2: CreateHttpUrlWithParams (URL-Objekt erstellen) + +**Wo:** Components → **Net.HTTP** → **CreateHttpUrlWithParams** + +In den Edit-Bereich ziehen (unter den Append). Konfigurieren: + +- Input **"url"**: `result` → ✅ By Reference (Output vom Append-Baustein) +- Alle anderen Inputs leer lassen (keine Query-Parameter nötig) +- Output **"httpUrl"** → wird automatisch erzeugt + +--- + +#### Baustein 3: HttpRequest (HTTP-Request absenden) + +**Wo:** Components → **Net.HTTP** → **HttpRequest** + +In den Edit-Bereich ziehen (unter CreateHttpUrlWithParams). Konfigurieren: + +- Input **"httpUrl"**: `httpUrl` → ✅ By Reference (Output von CreateHttpUrlWithParams) +- Input **"method"**: `GET` → ❌ Fester Text +- Alle anderen Inputs (body, headers, timeout) leer lassen +- Output brauchen wir nicht + +--- + +#### Baustein 4: Log (zum Debuggen) + +**Wo:** Components → **System** → **Log** + +In den Edit-Bereich ziehen (unter HttpRequest). Konfigurieren: + +- Input **"Log level"**: `INFO` (fester Text) +- Input **"Message"** (mehrere Werte): + +| Nr | Wert | By Reference | +|----|------|-------------| +| 1 | `Busylight: ` | ❌ Nein (fester Text) | +| 2 | `result` | ✅ Ja (die URL die aufgerufen wurde) | + +--- + +**Die fertige CallWebhook-Funktion sieht im Editor so aus:** + +``` +Append([GUI_WEBHOOK_URL, "/", loginId, "/", action]) → result +CreateHttpUrlWithParams(result) → httpUrl +HttpRequest(httpUrl, "GET") +Log("INFO", ["Busylight: ", result]) +``` + +--- + +### Schritt 4: Funktion "Call" erstellen + +Diese Funktion wird bei jedem Anruf-Event aufgerufen. Sie ermittelt die Durchwahl +und ruft je nach Status `CallWebhook` mit `callstart` oder `callend` auf. + +1. Links unter **Functions** auf **+** klicken → Name: `Call` +2. **Function Settings** → **Input-Variablen** anlegen: + +| Name | Typ | Beschreibung | +|------|-----|-------------| +| `UCI_CALL` | UCI_CALL | By Reference ✅ – Das Anruf-Objekt | +| `USER_ACCOUNT` | STARFACE_USER | By Reference ✅ – Der betroffene User | + +3. Zurück zu **Edit** und folgende Bausteine einfügen: + +--- + +#### Baustein 1: Call.getCallInformations + +**Wo:** Components → **Call** → **Call.getCallInformations** + +- Input **"call"**: `UCI_CALL` → ✅ By Reference +- Outputs die wir brauchen: + - `uciCallState` (String) – Der Anruf-Status + - `uciCalledNumber` (String) – Die angerufene Nummer + +--- + +#### Baustein 2: ResolveUserData (Benutzerdaten holen) + +**Wo:** Components → **STARFACE** → **ResolveUserData** + +- Input **"accountId"**: `USER_ACCOUNT` → ✅ By Reference +- Output den wir brauchen: + - `loginId` (String) – Die Login-ID / Durchwahl des Users + +--- + +#### Baustein 3: IsUser (Prüfen ob es ein echter User ist) + +**Wo:** Components → **STARFACE** → **IsUser** + +- Input **"accountId"**: `USER_ACCOUNT` → ✅ By Reference +- Output: `isUser` (Boolean) + +--- + +#### Baustein 4: if(!isUser) → exit + +Wenn es kein User ist (z.B. eine Gruppe oder Queue), abbrechen. + +**Wo:** Components → **Basic Components** → **if** + +- Bedingung: `isUser` → **is not true** (isNotTrueExpression) +- Innerhalb des if: **exit** einfügen (Components → Basic Components → exit) + +--- + +#### Baustein 5: switch(uciCallState) – Status-Weiche + +**Wo:** Components → **Basic Components** → **switch** + +- Variable: `uciCallState` → ✅ By Reference + +Dann 3 **case**-Blöcke hinzufügen (Components → Basic Components → case): + +--- + +##### case 'INCOMING' + +- Condition: `INCOMING` (fester Text) +- Innerhalb: **CallWebhook** aufrufen + - **Wo:** Links unter Functions → `CallWebhook` in den case ziehen + - `loginId` = `loginId` → ✅ By Reference (Output von ResolveUserData) + - `action` = `callstart` → ❌ Fester Text + +##### case 'OUTGOING' + +- Condition: `OUTGOING` (fester Text) +- Innerhalb: **CallWebhook** aufrufen + - `loginId` = `loginId` → ✅ By Reference + - `action` = `callstart` → ❌ Fester Text + +##### case 'HANGUP' + +- Condition: `HANGUP` (fester Text) +- Innerhalb: **CallWebhook** aufrufen + - `loginId` = `loginId` → ✅ By Reference + - `action` = `callend` → ❌ Fester Text + +--- + +**Die fertige Call-Funktion sieht im Editor so aus:** + +``` +Call.getCallInformations(UCI_CALL) → uciCallState, uciCalledNumber, ... +ResolveUserData(USER_ACCOUNT) → loginId, firstName, familyName, ... +IsUser(USER_ACCOUNT) → isUser + +if(!isUser) + exit + +switch(uciCallState) + case 'INCOMING': + CallWebhook(loginId, "callstart") + case 'OUTGOING': + CallWebhook(loginId, "callstart") + case 'HANGUP': + CallWebhook(loginId, "callend") +``` + +--- + +### Schritt 5: Funktion "Register" erstellen + +Diese Funktion registriert den Call-Event-Listener wenn das Modul aktiviert wird. + +1. Links unter **Functions** auf **+** klicken → Name: `Register` +2. Einen Baustein einfügen: + +**Wo:** Components → **Call** → **RegisterCallEventByUser** (oder ähnlich) + +- Dieser registriert die `Call`-Funktion als Handler für alle Anruf-Events +- Target-Funktion: `Call` + +**Hinweis:** Der genaue Baustein heißt je nach Starface-Version anders. +Im alten Modul steht er unter "Register" und verweist auf die "Call"-Funktion. + +--- + +### Schritt 6: Funktion "Unregister" erstellen + +1. Links unter **Functions** auf **+** klicken → Name: `Unregister` +2. Einen Baustein einfügen der den Event-Listener wieder abmeldet + +--- + +### Schritt 7: Entry Points setzen + +1. Tab **Module Settings** (oder unten im Development-Tab) +2. **Entry Points** / **Lifecycle Events** konfigurieren: + - **InstanceActivated** → Funktion `Register` aufrufen + - **InstanceDeactivated** → Funktion `Unregister` aufrufen + +--- + +### Schritt 8: Speichern und Installieren + +1. **Save** klicken +2. **Apply** klicken +3. Modul als `.sfm` exportieren (für Backup) +4. Unter **Module** → **Modulinstanzen** → Neue Instanz anlegen +5. `GUI_WEBHOOK_URL` = `http://100.95.224.14:8081` +6. **Aktivieren** + +--- ## Testen -### Von der Kommandozeile testen +### Schnelltest von der Kommandozeile ```bash -# Anruf simulieren (Durchwahl 222 = Nicklas Janzen) +# Anruf simulieren (Durchwahl 222) curl http://100.95.224.14:8081/222/callstart -# → Türschild sollte rot werden +# → Dashboard zeigt "Telefoniert" bei Nicklas Janzen # Anruf beenden curl http://100.95.224.14:8081/222/callend -# → Türschild sollte auf Zeiterfassungs-Status zurückspringen +# → Dashboard zeigt normalen Status ``` -### Im Busylight-Portal prüfen +### Im Starface Modulcreator -- **Dashboard**: Telefon-Badge sollte "Telefoniert" anzeigen -- **Protokoll**: Einträge mit `phone_active` und `phone_end` sollten erscheinen +- Tab **Log File** öffnen +- Bei einem Testanruf sollte erscheinen: + ``` + INFO: Busylight: http://100.95.224.14:8081/222/callstart + ``` -## Alternative: Starface Rufnummernaktionen +### Im Busylight-Portal -Falls kein Modulcreator verfügbar ist, können auch **Rufnummernaktionen** verwendet werden: +- **Dashboard**: Telefon-Badge wechselt auf "Telefoniert" (rot) +- **Protokoll**: Einträge mit `phone_active` und `phone_end` -1. **Admin** → **Rufnummern** → Durchwahl auswählen -2. **Aktionen** → **Neue Aktion** -3. **Bei Anrufbeginn**: HTTP Request an `http://BUSYLIGHT:8081/{durchwahl}/callstart` -4. **Bei Anrufende**: HTTP Request an `http://BUSYLIGHT:8081/{durchwahl}/callend` +--- -**Nachteil:** Muss pro Durchwahl einzeln eingerichtet werden. +## Zusammenfassung – Alle Funktionen + +| Funktion | Zweck | Bausteine | +|----------|-------|-----------| +| `CallWebhook` | URL bauen + HTTP GET senden | Append → CreateHttpUrlWithParams → HttpRequest → Log | +| `Call` | Anruf-Event verarbeiten | getCallInformations → ResolveUserData → IsUser → if/exit → switch/case → CallWebhook | +| `Register` | Event-Listener anmelden | RegisterCallEventByUser | +| `Unregister` | Event-Listener abmelden | UnregisterCallEventByUser | ## Fehlerbehebung -### Türschild reagiert nicht +### Webhook kommt nicht an +1. Starface Log File prüfen – steht die URL drin? +2. Firewall: Port 8081 vom Starface-Server (192.168.200.251) zum Busylight-Server (100.95.224.14) offen? +3. Test: `curl http://100.95.224.14:8081/` vom Starface-Server -1. Busylight-Server erreichbar? `curl http://100.95.224.14:8081/` -2. Durchwahl im Busylight-Portal beim Benutzer eingetragen? -3. Benutzer laut Zeiterfassung "anwesend" oder "homeoffice"? -4. Starface-Modul aktiviert? -5. Firewall: Port 8081 von der Starface zum Busylight-Server offen? +### Falscher User wird rot +- `loginId` = Starface Login-ID = Durchwahl (z.B. 222) +- Diese muss im Busylight-Portal unter **Benutzer** → **Durchwahl** eingetragen sein -### Falscher Benutzer wird rot - -- Prüfen ob die Durchwahl im Busylight-Portal dem richtigen Benutzer zugeordnet ist -- Variable im Modulcreator: `${call.calledNumber}` (nicht `${call.callingNumber}`) - -### Türschild bleibt nach Anrufende rot - -- Prüfen ob das HANGUP-Event im Modul konfiguriert ist -- Im Busylight-Protokoll prüfen ob `callend` ankommt -- Manuell zurücksetzen: `curl http://100.95.224.14:8081/{durchwahl}/callend` +### Türschild bleibt rot +- HANGUP-case prüfen – wird `callend` gesendet? +- Manuell zurücksetzen: `curl http://100.95.224.14:8081/222/callend` +- Im Busylight-Protokoll prüfen ob `phone_end` ankommt