Octave Resource Protocol

This topic describes the Octave Resource Protocol, which is the protocol that facilitates communications between your assets, Octave edge device, and the cloud.

What is the Octave Resource Protocol?

Octave Resource Protocol (ORP) is a simple ASCII-based protocol that is built on top of HDLC-framed data sent via UART. Using ORP, a customer asset (asset) can interact with Octave by sending and receiving ASCII-based messages with an Octave edge device.

This page provides the specification of this protocol:

ORP Version Updates

ORP Version 2

ORP version 2 is supported by Octave edge firmware, version 3.0.0, released in June 2020. There is no change in the protocol itself and it is backward compatible with version 1. Version 2 does however provide the following changes/enhancements:

  • The fields of the general packet description have been updated to support sequence numbers.
  • A "hello message" was added (SYNC). This includes a version number and sent/received packet counts. This message can be ignored by assets which do not wish to support it. The hello message is sent by the module when the ORP service starts and may be used by the asset to decide when to create or recreate the Resources.
  • The path of ORP Resources has changed:
    • All ORP Resources are under a node named orp.
    • Customer-defined Resources are under a node named orp/asset.
    • An asset has read/write access only to orp/asset. Other paths under orp are read-only.
    • A read-only status Resource is available under orp/status to report the connection state as well as packet statistics and errors

Packet Structure

Packets must adhere to the following:

  • Packets contain fixed-length and variable-length fields.
  • Fixed-length fields are located at the beginning of the packet, followed by any variable-length ones.
  • Fixed-length fields are mandatory. Their contents may be ignored when not needed for a given packet.
  • Variable-length fields begin with a 1-byte identifier and end with a separator. The final variable-length field does not end with a separator.
  • Data values may contain the separator. Therefore, data must appear as the last field in any packet.
  • Most fields are ASCII characters but are not null-terminated strings.

Request and Notification Structure

Protocol Version 1 - ASCII

The first 4 bytes of a request packet must be present, even if not all are applicable to the specific request.

<packet type[1]><data type[1]><segment[2]><contents[variable]>
Fields:
packet type : Identifies request or notification, 1-byte
data type   : Identifies data type of request or notification, if needed. Ignored for some types. 1-byte
segment     : Count allowing a request or notification to span multiple packets. 2-bytes
contents    : Packet dependent, variable length

Protocol Version 2 - ASCII

Version 2 introduces a message for synchonization between the Octave edge device and the asset. Protocol Version 2 is backward compatible with Version 1. Devices which do not
reply to the synchronization message or which report version 1 in the reply, can continue to follow version 1 of the protocol. Devices which report version 2 in the synchonization messages must use and increment the sequence field in any packet which specifies it. The packet sizes are unchanged but the use of some fields has been updated.

<packet type[1]><data type|version[1]><sequence[2]><contents[variable]>
Fields:
packet type       : Identifies request or notification, 1-byte
data type/version : Identifies data type or protocol version, if needed. Ignored for some types. 1-byte
sequence          : Packet number - count of packets sent by the sender since restart, including the current. 2-bytes, binary
contents          : Packet dependent, variable length

Request and Notification Packet Structure

Packet TypeRequest (asset to Octave edge device)Response (Octave edge device to asset)Version
Create Resource (input)I (49h)i (69h)1
Create Resource (output)O (4Fh)o (6Fh)1
Delete ResourceD (44h)d (64h)1
Add Push HandlerH (48h)h (68h)1
Remove Push HandlerK (4Bh)k (6Bh)1
Push to ResourceP (50h)p (70h)1
Get from ResourceG (47h)g (67h)1
Create SensorS (53h)s (73h)1
Remove SensorR (52h)r (72h)1
Set JSON ExampleE (45h)e (65h)1
Push Handler Callc (63h)C (43h)1
Sensor Handler Callb (62h)B (42h)1
SyncY (59h)y (79h)2
Unknown Request? (3Fh)1

Response Structure

