Building an OPC UA Server for S7-300 with SIMATIC IOT2040/IOT2050

David Krause15 min read
OPC / OPC UASiemensTutorial / How-to
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

1. Overview: S7-300 OPC UA Gateway Architecture

The SIMATIC S7-300 family does not include a native OPC UA server. Unlike the S7-1500 line, where the OPC UA server capability is integrated from firmware V2.0 and is fully configurable inside TIA Portal (see Enabling the OPC UA server (S7-1500) procedure), the S7-300 platform requires an external gateway that acts as both a client to the PLC and an OPC UA server to the SCADA/MES layer.

This article documents a field-proven architecture in which a SIMATIC IOT2040 or IOT2050 industrial gateway reads process data from a S7-300 CPU 315-2AH14-0AB0 (6ES7315-2AH14-0AB0) over the integrated PROFINET interface or the CP343-1 communications processor, then publishes the data on an OPC UA endpoint using Node-RED or the open-source Open62541 stack. The pattern is the same for any S7-300 / S7-400 / WinAC CPU that cannot host OPC UA natively.

S7-300 Station CPU 315-2AH14-0AB0 FW V3.3 / Work mem. 384 KB CP343-1 (6GK7343-1EX30) PUT/GET + FETCH/WRITE Process DBs DB10 (Inputs) DB11 (Outputs) DB20 (Diagnostics) PN IP: 192.168.0.10/24 S7 / PROFINET TCP port 102 SIMATIC IOT2040 / IOT2050 Yocto Linux + Node-RED opc-ua-server v3.x / Open62541 S7-Comm Client Node node-red-contrib-s7 Function / Mapping Address translation, scaling OPC UA Server Endpoint opc.tcp://iot-ip:4840 OPC UA TCP port 4840 SCADA / MES OPC UA Client Ignition, WinCC iBA, UaExpert Reads / writes via subscriptions

Putting the OPC UA server on a Linux gateway shifts certificate management, security policies, encryption, and node-address mapping away from the PLC's cyclic scan. The PLC remains a deterministic process controller; the IOT device handles all IT-side concerns.

2. Prerequisites

Before commissioning, confirm the following components and software versions are available.

Item Article No. Minimum Version Purpose
S7-300 CPU 315-2 PN/DP 6ES7315-2AH14-0AB0 Firmware V3.3 PLC with PROFINET and PROFIBUS DP interfaces, supports S7 communication as server
CP343-1 PROFINET I/O Controller 6GK7343-1EX30-0XE0 Firmware V3.0 Additional PROFINET interface; supports S7 communication, FETCH/WRITE, PUT/GET
CP343-1 Advanced (optional) 6GK7343-1GX31-0XE0 Firmware V3.0 Adds web server, FTP, integrated security, OPC UA passthrough helpers
SIMATIC IOT2040 (legacy) 6ES7647-0AA00-1YA2 Example image V2.6 (Yocto) Industrial gateway; Intel Quark X1020, 1 GB RAM, 8 GB eMMC
SIMATIC IOT2050 Basic 6ES7647-0BA00-0YA2 Example image V1.3 Industrial gateway; TI Sitara AM6528 ARM Cortex-A53, 1 GB RAM, 4 GB eMMC
SIMATIC IOT2050 Advanced 6ES7647-0BA00-1YA2 Example image V1.3 Industrial gateway; Intel Atom x6414RE, 4 GB RAM, 32 GB SSD
STEP 7 V5.6 + SP2 6ES7810-4CC11-0YA7 V5.6 SP2 Programming/configuring S7-300, enabling PUT/GET on CP343-1
S7-300 S7 example image — — Provided by Siemens for IOT2000 series; includes Node-RED, Open62541 binaries
OPC UA Client (UaExpert, Ignition, etc.) — UaExpert V1.6+ Verification of the published nodes
The SIMATIC IOT2040 has been phased out of active sale by Siemens in favor of the IOT2050 platform. New projects should default to the IOT2050. The IOT2040 remains functionally operational but receives only limited firmware updates.

You will additionally need an Ethernet switch or direct patch cable between the CPU/CP PROFINET port and the IOT device. A static IP plan must be agreed before commissioning; dynamic addressing is unsafe on the plant network.

3. Hardware Comparison: IOT2040 vs IOT2050

The OPC UA server workload is dominated by JSON parsing, certificate handling, and TCP/TLS state. Choosing the wrong platform produces Node-RED crashes after a few hours of continuous operation, especially with high tag counts.

