API – Documentation
Here you can access the old API Documentation, for software versions V2.7.10 and below.
Please consider updating the control unit to the newest software version and using the API as described here.
Getting started
This API was developed to enable customized control in the diverse machine control environments. The API provides programmatic access to read state and control the camera system.
Two web-based communication protocols are available. On the one hand, it is possible to set up a stateless connection via the standard HTTP Get or Post request and to fetch or set the desired data. On the other hand, an event-driven system can be developed via a websocket connection. In this way, the software programmed by the customer could react to changing information, which are synchronized in real time.
Http API
The http API is a RESTful API. The control unit of the Rotoclear C2 represents the server in the local network environment and the program is the client. Communication happens stateless between server and client. This means that the server does not know anything about the last requested data and even if the data is still up to date it will be sent again on request.
This API is ideal for writing a simple and small control program. It is also easy to test. The Get Requests URL can be entered directly in the browser in the URL input field, or it can be tested with postman or curl. All that is needed is a http Client and some understanding of the http protocol, url queries, the http headers and JSON format.
Connection
Http API can be accessed via both web servers on the control unit. In principle, the origin of the connection url is the same under which we can also call the web client in the browser. The path '/api' is appended to this url origin (see 'Connection URL examples'). Of course, the respective web server must be switched on in the connection settings (see http and https connection in menu). These connection settings also contain the port we need for our http client connection. Please note: For security reasons, the https connection is always recommended.
The API responds to two HTTP methods. The HTTP GET method can be used to set request details in the URL query. For practical reasons, it is also allowed to set parameters in the API (which will be explained below). With the HTTP POST method, more complex request structures can be mapped with a JSON formatted body.
Connection URL examples:
http://rotoclear.local:80/api
https://rotoclear.local:443/api
https://192.168.0.123:3000/api
Response:
401 Unauthorized
Authentication and Authorization
Furthermore, we need also the API token from the settings. This is configurable after the activation of the API module. The system has an internal permissions system, which can assign different rights for different users. With the activation of the API module, an 'API-User' user is created in addition to the 'admin' user. The token set in the settings reflects the password of the 'API-User'.
Authentication via parameters in the url query:
The user and the password can be set as one parameter in the URL query. In this case, the keywords 'token' and 'password' are mapped to the same field of the user as password. If the user is not passed, the 'API-User' is assumed as default. (example: 'Authentication in URL Query'). This authetification variant has advantages and disadvantages. One disadvantage is that the token is readable in its raw form in the url query. One advantage is that a request can be made simply as URL text, as for example with the GET request by entering the url in browser.
If an http client connects only with this information, then all information authorized for the user is sent as response, since no further information and selection is provided.
Authentication in URL Query:
http://rotoclear.local:80/api?user=API-User&token=***
https://rotoclear.local:443/api?token=***
https://192.168.0.123:3000/api?password=***
Curl example:
curl -X GET -G https://rotoclear.local:443/api -d token=***
Response:
200 Success.
With JsonObject as description of the state in body of the response.
Simplified and formatted body example of the response body:
{
"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,
...
}
Authentication via Basic Authentication:
The second authentication variant is Basic Authentication. For this purpose, according to the RFC7617 standard, the 'Authorization' key is specified in the http header. The value of authorization key composes the text "Basic " and the base64 encoded 'username:password'. Further information should be taken from the documentation of the respective http client and used programming language.
Basic Authentication - Curl example:
curl -X GET -G https://rotoclear.local:443/api \
-u "API-User:token"
Response:
200 Success.
With JsonObject as description of the state in body of the response.
Http Get method
Now that the connection and the authentication to the API was successful, we can go into some details about the requests. In the request with the http Get method, additional parameters can be added in the URL query. To get only the state of the system, the keyword 'get' can be used to list only the desired system state variables. The description of the state variables can be found at the end of this documentation (see: 'State Description'). All variables allowed to the user can be queried in this way. Unknown or unauthorized state variables are ignored by the API. This means that these values are not listed in the response.
Query selected state variables - URL example:
https://rotoclear.local:443/api?token=***&get=[light0,record,recordTime,pan0]
Query selected state variables - Curl example:
curl -X GET -G https://rotoclear.local:443/api \
-d token=*** \
-d get=[light0,record,recordTime,pan0]
Response:
{
"light0": true,
"record": "stop",
"recordTime": 0,
"pan0": {
"x": 50.26041666666666,
"y": 50.0
}
}
The Get method can also be used to set values in the system state. Please note that complex and nested structure variables cannot be easily mapped in a query, so they will not work with a GET request. To set a variable, simply match its key to the value in the query. Since in the query the variables are written only in the form of text, these variables are converted internally into the respective data types. That means "true" or "false" becomes a JSON boolean, written-out numbers are converted into the respective JSON numbers as Integer or Float number and saturated. In addition, the values are validated and caught in a valid and defined range. After setting the variable, the updated state variables are listed in the response of the request.
Set state variables - URL example:
https://rotoclear.local:443/api?token=***&light0=true&record=start
Set state variables - Curl example:
curl -X GET -G https://rotoclear.local:443/api \
-d token=*** \
-d light0=true \
-d record=start
Response:
{
"light0": true,
"record": "stop",
}
The system could respond with a "record": "stop" if, for example, no storage medium was selected for recording.
Http Post method
There are also some slightly more complex data types in the system state. These include for example network, time, stream pan settings, etc. If you want to set these more complex data types, you can use the http post method. To do this, the settings in JSON format are passed to the request in the body.
Set pan for first camera head - Post Request with a JSON body:
curl -X POST https://rotoclear.local:443/api \
-u "API-User:***" \
-H "Content-Type: application/json" \
-d '{"pan0": {"x": -10.5, "y": -10}, "zoom0": 20000}'
Response:
{
"pan0": {
"x": 39.5,
"y": 40.0
},
"zoom0": 20000
}
While the control of the camera heads, i.e. the pan and the zoom
are calculated relative to the current value, the return value
of the API is always the absolute value currently set.
For simplicity, values can also be queried via the post method. To do this, the get key must be matched with an array of keys in string form.
Furthermore, it should be mentioned that with one request state getter and setter can be sent at the same time. Usually these are executed in the written order. The same applies to the get requests, where the order of the query parameters is considered.
Query state - Post Request with a JSON body:
curl -X POST https://rotoclear.local:443/api \
-u "API-User:***" \
-H "Content-Type: application/json" \
-d '{"get": ["light0","record","recordTime","pan0"]}'
Response:
{
"light0": true,
"record": "stop",
"recordTime": 0,
"pan0": {
"x": 50.26041666666666,
"y": 50.0
}
}
WebSocket API
The websocket API is suitable for programming an event-based system. The API is based, as the name says, on the extended http API protocol called websocket. With a websocket a permanent connection can be established. To understand the communication over the websocket with the API we must consider the following points.
1. communication data and format:
The API communicates like the http API internally with JSON formatted data (there are some internal exceptions, but these should never occur in normal usage). This means that incoming messages to the websocket client will 'always' be JSON objects. In these objects one or more state variables of the system can be listed. This also means that the websocket client must also send its control messages in JSON format.
2. subscription:
When a connection is established with the API and authorized, all variables of the system authorized to the user are automatically subscribed to. This means that first, all these variables are packaged in JSON and sent to the client as an initial state, and then second, whenever the state changes, the corresponding variables are sent again to the client in real time. This way a system can be built which is synchronized in real time with the control unit.
3. control:
It is also possible for the websocket client to participate in the state of the system. As with the http Post request, the websocket can send JSON formatted messages. These are evaluated and set in real time. The data type as well as the write permission for the variables must be considered here. See the state table at the end of the document.
Connection
The websocket connections reside in the same endpoints as the http API connections. Again, both web servers (http and https web servers) are accessible for this connection. We only must note that "ws" must be written as protocol instead of "http".
For more information about websocket connections, please refer to documentation of the websocket and the respective development programming language of your client system.
Connection URL examples:
ws://rotoclear.local:80/api
wss://rotoclear.local:443/api
wss://192.168.0.123:3000/api
In Javascript:
const socket = new WebSocket("wss://rotoclear.local:443/api");
Response:
401 Unauthorized
Authentication and Authorization
For authentication and authorization of the connection, the token and the user must be set in the url query. See also the authentication of the http API in the paragraph: Authentication in URL Query.
Create connection to the WebSocket API in Javascript:
const token = "***"; // query conform encoding should be considered here
const socket = new WebSocket("wss://rotoclear.local:443/api?token=" + token);
// add callbacks
socket.onerror = function(error){ console.error(error); };
socket.onmessage = function(evt) {
if (typeof evt.data === "string") {
var jsonMsg = JSON.parse(evt.data);
console.debug(jsonMsg);
// The first message will represent the entire allowed state. The following ones will represent the updates.
}
}
Example
Create connection to the WebSocket API in Nodejs:
var WebSocket = require('websocket').w3cwebsocket;
const token = "***"; // query conform encoding should be considered here
const socket = new WebSocket("wss://rotoclear.local:443/api?token=" + token);
function sendToAPI(message) {
// stringify json message
connection.send(JSON.stringify(message));
}
connection.onopen = function() {
// now we can send messages to api
sendToAPI({ "light0": true });
};
connection.onerror = function(error) { console.error(error); };
connection.onmessage = function(evt) {
if (typeof evt.data === "string") {
var stateMsg = JSON.parse(evt.data);
console.debug(stateMsg);
// Use data from api to control your system
// ....
}
};
Camera stream
The camera stream can also be processed via the http requests. Please note that authentication with the corresponding credentials (username and password) is required in the http request to access the camera stream. For authentication and authorization see http API authentication in paragraph: Authentication in URL query.
1. Retrieving a JPEG image:
A JPEG image can be obtained by making an http GET request. To do this, the path '/camera.jpeg' and the authentication must be added to the connection.
Request Image:
http://rotoclear.local:80/camera.jpeg?user=admin&password=***
2. Streaming MJPEG:
For streaming MJPEG, the content type 'multipart/x-mixed-replace' is used. The server sends a continuous series of JPEG images in response to the http request. The content type of each individual image is specified as 'Content-Type: image/jpeg'.
The server will respond with a continuous series of JPEG images, transmitted in the body of the http response. Each image has the content type 'image/jpeg' and is sent in a separate http message. The client can process the MJPEG stream by extracting and displaying each individual JPEG image.
Request MJPEG:
http://rotoclear.local:80/camera.mjpeg?user=admin&password=***
State Description
The following table describes the state variables. Please note that some settings are dependent on each other. Accordingly, the system will validate the inputs and trigger notifications under certain circumstances.
Legend
r - readable
w - writeable
[x,y] - interval of valid values.
API Key | Value Datatype |
Permissions | Description |
---|---|---|---|
cam0Exists | Boolean | r | existence of the first camera head |
cam1Exists | Boolean | r | existence of the second camera head |
cameraSwitch | Boolean | rw | selection of the current streaming and recording camera head. false -> first camera is selected true -> second camera is selected |
lineRateA | String | r | data transmission rate of the first camera head |
lineRateB | String | r | data transmission rate of the second camera head |
ver0 | String | r | hardware and software version of the first camera head |
ver1 | String | r | hardware and software version of the second camera head |
autoRotate0 | Boolean | rw | automatic alignment of the first camera head false -> first camera is selected true -> second camera is selected |
autoRotate1 | Boolean | rw | automatic alignment of the second camera head false -> first camera is selected true -> second camera is selected |
dictRotation0 | Boolean | rw | first camera head disk rotation |
dictRotation1 | Boolean | rw | second camera head disk rotation |
rpm0 | Integer | r | read rotation speed setpoint of the first camera head |
rpm1 | Integer | r | read rotation speed setpoint of the second camera head |
RPM0 | Integer | r | measured rotation speed of the first camera head |
RPM1 | Integer | r | measured rotation speed of the second camera head |
light0 | Integer | rw | first camera head light false -> disabled true -> enabled |
light1 | Integer | rw | second camera head light false -> disabled true -> enabled |
downstat | String | r | state of the 'update process' working in the background |
fpgaTemp | String | r | temperature of the FPGA in the control box |
exposure | Boolean | rw | automatically aligned exposure of the picture false -> disabled true -> enabled |
whiteBalance | Boolean | rw | automatically white balance of the picture false -> disabled true -> enabled |
noiseSuppression | Boolean | rw | automatically noise suppression false -> disabled true -> enabled |
redGain | Integer [-128,127] | rw | red gain value works only if whiteBalance is disabled |
blueGain | Integer [-128,127] | rw | blue gain value works only if whiteBalance is disabled |
brightness | Integer [-7,7] | rw | brightness of the picture works only if exposure is disabled |
expo | Number [0.01,1000.0] | rw | exposure time [in ms] works only if exposure is disabled |
gain | Integer [0,42] | rw | gain works only if exposure is disabled |
sharpness | Integer [1,15] | rw | sharpness of the picture |
saturation | Number [-7,7] | rw | color saturation of the picture |
contrast | Number [1,2.5] | rw | contrast of the picture |
hdmiConnected | Boolean | r | indicates whether a monitor is connected to the control box |
hdmiName | String | r | name of the monitor |
cfg30 | String | r | rate of the first optical sensor of the first camera head (dependent on the quality of the connection) "0" ≙ no optical sensor found "30" ≙ optical sensor with 30fps found "60" ≙ optical sensor with 60fps found |
cfg40 | String | r | rate of the second optical sensor of the first camera head (dependent on the quality of the connection) "0" ≙ no optical sensor found "30" ≙ optical sensor with 30fps found "60" ≙ optical sensor with 60fps found |
cfg31 | String | r | rate of the first optical sensor of the second camera head (dependent on the quality of the connection) "0" ≙ no optical sensor found "30" ≙ optical sensor with 30fps found "60" ≙ optical sensor with 60fps found |
cfg41 | String | r | rate of the second optical sensor of the second camera head (dependent on the quality of the connection) "0" ≙ no optical sensor found "30" ≙ optical sensor with 30fps found "60" ≙ optical sensor with 60fps found |
oct0 | String | r | temperature of the first camera head |
oct1 | String | r | temperature of the second camera head |
cam0SelectedSensor | Integer [0,1] | rw | selected optical sensor of the first camera head Be careful, if your head does not have 2 optical sensors, it will mirror your image! |
cam1SelectedSensor | Integer [0,1] | rw | selected optical sensor of the second camera head Be careful, if your head does not have 2 optical sensors, it will mirror your image! |
language | String | rw | current selected language in menu Please note that only the selection of languages from the menu is valid. |
licenseConfig | Json Array | r | list of feature configurations in system |
licenseModules | Json Array | r | list of modules in system |
hasInternet | Boolean | r | control box has internet access |
macAddr | String | r | mac address of the first network device in hardware |
hostname | String | r | currently only read only access to hostname |
netInfo | Json Array | r | list network devices and settings |
zoom0 | Integer [0,31424] | rw | zoom of first camera head Please note: For algorithmic reasons, a relative value is always assumed when setting the value. But the response is always the absolute value. |
zoom1 | Integer [0,31424] | rw | zoom of second camera head Please note: For algorithmic reasons, a relative value is always assumed when setting the value. But the response is always the absolute value. |
pan0 | Json Object { "x": Number, "y": Number } |
rw | pan of the first camera head Please note: For algorithmic reasons, a relative value is always assumed when setting the value. But the response is always the absolute value. The values x and y are only valid in interval of [0.0,100.0] |
pan1 | Json Object { "x": Number, "y": Number } |
rw | pan of the second camera head Please note: For algorithmic reasons, a relative value is always assumed when setting the value. But the response is always the absolute value. The values x and y are only valid in interval of [0.0,100.0] |
pip | Number [0,4] | rw | picture in picture mode selection 0 ≙ only current camera 1 ≙ pip is top left 2 ≙ top right 3 ≙ bottom left 4 ≙ bottom right |
psi0 | String | r | sealing air of first camera head in bar |
psi1 | String | r | sealing air of second camera head in bar |
psiSetpoint | String | r | default sealing air set point in bar |
changeVideoName | String | rw | prefix of the recorded video file |
changeImageName | String | rw | prefix of the recorded image file |
changePostName | String | rw | postfix of the recorded file |
record | String | rw | state of recording options: "start", "pause", "release" or "stop" please note: that the recording requires some conditions such as the presence of the storage medium and sufficient storage space |
takePicture | Boolean | w | trigger snapshot |
recordTime | Number | r | traced time of current video recording |
rtspPort | Number | rw | port of rtsp server |
rtspOn | Boolean | rw | rtsp server running |
rtspStatus | Json Object | r | status of rtsp server |
diskStorages | Json Object | r | list of detected usb storages |
netStorages | Json Object | r | list of setted network storages |
recordingStorage | Json Object | r | selected manual recording storage description |
recordingStorage | String | w | select manual recording storage with uuid (select one id in diskStorages or netStorages) |
alignmentStream0 | String | rw | rotate stream of first camera head "0" ≙ 0° "1" ≙ 180° |
alignmentStream1 | String | rw | rotate stream of second camera head "0" ≙ 0° "1" ≙ 180° |
recordingResolution | String | rw | recording and stream resolution "4K": 3840x2160 "FullHD": 1920x1080 "HD": 1280x720 |
recordingFps | Integer | rw | recording and stream frames per second. options: 1, 5, 10, 15, 30, 60 |
recordingPictureQuality | Integer [1,100] | rw | quality of jpeg compressor |
mjpgStreamIsOpen | Boolean | rw | enable or disable the stream for clients without connection token |
recordingWithTimeStamp | Boolean | rw | write time into stream and recording |
recordingWithDateStamp | Boolean | rw | write date into stream and recording |
systemDescription | Json Object | r | hardware and system description of control box |
time | Json Array of numbers | r | systems time [year,month,day,hours,minutes,seconds] |
timezone | String | rw | selected timezone |
ntpHost | String | rw | address ot the ntp server |
ntpStatus | Json Object | r | State of last connection try to ntp server |
ntpSync | Boolean | rw | enable ntp syncronization |
seconds | Integer | r | epoch time seconds |
connectionUrls | Json Object | r | list of detected and assumed possible connections |
userAuthentication | Json Object | rw | enables password authentication in clients |
swVersion | String | r | current software version |
fmVersion | String | r | current firmware version |
httpOn | Boolean | rw | http webserver run setting |
httpsOn | Boolean | rw | https webserver run setting |
httpPort | Integer [1,65000] | rw | http webserver port |
httpsPort | Integer [1,65000] | rw | https webserver port |
httpStatus | Json Object | r | http webserver status |
httpsStatus | Json Object | r | https webserver status |
httpsCertificate | Json Object | r | certificate description |
Code examples
These code examples are designed to help you getting started using our API.
- Node.js
- C#
- NIM
- Python
Node.js
#!/usr/bin/env node
// Example for Nodejs - JS
//
// 1. Connect to websocket-server
// 2. Check camera 1 is connected
// 3. If camera 1 is connected toggle the light
// 4. Take a jpg image and save it as file
// 5. Close connection
//
// Install dependencies:
// npm install websocket
//
const W3CWebSocket = require('websocket').w3cwebsocket;
const http = require('http');
const fs = require('fs');
const RotoclearIp = "192.168.178.61"
const RotoclearApiPort = "80"
const ApiToken = "1a2B3c4D5e6f7G8h"
const WebsocketApiUrlWithAuth = "ws://" + RotoclearIp + ":" + RotoclearApiPort + "/api?token=" + ApiToken
const HttpCameraImageUrlWithAuth = "http://" + RotoclearIp + ":" + RotoclearApiPort + "/camera.jpeg?user=API-User&token=" + ApiToken
const imageName = 'myNewImage.jpg'
console.log("try to establish connection to ", WebsocketApiUrlWithAuth)
var connection = new W3CWebSocket(WebsocketApiUrlWithAuth);
function sendToAPI(message) {
// Send message to api server. Only stringified json object is accepted
connection.send(JSON.stringify(message));
}
connection.onerror = function (err) {
console.log('Connection error', err.toString());
};
connection.onopen = function () {
console.log('Connection successful established');
};
connection.onclose = function (ev) {
console.log('Client closed', ev.reason);
};
connection.onmessage = function (ev) {
if (typeof ev.data === "string") {
// if data is of type string, then it is json
var api_message = JSON.parse(ev.data);
if (api_message["cam0Exists"]) {
if(api_message["light0"]) {
sendToAPI({ "light0": false });
} else {
sendToAPI({ "jpeg": true });
}
http.get(HttpCameraImageUrlWithAuth, (res) => {
let data = [];
console.log('Status Code:', res.statusCode);
res.on('data', (chunk) => {
data.push(chunk);
});
res.on('end', () => {
const imageBuffer = Buffer.concat(data);
fs.writeFileSync(imageName, imageBuffer);
process.exit()
});
});
} else {
console.log("No camera head detected")
process.exit()
}
}
};
C#
// Dotnet c# API Example
//
// 1. Connect to websocket-server
// 2. Check camera 1 is connected
// 3. If camera 1 is connected toggle the light
// 4. Take a jpg image and save it as file
//
// Install dotnetSDK:
// see: https://docs.microsoft.com/de-de/dotnet/core/install
//
// Init project in current directory:
// dotnet new console
//
// copy the content to your Program.cs and replace the namespace "dotnet_websocket_api_example" with yours
using System.Text;
using System.Net.WebSockets;
using System.Text.Json;
using System.Net;
namespace dotnet_websocket_api_example
{
class Program
{
const string ServerIp = "192.168.178.61";
const int ServerPort = 80;
const string APIToken = "1a2B3c4D5e6f7G8h";
public static Task SendString(ClientWebSocket ws, String data)
{
var encoded = Encoding.UTF8.GetBytes(data);
var buffer = new ArraySegment<Byte>(encoded, 0, encoded.Length);
return ws.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
}
public static async Task<String> ReadString(ClientWebSocket ws)
{
ArraySegment<Byte> buffer = new ArraySegment<byte>(new Byte[32000]);
using (var ms = new MemoryStream())
{
while (true)
{
WebSocketReceiveResult result = await ws.ReceiveAsync(buffer, CancellationToken.None);
ms.Write(buffer.ToArray(), buffer.Offset, result.Count);
if (result.EndOfMessage) {
break;
}
}
ms.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(ms, Encoding.UTF8))
{
return reader.ReadToEnd();
}
}
}
static async Task Main(string[] args)
{
// Define the cancellation token.
using (var socket = new ClientWebSocket())
{
try
{
await socket.ConnectAsync(new Uri("ws://" + ServerIp + ":" + ServerPort + "/api?token=" + APIToken), CancellationToken.None);
string systemStateMessage = await ReadString(socket);
JsonDocument doc = JsonDocument.Parse(systemStateMessage);
var systemStateJson = doc.RootElement;
System.Console.WriteLine(systemStateJson.ToString());
if (!systemStateJson.GetProperty("cam0Exists").GetBoolean()) {
// toggle light
if (systemStateJson.GetProperty("light0").GetBoolean())
{
await SendString(socket, "{ \"light0\": false }");
}
else
{
await SendString(socket, "{ \"light0\": true }");
}
// # get jpeg and save it
using (var client = new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }))
{
HttpResponseMessage response = await client.GetAsync("http://" + ServerIp + ":" + ServerPort + "/camera.jpeg?user=API-User&token=" + APIToken);
var jpgBytes = await response.Content.ReadAsByteArrayAsync();
File.WriteAllBytes("streamImage.jpg", jpgBytes);
}
}
else
{
System.Console.WriteLine("No camera head detected");
}
}
catch (Exception ex)
{
Console.WriteLine($"ERROR - {ex.Message}");
}
}
}
}
}
NIM
# Example in NIM - Control light via websocket api
#
# 1. Connect to websocket-server
# 2. Check camera 1 is connected
# 3. If camera 1 is connected then toggle the light
# 4. Take a jpg image and save it as file
# 5. Close connection
#
# Install dependencies:
# nimble install ws
#
import std/[
strformat,
strutils,
json,
asyncdispatch,
httpclient
]
import ws
const
rotoclearIp = "192.168.178.61"
rotoclearApiPort = "80"
apiToken = "1a2B3c4D5e6f7G8h"
wsUrlWithAuthInQuery = fmt("ws://{rotoclearIp}:{rotoclearApiPort}/api?token={apiToken}")
streamImageUrlWithAuthInQuery = fmt("http://{rotoclearIp}:{rotoclearApiPort}/camera.jpeg?user=API-User&token={apiToken}")
proc runProcess() {.async.} =
# create connection
let conn = await newWebSocket(wsUrlWithAuthInQuery)
let
# after a successful authentication the response will be the whole state
response = await conn.receiveStrPacket()
currentStateJson = parseJson(response)
# print state in console
echo currentStateJson.pretty
if currentStateJson.hasKey("cam0Exists"):
if currentStateJson["cam0Exists"].getBool():
if currentStateJson["light0"].getBool():
let message = %*{ "light0": false }
await conn.send($message)
else:
let message = %*{ "light0": true }
await conn.send($message)
# get jpeg and save it
let
client = newHttpClient()
response = client.getContent(streamImageUrlWithAuthInQuery)
writeFile("currentImage.jpeg", response)
else:
echo "No camera head detected"
conn.close()
waitFor runProcess()
# Example in NIM - Use http api to get and set data
#
# 1. Connect to websocket-server
# 2. Fetch some information from the system (eg. light0, record, recordTime, pan0)
# 3. Disable light and move pan cursor from current position via post request
#
import std/[strformat, json, httpclient]
const
rotoclearIp = "192.168.178.61"
rotoclearApiPort = "80"
apiToken = "1a2B3c4D5e6f7G8h"
urlWithAuthInQuery = fmt("http://{rotoclearIp}:{rotoclearApiPort}/api?token={apiToken}")
let
client = newHttpClient()
response = client.getContent(urlWithAuthInQuery & "&get=[light0,record,recordTime,pan0]")
jsonResponse = response.parseJson()
echo jsonResponse.pretty()
# disable light and move pan cursor from current position via post request
let
message = %*{
"light0": false,
"pan0": { # relative values
"x": -20.0,
"y": -30.0
}
}
echo client.postContent(urlWithAuthInQuery, $message)
Python3
#!/usr/bin/python3
# Example in Python3
#
# 1. Connect to websocket-server
# 2. Check camera 1 is connected
# 3. If camera 1 is connected then toggle the light
# 4. Take a jpg image and save it as file
# 5. Close connection
#
# Install dependencies:
# pip install websocket-client
# pip install requests
# pip install json
#
from websocket import create_connection
import requests
import json
ROTO_CLEAR_IP = "192.168.178.61"
ROTO_CLEAR_PORT = "80"
MY_API_TOKEN = "1a2B3c4D5e6f7G8h"
WEBSOCKET_API_URL_WITH_AUTH = "ws://" + ROTO_CLEAR_IP + ":" + ROTO_CLEAR_PORT + "/api?token=" + MY_API_TOKEN
HTTP_CAMERA_IMAGE_URL_WITH_AUTH = "http://" + ROTO_CLEAR_IP + ":" + ROTO_CLEAR_PORT + "/camera.jpeg?user=API-User&token=" + MY_API_TOKEN
ws = create_connection(WEBSOCKET_API_URL_WITH_AUTH)
# after the connection the api response is the whole system state
response = ws.recv()
systemState = json.loads(response)
# print state in console
print(systemState)
if systemState["cam0Exists"]:
# toggle light
if systemState["light0"]:
jsonText = json.dumps({"light0": False})
ws.send(jsonText)
else:
jsonText = json.dumps({"light0": True})
ws.send(jsonText)
# get jpeg and save it
imageResponse = requests.get(HTTP_CAMERA_IMAGE_URL_WITH_AUTH)
f = open("myCurrentImg.jpg", "wb")
f.write(imageResponse.content)
f.close()
else:
print("No camera head detected")
ws.close()
#!/usr/bin/python3
# Example in Python3 - Use http api to get and set data
#
# 1. Connect to websocket-server
# 2. Fetch some information from the system (eg. light0, record, recordTime, pan0)
# 3. Disable light and move pan cursor from current position via post request
#
# Install dependencies:
# pip install requests
# pip install json
#
import requests
import json
ROTO_CLEAR_IP = "192.168.178.61"
ROTO_CLEAR_PORT = "80"
MY_API_TOKEN = "1a2B3c4D5e6f7G8h"
HTTP_API_URL_WITH_AUTH = "http://" + ROTO_CLEAR_IP + ":" + ROTO_CLEAR_PORT + "/api?user=API-User&token=" + MY_API_TOKEN
response = requests.get(HTTP_API_URL_WITH_AUTH +
"&get=[light0,record,recordTime,pan0]")
jsonResponse = json.loads(response.content)
print(jsonResponse)
# disable light and move pan cursor from current position via post request
message = json.dumps({
"light0": False,
"pan0": { # relative values
"x": -20.0,
"y": -30.0
}
})
response = requests.post(HTTP_API_URL_WITH_AUTH, message)
print(response.content)