node-red-contrib-s7-plus
v0.2.0
Published
Node-RED nodes for Siemens S7-1200/1500 via S7CommPlus (symbolic access)
Maintainers
Readme
node-red-contrib-s7-plus
Node-RED nodes for symbolic read/write access to Siemens S7-1200/1500 PLCs over the native S7CommPlus protocol.
Why this package
Most S7 drivers make you translate every tag into a byte/offset address (DB1.DBX0.0) and pick the right data type by hand. This package talks the PLC's own symbolic protocol instead — you browse the live symbol tree and click the tag you want. The driver resolves the address and data type for you, at runtime.
- Full symbolic access — browse the live PLC tree (DBs, structs, arrays) and add tags with one click via Pick from PLC. No address math.
- No extra dependencies — pure JavaScript with zero runtime npm dependencies; only Node-RED is required as a peer.
- Any CPU architecture — no native addons or binary modules; runs wherever Node.js runs (x64, ARM64, …).
- Optimized and non-optimized blocks — reads and writes data blocks with optimized or standard access alike; unlike S7comm-based drivers, there is no need to disable optimized access for communication.
- Automatic data types — types are resolved symbolically at runtime; you never set them manually. If the PLC program changes, the mismatch is detected and tags are re-resolved automatically.
- Multi-symbol read/write — read or write many tags in a single request, each with its own per-symbol status (a single bad tag doesn't fail the whole batch).
- Resilient connection — shared endpoint with reconnect/watchdog handling and overload protection (
skipped (busy)).
Quick start
Install from the Node-RED palette manager (Manage palette → Install → node-red-contrib-s7-plus), or from the command line in your Node-RED user directory:
npm install node-red-contrib-s7-plusThen build a minimal read flow:
[inject] → [S7+ Read] → [debug]- Add an S7+ Read node and create the S7+ Endpoint config in its settings (PLC IP address).
- In the S7+ Read node, click Pick from PLC and select your tags from the tree.
- Wire an inject in front and deploy — every incoming message triggers one read.
The result lands in msg.payload (object format):
{
"Motor.speed": { "value": 1450, "status": "ok", "error": "" },
"Tank.level": { "value": 73.2, "status": "ok", "error": "" }
}Writing works the same way: pick the tags, then send the value(s) in msg.payload (a single value for one tag, or an object keyed by tag name for several).
Nodes
| Node | Description |
| ----------------- | ----------------------------------------------------------------------------------------------------------------- |
| S7+ Endpoint | Shared connection (IP, port 102, timeout, reconnect/watchdog). |
| S7+ Read | Read symbol(s) on input; results in msg.payload. Override with msg.symbols, add extras with msg.addSymbols. |
| S7+ Write | Write values via msg.payload; override symbols with msg.symbols. Result replaces msg.payload. |
| S7+ Subscribe | Native subscription: the PLC pushes value changes (no polling). Emits changed symbols in msg.payload per cycle. |
| S7+ Explore | Full symbol catalog: flat names in msg.payload, optional msg.infos, browse summary in msg.meta. |
| S7+ Info | Session and PLC diagnostics in msg.payload (firmware, PAOM, limits, protection level, connection status). |
Data type mapping
S7 datatype → JavaScript type
| S7 Datatype | JavaScript Type | Note |
| ---------------------------------------- | --------------- | -------------------------------------------------------------------- |
| Bool | boolean | |
| Byte, Word, DWord | number | |
| LWord | BigInt | 64-bit, exceeds JS number |
| Char, WChar | string | single character |
| String, WString | string | |
| SInt, Int, DInt, USInt, UInt, UDInt | number | |
| LInt, ULInt | BigInt | |
| Real, LReal | number | |
| Time, S5Time | number | milliseconds |
| LTime | BigInt | nanoseconds |
| TOD (Time_Of_Day) | number | milliseconds since midnight |
| LTOD | BigInt | nanoseconds since midnight |
| Date | Date | |
| LDT, DTL | Date | ms resolution; sub-ms nanoseconds are not represented in a JS Date |
| Hardware datatypes (HW_IO, HW_DEVICE, …) | number | |
Requirements
- Node.js >= 20
- Node-RED >= 3.0
- S7-1200/1500 with secure communication (TLS) enabled; symbolic access for optimized and non-optimized blocks
- Project engineered with TIA Portal >= V17
Examples
Example flows live in [examples/](examples/). They target the test data blocks in [plc/s7-1500/](plc/s7-1500/) (S7-1500, optimized access).
PLC setup: import the DB_*.db sources and FB_TestSignalGenerator.scl from plc/s7-1500/ into your TIA Portal project. Call FB_TestSignalGenerator in the main cycle OB (e.g. OB1) so DB_TestSignals is filled with animated test values, then compile and download to the PLC.
Node-RED setup: Import one or more JSON files from examples/, Deploy, then open the shared S7+ Endpoint config node (PLC) and set the PLC IP address. All example flows reuse the same endpoint id (example_plc_ep), so importing multiple flows creates only one config node.
| File | Purpose |
| ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [explore-symbols-flow.json](examples/explore-symbols-flow.json) | Symbol catalog browse — full PLC tree, scoped DB/area browse (static + msg.exploreScope), msg.infos formats, output limit demo, and Explore → Read pipeline for DB_TestSignals. |
| [read-multiple-values-flow.json](examples/read-multiple-values-flow.json) | Read multiple values in one request — static symbol list in the read node, plus a second path with the same symbols via runtime msg.symbols. |
| [read-write-single-values-flow.json](examples/read-write-single-values-flow.json) | Manual write tests — one inject per scalar constant writes to the matching *_write tag; each datatype group includes a read-back row. Covers Binary through Timers; hardware and system datatypes are excluded. |
| [verify-read-write-values-flow.json](examples/verify-read-write-values-flow.json) | Automated verification — one inject runs write → read-back → compare for every scalar constant across all datatypes. Emits one result per datatype and a final summary. |
| [subscribe-values-flow.json](examples/subscribe-values-flow.json) | Native subscription — static DB_TestSignals symbols on deploy (object format) with per-symbol extraction; dynamic msg.symbols via inject (array format). |
Status
- Open-source software (LGPL-3.0-or-later), provided as-is without warranty
- Development stage — not approved for production use
- You are responsible for how and where you use it
- Not affiliated with or supported by Siemens
License
Copyright (C) 2026 Robert Mederer - DataLogXE. Licensed under LGPL-3.0-or-later. See LICENSE.
This project builds on the following work:
- S7CommPlus protocol portions — derived from S7CommPlusDriver (Thomas Wiens, LGPL-3.0-or-later).
- ISO-on-TCP/COTP transport patterns — informed by Snap7 (Davide Nardella, LGPL-3.0) and the C# reference driver above.
- S7CommPlus SymbolCRC (CRC32 polynomial and algorithm) — informed by HarpoS7 (bonk, MIT); see LICENSE for the full MIT notice.
