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