2 * Amazon FreeRTOS MQTT V2.0.0
\r
3 * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
6 * this software and associated documentation files (the "Software"), to deal in
\r
7 * the Software without restriction, including without limitation the rights to
\r
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
9 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
10 * subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
22 * http://aws.amazon.com/freertos
\r
23 * http://www.FreeRTOS.org
\r
28 * @brief User-facing functions of the MQTT 3.1.1 library.
\r
34 /* The config header is always included first. */
\r
35 #include "iot_config.h"
\r
37 /* MQTT types include. */
\r
38 #include "types/iot_mqtt_types.h"
\r
40 /*------------------------- MQTT library functions --------------------------*/
\r
43 * @functionspage{mqtt,MQTT library}
\r
44 * - @functionname{mqtt_function_init}
\r
45 * - @functionname{mqtt_function_cleanup}
\r
46 * - @functionname{mqtt_function_receivecallback}
\r
47 * - @functionname{mqtt_function_connect}
\r
48 * - @functionname{mqtt_function_disconnect}
\r
49 * - @functionname{mqtt_function_subscribe}
\r
50 * - @functionname{mqtt_function_timedsubscribe}
\r
51 * - @functionname{mqtt_function_unsubscribe}
\r
52 * - @functionname{mqtt_function_timedunsubscribe}
\r
53 * - @functionname{mqtt_function_publish}
\r
54 * - @functionname{mqtt_function_timedpublish}
\r
55 * - @functionname{mqtt_function_wait}
\r
56 * - @functionname{mqtt_function_strerror}
\r
57 * - @functionname{mqtt_function_operationtype}
\r
58 * - @functionname{mqtt_function_issubscribed}
\r
62 * @functionpage{IotMqtt_Init,mqtt,init}
\r
63 * @functionpage{IotMqtt_Cleanup,mqtt,cleanup}
\r
64 * @functionpage{IotMqtt_ReceiveCallback,mqtt,receivecallback}
\r
65 * @functionpage{IotMqtt_Connect,mqtt,connect}
\r
66 * @functionpage{IotMqtt_Disconnect,mqtt,disconnect}
\r
67 * @functionpage{IotMqtt_Subscribe,mqtt,subscribe}
\r
68 * @functionpage{IotMqtt_TimedSubscribe,mqtt,timedsubscribe}
\r
69 * @functionpage{IotMqtt_Unsubscribe,mqtt,unsubscribe}
\r
70 * @functionpage{IotMqtt_TimedUnsubscribe,mqtt,timedunsubscribe}
\r
71 * @functionpage{IotMqtt_Publish,mqtt,publish}
\r
72 * @functionpage{IotMqtt_TimedPublish,mqtt,timedpublish}
\r
73 * @functionpage{IotMqtt_Wait,mqtt,wait}
\r
74 * @functionpage{IotMqtt_strerror,mqtt,strerror}
\r
75 * @functionpage{IotMqtt_OperationType,mqtt,operationtype}
\r
76 * @functionpage{IotMqtt_IsSubscribed,mqtt,issubscribed}
\r
80 * @brief One-time initialization function for the MQTT library.
\r
82 * This function performs setup of the MQTT library. <b>It must be called
\r
83 * once (and only once) before calling any other MQTT function.</b> Calling this
\r
84 * function more than once without first calling @ref mqtt_function_cleanup
\r
85 * may result in a crash.
\r
87 * @return One of the following:
\r
88 * - #IOT_MQTT_SUCCESS
\r
89 * - #IOT_MQTT_INIT_FAILED
\r
91 * @warning No thread-safety guarantees are provided for this function.
\r
93 * @see @ref mqtt_function_cleanup
\r
95 /* @[declare_mqtt_init] */
\r
96 IotMqttError_t IotMqtt_Init( void );
\r
97 /* @[declare_mqtt_init] */
\r
100 * @brief One-time deinitialization function for the MQTT library.
\r
102 * This function frees resources taken in @ref mqtt_function_init. It should be
\r
103 * called after [closing all MQTT connections](@ref mqtt_function_disconnect) to
\r
104 * clean up the MQTT library. After this function returns, @ref mqtt_function_init
\r
105 * must be called again before calling any other MQTT function.
\r
107 * @warning No thread-safety guarantees are provided for this function. Do not
\r
108 * call this function if any MQTT connections are open!
\r
110 * @see @ref mqtt_function_init
\r
112 /* @[declare_mqtt_cleanup] */
\r
113 void IotMqtt_Cleanup( void );
\r
114 /* @[declare_mqtt_cleanup] */
\r
117 * @brief Network receive callback for the MQTT library.
\r
119 * This function should be called by the system whenever data is available for
\r
120 * the MQTT library.
\r
122 * @param[in] pNetworkConnection The network connection associated with the MQTT
\r
123 * connection, passed by the network stack.
\r
124 * @param[in] pReceiveContext A pointer to the MQTT connection handle for which
\r
125 * the packet was received.
\r
127 /* @[declare_mqtt_receivecallback] */
\r
128 void IotMqtt_ReceiveCallback( void * pNetworkConnection,
\r
129 void * pReceiveContext );
\r
130 /* @[declare_mqtt_receivecallback] */
\r
133 * @brief Establish a new MQTT connection.
\r
135 * This function opens a connection between a new MQTT client and an MQTT server
\r
136 * (also called a <i>broker</i>). MQTT connections are established on top of transport
\r
137 * layer protocols (such as TCP/IP), and optionally, application layer security
\r
138 * protocols (such as TLS). The MQTT packet that establishes a connection is called
\r
139 * the MQTT CONNECT packet. After @ref mqtt_function_init, this function must be
\r
140 * called before any other MQTT library function.
\r
142 * If [pConnectInfo->cleanSession](@ref IotMqttConnectInfo_t.cleanSession) is `true`,
\r
143 * this function establishes a clean MQTT session. Subscriptions and unacknowledged
\r
144 * PUBLISH messages will be discarded when the connection is closed.
\r
146 * If [pConnectInfo->cleanSession](@ref IotMqttConnectInfo_t.cleanSession) is `false`,
\r
147 * this function establishes (or re-establishes) a persistent MQTT session. The parameters
\r
148 * [pConnectInfo->pPreviousSubscriptions](@ref IotMqttConnectInfo_t.pPreviousSubscriptions)
\r
149 * and [pConnectInfo->previousSubscriptionCount](@ref IotMqttConnectInfo_t.previousSubscriptionCount)
\r
150 * may be used to restore subscriptions present in a re-established persistent session.
\r
151 * Any restored subscriptions <b>MUST</b> have been present in the persistent session;
\r
152 * <b>this function does not send an MQTT SUBSCRIBE packet!</b>
\r
154 * This MQTT library is network agnostic, meaning it has no knowledge of the
\r
155 * underlying network protocol carrying the MQTT packets. It interacts with the
\r
156 * network through a network abstraction layer, allowing it to be used with many
\r
157 * different network stacks. The network abstraction layer is established
\r
158 * per-connection, allowing every #IotMqttConnection_t to use a different network
\r
159 * stack. The parameter `pNetworkInterface` sets up the network abstraction layer
\r
160 * for an MQTT connection; see the documentation on #IotMqttNetworkInfo_t for details
\r
163 * The `pConnectInfo` parameter provides the contents of the MQTT CONNECT packet.
\r
164 * Most members [are defined by the MQTT spec.](@ref IotMqttConnectInfo_t). The
\r
165 * [pConnectInfo->pWillInfo](@ref IotMqttConnectInfo_t.pWillInfo) member provides
\r
166 * information on a Last Will and Testament (LWT) message to be published if the
\r
167 * MQTT connection is closed without [sending a DISCONNECT packet]
\r
168 * (@ref mqtt_function_disconnect). Unlike other PUBLISH
\r
169 * messages, a LWT message payload is limited to 65535 bytes in length. Additionally,
\r
170 * the retry [interval](@ref IotMqttPublishInfo_t.retryMs) and [limit]
\r
171 * (@ref IotMqttPublishInfo_t.retryLimit) members of #IotMqttPublishInfo_t
\r
172 * are ignored for LWT messages. The LWT message is optional; `pWillInfo` may be NULL.
\r
174 * Unlike @ref mqtt_function_publish, @ref mqtt_function_subscribe, and
\r
175 * @ref mqtt_function_unsubscribe, this function is always blocking. Additionally,
\r
176 * because the MQTT connection acknowledgement packet (CONNACK packet) does not
\r
177 * contain any information on <i>which</i> CONNECT packet it acknowledges, only one
\r
178 * CONNECT operation may be in progress at any time. This means that parallel
\r
179 * threads making calls to @ref mqtt_function_connect will be serialized to send
\r
180 * their CONNECT packets one-by-one.
\r
182 * @param[in] pNetworkInfo Information on the transport-layer network connection
\r
183 * to use with the MQTT connection.
\r
184 * @param[in] pConnectInfo MQTT connection setup parameters.
\r
185 * @param[in] timeoutMs If the MQTT server does not accept the connection within
\r
186 * this timeout, this function returns #IOT_MQTT_TIMEOUT.
\r
187 * @param[out] pMqttConnection Set to a newly-initialized MQTT connection handle
\r
188 * if this function succeeds.
\r
190 * @return One of the following:
\r
191 * - #IOT_MQTT_SUCCESS
\r
192 * - #IOT_MQTT_BAD_PARAMETER
\r
193 * - #IOT_MQTT_NO_MEMORY
\r
194 * - #IOT_MQTT_NETWORK_ERROR
\r
195 * - #IOT_MQTT_SCHEDULING_ERROR
\r
196 * - #IOT_MQTT_BAD_RESPONSE
\r
197 * - #IOT_MQTT_TIMEOUT
\r
198 * - #IOT_MQTT_SERVER_REFUSED
\r
202 * // An initialized and connected network connection.
\r
203 * IotNetworkConnection_t pNetworkConnection;
\r
205 * // Parameters to MQTT connect.
\r
206 * IotMqttConnection_t mqttConnection = IOT_MQTT_CONNECTION_INITIALIZER;
\r
207 * IotMqttNetworkInfo_t networkInfo = IOT_MQTT_NETWORK_INFO_INITIALIZER;
\r
208 * IotMqttConnectInfo_t connectInfo = IOT_MQTT_CONNECT_INFO_INITIALIZER;
\r
209 * IotMqttPublishInfo_t willInfo = IOT_MQTT_PUBLISH_INFO_INITIALIZER;
\r
211 * // Example network abstraction types.
\r
212 * IotNetworkServerInfo_t serverInfo = { ... };
\r
213 * IotNetworkCredentialInfo_t credentialInfo = { ... };
\r
214 * IotNetworkInterface_t networkInterface = { ... };
\r
216 * // Example using a generic network implementation.
\r
217 * networkInfo.createNetworkConnection = true;
\r
218 * networkInfo.pNetworkServerInfo = &serverInfo;
\r
219 * networkInfo.pNetworkCredentialInfo = &credentialInfo;
\r
220 * networkInfo.pNetworkInterface = &networkInterface;
\r
222 * // Set the members of the connection info (password and username not used).
\r
223 * connectInfo.cleanSession = true;
\r
224 * connectInfo.keepAliveSeconds = 30;
\r
225 * connectInfo.pClientIdentifier = "uniqueclientidentifier";
\r
226 * connectInfo.clientIdentifierLength = 22;
\r
228 * // Set the members of the will info (retain and retry not used).
\r
229 * willInfo.qos = IOT_MQTT_QOS_1;
\r
230 * willInfo.pTopicName = "will/topic/name";
\r
231 * willInfo.topicNameLength = 15;
\r
232 * willInfo.pPayload = "MQTT client unexpectedly disconnected.";
\r
233 * willInfo.payloadLength = 38;
\r
235 * // Set the pointer to the will info.
\r
236 * connectInfo.pWillInfo = &willInfo;
\r
238 * // Call CONNECT with a 5 second block time. Should return
\r
239 * // IOT_MQTT_SUCCESS when successful.
\r
240 * IotMqttError_t result = IotMqtt_Connect( &networkInfo,
\r
243 * &mqttConnection );
\r
245 * if( result == IOT_MQTT_SUCCESS )
\r
247 * // Do something with the MQTT connection...
\r
249 * // Clean up and close the MQTT connection once it's no longer needed.
\r
250 * IotMqtt_Disconnect( mqttConnection, 0 );
\r
254 /* @[declare_mqtt_connect] */
\r
255 IotMqttError_t IotMqtt_Connect( const IotMqttNetworkInfo_t * pNetworkInfo,
\r
256 const IotMqttConnectInfo_t * pConnectInfo,
\r
257 uint32_t timeoutMs,
\r
258 IotMqttConnection_t * const pMqttConnection );
\r
259 /* @[declare_mqtt_connect] */
\r
262 * @brief Closes an MQTT connection and frees resources.
\r
264 * This function closes an MQTT connection and should only be called once
\r
265 * the MQTT connection is no longer needed. Its exact behavior depends on the
\r
266 * `flags` parameter.
\r
268 * Normally, `flags` should be `0`. This gracefully shuts down an MQTT
\r
269 * connection by sending an MQTT DISCONNECT packet. Any [network close function]
\r
270 * (@ref IotNetworkInterface_t::close) provided [when the connection was established]
\r
271 * (@ref mqtt_function_connect) will also be called. Note that because the MQTT server
\r
272 * will not acknowledge a DISCONNECT packet, the client has no way of knowing if
\r
273 * the server received the DISCONNECT packet. In the case where the DISCONNECT
\r
274 * packet is lost in transport, any Last Will and Testament (LWT) message established
\r
275 * with the connection may be published. However, if the DISCONNECT reaches the
\r
276 * MQTT server, the LWT message will be discarded and not published.
\r
278 * Should the underlying network connection become unusable, this function should
\r
279 * be called with `flags` set to #IOT_MQTT_FLAG_CLEANUP_ONLY. In this case, no
\r
280 * DISCONNECT packet will be sent, though the [network close function](@ref IotNetworkInterface_t::close)
\r
281 * will still be called. This function will only free the resources used by the MQTT
\r
282 * connection; it still must be called even if the network is offline to avoid leaking
\r
285 * Once this function is called, its parameter `mqttConnection` should no longer
\r
288 * @param[in] mqttConnection The MQTT connection to close and clean up.
\r
289 * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags.
\r
291 /* @[declare_mqtt_disconnect] */
\r
292 void IotMqtt_Disconnect( IotMqttConnection_t mqttConnection,
\r
294 /* @[declare_mqtt_disconnect] */
\r
297 * @brief Subscribes to the given array of topic filters and receive an asynchronous
\r
298 * notification when the subscribe completes.
\r
300 * This function transmits an MQTT SUBSCRIBE packet to the server. A SUBSCRIBE
\r
301 * packet notifies the server to send any matching PUBLISH messages to this client.
\r
302 * A single SUBSCRIBE packet may carry more than one topic filter, hence the
\r
303 * parameters to this function include an array of [subscriptions]
\r
304 * (@ref IotMqttSubscription_t).
\r
306 * An MQTT subscription has two pieces:
\r
307 * 1. The subscription topic filter registered with the MQTT server. The MQTT
\r
308 * SUBSCRIBE packet sent from this client to server notifies the server to send
\r
309 * messages matching the given topic filters to this client.
\r
310 * 2. The [callback function](@ref IotMqttCallbackInfo_t.function) that this
\r
311 * client will invoke when an incoming message is received. The callback function
\r
312 * notifies applications of an incoming PUBLISH message.
\r
314 * The helper function @ref mqtt_function_issubscribed can be used to check if a
\r
315 * [callback function](@ref IotMqttCallbackInfo_t.function) is registered for
\r
316 * a particular topic filter.
\r
318 * To modify an already-registered subscription callback, call this function with
\r
319 * a new `pSubscriptionList`. Any topic filters in `pSubscriptionList` that already
\r
320 * have a registered callback will be replaced with the new values in `pSubscriptionList`.
\r
322 * @attention QoS 2 subscriptions are currently unsupported. Only 0 or 1 are valid
\r
323 * for subscription QoS.
\r
325 * @param[in] mqttConnection The MQTT connection to use for the subscription.
\r
326 * @param[in] pSubscriptionList Pointer to the first element in the array of
\r
328 * @param[in] subscriptionCount The number of elements in pSubscriptionList.
\r
329 * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags.
\r
330 * @param[in] pCallbackInfo Asynchronous notification of this function's completion.
\r
331 * @param[out] pSubscribeOperation Set to a handle by which this operation may be
\r
332 * referenced after this function returns. This reference is invalidated once
\r
333 * the subscription operation completes.
\r
335 * @return This function will return #IOT_MQTT_STATUS_PENDING upon success.
\r
336 * @return Upon completion of the subscription (either through an
\r
337 * #IotMqttCallbackInfo_t or @ref mqtt_function_wait), the status will be one of:
\r
338 * - #IOT_MQTT_SUCCESS
\r
339 * - #IOT_MQTT_NETWORK_ERROR
\r
340 * - #IOT_MQTT_SCHEDULING_ERROR
\r
341 * - #IOT_MQTT_BAD_RESPONSE
\r
342 * - #IOT_MQTT_SERVER_REFUSED
\r
343 * @return If this function fails before queuing a subscribe operation, it will return
\r
345 * - #IOT_MQTT_BAD_PARAMETER
\r
346 * - #IOT_MQTT_NO_MEMORY
\r
348 * @see @ref mqtt_function_timedsubscribe for a blocking variant of this function.
\r
349 * @see @ref mqtt_function_unsubscribe for the function that removes subscriptions.
\r
353 * #define NUMBER_OF_SUBSCRIPTIONS ...
\r
355 * // Subscription callback function.
\r
356 * void subscriptionCallback( void * pArgument, IotMqttCallbackParam_t * pPublish );
\r
358 * // An initialized and connected MQTT connection.
\r
359 * IotMqttConnection_t mqttConnection;
\r
361 * // Subscription information.
\r
362 * pSubscriptions[ NUMBER_OF_SUBSCRIPTIONS ] = { IOT_MQTT_SUBSCRIPTION_INITIALIZER };
\r
363 * IotMqttOperation_t lastOperation = IOT_MQTT_OPERATION_INITIALIZER;
\r
365 * // Set the subscription information.
\r
366 * for( int i = 0; i < NUMBER_OF_SUBSCRIPTIONS; i++ )
\r
368 * pSubscriptions[ i ].qos = IOT_MQTT_QOS_1;
\r
369 * pSubscriptions[ i ].pTopicFilter = "some/topic/filter";
\r
370 * pSubscriptions[ i ].topicLength = ( uint16_t ) strlen( pSubscriptions[ i ].pTopicFilter );
\r
371 * pSubscriptions[ i ].callback.function = subscriptionCallback;
\r
374 * IotMqttError_t result = IotMqtt_Subscribe( mqttConnection,
\r
376 * NUMBER_OF_SUBSCRIPTIONS,
\r
377 * IOT_MQTT_FLAG_WAITABLE,
\r
379 * &lastOperation );
\r
381 * // Subscribe returns IOT_MQTT_STATUS_PENDING when successful. Wait up to
\r
382 * // 5 seconds for the operation to complete.
\r
383 * if( result == IOT_MQTT_STATUS_PENDING )
\r
385 * result = IotMqtt_Wait( subscriptionRef, 5000 );
\r
388 * // Check that the subscriptions were successful.
\r
389 * if( result == IOT_MQTT_SUCCESS )
\r
391 * // Wait for messages on the subscription topic filters...
\r
393 * // Unsubscribe once the subscriptions are no longer needed.
\r
394 * result = IotMqtt_Unsubscribe( mqttConnection,
\r
396 * NUMBER_OF_SUBSCRIPTIONS,
\r
397 * IOT_MQTT_FLAG_WAITABLE,
\r
399 * &lastOperation );
\r
401 * // UNSUBSCRIBE returns IOT_MQTT_STATUS_PENDING when successful.
\r
402 * // Wait up to 5 seconds for the operation to complete.
\r
403 * if( result == IOT_MQTT_STATUS_PENDING )
\r
405 * result = IotMqtt_Wait( lastOperation, 5000 );
\r
408 * // Check which subscriptions were rejected by the server.
\r
409 * else if( result == IOT_MQTT_SERVER_REFUSED )
\r
411 * for( int i = 0; i < NUMBER_OF_SUBSCRIPTIONS; i++ )
\r
413 * if( IotMqtt_IsSubscribed( mqttConnection,
\r
414 * pSubscriptions[ i ].pTopicFilter,
\r
415 * pSubscriptions[ i ].topicFilterLength,
\r
416 * NULL ) == false )
\r
418 * // This subscription was rejected.
\r
424 /* @[declare_mqtt_subscribe] */
\r
425 IotMqttError_t IotMqtt_Subscribe( IotMqttConnection_t mqttConnection,
\r
426 const IotMqttSubscription_t * pSubscriptionList,
\r
427 size_t subscriptionCount,
\r
429 const IotMqttCallbackInfo_t * pCallbackInfo,
\r
430 IotMqttOperation_t * pSubscribeOperation );
\r
431 /* @[declare_mqtt_subscribe] */
\r
434 * @brief Subscribes to the given array of topic filters with a timeout.
\r
436 * This function transmits an MQTT SUBSCRIBE packet to the server, then waits for
\r
437 * a server response to the packet. Internally, this function is a call to @ref
\r
438 * mqtt_function_subscribe followed by @ref mqtt_function_wait. See @ref
\r
439 * mqtt_function_subscribe for more information about the MQTT SUBSCRIBE operation.
\r
441 * @attention QoS 2 subscriptions are currently unsupported. Only 0 or 1 are valid
\r
442 * for subscription QoS.
\r
444 * @param[in] mqttConnection The MQTT connection to use for the subscription.
\r
445 * @param[in] pSubscriptionList Pointer to the first element in the array of
\r
447 * @param[in] subscriptionCount The number of elements in pSubscriptionList.
\r
448 * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags.
\r
449 * Currently, flags are ignored by this function; this parameter is for
\r
450 * future-compatibility.
\r
451 * @param[in] timeoutMs If the MQTT server does not acknowledge the subscriptions within
\r
452 * this timeout, this function returns #IOT_MQTT_TIMEOUT.
\r
454 * @return One of the following:
\r
455 * - #IOT_MQTT_SUCCESS
\r
456 * - #IOT_MQTT_BAD_PARAMETER
\r
457 * - #IOT_MQTT_NO_MEMORY
\r
458 * - #IOT_MQTT_NETWORK_ERROR
\r
459 * - #IOT_MQTT_SCHEDULING_ERROR
\r
460 * - #IOT_MQTT_BAD_RESPONSE
\r
461 * - #IOT_MQTT_TIMEOUT
\r
462 * - #IOT_MQTT_SERVER_REFUSED
\r
464 /* @[declare_mqtt_timedsubscribe] */
\r
465 IotMqttError_t IotMqtt_TimedSubscribe( IotMqttConnection_t mqttConnection,
\r
466 const IotMqttSubscription_t * pSubscriptionList,
\r
467 size_t subscriptionCount,
\r
469 uint32_t timeoutMs );
\r
470 /* @[declare_mqtt_timedsubscribe] */
\r
473 * @brief Unsubscribes from the given array of topic filters and receive an asynchronous
\r
474 * notification when the unsubscribe completes.
\r
476 * This function transmits an MQTT UNSUBSCRIBE packet to the server. An UNSUBSCRIBE
\r
477 * packet removes registered topic filters from the server. After unsubscribing,
\r
478 * the server will no longer send messages on these topic filters to the client.
\r
480 * Corresponding [subscription callback functions](@ref IotMqttCallbackInfo_t.function)
\r
481 * are also removed from the MQTT connection. These subscription callback functions
\r
482 * will be removed even if the MQTT UNSUBSCRIBE packet fails to send.
\r
484 * @param[in] mqttConnection The MQTT connection used for the subscription.
\r
485 * @param[in] pSubscriptionList Pointer to the first element in the array of
\r
487 * @param[in] subscriptionCount The number of elements in pSubscriptionList.
\r
488 * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags.
\r
489 * @param[in] pCallbackInfo Asynchronous notification of this function's completion.
\r
490 * @param[out] pUnsubscribeOperation Set to a handle by which this operation may be
\r
491 * referenced after this function returns. This reference is invalidated once
\r
492 * the unsubscribe operation completes.
\r
494 * @return This function will return #IOT_MQTT_STATUS_PENDING upon success.
\r
495 * @return Upon completion of the unsubscribe (either through an
\r
496 * #IotMqttCallbackInfo_t or @ref mqtt_function_wait), the status will be one of:
\r
497 * - #IOT_MQTT_SUCCESS
\r
498 * - #IOT_MQTT_NETWORK_ERROR
\r
499 * - #IOT_MQTT_SCHEDULING_ERROR
\r
500 * - #IOT_MQTT_BAD_RESPONSE
\r
501 * @return If this function fails before queuing an unsubscribe operation, it will return
\r
503 * - #IOT_MQTT_BAD_PARAMETER
\r
504 * - #IOT_MQTT_NO_MEMORY
\r
506 * @see @ref mqtt_function_timedsubscribe for a blocking variant of this function.
\r
507 * @see @ref mqtt_function_subscribe for the function that adds subscriptions.
\r
509 /* @[declare_mqtt_unsubscribe] */
\r
510 IotMqttError_t IotMqtt_Unsubscribe( IotMqttConnection_t mqttConnection,
\r
511 const IotMqttSubscription_t * pSubscriptionList,
\r
512 size_t subscriptionCount,
\r
514 const IotMqttCallbackInfo_t * pCallbackInfo,
\r
515 IotMqttOperation_t * pUnsubscribeOperation );
\r
516 /* @[declare_mqtt_unsubscribe] */
\r
519 * @brief Unsubscribes from a given array of topic filters with a timeout.
\r
521 * This function transmits an MQTT UNSUBSCRIBE packet to the server, then waits
\r
522 * for a server response to the packet. Internally, this function is a call to
\r
523 * @ref mqtt_function_unsubscribe followed by @ref mqtt_function_wait. See @ref
\r
524 * mqtt_function_unsubscribe for more information about the MQTT UNSUBSCRIBE
\r
527 * @param[in] mqttConnection The MQTT connection used for the subscription.
\r
528 * @param[in] pSubscriptionList Pointer to the first element in the array of
\r
530 * @param[in] subscriptionCount The number of elements in pSubscriptionList.
\r
531 * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags.
\r
532 * Currently, flags are ignored by this function; this parameter is for
\r
533 * future-compatibility.
\r
534 * @param[in] timeoutMs If the MQTT server does not acknowledge the UNSUBSCRIBE within
\r
535 * this timeout, this function returns #IOT_MQTT_TIMEOUT.
\r
537 * @return One of the following:
\r
538 * - #IOT_MQTT_SUCCESS
\r
539 * - #IOT_MQTT_BAD_PARAMETER
\r
540 * - #IOT_MQTT_NO_MEMORY
\r
541 * - #IOT_MQTT_NETWORK_ERROR
\r
542 * - #IOT_MQTT_SCHEDULING_ERROR
\r
543 * - #IOT_MQTT_BAD_RESPONSE
\r
545 /* @[declare_mqtt_timedunsubscribe] */
\r
546 IotMqttError_t IotMqtt_TimedUnsubscribe( IotMqttConnection_t mqttConnection,
\r
547 const IotMqttSubscription_t * pSubscriptionList,
\r
548 size_t subscriptionCount,
\r
550 uint32_t timeoutMs );
\r
551 /* @[declare_mqtt_timedunsubscribe] */
\r
554 * @brief Publishes a message to the given topic name and receive an asynchronous
\r
555 * notification when the publish completes.
\r
557 * This function transmits an MQTT PUBLISH packet to the server. A PUBLISH packet
\r
558 * contains a payload and a topic name. Any clients with a subscription on a
\r
559 * topic filter matching the PUBLISH topic name will receive a copy of the
\r
560 * PUBLISH packet from the server.
\r
562 * If a PUBLISH packet fails to reach the server and it is not a QoS 0 message,
\r
563 * it will be retransmitted. See #IotMqttPublishInfo_t for a description
\r
564 * of the retransmission strategy.
\r
566 * @attention QoS 2 messages are currently unsupported. Only 0 or 1 are valid
\r
569 * @param[in] mqttConnection The MQTT connection to use for the publish.
\r
570 * @param[in] pPublishInfo MQTT publish parameters.
\r
571 * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags.
\r
572 * @param[in] pCallbackInfo Asynchronous notification of this function's completion.
\r
573 * @param[out] pPublishOperation Set to a handle by which this operation may be
\r
574 * referenced after this function returns. This reference is invalidated once
\r
575 * the publish operation completes.
\r
577 * @return This function will return #IOT_MQTT_STATUS_PENDING upon success for
\r
578 * QoS 1 publishes. For a QoS 0 publish it returns #IOT_MQTT_SUCCESS upon
\r
580 * @return Upon completion of a QoS 1 publish (either through an
\r
581 * #IotMqttCallbackInfo_t or @ref mqtt_function_wait), the status will be one of:
\r
582 * - #IOT_MQTT_SUCCESS
\r
583 * - #IOT_MQTT_NETWORK_ERROR
\r
584 * - #IOT_MQTT_SCHEDULING_ERROR
\r
585 * - #IOT_MQTT_BAD_RESPONSE
\r
586 * - #IOT_MQTT_RETRY_NO_RESPONSE (if [pPublishInfo->retryMs](@ref IotMqttPublishInfo_t.retryMs)
\r
587 * and [pPublishInfo->retryLimit](@ref IotMqttPublishInfo_t.retryLimit) were set).
\r
588 * @return If this function fails before queuing an publish operation (regardless
\r
589 * of QoS), it will return one of:
\r
590 * - #IOT_MQTT_BAD_PARAMETER
\r
591 * - #IOT_MQTT_NO_MEMORY
\r
593 * @note The parameters `pCallbackInfo` and `pPublishOperation` should only be used for QoS
\r
594 * 1 publishes. For QoS 0, they should both be `NULL`.
\r
596 * @see @ref mqtt_function_timedpublish for a blocking variant of this function.
\r
600 * // An initialized and connected MQTT connection.
\r
601 * IotMqttConnection_t mqttConnection;
\r
603 * // Publish information.
\r
604 * IotMqttPublishInfo_t publishInfo = IOT_MQTT_PUBLISH_INFO_INITIALIZER;
\r
606 * // Set the publish information. QoS 0 example (retain not used):
\r
607 * publishInfo.qos = IOT_MQTT_QOS_0;
\r
608 * publishInfo.pTopicName = "some/topic/name";
\r
609 * publishInfo.topicNameLength = 15;
\r
610 * publishInfo.pPayload = "payload";
\r
611 * publishInfo.payloadLength = 8;
\r
613 * // QoS 0 publish should return IOT_MQTT_SUCCESS upon success.
\r
614 * IotMqttError_t qos0Result = IotMqtt_Publish( mqttConnection,
\r
620 * // QoS 1 with retry example (using same topic name and payload as QoS 0 example):
\r
621 * IotMqttOperation_t qos1Operation = IOT_MQTT_OPERATION_INITIALIZER;
\r
622 * publishInfo.qos = IOT_MQTT_QOS_1;
\r
623 * publishInfo.retryMs = 1000; // Retry if no response is received in 1 second.
\r
624 * publishInfo.retryLimit = 5; // Retry up to 5 times.
\r
626 * // QoS 1 publish should return IOT_MQTT_STATUS_PENDING upon success.
\r
627 * IotMqttError_t qos1Result = IotMqtt_Publish( mqttConnection,
\r
629 * IOT_MQTT_FLAG_WAITABLE,
\r
631 * &qos1Operation );
\r
633 * // Wait up to 5 seconds for the publish to complete.
\r
634 * if( qos1Result == IOT_MQTT_STATUS_PENDING )
\r
636 * qos1Result = IotMqtt_Wait( qos1Operation, 5000 );
\r
640 /* @[declare_mqtt_publish] */
\r
641 IotMqttError_t IotMqtt_Publish( IotMqttConnection_t mqttConnection,
\r
642 const IotMqttPublishInfo_t * pPublishInfo,
\r
644 const IotMqttCallbackInfo_t * pCallbackInfo,
\r
645 IotMqttOperation_t * pPublishOperation );
\r
646 /* @[declare_mqtt_publish] */
\r
649 * @brief Publish a message to the given topic name with a timeout.
\r
651 * This function transmits an MQTT PUBLISH packet to the server, then waits for
\r
652 * a server response to the packet. Internally, this function is a call to @ref
\r
653 * mqtt_function_publish followed by @ref mqtt_function_wait. See @ref
\r
654 * mqtt_function_publish for more information about the MQTT PUBLISH operation.
\r
656 * @attention QoS 2 messages are currently unsupported. Only 0 or 1 are valid
\r
659 * @param[in] mqttConnection The MQTT connection to use for the publish.
\r
660 * @param[in] pPublishInfo MQTT publish parameters.
\r
661 * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags.
\r
662 * Currently, flags are ignored by this function; this parameter is for
\r
663 * future-compatibility.
\r
664 * @param[in] timeoutMs If the MQTT server does not acknowledge a QoS 1 PUBLISH
\r
665 * within this timeout, this function returns #IOT_MQTT_TIMEOUT. This parameter
\r
666 * is ignored for QoS 0 PUBLISH messages.
\r
668 * @return One of the following:
\r
669 * - #IOT_MQTT_SUCCESS
\r
670 * - #IOT_MQTT_BAD_PARAMETER
\r
671 * - #IOT_MQTT_NO_MEMORY
\r
672 * - #IOT_MQTT_NETWORK_ERROR
\r
673 * - #IOT_MQTT_SCHEDULING_ERROR
\r
674 * - #IOT_MQTT_BAD_RESPONSE
\r
675 * - #IOT_MQTT_RETRY_NO_RESPONSE (if [pPublishInfo->retryMs](@ref IotMqttPublishInfo_t.retryMs)
\r
676 * and [pPublishInfo->retryLimit](@ref IotMqttPublishInfo_t.retryLimit) were set).
\r
678 /* @[declare_mqtt_timedpublish] */
\r
679 IotMqttError_t IotMqtt_TimedPublish( IotMqttConnection_t mqttConnection,
\r
680 const IotMqttPublishInfo_t * pPublishInfo,
\r
682 uint32_t timeoutMs );
\r
683 /* @[declare_mqtt_timedpublish] */
\r
686 * @brief Waits for an operation to complete.
\r
688 * This function blocks to wait for a [subscribe](@ref mqtt_function_subscribe),
\r
689 * [unsubscribe](@ref mqtt_function_unsubscribe), or [publish]
\r
690 * (@ref mqtt_function_publish) to complete. These operations are by default
\r
691 * asynchronous; the function calls queue an operation for processing, and a
\r
692 * callback is invoked once the operation is complete.
\r
694 * To use this function, the flag #IOT_MQTT_FLAG_WAITABLE must have been
\r
695 * set in the operation's function call. Additionally, this function must always
\r
696 * be called with any waitable operation to clean up resources.
\r
698 * Regardless of its return value, this function always clean up resources used
\r
699 * by the waitable operation. This means `reference` is invalidated as soon as
\r
700 * this function returns, even if it returns #IOT_MQTT_TIMEOUT or another error.
\r
702 * @param[in] operation Reference to the operation to wait for. The flag
\r
703 * #IOT_MQTT_FLAG_WAITABLE must have been set for this operation.
\r
704 * @param[in] timeoutMs How long to wait before returning #IOT_MQTT_TIMEOUT.
\r
706 * @return The return value of this function depends on the MQTT operation associated
\r
707 * with `reference`. See #IotMqttError_t for possible return values.
\r
711 * // Operation reference and timeout.
\r
712 * IotMqttOperation_t publishOperation = IOT_MQTT_OPERATION_INITIALIZER;
\r
713 * uint32_t timeoutMs = 5000; // 5 seconds
\r
715 * // MQTT operation to wait for.
\r
716 * IotMqttError_t result = IotMqtt_Publish( mqttConnection,
\r
718 * IOT_MQTT_FLAG_WAITABLE,
\r
720 * &publishOperation );
\r
722 * // Publish should have returned IOT_MQTT_STATUS_PENDING. The call to wait
\r
723 * // returns once the result of the publish is available or the timeout expires.
\r
724 * if( result == IOT_MQTT_STATUS_PENDING )
\r
726 * result = IotMqtt_Wait( publishOperation, timeoutMs );
\r
728 * // After the call to wait, the result of the publish is known
\r
729 * // (not IOT_MQTT_STATUS_PENDING).
\r
730 * assert( result != IOT_MQTT_STATUS_PENDING );
\r
734 /* @[declare_mqtt_wait] */
\r
735 IotMqttError_t IotMqtt_Wait( IotMqttOperation_t operation,
\r
736 uint32_t timeoutMs );
\r
737 /* @[declare_mqtt_wait] */
\r
739 /*-------------------------- MQTT helper functions --------------------------*/
\r
742 * @brief Returns a string that describes an #IotMqttError_t.
\r
744 * Like the POSIX's `strerror`, this function returns a string describing a
\r
745 * return code. In this case, the return code is an MQTT library error code,
\r
748 * The string returned by this function <b>MUST</b> be treated as read-only: any
\r
749 * attempt to modify its contents may result in a crash. Therefore, this function
\r
750 * is limited to usage in logging.
\r
752 * @param[in] status The status to describe.
\r
754 * @return A read-only string that describes `status`.
\r
756 * @warning The string returned by this function must never be modified.
\r
758 /* @[declare_mqtt_strerror] */
\r
759 const char * IotMqtt_strerror( IotMqttError_t status );
\r
760 /* @[declare_mqtt_strerror] */
\r
763 * @brief Returns a string that describes an #IotMqttOperationType_t.
\r
765 * This function returns a string describing an MQTT operation type, `operation`.
\r
767 * The string returned by this function <b>MUST</b> be treated as read-only: any
\r
768 * attempt to modify its contents may result in a crash. Therefore, this function
\r
769 * is limited to usage in logging.
\r
771 * @param[in] operation The operation to describe.
\r
773 * @return A read-only string that describes `operation`.
\r
775 * @warning The string returned by this function must never be modified.
\r
777 /* @[declare_mqtt_operationtype] */
\r
778 const char * IotMqtt_OperationType( IotMqttOperationType_t operation );
\r
779 /* @[declare_mqtt_operationtype] */
\r
782 * @brief Check if an MQTT connection has a subscription for a topic filter.
\r
784 * This function checks whether an MQTT connection `mqttConnection` has a
\r
785 * subscription callback registered for a topic filter `pTopicFilter`. If a
\r
786 * subscription callback is found, its details are copied into the output parameter
\r
787 * `pCurrentSubscription`. This subscription callback will be invoked for incoming
\r
788 * PUBLISH messages on `pTopicFilter`.
\r
790 * <b>The check for a matching subscription is only performed client-side</b>;
\r
791 * therefore, this function should not be relied upon for perfect accuracy. For
\r
792 * example, this function may return an incorrect result if the MQTT server
\r
793 * crashes and drops subscriptions without informing the client.
\r
795 * Note that an MQTT connection's subscriptions might change between the time this
\r
796 * function checks the subscription list and its caller tests the return value.
\r
797 * This function certainly should not be used concurrently with any pending SUBSCRIBE
\r
798 * or UNSUBSCRIBE operations.
\r
800 * One suitable use of this function is to check <i>which</i> subscriptions were rejected
\r
801 * if @ref mqtt_function_subscribe returns #IOT_MQTT_SERVER_REFUSED; that return
\r
802 * code only means that <i>at least one</i> subscription was rejected.
\r
804 * @param[in] mqttConnection The MQTT connection to check.
\r
805 * @param[in] pTopicFilter The topic filter to check.
\r
806 * @param[in] topicFilterLength Length of `pTopicFilter`.
\r
807 * @param[out] pCurrentSubscription If a subscription is found, its details are
\r
808 * copied here. This output parameter is only valid if this function returns `true`.
\r
809 * Pass `NULL` to ignore.
\r
811 * @return `true` if a subscription was found; `false` otherwise.
\r
813 * @note The subscription QoS is not stored by the MQTT library; therefore,
\r
814 * `pCurrentSubscription->qos` will always be set to #IOT_MQTT_QOS_0.
\r
816 /* @[declare_mqtt_issubscribed] */
\r
817 bool IotMqtt_IsSubscribed( IotMqttConnection_t mqttConnection,
\r
818 const char * pTopicFilter,
\r
819 uint16_t topicFilterLength,
\r
820 IotMqttSubscription_t * pCurrentSubscription );
\r
821 /* @[declare_mqtt_issubscribed] */
\r
823 #endif /* ifndef IOT_MQTT_H_ */
\r