====== RICSerial and RICFrame Protocols ======
The RICSerial protocol is designed to work across all interfaces and handles “framing” using an “HDLC-like” mechanism. In practice this means that RICSerial data packets (blocks of bytes) can be split up in any fashion required (e.g. a packet containing 1000 bytes can be split into 100-byte chunks in order to send to an interface that can only support small packets - e.g. BLE) with no detrimental effects. The “framing” mechanism reassembles the original packets and provides a CRC-based check to ensure that all messages arrive “whole”. There is an overhead to RICSerial (in terms of both message size and processing time) but it is the protocol of choice in RIC Firmware.
RICFrame is a simpler protocol that does not provide “framing” and is used as the “payload” of RICSerial messages. It can also be used stand-alone but is only suitable for use on interfaces which implement strict framing themselves. Many interfaces interfaces (e.g. TCP and CommandSerial) are not suitable for use with stand-alone RICFrame.
RICFrame messages can carry various application-layer message types including RICREST (api requests) and ROSSERIAL (published messages).
HDLC is a very commonly used protocol and this implementation will only use a small part of it.
NOTE: standard HDLC uses different codes for BOUNDARY and ESCAPE octets.
The message structure is as follows:
Byte position | Field Name | Size (bytes) | Value/Description |
---|---|---|---|
0 | Boundary | 1 | 0xE7 (used to delimit the frame) |
1 | Frame | N | An encoded version of one or more RICFrame messages. See below |
N+2 | FCS | 2 | Frame-Check-Sequence, a CRC computed using 16-bit CRC-CCITT and over the message from byte 1 to byte N+2 (i.e. only excluding the boundary flags and FCS itself) |
N+3 | Boundary | 1 | 0xE7 (frame delimiter) |
HDLC is a protocol which requires that the Boundary value can never occur as part of the Frame or FCS. Hence, apart from the two boundary values, every byte (including bytes in the MsgNumber, Protocol and FCS) which would have the same value as the boundary value (i.e. 0xE7) must be replaced with a two-byte “escape sequence”. The escape sequence introduces a new first byte value which is 0xD7 and, since this value must now also be uniquely identified as the escape value, other occurrences of it must also be escaped.
To escape a value it must be replaced by the following two bytes:
0xD7
the original byte value with bit 5 inverted
Hence, to transmit the values: 0x01, 0x23, 0xE7, 0x92 as part of the Information payload of the message you would transmit: 0x01, 0x23, 0xD7, 0xC7, 0x92
RICFrame can stand-alone in frame oriented communications or be wrapped by RICSerial:
Byte position | Field Name | Size (bytes) | Value/Description |
---|---|---|---|
0 | MsgNumber | 1 | Message number:
|
1 | Protocol | 1 | Bit field as follows: Bit 7..6: MsgType
Commands flow from a controller (such as an app) to RIC and are numbered, Responses flow in the opposite direction and have the same message number as the command. Publish messages are sent by RIC and are assumed to be status updates, RIC doesn’t queue status messages to ensure the latest information is sent as soon as the channel permits. Report messages are sent from RIC and are assumed to be important messages that are queued if the channel isn’t immediately available. Bit 5..0: Payload protocol
Note that multiple ROSSerial messages can be wrapped in a single “framed” message. When RICSerial is used as a wrapper it provides the framing which indicates the total length of all messages. The same total length information is available when RICFrame messages are carried with a different framing protocol (e.g. BLE). |
2..N+1 | Information | N | Payload of the message (see note above about multiple ROSSerial messages) |