Sample description

The MQTT sample communicates with an MQTT broker either over LTE using an nRF91 Series device, or over Wi-Fi® using an nRF70 Series device or an nRF54L15 DK connected with nRF7002 EB as a shield.

Cellular connectivity is supported on the nRF91 Series SiPs, while Wi-Fi connectivity is supported on the nRF52 or nRF53 Series SoCs hosting the nRF70 Series Wi-Fi companion ICs.

The sample uses the connection manager that provides a common connectivity API for LTE and Wi-Fi stacks.

Requirements

The sample supports the following development kits:

Hardware platforms

PCA

Board name

Board target

Thingy:91 X

PCA20065

thingy91x

thingy91x/nrf9151/ns

Thingy:91

PCA20035

thingy91

thingy91/nrf9160/ns

nRF9161 DK

PCA10153

nrf9161dk

nrf9161dk/nrf9161/ns

nRF9160 DK

PCA10090

nrf9160dk

nrf9160dk/nrf9160/ns

nRF9151 DK

PCA10171

nrf9151dk

nrf9151dk/nrf9151/ns

nRF7002 DK

PCA10143

nrf7002dk

nrf7002dk/nrf5340/cpuapp/ns

Native Simulator

native_sim

native_sim

Additionally, the sample supports emulation using the native simulator.

Overview

The sample connects to either LTE or Wi-Fi, depending on the board for which the sample is compiled. Subsequently, the sample connects to a configured MQTT server (default is test.mosquitto.org), where it publishes messages to the topic <clientID>/my/publish/topic. You can also trigger message publication by pressing any of the buttons on the board.

The sample also subscribes to the topic <clientID>/my/subscribe/topic, and receives any message published to that topic.

The sample supports Transport Layer Security (TLS) and it can be enabled through overlay configuration files included in the sample.

Note

When enabling TLS and building for nRF91 Series devices, the size of the incoming message cannot exceed 2 kB. This is due to a limitation in the modem’s internal TLS buffers.

Configuration

See Configuring and building for information about how to permanently or temporarily change the configuration.

Configuration options

Check and configure the following Kconfig options:

General options

CONFIG_MQTT_SAMPLE_TRIGGER_TIMEOUT_SECONDS - Trigger timeout

This configuration option sets the interval at which the sample publishes a message to the MQTT broker.

CONFIG_MQTT_SAMPLE_TRANSPORT_RECONNECTION_TIMEOUT_SECONDS - Transport reconnection timeout

This configuration option sets the interval at which the sample tries to reconnect to the MQTT broker upon a lost connection.

CONFIG_MQTT_SAMPLE_TRANSPORT_BROKER_HOSTNAME - MQTT broker hostname

This configuration sets the MQTT broker hostname. Default is test.mosquitto.org.

CONFIG_MQTT_SAMPLE_TRANSPORT_CLIENT_ID - MQTT client ID

This configuration sets the MQTT client ID name. If not set, the client ID will default to the modem’s IMEI number for nRF91 Series devices, MAC address for nRF70 Series devices, or a random number for native simulator.

CONFIG_MQTT_SAMPLE_TRANSPORT_PUBLISH_TOPIC - MQTT publish topic

This configuration option sets the topic to which the sample publishes messages. Default is <clientID>/my/publish/topic.

CONFIG_MQTT_SAMPLE_TRANSPORT_SUBSCRIBE_TOPIC - MQTT subscribe topic

This configuration option sets the topic to which the sample subscribes. Default is <clientID>/my/subscribe/topic.

Configuring Wi-Fi access point credentials

This sample uses the Wi-Fi credentials library to manage Wi-Fi credentials. Before the sample can connect to a Wi-Fi network, you must configure at least one credential set.

Once you have flashed your device with this sample, connect to your device’s UART interface and add credentials using the following command:

wifi_cred add -s NetworkSSID -k SecurityMode -p NetworkPassword

