Client Edge APIs

The Client Edge APIs allow clients to access Uplink data from and send Downlink data to Network Assets. Additionally, the Client Edge APIs expose the set of Network Assets which are valid Subjects of Uplink and Downlink operations for the given client.

The Client Edge API base URL (ClientEdgeBase) is https://clientedge-conductor.link-labs.com/clientEdge, which is referred to as <ClientEdgeBase> for short.

Additional Swagger documentation of the Client Edge APIs is maintained at https://clientedge-conductor.link-labs.com/clientEdge/docs.html.

Client Edge Data API

The Client Edge Data API allows clients to access data from Nodes (i.e., modules, repeaters and gateways) to which they have access given their granted authorities.

In general, the Client Edge Data API is organized by:

  • the data type’s handled by Conductor,

  • the subject type’s supported by Conductor,

  • and specific subject id’s which are registered with Conductor. Here, the term subject refers to the subject of a data query or subscription (the item or items whose data is to be accessed).


Additionally, individual data events of every supported data type are exposed via their own unique URLs. Each of these URLs includes the data type as well as the unique UUID-EventTime pair of the given event.

Endpoints which comprise the Client Edge Data API take one of the following forms:

<ClientEdgeBase>/data/<dataType>/<subjectType>/<subjectId>

which is referred to using the shorthand <DataSubjectURL>, and

<ClientEdgeBase>/data/<dataType>/event/<UUID>/<eventTime>

which is referred to as <DataEventURL> for short.

The following definitions apply:

  • DataType -- The type/schema/format/content of the data item. See the Supported Data Types table, below.

  • SubjectType -- The Subject of the query: the abstract or concrete thing being queried, which defines the scope of the query. See the Supported Subject Types table, below.

  • SubjectId -- The unique ID of the Subject of the query. The format of this ID is a function of the SubjectType. See the Supported Subject Types table, below.

  • UUID -- The unique 128-bit ID of a data event.

  • eventTime -- The millisecond-precision timestamp of the event, in ISO 8601 format.

Supported Data Types

Data Type

Description

uplinkPayload

Overall payload message uplinked from a Node over the course of one or more over-the-air uplink packets.

avgSignalMetadata

Signal quality metrics of a message, averaged over each of the message’s over-the-air packets.

gatewayStatus

Periodic status report of a gateway.

 

 

Supported Subject Types

Subject Type

Description

Subject ID Format

node

Data is scoped to the specific Node.

<nodeAddress>

applicationToken

Data is scoped to all modules associated with the Application Token.

<80-bit Hex>

networkToken

Data is scoped to all gateways associated with the Network Token.

<32-bit Hex>

account

Data is scoped to all Network Assets associated with the Account.

<accountId>

 

Client Edge Data Query API

The Client Edge Data Query API consists of several different Subject based query types, each of which is summarized in the Query Types table, below

Query Types

Query Type

Description

URL Format

Time Range

Query the events from the given Subject after the floor time and before the ceiling time.

<DataSubjectURL>/events/

<ceilingTime>/<floorTime>

Most Recents

Query the most recent events from the given Subject at the time of the request.

<DataSubjectURL>/mostRecentEvents

Search

Query the events from the given Subject using search parameters. See the Search Parameters table below.

<DataSubjectURL>/events?<searchParams>

 

Search Parameters

Parameter

Description

Format

before

Query the events from the given Subject whose timestamps are before the given time.

?before=<ISO8601>

after

Query the events from the given Subject whose timestamps are after the given time.

?after=<ISO8601>

f.<property>

Query the events from the given Subject whose given property evaluates positively with respect to the given operation and reference value. See the Filter Operations table, below.

?f.<property>=<operation>.<refValue>

 

Filter Operations

Parameter

Description

EQ

Evaluates positively if the associated event’s property is equal to the given reference value.

NEQ

Evaluates positively if the associated event’s property is not equal to the given reference value.

 

Paging results

Client Edge will send back data in chunks for each request.  If a request has more results that exist for the requested time range, 2 flags will be set in the returned result set --  moreRecordsExist and nextPageId.  If the moreRecordsExist flag is true, the nextPageId property will be populated with an Id to pass in for the next query, to get the next set of results as a query parameter of pageId.

Example:

Query 1:  GET <clientEdgeBase>/clientEdge/data/uplinkPayload/applicationToken/1234567890abcdef1234/events/2016-10-20T15:51:26.213/2016-10-15T15:50:26.213

Returns:

{

queryUrl: {

href: "/clientEdge/data/uplinkPayload/applicationToken/1234567890abcdef1234/events/2016-10-20T15:51:26.213/2016-10-15T15:50:26.213"

},

subjectType: "applicationToken",

subject: "1234567890abcdef1234",

queryTime: "2016-10-20T16:59:27Z",

maxWTime: "2016-10-20T15:51:22.975",

minWTime: "2016-10-20T15:02:30.933",

resultCount: 1605,

moreRecordsExist: true,

nextPageId: "2cc3aab3-d694-4dd2-9385-9e73244b4228",

results: [ {<events here>} ]

}

Query 2:  GET <clientEdgeBase>/clientEdge/data/uplinkPayload/applicationToken/1234567890abcdef1234/events/2016-10-20T15:51:26.213/2016-10-15T15:50:26.213?pageId=2cc3aab3-d694-4dd2-9385-9e73244b4228

Returns:

{

queryUrl: {

href: "/clientEdge/data/uplinkPayload/applicationToken/1234567890abcdef1234/events/2016-10-20T15:51:26.213/2016-10-15T15:50:26.213"

},

subjectType: "applicationToken",

subject: "1234567890abcdef1234",

queryTime: "2016-10-20T16:59:35Z",

maxWTime: "2016-10-20T15:02:22.975",

minWTime: "2016-10-16T14:02:30.933",

resultCount: 564,

moreRecordsExist: false,

results: [ {<events here>} ]

}

Example Queries

Query UplinkPayload events from a given Node which occur within a given Time Range:

GET: <ClientEdgeBase>/data/uplinkPayload/node/$301$0-0-0-35426be41/events/2015-09-02T00:00:00/2015-09-01T00:00:00

Query the MostRecent AvgSignalMetadata events associated with a given Application Token:

GET: <ClientEdgeBase>/data/avgSignalMetadata/applicationToken/0123456789ABCDEF0123/mostRecentEvents

Query the GatewayStatus events associated with a given Network Token which occur before a ceiling time, after a floor time, and whose level property equals the value “Error”:

GET: <ClientEdgeBase>/data/gatewayStatus/networkToken/01234567/events?before=2015-09-01T01:00:00&after=2015-09-01T00:00:00&f.level=EQ.Error

Client Edge Command API

The Client Edge Command API allows clients to send Commands to Nodes.

There are two major sub-components of the Command API:

  • Commands -- where clients define the intrinsic state of a given Command.

  • Issued Commands -- where a given Command is issued to its target Node(s) and its status is made available for monitoring.

Commands

Interaction with the Commands sub-component of the Command API takes the following form:

  1. Define the desired binary payload of the Command.

  2. Optionally, define the communication requirements of the Command.

  3. Present the payload and optional communication requirements to the Command API in the form of a set of CommandProperties in order to obtain a handle to a unique Command object for the given CommandProperties.


Once a unique Command object has been defined, this same Command may be issued repeatedly to various target Nodes if desired.

The specific Command Definition API request is:

POST: <ClientEdgeBase>/commands
Request: CommandProperties
Response: Command

A CommandProperties object is defined as:

{
    "payloadHex": "0123456789ABCDEF",
    "commReqs": {
      "requiredAckRatio": 1.0,
      "requiredSuccessfulAckRatio": 1.0,
      "priority": 1,
      "ttlMSecs": 60000
    }
}

The fields of the CommandProperties object have the following meanings:

  • payloadHex (required) -- The hexadecimal representation of the desired binary payload.
  • requiredAckRatio(optional) -- The required ratio of any type of acknowledgements (i.e. either success or failure) from the targeted Nodes in order to consider the issuance of the given Command to be a success.

  • requiredSuccessfulAckRatio (optional) -- The required ratio of successful acknowledgement from the targeted Nodes in order to consider the issuance of the given Command to be a success.

  • priority (optional) -- The priority level of the Command (greater values indicating greater priority) to be considered during the propagation of the Command to its targeted Nodes.

  • ttlMSecs (optional) -- The Time to Live expiration of the Command, in milliseconds from time of issuance, for which acknowledgements from targeted Nodes will be accepted and considered as part of the overall success of the issuance of the given Command.

A Command object is defined as:

{
  "self": {"href": "<ClientEdgeBase>/command/<commandId>"},
  "commandId": "<id>",
  "commandProperties": {..}
}

The fields of a Command object have the following meanings:

  • commandId -- The system-assigned unique ID of the command defined by the given CommandProperties.
  • commandProperties -- The intrinsic CommandProperties which define the Command


Issued Commands

