Skip to content

Usage guide

Available nodes

Node Purpose
slmp-connection Shared MELSEC SLMP connection profile for slmp-read and slmp-write.
slmp-read Reads one or more device addresses and writes the result to msg.payload.
slmp-write Writes one or more device values from static configuration or incoming messages.

slmp-connection config node

Config field Description
Name Optional display-only label. Empty/whitespace/non-string values mean no custom label; duplicate labels are allowed and never identify a connection or PLC route.
Host PLC host name or IP address. For the examples, use 192.168.250.100.
Port TCP or UDP port. Use 1025 for TCP examples and 1035 for UDP examples.
Transport tcp or udp.
Timeout ms Communication timeout in milliseconds.
PLC profile Required canonical PLC profile. The current editor options are melsec:iq-f, melsec:iq-r, melsec:iq-r:rj71en71, melsec:iq-l, melsec:mx-f, melsec:mx-r, melsec:mx-r:rj71en71, melsec:lcpu, melsec:lcpu:lj71e71-100, melsec:qcpu:qj71e71-100, melsec:qnu, melsec:qnu:qj71e71-100, melsec:qnudv, and melsec:qnudv:qj71e71-100.
Use remote password Explicitly enables the remote-password lifecycle. Leave unchecked when the PLC route does not use it.
Remote password Required and non-empty when Use remote password is checked. Disabled otherwise.
Monitor timer SLMP monitoring timer field in 250 ms units, 0 to 65535. A new node starts at 16 (four seconds). An explicit 0 requests an indefinite PLC-side processing wait.
Network Target network number, 0 to 255.
Station Target station number, 0 to 255.
Module I/O Target module I/O number, entered as hexadecimal such as 03FF.
Multidrop Target multidrop station number, 0 to 255.

Requests that share one slmp-connection are sent in FIFO order. The next request waits until the previous request has received a response, timed out, or failed. This is intentional for SLMP compatibility because PLCs have model-dependent limits for commands sent before earlier responses arrive. Disconnect rejects both active and queued work and prevents queued work from reconnecting after that close. A later, newly admitted operation may open a new transport generation.

Concurrent disconnect/close() callers share one close flight. Managed password locking and local transport close run at most once for that flight, all callers observe the same result, and new connects or operations remain blocked until the complete close has settled. A later sequential close remains safe and idempotent.

TCP connections enable keepalive after 30 seconds idle. UDP timeouts discard the timed-out socket generation before a later request can open a new one. A UDP socket error also detaches and closes that generation so its local port and listeners are released; late events from it cannot affect a replacement socket. A UDP request completes only after both the socket send callback has succeeded and the matching response has arrived. A response received first is held provisionally. A later send failure discards it and invalidates the transport; request and byte counters are not published while the response is provisional. A missing callback or response remains bounded by the same absolute deadline.

The monitor timer and Timeout ms control different waits. The monitor timer is sent to the PLC. Timeout ms is one local absolute transaction deadline covering lazy connection, send completion, response framing/correlation, and decode. Therefore, even when the monitor timer is explicitly 0, the client can still end the request when its communication timeout expires. Missing monitor timer settings use 16; null, blank, Boolean, fractional, negative, non-finite, and out-of-range values are configuration errors rather than defaults.

For parallel communication, use separate slmp-connection config nodes. Each config node owns its own client connection and therefore its own request queue.

Remote password

Node-RED is the only SLMP package here with a connection-field remote password lifecycle. When Use remote password is checked and a non-empty credential is set, the node unlocks after opening and, when idle, tries to lock before disconnecting. If work is active or queued, disconnect prioritizes deterministic cancellation and local close, so the PLC lock state is unknown and disconnect reports SLMP_OPERATION_OUTCOME_UNKNOWN with reason closed. The local transport is still closed. The field is disabled and not forwarded when the checkbox is off. When it is on, iQ-R credentials must be 6–32 printable ASCII characters and Q/L credentials must be exactly 4 printable ASCII characters.

If a concurrent disconnect occurs only after a response has already decoded, the decoded success, write acknowledgement, or PLC end code remains the operation result. The same result remains definitive if the local transaction deadline passes afterward. An incomplete read reports SLMP_CLOSED. An incomplete state-changing operation that may have been sent reports SLMP_OPERATION_OUTCOME_UNKNOWN with reason closed.

Authentication belongs to one concrete TCP/UDP connection. A reconnect unlocks again before the first normal command; a failed normal command is never replayed automatically. Disconnect always closes the local transport. If the PLC rejects the final lock or the lock times out, the disconnect operation reports that failure and does not claim that the PLC is locked.

