1.. zephyr:code-sample:: mqtt-publisher 2 :name: MQTT publisher 3 :relevant-api: mqtt_socket 4 5 Send MQTT PUBLISH messages to an MQTT server. 6 7Overview 8******** 9 10`MQTT <http://mqtt.org/>`_ (MQ Telemetry Transport) is a lightweight 11publish/subscribe messaging protocol optimized for small sensors and 12mobile devices. 13 14The Zephyr MQTT Publisher sample application is a MQTT client that sends 15MQTT PUBLISH messages to a MQTT broker. The sample supports MQTT client in 16version v3.1.1 (default) and v5.0. 17 18See the `MQTT v3.1.1 spec`_ and `MQTT v5.0 spec`_ for more information about 19MQTT v3.1.1 and v5.0, respectively. 20 21.. _MQTT v3.1.1 spec: https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html 22.. _MQTT v5.0 spec: https://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html 23 24The source code of this sample application can be found at: 25:zephyr_file:`samples/net/mqtt_publisher`. 26 27Requirements 28************ 29 30- Linux machine 31- Freedom Board (FRDM-K64F) 32- Mosquitto server: any version that supports MQTT v3.1.1. This sample 33 was tested with mosquitto 1.3.4. 34- Mosquitto subscriber 35- LAN for testing purposes (Ethernet) 36 37Build and Running 38***************** 39 40Currently, this sample application only supports static IP addresses. 41Open the :file:`src/config.h` file and set the IP addresses according 42to the LAN environment. 43Alternatively, set the IP addresses in the :file:`prj.conf` file. 44 45The file :file:`src/config.h` also contains some variables that may be changed: 46 47MQTT broker TCP port: 48 49.. code-block:: c 50 51 #define SERVER_PORT 1883 52 53Application sleep time: 54 55.. code-block:: c 56 57 #define APP_SLEEP_MSECS 500 58 59Max number of connection tries: 60 61.. code-block:: c 62 63 #define APP_CONNECT_TRIES 10 64 65MQTT Client Identifier: 66 67.. code-block:: c 68 69 #define MQTT_CLIENTID "zephyr_publisher" 70 71This sample application supports the IBM Bluemix Watson topic format that can 72be enabled by changing the default value of APP_BLUEMIX_TOPIC from 0 to 1: 73 74.. code-block:: c 75 76 #define APP_BLUEMIX_TOPIC 1 77 78The Bluemix topic may include some parameters like device type, device 79identifier, event type and message format. This application uses the 80following macros to specify those values: 81 82.. code-block:: c 83 84 #define BLUEMIX_DEVTYPE "sensor" 85 #define BLUEMIX_DEVID "carbon" 86 #define BLUEMIX_EVENT "status" 87 #define BLUEMIX_FORMAT "json" 88 89Max number of MQTT PUBLISH iterations is defined in Kconfig: 90 91.. code-block:: cfg 92 93 CONFIG_NET_SAMPLE_APP_MAX_ITERATIONS=5 94 95On your Linux host computer, open a terminal window, locate the source code 96of this sample application (i.e., :zephyr_file:`samples/net/mqtt_publisher`) and type: 97 98.. zephyr-app-commands:: 99 :zephyr-app: samples/net/mqtt_publisher 100 :board: frdm_k64f 101 :goals: build flash 102 :compact: 103 104If the board is connected directly to the Linux host computer through LAN, 105configure the network interface: 106 107.. code-block:: console 108 109 $ IFACE=eth0 # Change this to the interface to which the LAN cable is connected 110 111 $ IPV4_ADDR_1="192.0.2.2/24" 112 $ IPV4_ROUTE_1="192.0.2.0/24" 113 114 $ sudo ip address add $IPV4_ADDR_1 dev $IFACE 115 $ sudo ip route add $IPV4_ROUTE_1 dev $IFACE 116 $ sudo ip link set dev $IFACE up 117 118You can run ``sudo ip addr flush dev $IFACE`` to undo the steps above. 119 120.. note:: 121 For mosquitto 2.0 and up, ensure you set unauthenticated access by 122 adding the following to the mosquitto configuration file ``mosquitto.conf``: 123 124 .. code-block:: none 125 126 listener 1883 127 allow_anonymous true 128 bind_interface eth0 129 130Open another terminal window and type: 131 132.. code-block:: console 133 134 $ sudo mosquitto -v -p 1883 # For mosquitto < 2.0 135 $ sudo mosquitto -v -c mosquitto.conf # For mosquitto >= 2.0 136 137Open another terminal window and type: 138 139.. code-block:: console 140 141 $ mosquitto_sub -t sensors 142 143MQTT v5.0 support 144================= 145 146The sample can be configured to use MQTT v5.0 instead of MQTT v3.1.1. To enable 147MQTT v5.0 in the sample, build it with ``-DEXTRA_CONF_FILE=overlay-mqtt-5.conf`` 148parameter. The sample should work with any broker supporting MQTT v5.0, however 149it was specifically tested with mosquitto version 2.0.21. Server side 150configuration in this particular case is the same as for MQTT v3.1.1. 151 152When the sample is configured in the MQTT v5.0 mode, it makes use of the topic 153aliasing feature. i.e. if the broker reports it supports topic aliases, the 154client will register a topic alias for the default ``sensors`` topic, and use it 155for consecutive MQTT Publish messages. It can be observed (for example using 156Wireshark) how the actual topic is only present in the first Publish message, and 157all subsequent Publish messages are smaller, as they include topic alias 158property only. 159 160Connecting securely using TLS 161============================= 162 163While it is possible to set up a local secure MQTT server and update the 164sample to connect to it, it does require some work on the user's part to 165create the certificates and to set them up with the server. 166 167Alternatively, a `publicly available Mosquitto MQTT server/broker 168<https://test.mosquitto.org/>`_ is available to quickly and easily 169try this sample with TLS enabled, by following these steps: 170 171- Download the server's CA certificate file in DER format from 172 https://test.mosquitto.org 173- In :file:`src/test_certs.h`, set ``ca_certificate[]`` using the certificate 174 contents (or set it to its filename if the socket offloading feature is 175 enabled on your platform and :kconfig:option:`CONFIG_TLS_CREDENTIAL_FILENAMES` is 176 set to ``y``). 177- In :file:`src/config.h`, set SERVER_ADDR to the IP address to connect to, 178 i.e., the IP address of test.mosquitto.org ``"37.187.106.16"`` 179- In :file:`src/main.c`, set TLS_SNI_HOSTNAME to ``"test.mosquitto.org"`` 180 to match the Common Name (CN) in the downloaded certificate. 181- Build the sample by specifying ``-DEXTRA_CONF_FILE=overlay-tls.conf`` 182 when running ``west build`` or ``cmake`` (or refer to the TLS offloading 183 section below if your platform uses the offloading feature). 184- Flash the binary onto the device to run the sample: 185 186.. code-block:: console 187 188 $ ninja flash 189 190TLS offloading 191============== 192 193For boards that support this feature, TLS offloading is used by 194specifying ``-DEXTRA_CONF_FILE=overlay-tls-offload.conf`` when running ``west 195build`` or ``cmake``. 196 197Using this overlay enables TLS without bringing in mbedtls. 198 199SOCKS5 proxy support 200==================== 201 202It is also possible to connect to the MQTT broker through a SOCKS5 proxy. 203To enable it, use ``-DEXTRA_CONF_FILE=overlay-socks5.conf`` when running ``west 204build`` or ``cmake``. 205 206By default, to make the testing easier, the proxy is expected to run on the 207same host as the MQTT broker. 208 209To start a proxy server, ``ssh`` can be used. 210Use the following command to run it on your host with the default port: 211 212.. code-block:: console 213 214 $ ssh -N -D 0.0.0.0:1080 localhost 215 216To connect to a proxy server that is not running under the same IP as the MQTT 217broker or uses a different port number, modify the following values: 218 219.. code-block:: c 220 221 #define SOCKS5_PROXY_ADDR SERVER_ADDR 222 #define SOCKS5_PROXY_PORT 1080 223 224MQTT logging backend 225==================== 226 227The sample can be configured to use an MQTT logging backend, which allows log 228messages from the application to be published to an MQTT broker. This feature 229uses the same MQTT client instance as the main sample application. 230 231The MQTT logging backend uses the :c:func:`log_backend_mqtt_client_set` API to 232register an MQTT client for publishing log messages. The backend only uses the 233client's :c:func:`mqtt_publish` function and does not manage the client's 234connection lifecycle - this remains the application's responsibility. 235 236To enable the MQTT logging backend in the sample, build it with 237``-DEXTRA_CONF_FILE=overlay-log-backend-mqtt.conf`` parameter. 238 239Key configuration options available: 240 241- :kconfig:option:`CONFIG_LOG_BACKEND_MQTT_TOPIC_DEFAULT`: Topic for publishing logs (default: "zephyr/logs") 242- :kconfig:option:`CONFIG_LOG_BACKEND_MQTT_QOS`: QoS level for log messages (default: 0) 243- :kconfig:option:`CONFIG_LOG_BACKEND_MQTT_RETAIN`: Whether to retain log messages (default: disabled) 244- :kconfig:option:`CONFIG_LOG_BACKEND_MQTT_MAX_MSG_SIZE`: Maximum log message size (default: 256 bytes) 245 246Running on cc3220sf_launchxl 247============================ 248 249Offloading on cc3220sf_launchxl also provides DHCP services, so the sample 250uses dynamic IP addresses on this board. 251 252By default, the sample is set up to connect to the broker at the address 253specified by SERVER_ADDR in config.h. If the broker is secured using TLS, users 254should enable TLS offloading, upload the server's certificate 255authority file in DER format to the device filesystem using TI Uniflash, 256and name it "ca_cert.der". 257 258In addition, TLS_SNI_HOSTNAME in main.c should be defined to match the 259Common Name (CN) in the certificate file in order for the TLS domain 260name verification to succeed. 261 262See the note on Provisioning and Fast Connect in :zephyr:board:`cc3220sf_launchxl`. 263 264The Secure Socket Offload section has information on programming the 265certificate to flash. 266 267Proceed to test as above. 268 269Sample output 270============= 271 272This is the output from the FRDM UART console, with: 273 274.. code-block:: cfg 275 276 CONFIG_NET_SAMPLE_APP_MAX_ITERATIONS=5 277 278.. code-block:: console 279 280 [dev/eth_mcux] [INF] eth_0_init: Enabled 100M full-duplex mode. 281 [dev/eth_mcux] [DBG] eth_0_init: MAC 00:04:9f:3e:1a:0a 282 [publisher:233] network_setup: 0 <OK> 283 [publisher:258] mqtt_init: 0 <OK> 284 [connect_cb:81] user_data: CONNECTED 285 [try_to_connect:212] mqtt_tx_connect: 0 <OK> 286 [publisher:276] try_to_connect: 0 <OK> 287 [publisher:285] mqtt_tx_pingreq: 0 <OK> 288 [publisher:290] mqtt_tx_publish: 0 <OK> 289 [publish_cb:149] <MQTT_PUBACK> packet id: 1888, user_data: PUBLISH 290 [publisher:295] mqtt_tx_publish: 0 <OK> 291 [publish_cb:149] <MQTT_PUBREC> packet id: 16356, user_data: PUBLISH 292 [publish_cb:149] <MQTT_PUBCOMP> packet id: 16356, user_data: PUBLISH 293 [publisher:300] mqtt_tx_publish: 0 <OK> 294 [publisher:285] mqtt_tx_pingreq: 0 <OK> 295 [publisher:290] mqtt_tx_publish: 0 <OK> 296 [publish_cb:149] <MQTT_PUBACK> packet id: 45861, user_data: PUBLISH 297 [publisher:295] mqtt_tx_publish: 0 <OK> 298 [publish_cb:149] <MQTT_PUBREC> packet id: 53870, user_data: PUBLISH 299 [publish_cb:149] <MQTT_PUBCOMP> packet id: 53870, user_data: PUBLISH 300 [publisher:300] mqtt_tx_publish: 0 <OK> 301 [publisher:285] mqtt_tx_pingreq: 0 <OK> 302 [publisher:290] mqtt_tx_publish: 0 <OK> 303 [publish_cb:149] <MQTT_PUBACK> packet id: 60144, user_data: PUBLISH 304 [publisher:295] mqtt_tx_publish: 0 <OK> 305 [publish_cb:149] <MQTT_PUBREC> packet id: 6561, user_data: PUBLISH 306 [publish_cb:149] <MQTT_PUBCOMP> packet id: 6561, user_data: PUBLISH 307 [publisher:300] mqtt_tx_publish: 0 <OK> 308 [publisher:285] mqtt_tx_pingreq: 0 <OK> 309 [publisher:290] mqtt_tx_publish: 0 <OK> 310 [publish_cb:149] <MQTT_PUBACK> packet id: 38355, user_data: PUBLISH 311 [publisher:295] mqtt_tx_publish: 0 <OK> 312 [publish_cb:149] <MQTT_PUBREC> packet id: 60656, user_data: PUBLISH 313 [publish_cb:149] <MQTT_PUBCOMP> packet id: 60656, user_data: PUBLISH 314 [publisher:300] mqtt_tx_publish: 0 <OK> 315 [publisher:285] mqtt_tx_pingreq: 0 <OK> 316 [publisher:290] mqtt_tx_publish: 0 <OK> 317 [publish_cb:149] <MQTT_PUBACK> packet id: 28420, user_data: PUBLISH 318 [publisher:295] mqtt_tx_publish: 0 <OK> 319 [publish_cb:149] <MQTT_PUBREC> packet id: 49829, user_data: PUBLISH 320 [publish_cb:149] <MQTT_PUBCOMP> packet id: 49829, user_data: PUBLISH 321 [publisher:300] mqtt_tx_publish: 0 <OK> 322 [disconnect_cb:101] user_data: DISCONNECTED 323 [publisher:304] mqtt_tx_disconnect: 0 <OK> 324 325 Bye! 326 327The line: 328 329.. code-block:: console 330 331 [try_to_connect:220] mqtt_connect: -5 <ERROR> 332 333means that an error was detected and a new connect message will be sent. 334 335The MQTT API is asynchronous, so messages are displayed as the callbacks are 336executed. 337 338This is the information that the subscriber will receive: 339 340.. code-block:: console 341 342 $ mosquitto_sub -t sensors 343 DOORS:OPEN_QoS0 344 DOORS:OPEN_QoS1 345 DOORS:OPEN_QoS2 346 DOORS:OPEN_QoS0 347 DOORS:OPEN_QoS1 348 DOORS:OPEN_QoS2 349 DOORS:OPEN_QoS0 350 DOORS:OPEN_QoS1 351 DOORS:OPEN_QoS2 352 DOORS:OPEN_QoS0 353 DOORS:OPEN_QoS1 354 DOORS:OPEN_QoS2 355 DOORS:OPEN_QoS0 356 DOORS:OPEN_QoS1 357 DOORS:OPEN_QoS2 358 359This is the output from the MQTT broker: 360 361.. code-block:: console 362 363 $ sudo mosquitto -v 364 1485663791: mosquitto version 1.3.4 (build date 2014-08-17 00:14:52-0300) starting 365 1485663791: Using default config. 366 1485663791: Opening ipv4 listen socket on port 1883. 367 1485663791: Opening ipv6 listen socket on port 1883. 368 1485663797: New connection from 192.168.1.101 on port 1883. 369 1485663797: New client connected from 192.168.1.101 as zephyr_publisher (c1, k0). 370 1485663797: Sending CONNACK to zephyr_publisher (0) 371 1485663798: Received PINGREQ from zephyr_publisher 372 1485663798: Sending PINGRESP to zephyr_publisher 373 1485663798: Received PUBLISH from zephyr_publisher (d0, q0, r0, m0, 'sensors', ... (15 bytes)) 374 1485663799: Received PUBLISH from zephyr_publisher (d0, q1, r0, m1888, 'sensors', ... (15 bytes)) 375 1485663799: Sending PUBACK to zephyr_publisher (Mid: 1888) 376 1485663799: Received PUBLISH from zephyr_publisher (d0, q2, r0, m16356, 'sensors', ... (15 bytes)) 377 1485663799: Sending PUBREC to zephyr_publisher (Mid: 16356) 378 1485663799: Received PUBREL from zephyr_publisher (Mid: 16356) 379 1485663799: Sending PUBCOMP to zephyr_publisher (Mid: 16356) 380 1485663800: Received PINGREQ from zephyr_publisher 381 1485663800: Sending PINGRESP to zephyr_publisher 382 1485663800: Received PUBLISH from zephyr_publisher (d0, q0, r0, m0, 'sensors', ... (15 bytes)) 383 1485663801: Received PUBLISH from zephyr_publisher (d0, q1, r0, m45861, 'sensors', ... (15 bytes)) 384 1485663801: Sending PUBACK to zephyr_publisher (Mid: 45861) 385 1485663801: Received PUBLISH from zephyr_publisher (d0, q2, r0, m53870, 'sensors', ... (15 bytes)) 386 1485663801: Sending PUBREC to zephyr_publisher (Mid: 53870) 387 1485663801: Received PUBREL from zephyr_publisher (Mid: 53870) 388 1485663801: Sending PUBCOMP to zephyr_publisher (Mid: 53870) 389 1485663802: Received PINGREQ from zephyr_publisher 390 1485663802: Sending PINGRESP to zephyr_publisher 391 1485663802: Received PUBLISH from zephyr_publisher (d0, q0, r0, m0, 'sensors', ... (15 bytes)) 392 1485663803: Received PUBLISH from zephyr_publisher (d0, q1, r0, m60144, 'sensors', ... (15 bytes)) 393 1485663803: Sending PUBACK to zephyr_publisher (Mid: 60144) 394 1485663803: Received PUBLISH from zephyr_publisher (d0, q2, r0, m6561, 'sensors', ... (15 bytes)) 395 1485663803: Sending PUBREC to zephyr_publisher (Mid: 6561) 396 1485663803: Received PUBREL from zephyr_publisher (Mid: 6561) 397 1485663803: Sending PUBCOMP to zephyr_publisher (Mid: 6561) 398 1485663804: Received PINGREQ from zephyr_publisher 399 1485663804: Sending PINGRESP to zephyr_publisher 400 1485663804: Received PUBLISH from zephyr_publisher (d0, q0, r0, m0, 'sensors', ... (15 bytes)) 401 1485663805: Received PUBLISH from zephyr_publisher (d0, q1, r0, m38355, 'sensors', ... (15 bytes)) 402 1485663805: Sending PUBACK to zephyr_publisher (Mid: 38355) 403 1485663805: Received PUBLISH from zephyr_publisher (d0, q2, r0, m60656, 'sensors', ... (15 bytes)) 404 1485663805: Sending PUBREC to zephyr_publisher (Mid: 60656) 405 1485663805: Received PUBREL from zephyr_publisher (Mid: 60656) 406 1485663805: Sending PUBCOMP to zephyr_publisher (Mid: 60656) 407 1485663806: Received PINGREQ from zephyr_publisher 408 1485663806: Sending PINGRESP to zephyr_publisher 409 1485663806: Received PUBLISH from zephyr_publisher (d0, q0, r0, m0, 'sensors', ... (15 bytes)) 410 1485663807: Received PUBLISH from zephyr_publisher (d0, q1, r0, m28420, 'sensors', ... (15 bytes)) 411 1485663807: Sending PUBACK to zephyr_publisher (Mid: 28420) 412 1485663807: Received PUBLISH from zephyr_publisher (d0, q2, r0, m49829, 'sensors', ... (15 bytes)) 413 1485663807: Sending PUBREC to zephyr_publisher (Mid: 49829) 414 1485663807: Received PUBREL from zephyr_publisher (Mid: 49829) 415 1485663807: Sending PUBCOMP to zephyr_publisher (Mid: 49829) 416 1485663808: Received DISCONNECT from zephyr_publisher 417 418Wi-Fi 419===== 420 421The IPv4 Wi-Fi support can be enabled in the sample with 422:ref:`Wi-Fi snippet <snippet-wifi-ipv4>`. 423