Where NetworkSSID is replaced with the SSID of the Wi-Fi access point you want your device to connect to, and NetworkPassword is its password. SecurityMode is replaced by the number as listed here:

  • 0: None

  • 1: WPA2-PSK

  • 2: WPA2-PSK-256

  • 3: SAE-HNP

  • 4: SAE-H2E

  • 5: SAE-AUTO

  • 6: WAPI

  • 7: EAP-TLS

  • 8: WEP

  • 9: WPA-PSK

  • 10: WPA-Auto-Personal

  • 11: DPP

If you are not sure which security mode to use, enable the CONFIG_NET_L2_WIFI_SHELL Kconfig option and use the wifi scan command to display a list of all accessible networks along with their corresponding security modes. Then either reboot the device or use the wifi_cred auto_connect command to manually trigger a connection attempt.

From now on, these credentials will be automatically used when the configured network is reachable.

When building as firmware image for a non-secure board target, the Wi-Fi credentials backend will be set to PSA using TF-M.

See the Wi-Fi: Shell sample document for more details on the wifi_cred command.

Wi-Fi static credential options

If you want to configure the credentials statically, set the CONFIG_WIFI_CREDENTIALS_STATIC Kconfig option to y.

Important

Do not use static credentials in production environments.

Other options for statically configuring your Wi-Fi credentials:

Additional configuration

Check and configure the following library Kconfig options specific to the MQTT helper library:

Configuration files

The sample provides predefined configuration files for the following development kits:

  • prj.conf - General project configuration file.

  • boards/nrf9151dk_nrf9151_ns.conf - Configuration file for the nRF9151 DK.

  • boards/nrf9161dk_nrf9161_ns.conf - Configuration file for the nRF9161 DK.

  • boards/nrf9160dk_nrf9160_ns.conf - Configuration file for the nRF9160 DK.

  • boards/thingy91_nrf9160_ns.conf - Configuration file for the Thingy:91.

  • thingy91x_nrf9151_ns.conf - Configuration file for the Thingy:91 X.

  • boards/nrf7002dk_nrf5340_cpuapp.conf - Configuration file for the nRF7002 DK.

  • nrf54l15dk_nrf54l15_cpuapp.conf - Configuration file for the nRF54L15 DK.

  • boards/native_sim.conf - Configuration file for the native simulator board.

Files that are located under the /boards folder is automatically merged with the prj.conf file when you build for corresponding target.

In addition, the sample provides the following overlay configuration files, which are used to enable additional features in the sample:

  • overlay-tls-nrf91.conf - TLS overlay configuration file for nRF91 Series devices.

  • overlay-tls-nrf70.conf - TLS overlay configuration file for nRF70 Series devices.

  • overlay-tls-nrf54l15-nrf70.conf - TLS overlay configuration file for nRF54L15 DK.

  • overlay-tls-native_sim.conf - TLS overlay configuration file for the native simulator board.

They are located in samples/net/mqtt folder.

To add a specific overlay configuration file to the build, add the -- -DEXTRA_CONF_FILE=<overlay_config_file> flag to your build.

See Providing CMake options for instructions on how to add this option to your build. For example, when building with the command line, the following commands can be used for the nRF9160 DK:

west build -b nrf9160dk/nrf9160/ns -- -DEXTRA_CONF_FILE=overlay-tls-nrf91.conf

For Thingy:91, with TLS and debug logging enabled for the MQTT helper library (for more information, see the related sample output):

west build -b thingy91/nrf9160/ns -- -DEXTRA_CONF_FILE=overlay-tls-nrf91.conf -DCONFIG_MQTT_HELPER_LOG_LEVEL_DBG=y

Sending traces over UART on an nRF91 Series DK

To send modem traces over UART on an nRF91 Series DK, configuration must be added for the UART device in the devicetree and Kconfig. This is done by adding the modem trace UART snippet when building and programming.

Use the Cellular Monitor app for capturing and analyzing modem traces.

TF-M logging must use the same UART as the application. For more details, see shared TF-M logging.

Building and running

This sample can be found under samples/net/mqtt in the nRF Connect SDK folder structure.

