LCOV - code coverage report
Current view: top level - zephyr/net - mqtt_sn.h Coverage Total Hit
Test: new.info Lines: 100.0 % 69 69
Test Date: 2025-10-20 12:20:01

            Line data    Source code
       1            1 : /*
       2              :  * Copyright (c) 2022 René Beckmann
       3              :  *
       4              :  * SPDX-License-Identifier: Apache-2.0
       5              :  */
       6              : 
       7              : /** @file mqtt_sn.h
       8              :  *
       9              :  * @brief MQTT-SN Client Implementation
      10              :  *
      11              :  * @details
      12              :  * MQTT-SN Client's Application interface is defined in this header.
      13              :  * Targets protocol version 1.2.
      14              :  *
      15              :  * @defgroup mqtt_sn_socket MQTT-SN Client library
      16              :  * @since 3.3
      17              :  * @version 0.1.0
      18              :  * @ingroup networking
      19              :  * @{
      20              :  */
      21              : 
      22              : #ifndef ZEPHYR_INCLUDE_NET_MQTT_SN_H_
      23              : #define ZEPHYR_INCLUDE_NET_MQTT_SN_H_
      24              : 
      25              : #include <stddef.h>
      26              : 
      27              : #include <zephyr/net_buf.h>
      28              : #include <zephyr/types.h>
      29              : 
      30              : #include <sys/types.h>
      31              : 
      32              : #ifdef CONFIG_MQTT_SN_TRANSPORT_UDP
      33              : #include <zephyr/net/net_ip.h>
      34              : #endif
      35              : 
      36              : #ifdef __cplusplus
      37              : extern "C" {
      38              : #endif
      39              : 
      40              : /**
      41              :  * Quality of Service. QoS 0-2 work the same as basic MQTT, QoS -1 is an MQTT-SN addition.
      42              :  * QOS -1 is not supported yet.
      43              :  */
      44            1 : enum mqtt_sn_qos {
      45              :         MQTT_SN_QOS_0, /**< QOS 0 */
      46              :         MQTT_SN_QOS_1, /**< QOS 1 */
      47              :         MQTT_SN_QOS_2, /**< QOS 2 */
      48              :         MQTT_SN_QOS_M1 /**< QOS -1 */
      49              : };
      50              : 
      51              : /**
      52              :  * MQTT-SN topic types.
      53              :  */
      54            1 : enum mqtt_sn_topic_type {
      55              :         /**
      56              :          * Normal topic.
      57              :          * It allows usage of any valid UTF-8 string as a topic name.
      58              :          */
      59              :         MQTT_SN_TOPIC_TYPE_NORMAL,
      60              :         /**
      61              :          * Pre-defined topic.
      62              :          * It allows usage of a two-byte identifier representing a topic name for
      63              :          * which the corresponding topic name is known in advance by both the client
      64              :          * and the gateway/server.
      65              :          */
      66              :         MQTT_SN_TOPIC_TYPE_PREDEF,
      67              :         /**
      68              :          * Short topic.
      69              :          * It allows usage of a two-byte string as a topic name.
      70              :          */
      71              :         MQTT_SN_TOPIC_TYPE_SHORT
      72              : };
      73              : 
      74              : /**
      75              :  * MQTT-SN return codes.
      76              :  */
      77            1 : enum mqtt_sn_return_code {
      78              :         MQTT_SN_CODE_ACCEPTED = 0x00,            /**< Accepted */
      79              :         MQTT_SN_CODE_REJECTED_CONGESTION = 0x01, /**< Rejected: congestion */
      80              :         MQTT_SN_CODE_REJECTED_TOPIC_ID = 0x02,   /**< Rejected: Invalid Topic ID */
      81              :         MQTT_SN_CODE_REJECTED_NOTSUP = 0x03,     /**< Rejected: Not Supported */
      82              : };
      83              : 
      84              : /** @brief Abstracts memory buffers. */
      85            1 : struct mqtt_sn_data {
      86            1 :         const uint8_t *data; /**< Pointer to data. */
      87            1 :         size_t size;         /**< Size of data, in bytes. */
      88              : };
      89              : 
      90              : /**
      91              :  * @brief Initialize memory buffer from C literal string.
      92              :  *
      93              :  * Use it as follows:
      94              :  *
      95              :  * struct mqtt_sn_data topic = MQTT_SN_DATA_STRING_LITERAL("/zephyr");
      96              :  *
      97              :  * @param[in] literal Literal string from which to generate mqtt_sn_data object.
      98              :  */
      99            1 : #define MQTT_SN_DATA_STRING_LITERAL(literal) ((struct mqtt_sn_data){literal, sizeof(literal) - 1})
     100              : 
     101              : /**
     102              :  * @brief Initialize memory buffer from single bytes.
     103              :  *
     104              :  * Use it as follows:
     105              :  *
     106              :  * struct mqtt_sn_data data = MQTT_SN_DATA_BYTES(0x13, 0x37);
     107              :  */
     108            1 : #define MQTT_SN_DATA_BYTES(...)                                                                    \
     109              :         ((struct mqtt_sn_data){(uint8_t[]){__VA_ARGS__}, sizeof((uint8_t[]){__VA_ARGS__})})
     110              : 
     111              : /**
     112              :  * Event types that can be emitted by the library.
     113              :  */
     114            1 : enum mqtt_sn_evt_type {
     115              :         MQTT_SN_EVT_CONNECTED,    /**< Connected to a gateway */
     116              :         MQTT_SN_EVT_DISCONNECTED, /**< Disconnected */
     117              :         MQTT_SN_EVT_ASLEEP,       /**< Entered ASLEEP state */
     118              :         MQTT_SN_EVT_AWAKE,        /**< Entered AWAKE state */
     119              :         MQTT_SN_EVT_PUBLISH,      /**< Received a PUBLISH message */
     120              :         MQTT_SN_EVT_PINGRESP,     /**< Received a PINGRESP */
     121              :         MQTT_SN_EVT_ADVERTISE,    /**< Received a ADVERTISE */
     122              :         MQTT_SN_EVT_GWINFO,       /**< Received a GWINFO */
     123              :         MQTT_SN_EVT_SEARCHGW      /**< Received a SEARCHGW */
     124              : };
     125              : 
     126              : /**
     127              :  * Event metadata.
     128              :  */
     129            1 : union mqtt_sn_evt_param {
     130              :         /** Structure holding publish event details */
     131              :         struct {
     132              :                 /** The payload data associated with the event */
     133            1 :                 struct mqtt_sn_data data;
     134              :                 /** The type of topic for the event */
     135            1 :                 enum mqtt_sn_topic_type topic_type;
     136              :                 /** The identifier for the topic of the event */
     137            1 :                 uint16_t topic_id;
     138            1 :         } publish;
     139              : };
     140              : 
     141              : /**
     142              :  * MQTT-SN event structure to be handled by the event callback.
     143              :  */
     144            1 : struct mqtt_sn_evt {
     145              :         /** Event type */
     146            1 :         enum mqtt_sn_evt_type type;
     147              :         /** Event parameters */
     148            1 :         union mqtt_sn_evt_param param;
     149              : };
     150              : 
     151              : struct mqtt_sn_client;
     152              : 
     153              : /**
     154              :  * @brief Asynchronous event notification callback registered by the
     155              :  *        application.
     156              :  *
     157              :  * @param[in] client Identifies the client for which the event is notified.
     158              :  * @param[in] evt Event description along with result and associated
     159              :  *                parameters (if any).
     160              :  */
     161            1 : typedef void (*mqtt_sn_evt_cb_t)(struct mqtt_sn_client *client, const struct mqtt_sn_evt *evt);
     162              : 
     163              : /**
     164              :  * @brief Structure to describe an MQTT-SN transport.
     165              :  *
     166              :  * MQTT-SN does not require transports to be reliable or to hold a connection.
     167              :  * Transports just need to be frame-based, so you can use UDP, ZigBee, or even
     168              :  * a simple UART, given some kind of framing protocol is used.
     169              :  */
     170            1 : struct mqtt_sn_transport {
     171              :         /**
     172              :          * @brief Will be called once on client init to initialize the transport.
     173              :          *
     174              :          * Use this to open sockets or similar. May be NULL.
     175              :          */
     176            1 :         int (*init)(struct mqtt_sn_transport *transport);
     177              : 
     178              :         /**
     179              :          * @brief Will be called on client deinit
     180              :          *
     181              :          * Use this to close sockets or similar. May be NULL.
     182              :          */
     183            1 :         void (*deinit)(struct mqtt_sn_transport *transport);
     184              : 
     185              :         /**
     186              :          * @brief Will be called by the library when it wants to send a message.
     187              :          *
     188              :          * Implementations should follow sendto conventions with exceptions.
     189              :          * When dest_addr == NULL, message should be broadcast with addrlen being
     190              :          * the broadcast radius. This should also handle setting up/destroying
     191              :          * connections as required when the address changes.
     192              :          *
     193              :          * @return ENOERR on connection+transmission success, Negative values
     194              :          *              signal errors.
     195              :          */
     196            1 :         int (*sendto)(struct mqtt_sn_client *client, void *buf, size_t sz, const void *dest_addr,
     197              :                       size_t addrlen);
     198              : 
     199              :         /**
     200              :          * @brief Will be called by the library when it wants to receive a message.
     201              :          *
     202              :          * Implementations should follow recvfrom conventions with the exception
     203              :          * of a NULL src_addr being a broadcast message.
     204              :          */
     205            1 :         ssize_t (*recvfrom)(struct mqtt_sn_client *client, void *rx_buf, size_t rx_len,
     206              :                             void *src_addr, size_t *addrlen);
     207              : 
     208              :         /**
     209              :          * @brief Check if incoming data is available.
     210              :          *
     211              :          * If poll() returns a positive number, recv must not block.
     212              :          *
     213              :          * May be NULL, but recv should not block then either.
     214              :          *
     215              :          * @return Positive number if data is available, or zero if there is none.
     216              :          * Negative values signal errors.
     217              :          */
     218            1 :         int (*poll)(struct mqtt_sn_client *client);
     219              : };
     220              : 
     221              : #ifdef CONFIG_MQTT_SN_TRANSPORT_UDP
     222              : /**
     223              :  * Transport struct for UDP based transport.
     224              :  */
     225              : struct mqtt_sn_transport_udp {
     226              :         /** Parent struct */
     227              :         struct mqtt_sn_transport tp;
     228              : 
     229              :         /** Socket FD */
     230              :         int sock;
     231              : 
     232              :         /** Address of broadcasts */
     233              :         struct sockaddr bcaddr;
     234              :         socklen_t bcaddrlen;
     235              : };
     236              : 
     237              : #define UDP_TRANSPORT(transport) CONTAINER_OF(transport, struct mqtt_sn_transport_udp, tp)
     238              : 
     239              : /**
     240              :  * @brief Initialize the UDP transport.
     241              :  *
     242              :  * @param[in] udp The transport to be initialized
     243              :  * @param[in] gwaddr Pre-initialized gateway address
     244              :  * @param[in] addrlen Size of the gwaddr structure.
     245              :  */
     246              : int mqtt_sn_transport_udp_init(struct mqtt_sn_transport_udp *udp, struct sockaddr *gwaddr,
     247              :                                socklen_t addrlen);
     248              : #endif
     249              : 
     250              : /**
     251              :  * Structure for storing will update state.
     252              :  */
     253            1 : struct mqtt_sn_will_update {
     254              :         /** An update message needs to be send */
     255            1 :         bool in_progress;
     256              : 
     257              :         /** Number of retries for failed update attempts */
     258            1 :         uint8_t retries;
     259              : 
     260              :         /** Timestamp of the last update attempt */
     261            1 :         int64_t last_attempt;
     262              : };
     263              : 
     264              : /**
     265              :  * Structure describing an MQTT-SN client.
     266              :  */
     267            1 : struct mqtt_sn_client {
     268              :         /** 1-23 character unique client ID */
     269            1 :         struct mqtt_sn_data client_id;
     270              : 
     271              :         /** Topic for Will message.
     272              :          * Must be initialized before connecting with will=true
     273              :          */
     274            1 :         struct mqtt_sn_data will_topic;
     275              : 
     276              :         /** Will message.
     277              :          * Must be initialized before connecting with will=true
     278              :          */
     279            1 :         struct mqtt_sn_data will_msg;
     280              : 
     281              :         /** Quality of Service for the Will message */
     282            1 :         enum mqtt_sn_qos will_qos;
     283              : 
     284              :         /** Flag indicating if the will message should be retained by the broker */
     285            1 :         bool will_retain;
     286              : 
     287              :         /** Underlying transport to be used by the client */
     288            1 :         struct mqtt_sn_transport *transport;
     289              : 
     290              :         /** Buffer for outgoing data */
     291            1 :         struct net_buf_simple tx;
     292              : 
     293              :         /** Buffer for incoming data */
     294            1 :         struct net_buf_simple rx;
     295              : 
     296              :         /** Buffer for incoming data sender address */
     297            1 :         struct net_buf_simple rx_addr;
     298              : 
     299              :         /** Event callback */
     300            1 :         mqtt_sn_evt_cb_t evt_cb;
     301              : 
     302              :         /** Message ID for the next message to be sent */
     303            1 :         uint16_t next_msg_id;
     304              : 
     305              :         /** List of pending publish messages */
     306            1 :         sys_slist_t publish;
     307              : 
     308              :         /** List of registered topics */
     309            1 :         sys_slist_t topic;
     310              : 
     311              :         /** List of found gateways */
     312            1 :         sys_slist_t gateway;
     313              : 
     314              :         /** Current state of the MQTT-SN client */
     315            1 :         int state;
     316              : 
     317              :         /** Timestamp of the last ping request */
     318            1 :         int64_t last_ping;
     319              : 
     320              :         /** Number of retries for failed ping attempts */
     321            1 :         uint8_t ping_retries;
     322              : 
     323              :         /** Timestamp of the next SEARCHGW transmission */
     324            1 :         int64_t ts_searchgw;
     325              : 
     326              :         /** Timestamp of the next GWINFO transmission */
     327            1 :         int64_t ts_gwinfo;
     328              : 
     329              :         /** Radius of the next GWINFO transmission */
     330            1 :         int64_t radius_gwinfo;
     331              : 
     332              :         /** State for will topic updates */
     333            1 :         struct mqtt_sn_will_update will_topic_update;
     334              : 
     335              :         /** State for will message updates */
     336            1 :         struct mqtt_sn_will_update will_message_update;
     337              : 
     338              :         /** Delayable work structure for processing MQTT-SN events */
     339            1 :         struct k_work_delayable process_work;
     340              : };
     341              : 
     342              : /**
     343              :  * @brief Initialize a client.
     344              :  *
     345              :  * @param client        The MQTT-SN client to initialize.
     346              :  * @param client_id     The ID to be used by the client.
     347              :  * @param transport     The transport to be used by the client.
     348              :  * @param evt_cb        The event callback function for the client.
     349              :  * @param tx            Pointer to the transmit buffer.
     350              :  * @param txsz          Size of the transmit buffer.
     351              :  * @param rx            Pointer to the receive buffer.
     352              :  * @param rxsz          Size of the receive buffer.
     353              :  *
     354              :  * @return 0 or a negative error code (errno.h) indicating reason of failure.
     355              :  */
     356            1 : int mqtt_sn_client_init(struct mqtt_sn_client *client, const struct mqtt_sn_data *client_id,
     357              :                         struct mqtt_sn_transport *transport, mqtt_sn_evt_cb_t evt_cb, void *tx,
     358              :                         size_t txsz, void *rx, size_t rxsz);
     359              : 
     360              : /**
     361              :  * @brief Deinitialize the client.
     362              :  *
     363              :  * This removes all topics and publishes, and also de-inits the transport.
     364              :  *
     365              :  * @param client        The MQTT-SN client to deinitialize.
     366              :  */
     367            1 : void mqtt_sn_client_deinit(struct mqtt_sn_client *client);
     368              : 
     369              : /**
     370              :  * @brief Manually add a Gateway, bypasing the normal search process.
     371              :  *
     372              :  * This function manually creates a gateway that is stored internal to the library.
     373              :  *
     374              :  * @param client      The MQTT-SN client to connect.
     375              :  * @param gw_id       Single byte Gateway Identifier
     376              :  * @param gw_addr     Address data structure to be used by the transport layer.
     377              :  *
     378              :  * @return 0 or a negative error code (errno.h) indicating reason of failure.
     379              :  */
     380            1 : int mqtt_sn_add_gw(struct mqtt_sn_client *client, uint8_t gw_id, struct mqtt_sn_data gw_addr);
     381              : 
     382              : /**
     383              :  * @brief Initiate the MQTT-SN GW Search process.
     384              :  *
     385              :  * @param client     The MQTT-SN client to connect.
     386              :  * @param radius     Broadcast radius for the search message.
     387              :  *
     388              :  * @return 0 or a negative error code (errno.h) indicating reason of failure.
     389              :  */
     390            1 : int mqtt_sn_search(struct mqtt_sn_client *client, uint8_t radius);
     391              : 
     392              : /**
     393              :  * @brief Connect the client.
     394              :  *
     395              :  * @param client            The MQTT-SN client to connect.
     396              :  * @param will              Flag indicating if a Will message should be sent.
     397              :  * @param clean_session     Flag indicating if a clean session should be started.
     398              :  *
     399              :  * @return 0 or a negative error code (errno.h) indicating reason of failure.
     400              :  */
     401            1 : int mqtt_sn_connect(struct mqtt_sn_client *client, bool will, bool clean_session);
     402              : 
     403              : /**
     404              :  * @brief Disconnect the client.
     405              :  *
     406              :  * @param client            The MQTT-SN client to disconnect.
     407              :  *
     408              :  * @return 0 or a negative error code (errno.h) indicating reason of failure.
     409              :  */
     410            1 : int mqtt_sn_disconnect(struct mqtt_sn_client *client);
     411              : 
     412              : /**
     413              :  * @brief Set the client into sleep state.
     414              :  *
     415              :  * @param client            The MQTT-SN client to be put to sleep.
     416              :  * @param duration          Sleep duration (in seconds).
     417              :  *
     418              :  * @return 0 on success, negative errno code on failure.
     419              :  */
     420            1 : int mqtt_sn_sleep(struct mqtt_sn_client *client, uint16_t duration);
     421              : 
     422              : /**
     423              :  * @brief Subscribe to a given topic.
     424              :  *
     425              :  * @param client            The MQTT-SN client that should subscribe.
     426              :  * @param qos               The desired quality of service for the subscription.
     427              :  * @param topic_name        The name of the topic to subscribe to.
     428              :  *
     429              :  * @return 0 or a negative error code (errno.h) indicating reason of failure.
     430              :  */
     431            1 : int mqtt_sn_subscribe(struct mqtt_sn_client *client, enum mqtt_sn_qos qos,
     432              :                       struct mqtt_sn_data *topic_name);
     433              : 
     434              : /**
     435              :  * @brief Unsubscribe from a topic.
     436              :  *
     437              :  * @param client            The MQTT-SN client that should unsubscribe.
     438              :  * @param qos               The quality of service used when subscribing.
     439              :  * @param topic_name        The name of the topic to unsubscribe from.
     440              :  *
     441              :  * @return 0 or a negative error code (errno.h) indicating reason of failure.
     442              :  */
     443            1 : int mqtt_sn_unsubscribe(struct mqtt_sn_client *client, enum mqtt_sn_qos qos,
     444              :                         struct mqtt_sn_data *topic_name);
     445              : 
     446              : /**
     447              :  * @brief Publish a value.
     448              :  *
     449              :  * If the topic is not yet registered with the gateway, the library takes care of it.
     450              :  *
     451              :  * @param client            The MQTT-SN client that should publish.
     452              :  * @param qos               The desired quality of service for the publish.
     453              :  * @param topic_name        The name of the topic to publish to.
     454              :  * @param retain            Flag indicating if the message should be retained by the broker.
     455              :  * @param data              The data to be published.
     456              :  *
     457              :  * @return 0 or a negative error code (errno.h) indicating reason of failure.
     458              :  */
     459            1 : int mqtt_sn_publish(struct mqtt_sn_client *client, enum mqtt_sn_qos qos,
     460              :                     struct mqtt_sn_data *topic_name, bool retain, struct mqtt_sn_data *data);
     461              : 
     462              : /**
     463              :  * @brief Check the transport for new incoming data.
     464              :  *
     465              :  * Call this function periodically, or if you have good reason to believe there is any data.
     466              :  * If the client's transport struct contains a poll-function, this function is non-blocking.
     467              :  *
     468              :  * @param client            The MQTT-SN client to check for incoming data.
     469              :  *
     470              :  * @return 0 or a negative error code (errno.h) indicating reason of failure.
     471              :  */
     472            1 : int mqtt_sn_input(struct mqtt_sn_client *client);
     473              : 
     474              : /**
     475              :  * @brief Get topic name by topic ID.
     476              :  *
     477              :  * @param[in] client The MQTT-SN client that uses this topic.
     478              :  * @param[in] id Topic identifier.
     479              :  * @param[out] topic_name Will be assigned to topic name.
     480              :  *
     481              :  * @return 0 on success, -ENOENT if topic ID doesn't exist,
     482              :  * or -EINVAL on invalid arguments.
     483              :  */
     484            1 : int mqtt_sn_get_topic_name(struct mqtt_sn_client *client, uint16_t id,
     485              :                            struct mqtt_sn_data *topic_name);
     486              : 
     487              : /**
     488              :  * @brief Predefine topic.
     489              :  *
     490              :  * Can be called before mqtt_sn_connect, because predefined topics are never cleared. If you call it
     491              :  * afterwards, it has to be called before calling mqtt_sn_input for the first time after the
     492              :  * connect, to prevent race conditions where incoming publications use predefined topics which were
     493              :  * not defined, yet.
     494              :  *
     495              :  * @param[in] client The MQTT-SN client to define the topic on.
     496              :  * @param[in] topic_id Topic identifier.
     497              :  * @param[in] topic_name The name of the topic.
     498              :  *
     499              :  * @return 0 or a negative error code (errno.h) indicating reason of failure.
     500              :  */
     501            1 : int mqtt_sn_predefine_topic(struct mqtt_sn_client *client, uint16_t topic_id,
     502              :                             struct mqtt_sn_data *topic_name);
     503              : 
     504              : /**
     505              :  * @brief Define a short topic.
     506              :  *
     507              :  * Can be called before mqtt_sn_connect, because short topics are never cleared.
     508              :  *
     509              :  * @param[in] client The MQTT-SN client to define the topic on.
     510              :  * @param[in] topic_name The name of the topic. Must be exactly 2 bytes long.
     511              :  *
     512              :  * @return 0 or a negative error code (errno.h) indicating reason of failure.
     513              :  */
     514            1 : int mqtt_sn_define_short_topic(struct mqtt_sn_client *client, struct mqtt_sn_data *topic_name);
     515              : 
     516              : /**
     517              :  * @brief Send a will topic update to the server.
     518              :  *
     519              :  * Call this to send the will topic stored in client->will_topic to the server.
     520              :  * Should be used if you changed the value after connecting. The variables
     521              :  * client->will_retain and client->will_qos will also be sent as part of the
     522              :  * update.
     523              :  *
     524              :  * @warning Since there is no message ID in the will topic update message,
     525              :  *          this can't be done without race conditions. Contribute to newer
     526              :  *          versions of the specification if you want this to be changed.
     527              :  *
     528              :  * @param[in] client The MQTT-SN client to use for sending the update.
     529              :  *
     530              :  * @return 0 or a negative error code (errno.h) indicating reason of failure.
     531              :  */
     532            1 : int mqtt_sn_update_will_topic(struct mqtt_sn_client *client);
     533              : 
     534              : /**
     535              :  * @brief Send a will message update to the server.
     536              :  *
     537              :  * Call this to send the will message stored in client->will_msg to the server.
     538              :  * Should be used if you changed the value after connecting.
     539              :  *
     540              :  * @warning Since there is no message ID in the will message update message,
     541              :  *          this can't be done without race conditions. Contribute to newer
     542              :  *          versions of the specification if you want this to be changed.
     543              :  *
     544              :  * @param[in] client The MQTT-SN client to use for sending the update.
     545              :  *
     546              :  * @return 0 or a negative error code (errno.h) indicating reason of failure.
     547              :  */
     548            1 : int mqtt_sn_update_will_message(struct mqtt_sn_client *client);
     549              : 
     550              : #ifdef __cplusplus
     551              : }
     552              : #endif
     553              : 
     554              : #endif /* ZEPHYR_INCLUDE_NET_MQTT_SN_H_ */
     555              : 
     556              : /**@}  */
        

Generated by: LCOV version 2.0-1