Skip to main content
Version: 3.0 (next)

Modbus Nodes

Modbus is the most widely deployed protocol in industrial automation. MaestroHub supports all three variants: TCP, RTU, and ASCII so you can communicate with PLCs, sensors, meters, and supervisory systems from a single node set.

Configuration Quick Reference​

FieldWhat you chooseDetails
ParametersConnection, Function, Function Parameters, Timeout OverrideSelect the connection profile, function, configure function parameters with expression support, and optionally override timeout.
SettingsDescription, Timeout (seconds), Retry on Timeout, Retry on Fail, On ErrorNode description, maximum execution time, retry behavior on timeout or failure, and error handling strategy. All execution settings default to pipeline-level values.

Modbus Read node configuration

Modbus Read Node

Modbus Read Node​

Read data from PLCs, sensors, meters, and industrial devices.

Supported Function Types:

Function NamePurposeCommon Use Cases
Read Coils (0x01)Read digital outputsMotor status, valve positions
Read Discrete Inputs (0x02)Read digital inputsLimit switches, sensors
Read Holding Registers (0x03)Read holding registersSetpoints, configuration
Read Input Registers (0x04)Read input registersTemperature, pressure, flow

Node Configuration​

ParameterTypeRequiredDescription
ConnectionSelectionYesModbus connection profile to use
FunctionSelectionYesRead function from the selected connection
Function ParametersDynamicVariesAuto-populated from the function schema (e.g., address, quantity, dataType). See your Modbus connection functions for full parameter details.
Timeout OverrideNumber (seconds)NoOverride the default function timeout

All function parameters support expression syntax ({{ expression }}) for dynamic values from the pipeline context.

Input​

The node receives the output of the previous node as input. Input data can be referenced in function parameter expressions using $input.

Output Structure​

On success the node delivers the read under result and execution facts under _metadata:

{
"result": {
"address": 0,
"quantity": 1,
"registers": [215],
"value": 21.5,
"dataType": "float32",
"raw": "AAE="
},
"_metadata": {
"success": true,
"functionId": "<function-id>",
"durationMs": 42,
"timestamp": "2026-01-15T08:30:00Z"
}
}
FieldTypeDescription
result.addressnumberThe start address that was read
result.quantitynumberHow many coils, inputs or registers were read
result.rawstringThe raw response bytes, base64-encoded
result.coilsboolean[]FC01 only — one boolean per coil, in address order
result.inputsboolean[]FC02 only — one boolean per discrete input, in address order
result.registersnumber[]FC03/FC04 only — the raw 16-bit register values
result.valueanyFC03/FC04 only — the registers decoded as the configured dataType. This is the reading: $node["Name"].result.value
result.dataTypestringFC03/FC04 only — the data type the registers were decoded as
_metadata.successbooleantrue when the function executed without errors
_metadata.functionIdstringID of the executed function
_metadata.durationMsnumberExecution time in milliseconds
_metadata.timestampstringISO 8601 / RFC 3339 UTC timestamp

Which keys are present depends on the function the node is bound to: a coil read has coils, a discrete-input read has inputs, a register read has registers, value and dataType. address, quantity and raw are always there.


Modbus Write node configuration

Modbus Write Node

Modbus Write Node​

Write control values, setpoints, and configuration to devices.

Supported Function Types:

Function NamePurposeCommon Use Cases
Write Single Coil (0x05)Write single digital outputStart/stop motor
Write Single Register (0x06)Write single registerUpdate setpoint
Write Multiple Coils (0x0F)Write multiple digital outputsBatch control
Write Multiple Registers (0x10)Write multiple registersConfiguration update

Node Configuration​

ParameterTypeRequiredDescription
ConnectionSelectionYesModbus connection profile to use
FunctionSelectionYesWrite function from the selected connection
Function ParametersDynamicVariesAuto-populated from the function schema (e.g., address, value, values). See your Modbus connection functions for full parameter details.
Timeout OverrideNumber (seconds)NoOverride the default function timeout

All function parameters support expression syntax ({{ expression }}) for dynamic values.

Input​

The node receives the output of the previous node as input. Use expressions like {{ $input[0].result.value }} to pass dynamic values to write parameters.

Output Structure​

The write node delivers a confirmation of what was written under result, with the same _metadata as the read node:

