The native command interface of the C100/AT300 uses JSON messages via Websocket (/socket). When establishing a new WebSocket connection, the webserver transmits one metadata message { "webserver_buildinfo": { "date": <string>, "time": <string> }, "protocol_features": <object> }. Whereas webserver_buildinfo can safely be ignored, protocol_features indicates support for API features that may be missing in older software versions and thus should always be parsed during initialization. For sufficiently old software versions, the protocol_features field will be missing entirely, implying protocol_features[x] = false for all x.
Each command is a JSON object containing at least the field op which contains the opcode to execute. The following opcodes are currently defined:
-
markerInserts a marker in the command stream which can be used to get a feedback after all previously issued commands have been executed. The marker is a 15 bit number (0 ... 32767) which must be specified in the fieldmarkerwith bit 15 set.Example:
{"op": "marker", "marker": 32769}will request a marker1to be sent back. -
dataBasic data changing command which can change one or more keywords inside one keyword list. The following fields are required:kwlThe keyword list namekwA JSON object where the field names are the keyword names. More than one keyword can be set in a single command.
Example:
{"op": "data", "kwl": "p_t_p_clock", "kw": {"mode": "UseInternalOscillator"}}When the target keyword is a fixed length array the parameter must be a JSON object of the same length or a partial update.
To update only some array elements send an JSON object (instead of an JSON array) where the key is the array index to update:
Example:
{"op": "data", "kwl":"audio_gain.levels[0].outputs[0].control", "kw": {"gain": {"0": -6.0, "7": +2.0}}} -
treeModify multiple keywords over multiple keyword lists in a compact format. The fieldkwlis a JSON object containing the first sub tree to modify. The field names are the keyword list names, and the values are JSON objects containing:kwl(optional) another subtree, the keyword list names are relative to the current keyword list.kw(optional) a JSON object where the field names are the keyword names. More than one keyword can be set in a single command.
Example:
{"op": "tree", "kwl": {"color_correction": {"kw": {"source_command": "video_signal_generator.output"}, "kwl": {"yuv": {"kw": {"active_command": true, "hue_offset": 0.01}}}}}}Array keywords are handled as with the
dataopcode. -
subscribeSubscribe to get notified when a keyword changes its value. The following fields are required:kwlThe keyword list name or an array of keyword list nameskw(optional) The keyword name or an array of keyword names
When an array of keyword list names is specified then the specified keywords are subscribed for each of the specified keyword lists. Keyword list names can also contain ranges where array / table indices are specified.
When an array of keyword names is specified then all specified keywords are subscribed for each listed keyword list. When no keyword names are specified then all keywords of the specified keyword lists are subscribed (this can be a lot of keywords!).
Examples
{"op": "subscribe", "kwl": "p_t_p_clock", "kw": ["state", "relative_clock_speed"]}{"op": "subscribe", "kwl": "network_interfaces.ports[0:1].aggregate_traffic_statistics.rx_multicast", "kw": "packets_per_sec"}
If a keyword was already subscribed then that keyword is ignored, otherwise the current value is sent back. You can use the
markerfunction to get a notification when all subscription commands have been executed. -
subscribe(with ID) Subscribe to get notified when a keyword changes its value. The following fields are required:kwlThe keyword list name or an array of keyword list nameskwThe keyword name or an array of keyword namesidThe starting ID - the client assigns this ID and must ensure that it is unique within the websocket session's active subscriptions. The maximum ID value is 0x7FFFFFFE.
When an array of keyword list names is specified then the specified keywords are subscribed for each of the specified keyword lists. Keyword list names can also contain ranges where array / table indices are specified.
When an array of keyword names is specified then all specified keywords are subscribed for each listed keyword list. The number of IDs used is
number of kwlstimesnumber of kw, starting with all specified keyword inkwin the firstkwl. If ranges are used than these are expanded before.If an keyword or keyword list is not found the IDs which would be assigned to it are skipped so that the remaining keywords get their ID independent of any previous errors. If an entry in
kwlcan't be parsed the command will stop and all following entries are ignored.Examples
-
{"op": "subscribe", "kwl": ["network_interfaces.ports[0].aggregate_traffic_statistics.rx_unicast", "network_interfaces.ports[0].aggregate_traffic_statistics.rx_multicast"], "kw": ["bytes_total", "packets_total"], "id": 42}In this example the IDs assigned are as following: 42. network_interfaces.ports[0].aggregate_traffic_statistics.rx_unicast.bytes_total 43. network_interfaces.ports[0].aggregate_traffic_statistics.rx_unicast.packets_total 44. network_interfaces.ports[0].aggregate_traffic_statistics.rx_multicast.bytes_total 45. network_interfaces.ports[0].aggregate_traffic_statistics.rx_multicast.packets_total
-
{"op": "subscribe", "kwl": ["network_interfaces.ports[0:1].aggregate_traffic_statistics.rx_unicast", "network_interfaces.ports[0:1].aggregate_traffic_statistics.rx_multicast"], "kw": ["bytes_total", "packets_total"], "id": 42}In this example the IDs assigned are as following: 42. network_interfaces.ports[0].aggregate_traffic_statistics.rx_unicast.bytes_total 43. network_interfaces.ports[0].aggregate_traffic_statistics.rx_unicast.packets_total 44. network_interfaces.ports[1].aggregate_traffic_statistics.rx_unicast.bytes_total 45. network_interfaces.ports[1].aggregate_traffic_statistics.rx_unicast.packets_total 46. network_interfaces.ports[0].aggregate_traffic_statistics.rx_multicast.bytes_total 47. network_interfaces.ports[0].aggregate_traffic_statistics.rx_multicast.packets_total 48. network_interfaces.ports[1].aggregate_traffic_statistics.rx_multicast.bytes_total 49. network_interfaces.ports[1].aggregate_traffic_statistics.rx_multicast.packets_total
-
unsubscribeUnsubscribe from keyword change notification and clears the ID. This command has the same fields and features as thesubscribecommand (except theid). -
readAllRead the current value of one or more keywords. This command has the same fields and features as thesubscribecommand. Unlike the subscribe command - this command will always send back the current value of a keyword even if a subscription exists. -
flagsModify flags of the current websocket session. The following flags are currently defined:report errorsWhen set totrueall errors encountered while parsing commands are reported viaerror reportresponse messages. Possible errors include unknown keyword (list) names or wrong value formats for keywords.
Example:
{"op": "flags", "flags": {"report errors":true}}A possible error response message may look like this:
{"error report": {"msg": "ParseError", "params": ["pool", "table_cmd", "DELETE_NO_ROWS"]}}
Additionally it is possible to send multiple commands in the same websocket message by packing them into a JSON array. A websocket message message must not exceed 1MB (1048576 bytes) or the websocket connection will be closed.
There are several keyword lists representing tables in the C100/AT300 which have a dynamic number of rows (including gaps).
One example of this is the table i_o_module.input. It has a keyword named rowMask which can only be read/subscribed and encodes which table rows exist.
The value is a string containing hex bytes. The first character encodes the present bits of table rows 0 to 3 (bit 0 for row 0 etc). The 2nd character encodes the present bits of table row 4 to 7 etc. Trailing 0 characters can be omitted.
The rows are named based on the table name with their index appended in brackets: i_o_module.input[0]
Named tables are an extension to normal tables. Rows can be created, deleted and named by the user. Row names are unique within the named table. The following keywords exist on the table level:
-
create_rowCreate new table rows. As value you can pass the following:-
nullCreates a new row with a default name if a free row exists. -
a JSON object containing one or more of the following requirements:
indexThe desired row indexnameThe desired row nameallow_reuse_rowIf set totruean existing row which matches all listed requirements will be returned instead of an error.request_idIf set to an unsigned 32-bit integer, this ID will be included with the corresponding response to safely distinguish between concurrent row creation requests. Note thatrequest_idis only supported ifprotocol_features['create_row_request_id'] = true; submitting request IDs to older software versions will cause the request to be denied.
If requirements are listed then all must be fulfilled or the request fails. If for example the specified row name already exists with another index than the requested one the request to create the row fails.
The result of creating the row is sent back only to the websocket connection from which the
create_rowcommand was received via the keywordcreated_row(you must subscribe to this keyword before sending the create row command). -
-
created_rowA subscribe only status keyword which is used to return the result of thecreate_rowkeyword. The value is an array of at least 2 elements, where the first entry is the row index and the second entry is the row name. If the row creation failed then both entries arenull. If arequest_idhad been specified as part of thecreate_rowrequest, it will be returned as the array's third entry. -
table_cmdCommands which affect all rows of the table:NOOPDoes nothingDELETE_ALL_ROWSDelete all rows of the table which can be deleted. Some tables have restriction that prevent deleting 'active' table rows. The definition of this depends on the named table.
In addition to the table keywords each named table row also has additional keywords:
-
row_name_commandChange the name of the table row. The name must follow the row name rules and must not be in use by another row of this table. -
row_name_statusThe current name of the table row. -
row_cmdCommands which affect only this table row:NOOPDoes nothingDELETE_ROWDelete this table row if it can be deleted.
Row names have a maximum length of 32 bytes and must be in UTF8 format. The following characters are not allowed:
- Control characters below 32
"quotation mark\back space
Each response is a JSON array which can contain one or more of the following JSON objects:
-
kwl,kwKeyword changes for keywordssubscribewithout ID orreadAllresults.kwlis a string naming the keyword list, andkwis a JSON object where the keys are the keyword names inside the specified keyword list. Examples:{"kwl":"network_interfaces.ports[0].aggregate_traffic_statistics.rx_unicast","kw":{"bytes_total":675234,"packets_total":562}} -
idKeyword changes for keywordssubscribewith ID.This contains a JSON object where the keys are the user defined IDs. Example:
{"id":{"42":675234,"43":562}}
The last JSON object in the array can also be one of the following. In which case the next websocket packet needs to be handled differently:
-
fileAn inline file (either text or binary) is sent following this websocket packet. The name of the file is specified as a value of this parameter. -
thumbnailAn inline thumbnail (JPEG format) is sent as a binary packet following this websocket packet. The name of the thumbnail is specified as a value of this parameter.Currently NOT implemented.
After the special packet has been send a normal JSON array is sent again.