API – Dokumentation

Hier können Sie auf die alte API Dokumentation zugreifen, für Softwareversionen V2.7.10 und niedriger.
Wir empfehlen, den Steuerrechner auf die neueste Softwareversion zu aktualisieren und die API wie hier beschrieben zu verwenden.

Einführung

Diese API wurde entwickelt, um eine kundenspezifische Steuerung in den verschiedenen Maschinensteuerungsumgebungen zu ermöglichen. Die API bietet einen programmiertechnischen Zugang zum Auslesen des Status und zur Steuerung des Kamera-Systems.

Es stehen zwei webbasierte Kommunikationsprotokolle zur Verfügung. Zum einen ist es möglich, eine zustandslose Verbindung über den Standard HTTP Get- oder Post-Request aufzubauen und die gewünschten Daten zu empfangen oder zu steuern. Zum anderen kann über eine Websocket-Verbindung ein ereignisgesteuertes System entwickelt werden. Auf diese Weise kann die vom Kunden programmierte Software auf sich ändernde Informationen reagieren, die in Echtzeit synchronisiert werden.

  • Http API
  • WebSocket API
  • Kamera stream
  • Visual Backup
  • Variablen Beschreibung
  • Code Beispiele

Http API

Die http API ist eine RESTful API. Der Steuerrechner von Rotoclear C2 stellt in der lokalen Netzwerkumgebung den Server dar und das Programm ist der Client. Die Kommunikation zwischen Server und Client erfolgt zustandslos. Das bedeutet, dass der Server nichts über die zuletzt angeforderten Daten weiß und selbst wenn die Daten noch aktuell sind, werden sie auf Anfrage erneut gesendet.

Diese API ist ideal, um ein einfaches und kleines Steuerprogramm zu schreiben. Sie ist auch leicht zu testen. Die URL von Get Requests kann direkt im Browser in das URL-Eingabefeld eingegeben werden, oder sie kann mit postman oder curl getestet werden. Alles, was benötigt wird, ist ein http Client und ein gewisses Verständnis des http Protokolls, url Abfragen, der http Header und des JSON Formats.

Verbindung

Die http API kann über beide Webserver auf dem Steuerrechner aufgerufen werden. Im Prinzip ist der Ursprung der Verbindungs-URL derselbe, unter dem wir auch den Web-Client im Browser aufrufen können. An diesen URL-Ursprung wird der Pfad '/api' angehängt (siehe 'Beispiele für Verbindungs-URLs'). Natürlich muss der entsprechende Webserver in den Verbindungseinstellungen eingeschaltet sein (siehe http- und https-Verbindung im Menü). Diese Verbindungseinstellungen enthalten auch den Port, den wir für unsere http-Client-Verbindung benötigen. Bitte beachten Sie: Aus Sicherheitsgründen ist die https-Verbindung immer zu empfehlen.

Die API antwortet auf zwei HTTP-Methoden. Die HTTP-GET-Methode kann verwendet werden, um Anfragedetails in der URL-Abfrage festzulegen. Aus praktischen Gründen ist es auch erlaubt, Parameter in der API zu setzen (was weiter unten erklärt wird). Mit der HTTP-POST-Methode können komplexere Anfragestrukturen mit einem JSON-formatierten Inhalt abgebildet werden.

Beispiele für Verbindungs-URLs: 
    http://rotoclear.local:80/api
    https://rotoclear.local:443/api
    https://192.168.0.123:3000/api

Antwort:
    401 Unauthorized

Authentifizierung und Autorisierung

Außerdem benötigen wir noch das API-Token aus den Einstellungen. Dieser ist nach der Aktivierung des API-Moduls konfigurierbar. Das System verfügt über ein internes Berechtigungssystem, das für verschiedene Benutzer unterschiedliche Rechte vergeben kann. Mit der Aktivierung des API-Moduls wird zusätzlich zum "admin"-Benutzer ein "API-User"-Benutzer angelegt. Das in den Einstellungen eingestellte Token spiegelt das Passwort des 'API-Users' wider.

Authentifizierung über Parameter in der Url-Abfrage:

Der Benutzer und das Passwort können als ein Parameter in der URL-Abfrage angegeben werden. In diesem Fall werden die Schlüsselwörter "Token" und "Passwort" demselben Feld des Benutzers wie das Passwort zugeordnet. Wird der Benutzer nicht übergeben, wird der 'API-User' als Standard angenommen. (Beispiel: 'Authentifizierung in URL-Abfrage'). Diese Authetifizierungsvariante hat Vor- und Nachteile. Ein Nachteil ist, dass das Token in der URL-Abfrage in seiner Rohform lesbar ist. Ein Vorteil ist, dass eine Anfrage einfach als URL-Text gestellt werden kann, wie z.B. bei der GET-Anfrage durch Eingabe der url im Browser.

Verbindet sich ein http-Client nur mit diesen Informationen, so werden alle für den Benutzer zugelassenen Informationen als Antwort gesendet, da keine weiteren Informationen und Auswahlmöglichkeiten bereitgestellt werden.

Authentifizierung in URL-Abfrage: 
    http://rotoclear.local:80/api?user=API-User&token=***
    https://rotoclear.local:443/api?token=***
    https://192.168.0.123:3000/api?password=***

Curl Beispiel:
    curl -X GET -G https://rotoclear.local:443/api -d token=***

Antwort:
    200 Success. 
    With JsonObject as description of the state in body of the response.

