Skip to content
Start free evaluation

JSON command reference

Everything in PDComm Modbus is a JSON command. In the SDK you pass it to pdcomm_modbus_call or a wrapper’s call/Call, in the headless simulator as one line of standard input, and in MCP as the arguments of a modbus_<action> tool. The C, C++ and .NET functions themselves are in the API reference.

Outcome Reply
Success {"ok":true,"result":<result>}
Service error {"ok":false,"error":"<message>"}; the C ABI returns it with PDCOMM_MODBUS_SERVICE_ERROR. License errors also carry a code.
  • A missing action fails with Action is required; an unknown one with Unknown service action.
  • Member order in objects carries no meaning; replies list members in name order.
  • Service errors lists the error messages.

The pdu of request and execute and the bytes of fault accept two forms:

  • A hex string: "0300000001". Spaces between bytes are ignored ("03 00 00 00 01"). An odd number of digits fails with Invalid hex length; non-hex characters with Invalid hex.
  • A byte array: [3,0,0,0,1]. Values outside 0–255 fail with Expected a byte array or hex string.

The response in results is always an array of decimal bytes, or null when there’s no response.

Returns the build’s features; takes no arguments.

Result member Meaning
protocol Always "modbus"
tcp, rtu, ascii, security Transports and security included in the build
functions, diagnostics Supported function codes and diagnostics sub-functions
mei13 "opaque_extension": MEI 13 content isn’t interpreted.
canopen Always false
project_version Supported project version (1)
diagnostic_logging, logging_schema_version Diagnostic log support and log format version

Returns {"config":{...},"connected":<bool>,"listen_only":<bool>,"delimiter":<ASCII end character>,"trace_count":<entries>}. When a TCP client closed its connection after a timeout or a peer close, connected is false.

Replaces the whole configuration while disconnected and returns the same result as state. It also restarts the server’s diagnostics state (counters, listen-only mode). While connected it fails with Disconnect before changing configuration.

{"action":"configure","config":{"transport":"tcp","role":"client","address":"127.0.0.1:1502","port":"","unit":1,"baud":19200,"parity":"even","stop_bits":1,"timeout_ms":1000}}
Member Required Values Notes
transport Yes tcp, rtu, ascii
role Yes client, server, gateway Use gateway with rtu or ascii.
address Yes IP:port TCP address; required by the format even for serial configurations. Host names aren’t accepted.
port Yes String Serial device; "" for TCP
unit Yes 1–247
baud Yes 1 or more Needs a value even for TCP.
parity Yes even, odd, none
stop_bits Yes 1, 2 2 with none parity
timeout_ms Yes 1–60000
ascii_timeout_ms No 1–60000, default 1000
turnaround_ms No 0–60000, default 100
routes No {"TCP unit":serial address} Gateway routes; keys 1–255, values 1–247
security No Object or null Modbus/TCP Security; see below

Members of the security object, for TCP configurations only:

Member Required Description
chain, private_key, trust Yes PEM file paths. chain must end with the root CA.
mode No encrypted (default) or authentication_only
hostname No Name or IP the client checks in the server certificate. Default localhost
roles No Server: {"role":[function codes,...]}
null_role No Server: function codes allowed without a role. Default []
crls No List of CRL file paths
require_revocation No When true, revocation must be checked against CRLs; needs crls.

Unknown members fail with unknown field ... and missing required members with missing field ....

connect opens the socket, listener or serial port and returns state. A server opened on port 0 reports its actual address in config.address. When already connected it fails with Endpoint is already connected. The SDK libraries check the license on connect and, without one, return an error whose code is license_required (see Service errors). disconnect returns {"connected":false} and succeeds even when not connected.

Has a server or gateway serve its pending requests once and returns {"handled":N}. An application that builds a server with the SDK repeats it on a worker thread; the GUI, headless simulator and MCP server repeat it themselves.

Argument Description
pdu Request PDU
unit Optional, 0–255. Defaults to the configured unit.

