MultiIoTBoard library
Revision 0:bad9495b4215, committed 2017-07-28
- Comitter:
- jksoft
- Date:
- Fri Jul 28 02:23:25 2017 +0000
- Commit message:
- First edition
Changed in this revision
diff -r 000000000000 -r bad9495b4215 BME280.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BME280.lib Fri Jul 28 02:23:25 2017 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/users/MACRUM/code/BME280/#ddcaa259e65b
diff -r 000000000000 -r bad9495b4215 ESP8266InterfaceTiny/ESP8266/CBuffer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ESP8266InterfaceTiny/ESP8266/CBuffer.h Fri Jul 28 02:23:25 2017 +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
diff -r 000000000000 -r bad9495b4215 ESP8266InterfaceTiny/ESP8266/ESP8266.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ESP8266InterfaceTiny/ESP8266/ESP8266.cpp Fri Jul 28 02:23:25 2017 +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, ...) printf("[ESP8266 : DBG]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); +#define WARN(x, ...) printf("[ESP8266 : WARN]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); +#define ERR(x, ...) 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; +}
diff -r 000000000000 -r bad9495b4215 ESP8266InterfaceTiny/ESP8266/ESP8266.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ESP8266InterfaceTiny/ESP8266/ESP8266.h Fri Jul 28 02:23:25 2017 +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
diff -r 000000000000 -r bad9495b4215 ESP8266InterfaceTiny/ESP8266Interface.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ESP8266InterfaceTiny/ESP8266Interface.cpp Fri Jul 28 02:23:25 2017 +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
diff -r 000000000000 -r bad9495b4215 ESP8266InterfaceTiny/ESP8266Interface.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ESP8266InterfaceTiny/ESP8266Interface.h Fri Jul 28 02:23:25 2017 +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_ */
diff -r 000000000000 -r bad9495b4215 ESP8266InterfaceTiny/Helper/def.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ESP8266InterfaceTiny/Helper/def.h Fri Jul 28 02:23:25 2017 +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
diff -r 000000000000 -r bad9495b4215 ESP8266InterfaceTiny/Socket/Endpoint.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ESP8266InterfaceTiny/Socket/Endpoint.cpp Fri Jul 28 02:23:25 2017 +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; +}
diff -r 000000000000 -r bad9495b4215 ESP8266InterfaceTiny/Socket/Endpoint.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ESP8266InterfaceTiny/Socket/Endpoint.h Fri Jul 28 02:23:25 2017 +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
diff -r 000000000000 -r bad9495b4215 ESP8266InterfaceTiny/Socket/Socket.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ESP8266InterfaceTiny/Socket/Socket.cpp Fri Jul 28 02:23:25 2017 +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 +}
diff -r 000000000000 -r bad9495b4215 ESP8266InterfaceTiny/Socket/Socket.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ESP8266InterfaceTiny/Socket/Socket.h Fri Jul 28 02:23:25 2017 +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_ */
diff -r 000000000000 -r bad9495b4215 ESP8266InterfaceTiny/Socket/TCPSocketConnection.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ESP8266InterfaceTiny/Socket/TCPSocketConnection.cpp Fri Jul 28 02:23:25 2017 +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); +}
diff -r 000000000000 -r bad9495b4215 ESP8266InterfaceTiny/Socket/TCPSocketConnection.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ESP8266InterfaceTiny/Socket/TCPSocketConnection.h Fri Jul 28 02:23:25 2017 +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
diff -r 000000000000 -r bad9495b4215 ESP8266InterfaceTiny/Socket/TCPSocketServer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ESP8266InterfaceTiny/Socket/TCPSocketServer.cpp Fri Jul 28 02:23:25 2017 +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
diff -r 000000000000 -r bad9495b4215 ESP8266InterfaceTiny/Socket/TCPSocketServer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ESP8266InterfaceTiny/Socket/TCPSocketServer.h Fri Jul 28 02:23:25 2017 +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
diff -r 000000000000 -r bad9495b4215 ESP8266InterfaceTiny/Socket/UDPSocket.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ESP8266InterfaceTiny/Socket/UDPSocket.cpp Fri Jul 28 02:23:25 2017 +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; +}
diff -r 000000000000 -r bad9495b4215 ESP8266InterfaceTiny/Socket/UDPSocket.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ESP8266InterfaceTiny/Socket/UDPSocket.h Fri Jul 28 02:23:25 2017 +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
diff -r 000000000000 -r bad9495b4215 HTTPClient/HTTPClient.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTTPClient/HTTPClient.cpp Fri Jul 28 02:23:25 2017 +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; +}
diff -r 000000000000 -r bad9495b4215 HTTPClient/HTTPClient.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTTPClient/HTTPClient.h Fri Jul 28 02:23:25 2017 +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
diff -r 000000000000 -r bad9495b4215 HTTPClient/IHTTPData.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTTPClient/IHTTPData.h Fri Jul 28 02:23:25 2017 +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
diff -r 000000000000 -r bad9495b4215 HTTPClient/data/HTTPMap.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTTPClient/data/HTTPMap.cpp Fri Jul 28 02:23:25 2017 +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; +}
diff -r 000000000000 -r bad9495b4215 HTTPClient/data/HTTPMap.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTTPClient/data/HTTPMap.h Fri Jul 28 02:23:25 2017 +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_ */
diff -r 000000000000 -r bad9495b4215 HTTPClient/data/HTTPText.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTTPClient/data/HTTPText.cpp Fri Jul 28 02:23:25 2017 +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 +{ + +} + + +
diff -r 000000000000 -r bad9495b4215 HTTPClient/data/HTTPText.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTTPClient/data/HTTPText.h Fri Jul 28 02:23:25 2017 +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_ */
diff -r 000000000000 -r bad9495b4215 SB1602E.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SB1602E.lib Fri Jul 28 02:23:25 2017 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/users/okano/code/SB1602E/#baf578069dfc
diff -r 000000000000 -r bad9495b4215 mitb.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mitb.h Fri Jul 28 02:23:25 2017 +0000 @@ -0,0 +1,38 @@ + + +#if defined(TARGET_SSCI824) +#define D0 dp16 +#define D1 dp17 +#define D2 dp2 +#define D3 dp3 +#define D4 dp4 +#define D5 dp5 +#define D6 dp6 +#define D7 dp7 +#define D8 dp8 +#define D9 dp9 +#define D10 dp10 +#define D11 dp11 +#define D12 dp12 +#define D13 dp25 +#define A0 dp18 +#define A1 dp19 +#define A2 dp20 +#define A3 dp21 +#define A4 dp22 +#define A5 dp23 +#define A6 dp24 +#define A7 dp15 +#endif + +#define MITB_LED D6 +#define MITB_WIFI_TX D1 +#define MITB_WIFI_RX D0 +#define MITB_WIFI_RST D2 +#define MITB_IR_TX D3 +#define MITB_IR_RX D9 +#define MITB_LX_SENSOR A6 +#define MITB_SD_MOSI D11 +#define MITB_SD_MISO D12 +#define MITB_SD_SCK D13 +#define MITB_SD_CS D10 \ No newline at end of file