Vereinfachtes und formatiertes Beispiel für den Textkörper der Antwort:
    {
      "oct0":"69.7°C",
      "oct1":"80.0°C",
      "light0":false,
      "light1":false,
      "hasInternet":true,
      "macAddr":"00:15:5D:7E:D9:46",
      "hostname":"rotoclear",
      "netInfo":[
        {
          "name":"eth0",
          "description":"eth0",
          "macAddress":"00:15:5D:7E:D9:46",
          "gateway":"",
          "isServer":false,
          "dhcp":true,
          "dhcpServers":[],
          "connections":[{
              "address":"172.28.32.226",
              "netmask":"255.255.240.0",
              "broadcast":"172.28.47.255"
          }],
          "dhcpSelected":true,
          "staticIp":"192.168.214.221",
          "staticMask":"255.255.255.0",
          "staticGateway":"192.168.214.1",
          "staticDns":"8.8.8.8",
          "staticUseGateway":false,
          "staticUseDns":false
        }
      ],
      "pan0":{"x":50.31323414252154,"y":49.89594172736733},
      "pan1":{"x":50,"y":50},
      "pip":0,
      "psi0":"1712mbar",
      "psi1":"1008mbar",
      "psiSetpoint":"1150mbar",
      "changeVideoName":"",
      "changeImageName":"",
      "changePostName":"",
      "record":"stop",
      "recordTime":0,
      "rtspPort":1025,
      ...
    }

Authentifizierung über Basic Authentication:

Die zweite Authentifizierungsvariante ist die Basisauthentifizierung. Zu diesem Zweck wird gemäß dem RFC7617-Standard der "Authorization"-Schlüssel im http-Header angegeben. Der Wert des Autorisierungsschlüssels setzt sich aus dem Text "Basic" und dem base64-kodierten "username:password" zusammen. Weitere Informationen sollten der Dokumentation des jeweiligen http-Clients und der verwendeten Programmiersprache entnommen werden.

Basic Authentication - Curl Beispiel:
    curl -X GET -G https://rotoclear.local:443/api \
        -u "API-User:token"

Antwort:
    200 Success. 
    With JsonObject as description of the state in body of the response.

Http Get-Methode

Nun, da die Verbindung und die Authentifizierung bei der API erfolgreich waren, können wir einige Details zu den Anfragen ausführen. Bei der Anfrage mit der http-Get-Methode können zusätzliche Parameter in die URL-Abfrage aufgenommen werden. Um nur den Zustand des Systems zu erhalten, kann das Schlüsselwort "get" verwendet werden, so dass die gewünschten Systemzustandsvariablen aufgelistet werden. Die Beschreibung der Zustandsvariablen finden Sie am Ende dieser Dokumentation (siehe: 'Variablen Beschreibung'). Alle dem Benutzer erlaubten Variablen können auf diese Weise abgefragt werden. Unbekannte oder nicht zugelassene Zustandsvariablen werden von der API ignoriert. Das bedeutet, dass diese Werte in der Antwort nicht aufgeführt werden.

Abfrage ausgewählter Zustandsvariablen - URL-Beispiel:
    https://rotoclear.local:443/api?token=***&get=[light0,record,recordTime,pan0]

Abfrage ausgewählter Zustandsvariablen - Curl Beispiel:
    curl -X GET -G https://rotoclear.local:443/api \
        -d token=*** \
        -d get=[light0,record,recordTime,pan0]
    
Antwort:
    {
      "light0": true,
      "record": "stop",
      "recordTime": 0,
      "pan0": {
        "x": 50.26041666666666,
        "y": 50.0
      }
    }

Die Get-Methode kann auch verwendet werden, um Werte im Systemstatus zu setzen. Bitte beachten Sie, dass komplexe und verschachtelte Strukturvariablen nicht ohne weiteres in einer Abfrage abgebildet werden können, so dass sie mit einer GET-Anfrage nicht funktionieren. Um eine Variable zu setzen, müssen Sie einfach ihren Schlüssel mit dem Wert in der Abfrage abgleichen. Da in der Abfrage die Variablen nur in Form von Text geschrieben werden, werden diese Variablen intern in die entsprechenden Datentypen umgewandelt. Das heißt "true" oder "false" wird zu einem JSON boolean, ausgeschriebene Zahlen werden in die entsprechenden JSON-Zahlen als Integer- oder Float-Zahl umgewandelt und gesättigt. Darüber hinaus werden die Werte validiert und in einem gültigen und definierten Bereich abgefangen. Nach dem Setzen der Variablen werden die aktualisierten Zustandsvariablen in der Antwort auf die Anfrage aufgelistet.

Statusvariablen setzen - Beispiel URL:
    https://rotoclear.local:443/api?token=***&light0=true&record=start

Statusvariablen setzen - Beispiel Curl:
    curl -X GET -G https://rotoclear.local:443/api \
        -d token=*** \
        -d light0=true \
        -d record=start

Antwort:
    {
      "light0": true,
      "record": "stop",
    }
Das System könnte mit einem "record": "stop" reagieren, wenn z.B. kein Speichermedium für die Aufzeichnung ausgewählt wurde.

Http Post-Methode

Es gibt auch einige etwas komplexere Datentypen im Systemstatus. Dazu gehören z. B. Netzwerk, Zeit, Stream-Pan-Einstellungen usw. Wenn Sie diese komplexeren Datentypen einstellen möchten, können Sie die http-Post-Methode verwenden. Dazu werden die Einstellungen in einem JSON-formatierten Paket an die Anfrage übergeben.

