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

Dependencies:   SDFileSystem

Fork of ATT_AWS_IoT_demo by Anthony Phillips

IoT Starter Kit Powered by AWS Demo

This program demonstrates the AT&T IoT Starter Kit sending data directly into AWS IoT. It's explained and used in the Getting Started with the IoT Starter Kit Powered by AWS on starterkit.att.com.

What's required

  • AT&T IoT LTE Add-on (also known as the Cellular Shield)
  • NXP K64F - for programming
  • microSD card - used to store your AWS security credentials
  • AWS account
  • Python, locally installed

If you don't already have an IoT Starter Kit, you can purchase a kit here. The IoT Starter Kit Powered by AWS includes the LTE cellular shield, K64F, and a microSD card.

Revision:
23:b9ff83dc965f
Parent:
20:ee34856ae510
Child:
24:224c07ec3bd0
--- a/main.cpp	Wed Dec 07 21:19:07 2016 +0000
+++ b/main.cpp	Thu Dec 15 18:05:09 2016 +0000
@@ -94,11 +94,15 @@
 char ThingName[32] = AWS_IOT_MY_THING_NAME;
 char PortString[5] = "8883";
 uint32_t port = AWS_IOT_MQTT_PORT;
+char iccidName[21] = "12345678901234567890";
 
 // Sensor data
 float temperature = 0.0;
 int   humidity    = 0;
 
+// Temp/humidity object
+HTS221 hts221; 
+
 //=====================================================================================================================
 //
 // Devices
@@ -166,6 +170,32 @@
     buttonOverride = true;
 }
 
+//*********************************************************************************************************************
+//* Print LED and sensor data
+//*********************************************************************************************************************
+void printData()
+{
+    INFO("Temperature is: %0.2f F", temperature);
+    INFO("Humidity    is: %02d", humidity);      
+    switch (ledColor) {
+         case COLOR_OFF:
+             INFO("LED: Off");
+             break;
+         case COLOR_RED:
+             INFO("LED: Red");
+             break;
+         case COLOR_GREEN:
+             INFO("LED: Green");
+             break;
+         case COLOR_BLUE:
+             INFO("LED: Blue");
+             break;
+         case COLOR_WHITE:
+             INFO("LED: White");
+             break;
+    }
+}
+
 //=====================================================================================================================
 //
 // AWS Shadow Callbacks
@@ -218,6 +248,171 @@
         INFO("pContext was detected as NULL");
     }
 }
