1.. _mqtt_sn_socket_interface:
2
3MQTT-SN
4#######
5
6.. contents::
7    :local:
8    :depth: 2
9
10Overview
11********
12
13MQTT-SN is a variant of the well-known MQTT protocol - see :ref:`mqtt_socket_interface`.
14
15In contrast to MQTT, MQTT-SN does not require a TCP transport, but is designed to be used
16over any message-based transport. Originally, it was mainly created with ZigBee in mind,
17but others like Bluetooth, UDP or even a UART can be used just as well.
18
19Zephyr provides an MQTT-SN client library built on top of BSD sockets API. The
20library can be enabled with :kconfig:option:`CONFIG_MQTT_SN_LIB` Kconfig option
21and is configurable at a per-client basis, with support for MQTT-SN version
221.2. The Zephyr MQTT-SN implementation can be used with any message-based transport,
23but support for UDP is already built-in.
24
25MQTT-SN clients require an MQTT-SN gateway to connect to. These gateways translate between
26MQTT-SN and MQTT. The Eclipse Paho project offers an implementation of a MQTT-SN gateway, but
27others are available too.
28https://www.eclipse.org/paho/index.php?page=components/mqtt-sn-transparent-gateway/index.php
29
30The MQTT-SN spec v1.2 can be found here:
31https://www.oasis-open.org/committees/download.php/66091/MQTT-SN_spec_v1.2.pdf
32
33Sample usage
34************
35
36To create an MQTT-SN client, a client context structure and buffers need to be
37defined:
38
39.. code-block:: c
40
41   /* Buffers for MQTT client. */
42   static uint8_t rx_buffer[256];
43   static uint8_t tx_buffer[256];
44
45   /* MQTT-SN client context */
46   static struct mqtt_sn_client client;
47
48Multiple MQTT-SN client instances can be created in the application and managed
49independently. Additionally, a structure for the transport is needed as well.
50The library already comes with an example implementation for UDP.
51
52.. code-block:: c
53
54   /* MQTT Broker address information. */
55   static struct mqtt_sn_transport tp;
56
57The MQTT-SN library will inform clients about certain events using a callback.
58
59.. code-block:: c
60
61   static void evt_cb(struct mqtt_sn_client *client,
62                      const struct mqtt_sn_evt *evt)
63   {
64      switch(evt->type) {
65      {
66         /* Handle events here. */
67      }
68   }
69
70For a list of possible events, see :ref:`mqtt_sn_api_reference`.
71
72The client context structure needs to be initialized and set up before it can be
73used. An example configuration for UDP transport is shown below:
74
75.. code-block:: c
76
77   struct mqtt_sn_data client_id = MQTT_SN_DATA_STRING_LITERAL("ZEPHYR");
78   struct sockaddr_in gateway = {0};
79
80   uint8_t tx_buf[256];
81   uint8_t rx_buf[256];
82
83   mqtt_sn_transport_udp_init(&tp, (struct sockaddr*)&gateway, sizeof((gateway)));
84
85   mqtt_sn_client_init(&client, &client_id, &tp.tp, evt_cb, tx_buf, sizeof(tx_buf), rx_buf, sizeof(rx_buf));
86
87After the configuration is set up, the network address for the gateway to
88connect to must be defined. The MQTT-SN protocol offers functionality to
89discover gateways through an advertisement or a search mechanism. A user
90should do at least one of the following steps to define a Gateway for the library:
91
92* Call the :c:func:`mqtt_sn_add_gw` function to manually define a Gateway address.
93* Wait for an :c:enumerator:`MQTT_SN_EVT_ADVERTISE`.
94* Call the :c:func:`mqtt_sn_search` function and wait for an :c:enumerator:`MQTT_SN_EVT_GWINFO` callback.
95  Make sure to call the :c:func:`mqtt_sn_input` function periodically to process incoming messages.
96
97Example :c:func:`mqtt_sn_search` function call:
98
99.. code-block:: c
100
101	err = mqtt_sn_search(&mqtt_client, 1);
102	k_sleep(K_SECONDS(10));
103	err = mqtt_sn_input(&mqtt_client);
104	__ASSERT(err == 0, "mqtt_sn_search() failed %d", err);
105
106After the Gateway address has been defined or found, the MQTT-SN client can
107connect to the gateway. Call the :c:func:`mqtt_sn_connect` function, which will send a
108``CONNECT`` MQTT-SN message. The application should periodically call the :c:func:`mqtt_sn_input`
109function to process the response received. The application does not have to call
110:c:func:`mqtt_sn_input` if it knows that no data has been received (e.g. when using Bluetooth).
111Note that :c:func:`mqtt_sn_input` is a non-blocking function, if the transport struct contains a
112:c:func:`poll` compatible function pointer.
113If the connection was successful, :c:enumerator:`MQTT_SN_EVT_CONNECTED` will be notified to the
114application through the callback function.
115
116.. code-block:: c
117
118	err = mqtt_sn_connect(&client, false, true);
119	__ASSERT(err == 0, "mqtt_sn_connect() failed %d", err);
120
121	while (1) {
122		mqtt_sn_input(&client);
123		if (connected) {
124			mqtt_sn_publish(&client, MQTT_SN_QOS_0, &topic_p, false, &pubdata);
125		}
126		k_sleep(K_MSEC(500));
127	}
128
129In the above code snippet, the gateway is connected to before publishing messages.
130If the connection fails at the MQTT level or a timeout occurs, the connection will be aborted and
131an error returned.
132
133After the connection is established, an application needs to call :c:func:`mqtt_input`
134function periodically to process incoming data. Connection upkeep, on the other hand,
135is done automatically using a k_work item.
136If a MQTT message is received, an MQTT callback function will be called and an
137appropriate event notified.
138
139The connection can be closed by calling the :c:func:`mqtt_sn_disconnect` function. This
140has no effect on the transport, however. If you want to close the transport (e.g.
141the socket), call :c:func:`mqtt_sn_client_deinit`, which will deinit the transport as well.
142
143Zephyr provides sample code utilizing the MQTT-SN client API. See
144:zephyr:code-sample:`mqtt-sn-publisher` for more information.
145
146Deviations from the standard
147****************************
148
149Certain parts of the protocol are not yet supported in the library.
150
151* Pre-defined topic IDs
152* QoS -1 - it's most useful with predefined topics
153* Setting the will topic and message after the initial connect
154* Forwarder Encapsulation
155
156.. _mqtt_sn_api_reference:
157
158API Reference
159*************
160
161.. doxygengroup:: mqtt_sn_socket
162