Pan für den ersten Kamerakopf einstellen - Post Request mit einem JSON Body:
    curl -X POST https://rotoclear.local:443/api \
      -u "API-User:***" \
      -H "Content-Type: application/json" \
      -d '{"pan0": {"x": -10.5, "y": -10}, "zoom0": 20000}'

Antwort:
      {
        "pan0": {
          "x": 39.5,
          "y": 40.0
        },
        "zoom0": 20000
      }
Während die Steuerung der Kameraköpfe, d.h. das Pan und der Zoom 
relativ zum aktuellen Wert berechnet werden, ist der Rückgabewert der API 
immer der absolute Wert, der gerade eingestellt ist.

Der Einfachheit halber können die Werte auch über die post-Methode abgefragt werden. Dazu muss der get-Schlüssel mit einem Array von Schlüsseln in String-Form abgeglichen werden.

Weiterhin ist zu erwähnen, dass mit einer Anfrage gleichzeitig state getter und setter gesendet werden können. In der Regel werden diese in der geschriebenen Reihenfolge ausgeführt. Dasselbe gilt für die get-Anfragen, bei denen die Reihenfolge der Abfrageparameter berücksichtigt wird.

Abfragezustand - Post Request mit einem JSON Body:
    curl -X POST https://rotoclear.local:443/api \
      -u "API-User:***" \
      -H "Content-Type: application/json" \
      -d '{"get": ["light0","record","recordTime","pan0"]}'

Antwort:
    {
      "light0": true,
      "record": "stop",
      "recordTime": 0,
      "pan0": {
        "x": 50.26041666666666,
        "y": 50.0
      }
    }

WebSocket API

Die Websocket API ist für die Programmierung eines ereignisbasierten Systems geeignet. Die API basiert, wie der Name schon sagt, auf dem erweiterten http API Protokoll namens Websocket. Mit einem Websocket kann eine permanente Verbindung aufgebaut werden. Um die Kommunikation über den Websocket mit der API zu verstehen, müssen wir die folgenden Punkte beachten.

1. Kommunikationsdaten und -format:
Die API kommuniziert wie die http API intern mit JSON-formatierten Daten (es gibt einige interne Ausnahmen, die aber bei normaler Verwendung nie auftreten sollten). Das bedeutet, dass eingehende Nachrichten an den Websocket-Client "immer" JSON-Objekte sind. In diesen Objekten können eine oder mehrere Zustandsvariablen des Systems aufgeführt werden. Dies bedeutet auch, dass der Websocket-Client seine Kontrollnachrichten ebenfalls im JSON-Format senden muss.

2. Abonnement:
Wenn eine Verbindung mit der API hergestellt und autorisiert wird, werden alle Variablen des Systems, für die der Benutzer autorisiert ist, automatisch abonniert. Das bedeutet, dass erstens alle diese Variablen in JSON verpackt und als Ausgangszustand an den Client gesendet werden und zweitens bei jeder Änderung des Zustands die entsprechenden Variablen erneut in Echtzeit an den Client gesendet werden. Auf diese Weise kann ein System aufgebaut werden, das in Echtzeit mit dem Steuerrechner synchronisiert ist.

3. Kontrolle:
Es ist auch möglich, dass der Websocket-Client am Zustand des Systems teilnimmt. Wie bei der http-Post-Anfrage kann der Websocket JSON-formatierte Nachrichten senden. Diese werden in Echtzeit ausgewertet und gesetzt. Dabei ist der Datentyp sowie die Schreibberechtigung für die Variablen zu beachten. Beachten Sie hierzu die Statustabelle am Ende des Dokuments.

Verbindung

Die Websocket-Verbindungen befinden sich an denselben Endpunkten wie die http API-Verbindungen. Auch hier sind beide Webserver (http- und https-Webserver) für diese Verbindung zugänglich. Wir müssen nur beachten, dass "ws" als Protokoll anstelle von "http" geschrieben werden muss.

Weitere Informationen zu Websocket-Verbindungen finden Sie in der Dokumentation des Websockets und der jeweiligen Entwicklungsprogrammiersprache Ihres Client-Systems.

Beispiele für Verbindungs-URLs: 
    ws://rotoclear.local:80/api
    wss://rotoclear.local:443/api
    wss://192.168.0.123:3000/api

In Javascript:

const socket = new WebSocket("wss://rotoclear.local:443/api");

Antwort:
    401 Unauthorized

Authentifizierung und Autorisierung

Zur Authentifizierung und Autorisierung der Verbindung müssen der Token und der Benutzer in der url-Abfrage angegeben werden. Siehe auch die Authentifizierung der http API im Abschnitt: Authentifizierung in URL-Abfrage.

Herstellen einer Verbindung mit der WebSocket-API in Javascript:

const token = "***"; // query conform encoding should be considered here
const socket = new WebSocket("wss://rotoclear.local:443/api?token=" + token);

// add callbacks
socket.onerror = function(error){ console.error(error); };
socket.onmessage = function(evt) { 
  if (typeof evt.data === "string") {  
    var jsonMsg = JSON.parse(evt.data);
    console.debug(jsonMsg);
    // The first message will represent the entire allowed state. The following ones will represent the updates.
  }
}

Beispiel

Herstellen einer Verbindung zur WebSocket-API in Nodejs:

