Raghu Tirumala / Mbed OS ATT_IoT_Project

Dependencies:   BufferedSoftSerial SDFileSystem

Fork of ATT_AWS_IoT_demo by AT&T IoT

main.cpp

Committer:
RaghuT
Date:
2017-08-01
Revision:
30:d2a7e413f658
Parent:
29:319446cd2880
Child:
32:acf84c7d0075

File content as of revision 30:d2a7e413f658:

#include <cstdlib>
#include "mbed.h"

// Serial extension
#include "MODSERIAL.h"
#include "SoftSerial.h"
#include "BufferedSoftSerial.h"

// Network includes
#include "WNCInterface.h"
#include "network_interface.h"
#include "WncControllerK64F/WncController/WncController.h"

// AWS includes
#include "aws_iot_log.h"
#include "aws_iot_version.h"
#include "aws_iot_shadow_interface.h"
#include "aws_iot_shadow_json_data.h"
#include "aws_iot_config.h"
#include "aws_iot_mqtt_interface.h"

#if DEBUG_LEVEL > 0
#include "mbedtls/debug.h"
#endif

//=====================================================================================================================
//
// Defines
//
//=====================================================================================================================
// LED Colors
#define COLOR_OFF    0x00
#define COLOR_RED    0x01
#define COLOR_GREEN  0x02
#define COLOR_BLUE   0x04
#define COLOR_WHITE  0x07
#define NUM_COLORS   5

// AWS defines
#define PATH_MAX    1024
#define MAX_LENGTH_OF_UPDATE_JSON_BUFFER 500 // NOTE: Be wary of this if your JSON doc grows
#define SHADOW_SYNC_INTERVAL 3.0             // How often we sync with AWS Shadow (in seconds)

// Comment out the following line if color is not supported on the terminal
//#define USE_COLOR
#ifdef USE_COLOR
#define BLK "\033[30m"
#define RED "\033[31m"
#define GRN "\033[32m"
#define YEL "\033[33m"
#define BLU "\033[34m"
#define MAG "\033[35m"
#define CYN "\033[36m"
#define WHT "\033[37m"
#define DEF "\033[39m"
#else
#define BLK
#define RED
#define GRN
#define YEL
#define BLU
#define MAG
#define CYN
#define WHT
#define DEF
#endif

// Sensor defines
#define CTOF(x)  ((x)*1.8+32) // Temperature

//=====================================================================================================================
//
// Globals
//
//=====================================================================================================================
// Controls LED color
unsigned char ledColor = COLOR_OFF;

// These defines are pulled from aws_iot_config.h
char HostAddress[255] = AWS_IOT_MQTT_HOST;
char MqttClientID[32] = AWS_IOT_MQTT_CLIENT_ID;
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;
float   humidity    = 0.0;
char *slaveData = "";

//Cell signal
int signalQuality = 0;

//Variable to store data usage
int dataUsage = 0;

//slave JSON to publish
string slaveJSON = "";

//=====================================================================================================================
//
// Devices
//
//=====================================================================================================================
// GPIOs for RGB LED
DigitalOut led_green(LED_GREEN);
DigitalOut led_red(LED_RED);
DigitalOut led_blue(LED_BLUE);

// USB Serial port (to PC)
MODSERIAL pc(USBTX,USBRX,256,256);

// radio serial
BufferedSoftSerial radio(PTC4, PTA2);

// I2C bus (SDA, SCL)
I2C i2c(PTC11, PTC10);

//=====================================================================================================================
//
// Functions
//
//=====================================================================================================================
//*********************************************************************************************************************
//* Prints the given format to the PC serial port.  Exposed to all files via aws_iot_log.h
//*********************************************************************************************************************
void pc_print(const char * format, ...)
{
    va_list vl;
    va_start(vl, format);
    pc.vprintf(format, vl);
    va_end(vl);
}

//*********************************************************************************************************************
//* Set the RGB LED's Color
//* LED Color 0=Off to 7=White.  3 bits represent BGR (bit0=Red, bit1=Green, bit2=Blue)
//*********************************************************************************************************************
void SetLedColor(unsigned char ucColor)
{
    //Note that when an LED is on, you write a 0 to it:
    led_red = !(ucColor & 0x1); //bit 0
    led_green = !(ucColor & 0x2); //bit 1
    led_blue = !(ucColor & 0x4); //bit 2
}

