Node Communication#

Communication between nodes is vital to ensure proper operation of the control system. Due to the distributed nature of the system, a standardised system to communicate between nodes is essential. There are two ways in which nodes communicate within the network. Clients will usually communicate with the command node board via the REST API provided by the client bridge. Nodes will usually communicate with each other over serial interfaces such as sockets, I2C and UART. In order to ensure that communication is as smooth as posible, simple standards for both serial communication and communication with the REST API have been developed. The API is documented using the OpenAPI 3.1 specification and the serial communication is defined using Augmented Backus–Naur form (ABNF) as defined by RFC 5234.

Registers#

Registers are conceptually similar to pigeonholes. In short, they are named locations on each node that store specific pieces of configuration data. These registers can be accessed and modified over the supported communications protocols. These form the basis for each nodes API and the registers are used to control the functionality of each node.

Each register has a locally unique address in the following format:

Listing 1 ABNF specification for a registers address#
register-addr   =       1*(ALPHA / %x2D / %x5F)
                            ; Only support alphanumeric characters as
                            ; well as - and _

This address is used by commands to retrieve and modify the data in a specific register.

Note

Register addresses are case insensitive. I.e. speed_channel_1 is the same as SPEED_CHANNEL_1.

In cases where a request is made for the contents of a register but the register is empty, null should be returned.

Reserved registers#

A number of addresses are reserved for use and MUST be present on all nodes. They are used by the control nodes to establish the specific features that an individual node supports and are essential to the correct interoperation of all nodes.

registers#

A comma seperated list of all supported register addresses available on this node. The comma seperated list SHOULD have the following format.

Listing 2 ABNF specification for register list#
register-list   =       *(register-addr %x4C)
                            ; 0 or more register addresses
                            ;   seperated by a comma without
                            ;   any spaces

Note

Any whitespace will be removed during processing of the list

serial#

A 16 character long string representing the serial number of the node. The serial number is an arbitary string that MAY be unique among boards. It is used solely for informational purposes. If no serial number is defined, null SHOULD be returned.

model#

The model number of this node. The model number is an arbitary string of maximum length 256 characters that does not need to be unique. It is used solely for informational purposes. If no model number is defined, null SHOULD be returned.

bootloader#

A string representing the current bootloader version installed on this node. This SHOULD be filled on all nodes. It is used to establish compatibility of firmware and supported features.

firmware#

A string representing the current firmware version installed on the node. This SHOULD be filled in on all nodes.

Client to Node#

REST API#

This is used as the main form of communication between a client bridge and a client. The specification is defined using the OpenAPI 3.1 standard and is listed below. A complete list of HTTP routes is also available at the end of this document. An interactive version of the OpenAPI documentation is also available.

GET /node/{addr}/register/{register}#

Get value of register

Return the value currently held in the specified register

Parameters
  • addr (string) –

  • register (string) –

Status Codes
  • 200 OK – Value of requested register

  • 404 Not Found – The requested node or register does not exist

  • default – General Error

PUT /node/{addr}/register/{register}#

Set register value

Set the value of the register to the specified value

Parameters
  • addr (string) –

  • register (string) –

Status Codes

Bootloader#

The client may, in order to complete some actions, decide to communicate with the bootloader interface of a node. If this is the case, the reset command should be issued to the board, and then any character send along the USB interface after approximately 1 second. This is to interupt the boot process. Various commands may then be sent to the bootloader as detailed below.

Listing 3 ABNF specification for client to node serial communication#
; SPDX-FileCopyrightText: 2022 Sidings Media <contact@sidingsmedia.com>
; SPDX-License-Identifier: CC-BY-SA-4.0

; Specification for commands sent a client and a node over serial links.

; Commands

command         =       (update / interrupt / reset) CRLF

update          =       "update"
                        ; Indicate that the client would like to provide
                        ;   a firmware file to update the board

interrupt       =       CHAR
                        ; Any key to cancel normal boot seq and enter
                        ;   bootloader interface

reset           =       "reset"
                        ; Reset the boards microcontroller

; Command option values
string-val      =       1*(ALPHA / %x2D / %x5F)
                            ; Only support alphanumeric characters as
                            ; well as - and _ 

bin-val         =       "0b" 1*BIT

bool-val        =       "true" / "false"

hex-val         =       "0x" 1*HEXDIG

