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 created
  • POST - create one or more end device events
  • PUT - create/update a device
  • DELETE - 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 created
  • PUT - create/update a device type
  • DELETE - 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 created
  • POST - 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 created
  • PUT - create/update an observation type
  • DELETE - 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.