Resolving LMQTT_Client Subscribe Topic Override on S7-1516
The Siemens LMQTT_Client function block, shipped with the SIMATIC S7-1500 MQTT client library, occasionally generates a misleading fault pattern at first scan: enabling the subscribe input causes the receive topic to be populated with the current value of mqttTopic instead of a separately configured subscription topic. This article documents the root cause, the exact block pin semantics, and the proven startup sequence that prevents the override.
1. Problem Description
Engineers configuring an S7-1516 as an MQTT client (not broker) report the following symptoms when commissioning the LMQTT_Client FB in TIA Portal:
- Publishing to
mqttTopicworks correctly and reaches the broker. - Immediately after PLC startup, toggling
subscribe := TRUEsubscribes the CPU tomqttTopicrather than to a separately assigned subscribe topic. - The topic displayed at the block's
receiveTopicpin equals the value currently held at themqttTopicinput. - Online monitoring shows the received payload data and QoS, but always against the publisher's topic instead of the desired subscription path.
The phenomenon only appears on the first call after the connection is established. Once the operator manually changes mqttTopic and re-arms subscribe, subsequent messages arrive at the expected topic.
2. Root Cause Analysis
The misunderstanding originates from the dual-use naming convention of the LMQTT_Client block. The Siemens documentation lists receiveTopic under the input section of the FB, but in practice the pin is a status output that reports the topic on which the most recent inbound MQTT message was received. It is not a subscribe filter.
The actual subscription filter is the mqttTopic input itself. When the user raises subscribe := TRUE, the FB transmits an MQTT SUBSCRIBE control packet to the broker using whatever value currently resides at mqttTopic. The receiveTopic pin is then overwritten with that same string as soon as the first PUBLISH packet echoes back from the broker, producing the appearance that the subscribe input was ignored.
This is the documented behavior on page 33 of the SIMATIC S7-1500 MQTT Client – Function Manual. The startup sequence described there is mandatory:
- Establish the broker connection.
- Load
mqttTopicwith the subscription topic string. - Pulse
subscribe := TRUE. - Wait for
subscribed := TRUEconfirmation. - Optionally overwrite
mqttTopicwith the publish topic string and pulsepublish := TRUE.
Both subscription and publication share the same WSTRING input; the block simply toggles its internal MQTT control flag based on whether the rising edge was detected at subscribe or publish.
3. LMQTT_Client Block Architecture
The LMQTT_Client FB is an instance-based block generated from the Siemens "SIMATIC S7-1500 MQTT Client" global library. The pinout relevant to this fault is summarized below.
| Pin | Direction | Data type | Function |
|---|---|---|---|
mqttTopic |
IN | WSTRING | Active topic string used for both SUBSCRIBE and PUBLISH operations |
subscribe |
IN | BOOL | Rising edge issues SUBSCRIBE packet to broker using mqttTopic value |
publish |
IN | BOOL | Rising edge issues PUBLISH packet using mqttTopic + payload |
receiveTopic |
OUT (status) | WSTRING | Reports topic of last received message; not an input |
subscribed |
OUT | BOOL | TRUE when broker has acknowledged the SUBSCRIBE packet |
payload |
IN_OUT | VARIANT | Publish payload or last received payload buffer |
qos |
IN | BYTE / INT | QoS level 0, 1, or 2 for current operation |
connect / disconnect
|
IN | BOOL | Connection management triggers |
connected |
OUT | BOOL | Connection state feedback |
error |
OUT | BOOL | Group fault indicator |
status |
OUT | WORD | Detailed status / error code (see Section 7) |
receiveTopic as a read-only diagnostic. Wiring a constant or variable to it in the editor does not configure the subscription – it is silently overwritten by the FB on every inbound PUBLISH frame.
4. Correct Startup Sequence
Use the following state machine to avoid the override. It is implemented in SCL for clarity and can be lifted directly into a function or FB.
// SCL snippet – LMQTT_Client startup sequencer
#region State machine
IF "initStartup" THEN
"phase" := 1; // 1 = connect, 2 = subscribe, 3 = publish loop
END_IF;
CASE "phase" OF
1: // Connect to broker
"LMQTT_DB".connect := TRUE;
IF "LMQTT_DB".connected THEN
"LMQTT_DB".connect := FALSE;
"phase" := 2;
END_IF;
2: // Subscribe – load SUBSCRIBE topic into mqttTopic first
"LMQTT_DB".mqttTopic := 'bs1/sortieranlage/eingaenge';
"LMQTT_DB".qos := 1;
"LMQTT_DB".subscribe := TRUE;
IF "LMQTT_DB".subscribed THEN
"LMQTT_DB".subscribe := FALSE;
"phase" := 3;
END_IF;
3: // Publish – change mqttTopic to PUBLISH topic, then arm publish edge
IF "triggerPublish" THEN
"LMQTT_DB".mqttTopic := 'bs1/sortieranlage/ausgaenge';
"LMQTT_DB".payload := "outgoingPayload";
"LMQTT_DB".qos := 1;
"LMQTT_DB".publish := TRUE;
// hold for one cycle, then drop
"holdPublish" := TRUE;
IF "holdPublish" AND "LMQTT_DB".busy = FALSE THEN
"LMQTT_DB".publish := FALSE;
"holdPublish" := FALSE;
END_IF;
END_IF;
END_CASE;
#endregion
Key invariants enforced by the sequencer:
-
mqttTopicis loaded before the subscribe edge fires. -
receiveTopicis never written from user code. -
subscribeandpublishedges are one-shot (single cycle TRUE followed by FALSE). - The sequencer waits for the broker acknowledgment (
subscribed) before changingmqttTopic.
5. Step-by-Step Configuration in TIA Portal
5.1 Prerequisites
- TIA Portal V17 Update 4 or later (V18 SP1 recommended for CPU firmware 2.9.x).
- S7-1500 CPU with firmware ≥ V2.8 to support the MQTT client blocks.
- MQTT broker reachable on the PLC's PROFINET/Industrial Ethernet interface.
- Global library SIMATIC S7-1500 MQTT Client installed (TIA Portal Options → Manage global libraries).
5.2 Procedure
- Open the TIA Portal project, navigate to Program blocks, and drag LMQTT_Client from the global library into the project.
- Create an instance DB (e.g. LMQTT_DB) when prompted. Do not use multi-instance, as the FB owns a large internal connection state.
- Open the instance DB and configure the connection parameters (brokerURI, clientID, keepAlive, userName, password, TLS settings). The TLS configuration requires that the PLC's certificate store has the broker CA imported via the TIA Portal Web server certificate manager.
- Wire the input pins as shown in Section 4. Leave
receiveTopicunwired or, if a tag is required for HMI display, use a separate display tag that simply mirrors"LMQTT_DB".receiveTopic. - Compile and download. Go online with the CPU.
- Monitor
"LMQTT_DB".connected– it must reach TRUE before the subscribe phase begins. - Trigger the subscribe sequence. Verify with an external MQTT client (e.g.
mosquitto_sub -t 'bs1/sortieranlage/eingaenge' -v) that the broker has registered the subscription. - From the external client, publish a test payload to the subscribed topic. Confirm that
payload,receiveTopic, and the inbound QoS update on the PLC. - Only then arm the publish sequence, having already loaded the publish topic into
mqttTopic.
6. Verification Procedures
| Check | Expected Result | Diagnostic Action if Failed |
|---|---|---|
connected = TRUE |
TCP/TLS session active with broker | Inspect status word; verify firewall / NAT / certificate chain |
subscribed = TRUE |
Broker acknowledged SUBSCRIBE for current mqttTopic
|
Check wildcard syntax; verify broker ACL allows PLC client ID |
External client shows PLC in $SYS/brokers/.../clients
|
PLC visible as connected client | Confirm client ID uniqueness |
External publish to mqttTopic produces updated payload on PLC |
Payload bytes match; receiveTopic = mqttTopic
|
QoS mismatch or topic filter too restrictive |
PLC publish to mqttTopic arrives at external subscriber |
External client logs the payload | Broker may require retain flag; check retain pin |
error = FALSE, status = 16#0000
|
No fault condition | See Section 7 status word decoding |
7. Status Word and Error Code Reference
The status output is a WORD following Siemens convention. The most relevant values observed during the subscribe topic override fault are listed below.
| status (hex) | Meaning | Remediation |
|---|---|---|
| 16#0000 | No error | – |
| 16#8001 | Connection lost | Check broker reachability, re-arm connect
|
| 16#8002 | Authentication failed | Verify userName / password against broker |
| 16#8003 | TLS handshake failed | Confirm CA certificate and time-of-day on PLC |
| 16#8010 | Invalid topic string | Check mqttTopic for empty string or unsupported wildcards |
| 16#8011 | Subscribe rejected by broker | Verify ACL / topic filter syntax; broker may forbid single-level wildcard at root |
| 16#8020 | Payload too large | Reduce payload size or raise broker's max_packet_size
|
| 16#80F0 | Internal resource exhausted | Reduce message rate; check that no orphan instance DBs are loaded |
8. Common Pitfalls and Workarounds
8.1 Wildcards in subscribe topic
MQTT allows + (single-level) and # (multi-level) wildcards in subscription filters only. Setting mqttTopic := 'factory/+/status' as a subscription works; setting it as a publish topic will be rejected by every conforming broker. Always verify the operation mode before assigning the string.
8.2 Cycling the connect input
Dropping connect while a SUBSCRIBE is pending causes the FB to discard the acknowledgment and to resend the SUBSCRIBE on the next connect cycle. If the application needs to disconnect/reconnect, do it only when subscribed = FALSE and busy = FALSE.
8.3 Multiple subscribe topics
The LMQTT_Client FB supports exactly one subscription at a time. To subscribe to multiple topics, instantiate the FB multiple times, each with its own mqttTopic and connect settings. Alternatively, migrate to OPC UA Pub/Sub over MQTT (Section 9) which natively supports topic groups.
8.4 Retain flag behavior
If the application requires that a freshly subscribed client immediately receive the last retained message, set the retain pin of the broker side to TRUE on the publisher. The Siemens FB does not control the retain bit of received messages.
8.5 CPU restart cold/warm
After a cold restart the instance DB is reinitialized and the subscription is lost. Always re-execute the startup sequence in OB100 (warm restart) or OB101 (hot restart). OB102 (cold restart) is the typical anchor for the sequencer.
9. Related Topics: OPC UA Pub/Sub over MQTT
Engineers using LMQTT_Client as a stepping stone to LOpcUa Pub/Sub (Acyclic / Cyclic transport over MQTT) commonly hit the same wiring traps. The OPC UA Pub/Sub extension uses the same MQTT foundation but introduces a WriterGroup / ReaderGroup model where metadata (dataset writer ID, network message ID) is exchanged out-of-band. When commissioning OPC UA Pub/Sub over MQTT:
- Ensure the WriterGroup metadata JSON is syntactically valid – the broker rejects malformed headers without raising the LMQTT_Client error bit.
- Configure a stable
WriterGroupIdandDatasetWriterId; mismatches between PLC and SCADA produce silent message drops. - For the ReaderGroup, the subscription topic follows the pattern
opcua/writergroup/<id>; populate it intomqttTopicbefore armingsubscribe. - Allow at least 3 × keepAlive intervals between connect and first publish to let the broker index the WriterGroup.
10. Long-Term Recommendations
-
Wrap LMQTT_Client in your own FB. Encapsulate the startup sequencer in a project-specific FB that exposes clear, named pins (iSubTopic, iPubTopic, iPayload, oReceivedTopic). This avoids future engineers confusing
receiveTopicwith a writable input. -
Document pin intent in the instance DB comments. Use the TIA Portal Comment column to state "READ-ONLY DIAGNOSTIC" on
receiveTopic. -
Use HMI tags with descriptive names. Avoid mapping
receiveTopicdirectly to an HMI tag named SubTopic; rename to LastReceivedTopic. - Unit-test the sequencer with a local Mosquitto broker. Add a CI loop that publishes to a test topic and asserts that the PLC subscription registered within 2 s.
- Pin TIA Portal and library versions. Record the exact library revision in the project properties; block changes without regression test.
11. Frequently Asked Questions
Is receiveTopic really an output, not an input?
Yes. In the LMQTT_Client FB, the receiveTopic pin is a status output that mirrors the topic of the last received PUBLISH packet. Wiring it to a constant or variable does not configure the subscription. The subscription filter is the value present at mqttTopic when the rising edge of subscribe fires.
Why does my first subscribe use the publish topic?
At program startup mqttTopic typically holds the default publish topic. If you arm subscribe := TRUE immediately, the FB subscribes to that default value. Load the desired subscribe string into mqttTopic before the subscribe edge and the broker will register the correct filter.
Can one LMQTT_Client instance subscribe to multiple topics?
No. The FB maintains exactly one active subscription at a time. To listen to multiple topics, instantiate the FB multiple times (each with its own mqttTopic) or migrate to OPC UA Pub/Sub over MQTT, which natively supports topic groups via WriterGroup / ReaderGroup metadata.
Which TIA Portal versions ship the LMQTT_Client block?
The "SIMATIC S7-1500 MQTT Client" library is available with TIA Portal V17 and later. Siemens recommends V18 SP1 or newer for CPU firmware ≥ V2.9. Earlier versions of the library used different pin names; consult the version-specific function manual on the Siemens Industry Online Support portal before upgrading.
How do I verify that the broker has actually accepted my subscription?
Monitor "LMQTT_DB".subscribed – it returns TRUE only after the broker has acknowledged the SUBSCRIBE packet. For external verification, use mosquitto_sub -v -t '$SYS/brokers/+/clients/#' on Mosquitto or the equivalent admin API of HiveMQ / AWS IoT Core to list active client subscriptions.