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
  • WebSocket API
  • Kamerastream
  • Variablen
  • KI-Modul
  • GPIO-Modul

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