| .. _mqtt_socket_interface: |
| |
| MQTT |
| #### |
| |
| .. contents:: |
| :local: |
| :depth: 2 |
| |
| Overview |
| ******** |
| |
| MQTT (Message Queuing Telemetry Transport) is an application layer protocol |
| which works on top of the TCP/IP stack. It is a lightweight |
| publish/subscribe messaging transport for machine-to-machine communication. |
| For more information about the protocol itself, see http://mqtt.org/. |
| |
| Zephyr provides an MQTT client library built on top of BSD sockets API. The |
| library is configurable at a per-client basis, with support for MQTT versions |
| 3.1.0 and 3.1.1. The Zephyr MQTT implementation can be used with either plain |
| sockets communicating over TCP, or with secure sockets communicating over |
| TLS. See :ref:`bsd_sockets_interface` for more information about Zephyr sockets. |
| |
| MQTT clients require an MQTT server to connect to. Such a server, called an MQTT Broker, |
| is responsible for managing client subscriptions and distributing messages |
| published by clients. There are many implementations of MQTT brokers, one of them |
| being Eclipse Mosquitto. See https://mosquitto.org/ for more information about |
| the Eclipse Mosquitto project. |
| |
| Sample usage |
| ************ |
| |
| To create an MQTT client, a client context structure and buffers need to be |
| defined: |
| |
| .. code-block:: c |
| |
| /* Buffers for MQTT client. */ |
| static uint8_t rx_buffer[256]; |
| static uint8_t tx_buffer[256]; |
| |
| /* MQTT client context */ |
| static struct mqtt_client client_ctx; |
| |
| Multiple MQTT client instances can be created in the application and managed |
| independently. Additionally, a structure for MQTT Broker address information |
| is needed. This structure must be accessible throughout the lifespan |
| of the MQTT client and can be shared among MQTT clients: |
| |
| .. code-block:: c |
| |
| /* MQTT Broker address information. */ |
| static struct sockaddr_storage broker; |
| |
| An MQTT client library will notify MQTT events to the application through a |
| callback function created to handle respective events: |
| |
| .. code-block:: c |
| |
| void mqtt_evt_handler(struct mqtt_client *client, |
| const struct mqtt_evt *evt) |
| { |
| switch (evt->type) { |
| /* Handle events here. */ |
| } |
| } |
| |
| For a list of possible events, see :ref:`mqtt_api_reference`. |
| |
| The client context structure needs to be initialized and set up before it can be |
| used. An example configuration for TCP transport is shown below: |
| |
| .. code-block:: c |
| |
| mqtt_client_init(&client_ctx); |
| |
| /* MQTT client configuration */ |
| client_ctx.broker = &broker; |
| client_ctx.evt_cb = mqtt_evt_handler; |
| client_ctx.client_id.utf8 = (uint8_t *)"zephyr_mqtt_client"; |
| client_ctx.client_id.size = sizeof("zephyr_mqtt_client") - 1; |
| client_ctx.password = NULL; |
| client_ctx.user_name = NULL; |
| client_ctx.protocol_version = MQTT_VERSION_3_1_1; |
| client_ctx.transport.type = MQTT_TRANSPORT_NON_SECURE; |
| |
| /* MQTT buffers configuration */ |
| client_ctx.rx_buf = rx_buffer; |
| client_ctx.rx_buf_size = sizeof(rx_buffer); |
| client_ctx.tx_buf = tx_buffer; |
| client_ctx.tx_buf_size = sizeof(tx_buffer); |
| |
| After the configuration is set up, the MQTT client can connect to the MQTT broker. |
| Call the ``mqtt_connect`` function, which will create the appropriate socket, |
| establish a TCP/TLS connection, and send an ``MQTT CONNECT`` message. |
| When notified, the application should call the ``mqtt_input`` function to process |
| the response received. Note, that ``mqtt_input`` is a non-blocking function, |
| therefore the application should use socket ``poll`` to wait for the response. |
| If the connection was successful, ``MQTT_EVT_CONNACK`` will be notified to the |
| application through the callback function. |
| |
| .. code-block:: c |
| |
| rc = mqtt_connect(&client_ctx); |
| if (rc != 0) { |
| return rc; |
| } |
| |
| fds[0].fd = client_ctx.transport.tcp.sock; |
| fds[0].events = ZSOCK_POLLIN; |
| poll(fds, 1, K_MSEC(5000)); |
| |
| mqtt_input(&client_ctx); |
| |
| if (!connected) { |
| mqtt_abort(&client_ctx); |
| } |
| |
| In the above code snippet, the MQTT callback function should set the ``connected`` |
| flag upon a successful connection. If the connection fails at the MQTT level |
| or a timeout occurs, the connection will be aborted, and the underlying socket |
| closed. |
| |
| After the connection is established, an application needs to call ``mqtt_input`` |
| and ``mqtt_live`` functions periodically to process incoming data and upkeep |
| the connection. If an MQTT message is received, an MQTT callback function will |
| be called and an appropriate event notified. |
| |
| The connection can be closed by calling the ``mqtt_disconnect`` function. |
| |
| Zephyr provides sample code utilizing the MQTT client API. See |
| :ref:`mqtt-publisher-sample` for more information. |
| |
| Using MQTT with TLS |
| ******************* |
| |
| The Zephyr MQTT library can be used with TLS transport for secure communication |
| by selecting a secure transport type (``MQTT_TRANSPORT_SECURE``) and some |
| additional configuration information: |
| |
| .. code-block:: c |
| |
| client_ctx.transport.type = MQTT_TRANSPORT_SECURE; |
| |
| struct mqtt_sec_config *tls_config = &client_ctx.transport.tls.config; |
| |
| tls_config->peer_verify = TLS_PEER_VERIFY_REQUIRED; |
| tls_config->cipher_list = NULL; |
| tls_config->sec_tag_list = m_sec_tags; |
| tls_config->sec_tag_count = ARRAY_SIZE(m_sec_tags); |
| tls_config->hostname = MQTT_BROKER_HOSTNAME; |
| |
| In this sample code, the ``m_sec_tags`` array holds a list of tags, referencing TLS |
| credentials that the MQTT library should use for authentication. We do not specify |
| ``cipher_list``, to allow the use of all cipher suites available in the system. |
| We set ``hostname`` field to broker hostname, which is required for server |
| authentication. Finally, we enforce peer certificate verification by setting |
| the ``peer_verify`` field. |
| |
| Note, that TLS credentials referenced by the ``m_sec_tags`` array must be |
| registered in the system first. For more information on how to do that, refer |
| to :ref:`secure sockets documentation <secure_sockets_interface>`. |
| |
| An example of how to use TLS with MQTT is also present in |
| :ref:`mqtt-publisher-sample`. |
| |
| .. _mqtt_api_reference: |
| |
| API Reference |
| ************* |
| |
| .. doxygengroup:: mqtt_socket |