//=====================================================================================================================
//
// AWS Shadow Callbacks
//
//=====================================================================================================================
//*********************************************************************************************************************
//* This is the callback function that fires when an update is sent.  It will print the update response status.
//*********************************************************************************************************************
void ShadowUpdateStatusCallback(const char *pThingName, ShadowActions_t action, Shadow_Ack_Status_t status,
                                const char *pReceivedJsonDocument, void *pContextData)
{

    INFO("Shadow Update Status Callback");

    if (status == SHADOW_ACK_TIMEOUT) {
        INFO("Update Timeout--");
    } else if (status == SHADOW_ACK_REJECTED) {
        INFO("Update RejectedXX");
    } else if (status == SHADOW_ACK_ACCEPTED) {
        INFO("Update Accepted!!"); // Good
    }
}

//*********************************************************************************************************************
//* These are the callback functions that fire when AWS has sends out a shadow update.
//*********************************************************************************************************************
void ledControl_Callback(const char *pJsonString, uint32_t JsonStringDataLen, jsonStruct_t *pContext)
{

    INFO("LED Callback Detected.");

    if (pContext != NULL) {
        switch (*(unsigned char *)(pContext->pData)) {
            case COLOR_OFF:
                INFO("LED -> OFF (%d)", *(unsigned char *)(pContext->pData));
                break;
            case COLOR_RED:
                INFO("LED -> RED (%d)", *(unsigned char *)(pContext->pData));
                break;
            case COLOR_GREEN:
                INFO("LED -> GREEN (%d)", *(unsigned char *)(pContext->pData));
                break;
            case COLOR_BLUE:
                INFO("LED -> BLUE (%d)", *(unsigned char *)(pContext->pData));
                break;
            case COLOR_WHITE:
                INFO("LED -> WHITE (%d)", *(unsigned char *)(pContext->pData));
                break;
        }
    } else {
        INFO("pContext was detected as NULL");
    }
}
//Callback when dataUsage stats are updated
void dataUsageCallback(const char *pJsonString, uint32_t JsonStringDataLen, jsonStruct_t *pContext)
{
    INFO("Data usage callback detected");
}
//*********************************************************************************************************************
//* 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);
        }
    }
}

//*********************************************************************************************************************
//* Get slave data over uart interface
//*********************************************************************************************************************
void getSlaveJSON()
{
    slaveJSON.clear();
    if(radio.writeable()) {
        radio.printf("d");
        while(radio.readable()) {
            slaveJSON += radio.getc();
        }
    }
    sprintf(slaveData, slaveJSON.c_str());
}

