Using widgets and REST sinks for traffic data retrieval
Learn how your applications can use the REST API to query for traffic data.
Widgets and REST sinks were introduced in the [general article][intro] as programming elements that allow your application to query the server for traffic data using its REST API. In this article, the concept is explored further.
As trajectories pass through operators, they change the operators’ internal values like statistical information about speeds and accelerations. These internal values are called attributes. Currently, all operators have the same kinds of attributes, but in the future, some new attributes will be relevant only for some types of operators. You'll find information about different attributes and their associated sink types in the dedicated articles about [widget types][wtypes] and [sink types][stypes].
The typical procedure for your application would be to request an array of all defined widgets or sinks and then periodically request data from outputs that are currently of interest to it. The following sections illustrate these steps using HTTP and JSON requests.
Working with widgets over the REST API is the same as with REST sinks. They just have different endpoints and widgets can be visualized on the FLOW Insights' dashboard. They share an ID pool, so it's impossible for a sink and a widget to have the same ID within the same analytic.
Getting a list of all widgets
Method: GET
URI:/cubes/{cube_id}/analytics/{analytic_id}/widgets
Query string parameters:
timestamp_format—can only be empty or have the "iso8601" string value. If it's not set, all timestamps in the response body will be in the milliseconds since epoch format. If the "iso8601" value is set, all timestamps will be in the ISO 8601 format, specifically in the formatyyyy-MM-ddTHH:mm:ss.zzzZ, whereyyyyis the year as a four-digit numberMMis the month as a number with a leading zero (01 to 12)ddis the day of the month as a number with a leading zero (01 to 31)Tis a literal separator for the time part of the DateTime stringHHis the hour with a leading zero (00 to 23)mmis the minute with a leading zero (00 to 59)ssis the whole second, with a leading zero (00 to 59)zzzis the fractional part of the second, to millisecond precision, including trailing zeroes where applicable (000 to 999)Zis a literal character denoting the UTC timezone
Keep in mind that using the ISO 8601 format is computationally demanding for the FLOW block and may delay the response by a few milliseconds depending on the number of required timestamp conversions.
Example response body:
{
"sequence_number": "36",
"timestamp": "1745926459560",
"widgets": [
{
"id": 0,
"name": "No. of Speeding Vehicles",
"output_value_type": "value",
"operator_attribute": "object_count",
"history": {
"enabled": true,
"policy": "fixed_interval",
"interval": "1000"
},
"history_capacity": 100000,
"history_start_timestamp": "0",
"history_end_timestamp": "1745926459600",
"history_records_count": 17614,
"current_configuration_history_start_timestamp": "0",
"current_configuration_history_end_timestamp": "1745926459600",
"current_configuration_history_records_count": 17614,
"tags": []
},
{
"id": 1,
"name": "Speed Statistical Widget - North Gate",
"output_value_type": "statistical_value",
"operator_attribute": "speed",
"history": {
"enabled": true,
"policy": "on_value_change"
},
"history_capacity": 100000,
"history_end_timestamp": "1745926376840",
"history_records_count": 14,
"history_start_timestamp": "1745921708760",
"current_configuration_history_start_timestamp": "1745921708760",
"current_configuration_history_end_timestamp": "1745926376840",
"current_configuration_history_records_count": 14,
"tags": []
},
{
"id": 2,
"name": "custom_heatmap",
"output_value_type": "heatmap",
"operator_attribute": "speed_map",
"history": {
"enabled": false
},
"tags": []
}
]
}Comments:
sequence_numberrefers to the current analytic. You can look at it as the analytic’s version—editing the analytic increments the number. Your application needs to send this number in all output requests. Obtaining the current sequence number is explained in the [article about the basics of FLOW's REST API][basic_comm]. Note that the sequence number will always be a string.timestampis the timestamp of the frame from which the data in the response have been evaluated. The frame (and its timestamp) is provided by the FLOW NODE. If e.g. the output's analytic would be disabled, this timestamp won't be updated.- The cubes and analytics part of the URI is explained in the [article about the basics of FLOW's REST API][basic_comm].
- For details about individual widget types and their properties in this output, see their dedicated sections.
historydescribes whether history is being saved by the output and if yes, what policy is being used. History policies are described in a [later article][hist]. Possible values areon_value_change,on_time_change, andfixed_interval. If the policy is set tofixed_interval, thenintervalcontains the interval length in milliseconds.history_start_timestamprefers to the origin time of the oldest snapshot of this output stored in the BLOCK. A zero or an empty string means that history is being recorded since the start of the analytic when its time wasn't yet properly initialized. See the Getting the history of widget values section for more details.- Likewise,
history_end_timestamprefers to the time of the most recent snapshot.history_records_countis the number of saved snapshots. Properties with thecurrent_configuration_prefix refer to the part of snapshot history that was created after the most recent analytic configuration change (sequence number change). operator_attributeis the attribute of the operator to which the widget is attached. This attribute is read and sent by the widget. Attributes are further explained in the next guide .tagsis a list conatining all tags assigned to the widget. Currently, only one tag can be assigned to each widget. For information about tags and their usage, see their dedicated article .
Getting outputs of selected widgets
Method: POST
URI:/cubes/{cube_id}/analytics/{analytic_id}/widgets/data
Query string parameters:
timestamp_format—see Getting a list of all widgets for details
Example request body:
{
"sequence_number": "36",
"widgets": [
{
"id": 0
},
{
"id": 1,
}
]
}Example response body:
{
"sequence_number": "36",
"settings_sequence_number": "0",
"timestamp": "1619088804432",
"widgets": [
{
"id": 0,
"name": "Speed - Value",
"output_type": "widget",
"output_value_type": "value",
"operator_attribute": "object_count",
"output_value_sub_type": "unknown",
"data_end_timestamp": "1619088804432",
"data_start_timestamp": "1619088624709",
"analytic_id": 0,
"cube_id": 0,
"tags_ids": [],
"data": {
"data_validity": "ok",
"evaluation_validity":"ok",
"object_count": 32,
"value": 2
}
},
{
"id": 1,
"name": "Speed - Statistical value",
"output_type": "widget",
"output_value_type": "statistical_value",
"operator_attribute": "speed",
"output_value_sub_type": "unknown",
"data_end_timestamp": "1619088804432",
"data_start_timestamp": "1619088624709",
"analytic_id": 0,
"cube_id": 0,
"tags_ids": [],
"data": {
"average": 11.363175912117441,
"data_validity": "ok",
"evaluation_validity":"ok",
"maximum": 20.562898635864258,
"median": 11.363175912117441,
"minimum": 8.132431983947754,
"object_count": 32,
"size": 1
}
}
]
}Comments:
- The server compares the received
sequence_numberto the analytic's current sequence number. If it's equal, it sends a standard response. If not, it returns an [Error object][error_ref] with theoutdated_sequence_numberreason. In that case, your application should request a new list of widgets and save the current sequence number. You must provide the sequence number as a string. settings_sequence_numberdenotes information unimportant for the data retrieval and can be ignored.- For identifying widgets and sinks, only their ID is relevant. The user-defined name is intended mainly for easier response parsing. The ID is persistent as long as the output exists. However, the ID of a deleted output can be reused for a new one. It's recommended to reestablish mapping between the name of the output and its ID when the sequence number changes.
- This example illustrates a situation where only outputs of widgets 0 and 1 are needed. You may ignore widgets where the output is not needed at the moment.
- It might take a long time for the block to respond to a heavy data widget (e.g. the trajectory view widget) data request. Due to this, all heavy data widget data requests must be sent separately—without requests for any other widget data in the same message. See the [Overview of widget types][wtypes] for a list of light data and heavy data widgets.
- If the
widgetsarray in the request is empty or missing, the block sends outputs of all light data widgets. - The output's attributes
data_start_timestampanddata_end_timestampdenote the time interval from which the output data originates. More specifically, they denote the time interval in which the trajectories from which the output has been calculated have been closed. Trajectory closure is explained in our article [Working with time in FLOW][time]. operator_attributedenotes which information the widget pulls and outputs from the operator to which it's attached. Attributes are explained in detail in the [next article][wtypes].data_validityis an enumeration string referring to the rate at which available trajectories' time of existence intersects with the snapshot's [time interval or time block][hist]. Possible values are:ok—the data fully intersects with the snapshot's time interval.cropped—the data partially intersects with the snapshot's time interval. Thedata_start_timestampand/ordata_end_timestamphave been modified to match the trajectories' actual time of existence.invalid—there is no intersection of the trajectories' time of existence with the snapshot's time interval.
evaluation_validityis an enumeration string describing whether there's a problem with an expression associated with a widget.ok—there is no problem with expression evaluation. This should always be the case with sinks.invalid—there's a syntactic or semantic problem (e.g. circular dependency on other expression widget) with the expression definition.
cube_idandanalytic_idshow the cube and analytic to which the widget belongs.
Getting the history of widget values
For certain types of outputs, the FLOW block saves snapshots of their output. For more details, refer to the article on [output history][hist]. Each output type has a different limit of snapshots. If the limit is exceeded, the oldest snapshot is replaced with the most recent one. You can find out the timestamp of the oldest snapshot from the history_start_timestamp property while getting the list of all widgets or sinks, or from the request below.
See [Overview of widget types][wtypes] for a list of widget types that support snapshots.
Method: POST
URI:/cubes/{cube_id}/analytics/{analytic_id}/widgets/history
Query string parameters:
timestamp_format—see Getting a list of all widgets for details. The request body is also expected to contain the timestamps in the format set by this parameter.
Example request body:
{
"sequence_number": "36",
"widgets": [
{
"id": 0,
"start_timestamp": "1619106105644",
"end_timestamp": "1619106108644"
}
]
}Example response body:
{
"sequence_number": "36",
"settings_sequence_number": "0",
"timestamp": "1619106834779",
"widgets": [
{
"id": 0,
"name": "Speed - Value",
"output_type": "widget",
"output_value_type": "value",
"operator_attribute": "object_count",
"history": {
"enabled": true,
"interval": "1000",
"policy": "fixed_interval"
},
"history_capacity": 10000,
"history_records_count": 656,
"history_start_timestamp": "1619106105644",
"history_end_timestamp": "1619106834779",
"current_configuration_history_records_count": 1429,
"current_configuration_history_start_timestamp": "1619106804791",
"current_configuration_history_end_timestamp": "1619106834779",
"snapshots": [
{
"data": {
"data_validity": "ok",
"evaluation_validity":"ok",
"object_count": 3,
"value": 3
},
"data_end_timestamp": "1619106633167",
"data_start_timestamp": "1619106103875",
"timestamp": "1619106633167"
},
{
"data": {
"data_validity": "ok",
"evaluation_validity":"ok",
"object_count": 3,
"value": 3
},
"data_end_timestamp": "1619106634168",
"data_start_timestamp": "1619106103875",
"timestamp": "1619106634168"
},
{
"data": {
"data_validity": "ok",
"evaluation_validity":"ok",
"object_count": 4,
"value": 4
},
"data_end_timestamp": "1619106635169",
"data_start_timestamp": "1619106103875",
"timestamp": "1619106635169"
}
]
}
]
}Comments:
- You can query for multiple widget histories in the same request. The
widgetproperty is an array. - The request's
start_timestampandend_timestampdenote the time interval with which the response snapshots'data_start_timestampanddata_end_timestampmust have an overlap. - The
timestampproperty inside the elements of thesnapshotsarray mostly contains the same value as the element'sdata_end_timestamp. If, however, the output's Time mode is set to Time Blocks, then thetimestampproperty contains the same value as the element'sdata_start_timestamp. data_start_timestamp,data_end_timestampattributes are explained in the section Getting outputs of selected widgets.settings_sequence_numberis an artifact and can be ignored.
Getting a list of all sinks
Method: GET
URI:/cubes/{cube_id}/analytics/{analytic_id}/sinks
Query string parameters:
timestamp_format—see Getting a list of all widgets for details.
Example response body:
{
"sequence_number": "16",
"timestamp": "1745838906960",
"sinks": [
{
"history": {
"enabled": false
},
"id": 6,
"name": "MOVEMENT 3 - Raw trajectories",
"output_value_type": "raw_trajectories",
"operator_attribute": "raw_trajectories",
"tags": []
},
{
"history": {
"enabled": false
},
"id": 7,
"name": "My survey file sink",
"output_value_type": "file",
"operator_attribute": "trajectories",
"tags": []
}
]
}Comments:
- Properties and their semantics are identical to widgets. Refer to Getting a list of all widgets for details.
- See [here][stypes] for details about sink types.
Getting outputs of selected sinks
Method: POST
URI:/cubes/{cube_id}/analytics/{analytic_id}/sinks/data
Query string parameters:
timestamp_format—see Getting a list of all widgets for details.
Example request body:
{
"sequence_number": "16",
"sinks": [
{
"id": 6
},
{
"id": 7,
}
]
}Example response body:
{
"sequence_number": "16",
"settings_sequence_number": "10",
"timestamp": "1745838190840",
"sinks": [
{
"id": 6,
"name": "MOVEMENT 3 - Raw trajectories",
"output_type": "sink",
"output_value_type": "raw_trajectories",
"operator_attribute": "raw_trajectories",
"data_end_timestamp": "1745838190880",
"data_start_timestamp": "1745837296600",
"analytic_id": 0,
"cube_id": 0,
"tags": [],
"data": {
"data_validity": "ok",
"evaluation_validity": "ok",
"object_count": 105,
"trajectories": [
{
"category": "pedestrian",
"color": "undefined",
"duration": 80000,
"id": "0",
"last_detection_score": 0.4995228350162506,
"license_plate": "",
"section_speed": 1.420454502105713,
"timestamp": "1745837296600",
"trajectory_score": 0.7575777173042297
"state_data": {
"bounding_boxes": [
[
0.9022210836410522,
0.5912331342697144,
0.9429348111152649,
0.7736831903457642
],
// ...
],
"map_accelerations": [
0.19777706265449524,
-0.3259845972061157,
-0.6550215482711792,
// ...
],
"map_positions": [
[
616145.0725747823,
5453500.069705306
],
[
616144.9350229837,
5453499.78742568
],
// ...
],
"map_speed_angles": [
null,
5.077451229095459,
5.068471431732178,
// ...
],
"map_speeds": [
0.13268446922302246,
0.2719743251800537,
0.3231255114078522,
// ...
],
"sensor_positions": [
[
0.922885537147522,
0.7752178311347961
],
[
0.9211771488189697,
0.7809019088745117
],
// ...
],
"timestamps": [
0,
5320,
5600,
5880,
// ...
],
"wgs84_positions": [
[
16.59509984737455,
49.223265604686055
],
[
16.595097877332947,
49.22326309257227
],
// ...
]
}
},
// ...
]
}
},
// ...
]
}Comments:
// ...here is used as an ellipsis for shortening long data outputs.- Properties and their semantics are identical to widgets. Refer to Getting outputs of selected widgets for details.
Need more help or have some questions?[Contact us!][contact]
Updated 6 months ago
See each sink type in detail, or read about UDP sinks for a subscription-based variant of sinks.
