Rotoclear C Pro
API – Dokumentation
Einführung
Diese API wurde entwickelt, um eine individuelle Steuerung in unterschiedlichen Maschinensteuerungsumgebungen zu ermöglichen. Sie bietet einen programmgesteuerten Zugriff zum Auslesen des Systemzustands und zur Steuerung des Kamerasystems.
Es stehen zwei webbasierte Kommunikationsprotokolle zur Verfügung. Zum einen lässt sich über standardmäßige HTTP-GET- oder HTTP-POST-Anfragen eine zustandslose Verbindung aufbauen, um die gewünschten Daten abzurufen oder zu setzen. Zum anderen kann über eine WebSocket-Verbindung ein ereignisgesteuertes System entwickelt werden. So kann kundenspezifische Software auf Änderungen reagieren, die in Echtzeit synchronisiert werden.
Http API
Die HTTP-API ist eine RESTful-API. Der Steuerrechner des Rotoclear C Pro fungiert im lokalen Netzwerk als Server, das aufrufende Programm als Client. Die Kommunikation zwischen Server und Client erfolgt zustandslos. Das bedeutet, dass der Server keine Informationen über zuletzt angeforderte Daten vorhält. Auch unveränderte Daten werden bei einer erneuten Anfrage nochmals gesendet.
Diese API eignet sich besonders für einfache, kompakte Steuerprogramme und lässt sich leicht testen. Die URL einer GET-Anfrage kann direkt in die Adresszeile des Browsers eingegeben oder mit Postman beziehungsweise curl getestet werden. Benötigt werden lediglich ein HTTP-Client sowie grundlegende Kenntnisse des HTTP-Protokolls, von URL-Abfrageparametern, HTTP-Headern und dem JSON-Format.
Verbindung
Die HTTP-API ist über beide Webserver vom Steuerrechner erreichbar. Die Basisadresse der Verbindungs-URL entspricht grundsätzlich der Adresse, über die auch der Webclient im Browser aufgerufen wird. An diese Basisadresse wird der Pfad '/api' angehängt (siehe „Beispiele für Verbindungs-URLs“). Der jeweilige Webserver muss in den Verbindungseinstellungen aktiviert sein (siehe HTTP- und HTTPS-Verbindung im Menü). Dort ist auch der Port angegeben, der für die Verbindung des HTTP-Clients benötigt wird. Bitte beachten: Aus Sicherheitsgründen wird grundsätzlich eine HTTPS-Verbindung empfohlen.
Die API unterstützt zwei HTTP-Methoden. Bei HTTP GET werden die Anfragedetails als URL-Abfrageparameter übergeben. Aus praktischen Gründen können damit auch Parameter der API gesetzt werden; dies wird weiter unten erläutert. Mit HTTP POST lassen sich komplexere Anfragestrukturen über einen JSON-formatierten Anfrageinhalt übertragen.
Beispiele für Verbindungs-URLs:
http://rotoclear-cam.local:80/api
https://rotoclear-cam.local:443/api
https://192.168.0.123:3000/api
Antwort:
401 Unauthorized
Authentifizierung und Autorisierung
Zusätzlich wird das API-Token aus den Einstellungen benötigt. Es kann nach der Aktivierung des API-Moduls konfiguriert werden. Das System verfügt über eine interne Rechteverwaltung, mit der verschiedenen Benutzern unterschiedliche Berechtigungen zugewiesen werden können. Bei der Aktivierung des API-Moduls wird neben dem Benutzer 'admin' ein Benutzer 'API-User' angelegt. Das in den Einstellungen hinterlegte Token entspricht dem Passwort des Benutzers 'API-User'.
Authentifizierung über URL-Abfrageparameter:
Benutzername und Passwort können jeweils als URL-Abfrageparameter übergeben werden. Dabei werden die Schlüssel 'token' und 'password' demselben Passwortfeld des Benutzers zugeordnet. Wird kein Benutzer angegeben, wird standardmäßig 'API-User' verwendet (siehe „Authentifizierung in der URL-Abfrage“). Diese Variante hat Vor- und Nachteile: Ein Nachteil ist, dass das Token im Klartext in der URL-Abfrage lesbar ist. Ein Vorteil ist, dass eine Anfrage einfach als URL ausgeführt werden kann, beispielsweise durch Eingabe einer GET-Anfrage in den Browser.
Verbindet sich ein HTTP-Client ausschließlich mit diesen Angaben, werden alle für den Benutzer freigegebenen Informationen als Antwort gesendet, da keine weitere Auswahl angegeben wurde.
Authentifizierung in der URL-Abfrage:
http://rotoclear-cam.local:80/api?user=API-User&token=***
https://rotoclear-cam.local:443/api?token=***
https://192.168.0.123:3000/api?password=***
curl-Beispiel:
curl -X GET -G https://rotoclear-cam.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 Antwortinhalt:
{
"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 Basic Authentication. Dazu wird gemäß RFC 7617 der Schlüssel 'Authorization' im HTTP-Header angegeben. Sein Wert besteht aus dem Text „Basic “ und der Base64-kodierten Zeichenfolge 'username:password'. Weitere Informationen finden sich in der Dokumentation des verwendeten HTTP-Clients und der jeweiligen Programmiersprache.
Basic Authentication – curl-Beispiel:
curl -X GET -G https://rotoclear-cam.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
Nach erfolgreichem Verbindungsaufbau und erfolgreicher Authentifizierung können die Anfragen genauer spezifiziert werden. Bei HTTP GET lassen sich zusätzliche URL-Abfrageparameter ergänzen. Über den Schlüssel 'get' können gezielt die gewünschten Zustandsvariablen des Systems aufgelistet werden. Ihre Beschreibung befindet sich im Abschnitt „Beschreibung der Zustandsvariablen“. Auf diese Weise lassen sich alle Variablen abfragen, für die der Benutzer berechtigt ist. Unbekannte oder nicht freigegebene Zustandsvariablen ignoriert die API; sie werden in der Antwort nicht aufgeführt.
Ausgewählte Zustandsvariablen abfragen – URL-Beispiel:
https://rotoclear-cam.local:443/api?token=***&get=[light0,record,recordTime,pan0]
Ausgewählte Zustandsvariablen abfragen – curl-Beispiel:
curl -X GET -G https://rotoclear-cam.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
}
}
Mit der GET-Methode können auch Werte des Systemzustands gesetzt werden. Komplexe und verschachtelte Datenstrukturen lassen sich jedoch nicht ohne Weiteres als URL-Abfrageparameter abbilden und können deshalb nicht auf diesem Weg gesetzt werden. Zum Setzen einer Variablen wird ihr Schlüssel dem gewünschten Wert in der URL-Abfrage zugeordnet. Da die Werte dort als Text vorliegen, wandelt das System sie intern in die jeweiligen Datentypen um: Aus „true“ beziehungsweise „false“ werden boolesche JSON-Werte, numerische Angaben werden in JSON-Zahlen als Ganzzahl oder Gleitkommazahl umgewandelt und bei Bedarf auf die zulässigen Grenzen begrenzt. Zusätzlich werden die Werte geprüft und auf den definierten gültigen Bereich beschränkt. Nach dem Setzen werden die aktualisierten Zustandsvariablen in der Antwort aufgeführt.
Zustandsvariablen setzen – URL-Beispiel:
https://rotoclear-cam.local:443/api?token=***&light0=true&record=start
Zustandsvariablen setzen – curl-Beispiel:
curl -X GET -G https://rotoclear-cam.local:443/api \
-d token=*** \
-d light0=true \
-d record=start
Antwort:
{
"light0": true,
"record": "stop",
}
Das System könnte beispielsweise mit „"record": "stop"“ antworten,
wenn kein Speichermedium für die Aufnahme ausgewählt wurde.
HTTP-POST-Methode
Zum Systemzustand gehören auch komplexere Datentypen, etwa für Netzwerk, Uhrzeit oder die Verschiebung des Stream-Bildausschnitts. Zum Setzen dieser Daten kann HTTP POST verwendet werden. Die Einstellungen werden dazu im JSON-Format im Anfrageinhalt (Body) übergeben.
Bildausschnitt des ersten Kamerakopfs verschieben – POST-Anfrage mit JSON-Inhalt:
curl -X POST https://rotoclear-cam.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
}
Bei der Steuerung der Kameraköpfe werden die Verschiebung des Bildausschnitts (Pan) und der
Zoom relativ zum aktuellen Wert berechnet. Die API gibt dagegen immer den
aktuell eingestellten absoluten Wert zurück.
Der Einfachheit halber können Werte auch über POST abgefragt werden. Dazu wird dem Schlüssel get ein Array mit den gewünschten Schlüsseln als Zeichenfolgen zugeordnet.
Innerhalb einer Anfrage können sowohl Lese- als auch Schreibzugriffe auf den Systemzustand übermittelt werden. Üblicherweise werden sie in der angegebenen Reihenfolge ausgeführt. Dies gilt auch für GET-Anfragen, bei denen die Reihenfolge der URL-Abfrageparameter berücksichtigt wird.
Systemzustand abfragen – POST-Anfrage mit JSON-Inhalt:
curl -X POST https://rotoclear-cam.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
}
}
Tag export (CSV)
Gibt die Tags als CSV-Datei zum Herunterladen zurück; mit format=tsv ist auch TSV möglich. Verwenden Sie für umfangreiche Auswahlen POST, da die Länge der Anfragezeile auf 8 KB begrenzt ist. Titel und Kategorien von KI-Tags werden so exportiert, wie sie gespeichert sind, also als Übersetzungsschlüssel (siehe „KI-Modul“).
Alle Tags eines Zeitraums exportieren:
http://rotoclear-cam.local:80/export-tags-csv?timestampStartMs=<ms>×tampEndMs=<ms>&user=API-User&token=***
Ausgewählte Tags exportieren (optional als TSV):
http://rotoclear-cam.local:80/export-tags-csv?ids=1,2,3&format=tsv&user=API-User&token=***
Umfangreiche Auswahlen:
POST http://rotoclear-cam.local:80/export-tags-csv?user=API-User&token=***
Body: {"ids": [1, 2, 3, ...]}
WebSocket-API
Die WebSocket-API eignet sich für die Entwicklung ereignisgesteuerter Systeme. Sie basiert auf dem WebSocket-Protokoll, das den Aufbau einer dauerhaften Verbindung ermöglicht. Für die Kommunikation mit der API sind die folgenden Punkte zu beachten.
1. Kommunikationsdaten und Datenformat:
Wie die HTTP-API verwendet auch die WebSocket-API intern JSON-formatierte Daten. Es gibt interne Ausnahmen, die im normalen Betrieb jedoch nicht auftreten sollten. Eingehende Nachrichten beim WebSocket-Client sind daher grundsätzlich JSON-Objekte. Sie können eine oder mehrere Zustandsvariablen des Systems enthalten. Auch der Client muss seine Steuerungsnachrichten im JSON-Format senden.
2. Abonnement:
Sobald eine Verbindung zur API aufgebaut und autorisiert ist, werden automatisch alle für den Benutzer freigegebenen Zustandsvariablen abonniert. Zunächst werden sämtliche freigegebenen Variablen als JSON an den Client gesendet und bilden den Ausgangszustand. Bei jeder anschließenden Zustandsänderung werden die betroffenen Variablen erneut in Echtzeit übertragen. So lässt sich ein System aufbauen, das in Echtzeit mit dem Steuerrechner synchronisiert ist.
3. Steuerung:
Der WebSocket-Client kann den Systemzustand auch verändern. Ähnlich wie bei HTTP POST lassen sich dazu JSON-formatierte Nachrichten senden, die in Echtzeit ausgewertet und angewendet werden. Dabei müssen die Datentypen und Schreibberechtigungen der jeweiligen Variablen berücksichtigt werden. Siehe dazu die Tabelle der Zustandsvariablen.
Verbindung
WebSocket-Verbindungen verwenden dieselben Endpunkte wie die HTTP-API. Auch hier sind beide Webserver vom Steuerrechner erreichbar. Als Protokoll wird „ws“ anstelle von „http“ beziehungsweise „wss“ anstelle von „https“ verwendet.
Weitere Informationen zu WebSocket-Verbindungen finden sich in der WebSocket-Dokumentation und in der Dokumentation der für das Clientsystem verwendeten Programmiersprache.
Beispiele für Verbindungs-URLs:
ws://rotoclear-cam.local:80/api
wss://rotoclear-cam.local:443/api
wss://192.168.0.123:3000/api
In Javascript:
const socket = new WebSocket("wss://rotoclear-cam.local:443/api");
Antwort:
401 Unauthorized
Authentifizierung und Autorisierung
Für die Authentifizierung und Autorisierung der Verbindung werden Token und Benutzer als URL-Abfrageparameter angegeben. Siehe auch den Abschnitt „Authentifizierung in der URL-Abfrage“ bei der HTTP-API.
Verbindung zur WebSocket-API in JavaScript:
const token = "***"; // query conform encoding should be considered here
const socket = new WebSocket("wss://rotoclear-cam.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
Verbindung zur WebSocket-API in Node.js:
var WebSocket = require('websocket').w3cwebsocket;
const token = "***"; // query conform encoding should be considered here
const socket = new WebSocket("wss://rotoclear-cam.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
// ....
}
};
Kamerastream
Der Steuerrechner des Rotoclear C Pro stellt den Kamerastream über RTSP und HTTP bereit. Der RTSP-Stream ist über das RTSP-Protokoll erreichbar. Die Verbindungs-URL könnte beispielsweise 'rtsp://:554/stream.h264' oder 'rtsp://:554/stream.mjpg' lauten.
Der Kamerastream kann auch über HTTP-GET-Anfragen verarbeitet werden. Für den Zugriff müssen die entsprechenden Zugangsdaten (Benutzername und Passwort) in der Anfrage enthalten sein. Informationen zur Authentifizierung und Autorisierung finden sich im Abschnitt „Authentifizierung in der URL-Abfrage“ bei der HTTP-API.
Solange auf dem Steuerrechner kein Passwort gesetzt ist (Benutzerauthentifizierung deaktiviert, Zustand userAuthentication), sind alle Streams ohne Zugangsdaten erreichbar. Einen separaten Schalter dafür gibt es nicht mehr; der frühere Schlüssel streamIsOpen wurde entfernt.
11. JPEG-Bild abrufen:
Ein JPEG-Bild kann über eine HTTP-GET-Anfrage abgerufen werden. Dazu werden der Pfad '/camera.jpeg' und die Angaben zur Authentifizierung an die Verbindungsadresse angehängt.
Bild anfordern:
http://rotoclear-cam.local:80/camera.jpeg?user=API-User&token=***
2. MJPEG-Streaming:
Beim MJPEG-Streaming wird der Inhaltstyp 'multipart/x-mixed-replace' verwendet. Der Server antwortet auf die HTTP-Anfrage mit einer fortlaufenden Folge von JPEG-Bildern. Der Inhaltstyp jedes einzelnen Bildes wird als 'Content-Type: image/jpeg' angegeben.
Die JPEG-Bilder werden fortlaufend im Inhalt der HTTP-Antwort übertragen. Jedes Bild hat den Inhaltstyp 'image/jpeg' und wird in einer separaten HTTP-Nachricht gesendet. Der Client kann den MJPEG-Stream verarbeiten, indem er die einzelnen JPEG-Bilder extrahiert und anzeigt.
MJPEG anfordern:
http://rotoclear-cam.local:80/camera.mjpeg?user=API-User&token=***
3. H.264-Streaming:
Für das Streaming unverpackter H.264-Daten wird der Inhaltstyp 'multipart/x-mixed-replace' verwendet. Der Server antwortet auf die HTTP-Anfrage mit einer fortlaufenden Folge von H.264-Frames. Der Inhaltstyp jedes Frames wird als 'Content-Type: video/h264' angegeben. Wie beim MJPEG-Stream werden die Frames fortlaufend im Inhalt der HTTP-Antwort übertragen. Jeder Frame hat den Inhaltstyp 'video/h264' und wird in einer separaten HTTP-Nachricht gesendet. Der Client kann den H.264-Stream verarbeiten, indem er die einzelnen Frames extrahiert und dekodiert.
H.264-Stream anfordern:
http://rotoclear-cam.local:80/camera.h264?user=API-User&token=***
4. Streaming unverarbeiteter NV12-Daten:
Für das Streaming unverarbeiteter NV12-Daten wird der Inhaltstyp 'multipart/x-mixed-replace' verwendet. Der Server antwortet auf die HTTP-Anfrage mit einer fortlaufenden Folge von NV12-Frames. Der Inhaltstyp jedes Frames wird als 'Content-Type: video/nv12' angegeben. Wie bei MJPEG- und H.264-Streams werden die NV12-Frames fortlaufend im Inhalt der HTTP-Antwort übertragen. Jeder Frame hat den Inhaltstyp 'video/nv12' und wird in einer separaten HTTP-Nachricht gesendet. Der Client kann den NV12-Stream verarbeiten, indem er die einzelnen Frames extrahiert und dekodiert. Jeder Frame hat eine Größe von Breite × Höhe × 1,5 Byte. Breite und Höhe entsprechen den Abmessungen des Videoframes; der Standard ist 1920x1080.
NV12-Stream anfordern:
http://rotoclear-cam.local:80/camera.nv12?user=API-User&token=***
WebRTC-Stream (WHEP)
Der Live-Stream ist auch über WebRTC mit sehr geringer Latenz verfügbar. Die Sitzung wird über einfache HTTP-Anfragen gemäß WHEP ausgehandelt (WebRTC-HTTP Egress Protocol, draft-ietf-wish-whep): Der Client sendet sein SDP-Angebot, der Server antwortet mit seiner SDP-Antwort. Eine WebSocket-Verbindung wird nicht verwendet. Als Videocodec kommt H.264 zum Einsatz. Beim Streamingformat HEVC ist WebRTC nicht verfügbar; der Server antwortet mit Statuscode 415. Enthält das Angebot einen Audioabschnitt und ist das Audiomodul aktiv, wird das Mikrofonsignal in derselben Sitzung als Opus übertragen.
Die Antwort enthält bereits alle ICE-Kandidaten (Non-Trickle-Verfahren). PATCH-Anfragen für Trickle ICE werden mit Statuscode 501 beantwortet. Beenden Sie eine nicht mehr benötigte Sitzung mit DELETE, da die Anzahl gleichzeitiger Sitzungen begrenzt ist.
Statuscodes:
201 – Sitzung erstellt
400 – ungültiges SDP-Angebot
409 – der Stream startet noch; nach der in Retry-After angegebenen Zeit erneut versuchen (1 s)
415 – falscher Content-Type oder kein unterstützter Codec im Angebot (z. B. kein H.264 oder Streamingformat HEVC)
503 – Höchstzahl gleichzeitiger Sitzungen erreicht oder Stream belegt (z. B. während einer Sonderaufnahme); nach der in Retry-After angegebenen Zeit erneut versuchen (5 oder 15 s)
404 – DELETE für eine unbekannte Sitzung
Sitzung starten:
POST https://rotoclear-cam.local:443/camera.whep?user=API-User&token=***
Content-Type: application/sdp
Body: SDP offer (recvonly video, optional recvonly audio)
Antwort:
201 Created
Content-Type: application/sdp
Location: /camera.whep/<session-id>
Body: SDP answer (complete, including all ICE candidates)
Sitzung beenden:
DELETE https://rotoclear-cam.local:443/camera.whep/<session-id>?user=API-User&token=***
Audiostream
Das Mikrofonsignal des Audiomoduls ist als separater Stream verfügbar. Über HTTP wird AAC als kontinuierlicher ADTS-Stream geliefert, den gängige Wiedergabeprogramme direkt abspielen können. Über WebSocket ist die erste Nachricht ein JSON-Textframe mit der Streambeschreibung (Codec, Abtastrate, Kanäle usw.). Darauf folgt pro kodiertem Audioframe eine binäre Nachricht: rohe AAC-Frames beziehungsweise Opus-Pakete mit jeweils 20 ms. Opus ist nur über WebSocket verfügbar; eine HTTP-Anfrage an /audio.opus wird mit Statuscode 415 beantwortet.
Der Pfad /audio ohne Dateiendung liefert AAC. Es gibt eine Ausnahme: Eine WebSocket-Anfrage von Firefox erhält Opus, da Firefox unter Android AAC nicht dekodieren kann. Verwenden Sie eine explizite Dateiendung, um einen bestimmten Codec anzufordern.
Voraussetzung sind das Audiomodul und ein angeschlossenes Mikrofon (siehe Zustandsvariablen audio und availableAudioDevices).
AAC anfordern (HTTP, ADTS):
http://rotoclear-cam.local:80/audio.aac?user=API-User&token=***
AAC anfordern (WebSocket):
ws://rotoclear-cam.local:80/audio.aac?user=API-User&token=***
Opus anfordern (nur WebSocket):
ws://rotoclear-cam.local:80/audio.opus?user=API-User&token=***
Stream über WebSocket
Alternativ zu HTTP-GET-Anfragen kann der Client den Stream auch über WebSocket abrufen und die Streamdaten in Blob-Paketen empfangen.
MJPEG über WebSocket anfordern:
ws://rotoclear-cam.local:80/camera.mjpeg?user=API-User&token=***
H.264 über WebSocket anfordern:
ws://rotoclear-cam.local:80/camera.h264?user=API-User&token=***
NV12 über WebSocket anfordern:
ws://rotoclear-cam.local:80/camera.nv12?user=API-User&token=***
Beschreibung der Zustandsvariablen
Die folgende Tabelle beschreibt die Zustandsvariablen. Einige Einstellungen hängen voneinander ab. Das System prüft die Eingaben daher und löst unter bestimmten Umständen Benachrichtigungen aus.
| API-Schlüssel | Datentyp | Berechtigungen | Beschreibung |
|---|---|---|---|
| cam0Exists | Boolean | r | Vorhandensein des Streams des ersten Kamerakopfs |
| cam1Exists | Boolean | r | Vorhandensein des Streams des zweiten Kamerakopfs |
| head0Exists | Boolean | r | Vorhandensein des ersten Kamerakopfs |
| head1Exists | Boolean | r | Vorhandensein des zweiten Kamerakopfs |
| head0IsSlowMoCompatible | Boolean | r | Der erste Kamerakopf unterstützt Zeitlupenaufnahmen |
| head1IsSlowMoCompatible | Boolean | r | Der zweite Kamerakopf unterstützt Zeitlupenaufnahmen |
| cameraSwitch | Boolean | rw | Auswahl des aktuell für Streaming und Aufnahmen verwendeten Kamerakopfs. false -> erste Kamera ausgewählt true -> zweite Kamera ausgewählt |
| lineRateA | String | r | Datenübertragungsrate des ersten Kamerakopfs |
| lineRateB | String | r | Datenübertragungsrate des zweiten Kamerakopfs |
| setLineRateA | String | rw | Datenübertragungsrate der ersten Kamera einstellen. Mögliche Werte: "2Gbps", "1Gbps" |
| setLineRateB | String | rw | Datenübertragungsrate der zweiten Kamera einstellen. Mögliche Werte: "2Gbps", "1Gbps" |
| ver0 | String | r | Hardware- und Softwareversion des ersten Kamerakopfs |
| ver1 | String | r | Hardware- und Softwareversion des zweiten Kamerakopfs |
| autoRotate0 | Boolean | rw | Automatische Ausrichtung des ersten Kamerakopfs false -> Automatik deaktivieren true -> Automatik aktivieren |
| autoRotate1 | Boolean | rw | Automatische Ausrichtung des zweiten Kamerakopfs false -> Automatik deaktivieren true -> Automatik aktivieren |
| dictRotation0 | Boolean | rw | Scheibenrotation des ersten Kamerakopfs |
| dictRotation1 | Boolean | rw | Scheibenrotation des zweiten Kamerakopfs |
| rpm0 | Integer | r | Drehzahlsollwert des ersten Kamerakopfs auslesen |
| rpm1 | Integer | r | Drehzahlsollwert des zweiten Kamerakopfs auslesen |
| RPM0 | Integer | r | Gemessene Drehzahl des ersten Kamerakopfs |
| RPM1 | Integer | r | Gemessene Drehzahl des zweiten Kamerakopfs |
| light0 | Integer | rw | Beleuchtung des ersten Kamerakopfs false -> deaktiviert true -> aktiviert |
| light1 | Integer | rw | Beleuchtung des zweiten Kamerakopfs false -> deaktiviert true -> aktiviert |
| light0Dim | Boolean | r | Die Helligkeit der Beleuchtung des ersten Kamerakopfs ist einstellbar |
| light1Dim | Boolean | r | Die Helligkeit der Beleuchtung des zweiten Kamerakopfs ist einstellbar |
| light0Brightness | Integer [0,100] | rw | Helligkeit der Beleuchtung des ersten Kamerakopfs |
| light1Brightness | Integer [0,100] | rw | Helligkeit der Beleuchtung des zweiten Kamerakopfs |
| downstat | String | r | Status des im Hintergrund laufenden Update-Prozesses |
| fpgaTemp | String | r | Temperatur des FPGA in dem Steuerrechner |
| exposure | Boolean | rw | Automatische Belichtungsregelung des Bildes false -> deaktiviert true -> aktiviert |
| whiteBalance | Boolean | rw | Automatischer Weißabgleich des Bildes false -> deaktiviert true -> aktiviert |
| noiseSuppression | Boolean | rw | Automatische Rauschunterdrückung false -> deaktiviert true -> aktiviert |
| redGain | Integer [-128,127] | rw | Verstärkungswert für den Rotkanal Nur wirksam, wenn whiteBalance deaktiviert ist |
| blueGain | Integer [-128,127] | rw | Verstärkungswert für den Blaukanal Nur wirksam, wenn whiteBalance deaktiviert ist |
| brightness | Integer [-7,7] | rw | Bildhelligkeit Nur wirksam, wenn exposure deaktiviert ist |
| expo | Number [0.01,1000.0] | rw | Belichtungszeit Nur wirksam, wenn exposure deaktiviert ist |
| gain | Integer [0,42] | rw | Verstärkung Nur wirksam, wenn exposure deaktiviert ist |
| sharpness | Integer [1,15] | rw | Bildschärfe |
| saturation | Number [-7,7] | rw | Farbsättigung des Bildes |
| contrast | Number [1,2.5] | rw | Bildkontrast |
| hdmiConnected | Boolean | r | Gibt an, ob ein Monitor an den Steuerrechner angeschlossen ist |
| hdmiName | String | r | Name des Monitors |
| cfg30 | String | r | Bildrate des ersten optischen Sensors des ersten Kamerakopfs (abhängig von der Verbindungsqualität) "0" ≙ kein optischer Sensor gefunden "30" ≙ optischer Sensor mit 30fps gefunden "60" ≙ optischer Sensor mit 60fps gefunden |
| cfg40 | String | r | Bildrate des zweiten optischen Sensors des ersten Kamerakopfs (abhängig von der Verbindungsqualität) "0" ≙ kein optischer Sensor gefunden "30" ≙ optischer Sensor mit 30fps gefunden "60" ≙ optischer Sensor mit 60fps gefunden |
| cfg31 | String | r | Bildrate des ersten optischen Sensors des zweiten Kamerakopfs (abhängig von der Verbindungsqualität) "0" ≙ kein optischer Sensor gefunden "30" ≙ optischer Sensor mit 30fps gefunden "60" ≙ optischer Sensor mit 60fps gefunden |
| cfg41 | String | r | Bildrate des zweiten optischen Sensors des zweiten Kamerakopfs (abhängig von der Verbindungsqualität) "0" ≙ kein optischer Sensor gefunden "30" ≙ optischer Sensor mit 30fps gefunden "60" ≙ optischer Sensor mit 60fps gefunden |
| oct0 | String | r | Temperatur des ersten Kamerakopfs |
| oct1 | String | r | Temperatur des zweiten Kamerakopfs |
| cam0Sensor0Exists | Boolean | r | Vorhandensein des ersten optischen Sensors des ersten Kamerakopfs |
| cam0Sensor1Exists | Boolean | r | Vorhandensein des zweiten optischen Sensors des ersten Kamerakopfs |
| cam1Sensor0Exists | Boolean | r | Vorhandensein des ersten optischen Sensors des zweiten Kamerakopfs |
| cam1Sensor1Exists | Boolean | r | Vorhandensein des zweiten optischen Sensors des zweiten Kamerakopfs |
| cam0SelectedSensor | Integer [0,1] | rw | Ausgewählter optischer Sensor des ersten Kamerakopfs Achtung: Wenn der Kamerakopf nicht über 2 optische Sensoren verfügt, wird das Bild gespiegelt! |
| cam1SelectedSensor | Integer [0,1] | rw | Ausgewählter optischer Sensor des zweiten Kamerakopfs Achtung: Wenn der Kamerakopf nicht über 2 optische Sensoren verfügt, wird das Bild gespiegelt! |
| focusCam0Sensor0Exists | Boolean | r | Vorhandensein des ersten Fokussensors des ersten Kamerakopfs |
| focusCam0Sensor1Exists | Boolean | r | Vorhandensein des zweiten Fokussensors des ersten Kamerakopfs |
| focusCam1Sensor0Exists | Boolean | r | Vorhandensein des ersten Fokussensors des zweiten Kamerakopfs |
| focusCam1Sensor1Exists | Boolean | r | Vorhandensein des zweiten Fokussensors des zweiten Kamerakopfs |
| focusCam0Sensor0 | Integer [0,1023] | r | Fokuswert des ersten Fokussensors des ersten Kamerakopfs |
| focusCam0Sensor1 | Integer [0,1023] | r | Fokuswert des zweiten Fokussensors des ersten Kamerakopfs |
| focusCam1Sensor0 | Integer [0,1023] | r | Fokuswert des ersten Fokussensors des zweiten Kamerakopfs |
| focusCam1Sensor1 | Integer [0,1023] | r | Fokuswert des zweiten Fokussensors des zweiten Kamerakopfs |
| tapToFocus | {'x': Number [0.0,1.0], 'y': Number} | rw | Auf einen bestimmten relativen Punkt im Bild des aktuellen Kamerakopfs fokussieren |
| language | String | rw | Aktuell im Menü ausgewählte Sprache Bitte beachten: Es sind nur die im Menü angebotenen Sprachen zulässig. |
| licenseModules | Json Array | r | Liste der Module im System |
| hasInternet | Boolean | r | Der Steuerrechner verfügt über Internetzugang |
| macAddr | String | r | MAC-Adresse des ersten physischen Netzwerkgeräts |
| hostname | String | rw | Hostname vom Steuerrechner im Netzwerk |
| workgroup | String | rw | Arbeitsgruppe vom Steuerrechner im Netzwerk |
| netInfo | Json Array | r | Liste der Netzwerkgeräte und ihrer Einstellungen |
| zoomSettings | Json Object | r | Zoomeinstellungen der aktuellen Kamera- und Sensorkonfiguration |
| zoomState | Json Object | rw | Zoomzustand der aktuellen Kamera- und Sensorkonfiguration einstellen zoomState.left und zoomState.top sind relative Werte zwischen 0.0 und 1.0 zoomState.zoom ist der Zoomfaktor im Bereich von 1 bis 4 |
| pip | Number [0,5] | rw | Auswahl des Bild-in-Bild-Modus oder der Darstellung nebeneinander 0 ≙ nur aktuelle Kamera 1 ≙ Bild-in-Bild unten links 2 ≙ oben links 3 ≙ oben rechts 4 ≙ unten rechts 5 ≙ nebeneinander |
| psi0 | String | r | Sperrluftdruck des ersten Kamerakopfs in bar |
| psi1 | String | r | Sperrluftdruck des zweiten Kamerakopfs in bar |
| psiControlBox | String | r | Sperrluftdruck vom Steuerrechner in bar |
| psiSetpoint | String | r | Standard-Sollwert des Sperrluftdrucks in bar |
| changePostName | String | rw | Namenssuffix der Aufnahmedatei |
| changeBackupPostName | String | rw | Namenssuffix der Backup-Aufnahmedatei |
| changeVideoName | String | rw | Basisname für Videoaufnahmen. Maximal 16 Zeichen; wird automatisch bereinigt (unzulässige Zeichen werden entfernt, Leerzeichen ersetzt). Der Name "Backup" ist reserviert und wird abgelehnt. |
| changeImageName | String | rw | Basisname für Schnappschussbilder. Maximal 16 Zeichen; es gelten dieselben Bereinigungsregeln wie für 'changeVideoName'. Der Name "Backup" ist reserviert und wird abgelehnt. |
| recordingFilename | String | r | Dateiname der aktuellen oder letzten normalen Aufnahme |
| fotoFilename | String | r | Dateiname des zuletzt aufgenommenen Schnappschusses |
| backupFilename | String | r | Dateiname der aktuellen Visual-Backup-Aufnahme |
| record | String | rw | Aufnahmestatus Optionen: "start", "timelapse", "slowmotion" oder "stop" Bitte beachten: Für die Aufnahme müssen bestimmte Voraussetzungen erfüllt sein, beispielsweise ein vorhandenes Speichermedium und ausreichend freier Speicherplatz. |
| takePicture | Boolean | w | Schnappschuss auslösen |
| recordTime | Number | r | Bisherige Laufzeit der aktuellen Videoaufnahme |
| backupActive | Boolean | rw | Visual-Backup-Aufnahme aktivieren oder deaktivieren. Visual Backup zeichnet parallel zur normalen Aufnahme kontinuierlich auf einem separaten Backup-Speicher auf (siehe 'backupStorage'). Sobald die konfigurierte Kapazität erreicht ist (siehe 'backupNumberOfSavedHours'), werden die ältesten Daten automatisch überschrieben. false -> deaktiviert true -> aktiviert Bitte beachten: Ein Backup-Speicher muss konfiguriert sein. Unter bestimmten Bedingungen kann das System diesen Wert automatisch auf false zurücksetzen (z. B. wenn keine Backup-Kapazität mehr verfügbar ist). |
| backupNumberOfSavedHours | Integer | rw | Maximale Dauer (in Stunden) der Visual-Backup-Aufnahmen, die auf dem Backup-Speicher aufbewahrt werden. Sobald diese Grenze erreicht ist, werden die ältesten Aufnahmen überschrieben. Mindestens 1 Stunde, Standardwert 12 |
| backupNumberOfSavedHoursSet | Integer | r | Vom System tatsächlich angewendete maximale Backup-Dauer (in Stunden). Kann niedriger als 'backupNumberOfSavedHours' sein, wenn der Backup-Speicher die angeforderte Dauer nicht aufnehmen kann. |
| backupUseCompleteSpace | Boolean | rw | Den gesamten freien Speicherplatz des Backup-Speichers für Visual Backup verwenden, anstatt die Dauer auf 'backupNumberOfSavedHours' zu begrenzen. false -> auf die konfigurierten Stunden begrenzen (Standard) true -> gesamten verfügbaren Speicherplatz verwenden |
| backupRemainingCapacitySeconds | Integer | r | Verbleibende Aufnahmekapazität für Visual Backup in Sekunden |
| backupAudioActive | Boolean | rw | Tonspur in der Visual-Backup-Aufnahme aufzeichnen (Audiomodul erforderlich). false -> deaktiviert true -> aktiviert (Standard) |
| audio | Json Object | rw | Beschreibung des angeschlossenen Mikrofons (Audiomodul erforderlich); leeres Objekt, wenn kein Mikrofon oder keine Lizenz vorhanden ist. Struktur: {name: String, device: String, path: String, settings: [Objects], selected: Number} Den Index eines Eintrags in settings (Number) schreiben, um die Abtastrate und Kanaleinstellung auszuwählen |
| availableAudioDevices | Json Array | r | Liste der erkannten Audioeingabegeräte |
| selectedAudioDevice | String | rw | Kennung des zu verwendenden Audioeingabegeräts (siehe availableAudioDevices) |
| selectedAudioQuality | Number | r | Index des ausgewählten Eintrags in audio.settings (-1 = Gerätestandard); wird über audio eingestellt |
| prerollSettings | Json Object | rw | Voraufzeichnung: Die letzten Sekunden vor dem Start einer Aufnahme werden in die Aufnahme einbezogen. Struktur: {enabled: Boolean, durationSec: Number [15,30]} Standard: {enabled: true, durationSec: 15} |
| prerollStatus | Json Object | r | Status des Voraufzeichnungspuffers. Struktur: {enabled: Boolean, active: Boolean, busy: Boolean, configuredSec: Number, bufferedSec: Number, bufferedBytes: Number, capacityBytes: Number, frames: Number} |
| rtspPort | Number | rw | Port des RTSP-Servers |
| rtspOn | Boolean | rw | Der RTSP-Server läuft |
| rtspStatus | Json Object | r | Status des RTSP-Servers |
| rtspUseTLS | Boolean | rw | RTSP-Stream mit TLS verschlüsseln (rtsps://). false -> rtsp:// (Standard) true -> rtsps://, verwendet das HTTPS-Zertifikat |
| rtspUseAuth | Boolean | rw | Zugangsdaten für den RTSP-Stream verlangen. true -> Zugangsdaten erforderlich (Standard) false -> jeder Client wird ohne Zugangsdaten akzeptiert Nur wirksam, wenn die Benutzerauthentifizierung aktiviert ist (ein Passwort ist gesetzt, Status userAuthentication); ohne Passwort ist der Stream ohnehin frei zugänglich Ersetzt den früheren Schlüssel rtspAuthDisabled (mit umgekehrter Bedeutung), der beim Update einmalig umgewandelt wird |
| diskStorages | Json Object | r | Liste der erkannten USB-Speicher |
| netStorages | Json Object | r | Liste der eingerichteten Netzwerkspeicher |
| recordingStorage | Json Object | r | Beschreibung des ausgewählten Speichers für manuelle Aufnahmen |
| recordingStorage | String | w | Speicher für manuelle Aufnahmen über die UUID auswählen (eine ID aus diskStorages oder netStorages auswählen) |
| backupStorage | Json Object | r | Beschreibung des ausgewählten Speichers für Backup-Aufnahmen |
| backupStorage | String | w | Speicher für Backup-Aufnahmen über die UUID auswählen (eine ID aus diskStorages oder netStorages auswählen) |
| alignmentStream0 | String | rw | Stream des ersten Kamerakopfs drehen "0" ≙ 0° "1" ≙ 180° |
| alignmentStream1 | String | rw | Stream des zweiten Kamerakopfs drehen "0" ≙ 0° "1" ≙ 180° |
| resolution | String | rw | Aufnahmeauflösung "4K": 3840x2160 "FullHD": 1920x1080 "HD": 1280x720 |
| fps | Integer | rw | Bildrate von Aufnahme und Stream in Bildern pro Sekunde Optionen: 1,5,10,15,30,60 |
| recordingFormat | String | rw | Für die Aufnahme verwendeter Videocodec. "h264" (Standard) "hevc" (Alias "h265") "mjpg" (nur für Zeitlupenaufnahmen) |
| recordingQuality | Integer [1,100] | rw | Qualität des Aufnahme-Encoders (Standardwert 75) |
| recordingMaxBitrate | Integer | rw | Maximale Aufnahmebitrate in Bits pro Sekunde (Standardwert 20000000 ≙ 20 Mbit/s) |
| recordingAudioActive | Boolean | rw | Tonspur in der normalen Aufnahme aufzeichnen (Audiomodul erforderlich). false -> deaktiviert true -> aktiviert (Standard) |
| uvc0 | Json Object | rw | Beschreibung der ersten USB-Kamera (UVC-Modul); leeres Objekt, wenn kein Gerät vorhanden ist. Stream: /uvc0.mjpg |
| uvc1 | Json Object | rw | Beschreibung der zweiten USB-Kamera (UVC-Modul); leeres Objekt, wenn kein Gerät vorhanden ist. Stream: /uvc1.mjpg |
| uvc2 | Json Object | rw | Beschreibung der dritten USB-Kamera (UVC-Modul); leeres Objekt, wenn kein Gerät vorhanden ist. Stream: /uvc2.mjpg |
| availableUvcDevices | Json Array | r | Liste der erkannten USB-Kameras |
| preferredUvc0Device | String | rw | Gerät, das als erste USB-Kamera verwendet werden soll (siehe availableUvcDevices) |
| preferredUvc1Device | String | rw | Gerät, das als zweite USB-Kamera verwendet werden soll (siehe availableUvcDevices) |
| preferredUvc2Device | String | rw | Gerät, das als dritte USB-Kamera verwendet werden soll (siehe availableUvcDevices) |
| slowmoQuality | Integer [1,100] | rw | Qualität des Encoders für Zeitlupenaufnahmen (Standardwert 85) |
| timelapseInputFps | Number | rw | Erfassungsrate (Bilder pro Sekunde) als Eingabe für eine Zeitrafferaufnahme (Standardwert 0.5) Siehe Option "timelapse" für record |
| timelapseOutputFps | Number | rw | Wiedergabebildrate (Bilder pro Sekunde) des resultierenden Zeitraffervideos (Standardwert 30) |
| fotoResolution | String | rw | Auflösung des Schnappschusses "4K": 3840x2160 "FullHD": 1920x1080 "HD": 1280x720 |
| pictureQuality | Integer [1,100] | rw | Qualität des JPEG-Kompressors |
| freeze | Boolean | rw | Stream einfrieren |
| recordingWithTimeStamp | Boolean | rw | Uhrzeit dauerhaft in die Aufnahme einblenden. Unabhängig vom Live-Stream und Visual Backup, siehe "streamingWithTimeStamp" Wird nicht auf Zeitlupenaufnahmen angewendet |
| recordingWithDateStamp | Boolean | rw | Datum dauerhaft in die Aufnahme einblenden. Unabhängig vom Live-Stream und Visual Backup, siehe "streamingWithDateStamp" Wird nicht auf Zeitlupenaufnahmen angewendet |
| recordingTimestampSetting | Json Object | rw | Position und Gestaltung des dauerhaft in die Aufnahme eingeblendeten Zeitstempels. Struktur: {x: Number, y: Number, scaleValue: Number, drawBackdrop: Boolean, backdropColor: String, textColor: String} |
| streamingBps | Number | r | Ungefähre Streaming-Bitrate in Bits pro Sekunde |
| streamingFormat | String | rw | Für den Live-Stream verwendeter Videocodec. "h264" (Standard) "hevc" (Alias "h265") |
| streamingResolution | String | rw | Auflösung des Live-Streams "4K": 3840x2160 "FullHD": 1920x1080 (Standard) "HD": 1280x720 |
| streamingFps | Integer | rw | Bildrate des Live-Streams in Bildern pro Sekunde Optionen: 1,5,10,15,24,30,60 (Standardwert 30) |
| streamingQuality | Integer [1,100] | rw | Qualität des Live-Stream-Encoders (Standardwert 75) |
| streamingBitrate | Integer | rw | Zielbitrate des Live-Streams in Bits pro Sekunde. 0 ≙ automatische / variable Bitrate (Standard) |
| streamingMaxBitrate | Integer | rw | Maximale Bitrate des Live-Streams in Bits pro Sekunde (Standardwert 20000000 ≙ 20 Mbit/s) |
| streamingWithTimeStamp | Boolean | rw | Uhrzeit dauerhaft in den Live-Stream einblenden und damit auch in Visual Backup, das den Stream-Kanal aufzeichnet. Unabhängig von der Aufnahme, siehe "recordingWithTimeStamp" |
| streamingWithDateStamp | Boolean | rw | Datum dauerhaft in den Live-Stream einblenden und damit auch in Visual Backup, das den Stream-Kanal aufzeichnet. Unabhängig von der Aufnahme, siehe "recordingWithDateStamp" |
| streamingTimestampSetting | Json Object | rw | Position und Gestaltung des dauerhaft in den Live-Stream eingeblendeten Zeitstempels. Struktur: {x: Number, y: Number, scaleValue: Number, drawBackdrop: Boolean, backdropColor: String, textColor: String} |
| systemDescription | Json Object | r | Hardware- und Systembeschreibung vom Steuerrechner |
| time | Json Array of numbers | r | Systemzeit [Jahr,Monat,Tag,Stunden,Minuten,Sekunden] |
| timezone | String | rw | Ausgewählte Zeitzone |
| ntpHost | String | rw | Adresse des NTP-Servers |
| ntpStatus | Json Object | r | Status des letzten Verbindungsversuchs zum NTP-Server |
| ntpSync | Boolean | rw | NTP-Synchronisierung aktivieren |
| seconds | Integer | r | Zeit seit der Unix-Epoche in Sekunden |
| connectionUrls | Json Object | r | Liste der erkannten und der vermutlich möglichen Verbindungen |
| swVersion | String | r | Aktuelle Softwareversion |
| fmVersion | String | r | Aktuelle Firmwareversion |
| httpOn | Boolean | rw | Betriebseinstellung des HTTP-Webservers |
| httpsOn | Boolean | rw | Betriebseinstellung des HTTPS-Webservers |
| httpPort | Integer [1,65000] | rw | Port des HTTP-Webservers |
| httpsPort | Integer [1,65000] | rw | Port des HTTPS-Webservers |
| httpStatus | Json Object | r | Status des HTTP-Webservers |
| httpsStatus | Json Object | r | Status des HTTPS-Webservers |
| httpsCertificate | Json Object | r | Beschreibung des Zertifikats |
| categories | Json Object | r | Liste der Kategorien für die Tags |
| changeTagCategory | Json Object | w | Tag-Kategorie erstellen, aktualisieren oder löschen Kategorie: { changeTagCategory: {action: String, id: String, name: String, color: String}} action: "create", "update" oder "delete" Beispiel: {changeTagCategory: {action: "create", name: "new category", color: "#ff0000"}} |
| createTag | Json Object | w | Neuen Tag erstellen Struktur { createTag: {title?: String, note?: String, category?: Name(String)|ID(Number), createdBy?: String}} |
| updateTag | Json Object | w | Tag aktualisieren Struktur {updateTag: {id: Number, title: String, note: String, category: ID(Number)}} |
| deleteTags | Array of ID's(Numbers) | w | Tags anhand ihrer IDs löschen Struktur: {deleteTags: [id1, id2, ...]} |
| records | Json Object | rw | Gefilterte Liste von Aufnahmen zurückgeben Anfragestruktur: {timestampStartMs: Number, timestampEndMs: Number} Antwortstruktur: {backup: [Objects], media: [Objects], tags: [Objects], timestampStartMs: Number, timestampEndMs: Number}]} |
KI-Modul
Das KI-Modul führt neuronale Netzwerkmodelle auf dem Steuerrechner aus (Hailo-Beschleuniger). Aus den Erkennungsergebnissen erzeugt es eine Statusampel, ein Live-Diagramm, einen Verlaufsgraphen und automatische Tags. Dafür wird das Lizenzmodul ki benötigt (siehe licenseModules). Es gibt drei Projekte mit jeweils eigenen Modellen: humandetect (bis zu 4 Modelle), spandetekt (Spanerkennung, bis zu 4 Modelle) und motiondetect. Es kann immer nur ein Projekt gleichzeitig ausgeführt werden.
Modellverwaltung
Modelle werden als .rhef-Paket hochgeladen. Dieses enthält das kompilierte Hailo-Modell (HEF) und optional eine JSON-Begleitdatei (Sidecar) mit Klassennamen, Erkennungsprofilen, Schwellenwerten für die Statusampel und Regeln für automatische Tags. Die maximale Größe beträgt 55 MB. Beide Anfragen erfordern die Berechtigung zum Ändern der Systemeinstellungen und liefern den aktualisierten Inhalt von kiModels zurück (Statuscode 200).
Statuscodes beim Hochladen: 400 – ungültiges Projekt, ungültiger Name, ungültiges Paket oder ungültiges JSON
403 – fehlende Berechtigung
409 – Modellgrenze des Projekts erreicht oder Modell bereits vorhanden
413 – Datei zu groß.
Statuscodes beim Löschen:
404 – unbekanntes Modell
409 – das Modell ist aktiv, während die KI läuft.
Modell hochladen:
POST https://rotoclear-cam.local:443/ki/models/upload?project=spandetekt&name=my_model.rhef&user=API-User&token=***
Content-Type: multipart/form-data (one part containing the .rhef file)
Modell löschen:
DELETE https://rotoclear-cam.local:443/ki/models/delete?project=spandetekt&name=my_model&user=API-User&token=***
KI-Variablen
| API-Schlüssel | Datentyp | Berechtigungen | Beschreibung |
|---|---|---|---|
| kiControl | Json Object | rw | KI starten oder stoppen und das Projekt auswählen. Struktur: {active: Boolean, project_name: "humandetect"|"spandetekt"|"motiondetect", confidence_threshold: Number, status: String, error: String} Schreibbeispiel: {kiControl: {project_name: "spandetekt", active: true}} status: "idle", "pending" oder "running"; error: Grund, warum die KI nicht läuft (z. B. "no license", "not available during recording") Während einer Sonderaufnahme (Zeitlupe, X-Aufnahme) kann die KI nicht ausgeführt werden |
| kiModels | Json Object | rw | Modelle pro Projekt. Struktur: {<project>: {models: [{name, size, uploadedAt, profiles: [String], sourceHash}], activeModel: String, limit: Number}} Nur das aktive Modell kann per Schreibzugriff geändert werden: {kiModels: {spandetekt: {activeModel: "my_model"}}} |
| kiRuntimeSettings | Json Object | rw | Laufzeiteinstellungen pro Projekt; überschreiben die Standardwerte aus der Begleitdatei des Modells (Model-Sidecar). Struktur: {<project>: {displayMode, showTool, profile, autoTag, deletable, tagRetentionDays, window, triggerTime, gap, cooldown, classes, titles, ampel}} Standardwerte: profile "balanced", autoTag false, deletable true, window 2 s, triggerTime 10 s, gap 10 s, cooldown 20 s Nur die übermittelten Schlüssel werden geändert; null setzt einen Schlüssel ({spandetekt: {window: null}}) oder das gesamte Projekt ({spandetekt: null}) auf die Standardwerte des Modells zurück |
| kiProjects | Json Object | r | Projekte, die aktuell Messwerte liefern. Struktur: {projects: [String]} |
| processAmpel | Json Object | r | Statusampel pro laufendem Projekt; wird einmal pro Sekunde anhand der Schwellenwerte des Modells ausgewertet. Struktur: {projects: {<project>: {state: "gray"|"green"|"orange"|"red"}}} "gray" = KI läuft nicht oder Modell ohne Statusampel |
| processGraph | Json Object | r | Aktuelle Erkennungsverteilung pro laufendem Projekt; wird mit jedem Messwert gesendet (etwa einmal pro Sekunde), auch bei unveränderten Werten. Struktur: {projects: {<project>: {classes: {<class name>: Number [0,1]}, frames: Number}}} Der Wert pro Klasse entspricht dem Anteil der Einzelbilder dieser Sekunde, in denen die Klasse erkannt wurde |
| kiLiveSamples | Json Object | w (query) | Rohmesswerte der letzten Sekunden, beispielsweise für ein Live-Diagramm. Anfrage: {kiLiveSamples: {project: String, seconds?: Number (bis zu 60, Standardwert 60)}} Antwort: {kiLiveSamples: {project, classes: [String], t: [ms], frames: [Number], values: [[Promille pro Messwert]]}} (values[class][sample]) |
| kiGraphProjects | Json Object | w (query) | Projekte mit gespeichertem Verlauf. Anfrage: {kiGraphProjects: {}} Antwort: {kiGraphProjects: {projects: [{name, firstMs, lastMs}]}} |
| kiGraphHistory | Json Object | w (query) | Gespeicherter Erkennungsverlauf eines Projekts, zusammengefasst in Zeitintervalle (Buckets). Erfordert einen Visual-Backup-Speicher (Aufbewahrungsdauer 90 Tage). Anfrage: {kiGraphHistory: {project: String, timestampStartMs: Number, timestampEndMs: Number, buckets?: Number}} Antwort: {kiGraphHistory: {project, timestampStartMs, timestampEndMs, t0, stepMs, count, classes: [String], frames: [..], wavg: [[..]], avg: [[..]], peak: [[..]]}} (Werte in Promille) |
| kiSample | Json Object | w | Eingabe für KI-Prozesse: Erkennungsverteilung einer Sekunde. Struktur: {kiSample: {project: String, distribution: {<class name>: Number [0,1]}, frameCount: Number}} Wird nur für das laufende Projekt akzeptiert; nur senden, wenn frameCount > 0 (keine Messwerte = KI aus) |
| scanForModel | String | w | Ein Speichergerät nach .rhef-Paketen durchsuchen und diese installieren; die Antwort führt erfolgreich installierte Dateien sowie fehlgeschlagene Installationen mit Begründung auf. Anfrage: {scanForModel: "<storage id>"} oder {scanForModel: {storage: "<storage id>"}} |
| deleteKiModel | Json Object | w | Ein Modell löschen, entspricht DELETE /ki/models/delete. Anfrage: {deleteKiModel: {project: String, name: String}} |
| reconstruction3dActive | Boolean | r | Die 3D-Rekonstruktion läuft (wird vom KI-Prozess gesetzt) |
Automatische Tags
Wenn autoTag aktiviert ist (siehe kiRuntimeSettings), erstellt die KI automatisch Tags in Visual Backup. Sobald der durchschnittliche Anteil einer Klasse – berechnet über window Sekunden – für triggerTime Sekunden oberhalb des zugehörigen Schwellenwerts bleibt, wird ein Tag geöffnet. Solange die Klasse aktiv bleibt, wird der Tag verlängert. Nach gap Sekunden unterhalb des Schwellenwerts wird er geschlossen. Anschließend wird für cooldown Sekunden kein neuer Tag derselben Klasse geöffnet. Tags werden nur erstellt, während Visual Backup aufzeichnet.
KI-Tags enthalten auto: true sowie deletable. Bei deletable: true ist das Video nicht vor der automatischen Speicherbereinigung geschützt. Kategorie und Titel werden als Übersetzungsschlüssel gespeichert: Die Kategorie lautet aiTagCategoryChip, der Titel entspricht dem Schlüssel der Klasse, beispielsweise aiSpanClassSpanstau. Web- und HDMI-Clients zeigen die übersetzten Texte an; API-Clients erhalten die Schlüssel (siehe records, categories und den Tag-Export).
GPIO-Modul
Der Steuerrechner verfügt über 4 digitale Eingänge und 4 digitale Ausgänge. Dafür wird das Lizenzmodul gpio benötigt. Ohne Lizenz werden die Pins nicht verwendet; sämtliche Einrichtungsanfragen werden mit „[error] gpio module not licensed“ beantwortet. Es gibt zwei Nutzungsarten: Zuordnungen (Bindings) verbinden einen Pin mit einem Serversignal oder einer Aktion aus einem Katalog; diese einfache Variante wird empfohlen. Aufgaben (Tasks) beschreiben Abläufe und Bedingungen im Detail und richten sich an fortgeschrittene Anwender. Anfragen werden mit einem Textergebnis beantwortet, beispielsweise {"gpioInputSetupTask": "[ok] task created/updated with id 3 ..."} oder „[error] ...“.
Bitte beachten Sie die Pin-Nummerierung: Zuordnungen verwenden pin 0..3, Aufgaben und Pin-Zustände dagegen pin1..pin4.
| API-Schlüssel | Datentyp | Berechtigungen | Beschreibung |
|---|---|---|---|
| gpioInput | Json Object | r | Aktueller Pegel der Eingänge. Struktur: {pin1: "0"|"1", pin2: .., pin3: .., pin4: ..} |
| gpioOutput | Json Object | r | Aktueller Pegel der Ausgänge; gleiche Struktur wie gpioInput"0"|"1", pin2: .., pin3: .., pin4: ..} |
Zuordnungen (Bindings)
Der Server stellt zwei selbsterklärende Kataloge bereit: gpioSources listet Signale auf, die einen Ausgang steuern können, beispielsweise laufende Aufnahme, aktives Visual Backup, Beleuchtung, Internetverbindung oder KI-Statusampel. gpioActions enthält Aktionen, die ein Eingang auslösen kann, etwa Licht ein-/ausschalten oder Aufnahme starten/stoppen. Eine Zuordnung verweist über die id auf einen Katalogeintrag. Ausgangszuordnungen werden bei jeder Änderung der Signalquelle ausgewertet. Ein Ausgangspin kann nur eine Zuordnung besitzen; eine neue ersetzt die bisherige. Eine Eingangszuordnung folgt dem Eingangspegel: High aktiviert die Aktion beziehungsweise onValue, Low deaktiviert sie beziehungsweise setzt offValue. Die Ausführung erfolgt mit den Berechtigungen des Benutzers, der die Zuordnung erstellt hat.
| API-Schlüssel | Datentyp | Berechtigungen | Beschreibung |
|---|---|---|---|
| gpioSources | Json Array | r | Katalog der Signale für Ausgänge. Eintrag: {id, label, valueType: "boolean"|"enum", states?: [{value, label}], read: {key, path?}, instance?: {label, from}} Einträge mit instance (z. B. kiAmpel) erfordern die Angabe einer Instanz, beispielsweise des KI-Projekts |
| gpioActions | Json Array | r | Katalog der Aktionen für Eingänge. Eintrag: {id, label, valueType, write: {key, onValue?, offValue?}} |
| gpioOutputBindings | Json Array | r | Konfigurierte Ausgangszuordnungen. Eintrag: {id, sourceId, instance, whenValue, pin, activeHigh} |
| gpioOutputBindingSetup | Json Object | w | Eine Ausgangszuordnung erstellen oder löschen. Erstellen: {gpioOutputBindingSetup: {sourceId: String, pin: Number [0,3], instance?: String, whenValue?: String, activeHigh?: Boolean}} whenValue: Der Aufzählungswert, der den Pin einschaltet (nur für valueType "enum", z. B. "red") activeHigh: true (Standard) = Pin auf High-Pegel, solange die Signalquelle aktiv ist Beispiel: {gpioOutputBindingSetup: {sourceId: "kiAmpel", instance: "spandetekt", whenValue: "red", pin: 0}} Löschen: {gpioOutputBindingSetup: {id: Number, delete: true}} |
| gpioInputBindings | Json Array | r | Konfigurierte Eingangszuordnungen. Eintrag: {id, pin, actionId, createdByUser} |
| gpioInputBindingSetup | Json Object | w | Eine Eingangszuordnung erstellen oder löschen. Erstellen: {gpioInputBindingSetup: {pin: Number [0,3], actionId: String}} Beispiel: {gpioInputBindingSetup: {pin: 1, actionId: "recording"}} Löschen: {gpioInputBindingSetup: {id: Number, delete: true}} |
Aufgaben
Ein Signal beschreibt alle vier Pins: {pin1, pin2, pin3, pin4}. Zulässige Werte sind „0“ (Low), „1“ (High), „x“ (ignorieren) und – nur für Eingangsbedingungen – „↑“ (steigende Flanke) sowie „↓“ (fallende Flanke). Ausgangsaufgaben spielen eine Signalfolge ab: Jede Aktion setzt ihr Signal und hält es für durationMs. Für repeatCount gilt: -1 (Standard) = einmal ausführen; N > 0 = N-mal wiederholen, also insgesamt N+1 Durchläufe; 0 = unbegrenzt wiederholen. Zwischen den Durchläufen ersetzt repeatDelayMs die Dauer der letzten Aktion. Nach dem Ende der Aufgabe behalten die Pins ihren letzten Pegel. Aktive Ausgangsaufgaben bleiben über einen Neustart hinweg erhalten. Eingangsaufgaben werden bei jeder Änderung eines Eingangs geprüft: Stimmen alle vier Bedingungen von signal überein, wird die Aktion ausgeführt. Pegelbedingungen („0“/„1“) können auch dann erfüllt sein, wenn sich ein anderer Pin ändert. Verwenden Sie Flanken, um eine Aktion einmal pro Ereignis auszulösen. Aktionen vom Typ StateChange werden mit den Berechtigungen des Benutzers ausgeführt, der die Aufgabe erstellt hat.
| API-Schlüssel | Datentyp | Berechtigungen | Beschreibung |
|---|---|---|---|
| gpioOutputSetupTask | Json Object | w | Eine Ausgangsaufgabe starten, ändern oder löschen. Starten: {gpioOutputSetupTask: {actions: [{signal: {pin1, pin2, pin3, pin4}, durationMs: Number}], repeatCount?: Number, repeatDelayMs?: Number, startDelayMs?: Number}} Beispiel (Pin 1 dreimal blinken lassen): {gpioOutputSetupTask: {actions: [{signal: {pin1: "1", pin2: "x", pin3: "x", pin4: "x"}, durationMs: 500}, {signal: {pin1: "0", pin2: "x", pin3: "x", pin4: "x"}, durationMs: 500}], repeatCount: 2}} Ändern: dieselbe Struktur mit id; Löschen: {gpioOutputSetupTask: {id: Number, delete: true}} Antwort: "[ok] task started with id N" |
| gpioOutputTasks | Json Object | r | Laufende Ausgangsaufgaben, nach ID indiziert |
| gpioInputSetupTask | Json Object | w | Eine Eingangsaufgabe erstellen, ändern oder löschen. Struktur: {gpioInputSetupTask: {id?: Number, isActive: Boolean, signal: {pin1, pin2, pin3, pin4}, kind: String, url?: String, message?: String, key?: String, value?: String, gpioOutputSignal?: {pin1, pin2, pin3, pin4}}} kind: "StateChange" - den Zustand key auf value setzen (Wert als JSON-Text, z. B. "true" oder "\"start\"") "HTTPGetRequest" / "HTTPPostRequest" - Anfrage an url; bei POST wird message als Anfrageinhalt gesendet "TCPRequest" / "UDPRequest" - message an url senden (tcp://host:port bzw. udp://host:port) "GPIOOutputSignalSet" - die Ausgänge auf gpioOutputSignal setzen "CreateTag" - einen Tag mit dem Titel key, der Notiz message und der Kategorie value erstellen Platzhalter in url, message und Tag-Texten: ${date}, ${timestamp}, ${gpio_in}, ${gpio_out} Beispiel: {gpioInputSetupTask: {isActive: true, signal: {pin1: "↑", pin2: "x", pin3: "x", pin4: "x"}, kind: "StateChange", key: "record", value: "\"start\""}} Löschen: {gpioInputSetupTask: {id: Number, delete: true}} Die Felder activateDaily, daysActive, timeStartSec, timeEndSec und delayMs werden gespeichert, aber noch nicht ausgewertet |
| gpioInputTasks | Json Object | r | Konfigurierte Eingangsaufgaben, nach ID indiziert; error beschreibt die letzte fehlgeschlagene Ausführung |