For C200-series password end codes, see the shared SLMP Troubleshooting & Codes page.

Routing / target station

Every saved connection explicitly contains all four route fields. The editor initializes a new connection for the directly connected own station. Change those values only when your PLC network is configured for another station, multi-CPU module I/O, or multidrop access.

Route fields control the SLMP destination header. They are not device family selectors; routed devices such as Un\Gn and Jn\... still need their own address syntax.

Per-request routing can be supplied from a message:

{
  "target": {
    "network": 1,
    "station": 2,
    "moduleIO": 1023,
    "multidrop": 0
  }
}

The same object can be placed in msg.slmp.target, or configured through the Route source on slmp-read and slmp-write.

Runtime route objects use primitive integer Numbers for all four fields. String, Boolean, boxed, and coercible values are rejected. Saved connection fields and literal Route JSON are editor configuration: the runtime converts their decimal fields and hexadecimal moduleIO field before calling the client, so the visible own-station default remains 03FF. Dynamic msg, flow, global, and environment route objects must already use Numbers.

Route priority is msg.target, msg.slmp.target, configured Route source, then the connection route when no override is present. If a higher-priority property or configured source exists but is invalid or missing its referenced value, the operation fails; it does not continue to a different PLC route.

JavaScript code that calls the low-level client can use ModuleIONo constants for moduleIO, for example ModuleIONo.MULTIPLE_CPU_2. Low-level clients must receive a complete route; a missing or partial route is rejected.

For low-level iQ-R multi-CPU U3En\HG... access, the qualified device never changes the request target. The application must explicitly select the target CPU when a write must be reflected there. A write can return a normal end code without changing the intended CPU buffer when the selected request target identifies a different CPU or Own Station; cross-CPU reads remain valid. No automatic target fallback, resend, readback, or retry is performed. See the shared iQ-R target guidance.

Low-level SlmpClient users can register Word/DWord monitor devices with registerMonitorDevices or registerMonitorDevicesExt, then execute one cycle with explicit wordPoints and dwordPoints. selfTestLoopback(Buffer) and clearError() provide fixed semantic system commands without raw command numbers. The combined monitor count must be nonzero and cannot exceed the selected profile's monitor-registration limit. These low-level operations are not additional Node-RED node types.

slmp-read and slmp-write use the public high-level address parser for normal device addresses. They do not expose Un\G, Un\HG, or Jn\... extended device access as user-facing address forms.

slmp-read node

Config field Description
Name Optional display-only label; it is not sent, emitted as metadata, or used as the connection identity.
Connection The slmp-connection config node to use.
Source Where to read the address list from: literal text, msg, flow, global, or env.
Addresses Literal address list when Source is literal text. Use one address per line for clarity.
Route Optional per-request route source: literal JSON, msg, flow, global, or env.
Route JSON Literal route object with network, station, moduleIO, and multidrop.
Output object always returns an address-keyed object, array always returns an array, and value requires exactly one address.
Metadata full, minimal, or off for msg.slmp output.
Errors Throw, attach to msg.error, or send the failed message to a second output.
Msg field Description
msg.addresses When present, a non-empty string or an array containing only non-empty address strings. Invalid input fails and never falls back to the configured Source.
msg.target Per-request route override object.
msg.slmp.target Per-request route override when msg.target is not set.
msg.topic connect, disconnect, or reinitialize controls the shared connection instead of reading.
msg.connect When true, opens the shared connection.
msg.disconnect When true, closes the shared connection.
msg.reinitialize When true, closes and reconnects the shared connection.
Output field Description
msg.payload Read result. Object mode is keyed by normalized address, array mode follows address order, and value mode returns a scalar for one address.
msg.slmp.addresses Full metadata mode only: normalized address list.
msg.slmp.connection Full metadata mode only: effective connection profile, frame type, target, and remote password status.
msg.slmp.target Full and minimal metadata modes: effective route target.
msg.slmp.targetSource Full and minimal metadata modes: msg.target, msg.slmp.target, configured.<type>, or connection.
msg.slmp.itemCount Minimal metadata mode only: number of requested addresses.
msg.error Error object when Errors is msg.error, or on the second output when Errors is second output.

slmp-write node

