Skip to main content

Live streaming data

The platform allows Manager users to get a live feed of of data updates for a given device, or for all devices in an ongoing activity.

The streaming API is accessible using the Websocket protocol.

There are three websocket endpoints:

  • wss://api.asi.swiss/ws/v1/computed-data/{activity}/{timeframe}/ : metrics for a single athlete
  • wss://api.asi.swiss/ws/v1/computed-data/{activity}/ : metrics for all athletes in an activity
  • wss://api.asi.swiss/ws/v1/preprocessed-data/{device}/ : sensor data for a single device

All of these endpoints have the same authorization mechanism.

caution

Live data could also be implemented using synchronous (polling) requests to the latest-preprocessed-data endpoint. While this may work for a couple devices during testing, it will not scale well for a production use case. The reason is that it is inefficient, and you may encounter issues related to rate-limiting. Therefore, we highly encourage you to use websockets whenever possible.

This is a more conceptual overview of the live streaming protocols. For more specific details, check out the reference page.

Authorization

Connecting to the websocket endpoint requires an access token for the Manager user that owns the device or activity, or has a READ permission on the timeframe.

The diagram below illustrates the initial message exchanges on a newly initialized websocket connection, that allow the client to provide its token to the server:

The first message ("Authorization needed") can be ignored by the client, meaning that the token can be sent before receiving it.

caution

The API allows all incoming connections to the websocket endpoints (with some possible rate limiting), however, the authentication message containing the access token must be sent by the client within the first 3 seconds. Otherwise, the connection is closed.

Computed data by athlete

The platform allows Manager users to get a live stream of computed data for an ongoing activity, given a timeframe identifier, on the url wss://api.asi.swiss/ws/v1/computed-data/{activity}/{timeframe}/.

  • activity (integer) is the activity identifier
  • timeframe (integer) is the timeframe identifier

Important: Manager user must have a read permission on the Athlete linked to the Time frame to live stream their data.

Computed data messages are JSON documents containing the computed data. For example:

{
"total_distance": 83.20118419047552,
"accelerations": {
"threshold_2": {
"threshold": 3,
"values": []
},
"threshold_1": {
"threshold": 2,
"values": []
}
},
"decelerations": {
"threshold_2": {
"threshold": 3,
"values": []
},
"threshold_1": {
"threshold": 2,
"values": []
}
},
"max_speed": 1.1826,
"average_speed": 0.20038889929742307,
"last_timestamp": 1597924127900.0
// other data
}

Note: computed data may vary depending on the activity and time frame configurations.

Computed data by activity

It is also possible to subscribe to all computed data concerning an activity. In that case, the path that needs to be used is /ws/v1/computed-data/{activity}/. The Manager is allowed to stream theses data if he's allowed to stream every activity's time frames computed data.

Computed data are still processed for each time frame, so messages received through this socket concerns only one time frame per message. Each message has a timeframe key containing the time frame ID for which computed data are processed.

For example:

{
// Time frame id
"timeframe": 86,
// Computed data for this timeframe
"data": {
"total_distance": 83.20118419047552,
"accelerations": {
"threshold_2": {
"threshold": 3,
"values": []
},
"threshold_1": {
"threshold": 2,
"values": []
}
},
"decelerations": {
"threshold_2": {
"threshold": 3,
"values": []
},
"threshold_1": {
"threshold": 2,
"values": []
}
},
"max_speed": 1.1826,
"average_speed": 0.20038889929742307,
"last_timestamp": 1597924127900.0
}
}
caution

This feature is currently not designed for large-scale activities. If your use-case potentially involves tracking more than about 30 devices in a single activity, please contact our API support team. This functionality is currently being tested in specific projects, and will eventually be available on our public platform.

Preprocessed data

Similary to computed data, managers can also subscribe to a WebSocket stream of preprocessed data for a given device. The path is /ws/v1/preprocessed-data/{device}/.

Important: Manager user must be the device owner when he subscribe to the WebSocket.

Authentication works the same as with computed data, previously explained.

Parameters

In addition to the token key in the authentication message, an optional params key can be specified.

For example:

{
"token": "your_token",
"params": {
"buffer_size": 10,
"drop_older": true,
"flush_timeout": 20
}
}

By default, messages are forwarded to the WebSocket client as soon as they are ready, without any guarantee of arriving in the right order. This problem is inherent to the real-time and distributed architecture but can be mitigated by setting the parameters such that the messages are buffered and reordered first. If buffer_size is set to some value n > 0, the last n messages are held in the buffer and the oldest (according to its timestamp) is released when the buffer exceeds n messages. This ensures the right ordering of messages up to the last n messages. By default, buffer_size is set to 0 meaning that no buffering is performed.

Note: buffering n messages implies a delay of about n seconds.

If a message arrives that is older than the last forwarded message (meaning it is about n seconds late at least), it will still be forwarded unless drop_older is set to true, in which case it is simply dropped. Dropping these messages is the only way to completely guarantee the right order.

To ensure all messages are forwarded even after device disconnection, the buffer is flushed (in the right order) after flush_timeout seconds.

The following table explains the params utility

ParamPossible valuesDefaultDescription
buffer_sizeinteger in [0,60]0Size of reordering buffer
drop_oldertrue | falsefalseControl if incoming message older than the last forwarded one should still be sent or dropped
flush_timeoutinteger in [2,62]10Timeout after which the messages in the buffer will be forwarded, should be greater or equal to buffer_size + 2

Note: in most cases, when messages arrive in wrong order without any params, it is just one message arriving right after its successor. So, a buffer of size 3 would cover a majority of cases, and the delay is not so big (~ 3 seconds)