Protocol Version 1 - ASCII

The first 4 bytes of a response packet must be present, even if not all are applicable to the specific response.

<packet type[1]><status[1]><segment[2]><contents[variable]>
Fields:
packet type : Identifies response, 1-byte
status      : Identifies status of response. 1-byte
segment     : Count allowing a responses to span multiple packets. 2-bytes
contents    : Packet dependent, variable length

Protocol Version 2 - ASCII

<packet type[1]><status[1]><sequence[2]><contents[variable]>
Fields:
packet type : Identifies response, 1-byte
status      : Identifies status of response. 1-byte
sequence    : Packet number - count of packets sent by the sender since restart, including the current. 2-bytes, binary
contents    : Packet dependent, variable length

Data Types

TypeValue
TriggerT (54h)
BooleanB (42h)
NumericN (4Eh)
StringS (53h)
JSONJ (4Ah)

📘

Note

When the data type field is ignored, any character may be used.

Version

The version byte is encoded in ASCII hex, beginning with '0'. The version number is calculated as follows:

version number = version byte + 0x01

For example, a version byte of 0x31 equates to version 2.

Sequence

The number of the current packet (i.e., count of the number of packets sent by the sender since restart, including the current one). This field is available in ORP versions 2.x and up.

Status

Octave edge devices provide a Resource with sub Resources under the node: orp/status. This status Resource provides the connection state as well as statistics and error reporting.

The status byte is encoded beginning with '@' (hex 40), which represents success. The status value can be calculated from this byte as:

status value = -1 * (<status byte> - 0x40)

where the status value is interpreted as:

CodeDescription
0OK
-1NOT FOUND
-3OUT OF RANGE
-4NO MEMORY
-5NOT PERMITTED
-6FAULT
-7COMM ERROR
-8TIMEOUT
-9OVERFLOW
-10UNDERFLOW
-11WOULD BLOCK
-12DEADLOCK
-13FORMAT ERROR
-14DUPLICATE
-15BAD PARAMETER
-16CLOSED
-17BUSY
-18UNSUPPORTED
-19IO ERROR
-20NOT IMPLEMENTED
-21UNAVAILABLE
-22TERMINATED

Timestamps

The timestamp is encoded as a whole number, representing seconds since the UNIX epoch. Digits are encoded as ASCII decimal and are preceded by the character 'T'.

For example: T946684799 = December 31, 1999 23:59:59 GMT

The maximum length of a timestamp is 11 ASCII digits.

Paths

The path is encoded as ASCII text string with no null terminator.. The path field is preceded by the character 'P'. (e.g., Pinput/button_01).

Allowable characters are: a-z A-Z 0-9 / _ -

The maximum length of a path depends on the type of Resource being created or accessed. A Sensor Resource includes auto-generated sub-nodes which reduce the allowable path length during the create request to 32 characters.

Paths which do not begin with a slash ‘/’ are treated as being relative to orp/asset. In order to access other Resources, such as those under orp/status, a full path must be provided that includes a beginning ‘/’ character (e.g., /orp/status/UART1/value).

FieldBytesComment
Path, Resource65Data Hub MAX_RESOURCE_PATH_LEN - "/app/orp/asset"
Path, Sensor57Resource path max len - "/trigger"

Data

Data is prepended with the character 'D' and there is no encoding of the contents. The data field must occur last in a packet. The maximum data length (payload) is 50,000 bytes.

For example: D0123456789,abc*

For some data types, the ORP service will transform the data it receives into the correct internal type. A failure to convert the data will result in an error being returned.

Data TypeConversion
triggerNot applicable
booleanCase insensitive comparison with "false" -> false
Case insensitive comparison with "true" ‐> true
"0" -> false
"1" -> true
Otherwise an error is returned
numericInterpreted as double-precision real
stringNo conversion
JSONNo conversion

Packet Counts