var WebSocket = require('websocket').w3cwebsocket;

const token = "***"; // query conform encoding should be considered here
const socket = new WebSocket("wss://rotoclear.local:443/api?token=" + token);

function sendToAPI(message) {
  // stringify json message
  connection.send(JSON.stringify(message));  
}

connection.onopen = function() {
  // now we can send messages to api
  sendToAPI({ "light0": true });
};

connection.onerror = function(error) { console.error(error); };

connection.onmessage = function(evt) { 
  if (typeof evt.data === "string") {  
    var stateMsg = JSON.parse(evt.data);
    console.debug(stateMsg);

    // Use data from api to control your system
    // .... 
  } 
};

Kamera Stream

Der Kamera-Stream kann auch über die http-Anfragen verarbeitet werden. Bitte beachten Sie, dass für den Zugriff auf den Kamera-Stream eine Authentifizierung mit den entsprechenden Anmeldedaten (Benutzername und Passwort) in der http-Anfrage erforderlich ist. Zur Authentifizierung und Autorisierung siehe http API-Authentifizierung im Abschnitt: Authentifizierung in URL-Abfrage.

1. Abrufen eines JPEG-Bildes:
Ein JPEG-Bild kann durch eine http-GET-Anfrage abgerufen werden. Dazu müssen der Pfad "/camera.jpeg" und die Authentifizierung zur Verbindung hinzugefügt werden.

Bild anfordern: 
    http://rotoclear.local:80/camera.jpeg?user=admin&password=***

2. MJPEG-Streaming:
Für das Streaming von MJPEG wird der Inhaltstyp "multipart/x-mixed-replace" verwendet. Der Server sendet eine kontinuierliche Reihe von JPEG-Bildern als Antwort auf die http-Anfrage. Der Inhaltstyp jedes einzelnen Bildes wird als "Content-Type: image/jpeg" angegeben.
Der Server antwortet mit einer fortlaufenden Serie von JPEG-Bildern, die im Body der http-Antwort übertragen werden. Jedes Bild hat den Inhaltstyp "image/jpeg" und wird in einer eigenen http-Nachricht gesendet. Der Client kann den MJPEG-Stream verarbeiten, indem er jedes einzelne JPEG-Bild extrahiert und anzeigt.

MJPEG anfordern: 
    http://rotoclear.local:80/camera.mjpeg?user=admin&password=***

Visual Backup

Visual Backup ist eine Funktion zur visuellen Dokumentation von Arbeitsprozessen durch eine Reihe von Videoaufzeichnungen.
Die Länge der einzelnen Aufnahmen variiert je nach Einstellungen und Speicherkapazität.
Diese Funktion wurde entwickelt, um vergangene Vorgänge innerhalb eines bestimmten Zeitrahmens zu überprüfen.

Ein Algorithmus löscht die ältesten freigegebenen Videos, wenn die Anzahl der aufgezeichneten Videostunden überschritten wird oder die Speicherkapazität gering ist.

Im Visual Backup können Sie mit Hilfe von sogenannten "Tags" eine Beschreibung zu einem Video hinzufügen.
Diese "Tags" dienen zur Sicherung und Visualisierung bestimmter Ereignisse und stellen außerdem sicher, dass die mit "Tags" versehenen Videos nicht durch den Backup-Algorithmus gelöscht werden können.
Die "Tags" können in der Backup Galerie entfernt werden, so dass der Algorithmus die Datei wieder löschen kann.

Darüber hinaus können die Benutzer zwischen verschiedenen Speichermedien für die Sicherung und die manuelle Aufzeichnung wählen.
Es ist wichtig, bei der Medienauswahl zwischen Visual Backup und manueller Aufzeichnung zu unterscheiden.
Obwohl Sie beide Medienspeicher in der Backup Galerie anzeigen können, gelten die Schreib- und Löschalgorithmen von Visual Backup nur für den ausgewählten Backup-Medienspeicher.
Daher muss die Änderung der Speichermedien in den Einstellungen sorgfältig vorgenommen werden.

Beachten Sie außerdem die folgenden allgemeinen Bedingungen.
a. Der Löschalgorithmus wird aktiviert, wenn Visual Backup zum ersten Mal gestartet wird und wenn die Software ihre Aufzeichnungen in separate Dateien aufteilt.
b. Achten Sie beim Start von Visual Backup darauf, dass mindestens eine Stunde für die Aufzeichnung zur Verfügung steht oder durch den Algorithmus freigegeben werden kann, bevor Sie eine weitere Aufzeichnung starten.

Berechnung

Berechnung der Backup Kapazität in Schritten.

1. Scannen der Speicherkapazität

example output:
  total:  125828988928
  totalStr: 117.187 GB
  used: 65710194688
  usedStr: 61.197 GB
  free: 60118794240
  freeStr: 55.990 GB

2. Berechnung der möglichen Videozeitkapazität des Speichers

// The possible capacity is calculated based on the
// recording resolution, frames per second and quality
// as well as the free memory of the storage.

function(
  resolution,
  fps,
  quality,
  freeStorageCapacity
) → remainingBackupVideoTimeInSeconds


example:
  function(
      "HD",
      30,
      75,
      60118794240
  ) → 14313 // this is approx. 3h 58min

3. Berechnung der aufgezeichneten Backup-Kapazitätszeit

// We iterate over all noted backup files that
// can be found and deleted and add up the duration