Specification IOT2040 (6ES7647-0AA00-1YA2) IOT2050 Basic (6ES7647-0BA00-0YA2) IOT2050 Advanced (6ES7647-0BA00-1YA2)
CPU Intel Quark X1020 (x86, 400 MHz single core) TI Sitara AM6528 (ARM Cortex-A53, dual core, 1.0 GHz) Intel Atom x6414RE (Elkhart Lake, quad core, 1.9 GHz)
RAM 1 GB DDR3 1 GB DDR4 4 GB DDR4
Mass storage 8 GB eMMC + SD slot 4 GB eMMC + SD slot 32 GB SSD + SD slot
Ethernet ports 2x 100 Mbit/s (RJ45) 2x 1 Gbit/s (RJ45) 2x 1 Gbit/s (RJ45)
USB 2x USB 2.0 2x USB 3.0 2x USB 3.0
Display — 1x DisplayPort 1x DisplayPort
Operating temperature 0 to 50 °C -20 to 60 °C -20 to 60 °C
Mounting DIN rail / wall DIN rail / wall DIN rail / wall
Linux image Yocto / Debian (legacy) Yocto (example image) Yocto / Debian (community)
Status Discontinued Active Active

For OPC UA workloads above ~500 tags with subscriptions > 500 ms update rate, the IOT2040's single-core 400 MHz CPU becomes the bottleneck. The Node-RED OPC UA server nodes (node-red-contrib-opcua) have been observed to crash after a few hours on the IOT2040 due to memory pressure in the V8 heap. The IOT2050 Advanced with 4 GB RAM is the recommended target for production deployments.

The OPC UA server nodes inside Node-RED are memory-sensitive. Always enable a watchdog (e.g., systemd or PM2) that restarts Node-RED if RSS exceeds 80 % of available RAM.

4. Communication Protocol Selection: S7 vs PROFINET vs TCP

Three logical options exist for moving data from the S7-300 to the IOT gateway. Each has different commissioning effort and traffic characteristics.

Protocol Mechanism CPU 315-2AH14 Support CP343-1 Required? Polling interval Recommended use
S7 Communication (PUT/GET) Bidirectional data exchange on ISO-on-TCP (port 102) Yes, integrated PN port supports S7 conn. (PUT/GET) Optional, useful for segregation 50–500 ms Preferred for tag mapping
PROFINET IO Cyclic I/O data exchange; no acyclic data Yes, as PROFINET IO Controller Yes, if IOT is a PROFINET device 1–32 ms Time-critical I/O (<10 ms)
TCP / ISO-on-TCP (raw) Custom protocol over TCON/TSEND/TRCV in PLC Yes, requires FB programming No Application defined Only when S7 not feasible
FETCH/WRITE (legacy) Pre-S7 passive read/write Yes, but deprecated Yes 100–1000 ms Migration of legacy SCADA

Recommendation: Use S7 Communication (PUT/GET) for the bulk of data because it requires no PLC program changes when the data already lives in a process DB. The IOT gateway can poll arbitrary DB areas at any update rate without disturbing the OB1 scan. PROFINET IO is only worthwhile when the data must arrive within the PLC's PROFINET update time (1–4 ms).

Verify that the CP343-1 has PUT/GET enabled, which is the default on CP343-1 (6GK7343-1EX30-0XE0) but must be confirmed in the hardware configuration.

5. S7-300 Network Configuration with CP343-1

Configure the S7-300 station in STEP 7 V5.6 (or TIA Portal V17+ with S7-300 HSP) as follows. The exact menu paths are for STEP 7 Classic; TIA Portal equivalents are noted in parentheses.

  1. Open the hardware configuration (HW Config) and place the CP343-1 in slot 4 next to the CPU.
  2. Double-click the CP343-1 and assign an IP address, e.g. 192.168.0.10, subnet mask 255.255.255.0. Do not use DHCP.
  3. Open Properties → Options and ensure Allow PUT/GET access from remote partner is checked. Without this flag, the CP rejects all S7 communication write/read requests, including those from the IOT gateway.
  4. If you require protection, define a connection resource (S7 connection) under NetPro with a local ID and the IOT IP as the partner. Leave the connection type as S7 Connection.
  5. Create the process DBs in the S7 program. The IOT will poll these directly:
    DB Symbol Offset / Length Type Description
    DB10 iProcImage DBW0–DBW30 (16 words) INT Process inputs (analog values, scaled)
    DB11 qProcImage DBW0–DBW30 (16 words) INT Process outputs (setpoints, commands)
    DB20 diagData DBW0–DBW100 (51 words) WORD/INT/DWORD Diagnostics block (last alarm, op hours, etc.)
  6. Compile and download the hardware configuration to the rack. The CP should reach RUN with no SF/BF errors.
