/* * IoT MQTT V2.1.0 * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /** * @file iot_mqtt.h * @brief User-facing functions of the MQTT 3.1.1 library. */ #ifndef IOT_MQTT_H_ #define IOT_MQTT_H_ /* The config header is always included first. */ #include "iot_config.h" /* MQTT types include. */ #include "types/iot_mqtt_types.h" /*------------------------- MQTT library functions --------------------------*/ /** * @functionspage{mqtt,MQTT library} * - @functionname{mqtt_function_init} * - @functionname{mqtt_function_cleanup} * - @functionname{mqtt_function_receivecallback} * - @functionname{mqtt_function_connect} * - @functionname{mqtt_function_disconnect} * - @functionname{mqtt_function_subscribeasync} * - @functionname{mqtt_function_subscribesync} * - @functionname{mqtt_function_unsubscribeasync} * - @functionname{mqtt_function_unsubscribesync} * - @functionname{mqtt_function_publishasync} * - @functionname{mqtt_function_publishsync} * - @functionname{mqtt_function_wait} * - @functionname{mqtt_function_strerror} * - @functionname{mqtt_function_operationtype} * - @functionname{mqtt_function_issubscribed} */ /** * @functionpage{IotMqtt_Init,mqtt,init} * @functionpage{IotMqtt_Cleanup,mqtt,cleanup} * @functionpage{IotMqtt_ReceiveCallback,mqtt,receivecallback} * @functionpage{IotMqtt_Connect,mqtt,connect} * @functionpage{IotMqtt_Disconnect,mqtt,disconnect} * @functionpage{IotMqtt_SubscribeAsync,mqtt,subscribeasync} * @functionpage{IotMqtt_SubscribeSync,mqtt,subscribesync} * @functionpage{IotMqtt_UnsubscribeAsync,mqtt,unsubscribeasync} * @functionpage{IotMqtt_UnsubscribeSync,mqtt,unsubscribesync} * @functionpage{IotMqtt_PublishAsync,mqtt,publishasync} * @functionpage{IotMqtt_PublishSync,mqtt,publishsync} * @functionpage{IotMqtt_Wait,mqtt,wait} * @functionpage{IotMqtt_strerror,mqtt,strerror} * @functionpage{IotMqtt_OperationType,mqtt,operationtype} * @functionpage{IotMqtt_IsSubscribed,mqtt,issubscribed} */ /** * @brief One-time initialization function for the MQTT library. * * This function performs setup of the MQTT library. It must be called * once (and only once) before calling any other MQTT function. Calling this * function more than once without first calling @ref mqtt_function_cleanup * may result in a crash. * * @return One of the following: * - #IOT_MQTT_SUCCESS * - #IOT_MQTT_NOT_INITIALIZED * * @warning No thread-safety guarantees are provided for this function. * * @see @ref mqtt_function_cleanup */ /* @[declare_mqtt_init] */ IotMqttError_t IotMqtt_Init( void ); /* @[declare_mqtt_init] */ /** * @brief One-time deinitialization function for the MQTT library. * * This function frees resources taken in @ref mqtt_function_init. It should be * called after [closing all MQTT connections](@ref mqtt_function_disconnect) to * clean up the MQTT library. After this function returns, @ref mqtt_function_init * must be called again before calling any other MQTT function. * * @warning No thread-safety guarantees are provided for this function. Do not * call this function if any MQTT connections are open! * * @see @ref mqtt_function_init */ /* @[declare_mqtt_cleanup] */ void IotMqtt_Cleanup( void ); /* @[declare_mqtt_cleanup] */ /** * @brief Network receive callback for the MQTT library. * * This function should be called by the system whenever data is available for * the MQTT library. * * @param[in] pNetworkConnection The network connection associated with the MQTT * connection, passed by the network stack. * @param[in] pReceiveContext A pointer to the MQTT connection handle for which * the packet was received. */ /* @[declare_mqtt_receivecallback] */ void IotMqtt_ReceiveCallback( IotNetworkConnection_t pNetworkConnection, void * pReceiveContext ); /* @[declare_mqtt_receivecallback] */ /** * @brief Establish a new MQTT connection. * * This function opens a connection between a new MQTT client and an MQTT server * (also called a broker). MQTT connections are established on top of transport * layer protocols (such as TCP/IP), and optionally, application layer security * protocols (such as TLS). The MQTT packet that establishes a connection is called * the MQTT CONNECT packet. After @ref mqtt_function_init, this function must be * called before any other MQTT library function. * * If [pConnectInfo->cleanSession](@ref IotMqttConnectInfo_t.cleanSession) is `true`, * this function establishes a clean MQTT session. Subscriptions and unacknowledged * PUBLISH messages will be discarded when the connection is closed. * * If [pConnectInfo->cleanSession](@ref IotMqttConnectInfo_t.cleanSession) is `false`, * this function establishes (or re-establishes) a persistent MQTT session. The parameters * [pConnectInfo->pPreviousSubscriptions](@ref IotMqttConnectInfo_t.pPreviousSubscriptions) * and [pConnectInfo->previousSubscriptionCount](@ref IotMqttConnectInfo_t.previousSubscriptionCount) * may be used to restore subscriptions present in a re-established persistent session. * Any restored subscriptions MUST have been present in the persistent session; * this function does not send an MQTT SUBSCRIBE packet! * * [pConnectInfo->pPreviousSubscriptions](@ref IotMqttConnectInfo_t.pPreviousSubscriptions) * and [pConnectInfo->previousSubscriptionCount](@ref IotMqttConnectInfo_t.previousSubscriptionCount) can * also be used to pass a list of subscriptions to be stored locally without a SUBSCRIBE packet being * sent to the broker. These subscriptions are useful to invoke application level callbacks for messages received * on unsolicited topics from the broker. * * This MQTT library is network agnostic, meaning it has no knowledge of the * underlying network protocol carrying the MQTT packets. It interacts with the * network through a network abstraction layer, allowing it to be used with many * different network stacks. The network abstraction layer is established * per-connection, allowing every #IotMqttConnection_t to use a different network * stack. The parameter `pNetworkInterface` sets up the network abstraction layer * for an MQTT connection; see the documentation on #IotMqttNetworkInfo_t for details * on its members. * * The `pConnectInfo` parameter provides the contents of the MQTT CONNECT packet. * Most members [are defined by the MQTT spec.](@ref IotMqttConnectInfo_t). The * [pConnectInfo->pWillInfo](@ref IotMqttConnectInfo_t.pWillInfo) member provides * information on a Last Will and Testament (LWT) message to be published if the * MQTT connection is closed without [sending a DISCONNECT packet] * (@ref mqtt_function_disconnect). Unlike other PUBLISH * messages, a LWT message payload is limited to 65535 bytes in length. Additionally, * the retry [interval](@ref IotMqttPublishInfo_t.retryMs) and [limit] * (@ref IotMqttPublishInfo_t.retryLimit) members of #IotMqttPublishInfo_t * are ignored for LWT messages. The LWT message is optional; `pWillInfo` may be NULL. * * Unlike @ref mqtt_function_publishasync, @ref mqtt_function_subscribeasync, and * @ref mqtt_function_unsubscribeasync, this function is always blocking. Additionally, * because the MQTT connection acknowledgement packet (CONNACK packet) does not * contain any information on which CONNECT packet it acknowledges, only one * CONNECT operation may be in progress at any time. This means that parallel * threads making calls to @ref mqtt_function_connect will be serialized to send * their CONNECT packets one-by-one. * * @param[in] pNetworkInfo Information on the transport-layer network connection * to use with the MQTT connection. * @param[in] pConnectInfo MQTT connection setup parameters. * @param[in] timeoutMs If the MQTT server does not accept the connection within * this timeout in milliseconds, this function returns #IOT_MQTT_TIMEOUT. * @param[out] pMqttConnection Set to a newly-initialized MQTT connection handle * if this function succeeds. * * @return One of the following: * - #IOT_MQTT_SUCCESS * - #IOT_MQTT_NOT_INITIALIZED * - #IOT_MQTT_BAD_PARAMETER * - #IOT_MQTT_NO_MEMORY * - #IOT_MQTT_NETWORK_ERROR * - #IOT_MQTT_SCHEDULING_ERROR * - #IOT_MQTT_BAD_RESPONSE * - #IOT_MQTT_TIMEOUT * - #IOT_MQTT_SERVER_REFUSED * * Example * @code{c} * * // Callback function to receive messages from the broker on an unsolicited topic. * void unsolicitedMessageCallback( void * pArgument, IotMqttCallbackParam_t * pPublish ); * * // Parameters to MQTT connect. * IotMqttConnection_t mqttConnection = IOT_MQTT_CONNECTION_INITIALIZER; * IotMqttNetworkInfo_t networkInfo = IOT_MQTT_NETWORK_INFO_INITIALIZER; * IotMqttConnectInfo_t connectInfo = IOT_MQTT_CONNECT_INFO_INITIALIZER; * IotMqttPublishInfo_t willInfo = IOT_MQTT_PUBLISH_INFO_INITIALIZER; * * // A local subscription to receive messages from the broker on an unsolicited topic. * IotMqttSubscription_t subscription = IOT_MQTT_SUBSCRIPTION_INITIALIZER; * * // Example network abstraction types. * IotNetworkServerInfo_t serverInfo = { ... }; * IotNetworkCredentials_t credentialInfo = { ... }; * IotNetworkInterface_t networkInterface = { ... }; * * // Example using a generic network implementation. * networkInfo.createNetworkConnection = true; * networkInfo.u.setup.pNetworkServerInfo = &serverInfo; * networkInfo.u.setup.pNetworkCredentialInfo = &credentialInfo; * networkInfo.pNetworkInterface = &networkInterface; * * // Set the members of the connection info (password and username not used). * connectInfo.cleanSession = true; * connectInfo.keepAliveSeconds = 30; * connectInfo.pClientIdentifier = "uniqueclientidentifier"; * connectInfo.clientIdentifierLength = 22; * * // Set the members of the will info (retain and retry not used). * willInfo.qos = IOT_MQTT_QOS_1; * willInfo.pTopicName = "will/topic/name"; * willInfo.topicNameLength = ( uint16_t ) strlen( willInfo.pTopicName ); * willInfo.pPayload = "MQTT client unexpectedly disconnected."; * willInfo.payloadLength = strlen( willInfo.pPayload ); * * // Set the pointer to the will info. * connectInfo.pWillInfo = &willInfo; * * // [Optional] Set a local subscription to receive the broker messages on an unsolicited topic. * subscription.qos = IOT_MQTT_QOS_0; * subscription.pTopicFilter = "some/unsolicited/topic"; * subscription.topicLength = ( uint16_t ) strlen( subscription.pTopicFilter ); * subscription.callback.function = unsolicitedMessageCallback; * connectInfo.pPreviousSubscriptions = &subscription; * connectInfo.previousSubscriptionCount = 1; * * * // Call CONNECT with a 5 second block time. Should return * // IOT_MQTT_SUCCESS when successful. * IotMqttError_t result = IotMqtt_Connect( &networkInfo, * &connectInfo, * 5000, * &mqttConnection ); * * if( result == IOT_MQTT_SUCCESS ) * { * // Do something with the MQTT connection... * * // Clean up and close the MQTT connection once it's no longer needed. * IotMqtt_Disconnect( mqttConnection, 0 ); * } * @endcode */ /* @[declare_mqtt_connect] */ IotMqttError_t IotMqtt_Connect( const IotMqttNetworkInfo_t * pNetworkInfo, const IotMqttConnectInfo_t * pConnectInfo, uint32_t timeoutMs, IotMqttConnection_t * const pMqttConnection ); /* @[declare_mqtt_connect] */ /** * @brief Closes an MQTT connection and frees resources. * * This function closes an MQTT connection and should only be called once * the MQTT connection is no longer needed. Its exact behavior depends on the * `flags` parameter. * * Normally, `flags` should be `0`. This gracefully shuts down an MQTT * connection by sending an MQTT DISCONNECT packet. Any [network close function] * (@ref IotNetworkInterface_t::close) provided [when the connection was established] * (@ref mqtt_function_connect) will also be called. Note that because the MQTT server * will not acknowledge a DISCONNECT packet, the client has no way of knowing if * the server received the DISCONNECT packet. In the case where the DISCONNECT * packet is lost in transport, any Last Will and Testament (LWT) message established * with the connection may be published. However, if the DISCONNECT reaches the * MQTT server, the LWT message will be discarded and not published. * * Should the underlying network connection become unusable, this function should * be called with `flags` set to #IOT_MQTT_FLAG_CLEANUP_ONLY. In this case, no * DISCONNECT packet will be sent, though the [network close function](@ref IotNetworkInterface_t::close) * will still be called. This function will only free the resources used by the MQTT * connection; it still must be called even if the network is offline to avoid leaking * resources. * * @ref mqtt_function_disconnect modifies `mqttConnection`, so it shouldn't * be used after calling this function. * * @param[in] mqttConnection The MQTT connection to close and clean up. * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags. */ /* @[declare_mqtt_disconnect] */ void IotMqtt_Disconnect( IotMqttConnection_t mqttConnection, uint32_t flags ); /* @[declare_mqtt_disconnect] */ /** * @brief Subscribes to the given array of topic filters and optionally * receive an asynchronous notification when the subscribe completes. * * This function sends an MQTT SUBSCRIBE packet to the server. A SUBSCRIBE * packet notifies the server to send any matching PUBLISH messages to this client. * A single SUBSCRIBE packet may carry more than one topic filter, hence the * parameters to this function include an array of [subscriptions] * (@ref IotMqttSubscription_t). * * An MQTT subscription has two pieces: * 1. The subscription topic filter registered with the MQTT server. The MQTT * SUBSCRIBE packet sent from this client to server notifies the server to send * messages matching the given topic filters to this client. * 2. The [callback function](@ref IotMqttCallbackInfo_t.function) that this * client will invoke when an incoming message is received. The callback function * notifies applications of an incoming PUBLISH message. * * The helper function @ref mqtt_function_issubscribed can be used to check if a * [callback function](@ref IotMqttCallbackInfo_t.function) is registered for * a particular topic filter. * * To modify an already-registered subscription callback, call this function with * a new `pSubscriptionList`. Any topic filters in `pSubscriptionList` that already * have a registered callback will be replaced with the new values in `pSubscriptionList`. * * @attention QoS 2 subscriptions are currently unsupported. Only 0 or 1 are valid * for subscription QoS. * * @param[in] mqttConnection The MQTT connection to use for the subscription. * @param[in] pSubscriptionList Pointer to the first element in the array of * subscriptions. * @param[in] subscriptionCount The number of elements in pSubscriptionList. * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags. * @param[in] pCallbackInfo Asynchronous notification of this function's completion (`NULL` to disable). * @param[out] pSubscribeOperation Set to a handle by which this operation may be * referenced after this function returns. This reference is invalidated once * the subscription operation completes. * * @return This function will return #IOT_MQTT_STATUS_PENDING upon success. * @return Upon completion of the subscription (either through an * #IotMqttCallbackInfo_t or @ref mqtt_function_wait), the status will be one of: * - #IOT_MQTT_SUCCESS * - #IOT_MQTT_NETWORK_ERROR * - #IOT_MQTT_SCHEDULING_ERROR * - #IOT_MQTT_BAD_RESPONSE * - #IOT_MQTT_SERVER_REFUSED * @return If this function fails before queuing a subscribe operation, it will return * one of: * - #IOT_MQTT_NOT_INITIALIZED * - #IOT_MQTT_BAD_PARAMETER * - #IOT_MQTT_NO_MEMORY * * @see @ref mqtt_function_subscribesync for a blocking variant of this function. * @see @ref mqtt_function_unsubscribeasync for the function that removes subscriptions. * * Example * @code{c} * #define NUMBER_OF_SUBSCRIPTIONS ... * * // Subscription callback function. * void subscriptionCallback( void * pArgument, IotMqttCallbackParam_t * pPublish ); * * // An initialized and connected MQTT connection. * IotMqttConnection_t mqttConnection; * * // Subscription information. * pSubscriptions[ NUMBER_OF_SUBSCRIPTIONS ] = { IOT_MQTT_SUBSCRIPTION_INITIALIZER }; * IotMqttOperation_t lastOperation = IOT_MQTT_OPERATION_INITIALIZER; * * // Set the subscription information. * for( int i = 0; i < NUMBER_OF_SUBSCRIPTIONS; i++ ) * { * pSubscriptions[ i ].qos = IOT_MQTT_QOS_1; * pSubscriptions[ i ].pTopicFilter = "some/topic/filter"; * pSubscriptions[ i ].topicLength = ( uint16_t ) strlen( pSubscriptions[ i ].pTopicFilter ); * pSubscriptions[ i ].callback.function = subscriptionCallback; * } * * IotMqttError_t result = IotMqtt_SubscribeAsync( mqttConnection, * pSubscriptions, * NUMBER_OF_SUBSCRIPTIONS, * IOT_MQTT_FLAG_WAITABLE, * NULL, * &lastOperation ); * * // Subscribe returns IOT_MQTT_STATUS_PENDING when successful. Wait up to * // 5 seconds for the operation to complete. * if( result == IOT_MQTT_STATUS_PENDING ) * { * result = IotMqtt_Wait( subscriptionRef, 5000 ); * } * * // Check that the subscriptions were successful. * if( result == IOT_MQTT_SUCCESS ) * { * // Wait for messages on the subscription topic filters... * * // Unsubscribe once the subscriptions are no longer needed. * result = IotMqtt_UnsubscribeAsync( mqttConnection, * pSubscriptions, * NUMBER_OF_SUBSCRIPTIONS, * IOT_MQTT_FLAG_WAITABLE, * NULL, * &lastOperation ); * * // UNSUBSCRIBE returns IOT_MQTT_STATUS_PENDING when successful. * // Wait up to 5 seconds for the operation to complete. * if( result == IOT_MQTT_STATUS_PENDING ) * { * result = IotMqtt_Wait( lastOperation, 5000 ); * } * } * // Check which subscriptions were rejected by the server. * else if( result == IOT_MQTT_SERVER_REFUSED ) * { * for( int i = 0; i < NUMBER_OF_SUBSCRIPTIONS; i++ ) * { * if( IotMqtt_IsSubscribed( mqttConnection, * pSubscriptions[ i ].pTopicFilter, * pSubscriptions[ i ].topicFilterLength, * NULL ) == false ) * { * // This subscription was rejected. * } * } * } * @endcode */ /* @[declare_mqtt_subscribeasync] */ IotMqttError_t IotMqtt_SubscribeAsync( IotMqttConnection_t mqttConnection, const IotMqttSubscription_t * pSubscriptionList, size_t subscriptionCount, uint32_t flags, const IotMqttCallbackInfo_t * pCallbackInfo, IotMqttOperation_t * const pSubscribeOperation ); /* @[declare_mqtt_subscribeasync] */ /** * @brief Subscribes to the given array of topic filters with a timeout. * * This function sends an MQTT SUBSCRIBE packet to the server, then waits for * a server response to the packet. Internally, this function is a call to @ref * mqtt_function_subscribeasync followed by @ref mqtt_function_wait. See @ref * mqtt_function_subscribeasync for more information about the MQTT SUBSCRIBE operation. * * @attention QoS 2 subscriptions are currently unsupported. Only 0 or 1 are valid * for subscription QoS. * * @param[in] mqttConnection The MQTT connection to use for the subscription. * @param[in] pSubscriptionList Pointer to the first element in the array of * subscriptions. * @param[in] subscriptionCount The number of elements in pSubscriptionList. * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags. * Currently, flags are ignored by this function; this parameter is for * future-compatibility. * @param[in] timeoutMs If the MQTT server does not acknowledge the subscriptions within * this timeout in milliseconds, this function returns #IOT_MQTT_TIMEOUT. * * @return One of the following: * - #IOT_MQTT_SUCCESS * - #IOT_MQTT_NOT_INITIALIZED * - #IOT_MQTT_BAD_PARAMETER * - #IOT_MQTT_NO_MEMORY * - #IOT_MQTT_NETWORK_ERROR * - #IOT_MQTT_SCHEDULING_ERROR * - #IOT_MQTT_BAD_RESPONSE * - #IOT_MQTT_TIMEOUT * - #IOT_MQTT_SERVER_REFUSED */ /* @[declare_mqtt_subscribesync] */ IotMqttError_t IotMqtt_SubscribeSync( IotMqttConnection_t mqttConnection, const IotMqttSubscription_t * pSubscriptionList, size_t subscriptionCount, uint32_t flags, uint32_t timeoutMs ); /* @[declare_mqtt_subscribesync] */ /** * @brief Unsubscribes from the given array of topic filters and optionally * receive an asynchronous notification when the unsubscribe completes. * * This function sends an MQTT UNSUBSCRIBE packet to the server. An UNSUBSCRIBE * packet removes registered topic filters from the server. After unsubscribing, * the server will no longer send messages on these topic filters to the client. * * Corresponding [subscription callback functions](@ref IotMqttCallbackInfo_t.function) * are also removed from the MQTT connection. These subscription callback functions * will be removed even if the MQTT UNSUBSCRIBE packet fails to send. * * @param[in] mqttConnection The MQTT connection used for the subscription. * @param[in] pSubscriptionList Pointer to the first element in the array of * subscriptions. * @param[in] subscriptionCount The number of elements in pSubscriptionList. * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags. * @param[in] pCallbackInfo Asynchronous notification of this function's completion (`NULL` to disable). * @param[out] pUnsubscribeOperation Set to a handle by which this operation may be * referenced after this function returns. This reference is invalidated once * the unsubscribe operation completes. * * @return This function will return #IOT_MQTT_STATUS_PENDING upon success. * @return Upon completion of the unsubscribe (either through an * #IotMqttCallbackInfo_t or @ref mqtt_function_wait), the status will be one of: * - #IOT_MQTT_SUCCESS * - #IOT_MQTT_NETWORK_ERROR * - #IOT_MQTT_SCHEDULING_ERROR * - #IOT_MQTT_BAD_RESPONSE * @return If this function fails before queuing an unsubscribe operation, it will return * one of: * - #IOT_MQTT_NOT_INITIALIZED * - #IOT_MQTT_BAD_PARAMETER * - #IOT_MQTT_NO_MEMORY * * @see @ref mqtt_function_unsubscribesync for a blocking variant of this function. * @see @ref mqtt_function_subscribeasync for the function that adds subscriptions. */ /* @[declare_mqtt_unsubscribeasync] */ IotMqttError_t IotMqtt_UnsubscribeAsync( IotMqttConnection_t mqttConnection, const IotMqttSubscription_t * pSubscriptionList, size_t subscriptionCount, uint32_t flags, const IotMqttCallbackInfo_t * pCallbackInfo, IotMqttOperation_t * const pUnsubscribeOperation ); /* @[declare_mqtt_unsubscribeasync] */ /** * @brief Unsubscribes from a given array of topic filters with a timeout. * * This function sends an MQTT UNSUBSCRIBE packet to the server, then waits * for a server response to the packet. Internally, this function is a call to * @ref mqtt_function_unsubscribeasync followed by @ref mqtt_function_wait. See @ref * mqtt_function_unsubscribeasync for more information about the MQTT UNSUBSCRIBE * operation. * * @param[in] mqttConnection The MQTT connection used for the subscription. * @param[in] pSubscriptionList Pointer to the first element in the array of * subscriptions. * @param[in] subscriptionCount The number of elements in pSubscriptionList. * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags. * Flags are currently ignored but reserved for future use. * @param[in] timeoutMs If the MQTT server does not acknowledge the UNSUBSCRIBE within * this timeout in milliseconds, this function returns #IOT_MQTT_TIMEOUT. * * @return One of the following: * - #IOT_MQTT_SUCCESS * - #IOT_MQTT_NOT_INITIALIZED * - #IOT_MQTT_BAD_PARAMETER * - #IOT_MQTT_NO_MEMORY * - #IOT_MQTT_NETWORK_ERROR * - #IOT_MQTT_SCHEDULING_ERROR * - #IOT_MQTT_BAD_RESPONSE */ /* @[declare_mqtt_unsubscribesync] */ IotMqttError_t IotMqtt_UnsubscribeSync( IotMqttConnection_t mqttConnection, const IotMqttSubscription_t * pSubscriptionList, size_t subscriptionCount, uint32_t flags, uint32_t timeoutMs ); /* @[declare_mqtt_unsubscribesync] */ /** * @brief Publishes a message to the given topic name and optionally * receive an asynchronous notification when the publish completes. * * This function sends an MQTT PUBLISH packet to the server. A PUBLISH packet * contains a payload and a topic name. Any clients with a subscription on a * topic filter matching the PUBLISH topic name will receive a copy of the * PUBLISH packet from the server. * * If a PUBLISH packet fails to reach the server and it is not a QoS 0 message, * it will be retransmitted. See #IotMqttPublishInfo_t for a description * of the retransmission strategy. * * @attention QoS 2 messages are currently unsupported. Only 0 or 1 are valid * for message QoS. * * @param[in] mqttConnection The MQTT connection to use for the publish. * @param[in] pPublishInfo MQTT publish parameters. * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags. * @param[in] pCallbackInfo Asynchronous notification of this function's completion (`NULL` to disable). * @param[out] pPublishOperation Set to a handle by which this operation may be * referenced after this function returns. This reference is invalidated once * the publish operation completes. * * @return This function will return #IOT_MQTT_STATUS_PENDING upon success for * QoS 1 publishes. For a QoS 0 publish it returns #IOT_MQTT_SUCCESS upon * success. * @return Upon completion of a QoS 1 publish (either through an * #IotMqttCallbackInfo_t or @ref mqtt_function_wait), the status will be one of: * - #IOT_MQTT_SUCCESS * - #IOT_MQTT_NETWORK_ERROR * - #IOT_MQTT_SCHEDULING_ERROR * - #IOT_MQTT_BAD_RESPONSE * - #IOT_MQTT_RETRY_NO_RESPONSE (if [pPublishInfo->retryMs](@ref IotMqttPublishInfo_t.retryMs) * and [pPublishInfo->retryLimit](@ref IotMqttPublishInfo_t.retryLimit) were set). * @return If this function fails before queuing an publish operation (regardless * of QoS), it will return one of: * - #IOT_MQTT_NOT_INITIALIZED * - #IOT_MQTT_BAD_PARAMETER * - #IOT_MQTT_NO_MEMORY * * @note The parameters `pCallbackInfo` and `pPublishOperation` should only be used for QoS * 1 publishes. For QoS 0, they should both be `NULL`. * * @see @ref mqtt_function_publishsync for a blocking variant of this function. * * Example * @code{c} * // An initialized and connected MQTT connection. * IotMqttConnection_t mqttConnection; * * // Publish information. * IotMqttPublishInfo_t publishInfo = IOT_MQTT_PUBLISH_INFO_INITIALIZER; * * // Set the publish information. QoS 0 example (retain not used): * publishInfo.qos = IOT_MQTT_QOS_0; * publishInfo.pTopicName = "some/topic/name"; * publishInfo.topicNameLength = ( uint16_t ) strlen( publishInfo.pTopicName ); * publishInfo.pPayload = "payload"; * publishInfo.payloadLength = strlen( publishInfo.pPayload ); * * // QoS 0 publish should return IOT_MQTT_SUCCESS upon success. * IotMqttError_t qos0Result = IotMqtt_PublishAsync( mqttConnection, * &publishInfo, * 0, * NULL, * NULL ); * * // QoS 1 with retry example (using same topic name and payload as QoS 0 example): * IotMqttOperation_t qos1Operation = IOT_MQTT_OPERATION_INITIALIZER; * publishInfo.qos = IOT_MQTT_QOS_1; * publishInfo.retryMs = 1000; // Retry if no response is received in 1 second. * publishInfo.retryLimit = 5; // Retry up to 5 times. * * // QoS 1 publish should return IOT_MQTT_STATUS_PENDING upon success. * IotMqttError_t qos1Result = IotMqtt_PublishAsync( mqttConnection, * &publishInfo, * IOT_MQTT_FLAG_WAITABLE, * NULL, * &qos1Operation ); * * // Wait up to 5 seconds for the publish to complete. * if( qos1Result == IOT_MQTT_STATUS_PENDING ) * { * qos1Result = IotMqtt_Wait( qos1Operation, 5000 ); * } * @endcode */ /* @[declare_mqtt_publishasync] */ IotMqttError_t IotMqtt_PublishAsync( IotMqttConnection_t mqttConnection, const IotMqttPublishInfo_t * pPublishInfo, uint32_t flags, const IotMqttCallbackInfo_t * pCallbackInfo, IotMqttOperation_t * const pPublishOperation ); /* @[declare_mqtt_publishasync] */ /** * @brief Publish a message to the given topic name with a timeout. * * This function sends an MQTT PUBLISH packet to the server, then waits for * a server response to the packet. Internally, this function is a call to @ref * mqtt_function_publishasync followed by @ref mqtt_function_wait. See @ref * mqtt_function_publishasync for more information about the MQTT PUBLISH operation. * * @attention QoS 2 messages are currently unsupported. Only 0 or 1 are valid * for message QoS. * * @param[in] mqttConnection The MQTT connection to use for the publish. * @param[in] pPublishInfo MQTT publish parameters. * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags. * Currently, flags are ignored by this function; this parameter is for * future-compatibility. * @param[in] timeoutMs If the MQTT server does not acknowledge a QoS 1 PUBLISH * within this timeout in milliseconds, this function returns #IOT_MQTT_TIMEOUT. * This parameter is ignored for QoS 0 PUBLISH messages. * * @return One of the following: * - #IOT_MQTT_SUCCESS * - #IOT_MQTT_NOT_INITIALIZED * - #IOT_MQTT_BAD_PARAMETER * - #IOT_MQTT_NO_MEMORY * - #IOT_MQTT_NETWORK_ERROR * - #IOT_MQTT_SCHEDULING_ERROR * - #IOT_MQTT_BAD_RESPONSE * - #IOT_MQTT_RETRY_NO_RESPONSE (if [pPublishInfo->retryMs](@ref IotMqttPublishInfo_t.retryMs) * and [pPublishInfo->retryLimit](@ref IotMqttPublishInfo_t.retryLimit) were set). */ /* @[declare_mqtt_publishsync] */ IotMqttError_t IotMqtt_PublishSync( IotMqttConnection_t mqttConnection, const IotMqttPublishInfo_t * pPublishInfo, uint32_t flags, uint32_t timeoutMs ); /* @[declare_mqtt_publishsync] */ /** * @brief Waits for an operation to complete. * * This function blocks to wait for a [subscribe](@ref mqtt_function_subscribeasync), * [unsubscribe](@ref mqtt_function_unsubscribeasync), or [publish] * (@ref mqtt_function_publishasync) to complete. These operations are by default * asynchronous; the function calls queue an operation for processing, and a * callback is invoked once the operation is complete. * * To use this function, the flag #IOT_MQTT_FLAG_WAITABLE must have been * set in the operation's function call. Additionally, this function must always * be called with any waitable operation to clean up resources. * * Regardless of its return value, this function always clean up resources used * by the waitable operation. This means `reference` is invalidated as soon as * this function returns, even if it returns #IOT_MQTT_TIMEOUT or another error. * * @param[in] operation Reference to the operation to wait for. The flag * #IOT_MQTT_FLAG_WAITABLE must have been set for this operation. * @param[in] timeoutMs How many milliseconds to wait before returning * #IOT_MQTT_TIMEOUT. * * @return The return value of this function depends on the MQTT operation associated * with `reference`. See #IotMqttError_t for possible return values. * * Example * @code{c} * // Operation reference and timeout. * IotMqttOperation_t publishOperation = IOT_MQTT_OPERATION_INITIALIZER; * uint32_t timeoutMs = 5000; // 5 seconds * * // MQTT operation to wait for. * IotMqttError_t result = IotMqtt_PublishAsync( mqttConnection, * &publishInfo, * IOT_MQTT_FLAG_WAITABLE, * NULL, * &publishOperation ); * * // Publish should have returned IOT_MQTT_STATUS_PENDING. The call to wait * // returns once the result of the publish is available or the timeout expires. * if( result == IOT_MQTT_STATUS_PENDING ) * { * result = IotMqtt_Wait( publishOperation, timeoutMs ); * * // After the call to wait, the result of the publish is known * // (not IOT_MQTT_STATUS_PENDING). * assert( result != IOT_MQTT_STATUS_PENDING ); * } * @endcode */ /* @[declare_mqtt_wait] */ IotMqttError_t IotMqtt_Wait( IotMqttOperation_t operation, uint32_t timeoutMs ); /* @[declare_mqtt_wait] */ /*-------------------------- MQTT helper functions --------------------------*/ /** * @brief Returns a string that describes an #IotMqttError_t. * * Like the POSIX `strerror`, this function returns a string describing a * return code. In this case, the return code is an MQTT library error code, * `status`. * * The string returned by this function MUST be treated as read-only: any * attempt to modify its contents may result in a crash. Therefore, this function * is limited to usage in logging. * * @param[in] status The status to describe. * * @return A read-only string that describes `status`. * * @warning The string returned by this function must never be modified. */ /* @[declare_mqtt_strerror] */ const char * IotMqtt_strerror( IotMqttError_t status ); /* @[declare_mqtt_strerror] */ /** * @brief Returns a string that describes an #IotMqttOperationType_t. * * This function returns a string describing an MQTT operation type, `operation`. * * The string returned by this function MUST be treated as read-only: any * attempt to modify its contents may result in a crash. Therefore, this function * is limited to usage in logging. * * @param[in] operation The operation to describe. * * @return A read-only string that describes `operation`. * * @warning The string returned by this function must never be modified. */ /* @[declare_mqtt_operationtype] */ const char * IotMqtt_OperationType( IotMqttOperationType_t operation ); /* @[declare_mqtt_operationtype] */ /** * @brief Check if an MQTT connection has a subscription for a topic filter. * * This function checks whether an MQTT connection `mqttConnection` has a * subscription callback registered for a topic filter `pTopicFilter`. If a * subscription callback is found, its details are copied into the output parameter * `pCurrentSubscription`. This subscription callback will be invoked for incoming * PUBLISH messages on `pTopicFilter`. * * The check for a matching subscription is only performed client-side; * therefore, this function should not be relied upon for perfect accuracy. For * example, this function may return an incorrect result if the MQTT server * crashes and drops subscriptions without informing the client. * * Note that an MQTT connection's subscriptions might change between the time this * function checks the subscription list and its caller tests the return value. * This function certainly should not be used concurrently with any pending SUBSCRIBE * or UNSUBSCRIBE operations. * * One suitable use of this function is to check which subscriptions were rejected * if @ref mqtt_function_subscribeasync returns #IOT_MQTT_SERVER_REFUSED; that return * code only means that at least one subscription was rejected. * * @param[in] mqttConnection The MQTT connection to check. * @param[in] pTopicFilter The topic filter to check. * @param[in] topicFilterLength Length of `pTopicFilter`. * @param[out] pCurrentSubscription If a subscription is found, its details are * copied here. This output parameter is only valid if this function returns `true` (`NULL` to disable). * * @return `true` if a subscription was found; `false` otherwise. * * @note The subscription QoS is not stored by the MQTT library; therefore, * `pCurrentSubscription->qos` will always be set to #IOT_MQTT_QOS_0. */ /* @[declare_mqtt_issubscribed] */ bool IotMqtt_IsSubscribed( IotMqttConnection_t mqttConnection, const char * pTopicFilter, uint16_t topicFilterLength, IotMqttSubscription_t * const pCurrentSubscription ); /* @[declare_mqtt_issubscribed] */ /** * @cond DOXYGEN_IGNORE * Doxygen should ignore this section. * * Backwards compatibility macros for previous function names. */ #define IotMqtt_Subscribe IotMqtt_SubscribeAsync #define IotMqtt_TimedSubscribe IotMqtt_SubscribeSync #define IotMqtt_Unsubscribe IotMqtt_UnsubscribeAsync #define IotMqtt_TimedUnsubscribe IotMqtt_UnsubscribeSync #define IotMqtt_Publish IotMqtt_PublishAsync #define IotMqtt_TimedPublish IotMqtt_PublishSync /** @endcond */ #endif /* ifndef IOT_MQTT_H_ */