Sync packets (version 2 and later) contain fields to report packets sent and received. These are whole numbers, encoded as ASCII decimal, and are preceded by an 'R' for received count and an 'S' for sent count (e.g., R251,S305).

Operations

Asset to Octave Edge Device

CreateResource

Request to create a Resource in the Data Hub. If a CreateResource request is received for a Resource which already exists, the request will succeed only if all requested parameters match those of the existing Resource. In this case, no changes are actually applied. If one or more parameters differs from the existing Resource, the request will fail.

Request:      <packet type[1]><data type[1]><sequence[2]><path>[,<units>]

packet type:  'I' || 'O'
data type:    'T' || 'B' || 'N' || 'S' || 'J'  (Trigger || Boolean || Numeric || String || Json)
sequence:     Version 1: ignored.  Version 2: packet number
path:         'P'<path of the Resource>
units:        'U'<units> (optional)
Response:     <packet type[1]><status[1]><sequence[2]>

packet type:  'i' || 'o'
status:       see above
sequence:     Version 1: ignored.  Version 2: packet number

DeleteResource

Request to remove a Resource from the Data Hub. When a Resource is deleted, any associated handlers are also de-registered.

Request:      <packet type[1]><data type[1]><sequence[2]><path>

packet type:  'D'
data type:    ignored
sequence:     Version 1: ignored.  Version 2: packet number
path:         'P'<path of the Resource>
Response:     <packet type[1]><status[1]><sequence[2]>

packet type:  'd'
status:       see above
sequence:     Version 1: ignored.  Version 2: packet number

AddPushHandler

Asset request to be notified when data is written to a path. Once an asset successfully registers a handler, notification packets will be sent by the ORP service whenever there is a change in the associated Resource (path).

Request:      <packet type[1]><data type[1]><sequence[2]><path>

packet type:  'H'
data type:    ignored
sequence:     Version 1: ignored.  Version 2: packet number
path:         'P'<path of the Resource>
Response:     <packet type[1]><status[1]><sequence[2]>

packet type:  'h'
status:       see above
sequence:     Version 1: ignored.  Version 2: packet number

RemovePushHandler

Asset request to cease notifications for a particular path.

Request:      <packet type[1]><data type[1]><sequence[2]><path>

packet type:  'K'
data type:    ignored
sequence:     Version 1: ignored.  Version 2: packet number
path:         'P'<path of the Resource>
Response:     <packet type[1]><status[1]><sequence[2]>

packet type:  'k'
status:       see above
sequence:     Version 1: ignored.  Version 2: packet number

Push

Asset request to push data to a Resource.

Request:      <packet type[1]><data type[1]><sequence[2]><path>[,<timestamp>][,<data>]

packet type:  'P'
data type:    'T' || 'B' || 'N' || 'S' || 'J'  (Trigger || Boolean || Numeric || String || Json)
sequence:      Version 1: ignored.  Version 2: packet number
path:         'P'<path of the Resource>
timestamp:    'T'<time in seconds>  (optional - omit to use current data hub timestamp)
data:         'D'<data>  (optional)
Response:     <packet type[1]><status[1]><sequence[2]>

packet type:  'p'
status:       see above
sequence:     Version 1: ignored.  Version 2: packet number

Get

Asset request to read data from a Resource.

Request:      <packet type[1]><data type[1]><sequence[2]><path>

packet type:  'G'
data type:    ignored
sequence:     Version 1: ignored.  Version 2: packet number
path:         'P'<path of the Resource>
Response:     <packet type[1]><status[1]><sequence[2]><timestamp>,<data>

packet type:  'g'
status:       see above
sequence:     Version 1: ignored.  Version 2: packet number
timestamp:    'T'<time in seconds>
data:         'D'<data>  (represented as ASCII, NOT null terminated)

CreateSensor

Asset request to create a sensor type in the Data Hub. If a CreateSensor request is received for a sensor which already exists, the request will succeed only if all requested parameters match those of the existing Resource. In this case, no changes are actually applied. If one or more parameters differs from the existing Resource, the request fails.