If the S7-300 is inside a safety-related plant segment, coordinate with the safety officer before enabling PUT/GET, as the flag relaxes the default access protection on the CP. On newer CPU firmware (V3.3+), per-connection access lists can constrain remote partners.

Verify connectivity from any PC with a SIMATIC NET installation before touching the IOT device:

ping 192.168.0.10

If the ping fails, check the CP's MAC in the diagnostic buffer (Module Information → Diagnostic Buffer) for PROFINET link-up events.

6. IOT2000 Software Image and Initial Setup

The SIMATIC IOT2000 ships with a Yocto Linux example image that includes Node-RED, an OPC UA client/server stack, and the SD card handling utilities. Siemens publishes the image and SDK at the official IOT2000 support portal.

  1. Download the SIMATIC IOT2050 product manual and locate the Example Image release notes for your hardware variant.
  2. Flash the example image to a USB stick or SD card using the Balena Etcher or dd tool: sudo dd if=iot2050-image-v1.3.1.wic of=/dev/sdX bs=4M status=progress conv=fsync
  3. Insert the SD card into the IOT and power it up. Connect a serial console (115200 8N1) on the debug UART or attach a DisplayPort monitor and USB keyboard.
  4. Default credentials are root / root. Change them immediately: passwd root
  5. Configure a static IP on the LAN-facing Ethernet port (the one connected to the S7-300). Edit /etc/network/interfaces:
    auto eth0
    iface eth0 inet static
      address 192.168.0.20
      netmask 255.255.255.0
      gateway 192.168.0.1
      dns-nameservers 192.168.0.1
  6. Restart networking: systemctl restart networking
  7. Test reachability to the CP: ping 192.168.0.10

Update the firmware and packages while still online:

opkg update && opkg upgrade

The example image's Node-RED should be listening on http://192.168.0.20:1880. The OPC UA server (when enabled) binds to opc.tcp://0.0.0.0:4840.

Always physically separate the IOT2000's two Ethernet ports: one for the PLC network (eth0) and one for the plant/corporate network (eth1). Bridging the two defeats the gateway's purpose and exposes the PLC to the IT network.

7. Installing Node-RED and OPC UA Server Nodes

Node-RED is bundled with the IOT2000 example image but the OPC UA nodes must be installed manually. Two packages are required:

  • node-red-contrib-s7 — S7 communication client (ISO-on-TCP, port 102)
  • node-red-contrib-opcua — OPC UA server and client (bundled with open62541 stack)
  1. Open the Node-RED UI at http://192.168.0.20:1880.
  2. Open the burger menu → Manage Palette → Install tab.
  3. Install node-red-contrib-s7 then node-red-contrib-opcua.
  4. Restart Node-RED to load the new nodes: systemctl restart node-red
  5. Verify the nodes appear under the function palette category.

If you prefer the command-line route (faster for reproducible deployments):

npm install -g node-red-contrib-s7 node-red-contrib-opcua
The Node-RED OPC UA nodes bundle the open62541 C library through node-opcua. The native build increases the Node-RED RSS by 80–120 MB. On an IOT2040 with only 1 GB RAM, leave at least 300 MB free for the V8 heap or risk OOM kills under load.

8. S7 Communication Driver Configuration

Place an s7 in node on the canvas and double-click it. The configuration parameters map directly to S7 Communication primitives.

Field Value (example) Notes
Connection type ISO-on-TCP (S7 Comm) TCP port 102, TPKT/COTP
Address (PLC) 192.168.0.10 CP343-1 PROFINET IP
Port 102 S7 Communication default
Rack 0 S7-300 always rack 0
Slot 2 CPU slot for 315-2AH14
Mode All (read DB + Merker + I/O) Restrictive modes reduce traffic
Cycle time 500 ms Tunable from 50 ms to 60 s
Timeout 3000 ms Reconnect threshold
Variable name iProcImage[0..15] Reads DB10.DBW0..DBW30

The Variable name field uses S7-style absolute addressing. Examples:

DB10,INT0,16   // reads 16 INT values from DB10 starting at offset 0
DB11,INT0,16
DB20,WORD0,10
DB20,DINT50,4   // 4 double words (32 bits each)
MW0,WORD,1      // Merker word
IW0,INT,4       // Input word area

Wiring the output of s7 in into a function node allows you to scale, debounce, or tag-strip the payload before publication.

9. OPC UA Server Configuration in Node-RED