{
"result": {
"address": 0,
"quantity": 2,
"values": [100, 200],
"raw": "AAE="
},
"_metadata": {
"success": true,
"functionId": "<function-id>",
"durationMs": 15,
"timestamp": "2026-01-15T08:30:00Z"
}
}
FieldTypeDescription
result.addressnumberThe address that was written
result.rawstringThe raw response bytes, base64-encoded
result.valueanyFC05/FC06 only — the single value that was written, as sent
result.quantitynumberFC15/FC16 only — how many coils or registers were written
result.valuesany[]FC15/FC16 only — the values that were written, as sent
Safety First

Always implement validation and safety checks before writing to industrial equipment. Consider adding condition nodes to verify values are within safe ranges.


Modbus Read Group Node​

The Modbus Read Group node executes multiple Modbus read operations in a single node. It supports selective function lists, an All Functions mode for complete device snapshots, and parallel or sequential execution.

Modbus Read Group node configuration

Modbus Read Group Node

Node Configuration​

ParameterTypeRequiredDefaultDescription
ConnectionSelectionYes—Modbus connection profile
Function SelectionSelectionNoSelect FunctionsSelect Functions reads the functions you list. All Functions reads every read function on the connection. By Labels reads every function whose labels match the labels you pick.
FunctionsArray of {functionId, alias}When Function Selection is Select Functions[]List of specific functions to execute. Each entry requires a functionId; alias is optional.
Execution ModeSelectionNoparallelparallel — all functions run concurrently. sequential — functions run one after another.
Continue on ErrorToggleNotrueWhen enabled, the node continues executing remaining functions even if one fails
Debug ModeToggleNofalseEnable detailed logging for troubleshooting

All Functions Mode​

When Function Selection is All Functions, the function list is ignored. The node automatically discovers and executes every read function defined on the selected connection.

Read function types that All Functions runs:

Function TypeFunction Code
modbus.read.coilsFC01
modbus.read.discreteInputsFC02
modbus.read.holdingRegistersFC03
modbus.read.inputRegistersFC04

Input​

The node receives the output of the previous node as input.

Output Structure​

The node output is the canonical {result, _metadata} envelope: result holds one entry per function read, keyed by the function's output key; _metadata holds the group's accounting.

{
"result": {
"Temperature Sensor": {
"value": 22.5,
"success": true,
"error": "",
"duration": 45,
"timestamp": "2026-09-07T08:30:00Z"
},
"Coil Bank": {
"value": { "address": 0, "quantity": 8, "raw": "AQ==", "coils": [true, false, false, true, false, false, false, false] },
"success": true,
"error": "",
"duration": 38,
"timestamp": "2026-09-07T08:30:00Z"
}
},
"_metadata": {
"connectionId": "conn-123",
"connectionName": "PLC-01",
"total": 2,
"successful": 2,
"failed": 0,
"totalDuration": 83,
"executionMode": "parallel",
"originalRequests": 2
}
}

Each entry under result is one function's read — keyed by the function's alias, else its name, else its id (see Output Key Resolution):

FieldTypeDescription
result.<alias>.valueanyWhat the function read — its own result.value when it has one (the registers decoded as the configured dataType for a register read; the whole {coils} or {inputs} object for a coil or discrete-input read), otherwise its whole result. null when the read failed
result.<alias>.successbooleantrue when this function's read succeeded
result.<alias>.errorstringWhy the read failed; empty when it succeeded — always present
result.<alias>.durationnumberHow long this function's read took, in milliseconds
result.<alias>.timestampstringWhen the read was issued, RFC 3339 UTC

The _metadata object is the group's execution summary:

FieldTypeDescription
_metadata.connectionIdstringThe connection every function was read on
_metadata.connectionNamestringThat connection's display name
_metadata.totalnumberHow many functions the group ran
_metadata.successfulnumberHow many read successfully — including the ones onChange then suppressed
_metadata.failednumberHow many failed; successful + failed = total
_metadata.totalDurationnumberWall-clock time of the whole group, in milliseconds
_metadata.executionModestringparallel or sequential
_metadata.originalRequestsnumberHow many functions were selected to run
_metadata.coalescedRequestsnumberParallel mode only, when coalescing merged adjacent register reads — how many protocol requests the batch issued; compare with originalRequests to see the saving. See Coalescing
_metadata.keyCollisionsstring[]Output keys that two or more functions resolved to — the later read overwrote the earlier under that key. Present only when it happened
_metadata.configWarningsstring[]Non-fatal problems in the node's config, each saying what was ignored. Present only when there were any
_metadata.outputModestringonChange — present only in that mode
_metadata.suppressedCountnumberonChange mode: how many successful reads were unchanged since the last run and left out of result
_metadata.emittedCountnumberonChange mode: how many entries result carries — total − suppressedCount
_metadata.suppressedKeysstring[]onChange mode: the output keys left out as unchanged. Present only when at least one was
_metadata.reasonstringonChange mode, when every successful read was unchanged: why result is empty — the node buffers instead of waking downstream

