# The uCentral communication protocol In order to operate in a uCentral system, devices and services must operate using a specific protocol. This protocol describes the interaction between the managed devices and the controller that manages the devices. This communictaion protocol uses the [WebSocket protocol](https://tools.ietf.org/html/rfc6455) on port 15002. ## The controller The controller is an application waiting for connection from devices on a given port. The controller waits for connections over TCP. The controller can operate over IPv4 in this initial version. An IPv6 version will exist later. The controller is able to support thousands of devices. ## The devices A device will be given a way to find the IP address of its controller as well s the port to communicate over. Devices always initiate the connection to the controller. ## The connection The connection uses the WebSocket protocol to maintain and frame messages. The communication protocol used is modeled after JSON-RPC for sending JSON structured messages. ## The messages The controller can send commands to the devices. These commands must be acknowledged by the devices. Any errors should be reported byu the devices. The devices may send unsolicited messages to the devices. These messages are not acknowledged by the controller and should be expected to be received and processed. The next section explains the different messages. ### Event Messages In this RPC, here are some common interpretations: - `when` : In a command, this is a suggestion as to when to perform something. 0 means right now, or otherwise the UTC time in seconds. - `serial` : This is the text representation of the serial number the device is using. Usually will be the MAC address of the device without an separator. - `uuid` : Is an int64 representing the current configuration ID. - `JSON documents` : when a field requires an JSON document, this is free form JSON and the controller and the AP agree on its content. - #### Connection event Device Sends connection notification to the controller after establishing a connection. The controller my decide to send the AP a newer configuration. The controller will record the device capabilities provided. ```json { "jsonrpc" : "2.0" , "method" : "connect" , "params" : { "serial" : , "uuid" : , "firmware" : , "wanip" : [ IP:Port, ... ], (a list of IPs the device is using as WAN IP and port as strings. IPv4 and IPv6, including the port) (example: [ "24.17.1.23:54322" , "[2345:23::234]:32323" ] ) "capabilities" : } } ``` #### State event The device sends device state information periodically. If the controller detects that it has a newer configuration, it may decide to send this new configuration to the AP. ```json { "jsonrpc" : "2.0" , "method" : "state" , "params" : { "serial" : , "uuid" : , "request_uuid" : "state" : } } ``` #### Healthcheck event Device sends a `healthcheck` periodically. This message contains information about how vital subsystems are operating and if they need attention. ```json { "jsonrpc" : "2.0" , "method" : "healthcheck" , "params" : { "serial" : , "uuid" : , "request_uuid" : "sanity: "data" : } } ``` #### Log event Device sends a log message whenever necessary. The controller will log this message to the log system for the device. ```json { "jsonrpc" : "2.0" , "method" : "log" , "params" : { "serial" : , "log" : "severity" : , "data" : } } ``` #### Events Channel Device sends unsolicited events to the controller. ```json { "jsonrpc" : "2.0" , "method" : "event" , "params" : { "serial" : "001122334455" , "data" : { "event" : [ 1871263817263, { "type" : "the event type", "payload" : { "field1" : "value1" } } ] } } } ``` The first element of the `event` array is always the `timestamp` of the event. The `payload` is a JSON document contains addition information about the event. This _may not_ be empty. #### Alarms Channel Device sends unsolicited alarms to the controller. ```json { "jsonrpc" : "2.0" , "method" : "alarm" , "params" : { "serial" : , "data" : } } ``` #### Wifiscan Channel Device sends unsolicited wifiscans to the controller. ```json { "jsonrpc" : "2.0" , "method" : "wifiscan" , "params" : { "serial" : , "data" : } } ``` ##### `severity` The `severity` matches the `syslog` levels. Here are the details: - 0 : LOG_EMERG 0 /* system is unusable */ - 1 : LOG_ALERT 1 /* action must be taken immediately */ - 2 : LOG_CRIT 2 /* critical conditions */ - 3 : LOG_ERR 3 /* error conditions */ - 4 : LOG_WARNING 4 /* warning conditions */ - 5 : LOG_NOTICE 5 /* normal but significant condition */ - 6 : LOG_INFO 6 /* informational */ - 7 : LOG_DEBUG 7 /* debug-level messages */ #### Crash Log event Device may send a `crash log event` during rebooting after a crash. The event cannot be sent until a connection event has been established. ```json { "jsonrpc" : "2.0" , "method" : "crashlog" , "params" : { "serial" : , "uuid" : , "loglines" : [ an array of strings representing the logs from the log file ] } } ``` #### Reboot Log event The device may send a `reboot log event` after a reboot. This maybe a scheduled reboot or caused in some other way. ```json { "jsonrpc" : "2.0" , "method" : "rebootLog" , "params" : { "serial" : , "uuid" : , "date" : , "type" : , "info" : [ "info 1", "info 2"] } } ``` Here is a possible list of reboot reasons: #### Config change pending event Device sends this message to tell the controller that the device has received a configuration but is still running an older configuration. The controller will not reply to this message. ```json { "jsonrpc" : "2.0" , "method" : "cfgpending" , "params" : { "serial" : , "active" : , "uuid" : } } ``` #### DeviceUpdate event Device sends this message to tell the controller it is changing something is its configuration because of some requirement or some changes. ```json { "jsonrpc" : "2.0" , "method" : "deviceupdate" , "params" : { "serial" : , # a list of key value pairs representing the change i.e # "currentPassword" : "mynewpassword" } } ``` #### Send a keepalive to the controller event Device sends a keepalive whenever necessary. The device will send this message to tell the controller which version it is running. The Controller may decide to send the device a newer configuration. ```json { "jsonrpc" : "2.0" , "method" : "ping" , "params" : { "serial" : , "uuid" : } } ``` #### Recovery Event Device may decide it has to do into recovery mode. This event should be used. ```json { "jsonrpc" : "2.0" , "method" : "recovery" , "params" : { "serial" : , "uuid" : , "firmware: , "reboot" : true/false (shoudld the device be instructed to reboot after loggin the information), "loglines" : [ an array of strings representing the logs from the log file ] } } ``` The device should answer: ```json { "jsonrpc" : "2.0" , "result" : { "serial" : , "status" : { "error" : 0 or an error number, "text" : } }, "id" : } ``` #### Device requests a venue broadcast message Device send this message when it wants to reach out to all other APs in the same venue. The GW will find the venue where this device belongs and resend the same message to all other devices in the venue. ```json { "jsonrpc" : "2.0" , "method" : "venue_broadcast" , "params" : { "serial" : , "timestamp" : , "data" : } } ``` Upon receiving a `venue_broadcast` message, the GW will simply resent the message to all the APs in the venue. ### Controller commands Most controller commands include a `when` member. This is a UTC clock time asking the AP to perform the command at that time. This is a suggestion only. The AP may ignore this parameter. If a 0 (zero) is given, the command should be performed immediately. `when` is always a numeric parameter. #### Controller wants the device to apply a given configuration Controller sends this command when it believes the device should load a new configuration. The device should send message with `pending change` events until this version has been applied and running. ```json { "jsonrpc" : "2.0" , "method" : "configure" , "params" : { "serial" : , "uuid" : , "when" : Optional - "config" : } ``` The device should answer: ```json { "jsonrpc" : "2.0" , "result" : { "serial" : , "uuid" : , "status" : { "error" : 0 or an error number, "text" : "when" : , "rejected" : [ { "parameter" : , "reason" : , "substitution" : } ] } }, "id" : } ``` #### Controller wants the device to apply a given fixed configuration Controller sends this command when it requires the device to apply fixed configuration, eg. country code. The device should respond with message indicating failure or success. ```json { "jsonrpc" : "2.0", "method" : "fixedconfig", "params" : { "serial" : , "when" : Optional - "country" : "" }, } ``` If AP supports compressed configuration feature by inidcating `compress_cmd=true` in its capabilities, controller will send a compressed configuration message where configuration payload (i.e. contents of `params`) is compressed and encoded in base64 format: ```json { "jsonrpc" : "2.0", "method" : "configure", "params" : { "compress_64" : "", "compress_sz" : "" }, "id" : } ``` The device should answer: ```json { "jsonrpc" : "2.0", "result" : { "serial": , "status": { "error": 0 or an error number, "text": }, "uuid": } } ``` ##### The Answer The device can answer and tell the controller it has rejected certain parts of the config and potentially replaced them with appropriate values. This could be used to allow a device to replace frequencies for the regions it is located in. The device can provide an array of these rejections. The substitution JSON is optional. ###### Error codes - 0 : configuration was applied as-is. - 1 : configuration was applied with the included substitutions in the `rejected` section. The device is operating with the new modified config. - 2 : configuration was rejected and will not be applied at all. The `rejected` section can be used to tell the controller why. ###### The `rejected` section The rejected section is an array containing the following: - `parameter` : the JSON code in the config that is causing this rejection - `reason` : anything to explain the rejection. - `substution` : the JSON code that `parameter` was replaced with. This could be absent meaning that the `parameter` code was simply removed from the configuration. #### Controller wants the device to reboot Controller sends this command when it believes the device should reboot. ```json { "jsonrpc" : "2.0" , "method" : "reboot" , "params" : { "serial" : , "when" : Optional - }, "id" : } ``` The device should answer: ```json { "jsonrpc" : "2.0" , "result" : { "serial" : , "status" : { "error" : 0 or an error number, "text" : , "when" :