Skip to content

CommandServer (TCP, UDP, HTTP) ​

Ein CommandServer ist eine eigene Verbindung des nomos system Controllers zu einem Gerät, über TCP, UDP, HTTP, HTTPS oder eine serielle Schnittstelle. Profile mit dem Engine-Typ CommandServer ("engineType": "") beschreiben diese Verbindung im Block structure. Wie der Rest eines Profils aufgebaut ist, steht unter Profilformat; vollständige Beispiele unter Beispielprofile.

Ablauf ​

json
"structure": {
	"config":   { "SERVERPROTOCOL": {"value": "TCP", "editable": false}, … },
	"commands": { "READ": {"sequence": "…", "parameterCount": 0}, … },
	"mappings": { "POWER": {"match": "…", "condition": "…", "onChange": true}, … }
}
  1. Verbindung (config): Wohin und wie der Controller sendet.
  2. Befehle (commands): Was gesendet wird. Eine Aktion des Profils, eine Abfrage oder eine Automation ruft einen Befehl auf, gegebenenfalls mit einem Wert.
  3. Antwortmuster (mappings): Was der Controller aus Antworten und Meldungen des Geräts herausliest. Jedes Muster, das passt, liefert einen benannten Wert, z. B. POWER=1250.
  4. Die Rückmeldungen des Profils (mappings auf oberster Ebene) holen sich diese Werte über ihr property ab: {"method": "get", "property": "POWER"}.

Beim Anlegen eines Geräts bekommt jede Verbindung einen eigenen Klassennamen aus className und einer laufenden Nummer, z. B. KEBA_P30_1. Unter diesem Namen können Sie Befehle im Internen Dienst von Hand senden, etwa <KEBA_P30_1><REPORT2></KEBA_P30_1> oder <KEBA_P30_1><SETCURR=16000></KEBA_P30_1>, und die Antworten in der Ausgabe verfolgen.

Verbindung ​

Jede Einstellung hat einen Wert und die Angabe, ob sie beim Anlegen des Geräts abgefragt wird:

json
"SERVERIP":   {"value": "", "editable": {"type": "host", "default": ""}},
"SERVERPORT": {"value": "502", "editable": {"type": "integer", "default": "502"}},
"SERVERMODE": {"value": "HEX", "editable": false}
  • editable: false: Der Wert gilt fest.
  • editable: {"type": …, "default": …}: Der Dialog Gerät erstellen fragt den Wert ab, vorbelegt mit default. type ist host, string, password, bool (wird zu YES/NO) oder integer/float (Zahlenfeld). Dazu ist help als Hilfetext möglich. Hinweis: Auch ein password wird im Dialog lesbar angezeigt.
  • comment: true: Die Einstellung ist ohne Wirkung, bleibt aber als Platzhalter nutzbar.