When built as firmware image for a board target with the */ns variant, the sample has Cortex-M Security Extensions (CMSE) enabled and separates the firmware between Non-Secure Processing Environment (NSPE) and Secure Processing Environment (SPE). Because of this, it automatically includes the Trusted Firmware-M (TF-M). To read more about CMSE, see Processing environments.

To build the sample, follow the instructions in Building an application for your preferred building environment. See also Programming an application for programming steps and Testing and optimization for general information about testing and debugging in the nRF Connect SDK.

Note

When building repository applications in the SDK repositories, building with sysbuild is enabled by default. If you work with out-of-tree freestanding applications, you need to manually pass the --sysbuild parameter to every build command or configure west to always use it.

Testing

After programming the sample to your development kit, complete the following steps to test it:

  1. Connect the kit to the computer using a USB cable. The kit is assigned a COM port (Windows) or ttyACM device (Linux), which is visible in the Device Manager.

  2. Connect to the kit with a terminal emulator (for example, nRF Connect Serial Terminal). See Testing and optimization for the required settings and steps.

  3. Reset your board.

  4. Observe that the board connects to the network and the configured MQTT broker (CONFIG_MQTT_SAMPLE_TRANSPORT_BROKER_HOSTNAME). When a network connection has been established, LED 1 (green) on the board lights up. After the connection has been established the board starts to publish messages to the topic set by CONFIG_MQTT_SAMPLE_TRANSPORT_PUBLISH_TOPIC. The frequency of the messages that are published to the broker can be set by CONFIG_MQTT_SAMPLE_TRIGGER_TIMEOUT_SECONDS or triggered asynchronously by pressing any of the buttons on the board. At any time, the sample can receive messages published to the subscribe topic set by CONFIG_MQTT_SAMPLE_TRANSPORT_SUBSCRIBE_TOPIC.

  5. Use an MQTT client like Mosquitto or VSMQTT to subscribe to, and publish data to the broker.

Sample output

The following serial UART output is displayed in the terminal emulator using a Wi-Fi connection, with the TLS overlay:

*** Booting Zephyr OS build v2.4.0-ncs1-rc1-6-g45f2d5cf8ea4  ***
[00:00:00.394,744] <inf> network: Bringing network interface up and connecting to the network
[00:00:12.736,297] <inf> network: Network connectivity established
[00:00:17.997,253] <inf> transport: Connected to MQTT broker
[00:00:18.007,049] <inf> transport: Hostname: test.mosquitto.org
[00:00:18.009,981] <inf> transport: Client ID: F4CE37111350
[00:00:18.013,519] <inf> transport: Port: 8883
[00:00:18.018,341] <inf> transport: TLS: Yes
[00:00:18.078,521] <inf> transport: Subscribed to topic F4CE37111350/my/subscribe/topic
[00:01:01.475,982] <inf> transport: Publishing message: "Hello MQTT! Current uptime is: 61458" on topic: "F4CE37111350/my/publish/topic"
[00:02:01.475,982] <inf> transport: Publishing message: "Hello MQTT! Current uptime is: 121458" on topic: "F4CE37111350/my/publish/topic"
[00:03:01.475,982] <inf> transport: Publishing message: "Hello MQTT! Current uptime is: 181458" on topic: "F4CE37111350/my/publish/topic"
[00:04:01.475,982] <inf> transport: Publishing message: "Hello MQTT! Current uptime is: 241458" on topic: "F4CE37111350/my/publish/topic"
[00:05:01.475,982] <inf> transport: Publishing message: "Hello MQTT! Current uptime is: 301459" on topic: "F4CE37111350/my/publish/topic"

The sample output showing IPv6, but for a different build configuration using LTE on the Thingy:91 with the TLS overlay, and debug logging enabled for the MQTT helper library:

