mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-12-23 11:09:28 -05:00
Changes to prepare for Jobs Library Demo (#401)
* Add submodule pointer to the aws/jobs-for-aws-iot-embedded-sdk repository for the Jobs library * Commonize the MQTT helper functions used by the Device Shadow demo by re-locating them to FreeRTOS-Plus/Demo/AWS/MQTT_Demo_Helpers and updating the Device Shadow demo to use the new files
This commit is contained in:
parent
de26f7f2f4
commit
e96fd8b872
7 changed files with 192 additions and 160 deletions
104
FreeRTOS-Plus/Demo/AWS/Device_Shadow_Windows_Simulator/Device_Shadow_Demo/DemoTasks/ShadowDemoMainExample.c
Normal file → Executable file
104
FreeRTOS-Plus/Demo/AWS/Device_Shadow_Windows_Simulator/Device_Shadow_Demo/DemoTasks/ShadowDemoMainExample.c
Normal file → Executable file
|
|
@ -62,10 +62,10 @@
|
|||
/* JSON library includes. */
|
||||
#include "core_json.h"
|
||||
|
||||
/* Shadow demo helpers header. */
|
||||
#include "shadow_demo_helpers.h"
|
||||
/* Include MQTT demo helpers header. */
|
||||
#include "mqtt_demo_helpers.h"
|
||||
|
||||
/* Demo Specific configs. */
|
||||
/* Demo Specific config file. */
|
||||
#include "demo_config.h"
|
||||
|
||||
|
||||
|
|
@ -148,25 +148,43 @@
|
|||
*/
|
||||
#define SHADOW_REPORTED_JSON_LENGTH ( sizeof( SHADOW_REPORTED_JSON ) - 3 )
|
||||
|
||||
#ifndef THING_NAME
|
||||
/*------------- Demo configurations -------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Predefined thing name.
|
||||
*
|
||||
* This is the example predefine thing name and could be compiled in ROM code.
|
||||
*/
|
||||
#define THING_NAME democonfigCLIENT_IDENTIFIER
|
||||
#ifndef democonfigTHING_NAME
|
||||
#define democonfigTHING_NAME democonfigCLIENT_IDENTIFIER
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief The length of #THING_NAME.
|
||||
* @brief The length of #democonfigTHING_NAME.
|
||||
*/
|
||||
#define THING_NAME_LENGTH ( ( uint16_t ) ( sizeof( THING_NAME ) - 1 ) )
|
||||
|
||||
|
||||
#define THING_NAME_LENGTH ( ( uint16_t ) ( sizeof( democonfigTHING_NAME ) - 1 ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief The MQTT context used for MQTT operation.
|
||||
*/
|
||||
static MQTTContext_t xMqttContext;
|
||||
|
||||
/**
|
||||
* @brief The network context used for mbedTLS operation.
|
||||
*/
|
||||
static NetworkContext_t xNetworkContext;
|
||||
|
||||
/**
|
||||
* @brief Static buffer used to hold MQTT messages being sent and received.
|
||||
*/
|
||||
static uint8_t ucSharedBuffer[ democonfigNETWORK_BUFFER_SIZE ];
|
||||
|
||||
/**
|
||||
* @brief Static buffer used to hold MQTT messages being sent and received.
|
||||
*/
|
||||
static MQTTFixedBuffer_t xBuffer =
|
||||
{
|
||||
.pBuffer = ucSharedBuffer,
|
||||
.size = democonfigNETWORK_BUFFER_SIZE
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The simulated device current power on state.
|
||||
*/
|
||||
|
|
@ -523,14 +541,15 @@ static void prvEventCallback( MQTTContext_t * pxMqttContext,
|
|||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* @brief Create the task that demonstrates the Shadow API Demo via a
|
||||
* MQTT mutually authenticated network connection with MQTT broker.
|
||||
* @brief Create the task that demonstrates the Device Shadow library API via a
|
||||
* MQTT mutually authenticated network connection with the AWS IoT broker.
|
||||
*/
|
||||
void vStartShadowDemo( void )
|
||||
{
|
||||
/* This example uses a single application task, which shows that how to
|
||||
* use Device Shadow library to get shadow topics and validate shadow topics
|
||||
* via MQTT APIs communicating with the MQTT broker. */
|
||||
* use Device Shadow library to generate and validate AWS IoT Device Shadow
|
||||
* MQTT topics, and use the coreMQTT library to communicate with the AWS IoT
|
||||
* Device Shadow service. */
|
||||
xTaskCreate( prvShadowDemoTask, /* Function that implements the task. */
|
||||
"DemoTask", /* Text name for the task - only used for debugging. */
|
||||
democonfigDEMO_STACKSIZE, /* Size of stack (in words, not bytes) to allocate for the task. */
|
||||
|
|
@ -538,7 +557,6 @@ void vStartShadowDemo( void )
|
|||
tskIDLE_PRIORITY, /* Task priority, must be between 0 and configMAX_PRIORITIES - 1. */
|
||||
NULL ); /* Used to pass out a handle to the created task - not used in this case. */
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
|
|
@ -564,14 +582,17 @@ void prvShadowDemoTask( void * pvParameters )
|
|||
{
|
||||
BaseType_t demoStatus = pdPASS;
|
||||
|
||||
/* Remove compiler warnings about unused parameters. */
|
||||
( void ) pvParameters;
|
||||
|
||||
/* A buffer containing the update document. It has static duration to prevent
|
||||
* it from being placed on the call stack. */
|
||||
static char pcUpdateDocument[ SHADOW_REPORTED_JSON_LENGTH + 1 ] = { 0 };
|
||||
|
||||
demoStatus = xEstablishMqttSession( prvEventCallback );
|
||||
/* Remove compiler warnings about unused parameters. */
|
||||
( void ) pvParameters;
|
||||
|
||||
demoStatus = xEstablishMqttSession( &xMqttContext,
|
||||
&xNetworkContext,
|
||||
&xBuffer,
|
||||
prvEventCallback );
|
||||
|
||||
if( pdFAIL == demoStatus )
|
||||
{
|
||||
|
|
@ -581,7 +602,8 @@ void prvShadowDemoTask( void * pvParameters )
|
|||
else
|
||||
{
|
||||
/* First of all, try to delete any Shadow document in the cloud. */
|
||||
demoStatus = xPublishToTopic( SHADOW_TOPIC_STRING_DELETE( THING_NAME ),
|
||||
demoStatus = xPublishToTopic( &xMqttContext,
|
||||
SHADOW_TOPIC_STRING_DELETE( democonfigTHING_NAME ),
|
||||
SHADOW_TOPIC_LENGTH_DELETE( THING_NAME_LENGTH ),
|
||||
pcUpdateDocument,
|
||||
0U );
|
||||
|
|
@ -589,23 +611,26 @@ void prvShadowDemoTask( void * pvParameters )
|
|||
/* Then try to subscribe shadow topics. */
|
||||
if( demoStatus == pdPASS )
|
||||
{
|
||||
demoStatus = xSubscribeToTopic( SHADOW_TOPIC_STRING_UPDATE_DELTA( THING_NAME ),
|
||||
demoStatus = xSubscribeToTopic( &xMqttContext,
|
||||
SHADOW_TOPIC_STRING_UPDATE_DELTA( democonfigTHING_NAME ),
|
||||
SHADOW_TOPIC_LENGTH_UPDATE_DELTA( THING_NAME_LENGTH ) );
|
||||
}
|
||||
|
||||
if( demoStatus == pdPASS )
|
||||
{
|
||||
demoStatus = xSubscribeToTopic( SHADOW_TOPIC_STRING_UPDATE_ACCEPTED( THING_NAME ),
|
||||
demoStatus = xSubscribeToTopic( &xMqttContext,
|
||||
SHADOW_TOPIC_STRING_UPDATE_ACCEPTED( democonfigTHING_NAME ),
|
||||
SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED( THING_NAME_LENGTH ) );
|
||||
}
|
||||
|
||||
if( demoStatus == pdPASS )
|
||||
{
|
||||
demoStatus = xSubscribeToTopic( SHADOW_TOPIC_STRING_UPDATE_REJECTED( THING_NAME ),
|
||||
demoStatus = xSubscribeToTopic( &xMqttContext,
|
||||
SHADOW_TOPIC_STRING_UPDATE_REJECTED( democonfigTHING_NAME ),
|
||||
SHADOW_TOPIC_LENGTH_UPDATE_REJECTED( THING_NAME_LENGTH ) );
|
||||
}
|
||||
|
||||
/* This demo uses a constant #THING_NAME known at compile time therefore we can use macros to
|
||||
/* This demo uses a constant #democonfigTHING_NAME known at compile time therefore we can use macros to
|
||||
* assemble shadow topic strings.
|
||||
* If the thing name is known at run time, then we could use the API #Shadow_GetTopicString to
|
||||
* assemble shadow topic strings, here is the example for /update/delta:
|
||||
|
|
@ -651,7 +676,8 @@ void prvShadowDemoTask( void * pvParameters )
|
|||
( int ) 1,
|
||||
( long unsigned ) ( xTaskGetTickCount() % 1000000 ) );
|
||||
|
||||
demoStatus = xPublishToTopic( SHADOW_TOPIC_STRING_UPDATE( THING_NAME ),
|
||||
demoStatus = xPublishToTopic( &xMqttContext,
|
||||
SHADOW_TOPIC_STRING_UPDATE( democonfigTHING_NAME ),
|
||||
SHADOW_TOPIC_LENGTH_UPDATE( THING_NAME_LENGTH ),
|
||||
pcUpdateDocument,
|
||||
( SHADOW_DESIRED_JSON_LENGTH + 1 ) );
|
||||
|
|
@ -683,7 +709,8 @@ void prvShadowDemoTask( void * pvParameters )
|
|||
( int ) ulCurrentPowerOnState,
|
||||
( long unsigned ) ulClientToken );
|
||||
|
||||
demoStatus = xPublishToTopic( SHADOW_TOPIC_STRING_UPDATE( THING_NAME ),
|
||||
demoStatus = xPublishToTopic( &xMqttContext,
|
||||
SHADOW_TOPIC_STRING_UPDATE( democonfigTHING_NAME ),
|
||||
SHADOW_TOPIC_LENGTH_UPDATE( THING_NAME_LENGTH ),
|
||||
pcUpdateDocument,
|
||||
( SHADOW_DESIRED_JSON_LENGTH + 1 ) );
|
||||
|
|
@ -698,42 +725,45 @@ void prvShadowDemoTask( void * pvParameters )
|
|||
{
|
||||
LogInfo( ( "Start to unsubscribe shadow topics and disconnect from MQTT. \r\n" ) );
|
||||
|
||||
demoStatus = xUnsubscribeFromTopic( SHADOW_TOPIC_STRING_UPDATE_DELTA( THING_NAME ),
|
||||
demoStatus = xUnsubscribeFromTopic( &xMqttContext,
|
||||
SHADOW_TOPIC_STRING_UPDATE_DELTA( democonfigTHING_NAME ),
|
||||
SHADOW_TOPIC_LENGTH_UPDATE_DELTA( THING_NAME_LENGTH ) );
|
||||
|
||||
if( demoStatus != pdPASS )
|
||||
{
|
||||
LogError( ( "Failed to unsubscribe the topic %s",
|
||||
SHADOW_TOPIC_STRING_UPDATE_DELTA( THING_NAME ) ) );
|
||||
SHADOW_TOPIC_STRING_UPDATE_DELTA( democonfigTHING_NAME ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
if( demoStatus == pdPASS )
|
||||
{
|
||||
demoStatus = xUnsubscribeFromTopic( SHADOW_TOPIC_STRING_UPDATE_ACCEPTED( THING_NAME ),
|
||||
demoStatus = xUnsubscribeFromTopic( &xMqttContext,
|
||||
SHADOW_TOPIC_STRING_UPDATE_ACCEPTED( democonfigTHING_NAME ),
|
||||
SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED( THING_NAME_LENGTH ) );
|
||||
|
||||
if( demoStatus != pdPASS )
|
||||
{
|
||||
LogError( ( "Failed to unsubscribe the topic %s",
|
||||
SHADOW_TOPIC_STRING_UPDATE_ACCEPTED( THING_NAME ) ) );
|
||||
SHADOW_TOPIC_STRING_UPDATE_ACCEPTED( democonfigTHING_NAME ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
if( demoStatus == pdPASS )
|
||||
{
|
||||
demoStatus = xUnsubscribeFromTopic( SHADOW_TOPIC_STRING_UPDATE_REJECTED( THING_NAME ),
|
||||
demoStatus = xUnsubscribeFromTopic( &xMqttContext,
|
||||
SHADOW_TOPIC_STRING_UPDATE_REJECTED( democonfigTHING_NAME ),
|
||||
SHADOW_TOPIC_LENGTH_UPDATE_REJECTED( THING_NAME_LENGTH ) );
|
||||
|
||||
if( demoStatus != pdPASS )
|
||||
{
|
||||
LogError( ( "Failed to unsubscribe the topic %s",
|
||||
SHADOW_TOPIC_STRING_UPDATE_REJECTED( THING_NAME ) ) );
|
||||
SHADOW_TOPIC_STRING_UPDATE_REJECTED( democonfigTHING_NAME ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* The MQTT session is always disconnected, even there were prior failures. */
|
||||
demoStatus = xDisconnectMqttSession();
|
||||
demoStatus = xDisconnectMqttSession( &xMqttContext, &xNetworkContext );
|
||||
|
||||
/* This demo performs only Device Shadow operations. If matching the Shadow
|
||||
* MQTT topic fails or there are failure in parsing the received JSON document,
|
||||
|
|
|
|||
|
|
@ -1,929 +0,0 @@
|
|||
/*
|
||||
* FreeRTOS V202011.00
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file shadow_demo_helpers.c
|
||||
*
|
||||
* @brief This file provides helper functions used by the Shadow demo application to
|
||||
* do MQTT operations over a mutually authenticated TLS connection.
|
||||
*
|
||||
* A mutually authenticated TLS connection is used to connect to the AWS IoT
|
||||
* MQTT message broker in this example. Define democonfigCLIENT_PRIVATE_KEY_PEM,
|
||||
* democonfigCLIENT_CERTIFICATE_PEM, and democonfigMQTT_BROKER_ENDPOINT in
|
||||
* demo_config.h to achieve mutual authentication.
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Kernel includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Shadow includes */
|
||||
#include "shadow_demo_helpers.h"
|
||||
|
||||
/* Demo Specific configs. */
|
||||
#include "demo_config.h"
|
||||
|
||||
/* MQTT library includes. */
|
||||
#include "core_mqtt.h"
|
||||
|
||||
/* Exponential backoff retry include. */
|
||||
#include "exponential_backoff.h"
|
||||
|
||||
/* Transport interface implementation include header for TLS. */
|
||||
#include "using_mbedtls.h"
|
||||
|
||||
/*------------- Demo configurations -------------------------*/
|
||||
|
||||
/** Note: The device client certificate and private key credentials are
|
||||
* obtained by the TLS transport interface implementation from the
|
||||
* demo_config.h file.
|
||||
*/
|
||||
|
||||
#ifndef democonfigCLIENT_PRIVATE_KEY_PEM
|
||||
#error "Please define client private key(democonfigCLIENT_PRIVATE_KEY_PEM) in demo_config.h."
|
||||
#endif
|
||||
|
||||
#ifndef democonfigCLIENT_CERTIFICATE_PEM
|
||||
#error "Please define client certificate(democonfigCLIENT_CERTIFICATE_PEM) in demo_config.h."
|
||||
#endif
|
||||
|
||||
#ifndef democonfigMQTT_BROKER_ENDPOINT
|
||||
#error "Please define democonfigMQTT_BROKER_ENDPOINT in demo_config.h."
|
||||
#endif
|
||||
|
||||
#ifndef democonfigMQTT_BROKER_PORT
|
||||
|
||||
/**
|
||||
* @brief The port to use for the demo.
|
||||
*/
|
||||
#define democonfigMQTT_BROKER_PORT ( 8883 )
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Timeout for receiving CONNACK packet in milliseconds.
|
||||
*/
|
||||
#define mqttexampleCONNACK_RECV_TIMEOUT_MS ( 1000U )
|
||||
|
||||
/**
|
||||
* @brief The number of topic filters to subscribe.
|
||||
*/
|
||||
#define mqttexampleTOPIC_COUNT ( 1 )
|
||||
|
||||
/**
|
||||
* @brief Time to wait between each cycle of the demo implemented by prvMQTTDemoTask().
|
||||
*/
|
||||
#define mqttexampleDELAY_BETWEEN_DEMO_ITERATIONS ( pdMS_TO_TICKS( 5000U ) )
|
||||
|
||||
/**
|
||||
* @brief Timeout for MQTT_ProcessLoop in milliseconds.
|
||||
*/
|
||||
#define mqttexamplePROCESS_LOOP_TIMEOUT_MS ( 500U )
|
||||
|
||||
/**
|
||||
* @brief Keep alive time reported to the broker while establishing an MQTT connection.
|
||||
*
|
||||
* It is the responsibility of the Client to ensure that the interval between
|
||||
* Control Packets being sent does not exceed this Keep Alive value. In the
|
||||
* absence of sending any other Control Packets, the Client MUST send a
|
||||
* PINGREQ Packet.
|
||||
*/
|
||||
#define mqttexampleKEEP_ALIVE_TIMEOUT_SECONDS ( 60U )
|
||||
|
||||
/**
|
||||
* @brief Delay between MQTT publishes. Note that the process loop also has a
|
||||
* timeout, so the total time between publishes is the sum of the two delays.
|
||||
*/
|
||||
#define mqttexampleDELAY_BETWEEN_PUBLISHES ( pdMS_TO_TICKS( 500U ) )
|
||||
|
||||
/**
|
||||
* @brief Transport timeout in milliseconds for transport send and receive.
|
||||
*/
|
||||
#define mqttexampleTRANSPORT_SEND_RECV_TIMEOUT_MS ( 200U )
|
||||
|
||||
/**
|
||||
* @brief Maximum number of outgoing publishes maintained in the application
|
||||
* until an ack is received from the broker.
|
||||
*/
|
||||
#define MAX_OUTGOING_PUBLISHES ( 1U )
|
||||
|
||||
/**
|
||||
* @brief Milliseconds per second.
|
||||
*/
|
||||
#define MILLISECONDS_PER_SECOND ( 1000U )
|
||||
|
||||
/**
|
||||
* @brief Milliseconds per FreeRTOS tick.
|
||||
*/
|
||||
#define MILLISECONDS_PER_TICK ( MILLISECONDS_PER_SECOND / configTICK_RATE_HZ )
|
||||
|
||||
/**
|
||||
* @brief The MQTT metrics string expected by AWS IoT.
|
||||
*/
|
||||
#define AWS_IOT_METRICS_STRING \
|
||||
"?SDK=" democonfigOS_NAME "&Version=" democonfigOS_VERSION \
|
||||
"&Platform=" democonfigHARDWARE_PLATFORM_NAME "&MQTTLib=" democonfigMQTT_LIB
|
||||
|
||||
/**
|
||||
* @brief The length of the MQTT metrics string expected by AWS IoT.
|
||||
*/
|
||||
#define AWS_IOT_METRICS_STRING_LENGTH ( ( uint16_t ) ( sizeof( AWS_IOT_METRICS_STRING ) - 1 ) )
|
||||
|
||||
/**
|
||||
* @brief ALPN (Application-Layer Protocol Negotiation) protocol name for AWS IoT MQTT.
|
||||
*
|
||||
* This will be used if democonfigMQTT_BROKER_PORT is configured as 443 for the AWS IoT MQTT broker.
|
||||
* Please see more details about the ALPN protocol for AWS IoT MQTT endpoint
|
||||
* in the link below.
|
||||
* https://aws.amazon.com/blogs/iot/mqtt-with-tls-client-authentication-on-port-443-why-it-is-useful-and-how-it-works/
|
||||
*/
|
||||
#define AWS_IOT_MQTT_ALPN "\x0ex-amzn-mqtt-ca"
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Structure to keep the MQTT publish packets until an ack is received
|
||||
* for QoS1 publishes.
|
||||
*/
|
||||
typedef struct PublishPackets
|
||||
{
|
||||
/**
|
||||
* @brief Packet identifier of the publish packet.
|
||||
*/
|
||||
uint16_t packetId;
|
||||
|
||||
/**
|
||||
* @brief Publish info of the publish packet.
|
||||
*/
|
||||
MQTTPublishInfo_t pubInfo;
|
||||
} PublishPackets_t;
|
||||
|
||||
/**
|
||||
* @brief Global entry time into the application to use as a reference timestamp
|
||||
* in the #prvGetTimeMs function. #prvGetTimeMs will always return the difference
|
||||
* between the current time and the global entry time. This will reduce the chances
|
||||
* of overflow for the 32 bit unsigned integer used for holding the timestamp.
|
||||
*/
|
||||
static uint32_t ulGlobalEntryTimeMs;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Packet Identifier generated when Subscribe request was sent to the broker;
|
||||
* it is used to match received Subscribe ACK to the transmitted subscribe.
|
||||
*/
|
||||
static uint16_t globalSubscribePacketIdentifier = 0U;
|
||||
|
||||
/**
|
||||
* @brief Packet Identifier generated when Unsubscribe request was sent to the broker;
|
||||
* it is used to match received Unsubscribe ACK to the transmitted unsubscribe
|
||||
* request.
|
||||
*/
|
||||
static uint16_t globalUnsubscribePacketIdentifier = 0U;
|
||||
|
||||
/**
|
||||
* @brief Array to keep the outgoing publish messages.
|
||||
* These stored outgoing publish messages are kept until a successful ack
|
||||
* is received.
|
||||
*/
|
||||
static PublishPackets_t outgoingPublishPackets[ MAX_OUTGOING_PUBLISHES ] = { 0 };
|
||||
|
||||
/**
|
||||
* @brief Static buffer used to hold MQTT messages being sent and received.
|
||||
*/
|
||||
static uint8_t ucSharedBuffer[ democonfigNETWORK_BUFFER_SIZE ];
|
||||
|
||||
/**
|
||||
* @brief The MQTT context used for MQTT operation.
|
||||
*/
|
||||
static MQTTContext_t mqttContext = { 0 };
|
||||
|
||||
/**
|
||||
* @brief The network context used for Openssl operation.
|
||||
*/
|
||||
static NetworkContext_t networkContext = { 0 };
|
||||
|
||||
/**
|
||||
* @brief The flag to indicate the mqtt session changed.
|
||||
*/
|
||||
static bool mqttSessionEstablished = false;
|
||||
|
||||
/**
|
||||
* @brief Static buffer used to hold MQTT messages being sent and received.
|
||||
*/
|
||||
static MQTTFixedBuffer_t xBuffer =
|
||||
{
|
||||
.pBuffer = ucSharedBuffer,
|
||||
.size = democonfigNETWORK_BUFFER_SIZE
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Connect to MQTT broker with reconnection retries.
|
||||
*
|
||||
* If connection fails, retry is attempted after a timeout.
|
||||
* Timeout value will exponentially increase until maximum
|
||||
* timeout value is reached or the number of attempts are exhausted.
|
||||
*
|
||||
* @param[out] pxNetworkContext The output parameter to return the created network context.
|
||||
*
|
||||
* @return The status of the final connection attempt.
|
||||
*/
|
||||
static TlsTransportStatus_t prvConnectToServerWithBackoffRetries( NetworkContext_t * pxNetworkContext );
|
||||
|
||||
/**
|
||||
* @brief Function to get the free index at which an outgoing publish
|
||||
* can be stored.
|
||||
*
|
||||
* @param[out] pucIndex The output parameter to return the index at which an
|
||||
* outgoing publish message can be stored.
|
||||
*
|
||||
* @return pdFAIL if no more publishes can be stored;
|
||||
* pdTRUE if an index to store the next outgoing publish is obtained.
|
||||
*/
|
||||
static BaseType_t prvGetNextFreeIndexForOutgoingPublishes( uint8_t * pucIndex );
|
||||
|
||||
/**
|
||||
* @brief Function to clean up an outgoing publish at given index from the
|
||||
* #outgoingPublishPackets array.
|
||||
*
|
||||
* @param[in] ucIndex The index at which a publish message has to be cleaned up.
|
||||
*/
|
||||
static void vCleanupOutgoingPublishAt( uint8_t ucIndex );
|
||||
|
||||
/**
|
||||
* @brief Function to clean up all the outgoing publishes maintained in the
|
||||
* array.
|
||||
*/
|
||||
static void vCleanupOutgoingPublishes( void );
|
||||
|
||||
/**
|
||||
* @brief Function to clean up the publish packet with the given packet id.
|
||||
*
|
||||
* @param[in] usPacketId Packet identifier of the packet to be cleaned up from
|
||||
* the array.
|
||||
*/
|
||||
static void vCleanupOutgoingPublishWithPacketID( uint16_t usPacketId );
|
||||
|
||||
/**
|
||||
* @brief Function to resend the publishes if a session is re-established with
|
||||
* the broker. This function handles the resending of the QoS1 publish packets,
|
||||
* which are maintained locally.
|
||||
*
|
||||
* @param[in] pxMqttContext MQTT context pointer.
|
||||
*/
|
||||
static BaseType_t xHandlePublishResend( MQTTContext_t * pxMqttContext );
|
||||
|
||||
/**
|
||||
* @brief The timer query function provided to the MQTT context.
|
||||
*
|
||||
* @return Time in milliseconds.
|
||||
*/
|
||||
static uint32_t prvGetTimeMs( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static TlsTransportStatus_t prvConnectToServerWithBackoffRetries( NetworkContext_t * pxNetworkContext )
|
||||
{
|
||||
TlsTransportStatus_t xNetworkStatus = TLS_TRANSPORT_SUCCESS;
|
||||
RetryUtilsStatus_t xRetryUtilsStatus = RetryUtilsSuccess;
|
||||
RetryUtilsParams_t xReconnectParams = { 0 };
|
||||
NetworkCredentials_t xNetworkCredentials = { 0 };
|
||||
|
||||
/* ALPN protocols must be a NULL-terminated list of strings. Therefore,
|
||||
* the first entry will contain the actual ALPN protocol string while the
|
||||
* second entry must remain NULL. */
|
||||
char * pcAlpnProtocols[] = { NULL, NULL };
|
||||
|
||||
/* Set the credentials for establishing a TLS connection. */
|
||||
xNetworkCredentials.pRootCa = ( const unsigned char * ) democonfigROOT_CA_PEM;
|
||||
xNetworkCredentials.rootCaSize = sizeof( democonfigROOT_CA_PEM );
|
||||
#ifdef democonfigCLIENT_CERTIFICATE_PEM
|
||||
xNetworkCredentials.pClientCert = ( const unsigned char * ) democonfigCLIENT_CERTIFICATE_PEM;
|
||||
xNetworkCredentials.clientCertSize = sizeof( democonfigCLIENT_CERTIFICATE_PEM );
|
||||
xNetworkCredentials.pPrivateKey = ( const unsigned char * ) democonfigCLIENT_PRIVATE_KEY_PEM;
|
||||
xNetworkCredentials.privateKeySize = sizeof( democonfigCLIENT_PRIVATE_KEY_PEM );
|
||||
#endif
|
||||
|
||||
xNetworkCredentials.disableSni = pdFALSE;
|
||||
/* The ALPN string changes depending on whether username/password authentication is used. */
|
||||
#ifdef democonfigCLIENT_USERNAME
|
||||
pcAlpnProtocols[ 0 ] = AWS_IOT_CUSTOM_AUTH_ALPN;
|
||||
#else
|
||||
pcAlpnProtocols[ 0 ] = AWS_IOT_MQTT_ALPN;
|
||||
#endif
|
||||
xNetworkCredentials.pAlpnProtos = pcAlpnProtocols;
|
||||
|
||||
/* Initialize reconnect attempts and interval. */
|
||||
RetryUtils_ParamsReset( &xReconnectParams );
|
||||
xReconnectParams.maxRetryAttempts = MAX_RETRY_ATTEMPTS;
|
||||
|
||||
/* Attempt to connect to MQTT broker. If connection fails, retry after
|
||||
* a timeout. Timeout value will exponentially increase until maximum
|
||||
* attempts are reached.
|
||||
*/
|
||||
do
|
||||
{
|
||||
/* Establish a TCP connection with the MQTT broker. This example connects to
|
||||
* the MQTT broker as specified in democonfigMQTT_BROKER_ENDPOINT and
|
||||
* democonfigMQTT_BROKER_PORT at the top of this file. */
|
||||
LogInfo( ( "Create a TCP connection to %s:%d.",
|
||||
democonfigMQTT_BROKER_ENDPOINT,
|
||||
democonfigMQTT_BROKER_PORT ) );
|
||||
xNetworkStatus = TLS_FreeRTOS_Connect( pxNetworkContext,
|
||||
democonfigMQTT_BROKER_ENDPOINT,
|
||||
democonfigMQTT_BROKER_PORT,
|
||||
&xNetworkCredentials,
|
||||
mqttexampleTRANSPORT_SEND_RECV_TIMEOUT_MS,
|
||||
mqttexampleTRANSPORT_SEND_RECV_TIMEOUT_MS );
|
||||
|
||||
if( xNetworkStatus != TLS_TRANSPORT_SUCCESS )
|
||||
{
|
||||
LogWarn( ( "Connection to the broker failed. Retrying connection with backoff and jitter." ) );
|
||||
xRetryUtilsStatus = RetryUtils_BackoffAndSleep( &xReconnectParams );
|
||||
}
|
||||
|
||||
if( xRetryUtilsStatus == RetryUtilsRetriesExhausted )
|
||||
{
|
||||
LogError( ( "Connection to the broker failed, all attempts exhausted." ) );
|
||||
xNetworkStatus = TLS_TRANSPORT_CONNECT_FAILURE;
|
||||
}
|
||||
} while( ( xNetworkStatus != TLS_TRANSPORT_SUCCESS ) && ( xRetryUtilsStatus == RetryUtilsSuccess ) );
|
||||
|
||||
return xNetworkStatus;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static BaseType_t prvGetNextFreeIndexForOutgoingPublishes( uint8_t * pucIndex )
|
||||
{
|
||||
BaseType_t returnStatus = pdFAIL;
|
||||
uint8_t ucIndex = 0;
|
||||
|
||||
configASSERT( outgoingPublishPackets != NULL );
|
||||
configASSERT( pucIndex != NULL );
|
||||
|
||||
for( ucIndex = 0; ucIndex < MAX_OUTGOING_PUBLISHES; ucIndex++ )
|
||||
{
|
||||
/* A free ucIndex is marked by invalid packet id.
|
||||
* Check if the the ucIndex has a free slot. */
|
||||
if( outgoingPublishPackets[ ucIndex ].packetId == MQTT_PACKET_ID_INVALID )
|
||||
{
|
||||
returnStatus = pdPASS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy the available ucIndex into the output param. */
|
||||
*pucIndex = ucIndex;
|
||||
|
||||
return returnStatus;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void vCleanupOutgoingPublishAt( uint8_t ucIndex )
|
||||
{
|
||||
configASSERT( outgoingPublishPackets != NULL );
|
||||
configASSERT( ucIndex < MAX_OUTGOING_PUBLISHES );
|
||||
|
||||
/* Clear the outgoing publish packet. */
|
||||
( void ) memset( &( outgoingPublishPackets[ ucIndex ] ),
|
||||
0x00,
|
||||
sizeof( outgoingPublishPackets[ ucIndex ] ) );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void vCleanupOutgoingPublishes( void )
|
||||
{
|
||||
configASSERT( outgoingPublishPackets != NULL );
|
||||
|
||||
/* Clean up all the outgoing publish packets. */
|
||||
( void ) memset( outgoingPublishPackets, 0x00, sizeof( outgoingPublishPackets ) );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void vCleanupOutgoingPublishWithPacketID( uint16_t usPacketId )
|
||||
{
|
||||
uint8_t ucIndex = 0;
|
||||
|
||||
configASSERT( outgoingPublishPackets != NULL );
|
||||
configASSERT( usPacketId != MQTT_PACKET_ID_INVALID );
|
||||
|
||||
/* Clean up all the saved outgoing publishes. */
|
||||
for( ; ucIndex < MAX_OUTGOING_PUBLISHES; ucIndex++ )
|
||||
{
|
||||
if( outgoingPublishPackets[ ucIndex ].packetId == usPacketId )
|
||||
{
|
||||
vCleanupOutgoingPublishAt( ucIndex );
|
||||
LogInfo( ( "Cleaned up outgoing publish packet with packet id %u.\n\n",
|
||||
usPacketId ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vHandleOtherIncomingPacket( MQTTPacketInfo_t * pxPacketInfo,
|
||||
uint16_t usPacketIdentifier )
|
||||
{
|
||||
/* Handle other packets. */
|
||||
switch( pxPacketInfo->type )
|
||||
{
|
||||
case MQTT_PACKET_TYPE_SUBACK:
|
||||
LogInfo( ( "MQTT_PACKET_TYPE_SUBACK.\n\n" ) );
|
||||
/* Make sure ACK packet identifier matches with Request packet identifier. */
|
||||
configASSERT( globalSubscribePacketIdentifier == usPacketIdentifier );
|
||||
break;
|
||||
|
||||
case MQTT_PACKET_TYPE_UNSUBACK:
|
||||
LogInfo( ( "MQTT_PACKET_TYPE_UNSUBACK.\n\n" ) );
|
||||
/* Make sure ACK packet identifier matches with Request packet identifier. */
|
||||
configASSERT( globalUnsubscribePacketIdentifier == usPacketIdentifier );
|
||||
break;
|
||||
|
||||
case MQTT_PACKET_TYPE_PINGRESP:
|
||||
|
||||
/* Nothing to be done from application as library handles
|
||||
* PINGRESP with the use of MQTT_ProcessLoop API function. */
|
||||
LogWarn( ( "PINGRESP should not be handled by the application "
|
||||
"callback when using MQTT_ProcessLoop.\n" ) );
|
||||
break;
|
||||
|
||||
case MQTT_PACKET_TYPE_PUBACK:
|
||||
LogInfo( ( "PUBACK received for packet id %u.\n\n",
|
||||
usPacketIdentifier ) );
|
||||
/* Cleanup publish packet when a PUBACK is received. */
|
||||
vCleanupOutgoingPublishWithPacketID( usPacketIdentifier );
|
||||
break;
|
||||
|
||||
/* Any other packet type is invalid. */
|
||||
default:
|
||||
LogError( ( "Unknown packet type received:(%02x).\n\n",
|
||||
pxPacketInfo->type ) );
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static BaseType_t xHandlePublishResend( MQTTContext_t * pxMqttContext )
|
||||
{
|
||||
BaseType_t returnStatus = pdTRUE;
|
||||
MQTTStatus_t xMQTTStatus = MQTTSuccess;
|
||||
uint8_t ucIndex = 0U;
|
||||
|
||||
configASSERT( outgoingPublishPackets != NULL );
|
||||
|
||||
/* Resend all the QoS1 publishes still in the array. These are the
|
||||
* publishes that haven't received a PUBACK. When a PUBACK is
|
||||
* received, the publish is removed from the array. */
|
||||
for( ucIndex = 0U; ucIndex < MAX_OUTGOING_PUBLISHES; ucIndex++ )
|
||||
{
|
||||
if( outgoingPublishPackets[ ucIndex ].packetId != MQTT_PACKET_ID_INVALID )
|
||||
{
|
||||
outgoingPublishPackets[ ucIndex ].pubInfo.dup = true;
|
||||
|
||||
LogInfo( ( "Sending duplicate PUBLISH with packet id %u.",
|
||||
outgoingPublishPackets[ ucIndex ].packetId ) );
|
||||
xMQTTStatus = MQTT_Publish( pxMqttContext,
|
||||
&outgoingPublishPackets[ ucIndex ].pubInfo,
|
||||
outgoingPublishPackets[ ucIndex ].packetId );
|
||||
|
||||
if( xMQTTStatus != MQTTSuccess )
|
||||
{
|
||||
LogError( ( "Sending duplicate PUBLISH for packet id %u "
|
||||
" failed with status %u.",
|
||||
outgoingPublishPackets[ ucIndex ].packetId,
|
||||
xMQTTStatus ) );
|
||||
returnStatus = pdFAIL;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogInfo( ( "Sent duplicate PUBLISH successfully for packet id %u.\n\n",
|
||||
outgoingPublishPackets[ ucIndex ].packetId ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return returnStatus;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xEstablishMqttSession( MQTTEventCallback_t eventCallback )
|
||||
{
|
||||
BaseType_t returnStatus = pdTRUE;
|
||||
MQTTStatus_t xMQTTStatus;
|
||||
MQTTConnectInfo_t xConnectInfo;
|
||||
TransportInterface_t xTransport;
|
||||
MQTTContext_t * pxMqttContext = &mqttContext;
|
||||
NetworkContext_t * pxNetworkContext = &networkContext;
|
||||
bool sessionPresent = false;
|
||||
|
||||
configASSERT( pxMqttContext != NULL );
|
||||
configASSERT( pxNetworkContext != NULL );
|
||||
|
||||
/* Initialize the mqtt context and network context. */
|
||||
( void ) memset( pxMqttContext, 0U, sizeof( MQTTContext_t ) );
|
||||
( void ) memset( pxNetworkContext, 0U, sizeof( NetworkContext_t ) );
|
||||
|
||||
if( prvConnectToServerWithBackoffRetries( pxNetworkContext ) != TLS_TRANSPORT_SUCCESS )
|
||||
{
|
||||
/* Log error to indicate connection failure after all
|
||||
* reconnect attempts are over. */
|
||||
LogError( ( "Failed to connect to MQTT broker %.*s.",
|
||||
strlen( democonfigMQTT_BROKER_ENDPOINT ),
|
||||
democonfigMQTT_BROKER_ENDPOINT ) );
|
||||
returnStatus = pdFAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fill in Transport Interface send and receive function pointers. */
|
||||
xTransport.pNetworkContext = pxNetworkContext;
|
||||
xTransport.send = TLS_FreeRTOS_send;
|
||||
xTransport.recv = TLS_FreeRTOS_recv;
|
||||
|
||||
/* Initialize MQTT library. */
|
||||
xMQTTStatus = MQTT_Init( pxMqttContext,
|
||||
&xTransport,
|
||||
prvGetTimeMs,
|
||||
eventCallback,
|
||||
&xBuffer );
|
||||
|
||||
if( xMQTTStatus != MQTTSuccess )
|
||||
{
|
||||
returnStatus = pdFAIL;
|
||||
LogError( ( "MQTT init failed with status %u.", xMQTTStatus ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Establish MQTT session by sending a CONNECT packet. */
|
||||
|
||||
/* Many fields not used in this demo so start with everything at 0. */
|
||||
( void ) memset( ( void * ) &xConnectInfo, 0x00, sizeof( xConnectInfo ) );
|
||||
|
||||
/* Start with a clean session i.e. direct the MQTT broker to discard any
|
||||
* previous session data. Also, establishing a connection with clean session
|
||||
* will ensure that the broker does not store any data when this client
|
||||
* gets disconnected. */
|
||||
xConnectInfo.cleanSession = true;
|
||||
|
||||
/* The client identifier is used to uniquely identify this MQTT client to
|
||||
* the MQTT broker. In a production device the identifier can be something
|
||||
* unique, such as a device serial number. */
|
||||
xConnectInfo.pClientIdentifier = democonfigCLIENT_IDENTIFIER;
|
||||
xConnectInfo.clientIdentifierLength = ( uint16_t ) strlen( democonfigCLIENT_IDENTIFIER );
|
||||
|
||||
/* The maximum time interval in seconds which is allowed to elapse
|
||||
* between two Control Packets.
|
||||
* It is the responsibility of the Client to ensure that the interval between
|
||||
* Control Packets being sent does not exceed this Keep Alive value. In the
|
||||
* absence of sending any other Control Packets, the Client MUST send a
|
||||
* PINGREQ Packet. */
|
||||
xConnectInfo.keepAliveSeconds = mqttexampleKEEP_ALIVE_TIMEOUT_SECONDS;
|
||||
|
||||
/* Append metrics when connecting to the AWS IoT Core broker. */
|
||||
#ifdef democonfigCLIENT_USERNAME
|
||||
xConnectInfo.pUserName = CLIENT_USERNAME_WITH_METRICS;
|
||||
xConnectInfo.userNameLength = ( uint16_t ) strlen( CLIENT_USERNAME_WITH_METRICS );
|
||||
xConnectInfo.pPassword = democonfigCLIENT_PASSWORD;
|
||||
xConnectInfo.passwordLength = ( uint16_t ) strlen( democonfigCLIENT_PASSWORD );
|
||||
#else
|
||||
xConnectInfo.pUserName = AWS_IOT_METRICS_STRING;
|
||||
xConnectInfo.userNameLength = AWS_IOT_METRICS_STRING_LENGTH;
|
||||
/* Password for authentication is not used. */
|
||||
xConnectInfo.pPassword = NULL;
|
||||
xConnectInfo.passwordLength = 0U;
|
||||
#endif /* ifdef democonfigCLIENT_USERNAME */
|
||||
|
||||
/* Send MQTT CONNECT packet to broker. */
|
||||
xMQTTStatus = MQTT_Connect( pxMqttContext,
|
||||
&xConnectInfo,
|
||||
NULL,
|
||||
mqttexampleCONNACK_RECV_TIMEOUT_MS,
|
||||
&sessionPresent );
|
||||
|
||||
if( xMQTTStatus != MQTTSuccess )
|
||||
{
|
||||
returnStatus = pdFAIL;
|
||||
LogError( ( "Connection with MQTT broker failed with status %u.", xMQTTStatus ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
LogInfo( ( "MQTT connection successfully established with broker.\n\n" ) );
|
||||
}
|
||||
}
|
||||
|
||||
if( returnStatus == pdFAIL )
|
||||
{
|
||||
/* Keep a flag for indicating if MQTT session is established. This
|
||||
* flag will mark that an MQTT DISCONNECT has to be sent at the end
|
||||
* of the demo even if there are intermediate failures. */
|
||||
mqttSessionEstablished = true;
|
||||
}
|
||||
|
||||
if( returnStatus == pdFAIL )
|
||||
{
|
||||
/* Check if session is present and if there are any outgoing publishes
|
||||
* that need to resend. This is only valid if the broker is
|
||||
* re-establishing a session which was already present. */
|
||||
if( sessionPresent == true )
|
||||
{
|
||||
LogInfo( ( "An MQTT session with broker is re-established. "
|
||||
"Resending unacked publishes." ) );
|
||||
|
||||
/* Handle all the resend of publish messages. */
|
||||
returnStatus = xHandlePublishResend( &mqttContext );
|
||||
}
|
||||
else
|
||||
{
|
||||
LogInfo( ( "A clean MQTT connection is established."
|
||||
" Cleaning up all the stored outgoing publishes.\n\n" ) );
|
||||
|
||||
/* Clean up the outgoing publishes waiting for ack as this new
|
||||
* connection doesn't re-establish an existing session. */
|
||||
vCleanupOutgoingPublishes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return returnStatus;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xDisconnectMqttSession( void )
|
||||
{
|
||||
MQTTStatus_t xMQTTStatus = MQTTSuccess;
|
||||
BaseType_t returnStatus = pdTRUE;
|
||||
TlsTransportStatus_t xNetworkStatus;
|
||||
MQTTContext_t * pxMqttContext = &mqttContext;
|
||||
NetworkContext_t * pxNetworkContext = &networkContext;
|
||||
|
||||
configASSERT( pxMqttContext != NULL );
|
||||
configASSERT( pxNetworkContext != NULL );
|
||||
|
||||
if( mqttSessionEstablished == true )
|
||||
{
|
||||
/* Send DISCONNECT. */
|
||||
xMQTTStatus = MQTT_Disconnect( pxMqttContext );
|
||||
|
||||
if( xMQTTStatus != MQTTSuccess )
|
||||
{
|
||||
LogError( ( "Sending MQTT DISCONNECT failed with status=%u.",
|
||||
xMQTTStatus ) );
|
||||
returnStatus = pdFAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Close the network connection. */
|
||||
TLS_FreeRTOS_Disconnect( pxNetworkContext );
|
||||
|
||||
return returnStatus;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xSubscribeToTopic( const char * pcTopicFilter,
|
||||
uint16_t usTopicFilterLength )
|
||||
{
|
||||
BaseType_t returnStatus = pdTRUE;
|
||||
MQTTStatus_t xMQTTStatus;
|
||||
MQTTContext_t * pxMqttContext = &mqttContext;
|
||||
MQTTSubscribeInfo_t pSubscriptionList[ mqttexampleTOPIC_COUNT ];
|
||||
|
||||
configASSERT( pxMqttContext != NULL );
|
||||
configASSERT( pcTopicFilter != NULL );
|
||||
configASSERT( usTopicFilterLength > 0 );
|
||||
|
||||
/* Start with everything at 0. */
|
||||
( void ) memset( ( void * ) pSubscriptionList, 0x00, sizeof( pSubscriptionList ) );
|
||||
|
||||
/* This example subscribes to only one topic and uses QOS1. */
|
||||
pSubscriptionList[ 0 ].qos = MQTTQoS1;
|
||||
pSubscriptionList[ 0 ].pTopicFilter = pcTopicFilter;
|
||||
pSubscriptionList[ 0 ].topicFilterLength = usTopicFilterLength;
|
||||
|
||||
/* Generate packet identifier for the SUBSCRIBE packet. */
|
||||
globalSubscribePacketIdentifier = MQTT_GetPacketId( pxMqttContext );
|
||||
|
||||
/* Send SUBSCRIBE packet. */
|
||||
xMQTTStatus = MQTT_Subscribe( pxMqttContext,
|
||||
pSubscriptionList,
|
||||
sizeof( pSubscriptionList ) / sizeof( MQTTSubscribeInfo_t ),
|
||||
globalSubscribePacketIdentifier );
|
||||
|
||||
if( xMQTTStatus != MQTTSuccess )
|
||||
{
|
||||
LogError( ( "Failed to send SUBSCRIBE packet to broker with error = %u.",
|
||||
xMQTTStatus ) );
|
||||
returnStatus = pdFAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogInfo( ( "SUBSCRIBE topic %.*s to broker.\n\n",
|
||||
usTopicFilterLength,
|
||||
pcTopicFilter ) );
|
||||
|
||||
/* Process incoming packet from the broker. Acknowledgment for subscription
|
||||
* ( SUBACK ) will be received here. However after sending the subscribe, the
|
||||
* client may receive a publish before it receives a subscribe ack. Since this
|
||||
* demo is subscribing to the topic to which no one is publishing, probability
|
||||
* of receiving publish message before subscribe ack is zero; but application
|
||||
* must be ready to receive any packet. This demo uses MQTT_ProcessLoop to
|
||||
* receive packet from network. */
|
||||
xMQTTStatus = MQTT_ProcessLoop( pxMqttContext, mqttexamplePROCESS_LOOP_TIMEOUT_MS );
|
||||
|
||||
if( xMQTTStatus != MQTTSuccess )
|
||||
{
|
||||
returnStatus = pdFAIL;
|
||||
LogError( ( "MQTT_ProcessLoop returned with status = %u.",
|
||||
xMQTTStatus ) );
|
||||
}
|
||||
}
|
||||
|
||||
return returnStatus;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xUnsubscribeFromTopic( const char * pcTopicFilter,
|
||||
uint16_t usTopicFilterLength )
|
||||
{
|
||||
BaseType_t returnStatus = pdTRUE;
|
||||
MQTTStatus_t xMQTTStatus;
|
||||
MQTTContext_t * pxMqttContext = &mqttContext;
|
||||
MQTTSubscribeInfo_t pSubscriptionList[ 1 ];
|
||||
|
||||
configASSERT( pxMqttContext != NULL );
|
||||
configASSERT( pcTopicFilter != NULL );
|
||||
configASSERT( usTopicFilterLength > 0 );
|
||||
|
||||
/* Start with everything at 0. */
|
||||
( void ) memset( ( void * ) pSubscriptionList, 0x00, sizeof( pSubscriptionList ) );
|
||||
|
||||
/* This example subscribes to only one topic and uses QOS1. */
|
||||
pSubscriptionList[ 0 ].qos = MQTTQoS1;
|
||||
pSubscriptionList[ 0 ].pTopicFilter = pcTopicFilter;
|
||||
pSubscriptionList[ 0 ].topicFilterLength = usTopicFilterLength;
|
||||
|
||||
/* Generate packet identifier for the UNSUBSCRIBE packet. */
|
||||
globalUnsubscribePacketIdentifier = MQTT_GetPacketId( pxMqttContext );
|
||||
|
||||
/* Send UNSUBSCRIBE packet. */
|
||||
xMQTTStatus = MQTT_Unsubscribe( pxMqttContext,
|
||||
pSubscriptionList,
|
||||
sizeof( pSubscriptionList ) / sizeof( MQTTSubscribeInfo_t ),
|
||||
globalUnsubscribePacketIdentifier );
|
||||
|
||||
if( xMQTTStatus != MQTTSuccess )
|
||||
{
|
||||
LogError( ( "Failed to send UNSUBSCRIBE packet to broker with error = %u.",
|
||||
xMQTTStatus ) );
|
||||
returnStatus = pdFAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogInfo( ( "UNSUBSCRIBE sent topic %.*s to broker.\n\n",
|
||||
usTopicFilterLength,
|
||||
pcTopicFilter ) );
|
||||
|
||||
/* Process the incoming packet from the broker. */
|
||||
xMQTTStatus = MQTT_ProcessLoop( pxMqttContext, mqttexamplePROCESS_LOOP_TIMEOUT_MS );
|
||||
|
||||
if( xMQTTStatus != MQTTSuccess )
|
||||
{
|
||||
returnStatus = pdFAIL;
|
||||
LogError( ( "MQTT_ProcessLoop returned with status = %u.",
|
||||
xMQTTStatus ) );
|
||||
}
|
||||
}
|
||||
|
||||
return returnStatus;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPublishToTopic( const char * pcTopicFilter,
|
||||
int32_t topicFilterLength,
|
||||
const char * pcPayload,
|
||||
size_t payloadLength )
|
||||
{
|
||||
BaseType_t returnStatus = pdPASS;
|
||||
MQTTStatus_t xMQTTStatus = MQTTSuccess;
|
||||
uint8_t ucPublishIndex = MAX_OUTGOING_PUBLISHES;
|
||||
MQTTContext_t * pxMqttContext = &mqttContext;
|
||||
|
||||
configASSERT( pxMqttContext != NULL );
|
||||
configASSERT( pcTopicFilter != NULL );
|
||||
configASSERT( topicFilterLength > 0 );
|
||||
|
||||
/* Get the next free index for the outgoing publish. All QoS1 outgoing
|
||||
* publishes are stored until a PUBACK is received. These messages are
|
||||
* stored for supporting a resend if a network connection is broken before
|
||||
* receiving a PUBACK. */
|
||||
returnStatus = prvGetNextFreeIndexForOutgoingPublishes( &ucPublishIndex );
|
||||
|
||||
if( returnStatus == pdFAIL )
|
||||
{
|
||||
LogError( ( "Unable to find a free spot for outgoing PUBLISH message.\n\n" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
LogInfo( ( "the published payload:%s \r\n ", pcPayload ) );
|
||||
/* This example publishes to only one topic and uses QOS1. */
|
||||
outgoingPublishPackets[ ucPublishIndex ].pubInfo.qos = MQTTQoS1;
|
||||
outgoingPublishPackets[ ucPublishIndex ].pubInfo.pTopicName = pcTopicFilter;
|
||||
outgoingPublishPackets[ ucPublishIndex ].pubInfo.topicNameLength = topicFilterLength;
|
||||
outgoingPublishPackets[ ucPublishIndex ].pubInfo.pPayload = pcPayload;
|
||||
outgoingPublishPackets[ ucPublishIndex ].pubInfo.payloadLength = payloadLength;
|
||||
|
||||
/* Get a new packet id. */
|
||||
outgoingPublishPackets[ ucPublishIndex ].packetId = MQTT_GetPacketId( pxMqttContext );
|
||||
|
||||
/* Send PUBLISH packet. */
|
||||
xMQTTStatus = MQTT_Publish( pxMqttContext,
|
||||
&outgoingPublishPackets[ ucPublishIndex ].pubInfo,
|
||||
outgoingPublishPackets[ ucPublishIndex ].packetId );
|
||||
|
||||
if( xMQTTStatus != MQTTSuccess )
|
||||
{
|
||||
LogError( ( "Failed to send PUBLISH packet to broker with error = %u.",
|
||||
xMQTTStatus ) );
|
||||
vCleanupOutgoingPublishAt( ucPublishIndex );
|
||||
returnStatus = pdFAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogInfo( ( "PUBLISH sent for topic %.*s to broker with packet ID %u.\n\n",
|
||||
topicFilterLength,
|
||||
pcTopicFilter,
|
||||
outgoingPublishPackets[ ucPublishIndex ].packetId ) );
|
||||
|
||||
/* Calling MQTT_ProcessLoop to process incoming publish echo, since
|
||||
* application subscribed to the same topic the broker will send
|
||||
* publish message back to the application. This function also
|
||||
* sends ping request to broker if MQTT_KEEP_ALIVE_INTERVAL_SECONDS
|
||||
* has expired since the last MQTT packet sent and receive
|
||||
* ping responses. */
|
||||
xMQTTStatus = MQTT_ProcessLoop( &mqttContext, mqttexamplePROCESS_LOOP_TIMEOUT_MS );
|
||||
|
||||
if( xMQTTStatus != MQTTSuccess )
|
||||
{
|
||||
LogWarn( ( "MQTT_ProcessLoop returned with status = %u.",
|
||||
xMQTTStatus ) );
|
||||
returnStatus = pdFAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return returnStatus;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static uint32_t prvGetTimeMs( void )
|
||||
{
|
||||
TickType_t xTickCount = 0;
|
||||
uint32_t ulTimeMs = 0UL;
|
||||
|
||||
/* Get the current tick count. */
|
||||
xTickCount = xTaskGetTickCount();
|
||||
|
||||
/* Convert the ticks to milliseconds. */
|
||||
ulTimeMs = ( uint32_t ) xTickCount * MILLISECONDS_PER_TICK;
|
||||
|
||||
/* Reduce ulGlobalEntryTimeMs from obtained time so as to always return the
|
||||
* elapsed time in the application. */
|
||||
ulTimeMs = ( uint32_t ) ( ulTimeMs - ulGlobalEntryTimeMs );
|
||||
|
||||
return ulTimeMs;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
* FreeRTOS V202011.00
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SHADOW_DEMO_HELPERS_H
|
||||
#define SHADOW_DEMO_HELPERS_H
|
||||
|
||||
/* MQTT API header. */
|
||||
#include "core_mqtt.h"
|
||||
|
||||
/* Transport interface implementation include header for TLS. */
|
||||
#include "using_mbedtls.h"
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Establish a MQTT connection.
|
||||
*
|
||||
* @param[in] eventCallback The callback function used to receive incoming
|
||||
* publishes and incoming acks from MQTT library.
|
||||
*
|
||||
* @return The status of the final connection attempt.
|
||||
*/
|
||||
BaseType_t xEstablishMqttSession( MQTTEventCallback_t eventCallback );
|
||||
|
||||
/**
|
||||
* @brief Handle the incoming packet if it's not related to the device shadow.
|
||||
*
|
||||
* @param[in] pxPacketInfo Packet Info pointer for the incoming packet.
|
||||
* @param[in] usPacketIdentifier Packet identifier of the incoming packet.
|
||||
*/
|
||||
void vHandleOtherIncomingPacket( MQTTPacketInfo_t * pxPacketInfo,
|
||||
uint16_t usPacketIdentifier );
|
||||
|
||||
/**
|
||||
* @brief Close the MQTT connection.
|
||||
*
|
||||
* @return pdPASS if DISCONNECT was successfully sent;
|
||||
* pdFAIL otherwise.
|
||||
*/
|
||||
BaseType_t xDisconnectMqttSession( void );
|
||||
|
||||
/**
|
||||
* @brief Subscribe to a MQTT topic filter.
|
||||
*
|
||||
* @param[in] pcTopicFilter Pointer to the shadow topic buffer.
|
||||
* @param[in] usTopicFilterLength Indicates the length of the shadow
|
||||
* topic filter.
|
||||
*
|
||||
* @return pdPASS if SUBSCRIBE was successfully sent;
|
||||
* pdFAIL otherwise.
|
||||
*/
|
||||
BaseType_t xSubscribeToTopic( const char * pcTopicFilter,
|
||||
uint16_t usTopicFilterLength );
|
||||
|
||||
/**
|
||||
* @brief Sends an MQTT UNSUBSCRIBE to unsubscribe from the shadow
|
||||
* topic.
|
||||
*
|
||||
* @param[in] pcTopicFilter Pointer to the shadow topic buffer.
|
||||
* @param[in] usTopicFilterLength Indicates the length of the shadow
|
||||
* topic filter.
|
||||
*
|
||||
* @return pdPASS if UNSUBSCRIBE was successfully sent;
|
||||
* pdFAIL otherwise.
|
||||
*/
|
||||
BaseType_t xUnsubscribeFromTopic( const char * pcTopicFilter,
|
||||
uint16_t usTopicFilterLength );
|
||||
|
||||
/**
|
||||
* @brief Publish a message to a MQTT topic.
|
||||
*
|
||||
* @param[in] pcTopicFilter Points to the topic.
|
||||
* @param[in] topicFilterLength The length of the topic.
|
||||
* @param[in] pcPayload Points to the payload.
|
||||
* @param[in] payloadLength The length of the payload.
|
||||
*
|
||||
* @return pdPASS if PUBLISH was successfully sent;
|
||||
* pdFAIL otherwise.
|
||||
*/
|
||||
BaseType_t xPublishToTopic( const char * pcTopicFilter,
|
||||
int32_t topicFilterLength,
|
||||
const char * pcPayload,
|
||||
size_t payloadLength );
|
||||
|
||||
#endif /* ifndef SHADOW_DEMO_HELPERS_H */
|
||||
|
|
@ -58,7 +58,7 @@
|
|||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..\..\..\..\Source\FreeRTOS-Plus-Trace\Include;..\..\..\..\..\FreeRTOS-Plus\Source\FreeRTOS-Plus-TCP\include;..\..\..\..\..\FreeRTOS-Plus\Source\FreeRTOS-Plus-TCP\portable\BufferManagement;..\..\..\..\..\FreeRTOS-Plus\Source\FreeRTOS-Plus-TCP\portable\Compiler\MSVC;..\..\..\..\..\FreeRTOS-Plus\Source\Utilities\logging;..\common\WinPCap;..\..\..\..\..\FreeRTOS\Source\include;..\..\..\..\..\FreeRTOS\Source\portable\MSVC-MingW;..\..\..\..\Source\Application-Protocols\coreMQTT\source\include;..\..\..\..\Source\Application-Protocols\coreMQTT\source\interface;..\..\..\..\Source\Utilities\exponential_backoff;..\..\..\..\Source\Application-Protocols\network_transport\freertos_plus_tcp;..\..\..\..\Source\Application-Protocols\network_transport\freertos_plus_tcp\using_mbedtls;..\..\..\..\Source\Utilities\mbedtls_freertos;..\..\..\..\..\Source\mbedtls_utils;..\..\..\..\ThirdParty\mbedtls\include;..\..\..\..\Source\AWS\device-shadow\source\include;..\..\..\..\Source\coreJSON\source\include;.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\..\..\..\..\Source\FreeRTOS-Plus-Trace\Include;..\..\..\..\..\FreeRTOS-Plus\Source\FreeRTOS-Plus-TCP\include;..\..\..\..\..\FreeRTOS-Plus\Source\FreeRTOS-Plus-TCP\portable\BufferManagement;..\..\..\..\..\FreeRTOS-Plus\Source\FreeRTOS-Plus-TCP\portable\Compiler\MSVC;..\..\..\..\..\FreeRTOS-Plus\Source\Utilities\logging;..\common\WinPCap;..\..\..\..\..\FreeRTOS\Source\include;..\..\..\..\..\FreeRTOS\Source\portable\MSVC-MingW;..\..\..\..\Source\Application-Protocols\coreMQTT\source\include;..\..\..\..\Source\Application-Protocols\coreMQTT\source\interface;..\..\..\..\Source\Utilities\exponential_backoff;..\..\..\..\Source\Application-Protocols\network_transport\freertos_plus_tcp;..\..\..\..\Source\Application-Protocols\network_transport\freertos_plus_tcp\using_mbedtls;..\..\..\..\Source\Utilities\mbedtls_freertos;..\..\..\..\..\Source\mbedtls_utils;..\..\..\..\ThirdParty\mbedtls\include;..\..\..\..\Source\AWS\device-shadow\source\include;..\..\..\..\Source\coreJSON\source\include;..\..\Mqtt_Demo_Helpers;.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>MBEDTLS_CONFIG_FILE="mbedtls_config.h";WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0500;WINVER=0x400;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
|
|
@ -490,7 +490,7 @@
|
|||
<ClCompile Include="..\..\..\..\..\FreeRTOS-Plus\Demo\Common\Logging\windows\Logging_WinSim.c" />
|
||||
<ClCompile Include="..\Common\main.c" />
|
||||
<ClCompile Include="DemoTasks\ShadowDemoMainExample.c" />
|
||||
<ClCompile Include="DemoTasks\shadow_demo_helpers.c" />
|
||||
<ClCompile Include="..\..\Mqtt_Demo_Helpers\mqtt_demo_helpers.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\..\..\FreeRTOS\Source\include\event_groups.h" />
|
||||
|
|
|
|||
|
|
@ -67,6 +67,17 @@ extern void vLoggingPrintf( const char * pcFormatString,
|
|||
|
||||
/************ End of logging configuration ****************/
|
||||
|
||||
/**
|
||||
* @brief The Thing resource registered on your AWS IoT account to use in the demo.
|
||||
* A Thing resource is required to communicate with the AWS IoT Device Shadow service.
|
||||
*
|
||||
* @note The Things associated with your AWS account can be found in the
|
||||
* AWS IoT console under Manage/Things, or using the ListThings REST API (that can
|
||||
* be called with the AWS CLI command line tool).
|
||||
*
|
||||
* #define democonfigTHING_NAME "...insert here..."
|
||||
*/
|
||||
|
||||
#ifndef democonfigCLIENT_IDENTIFIER
|
||||
|
||||
/**
|
||||
|
|
@ -83,16 +94,11 @@ extern void vLoggingPrintf( const char * pcFormatString,
|
|||
#endif
|
||||
|
||||
/**
|
||||
* @brief Endpoint of the MQTT broker to connect to.
|
||||
*
|
||||
* This demo application can be run with any MQTT broker, that supports mutual
|
||||
* authentication.
|
||||
*
|
||||
* For AWS IoT MQTT broker, this is the Thing's REST API Endpoint.
|
||||
* @brief The AWS IoT broker endpoint to connect to in the demo.
|
||||
*
|
||||
* @note Your AWS IoT Core endpoint can be found in the AWS IoT console under
|
||||
* Settings/Custom Endpoint, or using the describe-endpoint REST API (with
|
||||
* AWS CLI command line tool).
|
||||
* Settings/Custom Endpoint, or using the DescribeEndpoint REST API (that can
|
||||
* be called with AWS CLI command line tool).
|
||||
*
|
||||
* #define democonfigMQTT_BROKER_ENDPOINT "...insert here..."
|
||||
*/
|
||||
|
|
@ -113,8 +119,8 @@ extern void vLoggingPrintf( const char * pcFormatString,
|
|||
/**
|
||||
* @brief AWS root CA certificate.
|
||||
*
|
||||
* For AWS IoT MQTT broker, this certificate is used to identify the AWS IoT
|
||||
* server and is publicly available. Refer to the link below.
|
||||
* This certificate is used to identify the AWS IoT server and is publicly available.
|
||||
* Refer to the link below.
|
||||
* https://www.amazontrust.com/repository/AmazonRootCA1.pem
|
||||
*
|
||||
* @note This certificate should be PEM-encoded.
|
||||
|
|
@ -124,7 +130,6 @@ extern void vLoggingPrintf( const char * pcFormatString,
|
|||
* "...base64 data...\n"\
|
||||
* "-----END CERTIFICATE-----\n"
|
||||
*
|
||||
* #define democonfigROOT_CA_PEM "...insert here..."
|
||||
*/
|
||||
|
||||
#define democonfigROOT_CA_PEM \
|
||||
|
|
@ -152,7 +157,7 @@ extern void vLoggingPrintf( const char * pcFormatString,
|
|||
/**
|
||||
* @brief Client certificate.
|
||||
*
|
||||
* For AWS IoT MQTT broker, refer to the AWS documentation below for details
|
||||
* Please refer to the AWS documentation below for details
|
||||
* regarding client authentication.
|
||||
* https://docs.aws.amazon.com/iot/latest/developerguide/client-authentication.html
|
||||
*
|
||||
|
|
@ -169,7 +174,7 @@ extern void vLoggingPrintf( const char * pcFormatString,
|
|||
/**
|
||||
* @brief Client's private key.
|
||||
*
|
||||
* For AWS IoT MQTT broker, refer to the AWS documentation below for details
|
||||
* Please refer to the AWS documentation below for details
|
||||
* regarding clientauthentication.
|
||||
* https://docs.aws.amazon.com/iot/latest/developerguide/client-authentication.html
|
||||
*
|
||||
|
|
@ -187,7 +192,7 @@ extern void vLoggingPrintf( const char * pcFormatString,
|
|||
* @brief The username value for authenticating client to the MQTT broker when
|
||||
* username/password based client authentication is used.
|
||||
*
|
||||
* For AWS IoT MQTT broker, refer to the AWS IoT documentation below for
|
||||
* Please refer to the AWS IoT documentation below for
|
||||
* details regarding client authentication with a username and password.
|
||||
* https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html
|
||||
* An authorizer setup needs to be done, as mentioned in the above link, to use
|
||||
|
|
@ -200,7 +205,7 @@ extern void vLoggingPrintf( const char * pcFormatString,
|
|||
* @brief The password value for authenticating client to the MQTT broker when
|
||||
* username/password based client authentication is used.
|
||||
*
|
||||
* For AWS IoT MQTT broker, refer to the AWS IoT documentation below for
|
||||
* Please refer to the AWS IoT documentation below for
|
||||
* details regarding client authentication with a username and password.
|
||||
* https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html
|
||||
* An authorizer setup needs to be done, as mentioned in the above link, to use
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue