You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
173 lines
6.0 KiB
173 lines
6.0 KiB
.. _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 can be enabled with :kconfig:option:`CONFIG_MQTT_LIB` Kconfig option and |
|
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, 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 |
|
:zephyr:code-sample:`mqtt-publisher` 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 |
|
:zephyr:code-sample:`mqtt-publisher` sample application. |
|
|
|
.. _mqtt_api_reference: |
|
|
|
API Reference |
|
************* |
|
|
|
.. doxygengroup:: mqtt_socket
|
|
|