The result is {"response":[...]|null,"status":"success"|"exception"|"no_response","source":"wire"}. It works on a connected client only; otherwise it fails with Connect a client before sending a request. A serial client can broadcast (unit 0) writes only, and gets no_response.

Takes the same arguments as request and runs against the endpoint’s own data model, with source local. In a serial configuration, a request for another unit address returns no_response, and a write to unit 0 is handled as a broadcast.

Returns the whole data model, in the format of model_set.

Argument Description
table coils, discrete_inputs, holding_registers, input_registers
address Start address
values Array of values; 0 or 1 for bit tables

Returns {"written":N}. It can change input tables too. Outside the model it fails with Address outside configured table, with wrong values Invalid data values, and with a wrong table name Unknown data table.

Validates the whole model, replaces it in one step and returns {"updated":true}. On failure the existing model stays.

Member Format Rules
coils, discrete_inputs, holding_registers, input_registers {"start":N,"values":[...]} Start plus count must fit the 16-bit address range (Invalid table range). Bit tables hold 0 or 1.
files {"file number":[words,...]} File numbers from 1, up to 10000 records
fifos {"FIFO pointer address":[values,...]} Up to 31 values
objects {"object ID":[bytes,...]} 0, 1 and 2 required; 7–127 reserved; up to 244 bytes each
server_id [bytes,...] 2–251 bytes; the content of the function 17 response
exception_status 0–255 The function 07 response
individual_access true/false Allows MEI 14 individual object reads

diagnostics returns {"register":N,"listen_only":<bool>,"delimiter":N,"event_log":[...],"counters":{...}}, where counters holds bus_messages, communication_errors, exceptions, server_messages, no_responses, naks, busy, overruns and events.

diagnostics_set sets the diagnostic register (register, 0–65535) and the busy state (busy) for testing. With busy true, the status word of functions 11 and 12 is FFFF. configure resets both.

trace returns the last 1000 entries as {"entries":[...]}, in two kinds:

Kind Members
Request entry sequence, source (local, wire), unit, request, response, status. For a failed request, status holds the error message, such as Timeout.
Raw serial bytes sequence, source (wire), direction (tx, rx, rx_discarded), transport, bytes, timestamp_us, timestamp_scope (host_io_batch), truncated

rx_discarded records bytes dropped because they were left over before a request or came from another address. trace_clear returns {"cleared":true}.

project_export returns {"kind":"pdcomm.modbus.project","version":1,"config":{...},"model":{...}}. project_import takes that object as project and returns {"loaded":true}, only while disconnected. Headless runs and scenarios describes the rules.

Argument Description
bytes Raw bytes to decode, up to 4096
transport Optional: tcp, rtu or ascii. Defaults to the configured transport.
gap_us Optional virtual gap between bytes fed to the RTU or ASCII decoder. Default 100

Returns {"source":"synthetic","frames":[...],"errors":[...]} without any I/O. The RTU decoder derives t1.5 and t3.5 from the configured baud.

Returns {"ports":["/dev/cu.usbserial-...",...]}.

logging_configure, logging_status, logging_flush

Section titled “logging_configure, logging_status, logging_flush”

Control the diagnostic log. The config of logging_configure takes enabled, level, file, max_bytes, files and forensics, and the command returns the log status. logging_flush returns {"flushed":true}. See Diagnose failures and report them.

SDK libraries only; the headless and MCP simulators don’t have them. A license applies to the whole library, not to one endpoint, so send these to any endpoint.

Command Input Result
license_install text: the license text. An empty string removes the installed text. {"installed":N}, where N is the number of blocks with a valid signature. Without such a block it fails with the code license_invalid, and the earlier text stays.
license_status None The license status object (build_date, host_id, sources, licenses, modules, and more)
host_id None {"host_id":"PDH1-XXXX-XXXX-XXXX-XXXX"}. When the id can’t be read, it fails with the code host_id_unavailable.

See Install and check a license for details.

Headless simulator only: ends the program without a reply. The SDK and the MCP server don’t have it.