| /* |
| * Copyright (c) 2022 René Beckmann |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| /** @file mqtt_sn.h |
| * |
| * @defgroup mqtt_sn_socket MQTT-SN Client library |
| * @ingroup networking |
| * @{ |
| * @brief MQTT-SN Client Implementation |
| * |
| * @details |
| * MQTT-SN Client's Application interface is defined in this header. |
| * Targets protocol version 1.2. |
| * |
| */ |
| |
| #ifndef ZEPHYR_INCLUDE_NET_MQTT_SN_H_ |
| #define ZEPHYR_INCLUDE_NET_MQTT_SN_H_ |
| |
| #include <stddef.h> |
| |
| #include <zephyr/net/buf.h> |
| #include <zephyr/types.h> |
| |
| #include <sys/types.h> |
| |
| #ifdef CONFIG_MQTT_SN_TRANSPORT_UDP |
| #include <zephyr/net/net_ip.h> |
| #endif |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /** |
| * Quality of Service. QoS 0-2 work the same as basic MQTT, QoS -1 is an MQTT-SN addition. |
| * QOS -1 is not supported yet. |
| */ |
| enum mqtt_sn_qos { |
| MQTT_SN_QOS_0, /**< QOS 0 */ |
| MQTT_SN_QOS_1, /**< QOS 1 */ |
| MQTT_SN_QOS_2, /**< QOS 2 */ |
| MQTT_SN_QOS_M1 /**< QOS -1 */ |
| }; |
| |
| /** |
| * MQTT-SN topic types. |
| */ |
| enum mqtt_sn_topic_type { |
| /** |
| * Normal topic. |
| * It allows usage of any valid UTF-8 string as a topic name. |
| */ |
| MQTT_SN_TOPIC_TYPE_NORMAL, |
| /** |
| * Pre-defined topic. |
| * It allows usage of a two-byte identifier representing a topic name for |
| * which the corresponding topic name is known in advance by both the client |
| * and the gateway/server. |
| */ |
| MQTT_SN_TOPIC_TYPE_PREDEF, |
| /** |
| * Short topic. |
| * It allows usage of a two-byte string as a topic name. |
| */ |
| MQTT_SN_TOPIC_TYPE_SHORT |
| }; |
| |
| /** |
| * MQTT-SN return codes. |
| */ |
| enum mqtt_sn_return_code { |
| MQTT_SN_CODE_ACCEPTED = 0x00, /**< Accepted */ |
| MQTT_SN_CODE_REJECTED_CONGESTION = 0x01, /**< Rejected: congestion */ |
| MQTT_SN_CODE_REJECTED_TOPIC_ID = 0x02, /**< Rejected: Invalid Topic ID */ |
| MQTT_SN_CODE_REJECTED_NOTSUP = 0x03, /**< Rejected: Not Supported */ |
| }; |
| |
| /** @brief Abstracts memory buffers. */ |
| struct mqtt_sn_data { |
| const uint8_t *data; /**< Pointer to data. */ |
| uint16_t size; /**< Size of data, in bytes. */ |
| }; |
| |
| /** |
| * @brief Initialize memory buffer from C literal string. |
| * |
| * Use it as follows: |
| * |
| * struct mqtt_sn_data topic = MQTT_SN_DATA_STRING_LITERAL("/zephyr"); |
| * |
| * @param[in] literal Literal string from which to generate mqtt_sn_data object. |
| */ |
| #define MQTT_SN_DATA_STRING_LITERAL(literal) ((struct mqtt_sn_data){literal, sizeof(literal) - 1}) |
| |
| /** |
| * @brief Initialize memory buffer from single bytes. |
| * |
| * Use it as follows: |
| * |
| * struct mqtt_sn_data data = MQTT_SN_DATA_BYTES(0x13, 0x37); |
| */ |
| #define MQTT_SN_DATA_BYTES(...) \ |
| ((struct mqtt_sn_data) { (uint8_t[]){ __VA_ARGS__ }, sizeof((uint8_t[]){ __VA_ARGS__ })}) |
| |
| /** |
| * Event types that can be emitted by the library. |
| */ |
| enum mqtt_sn_evt_type { |
| MQTT_SN_EVT_CONNECTED, /**< Connected to a gateway */ |
| MQTT_SN_EVT_DISCONNECTED, /**< Disconnected */ |
| MQTT_SN_EVT_ASLEEP, /**< Entered ASLEEP state */ |
| MQTT_SN_EVT_AWAKE, /**< Entered AWAKE state */ |
| MQTT_SN_EVT_PUBLISH, /**< Received a PUBLISH message */ |
| MQTT_SN_EVT_PINGRESP /**< Received a PINGRESP */ |
| }; |
| |
| /** |
| * Event metadata. |
| */ |
| union mqtt_sn_evt_param { |
| /** Structure holding publish event details */ |
| struct { |
| /** The payload data associated with the event */ |
| struct mqtt_sn_data data; |
| /** The type of topic for the event */ |
| enum mqtt_sn_topic_type topic_type; |
| /** The identifier for the topic of the event */ |
| uint16_t topic_id; |
| } publish; |
| }; |
| |
| /** |
| * MQTT-SN event structure to be handled by the event callback. |
| */ |
| struct mqtt_sn_evt { |
| /** Event type */ |
| enum mqtt_sn_evt_type type; |
| /** Event parameters */ |
| union mqtt_sn_evt_param param; |
| }; |
| |
| struct mqtt_sn_client; |
| |
| /** |
| * @brief Asynchronous event notification callback registered by the |
| * application. |
| * |
| * @param[in] client Identifies the client for which the event is notified. |
| * @param[in] evt Event description along with result and associated |
| * parameters (if any). |
| */ |
| typedef void (*mqtt_sn_evt_cb_t)(struct mqtt_sn_client *client, const struct mqtt_sn_evt *evt); |
| |
| /** |
| * @brief Structure to describe an MQTT-SN transport. |
| * |
| * MQTT-SN does not require transports to be reliable or to hold a connection. |
| * Transports just need to be frame-based, so you can use UDP, ZigBee, or even |
| * a simple UART, given some kind of framing protocol is used. |
| */ |
| struct mqtt_sn_transport { |
| /** |
| * @brief Will be called once on client init to initialize the transport. |
| * |
| * Use this to open sockets or similar. May be NULL. |
| */ |
| int (*init)(struct mqtt_sn_transport *transport); |
| |
| /** |
| * @brief Will be called on client deinit |
| * |
| * Use this to close sockets or similar. May be NULL. |
| */ |
| void (*deinit)(struct mqtt_sn_transport *transport); |
| |
| /** |
| * Will be called by the library when it wants to send a message. |
| */ |
| int (*msg_send)(struct mqtt_sn_client *client, void *buf, size_t sz); |
| |
| /** |
| * @brief Will be called by the library when it wants to receive a message. |
| * |
| * Implementations should follow recv conventions. |
| */ |
| ssize_t (*recv)(struct mqtt_sn_client *client, void *buffer, size_t length); |
| |
| /** |
| * @brief Check if incoming data is available. |
| * |
| * If poll() returns a positive number, recv must not block. |
| * |
| * May be NULL, but recv should not block then either. |
| * |
| * @return Positive number if data is available, or zero if there is none. |
| * Negative values signal errors. |
| */ |
| int (*poll)(struct mqtt_sn_client *client); |
| }; |
| |
| #ifdef CONFIG_MQTT_SN_TRANSPORT_UDP |
| /** |
| * Transport struct for UDP based transport. |
| */ |
| struct mqtt_sn_transport_udp { |
| /** Parent struct */ |
| struct mqtt_sn_transport tp; |
| |
| /** Socket FD */ |
| int sock; |
| |
| /** Address of the gateway */ |
| struct sockaddr gwaddr; |
| socklen_t gwaddrlen; |
| }; |
| |
| #define UDP_TRANSPORT(transport) CONTAINER_OF(transport, struct mqtt_sn_transport_udp, tp) |
| |
| /** |
| * @brief Initialize the UDP transport. |
| * |
| * @param[in] udp The transport to be initialized |
| * @param[in] gwaddr Pre-initialized gateway address |
| * @param[in] addrlen Size of the gwaddr structure. |
| */ |
| int mqtt_sn_transport_udp_init(struct mqtt_sn_transport_udp *udp, struct sockaddr *gwaddr, |
| socklen_t addrlen); |
| #endif |
| |
| /** |
| * Structure describing an MQTT-SN client. |
| */ |
| struct mqtt_sn_client { |
| /** 1-23 character unique client ID */ |
| struct mqtt_sn_data client_id; |
| |
| /** Topic for Will message. |
| * Must be initialized before connecting with will=true |
| */ |
| struct mqtt_sn_data will_topic; |
| |
| /** Will message. |
| * Must be initialized before connecting with will=true |
| */ |
| struct mqtt_sn_data will_msg; |
| |
| /** Quality of Service for the Will message */ |
| enum mqtt_sn_qos will_qos; |
| |
| /** Flag indicating if the will message should be retained by the broker */ |
| bool will_retain; |
| |
| /** Underlying transport to be used by the client */ |
| struct mqtt_sn_transport *transport; |
| |
| /** Buffer for outgoing data */ |
| struct net_buf_simple tx; |
| |
| /** Buffer for incoming data */ |
| struct net_buf_simple rx; |
| |
| /** Event callback */ |
| mqtt_sn_evt_cb_t evt_cb; |
| |
| /** Message ID for the next message to be sent */ |
| uint16_t next_msg_id; |
| |
| /** List of pending publish messages */ |
| sys_slist_t publish; |
| |
| /** List of registered topics */ |
| sys_slist_t topic; |
| |
| /** Current state of the MQTT-SN client */ |
| int state; |
| |
| /** Timestamp of the last ping request */ |
| int64_t last_ping; |
| |
| /** Number of retries for failed ping attempts */ |
| uint8_t ping_retries; |
| |
| /** Delayable work structure for processing MQTT-SN events */ |
| struct k_work_delayable process_work; |
| }; |
| |
| /** |
| * @brief Initialize a client. |
| * |
| * @param client The MQTT-SN client to initialize. |
| * @param client_id The ID to be used by the client. |
| * @param transport The transport to be used by the client. |
| * @param evt_cb The event callback function for the client. |
| * @param tx Pointer to the transmit buffer. |
| * @param txsz Size of the transmit buffer. |
| * @param rx Pointer to the receive buffer. |
| * @param rxsz Size of the receive buffer. |
| * |
| * @return 0 or a negative error code (errno.h) indicating reason of failure. |
| */ |
| int mqtt_sn_client_init(struct mqtt_sn_client *client, const struct mqtt_sn_data *client_id, |
| struct mqtt_sn_transport *transport, mqtt_sn_evt_cb_t evt_cb, void *tx, |
| size_t txsz, void *rx, size_t rxsz); |
| |
| /** |
| * @brief Deinitialize the client. |
| * |
| * This removes all topics and publishes, and also de-inits the transport. |
| * |
| * @param client The MQTT-SN client to deinitialize. |
| */ |
| void mqtt_sn_client_deinit(struct mqtt_sn_client *client); |
| |
| /** |
| * @brief Connect the client. |
| * |
| * @param client The MQTT-SN client to connect. |
| * @param will Flag indicating if a Will message should be sent. |
| * @param clean_session Flag indicating if a clean session should be started. |
| * |
| * @return 0 or a negative error code (errno.h) indicating reason of failure. |
| */ |
| int mqtt_sn_connect(struct mqtt_sn_client *client, bool will, bool clean_session); |
| |
| /** |
| * @brief Disconnect the client. |
| * |
| * @param client The MQTT-SN client to disconnect. |
| * |
| * @return 0 or a negative error code (errno.h) indicating reason of failure. |
| */ |
| int mqtt_sn_disconnect(struct mqtt_sn_client *client); |
| |
| /** |
| * @brief Set the client into sleep state. |
| * |
| * @param client The MQTT-SN client to be put to sleep. |
| * @param duration Sleep duration (in seconds). |
| * |
| * @return 0 on success, negative errno code on failure. |
| */ |
| int mqtt_sn_sleep(struct mqtt_sn_client *client, uint16_t duration); |
| |
| /** |
| * @brief Subscribe to a given topic. |
| * |
| * @param client The MQTT-SN client that should subscribe. |
| * @param qos The desired quality of service for the subscription. |
| * @param topic_name The name of the topic to subscribe to. |
| * |
| * @return 0 or a negative error code (errno.h) indicating reason of failure. |
| */ |
| int mqtt_sn_subscribe(struct mqtt_sn_client *client, enum mqtt_sn_qos qos, |
| struct mqtt_sn_data *topic_name); |
| |
| /** |
| * @brief Unsubscribe from a topic. |
| * |
| * @param client The MQTT-SN client that should unsubscribe. |
| * @param qos The quality of service used when subscribing. |
| * @param topic_name The name of the topic to unsubscribe from. |
| * |
| * @return 0 or a negative error code (errno.h) indicating reason of failure. |
| */ |
| int mqtt_sn_unsubscribe(struct mqtt_sn_client *client, enum mqtt_sn_qos qos, |
| struct mqtt_sn_data *topic_name); |
| |
| /** |
| * @brief Publish a value. |
| * |
| * If the topic is not yet registered with the gateway, the library takes care of it. |
| * |
| * @param client The MQTT-SN client that should publish. |
| * @param qos The desired quality of service for the publish. |
| * @param topic_name The name of the topic to publish to. |
| * @param retain Flag indicating if the message should be retained by the broker. |
| * @param data The data to be published. |
| * |
| * @return 0 or a negative error code (errno.h) indicating reason of failure. |
| */ |
| int mqtt_sn_publish(struct mqtt_sn_client *client, enum mqtt_sn_qos qos, |
| struct mqtt_sn_data *topic_name, bool retain, struct mqtt_sn_data *data); |
| |
| /** |
| * @brief Check the transport for new incoming data. |
| * |
| * Call this function periodically, or if you have good reason to believe there is any data. |
| * If the client's transport struct contains a poll-function, this function is non-blocking. |
| * |
| * @param client The MQTT-SN client to check for incoming data. |
| * |
| * @return 0 or a negative error code (errno.h) indicating reason of failure. |
| */ |
| int mqtt_sn_input(struct mqtt_sn_client *client); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* ZEPHYR_INCLUDE_NET_MQTT_SN_H_ */ |
| |
| /**@} */ |