Place an opcua-server node on the canvas. Its configuration panel exposes the OPC UA endpoint, security, and node structure.

  1. Set Endpoint URL to opc.tcp://192.168.0.20:4840 (use the IOT's plant-facing IP, not 0.0.0.0, so clients can resolve it).
  2. Set Server certificate path. The node will auto-generate a self-signed cert at first start; replace it with a CA-signed cert before production.
  3. Choose a security policy. None is fine for testing; production should use Basic256Sha256 with SignAndEncrypt.
  4. Under Actions, add an Add Node action that creates an object Objects/S7300_Station and appends variables for each tag published by the S7 node.
  5. Connect the output of the function node (which receives S7 reads) to the input of the opcua-server node. Use msg.topic for the OPC UA node ID and msg.payload for the value:
// function node body
msg.topic = "ns=1;s=S7300_Station.Pressure";
msg.payload = parseFloat(msg.payload);
return msg;

The full address space for the example above would resemble:

Objects
  +-- S7300_Station
       +-- Pressure (Float, Read-only)
       +-- Temperature (Float, Read-only)
       +-- Speed (Int32, Read-only)
       +-- OpHours (UInt32, Read-only)
       +-- Command (Int16, Read-Write)  // writes back to DB11

For write-back (SCADA command to PLC), wire an opcua-client or opcua-listener node to an s7 out node. The s7 out node performs a PUT/GET write to the configured DBW.

10. Verification and Commissioning Steps

  1. From a Windows PC, install the UaExpert OPC UA Client (or any other OPC UA client). Use this only as a verification tool.
  2. Open UaExpert and select Add Server. Enter the endpoint URL opc.tcp://192.168.0.20:4840.
  3. Accept the self-signed certificate (move it from Rejected to Trusted) and connect.
  4. Expand the address space to Objects → S7300_Station. The variables listed in section 9 must appear.
  5. Drag a tag to the Data Access View and confirm the value updates at the configured poll rate.
  6. Force a value change in the S7-300 (e.g., move the value in DB10.DBW0 via the watch table in STEP 7) and observe the OPC UA value updates within one cycle (default 500 ms).
  7. For write-back, double-click a Read-Write tag, change its value, and confirm the corresponding DBW updates in the PLC.
  8. Pull a Wireshark capture on the PLC network segment to confirm traffic: you should see TPKT/COTP packets on port 102 (S7 communication) and opc.tcp packets on port 4840 (OPC UA).

Add the following acceptance criteria to the Site Acceptance Test (SAT):

Test Method Pass criterion
Endpoint reachable UaExpert connect Session opened within 5 s
Tag visibility Address space walk All expected nodes present
Update rate Force value change in PLC OPC UA value reflects change within 2 × poll interval
Round-trip write OPC UA write to Read-Write tag PLC DBW updates within 2 × poll interval
24-hour stability Soak test with 500 tags No Node-RED restart; RAM < 80 %
PLC link loss Unplug PROFINET cable for 30 s Node-RED reconnects; OPC UA quality = Bad until restore

11. Troubleshooting Common Issues

Symptom Probable root cause Diagnostic Remediation
UaExpert cannot reach endpoint IOT firewall blocks port 4840 iptables -L -n on IOT Open TCP/4840 inbound on eth1
Connection refused on port 102 CP343-1 PUT/GET disabled HW Config → CP343-1 → Options Enable "Allow PUT/GET from remote partner"
Tags read as 0 / stale DB optimized access enabled (TIA Portal) Open DB properties in TIA Disable optimized access, or use absolute addresses only
Node-RED crashes after a few hours IOT2040 RAM exhaustion from OPC UA nodes free -m via SSH Upgrade to IOT2050 Advanced or reduce tag count
Subscription data updates erratically Multiple clients at different rates UaExpert Monitored Items tab Set fixed publishing interval; enable queueSize
SF LED on CPU after PLC restart CP cannot reach IOT on subnet CP diagnostic buffer Confirm static IP and mask on IOT eth0
OPC UA variable shows Bad_CommunicationError S7 connection lost / wrong slot Node-RED debug tab Verify Rack=0, Slot=2 for CPU 315-2AH14
Certificate warning on every restart Self-signed cert regenerated Open /root/.node-red/opcua/ Move cert to persistent storage; set server restart policy
Tags lag the PLC by > 5 s Cycle time too long or scan interruption Node-RED status panel Reduce cycle time; check OB1 execution time
The PLC scan (OB1) is never interrupted by the IOT gateway, regardless of how often the gateway polls. However, if you use cyclic PROFINET IO instead of S7 Communication, the IOT device becomes a PROFINET device and its update time directly affects the OB1 scan budget.

12. Alternative Stack: Open62541

For deployments where Node-RED is too heavy or too slow, Open62541 is a high-performance open-source OPC UA stack written in C with Python and Java bindings. The library is licensed under MPL-2.0 and is suitable for embedded use on both IOT2040 (x86) and IOT2050 Basic (ARM).

