mirror of
https://github.com/FreeRTOS/FreeRTOS.git
synced 2025-08-06 01:35:12 +08:00
Updated device-shadow submodule to support named shadow, and updated demo to use named shadow (#636)
This commit is contained in:
@ -26,11 +26,12 @@
|
||||
|
||||
/*
|
||||
* Demo for showing how to use the Device Shadow library's API. This version
|
||||
* of the Device Shadow API provides macros and helper functions for assembling MQTT topics
|
||||
* strings, and for determining whether an incoming MQTT message is related to the
|
||||
* device shadow. The Device Shadow library does not depend on a MQTT library,
|
||||
* of the Device Shadow API provide macros and helper functions for assembling MQTT topics
|
||||
* strings, and for determining whether an incoming MQTT message is related to a
|
||||
* device shadow. The shadow can be either the classic shadow or a named shadow, selected by
|
||||
* defining #democonfigSHADOW_NAME. The Device Shadow library does not depend on a MQTT library,
|
||||
* therefore the code for MQTT connections are placed in another file (shadow_demo_helpers.c)
|
||||
* to make it easy to read the code using Device Shadow library.
|
||||
* to make it easy to read the code using the Device Shadow library.
|
||||
*
|
||||
* This example assumes there is a powerOn state in the device shadow. It does the
|
||||
* following operations:
|
||||
@ -40,7 +41,7 @@
|
||||
* 4. Publish a desired state of powerOn by using helper functions in shadow_demo_helpers.c. That will cause
|
||||
* a delta message to be sent to device.
|
||||
* 5. Handle incoming MQTT messages in prvEventCallback, determine whether the message is related to the device
|
||||
* shadow by using a function defined by the Device Shadow library (Shadow_MatchTopic). If the message is a
|
||||
* shadow by using a function defined by the Device Shadow library (Shadow_MatchTopicString). If the message is a
|
||||
* device shadow delta message, set a flag for the main function to know, then the main function will publish
|
||||
* a second message to update the reported state of powerOn.
|
||||
* 6. Handle incoming message again in prvEventCallback. If the message is from update/accepted, verify that it
|
||||
@ -208,6 +209,11 @@
|
||||
*/
|
||||
#define THING_NAME_LENGTH ( ( uint16_t ) ( sizeof( democonfigTHING_NAME ) - 1 ) )
|
||||
|
||||
/**
|
||||
* @brief The length of #democonfigSHADOW_NAME.
|
||||
*/
|
||||
#define SHADOW_NAME_LENGTH ( ( uint16_t ) ( sizeof( democonfigSHADOW_NAME ) - 1 ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
@ -674,7 +680,7 @@ static void prvUpdateAcceptedHandler( MQTTPublishInfo_t * pxPublishInfo )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* This is the callback function invoked by the MQTT stack when it receives
|
||||
* incoming messages. This function demonstrates how to use the Shadow_MatchTopic
|
||||
* incoming messages. This function demonstrates how to use the Shadow_MatchTopicString
|
||||
* function to determine whether the incoming message is a device shadow message
|
||||
* or not. If it is, it handles the message depending on the message type.
|
||||
*/
|
||||
@ -684,7 +690,9 @@ static void prvEventCallback( MQTTContext_t * pxMqttContext,
|
||||
{
|
||||
ShadowMessageType_t messageType = ShadowMessageTypeMaxNum;
|
||||
const char * pcThingName = NULL;
|
||||
uint16_t usThingNameLength = 0U;
|
||||
uint8_t ucThingNameLength = 0U;
|
||||
const char * pcShadowName = NULL;
|
||||
uint8_t ucShadowNameLength = 0U;
|
||||
uint16_t usPacketIdentifier;
|
||||
|
||||
( void ) pxMqttContext;
|
||||
@ -704,11 +712,13 @@ static void prvEventCallback( MQTTContext_t * pxMqttContext,
|
||||
LogInfo( ( "pPublishInfo->pTopicName:%s.", pxDeserializedInfo->pPublishInfo->pTopicName ) );
|
||||
|
||||
/* Let the Device Shadow library tell us whether this is a device shadow message. */
|
||||
if( SHADOW_SUCCESS == Shadow_MatchTopic( pxDeserializedInfo->pPublishInfo->pTopicName,
|
||||
pxDeserializedInfo->pPublishInfo->topicNameLength,
|
||||
&messageType,
|
||||
&pcThingName,
|
||||
&usThingNameLength ) )
|
||||
if( SHADOW_SUCCESS == Shadow_MatchTopicString( pxDeserializedInfo->pPublishInfo->pTopicName,
|
||||
pxDeserializedInfo->pPublishInfo->topicNameLength,
|
||||
&messageType,
|
||||
&pcThingName,
|
||||
&ucThingNameLength,
|
||||
&pcShadowName,
|
||||
&ucShadowNameLength ) )
|
||||
{
|
||||
/* Upon successful return, the messageType has been filled in. */
|
||||
if( messageType == ShadowMessageTypeUpdateDelta )
|
||||
@ -748,7 +758,7 @@ static void prvEventCallback( MQTTContext_t * pxMqttContext,
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError( ( "Shadow_MatchTopic parse failed:%s !!", ( const char * ) pxDeserializedInfo->pPublishInfo->pTopicName ) );
|
||||
LogError( ( "Shadow_MatchTopicString parse failed:%s !!", ( const char * ) pxDeserializedInfo->pPublishInfo->pTopicName ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -782,15 +792,17 @@ void vStartShadowDemo( void )
|
||||
*
|
||||
* This main function demonstrates how to use the macros provided by the
|
||||
* Device Shadow library to assemble strings for the MQTT topics defined
|
||||
* by AWS IoT Device Shadow. It uses these macros for topics to subscribe
|
||||
* to:
|
||||
* - SHADOW_TOPIC_STRING_UPDATE_DELTA for "$aws/things/thingName/shadow/update/delta"
|
||||
* - SHADOW_TOPIC_STRING_UPDATE_ACCEPTED for "$aws/things/thingName/shadow/update/accepted"
|
||||
* - SHADOW_TOPIC_STRING_UPDATE_REJECTED for "$aws/things/thingName/shadow/update/rejected"
|
||||
* by AWS IoT Device Shadow. Named shadow topic strings differ from unnamed
|
||||
* ("Classic") topic strings as indicated by the tokens within square brackets.
|
||||
*
|
||||
* The main function uses these macros for topics to subscribe to:
|
||||
* - SHADOW_TOPIC_STR_UPDATE_DELTA for "$aws/things/thingName/shadow[/name/shadowname]/update/delta"
|
||||
* - SHADOW_TOPIC_STR_UPDATE_ACC for "$aws/things/thingName/shadow[/name/shadowname]/update/accepted"
|
||||
* - SHADOW_TOPIC_STR_UPDATE_REJ for "$aws/things/thingName/shadow[/name/shadowname]/update/rejected"
|
||||
*
|
||||
* It also uses these macros for topics to publish to:
|
||||
* - SHADOW_TOPIC_STIRNG_DELETE for "$aws/things/thingName/shadow/delete"
|
||||
* - SHADOW_TOPIC_STRING_UPDATE for "$aws/things/thingName/shadow/update"
|
||||
* - SHADOW_TOPIC_STR_DELETE for "$aws/things/thingName/shadow[/name/shadowname]/delete"
|
||||
* - SHADOW_TOPIC_STR_UPDATE for "$aws/things/thingName/shadow[/name/shadowname]/update"
|
||||
*
|
||||
* The helper functions this demo uses for MQTT operations have internal
|
||||
* loops to process incoming messages. Those are not the focus of this demo
|
||||
@ -842,16 +854,16 @@ void prvShadowDemoTask( void * pvParameters )
|
||||
/* 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 ) );
|
||||
SHADOW_TOPIC_STR_DELETE_ACC( democonfigTHING_NAME, democonfigSHADOW_NAME ),
|
||||
SHADOW_TOPIC_LEN_DELETE_ACC( THING_NAME_LENGTH, SHADOW_NAME_LENGTH ) );
|
||||
}
|
||||
|
||||
if( xDemoStatus == pdPASS )
|
||||
{
|
||||
/* Try to subscribe to `/delete/rejected` topic. */
|
||||
xDemoStatus = xSubscribeToTopic( &xMqttContext,
|
||||
SHADOW_TOPIC_STRING_DELETE_REJECTED( democonfigTHING_NAME ),
|
||||
SHADOW_TOPIC_LENGTH_DELETE_REJECTED( THING_NAME_LENGTH ) );
|
||||
SHADOW_TOPIC_STR_DELETE_REJ( democonfigTHING_NAME, democonfigSHADOW_NAME ),
|
||||
SHADOW_TOPIC_LEN_DELETE_REJ( THING_NAME_LENGTH, SHADOW_NAME_LENGTH ) );
|
||||
}
|
||||
|
||||
if( xDemoStatus == pdPASS )
|
||||
@ -859,8 +871,8 @@ void prvShadowDemoTask( void * pvParameters )
|
||||
/* Publish to Shadow `delete` topic to attempt to delete the
|
||||
* Shadow document if exists. */
|
||||
xDemoStatus = xPublishToTopic( &xMqttContext,
|
||||
SHADOW_TOPIC_STRING_DELETE( democonfigTHING_NAME ),
|
||||
SHADOW_TOPIC_LENGTH_DELETE( THING_NAME_LENGTH ),
|
||||
SHADOW_TOPIC_STR_DELETE( democonfigTHING_NAME, democonfigSHADOW_NAME ),
|
||||
SHADOW_TOPIC_LEN_DELETE( THING_NAME_LENGTH, SHADOW_NAME_LENGTH ),
|
||||
pcUpdateDocument,
|
||||
0U );
|
||||
}
|
||||
@ -876,15 +888,15 @@ void prvShadowDemoTask( void * pvParameters )
|
||||
if( xDemoStatus == pdPASS )
|
||||
{
|
||||
xDemoStatus = xUnsubscribeFromTopic( &xMqttContext,
|
||||
SHADOW_TOPIC_STRING_DELETE_ACCEPTED( democonfigTHING_NAME ),
|
||||
SHADOW_TOPIC_LENGTH_DELETE_ACCEPTED( THING_NAME_LENGTH ) );
|
||||
SHADOW_TOPIC_STR_DELETE_ACC( democonfigTHING_NAME, democonfigSHADOW_NAME ),
|
||||
SHADOW_TOPIC_LEN_DELETE_ACC( THING_NAME_LENGTH, SHADOW_NAME_LENGTH ) );
|
||||
}
|
||||
|
||||
if( xDemoStatus == pdPASS )
|
||||
{
|
||||
xDemoStatus = xUnsubscribeFromTopic( &xMqttContext,
|
||||
SHADOW_TOPIC_STRING_DELETE_REJECTED( democonfigTHING_NAME ),
|
||||
SHADOW_TOPIC_LENGTH_DELETE_REJECTED( THING_NAME_LENGTH ) );
|
||||
SHADOW_TOPIC_STR_DELETE_REJ( democonfigTHING_NAME, democonfigSHADOW_NAME ),
|
||||
SHADOW_TOPIC_LEN_DELETE_REJ( THING_NAME_LENGTH, SHADOW_NAME_LENGTH ) );
|
||||
}
|
||||
|
||||
/* Check if Shadow document delete was successful. A delete can be
|
||||
@ -906,30 +918,30 @@ void prvShadowDemoTask( void * pvParameters )
|
||||
if( xDemoStatus == pdPASS )
|
||||
{
|
||||
xDemoStatus = xSubscribeToTopic( &xMqttContext,
|
||||
SHADOW_TOPIC_STRING_UPDATE_DELTA( democonfigTHING_NAME ),
|
||||
SHADOW_TOPIC_LENGTH_UPDATE_DELTA( THING_NAME_LENGTH ) );
|
||||
SHADOW_TOPIC_STR_UPDATE_DELTA( democonfigTHING_NAME, democonfigSHADOW_NAME ),
|
||||
SHADOW_TOPIC_LEN_UPDATE_DELTA( THING_NAME_LENGTH, SHADOW_NAME_LENGTH ) );
|
||||
}
|
||||
|
||||
if( xDemoStatus == pdPASS )
|
||||
{
|
||||
xDemoStatus = xSubscribeToTopic( &xMqttContext,
|
||||
SHADOW_TOPIC_STRING_UPDATE_ACCEPTED( democonfigTHING_NAME ),
|
||||
SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED( THING_NAME_LENGTH ) );
|
||||
SHADOW_TOPIC_STR_UPDATE_ACC( democonfigTHING_NAME, democonfigSHADOW_NAME ),
|
||||
SHADOW_TOPIC_LEN_UPDATE_ACC( THING_NAME_LENGTH, SHADOW_NAME_LENGTH ) );
|
||||
}
|
||||
|
||||
if( xDemoStatus == pdPASS )
|
||||
{
|
||||
xDemoStatus = xSubscribeToTopic( &xMqttContext,
|
||||
SHADOW_TOPIC_STRING_UPDATE_REJECTED( democonfigTHING_NAME ),
|
||||
SHADOW_TOPIC_LENGTH_UPDATE_REJECTED( THING_NAME_LENGTH ) );
|
||||
SHADOW_TOPIC_STR_UPDATE_REJ( democonfigTHING_NAME, democonfigSHADOW_NAME ),
|
||||
SHADOW_TOPIC_LEN_UPDATE_REJ( THING_NAME_LENGTH, SHADOW_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
|
||||
/* This demo uses constants #democonfigTHING_NAME and #democonfigSHADOW_NAME
|
||||
* known at compile time, therefore we can use macros to assemble shadow topic strings.
|
||||
* If the thing name or shadow name is only known at run time, then we could use the API
|
||||
* #Shadow_AssembleTopicString to assemble shadow topic strings. Here is the
|
||||
* example for /update/delta:
|
||||
*
|
||||
* For /update/delta:
|
||||
@ -941,14 +953,18 @@ void prvShadowDemoTask( void * pvParameters )
|
||||
* uint16_t usBufferSize = SHADOW_TOPIC_MAX_LENGTH;
|
||||
* uint16_t usOutLength = 0;
|
||||
* const char * pcThingName = "TestThingName";
|
||||
* uint16_t usThingNameLength = ( sizeof( pcThingName ) - 1U );
|
||||
* uint8_t ucThingNameLength = ( sizeof( pcThingName ) - 1U );
|
||||
* const char * pcShadowName = "TestShadowName";
|
||||
* uint8_t ucShadowNameLength = ( sizeof( pcShadowName ) - 1U );
|
||||
*
|
||||
* shadowStatus = Shadow_GetTopicString( SHADOW_TOPIC_STRING_TYPE_UPDATE_DELTA,
|
||||
* pcThingName,
|
||||
* usThingNameLength,
|
||||
* & ( cTopicBuffer[ 0 ] ),
|
||||
* usBufferSize,
|
||||
* & usOutLength );
|
||||
* shadowStatus = Shadow_AssembleTopicString( SHADOW_TOPIC_STRING_TYPE_UPDATE_DELTA,
|
||||
* pcThingName,
|
||||
* ucThingNameLength,
|
||||
* pcShadowName,
|
||||
* ucShadowNameLength,
|
||||
* & ( cTopicBuffer[ 0 ] ),
|
||||
* usBufferSize,
|
||||
* & usOutLength );
|
||||
*/
|
||||
|
||||
/* Then we publish a desired state to the /update topic. Since we've deleted
|
||||
@ -974,8 +990,8 @@ void prvShadowDemoTask( void * pvParameters )
|
||||
( long unsigned ) ( xTaskGetTickCount() % 1000000 ) );
|
||||
|
||||
xDemoStatus = xPublishToTopic( &xMqttContext,
|
||||
SHADOW_TOPIC_STRING_UPDATE( democonfigTHING_NAME ),
|
||||
SHADOW_TOPIC_LENGTH_UPDATE( THING_NAME_LENGTH ),
|
||||
SHADOW_TOPIC_STR_UPDATE( democonfigTHING_NAME, democonfigSHADOW_NAME ),
|
||||
SHADOW_TOPIC_LEN_UPDATE( THING_NAME_LENGTH, SHADOW_NAME_LENGTH ),
|
||||
pcUpdateDocument,
|
||||
( SHADOW_DESIRED_JSON_LENGTH + 1 ) );
|
||||
}
|
||||
@ -1007,8 +1023,8 @@ void prvShadowDemoTask( void * pvParameters )
|
||||
( long unsigned ) ulClientToken );
|
||||
|
||||
xDemoStatus = xPublishToTopic( &xMqttContext,
|
||||
SHADOW_TOPIC_STRING_UPDATE( democonfigTHING_NAME ),
|
||||
SHADOW_TOPIC_LENGTH_UPDATE( THING_NAME_LENGTH ),
|
||||
SHADOW_TOPIC_STR_UPDATE( democonfigTHING_NAME, democonfigSHADOW_NAME ),
|
||||
SHADOW_TOPIC_LEN_UPDATE( THING_NAME_LENGTH, SHADOW_NAME_LENGTH ),
|
||||
pcUpdateDocument,
|
||||
( SHADOW_DESIRED_JSON_LENGTH + 1 ) );
|
||||
}
|
||||
@ -1025,39 +1041,39 @@ void prvShadowDemoTask( void * pvParameters )
|
||||
LogInfo( ( "Start to unsubscribe shadow topics and disconnect from MQTT. \r\n" ) );
|
||||
|
||||
xDemoStatus = xUnsubscribeFromTopic( &xMqttContext,
|
||||
SHADOW_TOPIC_STRING_UPDATE_DELTA( democonfigTHING_NAME ),
|
||||
SHADOW_TOPIC_LENGTH_UPDATE_DELTA( THING_NAME_LENGTH ) );
|
||||
SHADOW_TOPIC_STR_UPDATE_DELTA( democonfigTHING_NAME, democonfigSHADOW_NAME ),
|
||||
SHADOW_TOPIC_LEN_UPDATE_DELTA( THING_NAME_LENGTH, SHADOW_NAME_LENGTH ) );
|
||||
|
||||
if( xDemoStatus != pdPASS )
|
||||
{
|
||||
LogError( ( "Failed to unsubscribe the topic %s",
|
||||
SHADOW_TOPIC_STRING_UPDATE_DELTA( democonfigTHING_NAME ) ) );
|
||||
SHADOW_TOPIC_STR_UPDATE_DELTA( democonfigTHING_NAME, democonfigSHADOW_NAME ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
if( xDemoStatus == pdPASS )
|
||||
{
|
||||
xDemoStatus = xUnsubscribeFromTopic( &xMqttContext,
|
||||
SHADOW_TOPIC_STRING_UPDATE_ACCEPTED( democonfigTHING_NAME ),
|
||||
SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED( THING_NAME_LENGTH ) );
|
||||
SHADOW_TOPIC_STR_UPDATE_ACC( democonfigTHING_NAME, democonfigSHADOW_NAME ),
|
||||
SHADOW_TOPIC_LEN_UPDATE_ACC( THING_NAME_LENGTH, SHADOW_NAME_LENGTH ) );
|
||||
|
||||
if( xDemoStatus != pdPASS )
|
||||
{
|
||||
LogError( ( "Failed to unsubscribe the topic %s",
|
||||
SHADOW_TOPIC_STRING_UPDATE_ACCEPTED( democonfigTHING_NAME ) ) );
|
||||
SHADOW_TOPIC_STR_UPDATE_ACC( democonfigTHING_NAME, democonfigSHADOW_NAME ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
if( xDemoStatus == pdPASS )
|
||||
{
|
||||
xDemoStatus = xUnsubscribeFromTopic( &xMqttContext,
|
||||
SHADOW_TOPIC_STRING_UPDATE_REJECTED( democonfigTHING_NAME ),
|
||||
SHADOW_TOPIC_LENGTH_UPDATE_REJECTED( THING_NAME_LENGTH ) );
|
||||
SHADOW_TOPIC_STR_UPDATE_REJ( democonfigTHING_NAME, democonfigSHADOW_NAME ),
|
||||
SHADOW_TOPIC_LEN_UPDATE_REJ( THING_NAME_LENGTH, SHADOW_NAME_LENGTH ) );
|
||||
|
||||
if( xDemoStatus != pdPASS )
|
||||
{
|
||||
LogError( ( "Failed to unsubscribe the topic %s",
|
||||
SHADOW_TOPIC_STRING_UPDATE_REJECTED( democonfigTHING_NAME ) ) );
|
||||
SHADOW_TOPIC_STR_UPDATE_REJ( democonfigTHING_NAME, democonfigSHADOW_NAME ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,4 +236,13 @@ extern void vLoggingPrintf( const char * pcFormatString,
|
||||
*/
|
||||
#define democonfigNETWORK_BUFFER_SIZE ( 1024U )
|
||||
|
||||
/**
|
||||
* @brief Predefined shadow name.
|
||||
*
|
||||
* Defaults to unnamed "Classic" shadow. Change to a custom string to use a named shadow.
|
||||
*/
|
||||
#ifndef democonfigSHADOW_NAME
|
||||
#define democonfigSHADOW_NAME SHADOW_NAME_CLASSIC
|
||||
#endif
|
||||
|
||||
#endif /* DEMO_CONFIG_H */
|
||||
|
Submodule FreeRTOS-Plus/Source/AWS/device-shadow updated: 508ce43a22...ff5a3e174c
10
lexicon.txt
10
lexicon.txt
@ -1478,6 +1478,7 @@ pcrestcommand
|
||||
pcrootdir
|
||||
pcrxbuffer
|
||||
pcrxedchar
|
||||
pcshadowname
|
||||
pcsource
|
||||
pcstatusmessage
|
||||
pcstring
|
||||
@ -2198,6 +2199,9 @@ sfprld
|
||||
sfr
|
||||
sfsrootcag
|
||||
sha
|
||||
shadow
|
||||
shadowname
|
||||
shadownamelength
|
||||
shadowstatus
|
||||
shasum
|
||||
shigherprioritytaskwoken
|
||||
@ -2373,6 +2377,7 @@ testcases
|
||||
testloop
|
||||
testrunnerafqp
|
||||
testrunnerfull
|
||||
testshadowname
|
||||
testthingname
|
||||
testval
|
||||
tex
|
||||
@ -2451,6 +2456,7 @@ uartcommandconsole
|
||||
uartlite
|
||||
uarts
|
||||
ubasetype
|
||||
uc
|
||||
uca
|
||||
ucautoreloadtimercounters
|
||||
ucbaddnsresponseh
|
||||
@ -2486,6 +2492,7 @@ ucrequest
|
||||
ucrequesttype
|
||||
ucrotaskfaulttracker
|
||||
ucsha
|
||||
ucshadownamelength
|
||||
ucsharedbuffer
|
||||
ucsharedmemory
|
||||
ucsharedmemoryn
|
||||
@ -2493,6 +2500,7 @@ ucslaveaddress
|
||||
ucsrb
|
||||
ucsrc
|
||||
uctempbuffer
|
||||
ucthingnamelength
|
||||
ucxbrf
|
||||
ucxbrs
|
||||
udp
|
||||
@ -3376,4 +3384,4 @@ yyyy
|
||||
yyyymmddhhmmss
|
||||
zc
|
||||
zer
|
||||
zynq
|
||||
zynq
|
||||
|
Reference in New Issue
Block a user