Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: NVIC_set_all_priorities mbed cc3000_hostdriver_mbedsocket TEMT6200 TSI Wi-Go_eCompass_Lib_V3 WiGo_BattCharger
Webserver/run_exosite.cpp
- Committer:
- frankvnk
- Date:
- 2013-12-01
- Revision:
- 4:8f8d0d19e6f1
File content as of revision 4:8f8d0d19e6f1:
/*****************************************************************************
*
*  demo.c - CC3000 Main Demo Application
*  Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*    Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*
*    Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the   
*    distribution.
*
*    Neither the name of Texas Instruments Incorporated nor the names of
*    its contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#include "run_exosite.h"
#include "Wi-Go_eCompass_Lib_V3.h"
#include "mbed.h"
#include "defLED.h"
#include "strlib.h"
extern DigitalOut ledr;
extern DigitalOut ledg;
extern DigitalOut ledb;
extern DigitalOut led1;
extern DigitalOut led2;
extern DigitalOut led3;
// local defines
#define WRITE_INTERVAL 5
#define EXO_BUFFER_SIZE 300 //reserve 300 bytes for our output buffer
typedef struct
{
    float *p;
    char *s;
} exo_data_ft;
typedef struct
{
    int16_t *p;
    char *s;
} exo_data_it;
//extern tUserFS user_info;
extern char requestBuffer[];
extern unsigned int compass_type, seconds;
char exo_meta[META_SIZE];
#define RX_SIZE 60
#define MAC_LEN 6
typedef enum
{
    CIK_LINE,
    HOST_LINE,
    CONTENT_LINE,
    ACCEPT_LINE,
    LENGTH_LINE,
    GETDATA_LINE,
    POSTDATA_LINE,
    VENDOR_LINE,
    EMPTY_LINE
} lineTypes;
#define STR_CIK_HEADER "X-Exosite-CIK: c3c675e0601551c6d4d3230e162d62cc8bba3311\r\n"
#define STR_CONTENT_LENGTH "Content-Length: "
#define STR_GET_URL "GET /api:v1/stack/alias?"
#define STR_HTTP "  HTTP/1.1\r\n"
#define STR_HOST "Host: avnet.m2.exosite.com\r\n"
#define STR_ACCEPT "Accept: application/x-www-form-urlencoded; charset=utf-8\r\n"
#define STR_CONTENT "Content-Type: application/x-www-form-urlencoded; charset=utf-8\r\n"
#define STR_VENDOR "vendor=avnet&model=wigosmartconfig&sn="
#define STR_CRLF "\r\n"
#define MY_CIK "27b9684751332589be52c8e5819e7c438f7e7479"
char myCIK[] = "c3c675e0601551c6d4d3230e162d62cc8bba3311";
// local functions
void activate_device(TCPSocketConnection *socket);
int readResponse(TCPSocketConnection *socket, char * expectedCode);
long connect_to_exosite(TCPSocketConnection *socket);
void sendLine(TCPSocketConnection *socket, unsigned char LINE, char * payload);
void exosite_meta_write(unsigned char * write_buffer, unsigned short srcBytes, unsigned char element);
void exosite_meta_read(unsigned char * read_buffer, unsigned short destBytes, unsigned char element);
int Exosite_Write(TCPSocketConnection *socket, char * pbuf, unsigned char bufsize);
int Exosite_Read(char * palias, char * pbuf, unsigned char bufsize);
int Exosite_Init(TCPSocketConnection *socket);
// global variables
static unsigned char exositeWriteFailures = 0;
// exported functions
// externs
extern char *itoa(int n, char *s, int b);
extern axis6_t axis6;
extern int secondFlag;
extern int server_running;
/** \brief Definition of data packet to be sent by server */
unsigned char dataPacket[] = { '\r', 0xBE, 128, 128, 128, 70, 36, 0xEF };
char activeCIK[41];
exo_data_ft exo_fdata[] = {
        &axis6.fGax,    "acc_x=%f&",
        &axis6.fGay,    "acc_y=%f&",
        &axis6.fGaz,    "acc_z=%f&",
        &axis6.fUTmx,   "mag_x=%f&",
        &axis6.fUTmy,   "mag_y=%f&",
        &axis6.fUTmz,   "mag_z=%f&",    
        &axis6.q0,      "q_w=%f&",  
        &axis6.q1,      "q_x=%f&",  
        &axis6.q2,      "q_y=%f&",  
        &axis6.q3,      "q_z=%f&",  
        0, 0 };