A minimal server in C exposes two variables sourced from an ISO-on-TCP read of DB10:

#include "open62541/server.h"
#include <unistd.h>

static UA_StatusCode readPressure(UA_Server *s,
        const UA_NodeId *n, UA_DataValue *dv) {
    UA_Float v = 12.34f;        // replace with S7 read
    UA_Variant_setScalar(&dv->value, &v, &UA_TYPES[UA_TYPES_FLOAT]);
    return UA_STATUSCODE_GOOD;
}

int main(void) {
    UA_Server *s = UA_Server_new();
    UA_ServerConfig_setMinimal(UA_Server_getConfig(s), 4840, NULL);
    UA_VariableAttributes attr = UA_VariableAttributes_default;
    attr.dataType = UA_TYPES[UA_TYPES_FLOAT].typeId;
    attr.accessLevel = UA_ACCESSLEVELMASK_READ;
    UA_Float init = 0.0f;
    UA_Variant_setScalar(&attr.value, &init, &UA_TYPES[UA_TYPES_FLOAT]);
    UA_NodeId id = UA_NODEID_STRING(1, "pressure");
    UA_Server_addVariableNode(s, id,
        UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
        UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
        UA_QUALIFIEDNAME(1, "Pressure"),
        UA_NODEID_NULL, attr, NULL);
    UA_ValueCallback cb;
    cb.read = readPressure;
    cb.write = NULL;
    UA_Server_setVariableNode_valueCallback(s, id, cb);
    UA_Server_run(s, &running);
    UA_Server_delete(s);
    return 0;
}

Compile and link:

gcc -o ua-gw ua-gw.c -lopen62541 -lpthread

The library ships with CMake helpers; the official Open62541 documentation covers TLS, certificates, subscriptions, and historical access. Open62541 typically uses 60–90 MB less RAM than the Node-RED OPC UA stack and is the preferred path when tag count exceeds 1000 or update rates fall below 200 ms.

13. Security Hardening Checklist

An OPC UA server crossing the OT/IT boundary is a security-sensitive component. Before handover, validate the following:

  • Port filtering. Block all inbound TCP except 4840 on eth1. Block all inbound except 102 (S7) on eth0. Confirm with iptables -S.
  • TLS. Switch the OPC UA server to Basic256Sha256 with a CA-signed certificate. Reject None and Basic128Rsa15.
  • Authentication. Configure anonymous = false and require username/password or X.509 client certificates for each SCADA client.
  • PLC access control. Use the CP343-1 connection resource list to restrict which partners can open S7 connections. Combine with PLC password protection in STEP 7.
  • Firmware updates. Track the IOT2050 firmware release notes and apply security patches within the agreed patching SLA.
  • Logging. Forward Node-RED and Open62541 logs to a central syslog/SIEM via rsyslog or syslog-ng.
  • Backup. Persist the Node-RED flow file and OPC UA certificates to a remote location so an IOT swap does not require re-commissioning.

Does the S7-300 support a native OPC UA server like the S7-1500?

No. The S7-300 family (including CPU 315-2AH14-0AB0) has no integrated OPC UA server. The S7-1500 OPC UA server, enabled via TIA Portal as described in the Enabling the OPC UA server (S7-1500) procedure, is not available on S7-300. An external gateway is mandatory.

Which SIMATIC IOT platform should I use for an OPC UA server today?

Use the SIMATIC IOT2050 (Basic 6ES7647-0BA00-0YA2 or Advanced 6ES7647-0BA00-1YA2). The IOT2040 is discontinued and the Node-RED OPC UA server nodes crash after a few hours on it due to the 1 GB RAM limit and the 400 MHz Intel Quark CPU.

Is the CP343-1 required, or can I use the CPU's PROFINET port?

The CPU 315-2AH14-0AB0 has an integrated PROFINET port that supports S7 Communication (PUT/GET) directly, so the CP343-1 is optional. Use the CP343-1 when you need a physically separate network segment or additional diagnostics such as the CP's web server.

What TCP port does the OPC UA server listen on?

The default OPC UA server endpoint is opc.tcp://<iot-ip>:4840. Confirm reachability with nc -zv 192.168.0.20 4840 from any client PC before commissioning.

How do I verify that PUT/GET is enabled on the CP343-1?

In STEP 7 V5.6 HW Config, double-click the CP343-1, open the Options tab, and check Allow PUT/GET access from remote partner. Compile, download the hardware configuration, and perform a power-cycle of the CP if the change does not take effect immediately.

Back to blog