2 * FreeRTOS Kernel V10.2.1
\r
3 * Copyright (C) 2017 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://www.FreeRTOS.org
\r
23 * http://aws.amazon.com/freertos
\r
25 * 1 tab == 4 spaces!
\r
28 /* Standard inclues. */
\r
32 /* Kernel includes. */
\r
33 #include "FreeRTOS.h"
\r
36 /* IoT SDK includes. */
\r
37 #include "iot_mqtt.h"
\r
38 #include "iot_taskpool.h"
\r
39 #include "platform/iot_network_freertos.h"
\r
42 * @brief The keep-alive interval used for this example.
\r
44 * An MQTT ping request will be sent periodically at this interval.
\r
46 #define mqttexampleKEEP_ALIVE_SECONDS ( 60 )
\r
49 * @brief The timeout for MQTT operations in this example.
\r
51 #define mqttexampleMQTT_TIMEOUT_MS ( 5000 )
\r
54 * @brief The MQTT client identifier used in this example.
\r
56 #define mqttexampleCLIENT_IDENTIFIER "mqttexampleclient"
\r
59 * @brief Details of the MQTT broker to connect to.
\r
61 * @note This example does not use TLS and therefore won't work with AWS IoT.
\r
64 #define mqttexampleMQTT_BROKER_ENDPOINT "test.mosquitto.org"
\r
65 #define mqttexampleMQTT_BROKER_PORT 1883
\r
68 * @brief The topic to subscribe and publish to in the example.
\r
70 #define mqttexampleTOPIC "example/topic"
\r
73 * @brief The MQTT message published in this example.
\r
75 #define mqttexampleMESSAGE "Hello World!"
\r
78 * @brief Paramters to control the retry behaviour in case a QoS1 publish
\r
79 * message gets lost.
\r
81 * Retry every minutes up to a maximum of 5 retries.
\r
83 #define mqttexamplePUBLISH_RETRY_MS ( 1000 )
\r
84 #define mqttexamplePUBLISH_RETRY_LIMIT ( 5 )
\r
87 * @brief The bit which is set in the demo task's notification value from the
\r
88 * disconnect callback to inform the demo task about the MQTT disconnect.
\r
90 #define mqttexampleDISCONNECTED_BIT ( 1UL << 0UL )
\r
93 * @brief The bit which is set in the demo task's notification value from the
\r
94 * publish callback to inform the demo task about the message received from the
\r
97 #define mqttexampleMESSAGE_RECEIVED_BIT ( 1UL << 1UL )
\r
98 /*-----------------------------------------------------------*/
\r
101 * @brief The MQTT connection handle used in this example.
\r
103 static IotMqttConnection_t xMQTTConnection = IOT_MQTT_CONNECTION_INITIALIZER;
\r
106 * @brief Parameters used to create the system task pool.
\r
108 static const IotTaskPoolInfo_t xTaskPoolParameters = {
\r
109 /* Minimum number of threads in a task pool.
\r
110 * Note the slimmed down version of the task
\r
111 * pool used by this library does not autoscale
\r
112 * the number of tasks in the pool so in this
\r
113 * case this sets the number of tasks in the
\r
116 /* Maximum number of threads in a task pool.
\r
117 * Note the slimmed down version of the task
\r
118 * pool used by this library does not autoscale
\r
119 * the number of tasks in the pool so in this
\r
120 * case this parameter is just ignored. */
\r
122 /* Stack size for every task pool thread - in
\r
123 * bytes, hence multiplying by the number of bytes
\r
124 * in a word as configMINIMAL_STACK_SIZE is
\r
125 * specified in words. */
\r
126 configMINIMAL_STACK_SIZE * sizeof( portSTACK_TYPE ),
\r
127 /* Priority for every task pool thread. */
\r
130 /*-----------------------------------------------------------*/
\r
133 * @brief The task used to demonstrate the MQTT API.
\r
135 * @param[in] pvParameters Parmaters as passed at the time of task creation. Not
\r
136 * used in this example.
\r
138 static void prvMQTTDemoTask( void *pvParameters );
\r
141 * @brief The callback invoked by the MQTT library when the MQTT connection gets
\r
144 * @param[in] pvCallbackContext Callback context as provided at the time of
\r
146 * @param[in] pxCallbackParams Contains the reason why the MQTT connection was
\r
149 static void prvExample_DisconnectCallback( void * pvCallbackContext,
\r
150 IotMqttCallbackParam_t * pxCallbackParams );
\r
153 * @brief The callback invoked by the MQTT library when a message is received on
\r
154 * a subscribed topic from the MQTT broker.
\r
156 * @param[in] pvCallbackContext Callback context as provided at the time of
\r
158 * @param[in] pxCallbackParams Contain the details about the received message -
\r
159 * topic on which the message was received, the received message.
\r
161 static void prvExample_PublishCallback( void * pvCallbackContext,
\r
162 IotMqttCallbackParam_t * pxCallbackParams );
\r
165 * @brief Connects to the MQTT broker as specified in mqttexampleMQTT_BROKER_ENDPOINT
\r
166 * and mqttexampleMQTT_BROKER_PORT.
\r
168 * @note This example does not use TLS and therefore will not work with MQTT.
\r
170 static void prvMQTTConnect( void );
\r
173 * @brief Subscribes to the topic as specified in mqttexampleTOPIC.
\r
175 static void prvMQTTSubscribe( void );
\r
178 * @brief Publishes a messages mqttexampleMESSAGE on mqttexampleTOPIC topic.
\r
180 static void prvMQTTPublish( void );
\r
183 * @brief Unsubscribes from the mqttexampleTOPIC topic.
\r
185 static void prvMQTTUnsubscribe( void );
\r
188 * @brief Disconnects from the MQTT broker gracefully by sending an MQTT
\r
189 * DISCONNECT message.
\r
191 static void prvMQTTDisconnect( void );
\r
192 /*-----------------------------------------------------------*/
\r
194 static void prvExample_DisconnectCallback( void * pvCallbackContext,
\r
195 IotMqttCallbackParam_t * pxCallbackParams )
\r
197 TaskHandle_t xDemoTaskHandle = ( TaskHandle_t ) pvCallbackContext;
\r
199 /* Ensure that we initiated the disconnect. */
\r
200 configASSERT( pxCallbackParams->u.disconnectReason == IOT_MQTT_DISCONNECT_CALLED );
\r
202 /* Inform the demo task about the disconnect. */
\r
203 xTaskNotify( xDemoTaskHandle,
\r
204 mqttexampleDISCONNECTED_BIT,
\r
205 eSetBits /* Set the mqttexampleDISCONNECTED_BIT in the demo task's notification value. */
\r
208 /*-----------------------------------------------------------*/
\r
210 static void prvExample_PublishCallback( void * pvCallbackContext,
\r
211 IotMqttCallbackParam_t * pxCallbackParams )
\r
213 TaskHandle_t xDemoTaskHandle = ( TaskHandle_t ) pvCallbackContext;
\r
215 /* Ensure that the message is received on the expected topic. */
\r
216 configASSERT( pxCallbackParams->u.message.info.topicNameLength == strlen( mqttexampleTOPIC ) );
\r
217 configASSERT( strncmp( pxCallbackParams->u.message.info.pTopicName,
\r
219 strlen( mqttexampleTOPIC ) ) == 0 );
\r
221 /* Ensure that the expected message is received. */
\r
222 configASSERT( pxCallbackParams->u.message.info.payloadLength == strlen( mqttexampleMESSAGE ) );
\r
223 configASSERT( strncmp( pxCallbackParams->u.message.info.pPayload,
\r
224 mqttexampleMESSAGE,
\r
225 strlen( mqttexampleMESSAGE ) ) == 0 );
\r
227 /* Ensure that the message QoS is as expected. */
\r
228 configASSERT( pxCallbackParams->u.message.info.qos == IOT_MQTT_QOS_1 );
\r
230 /* Inform the demo task about the message received from the MQTT broker. */
\r
231 xTaskNotify( xDemoTaskHandle,
\r
232 mqttexampleMESSAGE_RECEIVED_BIT,
\r
233 eSetBits /* Set the mqttexampleMESSAGE_RECEIVED_BIT in the demo task's notification value. */
\r
236 /*-----------------------------------------------------------*/
\r
238 void vStartSimpleMQTTDemo( void )
\r
240 /* This example uses a single application task, which in turn is used to
\r
241 * connect, subscribe, publish, unsubscribe and disconnect from the MQTT
\r
243 xTaskCreate( prvMQTTDemoTask, /* Function that implements the task. */
\r
244 "MQTTDemo", /* Text name for the task - only used for debugging. */
\r
245 configMINIMAL_STACK_SIZE, /* Size of stack (in words, not bytes) to allocate for the task. */
\r
246 NULL, /* Task parameter - not used in this case. */
\r
247 tskIDLE_PRIORITY, /* Task priority, must be between 0 and configMAX_PRIORITIES - 1. */
\r
248 NULL ); /* Used to pass out a handle to the created task - not used in this case. */
\r
250 /*-----------------------------------------------------------*/
\r
252 static void prvMQTTDemoTask( void *pvParameters )
\r
254 IotMqttError_t xResult;
\r
255 uint32_t ulNotificationValue = 0;
\r
256 const TickType_t xNoDelay = ( TickType_t ) 0;
\r
258 /* Remove compiler warnings about unused parameters. */
\r
259 ( void ) pvParameters;
\r
261 /* The MQTT library needs a task pool, so create the system task pool. */
\r
262 xResult = IotTaskPool_CreateSystemTaskPool( &( xTaskPoolParameters ) );
\r
263 configASSERT( xResult == IOT_TASKPOOL_SUCCESS );
\r
265 /* MQTT library must be initialized before it can be used. This is just one
\r
266 * time initialization. */
\r
267 xResult = IotMqtt_Init();
\r
268 configASSERT( xResult == IOT_MQTT_SUCCESS );
\r
272 /* Don't expect any notifications to be pending yet. */
\r
273 configASSERT( ulTaskNotifyTake( pdTRUE, xNoDelay ) == 0 );
\r
275 /* Establish a connection to the MQTT broker. This example connects to
\r
276 * the MQTT broker as specified in mqttexampleMQTT_BROKER_ENDPOINT and
\r
277 * mqttexampleMQTT_BROKER_PORT at the top of this file. Please change
\r
278 * it to the MQTT broker you want to connect to. Note that this example
\r
279 * does not use TLS and therefore will not work with AWS IoT. */
\r
282 /* Subscribe to the topic as specified in mqttexampleTOPIC at the top
\r
284 prvMQTTSubscribe();
\r
286 /* Publish a message on the mqttexampleTOPIC topic as specified at the
\r
287 * top of this file. */
\r
290 /* Since we are subscribed on the same topic, we will get the same
\r
291 * message back from the MQTT broker. Wait for the message to be
\r
292 * received which is informed to us by the publish callback
\r
293 * (prvExample_PublishCallback) by setting the mqttexampleMESSAGE_RECEIVED_BIT
\r
294 * in this task's notification value. */
\r
295 xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */
\r
296 0UL, /* Don't clear any bits on exit. */
\r
297 &( ulNotificationValue ), /* Obtain the notification value. */
\r
298 pdMS_TO_TICKS( mqttexampleMQTT_TIMEOUT_MS ) );
\r
299 configASSERT( ( ulNotificationValue & mqttexampleMESSAGE_RECEIVED_BIT ) == mqttexampleMESSAGE_RECEIVED_BIT );
\r
301 /* Unsubscribe from the topic mqttexampleTOPIC. */
\r
302 prvMQTTUnsubscribe();
\r
304 /* Gracefully disconnect from the MQTT broker by sending an MQTT
\r
305 * DISCONNECT message. */
\r
306 prvMQTTDisconnect();
\r
308 /* Wait for the disconnect operation to complete which is informed to us
\r
309 * by the disconnect callback (prvExample_DisconnectCallback)by setting
\r
310 * the mqttexampleDISCONNECTED_BIT in this task's notification value.
\r
311 * Note that all bits are cleared in the task's notification value to
\r
312 * ensure that it is ready for the next run. */
\r
313 xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */
\r
314 portMAX_DELAY, /* Clear all bits on exit - portMAX_DELAY is used as it is a portable way of having all bits set. */
\r
315 &( ulNotificationValue ), /* Obtain the notification value. */
\r
316 pdMS_TO_TICKS( mqttexampleMQTT_TIMEOUT_MS ) );
\r
317 configASSERT( ( ulNotificationValue & mqttexampleDISCONNECTED_BIT ) == mqttexampleDISCONNECTED_BIT );
\r
319 printf( "prvMQTTDemoTask() completed an iteration without hitting an assert.\r\n" );
\r
322 /* Wait for some time between two iterations to ensure that we do not
\r
323 * bombard the public test mosquitto broker. */
\r
324 vTaskDelay( pdMS_TO_TICKS( 5000 ) );
\r
327 /*-----------------------------------------------------------*/
\r
329 static void prvMQTTConnect( void )
\r
331 IotMqttError_t xResult;
\r
332 IotNetworkServerInfo_t xMQTTBrokerInfo;
\r
333 IotMqttNetworkInfo_t xNetworkInfo = IOT_MQTT_NETWORK_INFO_INITIALIZER;
\r
334 IotMqttConnectInfo_t xConnectInfo = IOT_MQTT_CONNECT_INFO_INITIALIZER;
\r
336 /******************* Broker information setup. **********************/
\r
337 xMQTTBrokerInfo.pHostName = mqttexampleMQTT_BROKER_ENDPOINT;
\r
338 xMQTTBrokerInfo.port = mqttexampleMQTT_BROKER_PORT;
\r
340 /******************* Network information setup. **********************/
\r
341 /* No connection to the MQTT broker has been established yet and we want to
\r
342 * establish a new connection. */
\r
343 xNetworkInfo.createNetworkConnection = true;
\r
344 xNetworkInfo.u.setup.pNetworkServerInfo = &( xMQTTBrokerInfo );
\r
346 /* This example does not use TLS and therefore pNetworkCredentialInfo must
\r
347 * be set to NULL. */
\r
348 xNetworkInfo.u.setup.pNetworkCredentialInfo = NULL;
\r
350 /* Use FreeRTOS+TCP network. */
\r
351 xNetworkInfo.pNetworkInterface = IOT_NETWORK_INTERFACE_AFR;
\r
353 /* Setup the callback which is called when the MQTT connection is disconnected. */
\r
354 xNetworkInfo.disconnectCallback.pCallbackContext = ( void * ) xTaskGetCurrentTaskHandle();
\r
355 xNetworkInfo.disconnectCallback.function = prvExample_DisconnectCallback;
\r
357 /****************** MQTT Connection information setup. ********************/
\r
358 /* This example does not use TLS and therefore won't work with AWS IoT. */
\r
359 xConnectInfo.awsIotMqttMode = false;
\r
361 /* Start with a clean session i.e. direct the MQTT broker to discard any
\r
362 * previous session data. Also, establishing a connection with clean session
\r
363 * will ensure that the broker does not store any data when this client
\r
364 * gets disconnected. */
\r
365 xConnectInfo.cleanSession = true;
\r
367 /* Since we are starting with a clean session, there are no previous
\r
368 * subscriptions to be restored. */
\r
369 xConnectInfo.pPreviousSubscriptions = NULL;
\r
370 xConnectInfo.previousSubscriptionCount = 0;
\r
372 /* We do not want to publish Last Will and Testament (LWT) message if the
\r
373 * client gets disconnected. */
\r
374 xConnectInfo.pWillInfo = NULL;
\r
376 /* Send an MQTT PING request every minute. */
\r
377 xConnectInfo.keepAliveSeconds = mqttexampleKEEP_ALIVE_SECONDS;
\r
379 /* The client identifier is used to uniquely identify this MQTT client to
\r
380 * the MQTT broker. */
\r
381 xConnectInfo.pClientIdentifier = mqttexampleCLIENT_IDENTIFIER;
\r
382 xConnectInfo.clientIdentifierLength = ( uint16_t ) strlen( mqttexampleCLIENT_IDENTIFIER );
\r
384 /* This example does not use any authentication and therefore username and
\r
385 * password fields are not used. */
\r
386 xConnectInfo.pUserName = NULL;
\r
387 xConnectInfo.userNameLength = 0;
\r
388 xConnectInfo.pPassword = NULL;
\r
389 xConnectInfo.passwordLength = 0;
\r
391 /* Establish the connection to the MQTT broker - It is a blocking call and
\r
392 will return only when connection is complete. */
\r
393 xResult = IotMqtt_Connect( &( xNetworkInfo ),
\r
395 mqttexampleMQTT_TIMEOUT_MS,
\r
396 &( xMQTTConnection ) );
\r
397 configASSERT( xResult == IOT_MQTT_SUCCESS );
\r
399 /*-----------------------------------------------------------*/
\r
401 static void prvMQTTSubscribe( void )
\r
403 IotMqttError_t xResult;
\r
404 IotMqttSubscription_t xMQTTSubscription;
\r
406 /* Subscribe to the mqttexampleTOPIC topic filter. */
\r
407 xMQTTSubscription.qos = IOT_MQTT_QOS_1;
\r
408 xMQTTSubscription.pTopicFilter = mqttexampleTOPIC;
\r
409 xMQTTSubscription.topicFilterLength = ( uint16_t ) strlen( mqttexampleTOPIC );
\r
410 xMQTTSubscription.callback.pCallbackContext = ( void * ) xTaskGetCurrentTaskHandle();
\r
411 xMQTTSubscription.callback.function = prvExample_PublishCallback;
\r
413 /* Use the synchronous API to subscribe - It is a blocking call and only
\r
414 * returns when the subscribe operation is complete. */
\r
415 xResult = IotMqtt_TimedSubscribe( xMQTTConnection,
\r
416 &( xMQTTSubscription ),
\r
417 1, /* We are subscribing to one topic filter. */
\r
418 0, /* flags - currently ignored. */
\r
419 mqttexampleMQTT_TIMEOUT_MS );
\r
420 configASSERT( xResult == IOT_MQTT_SUCCESS );
\r
422 /*-----------------------------------------------------------*/
\r
424 static void prvMQTTPublish( void )
\r
426 IotMqttError_t xResult;
\r
427 IotMqttPublishInfo_t xMQTTPublishInfo;
\r
429 /* Publish a message with QoS1 on the mqttexampleTOPIC topic. Since we are
\r
430 * subscribed to the same topic, the MQTT broker will send the same message
\r
431 * back to us. It is verified in the publish callback. */
\r
432 xMQTTPublishInfo.qos = IOT_MQTT_QOS_1;
\r
433 xMQTTPublishInfo.retain = false;
\r
434 xMQTTPublishInfo.pTopicName = mqttexampleTOPIC;
\r
435 xMQTTPublishInfo.topicNameLength = ( uint16_t ) strlen( mqttexampleTOPIC );
\r
436 xMQTTPublishInfo.pPayload = mqttexampleMESSAGE;
\r
437 xMQTTPublishInfo.payloadLength = strlen( mqttexampleMESSAGE );
\r
438 xMQTTPublishInfo.retryMs = mqttexamplePUBLISH_RETRY_MS;
\r
439 xMQTTPublishInfo.retryLimit = mqttexamplePUBLISH_RETRY_LIMIT;
\r
441 /* Use the synchronous API to publish - It is a blocking call and only
\r
442 * returns when the publish operation is complete. */
\r
443 xResult = IotMqtt_TimedPublish( xMQTTConnection,
\r
444 &( xMQTTPublishInfo ),
\r
445 0, /* flags - currently ignored. */
\r
446 mqttexampleMQTT_TIMEOUT_MS );
\r
447 configASSERT( xResult == IOT_MQTT_SUCCESS );
\r
449 /*-----------------------------------------------------------*/
\r
451 static void prvMQTTUnsubscribe( void )
\r
453 IotMqttError_t xResult;
\r
454 IotMqttSubscription_t xMQTTSubscription;
\r
456 /* Unsubscribe from the mqttexampleTOPIC topic filter. */
\r
457 xMQTTSubscription.pTopicFilter = mqttexampleTOPIC;
\r
458 xMQTTSubscription.topicFilterLength = ( uint16_t ) strlen( mqttexampleTOPIC );
\r
459 /* The following members of the IotMqttSubscription_t are ignored by the
\r
460 * unsubscribe operation. Just initialize them to avoid "use of uninitialized
\r
461 * variable" warnings. */
\r
462 xMQTTSubscription.qos = IOT_MQTT_QOS_1;
\r
463 xMQTTSubscription.callback.pCallbackContext = NULL;
\r
464 xMQTTSubscription.callback.function = NULL;
\r
466 /* Use the synchronous API to unsubscribe - It is a blocking call and only
\r
467 * returns when the unsubscribe operation is complete. */
\r
468 xResult = IotMqtt_TimedUnsubscribe( xMQTTConnection,
\r
469 &( xMQTTSubscription ),
\r
470 1, /* We are unsubscribing from one topic filter. */
\r
471 0, /* flags - currently ignored. */
\r
472 mqttexampleMQTT_TIMEOUT_MS );
\r
473 configASSERT( xResult == IOT_MQTT_SUCCESS );
\r
475 /*-----------------------------------------------------------*/
\r
477 static void prvMQTTDisconnect( void )
\r
479 /* Send a MQTT DISCONNECT packet to the MQTT broker to do a graceful
\r
481 IotMqtt_Disconnect( xMQTTConnection,
\r
482 0 /* flags - 0 means a graceful disconnect by sending MQTT DISCONNECT. */
\r
485 /*-----------------------------------------------------------*/
\r