Request:      <packet type[1]><data type[1]><sequence[2]><path>[,<units>]

packet type:  'S'
data type:    'B' || 'N' || 'S' || 'J'  (Boolean || Numeric || String || Json)
sequence:     Version 1: ignored.  Version 2: packet number
path:         'P'<path of the Resource>
units:        'U'<units> (optional)
Response:     <packet type[1]><status[1]><sequence[2]>

packet type:  's'
status:       see above
sequence:     Version 1: ignored.  Version 2: packet number

DestroySensor

Asset request to delete a sensor from the Data Hub.

Request:      <packet type[1]><data type[1]><sequence[2]><path>

packet type:  'R'
data type:    ignored
sequence:     Version 1: ignored.  Version 2: packet number
path:         'P'<path of the sensor>
Response:     <packet type[1]><status[1]><sequence[2]>

packet type:  'r'
status:       see above
sequence:     Version 1: ignored.  Version 2: packet number

SetJsonExample

Asset request to populate the JSON example node of a Resource.

Request:      <packet type[1]><data type[1]><sequence[2]><path>,<data>

packet type:  'E'
data type:    'J'  (Json)
sequence:     Version 1: ignored.  Version 2: packet number
path:         'P'<path of the Resource>
data:         'D'<data>
Response:     <packet type[1]><status[1]><sequence[2]>

packet type:  'e'
status:       see above
sequence:     Version 1: ignored.  Version 2: packet number

Octave Edge Device to Asset

PushHandler

Notification that data has changed on a Resource.

Notification: <packet type[1]><unused[1]><sequence[2]><timestamp>,<path>[,<data>]
packet type:  'c'

unused:       not applicable - ignore
sequence:     Version 1: ignored.  Version 2: packet number
timestamp:    'T'<time in seconds>
path:         'P'<path of the Resource>
data:         'D'<data> (optional)
Response:     <packet type[1]><status[1]><sequence[2]>

packet type:  'C'
status:       see above
sequence:     Version 1: ignored.  Version 2: packet number

SensorCall

Notification that a sensor is requesting a push. A SensorCall notification is to inform the owner of a sensor (the asset) that the Data Hub is requesting that data be pushed to the sensor value node. The asset should follow this notification with a Push to the sensor value Resource.

Notification: <packet type[1]><unused[1]><sequence[2]><path>

packet type:  'b'
unused:       not applicable - ignore
sequence:     Version 1: ignored.  Version 2: packet number
path:         'P'<path of the Resource>
Response:     <packet type[1]><status[1]><sequence[2]>

packet type:  'B'
status:       see above
sequence:     Version 1: ignored.  Version 2: packet number

Sync (Version 2 and up)

An unsolicited notification sent from the ORP service to the asset to indicate that the service has restarted.

After a restart of the ORP Service, the service will periodically send this message until either a direct response is received from the asset, or the asset sends any other valid packet. Once a response has been received, the ORP service will update its status to "connected".

The response packet must contain the protocol version which the remote device will use. The version byte is calculated as: version byte = version number - 0x01. If the remote device does not explicitly respond to the sync packet with a sync response but instead sends any other valid packet, the ORP service assumes that the remote is using protocol version 1.

📘

Note

The sequence numbers are not used in the sync and sync response packets. The sequence count must not be incremented when sending a sync or sync response.

Notification: <packet type[1]><version[1]><sequence[2]><timestamp><received><sent>

packet type:  'Y'
version:      Maximum ORP version supported
sequence:     unused
timestamp:    'T'<time in seconds>
received:     'R'<received count>. Packets received since restart, equal to zero (ASCII decimal, NOT null terminated)
sent:         'S'<sent count>. Packets sent since restart, equal to zero (ASCII decimal, NOT null terminated)
Response:     <packet type[1]><version[1]><sequence[2]>
packet type:  'y'
version:      ORP version supported
sequence:     unused