]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/DemoTasks/SimpleMQTTExamples.c
Add first draft of mqtt example
[freertos] / FreeRTOS-Plus / Demo / FreeRTOS_IoT_Libraries / mqtt / DemoTasks / SimpleMQTTExamples.c
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/DemoTasks/SimpleMQTTExamples.c b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/DemoTasks/SimpleMQTTExamples.c
new file mode 100644 (file)
index 0000000..d0c9e0b
--- /dev/null
@@ -0,0 +1,447 @@
+/*\r
+ * FreeRTOS Kernel V10.2.1\r
+ * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://aws.amazon.com/freertos\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ */\r
+\r
+/* Standard inclues. */\r
+#include <string.h>\r
+\r
+/* Kernel includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+\r
+/* MQTT include. */\r
+#include "iot_mqtt.h"\r
+\r
+/* Platform FreeRTOS network include. */\r
+#include "platform/iot_network_freertos.h"\r
+\r
+/**\r
+ * @brief The keep-alive interval used for this example.\r
+ *\r
+ * An MQTT ping request will be sent periodically at this interval.\r
+ */\r
+#define mqttexampleKEEP_ALIVE_SECONDS          ( 60 )\r
+\r
+/**\r
+ * @brief The timeout for MQTT operations in this example.\r
+ */\r
+#define mqttexampleMQTT_TIMEOUT_MS                     ( 5000 )\r
+\r
+/**\r
+ * @brief The MQTT client identifier used in this example.\r
+ */\r
+#define mqttexampleCLIENT_IDENTIFIER           "mqttexampleclient"\r
+\r
+/**\r
+ * @brief Details of the MQTT broker to connect to.\r
+ *\r
+ * @note This example does not use TLS and therefore won't work with AWS IoT.\r
+ */\r
+#define mqttexampleMQTT_BROKER_ENDPOINT                "10.60.214.105"\r
+#define mqttexampleMQTT_BROKER_PORT                    1883\r
+\r
+/**\r
+ * @brief The topic to subscribe and publish to in the example.\r
+ */\r
+#define mqttexampleTOPIC                                       "example/topic"\r
+\r
+/**\r
+ * @brief The MQTT message published in this example.\r
+ */\r
+#define mqttexampleMESSAGE                                     "Hello World!"\r
+\r
+/**\r
+ * @brief Paramters to control the retry behaviour in case a QoS1 publish\r
+ * message gets lost.\r
+ *\r
+ * Retry every minutes up to a maximum of 5 retries.\r
+ */\r
+#define mqttexamplePUBLISH_RETRY_MS                    ( 1000 )\r
+#define mqttexamplePUBLISH_RETRY_LIMIT         ( 5 )\r
+\r
+/**\r
+ * @brief The bit which is set in the demo task's notification value from the\r
+ * disconnect callback to inform the demo task about the MQTT disconnect.\r
+ */\r
+#define mqttexampleDISCONNECTED_BIT                    ( 1UL << 0UL )\r
+\r
+/**\r
+ * @brief The bit which is set in the demo task's notification value from the\r
+ * publish callback to inform the demo task about the message received from the\r
+ * MQTT broker.\r
+ */\r
+#define mqttexampleMESSAGE_RECEIVED_BIT                ( 1UL << 1UL )\r
+/*-----------------------------------------------------------*/\r
+\r
+/**\r
+ * @brief The MQTT connection handle used in this example.\r
+ */\r
+static IotMqttConnection_t xMQTTConnection = IOT_MQTT_CONNECTION_INITIALIZER;\r
+/*-----------------------------------------------------------*/\r
+\r
+/**\r
+ * @brief The task used to demonstrate the MQTT API.\r
+ *\r
+ * @param[in] pvParameters Parmaters as passed at the time of task creation. Not\r
+ * used in this example.\r
+ */\r
+static void prvMQTTDemoTask( void *pvParameters );\r
+\r
+/**\r
+ * @brief The callback invoked by the MQTT library when the MQTT connection gets\r
+ * disconnected.\r
+ * \r
+ * @param[in] pvCallbackContext Callback context as provided at the time of\r
+ * connect.\r
+ * @param[in] pxCallbackParams Contains the reason why the MQTT connection was\r
+ * disconnected.\r
+ */\r
+static void prvExample_DisconnectCallback( void * pvCallbackContext,\r
+                                                                                  IotMqttCallbackParam_t * pxCallbackParams );\r
+\r
+/**\r
+ * @brief The callback invoked by the MQTT library when a message is received on\r
+ * a subscribed topic from the MQTT broker.\r
+ * \r
+ * @param[in] pvCallbackContext Callback context as provided at the time of\r
+ * subscribe.\r
+ * @param[in] pxCallbackParams Contain the details about the received message - \r
+ * topic on which the message was received, the received message.\r
+ */\r
+static void prvExample_PublishCallback( void * pvCallbackContext,\r
+                                                                               IotMqttCallbackParam_t * pxCallbackParams );\r
+\r
+/**\r
+ * @brief Connects to the MQTT broker as specified in mqttexampleMQTT_BROKER_ENDPOINT\r
+ * and mqttexampleMQTT_BROKER_PORT.\r
+ * \r
+ * @note This example does not use TLS and therefore will not work with MQTT.\r
+ */\r
+static void prvMQTTConnect( void );\r
+\r
+/**\r
+ * @brief Subscribes to the topic as specified in mqttexampleTOPIC.\r
+ */\r
+static void prvMQTTSubscribe( void );\r
+\r
+/**\r
+ * @brief Publishes a messages mqttexampleMESSAGE on mqttexampleTOPIC topic.\r
+ */\r
+static void prvMQTTPublish( void );\r
+\r
+/**\r
+ * @brief Unsubscribes from the mqttexampleTOPIC topic.\r
+ */\r
+static void prvMQTTUnsubscribe( void );\r
+\r
+/**\r
+ * @brief Disconnects from the MQTT broker gracefully by sending an MQTT\r
+ * DISCONNECT message.\r
+ */\r
+static void prvMQTTDisconnect( void );\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvExample_DisconnectCallback( void * pvCallbackContext,\r
+                                                                                  IotMqttCallbackParam_t * pxCallbackParams )\r
+{\r
+TaskHandle_t xDemoTaskHandle = ( TaskHandle_t ) pvCallbackContext;\r
+\r
+       /* Ensure that we initiated the disconnect. */\r
+       configASSERT( pxCallbackParams->u.disconnectReason == IOT_MQTT_DISCONNECT_CALLED );\r
+\r
+       /* Inform the demo task about the disconnect. */\r
+       xTaskNotify( xDemoTaskHandle,\r
+                               mqttexampleDISCONNECTED_BIT,\r
+                               eSetBits /* Set the mqttexampleDISCONNECTED_BIT in the demo task's notification value. */\r
+                               );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvExample_PublishCallback( void * pvCallbackContext,\r
+                                                                               IotMqttCallbackParam_t * pxCallbackParams )\r
+{\r
+TaskHandle_t xDemoTaskHandle = ( TaskHandle_t ) pvCallbackContext;\r
+\r
+       /* Ensure that the message is received on the expected topic. */\r
+       configASSERT( pxCallbackParams->u.message.info.topicNameLength == strlen( mqttexampleTOPIC ) );\r
+       configASSERT( strncmp( pxCallbackParams->u.message.info.pTopicName,\r
+                                                  mqttexampleTOPIC,\r
+                                                  strlen( mqttexampleTOPIC ) ) == 0 );\r
+\r
+       /* Ensure that the expected message is received. */\r
+       configASSERT( pxCallbackParams->u.message.info.payloadLength == strlen( mqttexampleMESSAGE ) );\r
+       configASSERT( strncmp( pxCallbackParams->u.message.info.pPayload,\r
+                                                  mqttexampleMESSAGE,\r
+                                                  strlen( mqttexampleMESSAGE ) ) == 0 );\r
+\r
+       /* Ensure that the message QoS is as expected. */\r
+       configASSERT( pxCallbackParams->u.message.info.qos == IOT_MQTT_QOS_1 );\r
+\r
+       /* Inform the demo task about the message received from the MQTT broker. */\r
+       xTaskNotify( xDemoTaskHandle,\r
+                               mqttexampleMESSAGE_RECEIVED_BIT,\r
+                               eSetBits /* Set the mqttexampleMESSAGE_RECEIVED_BIT in the demo task's notification value. */\r
+                               );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vStartSimpleMQTTDemo( void )\r
+{\r
+       /* This example uses a single application task, which in turn is used to\r
+        * connect, subscribe, publish, unsubscribe and disconnect from the MQTT\r
+        * broker. */\r
+       xTaskCreate( prvMQTTDemoTask,                   /* Function that implements the task. */\r
+                                "MQTTDemo",                            /* Text name for the task - only used for debugging. */\r
+                                configMINIMAL_STACK_SIZE,      /* Size of stack (in words, not bytes) to allocate for the task. */\r
+                                NULL,                                          /* Task parameter - not used in this case. */\r
+                                tskIDLE_PRIORITY,                      /* Task priority, must be between 0 and configMAX_PRIORITIES - 1. */\r
+                                NULL );                                        /* Used to pass out a handle to the created task - not used in this case. */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvMQTTDemoTask( void *pvParameters )\r
+{\r
+IotMqttError_t xResult;\r
+uint32_t ulNotificationValue = 0;\r
+const TickType_t xNoDelay = ( TickType_t ) 0;\r
+\r
+       /* Remove compiler warnings about unused parameters. */\r
+       ( void ) pvParameters;\r
+\r
+       /* MQTT library must be initialized before it can be used. This is just one\r
+        * time initialization. */\r
+       xResult = IotMqtt_Init();\r
+       configASSERT( xResult == IOT_MQTT_SUCCESS );\r
+\r
+       for( ; ; )\r
+       {\r
+               /* Don't expect any notifications to be pending yet. */\r
+               configASSERT( ulTaskNotifyTake( pdTRUE, xNoDelay ) == 0 );\r
+\r
+               /* Establish a connection to the MQTT broker. This example connects to\r
+                * the MQTT broker as specified in mqttexampleMQTT_BROKER_ENDPOINT and\r
+                * mqttexampleMQTT_BROKER_PORT at the top of this file. Please change\r
+                * it to the MQTT broker you want to connect to. Note that this example\r
+                * does not use TLS and therefore will not work with AWS IoT. */\r
+               prvMQTTConnect();\r
+\r
+               /* Subscribe to the topic as specified in mqttexampleTOPIC at the top\r
+                * of this file. */\r
+               prvMQTTSubscribe();\r
+\r
+               /* Publish a message on the mqttexampleTOPIC topic as specified at the\r
+                * top of this file. */\r
+               prvMQTTPublish();\r
+\r
+               /* Since we are subscribed on the same topic, we will get the same\r
+                * message back from the MQTT broker. Wait for the message to be\r
+                * received which is informed to us by the publish callback\r
+                * (prvExample_PublishCallback) by setting the mqttexampleMESSAGE_RECEIVED_BIT\r
+                * in this task's notification value. */\r
+               xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */\r
+                                                0UL, /* Don't clear any bits on exit. */\r
+                                                &( ulNotificationValue ), /* Obtain the notification value. */\r
+                                                pdMS_TO_TICKS( mqttexampleMQTT_TIMEOUT_MS ) );\r
+               configASSERT( ( ulNotificationValue & mqttexampleMESSAGE_RECEIVED_BIT ) == mqttexampleMESSAGE_RECEIVED_BIT );\r
+\r
+               /* Unsubscribe from the topic mqttexampleTOPIC. */\r
+               prvMQTTUnsubscribe();\r
+\r
+               /* Gracefully disconnect from the MQTT broker by sending an MQTT\r
+                * DISCONNECT message. */\r
+               prvMQTTDisconnect();\r
+\r
+               /* Wait for the disconnect operation to complete which is informed to us\r
+                * by the disconnect callback (prvExample_DisconnectCallback)by setting\r
+                * the mqttexampleDISCONNECTED_BIT in this task's notification value.\r
+                * Note that all bits are cleared in the task's notification value to\r
+                * ensure that it is ready for the next run. */\r
+               xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */\r
+                                                portMAX_DELAY, /* Clear all bits on exit - portMAX_DELAY is used as it is a portable way of having all bits set. */\r
+                                                &( ulNotificationValue ), /* Obtain the notification value. */\r
+                                                pdMS_TO_TICKS( mqttexampleMQTT_TIMEOUT_MS ) );\r
+               configASSERT( ( ulNotificationValue & mqttexampleDISCONNECTED_BIT ) == mqttexampleDISCONNECTED_BIT );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvMQTTConnect( void )\r
+{\r
+IotMqttError_t xResult;\r
+IotNetworkServerInfo_t xMQTTBrokerInfo;\r
+IotMqttNetworkInfo_t xNetworkInfo = IOT_MQTT_NETWORK_INFO_INITIALIZER;\r
+IotMqttConnectInfo_t xConnectInfo = IOT_MQTT_CONNECT_INFO_INITIALIZER;\r
+\r
+       /******************* Broker information setup. **********************/\r
+       xMQTTBrokerInfo.pHostName = mqttexampleMQTT_BROKER_ENDPOINT;\r
+       xMQTTBrokerInfo.port = mqttexampleMQTT_BROKER_PORT;\r
+\r
+       /******************* Network information setup. **********************/\r
+       /* No connection to the MQTT broker has been established yet and we want to\r
+        * establish a new connection. */\r
+       xNetworkInfo.createNetworkConnection = true;\r
+       xNetworkInfo.u.setup.pNetworkServerInfo = &( xMQTTBrokerInfo );\r
+\r
+       /* This example does not use TLS and therefore pNetworkCredentialInfo must\r
+        * be set to NULL. */\r
+       xNetworkInfo.u.setup.pNetworkCredentialInfo = NULL;\r
+\r
+       /* Use FreeRTOS+TCP network. */\r
+       xNetworkInfo.pNetworkInterface = IOT_NETWORK_INTERFACE_AFR;\r
+\r
+       /* Setup the callback which is called when the MQTT connection is disconnected. */\r
+       xNetworkInfo.disconnectCallback.pCallbackContext = ( void * ) xTaskGetCurrentTaskHandle();\r
+       xNetworkInfo.disconnectCallback.function = prvExample_DisconnectCallback;\r
+\r
+       /****************** MQTT Connection information setup. ********************/\r
+       /* This example does not use TLS and therefore won't work with AWS IoT. */\r
+       xConnectInfo.awsIotMqttMode = false;\r
+\r
+       /* Start with a clean session i.e. direct the MQTT broker to discard any\r
+        * previous session data. Also, establishing a connection with clean session\r
+        * will ensure that the broker does not store any data when this client\r
+        * gets disconnected. */\r
+       xConnectInfo.cleanSession = true;\r
+\r
+       /* Since we are starting with a clean session, there are no previous\r
+        * subscriptions to be restored. */\r
+       xConnectInfo.pPreviousSubscriptions = NULL;\r
+       xConnectInfo.previousSubscriptionCount = 0;\r
+\r
+       /* We do not want to publish Last Will and Testament (LWT) message if the\r
+        * client gets disconnected. */\r
+       xConnectInfo.pWillInfo = NULL;\r
+\r
+       /* Send an MQTT PING request every minute. */\r
+       xConnectInfo.keepAliveSeconds = mqttexampleKEEP_ALIVE_SECONDS;\r
+\r
+       /* The client identifier is used to uniquely identify this MQTT client to\r
+        * the MQTT broker. */\r
+       xConnectInfo.pClientIdentifier = mqttexampleCLIENT_IDENTIFIER;\r
+       xConnectInfo.clientIdentifierLength = ( uint16_t ) strlen( mqttexampleCLIENT_IDENTIFIER );\r
+\r
+       /* This example does not use any authentication and therefore username and\r
+        * password fields are not used. */\r
+       xConnectInfo.pUserName = NULL;\r
+       xConnectInfo.userNameLength = 0;\r
+       xConnectInfo.pPassword = NULL;\r
+       xConnectInfo.passwordLength = 0;\r
+\r
+       /* Establish the connection to the MQTT broker - It is a blocking call and\r
+       will return only when connection is complete. */\r
+       xResult = IotMqtt_Connect( &( xNetworkInfo ),\r
+                                                          &( xConnectInfo ),\r
+                                                          mqttexampleMQTT_TIMEOUT_MS,\r
+                                                          &( xMQTTConnection ) );\r
+       configASSERT( xResult == IOT_MQTT_SUCCESS );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvMQTTSubscribe( void )\r
+{\r
+IotMqttError_t xResult;\r
+IotMqttSubscription_t xMQTTSubscription;\r
+\r
+       /* Subscribe to the mqttexampleTOPIC topic filter. */\r
+       xMQTTSubscription.qos = IOT_MQTT_QOS_1;\r
+       xMQTTSubscription.pTopicFilter = mqttexampleTOPIC;\r
+       xMQTTSubscription.topicFilterLength = ( uint16_t ) strlen( mqttexampleTOPIC );\r
+       xMQTTSubscription.callback.pCallbackContext = ( void * ) xTaskGetCurrentTaskHandle();\r
+       xMQTTSubscription.callback.function = prvExample_PublishCallback;\r
+\r
+       /* Use the synchronous API to subscribe - It is a blocking call and only\r
+        * returns when the subscribe operation is complete. */\r
+       xResult = IotMqtt_TimedSubscribe( xMQTTConnection,\r
+                                                                         &( xMQTTSubscription ),\r
+                                                                         1, /* We are subscribing to one topic filter. */\r
+                                                                         0, /* flags - currently ignored. */\r
+                                                                         mqttexampleMQTT_TIMEOUT_MS );\r
+       configASSERT( xResult == IOT_MQTT_SUCCESS );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvMQTTPublish( void )\r
+{\r
+IotMqttError_t xResult;\r
+IotMqttPublishInfo_t xMQTTPublishInfo;\r
+\r
+       /* Publish a message with QoS1 on the mqttexampleTOPIC topic. Since we are\r
+        * subscribed to the same topic, the MQTT broker will send the same message\r
+        * back to us. It is verified in the publish callback. */\r
+       xMQTTPublishInfo.qos = IOT_MQTT_QOS_1;\r
+       xMQTTPublishInfo.retain = false;\r
+       xMQTTPublishInfo.pTopicName = mqttexampleTOPIC;\r
+       xMQTTPublishInfo.topicNameLength = ( uint16_t ) strlen( mqttexampleTOPIC );\r
+       xMQTTPublishInfo.pPayload = mqttexampleMESSAGE;\r
+       xMQTTPublishInfo.payloadLength = strlen( mqttexampleMESSAGE );\r
+       xMQTTPublishInfo.retryMs = mqttexamplePUBLISH_RETRY_MS;\r
+       xMQTTPublishInfo.retryLimit = mqttexamplePUBLISH_RETRY_LIMIT;\r
+\r
+       /* Use the synchronous API to publish - It is a blocking call and only\r
+        * returns when the publish operation is complete. */\r
+       xResult = IotMqtt_TimedPublish( xMQTTConnection,\r
+                                                                       &( xMQTTPublishInfo ),\r
+                                                                       0, /* flags - currently ignored. */\r
+                                                                       mqttexampleMQTT_TIMEOUT_MS );\r
+       configASSERT( xResult == IOT_MQTT_SUCCESS );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvMQTTUnsubscribe( void )\r
+{\r
+IotMqttError_t xResult;\r
+IotMqttSubscription_t xMQTTSubscription;\r
+\r
+       /* Unsubscribe from the mqttexampleTOPIC topic filter. */\r
+       xMQTTSubscription.pTopicFilter = mqttexampleTOPIC;\r
+       xMQTTSubscription.topicFilterLength = ( uint16_t ) strlen( mqttexampleTOPIC );\r
+       /* The following members of the IotMqttSubscription_t are ignored by the\r
+        * unsubscribe operation. Just initialize them to avoid "use of uninitialized\r
+        * variable" warnings. */\r
+       xMQTTSubscription.qos = IOT_MQTT_QOS_1;\r
+       xMQTTSubscription.callback.pCallbackContext = NULL;\r
+       xMQTTSubscription.callback.function = NULL;\r
+\r
+       /* Use the synchronous API to unsubscribe - It is a blocking call and only\r
+        * returns when the unsubscribe operation is complete. */\r
+       xResult = IotMqtt_TimedUnsubscribe( xMQTTConnection,\r
+                                                                               &( xMQTTSubscription ),\r
+                                                                               1, /* We are unsubscribing from one topic filter. */\r
+                                                                               0, /* flags - currently ignored. */\r
+                                                                               mqttexampleMQTT_TIMEOUT_MS );\r
+       configASSERT( xResult == IOT_MQTT_SUCCESS );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvMQTTDisconnect( void )\r
+{\r
+       /* Send a MQTT DISCONNECT packet to the MQTT broker to do a graceful\r
+        * disconnect. */\r
+       IotMqtt_Disconnect( xMQTTConnection,\r
+                                               0 /* flags - 0 means a graceful disconnect by sending MQTT DISCONNECT. */\r
+                                               );\r
+}\r
+/*-----------------------------------------------------------*/\r