EinstellungBedeutungStandard
SERVERPROTOCOLTCP, UDP, HTTP, HTTPS oder SERIAL. Ein falsch geschriebener Wert gilt als UDPUDP
SERVERIPIP-Adresse des Geräts. Bei TCP und UDP nur eine IPv4-Adresse, kein Hostname. Bei HTTP(S) auch ein HostnamePflicht
SERVERPORTPort. Seriell (siehe Serielle Geräte): Gerät;Baud;Datenbits;Parität;Stoppbits;Fluss, z. B. /dev/ttyUSB0;9600;8;N;1;NONE oder AUTO;9600;8;N;1;NONEPflicht
SERVERMODEASCII (Text) oder HEX (Bytes als Hexziffern). Bei HTTP immer ASCIIPflicht
SERVERTIMEOUT_IN_MSWie lange die Verbindung nach dem letzten Befehl offen bleibt und auf Antworten wartet, in ms. NONE hält sie dauerhaft offen. Hat Vorrang vor SERVERTIMEOUTPflicht¹
SERVERTIMEOUTDasselbe in SekundenPflicht¹
MATCHINGFULL oder NORMAL, siehe Antwortmuster. Für fast alle Geräte FULLNORMAL
SPACINGPause nach jedem gesendeten Befehl in ms0
CONNECTEVENT, DISCONNECTEVENTMeldung beim Verbindungsaufbau bzw. -ende, meist REACHABLE=1 und REACHABLE=0, siehe Erreichbarkeit–
STARTUPCMDBefehle, die beim Start gesendet werden, getrennt durch Komma–
SHUTDOWNCMDBefehle, die bei jedem Ende der Verbindung gesendet werden–
HEARTBEATCMDBefehl;Sekunden, z. B. REPORT2;30: wird gesendet, wenn so lange kein anderer Befehl lief–
HEARTBEATTIMEOUTWartezeit in ms auf irgendeine Antwort nach dem Heartbeat; ohne Antwort wird die Verbindung beendet1000
RECONNECTYES: Nach dem Ende der Verbindung STARTUPCMD erneut senden. Wirkt nur zusammen mit HEARTBEATCMD und STARTUPCMDNO
RETRYINTERVALSekunden bis zum nächsten Versuch, wenn Verbinden oder Senden scheitert. Wiederholt ohne Ende, siehe Erreichbarkeit0
CMDPREFIX, CMDSUFFIXText vor bzw. hinter jedem Befehl, z. B. /api/ bei HTTP oder \x0D bei Text-Protokollen–
SEQUENCEPREFIX, SEQUENCESUFFIXText vor bzw. hinter dem ganzen gesendeten Paket–
MAPPREFIX, MAPSUFFIXText vor bzw. hinter jedem Antwortmuster–
STARTDELIMITER, ENDDELIMITERBeginn bzw. Ende einer Meldung, siehe Meldungen über mehrere Pakete–
SERVERTYPEPrüfsumme, nur bei HEX: MODBUS (CRC16 für Modbus RTU, Platzhalter XXXX in der Sequenz), SUM, SUM=a-b, XOR, XOR=a-b (über die Bytes a bis b, wird angehängt), außerdem RUS, ADNOTAM, SPEAKERCRAFT, TECNOALARM, SOUNDWEB, ESP3 für die gleichnamigen Protokolle–
USERNAME, PASSWORDHTTP(S): Basic-Anmeldung, wenn beide gesetzt sind. TCP, UDP, seriell: nach dem Verbindungsaufbau wird erst der Benutzername, dann das Kennwort gesendet, jeweils mit Zeilenende. Je höchstens 31 Zeichen–
LOCALPORTUDP: lokaler Port, an den das Gerät antwortet; RANDOM für einen zufälligen. Fehlt die Einstellung, gilt SERVERPORTSERVERPORT
NEGOTIATETELNET: Telnet-Aushandlung beantworten und aus den Antworten entfernen–
RESOLVE_SYSVARSYES: Variablen in eckigen Klammern ([ID]) in Sequenzen bei jedem Senden einsetzen, siehe VariablenNO
URL_SAFE_CHARSHTTP(S): Zeichen, die in der Adresse nicht kodiert werden sollen, z. B. ()–
DEBUGYES: jede Sequenz im Internen Dienst ausgebenNO
ACTIVENO schaltet die Verbindung abYES

¹ Eine der beiden Zeitangaben muss gesetzt sein.

WARNING

Eine fehlerhafte Verbindung wird ohne Meldung verworfen. Fehlt SERVERMODE oder eine Zeitangabe, ist der Port ungültig oder steht bei TCP/UDP ein Hostname statt einer IP-Adresse in SERVERIP, legt der Controller das Gerät zwar an, aber es sendet und empfängt nie etwas. Sehen Sie in diesem Fall im Internen Dienst nach, dort steht beim Start config of … is not valid - skipping.

Platzhalter ​