Config field Description
Name Optional display-only label; it is not sent, emitted as metadata, or used as the connection identity.
Connection The slmp-connection config node to use.
Source Where to read updates from: literal text, msg, flow, global, or env.
Static updates Literal JSON object when Source is literal text.
Route Optional per-request route source: literal JSON, msg, flow, global, or env.
Route JSON Literal route object with network, station, moduleIO, and multidrop.
Metadata full, minimal, or off for msg.slmp output.
Errors Throw, attach to msg.error, or send the failed message to a second output.
Msg field Description
msg.updates Runtime update object, for example { "D300:U": 123, "M1000:BIT": true }.
msg.address Single-address write path.
msg.dtype Required for a bare single-write address. Use exactly BIT, U, S, D, L, F, or STR. Omit it when the address already contains a complete dtype or word-bit selector; specifying both is an error.
msg.value Single-address write value. Required when msg.address is used.
msg.target Per-request route override object.
msg.slmp.target Per-request route override when msg.target is not set.
msg.topic connect, disconnect, or reinitialize controls the shared connection instead of writing.
msg.connect When true, opens the shared connection.
msg.disconnect When true, closes the shared connection.
msg.reinitialize When true, closes and reconnects the shared connection.

Runtime write fields are authoritative when present. msg.updates and msg.address are mutually exclusive, and msg.value/msg.dtype are valid only with msg.address. Invalid, empty, conflicting, or isolated runtime fields fail; the node does not execute configured updates as a fallback. Single-write dtype must come from exactly one source. A colon or period in msg.address must form a complete supported dtype/count or word-bit selector; an incomplete or conflicting selector is not completed from msg.dtype.

Every write changes PLC state. Use controlled test addresses, save the original value before a reversible test, and restore only after confirmed acknowledgements. A timeout or transport failure after send can mean the outcome is unknown; do not retry or assume restoration succeeded. Stop the automatic sequence and reconcile the target value manually. The maintained write flows demonstrate manual opt-in, random format-valid test values, and best-effort snapshot restoration.

Output field Description
msg.payload The incoming payload is preserved unless your flow changes it before the write.
msg.slmp.updates Full metadata mode only: normalized update object.
msg.slmp.connection Full metadata mode only: effective connection profile, frame type, target, and remote password status.
msg.slmp.target Full and minimal metadata modes: effective route target.
msg.slmp.targetSource Full and minimal metadata modes: selected route source.
msg.slmp.itemCount Minimal metadata mode only: number of update addresses.
msg.error Error object when Errors is msg.error, or on the second output when Errors is second output.

Address syntax

Form Example Meaning
Unsigned word D100:U Unsigned 16-bit word.
Signed word D100:S Signed 16-bit word.
Unsigned dword D100:D Unsigned 32-bit value.
Signed dword D100:L Signed 32-bit value.
Float D100:F 32-bit float.
String D100:STR,10 UTF-8 string with a 10-byte maximum, packed two bytes per word.
Bit in word D50.3 One bit inside a word device.
Direct bit M1000:BIT One bit device.
Counted bit M1000:BIT,8 One contiguous bit request.
Counted word D100:U,4 Four word entries inside one Random Read request.

Named addresses must include the intended type suffix, for example D100:U or M1000:BIT. The .bit form, such as D50.3, already declares bit-in-word access.

A textual ,count suffix contains ASCII decimal digits only and must represent an exact positive JavaScript safe integer. Signs, embedded whitespace, fractions, exponent notation, non-ASCII digits, suffix junk, zero, and values above Number.MAX_SAFE_INTEGER are rejected instead of being rounded or partially parsed. This syntax rule is separate from the lower command/profile point limit, which is applied afterward. Code calling formatParsedAddress with a hand-built parsed object must likewise provide a primitive positive safe-integer Number when hasCount is true; numeric strings and coercible objects are not accepted.

The complete accessed span must fit the selected SLMP device-number field: 24 bits for Q/L or 32 bits for ordinary iQ-R entries. A link-direct J-qualified device always uses the 24-bit Q/L device specification, including when the client profile is iQ-R. Ordinary DWord and float values consume two consecutive word addresses. Low-level packed word access to a bit-device family, and each Block bit point, consumes 16 consecutive bit-device numbers; a low-level packed DWord consumes 32. Crossing the wire boundary is rejected before communication. This check does not impose the profile catalog's practical device ranges; applications may enforce those separately when required.

Use only BIT, U, S, D, L, F, and STR. The removed compatibility spellings :I, :STRING, and DSTR... are rejected. :BIT and counted bit forms require a canonical bit device. Numeric and string forms require a canonical word device; use .0 through .F for a bit inside a word device. Explicit low-level word-unit access may still address a packed 16-bit word in a bit-device family.

