]> git.sur5r.net Git - freertos/blob - FreeRTOS-Labs/Demo/FreeRTOS_IoT_Libraries/mqtt/common/DemoTasks/SimpleMQTTExamples.c
7288238fde11b3cfdb60c45dec45c354dc759346
[freertos] / FreeRTOS-Labs / Demo / FreeRTOS_IoT_Libraries / mqtt / common / DemoTasks / SimpleMQTTExamples.c
1 /*\r
2  * FreeRTOS Kernel V10.3.0\r
3  * Copyright (C) 2020 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  * http://www.FreeRTOS.org\r
23  * http://aws.amazon.com/freertos\r
24  *\r
25  * 1 tab == 4 spaces!\r
26  */\r
27 \r
28 /*\r
29  * This file contains the common functions for plain text, basic TLS, and mutual\r
30  * authentication MQTT demos. Aside from the difference in security level during\r
31  * connect, the three demos perform the same interaction with a MQTT broker. The\r
32  * demos create a single application task that connects to a MQTT broker,\r
33  * subscribes to a topic, publishes a topic with a message, and disconnect from a\r
34  * MQTT broker. The task subscribes to the same topic it publishes to, receiving\r
35  * the message it sends to the broker. Note that this demo does not terminate, the\r
36  * connect-subscribe-publish-disconnect cycle is repeated for unlimited number of\r
37  * times.\r
38  *\r
39  * The plain text MQTT demo does not authenticate the server nor the client. The\r
40  * basic TLS MQTT demo builds on top of the plain text demo, adding broker\r
41  * authentication and encryption. The mutual authentication MQTT demo builds on top\r
42  * of the basic TLS demo, enabling both server and client authentication.\r
43  *\r
44  * For more information regarding the MQTT library and the demo, please refer to:\r
45  * https://freertos.org/mqtt/index.html\r
46  */\r
47 \r
48 /* Standard includes. */\r
49 #include <string.h>\r
50 #include <stdio.h>\r
51 \r
52 /* Kernel includes. */\r
53 #include "FreeRTOS.h"\r
54 #include "task.h"\r
55 \r
56 /* FreeRTOS+TCP includes. */\r
57 #include "FreeRTOS_IP.h"\r
58 \r
59 /* IoT SDK includes. */\r
60 #include "iot_mqtt.h"\r
61 #include "iot_taskpool_freertos.h"\r
62 #include "platform/iot_network_freertos.h"\r
63 \r
64 /* MQTT Demo Select */\r
65 #include "demo_config.h"\r
66 \r
67 /* Select MQTT profile based on the setting in demo_config.h */\r
68 #if ( democonfigPROFILE_USE_AWS_IOT == 1 )\r
69         #include "aws_iot_demo_profile.h"\r
70 #else\r
71         #include "mqtt_demo_profile.h"\r
72 #endif\r
73 \r
74 /* Preprocessor check for configuration */\r
75 #include "aws_iot_setup_check.h"\r
76 \r
77 /*\r
78  * Set connection profile based on the setting in demo_config.h. For more\r
79  * information on each variable, please refer to the respective *_profile.h\r
80  * file in FreeRTOS-Labs\Demo\FreeRTOS_IoT_Libraries\include.\r
81  *\r
82  * Note that if you are running mqtt_tls_mutual_auth demo please make sure to\r
83  * visit the following link for setup:\r
84  * https://www.freertos.org/mqtt/preconfiguredexamplesMA.html\r
85  */\r
86 #if ( democonfigPROFILE_USE_AWS_IOT == 1 )\r
87         #define mqttexampleBROKER_ENDPOINT                       awsiotdemoprofileAWS_ENDPOINT\r
88         #define mqttexampleBROKER_PORT                           awsiotdemoprofileAWS_MQTT_PORT\r
89         #define mqttexampleBROKER_CERTIFICATE_PEM        awsiotdemoprofileAWS_CERTIFICATE_PEM\r
90         #define mqttexampleCLIENT_IDENTIFIER             awsiotdemoprofileCLIENT_IDENTIFIER\r
91         #define mqttexampleCLIENT_CERTIFICATE_PEM        awsiotdemoprofileCLIENT_CERTIFICATE_PEM\r
92         #define mqttexampleCLIENT_PRIVATE_KEY_PEM        awsiotdemoprofileCLIENT_PRIVATE_KEY_PEM\r
93 #else\r
94         #define mqttexampleBROKER_ENDPOINT                       mqttdemoprofileBROKER_ENDPOINT\r
95         #define mqttexampleBROKER_PORT                           mqttdemoprofileBROKER_PORT\r
96         #define mqttexampleBROKER_CERTIFICATE_PEM        mqttdemoprofileBROKER_CERTIFICATE_PEM\r
97         #define mqttexampleCLIENT_IDENTIFIER             mqttdemoprofileCLIENT_IDENTIFIER\r
98 #endif /* if ( democonfigPROFILE_USE_AWS_IOT == pdTRUE ) */\r
99 \r
100 /**\r
101  * @brief The keep-alive interval used for this example.\r
102  *\r
103  * An MQTT ping request will be sent periodically at this interval.\r
104  *\r
105  * @note: This value is set to zero to disable MQTT\r
106  * keep alive for the Windows simulator project.\r
107  * The FreeRTOS kernel does not accurately calculate time for the Windows\r
108  * Simulator. Therefore, MQTT PING Request messages may be sent\r
109  * at an incorrect time interval to the broker. If the broker does\r
110  * not receive a ping request within 1.5x the time sent in a\r
111  * connection request, the broker may close the connection.\r
112  * To enable the keep alive feature, set this value\r
113  * to the desired interval in seconds.\r
114  */\r
115 #define mqttexampleKEEP_ALIVE_SECONDS      ( 0 )\r
116 \r
117 /**\r
118  * @brief The timeout for MQTT operations in this example.\r
119  */\r
120 #define mqttexampleMQTT_TIMEOUT_MS                 ( 5000 )\r
121 \r
122 /**\r
123  * @brief The topic to subscribe and publish to in the example.\r
124  *\r
125  * The topic starts with the client identifier to ensure that each demo interacts\r
126  * with a unique topic.\r
127  */\r
128 #define mqttexampleTOPIC                                   mqttexampleCLIENT_IDENTIFIER "/example/topic"\r
129 \r
130 /**\r
131  * @brief The MQTT message published in this example.\r
132  */\r
133 #define mqttexampleMESSAGE                                 "Hello World!"\r
134 \r
135 /**\r
136  * @brief Parameters to control the retry behavior in case a QoS1 publish\r
137  * message gets lost.\r
138  *\r
139  * Retry every minutes up to a maximum of 5 retries.\r
140  */\r
141 #define mqttexamplePUBLISH_RETRY_MS                ( 1000 )\r
142 #define mqttexamplePUBLISH_RETRY_LIMIT     ( 5 )\r
143 \r
144 /**\r
145  * @brief The bit which is set in the demo task's notification value from the\r
146  * disconnect callback to inform the demo task about the MQTT disconnect.\r
147  */\r
148 #define mqttexampleDISCONNECTED_BIT                ( 1UL << 0UL )\r
149 \r
150 /**\r
151  * @brief The bit which is set in the demo task's notification value from the\r
152  * publish callback to inform the demo task about the message received from the\r
153  * MQTT broker.\r
154  */\r
155 #define mqttexampleMESSAGE_RECEIVED_BIT    ( 1UL << 1UL )\r
156 \r
157 /*-----------------------------------------------------------*/\r
158 \r
159 /**\r
160  * @brief The task used to demonstrate the MQTT API.\r
161  *\r
162  * @param[in] pvParameters Parameters as passed at the time of task creation. Not\r
163  * used in this example.\r
164  */\r
165 static void prvMQTTDemoTask( void * pvParameters );\r
166 \r
167 /**\r
168  * @brief The callback invoked by the MQTT library when the MQTT connection gets\r
169  * disconnected.\r
170  *\r
171  * @param[in] pvCallbackContext Callback context as provided at the time of\r
172  * connect.\r
173  * @param[in] pxCallbackParams Contains the reason why the MQTT connection was\r
174  * disconnected.\r
175  */\r
176 static void prvExample_OnDisconnect( void * pvCallbackContext,\r
177                                                                          IotMqttCallbackParam_t * pxCallbackParams );\r
178 \r
179 /**\r
180  * @brief The callback invoked by the MQTT library when a message is received on\r
181  * a subscribed topic from the MQTT broker.\r
182  *\r
183  * @param[in] pvCallbackContext Callback context as provided at the time of\r
184  * subscribe.\r
185  * @param[in] pxCallbackParams Contain the details about the received message -\r
186  * topic on which the message was received, the received message.\r
187  */\r
188 static void prvExample_OnMessageReceived( void * pvCallbackContext,\r
189                                                                                   IotMqttCallbackParam_t * pxCallbackParams );\r
190 \r
191 /**\r
192  * @brief Connects to the MQTT broker as specified in mqttexampleBROKER_ENDPOINT\r
193  * and mqttexampleBROKER_PORT.\r
194  */\r
195 static void prvMQTTConnect( void );\r
196 \r
197 /**\r
198  * @brief Subscribes to the topic as specified in mqttexampleTOPIC.\r
199  */\r
200 static void prvMQTTSubscribe( void );\r
201 \r
202 /**\r
203  * @brief Publishes a messages mqttexampleMESSAGE on mqttexampleTOPIC topic.\r
204  */\r
205 static void prvMQTTPublish( void );\r
206 \r
207 /**\r
208  * @brief Unsubscribes from the mqttexampleTOPIC topic.\r
209  */\r
210 static void prvMQTTUnsubscribe( void );\r
211 \r
212 /**\r
213  * @brief Disconnects from the MQTT broker gracefully by sending an MQTT\r
214  * DISCONNECT message.\r
215  */\r
216 static void prvMQTTDisconnect( void );\r
217 \r
218 /**\r
219 * @brief Initializes the IoT libraries used by this demo.\r
220 */\r
221 static void prvInitialiseLibraries( void );\r
222 \r
223 /**\r
224  * @brief The MQTT connection handle used in this example.\r
225  */\r
226 static IotMqttConnection_t xMQTTConnection = IOT_MQTT_CONNECTION_INITIALIZER;\r
227 \r
228 /*-----------------------------------------------------------*/\r
229 \r
230 /**\r
231  * @brief Parameters used to create the system task pool.\r
232  */\r
233 static const IotTaskPoolInfo_t xTaskPoolParameters =\r
234 {\r
235         /* Minimum number of threads in a task pool.\r
236          * Note the slimmed down version of the task\r
237          * pool used by this library does not auto-scale\r
238          * the number of tasks in the pool so in this\r
239          * case this sets the number of tasks in the\r
240          * pool. */\r
241         1,\r
242 \r
243         /* Maximum number of threads in a task pool.\r
244          * Note the slimmed down version of the task\r
245          * pool used by this library does not auto-scale\r
246          * the number of tasks in the pool so in this\r
247          * case this parameter is just ignored. */\r
248         1,\r
249 \r
250         /* Stack size for every task pool thread - in\r
251          * bytes, hence multiplying by the number of bytes\r
252          * in a word as configMINIMAL_STACK_SIZE is\r
253          * specified in words. */\r
254         configMINIMAL_STACK_SIZE * sizeof( portSTACK_TYPE ),\r
255         /* Priority for every task pool thread. */\r
256         tskIDLE_PRIORITY,\r
257 };\r
258 \r
259 /*-----------------------------------------------------------*/\r
260 \r
261 static const struct IotNetworkServerInfo xMQTTBrokerInfo =\r
262 {\r
263         .pHostName = mqttexampleBROKER_ENDPOINT,\r
264         .port = mqttexampleBROKER_PORT\r
265 };\r
266 \r
267 #if ( democonfigENABLE_TLS )\r
268         static struct IotNetworkCredentials xNetworkSecurityCredentials =\r
269         {\r
270                 /* Optional TLS extensions. For this demo, they are disabled. */\r
271                 .pAlpnProtos = NULL,\r
272                 .maxFragmentLength = 0,\r
273 \r
274                 /* SNI is enabled by default. */\r
275                 .disableSni = false,\r
276 \r
277                 /* Provide the certificate for validating the server. Only required for\r
278                  * demos using TLS. */\r
279                 .pRootCa = mqttexampleBROKER_CERTIFICATE_PEM,\r
280                 .rootCaSize = sizeof( mqttexampleBROKER_CERTIFICATE_PEM ),\r
281 \r
282                 /* Strong mutual authentication to authenticate both the broker and\r
283                  * the client. */\r
284                 #if ( democonfigENABLE_MUTUAL_AUTH )\r
285                         .pClientCert = mqttexampleCLIENT_CERTIFICATE_PEM,\r
286                         .clientCertSize = sizeof( mqttexampleCLIENT_CERTIFICATE_PEM ),\r
287                         .pPrivateKey = mqttexampleCLIENT_PRIVATE_KEY_PEM,\r
288                         .privateKeySize = sizeof( mqttexampleCLIENT_PRIVATE_KEY_PEM )\r
289                 #else\r
290                         .pClientCert = NULL,\r
291                         .clientCertSize = 0,\r
292                         .pPrivateKey = NULL,\r
293                         .privateKeySize = 0\r
294                 #endif /* if ( democonfigENABLE_MUTUAL_AUTH ) */\r
295         };\r
296 #endif /* if ( democonfigENABLE_TLS ) */\r
297 \r
298 static IotMqttNetworkInfo_t xNetworkInfo =\r
299 {\r
300         /* No connection to the MQTT broker has been established yet and we want to\r
301          * establish a new connection. */\r
302         .createNetworkConnection = true,\r
303         .u.setup.pNetworkServerInfo = &( xMQTTBrokerInfo ),\r
304 \r
305         /* Set the TLS credentials for the new MQTT connection. This member is NULL\r
306          * for the plain text MQTT demo. */\r
307         #if ( democonfigENABLE_TLS )\r
308                 .u.setup.pNetworkCredentialInfo = &xNetworkSecurityCredentials,\r
309         #else\r
310                 .u.setup.pNetworkCredentialInfo = NULL, /* Not using TLS so no credentials. */\r
311         #endif\r
312 \r
313         /* Use FreeRTOS+TCP network interface. */\r
314         .pNetworkInterface = IOT_NETWORK_INTERFACE_FREERTOS,\r
315 \r
316         /* Setup the callback which is called when the MQTT connection is\r
317          * disconnected. The task handle is passed as the callback context which\r
318          * is used by the callback to send a task notification to this task.*/\r
319         .disconnectCallback.function = prvExample_OnDisconnect\r
320 };\r
321 \r
322 static const IotMqttConnectInfo_t xConnectInfo =\r
323 {\r
324         /* Set this flag to true if connecting to the AWS IoT MQTT broker. */\r
325         #if ( democonfigPROFILE_USE_AWS_IOT == 1 )\r
326                 .awsIotMqttMode = true,\r
327         #else\r
328                 .awsIotMqttMode = false,\r
329         #endif\r
330 \r
331         /* Start with a clean session i.e. direct the MQTT broker to discard any\r
332          * previous session data. Also, establishing a connection with clean session\r
333          * will ensure that the broker does not store any data when this client\r
334          * gets disconnected. */\r
335         .cleanSession = true,\r
336 \r
337         /* Since we are starting with a clean session, there are no previous\r
338          * subscriptions to be restored. */\r
339         .pPreviousSubscriptions = NULL,\r
340         .previousSubscriptionCount = 0,\r
341 \r
342         /* We do not want to publish Last Will and Testament (LWT) message if the\r
343          * client gets disconnected. */\r
344         .pWillInfo = NULL,\r
345 \r
346         /* Send an MQTT PING request every minute to keep the connection open if\r
347         there is no other MQTT traffic. */\r
348         .keepAliveSeconds = mqttexampleKEEP_ALIVE_SECONDS,\r
349 \r
350         /* The client identifier is used to uniquely identify this MQTT client to\r
351          * the MQTT broker.  In a production device the identifier can be something\r
352          * unique, such as a device serial number. */\r
353         .pClientIdentifier = mqttexampleCLIENT_IDENTIFIER,\r
354         .clientIdentifierLength = ( uint16_t ) sizeof( mqttexampleCLIENT_IDENTIFIER ) - 1,\r
355 \r
356         /* This example does not authenticate the client and therefore username and\r
357          * password fields are not used. */\r
358         .pUserName = NULL,\r
359         .userNameLength = 0,\r
360         .pPassword = NULL,\r
361         .passwordLength = 0\r
362 };\r
363 /*-----------------------------------------------------------*/\r
364 \r
365 \r
366 void vStartSimpleMQTTDemo( void )\r
367 {\r
368 TickType_t xShortDelay = ( TickType_t ) pdMS_TO_TICKS( ( TickType_t ) 500 );\r
369 \r
370         /* Wait a short time to allow receipt of the ARP replies. */\r
371         vTaskDelay( xShortDelay );\r
372 \r
373         /* This example uses a single application task, which in turn is used to\r
374          * connect, subscribe, publish, unsubscribe and disconnect from the MQTT\r
375          * broker. */\r
376         xTaskCreate( prvMQTTDemoTask,          /* Function that implements the task. */\r
377                                  "MQTTDemo",               /* Text name for the task - only used for debugging. */\r
378                                  democonfigDEMO_STACKSIZE, /* Size of stack (in words, not bytes) to allocate for the task. */\r
379                                  NULL,                     /* Task parameter - not used in this case. */\r
380                                  tskIDLE_PRIORITY,         /* Task priority, must be between 0 and configMAX_PRIORITIES - 1. */\r
381                                  NULL );                   /* Used to pass out a handle to the created task - not used in this case. */\r
382 }\r
383 /*-----------------------------------------------------------*/\r
384 \r
385 static void prvMQTTDemoTask( void * pvParameters )\r
386 {\r
387 uint32_t ulNotificationValue = 0, ulPublishCount;\r
388 const uint32_t ulMaxPublishCount = 5UL;\r
389 const TickType_t xNoDelay = ( TickType_t ) 0;\r
390 \r
391         /* Remove compiler warnings about unused parameters. */\r
392         ( void ) pvParameters;\r
393 \r
394         /* One time initialization of the libraries used by this demo. */\r
395         prvInitialiseLibraries();\r
396 \r
397         for( ; ; )\r
398         {\r
399                 /* Notifications are used to send events from the callback functions to this\r
400                  * task.  Don't expect any notifications to be pending at the beginning of the\r
401                  * loop. */\r
402                 configASSERT( ulTaskNotifyTake( pdTRUE, xNoDelay ) == 0 );\r
403 \r
404 \r
405                 /****************************** Connect. ******************************/\r
406 \r
407                 /* Establish a connection to the MQTT broker. This example connects to\r
408                  * the MQTT broker as specified by the compile time constants\r
409                  * mqttexampleBROKER_ENDPOINT and mqttexampleBROKER_PORT.\r
410                  * Please change it to the MQTT broker you want to connect to. */\r
411                 configPRINTF( ( "Attempt to connect to %s:%d\r\n", mqttexampleBROKER_ENDPOINT, mqttexampleBROKER_PORT ) );\r
412                 prvMQTTConnect();\r
413                 configPRINTF( ( "Connected to %s:%d\r\n", mqttexampleBROKER_ENDPOINT, mqttexampleBROKER_PORT ) );\r
414 \r
415 \r
416                 /**************************** Subscribe. ******************************/\r
417 \r
418                 /* The client is now connected to the broker. Subscribe to the topic\r
419                  * as specified by the mqttexampleTOPIC compile time constant.  This\r
420                  * client will then publish to the same topic it subscribed to, so will\r
421                  * expect all the messages it sends to the broker to be sent back to it\r
422                  * from the broker. */\r
423                 configPRINTF( ( "Attempt to subscribed to the topic %s\r\n", mqttexampleTOPIC ) );\r
424                 prvMQTTSubscribe();\r
425                 configPRINTF( ( "Subscribed to the topic %s\r\n", mqttexampleTOPIC ) );\r
426 \r
427 \r
428                 /*********************** Publish ulMaxPublishCount messages. **********/\r
429 \r
430                 /* Publish a few messages while connected. */\r
431                 for( ulPublishCount = 0; ulPublishCount < ulMaxPublishCount; ulPublishCount++ )\r
432                 {\r
433                         /* Publish a message on the topic specified by the mqttexampleTOPIC\r
434                          * compile time constant. */\r
435                         configPRINTF( ( "Publish %s on the topic %s\r\n", mqttexampleMESSAGE, mqttexampleTOPIC ) );\r
436                         prvMQTTPublish();\r
437                         configPRINTF( ( "Published %s on the topic %s\r\n", mqttexampleMESSAGE, mqttexampleTOPIC ) );\r
438 \r
439                         /* Since we are subscribed to the same topic as we published on, we\r
440                          * will get the same message back from the MQTT broker. Wait for the\r
441                          * message to be received which is signaled to us by the publish\r
442                          * callback (prvExample_OnMessageReceived) setting the\r
443                          * mqttexampleMESSAGE_RECEIVED_BIT bit in this task's notification\r
444                          * value. Note the bit is then cleared in the task's notification value\r
445                          * to ensure the bit being set can be detected on the next iteration. */\r
446                         xTaskNotifyWait( 0UL,                             /* Don't clear any bits on entry. */\r
447                                                          mqttexampleMESSAGE_RECEIVED_BIT, /* Clear bit on exit. */\r
448                                                          &( ulNotificationValue ),        /* Obtain the notification value. */\r
449                                                          pdMS_TO_TICKS( mqttexampleMQTT_TIMEOUT_MS ) );\r
450                         configASSERT( ( ulNotificationValue & mqttexampleMESSAGE_RECEIVED_BIT ) == mqttexampleMESSAGE_RECEIVED_BIT );\r
451                 }\r
452 \r
453                 /******************* Unsubscribe and Disconnect. **********************/\r
454 \r
455                 /* Unsubscribe from the topic mqttexampleTOPIC and disconnect\r
456                  * gracefully. */\r
457                 prvMQTTUnsubscribe();\r
458                 prvMQTTDisconnect();\r
459                 configPRINTF( ( "Disconnected from %s:%d\r\n\r\n", mqttexampleBROKER_ENDPOINT, mqttexampleBROKER_PORT ) );\r
460 \r
461                 /* Wait for the disconnect operation to complete which is signaled to us\r
462                  * by the disconnect callback (prvExample_OnDisconnect)by setting\r
463                  * the mqttexampleDISCONNECTED_BIT bit in this task's notification value.\r
464                  * Note the bit is cleared in the task's notification value again to ensure\r
465                  * it being set can be detected again on the next iteration. */\r
466                 xTaskNotifyWait( 0UL,                         /* Don't clear any bits on entry. */\r
467                                                  mqttexampleDISCONNECTED_BIT, /* Clear bit on exit. */\r
468                                                  &( ulNotificationValue ),    /* Obtain the notification value. */\r
469                                                  pdMS_TO_TICKS( mqttexampleMQTT_TIMEOUT_MS ) );\r
470                 configASSERT( ( ulNotificationValue & mqttexampleDISCONNECTED_BIT ) == mqttexampleDISCONNECTED_BIT );\r
471 \r
472                 /* Delay between iterations to avoid broker throttling. */\r
473                 configPRINTF( ( "prvMQTTDemoTask() completed an iteration successfully. Total free heap is %u\r\n", xPortGetFreeHeapSize() ) );\r
474                 configPRINTF( ( "Demo completed successfully.\r\n" ) );\r
475                 configPRINTF( ( "Short delay before starting the next iteration.... \r\n\r\n" ) );\r
476                 vTaskDelay( pdMS_TO_TICKS( mqttexampleMQTT_TIMEOUT_MS ) );\r
477         }\r
478 }\r
479 /*-----------------------------------------------------------*/\r
480 \r
481 static void prvExample_OnDisconnect( void * pvCallbackContext,\r
482                                                                          IotMqttCallbackParam_t * pxCallbackParams )\r
483 {\r
484 TaskHandle_t xDemoTaskHandle = ( TaskHandle_t ) pvCallbackContext;\r
485 \r
486         /* Ensure that we initiated the disconnect. */\r
487         configASSERT( pxCallbackParams->u.disconnectReason == IOT_MQTT_DISCONNECT_CALLED );\r
488 \r
489         /* Inform the demo task about the disconnect. */\r
490         xTaskNotify( xDemoTaskHandle,\r
491                                  mqttexampleDISCONNECTED_BIT,\r
492                                  eSetBits /* Set the mqttexampleDISCONNECTED_BIT in the demo task's notification value. */\r
493                                  );\r
494 }\r
495 /*-----------------------------------------------------------*/\r
496 \r
497 static void prvExample_OnMessageReceived( void * pvCallbackContext,\r
498                                                                                   IotMqttCallbackParam_t * pxCallbackParams )\r
499 {\r
500 TaskHandle_t xDemoTaskHandle = ( TaskHandle_t ) pvCallbackContext;\r
501 \r
502         /* Ensure the message is received on the expected topic. */\r
503         configASSERT( pxCallbackParams->u.message.info.topicNameLength == strlen( mqttexampleTOPIC ) );\r
504         configASSERT( strncmp( pxCallbackParams->u.message.info.pTopicName,\r
505                                                    mqttexampleTOPIC,\r
506                                                    strlen( mqttexampleTOPIC ) ) == 0 );\r
507 \r
508         /* Ensure the message itself is as expected. */\r
509         configASSERT( pxCallbackParams->u.message.info.payloadLength == strlen( mqttexampleMESSAGE ) );\r
510         configASSERT( strncmp( pxCallbackParams->u.message.info.pPayload,\r
511                                                    mqttexampleMESSAGE,\r
512                                                    strlen( mqttexampleMESSAGE ) ) == 0 );\r
513 \r
514         /* Ensure the message Quality of Service (QoS) is as expected. */\r
515         configASSERT( pxCallbackParams->u.message.info.qos == IOT_MQTT_QOS_1 );\r
516 \r
517         /* So as not to worry about string lengths the print message uses the\r
518          * consts rather than the data from the message, but the asserts above have\r
519          * already checked the two are equal. */\r
520         configPRINTF( ( "Received %s on the topic %s\r\n", mqttexampleMESSAGE, mqttexampleTOPIC ) );\r
521 \r
522         /* Inform the demo task about the message received from the MQTT broker by\r
523          * setting the mqttexampleMESSAGE_RECEIVED_BIT bit in the task's notification\r
524          * value. */\r
525         xTaskNotify( xDemoTaskHandle,\r
526                                  mqttexampleMESSAGE_RECEIVED_BIT,\r
527                                  eSetBits /* Set the mqttexampleMESSAGE_RECEIVED_BIT in the demo task's notification value. */\r
528                                  );\r
529 }\r
530 /*-----------------------------------------------------------*/\r
531 \r
532 static void prvMQTTConnect( void )\r
533 {\r
534 IotMqttError_t xResult;\r
535 \r
536         /* Set the context to pass into the disconnect callback function. */\r
537         xNetworkInfo.disconnectCallback.pCallbackContext = ( void * ) xTaskGetCurrentTaskHandle();\r
538 \r
539         /* Establish the connection to the MQTT broker - It is a blocking call and\r
540          * will return only when connection is complete or a timeout occurs.  The\r
541          * network and connection structures are declared and initialized at the top\r
542          * of this file. */\r
543         xResult = IotMqtt_Connect( &( xNetworkInfo ),\r
544                                                            &( xConnectInfo ),\r
545                                                            mqttexampleMQTT_TIMEOUT_MS,\r
546                                                            &( xMQTTConnection ) );\r
547         configASSERT( xResult == IOT_MQTT_SUCCESS );\r
548 }\r
549 /*-----------------------------------------------------------*/\r
550 \r
551 static void prvMQTTDisconnect( void )\r
552 {\r
553         /* Send a MQTT DISCONNECT packet to the MQTT broker to do a graceful\r
554          * disconnect. */\r
555         IotMqtt_Disconnect( xMQTTConnection,\r
556                                                 0 /* flags - 0 means a graceful disconnect by sending MQTT DISCONNECT. */\r
557                                                 );\r
558 }\r
559 /*-----------------------------------------------------------*/\r
560 \r
561 static void prvMQTTSubscribe( void )\r
562 {\r
563 IotMqttError_t xResult;\r
564 IotMqttSubscription_t xMQTTSubscription;\r
565 \r
566         /* Subscribe to the mqttexampleTOPIC topic filter. The task handle is passed\r
567          * as the callback context, which is then used by the callback to send a task\r
568          * notification to this task.*/\r
569         xMQTTSubscription.qos = IOT_MQTT_QOS_1;\r
570         xMQTTSubscription.pTopicFilter = mqttexampleTOPIC;\r
571         xMQTTSubscription.topicFilterLength = ( uint16_t ) strlen( mqttexampleTOPIC );\r
572         xMQTTSubscription.callback.pCallbackContext = ( void * ) xTaskGetCurrentTaskHandle();\r
573         xMQTTSubscription.callback.function = prvExample_OnMessageReceived;\r
574 \r
575         /* Use the synchronous API to subscribe - It is a blocking call and only\r
576          * returns when the subscribe operation is complete or a timeout occurs. */\r
577         xResult = IotMqtt_SubscribeSync( xMQTTConnection,\r
578                                                                          &( xMQTTSubscription ),\r
579                                                                          1, /* We are subscribing to one topic filter. */\r
580                                                                          0, /* flags - currently ignored. */\r
581                                                                          mqttexampleMQTT_TIMEOUT_MS );\r
582         configASSERT( xResult == IOT_MQTT_SUCCESS );\r
583 }\r
584 /*-----------------------------------------------------------*/\r
585 \r
586 static void prvMQTTPublish( void )\r
587 {\r
588 IotMqttError_t xResult;\r
589 IotMqttPublishInfo_t xMQTTPublishInfo;\r
590 \r
591         /* Publish a message with QoS1 on the mqttexampleTOPIC topic. Since we are\r
592          * subscribed to the same topic, the MQTT broker will send the same message\r
593          * back to us. It is verified in the publish callback. */\r
594         xMQTTPublishInfo.qos = IOT_MQTT_QOS_1;\r
595         xMQTTPublishInfo.retain = false;\r
596         xMQTTPublishInfo.pTopicName = mqttexampleTOPIC;\r
597         xMQTTPublishInfo.topicNameLength = ( uint16_t ) strlen( mqttexampleTOPIC );\r
598         xMQTTPublishInfo.pPayload = mqttexampleMESSAGE;\r
599         xMQTTPublishInfo.payloadLength = strlen( mqttexampleMESSAGE );\r
600         xMQTTPublishInfo.retryMs = mqttexamplePUBLISH_RETRY_MS;\r
601         xMQTTPublishInfo.retryLimit = mqttexamplePUBLISH_RETRY_LIMIT;\r
602 \r
603         /* Use the synchronous API to publish - It is a blocking call and only\r
604          * returns when the publish operation is complete or a timeout occurs. */\r
605         xResult = IotMqtt_PublishSync( xMQTTConnection,\r
606                                                                    &( xMQTTPublishInfo ),\r
607                                                                    0, /* flags - currently ignored. */\r
608                                                                    mqttexampleMQTT_TIMEOUT_MS );\r
609         configASSERT( xResult == IOT_MQTT_SUCCESS );\r
610 }\r
611 /*-----------------------------------------------------------*/\r
612 \r
613 static void prvMQTTUnsubscribe( void )\r
614 {\r
615 IotMqttError_t xResult;\r
616 IotMqttSubscription_t xMQTTSubscription;\r
617 \r
618         /* Unsubscribe from the mqttexampleTOPIC topic filter. */\r
619         xMQTTSubscription.pTopicFilter = mqttexampleTOPIC;\r
620         xMQTTSubscription.topicFilterLength = ( uint16_t ) strlen( mqttexampleTOPIC );\r
621 \r
622         /* The following members of the IotMqttSubscription_t are ignored by the\r
623          * unsubscribe operation. Just initialize them to avoid "use of uninitialized\r
624          * variable" warnings. */\r
625         xMQTTSubscription.qos = IOT_MQTT_QOS_1;\r
626         xMQTTSubscription.callback.pCallbackContext = NULL;\r
627         xMQTTSubscription.callback.function = NULL;\r
628 \r
629         /* Use the synchronous API to unsubscribe - It is a blocking call and only\r
630          * returns when the unsubscribe operation is complete or a timeout occurs. */\r
631         xResult = IotMqtt_UnsubscribeSync( xMQTTConnection,\r
632                                                                            &( xMQTTSubscription ),\r
633                                                                            1, /* We are unsubscribing from one topic filter. */\r
634                                                                            0, /* flags - currently ignored. */\r
635                                                                            mqttexampleMQTT_TIMEOUT_MS );\r
636         configASSERT( xResult == IOT_MQTT_SUCCESS );\r
637 }\r
638 /*-----------------------------------------------------------*/\r
639 \r
640 static void prvInitialiseLibraries( void )\r
641 {\r
642 IotTaskPoolError_t xTaskPoolResult;\r
643 IotMqttError_t xResult;\r
644 IotNetworkError_t xNetworkResult;\r
645 \r
646         /* The MQTT library needs a task pool, so create the system task pool. */\r
647         xTaskPoolResult = IotTaskPool_CreateSystemTaskPool( &( xTaskPoolParameters ) );\r
648         configASSERT( xTaskPoolResult == IOT_TASKPOOL_SUCCESS );\r
649 \r
650         /* Initialize the network stack abstraction for FreeRTOS. */\r
651         xNetworkResult = IotNetworkFreeRTOS_Init();\r
652         configASSERT( xNetworkResult == IOT_NETWORK_SUCCESS );\r
653 \r
654         /* MQTT library must be initialized before it can be used. This is just one\r
655          * time initialization. */\r
656         xResult = IotMqtt_Init();\r
657         configASSERT( xResult == IOT_MQTT_SUCCESS );\r
658 }\r
659 /*-----------------------------------------------------------*/\r