WebSocket API
Overview
This section describes the general Websocket publish / subscribe concept for connecting Location Cores and client services, and to exchange messages and events over a Websocket connection.
General omlox™ Publish / Subscribe Concept
Applications can subscribe and unsubscribe themselves to named topics. Data published to a topic will be received by all subscribers of that topic. All data sent to and received from the WebSocket connection is wrapped into the payload property of the wrapper object detailed in the next section.
To subscribe to a topic, the application sends a json encoded message. The server generates a response, either acknowledging a successful subscription / unsubscription or returns an error message.
The server also generates a subscription_id for a successful subscription. This allows an application to subscribe itself to the same topic multiple times with differing parameters and control each subscription separately. Subscriptions are otherwise automatically terminated when the websocket connection is closed.
Topics
The following named topics are available:
location_updates
This topic is used to retrieve real-time location updates, as well as sending location updates to the hub. Location data received by the hub is processed and then forwarded to all subscribers of this topic.
When receiving data for this topic, the payload of the wrapper object contains omlox™ Location objects.
location_updates:geojson
This topic is similar to location_updates, but instead of an omlox™ Location object GeoJson feature collections are returned as payload.
When receiving data for this topic, the payload of the wrapper object contains GeoJson feature collections.
collision_events
This topic is used to retrieve real-time collision events. The hub checks trackable movements for collisions and sends collision events when trackables: start to collide, continue to collide and end a collision.
When receiving data for this topic, the payload of the wrapper object contains omlox™ CollisionEvent objects.
fence_events
This topic is used to inform subscribers about geofence entry and exit events. The hub implementation checks location providers and trackables for fence events and sends appropriate events to subscribers of this topic immediately for each fence entry and fence exit event.
When receiving data for this topic, the payload of the wrapper object contains omlox™ FenceEvent objects.
fence_events:geojson
This topic is similar to fence_events, but instead of an omlox™ FenceEvent object, GeoJson feature collections are returned as payload.
When receiving data for this topic, the payload of the wrapper object contains GeoJson feature collections.
trackable_motions
This topic informs subscribers about movements of an omlox™ Trackable. For example, when one of the assigned omlox™ Location Providers changes its position.
When receiving data for this topic, the payload of the wrapper object contains omlox™ TrackableMotion objects.
provider_changes, trackable_changes, fence_changes, zone_changes, anchor_changes
These topics inform subscribers about changes of objects of the specified type.
They contain a field event_type
further specifying whether the change event is of type create, update, or delete.
For create and update events, the payload contains the new (updated) version of the object.
For delete, the payload contains the id of the deleted object.
Furthermore, they contain a field timestamp
that contains the timestamp the DeepHub associates with the event.
WebSocket Data Objects
Data between client and server are exchanged using a wrapper object with the following structure:
Name | Type | Description |
---|---|---|
event | string | Any of message , subscribe , subscribed , unsubscribe , unsubscribed |
topic | string | Topic name |
subscription_id | int | The concrete topic subscription which generated the data |
payload | array | An array containing valid omlox™ data objects (or empty) |
params | object | An optional object containing key-value pairs of parameters. Parameters usually match their REST API counterparts |
The field event
is always required for all data exchanged between client and server. Other fields are required depending on the event type. Concrete event based data structures are detailed in the respective sections below.
Example data object containing an omlox™ location object as payload:
{
"event": "message",
"topic": "location_updates",
"subscription_id": 123,
"payload": [
{
"position": {
"type": "Point",
"coordinates": [5, 4]
},
"source": "fdb6df62-bce8-6c23-e342-80bd5c938774",
"provider_type": "uwb",
"provider_id": "77:4f:34:69:27:40",
"timestamp_generated": "2019-09-02T22:02:24.355Z",
"timestamp_sent": "2019-09-02T22:02:24.355Z"
}
]
}
In case of an error, the server sends a json object with event type error
and the following data structure:
Name | Type | Description |
---|---|---|
event | string | Will be error for an error object |
description | string | A human readable error message |
code | int | Error code |
Example error object:
{
"event": "error",
"description": "Invalid data. The location data contains an invalid Position.",
"code": 10005
}
The error code can be used by applications to discern the type of the error, e.g. for error handling and messaging on the application side.
Possible error codes:
- 10000: Event type is unknown
- 10001: Unknown topic name
- 10002: Subscription failed
- 10003: Unsubscribe failed
- 10004: Not authorized
- 10005: Invalid payload data
- 10006: Not authenticated
- 10007: Invalid license
Subscribing to a Topic
Subscribing to a topic opens a connection to the websocket endpoint at e.g. ws://localhost:8081/deephub/v1/ws/socket. After successfully connecting, the client sends a subscribe request message to the server.
The subscribe request has the following structure:
Name | Type | Description |
---|---|---|
event | string | subscribe |
topic | string | Name of the topic, e.g. location_updates or fence_events |
params | object | An optional object containing key-value pairs of parameters. Parameters usually match their REST API counterparts |
An example subscribe request to the location_updates topic:
{
"event": "subscribe",
"topic": "location_updates",
"params": {
"crs": "EPSG:4326"
}
}
Example subscribe request to fence events:
{
"event": "subscribe",
"topic": "fence_events"
}
Successful Subscription Response
The server responds to the subscribe request either with a success response or an error response. Upon successful subscription, the server responds with a subscribed
event, a copy of the subscribed topic as well as the subscription_id for the concrete subscription.
It's important to keep the provided subscription_id on the client side in case the client wants to maintain multiple subscriptions to the same topic with different parameters. A client may however simply close it's connection, and all it's subscriptions will be cleaned up on the server side.
The subscription response has the following structure:
Name | Type | Description |
---|---|---|
event | string | On success subscribed |
topic | string | Name of the topic |
subscription_id | int | Topic subscription id |
Example server response for a successful subscription request:
{
"event": "subscribed",
"topic": "location_updates",
"subscription_id": 123
}
Unsubscribing
To unsubscribe, a client must either close the connection, or send an unsubscribe request with a concrete subscription id to the server.
The unsubscribe request has the following structure:
Name | Type | Description |
---|---|---|
event | string | Must be unsubscribe |
subscription_id | int | Topic subscription id to unsubscribe from |
Example unsubscribe object:
{
"event": "unsubscribe",
"subscription_id": 123
}
Unsubscribe Response
With a successful unsubscription, the server responds with an unsubscribed
event.
Unsubscribe event structure:
Name | Type | Description |
---|---|---|
event | string | Must be unsubscribed |
topic | string | Name of the topic |
subscription_id | int | Topic subscription id from which the application was successfully unsubscribed |
Example unsubscribe server response:
{
"event": "unsubscribed",
"topic": "location_updates",
"subscription_id": 123
}
Filtering & Subscription Parametrization
The publish / subscribe API allows to filter and transform data feeds by setting parameters as key / value pairs to the params section of a subscription request. The following example shows a subscription request to trackable motions with location data projected to UTM 32 (EPSG:32632) and filtering for a certain trackable id:
{
"event": "subscribe",
"topic": "trackable_motions",
"params": {
"crs": "EPSG:32632",
"id": "0b680db2-b39b-45be-be77-40d7d2296cb4"
}
}
Note: There can be any number of active subscriptions made by the same client to a topic. For example, it's possible to make two distinct subscriptions to the location_updates topic, where each subscription may filter for a different location provider. However, subscribing to the same topic with the same parameters twice will result in a subscription error.
The following parameters are available for the respective WebSocket topics.
Parameters for location_updates Topic
param | Type | Description |
---|---|---|
provider_id | string, array | Filter events matching the given provider ID |
source | string | Filter events based on the source of the location (caution: foreign_id and zone_id are not cross-matched) |
provider_type | string | Filter by omlox provider type (e.g., uwb, wifi, rfid) |
associated | boolean | Filter events which are currently associated to an infrastructure (e.g., relevant for wifi systems) |
accuracy | number | Filter events where the location's accuracy is better (less) than or equal to the value provided |
floor | number | Filter events where the location's floor matches the provided value |
crs | string | Project location data to the given crs. Any crs supported by omlox can be set (e.g., local, EPSG:32632) |
zone_id | string | The zone_id used for calculating the local coordinates, if crs is set to local. |
Parameters for trackable_motions Topic
param | Type | Description |
---|---|---|
trackable_id | string, array | Filter events matching the given trackable ID |
id | string, array | Same as trackable_id (omlox name) |
provider_id | string, array | Filter events matching the provider ID |
name | string | Filter events matching the trackable name |
accuracy | number | Filter events where the accuracy of the trackables motion's location is better (less) than or equal to the value provided |
floor | number | Filter events where the floor of the trackable motion's location matches the provided value |
crs | string | Project location data to the given crs. Any crs supported by omlox can be set (e.g., local, EPSG:32632) |
zone_id | string | The zone_id used for calculating the local coordinates, if crs is set to local. |
Parameters for fence_events Topic
param | Type | Description |
---|---|---|
fence_id | string, array | Filter events matching the given fence ID |
foreign_id | string, array | Filter events matching the given foreign ID |
provider_id | string, array | Filter events matching the provider ID which caused the fence event |
trackable_id | string, array | Filter events matching the trackable ID which was involved in the fence event |
event_type | string | Filter for fence entry (region_entry ) or fence exit (region_exit ) events |
object_type | string | Filter events by object type (one of trackable or location_provider ) |
Parameters for collision_events Topic
param | Type | Description |
---|---|---|
collision_id_1 | string | Filter events where one item of the collision pair matches a given id (e.g., trackable ID involved in the collision) |
collision_id_2 | string | Same as collision_id_1. Note: When both collision_id_1 and collision_id_2 are set, events will effectively be filtered for collisions between these two trackables |
object_id_1 | string | Same as collision_id_1 (omlox name) |
object_id_2 | string | Same as collision_id_2 (omlox name) |
collision_type | string | Filter events by collision type. One of collision_start, colliding, collision_end |
floor | number | Filter events where the floor of both collisions matches the provided value |
Parameters for provider_changes, trackable_changes, fence_changes, zone_changes, anchor_changes Topics
param | Type | Description |
---|---|---|
id | string, array | Filter the events based on the id of the associated object |
event_type | string | Filter events based on the event type. Supported event types are: create , update , and delete |
Sending Data via WebSocket
A client can send / publish data to the server directly over the websocket connection without a subscription. For example, a client can send raw location data to the location_updates topic; the server processes the data in the same way as the /providers/locations API and then publishes the processed location data to subscribers of the location_updates topic.
The message sent to the DeepHub must have the following structure:
Name | Type | Description |
---|---|---|
event | string | Must be message |
topic | string | Must be either location_updates or proximity_updates |
payload | array | An array containing topic specific omlox entities |
Examples
Example message for the location_updates topic:
{
"event": "message",
"topic": "location_updates",
"payload": [
{
"position": {
"type": "Point",
"coordinates": [5, 4]
},
"source": "fdb6df62-bce8-6c23-e342-80bd5c938774",
"provider_type": "uwb",
"provider_id": "77:4f:34:69:27:40"
}
]
}
Example message for the proximity_updates topic:
{
"event": "message",
"topic": "proximity_updates",
"payload": [
{
"source": "fdb6df62-bce8-6c23-e342-80bd5c938774",
"provider_type": "rfid",
"provider_id": "77:4f:34:69:27:40"
}
]
}
Authorization
When authorization is enabled, each message sent to the DeepHub must contain a JWT token in the params section.
The access token must be given in the token
field and an additional (topic dependent) field like fence_id
may be provided and will be checked for ownership.
For a topic subscription, this results in the following example message:
{
"event": "subscribe",
"topic": "fence_events",
"params": {
"token": "eyJhbG...",
"fence_id": "..."
}
}
Messages from a subscription will only be received if the permissions and ownership of the involved resources are satisfied in accordance to the required ownership.
Sending a location update via websocket presents the same requirements.
However, providing an additional field provider_id
is NOT supported.
This is an example of a location update:
{
"event": "message",
"topic": "location_updates",
"params": {"token": "eyJhbG..."},
"payload": [{...}]
}
Details on how to configure the DeepHub for authentication with Websocket can be found here.