Output Key Resolution​

Each function result is keyed in the output map using the first available value:

  1. Alias — the custom alias set in the function entry
  2. Function Name — the name defined on the connection function
  3. Function ID — the unique function identifier (fallback)

Use aliases to give results predictable, human-readable keys, especially when the same function type is read from multiple address ranges.

Execution Modes​

Parallel (Recommended) (default)

  • Adjacent function reads are merged into batched Modbus requests via register coalescing (see Coalescing below).
  • Fewest TCP roundtrips, lowest total execution time on most devices.
  • Best when functions cluster in nearby address ranges.

Sequential

  • Each function is sent as its own Modbus request, in list order.
  • No coalescing — every function reads exactly its own configured range.
  • More predictable timing and lower peak load on the device.
  • Use this mode if your slave has a sparse register map and a parallel read would batch across unmapped addresses.
  • When Continue on Error is off, execution stops at the first failure.

Coalescing​

In parallel mode, the Read Group node merges adjacent register reads into a single broader Modbus request to reduce TCP roundtrips. For example, three Read Holding Register functions at addresses 100, 102, and 104 (each reading 2 registers) become one ReadHolding(100, 6) instead of three separate requests.

The merging behavior is controlled by the Coalesce Max Register Gap setting on the Modbus connection — not on this node. This is intentional: the safe gap value depends on the slave's register layout, which is a property of the device, not of the pipeline.

Trade-off

Coalesce Max Register GapEffect
0 (default)Only strictly adjacent or overlapping reads merge. Safe on every slave; the executor never requests a register you didn't configure.
Higher valuesMore aggressive batching. The executor may request registers between your functions; if those registers are unmapped on the slave, the entire batch fails with illegal data address.

When parallel mode fails for one connection but works for another

The Modbus spec requires the slave to reject a Read Holding Registers request if any register in the requested range is unmapped — not just the ones you care about. So a coalesced batch can fail entirely on a sparse register map even when each individual function would succeed. If you see every function in a Read Group return exception '2' (illegal data address) only in parallel mode, lower the connection's Coalesce Max Register Gap value (or use sequential mode).

The _metadata.coalescedRequests field on the node output tells you how many actual Modbus requests were issued. Comparing it to originalRequests shows the optimization gain — for instance, originalRequests: 31, coalescedRequests: 8 means 31 user-defined functions were served by 8 protocol-level requests.

Error Handling​

Continue on ErrorBehavior
true (default)The node completes even if individual functions fail. Failed functions include an error field in their result. The node output remains successful.
falseThe node fails as soon as any function fails. In sequential mode, remaining functions are skipped. The node result is marked as failed.

Validation Rules​

  • connectionId is required.
  • executionMode must be parallel or sequential.
  • With Select Functions, at least one function entry is required; with By Labels, at least one label is required.
  • Duplicate functionId values are not allowed.
  • Duplicate alias values are not allowed.
  • The connection type must be modbus.

Best Practices​

  • Use All Functions for device commissioning, complete state backups, and monitoring dashboards where you need every data point.
  • Use specific functions in production pipelines with known data requirements for better performance and clarity.
  • Assign aliases when reading multiple functions of the same type to keep output keys readable.
  • Prefer parallel mode unless the target device has limited concurrent request handling.
  • Enable Continue on Error for monitoring scenarios where partial data is still valuable.

Settings Tab​

All three Modbus node types share the same Settings tab:

SettingTypeDefaultDescription
DescriptionText—Optional description displayed on the node
Timeout (seconds)NumberPipeline defaultMaximum time the node may run before timing out
Retry on TimeoutTogglePipeline defaultAutomatically retry the node if it times out
Retry on FailTogglePipeline defaultAutomatically retry the node if it fails
On ErrorSelectionPipeline defaultError strategy: Pipeline Default (the pipeline's Error Handling setting), Stop Pipeline or Continue Execution

When left at their defaults, these settings inherit from the pipeline-level execution configuration.