readNamed emits exactly one Random Read request or rejects the complete plan before transport. Counted words, strings, DWord arrays, and packable bit entries are expanded inside that one request and must fit the selected profile limit. It never hides a long-timer Direct Read fallback; use readTyped or an explicit long-timer helper for those routes. writeNamed must also fit one protocol request and rejects mixed command families before transport.

For repeated reads with the same client, addresses, and request options, create one prepareReadNamed(client, addresses, options) plan and call await plan.execute({ signal }) each cycle. Preparation owns and validates the Random Read payload and decode indexes once; each execution still uses normal FIFO admission, a fresh serial and deadline, and current open/close state. The plan is bound to that exact client configuration and must not be passed as the addresses argument to readNamed. Call plan.dispose() when finished; it releases retained planning references and rejects later executions without cancelling an execution that is already active. compileReadPlan is the separate inspectable structural expansion API and is not directly executable. The Node-RED read node automatically retains no more than one exact-match prepared plan.

Options such as a per-request target are forwarded by the high-level helpers. Their compiled device/value lists, block lists, point counts, and bit/word route remain authoritative; same-named caller option fields cannot redirect the operation or replace its values. Bit-in-word read-modify-write is not hidden inside writeNamed. The explicit writeBitInWord helper snapshots and validates its arguments before queue admission, prepares both request routes once, then holds one ordinary-client FIFO turn and one absolute procedure deadline across its word read and word write. It always sends both requests, including when the selected bit already has the requested value. That prevents same-client interleaving only. The two requests are not atomic at the PLC: another connection or PLC program logic can update the word between them, and they can observe different PLC scans. If the write may have been sent, its outcome is unknown after timeout, close, or transport failure. The helper does not retry automatically; verify PLC state first. Direct words use Direct Read/Write. Qualified U module-buffer and J link-direct words use the already-supported Extended Random Read/Write route. The selected route and qualification remain identical for both requests, and an unsupported profile/route combination fails before the read.

Direct write values are not coerced: word/DWord values must be exact in-range native JavaScript Numbers, float values must be finite and remain finite after Float32 conversion, and bits must be native JavaScript Booleans. Numeric strings such as "123", "1.5", and "1e3", boxed Numbers, BigInt, Booleans, null, arrays, and coercible objects are rejected before queue admission. STR still requires a string and BIT still requires a Boolean. Convert configuration text explicitly before calling a numeric write helper. Named writes also reject overlapping destinations. Extended random-read result keys append +Zn, +LZn, or +INDIRECT when a modifier is present.

remoteReset confirms that the request frame was transmitted, closes the current transport generation, and does not confirm PLC execution. Reconnect and verify PLC state before issuing another operation.

Long device families

Use explicit 32-bit forms for long current-value families:

Family Use
LTN Low-level readTyped/writeTyped with LTN0 and D or L
LSTN Low-level readTyped/writeTyped with LSTN0 and D or L
LCN LCN0:D or LCN0:L
LZ LZ0:D or LZ0:L

These are 32-bit families. Do not use direct plain word access for them; the lower-level direct word commands reject that shape. readNamed and the Node-RED read node accept Random-Read-compatible LCN and LZ entries, but reject LTN and LSTN because they would require a hidden Direct Read route.

Node status and diagnosis

Node status is a concise progress indicator. Use the selected error route and its Error object for diagnosis; do not parse status text as an error code.

Node / state Fill Shape Exact text
Connection created grey ring ready
Connection opening yellow ring connecting
Connection open green dot connected
Connection closing yellow ring disconnecting
Connection closed by a disconnect operation red ring disconnected
Connection closing and opening again yellow ring reinitializing
Config node removed or runtime stopped grey ring closed
Read in progress blue dot reading
Write in progress blue dot writing
Successful read or write green dot N item(s)
Failed read, write, or control action red ring The actual error.message

A connect, disconnect, or reinitialize control message first shows a yellow ring with that exact action name. Success then shows a dot with the same text: green for connect and reinitialize, red for disconnect.

The failure status is deliberately dynamic. Timeout, operation-outcome-unknown, and profile-capability failures are error classifications, not promised status strings. Depending on the configured Errors mode, inspect the Error passed to done(error) or the Error in msg.error on output 1 or output 2. Its JavaScript type and structured fields such as code, reason, endCode, errorInfo, and cause provide the available diagnosis.

A profile-capability rejection is local pre-transport validation; it does not prove that a PLC rejected a request. If a state-changing request may have been sent and its outcome is unknown, the node does not retry it automatically. Confirm PLC/application state with an appropriate read or operator procedure before deciding whether to issue another write.

Connection control messages

Send any of these fields to slmp-read or slmp-write:

