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
31 /* Kernel includes. */
\r
32 #include "FreeRTOS.h"
\r
36 #include "iot_mqtt.h"
\r
38 /* Platform FreeRTOS network include. */
\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
63 #define mqttexampleMQTT_BROKER_ENDPOINT "10.60.214.105"
\r
64 #define mqttexampleMQTT_BROKER_PORT 1883
\r
67 * @brief The topic to subscribe and publish to in the example.
\r
69 #define mqttexampleTOPIC "example/topic"
\r
72 * @brief The MQTT message published in this example.
\r
74 #define mqttexampleMESSAGE "Hello World!"
\r
77 * @brief Paramters to control the retry behaviour in case a QoS1 publish
\r
78 * message gets lost.
\r
80 * Retry every minutes up to a maximum of 5 retries.
\r
82 #define mqttexamplePUBLISH_RETRY_MS ( 1000 )
\r
83 #define mqttexamplePUBLISH_RETRY_LIMIT ( 5 )
\r
86 * @brief The bit which is set in the demo task's notification value from the
\r
87 * disconnect callback to inform the demo task about the MQTT disconnect.
\r
89 #define mqttexampleDISCONNECTED_BIT ( 1UL << 0UL )
\r
92 * @brief The bit which is set in the demo task's notification value from the
\r
93 * publish callback to inform the demo task about the message received from the
\r
96 #define mqttexampleMESSAGE_RECEIVED_BIT ( 1UL << 1UL )
\r
97 /*-----------------------------------------------------------*/
\r
100 * @brief The MQTT connection handle used in this example.
\r
102 static IotMqttConnection_t xMQTTConnection = IOT_MQTT_CONNECTION_INITIALIZER;
\r
103 /*-----------------------------------------------------------*/
\r
106 * @brief The task used to demonstrate the MQTT API.
\r
108 * @param[in] pvParameters Parmaters as passed at the time of task creation. Not
\r
109 * used in this example.
\r
111 static void prvMQTTDemoTask( void *pvParameters );
\r
114 * @brief The callback invoked by the MQTT library when the MQTT connection gets
\r
117 * @param[in] pvCallbackContext Callback context as provided at the time of
\r
119 * @param[in] pxCallbackParams Contains the reason why the MQTT connection was
\r
122 static void prvExample_DisconnectCallback( void * pvCallbackContext,
\r
123 IotMqttCallbackParam_t * pxCallbackParams );
\r
126 * @brief The callback invoked by the MQTT library when a message is received on
\r
127 * a subscribed topic from the MQTT broker.
\r
129 * @param[in] pvCallbackContext Callback context as provided at the time of
\r
131 * @param[in] pxCallbackParams Contain the details about the received message -
\r
132 * topic on which the message was received, the received message.
\r
134 static void prvExample_PublishCallback( void * pvCallbackContext,
\r
135 IotMqttCallbackParam_t * pxCallbackParams );
\r
138 * @brief Connects to the MQTT broker as specified in mqttexampleMQTT_BROKER_ENDPOINT
\r
139 * and mqttexampleMQTT_BROKER_PORT.
\r
141 * @note This example does not use TLS and therefore will not work with MQTT.
\r
143 static void prvMQTTConnect( void );
\r
146 * @brief Subscribes to the topic as specified in mqttexampleTOPIC.
\r
148 static void prvMQTTSubscribe( void );
\r
151 * @brief Publishes a messages mqttexampleMESSAGE on mqttexampleTOPIC topic.
\r
153 static void prvMQTTPublish( void );
\r
156 * @brief Unsubscribes from the mqttexampleTOPIC topic.
\r
158 static void prvMQTTUnsubscribe( void );
\r
161 * @brief Disconnects from the MQTT broker gracefully by sending an MQTT
\r
162 * DISCONNECT message.
\r
164 static void prvMQTTDisconnect( void );
\r
165 /*-----------------------------------------------------------*/
\r
167 static void prvExample_DisconnectCallback( void * pvCallbackContext,
\r
168 IotMqttCallbackParam_t * pxCallbackParams )
\r
170 TaskHandle_t xDemoTaskHandle = ( TaskHandle_t ) pvCallbackContext;
\r
172 /* Ensure that we initiated the disconnect. */
\r
173 configASSERT( pxCallbackParams->u.disconnectReason == IOT_MQTT_DISCONNECT_CALLED );
\r
175 /* Inform the demo task about the disconnect. */
\r
176 xTaskNotify( xDemoTaskHandle,
\r
177 mqttexampleDISCONNECTED_BIT,
\r
178 eSetBits /* Set the mqttexampleDISCONNECTED_BIT in the demo task's notification value. */
\r
181 /*-----------------------------------------------------------*/
\r
183 static void prvExample_PublishCallback( void * pvCallbackContext,
\r
184 IotMqttCallbackParam_t * pxCallbackParams )
\r
186 TaskHandle_t xDemoTaskHandle = ( TaskHandle_t ) pvCallbackContext;
\r
188 /* Ensure that the message is received on the expected topic. */
\r
189 configASSERT( pxCallbackParams->u.message.info.topicNameLength == strlen( mqttexampleTOPIC ) );
\r
190 configASSERT( strncmp( pxCallbackParams->u.message.info.pTopicName,
\r
192 strlen( mqttexampleTOPIC ) ) == 0 );
\r
194 /* Ensure that the expected message is received. */
\r
195 configASSERT( pxCallbackParams->u.message.info.payloadLength == strlen( mqttexampleMESSAGE ) );
\r
196 configASSERT( strncmp( pxCallbackParams->u.message.info.pPayload,
\r
197 mqttexampleMESSAGE,
\r
198 strlen( mqttexampleMESSAGE ) ) == 0 );
\r
200 /* Ensure that the message QoS is as expected. */
\r
201 configASSERT( pxCallbackParams->u.message.info.qos == IOT_MQTT_QOS_1 );
\r
203 /* Inform the demo task about the message received from the MQTT broker. */
\r
204 xTaskNotify( xDemoTaskHandle,
\r
205 mqttexampleMESSAGE_RECEIVED_BIT,
\r
206 eSetBits /* Set the mqttexampleMESSAGE_RECEIVED_BIT in the demo task's notification value. */
\r
209 /*-----------------------------------------------------------*/
\r
211 void vStartSimpleMQTTDemo( void )
\r
213 /* This example uses a single application task, which in turn is used to
\r
214 * connect, subscribe, publish, unsubscribe and disconnect from the MQTT
\r
216 xTaskCreate( prvMQTTDemoTask, /* Function that implements the task. */
\r
217 "MQTTDemo", /* Text name for the task - only used for debugging. */
\r
218 configMINIMAL_STACK_SIZE, /* Size of stack (in words, not bytes) to allocate for the task. */
\r
219 NULL, /* Task parameter - not used in this case. */
\r
220 tskIDLE_PRIORITY, /* Task priority, must be between 0 and configMAX_PRIORITIES - 1. */
\r
221 NULL ); /* Used to pass out a handle to the created task - not used in this case. */
\r
223 /*-----------------------------------------------------------*/
\r
225 static void prvMQTTDemoTask( void *pvParameters )
\r
227 IotMqttError_t xResult;
\r
228 uint32_t ulNotificationValue = 0;
\r
229 const TickType_t xNoDelay = ( TickType_t ) 0;
\r
231 /* Remove compiler warnings about unused parameters. */
\r
232 ( void ) pvParameters;
\r
234 /* MQTT library must be initialized before it can be used. This is just one
\r
235 * time initialization. */
\r
236 xResult = IotMqtt_Init();
\r
237 configASSERT( xResult == IOT_MQTT_SUCCESS );
\r
241 /* Don't expect any notifications to be pending yet. */
\r
242 configASSERT( ulTaskNotifyTake( pdTRUE, xNoDelay ) == 0 );
\r
244 /* Establish a connection to the MQTT broker. This example connects to
\r
245 * the MQTT broker as specified in mqttexampleMQTT_BROKER_ENDPOINT and
\r
246 * mqttexampleMQTT_BROKER_PORT at the top of this file. Please change
\r
247 * it to the MQTT broker you want to connect to. Note that this example
\r
248 * does not use TLS and therefore will not work with AWS IoT. */
\r
251 /* Subscribe to the topic as specified in mqttexampleTOPIC at the top
\r
253 prvMQTTSubscribe();
\r
255 /* Publish a message on the mqttexampleTOPIC topic as specified at the
\r
256 * top of this file. */
\r
259 /* Since we are subscribed on the same topic, we will get the same
\r
260 * message back from the MQTT broker. Wait for the message to be
\r
261 * received which is informed to us by the publish callback
\r
262 * (prvExample_PublishCallback) by setting the mqttexampleMESSAGE_RECEIVED_BIT
\r
263 * in this task's notification value. */
\r
264 xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */
\r
265 0UL, /* Don't clear any bits on exit. */
\r
266 &( ulNotificationValue ), /* Obtain the notification value. */
\r
267 pdMS_TO_TICKS( mqttexampleMQTT_TIMEOUT_MS ) );
\r
268 configASSERT( ( ulNotificationValue & mqttexampleMESSAGE_RECEIVED_BIT ) == mqttexampleMESSAGE_RECEIVED_BIT );
\r
270 /* Unsubscribe from the topic mqttexampleTOPIC. */
\r
271 prvMQTTUnsubscribe();
\r
273 /* Gracefully disconnect from the MQTT broker by sending an MQTT
\r
274 * DISCONNECT message. */
\r
275 prvMQTTDisconnect();
\r
277 /* Wait for the disconnect operation to complete which is informed to us
\r
278 * by the disconnect callback (prvExample_DisconnectCallback)by setting
\r
279 * the mqttexampleDISCONNECTED_BIT in this task's notification value.
\r
280 * Note that all bits are cleared in the task's notification value to
\r
281 * ensure that it is ready for the next run. */
\r
282 xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */
\r
283 portMAX_DELAY, /* Clear all bits on exit - portMAX_DELAY is used as it is a portable way of having all bits set. */
\r
284 &( ulNotificationValue ), /* Obtain the notification value. */
\r
285 pdMS_TO_TICKS( mqttexampleMQTT_TIMEOUT_MS ) );
\r
286 configASSERT( ( ulNotificationValue & mqttexampleDISCONNECTED_BIT ) == mqttexampleDISCONNECTED_BIT );
\r
289 /*-----------------------------------------------------------*/
\r
291 static void prvMQTTConnect( void )
\r
293 IotMqttError_t xResult;
\r
294 IotNetworkServerInfo_t xMQTTBrokerInfo;
\r
295 IotMqttNetworkInfo_t xNetworkInfo = IOT_MQTT_NETWORK_INFO_INITIALIZER;
\r
296 IotMqttConnectInfo_t xConnectInfo = IOT_MQTT_CONNECT_INFO_INITIALIZER;
\r
298 /******************* Broker information setup. **********************/
\r
299 xMQTTBrokerInfo.pHostName = mqttexampleMQTT_BROKER_ENDPOINT;
\r
300 xMQTTBrokerInfo.port = mqttexampleMQTT_BROKER_PORT;
\r
302 /******************* Network information setup. **********************/
\r
303 /* No connection to the MQTT broker has been established yet and we want to
\r
304 * establish a new connection. */
\r
305 xNetworkInfo.createNetworkConnection = true;
\r
306 xNetworkInfo.u.setup.pNetworkServerInfo = &( xMQTTBrokerInfo );
\r
308 /* This example does not use TLS and therefore pNetworkCredentialInfo must
\r
309 * be set to NULL. */
\r
310 xNetworkInfo.u.setup.pNetworkCredentialInfo = NULL;
\r
312 /* Use FreeRTOS+TCP network. */
\r
313 xNetworkInfo.pNetworkInterface = IOT_NETWORK_INTERFACE_AFR;
\r
315 /* Setup the callback which is called when the MQTT connection is disconnected. */
\r
316 xNetworkInfo.disconnectCallback.pCallbackContext = ( void * ) xTaskGetCurrentTaskHandle();
\r
317 xNetworkInfo.disconnectCallback.function = prvExample_DisconnectCallback;
\r
319 /****************** MQTT Connection information setup. ********************/
\r
320 /* This example does not use TLS and therefore won't work with AWS IoT. */
\r
321 xConnectInfo.awsIotMqttMode = false;
\r
323 /* Start with a clean session i.e. direct the MQTT broker to discard any
\r
324 * previous session data. Also, establishing a connection with clean session
\r
325 * will ensure that the broker does not store any data when this client
\r
326 * gets disconnected. */
\r
327 xConnectInfo.cleanSession = true;
\r
329 /* Since we are starting with a clean session, there are no previous
\r
330 * subscriptions to be restored. */
\r
331 xConnectInfo.pPreviousSubscriptions = NULL;
\r
332 xConnectInfo.previousSubscriptionCount = 0;
\r
334 /* We do not want to publish Last Will and Testament (LWT) message if the
\r
335 * client gets disconnected. */
\r
336 xConnectInfo.pWillInfo = NULL;
\r
338 /* Send an MQTT PING request every minute. */
\r
339 xConnectInfo.keepAliveSeconds = mqttexampleKEEP_ALIVE_SECONDS;
\r
341 /* The client identifier is used to uniquely identify this MQTT client to
\r
342 * the MQTT broker. */
\r
343 xConnectInfo.pClientIdentifier = mqttexampleCLIENT_IDENTIFIER;
\r
344 xConnectInfo.clientIdentifierLength = ( uint16_t ) strlen( mqttexampleCLIENT_IDENTIFIER );
\r
346 /* This example does not use any authentication and therefore username and
\r
347 * password fields are not used. */
\r
348 xConnectInfo.pUserName = NULL;
\r
349 xConnectInfo.userNameLength = 0;
\r
350 xConnectInfo.pPassword = NULL;
\r
351 xConnectInfo.passwordLength = 0;
\r
353 /* Establish the connection to the MQTT broker - It is a blocking call and
\r
354 will return only when connection is complete. */
\r
355 xResult = IotMqtt_Connect( &( xNetworkInfo ),
\r
357 mqttexampleMQTT_TIMEOUT_MS,
\r
358 &( xMQTTConnection ) );
\r
359 configASSERT( xResult == IOT_MQTT_SUCCESS );
\r
361 /*-----------------------------------------------------------*/
\r
363 static void prvMQTTSubscribe( void )
\r
365 IotMqttError_t xResult;
\r
366 IotMqttSubscription_t xMQTTSubscription;
\r
368 /* Subscribe to the mqttexampleTOPIC topic filter. */
\r
369 xMQTTSubscription.qos = IOT_MQTT_QOS_1;
\r
370 xMQTTSubscription.pTopicFilter = mqttexampleTOPIC;
\r
371 xMQTTSubscription.topicFilterLength = ( uint16_t ) strlen( mqttexampleTOPIC );
\r
372 xMQTTSubscription.callback.pCallbackContext = ( void * ) xTaskGetCurrentTaskHandle();
\r
373 xMQTTSubscription.callback.function = prvExample_PublishCallback;
\r
375 /* Use the synchronous API to subscribe - It is a blocking call and only
\r
376 * returns when the subscribe operation is complete. */
\r
377 xResult = IotMqtt_TimedSubscribe( xMQTTConnection,
\r
378 &( xMQTTSubscription ),
\r
379 1, /* We are subscribing to one topic filter. */
\r
380 0, /* flags - currently ignored. */
\r
381 mqttexampleMQTT_TIMEOUT_MS );
\r
382 configASSERT( xResult == IOT_MQTT_SUCCESS );
\r
384 /*-----------------------------------------------------------*/
\r
386 static void prvMQTTPublish( void )
\r
388 IotMqttError_t xResult;
\r
389 IotMqttPublishInfo_t xMQTTPublishInfo;
\r
391 /* Publish a message with QoS1 on the mqttexampleTOPIC topic. Since we are
\r
392 * subscribed to the same topic, the MQTT broker will send the same message
\r
393 * back to us. It is verified in the publish callback. */
\r
394 xMQTTPublishInfo.qos = IOT_MQTT_QOS_1;
\r
395 xMQTTPublishInfo.retain = false;
\r
396 xMQTTPublishInfo.pTopicName = mqttexampleTOPIC;
\r
397 xMQTTPublishInfo.topicNameLength = ( uint16_t ) strlen( mqttexampleTOPIC );
\r
398 xMQTTPublishInfo.pPayload = mqttexampleMESSAGE;
\r
399 xMQTTPublishInfo.payloadLength = strlen( mqttexampleMESSAGE );
\r
400 xMQTTPublishInfo.retryMs = mqttexamplePUBLISH_RETRY_MS;
\r
401 xMQTTPublishInfo.retryLimit = mqttexamplePUBLISH_RETRY_LIMIT;
\r
403 /* Use the synchronous API to publish - It is a blocking call and only
\r
404 * returns when the publish operation is complete. */
\r
405 xResult = IotMqtt_TimedPublish( xMQTTConnection,
\r
406 &( xMQTTPublishInfo ),
\r
407 0, /* flags - currently ignored. */
\r
408 mqttexampleMQTT_TIMEOUT_MS );
\r
409 configASSERT( xResult == IOT_MQTT_SUCCESS );
\r
411 /*-----------------------------------------------------------*/
\r
413 static void prvMQTTUnsubscribe( void )
\r
415 IotMqttError_t xResult;
\r
416 IotMqttSubscription_t xMQTTSubscription;
\r
418 /* Unsubscribe from the mqttexampleTOPIC topic filter. */
\r
419 xMQTTSubscription.pTopicFilter = mqttexampleTOPIC;
\r
420 xMQTTSubscription.topicFilterLength = ( uint16_t ) strlen( mqttexampleTOPIC );
\r
421 /* The following members of the IotMqttSubscription_t are ignored by the
\r
422 * unsubscribe operation. Just initialize them to avoid "use of uninitialized
\r
423 * variable" warnings. */
\r
424 xMQTTSubscription.qos = IOT_MQTT_QOS_1;
\r
425 xMQTTSubscription.callback.pCallbackContext = NULL;
\r
426 xMQTTSubscription.callback.function = NULL;
\r
428 /* Use the synchronous API to unsubscribe - It is a blocking call and only
\r
429 * returns when the unsubscribe operation is complete. */
\r
430 xResult = IotMqtt_TimedUnsubscribe( xMQTTConnection,
\r
431 &( xMQTTSubscription ),
\r
432 1, /* We are unsubscribing from one topic filter. */
\r
433 0, /* flags - currently ignored. */
\r
434 mqttexampleMQTT_TIMEOUT_MS );
\r
435 configASSERT( xResult == IOT_MQTT_SUCCESS );
\r
437 /*-----------------------------------------------------------*/
\r
439 static void prvMQTTDisconnect( void )
\r
441 /* Send a MQTT DISCONNECT packet to the MQTT broker to do a graceful
\r
443 IotMqtt_Disconnect( xMQTTConnection,
\r
444 0 /* flags - 0 means a graceful disconnect by sending MQTT DISCONNECT. */
\r
447 /*-----------------------------------------------------------*/
\r