DUET PlatformDocs
API referenceRead APISensors and signals

List signal values

available
GET
/platform/v1/signals

Lists time-series values for the project's tags, oldest first. Returns both lanes by default: raw_signal has every tag the site forwards, as the source sent it, and performance has the tags mapped to a DUET device, scaled. Each row says its lane and resolution. The response format follows the Accept header, as on /platform/v1/performance-v2.

Authorization

Bearer
headerAuthorizationBearer <token>

Query Parameters

project_id*string

The ID of the project to read signals from.

from?string

The start of the time range, inclusive. Required unless you set received_since.

Formatdate-time
to?string

The end of the time range, exclusive. Required unless you set received_since.

Formatdate-time
received_since?string

Returns the raw_signal rows that DUET stored at or after this time, compared against received_at, including samples that arrived late. Rows are sorted by received_at, then ts, then sensor_tag. To resume, set received_since to the last row's received_at, after_ts to its ts, and after_tag to its sensor_tag. Rows show up about 5 seconds after DUET stores them.

Formatdate-time
after_ts?string

The ts of the last row you received. Requires received_since and after_tag.

Formatdate-time
after_tag?string

The sensor_tag of the last row you received. Requires received_since and after_ts.

tag_class?string

Returns only tags of this class. For example, alarms returns the tags that drive alarms, without the measurement tags.

device_id?array<string>

Returns only performance rows of these DUET devices. raw_signal rows have no DUET device, so this filter leaves them out. Repeat the parameter for more than one device.

tag?array<string>

Returns only these tags, by sensor_tag. Repeat the parameter for more than one tag.

lane?string

Returns only rows from this lane. Both lanes by default.

Value in"raw_signal""performance"
resolution?string

Returns only rows of this resolution. Both resolutions by default.

Value in"raw""1m"
limit?integer

The maximum number of rows to return. The default is 10,000 and the maximum is 100,000.

Range1 <= value <= 100000
Default10000
offset?|

The number of rows to skip. With received_since, use after_ts and after_tag instead.

Range0 <= value
Default0

Header Parameters

Accept?string

The response format: Arrow stream, Parquet, or JSON sequence. The default is Arrow stream.

Default"application/vnd.apache.arrow.stream"
Value in"application/vnd.apache.arrow.stream""application/vnd.apache.parquet""application/json-seq"

Response Body

The signal rows, oldest first, in the format that the Accept header asks for.

  1. response
lane*string

Where the row comes from. raw_signal rows are every tag the site forwards, exactly as the source sent them: no scaling, and no DUET device. performance rows are the tags mapped to a DUET device, scaled to engineering units.

Value in"raw_signal""performance"
sensor_tag*string

The source system's tag.

hierarchy_id*|

The ID of the tag's row in the project's site hierarchy. Null on raw_signal rows.

device_id*|

The ID of the DUET device that the tag maps to. Null on raw_signal rows. An empty string ('') on a performance row whose tag sits under the site root.

device_key*|

The source system's key for the device that the tag belongs to. Null when the site hasn't sent device information for the tag.

device_name*|

The source system's name for the device that the tag belongs to. Null when the site hasn't sent device information for the tag.

tag_class*|

The class of the tag, for example alarms or measurement. Treat it as an open set. Null when the site hasn't classified the tag.

value_encoding*string

The column that holds the tag's value. float uses value, integer uses value_int, and string uses value_str. The other two columns are null.

Value in"float""integer""string"
unit*|

The unit of value. On raw_signal rows, the unit the source reports. On performance rows, the unit DUET stores the measure in, whatever the source sends: for example W for inverter active power, cm for snow depth. Null when the tag has no unit, or the measure is dimensionless.

resolution*string

The row's time resolution. raw rows are individual samples at the source's rate, which can be under a minute. 1m rows are one value per minute.

Value in"raw""1m"
ts*string

The sample time at the source, from the OPC UA SourceTimestamp, in UTC. On 1m rows, the start of the minute.

Formatdate-time
received_at*string

When DUET stored the row. received_since compares against this value.

Formatdate-time
server_ts*|

The OPC UA ServerTimestamp. Always null for now; reserved for when DUET stores it.

Formatdate-time
value*|

The value of a float tag, as a Float64, in unit. Scaled by DUET on performance rows, as the source sent it on raw_signal rows. Null for other encodings and when quality is bad.

raw_value*|

The value of a float tag as the source sent it, before scaling, in the source's unit. Equal to value on raw_signal rows. Null for other encodings and when quality is bad.

value_int*|

The exact value of an integer tag, as an Int64. Booleans are 0 or 1. State codes, fault codes, and bit-packed words are passed as they are, and you unpack the words. Null for other encodings and when quality is bad.

value_str*|

The value of a string tag. Null for other encodings and when quality is bad.

quality*|

The OPC UA quality class of the value: good, uncertain, or bad. A 1m row is partial when some of the minute's samples were bad; the counts say how many. DUET keeps uncertain values and flags them, for example a substituted night-time zero. DUET never returns a bad value as a number. The value columns are null instead. Null when the source doesn't report quality.

Value in"good""uncertain""bad""partial"
status_code*|

The full OPC UA StatusCode, a uint32, exactly as the source sent it, including any reason bits. 0 means Good. Null when the source doesn't report one.

status_name*|

The symbolic name of status_code, for example BadNodeIdUnknown. Null when there's no code or it isn't a known code. Many SCADA servers send only a generic Bad.

carried*boolean

Whether the value was carried forward from an earlier sample because the source didn't update in this minute. Always false on raw rows.

good_count*|

The number of samples in the minute with Good quality. Set on 1m rows only.

uncertain_count*|

The number of samples in the minute with Uncertain quality. Set on 1m rows only.

bad_count*|

The number of samples in the minute with Bad quality. Set on 1m rows only.

Example Request
curl -X GET 'https://api.enurgen.com/platform/v1/signals?project_id=string'
Example Response
{  "lane": "raw_signal",  "sensor_tag": "string",  "hierarchy_id": "string",  "device_id": "string",  "device_key": "string",  "device_name": "string",  "tag_class": "string",  "value_encoding": "float",  "unit": "string",  "resolution": "raw",  "ts": "2019-08-24T14:15:22Z",  "received_at": "2019-08-24T14:15:22Z",  "server_ts": "2019-08-24T14:15:22Z",  "value": 0,  "raw_value": 0,  "value_int": 0,  "value_str": "string",  "quality": "good",  "status_code": 0,  "status_name": "string",  "carried": true,  "good_count": 0,  "uncertain_count": 0,  "bad_count": 0}