Msg field Effect
msg.topic = "connect" Opens the shared connection.
msg.topic = "disconnect" Closes the shared connection.
msg.topic = "reinitialize" Closes and opens the shared connection.
msg.connect = true Same as connect.
msg.disconnect = true Same as disconnect.
msg.reinitialize = true Same as reinitialize.

Operational recipes

The examples/flows/slmp-multi-plc-monitor.json flow is a read-only multi-PLC monitor. It polls D100:U, emits long-form rows shaped as timestamp,plc,tag,value, and uses connected, lost, reconnecting, and recovered state transitions with a 1 second to 30 second backoff.

For config-driven polling, keep a JSON config in an Inject or Function node and feed msg.addresses into slmp-read; no extra node type is required.

To persist CSV-equivalent rows, route the long-form row messages through a CSV node with timestamp, plc, tag, and value columns, then into a File node in append mode.

Metadata output

When Metadata is full, msg.slmp includes:

Field Description
msg.slmp.addresses Normalized read addresses. Present on slmp-read.
msg.slmp.updates Normalized write updates. Present on slmp-write.
msg.slmp.connection Connection profile with host, port, transport, PLC profile, frame type, series, target, and remote password status.
msg.slmp.target Effective request target after route overrides.
msg.slmp.targetSource Selected route source and therefore why that target was used.

When Metadata is minimal, msg.slmp includes operation, target, targetSource, itemCount, and metadataMode.

When Metadata is off, the node leaves msg.slmp unchanged. Any pre-existing value is not guaranteed to describe the current operation or result.

Error handling

Success is always sent through output 1. The selected error mode determines the only failure route and therefore the saved terminal count: throw and msg have one terminal, while output2 has two. A flow whose saved count conflicts with the selected mode is rejected for migration review.

Mode Behavior
Throw Calls Node-RED done(error) and lets the runtime route the error.
msg.error Adds the error object to msg.error and sends the message on the normal output.
Second output Sends the failed message with msg.error on output 2.

For PLC response errors, read msg.error.endCode. When the PLC returned the structured error-information block, msg.error.errorInfo includes command and subcommand. Present structured error information must identify the active request's route, command, and subcommand. A mismatch is reported as a malformed SlmpError, invalidates the connection, and is never reported as a definite PLC rejection. If the affected operation may have changed PLC state, the public result is SLMP_OPERATION_OUTCOME_UNKNOWN with reason malformed-response; verify state before considering another write. Additional PLC data following a matching nine-byte error-information prefix remains available on the structured PLC error.

Standard write, monitor-registration, remote-control, clear-error, password, memory, extend-unit, and label APIs require an empty successful acknowledgement. Any data after end code zero is malformed and produces the same outcome-unknown classification and connection invalidation. The maintainer-level rawCommand() API remains the explicit surface for commands whose successful response may contain arbitrary data.

if (msg.error && msg.error.endCode !== undefined) {
    node.warn(`SLMP end_code=0x${msg.error.endCode.toString(16).padStart(4, "0").toUpperCase()}`);
    if (msg.error.errorInfo) {
        node.warn(`command=0x${msg.error.errorInfo.command.toString(16).padStart(4, "0").toUpperCase()}`);
        node.warn(`subcommand=0x${msg.error.errorInfo.subcommand.toString(16).padStart(4, "0").toUpperCase()}`);
    }
}

Profile capability failures use SlmpProfileFeatureError. Select the exact PLC profile and use a supported operation. Normal public APIs do not provide a profile-check bypass or an unsupported-device skip switch.

Older Function nodes may still add msg.slmpSkipUnsupported or msg.slmp.skipUnsupported. These inputs have been removed and produce a runtime migration warning. They never change the selected error route. To continue a flow after a specific capability error, select msg.error or the second output and make that decision explicitly in the application flow.

Request payload limits

One SLMP request can carry at most 65,529 command-payload bytes over TCP. UDP must also fit one complete datagram, so the command-payload maximum is 65,492 bytes for 3E and 65,488 bytes for 4E. Array and random label requests use even-sized payloads and therefore have a largest protocol-representable payload of 65,528 bytes before the lower UDP limit is applied.

An oversized request raises ValueError before connection, send, traffic counters, trace state, or 4E serial allocation. The client never truncates or automatically splits it; applications that need several requests must define ordering, partial-success, and write-atomicity behavior explicitly.

Traffic statistics

The low-level SlmpClient.trafficStats() method returns a frozen client-lifetime snapshot with requestCount, txBytes, and rxBytes. Complete sends and complete received frames are counted; close and reconnect do not reset the snapshot.