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