In Sequenzen, Antwortmustern, Bedingungen, Bodys und Kamera-URLs ersetzt der Controller %NAME% durch den Wert der Einstellung NAME, wie sie beim Anlegen eingegeben wurde, sonst durch den Wert im Profil. Außerdem stehen %CLASSNAME% (z. B. KEBA_P30_1) und %PLATFORM% zur Verfügung. Eigene Einstellungen, die das Gerät nicht kennt, sind erlaubt; mit comment: true bleiben sie ohne Wirkung und dienen nur als Platzhalter:

json
"config": {
	"DEVICEID": {"value": "1", "editable": {"type": "integer", "default": "1"}, "comment": true}
},
"commands": {
	"STATUS": {"sequence": "/api/device/%DEVICEID%/status", "parameterCount": 0}
}

Befehle ​

json
"commands": {
	"STATUS": {"sequence": "status?filter=frc,car,ama", "parameterCount": 0},
	"SETAMA": {"sequence": "set?ama=\\#", "parameterCount": 1},
	"READ_INSTANT": {"sequence": "000000000006010400000020", "parameterCount": 0, "tag": "instant"}
}
FeldBedeutung
SchlüsselName des Befehls in Großbuchstaben. SETNAME und GETNAME sind die Befehle für Aktionen mit "method": "set" bzw. "get" und "property": "NAME"
sequenceWas gesendet wird, siehe unten
parameterCountZahl der \# in Sequenz und Body
parameterBedingung und Format für den mitgeschickten Wert, siehe unten
timeoutErsetzt SERVERTIMEOUT_IN_MS für diesen Befehl (ms). 0: senden und die Verbindung sofort schließen. NONE: die Verbindung nach diesem Befehl offen halten
spacingErsetzt SPACING für diesen Befehl (ms)
tagOrdnet Antworten auf diesen Befehl bestimmten Antwortmustern zu, siehe Tags
httpMethod, contentType, bodyNur HTTP(S), siehe HTTP

Sequenz ​

  • ASCII: Text. Steuerzeichen und beliebige Bytes schreiben Sie als \x0D (Wagenrücklauf), \x0A (Zeilenvorschub) usw. Ein Semikolon als \x3B.
  • HEX: Nur Hexziffern, zwei je Byte, ohne Leerzeichen, z. B. 000000000006010400000020.
  • HTTP(S): Pfad mit Abfrage, z. B. /api/status?filter=car. Schreiben Sie Zeichen so, wie sie gemeint sind: Der Controller kodiert die Adresse selbst, ein vorkodiertes %20 würde zu %2520.

\# ist der Platz für den Wert, mit dem der Befehl aufgerufen wird. Mehrere Werte werden durch Komma getrennt übergeben und füllen die Plätze der Reihe nach. Fehlt der Wert ganz, sendet der Controller nichts und meldet einen Fehler.

Im HEX-Modus wird ein Wert ohne Format als genau ein Byte eingesetzt (5 → 05, -1 → FF). Für größere Werte ein Format wie {%hex4} angeben (zwei Bytes).

Parameter ​

parameter hat die Form Bedingung{%Format}, beides ist optional:

  • Das Format wird auf den Wert angewandt, bevor er eingesetzt wird. Beispiel: "sequence": "MV\#", "parameter": "{%+100,%c2,2}" macht aus 5 den Text MV05 (5 + 100 = 105, davon zwei Zeichen ab der zweiten Stelle). Alle Filter stehen unter Formatfilter.
  • Die Bedingung prüft den Wert, z. B. >=0 oder <>99. Ist sie nicht erfüllt, sendet der Controller nichts.

HTTP ​

  • Die Adresse ist http:// bzw. https://, dann SERVERIP, dann die Sequenz; der Port kommt aus SERVERPORT.
  • httpMethod: GET (Standard), POST, PUT, PATCH, DELETE. Für alles außer GET können body und contentType angegeben werden; ohne contentType erkennt der Controller JSON ({, [), XML (<) oder sonst ein Formular. \# im Body nimmt Werte auf, nachdem die Plätze der Sequenz gefüllt sind.
json
"SETMODE": {"sequence": "/api/mode", "httpMethod": "POST",
	"contentType": "application/json", "body": "{\"mode\": \\#}", "parameterCount": 1}
  • Ein GET gilt nur als erfolgreich, wenn das Gerät mit 200 und Inhalt antwortet. Andere Methoden gelten bei jeder Antwort 2xx als erfolgreich.
  • Die Antwort läuft als Text durch die Antwortmuster.
  • Anmeldung: nur Basic (USERNAME, PASSWORD). Bei HTTPS wird das Zertifikat nicht geprüft; selbst signierte Zertifikate funktionieren also.
  • Die Zeitgrenze einer Anfrage ist SERVERTIMEOUT_IN_MS; timeout am Befehl wirkt bei HTTP nicht.

Antwortmuster ​

json
"mappings": {
	"CAR": {"match": "\"car\":\\*,", "onChange": true},
	"WH": {"match": "\"wh\":\\*,", "onChange": true, "condition": "{%/1000.00}"},
	"GRID": {"match": "000000000043010440\\!48!\\^^^^^^^^", "onChange": true,
		"condition": "{%swap32,%float,%*-1}", "tag": "instant"}
}
FeldBedeutung
SchlüsselName des Werts, z. B. CAR. Rückmeldungen des Profils holen den Wert mit "property": "CAR" ab.
matchMuster, siehe unten. Groß-/Kleinschreibung spielt keine Rolle
conditionBedingung und Format, wie beim Parameter eines Befehls. Zuerst wird formatiert, dann geprüft. Ist die Bedingung nicht erfüllt, wird der Wert nicht übernommen
onChangetrue: localAction nur ausführen, wenn sich der Wert geändert hat. Der Wert selbst wird immer weitergegeben
localActionOptional: Befehl, der bei einem Treffer ausgeführt wird; \# steht für den Wert. Siehe Aktion und Befehle
tagSiehe Tags

Muster ​

Ein Muster ist Text (bei HEX: Hexziffern), in dem Platzhalter mit \ beginnen. Im JSON wird \ doppelt geschrieben: \\*.

PlatzhalterBedeutungBeispiel
\*Fängt alles bis zum Text, der danach folgtVOL=\*| auf VOL=42|MUTE=0 ergibt 42
\^Fängt genau ein Zeichen; \^^^^ fängt vierPWR\^ auf PWR1 ergibt 1
\?Überspringt genau ein Zeichen; \?? zwei01\?\?\^^ auf 0102030405 ergibt 03
\%Überspringt alles bis zum Text, der danach folgtB=\% \*X auf A=1 B=22 C=3X ergibt C=3
\!n!Überspringt n Zeichen (bei HEX zwei Zeichen je Byte)01\!4!\^^ auf 0102030405 ergibt 04

Ein Muster ohne Platzhalter prüft nur, ob der Text in der Antwort vorkommt.

Zu beachten:

  • Ein \* ganz am Ende fängt alles bis zum Ende der Antwort. Meist ist es besser, den Text dahinter anzugeben, der den Wert abschließt, etwa , oder \x0D.
  • Das letzte Feld eines JSON-Objekts endet nicht mit Komma, sondern mit }. "\"power\":\\*," findet power deshalb nicht, wenn es das letzte Feld ist; schreiben Sie dafür "\"power\":\\*}". Bei Geräten, die Felder in wechselnder Reihenfolge senden, fragen Sie besser ein Feld mehr ab, als Sie brauchen, damit kein benötigtes am Ende steht.
  • Mehrere Fangstellen in einem Muster ergeben einen Wert ohne Trennzeichen: \?\?\^^\^^ auf 0001020304 ergibt 0102.
  • Reicht ein Muster über das Ende der Antwort hinaus (\^, \? oder \!n! hinter dem letzten Zeichen), passt es nicht. Eine zu kurze Antwort liefert also keinen Wert statt eines falschen.

FULL und NORMAL ​

  • MATCHING FULL: Jedes Muster sucht in der ganzen Antwort. Für Antworten mit festem Aufbau (JSON, Modbus, Statuszeilen) die richtige Wahl.
  • NORMAL (Standard): Nach einem Treffer sehen die folgenden Muster nur noch den Rest der Antwort. Die Reihenfolge der Muster muss dann der Reihenfolge der Daten folgen.

In beiden Fällen trifft jedes Muster je Antwort höchstens einmal. Sobald es mindestens ein Muster gibt, wird alles, was keines trifft, verworfen.

Name und Wert ​

Fängt ein Muster einen Wert, gibt es NAME=wert weiter. Fängt es keinen (Muster ohne Platzhalter, oder \* bleibt leer), gibt es nur den Namen weiter. Darum tragen Muster für feste Antworten den Wert im Namen:

json
"POWER=1": {"match": "PWON\\x0D"},
"POWER=0": {"match": "PWSTANDBY\\x0D"}

Beide liefern den Wert POWER, einmal mit 1, einmal mit 0; die Rückmeldung {"property": "POWER"} bekommt beide. Der Profil Editor hängt =1 beim Speichern selbst an, wenn ein Muster keinen Platzhalter zum Fangen hat und der Name noch kein = enthält.

HEX-Antworten ​

Im HEX-Modus ist eine Antwort eine Folge von Hexziffern in Großbuchstaben. Ein gefangener Wert wird als vorzeichenlose Zahl ins Dezimale umgerechnet (00FF → 255), außer das Format beginnt mit %raw, %swap16, %swap32, %float oder %int16/%int32:

  • Vorzeichenbehaftete Register (Modbus INT16/INT32): {%int16} bzw. {%int32}.
  • Kommazahlen (FLOAT32, Byte-Reihenfolge wie bei Modbus üblich): {%swap32,%float}.

Beispiel Modbus TCP: Die Antwort auf „Lies 32 Register ab Adresse 0“ beginnt mit 000000000043010440 (Transaktion, Protokoll, Länge 0x43, Gerät 1, Funktion 4, 0x40 Bytes Daten). \!48! überspringt die ersten 24 Bytes (6 Register), \^^^^^^^^ fängt die nächsten 4 Bytes, also ein FLOAT32 ab Register 12.

Tags ​

Hat ein Befehl ein tag, werten seine Antworten nur die Muster mit demselben tag aus; Antworten auf Befehle ohne Tag nur die Muster ohne Tag. So lassen sich gleich aufgebaute Antworten auseinanderhalten, etwa zwei Modbus-Abfragen verschiedener Registerbereiche. Der Tag gilt, bis der nächste Befehl gesendet wird, auch für Meldungen, die das Gerät von sich aus schickt. Wählen Sie SPACING mindestens so lang wie die Antwortzeit des Geräts, damit eine späte Antwort nicht dem nächsten Befehl zugerechnet wird.

Berechnete Werte ​

Ein Muster mit leerem match und einer Bedingung der Form {$NAME$…} berechnet einen Wert aus anderen Werten:

json
"CHARGING": {"match": "", "onChange": true, "condition": "{$CAR$,%in2}"}

$NAME$ ist der zuletzt gelieferte Wert eines anderen Musters, mehrere lassen sich mit + - * / verknüpfen. Dahinter folgen Formatfilter. Im Beispiel ist CHARGING 1, wenn CAR den Wert 2 hat, sonst 0.

Meldungen über mehrere Pakete ​

Ohne Begrenzer wertet der Controller jedes empfangene Paket einzeln aus. Kommt eine längere Meldung in zwei TCP-Paketen, trifft ein Muster sie dann nicht. Mit ENDDELIMITER (z. B. \x0D\x0A) sammelt der Controller, bis das Ende kommt, und wertet jede Meldung einzeln aus. Die Begrenzer gehören zur Meldung und stehen auch im Muster.

Aktion und Befehle ​

Befehle an den Controller haben die Form <KLASSE><BEFEHL></KLASSE> oder, mit Wert, <KLASSE><BEFEHL=wert></KLASSE>. Mehrere Befehle einer Klasse stehen hintereinander, <KEBA_P30_1><REPORT2><REPORT3></KEBA_P30_1>, mehrere Klassen ebenso. Groß- und Kleinschreibung spielt keine Rolle. Klassen sind:

  • jede Verbindung eines CommandServer-Geräts, z. B. KEBA_P30_1, mit den Befehlen aus structure.commands,
  • SYS für Systembefehle, etwa:
BefehlWirkung
SETVAR=ID,wertSetzt die Variable ID, siehe Variablen
GETVAR=IDLiefert den Wert der Variable
WAKEONLAN=00:11:22:33:44:55Sendet ein Wake-on-LAN-Paket an diese MAC-Adresse
GETSERIALPORTLISTListet die seriellen Schnittstellen, siehe Serielle Geräte

Im Internen Dienst senden Sie solche Befehle von Hand. Die Antwort steht in der Ausgabe als parser: reply sequence: …, etwa <KEBA_P30_1>OK</KEBA_P30_1>; ein unbekannter Befehl antwortet mit NOK.

Aktion eines Antwortmusters: localAction ist ein solcher Befehl. Er wird bei jedem Treffer ausgeführt, mit onChange nur, wenn sich der Wert geändert hat. \# steht für den gefangenen Wert; fängt das Muster keinen Wert, wird eine Aktion mit \# nicht ausgeführt. Beispiele:

json
"REBOOT": {"match": "\"rbt\":\\*,", "onChange": true,
	"localAction": "<SYS><SETVAR=WALLBOX_UPTIME,\\#></SYS>"},
"TV_VOLUME": {"match": "data volume \\*\\x0D", "onChange": true,
	"localAction": "<AVR_1><VOLUME_SET=\\#></AVR_1>"}

Das erste schreibt jeden neuen Wert in eine Variable, das zweite gibt die Lautstärke eines Fernsehers an einen AV-Receiver weiter, der als eigenes CommandServer-Gerät mit der Klasse AVR_1 angelegt ist. Logik mit Bedingungen, Zeiten und mehreren Geräten gehört in Automationen; eine Aktion ist für das Weiterreichen eines Werts gedacht.

Formatfilter ​

Formate stehen in geschweiften Klammern am Ende von parameter bzw. condition, mehrere durch Komma getrennt, und wirken von links nach rechts: {%swap32,%float,%*-1}.

FilterWirkungBeispiel
%+n, %-n, %*n, %/nRechnen. Das Ergebnis hat so viele Nachkommastellen wie n4523.7 mit %/1000 → 5, mit %/1000.00 → 4.52
%int16, %int32Hex als vorzeichenbehaftete ZahlFFFF → -1
%floatHex als FLOAT32; vorher meist %swap32%swap32,%float: 43668000 → 230.500000
%swap16, %swap32Byte-Reihenfolge tauschenA1B2C3D4 → d4c3b2a1 (swap32)
%decHex als vorzeichenlose Zahl00FF → 255
%hex, %hexNGanze Zahl als Hex, mit N Stellen255 mit %hex4 → 00FF
%hex8Zahl als FLOAT32 in Hex1.5 → 3FC00000
%asciiHex als Text414243 → ABC
%in1|2|31, wenn der Wert in der Liste steht, sonst 03 mit %in2|3 → 1
%&n, %|nBitweises UND, ODER12 mit %&8 → 8
%shrN, %shlNBits verschieben256 mit %shr8 → 1
%rALT,NEUText ersetzenON mit %rON,1 → 1
%cS,LL Zeichen ab Position SHello mit %c2,3 → ell
%preTEXT, %sufTEXTText voran- bzw. anhängen
%rawHex-Wert unverändert lassen
%h, %m, %sSekunden als Zeit, z. B. {%h:%02m}3725 → 1:02

INFO

Gerechnet wird mit etwa sieben gültigen Stellen. Große Zählerstände (mehr als sieben Stellen) verlieren dadurch die letzten Ziffern; rechnen Sie sie besser in eine größere Einheit um, etwa Wh in kWh.

Eine Bedingung vor dem Format vergleicht den formatierten Wert: >0, <100, =5, >=5, <=5, <>5 (ungleich) oder einen Text, der genau gleich sein muss. Ein Text erfüllt keinen Zahlenvergleich; eine Zahl wie 0.000000 oder 00 gilt als 0.

Variablen ​

Eine Variable, die Sie unter Variablen anlegen, steht in Befehlen als [ID], mit der ID der Variable. Der Controller setzt ihren Wert ein:

WoWann
Aktionen und Befehle im Internen Dienstbei jeder Ausführung
Werte der Kommunikation (structure.config), etwa "PASSWORD": {"value": "[WALLBOX_PIN]"}wenn die Engine ihre Konfiguration lädt, also beim Start; eine geänderte Variable wirkt erst nach dem nächsten Start der Engine
Sequenzen und HTTP-Bodysbei jedem Senden, wenn RESOLVE_SYSVARS auf YES steht; sonst bleibt [ ein gewöhnliches Zeichen
Antwortmuster und Formatebei jeder Auswertung

Gibt es keine Variable mit dieser ID, bleibt [ID] als Text stehen. Mit <SYS><SETVAR=ID,wert></SYS> setzt eine Aktion eine Variable; legen Sie die Variable trotzdem unter Variablen an, denn eine Variable, die nur so entsteht, erscheint dort nicht.

Beispiel: Eine Automation setzt die Variable WALLBOX_MAX auf den erlaubten Ladestrom, die Abfrage der Wallbox schickt ihn mit:

json
"RESOLVE_SYSVARS": {"value": "YES", "editable": false}
…
"LIMIT": {"sequence": "set?ama=[WALLBOX_MAX]", "parameterCount": 0}

[ID] ist etwas anderes als die Platzhalter %NAME%: Platzhalter setzt der Controller einmal beim Anlegen des Geräts ein, Variablen zur Laufzeit.

Erreichbarkeit ​

Die Erreichbarkeit eines CommandServer-Geräts kommt aus CONNECTEVENT und DISCONNECTEVENT. Damit sie ankommt, braucht das Profil die Rückmeldung:

json
"reachable": {"method": "get", "property": "REACHABLE", "datatype": "bool", "defaultValue": false}

Ohne CONNECTEVENT/DISCONNECTEVENT gilt das Gerät immer als erreichbar. Wann die Meldungen kommen, hängt vom Protokoll ab:

ProtokollCONNECTEVENTDISCONNECTEVENT
TCPVerbindung aufgebautVerbindung beendet: Gerät schließt, Senden scheitert, Heartbeat ohne Antwort, Zeit abgelaufen
UDPBei jedem Start, auch wenn das Gerät aus istHeartbeat ohne Antwort
HTTP(S)Jede erfolgreiche AnfrageAnfrage gescheitert

Daraus folgt:

  • TCP: SERVERTIMEOUT_IN_MS auf NONE. Mit einer endlichen Zeit endet die Verbindung nach jeder Ruhepause, und das Gerät erscheint jedes Mal kurz als nicht erreichbar. Mit STARTUPCMD, HEARTBEATCMD und RECONNECT YES baut der Controller die Verbindung nach einem Abbruch selbst wieder auf.
  • UDP: Nur ein Heartbeat sagt etwas über das Gerät: HEARTBEATCMD mit einem Befehl, auf den das Gerät antwortet, und HEARTBEATTIMEOUT. CONNECTEVENT weglassen und REACHABLE=1 stattdessen aus einer Antwort ableiten, wie im Beispiel KEBA.
  • HTTP: Eine regelmäßige Abfrage prüft die Erreichbarkeit mit. Ein HTTP-Profil ohne Abfrage bekommt im Profil Editor die Abfrage „Reachable Check“ alle 30 Sekunden auf /; die Startseite des Geräts muss dafür mit 200 und Inhalt antworten. RETRYINTERVAL bei HTTP nicht setzen.
  • RETRYINTERVAL: Ist das Gerät beim Verbindungsaufbau nicht da, versucht der Controller es immer wieder, ohne DISCONNECTEVENT. Das Gerät bleibt dabei auf seinem letzten Zustand stehen.

Serielle Geräte ​

Geräte mit RS232- oder RS485-Schnittstelle schließen Sie über einen USB-Seriell-Adapter direkt am Controller an:

json
"SERVERPROTOCOL": {"value": "SERIAL", "editable": false},
"SERVERIP": {"value": "LOCAL", "editable": false},
"SERVERPORT": {"value": "/dev/ttyUSB0;9600;8;N;1;NONE", "editable": {"type": "string", "default": "/dev/ttyUSB0;9600;8;N;1;NONE"}},
"SERVERMODE": {"value": "ASCII", "editable": false},
"SERVERTIMEOUT_IN_MS": {"value": "NONE", "editable": false}

SERVERPORT hat sechs Teile, getrennt durch Semikolon: Gerät, Baudrate, Datenbits (5–8), Parität (N keine, E gerade, O ungerade), Stoppbits (1 oder 2) und Flusssteuerung (NONE, RTSCTS, DTRDSR oder XONXOFF). Statt des Geräts nimmt AUTO die erste gefundene Schnittstelle.

Welche Schnittstellen der Controller sieht, zeigt <SYS><GETSERIALPORTLIST></SYS> im Internen Dienst, etwa <SYS>GETSERIALPORTLIST=/dev/ttyUSB0|/dev/ttyUSB1|</SYS>. Gelistet werden USB-Adapter (/dev/ttyUSB…) und, sofern vorhanden, die eingebauten Schnittstellen /dev/ttyS0 und /dev/ttyS1; AUTO ist der erste Eintrag. Ein Adapter, der sich als /dev/ttyACM… meldet, fehlt in der Liste und bei AUTO, lässt sich aber mit seinem Namen eintragen.

  • Mit mehreren Adaptern: stecken Sie sie einzeln an und fragen Sie die Liste jedes Mal ab, dann wissen Sie, welcher Name zu welchem Gerät gehört.
  • Machen Sie SERVERPORT editierbar wie im Beispiel, dann trägt man Gerät und Einstellungen beim Gerät erstellen ein.

Grenzen ​

  • Sequenzen, Muster und Bedingungen: höchstens 255 Zeichen; längere werden abgeschnitten. Ein HTTP-Body darf länger sein (bis etwa 1000 Zeichen).
  • Diese Zeichen gehen in Sequenzen, Mustern und Werten nicht: Semikolon (als \x3B schreiben), Tabulator, Zeilenumbruch, /* und */. Ein Muster darf nicht mit // beginnen. Ein Wert mit einem dieser Zeichen, etwa ein Kennwort mit Semikolon, wird beim Gerät erstellen abgewiesen; die Meldung nennt die Einstellung. Ausnahme: HEARTBEATCMD und ein serieller SERVERPORT, die ihr Semikolon brauchen.
  • Klassenname: höchstens 28 Zeichen, damit die laufende Nummer noch passt; ein längerer wird abgewiesen.
  • Je Verbindung höchstens 100 wartende Befehle; was darüber hinausgeht, wird verworfen.
  • Ein Wert, der | oder = enthält, wird falsch zugeordnet. Ersetzen Sie solche Zeichen mit %r.