*** Booting Zephyr OS build v3.2.99-ncs2-34-gf8f113382356 ***
[00:00:00.286,254] <inf> network: Bringing network interface up and connecting to the network
[00:00:00.286,621] <dbg> mqtt_helper: mqtt_state_set: State transition: MQTT_STATE_UNINIT --> MQTT_STATE_DISCONNECTED
[00:00:00.310,028] <dbg> mqtt_helper: mqtt_helper_poll_loop: Waiting for connection_poll_sem
[00:00:04.224,426] <inf> network: Network connectivity established
[00:00:09.233,612] <dbg> mqtt_helper: broker_init: Resolving IP address for test.mosquitto.org
[00:00:10.541,839] <dbg> mqtt_helper: broker_init: IPv6 Address found 2001:41d0:1:925e::1 (AF_INET6)
[00:00:10.541,900] <dbg> mqtt_helper: mqtt_state_set: State transition: MQTT_STATE_DISCONNECTED --> MQTT_STATE_TRANSPORT_CONNECTING
[00:00:13.747,406] <dbg> mqtt_helper: mqtt_state_set: State transition: MQTT_STATE_TRANSPORT_CONNECTING --> MQTT_STATE_TRANSPORT_CONNECTED
[00:00:13.747,467] <dbg> mqtt_helper: mqtt_state_set: State transition: MQTT_STATE_TRANSPORT_CONNECTED --> MQTT_STATE_CONNECTING
[00:00:13.747,497] <dbg> mqtt_helper: client_connect: Using send socket timeout of 60 seconds
[00:00:13.747,497] <dbg> mqtt_helper: mqtt_helper_connect: MQTT connection request sent
[00:00:13.747,558] <dbg> mqtt_helper: mqtt_helper_poll_loop: Took connection_poll_sem
[00:00:13.747,558] <dbg> mqtt_helper: mqtt_helper_poll_loop: Starting to poll on socket, fd: 0
[00:00:13.747,589] <dbg> mqtt_helper: mqtt_helper_poll_loop: Polling on socket fd: 0
[00:00:14.370,727] <dbg> mqtt_helper: mqtt_evt_handler: MQTT mqtt_client connected
[00:00:14.370,788] <dbg> mqtt_helper: mqtt_state_set: State transition: MQTT_STATE_CONNECTING --> MQTT_STATE_CONNECTED
[00:00:14.370,788] <inf> transport: Connected to MQTT broker
[00:00:14.370,819] <inf> transport: Hostname: test.mosquitto.org
[00:00:14.370,849] <inf> transport: Client ID: 350457791735879
[00:00:14.370,880] <inf> transport: Port: 8883
[00:00:14.370,880] <inf> transport: TLS: Yes
[00:00:14.370,910] <dbg> mqtt_helper: mqtt_helper_subscribe: Subscribing to: F4CE37111350/my/subscribe/topic
[00:00:14.494,354] <dbg> mqtt_helper: mqtt_helper_poll_loop: Polling on socket fd: 0
[00:00:15.136,047] <dbg> mqtt_helper: mqtt_evt_handler: MQTT_EVT_SUBACK: id = 2469 result = 0
[00:00:15.136,077] <inf> transport: Subscribed to topic F4CE37111350/my/subscribe/topic
[00:00:15.136,108] <dbg> mqtt_helper: mqtt_helper_poll_loop: Polling on socket fd: 0
[00:00:15.136,260] <dbg> mqtt_helper: mqtt_evt_handler: MQTT_EVT_PUBLISH, message ID: 52428, len = 850
[00:00:15.136,444] <inf> transport: Received payload: Test message from mosquitto_pub! on topic: F4CE37111350/my/subscribe/topic
[00:00:15.136,444] <dbg> mqtt_helper: mqtt_helper_poll_loop: Polling on socket fd: 0
[00:00:44.495,147] <dbg> mqtt_helper: mqtt_helper_poll_loop: Polling on socket fd: 0
[00:00:45.478,210] <dbg> mqtt_helper: mqtt_evt_handler: MQTT_EVT_PINGRESP
[00:00:45.478,210] <dbg> mqtt_helper: mqtt_helper_poll_loop: Polling on socket fd: 0
[00:01:00.492,370] <dbg> mqtt_helper: mqtt_helper_publish: Publishing to topic: F4CE37111350/my/publish/topic
[00:01:00.493,133] <inf> transport: Published message: "Hello MQTT! Current uptime is: 60492" on topic: "F4CE37111350/my/publish/topic"
[00:01:01.270,690] <dbg> mqtt_helper: mqtt_evt_handler: MQTT_EVT_PUBACK: id = 60492 result = 0
[00:01:01.270,690] <dbg> mqtt_helper: mqtt_helper_poll_loop: Polling on socket fd: 0
[00:01:05.093,719] <dbg> mqtt_helper: mqtt_evt_handler: MQTT_EVT_PUBLISH, message ID: 52428, len = 32
[00:01:05.093,872] <inf> transport: Received payload: Test message from mosquitto_pub! on topic: F4CE37111350/my/subscribe/topic
[00:01:05.093,872] <dbg> mqtt_helper: mqtt_helper_poll_loop: Polling on socket fd: 0
[00:01:30.503,021] <dbg> mqtt_helper: mqtt_helper_poll_loop: Polling on socket fd: 0
[00:01:31.494,537] <dbg> mqtt_helper: mqtt_evt_handler: MQTT_EVT_PINGRESP
[00:01:31.494,567] <dbg> mqtt_helper: mqtt_helper_poll_loop: Polling on socket fd: 0
[00:02:00.492,462] <dbg> mqtt_helper: mqtt_helper_publish: Publishing to topic: F4CE37111350/my/publish/topic
[00:02:00.501,678] <inf> transport: Published message: "Hello MQTT! Current uptime is: 120492" on topic: "F4CE37111350/my/publish/topic"
[00:02:00.503,692] <dbg> mqtt_helper: mqtt_helper_poll_loop: Polling on socket fd: 0
[00:02:01.577,453] <dbg> mqtt_helper: mqtt_evt_handler: MQTT_EVT_PUBACK: id = 54956 result = 0
[00:02:01.577,484] <dbg> mqtt_helper: mqtt_helper_poll_loop: Polling on socket fd: 0

