温度センサLM75BとWi-FiモジュールESP-WROOM-02をmbed LPC1114FN28に繋げて、温度をIFTTTのMaker Channelに出力するプログラム

Dependencies:   LM75B mbed

Files at this revision

API Documentation at this revision

Comitter:
jksoft
Date:
Sun May 15 11:47:02 2016 +0000
Commit message:
??

Changed in this revision

ESP8266InterfaceTiny/ESP8266/CBuffer.h Show annotated file Show diff for this revision Revisions of this file
ESP8266InterfaceTiny/ESP8266/ESP8266.cpp Show annotated file Show diff for this revision Revisions of this file
ESP8266InterfaceTiny/ESP8266/ESP8266.h Show annotated file Show diff for this revision Revisions of this file
ESP8266InterfaceTiny/ESP8266Interface.cpp Show annotated file Show diff for this revision Revisions of this file
ESP8266InterfaceTiny/ESP8266Interface.h Show annotated file Show diff for this revision Revisions of this file
ESP8266InterfaceTiny/Helper/def.h Show annotated file Show diff for this revision Revisions of this file
ESP8266InterfaceTiny/Socket/Endpoint.cpp Show annotated file Show diff for this revision Revisions of this file
ESP8266InterfaceTiny/Socket/Endpoint.h Show annotated file Show diff for this revision Revisions of this file
ESP8266InterfaceTiny/Socket/Socket.cpp Show annotated file Show diff for this revision Revisions of this file
ESP8266InterfaceTiny/Socket/Socket.h Show annotated file Show diff for this revision Revisions of this file
ESP8266InterfaceTiny/Socket/TCPSocketConnection.cpp Show annotated file Show diff for this revision Revisions of this file
ESP8266InterfaceTiny/Socket/TCPSocketConnection.h Show annotated file Show diff for this revision Revisions of this file
ESP8266InterfaceTiny/Socket/TCPSocketServer.cpp Show annotated file Show diff for this revision Revisions of this file
ESP8266InterfaceTiny/Socket/TCPSocketServer.h Show annotated file Show diff for this revision Revisions of this file
ESP8266InterfaceTiny/Socket/UDPSocket.cpp Show annotated file Show diff for this revision Revisions of this file
ESP8266InterfaceTiny/Socket/UDPSocket.h Show annotated file Show diff for this revision Revisions of this file
HTTPClient/HTTPClient.cpp Show annotated file Show diff for this revision Revisions of this file
HTTPClient/HTTPClient.h Show annotated file Show diff for this revision Revisions of this file
HTTPClient/IHTTPData.h Show annotated file Show diff for this revision Revisions of this file
HTTPClient/data/HTTPMap.cpp Show annotated file Show diff for this revision Revisions of this file
HTTPClient/data/HTTPMap.h Show annotated file Show diff for this revision Revisions of this file
HTTPClient/data/HTTPText.cpp Show annotated file Show diff for this revision Revisions of this file
HTTPClient/data/HTTPText.h Show annotated file Show diff for this revision Revisions of this file
IFTTT/ifttt.cpp Show annotated file Show diff for this revision Revisions of this file
IFTTT/ifttt.h Show annotated file Show diff for this revision Revisions of this file
LM75B.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP8266InterfaceTiny/ESP8266/CBuffer.h	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,75 @@
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef CIRCBUFFER_H_
+#define CIRCBUFFER_H_
+
+template <class T>
+class CircBuffer {
+public:
+    CircBuffer(int length) {
+        write = 0;
+        read = 0;
+        size = length + 1;
+        buf = (T *)malloc(size * sizeof(T));
+    };
+
+    bool isFull() {
+        return (((write + 1) % size) == read);
+    };
+
+    bool isEmpty() {
+        return (read == write);
+    };
+
+    void queue(T k) {
+        if (isFull()) {
+            read++;
+            read %= size;
+        }
+        buf[write++] = k;
+        write %= size;
+    }
+    
+    void flush() {
+        read = 0;
+        write = 0;
+    }
+    
+
+    uint32_t available() {
+        return (write >= read) ? write - read : size - read + write;
+    };
+
+    bool dequeue(T * c) {
+        bool empty = isEmpty();
+        if (!empty) {
+            *c = buf[read++];
+            read %= size;
+        }
+        return(!empty);
+    };
+
+private:
+    volatile uint32_t write;
+    volatile uint32_t read;
+    uint32_t size;
+    T * buf;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP8266InterfaceTiny/ESP8266/ESP8266.cpp	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,519 @@
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "mbed.h"
+#include "ESP8266.h"
+#include "Endpoint.h"
+
+//#include <string>
+//#include <algorithm>
+
+//Debug is disabled by default
+#if 0
+#define DBG(x, ...)  pc.printf("[ESP8266 : DBG]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 
+#define WARN(x, ...) pc.printf("[ESP8266 : WARN]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 
+#define ERR(x, ...)  pc.printf("[ESP8266 : ERR]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 
+#else
+#define DBG(x, ...) //wait_us(10);
+#define WARN(x, ...) //wait_us(10);
+#define ERR(x, ...)
+#endif
+
+#if 0
+#define INFO(x, ...) printf("[ESP8266 : INFO]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 
+#else
+#define INFO(x, ...)
+#endif
+
+#define ESP_MAX_TRY_JOIN 3
+#define ESP_MAXID 4 // the largest possible ID Value (max num of sockets possible)
+
+ESP8266 * ESP8266::inst;
+char* ip = NULL;
+
+ESP8266::ESP8266(PinName tx, PinName rx, PinName reset, const char *ssid, const char *phrase, uint32_t baud) :
+    wifi(tx, rx), reset_pin(reset), buf_ESP8266(ESP_MBUFFE_MAX)
+{
+    INFO("Initializing ESP8266 object");
+    memset(&state, 0, sizeof(state));
+
+
+    strcpy(this->ssid, ssid);
+    strcpy(this->phrase, phrase);
+    inst = this;
+    attach_rx(false);
+
+    wifi.baud(baud); // initial baud rate of the ESP8266
+
+    state.associated = false;
+    state.cmdMode = false;
+}
+
+bool ESP8266::join()
+{
+    char cmd[100];
+    sendCommand( "AT+CWMODE=1", "change", NULL, 1000);
+    //string cmd="AT+CWJAP=\""+(string)this->ssid+"\",\""+(string)this->phrase+"\"";
+    sprintf(cmd,"AT+CWJAP=\"%s\",\"%s\"",this->ssid,this->phrase);
+    if( sendCommand( cmd, "OK", NULL, 10000) ) {
+        // successfully joined the network
+        state.associated = true;
+        INFO("ssid: %s, phrase: %s", this->ssid, this->phrase);
+        return true;
+    }
+    return false;
+}
+
+bool ESP8266::connect()
+{
+    sendCommand("AT+CWDHCP=1,1","OK",NULL,1000); // DHCP Enabled in Station Mode
+    return ESP8266::join();
+}
+
+bool ESP8266::is_connected()
+{
+    return true;
+}
+
+bool ESP8266::start(bool type,char* ip, int port, int id)
+{
+    char cmd[256];
+    // Error Check
+    if(id > ESP_MAXID) {
+        ERR("startUDPMulti: max id is: %d, id given is %d",ESP_MAXID,id);
+        return false;
+    }
+    // Single Connection Mode
+    if(id < 0) {
+        DBG("Start Single Connection Mode");
+        //char portstr[5];
+        bool check [3] = {0};
+        //sprintf(portstr, "%d", port);
+        switch(type) {
+            case ESP_UDP_TYPE : //UDP
+                sprintf(cmd,"AT+CIPSTART=\"UDP\",\"%s\",%d",ip,port);
+                check[0] = sendCommand(cmd, "OK", NULL, 10000);
+                //check[0] = sendCommand(( "AT+CIPSTART=\"UDP\",\"" + (string) ip + "\"," + (string) portstr ).c_str(), "OK", NULL, 10000);
+               break;
+            case ESP_TCP_TYPE : //TCP
+                sprintf(cmd,"AT+CIPSTART=\"TCP\",\"%s\",%d",ip,port);
+                check[0] = sendCommand(cmd, "OK", NULL, 10000);
+                //check[0] = sendCommand(( "AT+CIPSTART=\"TCP\",\"" + (string) ip + "\"," + (string) portstr ).c_str(), "OK", NULL, 10000);
+                break;
+            default:
+                ERR("Default hit for starting connection, this shouldnt be possible!!");
+                break;
+        }
+        check[1] = sendCommand("AT+CIPMODE=1", "OK", NULL, 1000);// go into transparent mode
+        check[2] = sendCommand("AT+CIPSEND", ">", NULL, 1000);// go into transparent mode
+        // check that all commands were sucessful
+        if(check[0] and check[1] and check[2]) {
+            state.cmdMode = false;
+            return true;
+        } else {
+            ERR("startUDPTransparent Failed for ip:%s, port:%d",ip,port);
+            return false;
+        }
+    }
+    // Multi Connection Mode
+    else {
+        //TODO: impliment Multi Connection Mode
+        ERR("Not currently Supported!");
+        return false;
+    }
+}
+
+bool ESP8266::startUDP(char* ip, int port, int id, int length)
+{
+    char cmd[256];
+    char portstr[5];
+    char idstr[1];
+    char lenstr[2];
+    
+    sprintf(portstr, "%d", port);
+    sprintf(idstr, "%d", id);
+    sprintf(lenstr, "%d", length);
+    
+    sendCommand("AT+CIPMUX=1", "OK", NULL, 1000);
+    sprintf(cmd,"AT+CIPSTART=%d,\"UDP\",\"%s\",%d,1112,0",id,ip,port);
+    sendCommand(cmd, "OK", NULL, 10000);
+    //sendCommand(( "AT+CIPSTART=" + string(idstr) + ",\"UDP\",\"" + (string) ip + "\"," + (string) portstr + ",1112,0").c_str(), "OK", NULL, 10000);
+    sprintf(cmd,"AT+CIPSEND=%d,%d",id,length);
+    sendCommand(cmd, ">", NULL, 1000);// go into transparent mode
+    //sendCommand(("AT+CIPSEND=" + (string)idstr + "," +  (string)lenstr).c_str(), ">", NULL, 1000);// go into transparent mode
+    DBG("Data Mode\r\n");
+    state.cmdMode = false;
+
+    return true;
+}
+
+bool ESP8266::startTCPServer(int port)
+{
+    char cmd[100];
+    bool command_results[3];
+    command_results[0]=sendCommand("AT+CWMODE=3", "OK", NULL, 1000);
+    command_results[1]=sendCommand("AT+CIPMUX=1", "OK", NULL, 1000);
+    if(port == 333){
+        command_results[2]=sendCommand("AT+CIPSERVER=1", "OK", NULL, 1000);
+    }
+    else{
+        sprintf(cmd,"AT+CIPSERVER=1,%d",port);
+        command_results[2]=sendCommand(cmd, "OK", NULL, 1000);
+    }
+    //sendCommand("AT+CIFSR", "OK", NULL, 1000);
+    DBG("Data Mode\r\n");
+    state.cmdMode = false;
+    if (command_results[0] and command_results[1] and command_results[2]){
+        return true;
+    }
+    else{
+        return false;
+    }
+}
+
+bool ESP8266::close()
+{
+    wait(0.1f);
+    send("+++",3);
+    wait(1.0f);
+    state.cmdMode = true;
+    sendCommand("AT+CIPCLOSE","OK", NULL, 10000);
+    return true;
+}
+
+bool ESP8266::disconnect()
+{
+    // if already disconnected, return
+    if (!state.associated)
+        return true;
+    // send command to quit AP
+    sendCommand("AT+CWQAP", "OK", NULL, 10000);
+    state.associated = false;
+    return true;
+}
+
+int ESP8266::strfind(const char *str,const char *chkstr,int pos)
+{
+    if( (strlen(str)-pos) < strlen(chkstr) )    return(-1);
+    
+
+    for(int i=pos;i<strlen(str);i++)
+    {
+        if(memcmp(chkstr,&str[i],strlen(chkstr))==0)
+        {
+            return(i);
+        }
+    }
+    return(-1);
+}
+
+char* ESP8266::substr(const char *str , char *outstr , int pos1 , int pos2 )
+{
+    int size = pos2 - pos1;
+    
+    memcpy(outstr , &str[pos1] , size );
+    outstr[size] = '\0';
+    
+    return(outstr);
+}
+
+int ESP8266::strcount(const char *str , char countstr )
+{
+    int ret = 0;
+    
+    for(int i = 0 ; i < strlen(str) ; i++)
+    {
+        if( str[i] == countstr )
+        {
+            ret++;
+        }
+        
+    }
+    
+    return(ret);
+}
+
+/*
+    Assuming Returned data looks like this:
+    +CIFSR:STAIP,"192.168.11.2"
+    +CIFSR:STAMAC,"18:fe:34:9f:3a:f5"
+    grabbing IP from first set of quotation marks
+*/
+char* ESP8266::getIPAddress()
+{
+    char result[30] = {0};
+    char tmp[30] = {0};
+    int check = 0;
+    check = sendCommand("AT+CIFSR", NULL, result, 1000);
+    //pc.printf("\r\nReceivedInfo for IP Command is: %s\r\n",result);
+    ip = ipString;
+    if(check) {
+        // Success
+        uint8_t pos1 = 0, pos2 = 0;
+        //uint8_t pos3 = 0, pos4 = 0;
+        pos1 = strfind(result,"+CIFSR:STAIP",0);
+        //pos1 = resultString.find("+CIFSR:STAIP");
+        pos1 = strfind(result,"\"",pos1);
+        //pos1 = resultString.find('"',pos1);
+        pos2 = strfind(result,"\"",pos1+1);
+        //pos2 = resultString.find('"',pos1+1);
+        //pos3 = resultString.find('"',pos2+1); //would find mac address
+        //pos4 = resultString.find('"',pos3+1);
+        strncpy(ipString,substr(result,tmp,pos1,pos2),sizeof(ipString));
+        INFO("IP: %s",ipString);
+        ip = ipString;
+
+    } else {
+        // Failure
+        ERR("getIPAddress() failed");
+        ip = NULL;
+    }
+    return ip;
+}
+
+bool ESP8266::gethostbyname(const char * host, char * ip)
+{
+    int nb_digits = 0;
+    char tmp[100];
+    
+    strcpy(ip,host);
+    
+    return true;
+
+    // no dns needed
+    int pos = strfind(host,".",0);
+    if (pos != -1) {
+        nb_digits = atoi(substr(host,tmp,0,pos));
+    }
+    //printf("substrL %s\r\n", sub.c_str());
+    if (strcount(host,'.') == 3 && nb_digits > 0) {
+        strcpy(ip, host);
+        return true;
+    } else {
+        // dns needed, not currently available
+        ERR("gethostbyname(): DNS Not currently available, only use IP Addresses!");
+        return false;
+    }
+}
+
+void ESP8266::reset()
+{
+    reset_pin = 0;
+    wait_us(20);
+    reset_pin = 1;
+    //wait(1);
+    //reset_pin = !reset_pin
+    //send("+++",3);
+    wait(1);
+    state.cmdMode = true;
+    sendCommand("AT", "OK", NULL, 1000);
+    sendCommand("AT+RST", "ready", NULL, 10000);
+    state.associated = false;
+
+}
+
+bool ESP8266::reboot()
+{
+    reset();
+    return true;
+}
+
+void ESP8266::handler_rx(void)
+{
+    //read characters
+    char c;
+    while (wifi.readable()) {
+        c=wifi.getc();
+        buf_ESP8266.queue(c);
+        //if (state.cmdMode) pc.printf("%c",c); //debug echo, needs fast serial console to prevent UART overruns
+    }
+}
+
+void ESP8266::attach_rx(bool callback)
+{
+    if (!callback) {
+        wifi.attach(NULL);
+    }
+    else {
+        wifi.attach(this, &ESP8266::handler_rx);
+    }
+}
+
+int ESP8266::readable()
+{
+    return buf_ESP8266.available();
+}
+
+int ESP8266::writeable()
+{
+    return wifi.writeable();
+}
+
+char ESP8266::getc()
+{
+    char c=0;
+    while (!buf_ESP8266.available());
+    buf_ESP8266.dequeue(&c);
+    return c;
+}
+
+int ESP8266::putc(char c)
+{
+    while (!wifi.writeable() || wifi.readable()); //wait for echoed command characters to be read first
+    return wifi.putc(c);
+}
+
+void ESP8266::flush()
+{
+    buf_ESP8266.flush();
+}
+
+int ESP8266::send(const char * buf, int len)
+{
+    //TODO: need to add handler for data > 2048B, this is the max packet size of the ESP8266.
+    if(len >= 2048){
+        WARN("send buffer >= 2048B, need to chunk this up to be less.");    
+    }
+    const char* bufptr=buf;
+    for(int i=0; i<len; i++) {
+        putc((int)*bufptr++);
+    }
+    return len;
+}
+
+bool ESP8266::sendCommand(const char * cmd, const char * ACK, char * res, int timeout)
+{
+    char read;
+    char checking[512] = "";
+    int checking_size = 0;
+    int fond = -1;
+    Timer tmr;
+    int result = 0;
+
+    DBG("sendCmd:\t %s",cmd);
+
+    attach_rx(true);
+
+    //We flush the buffer
+    while (readable())
+        getc();
+
+    if (!ACK || !strcmp(ACK, "NO")) {
+        for (int i = 0; i < strlen(cmd); i++) {
+            result = (putc(cmd[i]) == cmd[i]) ? result + 1 : result;
+            wait(0.005f); // prevents stuck recieve ready (?) need to let echoed character get read first
+        }
+        putc(13); //CR
+        wait(0.005f); // wait for echo
+        putc(10); //LF
+
+    } else {
+        //We flush the buffer
+        while (readable())
+            getc();
+
+        tmr.start();
+        for (int i = 0; i < strlen(cmd); i++) {
+            result = (putc(cmd[i]) == cmd[i]) ? result + 1 : result;
+            wait(.005); // wait for echo
+        }
+        putc(13); //CR
+        wait(0.005f); // wait for echo
+        putc(10); //LF
+
+        while (1) {
+            if (tmr.read_ms() > timeout) {
+                //We flush the buffer
+                while (readable())
+                    getc();
+
+                DBG("check:\t %s", checking);
+
+                attach_rx(true);
+                return -1;
+            } else if (readable()) {
+                read = getc();
+                //pc.printf("%c",read); //debug echo
+                if ( read != '\r' && read != '\n') {
+                    checking[checking_size] = read;
+                    checking_size++;
+                    checking[checking_size] = '\0';
+                    fond = strfind(checking,ACK,0);
+                    if (fond != -1) {
+                        wait(0.01f);
+
+                        //We flush the buffer
+                        while (readable())
+                            read = getc();
+                        //printf("%c",read); //debug echo
+                        break;
+                    }
+                }
+            }
+        }
+        DBG("check: %s", checking);
+
+        attach_rx(true);
+        return result;
+    }
+
+    //the user wants the result from the command (ACK == NULL, res != NULL)
+    if (res != NULL) {
+        int i = 0;
+        Timer timeout;
+        timeout.start();
+        tmr.reset();
+        while (1) {
+            if (timeout.read() > 2) {
+                if (i == 0) {
+                    res = NULL;
+                    break;
+                }
+                res[i] = '\0';
+                DBG("user str 1: %s", res);
+
+                break;
+            } else {
+                if (tmr.read_ms() > 300) {
+                    res[i] = '\0';
+                    DBG("user str: %s", res);
+
+                    break;
+                }
+                if (readable()) {
+                    tmr.start();
+                    read = getc();
+
+                    // we drop \r and \n
+                    if ( read != '\r' && read != '\n') {
+                        res[i++] = read;
+                    }
+                }
+            }
+        }
+        DBG("user str: %s", res);
+    }
+
+    //We flush the buffer
+    while (readable())
+        getc();
+
+    attach_rx(true);
+    DBG("result: %d", result)
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP8266InterfaceTiny/ESP8266/ESP8266.h	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,235 @@
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * @section DESCRIPTION
+ *
+ * ESP8266 serial wifi module
+ *
+ * Datasheet:
+ *
+ * http://www.electrodragon.com/w/Wi07c
+ */
+
+#ifndef ESP8266_H
+#define ESP8266_H
+
+#include "mbed.h"
+#include "CBuffer.h"
+
+#define DEFAULT_WAIT_RESP_TIMEOUT 500
+#define ESP_TCP_TYPE 1
+#define ESP_UDP_TYPE 0 
+#define ESP_MBUFFE_MAX 256
+
+/**
+ * The ESP8266 class
+ */
+class ESP8266
+{
+
+public:
+    /**
+    * Constructor
+    *
+    * @param tx mbed pin to use for tx line of Serial interface
+    * @param rx mbed pin to use for rx line of Serial interface
+    * @param reset reset pin of the wifi module ()
+    * @param ssid ssid of the network
+    * @param phrase WEP, WPA or WPA2 key
+    * @param baud the baudrate of the serial connection
+    */
+    ESP8266( PinName tx, PinName rx, PinName reset, const char * ssid, const char * phrase, uint32_t baud );
+
+    /**
+    * Connect the wifi module to the ssid contained in the constructor.
+    *
+    * @return true if connected, false otherwise
+    */
+    bool join();
+
+    /**
+    * Same as Join: connect to the ssid and get DHCP settings
+    * @return true if successful
+    */
+    bool connect();
+    
+    /**
+    * Check connection to the access point
+    * @return true if successful
+    */
+    bool is_connected();
+
+    /**
+    * Disconnect the ESP8266 module from the access point
+    *
+    * @return true if successful
+    */
+    bool disconnect();
+    
+    /*
+    * Start up a UDP or TCP Connection
+    * @param type 0 for UDP, 1 for TCP
+    * @param ip A string that contains the IP, no quotes
+    * @param port Numerical port number to connect to
+    * @param id number between 0-4, if defined it denotes ID to use in multimode (Default to Single connection mode with -1)
+    * @return true if sucessful, 0 if fail
+    */
+    bool start(bool type, char* ip, int port, int id = -1);
+    
+    /*
+    * Legacy Start for UDP only connection in transparent mode
+    * @param ip A string that contains the IP, no quotes
+    * @param id number between 0-4
+    * @param port Numerical port number to connect to
+    * @param length number of characters in the message being sent
+    */
+    bool startUDP(char* ip, int port, int id, int length);
+
+    /*
+    * Legacy Start for UDP only connection in transparent mode
+    * @param ip A string that contains the IP, no quotes
+    * @param id number between 0-4
+    * @param port Numerical port number to connect to
+    * @param length number of characters in the message being sent
+    */
+    //bool startUDP(char* ip, int port, int id, int length);
+
+    /*
+    *Starts the ESP chip as a TCP Server
+    *@param port Numerical port of the server, default is 333
+    */
+    bool startTCPServer(int port = 333);
+
+    /**
+    * Close a connection
+    *
+    * @return true if successful
+    */
+    bool close();
+    
+    /**
+    * Return the IP address 
+    * @return IP address as a string
+    */
+    char* getIPAddress();
+
+    /**
+    * Return the IP address from host name
+    * @return true on success, false on failure
+    */    
+    bool gethostbyname(const char * host, char * ip);
+
+    /**
+    * Reset the wifi module
+    */
+    void reset();
+    
+    /**
+    * Reboot the wifi module
+    */
+    bool reboot();
+
+    /**
+    * Check if characters are available
+    *
+    * @return number of available characters
+    */
+    int readable();
+
+    /**
+    * Check if characters are available
+    *
+    * @return number of available characters
+    */
+    int writeable();
+
+    /**
+    * Read a character
+    *
+    * @return the character read
+    */
+    char getc();
+
+    /**
+    * Write a character
+    *
+    * @param the character which will be written
+    */
+    int putc(char c);
+
+    /**
+    * Flush the buffer
+    */
+    void flush();
+
+    /**
+    * Send a command to the wifi module. Check if the module is in command mode. If not enter in command mode
+    *
+    * @param str string to be sent
+    * @param ACK string which must be acknowledge by the wifi module. If ACK == NULL, no string has to be acknowledged. (default: "NO")
+    * @param res this field will contain the response from the wifi module, result of a command sent. This field is available only if ACK = "NO" AND res != NULL (default: NULL)
+    *
+    * @return true if successful
+    */
+    bool sendCommand(const char * cmd, const char * ack = NULL, char * res = NULL, int timeout = DEFAULT_WAIT_RESP_TIMEOUT);
+
+    /**
+    * Send a string to the wifi module by serial port. This function desactivates the user interrupt handler when a character is received to analyze the response from the wifi module.
+    * Useful to send a command to the module and wait a response.
+    *
+    *
+    * @param str string to be sent
+    * @param len string length
+    * @param ACK string which must be acknowledge by the wifi module. If ACK == NULL, no string has to be acknoledged. (default: "NO")
+    * @param res this field will contain the response from the wifi module, result of a command sent. This field is available only if ACK = "NO" AND res != NULL (default: NULL)
+    *
+    * @return true if ACK has been found in the response from the wifi module. False otherwise or if there is no response in 5s.
+    */
+    int send(const char * buf, int len);
+
+    static ESP8266 * getInstance() {
+        return inst;
+    };
+
+protected:
+    int strfind(const char *str,const char *chkstr,int pos=0);
+    char* substr(const char *str , char *outstr , int pos1 , int pos2 );
+    int strcount(const char *str , char countstr );
+
+
+    RawSerial wifi;
+    DigitalOut reset_pin;
+    char phrase[30];
+    char ssid[30];
+    char ipString[20];
+    CircBuffer<char> buf_ESP8266;
+
+    static ESP8266 * inst;
+
+    void attach_rx(bool null);
+    void handler_rx(void);
+
+
+    typedef struct STATE {
+        bool associated;
+        bool cmdMode;
+    } State;
+
+    State state;
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP8266InterfaceTiny/ESP8266Interface.cpp	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,28 @@
+#include "ESP8266Interface.h"
+
+ESP8266Interface::ESP8266Interface( PinName tx, PinName rx, PinName reset,
+                                const char * ssid, const char * phrase, uint32_t baud ) :
+    ESP8266(tx, rx, reset, ssid, phrase, baud )
+{
+}
+
+int ESP8266Interface::init()
+{
+    ESP8266::reset();
+    return 0;
+}
+
+bool ESP8266Interface::connect()
+{
+    return ESP8266::connect();
+}
+
+int ESP8266Interface::disconnect()
+{
+    return ESP8266::disconnect();
+}
+
+char * ESP8266Interface::getIPAddress()
+{
+    return ESP8266::getIPAddress();
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP8266InterfaceTiny/ESP8266Interface.h	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,73 @@
+/* ESP8266Interface.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+ 
+#ifndef ESP8266INTERFACE_H_
+#define ESP8266INTERFACE_H_
+
+#include "ESP8266.h"
+#include "Endpoint.h"
+
+ /**
+ * Interface using ESP8266 to connect to an IP-based network
+ */
+class ESP8266Interface: public ESP8266 {
+public:
+
+    /**
+    * Constructor
+    *
+    * \param tx mbed pin to use for tx line of Serial interface
+    * \param rx mbed pin to use for rx line of Serial interface
+    * \param reset reset pin of the wifi module ()
+    * \param ssid ssid of the network
+    * \param phrase WEP or WPA key
+    * \param baud the baudrate of the serial connection (defaults to 115200, diff revs of the firmware use diff baud rates
+    */
+  ESP8266Interface(PinName tx, PinName rx, PinName reset, const char * ssid, const char * phrase, uint32_t baud = 115200 );
+
+  /** Initialize the interface with DHCP.
+  * Initialize the interface and configure it to use DHCP (no connection at this point).
+  * \return 0 on success, a negative number on failure
+  */
+  int init(); //With DHCP
+
+  /** Connect
+  * Bring the interface up, start DHCP if needed.
+  * \return 0 on success, a negative number on failure
+  */
+  bool connect();
+  
+  /** Disconnect
+  * Bring the interface down
+  * \return 0 on success, a negative number on failure
+  */
+  int disconnect();
+  
+  /** Get IP address
+  *
+  * \return ip address
+  */
+  char* getIPAddress();
+  
+private:
+};
+
+#include "UDPSocket.h"
+
+#endif /* ESP8266INTERFACE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP8266InterfaceTiny/Helper/def.h	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,28 @@
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+ 
+#ifndef DEF_H
+#define DEF_H
+
+#include "cmsis.h"
+#define htons(x)      __REV16(x)
+#define ntohs(x)      __REV16(x)
+#define htonl(x)      __REV(x)
+#define ntohl(x)      __REV(x)
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP8266InterfaceTiny/Socket/Endpoint.cpp	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,64 @@
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "Socket/Socket.h"
+#include "Socket/Endpoint.h"
+#include <cstring>
+
+using std::memset;
+
+Endpoint::Endpoint()
+{
+    ESP8266 = ESP8266::getInstance();
+    if (ESP8266 == NULL)
+        error("Endpoint constructor error: no ESP8266 instance available!\r\n");
+    reset_address();
+}
+Endpoint::~Endpoint() {}
+
+void Endpoint::reset_address(void)
+{
+    _ipAddress[0] = '\0';
+    _port = 0;
+    _id = -1;
+}
+
+int Endpoint::set_address(const char* host, const int port)
+{
+    //Resolve DNS address or populate hard-coded IP address
+    if(ESP8266->gethostbyname(host, _ipAddress)) {
+        _port = port;
+        return 0;
+    } else {
+        return -1;
+    }
+}
+
+char* Endpoint::get_address()
+{
+    return _ipAddress;
+}
+
+int   Endpoint::get_port()
+{
+    return _port;
+}
+
+int Endpoint::get_id()
+{
+    return _id;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP8266InterfaceTiny/Socket/Endpoint.h	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,72 @@
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef ENDPOINT_H
+#define ENDPOINT_H
+
+#include "ESP8266.h"
+
+class UDPSocket;
+
+/**
+IP Endpoint (address, port)
+*/
+class Endpoint {
+    friend class UDPSocket;
+
+public:
+    /** IP Endpoint (address, port)
+     */
+    Endpoint(void);
+    
+    ~Endpoint(void);
+    
+    /** Reset the address of this endpoint
+     */
+    void reset_address(void);
+    
+    /** Set the address of this endpoint
+    \param host The endpoint address (it can either be an IP Address or a hostname that will be resolved with DNS).
+    \param port The endpoint port
+    \return 0 on success, -1 on failure (when an hostname cannot be resolved by DNS).
+     */
+    int  set_address(const char* host, const int port);
+    
+    /** Get the IP address of this endpoint
+    \return The IP address of this endpoint.
+     */
+    char* get_address(void);
+    
+    /** Get the port of this endpoint
+    \return The port of this endpoint
+     */
+    int get_port(void);
+    
+    /** Get the id of this endpoint
+    \return The id of this endpoint
+     */
+    int get_id(void);
+
+protected:
+    char _ipAddress[64];
+    int _port;
+    int _id;
+    
+    ESP8266 * ESP8266;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP8266InterfaceTiny/Socket/Socket.cpp	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,57 @@
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+ 
+#include "Socket.h"
+#include <cstring>
+
+//Debug is disabled by default
+#if 0
+//Enable debug
+#include <cstdio>
+#define DBG(x, ...) std::printf("[Socket : DBG]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 
+#define WARN(x, ...) std::printf("[Socket : WARN]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 
+#define ERR(x, ...) std::printf("[Socket : ERR]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 
+
+#else
+//Disable debug
+#define DBG(x, ...) 
+#define WARN(x, ...)
+#define ERR(x, ...) 
+
+#endif
+
+Socket::Socket() : _blocking(true), _timeout(1500) {
+    wifi = ESP8266::getInstance();
+    if (wifi == NULL)
+        ERR("Socket constructor error: no ESP8266 instance available!");
+}
+
+void Socket::set_blocking(bool blocking, unsigned int timeout) {
+    DBG("set blocking: %d %d", blocking, timeout);
+    _blocking = blocking;
+    _timeout = timeout;
+}
+
+int Socket::close() {
+    
+    return (wifi->close()) ? 0 : -1;
+}
+
+Socket::~Socket() {
+    close(); //Don't want to leak
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP8266InterfaceTiny/Socket/Socket.h	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,51 @@
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef SOCKET_H_
+#define SOCKET_H_
+
+#include "ESP8266.h"
+
+/** Socket file descriptor and select wrapper
+  */
+class Socket {
+public:
+    /** Socket
+     */
+    Socket();
+    
+    /** Set blocking or non-blocking mode of the socket and a timeout on
+        blocking socket operations
+    \param blocking  true for blocking mode, false for non-blocking mode.
+    \param timeout   timeout in ms [Default: (1500)ms].
+    */
+    void set_blocking(bool blocking, unsigned int timeout=1500);
+    
+    /** Close the socket file descriptor
+     */
+    int close();
+    
+    ~Socket();
+    
+protected:
+    bool _blocking;
+    int _timeout;
+    ESP8266 * wifi;
+};
+
+
+#endif /* SOCKET_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP8266InterfaceTiny/Socket/TCPSocketConnection.cpp	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,246 @@
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "TCPSocketConnection.h"
+#include <cstring>
+#include <algorithm>
+
+using std::memset;
+using std::memcpy;
+
+//Debug is disabled by default
+#if 1
+#define DBG(x, ...)  printf("[TCPConnection : DBG]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 
+#define WARN(x, ...) printf("[TCPConnection: WARN]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 
+#define ERR(x, ...)  printf("[TCPConnection : ERR]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 
+#else
+#define DBG(x, ...)
+#define WARN(x, ...)
+#define ERR(x, ...)
+#endif
+
+TCPSocketConnection::TCPSocketConnection() :
+    _is_connected(false)
+{
+}
+
+int TCPSocketConnection::connect(const char* host, const int port)
+{
+//    if (init_socket(SOCK_STREAM) < 0)
+//        return -1;
+//
+    if (set_address(host, port) != 0)
+        return -1;
+//
+//    if (lwip_connect(_sock_fd, (const struct sockaddr *) &_remoteHost, sizeof(_remoteHost)) < 0) {
+//        close();
+//        return -1;
+//    }
+//    _is_connected = true;
+
+    _is_connected = ESP8266->start(ESP_TCP_TYPE,_ipAddress,_port);
+    if(_is_connected) { //success
+        return 0;
+    } else { // fail
+        return -1;
+    }
+}
+
+bool TCPSocketConnection::is_connected(void)
+{
+    return _is_connected;
+}
+
+int TCPSocketConnection::send(char* data, int length)
+{
+    if (!_is_connected) {
+        ERR("TCPSocketConnection::receive() - _is_connected is false : you cant receive data until you connect to a socket!");
+        return -1;
+    }
+    Timer tmr;
+    int idx = 0;
+    tmr.start();
+    while ((tmr.read_ms() < _timeout) || _blocking) {
+
+        idx += wifi->send(data, length);
+
+        if (idx == length)
+            return idx;
+    }
+    return (idx == 0) ? -1 : idx;
+
+    //return wifi->send(data,length);
+//
+//    if (!_blocking) {
+//        TimeInterval timeout(_timeout);
+//        if (wait_writable(timeout) != 0)
+//            return -1;
+//    }
+//
+//    int n = lwip_send(_sock_fd, data, length, 0);
+//    _is_connected = (n != 0);
+//
+//    return n;
+
+}
+
+// -1 if unsuccessful, else number of bytes written
+int TCPSocketConnection::send_all(char* data, int length)
+{
+//   if ((_sock_fd < 0) || !_is_connected)
+//        return -1;
+//
+//    int writtenLen = 0;
+//    TimeInterval timeout(_timeout);
+//    while (writtenLen < length) {
+//        if (!_blocking) {
+//            // Wait for socket to be writeable
+//            if (wait_writable(timeout) != 0)
+//                return writtenLen;
+//        }
+//
+//        int ret = lwip_send(_sock_fd, data + writtenLen, length - writtenLen, 0);
+//        if (ret > 0) {
+//            writtenLen += ret;
+//            continue;
+//        } else if (ret == 0) {
+//            _is_connected = false;
+//            return writtenLen;
+//        } else {
+//            return -1; //Connnection error
+//        }
+//    }
+//    return writtenLen;
+    return send(data,length); // just remap to send
+}
+
+int TCPSocketConnection::receive(char* buffer, int length)
+{
+    if (!_is_connected) {
+        ERR("TCPSocketConnection::receive() - _is_connected is false : you cant receive data until you connect to a socket!");
+        return -1;
+    }
+    Timer tmr;
+    int idx = 0;
+    int nb_available = 0;
+    int time = -1;
+
+    //make this the non-blocking case and return if <= 0
+    // remember to change the config to blocking
+    // if ( ! _blocking) {
+    // if ( wifi.readable <= 0 ) {
+    // return (wifi.readable);
+    // }
+    // }
+    //---
+    tmr.start();
+    if (_blocking) {
+        while (1) {
+            nb_available = wifi->readable();
+            if (nb_available != 0) {
+                break;
+            }
+        }
+    }
+    //---
+    // blocking case
+    else {
+        tmr.reset();
+
+        while (time < _timeout) {
+            nb_available = wifi->readable();
+            if (nb_available < 0) return nb_available;
+            if (nb_available > 0) break ;
+            time = tmr.read_ms();
+        }
+
+        if (nb_available == 0) return nb_available;
+    }
+
+    // change this to < 20 mS timeout per byte to detect end of packet gap
+    // this may not work due to buffering at the UART interface
+    tmr.reset();
+    // while ( tmr.read_ms() < 20 ) {
+    // if ( wifi.readable() && (idx < length) ) {
+    // buffer[idx++] = wifi->getc();
+    // tmr.reset();
+    // }
+    // if ( idx == length ) {
+    // break;
+    // }
+    // }
+    //---
+    while (time < _timeout) {
+
+        nb_available = wifi->readable();
+        //for (int i = 0; i < min(nb_available, length); i++) {
+        for (int i = 0; i < min(nb_available, (length-idx)); i++) {
+            buffer[idx] = wifi->getc();
+            idx++;
+        }
+        if (idx == length) {
+            break;
+        }
+        time = tmr.read_ms();
+    }
+    //---
+    return (idx == 0) ? -1 : idx;
+
+//************************ original code below
+//
+//    if (!_blocking) {
+//        TimeInterval timeout(_timeout);
+//        if (wait_readable(timeout) != 0)
+//            return -1;
+//    }
+//
+//    int n = lwip_recv(_sock_fd, data, length, 0);
+//    _is_connected = (n != 0);
+//
+//    return n;
+
+}
+
+// -1 if unsuccessful, else number of bytes received
+int TCPSocketConnection::receive_all(char* data, int length)
+{
+    //ERR("receive_all() not yet implimented");
+    //  if ((_sock_fd < 0) || !_is_connected)
+//        return -1;
+//
+//    int readLen = 0;
+//    TimeInterval timeout(_timeout);
+//    while (readLen < length) {
+//        if (!_blocking) {
+//            //Wait for socket to be readable
+//            if (wait_readable(timeout) != 0)
+//                return readLen;
+//        }
+//
+//        int ret = lwip_recv(_sock_fd, data + readLen, length - readLen, 0);
+//        if (ret > 0) {
+//            readLen += ret;
+//        } else if (ret == 0) {
+//            _is_connected = false;
+//            return readLen;
+//        } else {
+//            return -1; //Connnection error
+//        }
+//    }
+//    return readLen;
+    receive(data,length);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP8266InterfaceTiny/Socket/TCPSocketConnection.h	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,82 @@
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+ 
+#ifndef TCPSOCKET_H
+#define TCPSOCKET_H
+ 
+#include "Socket/Socket.h"
+#include "Socket/Endpoint.h"
+ 
+/**
+TCP socket connection
+*/
+class TCPSocketConnection : public Socket, public Endpoint {
+    friend class TCPSocketServer;
+    
+public:
+    /** TCP socket connection
+    */
+    TCPSocketConnection();
+    
+    /** Connects this TCP socket to the server
+    \param host The host to connect to. It can either be an IP Address or a hostname that will be resolved with DNS.
+    \param port The host's port to connect to.
+    \return 0 on success, -1 on failure.
+    */
+    int connect(const char* host, const int port);
+    
+    /** Check if the socket is connected
+    \return true if connected, false otherwise.
+    */
+    bool is_connected(void);
+    
+    /** Send data to the remote host.
+    \param data The buffer to send to the host.
+    \param length The length of the buffer to send.
+    \return the number of written bytes on success (>=0) or -1 on failure
+     */
+    int send(char* data, int length);
+    
+    /** Send all the data to the remote host.
+    \param data The buffer to send to the host.
+    \param length The length of the buffer to send.
+    \return the number of written bytes on success (>=0) or -1 on failure
+    */
+    int send_all(char* data, int length);
+    
+    /** Receive data from the remote host.
+    \param data The buffer in which to store the data received from the host.
+    \param length The maximum length of the buffer.
+    \return the number of received bytes on success (>=0) or -1 on failure
+     */
+    int receive(char* data, int length);
+    
+    /** Receive all the data from the remote host.
+    \param data The buffer in which to store the data received from the host.
+    \param length The maximum length of the buffer.
+    \return the number of received bytes on success (>=0) or -1 on failure
+    */
+    int receive_all(char* data, int length);
+ 
+private:
+    bool _is_connected;
+ 
+};
+ 
+#endif
+ 
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP8266InterfaceTiny/Socket/TCPSocketServer.cpp	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,44 @@
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "TCPSocketServer.h"
+ 
+#include <cstring>
+ 
+using std::memset;
+using std::memcpy;
+ 
+TCPSocketServer::TCPSocketServer() {
+    
+}
+ 
+int TCPSocketServer::bind(int port) {
+  if(!wifi->startTCPServer(port)) {
+            return(-1);
+   }
+    _port = port;
+    return 0;
+}
+ 
+int TCPSocketServer::listen(int max) {
+    
+    return 0;
+}
+ 
+int TCPSocketServer::accept(TCPSocketConnection& connection) {
+    return 0;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP8266InterfaceTiny/Socket/TCPSocketServer.h	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,55 @@
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef TCPSOCKETSERVER_H
+#define TCPSOCKETSERVER_H
+ 
+#include "Socket/Socket.h"
+#include "TCPSocketConnection.h"
+ 
+/** TCP Server.
+  */
+class TCPSocketServer : public Socket {
+  friend class TCPSocketConnection;
+  public:
+    /** Instantiate a TCP Server.
+    */
+    TCPSocketServer();
+    
+    /** Bind a socket to a specific port.
+    \param port The port to listen for incoming connections on.
+    \return 0 on success, -1 on failure.
+    */
+    int bind(int port);
+    
+    /** Start listening for incoming connections.
+    \param backlog number of pending connections that can be queued up at any
+                   one time [Default: 1].
+    \return 0 on success, -1 on failure.
+    */
+    int listen(int backlog=1);
+    
+    /** Accept a new connection.
+    \param connection A TCPSocketConnection instance that will handle the incoming connection.
+    \return 0 on success, -1 on failure.
+    */
+    int accept(TCPSocketConnection& connection);
+private:
+    int _port;
+};
+ 
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP8266InterfaceTiny/Socket/UDPSocket.cpp	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,154 @@
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "UDPSocket.h"
+
+#include <string>
+#include <algorithm>
+
+UDPSocket::UDPSocket()
+{
+    endpoint_configured = false;
+    endpoint_read = false;
+    Endpoint currentEndpoint;
+}
+
+int UDPSocket::init(void)
+{
+    return 0;
+}
+
+// Server initialization
+int UDPSocket::bind(int port)
+{
+    return 0;
+}
+
+// -1 if unsuccessful, else number of bytes written
+int UDPSocket::sendTo(Endpoint &remote, char *packet, int length)
+{
+    Timer tmr;
+    int idx = 0;
+
+
+    confEndpoint(remote);
+    
+    // initialize transparent mode if not already done
+    if(!endpoint_configured) {
+        // initialize UDP (default id of -1 means transparent mode)
+        //!wifi->start(ESP_UDP_TYPE, remote._ipAddress, remote._port, remote._id
+        if(!wifi->startUDP(remote._ipAddress, remote._port, 0,length)) {
+            return(-1);
+        }
+        endpoint_configured = true;
+    }
+    
+    tmr.start();
+
+    while ((tmr.read_ms() < _timeout) || _blocking) {
+
+        idx += wifi->send(packet, length);
+
+        if (idx == length)
+            return idx;
+    }
+    return (idx == 0) ? -1 : idx;
+}
+
+// -1 if unsuccessful, else number of bytes received
+int UDPSocket::receiveFrom(Endpoint &remote, char *buffer, int length)
+{
+    Timer tmr;
+    int idx = 0;
+    int nb_available = 0;
+    int time = -1;
+
+    //make this the non-blocking case and return if <= 0
+    // remember to change the config to blocking
+    // if ( ! _blocking) {
+    // if ( wifi.readable <= 0 ) {
+    // return (wifi.readable);
+    // }
+    // }
+    //---
+    tmr.start();
+    if (_blocking) {
+        while (1) {
+            nb_available = wifi->readable();
+            if (nb_available != 0) {
+                break;
+            }
+        }
+    }
+    //---
+    // blocking case
+    else {
+        tmr.reset();
+
+        while (time < _timeout) {
+            nb_available = wifi->readable();
+            if (nb_available < 0) return nb_available;
+            if (nb_available > 0) break ;
+            time = tmr.read_ms();
+        }
+
+        if (nb_available == 0) return nb_available;
+    }
+
+    // change this to < 20 mS timeout per byte to detect end of packet gap
+    // this may not work due to buffering at the UART interface
+    tmr.reset();
+    // while ( tmr.read_ms() < 20 ) {
+    // if ( wifi.readable() && (idx < length) ) {
+    // buffer[idx++] = wifi->getc();
+    // tmr.reset();
+    // }
+    // if ( idx == length ) {
+    // break;
+    // }
+    // }
+    //---
+    while (time < _timeout) {
+
+        nb_available = wifi->readable();
+        //for (int i = 0; i < min(nb_available, length); i++) {
+        for (int i = 0; i < min(nb_available, (length-idx)); i++) {
+            buffer[idx] = wifi->getc();
+            idx++;
+        }
+        if (idx == length) {
+            break;
+        }
+        time = tmr.read_ms();
+    }
+    //---
+    readEndpoint(remote);
+    return (idx == 0) ? -1 : idx;
+}
+
+bool UDPSocket::confEndpoint(Endpoint & ep)
+{
+    currentEndpoint = ep;
+    return true;
+}
+
+bool UDPSocket::readEndpoint(Endpoint & ep)
+{
+    ep = currentEndpoint;
+    return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP8266InterfaceTiny/Socket/UDPSocket.h	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,76 @@
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef UDPSOCKET_H
+#define UDPSOCKET_H
+
+#include "Endpoint.h"
+#include "Socket.h"
+
+#include <cstdint>
+
+/**
+UDP Socket
+*/
+class UDPSocket: public Socket {
+
+public:
+    /** Instantiate an UDP Socket.
+    */
+    UDPSocket();
+    
+    /** Init the UDP Client Socket without binding it to any specific port
+    \return 0 on success, -1 on failure.
+    */
+    int init(void);
+    
+    /** Bind a UDP Server Socket to a specific port
+    \param port The port to listen for incoming connections on
+    \return 0 on success, -1 on failure.
+    */
+    int bind(int port = -1);
+    
+    /** Send a packet to a remote endpoint
+    \param remote   The remote endpoint
+    \param packet   The packet to be sent
+    \param length   The length of the packet to be sent
+    \return the number of written bytes on success (>=0) or -1 on failure
+    */
+    int sendTo(Endpoint &remote, char *packet, int length);
+    
+    /** Receive a packet from a remote endpoint
+    \param remote   The remote endpoint
+    \param buffer   The buffer for storing the incoming packet data. If a packet
+           is too long to fit in the supplied buffer, excess bytes are discarded
+    \param length   The length of the buffer
+    \return the number of received bytes on success (>=0) or -1 on failure
+    */
+    int receiveFrom(Endpoint &remote, char *buffer, int length);
+    
+private:
+    bool confEndpoint(Endpoint & ep);
+    bool readEndpoint(Endpoint & ep);
+    bool endpoint_configured;
+    bool endpoint_read;
+    Endpoint currentEndpoint;
+    
+};
+
+#include "def.h"
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPClient/HTTPClient.cpp	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,739 @@
+/* HTTPClient.cpp */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+//Debug is disabled by default
+#if 0
+//Enable debug
+#include <cstdio>
+#define DBG(x, ...) std::printf("[HTTPClient : DBG]"x"\r\n", ##__VA_ARGS__); 
+#define WARN(x, ...) std::printf("[HTTPClient : WARN]"x"\r\n", ##__VA_ARGS__); 
+#define ERR(x, ...) std::printf("[HTTPClient : ERR]"x"\r\n", ##__VA_ARGS__); 
+
+#else
+//Disable debug
+#define DBG(x, ...) 
+#define WARN(x, ...)
+#define ERR(x, ...) 
+
+#endif
+
+#define HTTP_PORT 80
+
+#define OK 0
+
+#define MIN(x,y) (((x)<(y))?(x):(y))
+#define MAX(x,y) (((x)>(y))?(x):(y))
+
+#define CHUNK_SIZE 256
+
+#include <cstring>
+
+#include "HTTPClient.h"
+
+
+HTTPClient::HTTPClient() :
+m_sock(), m_basicAuthUser(NULL), m_basicAuthPassword(NULL), m_httpResponseCode(0)
+{
+
+}
+
+HTTPClient::~HTTPClient()
+{
+
+}
+
+#if 0
+void HTTPClient::basicAuth(const char* user, const char* password) //Basic Authentification
+{
+  m_basicAuthUser = user;
+  m_basicAuthPassword = password;
+}
+#endif
+
+HTTPResult HTTPClient::get(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
+{
+  return connect(url, HTTP_GET, NULL, pDataIn, timeout);
+}
+
+HTTPResult HTTPClient::get(const char* url, char* result, size_t maxResultLen, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
+{
+  HTTPText str(result, maxResultLen);
+  return get(url, &str, timeout);
+}
+
+HTTPResult HTTPClient::post(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
+{
+  return connect(url, HTTP_POST, (IHTTPDataOut*)&dataOut, pDataIn, timeout);
+}
+
+HTTPResult HTTPClient::put(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
+{
+  return connect(url, HTTP_PUT, (IHTTPDataOut*)&dataOut, pDataIn, timeout);
+}
+
+HTTPResult HTTPClient::del(const char* url, IHTTPDataIn* pDataIn, int timeout /*= HTTP_CLIENT_DEFAULT_TIMEOUT*/) //Blocking
+{
+  return connect(url, HTTP_DELETE, NULL, pDataIn, timeout);
+}
+
+
+int HTTPClient::getHTTPResponseCode()
+{
+  return m_httpResponseCode;
+}
+
+#define CHECK_CONN_ERR(ret) \
+  do{ \
+    if(ret) { \
+      m_sock.close(); \
+      ERR("Connection error (%d)", ret); \
+      return HTTP_CONN; \
+    } \
+  } while(0)
+
+#define PRTCL_ERR() \
+  do{ \
+    m_sock.close(); \
+    ERR("Protocol error"); \
+    return HTTP_PRTCL; \
+  } while(0)
+
+HTTPResult HTTPClient::connect(const char* url, HTTP_METH method, IHTTPDataOut* pDataOut, IHTTPDataIn* pDataIn, int timeout) //Execute request
+{ 
+  m_httpResponseCode = 0; //Invalidate code
+  m_timeout = timeout;
+  
+  pDataIn->writeReset();
+  if( pDataOut )
+  {
+    pDataOut->readReset();
+  }
+
+  char scheme[8];
+  uint16_t port;
+  char host[32];
+  char path[64];
+  //First we need to parse the url (http[s]://host[:port][/[path]]) -- HTTPS not supported (yet?)
+  HTTPResult res = parseURL(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path));
+  if(res != HTTP_OK)
+  {
+    ERR("parseURL returned %d", res);
+    return res;
+  }
+
+  if(port == 0) //TODO do handle HTTPS->443
+  {
+    port = 80;
+  }
+
+  DBG("Scheme: %s", scheme);
+  DBG("Host: %s", host);
+  DBG("Port: %d", port);
+  DBG("Path: %s", path);
+
+  //Connect
+  DBG("Connecting socket to server");
+  int ret = m_sock.connect(host, port);
+  if (ret < 0)
+  {
+    m_sock.close();
+    ERR("Could not connect");
+    return HTTP_CONN;
+  }
+  //Send request
+  DBG("Sending request");
+  char buf[CHUNK_SIZE];
+  const char* meth = (method==HTTP_GET)?"GET":(method==HTTP_POST)?"POST":(method==HTTP_PUT)?"PUT":(method==HTTP_DELETE)?"DELETE":"";
+  snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\nHost: %s\r\n", meth, path, host); //Write request
+  ret = send(buf);
+  if(ret)
+  {
+    m_sock.close();
+    ERR("Could not write request");
+    return HTTP_CONN;
+  }
+
+  //Send all headers
+
+  //Send default headers
+  DBG("Sending headers");
+  if( pDataOut != NULL )
+  {
+    if( pDataOut->getIsChunked() )
+    {
+      ret = send("Transfer-Encoding: chunked\r\n");
+      CHECK_CONN_ERR(ret);
+    }
+    else
+    {
+      snprintf(buf, sizeof(buf), "Content-Length: %d\r\n", pDataOut->getDataLen());
+      ret = send(buf);
+      CHECK_CONN_ERR(ret);
+    }
+    char type[48];
+    if( pDataOut->getDataType(type, 48) == HTTP_OK )
+    {
+      snprintf(buf, sizeof(buf), "Content-Type: %s\r\n", type);
+      ret = send(buf);
+      CHECK_CONN_ERR(ret);
+    }
+    
+    //Send specific headers
+    while( pDataOut->getHeader(buf, sizeof(buf) - 3) ) //must have space left for CRLF + 0 terminating char
+    {
+      size_t headerlen = strlen(buf);
+      snprintf(buf + headerlen, sizeof(buf) - headerlen, "\r\n");
+      ret = send(buf);
+      CHECK_CONN_ERR(ret);
+    }
+  }
+  
+  //Send specific headers
+  while( pDataIn->getHeader(buf, sizeof(buf) - 3) )
+  {
+    size_t headerlen = strlen(buf);
+    snprintf(buf + headerlen, sizeof(buf) - headerlen, "\r\n");
+    ret = send(buf);
+    CHECK_CONN_ERR(ret);
+  }
+  
+  //Close headers
+  DBG("Headers sent");
+  ret = send("\r\n");
+  CHECK_CONN_ERR(ret);
+
+  size_t trfLen;
+  
+  //Send data (if available)
+  if( pDataOut != NULL )
+  {
+    DBG("Sending data");
+    while(true)
+    {
+      size_t writtenLen = 0;
+      pDataOut->read(buf, CHUNK_SIZE, &trfLen);
+      if( pDataOut->getIsChunked() )
+      {
+        //Write chunk header
+        char chunkHeader[16];
+        snprintf(chunkHeader, sizeof(chunkHeader), "%X\r\n", trfLen); //In hex encoding
+        ret = send(chunkHeader);
+        CHECK_CONN_ERR(ret);
+      }
+      else if( trfLen == 0 )
+      {
+        break;
+      }
+      if( trfLen != 0 )
+      {
+        ret = send(buf, trfLen);
+        CHECK_CONN_ERR(ret);
+      }
+
+      if( pDataOut->getIsChunked()  )
+      {
+        ret = send("\r\n"); //Chunk-terminating CRLF
+        CHECK_CONN_ERR(ret);
+      }
+      else
+      {
+        writtenLen += trfLen;
+        if( writtenLen >= pDataOut->getDataLen() )
+        {
+          break;
+        }
+      }
+
+      if( trfLen == 0 )
+      {
+        break;
+      }
+    }
+  }
+  
+  //Receive response
+  DBG("Receiving response");
+  ret = recv(buf, 1, CHUNK_SIZE - 1, &trfLen); //Read n bytes
+  CHECK_CONN_ERR(ret);
+
+  buf[trfLen] = '\0';
+
+  //Make sure we got the first response line
+  char* crlfPtr = NULL;
+  while( true )
+  {
+    crlfPtr = strstr(buf, "\r\n");
+  if(crlfPtr == NULL)
+  {
+      if( trfLen < CHUNK_SIZE - 1 )
+      {
+        size_t newTrfLen;
+        ret = recv(buf + trfLen, 1, CHUNK_SIZE - trfLen - 1, &newTrfLen);
+        trfLen += newTrfLen;
+        buf[trfLen] = '\0';
+        DBG("Read %d chars; In buf: [%s]", newTrfLen, buf);
+        CHECK_CONN_ERR(ret);
+        continue;
+      }
+      else
+      {
+    PRTCL_ERR();
+  }
+    }
+    break;
+  }
+
+  int crlfPos = crlfPtr - buf;
+  buf[crlfPos] = '\0';
+
+  //Parse HTTP response
+  //if( sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &m_httpResponseCode) != 1 )
+  if(crlfPos > 13)
+  {
+    buf[13] = '\0';
+  }
+  if( sscanf(buf, "HTTP/%*d.%*d %d", &m_httpResponseCode) != 1 ) //Kludge for newlib nano
+  {
+    //Cannot match string, error
+    ERR("Not a correct HTTP answer : %s\n", buf);
+    PRTCL_ERR();
+  }
+
+  if( (m_httpResponseCode < 200) || (m_httpResponseCode >= 300) )
+  {
+    //Did not return a 2xx code; TODO fetch headers/(&data?) anyway and implement a mean of writing/reading headers 
+    WARN("Response code %d", m_httpResponseCode);
+    PRTCL_ERR();
+  }
+
+  DBG("Reading headers");
+
+  memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well
+  trfLen -= (crlfPos + 2);
+
+  size_t recvContentLength = 0;
+  bool recvChunked = false;
+  bool recvLengthUnknown = true;
+  //Now get headers
+  while( true )
+  {
+    crlfPtr = strstr(buf, "\r\n");
+    if(crlfPtr == NULL)
+    {
+      if( trfLen < CHUNK_SIZE - 1 )
+      {
+        size_t newTrfLen;
+        ret = recv(buf + trfLen, 1, CHUNK_SIZE - trfLen - 1, &newTrfLen);
+        trfLen += newTrfLen;
+        buf[trfLen] = '\0';
+        DBG("Read %d chars; In buf: [%s]", newTrfLen, buf);
+        CHECK_CONN_ERR(ret);
+        continue;
+      }
+      else
+      {
+        PRTCL_ERR();
+      }
+    }
+
+    crlfPos = crlfPtr - buf;
+
+    if(crlfPos == 0) //End of headers
+    {
+      DBG("Headers read");
+      memmove(buf, &buf[2], trfLen - 2 + 1); //Be sure to move NULL-terminating char as well
+      trfLen -= 2;
+      break;
+    }
+
+    buf[crlfPos] = '\0';
+
+    char key[32];
+    char value[32];
+
+    //key[31] = '\0';
+    //value[31] = '\0';
+
+    memset(key, 0, 32);
+    memset(value, 0, 32);
+
+    //int n = sscanf(buf, "%31[^:]: %31[^\r\n]", key, value);
+    
+    int n = 0;
+    
+    char* keyEnd = strchr(buf, ':');
+    if(keyEnd != NULL)
+    {
+      *keyEnd = '\0';
+      if(strlen(buf) < 32)
+      {
+        strcpy(key, buf);
+        n++;
+        char* valueStart = keyEnd + 2;
+        if( (valueStart - buf) < crlfPos )
+        {
+          if(strlen(valueStart) < 32)
+          { 
+            strcpy(value, valueStart);
+            n++;
+          }
+        }
+      }
+    }
+    if ( n == 2 )
+    {
+      DBG("Read header : %s: %s\n", key, value);
+      if( !strcmp(key, "Content-Length") )
+      {
+        sscanf(value, "%d", &recvContentLength);
+        recvLengthUnknown = false;
+        pDataIn->setDataLen(recvContentLength);
+      }
+      else if( !strcmp(key, "Transfer-Encoding") )
+      {
+        if( !strcmp(value, "Chunked") || !strcmp(value, "chunked") )
+        {
+          recvChunked = true;
+          recvLengthUnknown = false;
+          pDataIn->setIsChunked(true);
+        }
+      }
+      else if( !strcmp(key, "Content-Type") )
+      {
+        pDataIn->setDataType(value);
+      }
+
+      memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2) + 1); //Be sure to move NULL-terminating char as well
+      trfLen -= (crlfPos + 2);
+
+    }
+    else
+    {
+      ERR("Could not parse header");
+      PRTCL_ERR();
+    }
+
+  }
+
+  //Receive data
+  DBG("Receiving data");
+  while(true)
+  {
+    size_t readLen = 0;
+
+    if( recvChunked )
+    {
+      //Read chunk header
+      bool foundCrlf;
+      do
+      {
+        foundCrlf = false;
+        crlfPos=0;
+        buf[trfLen]=0;
+        if(trfLen >= 2)
+        {
+          for(; crlfPos < trfLen - 2; crlfPos++)
+          {
+            if( buf[crlfPos] == '\r' && buf[crlfPos + 1] == '\n' )
+            {
+              foundCrlf = true;
+              break;
+            }
+          }
+        }
+        if(!foundCrlf) //Try to read more
+        {
+          if( trfLen < CHUNK_SIZE )
+          {
+            size_t newTrfLen;
+            ret = recv(buf + trfLen, 0, CHUNK_SIZE - trfLen - 1, &newTrfLen);
+            trfLen += newTrfLen;
+            CHECK_CONN_ERR(ret);
+            continue;
+          }
+          else
+          {
+            PRTCL_ERR();
+          }
+        }
+      } while(!foundCrlf);
+      buf[crlfPos] = '\0';
+      int n = sscanf(buf, "%x", &readLen);
+      if(n!=1)
+      {
+        ERR("Could not read chunk length");
+        PRTCL_ERR();
+      }
+
+      memmove(buf, &buf[crlfPos+2], trfLen - (crlfPos + 2)); //Not need to move NULL-terminating char any more
+      trfLen -= (crlfPos + 2);
+
+      if( readLen == 0 )
+      {
+        //Last chunk
+        break;
+      }
+    }
+    else
+    {
+      readLen = recvContentLength;
+    }
+
+    DBG("Retrieving %d bytes (%d bytes in buffer)", readLen, trfLen);
+
+    do
+    {
+      if(recvLengthUnknown )
+      {
+        readLen = trfLen;
+      }
+      pDataIn->write(buf, MIN(trfLen, readLen));
+      if(!recvLengthUnknown)
+      {
+        if( trfLen > readLen )
+        {
+          memmove(buf, &buf[readLen], trfLen - readLen);
+          trfLen -= readLen;
+          readLen = 0;
+        }
+        else
+        {
+          readLen -= trfLen;
+        }
+      }
+      else
+      {
+        trfLen = 0;
+      }
+
+      if(readLen || recvLengthUnknown)
+      {
+        ret = recv(buf, 1, CHUNK_SIZE - trfLen - 1, &trfLen);
+        if(recvLengthUnknown && (ret == HTTP_CLOSED))
+        {
+          //Write and exit
+          pDataIn->write(buf, trfLen);
+          break;
+        }
+        CHECK_CONN_ERR(ret);
+        if(recvLengthUnknown && (trfLen == 0))
+        {
+          break;
+        }
+      }
+    } while(readLen || recvLengthUnknown);
+
+    if( recvChunked )
+    {
+      if(trfLen < 2)
+      {
+        size_t newTrfLen;
+        //Read missing chars to find end of chunk
+        ret = recv(buf + trfLen, 2 - trfLen, CHUNK_SIZE - trfLen - 1, &newTrfLen);
+        CHECK_CONN_ERR(ret);
+        trfLen += newTrfLen;
+      }
+      if( (buf[0] != '\r') || (buf[1] != '\n') )
+      {
+        ERR("Format error");
+        PRTCL_ERR();
+      }
+      memmove(buf, &buf[2], trfLen - 2);
+      trfLen -= 2;
+    }
+    else
+    {
+      break;
+    }
+
+  }
+
+  m_sock.close();
+  DBG("Completed HTTP transaction");
+
+  return HTTP_OK;
+}
+
+HTTPResult HTTPClient::recv(char* buf, size_t minLen, size_t maxLen, size_t* pReadLen) //0 on success, err code on failure
+{
+  DBG("Trying to read between %d and %d bytes", minLen, maxLen);
+  size_t readLen = 0;
+      
+  if(!m_sock.is_connected())
+  {
+    WARN("Connection was closed by server");
+    return HTTP_CLOSED; //Connection was closed by server 
+  }
+    
+  int ret;
+  while(readLen < maxLen)
+  {
+    if(readLen < minLen)
+    {
+      DBG("Trying to read at most %d bytes [Blocking]", minLen - readLen);
+      m_sock.set_blocking(false, m_timeout);
+      ret = m_sock.receive_all(buf + readLen, minLen - readLen);
+    }
+    else
+    {
+      DBG("Trying to read at most %d bytes [Not blocking]", maxLen - readLen);
+      m_sock.set_blocking(false, 0);
+      ret = m_sock.receive(buf + readLen, maxLen - readLen);
+    }
+    
+    if( ret > 0)
+    {
+      readLen += ret;
+    }
+    else if( ret == 0 )
+    {
+      break;
+    }
+    else
+    {
+      if(!m_sock.is_connected())
+      {
+        ERR("Connection error (recv returned %d)", ret);
+        *pReadLen = readLen;
+        return HTTP_CONN;
+      }
+      else
+      {
+        break;      
+      }
+    }
+    
+    if(!m_sock.is_connected())
+    {
+      break;
+    }
+  }
+  DBG("Read %d bytes", readLen);
+  *pReadLen = readLen;
+  return HTTP_OK;
+}
+
+HTTPResult HTTPClient::send(char* buf, size_t len) //0 on success, err code on failure
+{
+  if(len == 0)
+  {
+    len = strlen(buf);
+  }
+  DBG("Trying to write %d bytes", len);
+  size_t writtenLen = 0;
+    
+  if(!m_sock.is_connected())
+  {
+    WARN("Connection was closed by server");
+    return HTTP_CLOSED; //Connection was closed by server 
+  }
+  
+  m_sock.set_blocking(false, m_timeout);
+  int ret = m_sock.send_all(buf, len);
+  if(ret > 0)
+  {
+    writtenLen += ret;
+  }
+  else if( ret == 0 )
+  {
+    WARN("Connection was closed by server");
+    return HTTP_CLOSED; //Connection was closed by server
+  }
+  else
+  {
+    ERR("Connection error (send returned %d)", ret);
+    return HTTP_CONN;
+  }
+  
+  DBG("Written %d bytes", writtenLen);
+  return HTTP_OK;
+}
+
+HTTPResult HTTPClient::parseURL(const char* url, char* scheme, size_t maxSchemeLen, char* host, size_t maxHostLen, uint16_t* port, char* path, size_t maxPathLen) //Parse URL
+{
+  char* schemePtr = (char*) url;
+  char* hostPtr = (char*) strstr(url, "://");
+  if(hostPtr == NULL)
+  {
+    WARN("Could not find host");
+    return HTTP_PARSE; //URL is invalid
+  }
+
+  if( maxSchemeLen < hostPtr - schemePtr + 1 ) //including NULL-terminating char
+  {
+    WARN("Scheme str is too small (%d >= %d)", maxSchemeLen, hostPtr - schemePtr + 1);
+    return HTTP_PARSE;
+  }
+  memcpy(scheme, schemePtr, hostPtr - schemePtr);
+  scheme[hostPtr - schemePtr] = '\0';
+
+  hostPtr+=3;
+
+  size_t hostLen = 0;
+
+  char* portPtr = strchr(hostPtr, ':');
+  if( portPtr != NULL )
+  {
+    hostLen = portPtr - hostPtr;
+    portPtr++;
+    if( sscanf(portPtr, "%hu", port) != 1)
+    {
+      WARN("Could not find port");
+      return HTTP_PARSE;
+    }
+  }
+  else
+  {
+    *port=0;
+  }
+  char* pathPtr = strchr(hostPtr, '/');
+  if( hostLen == 0 )
+  {
+    hostLen = pathPtr - hostPtr;
+  }
+
+  if( maxHostLen < hostLen + 1 ) //including NULL-terminating char
+  {
+    WARN("Host str is too small (%d >= %d)", maxHostLen, hostLen + 1);
+    return HTTP_PARSE;
+  }
+  memcpy(host, hostPtr, hostLen);
+  host[hostLen] = '\0';
+
+  size_t pathLen;
+  char* fragmentPtr = strchr(hostPtr, '#');
+  if(fragmentPtr != NULL)
+  {
+    pathLen = fragmentPtr - pathPtr;
+  }
+  else
+  {
+    pathLen = strlen(pathPtr);
+  }
+
+  if( maxPathLen < pathLen + 1 ) //including NULL-terminating char
+  {
+    WARN("Path str is too small (%d >= %d)", maxPathLen, pathLen + 1);
+    return HTTP_PARSE;
+  }
+  memcpy(path, pathPtr, pathLen);
+  path[pathLen] = '\0';
+  
+  return HTTP_OK;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPClient/HTTPClient.h	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,159 @@
+/* HTTPClient.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/** \file
+HTTP Client header file
+*/
+
+#ifndef HTTP_CLIENT_H
+#define HTTP_CLIENT_H
+
+#include "TCPSocketConnection.h"
+
+#define HTTP_CLIENT_DEFAULT_TIMEOUT 15000
+
+class HTTPData;
+
+#include "IHTTPData.h"
+#include "mbed.h"
+
+///HTTP client results
+enum HTTPResult
+{
+  HTTP_PROCESSING, ///<Processing
+  HTTP_PARSE, ///<url Parse error
+  HTTP_DNS, ///<Could not resolve name
+  HTTP_PRTCL, ///<Protocol error
+  HTTP_NOTFOUND, ///<HTTP 404 Error
+  HTTP_REFUSED, ///<HTTP 403 Error
+  HTTP_ERROR, ///<HTTP xxx error
+  HTTP_TIMEOUT, ///<Connection timeout
+  HTTP_CONN, ///<Connection error
+  HTTP_CLOSED, ///<Connection was closed by remote host
+  HTTP_OK = 0, ///<Success
+};
+
+/**A simple HTTP Client
+The HTTPClient is composed of:
+- The actual client (HTTPClient)
+- Classes that act as a data repository, each of which deriving from the HTTPData class (HTTPText for short text content, HTTPFile for file I/O, HTTPMap for key/value pairs, and HTTPStream for streaming purposes)
+*/
+class HTTPClient
+{
+public:
+  ///Instantiate the HTTP client
+  HTTPClient();
+  ~HTTPClient();
+  
+#if 0 //TODO add header handlers
+  /**
+  Provides a basic authentification feature (Base64 encoded username and password)
+  Pass two NULL pointers to switch back to no authentication
+  @param user username to use for authentication, must remain valid durlng the whole HTTP session
+  @param user password to use for authentication, must remain valid durlng the whole HTTP session
+  */
+  void basicAuth(const char* user, const char* password); //Basic Authentification
+#endif
+  
+  //High Level setup functions
+  /** Execute a GET request on the URL
+  Blocks until completion
+  @param url : url on which to execute the request
+  @param pDataIn : pointer to an IHTTPDataIn instance that will collect the data returned by the request, can be NULL
+  @param timeout waiting timeout in ms (osWaitForever for blocking function, not recommended)
+  @return 0 on success, HTTP error (<0) on failure
+  */
+  HTTPResult get(const char* url, IHTTPDataIn* pDataIn, int timeout = HTTP_CLIENT_DEFAULT_TIMEOUT); //Blocking
+  
+  /** Execute a GET request on the URL
+  Blocks until completion
+  This is a helper to directly get a piece of text from a HTTP result
+  @param url : url on which to execute the request
+  @param result : pointer to a char array in which the result will be stored
+  @param maxResultLen : length of the char array (including space for the NULL-terminating char)
+  @param timeout waiting timeout in ms (osWaitForever for blocking function, not recommended)
+  @return 0 on success, HTTP error (<0) on failure
+  */
+  HTTPResult get(const char* url, char* result, size_t maxResultLen, int timeout = HTTP_CLIENT_DEFAULT_TIMEOUT); //Blocking
+
+  /** Execute a POST request on the URL
+  Blocks until completion
+  @param url : url on which to execute the request
+  @param dataOut : a IHTTPDataOut instance that contains the data that will be posted
+  @param pDataIn : pointer to an IHTTPDataIn instance that will collect the data returned by the request, can be NULL
+  @param timeout waiting timeout in ms (osWaitForever for blocking function, not recommended)
+  @return 0 on success, HTTP error (<0) on failure
+  */
+  HTTPResult post(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout = HTTP_CLIENT_DEFAULT_TIMEOUT); //Blocking
+  
+  /** Execute a PUT request on the URL
+  Blocks until completion
+  @param url : url on which to execute the request
+  @param dataOut : a IHTTPDataOut instance that contains the data that will be put
+  @param pDataIn : pointer to an IHTTPDataIn instance that will collect the data returned by the request, can be NULL
+  @param timeout waiting timeout in ms (osWaitForever for blocking function, not recommended)
+  @return 0 on success, HTTP error (<0) on failure
+  */
+  HTTPResult put(const char* url, const IHTTPDataOut& dataOut, IHTTPDataIn* pDataIn, int timeout = HTTP_CLIENT_DEFAULT_TIMEOUT); //Blocking
+  
+  /** Execute a DELETE request on the URL
+  Blocks until completion
+  @param url : url on which to execute the request
+  @param pDataIn : pointer to an IHTTPDataIn instance that will collect the data returned by the request, can be NULL
+  @param timeout waiting timeout in ms (osWaitForever for blocking function, not recommended)
+  @return 0 on success, HTTP error (<0) on failure
+  */
+  HTTPResult del(const char* url, IHTTPDataIn* pDataIn, int timeout = HTTP_CLIENT_DEFAULT_TIMEOUT); //Blocking
+  
+  /** Get last request's HTTP response code
+  @return The HTTP response code of the last request
+  */
+  int getHTTPResponseCode();
+  
+private:
+  enum HTTP_METH
+  {
+    HTTP_GET,
+    HTTP_POST,
+    HTTP_PUT,
+    HTTP_DELETE,
+    HTTP_HEAD
+  };
+
+  HTTPResult connect(const char* url, HTTP_METH method, IHTTPDataOut* pDataOut, IHTTPDataIn* pDataIn, int timeout); //Execute request
+  HTTPResult recv(char* buf, size_t minLen, size_t maxLen, size_t* pReadLen); //0 on success, err code on failure
+  HTTPResult send(char* buf, size_t len = 0); //0 on success, err code on failure
+  HTTPResult parseURL(const char* url, char* scheme, size_t maxSchemeLen, char* host, size_t maxHostLen, uint16_t* port, char* path, size_t maxPathLen); //Parse URL
+
+  //Parameters
+  TCPSocketConnection m_sock;
+  
+  int m_timeout;
+
+  const char* m_basicAuthUser;
+  const char* m_basicAuthPassword;
+  int m_httpResponseCode;
+
+};
+
+//Including data containers here for more convenience
+#include "data/HTTPText.h"
+#include "data/HTTPMap.h"
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPClient/IHTTPData.h	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,105 @@
+/* IHTTPData.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef IHTTPDATA_H
+#define IHTTPDATA_H
+
+#include <cstring>
+
+using std::size_t;
+
+class IHTTPData
+{
+  protected:
+  /** Get a specific header
+  *
+  */
+  virtual bool getHeader(char* header, size_t maxHeaderLen) { return false; }
+};
+
+///This is a simple interface for HTTP data storage (impl examples are Key/Value Pairs, File, etc...)
+class IHTTPDataOut : public IHTTPData
+{
+protected:
+  friend class HTTPClient;
+  
+  /** Reset stream to its beginning 
+   * Called by the HTTPClient on each new request
+   */
+  virtual void readReset() = 0;
+
+  /** Read a piece of data to be transmitted
+   * @param buf Pointer to the buffer on which to copy the data
+   * @param len Length of the buffer
+   * @param pReadLen Pointer to the variable on which the actual copied data length will be stored
+   */
+  virtual int read(char* buf, size_t len, size_t* pReadLen) = 0;
+  
+  /** Get MIME type
+   * @param type Internet media type from Content-Type header
+   */
+  virtual int getDataType(char* type, size_t maxTypeLen) = 0; //Internet media type for Content-Type header
+  
+  /** Determine whether the HTTP client should chunk the data
+   *  Used for Transfer-Encoding header
+   */
+  virtual bool getIsChunked() = 0;
+  
+  /** If the data is not chunked, get its size
+   *  Used for Content-Length header
+   */
+  virtual size_t getDataLen() = 0;
+
+};
+
+///This is a simple interface for HTTP data storage (impl examples are Key/Value Pairs, File, etc...)
+class IHTTPDataIn : public IHTTPData
+{
+protected:
+  friend class HTTPClient;
+
+  /** Reset stream to its beginning 
+   * Called by the HTTPClient on each new request
+   */
+  virtual void writeReset() = 0;
+
+  /** Write a piece of data transmitted by the server
+   * @param buf Pointer to the buffer from which to copy the data
+   * @param len Length of the buffer
+   */
+  virtual int write(const char* buf, size_t len) = 0;
+
+  /** Set MIME type
+   * @param type Internet media type from Content-Type header
+   */
+  virtual void setDataType(const char* type) = 0;
+
+  /** Determine whether the data is chunked
+   *  Recovered from Transfer-Encoding header
+   */
+  virtual void setIsChunked(bool chunked) = 0;
+  
+  /** If the data is not chunked, set its size
+   * From Content-Length header
+   */
+  virtual void setDataLen(size_t len) = 0;
+
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPClient/data/HTTPMap.cpp	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,200 @@
+/* HTTPMap.cpp */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "HTTPMap.h"
+
+#include <cstring>
+
+#include <cctype>
+
+#define OK 0
+
+using std::strncpy;
+
+HTTPMap::HTTPMap() : m_pos(0), m_count(0)
+{
+
+}
+
+void HTTPMap::put(const char* key, const char* value)
+{
+  if(m_count >= HTTPMAP_TABLE_SIZE)
+  {
+    return;
+  }
+  m_keys[m_count] = key;
+  m_values[m_count] = value;
+  m_count++;
+}
+
+void HTTPMap::clear()
+{
+  m_count = 0;
+  m_pos = 0;
+}
+
+/*virtual*/ void HTTPMap::readReset()
+{
+  m_pos = 0;
+}
+
+/*virtual*/ int HTTPMap::read(char* buf, size_t len, size_t* pReadLen)
+{
+  if(m_pos >= m_count)
+  {
+    *pReadLen = 0;
+    m_pos = 0;
+    return OK;
+  }
+
+  //URL encode
+  char* out = buf;
+  const char* in = m_keys[m_pos];
+  if( (m_pos != 0) && (out - buf < len - 1) )
+  {
+    *out='&';
+    out++;
+  }
+
+  while( (*in != '\0') && (out - buf < len - 3) )
+  {
+    if (std::isalnum(*in) || *in == '-' || *in == '_' || *in == '.' || *in == '~')
+    {
+      *out = *in;
+      out++;
+    }
+    else if( *in == ' ' )
+    {
+      *out='+';
+      out++;
+    }
+    else
+    {
+      char hex[] = "0123456789abcdef";
+      *out='%';
+      out++;
+      *out=hex[(*in>>4)&0xf];
+      out++;
+      *out=hex[(*in)&0xf];
+      out++;
+    }
+    in++;
+  }
+
+  if( out - buf < len - 1 )
+  {
+    *out='=';
+    out++;
+  }
+
+  in = m_values[m_pos];
+  while( (*in != '\0') && (out - buf < len - 3) )
+  {
+    if (std::isalnum(*in) || *in == '-' || *in == '_' || *in == '.' || *in == '~')
+    {
+      *out = *in;
+      out++;
+    }
+    else if( *in == ' ' )
+    {
+      *out='+';
+      out++;
+    }
+    else
+    {
+      char hex[] = "0123456789abcdef";
+      *out='%';
+      out++;
+      *out=hex[(*in>>4)&0xf];
+      out++;
+      *out=hex[(*in)&0xf];
+      out++;
+    }
+    in++;
+  }
+
+  *pReadLen = out - buf;
+
+  m_pos++;
+  return OK;
+}
+
+/*virtual*/ int HTTPMap::getDataType(char* type, size_t maxTypeLen) //Internet media type for Content-Type header
+{
+  strncpy(type, "application/x-www-form-urlencoded", maxTypeLen-1);
+  type[maxTypeLen-1] = '\0';
+  return OK;
+}
+
+/*virtual*/ bool HTTPMap::getIsChunked() //For Transfer-Encoding header
+{
+  return false; ////Data is computed one key/value pair at a time
+}
+
+/*virtual*/ size_t HTTPMap::getDataLen() //For Content-Length header
+{
+  size_t count = 0;
+  for(size_t i = 0; i< m_count; i++)
+  {
+    //URL encode
+    const char* in = m_keys[i];
+    if( i != 0 )
+    {
+      count++;
+    }
+
+    while( (*in != '\0') )
+    {
+      if (std::isalnum(*in) || *in == '-' || *in == '_' || *in == '.' || *in == '~')
+      {
+        count++;
+      }
+      else if( *in == ' ' )
+      {
+        count++;
+      }
+      else
+      {
+        count+=3;
+      }
+      in++;
+    }
+
+    count ++;
+
+    in = m_values[i];
+    while( (*in != '\0') )
+    {
+      if (std::isalnum(*in) || *in == '-' || *in == '_' || *in == '.' || *in == '~')
+      {
+        count++;
+      }
+      else if( *in == ' ' )
+      {
+        count++;
+      }
+      else
+      {
+        count+=3;
+      }
+      in++;
+    }
+  }
+  return count;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPClient/data/HTTPMap.h	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,71 @@
+/* HTTPMap.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef HTTPMAP_H_
+#define HTTPMAP_H_
+
+#include "../IHTTPData.h"
+
+#define HTTPMAP_TABLE_SIZE 32
+
+/** Map of key/value pairs
+ * Used to transmit POST data using the application/x-www-form-urlencoded encoding
+ */
+class HTTPMap: public IHTTPDataOut
+{
+public:
+  /**
+   Instantiates HTTPMap
+   It supports at most 32 key/values pairs
+   */
+  HTTPMap();
+
+  /** Put Key/Value pair
+   The references to the parameters must remain valid as long as the clear() function is not called
+   @param key The key to use
+   @param value The corresponding value
+   */
+  void put(const char* key, const char* value);
+
+  /** Clear table
+   */
+  void clear();
+
+protected:
+  //IHTTPDataIn
+  virtual void readReset();
+
+  virtual int read(char* buf, size_t len, size_t* pReadLen);
+
+  virtual int getDataType(char* type, size_t maxTypeLen); //Internet media type for Content-Type header
+
+  virtual bool getIsChunked(); //For Transfer-Encoding header
+
+  virtual size_t getDataLen(); //For Content-Length header
+
+private:
+  const char* m_keys[HTTPMAP_TABLE_SIZE];
+  const char* m_values[HTTPMAP_TABLE_SIZE];
+
+  size_t m_pos;
+  size_t m_count;
+};
+
+#endif /* HTTPMAP_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPClient/data/HTTPText.cpp	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,108 @@
+/* HTTPText.cpp */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "HTTPText.h"
+
+#include <cstring>
+
+#define OK 0
+
+using std::memcpy;
+using std::strncpy;
+using std::strlen;
+
+#define MIN(x,y) (((x)<(y))?(x):(y))
+
+HTTPText::HTTPText(char* str) : m_str(str), m_pos(0)
+{
+  m_size = strlen(str) + 1;
+}
+
+HTTPText::HTTPText(char* str, size_t size) : m_str(str), m_size(size), m_pos(0)
+{
+
+}
+
+//IHTTPDataIn
+/*virtual*/ void HTTPText::readReset()
+{
+  m_pos = 0;
+}
+
+/*virtual*/ int HTTPText::read(char* buf, size_t len, size_t* pReadLen)
+{
+  *pReadLen = MIN(len, m_size - 1 - m_pos);
+  memcpy(buf, m_str + m_pos, *pReadLen);
+  m_pos += *pReadLen;
+  return OK;
+}
+
+/*virtual*/ int HTTPText::getDataType(char* type, size_t maxTypeLen) //Internet media type for Content-Type header
+{
+#if 1
+  strncpy(type, "application/json", maxTypeLen-1);
+#else
+  strncpy(type, "text/plain", maxTypeLen-1);
+#endif
+  type[maxTypeLen-1] = '\0';
+  return OK;
+}
+
+/*virtual*/ bool HTTPText::getIsChunked() //For Transfer-Encoding header
+{
+  return false;
+}
+
+/*virtual*/ size_t HTTPText::getDataLen() //For Content-Length header
+{
+  return m_size - 1;
+}
+
+//IHTTPDataOut
+/*virtual*/ void HTTPText::writeReset()
+{
+  m_pos = 0;
+}
+
+/*virtual*/ int HTTPText::write(const char* buf, size_t len)
+{
+  size_t writeLen = MIN(len, m_size - 1 - m_pos);
+  memcpy(m_str + m_pos, buf, writeLen);
+  m_pos += writeLen;
+  m_str[m_pos] = '\0';
+  return OK;
+}
+
+/*virtual*/ void HTTPText::setDataType(const char* type) //Internet media type from Content-Type header
+{
+
+}
+
+/*virtual*/ void HTTPText::setIsChunked(bool chunked) //From Transfer-Encoding header
+{
+
+}
+
+/*virtual*/ void HTTPText::setDataLen(size_t len) //From Content-Length header, or if the transfer is chunked, next chunk length
+{
+
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPClient/data/HTTPText.h	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,72 @@
+/* HTTPText.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef HTTPTEXT_H_
+#define HTTPTEXT_H_
+
+#include "../IHTTPData.h"
+
+/** A data endpoint to store text
+*/
+class HTTPText : public IHTTPDataIn, public IHTTPDataOut
+{
+public:
+  /** Create an HTTPText instance for output
+   * @param str String to be transmitted
+   */
+  HTTPText(char* str);
+
+  /** Create an HTTPText instance for input
+   * @param str Buffer to store the incoming string
+   * @param size Size of the buffer
+   */
+  HTTPText(char* str, size_t size);
+
+protected:
+  //IHTTPDataIn
+  virtual void readReset();
+  
+  virtual int read(char* buf, size_t len, size_t* pReadLen);
+
+  virtual int getDataType(char* type, size_t maxTypeLen); //Internet media type for Content-Type header
+
+  virtual bool getIsChunked(); //For Transfer-Encoding header
+
+  virtual size_t getDataLen(); //For Content-Length header
+
+  //IHTTPDataOut
+  virtual void writeReset();
+  
+  virtual int write(const char* buf, size_t len);
+
+  virtual void setDataType(const char* type); //Internet media type from Content-Type header
+
+  virtual void setIsChunked(bool chunked); //From Transfer-Encoding header
+
+  virtual void setDataLen(size_t len); //From Content-Length header, or if the transfer is chunked, next chunk length
+
+private:
+  char* m_str;
+  size_t m_size;
+
+  size_t m_pos;
+};
+
+#endif /* HTTPTEXT_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IFTTT/ifttt.cpp	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,220 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mbed.h"
+#include "ifttt.h"
+//#include <string>
+
+#if 0
+#define DBG(x, ...)  pc.printf("[IFTTT : DBG]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__);
+#define WARN(x, ...) pc.printf("[IFTTT : WARN]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__);
+#define ERR(x, ...)  pc.printf("[IFTTT : ERR]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__);
+#else
+#define DBG(x, ...) //wait_us(10);
+#define WARN(x, ...) //wait_us(10);
+#define ERR(x, ...)
+#endif
+
+#if 0
+#define INFO(x, ...) pc.printf("[IFTTT : INFO]"x" \r\n",##__VA_ARGS__);
+#else
+#define INFO(x, ...)
+#endif
+
+//
+// Initialize object with Event, Key, and valid socket.
+// TODO: accept hostname parameter / implement DNS lookup
+//
+IFTTT::IFTTT(const char * event, const char * key, TCPSocketConnection * s)
+{
+    // Error Check
+    if(sizeof(event) > IFTTT_MAX_SIZE_EVENTNAME) {
+        ERR("Given event > IFTTT_MAX_SIZE_EVENTNAME, increase the max event string size in ifttt.h");
+    }
+    if(sizeof(key) > IFTTT_MAX_SIZE_SECRETKEY) {
+        ERR("Given key > IFTTT_MAX_SIZE_SECRETKEY, increase the max secret key string size in ifttt.h");
+    }
+    // Copy event name and secret key into object instance
+    strcpy(this->eventName,event);
+    strcpy(this->secretKey,key);
+
+    // Set up Socket
+    if(NULL == s) {
+        WARN("Given Socket Pointer is NULL, will try opening a socket.");
+    }
+    this->socket = s;
+
+    // Set up Host / Port
+    this->port = IFTTT_PORT;
+    this->host = IFTTT_IP;
+    
+    // Initialize ingredient values to empty strings.
+    v1 = "";
+    v2 = "";
+    v3 = "";
+}
+
+//
+// Add ingredients to be sent.
+//
+bool
+IFTTT::addIngredients( char * value1,  char * value2,  char * value3)
+{
+    // update internal pointers. If variable not given then pass an empty string
+    v1 = (NULL == value1)?"":value1;
+    v2 = (NULL == value2)?"":value2;
+    v3 = (NULL == value3)?"":value3;
+    return true;
+}
+
+//
+// This function sends data to maker.ifttt.org via GET query commands
+// return true on sucess, false on fail
+//
+bool IFTTT::get()
+{
+    // Connect to maker.ifttt.org
+    int retry = 0;
+    for(retry=0; retry<IFTTT_MAX_RETRY; retry++) {
+        int ret = this->socket->connect(this->host, this->port);
+        if(ret == 0) {
+            DBG("Successfully Connected socket to host");
+            break ;
+        }
+    }
+    if(retry == IFTTT_MAX_RETRY) {
+        this->socket->close();
+        ERR("Could not connect socket to host\r\n");
+        return false;
+    }
+
+    // Prep data to send
+    // TODO: verify / modify data to be query string compliant (convert spaces to '+', convert non-alpha-numberic characters to the proper encoding... etc)
+    char str[IFTTT_MAX_SIZE_STRING] = {0};
+    sprintf(str, "GET /trigger/%s/with/key/%s/?value1=%s&value2=%s&value3=%s HTTP/1.1\r\nHost: maker.ifttt.com\r\n\r\n",eventName,secretKey,v1,v2,v3);
+    DBG("String to send is:\n\r%s",str);
+
+    // Send Data
+    DBG("Sending GET data...");
+    int check = 0;
+    check = this->socket->send_all(str,sizeof(str));
+    if(check) {
+        DBG("Sent Sucessfully %d bytes",check);
+    } else {
+        ERR("Sending failed");
+        return false;
+    }
+    DBG("Waiting on reply ... \r\n");
+    int ret = this->socket->receive(str,50);
+    str[ret]=0;
+    DBG("Received String : %s",str);
+    this->socket->close();
+
+    return true;
+}
+
+//
+// This function sends JSON encoded data encoded in a POST packet, 
+//
+bool IFTTT::post()
+{
+    // Connect to maker.ifttt.org
+    int retry = 0;
+    for(retry=0; retry<IFTTT_MAX_RETRY; retry++) {
+        int ret = this->socket->connect(this->host, this->port);
+        if(ret == 0) {
+            DBG("Successfully Connected socket to host");
+            break ;
+        }
+    }
+    if(retry == IFTTT_MAX_RETRY) {
+        this->socket->close();
+        ERR("Could not connect socket to host\r\n");
+        return false;
+    }
+
+    // Prep data to send, the Assembled POST packet should look like this
+    //
+    //
+    //POST /trigger/<eventName>/with/key/<secretKey> HTTP/1.1
+    //Host: maker.ifttt.com
+    //Content-Length: <length of POST data>
+    //Content-Type: application/json
+    //
+    //{"value1":"<v1>","value2":"<v2>","value3":"<v3>"}
+    //
+    //
+    char str[IFTTT_MAX_SIZE_STRING] = {0};
+    char header[100] = {0};
+    sprintf(header, "POST /trigger/%s/with/key/%s HTTP/1.1\r\n",eventName,secretKey);
+    const char * host = "Host: maker.ifttt.com\r\n";
+    char contentLen[50] = {0};
+    const char * contentType = "Content-Type: application/json\r\n\r\n";
+    char valueData [150] = {0};
+    sprintf(valueData,"{\"value1\":\"%s\",\"value2\":\"%s\",\"value3\":\"%s\"}\r\n",v1,v2,v3);
+    sprintf(contentLen,"Content-Length: %d\r\n",strlen(valueData));
+    sprintf(str,"%s%s%s%s%s",header,host,contentLen,contentType,valueData);
+
+    DBG("String to send is:\n\r%s",str);
+
+    // Send Data
+    DBG("Sending POST data...");
+    int check = 0;
+    check = this->socket->send_all(str,strlen(str));
+    if(check) {
+        DBG("Sent Sucessfully %d bytes",check);
+    } else {
+        ERR("Sending failed");
+        return false;
+    }
+    DBG("Waiting on reply ... \r\n");
+    int ret = this->socket->receive(str,IFTTT_MAX_SIZE_STRING);
+    str[ret]=0;
+    DBG("Received String : %s",str);
+    this->socket->close();
+
+    return true;
+}
+
+//
+// Send trigger and any values associated to maker.ifttt.com
+// currently  unsecured (sends over HTTP, not https)
+//
+bool
+IFTTT::trigger(int triggerType)
+{
+    int ret = 0;
+    switch(triggerType) {
+        case IFTTT_GET:
+            DBG("Sending Data as GET request");
+            ret = get();
+            break;
+        case IFTTT_POST:
+            DBG("Sending Data as POST request");
+            ret = post();
+            break;
+
+        default:
+            WARN("Invalid type, defaulting to sending data as POST request");
+            ret = post();
+            break;
+    }
+    DBG("Sending Data return code : %d",ret);
+    if(ret){
+    INFO("Successfully triggered event: '%s' with v1='%s', v2='%s', v3='%s' !",eventName,v1,v2,v3);
+    }
+    return ret;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IFTTT/ifttt.h	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,115 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef IFTTT_H
+#define IFTTT_H
+
+#include "mbed.h"
+#include "TCPSocketConnection.h"
+
+#define IFTTT_FAIL -1
+#define IFTTT_SUCCESS 0
+
+#define IFTTT_MAX_RETRY 5
+#define IFTTT_MAX_SIZE_SECRETKEY 50
+#define IFTTT_MAX_SIZE_EVENTNAME 50
+#define IFTTT_MAX_SIZE_STRING 512
+
+#define IFTTT_IP "maker.ifttt.com"
+#define IFTTT_PORT 80
+
+#define IFTTT_GET 0
+#define IFTTT_POST 1
+
+
+/**
+* The IFTTT class (if this then that)
+*/
+class IFTTT
+{
+
+public:
+
+    /**
+    * Constructor, initialize the Event Name and Secret Key to be used
+    *
+    * @param event event name of trigger
+    * @param key secret key provided by the maker channel for your event
+    */
+    IFTTT(const char * event, const char * key, TCPSocketConnection * s = NULL);
+
+    /**
+    * Add ingredients (values) to be sent to maker.ifttt.com
+    *
+    * @param v1 value 1 to send
+    * @param v2 value 2 to send
+    * @param v3 value 3 to send
+    *
+    * @return true if successful, false if failed
+    */
+    bool addIngredients(char * v1 = NULL, char * v2 = NULL, char * v3 = NULL);
+
+    /**
+    * Add ingredients (values) to be sent to maker.ifttt.com
+    *
+    * @param v1 value 1 to send
+    * @param v2 value 2 to send
+    * @param v3 value 3 to send
+    *
+    * @return true if successful, false if failed
+    */
+    bool addIngredients(int v1 = NULL, int v2 = NULL, int v3 = NULL);
+
+    /**
+    * Send data via POST or GET to maker.ifttt.com
+    *
+    * @param iftttType specifies how to send the data. POST by default, GET optional.
+    *
+    * @return true if successful, false if failed
+    */
+    bool trigger(int triggerType = IFTTT_POST);
+
+private:
+
+    /**
+    * Send data to maker.ifttt.com via GET Query parameters
+    *
+    * @param name explanation
+    *
+    * @return true if successful, false if failed
+    */
+    bool get();
+
+    /**
+    * Send data to maker.ifttt.com via POST payload, encoded as JSON
+    *
+    * @param name explanation
+    *
+    * @return true if successful, false if failed
+    */
+    bool post();
+
+    TCPSocketConnection * socket;
+    char eventName[IFTTT_MAX_SIZE_EVENTNAME];
+    char secretKey[IFTTT_MAX_SIZE_SECRETKEY];
+    const char * v1;
+    const char * v2;
+    const char * v3;
+    const char * host;
+    int port;
+
+};
+
+#endif // IFTTT_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LM75B.lib	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/neilt6/code/LM75B/#7ac462ba84ac
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,26 @@
+#include "mbed.h"
+#include "ESP8266Interface.h"
+#include "TCPSocketConnection.h"
+#include "ifttt.h"
+#include "LM75B.h"
+
+LM75B sensor(dp5, dp27);
+ESP8266Interface wifi(dp16,dp15,dp4,"SSID","Password",115200); // TX,RX,Reset,SSID,Password,Baud
+
+int main()
+{
+    char value[64];
+    
+    wifi.init(); //Reset
+    wifi.connect(); //Use DHCP
+    
+    TCPSocketConnection socket;
+    
+    // Initialize ifttt object, add up to 3 optional values, trigger event. 
+    IFTTT ifttt("EverntName","Secret Key", &socket); // EventName, Secret Key, socket to use
+    
+    sprintf(value,"%.3f", (float)sensor);
+
+    ifttt.addIngredients(value,"value2","value3");
+    ifttt.trigger(IFTTT_POST);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sun May 15 11:47:02 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/082adc85693f
\ No newline at end of file