recordedBackupCapacityInSeconds = sum(
    file.where(
      'file exists in backup storage' and 
      'can be deleted'
    )
  )

4. Berechnung der gesamten Backup-Kapazität

storageBackupCapacityInSeconds =  
    remainingBackupVideoTimeInSeconds + 
    recordedBackupCapacityInSeconds

Diesen Wert finden wir im Menü "Visual Backup" unter der Speicherverwaltung mit dem Namen 'Backup-Kapazität'. Dieser Wert sollte in der Regel größer oder gleich der Restkapazität des Speichers sein.

Variablen Beschreibung

Die folgende Tabelle beschreibt die Zustandsvariablen. Bitte beachten Sie, dass einige Einstellungen voneinander abhängig sind. Dementsprechend validiert das System die Eingaben und löst unter bestimmten Umständen Benachrichtigungen aus.

Legende

r - lesbar
w - beschreibbar
[x,y] - Intervall der gültigen Werte.

API Key Wert
Datentyp
Berechtigungen Beschreibung
cam0Exists Boolean r existence of the first camera head
cam1Exists Boolean r existence of the second camera head
cameraSwitch Boolean rw selection of the current streaming and recording camera head.
false -> first camera is selected
true -> second camera is selected
lineRateA String r data transmission rate of the first camera head
lineRateB String r data transmission rate of the second camera head
ver0 String r hardware and software version of the first camera head
ver1 String r hardware and software version of the second camera head
autoRotate0 Boolean rw automatic alignment of the first camera head
false -> first camera is selected
true -> second camera is selected
autoRotate1 Boolean rw automatic alignment of the second camera head
false -> first camera is selected
true -> second camera is selected
dictRotation0 Boolean rw first camera head disk rotation
dictRotation1 Boolean rw second camera head disk rotation
rpm0 Integer r read rotation speed setpoint of the first camera head
rpm1 Integer r read rotation speed setpoint of the second camera head
RPM0 Integer r measured rotation speed of the first camera head
RPM1 Integer r measured rotation speed of the second camera head
light0 Integer rw first camera head light
false -> disabled
true -> enabled
light1 Integer rw second camera head light
false -> disabled
true -> enabled
downstat String r state of the 'update process' working in the background
fpgaTemp String r temperature of the FPGA in the control box
exposure Boolean rw automatically aligned exposure of the picture
false -> disabled
true -> enabled
whiteBalance Boolean rw automatically white balance of the picture
false -> disabled
true -> enabled
noiseSuppression Boolean rw automatically noise suppression
false -> disabled
true -> enabled
redGain Integer [-128,127] rw red gain value
works only if whiteBalance is disabled
blueGain Integer [-128,127] rw blue gain value
works only if whiteBalance is disabled
brightness Integer [-7,7] rw brightness of the picture
works only if exposure is disabled
expo Number [0.01,1000.0] rw exposure time [in ms]
works only if exposure is disabled
gain Integer [0,42] rw gain
works only if exposure is disabled
sharpness Integer [1,15] rw sharpness of the picture
saturation Number [-7,7] rw color saturation of the picture
contrast Number [1,2.5] rw contrast of the picture
hdmiConnected Boolean r indicates whether a monitor is connected to the control box
hdmiName String r name of the monitor
cfg30 String r rate of the first optical sensor of the first camera head (dependent on the quality of the connection)
"0" ≙ no optical sensor found
"30" ≙ optical sensor with 30fps found
"60" ≙ optical sensor with 60fps found
cfg40 String r rate of the second optical sensor of the first camera head (dependent on the quality of the connection)
"0" ≙ no optical sensor found
"30" ≙ optical sensor with 30fps found
"60" ≙ optical sensor with 60fps found
cfg31 String r rate of the first optical sensor of the second camera head (dependent on the quality of the connection)
"0" ≙ no optical sensor found
"30" ≙ optical sensor with 30fps found
"60" ≙ optical sensor with 60fps found
cfg41 String r rate of the second optical sensor of the second camera head (dependent on the quality of the connection)
"0" ≙ no optical sensor found
"30" ≙ optical sensor with 30fps found
"60" ≙ optical sensor with 60fps found
oct0 String r temperature of the first camera head
oct1 String r temperature of the second camera head
cam0SelectedSensor Integer [0,1] rw selected optical sensor of the first camera head
Be careful, if your head does not have 2 optical sensors, it will mirror your image!
cam1SelectedSensor Integer [0,1] rw selected optical sensor of the second camera head
Be careful, if your head does not have 2 optical sensors, it will mirror your image!
language String rw current selected language in menu
Please note that only the selection of languages from the menu is valid.
licenseConfig Json Array r list of feature configurations in system
licenseModules Json Array r list of modules in system
hasInternet Boolean r control box has internet access
macAddr String r mac address of the first network device in hardware
hostname String r currently only read only access to hostname
netInfo Json Array r list network devices and settings
zoom0 Integer [0,31424] rw zoom of first camera head
Please note: For algorithmic reasons, a relative value is always assumed when setting the value. But the response is always the absolute value.
zoom1 Integer [0,31424] rw zoom of second camera head
Please note: For algorithmic reasons, a relative value is always assumed when setting the value. But the response is always the absolute value.
pan0 Json Object
{
  "x": Number,
  "y": Number
}
rw pan of the first camera head
Please note: For algorithmic reasons, a relative value is always assumed when setting the value. But the response is always the absolute value.
The values x and y are only valid in interval of [0.0,100.0]
pan1 Json Object
{
  "x": Number,
  "y": Number
}
rw pan of the second camera head
Please note: For algorithmic reasons, a relative value is always assumed when setting the value. But the response is always the absolute value.
The values x and y are only valid in interval of [0.0,100.0]
pip Number [0,4] rw picture in picture mode selection
0 ≙ only current camera
1 ≙ pip is top left
2 ≙ top right
3 ≙ bottom left
4 ≙ bottom right
psi0 String r sealing air of first camera head in bar
psi1 String r sealing air of second camera head in bar
psiSetpoint String r default sealing air set point in bar
changeVideoName String rw prefix of the recorded video file
changeImageName String rw prefix of the recorded image file
changePostName String rw postfix of the recorded file
changeBackupPostName String rw postfix of the recorded backup file
record String rw state of recording
options: "start", "pause", "release" or "stop"
please note: that the recording requires some conditions such as the presence of the storage medium and sufficient storage space
takePicture Boolean w trigger snapshot
recordTime Number r traced time of current video recording
rtspPort Number rw port of rtsp server
rtspOn Boolean rw rtsp server running
rtspStatus Json Object r status of rtsp server
diskStorages Json Object r list of detected usb storages
netStorages Json Object r list of setted network storages
backupStorage Json Object r selected visual backup storage description
backupStorage String w select visual backup storage with uuid (select one id in diskStorages or netStorages)
recordingStorage Json Object r selected manual recording storage description
recordingStorage String w select manual recording storage with uuid (select one id in diskStorages or netStorages)
alignmentStream0 String rw rotate stream of first camera head
"0" ≙ 0°
"1" ≙ 180°
alignmentStream1 String rw rotate stream of second camera head
"0" ≙ 0°
"1" ≙ 180°
backupResolution String rw backup recording and stream resolution
"FullHD": 1920x1080
"HD": 1280x720
recordingResolution String rw recording and stream resolution
"4K": 3840x2160
"FullHD": 1920x1080
"HD": 1280x720
recordingFps Integer rw recording and stream frames per second.
options: 1, 5, 10, 15, 30, 60
backupFps Integer rw backup recording and stream frames per second.
options: 1, 5, 10, 15, 30
recordingPictureQuality Integer [1,100] rw quality of jpeg compressor
backupPictureQuality Integer [1,100] rw quality of jpeg compressor
mjpgStreamIsOpen Boolean rw enable or disable the stream for clients without connection token
recordingWithTimeStamp Boolean rw write time into stream and recording
recordingWithDateStamp Boolean rw write date into stream and recording
backupWithTimeStamp Boolean rw write time into stream and backup recording
backupWithDateStamp Boolean rw write date into stream and backup recording
systemDescription Json Object r hardware and system description of control box
time Json Array of numbers r systems time [year,month,day,hours,minutes,seconds]
timezone String rw selected timezone
ntpHost String rw address ot the ntp server
ntpStatus Json Object r State of last connection try to ntp server
ntpSync Boolean rw enable ntp syncronization
seconds Integer r epoch time seconds
connectionUrls Json Object r list of detected and assumed possible connections
userAuthentication Json Object rw enables password authentication in clients
swVersion String r current software version
fmVersion String r current firmware version
httpOn Boolean rw http webserver run setting
httpsOn Boolean rw https webserver run setting
httpPort Integer [1,65000] rw http webserver port
httpsPort Integer [1,65000] rw https webserver port
httpStatus Json Object r http webserver status
httpsStatus Json Object r https webserver status
httpsCertificate Json Object r certificate description
backupActive Boolean rw Visual Backup recording is on/off
backupUseCompleteSpace Boolean rw enables the Visual Backup storage strategy to use the whole storage (the oldest files are deleted only when there is less than 1 hour of memory left)
backupMaximumRecordingTimeCapacity Integer rw if backupUseCompleteSpace is off, then this value is used to limit the space of stored data
backupStoredFileDuration String r describes the complete stored backup video duration, that can be found in current storages
backupFileCapacity String r describes the current overwritable stored backup video duration
backupRemainingCapacitySeconds String r describes the free space of current backup storage in video time seconds as number value
backupRemainingCapacityHours String r describes the free space of current Visual Backup storage in video time hours as number value
backupRemainingCapacity String r describes the free space of current Visual Backup storage in video time as text (example '15:35h')
storageBackupCapacity String r describes the limit of the current Visual Backup storage (backupRemainingCapacity + backupFileCapacity)
createTag Json Object
{
creationTime:
<unix seconds as number>
or
<timestamp formatted as string:
"yyyy-MM-dd'T'HH:mm:sszzz">,
title: <string>,
note: <string>,
}
w Create a tag. If currently backup is not running and not creationTime is set in the message, it starts the recording immediately. All parameters in the json request object are optional.