int-val         =       1*DIGIT

signed-int-val  =       [%x2d] int-val

null-val        =       "null"

;IPv6 Address from RFC5954
IPv6address     =       6( h16 ":" ) ls32
                        / "::" 5( h16 ":" ) ls32
                        / [               h16 ] "::" 4( h16 ":" ) ls32
                        / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
                        / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
                        / [ *3( h16 ":" ) h16 ] "::"    h16 ":"   ls32
                        / [ *4( h16 ":" ) h16 ] "::"              ls32
                        / [ *5( h16 ":" ) h16 ] "::"              h16
                        / [ *6( h16 ":" ) h16 ] "::"

h16             =       1*4HEXDIG

ls32            =       ( h16 ":" h16 ) / IPv4address

IPv4address     =       dec-octet "." dec-octet "." dec-octet "." dec-octet

dec-octet       =       DIGIT                   ; 0-9
                        / %x31-39 DIGIT         ; 10-99
                        / "1" 2DIGIT            ; 100-199
                        / "2" %x30-34 DIGIT     ; 200-249
                        / "25" %x30-35          ; 250-255

Node to Node#

Serial Commands#

Serial commands are used for inter-node communication in almost all cases. Most nodes are connected via serial communication mediums such as I2C, UART and sockets. In these cases, the below specification for serial commands should be used.

These commands are loosely inspired by SQL statements. There are two types of command, the get command and the set command. As the names suggest, get commands retrieve a value from a register and set commands set the value of a register.

In most cases, it is required to state the address of the node the command is being sent to. This is to facilitate the command traversing client bridges and interface cards. The only circumstance where the address can be omitted is on commands sent by the command node to devices directly connected on the I2C bus. This is possible as the address is already specified by the command node when sending the command over the I2C bus.

Listing 4 ABNF specification for node to node serial communication#
; SPDX-FileCopyrightText: 2022 Sidings Media <contact@sidingsmedia.com>
; SPDX-License-Identifier: CC-BY-SA-4.0

; Specification for commands sent between nodes over serial links.

; Commands
command         =       (set / get / reset) [SP addr] CRLF
                            ; SQL like format. CRLF indicates line end.
                            ;   Address is only required when sending
                            ;   commands via an interface card. I.e.
                            ;   when being sent over the network. It is
                            ;   not required for direct I2C interfaces.

get             =       "get" SP register-addr
                            ; GET commands used to retrieve data from
                            ;   registers

set             =       "set" SP register-addr %x3D register-val
                            ; SET commands used to set the value of a
                            ;   register

reset           =       "reset"
                            ; RESET command used to cause system reset
                            ;   and allow access to bootloader interface

addr            =       "at" SP node-addr

; Command option values
register-addr   =       string-val

node-addr       =       hex-val
                        / IPv6address

register-val    =       string-val
                        / bin-val
                        / bool-val
                        / hex-val
                        / int-val
                        / signed-int-val   
                        / null-val

string-val      =       1*(ALPHA / %x2D / %x5F)
                            ; Only support alphanumeric characters as
                            ; well as - and _ 

bin-val         =       "0b" 1*BIT

bool-val        =       "true" / "false"

hex-val         =       "0x" 1*HEXDIG

int-val         =       1*DIGIT

signed-int-val  =       [%x2d] int-val

null-val        =       "null"

;IPv6 Address from RFC5954
IPv6address     =       6( h16 ":" ) ls32
                        / "::" 5( h16 ":" ) ls32
                        / [               h16 ] "::" 4( h16 ":" ) ls32
                        / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
                        / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
                        / [ *3( h16 ":" ) h16 ] "::"    h16 ":"   ls32
                        / [ *4( h16 ":" ) h16 ] "::"              ls32
                        / [ *5( h16 ":" ) h16 ] "::"              h16
                        / [ *6( h16 ":" ) h16 ] "::"

h16             =       1*4HEXDIG

ls32            =       ( h16 ":" h16 ) / IPv4address

IPv4address     =       dec-octet "." dec-octet "." dec-octet "." dec-octet

dec-octet       =       DIGIT                   ; 0-9
                        / %x31-39 DIGIT         ; 10-99
                        / "1" 2DIGIT            ; 100-199
                        / "2" %x30-34 DIGIT     ; 200-249
                        / "25" %x30-35          ; 250-255