|
1 | 1 | .. _mqtt_socket_interface:
|
2 | 2 |
|
3 | 3 | MQTT
|
4 |
| -##### |
| 4 | +#### |
5 | 5 |
|
6 | 6 | Overview
|
7 | 7 | ********
|
8 | 8 |
|
| 9 | +MQTT (Message Queuing Telemetry Transport) is an application layer protocol |
| 10 | +which works on top of the TCP/IP stack. It is a lightweight |
| 11 | +publish/subscribe messaging transport for machine-to-machine communication. |
| 12 | +For more information about the protocol itself, see http://mqtt.org/. |
| 13 | + |
| 14 | +Zephyr provides an MQTT client library built on top of BSD sockets API. The |
| 15 | +library is configurable at a per-client basis, with support for MQTT versions |
| 16 | +3.1.0 and 3.1.1. The Zephyr MQTT implementation can be used with either plain |
| 17 | +sockets communicating over TCP, or with secure sockets communicating over |
| 18 | +TLS. See :ref:`bsd_sockets_interface` for more information about Zephyr sockets. |
| 19 | + |
| 20 | +MQTT clients require an MQTT server to connect to. Such a server, called an MQTT Broker, |
| 21 | +is responsible for managing client subscriptions and distributing messages |
| 22 | +published by clients. There are many implementations of MQTT brokers, one of them |
| 23 | +being Eclipse Mosquitto. See https://mosquitto.org/ for more information about |
| 24 | +the Eclipse Mosquitto project. |
| 25 | + |
| 26 | +Sample usage |
| 27 | +************ |
| 28 | + |
| 29 | +To create an MQTT client, a client context structure and buffers need to be |
| 30 | +defined: |
| 31 | + |
| 32 | +.. code-block:: c |
| 33 | +
|
| 34 | + /* Buffers for MQTT client. */ |
| 35 | + static u8_t rx_buffer[256]; |
| 36 | + static u8_t tx_buffer[256]; |
| 37 | +
|
| 38 | + /* MQTT client context */ |
| 39 | + static struct mqtt_client client_ctx; |
| 40 | +
|
| 41 | +Multiple MQTT client instances can be created in the application and managed |
| 42 | +independently. Additionally, a structure for MQTT Broker address information |
| 43 | +is needed. This structure must be accessible throughout the lifespan |
| 44 | +of the MQTT client and can be shared among MQTT clients: |
| 45 | + |
| 46 | +.. code-block:: c |
| 47 | +
|
| 48 | + /* MQTT Broker address information. */ |
| 49 | + static struct sockaddr_storage broker; |
| 50 | +
|
| 51 | +An MQTT client library will notify MQTT events to the application through a |
| 52 | +callback function created to handle respective events: |
| 53 | + |
| 54 | +.. code-block:: c |
| 55 | +
|
| 56 | + void mqtt_evt_handler(struct mqtt_client *client, |
| 57 | + const struct mqtt_evt *evt) |
| 58 | + { |
| 59 | + switch (evt->type) { |
| 60 | + /* Handle events here. */ |
| 61 | + } |
| 62 | + } |
| 63 | +
|
| 64 | +For a list of possible events, see :ref:`mqtt_api_reference`. |
| 65 | + |
| 66 | +The client context structure needs to be initialized and set up before it can be |
| 67 | +used. An example configuration for TCP transport is shown below: |
| 68 | + |
| 69 | +.. code-block:: c |
| 70 | +
|
| 71 | + mqtt_client_init(&client_ctx); |
| 72 | +
|
| 73 | + /* MQTT client configuration */ |
| 74 | + client_ctx.broker = &broker; |
| 75 | + client_ctx.evt_cb = mqtt_evt_handler; |
| 76 | + client_ctx.client_id.utf8 = (u8_t *)"zephyr_mqtt_client"; |
| 77 | + client_ctx.client_id.size = sizeof("zephyr_mqtt_client") - 1; |
| 78 | + client_ctx.password = NULL; |
| 79 | + client_ctx.user_name = NULL; |
| 80 | + client_ctx.protocol_version = MQTT_VERSION_3_1_1; |
| 81 | + client_ctx.transport.type = MQTT_TRANSPORT_NON_SECURE; |
| 82 | +
|
| 83 | + /* MQTT buffers configuration */ |
| 84 | + client_ctx.rx_buf = rx_buffer; |
| 85 | + client_ctx.rx_buf_size = sizeof(rx_buffer); |
| 86 | + client_ctx.tx_buf = tx_buffer; |
| 87 | + client_ctx.tx_buf_size = sizeof(tx_buffer); |
| 88 | +
|
| 89 | +After the configuration is set up, the MQTT client can connect to the MQTT broker. |
| 90 | +Call the ``mqtt_connect`` function, which will create the appropriate socket, |
| 91 | +establish a TCP/TLS connection, and send an `MQTT CONNECT` message. |
| 92 | +When notified, the application should call the ``mqtt_input`` function to process |
| 93 | +the response received. Note, that ``mqtt_input`` is a non-blocking function, |
| 94 | +therefore the application should use socket ``poll`` to wait for the response. |
| 95 | +If the connection was successful, ``MQTT_EVT_CONNACK`` will be notified to the |
| 96 | +application through the callback function. |
| 97 | + |
| 98 | +.. code-block:: c |
| 99 | +
|
| 100 | + rc = mqtt_connect(&client_ctx); |
| 101 | + if (rc != 0) { |
| 102 | + return rc; |
| 103 | + } |
| 104 | +
|
| 105 | + fds[0].fd = client_ctx.transport.tcp.sock; |
| 106 | + fds[0].events = ZSOCK_POLLIN; |
| 107 | + poll(fds, 1, K_MSEC(5000)); |
| 108 | +
|
| 109 | + mqtt_input(&client_ctx); |
| 110 | +
|
| 111 | + if (!connected) { |
| 112 | + mqtt_abort(&client_ctx); |
| 113 | + } |
| 114 | +
|
| 115 | +In the above code snippet, the MQTT callback function should set the ``connected`` |
| 116 | +flag upon a successful connection. If the connection fails at the MQTT level |
| 117 | +or a timeout occurs, the connection will be aborted, and the underlying socket |
| 118 | +closed. |
| 119 | + |
| 120 | +After the connection is established, an application needs to call ``mqtt_input`` |
| 121 | +and ``mqtt_live`` functions periodically to process incoming data and upkeep |
| 122 | +the connection. If an MQTT message is received, an MQTT callback function will |
| 123 | +be called and an appropriate event notified. |
| 124 | + |
| 125 | +The connection can be closed by calling the ``mqtt_disconnect`` function. |
| 126 | + |
| 127 | +Zephyr provides sample code utilizing the MQTT client API. See |
| 128 | +:ref:`mqtt-publisher-sample` for more information. |
| 129 | + |
| 130 | +Using MQTT with TLS |
| 131 | +******************* |
| 132 | + |
| 133 | +The Zephyr MQTT library can be used with TLS transport for secure communication |
| 134 | +by selecting a secure transport type (``MQTT_TRANSPORT_SECURE``) and some |
| 135 | +additional configuration information: |
| 136 | + |
| 137 | +.. code-block:: c |
| 138 | +
|
| 139 | + client_ctx.transport.type = MQTT_TRANSPORT_SECURE; |
| 140 | +
|
| 141 | + struct mqtt_sec_config *tls_config = &client_ctx.transport.tls.config; |
| 142 | +
|
| 143 | + tls_config->peer_verify = 2; |
| 144 | + tls_config->cipher_list = NULL; |
| 145 | + tls_config->sec_tag_list = m_sec_tags; |
| 146 | + tls_config->sec_tag_count = ARRAY_SIZE(m_sec_tags); |
| 147 | + tls_config->hostname = MQTT_BROKER_HOSTNAME; |
| 148 | +
|
| 149 | +In this sample code, the ``m_sec_tags`` array holds a list of tags, referencing TLS |
| 150 | +credentials that the MQTT library should use for authentication. We do not specify |
| 151 | +``cipher_list``, to allow the use of all cipher suites available in the system. |
| 152 | +We set ``hostname`` field to broker hostname, which is required for server |
| 153 | +authentication. Finally, we enforce peer certificate verification by setting |
| 154 | +the ``peer_verify`` field. |
| 155 | + |
| 156 | +Note, that TLS credentials referenced by the ``m_sec_tags`` array must be |
| 157 | +registered in the system first. For more information on how to do that, refer |
| 158 | +to :ref:`secure sockets documentation <secure_sockets_interface>`. |
| 159 | + |
| 160 | +An example of how to use TLS with MQTT is also present in |
| 161 | +:ref:`mqtt-publisher-sample`. |
| 162 | + |
| 163 | +.. _mqtt_api_reference: |
9 | 164 |
|
10 | 165 | API Reference
|
11 | 166 | *************
|
|
0 commit comments