+ 
+//*********************************************************************************************************************
+//* Subscribe callback (used with alternate demo)
+//*********************************************************************************************************************
+int MQTTcallbackHandler(MQTTCallbackParams params) {
+
+    INFO("Subscribe callback");
+    INFO("%.*s\t%.*s",
+            (int)params.TopicNameLen, params.pTopicName,
+            (int)params.MessageParams.PayloadLen, (char*)params.MessageParams.pPayload);
+
+    return 0;
+}
+
+//*********************************************************************************************************************
+//* Disconnect handling (used with alternate demo)
+//*********************************************************************************************************************
+void disconnectCallbackHandler(void) {
+    WARN("MQTT Disconnect");
+    IoT_Error_t rc = NONE_ERROR;
+    if(aws_iot_is_autoreconnect_enabled()){
+        INFO("Auto Reconnect is enabled, Reconnecting attempt will start now");
+    }else{
+        WARN("Auto Reconnect not enabled. Starting manual reconnect...");
+        rc = aws_iot_mqtt_attempt_reconnect();
+        if(RECONNECT_SUCCESSFUL == rc){
+            WARN("Manual Reconnect Successful");
+        }else{
+            WARN("Manual Reconnect Failed - %d", rc);
+        }
+    }
+}
+
+//=====================================================================================================================
+//
+// Out-of-Box Demo: This function is used as part of the binary that comes with the Starter Kit.  Instead of using an
+//                  AWS device shadow, it publishes to an AWS Rule. The Rule is setup to store data to a DynamoDB, and
+//                  the demo S3 website pulls that data from the DynamoDB and displays it.
+//
+//=====================================================================================================================
+int outOfBoxDemo() {
+    INFO("Running Out-of-Box Function (alternate demo).");
+    
+    IoT_Error_t rc = NONE_ERROR;
+    int32_t i = 0;
+    int publishCount = 0;
+    bool infinitePublishFlag = true;
+    char cPayload[100];
+    char cTopic[100];
+    const string colorStrings[] = {"Off", "Red", "Green", "", "Blue", "", "", "White"};
+    float updateInterval = 5.0; // seconds
+
+    MQTTConnectParams connectParams = MQTTConnectParamsDefault;
+    connectParams.KeepAliveInterval_sec = 10;
+    connectParams.isCleansession = true;
+    connectParams.MQTTVersion = MQTT_3_1_1;
+    connectParams.pClientID = iccidName;  // Using ICCID for unique Client ID
+    connectParams.pHostURL = HostAddress;
+    connectParams.port = port;
+    connectParams.isWillMsgPresent = false;
+    connectParams.pRootCALocation = AWS_IOT_ROOT_CA_FILENAME;
+    connectParams.pDeviceCertLocation = AWS_IOT_CERTIFICATE_FILENAME;
+    connectParams.pDevicePrivateKeyLocation = AWS_IOT_PRIVATE_KEY_FILENAME;
+    connectParams.mqttCommandTimeout_ms = 10000;
+    connectParams.tlsHandshakeTimeout_ms = 10000;
+    connectParams.isSSLHostnameVerify = true; // ensure this is set to true for production
+    connectParams.disconnectHandler = disconnectCallbackHandler;
+
+    INFO("Connecting...");
+    rc = aws_iot_mqtt_connect(&connectParams);
+    if (NONE_ERROR != rc) {
+        ERROR("Error(%d) connecting to %s:%d", rc, connectParams.pHostURL, connectParams.port);
+    }
+    
+    /*
+     * Enable Auto Reconnect functionality. Minimum and Maximum time of Exponential backoff are set in aws_iot_config.h
+     *  #AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL
+     *  #AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL
+     */
+    INFO("Set Auto Reconnect...");
+    rc = aws_iot_mqtt_autoreconnect_set_status(true);
+    if (NONE_ERROR != rc) {
+        ERROR("Unable to set Auto Reconnect to true - %d", rc);
+        return rc;
+    }
+
+    // Comment this in if you want to subscribe
+    /*MQTTSubscribeParams subParams = MQTTSubscribeParamsDefault;
+    subParams.mHandler = MQTTcallbackHandler;
+    subParams.pTopic = "sdkTest/sub";
+    subParams.qos = QOS_0;
+
+    if (NONE_ERROR == rc) {
+        INFO("Subscribing...");
+        rc = aws_iot_mqtt_subscribe(&subParams);
+        if (NONE_ERROR != rc) {
+            ERROR("Error subscribing");
+        }
+    }*/
+
+    // Initializ the payload
+    MQTTMessageParams Msg = MQTTMessageParamsDefault;
+    Msg.qos = QOS_0;
+    Msg.pPayload = (void *) cPayload;
+
+    MQTTPublishParams Params = MQTTPublishParamsDefault;
+    
+    // Sets up the topic to publish to
+    sprintf(cTopic, AWS_IOT_MY_TOPIC, iccidName);
+    Params.pTopic = cTopic;
+
+    if (publishCount != 0) {
+        infinitePublishFlag = false;
+    }
+      
+    INFO("READY TO PUBLISH! Press SW3 button to publish current data.");
+    while ((NETWORK_ATTEMPTING_RECONNECT == rc || RECONNECT_SUCCESSFUL == rc || NONE_ERROR == rc)
+            && (publishCount > 0 || infinitePublishFlag)) {
+
+        // Max time the yield function will wait for read messages
+        rc = aws_iot_mqtt_yield(100);
+        if(NETWORK_ATTEMPTING_RECONNECT == rc){
+            INFO("--> sleep (attempting to reconnect)");
+            wait(1);
+            // If the client is attempting to reconnect we will skip the rest of the loop.
+            continue;
+        }
+        
+        // Whenever the software button (SW3) is pressed the LED will changes color and this will
+        // trigger a publish to the AWS topic specified.
+        if (buttonOverride) {
+            buttonOverride = false;
+            
+            // Get temp/humidity values
+            temperature = CTOF(hts221.readTemperature());
+            humidity = hts221.readHumidity();
+    
+            // Loading data into JSON format
+            sprintf(cPayload, "{\"color\":\"%s\",\"temperature\":%f,\"humidity\":%d}", colorStrings[ledColor], temperature, humidity);
+            Msg.PayloadLen = strlen(cPayload) + 1;
+            Params.MessageParams = Msg;
+            
+            // Publish
+            rc = aws_iot_mqtt_publish(&Params);
+            if (publishCount > 0) {
+                publishCount--;
+            }
+                      
+            printData();
+            INFO("--> Update sent. Sleep for %f seconds", updateInterval);
+            wait(updateInterval-.02);
+        }
+        else {
+            wait(.3); // 300 ms
+        }
+    }
+
+    if (NONE_ERROR != rc) {
+        ERROR("An error occurred in the loop.\n");
+    } else {
+        INFO("Publish done\n");
+    }
+
+    return rc;
+}
 
 //=====================================================================================================================
 //