exo_data_it exo_idata[] = {
        &axis6.roll,    "roll=%d&",
        &axis6.pitch,   "pitch=%d&",
        &axis6.yaw,     "yaw=%d&",
        &axis6.alt,     "alt=%d&",
        &axis6.temp,    "temp=%d&",
        &axis6.light,   "light=%d&",
        0, 0
};
    
//*****************************************************************************
//
//!  main
//!
//!  \param  None
//!
//!  \return none
//!
//!  \brief   The main loop is executed here
//
//*****************************************************************************
void run_exosite(TCPSocketConnection *socket)
{
    int value;
    exo_data_it *tsp;
    exo_data_ft *tspf;
    
    printf("\nConnecting to Exosite\n");
    //user_info.validCIK = 0; // uncomment this to force provisioning every time, only used for debug
    
    if(!user_info.validCIK)
    {
        printf("Activating Wi-Go System on Exosite\n");
        uint8_t myMAC[8];
        wifi.get_mac_address(myMAC);
        printf(" MAC address %02x:%02x:%02x:%02x:%02x:%02x \r\n \r\n", myMAC[0], myMAC[1], myMAC[2], myMAC[3], myMAC[4], myMAC[5]);
        wait_ms(100);
        printf("Enter the device MAC on your Exosite device portal to prepare\n");
        wait_ms(100);
        printf("the system for provisioning your Wi-Go system onto Exosite\n");
        wait_ms(100);
        printf("Hit any key to continue.....\n");
        getchar();
        Exosite_Init(socket);
    }
    
    for(value=0 ;value < CIK_LENGTH ; value++) activeCIK[value] = user_info.CIK[value];
    activeCIK[value] = NULL;
    // Main Loop
    while (1)
    {
        while(!secondFlag) /*__wfi()*/;
        secondFlag = 0;
        LED_D2_ON;
        // Build string
        requestBuffer[0] = 0;
        tsp     = &exo_idata[0];
        tspf    = &exo_fdata[0];
        while(tsp->p)
        {
            sprintf( requestBuffer + strlen(requestBuffer), tsp->s, *tsp->p);
            tsp++;
        }
        while(tspf->p)
        {
            sprintf( requestBuffer + strlen(requestBuffer), tspf->s, *tspf->p);
            tspf++;
        }
        sprintf( requestBuffer + strlen(requestBuffer), "time=%d\r\n", axis6.timestamp);
        if(strlen(requestBuffer) > 300) printf("Buffer size= %d too small!!!", strlen(requestBuffer));
        //printf("Buffer size= %d\n", strlen(requestBuffer));
        value = Exosite_Write(socket, requestBuffer, strlen(requestBuffer));    //write all sensor values to the cloud
        LED_D2_OFF; 
        if(value == -1)
        {
            LED_D3_OFF;
            wifi.stop();
            if (wifi.connect() == -1)
                printf("Failed to connect. Please verify connection details and try again. \r\n");
            else
            {
                printf("Connected - IP address: %s \r\n",wifi.getIPAddress());
                LED_D3_ON;
            }
        }
    }
}
//*****************************************************************************
//
//! Exosite_Init
//!
//!  \param  None
//!
//!  \return 0 success; -1 failure
//!
//!  \brief  The function initializes the cloud connection to Exosite
//
//*****************************************************************************
int Exosite_Init(TCPSocketConnection *socket)
{
    char strBuf[META_MARK_SIZE];
    const unsigned char meta_server_ip[6] = {173,255,209,28,0,80};
    uint8_t mac_status = 1;
    uint8_t myMAC[8];
    int i;
    char tempCIK[CIK_LENGTH];
    //check our meta mark - if it isn't there, we wipe the meta structure
    exosite_meta_read((unsigned char *)strBuf, META_MARK_SIZE, META_MARK);
    if (strncmp(strBuf, EXOMARK, META_MARK_SIZE))
    {
        memset(exo_meta, 0, META_SIZE); //erase the information currently in meta
        exosite_meta_write((unsigned char *)meta_server_ip, 6, META_SERVER);     //store server IP
        exosite_meta_write((unsigned char *)EXOMARK, META_MARK_SIZE, META_MARK); //store exosite mark
    }
    while(mac_status) mac_status = wifi.get_mac_address(myMAC);
    exosite_meta_write((unsigned char *)myMAC, 17, META_UUID);
    //setup some of our globals for operation
    exositeWriteFailures = 0;
    //exosite Re-init : Called after Init has been ran in the past, but maybe
    //                  comms were down and we have to keep trying...
    activate_device(socket);    //the moment of truth - can this device provision with the Exosite cloud?...
    exosite_meta_read((unsigned char *)tempCIK, CIK_LENGTH, META_CIK); //sanity check on the CIK
    for (i = 0; i < CIK_LENGTH; i++)
    {
        if (!(tempCIK[i] >= 'a' && tempCIK[i] <= 'f' || tempCIK[i] >= '0' && tempCIK[i] <= '9'))
        {
            return -1;
        }
    }
    for(i=0;i<CIK_LENGTH;i++) user_info.CIK[i] = tempCIK[i];
    user_info.validCIK = 1;
    wifi._nvmem.write( NVMEM_USER_FILE_1_FILEID, sizeof(user_info), 0, (unsigned char *) &user_info);
    return 0;
}
//*****************************************************************************
//
//! Exosite_Write
//!
//!  \param  pbuf - string buffer containing data to be sent
//!          bufsize - number of bytes to send
//!
//!  \return 0 success; -1 failure
//!
//!  \brief  The function writes data to Exosite
//
//*****************************************************************************
int Exosite_Write(TCPSocketConnection *socket, char * pbuf, unsigned char bufsize)
{
    char strBuf[10];
    long sock = -1;
    sock = connect_to_exosite(socket);
    if(sock == -1) return(sock);
// This is an example write POST...
//  s.send('POST /api:v1/stack/alias HTTP/1.1\r\n')
//  s.send('Host: m2.exosite.com\r\n')
//  s.send('X-Exosite-CIK: 5046454a9a1666c3acfae63bc854ec1367167815\r\n')
//  s.send('Content-Type: application/x-www-form-urlencoded; charset=utf-8\r\n')
//  s.send('Content-Length: 6\r\n\r\n')
//  s.send('temp=2')
    sprintf(strBuf, "%d", (int)bufsize); //make a string for length
    sendLine(socket, POSTDATA_LINE, "/onep:v1/stack/alias");
    sendLine(socket, HOST_LINE, NULL);
    sendLine(socket, CIK_LINE, NULL);
    sendLine(socket, CONTENT_LINE, NULL);
    sendLine(socket, LENGTH_LINE, strBuf);
    //printf("Data=%s\n", pbuf);
    socket->send_all(pbuf, bufsize); //alias=value
    wifi._event.hci_unsolicited_event_handler();
    if (0 == readResponse(socket, "204"))
    {
        exositeWriteFailures = 0;
    }
    else
    {
        exositeWriteFailures++;
    }
    socket->close();
    if (exositeWriteFailures > 5)
    {
        // sometimes transport connect works even if no connection...
        printf("ERROR %d\r\n", EXO_ERROR_WRITE);
    }
    if (!exositeWriteFailures)
    {
        //printf("ShowUIcode %d\n", EXO_CLIENT_RW);
        return 0; // success
    }
    return 0;
}    
//*****************************************************************************
//
//! activate_device
//!
//!  \param  none
//!
//!  \return none
//!
//!  \brief  Calls activation API - if successful, it saves the returned
//!          CIK to non-volatile
//
//*****************************************************************************
void activate_device(TCPSocketConnection *socket)
{
    long sock = -1;
    volatile int length;
    char strLen[5];
    while (sock < 0)
    sock = connect_to_exosite(socket);
    printf("Activating Device\n");
    length = strlen(STR_VENDOR) + META_UUID_SIZE;
    itoa(length, strLen, 10); //make a string for length
    sendLine(socket, POSTDATA_LINE, "/provision/activate");
    sendLine(socket, HOST_LINE, NULL);
    sendLine(socket, CONTENT_LINE, NULL);
    sendLine(socket, LENGTH_LINE, strLen);
    sendLine(socket, VENDOR_LINE, NULL);
    if (0 == readResponse(socket, "200"))
    {
        char strBuf[RX_SIZE];
        unsigned char strLen, len;
        char *p;
        unsigned char crlf = 0;
        unsigned char ciklen = 0;
        char NCIK[CIK_LENGTH];
        do
        {
            strLen = socket->receive(strBuf, RX_SIZE);
            len = strLen;
            p = strBuf;
            // Find 4 consecutive \r or \n - should be: \r\n\r\n
            while (0 < len && 4 > crlf)
            {
                if ('\r' == *p || '\n' == *p)
                {
                    ++crlf;
                }
                else
                {
                    crlf = 0;
                }
                ++p;
                --len;
            }
            // The body is the CIK
            if (0 < len && 4 == crlf && CIK_LENGTH > ciklen)
            {
                // TODO, be more robust - match Content-Length header value to CIK_LENGTH
                unsigned char need, part;
                need = CIK_LENGTH - ciklen;
                part = need < len ? need : len;
                strncpy(NCIK + ciklen, p, part);
                ciklen += part;
            }
        } while (RX_SIZE == strLen);
        if (CIK_LENGTH == ciklen)
        {
            exosite_meta_write((unsigned char *)NCIK, CIK_LENGTH, META_CIK);
        }
    }
    else
    {
        printf("Activation failed\n");
        getchar();
    }
    socket->close();
}
//*****************************************************************************
//
//! connect_to_exosite
//!
//!  \param  None
//!
//!  \return socket handle
//!
//!  \brief  Establishes a connection with the Exosite API server
//
//*****************************************************************************
long connect_to_exosite(TCPSocketConnection *socket)
{    
    static unsigned char connectRetries = 0;
    long sock;
    if (connectRetries++ > 5)
    {
        connectRetries = 0;
        printf("ERROR %d\r\n", EXO_ERROR_CONNECT);
    }
    const char* ECHO_SERVER_ADDRESS = "173.255.209.28"; //TODO - use DNS or check m2.exosite.com/ip to check for updates
    const int ECHO_SERVER_PORT = 80;
    
    unsigned char server[META_SERVER_SIZE];
    exosite_meta_read(server, META_SERVER_SIZE, META_SERVER);
    sock = socket->connect(ECHO_SERVER_ADDRESS, ECHO_SERVER_PORT);
    if(sock < 0)
    {
        printf("Connection to server failed\n");
        socket->close();
        wait_ms(200);
        return -1;
    }
    else
    {
        connectRetries = 0;
        //printf("ShowUIcode %d\n", EXO_SERVER_CONNECTED);
    }
    // Success
    //printf("success\n");
    return sock;
}
//*****************************************************************************
//
//! readResponse
//!
//!  \param  socket handle, pointer to expected HTTP response code
//!
//!  \return 0 if match, -1 if no match
//!
//!  \brief  Reads first 12 bytes of HTTP response and extracts the 3 byte code
//
//*****************************************************************************
int readResponse(TCPSocketConnection *socket, char * code)
{
    char rxBuf[12];
    unsigned char rxLen;
    rxLen = socket->receive(rxBuf, 12);
//PROBLEM : more than 12 chars are printed 
    printf("rec %s\n", rxBuf);
    if (12 == rxLen && code[0] == rxBuf[9] && code[1] == rxBuf[10] && code[2] == rxBuf[11])
    {
        return 0;
    }
    return -1;
}
//*****************************************************************************
//
//! sendLine
//!
//!  \param  Which line type
//!
//!  \return socket handle
//!
//!  \brief  Sends data out the socket
//
//*****************************************************************************
void sendLine(TCPSocketConnection *socket, unsigned char LINE, char * payload)
{
    char strBuf[80];
    unsigned char strLen = 0;
    switch(LINE)
    {
    case CIK_LINE:
        sprintf(strBuf, "X-Exosite-CIK: %s\r\n", activeCIK);    
        strLen = strlen(strBuf);
        //strLen = 57;
        //memcpy(strBuf,STR_CIK_HEADER,strLen);
        //exosite_meta_read((unsigned char *)&strBuf[strLen], CIK_LENGTH, META_CIK);
        //strLen += CIK_LENGTH;
        //memcpy(&strBuf[strLen],STR_CRLF, 2);
        //strLen += 2;
        break;
    case HOST_LINE:
        strLen = 28;
        memcpy(strBuf,STR_HOST,strLen);
        strBuf[strLen] = NULL;
        break;
    case CONTENT_LINE:
        strLen = 64;
        memcpy(strBuf,STR_CONTENT,strLen);
        strBuf[strLen] = NULL;
        break;
    case ACCEPT_LINE:
        strLen = 58;
        memcpy(strBuf,STR_ACCEPT,strLen);
        memcpy(&strBuf[strLen],payload, strlen(payload));
        strLen += strlen(payload);
        break;
    case LENGTH_LINE: // Content-Length: NN
        strLen = 16;
        memcpy(strBuf,STR_CONTENT_LENGTH,strLen);
        memcpy(&strBuf[strLen],payload, strlen(payload));
        strLen += strlen(payload);
        memcpy(&strBuf[strLen],STR_CRLF, 2);
        strLen += 2;
        memcpy(&strBuf[strLen],STR_CRLF, 2);
        strLen += 2;
        strBuf[strLen] = NULL;
        break;
    case GETDATA_LINE:
        strLen = 24;
        memcpy(strBuf,STR_GET_URL,strLen);
        memcpy(&strBuf[strLen],payload, strlen(payload));
        strLen += strlen(payload);
        memcpy(&strBuf[strLen],STR_HTTP, 12);
        strLen += 12;
        break;
    case VENDOR_LINE:
        strLen = strlen(STR_VENDOR);
        memcpy(strBuf, STR_VENDOR, strLen);
        exosite_meta_read((unsigned char *)&strBuf[strLen], META_UUID_SIZE, META_UUID);
        strLen += META_UUID_SIZE;
        strBuf[strLen] = NULL;
        break;
    case POSTDATA_LINE:
        strLen = 5;
        memcpy(strBuf,"POST ", strLen);
        memcpy(&strBuf[strLen],payload, strlen(payload));
        strLen += strlen(payload);
        memcpy(&strBuf[strLen],STR_HTTP, 12);
        strLen += 12;
        strBuf[strLen] = NULL;
        break;
    case EMPTY_LINE:
        strLen = 2;
        memcpy(strBuf,STR_CRLF,strLen);
        break;
    default:
        break;
    }
    //printf("sendLine: %s\n", strBuf);
    socket->send_all(strBuf, strLen);
    wifi._event.hci_unsolicited_event_handler();
    return;
}
//*****************************************************************************
//
//! exosite_meta_write
//!
//!  \param  write_buffer - string buffer containing info to write to meta;
//!          srcBytes - size of string in bytes; element - item from
//!          MetaElements enum.
//!
//!  \return None
//!
//!  \brief  Writes specific meta information to meta memory.
//
//*****************************************************************************
void exosite_meta_write(unsigned char * write_buffer, unsigned short srcBytes, unsigned char element)
{
    exosite_meta * meta_info = 0;
    //TODO - do not write if the data already there is identical...
    switch (element)
    {
        case META_CIK:
            if (srcBytes > META_CIK_SIZE) return;
            memcpy((char *)(exo_meta + (int)meta_info->cik), write_buffer, srcBytes); //store CIK
            break;
        case META_SERVER:
            if (srcBytes > META_SERVER_SIZE) return;
            memcpy((char *)(exo_meta + (int)meta_info->server), write_buffer, srcBytes); //store server IP
            break;
        case META_MARK:
            if (srcBytes > META_MARK_SIZE) return;
            memcpy((char *)(exo_meta + (int)meta_info->mark), write_buffer, srcBytes); //store exosite mark
            break;
        case META_UUID:
            if (srcBytes > META_UUID_SIZE) return;
            memcpy((char *)(exo_meta + (int)meta_info->uuid), write_buffer, srcBytes); //store UUID
            break;
        case META_MFR:
            if (srcBytes > META_MFR_SIZE) return;
            memcpy((char *)(exo_meta + (int)meta_info->mfr), write_buffer, srcBytes); //store manufacturing info
            break;
        case META_NONE:
        default:
            break;
    }
    return;
}
//*****************************************************************************
//
//! exosite_meta_read
//!
//!  \param  read_buffer - string buffer to receive element data; destBytes -
//!          size of buffer in bytes; element - item from MetaElements enum.
//!
//!  \return None
//!
//!  \brief  Writes specific meta information to meta memory.
//
//*****************************************************************************
void exosite_meta_read(unsigned char * read_buffer, unsigned short destBytes, unsigned char element)
{
    exosite_meta * meta_info = 0;
    switch (element)
    {
        case META_CIK:
            if (destBytes < META_CIK_SIZE) return;
            memcpy(read_buffer, (char *)(exo_meta + (int)meta_info->cik), destBytes); //read CIK
            break;
        case META_SERVER:
            if (destBytes < META_SERVER_SIZE) return;
            memcpy(read_buffer, (char *)(exo_meta + (int)meta_info->server), destBytes); //read server IP
            break;
        case META_MARK:
            if (destBytes < META_MARK_SIZE) return;
            memcpy(read_buffer, (char *)(exo_meta + (int)meta_info->mark), destBytes); //read exosite mark
            break;
        case META_UUID:
            if (destBytes < META_UUID_SIZE) return;
            memcpy(read_buffer, (char *)(exo_meta + (int)meta_info->uuid), destBytes); //read exosite mark
            break;
        case META_MFR:
            if (destBytes < META_MFR_SIZE) return;
            memcpy(read_buffer, (char *)(exo_meta + (int)meta_info->mfr), destBytes); //read exosite mark
            break;
        case META_NONE:
            default:
            break;
    }
    return;
}
            
     Avnet Wi-Go System
            Avnet Wi-Go System