LoopIT

JSON command reference

neuroConn GmbH

2026-06-05

JSON command reference

A structured reference for the parameter server messages, to complement the parameter server guide (which explains the concepts). Each entry gives the request shape, the reply, and a concrete example.

Conventions used here:

  • Requests are JSON objects sent over TCP to port 1219; a request is shown as a code block, a reply as indented text (it is server output, not something you send).
  • A parameter is addressed by module -> "index" (a quoted string, counting from zero) -> field. By default every request also carries a top-level token (omitted from the examples below for brevity — see Authentication).
  • value is a string, integer, boolean, or a nested object.

Discovery

Current configuration

The headline discovery call: refresh and return the device’s full configuration — every module, instance, and parameter, with metadata.

{ "?": { "!": "conf" } }

Reply (shape): a nested module -> index -> parameter object describing what the device supports. Read it to learn which modules and fields exist, then address those.

Cached configuration

Return the last configuration without refreshing it.

{ "?": "conf" }

Sockets

List the device’s module sockets, refreshing first or from cache:

{ "?": { "!": "sockets" } }
{ "?": "sockets" }

Reading and writing

Read a parameter

Use null as the value.

{ "current_source": { "0": { "stimulation": null } } }

Reply (shape): the same object with the current value in place of null, e.g. {"current_source": {"0": {"stimulation": false}}}.

Set a parameter

Give a real value.

{ "current_source": { "0": { "stimulation": true } } }

Reply: the request echoed back on success.

Set a mode

Some modules run in modes; the mode name nests between the index and the parameters. Changing a mode requires supplying all of that mode’s parameters (the device keeps no defaults).

{
  "current_source": {
    "0": {
      "tdcs": {
        "amplitude": 1000000,
        "duration": 6000,
        "fade_in": 3000,
        "fade_out": 3000,
        "fade_in_type": "linear",
        "fade_out_type": "linear"
      }
    }
  }
}

Wildcards

"*" matches everything at its level. Read every parameter of every module:

{ "*": null }

Read every parameter of one module instance:

{ "current_source": { "0": { "*": null } } }

Authentication

By default every message carries a top-level token (the six-digit one-time password shown on the device’s touchscreen):

{ "token": "123456", "current_source": { "0": { "stimulation": true } } }

Token errors come back as [null, <reason>] with reason token::invalid (wrong token) or token::deprecated (the IP was paired but the token has since changed). After several invalid attempts the device temporarily refuses further tokens from that IP.

Replies and errors

Every request gets a reply. A valid request echoes the value. An invalid key or value is reported in one of two forms — a bare null child of the offending key, or a two-element array whose second entry is a reason string:

{"current_source": {"0": {"stimulation": null}}}
{"current_source": {"0": {"amplitude": [null, "invalid_value"]}}}

A single request can mix valid and invalid parameters; the reply is per-parameter (the accepted ones echo, only the offending ones carry an error). The reason strings the device uses are:

write_protected, read_protected, not_available, invalid_token, invalid_syntax, invalid_module, invalid_index, invalid_field, invalid_value, invalid_mode, invalid_mode_syntax, too_few_fields, too_many_fields, too_many_values, too_few_values, missing_required_field, mixed_getters_and_setters.

A message sent before the device has finished booting receives [null, "still-booting"]; an over-length or non-ASCII message receives message-larger-than-allowed or message-contains-non-ascii-characters.

Deploying a real-time script

Write the RALGOL script text to the .protocol field of the ral module:

{ "ral": { "0": { ".protocol": "1w interface{1w reserved;} ral; script{};" } } }

Read the running script back:

{ "ral": { "0": { ".protocol": null } } }

On success the reply echoes the script and, when a timing model is present, adds an estimated_runtime with the per-cycle cost at the 50th/90th/99th percentile in microseconds:

{"ral": {"0": {".protocol": "...", "estimated_runtime": {"p50_us": 7, "p90_us": 9, "p99_us": 12}}}}

A compile or assembly failure returns [null, "<compiler message>"]; a script that would not fit the real-time budget returns [null, "Script exceeds RT budget ..."]. The companion field .cycle_time_in_ms selects the engine (<= 0 real-time RALEE, > 0 event-driven EVEE) and must be set before .protocol:

{ "ral": { "0": { ".cycle_time_in_ms": 0 } } }

Not implemented

The device-identification query {"?": null} (returning model name, serial number, and unique device identifier) is not currently implemented and is not answered.

See also

LoopIT documentation · neuroConn