@@ -231,8 +426,7 @@
     INFO("Hello World from AT&T IoT Start Kit demo!");
               
     int i;          
-    IoT_Error_t rc = NONE_ERROR;
-    HTS221 hts221;  // Temp/humidity  
+    IoT_Error_t rc = NONE_ERROR;  
     char JsonDocumentBuffer[MAX_LENGTH_OF_UPDATE_JSON_BUFFER];
     size_t sizeOfJsonDocumentBuffer = sizeof(JsonDocumentBuffer) / sizeof(JsonDocumentBuffer[0]);
 
@@ -281,6 +475,7 @@
     SetLedColor(COLOR_OFF);
     
     // Initialize sensors
+    INFO("Init sensors...");
     void hts221_init(void);
     i = hts221.begin();  
     if(!i) {
@@ -288,11 +483,20 @@
     }
       
     // Setup SW3 button to falling edge interrupt
+    INFO("Init interrupts...");
     Interrupt.fall(&sw3ButtonHandler);
       
     // Boot the Avnet Shield before any other operations
+    INFO("Net Boot...");
     net_modem_boot();
-      
+    
+    //==========================================================================
+    // NOTE:  You can comment in the following line for an alternate demo that
+    // is used as the out-of-box demo binary that comes with the  AT&T IoT 
+    // Starter Kit.  It loops instead of the rest of Main()
+    //return outOfBoxDemo();
+    //==========================================================================
+          
     // Intialize MQTT/Cert parameters
     ShadowParameters_t sp = ShadowParametersDefault;
 #ifdef USING_SD_CARD
@@ -309,6 +513,10 @@
     sp.pMqttClientId = AWS_IOT_MQTT_CLIENT_ID;
     sp.pHost = HostAddress;
     sp.port = port;
+    
+    sp.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME;
+    sp.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME;
+    sp.pRootCA = AWS_IOT_ROOT_CA_FILENAME;
 #endif
           
     INFO("Initialize the MQTT client...");
@@ -372,17 +580,11 @@
             
             // If there has been a SW3 button press update the 'desired' color
             if (buttonOverride) {
-                rc = aws_iot_shadow_add_desired(JsonDocumentBuffer, sizeOfJsonDocumentBuffer, 1, &ledController);
-                //rc = aws_iot_shadow_add_desired(JsonDocumentBuffer, sizeOfJsonDocumentBuffer, 3, &ledController,
-                //                                                                                 &temperatureHandler,
-                //                                                                                 &humidityHandler);
+                rc = aws_iot_shadow_add_desired(JsonDocumentBuffer, sizeOfJsonDocumentBuffer, 1, &ledController);               
                 buttonOverride = false;
             }
                   
-            // Updates the 'reported' color
-            //rc = aws_iot_shadow_add_reported(JsonDocumentBuffer, sizeOfJsonDocumentBuffer, 1, &ledController);
-                
-            // TODO: format for adding temperature
+            // Updates the 'reported' color/temp/humidity
             rc = aws_iot_shadow_add_reported(JsonDocumentBuffer, sizeOfJsonDocumentBuffer, 3, &ledController,
                                                                                               &temperatureHandler,
                                                                                               &humidityHandler);
@@ -399,25 +601,7 @@
         }  
         
         // Print data    
-        INFO("Temperature is: %0.2f F", temperature);
-        INFO("Humidity    is: %02d", humidity);      
-        switch (ledColor) {
-             case COLOR_OFF:
-                 INFO("LED: OFF");
-                 break;
-             case COLOR_RED:
-                 INFO("LED: RED");
-                 break;
-             case COLOR_GREEN:
-                 INFO("LED: GREEN");
-                 break;
-             case COLOR_BLUE:
-                 INFO("LED: BLUE");
-                 break;
-             case COLOR_WHITE:
-                 INFO("LED: WHITE");
-                 break;
-        }
+        printData();
         INFO("*****************************************************************************************");
          
         // Set the LED color