WebSocket API

subscribe to a live sensor data feed

The event-based, real-time WebSocket API is used to subscribe to a live sensor data feed, removing the need to pull the data periodically. For new data inserts, meaning that whenever sensor data is retrieved, a message is sent to all subscribers for that specific sensor. Device data is stored in an append-only format, therefore all measurements stored in the akenza database lead to new data inserts. An API client (hereafter Client) can either subscribe to multiple devices at once or to individual device as seen fit.

For using the WebSocket API, data needs to be stored in the akenza database using either the akenza database output connector or Custom akenza database rule action.

The Client calls wss://api.akenza.io/v3/data-streams (note that the base URL for private deployments of akenza is different) in order to open a new WebSocket session on the server. The client will get the following response initially if the connection has been successfully established:

{
"type": "connected",
"message": "greeting message",
"timestamp": "ISO-8601 timestamp"
}

Authentication

There are multiple forms of authentication:

  • Using the URL-Param “access_token” with a valid JWT token for the initial connection (recommended). The OAuth2 access token is retrieved from the akenza Auth service via standard flow (authorization code or implicit)

  • Using the URL-Param “xApiKey” for API-Keys for the initial connection. An API-Key can be created on akenza

For deferred subscriptions, the Client needs to send the access token alongside the message in the property “accessToken” when sending a subscribe message. This will ensure that the client always sends a valid JWT to the server with which it can ensure the proper permission handling. If “accessToken” is not set, the server will fall back to the initially provided token via URL-Param. Depending on token lifetime, this can lead to unexpected permission check failures.

Subscribing to Asset Data Change Streams

The Client can send the following message to the server to get live updates about the respective device data.

{
"type": "subscribe/unsubscribe",
"id": "messageId", // optional but strongly encouraged
"subscriptions": [
{
"assetId": "akenzaDeviceId", // can only be set if tagId is not set
"tagId": "tagId", // can only be set if assetId is not set
"topic": "the topic" // optional, default "default", use * for all topics
}
],
"accessToken": "JWT-Token"
}

The provided asset ID corresponds to the Akenza ID on akenza that is used as a virtual identifier for the sensor. The id is a unique message identifier that is returned in the response.

If the subscription was initialized correctly, the server will respond with the following acknowledge message:

{
"type": "subscribed",
"replyTo": "messageId",
"subscriptions": [{ ... // same as above }, ... ], // contains all open subscriptions, sorted by assetId
"timestamp": "ISO-8601 timestamp"
}

Note:

  • calling unsubscribe with subscriptions will unsubscribe only the given assetId-topic combination from the change stream

  • calling unsubscribe with no subscriptions will cancel all subscriptions. The connection to the Client will remain opened

  • calling subscribe multiple times for an asset with different topics creates a new subscription. If the same assetId-topic combination is requested multiple times, the server just acknowledges it but doesn’t create a new subscription on the change stream

  • calling subscribe for an asset with wildcard topic (*) will create subscription with only assetId and no criteria for topic

  • calling subscribe with no subscriptions will return an error

  • calling subscribe with a tagId will create a change stream subscription for all assets with this tag. In a future update, the subscription will automatically update if an asset is added the tag. Until further notice however, the subscriptions needs to be cancelled and re-created

Sample Received Event

The following message is sent from the server to the Client after a new sample has been received for one of the active subscriptions:

{
"type": "sample_insert",
"sample": {
"deviceId": "theAkenzaDeviceId",
"topic": "topic",
"timestamp": "ISO-8601 timestamp",
"data": {
... // the actual asset data
}
},
"timestamp": "ISO-8601 timestamp"
}

The actual data format can be configured using the uplink scripts on akenza.

Message consistency

Data points are not guaranteed to be sent in the right order (time of arrival), the ordering has to be done by the Client. If the connection between the Client and Server fails for some reason (disconnect), the missing data for this time period has to be reloaded.

Errors

If an error occurs, a message in the following format is returned:

{
"type": "error",
"replyTo": "messageId", // if applicable
"errorCode": "WebSocket error code", // if applicable
"errorId": "Akenza errorID",
"message": "the error message",
"timestamp": "ISO-8601 timestamp"
}

Ping-Pong

In order to keep the connection alive, the Client should send a ping message every 30 seconds. If the Client does not support the WebSocket ping specification, the following message should be sent:

{
"type": "ping",
"id": "messageId", // optional but strongly encouraged
}

When a Client sends a ping command in order to keep the connection alive, the server responds with the following message. Pong messages can be ignored by the Client since they do not hold any significant information:

{
"type": "pong",
"replyTo": "messageId", // if applicable
"timestamp": "ISO-8601 timestamp"
}