@ -1,5 +1,5 @@
/*
/*
* FreeRTOS Kernel V10 .3 . 0
* FreeRTOS V202011.0 0
* Copyright ( C ) 2020 Amazon . com , Inc . or its affiliates . All Rights Reserved .
* 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
* Permission is hereby granted , free of charge , to any person obtaining a copy of
@ -19,9 +19,10 @@
* IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM , OUT OF OR IN
* 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 .
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE .
*
*
* http : //www.FreeRTOS.org
* http s : //www.FreeRTOS.org
* http : //aws.amazon.com/freertos
* http s: //github.com/FreeRTOS
*
*
* 1 tab = = 4 spaces !
*/
*/
/*
/*
@ -589,92 +590,137 @@ void prvShadowDemoTask( void * pvParameters )
/* Remove compiler warnings about unused parameters. */
/* Remove compiler warnings about unused parameters. */
( void ) pvParameters ;
( void ) pvParameters ;
/****************************** Connect. ******************************/
demoStatus = xEstablishMqttSession ( & xMqttContext ,
demoStatus = xEstablishMqttSession ( & xMqttContext ,
& xNetworkContext ,
& xNetworkContext ,
& xBuffer ,
& xBuffer ,
prvEventCallback ) ;
prvEventCallback ) ;
if ( pdFAIL = = demoStatus )
if ( demoStatus = = pdFAIL )
{
{
/* Log error to indicate connection failure. */
/* Log error to indicate connection failure. */
LogError ( ( " Failed to connect to MQTT broker. " ) ) ;
LogError ( ( " Failed to connect to MQTT broker. " ) ) ;
}
}
else
if ( demoStatus = = pdPASS )
{
{
/* First of all, try to delete any Shadow document in the cloud. */
/* Try to delete any Shadow document in the cloud. This is done to
* ensure possbile previous Shadow documents do not affect the state
* expected in the current demo . */
demoStatus = xPublishToTopic ( & xMqttContext ,
demoStatus = xPublishToTopic ( & xMqttContext ,
SHADOW_TOPIC_STRING_DELETE ( democonfigTHING_NAME ) ,
SHADOW_TOPIC_STRING_DELETE ( democonfigTHING_NAME ) ,
SHADOW_TOPIC_LENGTH_DELETE ( THING_NAME_LENGTH ) ,
SHADOW_TOPIC_LENGTH_DELETE ( THING_NAME_LENGTH ) ,
pcUpdateDocument ,
pcUpdateDocument ,
0U ) ;
0U ) ;
}
/* Then try to subscribe shadow topics. */
/********************* Subscribe to Shadow topics. ************************/
if ( demoStatus = = pdPASS )
{
demoStatus = xSubscribeToTopic ( & xMqttContext ,
SHADOW_TOPIC_STRING_UPDATE_DELTA ( democonfigTHING_NAME ) ,
SHADOW_TOPIC_LENGTH_UPDATE_DELTA ( THING_NAME_LENGTH ) ) ;
}
if ( demoStatus = = pdPASS )
/* Then try to subscribe the Shadow topics. */
{
demoStatus = xSubscribeToTopic ( & xMqttContext ,
SHADOW_TOPIC_STRING_UPDATE_ACCEPTED ( democonfigTHING_NAME ) ,
SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED ( THING_NAME_LENGTH ) ) ;
}
if ( demoStatus = = pdPASS )
if ( demoStatus = = pdPASS )
{
{
demoStatus = xSubscribeToTopic ( & xMqttContext ,
demoStatus = xSubscribeToTopic ( & xMqttContext ,
SHADOW_TOPIC_STRING_UPDATE_REJECTED ( democonfigTHING_NAME ) ,
SHADOW_TOPIC_STRING_UPDATE_DELTA ( democonfigTHING_NAME ) ,
SHADOW_TOPIC_LENGTH_UPDATE_REJECTED ( THING_NAME_LENGTH ) ) ;
SHADOW_TOPIC_LENGTH_UPDATE_DELTA ( THING_NAME_LENGTH ) ) ;
}
}
/* This demo uses a constant #democonfigTHING_NAME known at compile time therefore we can use macros to
if ( demoStatus = = pdPASS )
* assemble shadow topic strings .
{
* If the thing name is known at run time , then we could use the API # Shadow_GetTopicString to
demoStatus = xSubscribeToTopic ( & xMqttContext ,
* assemble shadow topic strings , here is the example for / update / delta :
SHADOW_TOPIC_STRING_UPDATE_ACCEPTED ( democonfigTHING_NAME ) ,
*
SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED ( THING_NAME_LENGTH ) ) ;
* 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
if ( demoStatus = = pdPASS )
* the device shadow at the beginning of the demo , this will cause a delta message
{
* to be published , which we have subscribed to .
demoStatus = xSubscribeToTopic ( & xMqttContext ,
* In many real applications , the desired state is not published by
SHADOW_TOPIC_STRING_UPDATE_REJECTED ( democonfigTHING_NAME ) ,
* the device itself . But for the purpose of making this demo self - contained ,
SHADOW_TOPIC_LENGTH_UPDATE_REJECTED ( THING_NAME_LENGTH ) ) ;
* we publish one here so that we can receive a delta message later .
}
/********************* 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 ( 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 )
{
/* 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 ( demoStatus = = pdPASS )
if ( stateChanged = = true )
{
{
/* Desired power on state . */
/* Report the latest power state back to device shadow. */
LogInfo ( ( " Send desired power state with 1. " ) ) ;
LogInfo ( ( " Report to the state change: %d " , ulCurrentPowerOnState ) ) ;
( 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_DESIRED_JSON_LENGTH + 1 ,
SHADOW_ REPORT ED_JSON_LENGTH + 1 ,
SHADOW_DESIRED_JSON ,
SHADOW_ REPORT ED_JSON,
( int ) 1 ,
( int ) ulCurrentPowerOnState ,
( long unsigned ) ( xTaskGetTickCount ( ) % 1000000 ) ) ;
( long unsigned ) ulClientToken ) ;
demoStatus = xPublishToTopic ( & xMqttContext ,
demoStatus = xPublishToTopic ( & xMqttContext ,
SHADOW_TOPIC_STRING_UPDATE ( democonfigTHING_NAME ) ,
SHADOW_TOPIC_STRING_UPDATE ( democonfigTHING_NAME ) ,
@ -682,105 +728,75 @@ void prvShadowDemoTask( void * pvParameters )
pcUpdateDocument ,
pcUpdateDocument ,
( SHADOW_DESIRED_JSON_LENGTH + 1 ) ) ;
( SHADOW_DESIRED_JSON_LENGTH + 1 ) ) ;
}
}
else
if ( demoStatus = = pdPASS )
{
{
/* Note that PublishToTopic already called MQTT_ProcessLoop,
LogInfo ( ( " No change from /update/delta, unsubscribe all shadow topics and disconnect from MQTT. \r \n " ) ) ;
* 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 ) ;
demoStatus = 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 " ) ) ;
}
}
}
}
if ( demoStatus = = pdPASS )
/****************** Unsubscribe from Shadow topics. *******************/
{
LogInfo ( ( " Start to unsubscribe shadow topics and disconnect from MQTT. \r \n " ) ) ;
demoStatus = xUnsubscribeFromTopic ( & xMqttContext ,
if ( demoStatus = = pdPASS )
SHADOW_TOPIC_STRING_UPDATE_DELTA ( democonfigTHING_NAME ) ,
{
SHADOW_TOPIC_LENGTH_UPDATE_DELTA ( THING_NAME_LENGTH ) ) ;
LogInfo ( ( " Start to unsubscribe shadow topics and disconnect from MQTT. \r \n " ) ) ;
if ( demoStatus ! = pdPASS )
demoStatus = xUnsubscribeFromTopic ( & xMqttContext ,
{
SHADOW_TOPIC_STRING_UPDATE_DELTA ( democonfigTHING_NAME ) ,
LogError ( ( " Failed to unsubscribe the topic %s " ,
SHADOW_TOPIC_LENGTH_UPDATE_DELTA ( THING_NAME_LENGTH ) ) ;
SHADOW_TOPIC_STRING_UPDATE_DELTA ( democonfigTHING_NAME ) ) ) ;
}
}
if ( demoStatus = = pdPASS )
if ( demoStatus ! = pdPASS )
{
{
demoStatus = xUnsubscribeFromTopic ( & xMqttContext ,
LogError ( ( " Failed to unsubscribe the topic %s " ,
SHADOW_TOPIC_STRING_UPDATE_ACCEPTED ( democonfigTHING_NAME ) ,
SHADOW_TOPIC_STRING_UPDATE_DELTA ( 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 ( democonfigTHING_NAME ) ) ) ;
}
}
}
}
if ( demoStatus = = pdPASS )
if ( demoStatus = = pdPASS )
{
{
demoStatus = xUnsubscribeFromTopic ( & xMqttContext ,
demoStatus = xUnsubscribeFromTopic ( & xMqttContext ,
SHADOW_TOPIC_STRING_UPDATE_REJEC TED( democonfigTHING_NAME ) ,
SHADOW_TOPIC_STRING_UPDATE_ACCEPTED ( democonfigTHING_NAME ) ,
SHADOW_TOPIC_LENGTH_UPDATE_REJEC TED( THING_NAME_LENGTH ) ) ;
SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED ( THING_NAME_LENGTH ) ) ;
if ( demoStatus ! = pdPASS )
if ( demoStatus ! = pdPASS )
{
{
LogError ( ( " Failed to unsubscribe the topic %s " ,
LogError ( ( " Failed to unsubscribe the topic %s " ,
SHADOW_TOPIC_STRING_UPDATE_REJECTED ( democonfigTHING_NAME ) ) ) ;
SHADOW_TOPIC_STRING_UPDATE_ACCEPTED ( democonfigTHING_NAME ) ) ) ;
}
}
}
}
/* The MQTT session is always disconnected, even there were prior failures. */
if ( demoStatus = = pdPASS )
demoStatus = xDisconnectMqttSession ( & xMqttContext , & xNetworkContext ) ;
{
demoStatus = xUnsubscribeFromTopic ( & xMqttContext ,
SHADOW_TOPIC_STRING_UPDATE_REJECTED ( democonfigTHING_NAME ) ,
SHADOW_TOPIC_LENGTH_UPDATE_REJECTED ( THING_NAME_LENGTH ) ) ;
/* This demo performs only Device Shadow operations. If matching the Shadow
if ( demoStatus ! = pdPASS )
* 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 ( ( " Callback function failed. " ) ) ;
LogError ( ( " Failed to unsubscribe the topic %s " ,
SHADOW_TOPIC_STRING_UPDATE_REJECTED ( democonfigTHING_NAME ) ) ) ;
}
}
}
if ( demoStatus = = pdPASS )
/****************************** Disconnect. *******************************/
{
LogInfo ( ( " Demo completed successfully. " ) ) ;
/* The MQTT session is always disconnected, even if there were prior failures. */
}
demoStatus = xDisconnectMqttSession ( & xMqttContext , & xNetworkContext ) ;
else
{
/* This demo performs only Device Shadow operations. If matching the Shadow
LogError ( ( " Shadow Demo failed. " ) ) ;
* 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 ( ( " Callback function failed. " ) ) ;
}
if ( demoStatus = = pdPASS )
{
LogInfo ( ( " Demo completed successfully. " ) ) ;
}
else
{
LogError ( ( " Shadow Demo failed. " ) ) ;
}
}
/* Delete this task. */
/* Delete this task. */