API
The Control Center runs both in the cloud and at the edge and provides a programmatic API via http REST. This API can be used by third party developers to provision end devices and observe them.
Schema
All API access is over HTTPS, and accessed from https://xdp.titanclass.com.au/api (referred to as $API
for the remainder of this document).
All data is sent and received as JSON.
All timestamps return in ISO 8601 format and expressed as UTC time at a millisecond resolution:
YYYY-MM-DDTHH:MM:SS.mmmZ
Offsets are what we use to uniquely identify an event and we provide a means to query them randomly for some events. This documentation will detail when offsets can be used as part of the query. Note that offsets are not always provided as the event may be a product of other events and must therefore be calculated.
Authentication
Unauthorized requests are represented with a 401 status. An unauthorized request occurs as a result of no authorization token being provided or an authorization token having expired. In either case, an authentication request is required to obtain a token. We will provide you with an a username and password that can be used for the purposes of API access. Here’s is a sample request for authentication given a fictitious user named someapiuser
with a password of A90CEA95-69D7-41EE-81C9-9EAEC123B406
:
curl \
-v \
-d'{"username":"someapiuser","password":"A90CEA95-69D7-41EE-81C9-9EAEC123B406"}' \
-H"Content-Type: application/json" \
$API/login
The resulting token is replied as a string text and conveyed using the Authorization Bearer
token. Supposing the above reply was captured into an environment variable, here is an example:
curl \
-v \
-X PUT \
-d '2B7E151628AED2A6ABF7158809CF4F3C' \
-H"Content-Type: text/plain" \
-H"Authorization: Bearer $AUTH_TOKEN" \
$API/secrets/secrets.dashboards-events.key
Namespaces
xDP equates a namespace to a site, which can be a farm or a part of a farm. Namespaces route requests and your authenticated token’s authorization will determine if you able to access the associated data. All API requests must therefore contain the xDP-Namespace
header along with a string value representing the site. We will inform you of the namespaces that you have access to.
Server Sent Events (SSE)
SSE is used for many resources where the HTTP GET
operation is used. We denote such operations as GET
(SSE).
All GET
(SSE) requests can have an optional finite=true
parameter which, when provided, causes the service to close the connection once all events have been received. When this parameter is not specified, or it has the value false
then the connection will remain open and new events will be streamed as they occur.
A StoredXXXDone
will occur when all known events have been streamed where XXX
represents the type of event. While there can be more events subsequently, having this signal can be useful for a user interface. For example, the user interface might show a spinning arrow to indicate connectivity and download with the Control Center services. Upon receiving the signal, it could stop spinning the arrow to indicate that the initial loading has completed.
SSE heartbeats are also provided and have an empty SSE data
field with no event type.
Here is an example of a stream of responses as output by the curl
tool:
data:{"data":{"nwkAddr":23352963,"position":{"lat":-37.110457,"lng":146.158180},"time":"2019-09-11T23:44:56.121Z"}}
event:PositionUpdated
data:{"data":{"nwkAddr":23352963,"topic":"ellenex-pt-data-up-mac-payload"}}
event:TopicUpdated
data:{"data":{"name":"No. 1 Paddock NE","nwkAddr":23352963}}
event:NameUpdated
data:{"data":{"data":{"voltage":6.2},"nwkAddr":27435,"source":"electric-fence-data-up-json","time":"2019-09-12T04:57:51.484665Z"}}
event:ObservationRecorded
data:{"data":{"topic":"electric-fence-data-up-json"},"offset":77773267795971}
event:StoredObservationRecordedEventsDone
Within each SSE data
field, there is a JSON payload with a data
field and an optional offset
. The data
field describes the actual event and is documented in detail below. An optional offset
field provides an opaque data structure that can be used to randomly access an event. In particular, the retrieval of observation recordings permits offsets to be provided. These are generally used to resume a stream of events from where they were last received and can significantly improve retrieval performance.
End Device resources
End devices describe sensors and actuators.
The following operations are supported:
GET
(SSE) - stream events as they are createdPOST
- create one or more end device eventsPUT
- create/update a deviceDELETE
- remove a device and/or its session
GET
(SSE) /end-devices/events
Optional parameters: includeDeviceSecrets
- as an additional security step, secrets are not provided by default. This parameter can be used to see that secrets are provided.
The following SSE event types are available:
BatteryLevelUpdated
- Battery level updated
Field | Type | Description |
---|---|---|
nwkAddr |
UInt32 |
The system’s 32 bit identifier of the device. |
time |
ISOTimeStr |
The ISO 8601 time that a device’s battery level changed. |
voltage |
UInt64 |
The battery level in V. |
NameUpdated
- Name updated
Field | Type | Description |
---|---|---|
name |
Str |
A user-friendly name associated with the device. |
nwkAddr |
UInt32 |
The system’s 32 bit identifier of the device. |
NoncesUpdated
- Device nonces updated
Field | Type | Description |
---|---|---|
devNonce |
UInt32 |
The device nonce is a counter of the number of times it has attempted to join the network. |
joinNonce |
UInt32 |
The join nonce is a counter of the number of times the device has been accepted to join the network. |
nwkAddr |
UInt32 |
The system’s 32 bit identifier of the device. |
NwkAddrUpdated
- Network address updated
Field | Type | Description |
---|---|---|
devEUI |
Base64 |
A 64 bit globally unique identifier of the device, typically assigned when manufactured. |
nwkAddr |
UInt32 |
The system’s 32 bit identifier of the device. |
NwkAddrRemoved
- Network address removed (device removed)
Field | Type | Description |
---|---|---|
nwkAddr |
UInt32 |
The system’s 32 bit identifier of the device. |
PositionUpdated
- Position Updated
Field | Type | Description |
---|---|---|
nwkAddr |
UInt32 |
The system’s 32 bit identifier of the device. |
position |
Object |
An object contain lat and lng numbers of the device’s position. |
time |
ISOTimeStr |
The ISO 8601 time that a device’s position was recorded. |
SecretsUpdated
- Secret updated
Field | Type | Description |
---|---|---|
nonce |
UUIDStr |
A nonce value used when encrypting this device’s secrets. |
nwkAddr |
UInt32 |
The system’s 32 bit identifier of the device. |
secrets |
Object |
If includeDeviceSecrets is provided as a parameter then an object is returned containing key/value pairs relating to device secrets. Each secret is conveyed as a hex string value. |
StoredEndDeviceEventsDone
- All known events done
No fields.
TopicUpdated
- Topic updated
Field | Type | Description |
---|---|---|
nwkAddr |
UInt32 |
The system’s 32 bit identifier of the device. |
topic |
Str |
The device type topic associated with the raw payload. |
VersionUpdated
- LoRaWAN version updated
Field | Type | Description |
---|---|---|
nwkAddr |
UInt32 |
The system’s 32 bit identifier of the device. |
version |
UInt32 |
The LoRaWAN version. |
POST
/end-devices/events
Optional parameters: provisionKeys
Creates an end device event as opposed to the next operation, PUT
which establishes or updates an event-sourced end device object.
JSON Lines is used to convey one or more end device events structured similarly to the GET
operation, with the addition of a type
field to indicate the event type. Here is an example to clarify:
{
"nwkAddr": 1,
"version": 1,
"type": "VersionUpdated"
}
PUT
/end-devices/{nwkAddr}
A nwkAddr
can be derived from a devEUI
by using the lower 32 bits and then performing a bitwise AND
using the hex value 01ffffff
(assuming a type 0 network such as that used by The Things Network and xDP).
Two types of update are permitted:
- Activation By Personalization (ABP)
- Over The Air Activation (OTAA)
Field | Type | Required | Description |
---|---|---|---|
appKey |
Base64 |
The application key for OTAA. | |
appSKey |
Base64 |
The application session key for ABP. | |
devEUI |
Base64 |
A 64 bit globally unique identifier of the device, typically assigned when manufactured. | |
endDeviceTopic |
Str |
Y | The device type topic associated with the raw payload. |
name |
Str |
A user-friendly name associated with the device. | |
fNwkSIntKey |
Base64 |
A “forwarding Network session integrity key” for ABP. Prior to LoRaWAN 1.1, this is the same value as nwkSEncKey and sNwkSIntKey which collectively known as a “network session key”. |
|
nwkSEncKey |
Base64 |
A “network session encryption key” for ABP. Prior to LoRaWAN 1.1, this is the same value as fNwkSIntKey and sNwkSIntKey which collectively known as a “network session key”. |
|
position |
Object |
An object contain lat and lng numbers of the device’s position. |
|
nwkKey |
Base64 |
The network key for OTAA. | |
sNwkSIntKey |
Base64 |
A “serving Network session integrity key” for ABP. Prior to LoRaWAN 1.1, this is the same value as fNwkSIntKey and nwkSEncKey which collectively known as a “network session key”. |
|
version |
UInt32 |
The LoRaWAN version. | |
secretsUpdatedNonce |
UUIDStr |
A nonce value used when encrypting this device’s secrets. |
If a secret is updated then the device’s “session” is also reset (its counters and nonces).
Here is an example ABP update:
cat > /tmp/end-device.json <<EOF
{
"appSKey": "EjRWeJCrze8SNFZ4kKvN7w==",
"devEUI": "EjRWeJCrze8=",
"endDeviceTopic": "agri-ace-data-up-mac-payload",
"fNwkSIntKey": "q83vEjRWeJCrze8SNFZ4kA==",
"nwkSEncKey": "q83vEjRWeJCrze8SNFZ4kA==",
"sNwkSIntKey": "q83vEjRWeJCrze8SNFZ4kA==",
"version": 1,
"name": "Device 1"
}
EOF
curl \
-v \
-X PUT \
-d @/tmp/end-device.json \
-H"Content-Type: application/json" \
-H"Authorization: Bearer $AUTH_TOKEN" \
$API/end-devices/29261297
DELETE
/end-devices/{nwkAddr}
Remove an end device.
DELETE
/end-devices/{nwkAddr}/session
Remove an end device’s session (counters and nonces).
End Device Type resources
End device types describe a category physical sensors and actuators i.e. those specific to a device manufacturer. For comparison, observation types describe devices in a generic fashion e.g. water level sensors, electric fence sensors etc.
The following operations are supported:
GET
(SSE) - stream events as they are createdPUT
- create/update a device typeDELETE
- remove a device type
GET
(SSE) /end-device-types/events
The following SSE event types are available:
EndDeviceTypeRemoved
- Type removed
Field | Type | Description |
---|---|---|
topic |
Str |
The device type topic. |
EndDeviceTypeUpdated
- Type updated
Field | Type | Description |
---|---|---|
name |
Str |
A user-friendly name associated with the type. |
topic |
Str |
The device type topic (its identifier). |
StoredEndDeviceTypeEventsDone
- All known events done
No fields.
PUT
/end-device-types/{topic}
Field | Type | Required | Description |
---|---|---|---|
name |
Str |
Y | A user-friendly name associated with the type. |
Here is a sample type update:
curl \
-v \
-X PUT \
-d '{"name":"Agriace Electric Fence Sensors"}' \
-H"Content-Type: application/json" \
-H"Authorization: Bearer $AUTH_TOKEN" \
$API/end-device-types/agri-ace-data-up-mac-payload
By convention, we use the
{manufacturer-device}-data-up-mac-payload
format. “data up” refers to the data being an uplink and “mac payload” means the “machine specific payload”.
DELETE
/end-device-types/{topic}
Remove an end device type.
Recording resources
Recordings are the actual observations and relate to “observation types” e.g. recordings for water tank levels (one or more types of end device relates to an observation type).
The following operations are supported:
GET
(SSE) - stream events as they are createdPOST
- create/update a recording
GET
(SSE) /recordings/events
Optional parameters: offsets
- a map of offsets in relation to their topics.
Here is a sample retrieval illustrating the use of offset maps:
curl \
-H"Authorization: Bearer $AUTH_TOKEN" \
"$API/recordings/events?offsets\[waterstate-data-up-json\]=78108275245056&offsets\[electric-fence-data-up-json\]=78108275245060"
The following SSE event types are available:
ObservationRecorded
- Observation recorded
Field | Type | Description |
---|---|---|
data |
Object |
A JSON object describing the recording. The layout of the object will be in accordance with its observation type. |
nwkAddr |
UInt32 |
The system’s 32 bit identifier of the device. |
source |
Str |
The observation type topic (its identifier). |
time |
ISOTimeStr |
The ISO 8601 time that a observation was recorded. |
StoredObservationRecordedEventsDone
- All known events done
Field | Type | Description |
---|---|---|
source |
Str |
The observation type topic that pertains to this offset (optional). |
POST
/recordings/events
Posting events can be useful for receiving events outside of those collected directly by our LoRaWAN Network Server. For example, an observation may have been received by an end device that uses satellite for its communications. In this case, the observation is conveyed over the internet and then to our cloud based Control Center. We then take care of propagating the observation to the edge where it can then be presented and processed with other observations.
JSON Lines is used to convey one or more observations structured similarly to the GET
operation. Here is an example that posts two observations to the waterstate-data-up-json
topic:
curl \
-v \
-X POST \
-d '{"data":{"height":300.0,"temperature":10.0},"nwkAddr":23352963,"source":"waterstate-data-up-json","time":"2019-09-03T08:30:29.858Z"}
{"data":{"height":150.0,"temperature":0.0},"nwkAddr":23352963,"source":"waterstate-data-up-json","time":"2019-09-03T08:31:29.858Z"}' \
-H"Content-Type: application/json" \
-H"Authorization: Bearer $AUTH_TOKEN" \
$API/recordings/events
Observation Type resources
Observation types describe device observations in a generic fashion e.g. water level sensors, electric fence sensors etc. For comparison, end device types describe a category of physical sensors and actuators i.e. those specific to a device manufacturer.
The following operations are supported:
GET
(SSE) - stream events as they are createdPUT
- create/update an observation typeDELETE
- remove an observation type
GET
(SSE) /observation-types/events
The following SSE event types are available:
ObservationTypeRemoved
- Type removed
Field | Type | Description |
---|---|---|
topic |
Str |
The device type topic. |
ObservationTypeUpdated
- Type updated
Field | Type | Description |
---|---|---|
name |
Str |
A user-friendly name associated with the type. |
secretPath |
Str |
The path to associate with a secret that will be used to encrypt/decrypt payloads. |
topic |
Str |
The observation type topic (its identifier). |
view |
Str |
A JavaScript function that describes how observation data should be rendered. |
StoredObservationTypeEventsDone
- All known events done
No fields.
PUT
/observation-types/{topic}
Optional parameters: provisionKeys
Field | Type | Required | Description |
---|---|---|---|
name |
Str |
Y | A user-friendly name associated with the type. |
secretPath |
Str |
Y | The path to associate with a secret that will be used to encrypt/decrypt payloads. If the provisionKeys query parameter is set to true then a key value will also be generated and stored. |
view |
Str |
Y | A JavaScript function that describes how observation data should be rendered. |
Here is a sample type update:
curl \
-v \
-X PUT \
-d '{"name":"Agriace Electric Fence Sensors","secretPath":"secrets.electric-fence.key","view":"function(){}"}' \
-H"Content-Type: application/json" \
-H"Authorization: Bearer $AUTH_TOKEN" \
$API/observation-types/electric-fence-data-up-json?provisionKeys=true
By convention, we use the
{observation-type}-data-up-json
format. “data up” refers to the data being an uplink and “json” means a normalized “JSON payload”.
DELETE
/observation-types/{topic}
Remove an observation type.