//=====================================================================================================================
//
// Main
//
//=====================================================================================================================
int main()
{
    // Set baud rate for PC Serial
    pc.baud(115200);
    radio.baud(9600);
    INFO("Program Start");

    IoT_Error_t rc = NONE_ERROR;
    char JsonDocumentBuffer[MAX_LENGTH_OF_UPDATE_JSON_BUFFER];
    size_t sizeOfJsonDocumentBuffer = sizeof(JsonDocumentBuffer) / sizeof(JsonDocumentBuffer[0]);

    //JSON struct for signal strength readings
    jsonStruct_t signalStrengthHandler;
    signalStrengthHandler.cb = NULL;
    signalStrengthHandler.pKey = "Signal Strength";
    signalStrengthHandler.pData = &signalQuality;
    signalStrengthHandler.type = SHADOW_JSON_INT16;

    //JSON struct for data usage
    jsonStruct_t dataUsageHandler;
    dataUsageHandler.cb = dataUsageCallback;
    dataUsageHandler.pKey = "Data Usage";
    dataUsageHandler.pData = &dataUsage;
    dataUsageHandler.type = SHADOW_JSON_UINT32;
    
    //JSON struct for slave data
    jsonStruct_t slaveDataHandler;
    slaveDataHandler.cb = NULL;
    slaveDataHandler.pKey = "slaves";
    slaveDataHandler.pData = slaveData;
    slaveDataHandler.type = SHADOW_JSON_STRING;
    
    INFO("AWS IoT SDK Version(dev) %d.%d.%d-%s", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG);


    INFO("Using #defines in aws_iot_config.h and certs from certs.cpp for AWS config.");

    // Startup signal - blinks through RGBW then turns off
    SetLedColor(COLOR_RED);
    wait(.5);
    SetLedColor(COLOR_GREEN);
    wait(.5);
    SetLedColor(COLOR_BLUE);
    wait(.5);
    SetLedColor(COLOR_WHITE);
    wait(.5);
    SetLedColor(COLOR_OFF);

    // Boot the Avnet Shield before any other operations
    INFO("Net Boot...");
    net_modem_boot();
    
    // Intialize MQTT/Cert parameters
    ShadowParameters_t sp = ShadowParametersDefault;
#ifdef USING_SD_CARD
    rc = (IoT_Error_t)mbedtls_mqtt_config_parse_file(&sp, AWS_MQTT_CONFIG_FILENAME);
    if (NONE_ERROR != rc) {
        ERROR("Failed to initialize mqtt parameters %d", rc);
        return rc;
    }
    sp.pClientCRT = AWS_IOT_CERTIFICATE_FILENAME;
    sp.pClientKey = AWS_IOT_PRIVATE_KEY_FILENAME;
    sp.pRootCA = AWS_IOT_ROOT_CA_FILENAME;
#else
    sp.pMyThingName = AWS_IOT_MY_THING_NAME;
    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...");
    MQTTClient_t mqttClient;
    aws_iot_mqtt_init(&mqttClient);

    INFO("Shadow Init...");
    rc = aws_iot_shadow_init(&mqttClient);
    if (NONE_ERROR != rc) {
        ERROR("Shadow Init Error %d", rc);
        return rc;
    }

    INFO("Shadow Connect...");
    rc = aws_iot_shadow_connect(&mqttClient, &sp);
    if (NONE_ERROR != rc) {
        ERROR("Shadow Connection Error %d", rc);
        return rc;
    }

    // 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

    rc = mqttClient.setAutoReconnectStatus(true);
    if (NONE_ERROR != rc) {
        ERROR("Unable to set Auto Reconnect to true - %d", rc);
        return rc;
    }

    INFO("Shadow Register Delta...");
    rc = aws_iot_shadow_register_delta(&mqttClient, &dataUsageHandler);
    if (NONE_ERROR != rc) {
        ERROR("Shadow Register Delta dataUsage Error");
        return rc;
    }
    
    INFO("Will attempt to sync with device shadow every %f seconds.", SHADOW_SYNC_INTERVAL);
    // Loop and publish changes from the FRDM board
    while (NETWORK_ATTEMPTING_RECONNECT == rc || RECONNECT_SUCCESSFUL == rc || NONE_ERROR == rc) {
        // Looks for incoming socket messages
        rc = aws_iot_shadow_yield(&mqttClient, 200);
        if (NETWORK_ATTEMPTING_RECONNECT == rc) {
            // If the client is attempting to reconnect we will skip the rest of the loop.
            INFO("Attempting to reconnect...");
            wait(1);
            continue;
        }
        //Read signal quality
        signalQuality = WNCInterface::_pwnc->getDbmRssi();
        //get slave data
        getSlaveJSON();
        INFO("\n=======================================================================================\n");
        // Initialize JSON shadow document
        rc = aws_iot_shadow_init_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer);
        if (rc == NONE_ERROR) {

            // Updates the 'reported' color/temp/humidity
            rc = aws_iot_shadow_add_reported(JsonDocumentBuffer, sizeOfJsonDocumentBuffer, 3, &signalStrengthHandler,
                                             &dataUsageHandler, &slaveDataHandler);

            if (rc == NONE_ERROR) {
                rc = aws_iot_finalize_json_document(JsonDocumentBuffer, sizeOfJsonDocumentBuffer);

                if (rc == NONE_ERROR) {
                    INFO("Update Shadow: %s", JsonDocumentBuffer);
                    rc = aws_iot_shadow_update(&mqttClient, sp.pMyThingName, JsonDocumentBuffer,
                                               ShadowUpdateStatusCallback, NULL, 15, true);
                }
            }
        }
        wait(SHADOW_SYNC_INTERVAL);
    }

    if (NONE_ERROR != rc) {
        ERROR("An error occurred in the loop %d", rc);
    }

    INFO("Disconnecting");
    rc = aws_iot_shadow_disconnect(&mqttClient);

    if (NONE_ERROR != rc) {
        ERROR("Disconnect error %d", rc);
    }

    return rc;
}