Configuring S7-1500 to Azure IoT Hub via IOT2040 Node-RED

David Krause9 min read
Industrial NetworkingSiemensTutorial / 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

Siemens SIMATIC S7-1500 controllers dominate the mid- to high-end PLC segment, and pushing real-time process data from the controller to Microsoft Azure IoT Hub unlocks remote dashboards, predictive maintenance, and cloud-side analytics. The Siemens IOT2040 (6ES7647-0AA00-0YA2) — succeeded by the IOT2050 (6ES7647-0BA00-0YA2) — is an industrial edge gateway that runs a Yocto-based Linux image with Node-RED pre-installed. It bridges the ISO-on-TCP / PROFINET world of the S7-1500 with the MQTT- and AMQP-based telemetry of Azure IoT Hub.

This guide consolidates a field-proven path for moving tag data from an S7-1500 data block to Azure IoT Hub through Node-RED on the IOT2040. The first attempts failed for three reasons: (a) the wrong Node-RED Azure package, (b) a payload that was not string-encoded for the cloud SDK, and (c) AMQP transport errors caused by outbound port 5671 being blocked on industrial networks. The corrected topology uses node-red-contrib-s7 for S7 polling, node-red-contrib-azureiothubnode for MQTT-style device-to-cloud (D2C) telemetry, and a function node that stringifies the JSON body Azure expects.

2. Prerequisites

Component Version / Specification
S7-1500 CPU e.g., CPU 1515-2 PN (6ES7515-2AM02-0AB0), firmware ≥ V2.0
TIA Portal V16 or later for S7-1500 project engineering and download
IOT2040 6ES7647-0AA00-0YA2 with Example Image V2.6.x (Yocto Linux)
Node-RED Pre-installed on the IOT2040 image; upgrade Node.js ≥ V10
Azure subscription Active subscription with permission to create an IoT Hub
Network TCP/IP reachability from IOT2040 to S7-1500 (port 102) and outbound to Azure (port 8883 for MQTT or 5671 for AMQP)
Azure CLI workstation Windows or Linux PC with Azure CLI ≥ 2.40 for device identity management
The IOT2040 has been succeeded by the IOT2050 (6ES7647-0BA00-0YA2). Most Node-RED flows transfer unchanged, but verify the underlying Yocto image supports Node.js ≥ V10 and the updated CA certificate bundle before reusing older IOT2040 packages.

3. System Architecture

The data path is:

S7-1500 CPU → ISO-on-TCP (TCP 102) → IOT2040 Node-RED → MQTT TLS (TCP 8883) → Azure IoT Hub endpoint → Stream Analytics / Time Series Insights / Blob Storage

Node-RED flows inside the IOT2040:

  1. An Inject node (or a schedule node) drives periodic polling.
  2. The s7 node reads DB100 (or any configured DB) and emits msg.payload.
  3. A function node converts native S7 values into a JSON string.
  4. The azureiothub node publishes the JSON to the device-to-cloud stream.

4. S7-1500 PLC Configuration in TIA Portal

4.1 Enable PUT/GET access on the CPU

Open the S7-1500 device properties in TIA Portal → Protection & Security → Connection mechanisms and tick Permit access with PUT/GET communication from remote partner. The official SIMATIC S7-1500 System Manual documents that PUT/GET access via the integrated PROFINET interface is required for S7-200/300/400/1200/1500 communication drivers.

4.2 Define a global data block, e.g., DB100

  • Bool tags for status, Real tags for analog values, Int tags for counters.
  • For early versions of node-red-contrib-s7, disable Optimized block access on the DB so the byte-offset addressing is reliable. Newer versions support symbolic access; keep the DB optimized if you switch the S7 node to symbol mode.

4.3 Compile, download, and verify

After download, confirm the IP address and the rack/slot (default 0/1 for an S7-1500). Use the Online & Diagnostics view to verify the PLC is in RUN.

5. IOT2040 Image and Node-RED Preparation

The IOT2040 ships with the SIMATIC IOT2000 SD card example image. SSH into the device and prepare the environment:

opkg update
opkg install nodejs nodejs-npm

For a clean reflash, download the Siemens Example Image from the Siemens support portal and reflash the SD card. Launch Node-RED:

node-red-pi --max-old-space-size=256

Open the editor at http://<iot2040-ip>:1880. The official Siemens IOT2000 setup page documents the exact procedure for first commissioning and Node-RED startup parameters.

6. Installing the Required Node-RED Nodes

From the Node-RED palette manager or from the command line on the IOT2040:

cd ~/.node-red
npm install node-red-contrib-s7
npm install node-red-contrib-azureiothubnode
Do not install node-red-contrib-azure-iot-hub alongside node-red-contrib-azureiothubnode. The two packages register conflicting transports in the Node.js SDK and produce intermittent authentication failures. The original failing deployment on the IOT2040 had both installed, which contributed to the AMQP errors discussed in section 12.

node-red-contrib-s7 is the standard Node-RED gateway for S7-300/400/1200/1500 communication. node-red-contrib-azureiothubnode wraps the Microsoft azure-iot-device MQTT client and accepts a string body for D2C messages.

7. Configuring the S7 Node

Double-click the S7 node and enter:

Field Value
IP IP of the S7-1500 CPU, e.g., 192.168.0.10
Port 102 (default ISO-on-TCP)
Rack 0
Slot 1
Mode Single variable (debug) or All variables (production)
Variable (single mode) e.g., DB100,REAL0 for a Real at offset 0; DB100,X0.0 for a Bool at byte 0, bit 0

The S7 node injects msg.payload with the typed value (e.g., 23.7). Wire the S7 output to a debug node and verify the values appear in the Node-RED debug tab before continuing.

8. Provisioning the Device in Azure IoT Hub

In the Azure portal, create an IoT Hub and register a device identity:

  1. Azure Portal → IoT Hub → Devices → Add Device.
  2. Device ID: e.g., iot2040-plant1.
  3. Authentication type: Symmetric key (default).
  4. Copy the Primary Connection String.

The full connection string is required for node-red-contrib-azureiothubnode. Format:

HostName=<your-hub>.azure-devices.net;DeviceId=<device-id>;SharedAccessKey=<base64-key>
The iothub-explorer Node.js tool used in older Siemens guides is deprecated by Microsoft. Replace it with the Azure CLI on a workstation: az iot hub device-identity create --hub-name <hub> --device-id <device-id> and az iot hub device-identity show-connection-string --hub-name <hub> --device-id <device-id>. The Azure CLI itself is not runnable on the IOT2040 (no x86_64 Python 3 toolchain in the Yocto image) — manage the device identity from a Windows or Linux workstation.

9. Selecting the Right Azure Node

Node Transport Notes
node-red-contrib-azure-iot-hub AMQP Default transport; clashes with azureiothubnode; difficult to debug on IOT2040
node-red-contrib-azureiothubnode MQTT (TLS 8883) Stable, accepts a string payload, recommended for IOT2040
node-red-contrib-azure-iot-hub-cds (community forks) AMQP / MQTT Variable maintenance; review before production use

Use node-red-contrib-azureiothubnode and feed it a stringified JSON object. The Siemens application example "Data transfer to Microsoft Azure with an S7-1x00" also uses MQTT over port 8883 with the LMQTT library on the PLC side, which is consistent with the MQTT choice on the gateway side.

10. Payload Construction Function Node

Place a function node between the S7 node and the Azure node. For a single variable read:

// msg.payload arrives as the typed S7 value (e.g., 23.7)
var body = {
    deviceId: "iot2040-plant1",
    timestamp: new Date().toISOString(),
    tag: {
        value: msg.payload
    }
};

msg.payload = JSON.stringify(body);
return msg;

For a multi-tag S7 read using mode All variables — the S7 node returns an object keyed by the variable name you entered — the function simplifies to:

var body = {
    deviceId: "iot2040-plant1",
    timestamp: new Date().toISOString(),
    tags: msg.payload
};

msg.payload = JSON.stringify(body);
return msg;

Wire the function node's output to the Azure IoT Hub node. The Node.js azure-iot-device SDK requires a string body for D2C telemetry; sending a raw object or number causes silent rejection in some SDK versions.

11. Configuring the Azure Node

In node-red-contrib-azureiothubnode:

  • Connection String: paste the Azure primary connection string captured in section 8.
  • Method: send.
  • Topic: optional; for telemetry, leave at default device-to-cloud.

Once deployed, the device-to-cloud messages appear in Azure IoT Hub. Verify with the Azure CLI from the workstation:

az iot hub monitor-events --hub-name <your-hub> --device-id iot2040-plant1

12. AMQP Troubleshooting

The original traceback reported:

Error: Error while trying to send message:Error: AMQP Transport: Could not connect