Code Beispiele

Diese Code Beispiele sollen den ersten Einstieg in die Verwendung unserer API erleichtern.

  • Node.js
  • C#
  • NIM
  • Python

Node.js

#!/usr/bin/env node

// Example for Nodejs - JS
//
// 1. Connect to websocket-server
// 2. Check camera 1 is connected
// 3. If camera 1 is connected toggle the light
// 4. Take a jpg image and save it as file
// 5. Close connection
//
// Install dependencies:
//   npm install websocket
//


const W3CWebSocket = require('websocket').w3cwebsocket;
const http = require('http');
const fs = require('fs');

const RotoclearIp = "192.168.178.61"
const RotoclearApiPort = "80"
const ApiToken = "1a2B3c4D5e6f7G8h"
const WebsocketApiUrlWithAuth = "ws://" + RotoclearIp + ":" + RotoclearApiPort + "/api?token=" + ApiToken
const HttpCameraImageUrlWithAuth = "http://" + RotoclearIp + ":" + RotoclearApiPort + "/camera.jpeg?user=API-User&token=" + ApiToken
const imageName = 'myNewImage.jpg'

console.log("try to establish connection to ", WebsocketApiUrlWithAuth)
var connection = new W3CWebSocket(WebsocketApiUrlWithAuth);

