PROFINET to MQTT is a question many automation teams ask once they want machine data in dashboards or the cloud, and the answer is less obvious than for Modbus or OPC UA. This guide explains why PROFINET data cannot simply be polled, compares the four practical gateway options, and walks through a working example that reads process values from a Siemens S7 controller and publishes them to an MQTT broker. By the end you will know which option fits your plant and what to watch out for.
Why PROFINET Is Different
PROFINET IO is an industrial Ethernet standard for real-time, cyclic exchange between an IO controller (usually a PLC) and IO devices (remote I/O, drives, valve terminals, sensors). The controller establishes application relationships with each device according to the hardware configuration in the engineering tool, then exchanges process data at a fixed cycle, often every few milliseconds. Alarms and acyclic record data travel alongside.
Three properties matter for MQTT integration:
- The controller owns the devices. An IO device exchanges cyclic data with the controller it was configured for. A random client on the network cannot just ask a drive for its speed the way a Modbus master asks a meter for a register.
- Process data is raw bytes. Cyclic data is a block of input and output bytes whose meaning is defined in the PLC project and device description (GSDML) files, not on the wire.
- The real-time network is precious. Adding traffic or devices to a PROFINET network should be planned with the controls engineer, never improvised.
The practical consequence: in almost every case, the best source of PROFINET data is the PLC that already controls the devices, because it has the data, the context and the names.
The Four PROFINET to MQTT Options
| Option | How it works | Pros | Cons | Typical fit |
|---|---|---|---|---|
| 1. Read the PLC from an edge gateway | Gateway reads PLC memory through its native protocol or OPC UA server, then publishes MQTT | No change to the PROFINET network; uses existing tag names | Polling; may need PLC settings changed (access rights, OPC UA enabled) | Most brownfield sites |
| 2. PLC publishes MQTT itself | A vendor MQTT client library runs in the PLC program | No extra hardware; data published on change in PLC logic | PLC programming effort; CPU load and TLS handling in the PLC | Greenfield or when PLC programming is in-house |
| 3. PROFINET device gateway | A gateway appears as an IO device in the PLC configuration; the PLC writes data into its input/output area and the gateway publishes MQTT | Clean cyclic interface; no polling of the PLC | Requires hardware configuration change and a PLC download | Sites that prefer hardware gateways with a fixed interface |
| 4. Passive monitoring | A tap or mirror port captures PROFINET frames for diagnostics | No change to controller | Data meaning unknown without the project; not a data integration method | Network diagnostics only |
Option 4 is listed because it comes up in discussions, but it is a diagnostic technique, not a sound way to build a data pipeline. The rest of this guide focuses on the first three.
Option 1: Read the PLC from an Edge Gateway
This is the least intrusive approach and the one most teams start with. The gateway sits on the plant network, reads values from the PLC, and publishes them to MQTT. Two access paths are common on Siemens controllers:
- OPC UA server. S7-1500 controllers (and S7-1200 with recent firmware) can run an OPC UA server. You enable it in the hardware configuration and choose which tags to expose. The gateway then uses an OPC UA client, as in our OPC UA to MQTT gateway tutorial. This is the preferred path when available: secure, symbolic and supported.
- S7 communication (PUT/GET). Open-source libraries such as python-snap7 read data blocks by address. On S7-1200 and S7-1500, this needs PUT/GET access enabled in the CPU protection settings and the data block set to non-optimised access so that byte offsets are fixed. Enabling PUT/GET reduces the CPU's protection level, so agree it with whoever owns the PLC security.
Other vendors with PROFINET controllers offer similar choices, typically an OPC UA server or a vendor-specific read protocol.
Example: S7 Data Block to MQTT with python-snap7
Assume the PLC programmer has created a non-optimised data block DB10 that collects the values to share, a common and recommended pattern called an interface block:
| Offset | Name | Type |
|---|---|---|
| 0.0 | LineSpeed | Real |
| 4.0 | MotorCurrent | Real |
| 8.0 | GoodCount | DInt |
| 12.0 | Running | Bool |
| 12.1 | Fault | Bool |
pip install python-snap7 "paho-mqtt>=2.0"
# s7_profinet_mqtt.py - read an S7 interface DB and publish to MQTT
import json, logging, time, uuid
import paho.mqtt.client as mqtt
import snap7
from snap7.util import get_real, get_dint, get_bool
logging.basicConfig(level=logging.INFO)
log = logging.getLogger("s7")
PLC_IP, RACK, SLOT = "192.168.0.10", 0, 1 # S7-1200/1500: rack 0, slot 1 is typical
DB_NUMBER, DB_SIZE = 10, 14
TOPIC_ROOT = "connectmq/demo/p3x8/plant1/assembly/line3" # your own random id
MQTT_HOST, MQTT_PORT = "broker.connectmq.com", 1883 # production: 8883 with TLS
MQTT_USER, MQTT_PASS = None, None # production: "YOUR_USERNAME", "YOUR_PASSWORD"
CLIENT_ID = f"s7-bridge-{uuid.uuid4().hex[:8]}" # production: "YOUR_CLIENT_ID"
def decode(buf):
return {
"line_speed": round(get_real(buf, 0), 2),
"motor_current": round(get_real(buf, 4), 2),
"good_count": get_dint(buf, 8),
"running": get_bool(buf, 12, 0),
"fault": get_bool(buf, 12, 1),
}
def main():
mq = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=CLIENT_ID)
if MQTT_USER:
mq.username_pw_set(MQTT_USER, MQTT_PASS)
mq.tls_set()
mq.will_set(f"{TOPIC_ROOT}/bridge", "offline", qos=1, retain=True)
mq.on_connect = lambda c, u, f, rc, p: c.publish(f"{TOPIC_ROOT}/bridge", "online", qos=1, retain=True)
mq.connect(MQTT_HOST, MQTT_PORT, keepalive=30)
mq.loop_start()
plc = snap7.client.Client()
last = {}
while True:
try:
if not plc.get_connected():
plc.connect(PLC_IP, RACK, SLOT)
log.info("connected to PLC %s", PLC_IP)
values = decode(plc.db_read(DB_NUMBER, 0, DB_SIZE))
ts = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
for name, value in values.items():
if last.get(name) != value: # publish on change only
mq.publish(f"{TOPIC_ROOT}/{name}",
json.dumps({"value": value, "ts": ts}), qos=1, retain=True)
last[name] = value
except Exception as exc: # snap7 raises RuntimeError on comms errors
log.error("PLC read failed: %s", exc)
plc.disconnect()
time.sleep(5)
time.sleep(1)
if __name__ == "__main__":
main()
For analog values that drift constantly, add a deadband so the bridge does not publish every tiny change; our report by exception guide shows how. To watch the result, subscribe on the public MQTT test broker, keeping in mind that anyone can read it, so use test data only:
mosquitto_sub -h broker.connectmq.com -p 1883 -i s7-viewer-p3x8 -t "connectmq/demo/p3x8/#" -v
Option 2: Let the PLC Publish MQTT Directly
Several PLC vendors provide MQTT client function blocks. On Siemens S7-1500 and S7-1200, for example, an MQTT client library is available for TIA Portal that builds on the CPU's open user communication with TLS support. The PLC program then decides exactly when to publish, which is ideal for event-driven data such as batch completions or alarms.
Things to plan for:
- Certificates. For TLS, the CPU must trust the broker's CA. The broker uses a Let's Encrypt certificate, so load the corresponding root certificate into the PLC's certificate store.
- CPU and communication load. Publishing many values at high rates from the PLC competes with control tasks. Publish summaries and events, not every scan.
- Reconnect handling. The program must handle broker disconnects gracefully and not block control logic.
- Change management. Every topic or payload change is a PLC download. Keep the PLC side simple and do heavier mapping downstream.
Our Siemens S7 MQTT article goes deeper on the PLC-side setup.
Option 3: A PROFINET Device Gateway
Hardware gateways from several vendors act as a PROFINET IO device on one side and an MQTT client on the other. You import the gateway's GSDML file into the engineering tool, add it to the hardware configuration, and map PLC data into its cyclic input/output area. The gateway converts those bytes into MQTT messages according to its own configuration.
This gives a clean, deterministic interface: the PLC simply copies values into the gateway's output area every cycle, and nothing polls the PLC. The trade-offs are a hardware change, a PLC download to add the device, and a second place (the gateway's web UI) where the data mapping lives. It suits sites with strict rules against enabling PUT/GET or OPC UA on controllers.
Choosing the Right Option
Use this checklist with the controls engineer:
- Does the PLC have an OPC UA server you can enable? Use option 1 with OPC UA.
- Is PUT/GET acceptable under your security policy? Option 1 with S7 communication is quick and cheap.
- Do you need event-driven data defined in PLC logic? Option 2.
- Are controller settings locked down, but a hardware change is acceptable? Option 3.
- Is this a pilot on one line? Start with option 1; you can always move to option 2 or 3 at scale.
Whatever you choose, give the data an ISA-95 style topic structure so that PROFINET-sourced values sit alongside Modbus, EtherNet/IP and OPC UA data in one namespace; see our ISA-95 MQTT topics guide.
The Broker Side
All three options end with an MQTT client publishing to a broker, so the broker choice is independent of the field protocol. A hosted MQTT broker such as ConnectMQ supports MQTT 3.1.1 and 5.0 over TLS on 8883, detects ISA-95 and Unified Namespace topics, and shows them in a live topic explorer and a devices view organised by ISA-95 levels. Threshold alert rules can then flag a fault bit or a motor current above its limit without extra code. For the overall reference architecture, read the industrial IoT MQTT guide.
Get Started with ConnectMQ
Pick your PROFINET path, and let the broker be the easy part. Sign up at app.connectmq.com, choose the free Serverless plan (no credit card), create a broker and use the generated username, password and client ID in your gateway or PLC MQTT client. Your line data will be visible in the ConnectMQ portal within minutes.
Frequently Asked Questions
Can an MQTT gateway read PROFINET devices directly?
Not in the way a Modbus master polls a meter. PROFINET IO devices exchange cyclic data with their configured controller, so gateways either read the controller or are themselves configured as IO devices.
Is enabling PUT/GET on an S7-1200 or S7-1500 safe?
It lowers the CPU's access protection, so it should be a deliberate, documented decision with network segmentation in place. Where available, the PLC's OPC UA server is the more secure alternative.
Do I need GSDML files for a PROFINET to MQTT gateway?
Only for option 3, where the gateway is added to the PLC hardware configuration as an IO device. Reading the PLC through OPC UA or S7 communication does not require them.
Does reading the PLC affect PROFINET real-time performance?
Reads go to the CPU's communication interface, not the cyclic IO exchange, and moderate polling has little impact. Keep poll rates sensible and read compact interface blocks.



