|
|
@ -148,6 +148,55 @@
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
#define SHADOW_REPORTED_JSON_LENGTH ( sizeof( SHADOW_REPORTED_JSON ) - 3 )
|
|
|
|
#define SHADOW_REPORTED_JSON_LENGTH ( sizeof( SHADOW_REPORTED_JSON ) - 3 )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief The maximum number of times to run the loop in this demo.
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @note The demo loop is attempted to re-run only if it fails in an iteration.
|
|
|
|
|
|
|
|
* Once the demo loop succeeds in an iteration, the demo exits successfully.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef SHADOW_MAX_DEMO_LOOP_COUNT
|
|
|
|
|
|
|
|
#define SHADOW_MAX_DEMO_LOOP_COUNT ( 3 )
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief Time in ticks to wait between retries of the demo loop if
|
|
|
|
|
|
|
|
* demo loop fails.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define DELAY_BETWEEN_DEMO_RETRY_ITERATIONS_TICKS ( pdMS_TO_TICKS( 5000U ) )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief The maximum number of times to call MQTT_ProcessLoop() when waiting
|
|
|
|
|
|
|
|
* for a response for Shadow delete operation.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define MQTT_PROCESS_LOOP_DELETE_RESPONSE_COUNT_MAX ( 30U )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief Timeout for MQTT_ProcessLoop in milliseconds.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define MQTT_PROCESS_LOOP_TIMEOUT_MS ( 700U )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief JSON key for response code that indicates the type of error in
|
|
|
|
|
|
|
|
* the error document received on topic `/delete/rejected`.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define SHADOW_DELETE_REJECTED_ERROR_CODE_KEY "code"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief Length of #SHADOW_DELETE_REJECTED_ERROR_CODE_KEY.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define SHADOW_DELETE_REJECTED_ERROR_CODE_KEY_LENGTH ( ( uint16_t ) ( sizeof( SHADOW_DELETE_REJECTED_ERROR_CODE_KEY ) - 1 ) )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief Error response code sent from AWS IoT Shadow service when an attempt
|
|
|
|
|
|
|
|
* is made to delete a Shadow document that doesn't exist.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define SHADOW_NO_SHADOW_EXISTS_ERROR_CODE "404"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief Length of #SHADOW_NO_SHADOW_EXISTS_ERROR_CODE.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define SHADOW_NO_SHADOW_EXISTS_ERROR_CODE_LENGTH ( ( uint16_t ) ( sizeof( SHADOW_NO_SHADOW_EXISTS_ERROR_CODE ) - 1 ) )
|
|
|
|
|
|
|
|
|
|
|
|
/*------------- Demo configurations -------------------------*/
|
|
|
|
/*------------- Demo configurations -------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef democonfigTHING_NAME
|
|
|
|
#ifndef democonfigTHING_NAME
|
|
|
@ -225,6 +274,24 @@ static BaseType_t xUpdateDeltaReturn = pdPASS;
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static BaseType_t xUpdateAcceptedReturn = pdPASS;
|
|
|
|
static BaseType_t xUpdateAcceptedReturn = pdPASS;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief Status of the response of Shadow delete operation from AWS IoT
|
|
|
|
|
|
|
|
* message broker.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
static BaseType_t xDeleteResponseReceived = pdFALSE;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief Status of the Shadow delete operation.
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* The Shadow delete status will be updated by the incoming publishes on the
|
|
|
|
|
|
|
|
* MQTT topics for delete acknowledgement from AWS IoT message broker
|
|
|
|
|
|
|
|
* (accepted/rejected). Shadow document is considered to be deleted if an
|
|
|
|
|
|
|
|
* incoming publish is received on `/delete/accepted` topic or an incoming
|
|
|
|
|
|
|
|
* publish is received on `/delete/rejected` topic with error code 404. Code 404
|
|
|
|
|
|
|
|
* indicates that the Shadow document does not exist for the Thing yet.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
static BaseType_t xShadowDeleted = pdFALSE;
|
|
|
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -271,6 +338,126 @@ static void prvUpdateAcceptedHandler( MQTTPublishInfo_t * pxPublishInfo );
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static void prvShadowDemoTask( void * pvParameters );
|
|
|
|
static void prvShadowDemoTask( void * pvParameters );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief Process payload from `/delete/rejected` topic.
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* This handler examines the rejected message to look for the reject reason code.
|
|
|
|
|
|
|
|
* If the reject reason code is `404`, an attempt was made to delete a shadow
|
|
|
|
|
|
|
|
* document which was not present yet. This is considered to be success for this
|
|
|
|
|
|
|
|
* demo application.
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param[in] pxPublishInfo Deserialized publish info pointer for the incoming
|
|
|
|
|
|
|
|
* packet.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void prvDeleteRejectedHandler( MQTTPublishInfo_t * pxPublishInfo );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief Helper function to wait for a response for Shadow delete operation.
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param[in] pxMQTTContext MQTT context pointer.
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @return pdPASS if successfully received a response for Shadow delete
|
|
|
|
|
|
|
|
* operation; pdFAIL otherwise.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
static BaseType_t prvWaitForDeleteResponse( MQTTContext_t * pxMQTTContext );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static BaseType_t prvWaitForDeleteResponse( MQTTContext_t * pxMQTTContext )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
uint8_t ucCount = 0U;
|
|
|
|
|
|
|
|
MQTTStatus_t xMQTTStatus = MQTTSuccess;
|
|
|
|
|
|
|
|
BaseType_t xReturnStatus = pdPASS;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
configASSERT( pxMQTTContext != NULL );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while( ( xDeleteResponseReceived != pdTRUE ) &&
|
|
|
|
|
|
|
|
( ucCount++ < MQTT_PROCESS_LOOP_DELETE_RESPONSE_COUNT_MAX ) &&
|
|
|
|
|
|
|
|
( xMQTTStatus == MQTTSuccess ) )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* Event callback will set #xDeleteResponseReceived when receiving an
|
|
|
|
|
|
|
|
* incoming publish on either `/delete/accepted` or `/delete/rejected`
|
|
|
|
|
|
|
|
* Shadow topics. */
|
|
|
|
|
|
|
|
xMQTTStatus = MQTT_ProcessLoop( pxMQTTContext, MQTT_PROCESS_LOOP_TIMEOUT_MS );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( ( xMQTTStatus != MQTTSuccess ) || ( xDeleteResponseReceived != pdTRUE ) )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
LogError( ( "MQTT_ProcessLoop failed to receive a response for Shadow delete operation:"
|
|
|
|
|
|
|
|
" LoopDuration=%u, MQTT Status=%s.",
|
|
|
|
|
|
|
|
( MQTT_PROCESS_LOOP_TIMEOUT_MS * ucCount ),
|
|
|
|
|
|
|
|
MQTT_Status_strerror( xMQTTStatus ) ) );
|
|
|
|
|
|
|
|
xReturnStatus = pdFAIL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return xReturnStatus;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void prvDeleteRejectedHandler( MQTTPublishInfo_t * pxPublishInfo )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
JSONStatus_t result = JSONSuccess;
|
|
|
|
|
|
|
|
char * pcOutValue = NULL;
|
|
|
|
|
|
|
|
uint32_t ulOutValueLength = 0UL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
configASSERT( pxPublishInfo != NULL );
|
|
|
|
|
|
|
|
configASSERT( pxPublishInfo->pPayload != NULL );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LogInfo( ( "/delete/rejected json payload:%s.", ( const char * ) pxPublishInfo->pPayload ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* The payload will look similar to this:
|
|
|
|
|
|
|
|
* {
|
|
|
|
|
|
|
|
* "code": error-code,
|
|
|
|
|
|
|
|
* "message": "error-message",
|
|
|
|
|
|
|
|
* "timestamp": timestamp,
|
|
|
|
|
|
|
|
* "clientToken": "token"
|
|
|
|
|
|
|
|
* }
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Make sure the payload is a valid json document. */
|
|
|
|
|
|
|
|
result = JSON_Validate( pxPublishInfo->pPayload,
|
|
|
|
|
|
|
|
pxPublishInfo->payloadLength );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( result == JSONSuccess )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* Then we start to get the version value by JSON keyword "version". */
|
|
|
|
|
|
|
|
result = JSON_SearchConst( pxPublishInfo->pPayload,
|
|
|
|
|
|
|
|
pxPublishInfo->payloadLength,
|
|
|
|
|
|
|
|
SHADOW_DELETE_REJECTED_ERROR_CODE_KEY,
|
|
|
|
|
|
|
|
SHADOW_DELETE_REJECTED_ERROR_CODE_KEY_LENGTH,
|
|
|
|
|
|
|
|
&pcOutValue,
|
|
|
|
|
|
|
|
( size_t * ) &ulOutValueLength,
|
|
|
|
|
|
|
|
NULL );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
LogError( ( "The json document is invalid!!" ) );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( result == JSONSuccess )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
LogInfo( ( "Error code is: %.*s.",
|
|
|
|
|
|
|
|
ulOutValueLength,
|
|
|
|
|
|
|
|
pcOutValue ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Check if error code is `404`. An error code `404` indicates that an
|
|
|
|
|
|
|
|
* attempt was made to delete a Shadow document that didn't exist. */
|
|
|
|
|
|
|
|
if( ulOutValueLength == SHADOW_NO_SHADOW_EXISTS_ERROR_CODE_LENGTH )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if( strncmp( pcOutValue, SHADOW_NO_SHADOW_EXISTS_ERROR_CODE,
|
|
|
|
|
|
|
|
SHADOW_NO_SHADOW_EXISTS_ERROR_CODE_LENGTH ) == 0 )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
xShadowDeleted = pdTRUE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
LogError( ( "No error code in json document!!" ) );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
static void prvUpdateDeltaHandler( MQTTPublishInfo_t * pxPublishInfo )
|
|
|
|
static void prvUpdateDeltaHandler( MQTTPublishInfo_t * pxPublishInfo )
|
|
|
@ -536,6 +723,18 @@ static void prvEventCallback( MQTTContext_t * pxMqttContext,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogInfo( ( "/update/rejected json payload:%s.", ( const char * ) pxDeserializedInfo->pPublishInfo->pPayload ) );
|
|
|
|
LogInfo( ( "/update/rejected json payload:%s.", ( const char * ) pxDeserializedInfo->pPublishInfo->pPayload ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else if( messageType == ShadowMessageTypeDeleteAccepted )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
LogInfo( ( "Received an MQTT incoming publish on /delete/accepted topic." ) );
|
|
|
|
|
|
|
|
xShadowDeleted = pdTRUE;
|
|
|
|
|
|
|
|
xDeleteResponseReceived = pdTRUE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if( messageType == ShadowMessageTypeDeleteRejected )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* Handler function to process payload. */
|
|
|
|
|
|
|
|
prvDeleteRejectedHandler( pxDeserializedInfo->pPublishInfo );
|
|
|
|
|
|
|
|
xDeleteResponseReceived = pdTRUE;
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogInfo( ( "Other message type:%d !!", messageType ) );
|
|
|
|
LogInfo( ( "Other message type:%d !!", messageType ) );
|
|
|
@ -593,7 +792,8 @@ void vStartShadowDemo( void )
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
void prvShadowDemoTask( void * pvParameters )
|
|
|
|
void prvShadowDemoTask( void * pvParameters )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
BaseType_t demoStatus = pdPASS;
|
|
|
|
BaseType_t xDemoStatus = pdPASS;
|
|
|
|
|
|
|
|
UBaseType_t uxDemoRunCount = 0UL;
|
|
|
|
|
|
|
|
|
|
|
|
/* A buffer containing the update document. It has static duration to prevent
|
|
|
|
/* A buffer containing the update document. It has static duration to prevent
|
|
|
|
* it from being placed on the call stack. */
|
|
|
|
* it from being placed on the call stack. */
|
|
|
@ -607,205 +807,291 @@ void prvShadowDemoTask( void * pvParameters )
|
|
|
|
|
|
|
|
|
|
|
|
/****************************** Connect. ******************************/
|
|
|
|
/****************************** Connect. ******************************/
|
|
|
|
|
|
|
|
|
|
|
|
demoStatus = xEstablishMqttSession( &xMqttContext,
|
|
|
|
/* This demo runs a single loop unless there are failures in the demo execution.
|
|
|
|
&xNetworkContext,
|
|
|
|
* In case of failures in the demo execution, demo loop will be retried for up to
|
|
|
|
&xBuffer,
|
|
|
|
* SHADOW_MAX_DEMO_LOOP_COUNT times. */
|
|
|
|
prvEventCallback );
|
|
|
|
do
|
|
|
|
|
|
|
|
|
|
|
|
if( demoStatus == pdFAIL )
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
/* Log error to indicate connection failure. */
|
|
|
|
/****************************** Connect. ******************************/
|
|
|
|
LogError( ( "Failed to connect to MQTT broker." ) );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( demoStatus == pdPASS )
|
|
|
|
xDemoStatus = xEstablishMqttSession( &xMqttContext,
|
|
|
|
{
|
|
|
|
&xNetworkContext,
|
|
|
|
/* Try to delete any Shadow document in the cloud. This is done to
|
|
|
|
&xBuffer,
|
|
|
|
* ensure possbile previous Shadow documents do not affect the state
|
|
|
|
prvEventCallback );
|
|
|
|
* expected in the current demo. */
|
|
|
|
|
|
|
|
demoStatus = xPublishToTopic( &xMqttContext,
|
|
|
|
|
|
|
|
SHADOW_TOPIC_STRING_DELETE( democonfigTHING_NAME ),
|
|
|
|
|
|
|
|
SHADOW_TOPIC_LENGTH_DELETE( THING_NAME_LENGTH ),
|
|
|
|
|
|
|
|
pcUpdateDocument,
|
|
|
|
|
|
|
|
0U );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/********************* Subscribe to Shadow topics. ************************/
|
|
|
|
if( xDemoStatus == pdFAIL )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* Log error to indicate connection failure. */
|
|
|
|
|
|
|
|
LogError( ( "Failed to connect to MQTT broker." ) );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Then try to subscribe the Shadow topics. */
|
|
|
|
/**************** Attempt to delete Shadow document. ******************/
|
|
|
|
|
|
|
|
|
|
|
|
if( demoStatus == pdPASS )
|
|
|
|
if( xDemoStatus == pdPASS )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
demoStatus = xSubscribeToTopic( &xMqttContext,
|
|
|
|
/* Reset the shadow delete status flags. */
|
|
|
|
SHADOW_TOPIC_STRING_UPDATE_DELTA( democonfigTHING_NAME ),
|
|
|
|
xDeleteResponseReceived = pdFALSE;
|
|
|
|
SHADOW_TOPIC_LENGTH_UPDATE_DELTA( THING_NAME_LENGTH ) );
|
|
|
|
xShadowDeleted = pdFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* First of all, try to delete any Shadow document in the cloud.
|
|
|
|
|
|
|
|
* Try to subscribe to `/delete/accepted` and `/delete/rejected` topics. */
|
|
|
|
|
|
|
|
xDemoStatus = xSubscribeToTopic( &xMqttContext,
|
|
|
|
|
|
|
|
SHADOW_TOPIC_STRING_DELETE_ACCEPTED( democonfigTHING_NAME ),
|
|
|
|
|
|
|
|
SHADOW_TOPIC_LENGTH_DELETE_ACCEPTED( THING_NAME_LENGTH ) );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if( demoStatus == pdPASS )
|
|
|
|
if( xDemoStatus == pdPASS )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
demoStatus = xSubscribeToTopic( &xMqttContext,
|
|
|
|
/* Try to subscribe to `/delete/rejected` topic. */
|
|
|
|
SHADOW_TOPIC_STRING_UPDATE_ACCEPTED( democonfigTHING_NAME ),
|
|
|
|
xDemoStatus = xSubscribeToTopic( &xMqttContext,
|
|
|
|
SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED( THING_NAME_LENGTH ) );
|
|
|
|
SHADOW_TOPIC_STRING_DELETE_REJECTED( democonfigTHING_NAME ),
|
|
|
|
}
|
|
|
|
SHADOW_TOPIC_LENGTH_DELETE_REJECTED( THING_NAME_LENGTH ) );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if( demoStatus == pdPASS )
|
|
|
|
if( xDemoStatus == pdPASS )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
demoStatus = xSubscribeToTopic( &xMqttContext,
|
|
|
|
/* Publish to Shadow `delete` topic to attempt to delete the
|
|
|
|
SHADOW_TOPIC_STRING_UPDATE_REJECTED( democonfigTHING_NAME ),
|
|
|
|
* Shadow document if exists. */
|
|
|
|
SHADOW_TOPIC_LENGTH_UPDATE_REJECTED( THING_NAME_LENGTH ) );
|
|
|
|
xDemoStatus = xPublishToTopic( &xMqttContext,
|
|
|
|
}
|
|
|
|
SHADOW_TOPIC_STRING_DELETE( democonfigTHING_NAME ),
|
|
|
|
|
|
|
|
SHADOW_TOPIC_LENGTH_DELETE( THING_NAME_LENGTH ),
|
|
|
|
|
|
|
|
pcUpdateDocument,
|
|
|
|
|
|
|
|
0U );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/********************* Publish to Shadow topics. **********************/
|
|
|
|
/* Wait for an incoming publish on `/delete/accepted` or `/delete/rejected`
|
|
|
|
|
|
|
|
* topics, if not already received a publish. */
|
|
|
|
/* This demo uses a constant #democonfigTHING_NAME known at compile time
|
|
|
|
if( ( xDemoStatus == pdPASS ) && ( xDeleteResponseReceived != pdTRUE ) )
|
|
|
|
* 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
|
|
|
|
xDemoStatus = prvWaitForDeleteResponse( &xMqttContext );
|
|
|
|
* #Shadow_GetTopicString to assemble shadow topic strings, here is the
|
|
|
|
}
|
|
|
|
* example for /update/delta:
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* For /update/delta:
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* #define SHADOW_TOPIC_MAX_LENGTH (256U)
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* ShadowStatus_t shadowStatus = SHADOW_STATUS_SUCCESS;
|
|
|
|
|
|
|
|
* char cTopicBuffer[ SHADOW_TOPIC_MAX_LENGTH ] = { 0 };
|
|
|
|
|
|
|
|
* uint16_t usBufferSize = SHADOW_TOPIC_MAX_LENGTH;
|
|
|
|
|
|
|
|
* uint16_t usOutLength = 0;
|
|
|
|
|
|
|
|
* const char * pcThingName = "TestThingName";
|
|
|
|
|
|
|
|
* uint16_t usThingNameLength = ( sizeof( pcThingName ) - 1U );
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* shadowStatus = Shadow_GetTopicString( SHADOW_TOPIC_STRING_TYPE_UPDATE_DELTA,
|
|
|
|
|
|
|
|
* pcThingName,
|
|
|
|
|
|
|
|
* usThingNameLength,
|
|
|
|
|
|
|
|
* & ( cTopicBuffer[ 0 ] ),
|
|
|
|
|
|
|
|
* usBufferSize,
|
|
|
|
|
|
|
|
* & usOutLength );
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Then we publish a desired state to the /update topic. Since we've deleted
|
|
|
|
/* Unsubscribe from the `/delete/accepted` and 'delete/rejected` topics.*/
|
|
|
|
* the device shadow at the beginning of the demo, this will cause a delta
|
|
|
|
if( xDemoStatus == pdPASS )
|
|
|
|
* message to be published, which we have subscribed to.
|
|
|
|
{
|
|
|
|
* In many real applications, the desired state is not published by
|
|
|
|
xDemoStatus = xUnsubscribeFromTopic( &xMqttContext,
|
|
|
|
* the device itself. But for the purpose of making this demo self-contained,
|
|
|
|
SHADOW_TOPIC_STRING_DELETE_ACCEPTED( democonfigTHING_NAME ),
|
|
|
|
* we publish one here so that we can receive a delta message later.
|
|
|
|
SHADOW_TOPIC_LENGTH_DELETE_ACCEPTED( THING_NAME_LENGTH ) );
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
if( demoStatus == pdPASS )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* Desired power on state . */
|
|
|
|
|
|
|
|
LogInfo( ( "Send desired power state with 1." ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
( void ) memset( pcUpdateDocument,
|
|
|
|
|
|
|
|
0x00,
|
|
|
|
|
|
|
|
sizeof( pcUpdateDocument ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
snprintf( pcUpdateDocument,
|
|
|
|
|
|
|
|
SHADOW_DESIRED_JSON_LENGTH + 1,
|
|
|
|
|
|
|
|
SHADOW_DESIRED_JSON,
|
|
|
|
|
|
|
|
( int ) 1,
|
|
|
|
|
|
|
|
( long unsigned ) ( xTaskGetTickCount() % 1000000 ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
demoStatus = xPublishToTopic( &xMqttContext,
|
|
|
|
|
|
|
|
SHADOW_TOPIC_STRING_UPDATE( democonfigTHING_NAME ),
|
|
|
|
|
|
|
|
SHADOW_TOPIC_LENGTH_UPDATE( THING_NAME_LENGTH ),
|
|
|
|
|
|
|
|
pcUpdateDocument,
|
|
|
|
|
|
|
|
( SHADOW_DESIRED_JSON_LENGTH + 1 ) );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( demoStatus == pdPASS )
|
|
|
|
if( xDemoStatus == pdPASS )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
/* Note that PublishToTopic already called MQTT_ProcessLoop,
|
|
|
|
xDemoStatus = xUnsubscribeFromTopic( &xMqttContext,
|
|
|
|
* therefore responses may have been received and the prvEventCallback
|
|
|
|
SHADOW_TOPIC_STRING_DELETE_REJECTED( democonfigTHING_NAME ),
|
|
|
|
* may have been called, which may have changed the stateChanged flag.
|
|
|
|
SHADOW_TOPIC_LENGTH_DELETE_REJECTED( THING_NAME_LENGTH ) );
|
|
|
|
* Check if the state change flag has been modified or not. If it's modified,
|
|
|
|
}
|
|
|
|
* then we publish reported state to update topic.
|
|
|
|
|
|
|
|
|
|
|
|
/* Check if Shadow document delete was successful. A delete can be
|
|
|
|
|
|
|
|
* successful in cases listed below.
|
|
|
|
|
|
|
|
* 1. If an incoming publish is received on `/delete/accepted` topic.
|
|
|
|
|
|
|
|
* 2. If an incoming publish is received on `/delete/rejected` topic
|
|
|
|
|
|
|
|
* with error code 404. This indicates that a Shadow document was
|
|
|
|
|
|
|
|
* not present for the Thing. */
|
|
|
|
|
|
|
|
if( xShadowDeleted == pdFALSE )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
LogError( ( "Shadow delete operation failed." ) );
|
|
|
|
|
|
|
|
xDemoStatus = pdFAIL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/********************* Subscribe to Shadow topics. ************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Then try to subscribe the Shadow topics. */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( xDemoStatus == pdPASS )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
xDemoStatus = xSubscribeToTopic( &xMqttContext,
|
|
|
|
|
|
|
|
SHADOW_TOPIC_STRING_UPDATE_DELTA( democonfigTHING_NAME ),
|
|
|
|
|
|
|
|
SHADOW_TOPIC_LENGTH_UPDATE_DELTA( THING_NAME_LENGTH ) );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( xDemoStatus == pdPASS )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
xDemoStatus = xSubscribeToTopic( &xMqttContext,
|
|
|
|
|
|
|
|
SHADOW_TOPIC_STRING_UPDATE_ACCEPTED( democonfigTHING_NAME ),
|
|
|
|
|
|
|
|
SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED( THING_NAME_LENGTH ) );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( xDemoStatus == pdPASS )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
xDemoStatus = xSubscribeToTopic( &xMqttContext,
|
|
|
|
|
|
|
|
SHADOW_TOPIC_STRING_UPDATE_REJECTED( democonfigTHING_NAME ),
|
|
|
|
|
|
|
|
SHADOW_TOPIC_LENGTH_UPDATE_REJECTED( THING_NAME_LENGTH ) );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/********************* Publish to Shadow topics. **********************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 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:
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* For /update/delta:
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* #define SHADOW_TOPIC_MAX_LENGTH (256U)
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* ShadowStatus_t shadowStatus = SHADOW_STATUS_SUCCESS;
|
|
|
|
|
|
|
|
* char cTopicBuffer[ SHADOW_TOPIC_MAX_LENGTH ] = { 0 };
|
|
|
|
|
|
|
|
* uint16_t usBufferSize = SHADOW_TOPIC_MAX_LENGTH;
|
|
|
|
|
|
|
|
* uint16_t usOutLength = 0;
|
|
|
|
|
|
|
|
* const char * pcThingName = "TestThingName";
|
|
|
|
|
|
|
|
* uint16_t usThingNameLength = ( sizeof( pcThingName ) - 1U );
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* shadowStatus = Shadow_GetTopicString( SHADOW_TOPIC_STRING_TYPE_UPDATE_DELTA,
|
|
|
|
|
|
|
|
* pcThingName,
|
|
|
|
|
|
|
|
* usThingNameLength,
|
|
|
|
|
|
|
|
* & ( cTopicBuffer[ 0 ] ),
|
|
|
|
|
|
|
|
* usBufferSize,
|
|
|
|
|
|
|
|
* & usOutLength );
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Then we publish a desired state to the /update topic. Since we've deleted
|
|
|
|
|
|
|
|
* the device shadow at the beginning of the demo, this will cause a delta
|
|
|
|
|
|
|
|
* message to be published, which we have subscribed to.
|
|
|
|
|
|
|
|
* In many real applications, the desired state is not published by
|
|
|
|
|
|
|
|
* the device itself. But for the purpose of making this demo self-contained,
|
|
|
|
|
|
|
|
* we publish one here so that we can receive a delta message later.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
if( stateChanged == true )
|
|
|
|
if( xDemoStatus == pdPASS )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
/* Report the latest power state back to device shadow. */
|
|
|
|
/* Desired power on state . */
|
|
|
|
LogInfo( ( "Report to the state change: %d", ulCurrentPowerOnState ) );
|
|
|
|
LogInfo( ( "Send desired power state with 1." ) );
|
|
|
|
|
|
|
|
|
|
|
|
( void ) memset( pcUpdateDocument,
|
|
|
|
( void ) memset( pcUpdateDocument,
|
|
|
|
0x00,
|
|
|
|
0x00,
|
|
|
|
sizeof( pcUpdateDocument ) );
|
|
|
|
sizeof( pcUpdateDocument ) );
|
|
|
|
|
|
|
|
|
|
|
|
/* Keep the client token in global variable used to compare if
|
|
|
|
|
|
|
|
* the same token in /update/accepted. */
|
|
|
|
|
|
|
|
ulClientToken = ( xTaskGetTickCount() % 1000000 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
snprintf( pcUpdateDocument,
|
|
|
|
snprintf( pcUpdateDocument,
|
|
|
|
SHADOW_REPORTED_JSON_LENGTH + 1,
|
|
|
|
SHADOW_DESIRED_JSON_LENGTH + 1,
|
|
|
|
SHADOW_REPORTED_JSON,
|
|
|
|
SHADOW_DESIRED_JSON,
|
|
|
|
( int ) ulCurrentPowerOnState,
|
|
|
|
( int ) 1,
|
|
|
|
( long unsigned ) ulClientToken );
|
|
|
|
( long unsigned ) ( xTaskGetTickCount() % 1000000 ) );
|
|
|
|
|
|
|
|
|
|
|
|
demoStatus = xPublishToTopic( &xMqttContext,
|
|
|
|
xDemoStatus = xPublishToTopic( &xMqttContext,
|
|
|
|
SHADOW_TOPIC_STRING_UPDATE( democonfigTHING_NAME ),
|
|
|
|
SHADOW_TOPIC_STRING_UPDATE( democonfigTHING_NAME ),
|
|
|
|
SHADOW_TOPIC_LENGTH_UPDATE( THING_NAME_LENGTH ),
|
|
|
|
SHADOW_TOPIC_LENGTH_UPDATE( THING_NAME_LENGTH ),
|
|
|
|
pcUpdateDocument,
|
|
|
|
pcUpdateDocument,
|
|
|
|
( SHADOW_DESIRED_JSON_LENGTH + 1 ) );
|
|
|
|
( SHADOW_DESIRED_JSON_LENGTH + 1 ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
|
|
|
|
|
|
|
|
if( xDemoStatus == pdPASS )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogInfo( ( "No change from /update/delta, unsubscribe all shadow topics and disconnect from MQTT.\r\n" ) );
|
|
|
|
/* Note that PublishToTopic already called MQTT_ProcessLoop,
|
|
|
|
|
|
|
|
* therefore responses may have been received and the prvEventCallback
|
|
|
|
|
|
|
|
* may have been called, which may have changed the stateChanged flag.
|
|
|
|
|
|
|
|
* Check if the state change flag has been modified or not. If it's modified,
|
|
|
|
|
|
|
|
* then we publish reported state to update topic.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
if( stateChanged == true )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* Report the latest power state back to device shadow. */
|
|
|
|
|
|
|
|
LogInfo( ( "Report to the state change: %d", ulCurrentPowerOnState ) );
|
|
|
|
|
|
|
|
( void ) memset( pcUpdateDocument,
|
|
|
|
|
|
|
|
0x00,
|
|
|
|
|
|
|
|
sizeof( pcUpdateDocument ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Keep the client token in global variable used to compare if
|
|
|
|
|
|
|
|
* the same token in /update/accepted. */
|
|
|
|
|
|
|
|
ulClientToken = ( xTaskGetTickCount() % 1000000 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
snprintf( pcUpdateDocument,
|
|
|
|
|
|
|
|
SHADOW_REPORTED_JSON_LENGTH + 1,
|
|
|
|
|
|
|
|
SHADOW_REPORTED_JSON,
|
|
|
|
|
|
|
|
( int ) ulCurrentPowerOnState,
|
|
|
|
|
|
|
|
( long unsigned ) ulClientToken );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
xDemoStatus = xPublishToTopic( &xMqttContext,
|
|
|
|
|
|
|
|
SHADOW_TOPIC_STRING_UPDATE( democonfigTHING_NAME ),
|
|
|
|
|
|
|
|
SHADOW_TOPIC_LENGTH_UPDATE( THING_NAME_LENGTH ),
|
|
|
|
|
|
|
|
pcUpdateDocument,
|
|
|
|
|
|
|
|
( SHADOW_DESIRED_JSON_LENGTH + 1 ) );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
LogInfo( ( "No change from /update/delta, unsubscribe all shadow topics and disconnect from MQTT.\r\n" ) );
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************** Unsubscribe from Shadow topics. *******************/
|
|
|
|
/****************** Unsubscribe from Shadow topics. *******************/
|
|
|
|
|
|
|
|
|
|
|
|
if( demoStatus == pdPASS )
|
|
|
|
if( xDemoStatus == pdPASS )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogInfo( ( "Start to unsubscribe shadow topics and disconnect from MQTT. \r\n" ) );
|
|
|
|
LogInfo( ( "Start to unsubscribe shadow topics and disconnect from MQTT. \r\n" ) );
|
|
|
|
|
|
|
|
|
|
|
|
demoStatus = xUnsubscribeFromTopic( &xMqttContext,
|
|
|
|
xDemoStatus = xUnsubscribeFromTopic( &xMqttContext,
|
|
|
|
SHADOW_TOPIC_STRING_UPDATE_DELTA( democonfigTHING_NAME ),
|
|
|
|
SHADOW_TOPIC_STRING_UPDATE_DELTA( democonfigTHING_NAME ),
|
|
|
|
SHADOW_TOPIC_LENGTH_UPDATE_DELTA( THING_NAME_LENGTH ) );
|
|
|
|
SHADOW_TOPIC_LENGTH_UPDATE_DELTA( THING_NAME_LENGTH ) );
|
|
|
|
|
|
|
|
|
|
|
|
if( demoStatus != pdPASS )
|
|
|
|
if( xDemoStatus != pdPASS )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogError( ( "Failed to unsubscribe the topic %s",
|
|
|
|
LogError( ( "Failed to unsubscribe the topic %s",
|
|
|
|
SHADOW_TOPIC_STRING_UPDATE_DELTA( democonfigTHING_NAME ) ) );
|
|
|
|
SHADOW_TOPIC_STRING_UPDATE_DELTA( democonfigTHING_NAME ) ) );
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( demoStatus == pdPASS )
|
|
|
|
if( xDemoStatus == pdPASS )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
demoStatus = xUnsubscribeFromTopic( &xMqttContext,
|
|
|
|
xDemoStatus = xUnsubscribeFromTopic( &xMqttContext,
|
|
|
|
SHADOW_TOPIC_STRING_UPDATE_ACCEPTED( democonfigTHING_NAME ),
|
|
|
|
SHADOW_TOPIC_STRING_UPDATE_ACCEPTED( democonfigTHING_NAME ),
|
|
|
|
SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED( THING_NAME_LENGTH ) );
|
|
|
|
SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED( THING_NAME_LENGTH ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( xDemoStatus != pdPASS )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
LogError( ( "Failed to unsubscribe the topic %s",
|
|
|
|
|
|
|
|
SHADOW_TOPIC_STRING_UPDATE_ACCEPTED( democonfigTHING_NAME ) ) );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if( demoStatus != pdPASS )
|
|
|
|
if( xDemoStatus == pdPASS )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogError( ( "Failed to unsubscribe the topic %s",
|
|
|
|
xDemoStatus = xUnsubscribeFromTopic( &xMqttContext,
|
|
|
|
SHADOW_TOPIC_STRING_UPDATE_ACCEPTED( democonfigTHING_NAME ) ) );
|
|
|
|
SHADOW_TOPIC_STRING_UPDATE_REJECTED( democonfigTHING_NAME ),
|
|
|
|
|
|
|
|
SHADOW_TOPIC_LENGTH_UPDATE_REJECTED( THING_NAME_LENGTH ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( xDemoStatus != pdPASS )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
LogError( ( "Failed to unsubscribe the topic %s",
|
|
|
|
|
|
|
|
SHADOW_TOPIC_STRING_UPDATE_REJECTED( democonfigTHING_NAME ) ) );
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( demoStatus == pdPASS )
|
|
|
|
/****************************** Disconnect. *******************************/
|
|
|
|
{
|
|
|
|
|
|
|
|
demoStatus = xUnsubscribeFromTopic( &xMqttContext,
|
|
|
|
|
|
|
|
SHADOW_TOPIC_STRING_UPDATE_REJECTED( democonfigTHING_NAME ),
|
|
|
|
|
|
|
|
SHADOW_TOPIC_LENGTH_UPDATE_REJECTED( THING_NAME_LENGTH ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( demoStatus != pdPASS )
|
|
|
|
/* The MQTT session is always disconnected, even if there were prior failures. */
|
|
|
|
|
|
|
|
xDemoStatus = 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,
|
|
|
|
|
|
|
|
* then this demo was not successful. */
|
|
|
|
|
|
|
|
if( ( xUpdateAcceptedReturn != pdPASS ) || ( xUpdateDeltaReturn != pdPASS ) )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogError( ( "Failed to unsubscribe the topic %s",
|
|
|
|
LogError( ( "Callback function failed." ) );
|
|
|
|
SHADOW_TOPIC_STRING_UPDATE_REJECTED( democonfigTHING_NAME ) ) );
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************** Disconnect. *******************************/
|
|
|
|
/*********************** Retry in case of failure. ************************/
|
|
|
|
|
|
|
|
|
|
|
|
/* The MQTT session is always disconnected, even if there were prior failures. */
|
|
|
|
/* Increment the demo run count. */
|
|
|
|
demoStatus = xDisconnectMqttSession( &xMqttContext, &xNetworkContext );
|
|
|
|
uxDemoRunCount++;
|
|
|
|
|
|
|
|
|
|
|
|
/* This demo performs only Device Shadow operations. If matching the Shadow
|
|
|
|
if( xDemoStatus == pdPASS )
|
|
|
|
* MQTT topic fails or there are failure in parsing the received JSON document,
|
|
|
|
{
|
|
|
|
* then this demo was not successful. */
|
|
|
|
LogInfo( ( "Demo iteration %lu is successful.", uxDemoRunCount ) );
|
|
|
|
if( ( xUpdateAcceptedReturn != pdPASS ) || ( xUpdateDeltaReturn != pdPASS ) )
|
|
|
|
}
|
|
|
|
{
|
|
|
|
/* Attempt to retry a failed iteration of demo for up to #SHADOW_MAX_DEMO_LOOP_COUNT times. */
|
|
|
|
LogError( ( "Callback function failed." ) );
|
|
|
|
else if( uxDemoRunCount < SHADOW_MAX_DEMO_LOOP_COUNT )
|
|
|
|
}
|
|
|
|
{
|
|
|
|
|
|
|
|
LogWarn( ( "Demo iteration %lu failed. Retrying...", uxDemoRunCount ) );
|
|
|
|
|
|
|
|
vTaskDelay( DELAY_BETWEEN_DEMO_RETRY_ITERATIONS_TICKS );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Failed all #SHADOW_MAX_DEMO_LOOP_COUNT demo iterations. */
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
LogError( ( "All %d demo iterations failed.", SHADOW_MAX_DEMO_LOOP_COUNT ) );
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} while( xDemoStatus != pdPASS );
|
|
|
|
|
|
|
|
|
|
|
|
if( demoStatus == pdPASS )
|
|
|
|
if( xDemoStatus == pdPASS )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LogInfo( ( "Demo completed successfully." ) );
|
|
|
|
LogInfo( ( "Demo completed successfully." ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|