Skip to content

Instantly share code, notes, and snippets.

@accuware accuware/dragonfly2java-latest.md Secret
Last active Sep 27, 2019

Embed
What would you like to do?
Dragonfly Java app, dashboard and REST API description, latest version

Dragonfly Java Dashboard and REST API

Version 1.4 feature table

Feature Supported
Java standalone app, available as obfuscated JAR
USB, internal or external camera support
Web server and REST interface for control and status
SSL support
GZIP support
Local map save and load
Local map update and delete
Configuration read/write available via REST
Map synchronization
Support for camera capture, native, mono and stereo
Offline map display
Position upload, history, custom server
Position logging to CSV
Local video recording
Support for virtual markers
Support for plain X, Y and Z display
Support for pitch, yaw, roll and rotation matrix
Support for version update check
Support for metric coordinates
Map point API
WebRTC support

Functions of the Java app

The Java app, controlled and monitored by this dashboard, makes use of an internal or external camera and feeds the captured images to native code, which finally enables it to determine the position of the device and to 3D-map the environment.

Because 3D-Mapping is one of the central tasks of the Java app and the item "map" or "mapping" is all the way used in this documentation, here a short primer regarding "What is a map?" in the context of Dragonfly:

A map is the virtual representation of what has been already seen by Dragonfly. It corresponds to a file, that stores all the information describing a visual environment and enables the tracking of the positions of a camera fitted device in this environment later on, hence "no map, no positioning".

A map contains:

  • A store of all the markers that have previously been detected with their position, printed markers as well as virtual markers (reference points, see below)
  • All the 3D points corresponding to the 3D reconstruction of the environment
  • All the features that have been detected, together with a visual representation of these features

Even though the dashboard is fully capable of loading, storing and manipulating those maps from a local, non-Internet connected environment, there is a special branch of the dashboard responsible for synchronizing maps with a central repository hosted at Accuware. This enables collaborative work between different parties on the maps. Please refer to Map Synchronization for details on how the synchronization process is working and what basic principles apply.

The Java app exposes a Web server interface on a configurable port and a REST API for remote control. It also hosts a dashboard.

Markers

Markers are an important part of the positioning process. They help in determining the relation of the internally used virtual coordinates to the coordinate system of the "real" world.

Markers can be made known to the system in two different ways:

  • In the form of printed visual markers (aka real markers), which are permanently installed at previously defined coordinates and recognized at runtime.
  • In the form of manually fixed reference points (aka virtual markers), which are transmitted via this dashboard to the Dragonfly Java App exactly at the time when the device is at this point.

For the first method the Accuware Dashboard provides a page, which helps you to create, configure and print the markers.

In case, placing printed visual markers is not an option, you can alternatively pin-point the current location of the device live on the floor plan. Check out the Quick help given on the Map calibration tab of this dashboard for details.

In any way, these two methods have to be applied only once in the entire mapping process for a level.

WebRTC

The Java app supports WebRTC in various variants as a means to feed external video. Since it can be a very challenging task to setup all required software and configuration, we don't promote this way actively. Within this documentation you will find just scattered hints about the configurations within the Dragonfly Java app. For deeper insight please refer to the Backup section.

How the app is deployed

The app comes packed in a ZIP file. Unpack into a directory of your choice and launch the app by simply typing

java -jar dfja-1.4-dist.jar

in a terminal window.

The app requires Java 11 JDK minimum. Check your environment with java -version. If the given JDK version is 11 or higher, you are OK to go.

There is also an experimental Docker deployment.

Functions of the dashboard

The dashboard you are currently using is a ReactJS static web app hosted by the Java app. It is providing currently four tabs

  • Main
  • Maps
  • Configuration
  • Documentation

The app makes use of the REST API, also hosted by the Java app. It generally provides all functionality available via REST plus means to fetch and use floor plans.

Even though web based, the app itself does not necessarily need to have Internet connectivity. This applies with the exception of the initialization of the floor plan display as described below.

The Main tab shows a tabular overview of status parameters obtained using the Get status API. Additionally it allows to start/stop a mapping and/or positioning. It displays the position on a floor plan view. If the site has floor plans, it downloads, caches and displays it, together with available geo fence information, if appropriate location and level information is provided by the core. It uses the site username and password information provided in configuration. Whenever Internet is available, the app checks for fresh floor plan and geo fences in the Accuware cloud. Generally an Internet connection is at least required once in order to download and cache floor plans and geo fences. Additionally means to pin-point real-time positions on floor plans are provided.

The Map tab allows to load, save, reset, update, delete local maps and sync local maps with the remote server. Maps are the results of the 3D mapping of the visual environment.

The Configuration tab provides means to configure the Java app. Other utility functions are offered.

The Documentation tab contains this documentation.

If default parameters are applied, the dashboard is available at http://localhost:5000. No authentication required. The webserver supports SSL.

In case you have a valid certificate, please provide the path to WEBSERVER_KEYSTORE_FILE and WEBSERVER_KEYSTORE_PASSWORD (best encrypted) in ./data/dragonfly2.properties and set WEBSERVER_SSL_SUPPORTED to true.

Note: The use of self-signed server certificates requires each curl REST API call to be decorated with the extra parameter -k in order to make curl accepting the certificate. Ex: curl https://localhost:5000/api/v1/config -k. You will additionally be requested to trust the self signed certificate, if you open the dashboard the first time in your browser.

Start of the Java app

In a terminal window:

java -jar dfja-1.4-dist.jar

The app is logging to console and to a daily rolling log file in ./data/logs.

Configuration of the Java app

Configuration can be provided by either a Java property file (./data/config/dragonfly2.properties) or the dashboard, page "Configuration".

The configuration file does not necessarily have to be available at very first startup. Mandatory parameters will be determined in dialog with user and file will be created.

There are currently only two mandatory parameters, listed first below.

