Skip to content

MQTT / MQTTS

An MQTT client with TLS, automatic reconnection and subscriptions restored on their own. Built with IoT platforms in mind, but it works with any broker.

Install the library first — see Library. Text parameters are POINTER TO BYTE, passed with ADR().

FilenXPicoMQTT.compiled-library
TypePrecompiled library: no source, nothing to build
Exported functions8, listed below
BoardsnXPico W only
RequiresA configured WiFi link and, for any TLS, nXPicoX509: the trust anchor is stored only after the device identity has been generated

Transport and authentication are two separate choices

Section titled “Transport and authentication are two separate choices”

The transport is declared by the application, with the xTls argument of mqttConnect. The authentication depends on what is passed, plus what is stored on the device.

xTlsTransportRequires
TRUETLS, server verified by pinninga trust anchor in flash, which in turn requires the device’s X.509 identity — otherwise mqttConnect returns 3 immediately
FALSEplain TCPnothing
CredentialsAuthentication
pUser = token, pPass = ''token as username — the ThingsBoard model
pUser + pPassusername and password
both ''X.509 client certificate, if the device identity is in flash (mutual TLS)

The port is just the TCP port. 0 gives the conventional one for the transport you chose: 8883 with TLS, 1883 in plain.

Stores the certificate used to verify the broker. Asynchronous, once per device.

FUNCTION mqttSetTrustAnchor : DINT
VAR_INPUT
pPem : POINTER TO BYTE; (* server certificate, PEM *)
udiLen : UDINT; (* length in bytes *)
END_VAR
ReturnMeaning
10accepted, written to flash at the first opportunity
2PEM missing, empty, longer than 2048 bytes or incomplete (no BEGIN/END delimiters)
11a write is already in progress

Check the outcome with mqttHasTrustAnchor(), not with the return value: the write is deferred. If the device identity is missing the function still returns 10: the refusal comes later, at write time, shows up only in the log (trust anchor RIFIUTATO: manca l'identita' X.509 del device), and mqttHasTrustAnchor() stays FALSE. Run x509GenerateDeviceCert first.

Requirements on the server certificate. PEM format with line breaks, and — if it is a self-signed certificate used as a root of trust — it must carry basicConstraints: CA:TRUE. A certificate without that extension is rejected during the handshake, even if other tools accept it.

FUNCTION mqttHasTrustAnchor : BOOL

Requests a connection. Asynchronous: the internal state machine synchronises the clock, resolves the name, opens TLS and waits for CONNACK, retrying with growing back-off.

FUNCTION mqttConnect : DINT
VAR_INPUT
pHost : POINTER TO BYTE; (* hostname or IP address *)
uiPort : UINT; (* 0 = 8883 with TLS, 1883 in plain *)
pClientId : POINTER TO BYTE;
pUser : POINTER TO BYTE; (* token or username; ADR('') for none *)
pPass : POINTER TO BYTE; (* ADR('') when there is no password *)
xTls : BOOL; (* TRUE = TLS, FALSE = plain TCP *)
END_VAR

The three ways to authenticate:

(* 1 — token as username *)
diRes := mqttConnect(ADR(sHost), 1883, ADR(sId), ADR(sToken), ADR(''), FALSE);
(* 2 — username and password *)
diRes := mqttConnect(ADR(sHost), 1883, ADR(sId), ADR(sUser), ADR(sPass), FALSE);
(* 3 — X.509 client certificate, over TLS *)
diRes := mqttConnect(ADR(sHost), 8883, ADR(sId), ADR(''), ADR(''), TRUE);
ReturnMeaning
10request accepted
2host missing or empty
3xTls is TRUE but no trust anchor is stored

Follow progress with mqttGetState().

FUNCTION mqttDisconnect : DINT

Closes the connection and stops retrying. Returns 0.

FUNCTION mqttGetState : DINT
ReturnMeaning
0idle
1connecting
2connected
-1name resolution failed
-2network time unavailable (needed to validate certificates)
-4TLS configuration failed (not enough memory, or invalid certificates)
-5not enough memory to create the MQTT client
-6connection refused
-7handshake or CONNACK timed out
-102broker: client identifier rejected
-104broker: bad username or password
-105broker: not authorised (wrong token, or device not enabled)
-356connection dropped

Queues a message and returns immediately.

FUNCTION mqttPublish : DINT
VAR_INPUT
pTopic : POINTER TO BYTE;
pPayload : POINTER TO BYTE;
udiLen : UDINT; (* use LEN(payload) *)
byQos : BYTE; (* 0 or 1 *)
xRetain : BOOL;
END_VAR
ReturnMeaning
0queued
15topic ≥ 128 characters, or payload > 512 bytes
17queue full: you are publishing faster than the network drains
2topic missing or empty

17 is not a fault — it is the mechanism that stops messages piling up without bound. Retry next cycle; if it persists, publish less often.

Limits: topic max 127 characters, payload max 512 bytes, queue of 3 messages.

FUNCTION mqttSubscribe : DINT
VAR_INPUT
pTopic : POINTER TO BYTE; (* + and # wildcards allowed *)
byQos : BYTE;
END_VAR
ReturnMeaning
0registered
17maximum of 4 subscriptions reached
2topic missing or too long

Call it once. The device restores its subscriptions itself on every reconnection — you do not need to redo them, and you do not need to notice the drops.

Pulls one received message off the queue.

FUNCTION mqttGetMessage : DINT
VAR_INPUT
pTopic : POINTER TO BYTE;
udiTopicSize : UDINT;
pPayload : POINTER TO BYTE;
udiPayloadSize : UDINT;
END_VAR
ReturnMeaning
> 0length of the delivered payload
0no message waiting
-15buffers too small — the message is discarded
-2invalid parameters

The queue holds 3 messages and drops new ones when full — call this every cycle.

  1. Generate the device identity — x509GenerateDeviceCert.
  2. Print it with x509DumpDeviceCert and register it on the platform.
  3. Store the broker certificate with mqttSetTrustAnchor.
  4. mqttSubscribe for the topics you need — once.
  5. mqttConnect with xTls := TRUE on port 8883, and watch mqttGetState() reach 2.