Interaction with the Issued Commands sub-component of the Command API takes the following form:

  1. Obtain a handle on the Command which is to be issued (See the Commands section, above)

  2. Define the desired target Nodes of the given Command, either by:

    1. specifying the Node addresses to be targeted, requiring that Conductor look for recent activity related to the targeted Nodes  (Targeted Node style).

    2. specifying the explicit Link address over which to route the Command (Routed style).

    3. defining the Command in the same step as targeting Nodes or specifying Links (Combined style).

  3. Issue the Command and obtain a handle on the status monitoring URL for the given Issued Command.

  4. Monitor the status of Issued Command as desired until it is considered to be a Success or Failure given the associated communication requirements.


The specific Command Issuance API request is:

Targeted Node Style
POST: <ClientEdgeBase>/issuedCommands/<commandId>?since=<ISO8601>
Request: JSON array of Node Addresses to Target ["","",...""]
Response: IssuedCommand
Routed Style
POST: <ClientEdgeBase>/issuedCommands/routed/<commandId>
Request: JSON array of Link Addresses to Route over ["","",...""]
Response: IssuedCommand
Combined Style
POST: <ClientEdgeBase>/issueCommand
Request: CommandIssuanceInfo
Response: IssuedCommand

In the above, a CommandIssuanceInfo object is defined as:

{
  "commandProperties": {...}
  },
  "commandTargets": {
    "targetNodeAddresses": ["","",...""],
    "routesSinceTime": "<ISO8601>"
  },
  "commandRoutes": {
    "linkAddresses": ["","",...""]
  }
}

The fields of the CommandIssuanceInfo object have the following meanings:

  • commandProperties (required) -- The intrinsic CommandProperties which define the Command.

  • targetNodeAddresses (optional) -- JSON array of Node Addresses to Target.

  • routesSinceTime (optional) -- The time after which recent activity for the given Node Addresses should be considered when determining the set of Links to over which to Route.

  • linkAddresses (optional) -- JSON array of Link Addresses over which to Route.


NOTE: Either commandTargets or commandRoutes is optional, but not both.

In the above, an IssuedCommand object is defined as:

{
  "self": {"href": "<ClientEdgeBase>/issuedCommand/<issuanceId>"},
  "issuanceId": "<id>",
  "issuanceTime": "<ISO8601>",
  "commandRel": {"href": "<ClientEdgeBase>/command/<commandId>"},
  "downlinkStatusRel": {"href": "<ClientEdgeBase>/issuedCommand/<issuanceId>/status"},
  "routeAssignments": [
    {
      "targetNode": "<nodeAddress>",
      "assignedLink": "<linkAddress>"
    }
  ],
  "downlinkStatusDetailRels": [
    {"href": "<ClientEdgeBase>/issuedCommand/<issuanceId>/statusDetail/<linkAddress>"}
  ]
}

Issued Command Status

The Issued Command Status endpoint allows clients to monitor the status of a previously issued command that is still being tracked by Conductor.

The specific Issued Command Status  API request is:

GET: <ClientEdgeBase>/issuedCommand/<issuanceId>/status
Request: N/A
Response: DownlinkStatus

In the above, the DownlinkStatus object is defined as:

{
  "self": {"href": "<ClientEdgeBase>/issuedCommand/<issuanceId>/status"},
  "downlinkItemRel": {"href": "<ClientEdgeBase>/issuedCommand/<issuanceId>"},
  "statusTime": "<ISO8601>",
  "status": "",
  "statusInfo": ""
}

The fields of the DownlinkStatus object have the following meanings:

  • statusTime -- The applicable time for the given status of the given Issued Command.

  • status -- The status value.  Valid values related to the status of the given Issued Command are:

    • Pending -- Has not yet expired and has not yet met its acknowledgement requirements.
    • Expired -- Has not met its acknowledgement requirements within the Time to Live expiration of the Command given its issuance time.
    • Failed -- Has either not been able to be propagated to its intended targets or the intended targets have not accepted it.
    • AcknowledgedSuccessful -- Has met its successful acknowledgement requirements.
    • Successful -- Has met its acknowledgement requirements of any type.
  • statusInfo (optional) -- Depending upon the status value, may contain additional info pertaining to how the given status value was achieved.  


Issued Command Status Details

The Issued Command Status Details endpoint allows clients to monitor the status of a specific route of a previously issued command that is still being tracked by Conductor. These details are presented as history-of-propagation events for the specific route.

The specific Issued Command Status Details API request is:

GET: <ClientEdgeBase>/issuedCommand/<issuanceId>/statusDetail/<linkAddress>
Request: N/A
Response: DownlinkStatusDetail

In the above, a DownlinkStatusDetail object is defined as:

{
  "self": {"href": "<ClientEdgeBase>/issuedCommand/<issuanceId>/statusDetail/<linkAddress>
"},
  "associatedDownlinkItemRel": {"href": "<ClientEdgeBase>/issuedCommand/<issuanceId>"},
  "routeAssignment": {
      "targetNode": "<nodeAddress>",
      "assignedLink": "<linkAddress>"
    },
  "downlinkEvents": [
    {
      "stateTime": "<ISO8601>",
      "state": "",
      "payload": ""
    }
  ]
}

The fields of the DownlinkStatus have the following meaning:

  • stateTime -- The applicable time for the given state of the propagation of the Issued Command on the given route.

  • state -- The state value. Valid values related to the state of the given Issued Command on the given route are:

    • Issued -- Has not yet been submitted to the gateway.
    • Submitting -- Is being submitted to the gateway.
    • Submitted -- Has been successfully submitted to the gateway.
    • SubmissionRejected -- Has been rejected by the gateway.
    • Sending -- Gateway is sending to the intended target Node.
    • Sent -- Gateway has successfully sent to the intended target Node.
    • SendFailed -- Gateway has failed to send to the intended target Node.
    • ReceivedRejected -- Received but rejected by the intended target Node.
    • Acknowledged -- Received and accepted by the intended target Node.
    • Expired -- Has not met its acknowledgement requirements within the Time to Live expiration of the Command given its issuance time.
  • payload (optional) -- Depending upon the state value, may contain a payload associated with the reporting of the state back to Conductor.


Client Edge Subscription API

The Client Edge Subscription API allows clients to subscribe for event data and the data in near real-time as it is generated. Client Edge provides different types of subscriptions to meet the needs of the client.  Subscriptions are created via the Subscription REST Api by posting to an endpoint.  The body is an json formatted Subscription Request that will be specific to the subscription type.  In the Subscription request, the ChannelRequest specifies how the client would like to receive data.  This may be Websocket, tcp socket, ZeroMQ, HTTP post, etc.  Available ChannelRequest types are listed below, and will be added to over time.

POST <ClientEdgeBase>/data/<dataType>/<subjectType>/<subjectId>/subscriptions
body: application/json
{
  "subscriptionProperties": {
    "priority": 0,
    "filterProperties": [
      {
        "name": "",
        "value": ""
      }
    ]
  },
  "channelRequest": {
    "type": "",
    "endpoint": "",
    "properties": [
      {
        "name": "",
        "value": ""
      }
    ]
  }
}

DataType, subjectType, and subjectId are the same available options as in the ClientEdge Data Query Api.

Websocket Subscription

A Websocket Subscription is a type of short lived, session-based subscription.  This subscriptions type provides streaming data via the HTML 5 websockets standard. HTML 5 websockets are supported in the following browsers:

  • IE 10+

  • Firefox 11+

  • Chrome 16+

  • Safari 6+

  • Opera 12.10+


To create a websocket subscription, the ChannelRequest would specify a type of WebSocket.  This is a two-step process.  The first step is to register the subscription.  At this point, the request is authenticated to ensure the client has the proper permission for the subscription and subject.  An authenticated client will get back a Subscription response (json), which will point to the websocket URL that a client must hit to open the websocket and begin streaming data.

 

For example, to subscribe to all data for a gateway, the request would be:

Request to register the subscription.  Specify a channelRequest.type of Websocket.  The other properties of ChannelRequest are not needed in this case.

POST <ClientEdgeBase>/data/uplinkPayload/node/$101$0-0-0-feed12345/subscriptions
body:  application/json
{
  "subscriptionProperties": {
    "filterProperties": [
    ]
  },
  "channelRequest": {
    "type": "Websocket"
  }
} 

Response application/json.  This response contains the websocketUrl url that a client can use to initiate a websocket call.

{
	"id":"a19b514d-7c55-4908-8866-5f800b41fc53",
	"time":"20160111T175135.951",
	"channels":[
		{
			"time":"20160111T175135.951",
			"type":"Websocket",		 		"endpoint":"wss://clientedge-conductor.link-labs.com/clientEdge/websocket/a19b514d-7c55-4908-8866-5f800b41fc53",
			"properties":null,
			"lifetimeEventCountActivity":null,
			"recentEventCountActivity":null
		}
	],
	"websocketUrl":{
		"href":"wss://clientedge-conductor.link-labs.com/clientEdge/websocket/a19b514d-7c55-4908-8866-5f800b41fc53",
		"desc":"websocket subscription for uplinkPayload/node/$101$0-0-0-feed12345"
	}
}

Available subscription types (with added notes about the specific implementation)

  • Websocket
    • channelRequest.type = "Websocket"
    • two step process to get the websocket connected
    • response contains websocketUrl
  • ZeroMQ2
    • wraps the event with data headers and information as to the type of event
    • allows feedback to the client when the subscription is closed and why
    • channelRequest.type = "ZeroMQ2"
    • channelRequest.endpont = "tcp://xxxx"
    • this is a 0MQ REP socket that is waiting for results
    • single step process to get the subscription created
  • Future Planned subscription types
    • tcp - open a tcp socket and send to the user upon data event match
    • HTTP Post - REST Post to client upon data event match
    • Email - get notified via email for certain events
    • Additional types as clients needs change

Websocket Authentication

If the connection to a websocket endpoint occurs in the context of a web browser, then the authentication is handled by the web browser. The credentials are the user’s Conductor username and password.

ZeroMQ Subscriptions

ZeroMQ subscriptions provide a way for a client to set up a ZeroMQ REQ/REP socket pair to stream events.  The client should set up a ZeroMQ REP socket "server" to listen for events.  When the server receives an event, it must send a Response json object back to acknowledge receipt of the event.  If the acknowledgment is not received within 10 seconds, the ZeroMQ socket will be assumed to be dead and the subscription will be closed.  It is recommended that the client send the response right away after receiving the event, and not after processing the event in order to ensure the channel stays alive. 

The following list of types of events that may be sent:

  • Required Response from ZeroMQ "server"

{

"requestId":"8ae5942c-38f2-4e62-ae1d-1eb40534b062",

"responseStatus":{"OK":null},

"service":"Subscription",

"method":"Subscription",

"responseData":null

}

 

  • Normal event flow to client server

{

 "subscriptionId" : "dc05dfe9-d21c-45c8-a56b-5d1656919011",

 "messageType" : "SubscriptionEvent",

 "headers" : null,

 "event" : {

   "uuid" : "1a2dba0f-3ce1-416b-bf73-49c37a7ccf2c",

   "time" : "2016-04-11T18:25:40.941",

   "metadata" : {

     "tags" : [ ],

     "props" : {

       "acctId" : "1",

       "app_tok" : "1234567890abcdef1234",

       "net_tok" : "abcdabcd",

       "t_ingest" : "1460399141296"

     }

   },

   "type" : "uplinkPayload",

   "value" : {

     "module" : "$301$0-0-0-030002467",

     "linkType" : "257-SymphonyLoRa",

     "gateway" : "$101$0-0-0-db9360af8",

     "linkAddress" : null,

     "startReceiveTime" : "2016-04-11T18:25:40.941",

     "messageSequence" : "1",

     "avgSignalMetadata" : {

       "sourceAddress" : "$301$0-0-0-abcdef123",

       "destAddress" : "$101$0-0-0-123456789",

       "linkType" : "257-SymphonyLoRa",

       "rssi" : -135.1999969482422,

       "snr" : -7.25,

       "chipNumber" : 0,

       "bandwidth" : 72,

       "codingRate" : 1,

       "sf" : 7,

       "channelNumber" : 65,

       "frequency" : 913250000,

       "crcValid" : true

     },

     "pld" : "feedface"

   }

 }

}

 

  • Subscription closed by user

{

 "subscriptionId" : "dc05dfe9-d21c-45c8-a56b-5d1656919011",

 "messageType" : "UnsubscribeRequest",

 "headers" : {

   "matchedEventCount" : 365,

   "ClosedReason" : "Requested by user",

   "publishedEventCount" : 365

 },

 "event" : null

}

 

  • Subscription closed due to error

{

 "subscriptionId" : "8ae5942c-38f2-4e62-ae1d-1eb40534b062",

 "messageType" : "Error",

 "headers" : {

   "matchedEventCount" : 2,

   "ClosedReason" : "No response from after sending event",

   "publishedEventCount" : 1

 },

 "event" : null

}

Example JavaScript code to connect to a Websocket Subscription previously generated for Uplink Data

var socket = new WebSocket('wss://clientedge-conductor.link-labs.com/clientEdge/websocket/a19b514d-7c55-4908-8866-5f800b41fc53);
socket.onopen = function() {
    console.log('Socket has been opened!');
};
socket.onmessage = function(message) {
    console.log('Socket has received data: ' + message.data);
    $('#uplinkPayloadData').append(message.data + '<br />');
};
socket.onclose = function() {
    console.log('Socket has been closed!');
};
socket.onerror = function() {
    console.log('Socket has received an error!');
};

0 Comments

Add your comment

E-Mail me when someone replies to this comment