A simple client that allows the user to send Json data to Axeda's IoT cloud using an SSL socket (with certificate verification).

Dependencies:   mbed

Only allows use of URLs, not IP addresses. Most CyaSSL errors are caused by incorrect certificates or failed certificate verification (188, 151, 155).

main.cpp

Committer:
Vanger
Date:
2015-01-19
Revision:
0:562ad81d9dd4
Child:
1:2d299b96dc79

File content as of revision 0:562ad81d9dd4:

#include "mbed.h"
#include "mtsas.h"

//Simple function that converts the HTTP result to a string
//Ex: Result is 0, the string result will be "HTTP_OK"
char * httpResToStr(HTTPResult res);

int main(){
    
    //Sets the log level to INFO, higher log levels produce more log output.
    //Possible levels: NONE, FATAL, ERROR, WARNING, INFO, DEBUG, TRACE
    MTSLog::setLogLevel(MTSLog::INFO_LEVEL);
    
    /**Root Certificate(s) of the remote server you want to connect to.
     * Make sure the certificates are in PEM format, contain \r\n to end each line,
     * and if using multiple root CA certificates, just make multiple calls to the addRootCACertificate
     * function for each root certificate you wish to add.
     */
    const char CERTIFICATES[] = "";
    /**Example certificate formatted correctly (length not to scale):
     -----BEGIN CERTIFICATE-----\r\n
     aosdfijaaosdfijaaosdfijaaosdfijaaosdfijaaosdfijaaosdfijaaosdfija\r\n
     afjklewijafliefhiszelifhlsfhilasihflihsalifhalhifliahlfihaslihfl\r\n
     fawefaewf==\r\n
     -----END CERTIFICATE-----\r\n
     */
    
    //Modify to match your apn if you are using an HSPA radio with a SIM card
    const char APN[] = "";
    
    /** STMicro Nucelo F401RE
    * The supported jumper configurations of the MTSAS do not line up with
    * the pin mapping of the Nucleo F401RE. Therefore, the MTSAS serial TX
    * pin (JP8 Pin 2) must be manually jumped to Serial1 RX (Shield pin D2)
    * and the MTSAS serial RX pin (JP9 Pin 2) pin must be manually jumped to
    * Serial1 TX (Shield pin D8).
    * Uncomment the following line to use the STMicro Nuceleo F401RE
    */
    MTSSerialFlowControl* io = new MTSSerialFlowControl(D8, D2, D3, D6);
    
    /** Freescale KL46Z
    * To configure the serial pins for the Freescale KL46Z board, use MTSAS jumper
    * configuration B. Uncomment the following line to use the Freescale KL46Z board
    */
    //MTSSerialFlowControl* io = new MTSSerialFlowControl(D2, D9, D3, D6);
    
    /** Freescale K64F
    * To configure the serial pins for the Freescale K64F board, use MTSAS jumper
    * configuration A. Uncomment the following line to use the Freescale K64F board
    */
    //MTSSerialFlowControl* io = new MTSSerialFlowControl(D1, D0, D3, D6);
    
    //Sets the baud rate for communicating with the radio
    io->baud(115200); 
    
    //Initialize radio configurations
    Cellular* radio = CellularFactory::create(io);
    if( ! radio) {
        logFatal("Radio initialization failed");
        return 1;
    }
    radio->configureSignals(D4,D7,RESET);
    Transport::setTransport(radio);
    
    //Set radio APN
    for (int i = 0; i < 10; i++) {
        if (i >= 10) {
            logError("Failed to set APN to %s", APN);
        }
        if (radio->setApn(APN) == MTS_SUCCESS) {
            logInfo("Successfully set APN to %s", APN);
            break;
        } else {
            wait(1);
        }
    }
    
    //Establish PPP link
    for (int i = 0; i < 10; i++) {
        if (i >= 10) {
            logError("Failed to establish PPP link");
        }
        if (radio->connect() == true) {
            logInfo("Successfully established PPP link");
            break;
        } else {
            wait(1);
        }
    }
    
    //Receive buffer
    char rbuf[2000];
    HTTPText* receive = new HTTPText(rbuf, sizeof(rbuf));
    
    //Json output object, data must be in Json format
    char sbuf[2000] = "{\"data\":[{\"dataItems\":{\"mental_trauma\":1,\"physical_trauma\":2,\"emotional_trauma\":3}}]}\0";
    HTTPJson* send = new HTTPJson(sbuf);
    
    //Create HTTP Client Instance
    HTTPClient* http = new HTTPClient();
    if( !http || !receive || !send) {
        logFatal("Failed to instantiate client or send buffer or receive buffer");
        return 1;
    }
    
    logTrace("Loading certificate(s)");
    HTTPResult res = http->addRootCACertificate(CERTIFICATES);
    if(res != HTTP_OK) {
        logError("Failed to load CERTIFICATES");
    }
    
    /**Set whether or not to verify the remote server's certificate
     * VERIFY_NONE,VERIFY_PEER
     */
    http->setPeerVerification(VERIFY_PEER);
    
    //URL for remote host (includes path)
    //Format: https://nucleus-connect.axeda.com/ammp/data/1/MODEL_STRING_HERE!<SERIAL_NUMBER_HERE>
    string url = "https://nucleus-connect.axeda.com/ammp/data/1/nlr_selfcrt_arm32!nlr__EPratt_multitech_com___1159423";
        
    logTrace("HTTPS POST Request with Certificate");
    res = http->post(url.c_str(), *send, receive);
        if(res == HTTP_OK) {
            logInfo("HTTPS POST succeeded");
        } else {
            logInfo("HTTPS POST failed [%s]", httpResToStr(res));
        }
    
    return 0;
}

//Simple error code to string function
char * httpResToStr(HTTPResult res) {
    switch(res) {
        case HTTP_PROCESSING:
            return "HTTP_PROCESSING";
        case HTTP_PARSE:
            return "HTTP_PARSE";
        case HTTP_DNS:
            return "HTTP_DNS";
        case HTTP_PRTCL:
            return "HTTP_PRTCL";
        case HTTP_NOTFOUND:
            return "HTTP_NOTFOUND";
        case HTTP_REFUSED:
            return "HTTP_REFUSED";
        case HTTP_ERROR:
            return "HTTP_ERROR";
        case HTTP_TIMEOUT:
            return "HTTP_TIMEOUT";
        case HTTP_CONN:
            return "HTTP_CONN";
        case HTTP_CLOSED:
            return "HTTP_CLOSED";
        case HTTP_REDIRECT:
            return "HTTP_REDIRECT";
        case HTTP_OK:
            return "HTTP_OK";
        default:
            return "HTTP Result unknown";
    }
}