Closed sheldon123z closed 5 years ago
Hello sheldon123z ,
Thanks for contacting us. Can you please let us know what is the size of shadow document ? Also, is it possible to get wire trace ? It will be helpful to see packet trace from subscribe to response. Thanks.
Hi,
The shadow document is not very large, the total length is about 1700 bytes. The most time consuming part is the SUBSCRIBE and UNSUBSCRIBE operation. Also I am very confused why each GET operation will need to do two subscribe operations? Is that because one subscription is for get
topic and another operation is for get/accept
topic? Also, can I just use a persistent subscription to continuously get the shadow document without doing the UNSUBSCRIBE operation?
Here is a part of the running log, I added time stamps in the front:
[2019-08-02 10:51:55.357] I (3349) WIFI: SYSTEM_EVENT_STA_CONNECTED
[2019-08-02 10:51:58.337] 3 602 [IP-task] vDHCPProcess: offer c0a80203ip
[2019-08-02 10:51:58.344] I (6349) event: sta ip: 192.168.2.3, mask: 255.255.255.0, gw: 192.168.2.1
[2019-08-02 10:51:58.353] I (6349) WIFI: SYSTEM_EVENT_STA_GOT_IP
[2019-08-02 10:51:58.357] 4 603 [IP-task] vDHCPProcess: offer c0a80203ip
[2019-08-02 10:51:58.360] 5 603 [iot_thread] [INFO ][DEMO][6030] Successfully initialized the demo. Network type for the demo: 1
[2019-08-02 10:51:58.369] 6 603 [iot_thread] [INFO ][DEMO][6030] thingNameLength is 5, Identifier esp32
[2019-08-02 10:51:58.378] 7 603 [iot_thread] [INFO ][MQTT][6030] MQTT library successfully initialized.
[2019-08-02 10:51:58.384] 8 603 [iot_thread] [INFO ][Shadow][6030] Shadow library successfully initialized.
[2019-08-02 10:51:58.393] 9 603 [iot_thread] [INFO ][DEMO][6030] Shadow Thing Name is esp32 (length 5).
[2019-08-02 10:52:08.873] 10 1656 [iot_thread] [INFO ][MQTT][16560] Establishing new MQTT connection.
[2019-08-02 10:52:08.881] 11 1656 [iot_thread] [INFO ][MQTT][16560] (MQTT connection 0x3ffd4ee8, CONNECT operation 0x3ffd4bec) Waiting for operation completion.
[2019-08-02 10:52:09.180] 12 1686 [iot_thread] [INFO ][MQTT][16860] (MQTT connection 0x3ffd4ee8, CONNECT operation 0x3ffd4bec) Wait complete with result SUCCESS.
[2019-08-02 10:52:09.193] 13 1686 [iot_thread] [INFO ][MQTT][16860] schedule keep alive job here
[2019-08-02 10:52:09.202] 14 1686 [iot_thread] [INFO ][MQTT][16860] New MQTT connection 0x3ffde2a0 established.
[2019-08-02 10:52:09.207] 15 1686 [iot_thread] [INFO ][DEMO][16860] free heap size is 32368 bytes
[2019-08-02 10:52:09.213] 16 1686 [iot_thread] [INFO ][DEMO][16860] entered getThingshadow function
[2019-08-02 10:52:09.222] 17 1686 [iot_thread] [INFO ][MQTT][16860] (MQTT connection 0x3ffd4ee8) SUBSCRIBE operation scheduled.
[2019-08-02 10:52:09.233] 18 1686 [iot_thread] [INFO ][MQTT][16860] (MQTT connection 0x3ffd4ee8, SUBSCRIBE operation 0x3fff8504) Waiting for operation completion.
[2019-08-02 10:52:09.489] 19 1717 [iot_thread] [INFO ][MQTT][17170] (MQTT connection 0x3ffd4ee8, SUBSCRIBE operation 0x3fff8504) Wait complete with result SUCCESS.
[2019-08-02 10:52:09.511] 20 1717 [iot_thread] [INFO ][MQTT][17170] (MQTT connection 0x3ffd4ee8) SUBSCRIBE operation scheduled.
[2019-08-02 10:52:09.523] 21 1717 [iot_thread] [INFO ][MQTT][17170] (MQTT connection 0x3ffd4ee8, SUBSCRIBE operation 0x3ffd49c0) Waiting for operation completion.
[2019-08-02 10:52:09.791] 22 1747 [iot_thread] [INFO ][MQTT][17470] (MQTT connection 0x3ffd4ee8, SUBSCRIBE operation 0x3ffd49c0) Wait complete with result SUCCESS.
[2019-08-02 10:52:09.805] 23 1748 [iot_thread] [INFO ][MQTT][17480] (MQTT connection 0x3ffd4ee8) MQTT PUBLISH operation queued.
[2019-08-02 10:52:11.332] 24 1902 [iot_thread] [INFO ][Shadow][19010] Shadow GET of esp32 was ACCEPTED.
[2019-08-02 10:52:11.340] 25 1902 [iot_thread] [INFO ][Shadow][19020] pDocument here,payloadLength is 1723
[2019-08-02 10:52:11.347] 26 1902 [iot_thread] [INFO ][MQTT][19020] (MQTT connection 0x3ffd4ee8) UNSUBSCRIBE operation scheduled.
[2019-08-02 10:52:11.365] 27 1902 [iot_thread] [INFO ][MQTT][19020] (MQTT connection 0x3ffd4ee8, UNSUBSCRIBE operation 0x3ffd4bec) Waiting for operation completion.
[2019-08-02 10:52:11.644] 28 1932 [iot_thread] [INFO ][MQTT][19320] (MQTT connection 0x3ffd4ee8, UNSUBSCRIBE operation 0x3ffd4bec) Wait complete with result SUCCESS.
[2019-08-02 10:52:11.651] 29 1932 [iot_thread] [INFO ][MQTT][19320] (MQTT connection 0x3ffd4ee8) UNSUBSCRIBE operation scheduled.
[2019-08-02 10:52:11.666] 30 1932 [iot_thread] [INFO ][MQTT][19320] (MQTT connection 0x3ffd4ee8, UNSUBSCRIBE operation 0x3ffd4bec) Waiting for operation completion.
[2019-08-02 10:52:11.945] 31 1963 [iot_thread] [INFO ][MQTT][19620] (MQTT connection 0x3ffd4ee8, UNSUBSCRIBE operation 0x3ffd4bec) Wait complete with result SUCCESS.
[2019-08-02 10:52:11.978] 32 1963 [iot_thread] [INFO ][DEMO][19630] Get Shadow document, begin to analyze the retrived shadow document
[2019-08-02 10:52:11.979] 33 1963 [iot_thread] [INFO ][DEMO][19630] attributeFound
[2019-08-02 10:52:11.979] 34 1963 [iot_thread] [INFO ][DEMO][19630] command is :"ON"
[2019-08-02 10:52:11.979] 35 1963 [iot_thread] [INFO ][DEMO][19630] Write command to uart port successful! the data is :"ON"
[2019-08-02 10:52:11.987]
[2019-08-02 10:52:11.987] 36 1963 [iot_thread] [INFO ][MQTT][19630] (MQTT connection 0x3ffd4ee8) SUBSCRIBE operation scheduled.
[2019-08-02 10:52:11.996] 37 1963 [iot_thread] [INFO ][MQTT][19630] (MQTT connection 0x3ffd4ee8, SUBSCRIBE operation 0x3fff8504) Waiting for operation completion.
[2019-08-02 10:52:12.250] 38 1993 [iot_thread] [INFO ][MQTT][19930] (MQTT connection 0x3ffd4ee8, SUBSCRIBE operation 0x3fff8504) Wait complete with result SUCCESS.
[2019-08-02 10:52:12.263] 39 1993 [iot_thread] [INFO ][MQTT][19930] (MQTT connection 0x3ffd4ee8) SUBSCRIBE operation scheduled.
[2019-08-02 10:52:12.272] 40 1993 [iot_thread] [INFO ][MQTT][19930] (MQTT connection 0x3ffd4ee8, SUBSCRIBE operation 0x3ffd495c) Waiting for operation completion.
[2019-08-02 10:52:12.558] 41 2024 [iot_thread] [INFO ][MQTT][20240] (MQTT connection 0x3ffd4ee8, SUBSCRIBE operation 0x3ffd495c) Wait complete with result SUCCESS.
[2019-08-02 10:52:12.570] 42 2024 [iot_thread] [INFO ][MQTT][20240] (MQTT connection 0x3ffd4ee8) MQTT PUBLISH operation queued.
[2019-08-02 10:52:14.404] 43 2209 [iot_thread] [INFO ][Shadow][22090] Shadow GET of esp32 was ACCEPTED.
[2019-08-02 10:52:14.412] 44 2209 [iot_thread] [INFO ][Shadow][22090] pDocument here,payloadLength is 1723
[2019-08-02 10:52:14.419] 45 2209 [iot_thread] [INFO ][MQTT][22090] (MQTT connection 0x3ffd4ee8) UNSUBSCRIBE operation scheduled.
[2019-08-02 10:52:14.429] 46 2209 [iot_thread] [INFO ][MQTT][22090] (MQTT connection 0x3ffd4ee8, UNSUBSCRIBE operation 0x3ffd495c) Waiting for operation completion.
[2019-08-02 10:52:14.709] 47 2239 [iot_thread] [INFO ][MQTT][22390] (MQTT connection 0x3ffd4ee8, UNSUBSCRIBE operation 0x3ffd495c) Wait complete with result SUCCESS.
[2019-08-02 10:52:14.722] 48 2239 [iot_thread] [INFO ][MQTT][22390] (MQTT connection 0x3ffd4ee8) UNSUBSCRIBE operation scheduled.
[2019-08-02 10:52:14.731] 49 2239 [iot_thread] [INFO ][MQTT][22390] (MQTT connection 0x3ffd4ee8, UNSUBSCRIBE operation 0x3ffd495c) Waiting for operation completion.
[2019-08-02 10:52:15.017] 50 2270 [iot_thread] [INFO ][MQTT][22700] (MQTT connection 0x3ffd4ee8, UNSUBSCRIBE operation 0x3ffd495c) Wait complete with result SUCCESS.
[2019-08-02 10:52:15.031] 51 2270 [iot_thread] [INFO ][DEMO][22700] Get Shadow document, begin to analyze the retrived shadow document
[2019-08-02 10:52:15.040] 52 2270 [iot_thread] [INFO ][DEMO][22700] attributeFound
[2019-08-02 10:52:15.045] 53 2270 [iot_thread] [INFO ][DEMO][22700] command is :"ON"
[2019-08-02 10:52:15.050] 54 2270 [iot_thread] [INFO ][DEMO][22700] Write command to uart port successful! the data is :"ON"
[2019-08-02 10:52:15.062]
Hello sheldon123z ,
I do see two subscribe and unsubscribe operations from your log. Can you please share the application code that you are using to get the shadow document ?
Also, can I just use a persistent subscription to continuously get the shadow document without doing the UNSUBSCRIBE operation?
I think it should be possible , have you tried keeping persistent connection ? I'll investigate more and let you know on Monday. Thanks.
Hi abhidixi11, Yes, here is the application code, I actually just modified the original code:
/* The config header is always included first. */
#include "iot_config.h"
/* Standard includes. */
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
/* Set up logging for this demo. */
#include "iot_demo_logging.h"
/* Platform layer includes. */
#include "platform/iot_clock.h"
#include "platform/iot_threads.h"
/* MQTT include. */
#include "iot_mqtt.h"
/* Shadow include. */
#include "aws_iot_shadow.h"
/* JSON utilities include. */
#include "iot_json_utils.h"
#include "FreeRTOSIPConfig.h"
/*Uart headers */
#include "FreeRTOS.h"
#include "task.h"
#include "driver/uart.h"
#include "aws_iot_shadow_blem.h"
/*
* - Port: UART1
* - Receive (Rx) buffer: on
* - Transmit (Tx) buffer: off
* - Flow control: off
* - Event queue: off
* - Pin assignment: see defines below
*/
#define ECHO_TEST_TXD (GPIO_NUM_16)
#define ECHO_TEST_RXD (GPIO_NUM_17)
#define ECHO_TEST_RTS (UART_PIN_NO_CHANGE)
#define ECHO_TEST_CTS (UART_PIN_NO_CHANGE)
#define BUF_SIZE (1024)
/**
* Provide default values for undefined configuration settings.
*/
#define SHADOW_UPDATE_PERIOD_MS (2000)
#define SHADOW_GET_PERIOD_MS (2000)
/* Validate Shadow demo configuration settings. */
#if SHADOW_UPDATE_PERIOD_MS <= 0
#error "SHADOW_UPDATE_PERIOD_MS cannot be 0 or negative."
#endif
/**
* @brief The keep-alive interval used for this demo.
*
* An MQTT ping request will be sent periodically at this interval.
*/
#define KEEP_ALIVE_SECONDS (600)
/**
* @brief The timeout for Shadow and MQTT operations in this demo.
*/
#define TIMEOUT_MS (10000)
/*-----------------------------------------------------------*/
static void uart_init()
{
/* Configure parameters of an UART driver,
* communication pins and install the driver */
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE};
uart_param_config(UART_NUM_1, &uart_config);
uart_set_pin(UART_NUM_1, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS);
uart_driver_install(UART_NUM_1, BUF_SIZE * 2,BUF_SIZE * 2, 0, NULL, 0);
}
/*-----------------------------------------------------------*/
/* Declaration of demo function. */
int RunShadowDemo(bool awsIotMqttMode,
const char *pIdentifier,
void *pNetworkServerInfo,
void *pNetworkCredentialInfo,
const IotNetworkInterface_t *pNetworkInterface);
/*-----------------------------------------------------------*/
/**
* @brief Initialize the the MQTT library and the Shadow library.
*
* @return `EXIT_SUCCESS` if all libraries were successfully initialized;
* `EXIT_FAILURE` otherwise.
*/
static int _initializeDemo(void)
{
int status = EXIT_SUCCESS;
IotMqttError_t mqttInitStatus = IOT_MQTT_SUCCESS;
AwsIotShadowError_t shadowInitStatus = AWS_IOT_SHADOW_SUCCESS;
/* Flags to track cleanup on error. */
bool mqttInitialized = false;
/* Initialize the MQTT library. */
mqttInitStatus = IotMqtt_Init();
if (mqttInitStatus == IOT_MQTT_SUCCESS)
{
mqttInitialized = true;
}
else
{
status = EXIT_FAILURE;
}
/* Initialize the Shadow library. */
if (status == EXIT_SUCCESS)
{
/* Use the default MQTT timeout. */
shadowInitStatus = AwsIotShadow_Init(0);
if (shadowInitStatus != AWS_IOT_SHADOW_SUCCESS)
{
status = EXIT_FAILURE;
}
}
/* Clean up on error. */
if (status == EXIT_FAILURE)
{
if (mqttInitialized == true)
{
IotMqtt_Cleanup();
}
}
return status;
}
/*-----------------------------------------------------------*/
/**
* @brief Clean up the the MQTT library and the Shadow library.
*/
static void _cleanupDemo(void)
{
AwsIotShadow_Cleanup();
IotMqtt_Cleanup();
}
/*-----------------------------------------------------------*/
/**
* @brief Establish a new connection to the MQTT server for the Shadow demo.
*
* @param[in] pIdentifier NULL-terminated MQTT client identifier. The Shadow
* demo will use the Thing Name as the client identifier.
* @param[in] pNetworkServerInfo Passed to the MQTT connect function when
* establishing the MQTT connection.
* @param[in] pNetworkCredentialInfo Passed to the MQTT connect function when
* establishing the MQTT connection.
* @param[in] pNetworkInterface The network interface to use for this demo.
* @param[out] pMqttConnection Set to the handle to the new MQTT connection.
*
* @return `EXIT_SUCCESS` if the connection is successfully established; `EXIT_FAILURE`
* otherwise.
*/
static int _establishMqttConnection(const char *pIdentifier,
void *pNetworkServerInfo,
void *pNetworkCredentialInfo,
const IotNetworkInterface_t *pNetworkInterface,
IotMqttConnection_t *pMqttConnection)
{
int status = EXIT_SUCCESS;
IotMqttError_t connectStatus = IOT_MQTT_STATUS_PENDING;
IotMqttNetworkInfo_t networkInfo = IOT_MQTT_NETWORK_INFO_INITIALIZER;
IotMqttConnectInfo_t connectInfo = IOT_MQTT_CONNECT_INFO_INITIALIZER;
if (pIdentifier == NULL)
{
IotLogError("Shadow Thing Name must be provided.");
status = EXIT_FAILURE;
}
if (status == EXIT_SUCCESS)
{
/* Set the members of the network info not set by the initializer. This
* struct provided information on the transport layer to the MQTT connection. */
networkInfo.createNetworkConnection = true;
networkInfo.u.setup.pNetworkServerInfo = pNetworkServerInfo;
networkInfo.u.setup.pNetworkCredentialInfo = pNetworkCredentialInfo;
networkInfo.pNetworkInterface = pNetworkInterface;
#if (IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES == 1) && defined(IOT_DEMO_MQTT_SERIALIZER)
networkInfo.pMqttSerializer = IOT_DEMO_MQTT_SERIALIZER;
#endif
/* Set the members of the connection info not set by the initializer. */
connectInfo.awsIotMqttMode = true;
connectInfo.cleanSession = true;
connectInfo.keepAliveSeconds = KEEP_ALIVE_SECONDS;
/* AWS IoT recommends the use of the Thing Name as the MQTT client ID. */
connectInfo.pClientIdentifier = pIdentifier;
connectInfo.clientIdentifierLength = (uint16_t)strlen(pIdentifier);
IotLogInfo("Shadow Thing Name is %.*s (length %hu).",
connectInfo.clientIdentifierLength,
connectInfo.pClientIdentifier,
connectInfo.clientIdentifierLength);
/* Establish the MQTT connection. */
connectStatus = IotMqtt_Connect(&networkInfo,
&connectInfo,
100000,
pMqttConnection);
if (connectStatus != IOT_MQTT_SUCCESS)
{
IotLogError("MQTT CONNECT returned error %s.",
IotMqtt_strerror(connectStatus));
status = EXIT_FAILURE;
}
}
return status;
}
/*------------------------------------------------------------------------*/
/*get specific value in the shadow document
the maximum nested layers for the shadow document is 4
shadow document format should be followed as below:
"{" \
"\"state\":{" \
"\"desired\": {" \
"\"Lights\" :{" \
"\"thing name\" : \"sample-light\"," \
"\"device info\":\"000\"," \
"\"ON_OFF\":\"%s\"," \
"\"brightness\":\"%s\", \
"\"value\" : {\"value\": \"%s\" }," \
"\"property1\" : {\"default property1\": 0 }," \
"\"colorTemperatureInKelvin\" : \"%s\"" \
"}," \
"\"Switch\":{" \
"\"Switch value\": \"%s\"" \
"}," \
"\"Lock\":{" \
"\"Lock value\": \"%s\"" \
"}" \
"}" \
"}" \
"\"clientToken\":\"%06lu\"" \
"}" \
*/
/**
* The shadow document must be 4 nested layer like showed above, if you want to change
* the structure of the shadow document, you need not only change this function, but also
* change alexa skill and iot console document
* param receivedDocument Received shadow document from AwsIot_Get
* param receivedDocumentLength Received shadow document length
* param sectionId The section name, ie.state, delta etc
* param desiredOrReportedId Desired or reported wanted
* param attributeId Attribute wanted
* param attributeGot [out] A pointer points to the attribute value got
* param attributeLen [out] A pointer points to the length value
*/
static bool _getSpecificValue(const char* receivedDocument,
size_t receivedDocumentLength,
const char* sectionId,
const char* desiredOrReportedId,
const char* deviceNameId,
const char* attributeId,
const char** attributeGot,
size_t *attributeLen)
{
const char *stateSection = NULL;
size_t stateSectionLen =0;
bool sectionFound = false;
size_t sectionKeyLen = strlen(sectionId);
/* Find the "state" key in the shadow document. */
sectionFound = IotJsonUtils_FindJsonValue(receivedDocument,
receivedDocumentLength,
sectionId,
sectionKeyLen,
&stateSection,
&stateSectionLen);
// IotLogInfo("state section is %s",stateSection);
if(sectionFound)
{
// IotLogInfo("stateSectionFound");
const char *desiredSection = NULL;
size_t desiredSectionLength = 0;
bool desiredFound = false;
size_t desiredKeyLength = strlen(desiredOrReportedId);
/* Find the delta key within the "desired" section. */
desiredFound = IotJsonUtils_FindJsonValue( stateSection,
stateSectionLen,
desiredOrReportedId,
desiredKeyLength,
&desiredSection,
&desiredSectionLength);
if(desiredFound)
{
// IotLogInfo("desiredSectionFound");
const char *deviceState = NULL;
size_t deviceStateLen =0;
bool deviceFound = false;
const size_t deviceKeyLength = strlen(deviceNameId);
/* Find the delta key within the "device" section. */
deviceFound = IotJsonUtils_FindJsonValue( desiredSection,
desiredSectionLength,
deviceNameId,
deviceKeyLength,
&deviceState,
&deviceStateLen);
if(deviceFound)
{
// IotLogInfo("deviceFound");
bool attributeFound = false;
const size_t attributeKeyLength = strlen(attributeId);
/* Find the delta key within the "attribute" section. */
attributeFound = IotJsonUtils_FindJsonValue( deviceState,
deviceStateLen,
attributeId,
attributeKeyLength,
attributeGot,
attributeLen);
if(attributeFound)
{
IotLogInfo("attributeFound");
}
else
{IotLogInfo("attribute didn't find");}
return attributeFound;
}
else
{IotLogWarn("device didn't find");}
return deviceFound;
}
else
{IotLogWarn("desired didn't find");}
return desiredFound;
}
else
{IotLogInfo("state section didn't find!");}
return sectionFound;
}
/**
* write value to the uart port
* @param command the value to be written into uart port
* */
static void _write_command_into_uart(const char* command, size_t commandLength)
{
IotLogInfo(" command is :%.*s ",commandLength,command);
char value[commandLength+1];
//clear buffer but left the last one
memset(value,0,commandLength*sizeof(char));
strncpy(value,command,commandLength);
int result = 0;
//set the last bit of the buffer as '\n' to trigger the bg13
value[commandLength]='\n';
//write the data to uart
result = uart_write_bytes(UART_NUM_1, (const char*)value, sizeof(value));
if(result == -1)
{
IotLogInfo("Write command %s failed",value);
}
else
{
IotLogInfo("Write command to uart port successful! the data is :%.*s\n",commandLength,value);
}
//clear buffer but left the last one
memset(value,0,commandLength*sizeof(value[0]));
return;
}
/*Get thing shadow from iot */
static int _thingShadowOperation( IotMqttConnection_t mqttConnection,
const char * pThingName,
size_t thingNameLength
)
{
IotLogInfo("entered getThingshadow function");
int status = EXIT_SUCCESS;
AwsIotShadowDocumentInfo_t getInfo = AWS_IOT_SHADOW_DOCUMENT_INFO_INITIALIZER;
getInfo.pThingName = pThingName;
getInfo.thingNameLength = thingNameLength;
getInfo.u.get.mallocDocument = malloc;
AwsIotShadowOperation_t getOperation = AWS_IOT_SHADOW_OPERATION_INITIALIZER;
/*using a while loop to continuously running the program */
while(1)
{
//check if local has command to send to update the shadow document
uint32_t length = uart_get_buffered_data_len(UART_NUM_1, (size_t*)&length);
ESP_ERROR_CHECK(uart_get_buffered_data_len(UART_NUM_1, (size_t*)&length));
if(length!=0)
{
status = reportLocalChange( length,
mqttConnection,
pThingName,
thingNameLength,
status);
if(status != EXIT_SUCCESS)
{
IotLogInfo("Report local change failed");
break;
}
}
status = retriveCloudCommand( mqttConnection,
getInfo,
getOperation,
status);
if(status != EXIT_SUCCESS)
{
IotLogInfo("Retrive Cloud command failed");
break;
}
}
IotLogInfo("left getThingshadow function, the status now is %d",status);
return status;
}
/**
* Retrive the cloud shadow document and invoke the analyze function
* then send the command to ble provisioner
*/
static int retriveCloudCommand( IotMqttConnection_t mqttConnection,
AwsIotShadowDocumentInfo_t getInfo,
AwsIotShadowOperation_t getOperation,
int status
)
{
AwsIotShadowError_t result = AWS_IOT_SHADOW_STATUS_PENDING;
result = AwsIotShadow_Get( mqttConnection,
&getInfo,
AWS_IOT_SHADOW_FLAG_WAITABLE,
NULL,
&getOperation);
const char *receivedDocument = NULL;
size_t receivedDocumentLength =0;
if(result == AWS_IOT_SHADOW_STATUS_PENDING)//AWS_IOT_SHADOW_SUCCESS
{
result = AwsIotShadow_Wait( getOperation,
200000,//set 20 s as the time out so that it will wait for the operation done
&receivedDocument,
&receivedDocumentLength );
assert( result != AWS_IOT_SHADOW_STATUS_PENDING );
// The retrieved Shadow document is only valid for a successful Shadow get.
if( result == AWS_IOT_SHADOW_SUCCESS )
{
IotLogInfo("Get Shadow document, begin to analyze the retrived shadow document");
bool analyzeResult = false;
//process the document to get value needed
const char *receivedAttribute = NULL;
size_t receivedAttributeLength =0;
analyzeResult = _getSpecificValue( receivedDocument,
receivedDocumentLength,
"state",
"desired",
"Lights",
"ON_OFF",
&receivedAttribute,
&receivedAttributeLength
);
if(analyzeResult)
{
//write extracted command to uart
_write_command_into_uart(receivedAttribute,receivedAttributeLength);
status = EXIT_SUCCESS;
}
else
{
IotLogWarn("write specific value from received document failed");
status = EXIT_FAILURE;
}
//release the memory allocated to mallocDocument
free( (char*)receivedDocument );
}
else
{
IotLogWarn("Wait operation failed");
status = EXIT_FAILURE;
}
}
else
{
IotLogWarn("Retriving thing shadow document failed");
status = EXIT_FAILURE;
}
// IotLogInfo("free heap size is %d bytes ",xPortGetMinimumEverFreeHeapSize());
// wait some time to get the second time shadow
// IotClock_SleepMs(500);
return status;
}
/**
* report the local changes to cloud, if the button on the switch is pressed,
* then update the shadow document on the cloud
*/
static int reportLocalChange( uint32_t length,
IotMqttConnection_t mqttConnection,
const char * pThingName,
size_t thingNameLength,
int status)
{
/** check if there is message in the rx buffer. if there is, analysis the data and update thing shadow */
uint8_t *data = (uint8_t *) malloc(length);
length = uart_read_bytes(UART_NUM_1, data, length, 100/portTICK_PERIOD_MS);
IotLogInfo("Read from rx buffer:%.*s, length is %d",length,data,length);
//analysis the operation type represented by the data received from uart
//extract information from the data packet sent from bg13
/*get the update operation type */
UpdateOperation_t analysisResult = analysisOperation(data);
/*get the deviceType */
Device_t deviceType = analysisDeviceType(data);
/*get the attribute */
Attribute_t attributeType = analysisAttribute(data);
/**get device name from data*/
//TODO increase the packet length
// char *deviceName = getDeviceNameFromPacket(data);
// IotLogInfo("device name is %s: ",deviceName);
/**get device attribute name from data*/
// char *attributeName = getAttributeNameFromPacket(data);
// IotLogInfo("attribute name is %s: ",deviceName);
/*get the attribute value from data */
char *attributeValue = _getAttributeValue(attributeType, data);
char* pUpdateDocument = NULL;
//if result is change endpoint state, then construct a shadow document
if(analysisResult == CHANGE_ENDPOINT_STATE)
{
//generate the shadow document to send plus 20 to avoid data overflow
pUpdateDocument = generateControlShadowDocument( deviceType,
attributeType,
attributeValue
);
}
//TODO
// if(analysisResult == ADD_DEVICE )
/**update thing shadow document */
// IotLogInfo("shadow document generated is %s",pUpdateDocument);
AwsIotShadowError_t updateResult = AWS_IOT_SHADOW_STATUS_PENDING;
updateResult = wrapUpdateThingShadow( pUpdateDocument,
mqttConnection,
pThingName,
thingNameLength );
if( updateResult != AWS_IOT_SHADOW_SUCCESS )
{
IotLogError( "thing shadow update error %s.", AwsIotShadow_strerror( updateResult ) );
status = EXIT_FAILURE;
}
else
{
IotLogInfo( "Successfully sent Shadow update ");
esp_err_t success = uart_flush_input(UART_NUM_1);
if(success != ESP_OK)
{
IotLogWarn("UART clear failed");
}
}
free(data);
return status;
}
/**
* the length of each block should be showed as packet defined
*/
static char* _getAttributeValue(Attribute_t attributeType, uint8_t *data)
{
static char attributeValue[attributeValueLength] ={ '\0' };
memset(attributeValue,'\0',attributeValueLength*sizeof(char));
int length = 0;
if(attributeType==ON_OFF)
{
//decide is "ON" or "OFF"
if(data[31] =='O' && data[32]=='N' )
length = 2;
else
length = 3;
}
if(attributeType == LOCK_UNLOCK)
{
if(data[31] == 'L' && data[32]=='O')
{
length = 4;
}
else
{
length = 6;
}
}
//get third block of the data packet into attributeValue
strncpy( attributeValue,(const char*)(data \
+operationTypeLength \
+deviceNameLength \
+attributeNameLength), \
length);
IotLogInfo("attribute value is %s", attributeValue);
return attributeValue;
}
// static char* getDeviceNameFromPacket(uint8_t* data)
// {
// static char deviceName[deviceNameLength]={'\0'};
// memset(deviceName,'\0',deviceNameLength*sizeof(char));
// int i =1;
// while(data[i] != 'x')
// {
// i++;
// }
// strncpy(deviceName,(const char*)(data+1), i);
// IotLogInfo("Get DeviceName is :%s",deviceName);
// return deviceName;
// }
// static char* getAttributeNameFromPacket(uint8_t* data)
// {
// static char attributeName[attributeNameLength]={'\0'};
// memset(attributeName,'\0',attributeNameLength*sizeof(char));
// int i =deviceNameLength+attributeNameLength;
// while(data[i] != 'x')
// {
// i++;
// }
// strncpy(attributeName,(const char*)(data+deviceNameLength), i);
// IotLogInfo("Get attributeName is :%s",attributeName);
// return attributeName;
// }
/**
* analysis the received data from UART and give corresponding updating operation type
* type includes adding devices to shadow document
* change device
*/
static UpdateOperation_t analysisOperation(uint8_t* data)
{
UpdateOperation_t type = UNKNOWN_OP;
if(data[0]=='1')
{
type = CHANGE_ENDPOINT_STATE;
IotLogInfo("the type is CHANGE_ENDPOINT_STATE");
}
if (data[0]=='0')
{
type = ADD_DEVICE;
IotLogInfo("the type is ADD_DEVICE");
}
return type;
}
/**
* |----1--------|------10----|--------20------|--------10-------|
* | operation |device type | attribute name | attribute value|
* the length of each block should be showed as above
*/
/**Analysis device type that the data sent from esp32 has */
static Device_t analysisDeviceType(uint8_t* data)
{
char deviceType[deviceNameLength]={'\0'};
Device_t type = UNKNOWN_TYPE;
//copy the first 10 characters
int i =1;
while(data[i]!='x')
{
deviceType[i-1]=data[i];
i++;
}
if(strcmp((const char*)deviceType,"Lights")==0)
{
type = LIGHT;
IotLogInfo("the device type is LIGHT");
}
else if (strcmp((const char*)deviceType,"Switch")==0)
{
type = SWITCH;
IotLogInfo("the device type is SWITCH");
}
else if (strcmp((const char*)deviceType,"Lock")==0)
{
type = LOCK;
IotLogInfo("the device type is LOCK");
}
else{
type = UNKNOWN_TYPE;
}
return type;
}
/**
* Analysis what attribute the endpoint want to update
* return the attribute type received from the packet
* the length of each block should be showed as above
*
* The attribute codes available are: ON_OFF,LOCK_UNLOCK,POWER_LEVEL
*/
static Attribute_t analysisAttribute(uint8_t* data)
{
char attribute[15] ={'\0'};
Attribute_t att = UNKNOWN_ATT;
//
int i = operationTypeLength + deviceNameLength;
int j = 0;
while(data[i]!='x')
{
attribute[j]=data[i];
i++;
j++;
}
IotLogInfo("the device attribute is %s",attribute);
if (strcmp((const char*)attribute,"ON_OFF")==0)
{
att = ON_OFF;
IotLogInfo("the attribute type is ON_OFF");
}
else if (strcmp((const char*)attribute,"LOCK_UNLOCK")==0)
{
/* code */
att = LOCK_UNLOCK;
IotLogInfo("the attribute type is LOCK_UNLOCK");
}
else if (strcmp((const char*)attribute,"POWER_LEVEL") == 0)
{
/* code */
att = POWER_LEVEL;
IotLogInfo("the attribute type is POWER_LEVEL");
}
return att;
}
/**
* generate shadow document if the data analysis result is a change state directive
* everytime a specific attribute value changes but the rest are not, then the rest attributes
* should be remain in their default value
*/
static char* generateControlShadowDocument( Device_t deviceType,
Attribute_t attributeType,
char *attributeValue
)
{
int length = 0;
static char pUpdateDocument[ SHADOW_REPORTED_JSON_SIZE + 20 ] = { 0 };
if(deviceType == LIGHT && attributeType == ON_OFF)
{
length = sprintf( pUpdateDocument,
SHADOW_REPORTED_LIGHT_JSON,
attributeValue,
(int)D_Temperature,
( long unsigned ) ( IotClock_GetTimeMs() % 1000000 ) ); //the clienToken
IotLogInfo("document generated is %.*s: ",length,pUpdateDocument);
}
if(deviceType == LIGHT && attributeType == TEMPERATURE)
{
length = sprintf( pUpdateDocument,
SHADOW_REPORTED_LIGHT_JSON,
"ON",
atoi(attributeValue),
( long unsigned ) ( IotClock_GetTimeMs() % 1000000 ) ); //the clienToken
IotLogInfo("document generated is %.*s: ",length,pUpdateDocument);
}
return pUpdateDocument;
}
/**
* generate shadow document if the data analysis result is a add device directive
*/
// static char* generateAddDeviceShadowDocument( Device_t deviceType,
// char* deviceName,
// Attribute_t attributeType,
// char* attributeName,
// char *attributeValue
// )
// {
// int length = 0;
// static char pUpdateDocument[ DESIRED_ADD_DEVICE_STRING_ATTRIBUTE_SIZE + 20 ] = { 0 };
// if((deviceType == LIGHT || deviceType == SWITCH) && attributeType == ON_OFF)
// {
// length = sprintf( pUpdateDocument,
// DESIRED_ADD_DEVICE_STRING_ATTRIBUTE_JSON,
// deviceName,
// attributeName,
// attributeValue,
// ( long unsigned ) ( IotClock_GetTimeMs() % 1000000 ) ); //the clienToken
// IotLogInfo("document generated is %.*s: ",length,pUpdateDocument);
// }
// if((deviceType == LOCK) && (attributeType == LOCK_UNLOCK))
// {
// length = sprintf( pUpdateDocument,
// DESIRED_ADD_DEVICE_STRING_ATTRIBUTE_JSON,
// deviceName,
// attributeName,
// attributeValue,
// ( long unsigned ) ( IotClock_GetTimeMs() % 1000000 ) ); //the clienToken
// IotLogInfo("document generated is %.*s: ",length,pUpdateDocument);
// }
// return pUpdateDocument;
// }
//update desired part thing shadow, only called when device has data coming
static AwsIotShadowError_t wrapUpdateThingShadow( char *pUpdateDocument,
IotMqttConnection_t mqttConnection,
const char * const pThingName,
size_t thingNameLength )
{
AwsIotShadowError_t updateStatus = AWS_IOT_SHADOW_STATUS_PENDING;
AwsIotShadowDocumentInfo_t updateDocument = AWS_IOT_SHADOW_DOCUMENT_INFO_INITIALIZER;
/* Set the common members of the Shadow update document info. */
updateDocument.pThingName = pThingName;
updateDocument.thingNameLength = thingNameLength;
updateDocument.u.update.pUpdateDocument = pUpdateDocument;
updateDocument.u.update.updateDocumentLength = strlen( updateDocument.u.update.pUpdateDocument );
/* Send the Shadow update. Because the Shadow is constantly updated in
* this demo, the "Keep Subscriptions" flag is passed to this function.
* Note that this flag only needs to be passed on the first call, but
* passing it for subsequent calls is fine.
*/
updateStatus = AwsIotShadow_TimedUpdate( mqttConnection,
&updateDocument,
AWS_IOT_SHADOW_FLAG_KEEP_SUBSCRIPTIONS,
TIMEOUT_MS );
return updateStatus;
}
/*-----------------------------------------------------------*/
/**
* @brief The function that runs the Shadow demo, called by the demo runner.
*
* @param[in] awsIotMqttMode Ignored for the Shadow demo.
* @param[in] pIdentifier NULL-terminated Shadow Thing Name.
* @param[in] pNetworkServerInfo Passed to the MQTT connect function when
* establishing the MQTT connection for Shadows.
* @param[in] pNetworkCredentialInfo Passed to the MQTT connect function when
* establishing the MQTT connection for Shadows.
* @param[in] pNetworkInterface The network interface to use for this demo.
*
* @return `EXIT_SUCCESS` if the demo completes successfully; `EXIT_FAILURE` otherwise.
*/
int RunShadowDemo(bool awsIotMqttMode,
const char *pIdentifier,
void *pNetworkServerInfo,
void *pNetworkCredentialInfo,
const IotNetworkInterface_t *pNetworkInterface)
{
/** initialize the uart */
uart_init();
/* Return value of this function and the exit status of this program. */
int status = 0;
/* Handle of the MQTT connection used in this demo. */
IotMqttConnection_t mqttConnection = IOT_MQTT_CONNECTION_INITIALIZER;
/* Length of Shadow Thing Name. */
size_t thingNameLength = 0;
/* Flags for tracking which cleanup functions must be called. */
bool librariesInitialized = false, connectionEstablished = false;
// bool deltaSemaphoreCreated = false
/* The first parameter of this demo function is not used. Shadows are specific
* to AWS IoT, so this value is hardcoded to true whenever needed. */
(void)awsIotMqttMode;
/* Determine the length of the Thing Name. */
if (pIdentifier != NULL)
{
thingNameLength = strlen(pIdentifier);
IotLogInfo("thingNameLength is %d, Identifier %s",thingNameLength,pIdentifier);
if (thingNameLength == 0)
{
IotLogError("The length of the Thing Name (identifier) must be nonzero.");
status = EXIT_FAILURE;
}
}
else
{
IotLogError("A Thing Name (identifier) must be provided for the Shadow demo.");
status = EXIT_FAILURE;
}
/* Initialize the libraries required for this demo. */
if (status == EXIT_SUCCESS)
{
status = _initializeDemo();
}
if (status == EXIT_SUCCESS)
{
/* Mark the libraries as initialized. */
librariesInitialized = true;
/* Establish a new MQTT connection. */
status = _establishMqttConnection(pIdentifier,
pNetworkServerInfo,
pNetworkCredentialInfo,
pNetworkInterface,
&mqttConnection);
}
if (status == EXIT_SUCCESS)
{
/* Mark the MQTT connection as established. */
connectionEstablished = true;
}
if(status == EXIT_SUCCESS)
{
IotLogInfo("free heap size is %d bytes ",xPortGetFreeHeapSize());
status = _thingShadowOperation( mqttConnection,
pIdentifier,
thingNameLength);
}
/* Disconnect the MQTT connection if it was established. */
if (connectionEstablished == true)
{
IotMqtt_Disconnect(mqttConnection, 0);
}
/* Clean up libraries if they were initialized. */
if (librariesInitialized == true)
{
_cleanupDemo();
}
return status;
}
Hi @sheldon123z, would you mind attaching the FreeRTOSIPConfig that you are using? The settings of FreeRTOS+TCP are also determining the communication speed. Hein
Hi @sheldon123z,
Some things to speed up Shadow operations:
Closing this issue. Feel free to re-open if there is still an issue.
Hi, I am currently doing a project using esp32 to get thing shadow from IoT Core, my project now is encountering a problem that the responding time from IoT console is too long. I used the
AwsIotShadow_Get
function andAwsIotShadow_Wait
to acquire the shadow document, but it usually takes more than 3 or 4 seconds to finish this operation. I wonder what's caused this lag and if I can do anything to improve it?Thank you very much & Regards ! Sheldon