Demo application for using the AT&T IoT Starter Kit Powered by AWS.

Dependencies:   SDFileSystem

Fork of ATT_AWS_IoT_demo by Anthony Phillips

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002  *  AT&T IoT Starter Kit example using Amazon Web Service 
00003  */
00004 #include "mbed.h"
00005 
00006 // SD File System
00007 #include "SDFileSystem.h"
00008 
00009 // Serial extension
00010 #include "MODSERIAL.h"
00011 
00012 // Network includes
00013 #include "WNCInterface.h"
00014 #include "network_interface.h"
00015 
00016 // AWS includes
00017 #include "aws_iot_log.h"
00018 #include "aws_iot_version.h"
00019 #include "aws_iot_shadow_interface.h"
00020 #include "aws_iot_shadow_json_data.h"
00021 #include "aws_iot_config.h"
00022 #include "aws_iot_mqtt_interface.h"
00023 
00024 // Sensors
00025 #include "HTS221.h"
00026 
00027 #if DEBUG_LEVEL > 0
00028 #include "mbedtls/debug.h"
00029 #endif
00030 
00031 //=====================================================================================================================
00032 //
00033 // Defines
00034 //
00035 //=====================================================================================================================
00036 // LED Colors
00037 #define COLOR_OFF    0x00
00038 #define COLOR_RED    0x01
00039 #define COLOR_GREEN  0x02
00040 #define COLOR_BLUE   0x04
00041 #define COLOR_WHITE  0x07
00042 #define NUM_COLORS   5
00043 
00044 // AWS defines
00045 #define PATH_MAX    1024
00046 #define MAX_LENGTH_OF_UPDATE_JSON_BUFFER 200 // NOTE: Be wary of this if your JSON doc grows
00047 #define SHADOW_SYNC_INTERVAL 3.0             // How often we sync with AWS Shadow (in seconds)
00048 
00049 // Comment out the following line if color is not supported on the terminal
00050 //#define USE_COLOR
00051 #ifdef USE_COLOR
00052  #define BLK "\033[30m"
00053  #define RED "\033[31m"
00054  #define GRN "\033[32m"
00055  #define YEL "\033[33m"
00056  #define BLU "\033[34m"
00057  #define MAG "\033[35m"
00058  #define CYN "\033[36m"
00059  #define WHT "\033[37m"
00060  #define DEF "\033[39m"
00061 #else
00062  #define BLK
00063  #define RED
00064  #define GRN
00065  #define YEL
00066  #define BLU
00067  #define MAG
00068  #define CYN
00069  #define WHT
00070  #define DEF
00071 #endif
00072 
00073 // Sensor defines
00074 #define CTOF(x)  ((x)*1.8+32) // Temperature
00075 
00076 //=====================================================================================================================
00077 //
00078 // Globals
00079 //
00080 //=====================================================================================================================
00081 // Controls LED color
00082 unsigned char ledColor = COLOR_OFF;
00083 
00084 // Color cycle array (used with SW3 button presses)
00085 unsigned char colorCycle[NUM_COLORS] = {COLOR_OFF, COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_WHITE};
00086 
00087 // Button interrupts
00088 bool buttonOverride = false;
00089 InterruptIn Interrupt(SW3);
00090 
00091 // These defines are pulled from aws_iot_config.h
00092 char HostAddress[255] = AWS_IOT_MQTT_HOST;
00093 char MqttClientID[32] = AWS_IOT_MQTT_CLIENT_ID;
00094 char ThingName[32] = AWS_IOT_MY_THING_NAME;
00095 char PortString[5] = "8883";
00096 uint32_t port = AWS_IOT_MQTT_PORT;
00097 char iccidName[21] = "12345678901234567890";
00098 
00099 // Sensor data
00100 float temperature = 0.0;
00101 int   humidity    = 0;
00102 
00103 // Temp/humidity object
00104 HTS221 hts221; 
00105 
00106 //=====================================================================================================================
00107 //
00108 // Devices
00109 //
00110 //=====================================================================================================================
00111 // GPIOs for RGB LED
00112 DigitalOut led_green(LED_GREEN);
00113 DigitalOut led_red(LED_RED);
00114 DigitalOut led_blue(LED_BLUE);
00115 
00116 // USB Serial port (to PC)
00117 MODSERIAL pc(USBTX,USBRX,256,256);
00118 
00119 // SD card access (MOSI, MISO, SCK, CS)
00120 SDFileSystem sd(PTE3, PTE1, PTE2, PTE4, "sd");
00121 
00122 // I2C bus (SDA, SCL)
00123 I2C i2c(PTC11, PTC10);
00124 
00125 //=====================================================================================================================
00126 //
00127 // Functions
00128 //
00129 //=====================================================================================================================
00130 //*********************************************************************************************************************
00131 //* Prints the given format to the PC serial port.  Exposed to all files via aws_iot_log.h
00132 //*********************************************************************************************************************
00133 void pc_print(const char * format, ...)
00134 {
00135     va_list vl;
00136     va_start(vl, format);
00137     pc.vprintf(format, vl);
00138     va_end(vl);
00139 }
00140 
00141 //*********************************************************************************************************************
00142 //* Set the RGB LED's Color
00143 //* LED Color 0=Off to 7=White.  3 bits represent BGR (bit0=Red, bit1=Green, bit2=Blue) 
00144 //*********************************************************************************************************************
00145 void SetLedColor(unsigned char ucColor)
00146 {    
00147     //Note that when an LED is on, you write a 0 to it:
00148     led_red = !(ucColor & 0x1); //bit 0
00149     led_green = !(ucColor & 0x2); //bit 1
00150     led_blue = !(ucColor & 0x4); //bit 2
00151 }
00152 
00153 //*********************************************************************************************************************
00154 //* SW3 Button handler.  Finds the current LED color and sets the button to the next color in colorCycle[]
00155 //*********************************************************************************************************************
00156 void sw3ButtonHandler()
00157 {
00158     int i;
00159     for(i=0; i < NUM_COLORS; i++) {
00160         if (ledColor == colorCycle[i])
00161             break;
00162     }
00163     
00164     // (circular-queue)
00165     if (++i == NUM_COLORS)
00166         i = 0;
00167         
00168     ledColor = colorCycle[i];
00169     SetLedColor(ledColor);
00170     buttonOverride = true;
00171 }
00172 
00173 //*********************************************************************************************************************
00174 //* Print LED and sensor data
00175 //*********************************************************************************************************************
00176 void printData()
00177 {
00178     INFO("Temperature is: %0.2f F", temperature);
00179     INFO("Humidity    is: %02d", humidity);      
00180     switch (ledColor) {
00181          case COLOR_OFF:
00182              INFO("LED: Off");
00183              break;
00184          case COLOR_RED:
00185              INFO("LED: Red");
00186              break;
00187          case COLOR_GREEN:
00188              INFO("LED: Green");
00189              break;
00190          case COLOR_BLUE:
00191              INFO("LED: Blue");
00192              break;
00193          case COLOR_WHITE:
00194              INFO("LED: White");
00195              break;
00196     }
00197 }
00198 
00199 //=====================================================================================================================
00200 //
00201 // AWS Shadow Callbacks
00202 //
00203 //=====================================================================================================================
00204 //*********************************************************************************************************************
00205 //* This is the callback function that fires when an update is sent.  It will print the update response status.
00206 //*********************************************************************************************************************
00207 void ShadowUpdateStatusCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status,
00208         const char *pReceivedJsonDocument, void *pContextData) {
00209 
00210     INFO("Shadow Update Status Callback");
00211     
00212     if (status == SHADOW_ACK_TIMEOUT) {
00213         INFO("Update Timeout--");
00214     } else if (status == SHADOW_ACK_REJECTED) {
00215         INFO("Update RejectedXX");
00216     } else if (status == SHADOW_ACK_ACCEPTED) {
00217         INFO("Update Accepted!!"); // Good
00218     }
00219 }
00220 
00221 //*********************************************************************************************************************
00222 //* This is the callback function that fires when AWS has sends out a shadow update. 
00223 //*********************************************************************************************************************
00224 void ledControl_Callback(const char *pJsonString, uint32_t JsonStringDataLen, jsonStruct_t *pContext) {
00225     
00226     INFO("LED Callback Detected.");
00227     
00228     if (pContext != NULL) {
00229         switch (*(unsigned char *)(pContext->pData)){   
00230             case COLOR_OFF:
00231                 INFO("LED -> OFF (%d)", *(unsigned char *)(pContext->pData));
00232                 break;
00233             case COLOR_RED:
00234                 INFO("LED -> RED (%d)", *(unsigned char *)(pContext->pData));
00235                 break;
00236             case COLOR_GREEN:
00237                 INFO("LED -> GREEN (%d)", *(unsigned char *)(pContext->pData));
00238                 break;
00239             case COLOR_BLUE:
00240                 INFO("LED -> BLUE (%d)", *(unsigned char *)(pContext->pData));
00241                 break;
00242             case COLOR_WHITE:
00243                 INFO("LED -> WHITE (%d)", *(unsigned char *)(pContext->pData));
00244                 break;    
00245         }
00246     }
00247     else {
00248         INFO("pContext was detected as NULL");
00249     }
00250 }
00251  
00252 //*********************************************************************************************************************
00253 //* Subscribe callback (used with alternate demo)
00254 //*********************************************************************************************************************
00255 int MQTTcallbackHandler(MQTTCallbackParams params) {
00256 
00257     INFO("Subscribe callback");
00258     INFO("%.*s\t%.*s",
00259             (int)params.TopicNameLen, params.pTopicName,
00260             (int)params.MessageParams.PayloadLen, (char*)params.MessageParams.pPayload);
00261 
00262     return 0;
00263 }
00264 
00265 //*********************************************************************************************************************
00266 //* Disconnect handling (used with alternate demo)
00267 //*********************************************************************************************************************
00268 void disconnectCallbackHandler(void) {
00269     WARN("MQTT Disconnect");
00270     IoT_Error_t rc = NONE_ERROR;
00271     if(aws_iot_is_autoreconnect_enabled()){
00272         INFO("Auto Reconnect is enabled, Reconnecting attempt will start now");
00273     }else{
00274         WARN("Auto Reconnect not enabled. Starting manual reconnect...");
00275         rc = aws_iot_mqtt_attempt_reconnect();
00276         if(RECONNECT_SUCCESSFUL == rc){
00277             WARN("Manual Reconnect Successful");
00278         }else{
00279             WARN("Manual Reconnect Failed - %d", rc);
00280         }
00281     }
00282 }
00283 
00284 //=====================================================================================================================
00285 //
00286 // Out-of-Box Demo: This function is used as part of the binary that comes with the Starter Kit.  Instead of using an
00287 //                  AWS device shadow, it publishes to an AWS Rule. The Rule is setup to store data to a DynamoDB, and
00288 //                  the demo S3 website pulls that data from the DynamoDB and displays it.
00289 //
00290 //=====================================================================================================================
00291 int outOfBoxDemo() {
00292     INFO("Running Out-of-Box Function (alternate demo).");
00293     
00294     IoT_Error_t rc = NONE_ERROR;
00295     int32_t i = 0;
00296     int publishCount = 0;
00297     bool infinitePublishFlag = true;
00298     char cPayload[100];
00299     char cTopic[100];
00300     const string colorStrings[] = {"Off", "Red", "Green", "", "Blue", "", "", "White"};
00301     float updateInterval = 1.0; // seconds
00302 
00303     MQTTConnectParams connectParams = MQTTConnectParamsDefault;
00304     connectParams.KeepAliveInterval_sec = 10;
00305     connectParams.isCleansession = true;
00306     connectParams.MQTTVersion = MQTT_3_1_1;
00307     connectParams.pClientID = iccidName;  // Using ICCID for unique Client ID
00308     connectParams.pHostURL = HostAddress;
00309     connectParams.port = port;
00310     connectParams.isWillMsgPresent = false;
00311     connectParams.pRootCALocation = AWS_IOT_ROOT_CA_FILENAME;
00312     connectParams.pDeviceCertLocation = AWS_IOT_CERTIFICATE_FILENAME;
00313     connectParams.pDevicePrivateKeyLocation = AWS_IOT_PRIVATE_KEY_FILENAME;
00314     connectParams.mqttCommandTimeout_ms = 10000;
00315     connectParams.tlsHandshakeTimeout_ms = 10000;
00316     connectParams.isSSLHostnameVerify = true; // ensure this is set to true for production
00317     connectParams.disconnectHandler = disconnectCallbackHandler;
00318 
00319     INFO("Connecting...");
00320     rc = aws_iot_mqtt_connect(&connectParams);
00321     if (NONE_ERROR != rc) {
00322         ERROR("Error(%d) connecting to %s:%d", rc, connectParams.pHostURL, connectParams.port);
00323     }
00324     
00325     /*
00326      * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h
00327      *  #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL
00328      *  #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL
00329      */
00330     INFO("Set Auto Reconnect...");
00331     rc = aws_iot_mqtt_autoreconnect_set_status(true);
00332     if (NONE_ERROR != rc) {
00333         ERROR("Unable to set Auto Reconnect to true - %d", rc);
00334         return rc;
00335     }
00336 
00337     // Comment this in if you want to subscribe
00338     /*MQTTSubscribeParams subParams = MQTTSubscribeParamsDefault;
00339     subParams.mHandler = MQTTcallbackHandler;
00340     subParams.pTopic = "sdkTest/sub";
00341     subParams.qos = QOS_0;
00342 
00343     if (NONE_ERROR == rc) {
00344         INFO("Subscribing...");
00345         rc = aws_iot_mqtt_subscribe(&subParams);
00346         if (NONE_ERROR != rc) {
00347             ERROR("Error subscribing");
00348         }
00349     }*/
00350 
00351     // Initializ the payload
00352     MQTTMessageParams Msg = MQTTMessageParamsDefault;
00353     Msg.qos = QOS_0;
00354     Msg.pPayload = (void *) cPayload;
00355 
00356     MQTTPublishParams Params = MQTTPublishParamsDefault;
00357     
00358     // Sets up the topic to publish to
00359     sprintf(cTopic, AWS_IOT_MY_TOPIC, iccidName);
00360     Params.pTopic = cTopic;
00361 
00362     if (publishCount != 0) {
00363         infinitePublishFlag = false;
00364     }
00365       
00366     INFO("READY TO PUBLISH! Press SW3 button to publish current data.");
00367     while ((NETWORK_ATTEMPTING_RECONNECT == rc || RECONNECT_SUCCESSFUL == rc || NONE_ERROR == rc)
00368             && (publishCount > 0 || infinitePublishFlag)) {
00369 
00370         // Max time the yield function will wait for read messages
00371         rc = aws_iot_mqtt_yield(100);
00372         if(NETWORK_ATTEMPTING_RECONNECT == rc){
00373             INFO("--> sleep (attempting to reconnect)");
00374             wait(1);
00375             // If the client is attempting to reconnect we will skip the rest of the loop.
00376             continue;
00377         }
00378         
00379         // Whenever the software button (SW3) is pressed the LED will changes color and this will
00380         // trigger a publish to the AWS topic specified.
00381         if (buttonOverride) {
00382             buttonOverride = false;
00383             
00384             // Get temp/humidity values
00385             temperature = CTOF(hts221.readTemperature());
00386             humidity = hts221.readHumidity();
00387     
00388             // Loading data into JSON format
00389             sprintf(cPayload, "{\"color\":\"%s\",\"temperature\":%f,\"humidity\":%d}", colorStrings[ledColor], temperature, humidity);
00390             Msg.PayloadLen = strlen(cPayload) + 1;
00391             Params.MessageParams = Msg;
00392             
00393             // Publish
00394             rc = aws_iot_mqtt_publish(&Params);
00395             if (publishCount > 0) {
00396                 publishCount--;
00397             }
00398                       
00399             printData();
00400             INFO("--> Update sent. Sleep for %f seconds", updateInterval);
00401             wait(updateInterval-.02);
00402         }
00403         else {
00404             wait(.3); // 300 ms
00405         }
00406     }
00407 
00408     if (NONE_ERROR != rc) {
00409         ERROR("An error occurred in the loop.\n");
00410     } else {
00411         INFO("Publish done\n");
00412     }
00413 
00414     return rc;
00415 }
00416 
00417 //=====================================================================================================================
00418 //
00419 // Main
00420 //
00421 //=====================================================================================================================
00422 int main() {
00423     
00424     // Set baud rate for PC Serial
00425     pc.baud(115200);
00426     INFO("Hello World from AT&T IoT Start Kit demo!");
00427               
00428     int i;          
00429     IoT_Error_t rc = NONE_ERROR;  
00430     char JsonDocumentBuffer[MAX_LENGTH_OF_UPDATE_JSON_BUFFER];
00431     size_t sizeOfJsonDocumentBuffer = sizeof(JsonDocumentBuffer) / sizeof(JsonDocumentBuffer[0]);
00432 
00433     // JSON struct for LED control
00434     jsonStruct_t ledController;
00435     ledController.cb = ledControl_Callback;
00436     ledController.pData = &ledColor;
00437     ledController.pKey = "ledColor";
00438     ledController.type = SHADOW_JSON_UINT8;
00439 
00440     // JSON struct for temperature\humidity readings
00441     jsonStruct_t temperatureHandler;
00442     temperatureHandler.cb = NULL;
00443     temperatureHandler.pKey = "temperature";
00444     temperatureHandler.pData = &temperature;
00445     temperatureHandler.type = SHADOW_JSON_FLOAT;
00446     
00447     jsonStruct_t humidityHandler;
00448     humidityHandler.cb = NULL;
00449     humidityHandler.pKey = "humidity";
00450     humidityHandler.pData = &humidity;
00451     humidityHandler.type = SHADOW_JSON_INT16;
00452     
00453     INFO("AWS IoT SDK Version(dev) %d.%d.%d-%s", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG);
00454 
00455 #ifdef USING_SD_CARD
00456     // Paths for certs from SD card
00457     INFO("Using SD card files for AWS config.");  
00458     DEBUG("- mqtt config path: %s", AWS_MQTT_CONFIG_FILENAME);
00459     DEBUG("- rootCA path: %s", AWS_IOT_ROOT_CA_FILENAME);
00460     DEBUG("- clientCRT path: %s", AWS_IOT_CERTIFICATE_FILENAME);
00461     DEBUG("- clientKey path: %s", AWS_IOT_PRIVATE_KEY_FILENAME);
00462 #else
00463     INFO("Using #defines in aws_iot_config.h and certs from certs.cpp for AWS config.");      
00464 #endif
00465     
00466     // Startup signal - blinks through RGBW then turns off
00467     SetLedColor(COLOR_RED);
00468     wait(.5);
00469     SetLedColor(COLOR_GREEN);
00470     wait(.5);
00471     SetLedColor(COLOR_BLUE);
00472     wait(.5);
00473     SetLedColor(COLOR_WHITE);
00474     wait(.5);
00475     SetLedColor(COLOR_OFF);
00476     
00477     // Initialize sensors
00478     INFO("Init sensors...");
00479     void hts221_init(void);
00480     i = hts221.begin();  
00481     if(!i) {
00482         WARN(RED "HTS221 NOT DETECTED!!\n\r");
00483     }
00484       
00485     // Setup SW3 button to falling edge interrupt
00486     INFO("Init interrupts...");
00487     Interrupt.fall(&sw3ButtonHandler);
00488       
00489     // Boot the Avnet Shield before any other operations
00490     INFO("Net Boot...");
00491     net_modem_boot();
00492     
00493     //==========================================================================
00494     // NOTE:  You can comment in the following line for an alternate demo that
00495     // is used as the out-of-box demo binary that comes with the  AT&T IoT 
00496     // Starter Kit.  It loops instead of the rest of Main()
00497     //return outOfBoxDemo();
00498     //==========================================================================
00499           
00500     // Intialize MQTT/Cert parameters
00501     ShadowParameters_t sp = ShadowParametersDefault;
00502 #ifdef USING_SD_CARD
00503     rc = (IoT_Error_t)mbedtls_mqtt_config_parse_file(&sp, AWS_MQTT_CONFIG_FILENAME);
00504     if (NONE_ERROR != rc) {
00505         ERROR("Failed to initialize mqtt parameters %d", rc);
00506         return rc;
00507     }   
00508     sp.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME;
00509     sp.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME;
00510     sp.pRootCA = AWS_IOT_ROOT_CA_FILENAME;
00511 #else
00512     sp.pMyThingName = AWS_IOT_MY_THING_NAME;
00513     sp.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID;
00514     sp.pHost = HostAddress;
00515     sp.port = port;
00516     
00517     sp.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME;
00518     sp.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME;
00519     sp.pRootCA = AWS_IOT_ROOT_CA_FILENAME;
00520 #endif
00521           
00522     INFO("Initialize the MQTT client...");
00523     MQTTClient_t mqttClient;
00524     aws_iot_mqtt_init(&mqttClient);
00525 
00526     INFO("Shadow Init...");
00527     rc = aws_iot_shadow_init(&mqttClient);
00528     if (NONE_ERROR != rc) {
00529         ERROR("Shadow Init Error %d", rc);
00530         return rc;
00531     }
00532     
00533     INFO("Shadow Connect...");   
00534     rc = aws_iot_shadow_connect(&mqttClient, &sp);
00535     if (NONE_ERROR != rc) {
00536         ERROR("Shadow Connection Error %d", rc);
00537         return rc;
00538     }
00539 
00540     // Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h
00541     // #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL
00542     // #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL
00543     rc = mqttClient.setAutoReconnectStatus(true);
00544     if (NONE_ERROR != rc) {
00545         ERROR("Unable to set Auto Reconnect to true - %d", rc);
00546         return rc;
00547     }
00548     
00549     // Example line of how to delete a shadow (not used in this demo)
00550     //aws_iot_shadow_delete(&mqttClient, AWS_IOT_MY_THING_NAME, ShadowUpdateStatusCallback, NULL, 8, true);
00551 
00552     INFO("Shadow Register Delta...");
00553     rc = aws_iot_shadow_register_delta(&mqttClient, &ledController);
00554     if (NONE_ERROR != rc) {
00555         ERROR("Shadow Register Delta Error");
00556         return rc;
00557     }
00558     
00559     INFO("Will attempt to sync with device shadow every %f seconds.", SHADOW_SYNC_INTERVAL);
00560     // Loop and publish changes from the FRDM board
00561     while (NETWORK_ATTEMPTING_RECONNECT == rc || RECONNECT_SUCCESSFUL == rc || NONE_ERROR == rc) {
00562         
00563         // Looks for incoming socket messages
00564         rc = aws_iot_shadow_yield(&mqttClient, 200);
00565         if (NETWORK_ATTEMPTING_RECONNECT == rc) {
00566             // If the client is attempting to reconnect we will skip the rest of the loop.
00567             INFO("Attempting to reconnect...");
00568             wait(1);
00569             continue;
00570         }
00571         
00572         // Read sensor data
00573         temperature = CTOF(hts221.readTemperature());
00574         humidity = hts221.readHumidity();
00575                                 
00576         INFO("\n=======================================================================================\n");             
00577         // Initialize JSON shadow document          
00578         rc = aws_iot_shadow_init_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer);
00579         if (rc == NONE_ERROR) {
00580             
00581             // If there has been a SW3 button press update the 'desired' color
00582             if (buttonOverride) {
00583                 rc = aws_iot_shadow_add_desired(JsonDocumentBuffer, sizeOfJsonDocumentBuffer, 1, &ledController);               
00584                 buttonOverride = false;
00585             }
00586                   
00587             // Updates the 'reported' color/temp/humidity
00588             rc = aws_iot_shadow_add_reported(JsonDocumentBuffer, sizeOfJsonDocumentBuffer, 3, &ledController,
00589                                                                                               &temperatureHandler,
00590                                                                                               &humidityHandler);
00591                  
00592             if (rc == NONE_ERROR) {               
00593                 rc = aws_iot_finalize_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer);   
00594                             
00595                 if (rc == NONE_ERROR) {
00596                     INFO("Update Shadow: %s", JsonDocumentBuffer);
00597                     rc = aws_iot_shadow_update(&mqttClient, sp.pMyThingName, JsonDocumentBuffer,
00598                             ShadowUpdateStatusCallback, NULL, 8, true);
00599                 }
00600             }
00601         }  
00602         
00603         // Print data    
00604         printData();
00605         INFO("*****************************************************************************************");
00606          
00607         // Set the LED color    
00608         SetLedColor(ledColor);
00609         wait(SHADOW_SYNC_INTERVAL);
00610     }
00611 
00612     if (NONE_ERROR != rc) {
00613         ERROR("An error occurred in the loop %d", rc);
00614     }
00615 
00616     INFO("Disconnecting");
00617     rc = aws_iot_shadow_disconnect(&mqttClient);
00618 
00619     if (NONE_ERROR != rc) {
00620         ERROR("Disconnect error %d", rc);
00621     }
00622 
00623     return rc;   
00624 }