Configuration Item Type Meaning Default
SITE_ID String MANDATORY Accuware Site ID n.a.
SITE_USERNAME String MANDATORY Accuware Site Username n.a.
SITE_PASSWORD String Accuware Site Password (un-encrypted or encrypted), see "Encrypt string" n.a.
WEBSERVER_PORT Integer Local web server port 5000
WEBSERVER_SSL_SUPPORTED Boolean Local web server SSL supported (requires WEBSERVER_KEYSTORE_FILE and WEBSERVER_KEYSTORE_PASSWORD) false
WEBSERVER_KEYSTORE_FILE String Path to keystore.jks file n.a.
WEBSERVER_KEYSTORE_PASSWORD String Password for keystore.jks file (un-encrypted or encrypted), see "Encrypt string" n.a.
WEBSERVER_WEBSOCKET_ENABLED Boolean Enables use of status pushes via websocket true
LOG_LEVEL Integer Controls granularity of logging. 0: off, 1: fatal, 2: error, 3: warn, 4: info, 5: debug, 6: trace, 7: all 7
JMX_REMOTE_MONITORING_ENABLED Boolean Enables monitoring via JConsole. Authorization/Authentication taken from files ./data/config/jmx_access and ./data/config/jmx_password false
JMX_RMI_REGISTRY_PORT Integer JMX registry port, required to form the JMX Service URL 33985
JMX_RMI_SERVER_PORT Integer JMX server port, required to form the JMX Service URL 33986
AUDIBLE_STATUS_ENABLED Boolean Gives audible feedback on status changes and marker detection true
CAM_MODE String Controls, in which mode the camera(s) should be operated, "mono" or "stereo" "mono"
CAM_SOURCE String GStreamer pipe definition, FFMPEG parameter, index or list of comma separated indexes. Default -1 (default camera) (see "CAM_SOURCE explained"). "-1"
CAM_PREVIEW_OPTION Integer Visible feedback of the image processing. 0: off, 1: in Javascript (websockets must be enabled), 2: in Java, 3: in Javascript and Java (just for completeness) 1
CAM_FOV Number Programmatically rectify the image and set a custom field-of-view. Value should be above 0 and below the actual FOV of the camera (max 180). Default 0 (not applied) 0
CAM_IMAGE_WIDTH Integer Camera capture and preview image width 640
CAM_IMAGE_HEIGHT Integer Camera capture and preview image height 480
CAM_CALIBRATION_FILE String Filename of the JSON camera calibration params file, created by CalibrationNative app, located in ./data/config ""
MAP_CALIBRATION_METHOD Integer Number of markers required to be detected, either 0 or 3. If you are using printed or virtual markers, the number has to be 3. If you configuring 0, positions are displayed in Direct view only, w/o any geo-reference. 3
POSITION_UPLOAD_INTERVAL Integer Number of milliseconds between two consecutive uploads of positions to the Accuware Dashboard (for tracking the deviceId) 0
POSITION_UPLOAD_STORE Boolean Controls, if uploaded positions will be stored in the Accuware Cloud false
POSITION_LOG_ENABLED Boolean Controls, if positions should be saved locally (daily rolling CSV log './data/logs/positionlog.csv', see CSV logging) false
MAP_FUSION_ENABLED Boolean Controls, if map fusion should be enabled or not false
VIDEO_RECORDING_ENABLED Boolean Controls, if the video taken from the camera(s) should be stored locally, folder './data/recorded', grouped by siteId false
VPS_SERVER_URL String Allows you to overwrite the VPS server URL (Note: provide the entire initial path as shown in default) https://cvnav.accuware.com/api/v1
PATH_TO_CHROMIUM String Path to an installed Chromium or Chrome browser instance. If empty, WebRTC functionality will be performed using GStreamer, if possible empty

Note: Camera calibration is a procedure to improve the accuracy of positioning results and mandatory for stereo cameras. For obtaining information about how to calibrate stereo cameras please consult Accuware Support. The calibration of a monocular camera can be done using the Accuware Dragonfly Demo on the web. Whereas in CAM_MODE "mono" it is allowed to start positioning w/o configured calibration file, a start is rejected in CAM_MODE "stereo" . The VPS_SERVER_URL is a private configuration parameter of the Java property file (./data/config/dragonfly2.properties). It is not available for modifications via the JS GUI. It is also possible to calibrate cameras, which are connected via WebRTC or RTSP. See Camera calibrationin section CAM_SOURCE explained.

Startup behavior clarified

If after startup the Java app detects, that there is no Java property file (./data/config/dragonfly2.properties), it usually presents an entry form, in which SITE_ID and SITE_USERNAME - the only mandatory parameters - are obtained in order to enable the error free start of the app. If a SITE_PASSWORD is available, it can be entered here too. All credentials are immediately validated against the Accuware Dragonfly Cloud. Validated credentials allow you to use the app for a certain amount of time without the need for an Internet connection. If you don't have credentials, you can directly sign-up from this form for a time limited demo account.

Valid credentials are also required in order to perform the initial download of metadata like floor plans and defined geo fences from the Accuware Dragonfly Cloud.

Note: A validation error of any kind is immediately reported, so that you will not be able to launch the app with invalid credentials. That in turn means, that your initial start of the Java application unconditionally requires an active Internet connection.

Once the online validation has been passed, the initial ./data/config/dragonfly2.properties is written to disk and the Java app launches a GUI automatically into your default browser at localhost:5000.

Since this credential input form might not be accessible in headless installations, it is possible to provide a handful of important startup parameters in System.properties via command line parameters.

Those are:

Parameter Meaning
siteId see SITE_ID setting
login see SITE_USERNAME setting
password see SITE_PASSWORD setting, accepted as unencrypted or encrypted string, see "Encrypt string"
webServerPort see WEBSERVER_PORT setting
vpsServerUrl see VPS_SERVER_URL setting
logLevel see LOG_LEVEL setting

If at least siteId and login are provided at command line level and there is not already a ./data/config/dragonfly2.properties file available, the values are taken and used to create an initial ./data/config/dragonfly2.properties, which then can be fine tuned via the configuration GUI in the JS web controlling app or by directly manipulating the file. The credentials are validated against the Accuware Dragonfly Cloud before they are written into the ./data/config/dragonfly2.properties file. In case of a failure, the start of the app is abandoned with an error.

Note: The command line parameters are no longer taken into account, if there is a valid ./data/config/dragonfly2.properties. Please note also, that the GUI is not automatically launched, if the initial configuration of the ./data/config/dragonfly2.properties has been performed by command line parameters. It is assumed, that intentionally no GUI is necessary, if one launches the app that way.

For example the launch request could look like so now:

java -jar -DsiteId="1000"                                              \
          -Dlogin="test@test.com"                                      \
          -Dpassword="testpassword"                                    \
          -DwebServerPort="4711"                                       \
          -DvpsServerUrl="https://myVPSServer.myDomain.com/api/v1"     \
          -DlogLevel="1"                                               \
dfja-1.4-dist.jar

If the platform validation passes OK, a valid initial ./data/config/dragonfly2.properties is written and the app launches w/o bringing up the GUI.

CAM_SOURCE explained

The configuration parameter CAM_SOURCE is an important configuration parameter and has a couple of variances. The default value is -1, which advices the app to use the default system camera.

Other numerical values can be used and define the index of the camera as enumerated by the system. A list of available cameras can be obtained by the API function "Get list of cameras". There can be multiple indexes specified (comma separated, (e.g. left cam index","right cam index), so in case a stereo camera is made of two separate USB cameras.

On the other hand the parameter allows the specification of GStreamer pipelines or parameter strings to be used for by FFMPEG internally. The prefixes gstreamer: and ffmpeg: are used to decide, which internal API needs to be fed with the rest of the parameter string. Those pipelines can be used in order to mount external cameras via network or internet.

There is an additionally supported prefix named webrtc:, which enables the app to use the video from an external WebRTC source.

It goes without saying, that using GStreamer and/or FFMPEG requires to have the appropriate GStreamer 1.0 and FFMPEG APIs available on your system. This is the case if you have installed the Dragonfly app from the installation procedure provided here.

If you intend to use WebRTC via GStreamer, then you need to have at least GStreamer 1.14 installed, better 1.16 since it comes with a lot of improvements for the libnice component. There are some restrictions with Ubuntu and higher versions of GStreamer. As a fall-back the Java app supports WebRTC using a Chromium instance, which is configured in the setting PATH_TO_CHROMIUM. Please download the latest Chromium app for your system, install it and configure the path. Example configuration for macOS: PATH_TO_CHROMIUM=/Applications/Chromium.app/Contents/MacOS/Chromium or if you are preferring Chrome PATH_TO_CHROMIUM=/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome

Some ready to be used examples for pipeline configurations and FFMPEG parameters are given below. You might have to adapt the IP addresses and/or URLs:

GStreamer configuration to be used in order to consume a Raspberry PI camera, streaming H.264 via TCP (Accuware Dragonfly Car)

The RPI is streaming RTP from 192.168.188.66, port 5000:

CAM_SOURCE=gstreamer:tcpclientsrc host=192.168.188.66 port=5000 ! gdpdepay !  rtph264depay ! avdec_h264 ! videoconvert ! appsink sync=false

Additional info: RTP streaming from Raspberry PI

GStreamer target sink is always appsink.

GStreamer configuration to be used in order to consume a Raspberry PI camera, streaming H.264 via RTSP

The RPI at 192.168.188.66 is providing an RTSP stream:

CAM_SOURCE=gstreamer:rtspsrc location=rtsp://192.168.188.66:8554/test latency=0 buffer-mode=auto ! rtph264depay ! avdec_h264 ! videoconvert ! appsink sync=false

The PI needs to be available on the same network as the Java app.

Additional info: RTSP streaming from Raspberry PI

GStreamer configuration to be used to consume a web video, provided as RTSP stream

CAM_SOURCE=gstreamer:rtspsrc location=rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov latency=0 buffer-mode=auto ! rtph264depay ! avdec_h264 ! videoconvert ! appsink sync=false

FFMPEG configuration to consume a local MP4 video from disk

CAM_SOURCE=ffmpeg:/home/user/documents/test.mp4
CAM_SOURCE=ffmpeg:/home/user/documents/test.mp4 --startingFrame=500
CAM_SOURCE=ffmpeg:file://home/user/documents/test.mp4

FFMPEG configuration to consume an RTMP video from the web

CAM_SOURCE=ffmpeg:rtmp://184.72.239.149/vod/mp4:bigbuckbunny_1500.mp4

WebRTC configuration to get the video of a WebRTC enabled Raspberry PI via Accuware Signaling Server

CAM_SOURCE=webrtc:https://dragonfly-demo.accuware.com:8443/?room=pi&mode=1&use-hw-codec=false

This connection string addresses a Raspberry PI (using UV4L WebRTC and Signaling Proxy), who is booked into room pi. The connection string advices to immediately connect to the PI (mode=1) and the PI's H.264 hardware codec shall not be used during this session.

Additional info: WebRTC streaming from Raspberry PI

WebRTC configuration to get the video from another PC, booked in into room "test" at the Accuware Signaling Server

CAM_SOURCE=webrtc:https://dragonfly-demo.accuware.com:8443/?room=test&mode=2

The PC is using the Accuware Dragonfly Demo, enters the same room and just waits. Once the camera is opened with the a.m. connection string from the Java app, the browser is contacted (probably you need to allow access to the camera and if auto-answer is not enabled, a bell will ring) and the video is displayed. mode=2 automatically starts the call to the browser.

WebRTC configuration to get the video from a DJI drone

CAM_SOURCE=webrtc:https://dragonfly-demo.accuware.com:8443/licensed/?userid=7773601236&licensekey=D00289AE-DBF2-42C6-ABCD-8CBE81D555D0&mode=2

The drone is using an Android app and a library in order to enter the licensed section specified by userId and licenseKey and enable the video transmission. It then waits for the call of the Java app in order to deliver the video.

Please also checkout these resources in order to learn about the ways to connect to DJI drones via WebRTC.

WebRTC configuration to get the video from a Raspberry PI directly from UV4L

CAM_SOURCE=webrtc:https://192.168.188.36/stream/webrtc/?use-hw-codec=false&server-url=https://dragonfly-demo.accuware.com:8443/uv4l&headless=true

If the PI is on the same network as the Java app or publicly reachable, there is no need to incorporate a Signaling Server and Signaling Proxy, since both parties can directly exchange the necessary parameters. The Java app utilizes the UV4L WebRTC extension protocol then.

Additional info: WebRTC streaming from Raspberry PI using UV4L directly.

All these example CAM_SOURCE strings need some extra explanations. The first parameter after webrtc: is always the URL of the signaling server or the server, which provides WebRTC functionality directly. It can be any URL, as long as the proprietary Accuware WebRTC Signaling Protocol (either licensed or community edition) is matched or the described server is providing the UV4L WebRTC protocol via REST API directly.

Parameter Meaning Default
room The room in which to meet the other party
mode The mode of operation 1: Automatic call to a PI, 2: Automatic call to any other source 1
name Optional name, with which you appear at the other party
quality Quality of JPEG encoding (Chromium only) 0.75
fps Target frame rate at JPEG level (Chromium only) 30
headless Headless run of the browser (Chromium only), false: non-headless true
userId UserID for the licensed version of the Accuware Signaling Server
licenseKey License key for the licensed version of the Accuware Signaling Server
use-hw-codec Enforcement of the Raspberry PI hardware codec (H.264) Chromium: false, GStreamer: true
server-url Required only, if you use the direct UV4L approach Required only, if PATH_TO_CHROMIUM is set

Note: The use-hw-codec parameter addresses a problem with Chromium. We suggest to not enforce PI's H.264 hardware codec with this browser, since H.264 is not supported there. If the remote party is NOT a Raspberry PI the parameter is ignored. For the GStreamer and Chrome approach there is no such a problem with the PI's H.264 hardware encoder, you are free to use the hardware encoder or not.

Unless the direct UV4L approach is used with a Raspberry PI we need a little proxy between our Signaling Server and UV4L, running on the PI. Please contact us for details and support. See Backup section at the end of this document for the various ways to make WebRTC running with a Raspberry PI.

Calibration of remote cameras

Calibration support is currently available on the Internet only, section Calibration Mode. If you intend to calibrate one of the cameras connected via WebRTC, just copy the entire CAM_SOURCE configuration string after and including webrtc: and provide this als video-url parameter to the web based calibration app.

Examples:

WebRTC via Signaling Server:

https://dragonfly-demo.accuware.com/?video-url=webrtc:https://dragonfly-demo.accuware.com:8443/?room=pi&mode=1&use-hw-codec=false

WebRTC via UV4L Server directly:

https://dragonfly-demo.accuware.com/?video-url=webrtc:https://192.168.188.36/stream/webrtc&use-hw-codec=false

Please mind, that you would need to provide SSL support for the UV4L server for being able to calibrate the camera and/or use the browser based approach (PATH_TO_CHROMIUM is set) for positioning operations (mixed content policy of the browsers).

An RTSP source needs to be available on the public Internet and is configured using their public URL:

https://dragonfly-demo.accuware.com/?video-url=rtsp://my-public-rtsp-server:8554/test

If it is not possible to publish your RTSP source on the Internet, not even for the short time of calibration, then there is a little Node helper project, which can act as an RTSP-to-MJPEG converter. Your RTSP source would then be made available to the calibration server using this URL:

https://dragonfly-demo.accuware.com/?video-url=https://localhost:9000

The localhost:9000 link has to be secure because of the mixed content policy of the browsers.

This proxy, BTW, would also help to calibrate a Raspberry PI camera from a PI, which streams just RTP via TCP (see RTP streaming from Raspberry PI).

Note: Generally it can sometimes be a bit cumbersome to calibrate remote network cameras (especially Raspberry PI), since there are a couple of temporary software installations and configurations necessary. In order to make your (and our) lives easier, we provide a couple of canned calibration files as download (see Backup section).

JConsole monitoring

If enabled, the function of the app can be monitored by using JConsole. If the Java app is running, and JMX_REMOTE_MONITORING_ENABLED is set to true in configuration, run

jconsole

Since an authentication is necessary, the first connection attempt will fail. Cancel the error message dialog, that appears.

In the dialog window in foreground now...

  • click Remote Process and enter localhost:<port> in the edit field below, whereas <port> is the configured JMX_RMI_REGISTRY_PORT, 33985 by default
  • enter username and password from ./data/config/jmx_password and hit Connect. Default for username and password is accuware and 4711.
  • on the next screen hit Insecure connection, because the JMX server doesn't support SSL. You will be able to monitor memory consumption, threads and CPU utilization of the Java app.

CSV logging

If enabled, the app provides a CSV log of all positions made. This log can be found in the ./data/logs folder and is named positionlog.csv. It has an automatic daily rollover mechanism built in.

The log contains the following info elements, separated by ",". rxx parameters are the elements of the rotation matrix, state is the current positioning state at time of recording (see Get status)

EPOCH-timestamp-in-milliseconds,siteId,levelId,latitude,longitude,altitude,pitch,yaw,roll,r00,r01,r02,r10,r11,r12,r20,r21,r22,x,y,z,state

For example:

549567996549,1005,0,-0.000587,0.014597,-0.022552,-0.032113,-0.184232,0.677457,0.999925,-0.011822,-0.003222,0.011824,0.999930,0.000522,0.003215,-0.000560,0.999995,-8.44,1.21,0.84,NAVIGATION

Note: Not all elements must always be available for a given entry. Please also note the coordinate exchange at the metric coordinates x, y and z (explained in the paragraph Metric coordinates). Our "Z" is the commonly known "Y" and vice versa.

Local web server

By default the app exposes a local web server running at port WEBSERVER_PORT. You are on it if you can see this GUI.

REST API

There is no authentication/authorization support on the REST API currently. However, SSL is supported.

All curl based examples are expecting a WEBSERVER_PORT that is equal to default 5000. The REST API is fully CORS enabled.

Summary

Currently 29 API functions plus 1 websocket interface are supported via REST. None of these functions have to be called mandatorily with the exception of Start positioning and Stop positioning, which are the only ways to start/stop mapping/positioning sessions after the Java app has passed the initialization phase. Just a few of these API functions require Internet connectivity. Those are explicitly mentioned.

API function Purpose
Utilities
GET /api/v1/utils/status Get status
GET /api/v1/utils/errors Get errors
GET /api/v1/utils/config Get config
PUT /api/v1/utils/config Save config
GET /api/v1/utils/encrypt Encrypt string
GET /api/v1/utils/cameras Get list of cameras
PUT /api/v1/utils/restart Restart Java application
PUT /api/v1/utils/terminate Terminate Java application
GET /api/v1/utils/updateinfo Get software update info
Positioning
PUT /api/v1/positioning/start Start positioning
PUT /api/v1/positioning/stop Stop positioning
Mapping (general map information)
GET /api/v1/manage/maps/list Get list of maps
GET /api/v1/manage/maps/list/server Get list of maps from server
PUT /api/v1/manage/maps/reset Reset current map
Mapping (virtual markers)
GET /api/v1/manage/maps/markers Get list of virtual markers
GET /api/v1/manage/maps/markers/:id Get virtual marker
POST /api/v1/manage/maps/markers Create virtual marker
PUT /api/v1/manage/maps/markers/:id Edit virtual marker
DELETE /api/v1/manage/maps/markers/:id Delete virtual marker
Mapping (local operations on a specific map)
POST /api/v1/maps Save current map
GET /api/v1/maps/:map_name Load specific map
DELETE /api/v1/maps/:map_name Delete specific map
PUT /api/v1/maps/:map_name Update specific map
Mapping (map synchronization with server)
GET /api/v1/manage/maps/list/deltas Get a summary of map deltas between client and server
POST /api/v1/manage/maps/sync Sync with server
GET /api/v1/maps/sync Get general sync status
GET /api/v1/maps/sync/:id Get specific sync status
DELETE /api/v1/maps/sync/:id Cancel specific sync process
Mapping (visualization)
GET /api/v1/manage/maps/mappoints Get list of map points

Utility functions

Get Status

Obtain status. Result structure is also available as payload of the websocket status response.

Request-Resource: GET /api/v1/utils/status
curl localhost:5000/api/v1/utils/status -X GET
Response: 200 OK, 'application/json'
{
  "version": "1.4",
  "siteId": "1000",
  "deviceId": "D40K419JW256",
  "state": 1,
  "isStarted": false,
  "mapPointCount": 0,
  "markerCount": 0,
  "loopCount": 0,
  "fps": 0.0
}

Complete list of possible object properties. All of these are optional.

Response-Parameter Type Meaning
version String The version of the Java app and SDK plus the version of the native code plugin separated by '/'
deviceId String The unique device Id. Can be used in Accuware Dashboard for tracking
state Integer The positioning state. 0: Not ready, 1: Idle, 2: Map Initialization, 3: Navigation, 4: Lost, 5: Mapping
isStarted Boolean Whether or not positioning is running
mapPointCount Integer Mapping: Number of map points detected so far in this session
markerCount Integer Mapping: Number of markers detected so far in this session (printed and virtual)
loopCount Integer Mapping: Number of closed loops detected so far in this session
fps Double Camera: Number of frames per second achieved, current value, rounded
latitude Double Navigation: Currently known latitude of device (WGS-84)
longitude Double Navigation: Currently known longitude of device (WGS-84)
altitude Double Navigation: Currently known altitude of device (meters)
pitch Double Navigation: Rotation around the X-axis (degrees), see Pitch, yaw and roll explained
roll Double Navigation: Rotation around the Z-axis (degrees)
yaw Double Navigation: Rotation around the Y-axis (degrees)
x Double Navigation: Metric distance from the origin of the coordinate system along the X-axis in m see Metric coordinates
y Double Navigation: Metric distance from the origin of the coordinate system along the Y-axis in m
z Double Navigation: Metric distance from the origin of the coordinate system along the Z-axis in m
rotationMatrix Double[][] Rotation matrix, see below
levelId Integer Navigation: Currently known level Id of device
currentMapName String Mapping: Currently used map

Note: Depending on the current state, not all response parameter values must be contained in a given response.

Pitch, yaw and roll explained

Pitch, yaw and roll

The rotation matrix is provided as an array of arrays of doubles. More precisely

Double[][] rotationMatrix = new Double[3][3]

or

[
    [    r00,    r01,    r02 ],
    [    r10,    r11,    r12 ],
    [    r20,    r21,    r22 ]
]

Metric coordinates

In addition to the delivery of WGS84 coordinates (latitude, longitude and altitude) metric coordinates are delivered since v. 1.0. Those coordinates are always relative distances in m to the origin (0,0), if there is no other origin specified. This projection is known as ordinary 2D X/Y diagram. Since the Dragonfly axis names differ from the axis names in such a diagram, the following rules apply:

  • take x value as "X", positive values right, negative values left of (0,0)
  • forget about the y value. This value is always equal to the altitude value and cannot be displayed in a 2D diagram
  • mentally rename the z value to "Y", positive values above, negative values below (0,0)

Since the error of this projection can become relatively high and coordinates may become unusable, if the origin is not close enough to a bounding box of the delivered coordinates, there is a documented way to move the origin to another coordinate at Start positioning. The JS GUI makes use of this by providing the center coordinates and rotation of all available floor plans to the core. Now x, y and z are relative distances [m] to the center of a given, internally north-aligned floor plan (even if the real geographical rotation of a floor plan is a completely different one).

Get Errors

Retrieves a list of initialization errors. This API is just providing the errors happened while initializing the Java app part. It does not cover errors happening in the GUI part. API should not be used out of the context of the WebApp, since it doesn't give a complete picture.

Request-Resource: GET /api/v1/utils/status
curl localhost:5000/api/v1/utils/errors -X GET
Response: 200 OK, 'application/json'
{
}

Get config

Retrieve config as provided by ./data/config/dragonfly2.properties configuration file for the Java app.

Request-Resource: GET /api/v1/utils/config
curl localhost:5000/api/v1/utils/config
Response: 200 OK, ConfigurationObject, 'application/json'
{
  "site_id": "some_site_id",
  "site_username": "some_user_name",
  "site_password": "some_password_best_encrypted",
  "log_level": 7,
  "webserver_port": 5000,
  "webserver_ssl_supported": false,
  "webserver_keystore_file": "./data/config/keystore.jks",
  "webserver_keystore_password": "some_keystore_password_best_encrypted",
  "webserver_websockets_enabled": true,
  "jmx_remote_monitoring_enabled": true,
  "jmx_rmi_registry_port": 33985,
  "jmx_rmi_server_port": 33986,
  "audible_status_enabled": true,
  "cam_image_width": 640,
  "cam_image_height": 480,
  "cam_preview_option": 1,
  "cam_fov": 0,
  "cam_source": -1,
  "cam_mode": "mono",
  "cam_calibration_file": "mono.json",
  "map_calibration_method": 3,
  "position_upload_interval": 5000,
  "path_to_chromium": "",
  "position_upload_store": false,
  "position_log_enabled": false,
  "map_fusion_enabled": false,
  "video_recording_enabled": true
}

Note: Not all properties must be included in response payload. The content of the response is the same as documented here, all lower-case.

Response: 400 Bad Request, 'application/json'
{
  "status": "error",
  "errors": [
    "Could not read config"
  ]
}

Save config

Request-Resource: PUT /api/v1/utils/config
curl localhost:5000/api/v1/utils/config -X PUT -d@config_file.json
Request-Parameter: ConfigurationObject, 'application/json'

Note: The payload of the request is a ConfigurationObject as shown in "Get Config". Except "site_id" and "site_username" none of the parameters is mandatory. Any change of configuration parameters requires a restart of the Java app.

Response: 200 OK, ConfigurationObject, 'application/json'
{
  "site_id": "some_site_id",
  "site_username": "some_user_name",
  "site_password": "some_password_best_encrypted",
  "log_level": 7,
  "webserver_port": 5000,
  "webserver_ssl_supported": false,
  "webserver_keystore_file": "./data/config/keystore.jks",
  "webserver_keystore_password": "some_keystore_password_best_encrypted",
  "webserver_websockets_enabled": true,
  "jmx_remote_monitoring_enabled": true,
  "jmx_rmi_registry_port": 33985,
  "jmx_rmi_server_port": 33986,
  "audible_status_enabled": true,
  "cam_image_width": 640,
  "cam_image_height": 480,
  "cam_preview_option": 1,
  "cam_fov": 0,
  "cam_source": -1,
  "cam_mode": "mono",
  "cam_calibration_file": "mono.json",
  "map_calibration_method": 3,
  "position_upload_interval": 5000,
  "path_to_chromium": "",
  "position_upload_store": false,
  "position_log_enabled": false,
  "map_fusion_enabled": false,
  "video_recording_enabled": true
}
Response: 400 Bad Request, 'application/json'
{
  "status": "error",
  "errors": [
    "Configuration could not be saved"
  ]
}

Encrypt string

Function provides encrypted version of a string provided as value in query string. Result can be used everywhere in config, where encrypted values are accepted.

Request-Resource: GET /api/v1/utils/encrypt
curl localhost:5000/api/v1/utils/encrypt -G --data-urlencode "value=password"
Request-Parameter: Query-String
Parameter Meaning Default
value The string to be encoded n.a.
Response: 200 OK, 'text/html'
5D6D8A590CB4BA7E07F8FF84E7EF45E0

Get list of cameras

Function delivers a list of available cameras. The position of each listed camera can be used as parameter "CAM_SOURCE" in configuration, if a specific camera should be selected.

Note: The list of available cameras is not a static list. It changes with the addition/removal of cameras.

Request-Resource: GET /api/v1/utils/cameras
curl localhost:5000/api/v1/utils/cameras -X GET
Response: 200 OK, 'application/json'
[
  "HD Pro Webcam C920 0x14100000046d082d",
  "FaceTime HD Camera DJH4273WRR4F6VTDQ"
]

Restart Java application

Restart Java application. Does work only, if the Java app is launched as JAR (not from IDE)

Request-Resource: PUT /api/v1/utils/restart
curl localhost:5000/api/v1/utils/restart -X PUT
Response: 200 OK, 'application/json'
{
  "status": "success"
}
Response: 400 Bad Request, 'application/json'
{
  "status": "error",
  "errors": [
    "Could not restart Java application"
  ]
}

Terminate Java application

Terminate Java application. Does work only, if the Java app is launched as JAR (not from IDE)

Request-Resource: PUT /api/v1/utils/terminate
curl localhost:5000/api/v1/utils/terminate -X PUT
Response: 200 OK, 'application/json'
{
  "status": "success"
}
Response: 400 Bad Request, 'application/json'
{
  "status": "error",
  "errors": [
    "Could not terminate Java application"
  ]
}

Get software update info

Clients may obtain information about the availability of a new software bundle version. Internally the Java app checks at startup and once per five minutes if there is a new software bundle version available server side. In case it is, the info is traced using the INFO tag to the console:

2019-02-18 13:35:03,841 SoftwareUpdateChecker$1$1 71 INFO  [I/O dispatcher 2]: Dragonfly2SDK:  New application version available: Version: x.xx, Linux download: https://s3.amazonaws.com/navizon.indoors.camera/dragonfly/dragonfly_update_linux_yyyymmdd.zip, macOS download: https://s3.amazonaws.com/navizon.indoors.camera/dragonfly_update_mac_yyyymmdd.zip

In parallel the GUI checks once per minute, if an update is available. In case it is, an alert is popping up once per session, which recommends you to update.

Request-Resource: GET /api/v1/utils/updateinfo
curl localhost:5000/api/v1/utils/updateinfo -X GET
Response: 200 OK, 'application/json'
{
  "version": "x.xx",
  "patch_url_linux": "https://s3.amazonaws.com/navizon.indoors.camera/dragonfly/dragonfly_update_linux_yyyymmdd.zip",
  "patch_url_macos": "https://s3.amazonaws.com/navizon.indoors.camera/dragonfly/dragonfly_update_mac_yyyymmdd.zip"
}
Response: 304 Not Modified

There is no new version available

Positioning

Function provides means to start and stop a positioning session. By using dontmap you advise the software to no longer accumulate mapping data, but navigate on the existing map.

Start positioning

Request-Resource: PUT /api/v1/positioning/start
curl localhost:5000/api/v1/positioning/start -X PUT
curl localhost:5000/api/v1/positioning/start&dontmap=true -X PUT
Request-Parameter: Query-String
Parameter Meaning Default
dontmap true: Disables simultaneous mapping, only navigating on an existing map false
Request-Parameter: Payload, 'application/json'
Parameter Meaning Default
array Optional array of objects, containing the Integer levelId and Double WGS84 coordinates of the origin for the metric projection (origin_lat, origin_lng, origin_alt plus the Double rotation of the floor plan in degrees) n.a.
[
  {
    "levelId": 1,
    "origin_lat": 25.xxxxxx,
    "origin_lng": -80.xxxxxx,
    "origin_alt": 0.0,                              // always 0, ignored
    "rotation": 170.0
  },
  {
    ...
  }
]

The JS GUI is providing this array by specifying the center coordinates of all available floor plans of all possible levels. This generally allows proper metric coordinates, it is not required for ordinary WGS84 projection.

Response: 200 OK, 'application/json'
{
  "status": "success"
}
Response: 400 Bad Request, 'application/json'
{
  "status": "error",
  "errors": [
    "Could not open camera"
  ]
}

Stop positioning

Request-Resource: PUT /api/v1/positioning/stop
curl localhost:5000/api/v1/positioning/stop -X PUT
Result: 200 OK, 'application/json'
{
  "status": "success"
}

Mapping

Functions to list, load, save, edit, reset and delete maps locally plus functions to sync client and server maps.

Get list of maps

Request-Resource: GET /api/v1/manage/maps/list
curl localhost:5000/api/v1/manage/maps/list -X GET
Result: 200 OK, 'application/json'
[
  {
    "map_name": "map1",
    "description": "Room1",
    "checksum": "30b0f2e646e4373c2042de216d9a46be9778b775",
    "status": 1,
    "version": 1,
    "timestamp": 1515495422,
    "owner": "me@accuware.com",
    "access": 0
  },
  {
    "map_name": "map2",
    "description": "Room2",
    "checksum": "f7b6bd202b20d6822d4e36d27a9853ef381bdadf",
    "status": 1,
    "version": 5,
    "timestamp": 1515495422,
    "owner": "me@accuware.com",
    "access": 0
  }
]
Response-Parameter Type Meaning
map_name String The name of the map
description String The description of the map
checksum String 40 byte SHA-1 checksum over the map content
status Integer Status of the map, see below
version Integer Version number, up-counted on every change
timestamp Integer EPOCH timestamp in seconds of last change
owner String Accuware Username of the owner of the map
access Integer Access control flag (not used yet)
status Value Meaning
NOT_SYNCHRONIZED 0 Client map, not synchronized with server
SYNCHRONIZED 1 Client and server map identical

Get list of maps from server

An optional function to obtain a list of maps held by the server for informational purposes. This API function requires an Internet connection.

With the exception of the missing status property the payload returned is identical to the Get list of maps API.

Request-Resource: GET /api/v1/manage/maps/list/server
curl localhost:5000/api/v1/manage/maps/list/server -X GET
Result: 200 OK, 'application/json'
[
  {
    "map_name": "map3",
    "description": "Room3",
    "checksum": "30b0f2e646e4373c2042de216d9a46be9778b775",
    "version": 10,
    "timestamp": 1515495422,
    "owner": "you@accuware.com",
    "access": 0
  }
]
Response: 400 Bad Request, 'application/json'
{
  "status": "error",
  "errors": [
    "No Internet access."
  ]

Reset current map

Resets the currently used map. A running positioning session will be terminated.

Request-Resource: PUT /api/v1/manage/maps/reset
curl localhost:5000/api/v1/manage/maps/reset -X PUT
Response: 200 OK, 'application/json'
{
  "status": "success"
}

Save current map

Put the current map results into a map named by map_name and give it a description. Both request payload parameters are mandatory and pre-processed. Only alphanumeric characters and some special selected characters are allowed (see regular expression below). The length of both parameters is limited. Both parameters are lower-cased, spaces are transformed to _.

Request-Resource: POST /api/v1/maps
curl localhost:5000/api/v1/maps -X POST -H "Content-Type: application/json" -d '{"map_name": "map1", "description":"Map 1"}'
Request-Parameter: Payload, 'application/json'
Parameter Meaning Default
object Object containing mandatory map_name and description as strings. Allowed characters must match this regular expression: ^[0-9a-zA-Z\ _\-\.@]+$ n.a.
Response: 200 OK, 'application/json'
{
  "status": "success"
}
Response: 400 Bad Request, 'application/json'
{
  "status": "error",
  "errors": [
    "The system has not computed a map yet."
  ]
}

Load specific map

Request-Resource: GET /api/v1/maps/:map_name
curl "localhost:5000/api/v1/maps/map1" -X GET
Request-Parameter: URL-Parameter, urlencoded
Parameter Meaning Default
:map_name Mandatory name of the map to be loaded, urlencoded n.a.
Response: 200 OK, 'application/json'
{
  "status": "success"
}

Map has been loaded and will be used for positioning.

Response: 400 Bad Request, 'application/json'
{
  "status": "error",
  "errors": [
    "Map \"map1\" doesn\u0027t exist."
  ]
}

Delete specific map

Deletes the map named by parameter :map_name.

Request-Resource: DELETE /api/v1/maps/:map_name
curl localhost:5000/api/v1/maps/map1 -X DELETE
Request-Parameter: URL-String
Parameter Meaning Default
:map_name Mandatory name of the map to be deleted n.a.
Response: 200 OK, 'application/json'
{
  "status": "success"
}
Response: 400 Bad Request, 'application/json'
{
  "status": "error",
  "errors": [
    "Map \"map1\" doesn\u0027t exist."
  ]
}

Update specific map

Request-Resource: PUT /api/v1/maps/:map_name

Allows to change map_name and/or description of the map named by parameter :map_name.

curl localhost:5000/api/v1/maps/map1 -X PUT -H "Content-Type: application/json" -d '{"map_name": "map1", "description": "New Description"}'
Request-Parameter: URL-Parameter, urlencoded
Parameter Meaning Default
map_name Mandatory name of the map to be deleted n.a.
Request-Parameter: Payload, 'application/json'
Parameter Meaning Default
object Object containing mandatory map_name and description as strings. Allowed characters must match this regular expression: ^[0-9a-zA-Z\ _\-\.@]+$ n.a.
Response: 200 OK, 'application/json'
{
  "status": "success"
}
Response: 400 Bad Request, 'application/json'
{
  "status": "error",
  "errors": [
    "Map \"map1\" doesn\u0027t exist."
  ]
}

Map Synchronization

The purpose of the Map Synchronization process is to achieve equality of the maps held locally (on client) and remotely (on server). On client machines maps are located in the sub directory ./data/maps, grouped by Accuware Site Id. The folders contain zero or more map files (extension .osm) and a maplist.json file, which is used to hold meta data. It is not recommended to directly manipulate either of these files.

The structure below already shows, that the map name must be unique throughout an Accuware Site. The Java app is maintaining a File System Watcher, being triggered by either changes of map meta data (e.g. map_name or description). If Internet access is available at this moment, the Java app internally utilizes the Get a summary of map deltas between client and server API in order to determine the synchronization state between client and server. It reports the results immediately via the websocket status API to the dashboard, which visualizes the results. Version 1.4 just indicates, if a Sync with server request should be issued or not.

In addition the dashboard itself tries once per minute to determine the state to bring it to the user's attention.

.
├── 1000
│   ├── maplist.json
│   └── test.osm
└── 1005
    ├── maplist.json
    └── test.osm

2 directories, 4 files

For the function of the Dragonfly app it is completely sufficient to work with local maps only. Just in case you want to share maps with third parties or do a collaborative creation, utilization or maintenance of maps a synchronization process is necessary, which synchronizes the maps available locally with the maps available server side for a particular Accuware Site.

The REST API Sync with server is intended to provide means to start such a synchronization process.

There are some rules, enforced by the REST server while synchronizing against the Accuware Servers:

Basic rules

  • Maps belong to an owner, which is formed by the currently used Accuware Site Username on creation
  • Only owners are allowed to create, rename and delete a map on the server
  • Anybody is allowed to update meta data of a map and - more importantly - to contribute to the map content (i.e. mapping)

Furthermore these Synchronization rules apply:

Map available Synchronization rule
On client only Maps owned by the user with the currently used Accuware Site Username: Will be created on server
Maps owned by somebody else: Will be deleted on client
On server only Maps owned by the user with the currently used Accuware Site Username: Will be deleted on server
Maps owned by somebody else: Will be created on client
On server and client Maps with a higher client version will be updated on server
Maps with a higher server version will be updated on client

TODO: Maps have unique names, so there cannot be two maps with the same name. However, with version 1.4 there is still a problem with maps, created from different owners, having the same name. The sync process would always let the map with the highest version number win, which in most cases will not show the desired results. This problem needs to be addressed in future versions.

Get a summary of map deltas between client and server

This API can be used in order to get a detailed overview about what is available

  • on client only
  • on server only
  • on client and server

The function internally determines the required actions and displays it. This API is just informational and used internally by the Java app. It is not necessary at all for the synchronization request.

In order to proceed successfully an Internet connection is required.

Request-Resource: GET /api/v1/manage/maps/list/deltas
curl "localhost:5000/api/v1/maps/list/deltas" -X GET
Result: 200 OK, 'application/json'
{
  "status": "success",
  "clientOnly": {
    "createOnServer": [],
    "deleteOnClient": []
  },
  "serverOnly": {
    "createOnClient": [],
    "deleteOnServer": []
  },
  "clientAndServer": {
    "updateOnClient": [],
    "updateOnServer": []
  }
}
Response-Parameter Type Meaning
status String Either "error" or "success"
clientOnly String Container object for maps existing on client only
serverOnly String Container object for maps existing on server only
clientAndServer String Container object for maps existing on client and server
createOnServer Array of String List of map names, which will be created on server on next sync
deleteOnClient Array of String List of map names, which will be deleted on client on next sync
createOnClient Array of String List of map names, which will be created on client on next sync
deleteOnServer Array of String List of map names, which will be deleted on server on next sync
updateOnClient Array of String List of map names, which will be updated on client on next sync
updateOnServer Array of String List of map names, which will be updated on server on next sync
Response: 400 Bad Request, 'application/json'
{
  "status": "error",
  "errors": [
    "No Internet access."
  ]

Sync with server

The synchronization is always a client-initiated process using this API. Because it might need a lot of time (please note: big map files probably have to be up- and downloaded), this function just initiates a synchronization process. In case, no other sync is currently running, it returns immediately, providing an ID, which furthermore can be used to obtain status and result or to cancel a sync process.

Request-Resource: POST /api/v1/manage/maps/sync
curl localhost:5000/api/v1/manage/maps/sync -X POST
Response: 200 OK, 'application/json'
{
  "id": 1
}
Response: 400 Bad Request, 'application/json'
{
  "status": "error",
  "errors": [
    "Sync process with id 1 already running."
  ]
}

Get general sync status

This API call can be used in order to obtain the status of synchronization process.

Request-Resource: GET /api/v1/maps/sync
curl "localhost:5000/api/v1/maps/sync" -X GET
Response: 200 OK, 'application/json'
{
  "status": "not running"
}

Get specific sync status

Obtains the status of a specific synchronization process, identified by parameter :id, previously returned from a Sync with server API call.

Request-Resource: GET /api/v1/maps/sync/:id
curl "localhost:5000/api/v1/maps/sync/1" -X GET
Response: 200 OK, 'application/json'
{
  "status": "finished successfully"
}
Response: 400 Bad Request, 'application/json'
{
  "status": "error",
  "errors": [
    "No sync process with id 1 running."
  ]
}

Cancel specific sync process

Can be used in order to cancel a specific synchronization process, identified by parameter :id, previously returned from a Sync with server API call. This call just abandons a synchronization, it doesn't roll back the results, so the final state might be something "in between" and would probably need another sync request to return to a stable situation.

Request-Resource: DELETE /api/v1/maps/sync/:id
curl "localhost:5000/api/v1/maps/sync/1" -X DELETE
Response: 200 OK, 'application/json'
{
  "status": "cancelled"
}
Response: 400 Bad Request, 'application/json'
{
  "status": "error",
  "errors": [
    "No sync process with id 1 running."
  ]
}

Virtual marker management

Virtual marker operations do always work on the currently loaded and/or used map. A positioning session must be running and in order to make the most functions proceed, the positioning status must have been reached and kept.

Get list of virtual markers

Gets a list of IDs of virtual markers. The IDs can be used in subsequent API calls.

Request-Resource: GET /api/v1/manage/maps/markers
curl localhost:5000/api/v1/manage/maps/markers
Response: 200 OK, 'application/json'
[
  504,
  529
]

Get virtual marker

Get information for the virtual marker for ID :id

Request-Resource: GET /api/v1/manage/maps/markers/:id
curl localhost:5000/api/v1/manage/maps/markers/504
Response: 200 OK, 'application/json'
{
  "latitude": 2.5958528417757048E-5,
  "longitude": -3.495204476621969E-5,
  "altitude": 0.0,
  "levelId": -11
}
Response: 400 Bad Request, 'application/json'
{
  "status": "error",
  "errors": [
    "No reference point data for id 504"
  ]
}

Create virtual marker

Create virtual marker at position.

Request-Resource: POST /api/v1/manage/maps/markers
curl localhost:5000/api/v1/manage/maps/markers -X POST -H "Content-Type: application/json" -d '{"latitude": 0.0, "longitude": 0.0, "altitude": 0.0, "levelId": 0}'
Response: 200 OK, 'application/json'

Returns the ID of a newly created marker or -1

1492
Response: 400 Bad Request, 'application/json'
{
  "status": "error",
  "errors": [
    "Could not add reference point. Positioning must be running and your device must not be in \u0027Lost\u0027 state."
  ]
}

Edit virtual marker

Edit virtual marker with ID :id

Request-Resource: PUT /api/v1/manage/maps/markers/:id
curl localhost:5000/api/v1/manage/maps/markers/1492 -X PUT -H "Content-Type: application/json" -d '{"latitude": 0.0, "longitude": 0.0, "altitude": 1.0, "levelId": 0}'
Response: 200 OK, 'application/json'
{
  "status": "success"
}
Response: 400 Bad Request, 'application/json'
{
  "status": "error",
  "errors": [
    "Could not edit reference point. Positioning must be running and your device must not be in \u0027Lost\u0027 state."
  ]
}

Delete virtual marker

Deletes virtual marker with ID :id

Request-Resource: DELETE /api/v1/manage/maps/markers/:id
curl localhost:5000/api/v1/manage/maps/markers/1492 -X DELETE
Response: 200 OK, 'application/json'
{
  "status": "success"
}

Visualization of mappoints

This API is providing useful results only under special conditions:

  • The configuration parameter MAP_CALIBRATION_METHOD must be set to 0
  • A mapping and positioning session must be running

The results are used internally to visualize the quality of mapping.

Get list of map points

Gets a list of map points.

Request-Resource: GET /api/v1/manage/maps/mappoints
curl localhost:5000/api/v1/manage/maps/mappoints
Response: 200 OK, 'application/json'
[
  0.4075704,
  0.14189786,
  0.52664083,
  -0.3725887,
  -0.18158877,
  0.26187122,
  -0.27079827,
  -0.24362804,
  0.6445207,
  0.1305532,
  0.39491752,
  ....
]
Response: 400 Bad Request, 'application/json'
{
  "status": "error",
  "errors": [
    "This API is available only if MAP_CALIBRATION_METHOD is configured to be 0"
  ]
}

Websocket to push general and map synchronization status

As convenience method for obtaining general and map synchronization status in real time the REST web server provides a websocket based status push service. The URL is ws://localhost:5000/websockets/status. The provided information matches generally the response payload of the Get Status and the Get a summary of map deltas between client and server REST API functions. However, due to the necessary discrimination between different payload types, an additional context identifier has been added (see samples below).

In case SSL is enabled on the web server, use wss://localhost:5000/websockets/status

Note: WEBSERVER_WEBSOCKETS_ENABLED must be true in ./data/config/dragonfly2.properties and the Java app must have started a positioning session. There is currently no websocket status update outside a positioning session (see Positioning), use ordinary Get Status in this case.

There are several ways to contact the web server for a websocket connection:

1. The CURL approach

curl --include \
     --no-buffer \
     --header "Connection: Upgrade" \
     --header "Upgrade: websocket" \
     --header "Host: localhost:5000" \
     --header "Origin: http://localhost:5000" \
     --header "Sec-WebSocket-Key: SGVsbG8sIHdvcmxkIQ==" \
     --header "Sec-WebSocket-Version: 13" \
http://localhost:5000/websockets/status

Note: The console will show the raw websocket output

There are currently three different payloads carried via the websocket connection:

  • General status information
  • Map delta information
  • Image information (in case CAM_PREVIEW_OPTION contains the bit for the Javascript display)

An example payload for a General status report looks like so:

Note: Depending on the current state, status may contain not all shown properties or even more.

}?~?{
  "status": {
      "version": "1.4/2.1-b19",
      "siteId": "1000",
      "deviceId": "D40K419JW256",
      "state": 2,
      "isStarted": true,
      "mapPointCount": 0,
      "markerCount": 0,
      "loopCount": 0,
      "fps": 20.2429141998291
    }
}?~?{
  "status": {
      "version": "1.4/2.1-b19",
      "siteId": "1000",
      "deviceId": "D40K419JW256",
      "state": 2,
      "isStarted": true,
      "mapPointCount": 0,
      "markerCount": 0,
      "loopCount": 0,
      "fps": 20.2429141998291
    }
}?~?{
  "status": {
      "version": "1.4/2.1-b19",
      "siteId": "1000",
      "deviceId": "D40K419JW256",
      "state": 2,
      "isStarted": true,
      "mapPointCount": 0,
      "markerCount": 0,
      "loopCount": 0,
      "fps": 20.2429141998291
    }
    ...

An example Map Delta report (see Map Synchronization) is indicated like so:

}?~({
  "deltas": {
    "status": "success",
    "clientOnly": {
      "createOnServer": ["map1"],
      "deleteOnClient": []
    },
    "serverOnly": {
      "createOnClient": [],
      "deleteOnServer": []
    },
    "clientAndServer": {
      "updateOnClient": [],
      "updateOnServer": []
    }
  }
}

For a description of the content see Get a summary of map deltas between client and server REST API.

An example payload for an Image report looks like so:

}?~({
  "image": {
    ...Base64 encoded JPG image payload...
  }
}

Since the payload is BASE64 JPG it can directly been put into an HTML image tag (e.g. with ReactJS):

<img id="videoPreview" alt="Video Preview scaled down to 320x240" width="320" height="240" src={"data:image/jpg;base64," + this.state.image} />

2. The Chrome approach

There is a variety of Chrome plugins supporting websockets. One of them is this. Install and enter the above mentioned status websocket URL into the address field.

More info

Find usage information and more check here

This documentation is also available online as secret gist.

Backup

WebRTC details

With WebRTC

  • we can literally "mount" the camera of a Raspberry PI by either directly interacting with the UV4L server on the PI (possible, if the PI is on the same network or publicly available) or by utilizing the signaling server functions of the Accuware WebRTC Demo server on the web, which would allow us to reach any PI in the world, as long as there is a possible path through the Internet,
  • we can literally mount any WebRTC enabled device or browser, as long as it is enable to talk to our signaling server. The protocol is simple, we provide a description on demand. This includes DJI drones. By use of the controlling Android app (iOS on demand) we can "WebRTC" the real-time video of a DJI drone to any consumer at any place in the world with latencies below 1 second.

Please have a look at the online help of the Accuware WebRTC Demo server and learn about the principles of WebRTC operation. Try it out. There is also a licensed version, which allows you to test the DJI drone connection, if you are an Android developer (Accuware WebRTC Demo, Licensed Edition)

Details on how to use a WebRTC bound camera within the Dragonfly Java app can be found in section "CAM_SOURCE explained".

RTP streaming from Raspberry PI

Accuware Gist

RTSP streaming from Raspberry PI

Accuware Gist

WebRTC streaming from Raspberry PI

Accuware Gist

WebRTC streaming from Raspberry PI using UV4L directly

Accuware Gist

Create and deploy a self-signed certificate for the Raspberry PI

Accuware Gist

Pre-configured calibration files for download

If you don't want to perform the calibration of your camera, you might find your specific calibration file here. Please download the appropriate file, copy it into the Dragonfly's ./data/config/ directory and configure the filename in the configuration parameter CAM_CALIBRATION_FILE.

Calibration file for Raspberry Pi camera module

Amazon Link

Calibration file

Calibration file for Raspberry SainSmart Wide Angle Fish-Eye

Amazon Link

Calibration file

Calibration file for Logitech C920 HD Pro Webcam

Amazon Link

Calibration file

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.