Skip to main content

Embed NanoMQTT in C

This topic shows the smallest synchronous flow needed to connect, subscribe, publish, and service the receive loop in a single-threaded application.

Before you begin

  • If you plan to use TLS, create and negotiate a NanoSSL connection:

    • Create the NanoSSL handle with SSL_connect().

    • Complete the handshake with SSL_negotiateConnection().

    • Bind the SSL handle to the MQTT connection with MQTT_setTransportSSL(connInst, sslConnInst) before you call MQTT_negotiateConnection().

  • Examples assume sockets are non-blocking so a single event loop can multiplex TCP/TLS traffic. Build with the asynchronous client enabled (__ENABLE_MQTT_ASYNC_CLIENT__ or --async in the build script) and open your sockets in non-blocking mode. Blocking sockets work, but they prevent multiplexing.

  • A reachable MQTT 5 or 3.1.1 broker (port 1883 for TCP, 8883 for TLS).

Minimal synchronous example

#include "mqtt_client.h"
#include "ssl_api.h"          /* Needed only for TLS */

static void on_publish(const MqttPublishRx *msg, void *arg)
{
    /* Handle inbound publishes here */
}

/* ---------- 1. Allocate an MQTT connection (stores Client-ID) */
MqttConnectionHandle conn =
    MQTT_connect(MQTT_V5, "device-123", strlen("device-123"));

/* ---------- 2. Bind a transport ----------------------------------------- */
/* (a) Clear-text TCP:                                                     */
/* int socketFd = ... ;  MQTT_setTransportTCP(conn, socketFd);            */
/* (b) TLS transport (shown):                                              */
MQTT_setTransportSSL(conn, sslConnInst);   /* sslConnInst = NanoSSL handle */
/* Transport may be bound at any point *before* MQTT_negotiateConnection.  */

/* ---------- 3. Register control-packet handlers ------------------------- */
MqttPacketHandlers h = { .publishHandler = on_publish };
MQTT_setControlPacketHandlers(conn, &h);

/* ---------- 4. Negotiate the session (CONNECT / CONNACK) --------------- */
MqttConnectOptions opts = {
    .cleanStart        = true,
    .keepAliveInterval = 30,   /* seconds; 0 disables keep-alive */
};
if (MQTT_negotiateConnection(conn, &opts) < 0) {
    /* handle error */
}

/* ---------- 5. Subscribe and publish ------------------------------------ */
MqttSubscribeTopic   subTopic = { .pTopic = "alerts/#", .topicLen = 8, .qos = 1 };
MqttSubscribeOptions subOpts  = { 0 };   /* no extra options */
MQTT_subscribe(conn, &subTopic, 1, &subOpts);

MqttPublishOptions   pubOpts  = { .qos = 0, .retain = false };
const char payload[] = "Hello NanoMQTT";
MQTT_publish(conn, &pubOpts,
             "telemetry", 9,
             payload, sizeof payload - 1);

/* ---------- 6. Main receive loop ---------------------------------------- */
while (running) {
    if (MQTT_recv(conn) < 0) {   /* dispatches callbacks */
        /* handle error or reconnect */
    }
}

/* ---------- 7. Graceful shutdown --------------------------------------- */
MQTT_disconnect(conn, NULL);   /* default DISCONNECT           */
MQTT_closeConnection(conn);    /* free all connection memory   */

How it works

Table 1. Minimal synchronous example code description

Step

Call

Purpose

1

MQTT_connect

Allocate the client state machine and store the Client-ID.

2

MQTT_setTransportSSL / MQTT_setTransportTCP

Bind TLS or clear-text transport before negotiation.

3

MQTT_setControlPacketHandlers

Register application callbacks (publish, disconnect, etc.).

4

MQTT_negotiateConnection

Send CONNECT, wait for CONNACK, apply keep-alive.

5

MQTT_subscribe / MQTT_publish

Add subscriptions or transmit payloads.

6

MQTT_recv

Drive the synchronous loop; dispatch callbacks.

7

MQTT_disconnect / MQTT_closeConnection

Clean up network state and free all allocated memory.


Note

Return codes: All NanoMQTT functions return MQTT_OK (0) or a negative error code. Check each call; on failure disconnect, free, and reconnect.

Implementation notes

Table 2. Implementation topics and notes

Topic

Note

Build toggle

NanoMQTT is part of the default TrustCore SDK build. Use ./build.sh nanomqtt (or the --module nanomqtt CMake option) if you want to build only the NanoMQTT components.

Auto-PING logic

MQTT_recv() automatically injects a PINGREQ whenever no other data has flowed for one keep-alive interval. Applications do not need to call MQTT_pingRequest() unless they choose to manage keep-alive manually. If the keep-alive interval is 0, NanoMQTT will not send PINGREQ packets.

Memory ownership

MQTT_disconnect() terminates the network session but does not free the client state. Always follow it with MQTT_closeConnection(conn) (or drop the handle) to release memory.