Note

For nRF91 Series devices, the output differs from the above example output. This is because the sample enables the AT Host library using the CONFIG_AT_HOST_LIBRARY option. This library makes it possible to send AT commands to the nRF91 Series modem and receive responses using the Cellular Monitor app from nRF Connect for Desktop. The additional logs are AT command responses that the modem sends to the application core that are forwarded over UART to be displayed on any of these nRF Connect for Desktop apps.

Reconnection logic

If the network connection is lost, the following log output is displayed:

<inf> network: Disconnected

If this occurs, the network stack automatically reconnects to the network using its built-in backoff functionality.

If the TCP/IP (MQTT) connection is lost, the following log output is displayed:

<inf> transport: Disconnected from MQTT broker

If this occurs, the sample’s transport module has built-in reconnection logic that will try to reconnect at the frequency set by CONFIG_MQTT_SAMPLE_TRANSPORT_RECONNECTION_TIMEOUT_SECONDS.

Emulation

The sample can be run in native simulator that simplifies development and testing and removes the need for hardware. Before you can build and the run native simulator, you need to perform the steps included in this link: Networking with native_sim board.

When the aforementioned steps are completed, you can build and run the sample by using the following commands:

west build -b native_sim samples/net/mqtt
west build -t run

Troubleshooting

To enable more verbose logging from the MQTT helper library, enable the CONFIG_MQTT_HELPER_LOG_LEVEL_DBG option.

  • If you have issues with connectivity on nRF91 Series devices, see the Cellular Monitor documentation to learn how to capture modem traces in order to debug network traffic in Wireshark. The sample enables modem traces by default.

  • Public MQTT brokers might be unstable. If you have trouble connecting to the MQTT broker, try switching to another broker by changing the value of the CONFIG_MQTT_SAMPLE_TRANSPORT_BROKER_HOSTNAME configuration option. If you are switching to another broker, remember to update the CA certificate. To know more on certificates and provisioning, see Provisioning.

Dependencies

This sample uses the following nRF Connect SDK and Zephyr libraries: