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