function sendToAPI(message) {
  // Send message to api server. Only stringified json object is accepted
  connection.send(JSON.stringify(message));
}


connection.onerror = function (err) {
  console.log('Connection error', err.toString());
};

connection.onopen = function () {
  console.log('Connection successful established');
};

connection.onclose = function (ev) {
  console.log('Client closed', ev.reason);
};

connection.onmessage = function (ev) {
  if (typeof ev.data === "string") {
    // if data is of type string, then it is json
    var api_message = JSON.parse(ev.data);

    if (api_message["cam0Exists"]) {
      if(api_message["light0"]) {
        sendToAPI({ "light0": false });
      } else {
        sendToAPI({ "jpeg": true });
      }

      http.get(HttpCameraImageUrlWithAuth, (res) => {
        let data = [];
        console.log('Status Code:', res.statusCode);
        res.on('data', (chunk) => {
          data.push(chunk);
        });
        
        res.on('end', () => {
          const imageBuffer = Buffer.concat(data);
          fs.writeFileSync(imageName, imageBuffer);

          process.exit()
        });
        
      }); 
    } else {
      console.log("No camera head detected")
      process.exit()
    }
  } 
};

C#

// Dotnet c# API Example
//
// 1. Connect to websocket-server
// 2. Check camera 1 is connected
// 3. If camera 1 is connected toggle the light
// 4. Take a jpg image and save it as file
//
// Install dotnetSDK:
//   see:  https://docs.microsoft.com/de-de/dotnet/core/install
// 
// Init project in current directory:
//   dotnet new console
// 
// copy the content to your Program.cs and replace the namespace "dotnet_websocket_api_example" with yours

using System.Text;
using System.Net.WebSockets;
using System.Text.Json;
using System.Net;

namespace dotnet_websocket_api_example
{
  class Program
  {
    const string ServerIp = "192.168.178.61";
    const int ServerPort = 80;
    const string APIToken = "1a2B3c4D5e6f7G8h";


    public static Task SendString(ClientWebSocket ws, String data)
    {
      var encoded = Encoding.UTF8.GetBytes(data);
      var buffer = new ArraySegment<Byte>(encoded, 0, encoded.Length);
      return ws.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    }

    public static async Task<String> ReadString(ClientWebSocket ws)
    {
      ArraySegment<Byte> buffer = new ArraySegment<byte>(new Byte[32000]);

      using (var ms = new MemoryStream())
      {
        while (true)
        {
          WebSocketReceiveResult result = await ws.ReceiveAsync(buffer, CancellationToken.None);
          ms.Write(buffer.ToArray(), buffer.Offset, result.Count);
          if (result.EndOfMessage) {
            break;
          }
        }

        ms.Seek(0, SeekOrigin.Begin);
        using (var reader = new StreamReader(ms, Encoding.UTF8))
        {
          return reader.ReadToEnd();
        }
      }
    }

    static async Task Main(string[] args)
    {
      // Define the cancellation token.
      using (var socket = new ClientWebSocket())
      {

        try
        {
          await socket.ConnectAsync(new Uri("ws://" + ServerIp + ":" + ServerPort + "/api?token=" + APIToken), CancellationToken.None);

          string systemStateMessage = await ReadString(socket);
          JsonDocument doc = JsonDocument.Parse(systemStateMessage);
          var systemStateJson = doc.RootElement;

          System.Console.WriteLine(systemStateJson.ToString());

          if (!systemStateJson.GetProperty("cam0Exists").GetBoolean()) {
            // toggle light
            if (systemStateJson.GetProperty("light0").GetBoolean()) 
            { 
              await SendString(socket, "{ \"light0\": false }");
            }
            else
            {
              await SendString(socket, "{ \"light0\": true }");
            }

            // # get jpeg and save it
            using (var client = new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }))
            {
                HttpResponseMessage response = await client.GetAsync("http://" + ServerIp + ":" + ServerPort + "/camera.jpeg?user=API-User&token=" + APIToken);
                var jpgBytes = await response.Content.ReadAsByteArrayAsync();
                File.WriteAllBytes("streamImage.jpg", jpgBytes);
            }
          }
          else
          {
            System.Console.WriteLine("No camera head detected");
          }
        }
        catch (Exception ex)
        {
          Console.WriteLine($"ERROR - {ex.Message}");
        }
      }
    }
  }
}

NIM

# Example in NIM - Control light via websocket api
#
# 1. Connect to websocket-server
# 2. Check camera 1 is connected
# 3. If camera 1 is connected then toggle the light
# 4. Take a jpg image and save it as file
# 5. Close connection
#
# Install dependencies:
#   nimble install ws
#

import std/[
    strformat,
    strutils,
    json,
    asyncdispatch,
    httpclient
  ]
import ws

const
  rotoclearIp = "192.168.178.61" 
  rotoclearApiPort = "80" 
  apiToken = "1a2B3c4D5e6f7G8h"
  wsUrlWithAuthInQuery = fmt("ws://{rotoclearIp}:{rotoclearApiPort}/api?token={apiToken}")
  streamImageUrlWithAuthInQuery = fmt("http://{rotoclearIp}:{rotoclearApiPort}/camera.jpeg?user=API-User&token={apiToken}")


proc runProcess() {.async.} = 
  # create connection
  let conn = await newWebSocket(wsUrlWithAuthInQuery)

  let
    # after a successful authentication the response will be the whole state
    response = await conn.receiveStrPacket()
    currentStateJson = parseJson(response)

  # print state in console
  echo currentStateJson.pretty

  if currentStateJson.hasKey("cam0Exists"): 
    if currentStateJson["cam0Exists"].getBool():
      if currentStateJson["light0"].getBool(): 
        let message = %*{ "light0": false }
        await conn.send($message)
      else:
        let message = %*{ "light0": true }
        await conn.send($message)
      
      # get jpeg and save it
      let
        client = newHttpClient()
        response = client.getContent(streamImageUrlWithAuthInQuery)

      writeFile("currentImage.jpeg", response)
    else:
      echo "No camera head detected"
  conn.close()

waitFor runProcess()
# Example in NIM - Use http api to get and set data
#
# 1. Connect to websocket-server
# 2. Fetch some information from the system (eg. light0, record, recordTime, pan0)
# 3. Disable light and move pan cursor from current position via post request
# 

import std/[strformat, json, httpclient]

const
  rotoclearIp = "192.168.178.61" 
  rotoclearApiPort = "80" 
  apiToken = "1a2B3c4D5e6f7G8h"
  urlWithAuthInQuery = fmt("http://{rotoclearIp}:{rotoclearApiPort}/api?token={apiToken}")

let
  client = newHttpClient()
  response = client.getContent(urlWithAuthInQuery & "&get=[light0,record,recordTime,pan0]")
  jsonResponse = response.parseJson()

echo jsonResponse.pretty()

# disable light and move pan cursor from current position via post request
let
  message = %*{ 
    "light0": false,
    "pan0": { # relative values
      "x": -20.0, 
      "y": -30.0
    }
  }

echo client.postContent(urlWithAuthInQuery, $message)

Python3

#!/usr/bin/python3

# Example in Python3
#
# 1. Connect to websocket-server
# 2. Check camera 1 is connected
# 3. If camera 1 is connected then toggle the light
# 4. Take a jpg image and save it as file
# 5. Close connection
#
# Install dependencies:
#   pip install websocket-client
#   pip install requests
#   pip install json
#

from websocket import create_connection
import requests
import json

ROTO_CLEAR_IP = "192.168.178.61"
ROTO_CLEAR_PORT = "80"
MY_API_TOKEN = "1a2B3c4D5e6f7G8h"

WEBSOCKET_API_URL_WITH_AUTH = "ws://" + ROTO_CLEAR_IP + ":" + ROTO_CLEAR_PORT + "/api?token=" + MY_API_TOKEN
HTTP_CAMERA_IMAGE_URL_WITH_AUTH = "http://" + ROTO_CLEAR_IP + ":" + ROTO_CLEAR_PORT + "/camera.jpeg?user=API-User&token=" + MY_API_TOKEN

ws = create_connection(WEBSOCKET_API_URL_WITH_AUTH)

# after the connection the api response is the whole system state
response = ws.recv()
systemState = json.loads(response)

# print state in console
print(systemState)

if systemState["cam0Exists"]:
    # toggle light
    if systemState["light0"]:
        jsonText = json.dumps({"light0": False})
        ws.send(jsonText)
    else:
        jsonText = json.dumps({"light0": True})
        ws.send(jsonText)

    # get jpeg and save it
    imageResponse = requests.get(HTTP_CAMERA_IMAGE_URL_WITH_AUTH)

    f = open("myCurrentImg.jpg", "wb")
    f.write(imageResponse.content)
    f.close()
else:
    print("No camera head detected")

ws.close()
#!/usr/bin/python3

# Example in Python3 - Use http api to get and set data
#
# 1. Connect to websocket-server
# 2. Fetch some information from the system (eg. light0, record, recordTime, pan0)
# 3. Disable light and move pan cursor from current position via post request
#
# Install dependencies:
#   pip install requests
#   pip install json
#

import requests
import json

ROTO_CLEAR_IP = "192.168.178.61"
ROTO_CLEAR_PORT = "80"
MY_API_TOKEN = "1a2B3c4D5e6f7G8h"
HTTP_API_URL_WITH_AUTH = "http://" + ROTO_CLEAR_IP + ":" + ROTO_CLEAR_PORT + "/api?user=API-User&token=" + MY_API_TOKEN

response = requests.get(HTTP_API_URL_WITH_AUTH + 
                            "&get=[light0,record,recordTime,pan0]")
jsonResponse = json.loads(response.content)

print(jsonResponse)

# disable light and move pan cursor from current position via post request
message = json.dumps({ 
    "light0": False,
    "pan0": { # relative values
        "x": -20.0, 
        "y": -30.0
    }
})

response = requests.post(HTTP_API_URL_WITH_AUTH, message)
print(response.content)