REST-API
Konzept
Der REST-Treiber ist ein HTTP(S)-Client mit JSON-, XML/SOAP-, Text- und JPEG-Unterstützung. Zusätzlich kann er als Listener (HTTP-Server für Push-Ereignisse) und als SSE-Client (Server-Sent Events) arbeiten. PROTOCOL beginnt mit REST (z. B. REST-API (DDF)).
Jede Funktion ist ein Request: Methode + URL + Argumente. Die Antwort wird anhand ihres Content-Type geparst und ist in der Formel über Pfadzugriffe lesbar.
Parameter (*GENERAL)
| Key | Beschreibung |
|---|---|
CONNECTION |
meist DOMAIN |
DOMAIN |
Basis-URL, z. B. http://<DEVICE_IP> oder https://api.example.com. Bei Multi-Instanzen als Liste bzw. Bereich. |
AUTHENTIFICATION |
NONE, PASSWORD, TOKEN, OAUTH_DEVICE_FLOW, OAUTH_GRANT_FLOW, BASIC_AUTH |
USER / PASSWORD |
für BASIC_AUTH (HTTP Basic) bzw. PASSWORD. Werte setzt der Benutzer. |
LISTENER_PORT |
Port für METHOD=LISTEN |
SOAPACTION, SOAPNS |
für DATATYPE=SOAP |
JPEGFILE |
Ablage für JPEG-Antworten |
TIMEOUT |
Hinweis: Der Client verwendet intern Timeouts von 4 s. |
TLS
Die Zertifikatsprüfung ist im Client abgeschaltet. HTTPS verschlüsselt also, authentifiziert den Server aber nicht.
Spalten der Funktionen
| Spalte | Beschreibung |
|---|---|
ALIAS |
Name |
METHOD |
GET, POST, PUT, PATCH, DELETE, URL (nur URL bauen), SSE (Event-Stream), GETSTREAM, LISTEN (Listener) |
URL |
Pfad relativ zu DOMAIN (oder eine absolute URL) |
DATATYPE |
JSON, TEXT, XML, SOAP, X-WWW-FORM-URLENCODED (bestimmt Body-Format und Content-Type) |
POLLING |
ms |
FORMULA |
Auswertung der Antwort |
Argumente
;*ARGS;METHOD;ALIAS;TYPE;NAME;VALUE;ITEM;FORMAT;
;ARGS;<FunktionsALIAS>;;<TYPE>;<NAME>;<VALUE>;<ITEM>;<FORMAT>;
Die Spalte direkt nach ARGS ist der Funktions-Alias (im Kopf METHOD). Die Spalte ALIAS bleibt in den Originaldateien leer.
| Spalte | Beschreibung |
|---|---|
METHOD (Spalte nach ARGS) |
Funktions-Alias oder *ALL |
ALIAS |
leer (Bedeutung zu klären) |
TYPE |
url = Pfadteil anhängen · arg = Query-Parameter (?/&, URL-kodiert) · header = HTTP-Header · data = Body-Feld |
NAME |
Name des Parameters/Headers/JSON-Schlüssels |
VALUE |
fester Wert |
ITEM |
Quelle des Werts: Variablen-/Itemname, oder $KEY für params[KEY] (z. B. $TOKEN) |
FORMAT |
Formatierung (siehe unten) |
Zur Laufzeit lassen sich Argumente per <ALIAS>.ARG.<name> := wert; setzen.
FORMAT-Werte
| FORMAT | Wirkung |
|---|---|
(leer) / STRING |
als String |
DEZIMAL |
Ganzzahl |
FLOAT |
Gleitkomma |
ISO8601 |
Zeitstempel → ISO-8601 |
DAY |
Datum |
T_YYYYMMDDHHMM |
Zeitformat YYYYMMDDHHMM |
ENUM:0=a,1=b |
Zahl → Text |
BLOCK, BLOCK_START, BLOCK_END |
verschachtelte JSON-Objekte öffnen/schließen |
ARRAY_START, ARRAY_END |
JSON-Array öffnen/schließen |
%s, %lld, %g … |
printf-Format |
Ein JSON-Body wird automatisch in { … } eingeschlossen. Bei SOAP erzeugt der Treiber den Envelope mit SOAPNS/SOAPACTION.
Zugriff auf die Antwort
| Ausdruck | Bedeutung |
|---|---|
<A>.HTTP_CODE |
HTTP-Statuscode |
<A>.HTTP_DATA |
Rohantwort (String) |
<A>.HTTP_DATA_TYPE |
erkannter Content-Type |
<A>.VALUE.<pfad> |
Wert an JSON/XML-Pfad, z. B. R.VALUE.data.power, Arrays mit name[n] |
<A>.EXIST.<pfad> |
1, wenn der Pfad existiert |
<A>.FIND.<str>.<pfad> |
Suche nach str |
<A>.FINDVALUE.<key>.<str>.<pfad> |
Element finden, dessen key = str ist, und pfad darin lesen |
<A>.ASLIST.<arr[-1]…> |
Array als Liste |
<A>.ARRAY.MEDIA|MIN|MAX|LEN.<pfad> |
Mittelwert, Minimum, Maximum, Länge eines Zahlenarrays |
<A>.ARG.<name> |
Argumentwert |
.Q, .F, .URL, … |
allgemeine Suffixe |
Ergänzend gibt es die Formelfunktionen JSONGETVALUE(json,pfad) und JSONGETVALUEFROMARRAY(…) (siehe Formelreferenz).
Listener (Push)
METHOD=LISTENundLISTENER_PORTim*GENERAL.- Eingehende Requests werden über die IP des Absenders dem Gerät (der
DOMAIN) zugeordnet. - Unterstützte Content-Types: XML, JSON, multipart. Max. 10 gleichzeitige Verbindungen, Timeout 12 s.
- Die Formel der Listener-Funktion wertet den empfangenen Inhalt mit denselben Pfadzugriffen aus.
SSE
METHOD=SSE öffnet einen Event-Stream. Jedes Ereignis wird in JSON gewandelt ({"event":…}) und steht der Formel wie eine normale Antwort zur Verfügung.
Schritt für Schritt
- Die API-Doku auswerten: Basis-URL, Authentifizierung, Endpunkte, Antwortformat.
*GENERAL:PROTOCOL;REST-API (DDF),CONNECTION;DOMAIN,DOMAINals Vorgabe (oder leer lassen, dann setzt sie der Benutzer),AUTHENTIFICATION.- Je Endpunkt eine
*READ-Funktion (GET,POLLING). - Header und Query als
ARGS. Geheimnisse nie fest eintragen, sondern überITEM=$KEYaus den Parametern nehmen. - In der Formel
IF R.Q && R.HTTP_CODE == 200 THEN … ENDIF;prüfen undR.VALUE.<pfad>auslesen. - Schreibende Endpunkte als
*WRITEmitPOLLING0 anlegen. Das Item setzt in derWFORMULA<A>.ARG.<name>und<A>.F:=1;.
Realer Auszug: Shelly DUO RGBW Bulb
Datei Shelly.Lamp.REST-API (DDF).DUO RGBW Bulb.1(0x0D00002D00010100).csv (gekürzt, Geräte-IP geschwärzt):
*GENERAL;
;DEVICE;DUO RGBW Bulb;
;MANUFACTURER;Shelly;
;TYPE;Lamp;
;PROTOCOL;REST-API (DDF);
;MODEL_NR;1;
;VERSION_NR;1;
;ID;0x0D00002D00010100;
*GENERAL;
;CONNECTION;DOMAIN;
;AUTHENTIFICATION;NONE;
;DOMAIN;http://<DEVICE_IP>;
;SLAVESMAX;20;
*READ;ALIAS;METHOD;URL;DATATYPE;FORMULA;POLLING;
;STATE;GET;;JSON;"""IF STATE.HTTP_CODE == 200 THEN
X.100 := STATE.VALUE.ison;
X.101 := STATE.VALUE.mode;
X.102 := STATE.VALUE.brightness * 32767 / 100;
X.103 := STATE.VALUE.red * 32767 / 255;
X.108 := (STATE.VALUE.temp - 3000) * 4681 / 495;
X.200 := 1;
ELSE
X.200 := 0;
ENDIF;
STATE.F := 0;""";5000;
;*ARGS;METHOD;ALIAS;TYPE;NAME;VALUE;ITEM;FORMAT;
;ARGS;STATE;;url;/light/0;
*WRITE;ALIAS;METHOD;URL;DATATYPE;FORMULA;
;TURN;GET;;JSON;"""IF TURN.HTTP_CODE == 200 THEN
X.200 := 1;
ELSE
X.200 := 0;
ENDIF;
TURN.F := 0;""";
;*ARGS;METHOD;ALIAS;TYPE;NAME;VALUE;ITEM;FORMAT;
;ARGS;TURN;;url;/light/0;
;ARGS;TURN;;arg;turn;;turn_val;STRING;
;ARGS;TURN;;arg;transition;;X.7;DEZIMAL;
;RGB;GET;;JSON;"""IF RGB.HTTP_CODE == 200 THEN
X.200 := 1;
ELSE
X.200 := 0;
ENDIF;
RGB.F := 0;""";
;*ARGS;METHOD;ALIAS;TYPE;NAME;VALUE;ITEM;FORMAT;
;ARGS;RGB;;url;/light/0;
;ARGS;RGB;;arg;red;;red_val;DEZIMAL;
;ARGS;RGB;;arg;gain;100;;DEZIMAL;
;ARGS;RGB;;arg;mode;color;;STRING;
*GROUP;ID;ALIAS;NAME;
;0;BULB;BULB;
*ITEM;GROUP;ALIAS;NAME;ID;VISIBILITY;UNIT;TYPE;DEFAULT;WFORMULA;RFORMULA;POLLING;
;0;TURN_SET;Turn SET;0;;0=Off, 1=On;;;"""IF X.0 THEN
turn_val := 'on';
ELSE
turn_val := 'off';
ENDIF;
TURN.F := 1;""";
;0;RED_SET;Red SET;3;;%;;;"""red_val :=X.3 *255 / 32767; RGB.F:=1;""";
;0;TRANSITION_SET;Transition SET;7;;[0,5000] ms;
;0;ISON_FB;Ison FB;100;;0=Off, 1=On;
;0;NEXT_REQUEST;Next Request;199;;s;;;;"""IF STATE.HTTP_CODE == 200 THEN
X.199 := 5 - ($.SYS.TIME - STATE.T);
ENDIF;""";250;
;0;QUALITY;Quality;200;;0=Error, 1=Ok;
Was der Auszug zeigt:
- Jede Anweisung endet mit
;, auch in einzeiligen Formeln (red_val :=X.3 *255 / 32767; RGB.F:=1;). - Die
URL-Spalte der Funktion ist leer. Der Pfad/light/0wird über ein Argument vomTYPEurlangehängt. - Argumentzeilen: Die Spalte direkt nach
ARGSenthält den Funktions-Alias. Im Kopf heißt sie hierMETHOD. Danach folgen die Spalten des Kopfes (ALIASleer,TYPE,NAME,VALUE,ITEM,FORMAT). ITEMeines Arguments kann eine temporäre Variable (turn_val,red_val) oder ein Item (X.7) sein. DieWFORMULAsetzt die Variable und löst die Funktion per.F := 1;aus.- Items werden über ihre ID angesprochen (
X.100).X.0in derWFORMULAvon Item 0 ist dessen eigener neuer Wert. - Ein Gerät darf mehrere
*GENERAL-Blöcke haben, deren Parameter zusammengeführt werden. - Die Funktion setzt ihr eigenes Flag am Ende zurück (
STATE.F := 0;).
Fallstricke
DOMAINohne Schema (http://) führt zu ungültigen URLs.- Ein JSON-Body wird automatisch in
{}gepackt. Ein eigenes{inVALUEerzeugt deshalb doppelte Klammern. - Bei verschachtelten Bodys gehören
BLOCK_START/BLOCK_ENDpaarweise zusammen. - Bei Listenern muss die Absender-IP zur
DOMAINpassen, sonst wird das Ereignis keinem Gerät zugeordnet. - Lange Antwortzeiten (> 4 s) führen zu Timeouts.
- Keine Secrets in der DDF: Tokens und Passwörter kommen aus den Parametern.
Checkliste
- [ ]
PROTOCOLbeginnt mitREST - [ ]
DOMAINmit Schema, Pfade inURLbeginnen mit/ - [ ]
DATATYPEpasst zum Body - [ ] Argumente mit korrektem
TYPE(url/arg/header/data) - [ ] Formeln prüfen
.QundHTTP_CODE - [ ] Schreibfunktionen
POLLING0, Auslösen über.F - [ ] keine Secrets im Klartext