Common causes and fixes:

  1. Outbound firewall blocking AMQP port 5671 — open TCP 5671 or switch to MQTT (port 8883). Industrial sites often only allow 443/8883 outbound.
  2. Conflicting Azure node packages — remove the AMQP-based node and restart Node-RED:
    npm uninstall node-red-contrib-azure-iot-hub
    node-red-stop && node-red-start
  3. Wrong connection string or expired SAS key — re-issue from the Azure portal.
  4. Old azure-iot-device version — pull a current version:
    npm install azure-iot-device@latest
  5. Yocto Linux missing CA certificate bundle — install the Mozilla CA bundle and restart Node-RED; azure-devices.net cannot complete the TLS handshake without it.

The Microsoft community thread "Siemens CPU S7-1200/-1500 to Azure IoT-Hub" confirms that direct S7-1500 → Azure IoT Hub MQTT works on recent CPU firmware (≥ V2.6) but is unreliable for production use, which is why the IOT2040 gateway approach is the recommended path.

13. Verification Checklist

  1. S7 node debug tab shows real values when the PLC is online.
  2. Function node debug tab shows a JSON string in msg.payload.
  3. Azure node debug tab shows Message sent.
  4. az iot hub monitor-events displays the device-to-cloud payload in the Azure CLI shell.
  5. Azure IoT Hub metrics show successful telemetryMessages.used count.

14. Common Errors and Resolution Matrix

Symptom Likely Cause Fix
Error: AMQP Transport: Could not connect Blocked port 5671 or conflicting node Switch to MQTT (8883); remove old Azure node
iothub-explorer: command not found Tool deprecated Use az iot hub commands on a workstation
Login incorrect on Azure CLI Wrong key / typo Re-copy Primary Connection String
msg.payload is not a string Sending object to Azure node JSON.stringify in function node
S7: connection timed out Wrong IP / CPU protection enabled Verify CPU Permit access with PUT/GET
iothub-connection-string invalid Hub name with capitals or extra spaces Trim and use lowercase hub name
Empty payload in Azure monitor-events Function node did not return msg Add return msg; at end of function
Cert error on TLS handshake Outdated CA bundle Update ca-certificates package

15. Extended Topics

15.1 Direct S7-1500 to Azure MQTT (LMQTT library)

Siemens publishes a library "LMQTT" that allows the S7-1500 CPU to publish MQTT messages directly, eliminating the IOT2040. This is suitable for cells without an edge gateway. The library, sample blocks, and certificate handling are documented in the Siemens application example. The trade-off is that direct CPU-to-cloud has less buffering, no local store-and-forward, and exposes the PLC to cloud-side outages.

15.2 Storage and Analytics

Once data lands in Azure IoT Hub, route it to Azure Blob Storage, Time Series Insights, or Stream Analytics. The Azure Import/Export service is a related but distinct bulk-data mechanism for offline seeding of storage accounts with physical drives and is not used for live telemetry.

15.3 Security Hardening

  • Use X.509 certificates rather than symmetric keys when scaling to more than one device.
  • Enable Azure IoT Hub IP filtering and DPS (Device Provisioning Service) for production.
  • Disable PUT/GET on the S7-1500 once data is flowing and rely on the OPC UA server instead, if a future migration is planned.
  • Place the IOT2040 on a dedicated OT VLAN and restrict outbound traffic to *.azure-devices.net:8883.

16. References

FAQ

Why does node-red-contrib-azure-iot-hub fail on IOT2040 with "AMQP Transport: Could not connect"?

The IOT2040 Yocto image ships without an AMQP-friendly TLS stack and most field networks block TCP 5671. Switch to node-red-contrib-azureiothubnode (MQTT over 8883) and uninstall the AMQP-based node to avoid the SDK conflict.

Can I install the Azure CLI directly on the IOT2040?

No. The IOT2040 Yocto image lacks the x86_64 Python 3 toolchain that the Azure CLI requires. Register devices and pull connection strings from a Windows or Linux workstation using az iot hub device-identity commands.

Which S7-1500 firmware supports direct MQTT to Azure?

CPU firmware V2.6 or later with the LMQTT library is required for direct CPU-to-Azure MQTT. For IOT2040 gateway topologies, any firmware that allows PUT/GET access (typically V2.0+) is sufficient.

Should I send a number or a string to the Azure node?

Send a JSON-encoded string produced by a function node. node-red-contrib-azureiothubnode accepts a string body and forwards it to the device-to-cloud endpoint; sending a raw number causes silent rejection in some Node.js SDK versions.

Does the S7 node require the data block to be non-optimized?

For older versions of node-red-contrib-s7, non-optimized blocks with absolute byte addresses are the most reliable path. If you keep the DB optimized, use symbolic names and the S7 node's S7_SYMBOL mode, or upgrade to a current version of the node package.

Back to blog