]> git.sur5r.net Git - freertos/blob - FreeRTOS-Labs/Source/FreeRTOS-IoT-Libraries/c_sdk/standard/mqtt/include/iot_mqtt.h
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Source / FreeRTOS-IoT-Libraries / c_sdk / standard / mqtt / include / iot_mqtt.h
1 /*\r
2  * IoT MQTT V2.1.0\r
3  * Copyright (C) 2018 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\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
11  *\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
14  *\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
21  */\r
22 \r
23 /**\r
24  * @file iot_mqtt.h\r
25  * @brief User-facing functions of the MQTT 3.1.1 library.\r
26  */\r
27 \r
28 #ifndef IOT_MQTT_H_\r
29 #define IOT_MQTT_H_\r
30 \r
31 /* The config header is always included first. */\r
32 #include "iot_config.h"\r
33 \r
34 /* MQTT types include. */\r
35 #include "types/iot_mqtt_types.h"\r
36 \r
37 /*------------------------- MQTT library functions --------------------------*/\r
38 \r
39 /**\r
40  * @functionspage{mqtt,MQTT library}\r
41  * - @functionname{mqtt_function_init}\r
42  * - @functionname{mqtt_function_cleanup}\r
43  * - @functionname{mqtt_function_receivecallback}\r
44  * - @functionname{mqtt_function_connect}\r
45  * - @functionname{mqtt_function_disconnect}\r
46  * - @functionname{mqtt_function_subscribeasync}\r
47  * - @functionname{mqtt_function_subscribesync}\r
48  * - @functionname{mqtt_function_unsubscribeasync}\r
49  * - @functionname{mqtt_function_unsubscribesync}\r
50  * - @functionname{mqtt_function_publishasync}\r
51  * - @functionname{mqtt_function_publishsync}\r
52  * - @functionname{mqtt_function_wait}\r
53  * - @functionname{mqtt_function_strerror}\r
54  * - @functionname{mqtt_function_operationtype}\r
55  * - @functionname{mqtt_function_issubscribed}\r
56  */\r
57 \r
58 /**\r
59  * @functionpage{IotMqtt_Init,mqtt,init}\r
60  * @functionpage{IotMqtt_Cleanup,mqtt,cleanup}\r
61  * @functionpage{IotMqtt_ReceiveCallback,mqtt,receivecallback}\r
62  * @functionpage{IotMqtt_Connect,mqtt,connect}\r
63  * @functionpage{IotMqtt_Disconnect,mqtt,disconnect}\r
64  * @functionpage{IotMqtt_SubscribeAsync,mqtt,subscribeasync}\r
65  * @functionpage{IotMqtt_SubscribeSync,mqtt,subscribesync}\r
66  * @functionpage{IotMqtt_UnsubscribeAsync,mqtt,unsubscribeasync}\r
67  * @functionpage{IotMqtt_UnsubscribeSync,mqtt,unsubscribesync}\r
68  * @functionpage{IotMqtt_PublishAsync,mqtt,publishasync}\r
69  * @functionpage{IotMqtt_PublishSync,mqtt,publishsync}\r
70  * @functionpage{IotMqtt_Wait,mqtt,wait}\r
71  * @functionpage{IotMqtt_strerror,mqtt,strerror}\r
72  * @functionpage{IotMqtt_OperationType,mqtt,operationtype}\r
73  * @functionpage{IotMqtt_IsSubscribed,mqtt,issubscribed}\r
74  */\r
75 \r
76 /**\r
77  * @brief One-time initialization function for the MQTT library.\r
78  *\r
79  * This function performs setup of the MQTT library. <b>It must be called\r
80  * once (and only once) before calling any other MQTT function.</b> Calling this\r
81  * function more than once without first calling @ref mqtt_function_cleanup\r
82  * may result in a crash.\r
83  *\r
84  * @return One of the following:\r
85  * - #IOT_MQTT_SUCCESS\r
86  * - #IOT_MQTT_NOT_INITIALIZED\r
87  *\r
88  * @warning No thread-safety guarantees are provided for this function.\r
89  *\r
90  * @see @ref mqtt_function_cleanup\r
91  */\r
92 /* @[declare_mqtt_init] */\r
93 IotMqttError_t IotMqtt_Init( void );\r
94 /* @[declare_mqtt_init] */\r
95 \r
96 /**\r
97  * @brief One-time deinitialization function for the MQTT library.\r
98  *\r
99  * This function frees resources taken in @ref mqtt_function_init. It should be\r
100  * called after [closing all MQTT connections](@ref mqtt_function_disconnect) to\r
101  * clean up the MQTT library. After this function returns, @ref mqtt_function_init\r
102  * must be called again before calling any other MQTT function.\r
103  *\r
104  * @warning No thread-safety guarantees are provided for this function. Do not\r
105  * call this function if any MQTT connections are open!\r
106  *\r
107  * @see @ref mqtt_function_init\r
108  */\r
109 /* @[declare_mqtt_cleanup] */\r
110 void IotMqtt_Cleanup( void );\r
111 /* @[declare_mqtt_cleanup] */\r
112 \r
113 /**\r
114  * @brief Network receive callback for the MQTT library.\r
115  *\r
116  * This function should be called by the system whenever data is available for\r
117  * the MQTT library.\r
118  *\r
119  * @param[in] pNetworkConnection The network connection associated with the MQTT\r
120  * connection, passed by the network stack.\r
121  * @param[in] pReceiveContext A pointer to the MQTT connection handle for which\r
122  * the packet was received.\r
123  */\r
124 /* @[declare_mqtt_receivecallback] */\r
125 void IotMqtt_ReceiveCallback( IotNetworkConnection_t pNetworkConnection,\r
126                               void * pReceiveContext );\r
127 /* @[declare_mqtt_receivecallback] */\r
128 \r
129 /**\r
130  * @brief Establish a new MQTT connection.\r
131  *\r
132  * This function opens a connection between a new MQTT client and an MQTT server\r
133  * (also called a <i>broker</i>). MQTT connections are established on top of transport\r
134  * layer protocols (such as TCP/IP), and optionally, application layer security\r
135  * protocols (such as TLS). The MQTT packet that establishes a connection is called\r
136  * the MQTT CONNECT packet. After @ref mqtt_function_init, this function must be\r
137  * called before any other MQTT library function.\r
138  *\r
139  * If [pConnectInfo->cleanSession](@ref IotMqttConnectInfo_t.cleanSession) is `true`,\r
140  * this function establishes a clean MQTT session. Subscriptions and unacknowledged\r
141  * PUBLISH messages will be discarded when the connection is closed.\r
142  *\r
143  * If [pConnectInfo->cleanSession](@ref IotMqttConnectInfo_t.cleanSession) is `false`,\r
144  * this function establishes (or re-establishes) a persistent MQTT session. The parameters\r
145  * [pConnectInfo->pPreviousSubscriptions](@ref IotMqttConnectInfo_t.pPreviousSubscriptions)\r
146  * and [pConnectInfo->previousSubscriptionCount](@ref IotMqttConnectInfo_t.previousSubscriptionCount)\r
147  * may be used to restore subscriptions present in a re-established persistent session.\r
148  * Any restored subscriptions <b>MUST</b> have been present in the persistent session;\r
149  * <b>this function does not send an MQTT SUBSCRIBE packet!</b>\r
150  *\r
151  * [pConnectInfo->pPreviousSubscriptions](@ref IotMqttConnectInfo_t.pPreviousSubscriptions)\r
152  * and [pConnectInfo->previousSubscriptionCount](@ref IotMqttConnectInfo_t.previousSubscriptionCount) can\r
153  * also be used to pass a list of subscriptions to be stored locally without a SUBSCRIBE packet being\r
154  * sent to the broker. These subscriptions are useful to invoke application level callbacks for messages received\r
155  * on unsolicited topics from the broker.\r
156  *\r
157  * This MQTT library is network agnostic, meaning it has no knowledge of the\r
158  * underlying network protocol carrying the MQTT packets. It interacts with the\r
159  * network through a network abstraction layer, allowing it to be used with many\r
160  * different network stacks. The network abstraction layer is established\r
161  * per-connection, allowing every #IotMqttConnection_t to use a different network\r
162  * stack. The parameter `pNetworkInterface` sets up the network abstraction layer\r
163  * for an MQTT connection; see the documentation on #IotMqttNetworkInfo_t for details\r
164  * on its members.\r
165  *\r
166  * The `pConnectInfo` parameter provides the contents of the MQTT CONNECT packet.\r
167  * Most members [are defined by the MQTT spec.](@ref IotMqttConnectInfo_t). The\r
168  * [pConnectInfo->pWillInfo](@ref IotMqttConnectInfo_t.pWillInfo) member provides\r
169  * information on a Last Will and Testament (LWT) message to be published if the\r
170  * MQTT connection is closed without [sending a DISCONNECT packet]\r
171  * (@ref mqtt_function_disconnect). Unlike other PUBLISH\r
172  * messages, a LWT message payload is limited to 65535 bytes in length. Additionally,\r
173  * the retry [interval](@ref IotMqttPublishInfo_t.retryMs) and [limit]\r
174  * (@ref IotMqttPublishInfo_t.retryLimit) members of #IotMqttPublishInfo_t\r
175  * are ignored for LWT messages. The LWT message is optional; `pWillInfo` may be NULL.\r
176  *\r
177  * Unlike @ref mqtt_function_publishasync, @ref mqtt_function_subscribeasync, and\r
178  * @ref mqtt_function_unsubscribeasync, this function is always blocking. Additionally,\r
179  * because the MQTT connection acknowledgement packet (CONNACK packet) does not\r
180  * contain any information on <i>which</i> CONNECT packet it acknowledges, only one\r
181  * CONNECT operation may be in progress at any time. This means that parallel\r
182  * threads making calls to @ref mqtt_function_connect will be serialized to send\r
183  * their CONNECT packets one-by-one.\r
184  *\r
185  * @param[in] pNetworkInfo Information on the transport-layer network connection\r
186  * to use with the MQTT connection.\r
187  * @param[in] pConnectInfo MQTT connection setup parameters.\r
188  * @param[in] timeoutMs If the MQTT server does not accept the connection within\r
189  * this timeout in milliseconds, this function returns #IOT_MQTT_TIMEOUT.\r
190  * @param[out] pMqttConnection Set to a newly-initialized MQTT connection handle\r
191  * if this function succeeds.\r
192  *\r
193  * @return One of the following:\r
194  * - #IOT_MQTT_SUCCESS\r
195  * - #IOT_MQTT_NOT_INITIALIZED\r
196  * - #IOT_MQTT_BAD_PARAMETER\r
197  * - #IOT_MQTT_NO_MEMORY\r
198  * - #IOT_MQTT_NETWORK_ERROR\r
199  * - #IOT_MQTT_SCHEDULING_ERROR\r
200  * - #IOT_MQTT_BAD_RESPONSE\r
201  * - #IOT_MQTT_TIMEOUT\r
202  * - #IOT_MQTT_SERVER_REFUSED\r
203  *\r
204  * <b>Example</b>\r
205  * @code{c}\r
206  *\r
207  * // Callback function to receive messages from the broker on an unsolicited topic.\r
208  * void unsolicitedMessageCallback( void * pArgument, IotMqttCallbackParam_t * pPublish );\r
209  *\r
210  * // Parameters to MQTT connect.\r
211  * IotMqttConnection_t mqttConnection = IOT_MQTT_CONNECTION_INITIALIZER;\r
212  * IotMqttNetworkInfo_t networkInfo = IOT_MQTT_NETWORK_INFO_INITIALIZER;\r
213  * IotMqttConnectInfo_t connectInfo = IOT_MQTT_CONNECT_INFO_INITIALIZER;\r
214  * IotMqttPublishInfo_t willInfo = IOT_MQTT_PUBLISH_INFO_INITIALIZER;\r
215  *\r
216  * // A local subscription to receive messages from the broker on an unsolicited topic.\r
217  * IotMqttSubscription_t subscription = IOT_MQTT_SUBSCRIPTION_INITIALIZER;\r
218  *\r
219  * // Example network abstraction types.\r
220  * IotNetworkServerInfo_t serverInfo = { ... };\r
221  * IotNetworkCredentials_t credentialInfo = { ... };\r
222  * IotNetworkInterface_t networkInterface = { ... };\r
223  *\r
224  * // Example using a generic network implementation.\r
225  * networkInfo.createNetworkConnection = true;\r
226  * networkInfo.u.setup.pNetworkServerInfo = &serverInfo;\r
227  * networkInfo.u.setup.pNetworkCredentialInfo = &credentialInfo;\r
228  * networkInfo.pNetworkInterface = &networkInterface;\r
229  *\r
230  * // Set the members of the connection info (password and username not used).\r
231  * connectInfo.cleanSession = true;\r
232  * connectInfo.keepAliveSeconds = 30;\r
233  * connectInfo.pClientIdentifier = "uniqueclientidentifier";\r
234  * connectInfo.clientIdentifierLength = 22;\r
235  *\r
236  * // Set the members of the will info (retain and retry not used).\r
237  * willInfo.qos = IOT_MQTT_QOS_1;\r
238  * willInfo.pTopicName = "will/topic/name";\r
239  * willInfo.topicNameLength = ( uint16_t ) strlen( willInfo.pTopicName );\r
240  * willInfo.pPayload = "MQTT client unexpectedly disconnected.";\r
241  * willInfo.payloadLength = strlen( willInfo.pPayload );\r
242  *\r
243  * // Set the pointer to the will info.\r
244  * connectInfo.pWillInfo = &willInfo;\r
245  *\r
246  * // [Optional] Set a local subscription to receive the broker messages on an unsolicited topic.\r
247  * subscription.qos = IOT_MQTT_QOS_0;\r
248  * subscription.pTopicFilter = "some/unsolicited/topic";\r
249  * subscription.topicLength = ( uint16_t ) strlen( subscription.pTopicFilter );\r
250  * subscription.callback.function = unsolicitedMessageCallback;\r
251  * connectInfo.pPreviousSubscriptions = &subscription;\r
252  * connectInfo.previousSubscriptionCount = 1;\r
253  *\r
254  *\r
255  * // Call CONNECT with a 5 second block time. Should return\r
256  * // IOT_MQTT_SUCCESS when successful.\r
257  * IotMqttError_t result = IotMqtt_Connect( &networkInfo,\r
258  *                                          &connectInfo,\r
259  *                                          5000,\r
260  *                                          &mqttConnection );\r
261  *\r
262  * if( result == IOT_MQTT_SUCCESS )\r
263  * {\r
264  *     // Do something with the MQTT connection...\r
265  *\r
266  *     // Clean up and close the MQTT connection once it's no longer needed.\r
267  *     IotMqtt_Disconnect( mqttConnection, 0 );\r
268  * }\r
269  * @endcode\r
270  */\r
271 /* @[declare_mqtt_connect] */\r
272 IotMqttError_t IotMqtt_Connect( const IotMqttNetworkInfo_t * pNetworkInfo,\r
273                                 const IotMqttConnectInfo_t * pConnectInfo,\r
274                                 uint32_t timeoutMs,\r
275                                 IotMqttConnection_t * const pMqttConnection );\r
276 /* @[declare_mqtt_connect] */\r
277 \r
278 /**\r
279  * @brief Closes an MQTT connection and frees resources.\r
280  *\r
281  * This function closes an MQTT connection and should only be called once\r
282  * the MQTT connection is no longer needed. Its exact behavior depends on the\r
283  * `flags` parameter.\r
284  *\r
285  * Normally, `flags` should be `0`. This gracefully shuts down an MQTT\r
286  * connection by sending an MQTT DISCONNECT packet. Any [network close function]\r
287  * (@ref IotNetworkInterface_t::close) provided [when the connection was established]\r
288  * (@ref mqtt_function_connect) will also be called. Note that because the MQTT server\r
289  * will not acknowledge a DISCONNECT packet, the client has no way of knowing if\r
290  * the server received the DISCONNECT packet. In the case where the DISCONNECT\r
291  * packet is lost in transport, any Last Will and Testament (LWT) message established\r
292  * with the connection may be published. However, if the DISCONNECT reaches the\r
293  * MQTT server, the LWT message will be discarded and not published.\r
294  *\r
295  * Should the underlying network connection become unusable, this function should\r
296  * be called with `flags` set to #IOT_MQTT_FLAG_CLEANUP_ONLY. In this case, no\r
297  * DISCONNECT packet will be sent, though the [network close function](@ref IotNetworkInterface_t::close)\r
298  * will still be called. This function will only free the resources used by the MQTT\r
299  * connection; it still must be called even if the network is offline to avoid leaking\r
300  * resources.\r
301  *\r
302  * @ref mqtt_function_disconnect modifies `mqttConnection`, so it shouldn't\r
303  * be used after calling this function.\r
304  *\r
305  * @param[in] mqttConnection The MQTT connection to close and clean up.\r
306  * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags.\r
307  */\r
308 /* @[declare_mqtt_disconnect] */\r
309 void IotMqtt_Disconnect( IotMqttConnection_t mqttConnection,\r
310                          uint32_t flags );\r
311 /* @[declare_mqtt_disconnect] */\r
312 \r
313 /**\r
314  * @brief Subscribes to the given array of topic filters and optionally\r
315  * receive an asynchronous notification when the subscribe completes.\r
316  *\r
317  * This function sends an MQTT SUBSCRIBE packet to the server. A SUBSCRIBE\r
318  * packet notifies the server to send any matching PUBLISH messages to this client.\r
319  * A single SUBSCRIBE packet may carry more than one topic filter, hence the\r
320  * parameters to this function include an array of [subscriptions]\r
321  * (@ref IotMqttSubscription_t).\r
322  *\r
323  * An MQTT subscription has two pieces:\r
324  * 1. The subscription topic filter registered with the MQTT server. The MQTT\r
325  * SUBSCRIBE packet sent from this client to server notifies the server to send\r
326  * messages matching the given topic filters to this client.\r
327  * 2. The [callback function](@ref IotMqttCallbackInfo_t.function) that this\r
328  * client will invoke when an incoming message is received. The callback function\r
329  * notifies applications of an incoming PUBLISH message.\r
330  *\r
331  * The helper function @ref mqtt_function_issubscribed can be used to check if a\r
332  * [callback function](@ref IotMqttCallbackInfo_t.function) is registered for\r
333  * a particular topic filter.\r
334  *\r
335  * To modify an already-registered subscription callback, call this function with\r
336  * a new `pSubscriptionList`. Any topic filters in `pSubscriptionList` that already\r
337  * have a registered callback will be replaced with the new values in `pSubscriptionList`.\r
338  *\r
339  * @attention QoS 2 subscriptions are currently unsupported. Only 0 or 1 are valid\r
340  * for subscription QoS.\r
341  *\r
342  * @param[in] mqttConnection The MQTT connection to use for the subscription.\r
343  * @param[in] pSubscriptionList Pointer to the first element in the array of\r
344  * subscriptions.\r
345  * @param[in] subscriptionCount The number of elements in pSubscriptionList.\r
346  * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags.\r
347  * @param[in] pCallbackInfo Asynchronous notification of this function's completion (`NULL` to disable).\r
348  * @param[out] pSubscribeOperation Set to a handle by which this operation may be\r
349  * referenced after this function returns. This reference is invalidated once\r
350  * the subscription operation completes.\r
351  *\r
352  * @return This function will return #IOT_MQTT_STATUS_PENDING upon success.\r
353  * @return Upon completion of the subscription (either through an\r
354  * #IotMqttCallbackInfo_t or @ref mqtt_function_wait), the status will be one of:\r
355  * - #IOT_MQTT_SUCCESS\r
356  * - #IOT_MQTT_NETWORK_ERROR\r
357  * - #IOT_MQTT_SCHEDULING_ERROR\r
358  * - #IOT_MQTT_BAD_RESPONSE\r
359  * - #IOT_MQTT_SERVER_REFUSED\r
360  * @return If this function fails before queuing a subscribe operation, it will return\r
361  * one of:\r
362  * - #IOT_MQTT_NOT_INITIALIZED\r
363  * - #IOT_MQTT_BAD_PARAMETER\r
364  * - #IOT_MQTT_NO_MEMORY\r
365  *\r
366  * @see @ref mqtt_function_subscribesync for a blocking variant of this function.\r
367  * @see @ref mqtt_function_unsubscribeasync for the function that removes subscriptions.\r
368  *\r
369  * <b>Example</b>\r
370  * @code{c}\r
371  * #define NUMBER_OF_SUBSCRIPTIONS ...\r
372  *\r
373  * // Subscription callback function.\r
374  * void subscriptionCallback( void * pArgument, IotMqttCallbackParam_t * pPublish );\r
375  *\r
376  * // An initialized and connected MQTT connection.\r
377  * IotMqttConnection_t mqttConnection;\r
378  *\r
379  * // Subscription information.\r
380  * pSubscriptions[ NUMBER_OF_SUBSCRIPTIONS ] = { IOT_MQTT_SUBSCRIPTION_INITIALIZER };\r
381  * IotMqttOperation_t lastOperation = IOT_MQTT_OPERATION_INITIALIZER;\r
382  *\r
383  * // Set the subscription information.\r
384  * for( int i = 0; i < NUMBER_OF_SUBSCRIPTIONS; i++ )\r
385  * {\r
386  *     pSubscriptions[ i ].qos = IOT_MQTT_QOS_1;\r
387  *     pSubscriptions[ i ].pTopicFilter = "some/topic/filter";\r
388  *     pSubscriptions[ i ].topicLength = ( uint16_t ) strlen( pSubscriptions[ i ].pTopicFilter );\r
389  *     pSubscriptions[ i ].callback.function = subscriptionCallback;\r
390  * }\r
391  *\r
392  * IotMqttError_t result = IotMqtt_SubscribeAsync( mqttConnection,\r
393  *                                                 pSubscriptions,\r
394  *                                                 NUMBER_OF_SUBSCRIPTIONS,\r
395  *                                                 IOT_MQTT_FLAG_WAITABLE,\r
396  *                                                 NULL,\r
397  *                                                 &lastOperation );\r
398  *\r
399  * // Subscribe returns IOT_MQTT_STATUS_PENDING when successful. Wait up to\r
400  * // 5 seconds for the operation to complete.\r
401  * if( result == IOT_MQTT_STATUS_PENDING )\r
402  * {\r
403  *     result = IotMqtt_Wait( subscriptionRef, 5000 );\r
404  * }\r
405  *\r
406  * // Check that the subscriptions were successful.\r
407  * if( result == IOT_MQTT_SUCCESS )\r
408  * {\r
409  *     // Wait for messages on the subscription topic filters...\r
410  *\r
411  *     // Unsubscribe once the subscriptions are no longer needed.\r
412  *     result = IotMqtt_UnsubscribeAsync( mqttConnection,\r
413  *                                        pSubscriptions,\r
414  *                                        NUMBER_OF_SUBSCRIPTIONS,\r
415  *                                        IOT_MQTT_FLAG_WAITABLE,\r
416  *                                        NULL,\r
417  *                                        &lastOperation );\r
418  *\r
419  *     // UNSUBSCRIBE returns IOT_MQTT_STATUS_PENDING when successful.\r
420  *     // Wait up to 5 seconds for the operation to complete.\r
421  *     if( result == IOT_MQTT_STATUS_PENDING )\r
422  *     {\r
423  *         result = IotMqtt_Wait( lastOperation, 5000 );\r
424  *     }\r
425  * }\r
426  * // Check which subscriptions were rejected by the server.\r
427  * else if( result == IOT_MQTT_SERVER_REFUSED )\r
428  * {\r
429  *     for( int i = 0; i < NUMBER_OF_SUBSCRIPTIONS; i++ )\r
430  *     {\r
431  *         if( IotMqtt_IsSubscribed( mqttConnection,\r
432  *                                   pSubscriptions[ i ].pTopicFilter,\r
433  *                                   pSubscriptions[ i ].topicFilterLength,\r
434  *                                   NULL ) == false )\r
435  *         {\r
436  *             // This subscription was rejected.\r
437  *         }\r
438  *     }\r
439  * }\r
440  * @endcode\r
441  */\r
442 /* @[declare_mqtt_subscribeasync] */\r
443 IotMqttError_t IotMqtt_SubscribeAsync( IotMqttConnection_t mqttConnection,\r
444                                        const IotMqttSubscription_t * pSubscriptionList,\r
445                                        size_t subscriptionCount,\r
446                                        uint32_t flags,\r
447                                        const IotMqttCallbackInfo_t * pCallbackInfo,\r
448                                        IotMqttOperation_t * const pSubscribeOperation );\r
449 /* @[declare_mqtt_subscribeasync] */\r
450 \r
451 /**\r
452  * @brief Subscribes to the given array of topic filters with a timeout.\r
453  *\r
454  * This function sends an MQTT SUBSCRIBE packet to the server, then waits for\r
455  * a server response to the packet. Internally, this function is a call to @ref\r
456  * mqtt_function_subscribeasync followed by @ref mqtt_function_wait. See @ref\r
457  * mqtt_function_subscribeasync for more information about the MQTT SUBSCRIBE operation.\r
458  *\r
459  * @attention QoS 2 subscriptions are currently unsupported. Only 0 or 1 are valid\r
460  * for subscription QoS.\r
461  *\r
462  * @param[in] mqttConnection The MQTT connection to use for the subscription.\r
463  * @param[in] pSubscriptionList Pointer to the first element in the array of\r
464  * subscriptions.\r
465  * @param[in] subscriptionCount The number of elements in pSubscriptionList.\r
466  * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags.\r
467  * Currently, flags are ignored by this function; this parameter is for\r
468  * future-compatibility.\r
469  * @param[in] timeoutMs If the MQTT server does not acknowledge the subscriptions within\r
470  * this timeout in milliseconds, this function returns #IOT_MQTT_TIMEOUT.\r
471  *\r
472  * @return One of the following:\r
473  * - #IOT_MQTT_SUCCESS\r
474  * - #IOT_MQTT_NOT_INITIALIZED\r
475  * - #IOT_MQTT_BAD_PARAMETER\r
476  * - #IOT_MQTT_NO_MEMORY\r
477  * - #IOT_MQTT_NETWORK_ERROR\r
478  * - #IOT_MQTT_SCHEDULING_ERROR\r
479  * - #IOT_MQTT_BAD_RESPONSE\r
480  * - #IOT_MQTT_TIMEOUT\r
481  * - #IOT_MQTT_SERVER_REFUSED\r
482  */\r
483 /* @[declare_mqtt_subscribesync] */\r
484 IotMqttError_t IotMqtt_SubscribeSync( IotMqttConnection_t mqttConnection,\r
485                                       const IotMqttSubscription_t * pSubscriptionList,\r
486                                       size_t subscriptionCount,\r
487                                       uint32_t flags,\r
488                                       uint32_t timeoutMs );\r
489 /* @[declare_mqtt_subscribesync] */\r
490 \r
491 /**\r
492  * @brief Unsubscribes from the given array of topic filters and optionally\r
493  * receive an asynchronous notification when the unsubscribe completes.\r
494  *\r
495  * This function sends an MQTT UNSUBSCRIBE packet to the server. An UNSUBSCRIBE\r
496  * packet removes registered topic filters from the server. After unsubscribing,\r
497  * the server will no longer send messages on these topic filters to the client.\r
498  *\r
499  * Corresponding [subscription callback functions](@ref IotMqttCallbackInfo_t.function)\r
500  * are also removed from the MQTT connection. These subscription callback functions\r
501  * will be removed even if the MQTT UNSUBSCRIBE packet fails to send.\r
502  *\r
503  * @param[in] mqttConnection The MQTT connection used for the subscription.\r
504  * @param[in] pSubscriptionList Pointer to the first element in the array of\r
505  * subscriptions.\r
506  * @param[in] subscriptionCount The number of elements in pSubscriptionList.\r
507  * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags.\r
508  * @param[in] pCallbackInfo Asynchronous notification of this function's completion (`NULL` to disable).\r
509  * @param[out] pUnsubscribeOperation Set to a handle by which this operation may be\r
510  * referenced after this function returns. This reference is invalidated once\r
511  * the unsubscribe operation completes.\r
512  *\r
513  * @return This function will return #IOT_MQTT_STATUS_PENDING upon success.\r
514  * @return Upon completion of the unsubscribe (either through an\r
515  * #IotMqttCallbackInfo_t or @ref mqtt_function_wait), the status will be one of:\r
516  * - #IOT_MQTT_SUCCESS\r
517  * - #IOT_MQTT_NETWORK_ERROR\r
518  * - #IOT_MQTT_SCHEDULING_ERROR\r
519  * - #IOT_MQTT_BAD_RESPONSE\r
520  * @return If this function fails before queuing an unsubscribe operation, it will return\r
521  * one of:\r
522  * - #IOT_MQTT_NOT_INITIALIZED\r
523  * - #IOT_MQTT_BAD_PARAMETER\r
524  * - #IOT_MQTT_NO_MEMORY\r
525  *\r
526  * @see @ref mqtt_function_unsubscribesync for a blocking variant of this function.\r
527  * @see @ref mqtt_function_subscribeasync for the function that adds subscriptions.\r
528  */\r
529 /* @[declare_mqtt_unsubscribeasync] */\r
530 IotMqttError_t IotMqtt_UnsubscribeAsync( IotMqttConnection_t mqttConnection,\r
531                                          const IotMqttSubscription_t * pSubscriptionList,\r
532                                          size_t subscriptionCount,\r
533                                          uint32_t flags,\r
534                                          const IotMqttCallbackInfo_t * pCallbackInfo,\r
535                                          IotMqttOperation_t * const pUnsubscribeOperation );\r
536 /* @[declare_mqtt_unsubscribeasync] */\r
537 \r
538 /**\r
539  * @brief Unsubscribes from a given array of topic filters with a timeout.\r
540  *\r
541  * This function sends an MQTT UNSUBSCRIBE packet to the server, then waits\r
542  * for a server response to the packet. Internally, this function is a call to\r
543  * @ref mqtt_function_unsubscribeasync followed by @ref mqtt_function_wait. See @ref\r
544  * mqtt_function_unsubscribeasync for more information about the MQTT UNSUBSCRIBE\r
545  * operation.\r
546  *\r
547  * @param[in] mqttConnection The MQTT connection used for the subscription.\r
548  * @param[in] pSubscriptionList Pointer to the first element in the array of\r
549  * subscriptions.\r
550  * @param[in] subscriptionCount The number of elements in pSubscriptionList.\r
551  * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags.\r
552  * Flags are currently ignored but reserved for future use.\r
553  * @param[in] timeoutMs If the MQTT server does not acknowledge the UNSUBSCRIBE within\r
554  * this timeout in milliseconds, this function returns #IOT_MQTT_TIMEOUT.\r
555  *\r
556  * @return One of the following:\r
557  * - #IOT_MQTT_SUCCESS\r
558  * - #IOT_MQTT_NOT_INITIALIZED\r
559  * - #IOT_MQTT_BAD_PARAMETER\r
560  * - #IOT_MQTT_NO_MEMORY\r
561  * - #IOT_MQTT_NETWORK_ERROR\r
562  * - #IOT_MQTT_SCHEDULING_ERROR\r
563  * - #IOT_MQTT_BAD_RESPONSE\r
564  */\r
565 /* @[declare_mqtt_unsubscribesync] */\r
566 IotMqttError_t IotMqtt_UnsubscribeSync( IotMqttConnection_t mqttConnection,\r
567                                         const IotMqttSubscription_t * pSubscriptionList,\r
568                                         size_t subscriptionCount,\r
569                                         uint32_t flags,\r
570                                         uint32_t timeoutMs );\r
571 /* @[declare_mqtt_unsubscribesync] */\r
572 \r
573 /**\r
574  * @brief Publishes a message to the given topic name and optionally\r
575  * receive an asynchronous notification when the publish completes.\r
576  *\r
577  * This function sends an MQTT PUBLISH packet to the server. A PUBLISH packet\r
578  * contains a payload and a topic name. Any clients with a subscription on a\r
579  * topic filter matching the PUBLISH topic name will receive a copy of the\r
580  * PUBLISH packet from the server.\r
581  *\r
582  * If a PUBLISH packet fails to reach the server and it is not a QoS 0 message,\r
583  * it will be retransmitted. See #IotMqttPublishInfo_t for a description\r
584  * of the retransmission strategy.\r
585  *\r
586  * @attention QoS 2 messages are currently unsupported. Only 0 or 1 are valid\r
587  * for message QoS.\r
588  *\r
589  * @param[in] mqttConnection The MQTT connection to use for the publish.\r
590  * @param[in] pPublishInfo MQTT publish parameters.\r
591  * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags.\r
592  * @param[in] pCallbackInfo Asynchronous notification of this function's completion (`NULL` to disable).\r
593  * @param[out] pPublishOperation Set to a handle by which this operation may be\r
594  * referenced after this function returns. This reference is invalidated once\r
595  * the publish operation completes.\r
596  *\r
597  * @return This function will return #IOT_MQTT_STATUS_PENDING upon success for\r
598  * QoS 1 publishes. For a QoS 0 publish it returns #IOT_MQTT_SUCCESS upon\r
599  * success.\r
600  * @return Upon completion of a QoS 1 publish (either through an\r
601  * #IotMqttCallbackInfo_t or @ref mqtt_function_wait), the status will be one of:\r
602  * - #IOT_MQTT_SUCCESS\r
603  * - #IOT_MQTT_NETWORK_ERROR\r
604  * - #IOT_MQTT_SCHEDULING_ERROR\r
605  * - #IOT_MQTT_BAD_RESPONSE\r
606  * - #IOT_MQTT_RETRY_NO_RESPONSE (if [pPublishInfo->retryMs](@ref IotMqttPublishInfo_t.retryMs)\r
607  * and [pPublishInfo->retryLimit](@ref IotMqttPublishInfo_t.retryLimit) were set).\r
608  * @return If this function fails before queuing an publish operation (regardless\r
609  * of QoS), it will return one of:\r
610  * - #IOT_MQTT_NOT_INITIALIZED\r
611  * - #IOT_MQTT_BAD_PARAMETER\r
612  * - #IOT_MQTT_NO_MEMORY\r
613  *\r
614  * @note The parameters `pCallbackInfo` and `pPublishOperation` should only be used for QoS\r
615  * 1 publishes. For QoS 0, they should both be `NULL`.\r
616  *\r
617  * @see @ref mqtt_function_publishsync for a blocking variant of this function.\r
618  *\r
619  * <b>Example</b>\r
620  * @code{c}\r
621  * // An initialized and connected MQTT connection.\r
622  * IotMqttConnection_t mqttConnection;\r
623  *\r
624  * // Publish information.\r
625  * IotMqttPublishInfo_t publishInfo = IOT_MQTT_PUBLISH_INFO_INITIALIZER;\r
626  *\r
627  * // Set the publish information. QoS 0 example (retain not used):\r
628  * publishInfo.qos = IOT_MQTT_QOS_0;\r
629  * publishInfo.pTopicName = "some/topic/name";\r
630  * publishInfo.topicNameLength = ( uint16_t ) strlen( publishInfo.pTopicName );\r
631  * publishInfo.pPayload = "payload";\r
632  * publishInfo.payloadLength = strlen( publishInfo.pPayload );\r
633  *\r
634  * // QoS 0 publish should return IOT_MQTT_SUCCESS upon success.\r
635  * IotMqttError_t qos0Result = IotMqtt_PublishAsync( mqttConnection,\r
636  *                                                   &publishInfo,\r
637  *                                                   0,\r
638  *                                                   NULL,\r
639  *                                                   NULL );\r
640  *\r
641  * // QoS 1 with retry example (using same topic name and payload as QoS 0 example):\r
642  * IotMqttOperation_t qos1Operation = IOT_MQTT_OPERATION_INITIALIZER;\r
643  * publishInfo.qos = IOT_MQTT_QOS_1;\r
644  * publishInfo.retryMs = 1000; // Retry if no response is received in 1 second.\r
645  * publishInfo.retryLimit = 5; // Retry up to 5 times.\r
646  *\r
647  * // QoS 1 publish should return IOT_MQTT_STATUS_PENDING upon success.\r
648  * IotMqttError_t qos1Result = IotMqtt_PublishAsync( mqttConnection,\r
649  *                                                   &publishInfo,\r
650  *                                                   IOT_MQTT_FLAG_WAITABLE,\r
651  *                                                   NULL,\r
652  *                                                   &qos1Operation );\r
653  *\r
654  * // Wait up to 5 seconds for the publish to complete.\r
655  * if( qos1Result == IOT_MQTT_STATUS_PENDING )\r
656  * {\r
657  *     qos1Result = IotMqtt_Wait( qos1Operation, 5000 );\r
658  * }\r
659  * @endcode\r
660  */\r
661 /* @[declare_mqtt_publishasync] */\r
662 IotMqttError_t IotMqtt_PublishAsync( IotMqttConnection_t mqttConnection,\r
663                                      const IotMqttPublishInfo_t * pPublishInfo,\r
664                                      uint32_t flags,\r
665                                      const IotMqttCallbackInfo_t * pCallbackInfo,\r
666                                      IotMqttOperation_t * const pPublishOperation );\r
667 /* @[declare_mqtt_publishasync] */\r
668 \r
669 /**\r
670  * @brief Publish a message to the given topic name with a timeout.\r
671  *\r
672  * This function sends an MQTT PUBLISH packet to the server, then waits for\r
673  * a server response to the packet. Internally, this function is a call to @ref\r
674  * mqtt_function_publishasync followed by @ref mqtt_function_wait. See @ref\r
675  * mqtt_function_publishasync for more information about the MQTT PUBLISH operation.\r
676  *\r
677  * @attention QoS 2 messages are currently unsupported. Only 0 or 1 are valid\r
678  * for message QoS.\r
679  *\r
680  * @param[in] mqttConnection The MQTT connection to use for the publish.\r
681  * @param[in] pPublishInfo MQTT publish parameters.\r
682  * @param[in] flags Flags which modify the behavior of this function. See @ref mqtt_constants_flags.\r
683  * Currently, flags are ignored by this function; this parameter is for\r
684  * future-compatibility.\r
685  * @param[in] timeoutMs If the MQTT server does not acknowledge a QoS 1 PUBLISH\r
686  * within this timeout in milliseconds, this function returns #IOT_MQTT_TIMEOUT.\r
687  * This parameter is ignored for QoS 0 PUBLISH messages.\r
688  *\r
689  * @return One of the following:\r
690  * - #IOT_MQTT_SUCCESS\r
691  * - #IOT_MQTT_NOT_INITIALIZED\r
692  * - #IOT_MQTT_BAD_PARAMETER\r
693  * - #IOT_MQTT_NO_MEMORY\r
694  * - #IOT_MQTT_NETWORK_ERROR\r
695  * - #IOT_MQTT_SCHEDULING_ERROR\r
696  * - #IOT_MQTT_BAD_RESPONSE\r
697  * - #IOT_MQTT_RETRY_NO_RESPONSE (if [pPublishInfo->retryMs](@ref IotMqttPublishInfo_t.retryMs)\r
698  * and [pPublishInfo->retryLimit](@ref IotMqttPublishInfo_t.retryLimit) were set).\r
699  */\r
700 /* @[declare_mqtt_publishsync] */\r
701 IotMqttError_t IotMqtt_PublishSync( IotMqttConnection_t mqttConnection,\r
702                                     const IotMqttPublishInfo_t * pPublishInfo,\r
703                                     uint32_t flags,\r
704                                     uint32_t timeoutMs );\r
705 /* @[declare_mqtt_publishsync] */\r
706 \r
707 /**\r
708  * @brief Waits for an operation to complete.\r
709  *\r
710  * This function blocks to wait for a [subscribe](@ref mqtt_function_subscribeasync),\r
711  * [unsubscribe](@ref mqtt_function_unsubscribeasync), or [publish]\r
712  * (@ref mqtt_function_publishasync) to complete. These operations are by default\r
713  * asynchronous; the function calls queue an operation for processing, and a\r
714  * callback is invoked once the operation is complete.\r
715  *\r
716  * To use this function, the flag #IOT_MQTT_FLAG_WAITABLE must have been\r
717  * set in the operation's function call. Additionally, this function must always\r
718  * be called with any waitable operation to clean up resources.\r
719  *\r
720  * Regardless of its return value, this function always clean up resources used\r
721  * by the waitable operation. This means `reference` is invalidated as soon as\r
722  * this function returns, even if it returns #IOT_MQTT_TIMEOUT or another error.\r
723  *\r
724  * @param[in] operation Reference to the operation to wait for. The flag\r
725  * #IOT_MQTT_FLAG_WAITABLE must have been set for this operation.\r
726  * @param[in] timeoutMs How many milliseconds to wait before returning\r
727  * #IOT_MQTT_TIMEOUT.\r
728  *\r
729  * @return The return value of this function depends on the MQTT operation associated\r
730  * with `reference`. See #IotMqttError_t for possible return values.\r
731  *\r
732  * <b>Example</b>\r
733  * @code{c}\r
734  * // Operation reference and timeout.\r
735  * IotMqttOperation_t publishOperation = IOT_MQTT_OPERATION_INITIALIZER;\r
736  * uint32_t timeoutMs = 5000; // 5 seconds\r
737  *\r
738  * // MQTT operation to wait for.\r
739  * IotMqttError_t result = IotMqtt_PublishAsync( mqttConnection,\r
740  *                                               &publishInfo,\r
741  *                                               IOT_MQTT_FLAG_WAITABLE,\r
742  *                                               NULL,\r
743  *                                               &publishOperation );\r
744  *\r
745  * // Publish should have returned IOT_MQTT_STATUS_PENDING. The call to wait\r
746  * // returns once the result of the publish is available or the timeout expires.\r
747  * if( result == IOT_MQTT_STATUS_PENDING )\r
748  * {\r
749  *     result = IotMqtt_Wait( publishOperation, timeoutMs );\r
750  *\r
751  *     // After the call to wait, the result of the publish is known\r
752  *     // (not IOT_MQTT_STATUS_PENDING).\r
753  *     assert( result != IOT_MQTT_STATUS_PENDING );\r
754  * }\r
755  * @endcode\r
756  */\r
757 /* @[declare_mqtt_wait] */\r
758 IotMqttError_t IotMqtt_Wait( IotMqttOperation_t operation,\r
759                              uint32_t timeoutMs );\r
760 /* @[declare_mqtt_wait] */\r
761 \r
762 /*-------------------------- MQTT helper functions --------------------------*/\r
763 \r
764 /**\r
765  * @brief Returns a string that describes an #IotMqttError_t.\r
766  *\r
767  * Like the POSIX `strerror`, this function returns a string describing a\r
768  * return code. In this case, the return code is an MQTT library error code,\r
769  * `status`.\r
770  *\r
771  * The string returned by this function <b>MUST</b> be treated as read-only: any\r
772  * attempt to modify its contents may result in a crash. Therefore, this function\r
773  * is limited to usage in logging.\r
774  *\r
775  * @param[in] status The status to describe.\r
776  *\r
777  * @return A read-only string that describes `status`.\r
778  *\r
779  * @warning The string returned by this function must never be modified.\r
780  */\r
781 /* @[declare_mqtt_strerror] */\r
782 const char * IotMqtt_strerror( IotMqttError_t status );\r
783 /* @[declare_mqtt_strerror] */\r
784 \r
785 /**\r
786  * @brief Returns a string that describes an #IotMqttOperationType_t.\r
787  *\r
788  * This function returns a string describing an MQTT operation type, `operation`.\r
789  *\r
790  * The string returned by this function <b>MUST</b> be treated as read-only: any\r
791  * attempt to modify its contents may result in a crash. Therefore, this function\r
792  * is limited to usage in logging.\r
793  *\r
794  * @param[in] operation The operation to describe.\r
795  *\r
796  * @return A read-only string that describes `operation`.\r
797  *\r
798  * @warning The string returned by this function must never be modified.\r
799  */\r
800 /* @[declare_mqtt_operationtype] */\r
801 const char * IotMqtt_OperationType( IotMqttOperationType_t operation );\r
802 /* @[declare_mqtt_operationtype] */\r
803 \r
804 /**\r
805  * @brief Check if an MQTT connection has a subscription for a topic filter.\r
806  *\r
807  * This function checks whether an MQTT connection `mqttConnection` has a\r
808  * subscription callback registered for a topic filter `pTopicFilter`. If a\r
809  * subscription callback is found, its details are copied into the output parameter\r
810  * `pCurrentSubscription`. This subscription callback will be invoked for incoming\r
811  * PUBLISH messages on `pTopicFilter`.\r
812  *\r
813  * <b>The check for a matching subscription is only performed client-side</b>;\r
814  * therefore, this function should not be relied upon for perfect accuracy. For\r
815  * example, this function may return an incorrect result if the MQTT server\r
816  * crashes and drops subscriptions without informing the client.\r
817  *\r
818  * Note that an MQTT connection's subscriptions might change between the time this\r
819  * function checks the subscription list and its caller tests the return value.\r
820  * This function certainly should not be used concurrently with any pending SUBSCRIBE\r
821  * or UNSUBSCRIBE operations.\r
822  *\r
823  * One suitable use of this function is to check <i>which</i> subscriptions were rejected\r
824  * if @ref mqtt_function_subscribeasync returns #IOT_MQTT_SERVER_REFUSED; that return\r
825  * code only means that <i>at least one</i> subscription was rejected.\r
826  *\r
827  * @param[in] mqttConnection The MQTT connection to check.\r
828  * @param[in] pTopicFilter The topic filter to check.\r
829  * @param[in] topicFilterLength Length of `pTopicFilter`.\r
830  * @param[out] pCurrentSubscription If a subscription is found, its details are\r
831  * copied here. This output parameter is only valid if this function returns `true` (`NULL` to disable).\r
832  *\r
833  * @return `true` if a subscription was found; `false` otherwise.\r
834  *\r
835  * @note The subscription QoS is not stored by the MQTT library; therefore,\r
836  * `pCurrentSubscription->qos` will always be set to #IOT_MQTT_QOS_0.\r
837  */\r
838 /* @[declare_mqtt_issubscribed] */\r
839 bool IotMqtt_IsSubscribed( IotMqttConnection_t mqttConnection,\r
840                            const char * pTopicFilter,\r
841                            uint16_t topicFilterLength,\r
842                            IotMqttSubscription_t * const pCurrentSubscription );\r
843 /* @[declare_mqtt_issubscribed] */\r
844 \r
845 /**\r
846  * @cond DOXYGEN_IGNORE\r
847  * Doxygen should ignore this section.\r
848  *\r
849  * Backwards compatibility macros for previous function names.\r
850  */\r
851 #define IotMqtt_Subscribe           IotMqtt_SubscribeAsync\r
852 #define IotMqtt_TimedSubscribe      IotMqtt_SubscribeSync\r
853 #define IotMqtt_Unsubscribe         IotMqtt_UnsubscribeAsync\r
854 #define IotMqtt_TimedUnsubscribe    IotMqtt_UnsubscribeSync\r
855 #define IotMqtt_Publish             IotMqtt_PublishAsync\r
856 #define IotMqtt_TimedPublish        IotMqtt_PublishSync\r
857 /** @endcond */\r
858 \r
859 #endif /* ifndef IOT_MQTT_H_ */\r