From 95dada180c7c9c8c0c721ed5c997474adcaadf29 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Mon, 16 Nov 2015 19:29:33 +0100 Subject: [PATCH 01/18] first httpClient --- .../ESP8266httpClient/library.properties | 9 + .../src/ESP8266httpClient.cpp | 195 ++++++++++++++++++ .../ESP8266httpClient/src/ESP8266httpClient.h | 78 +++++++ 3 files changed, 282 insertions(+) create mode 100644 libraries/ESP8266httpClient/library.properties create mode 100644 libraries/ESP8266httpClient/src/ESP8266httpClient.cpp create mode 100644 libraries/ESP8266httpClient/src/ESP8266httpClient.h diff --git a/libraries/ESP8266httpClient/library.properties b/libraries/ESP8266httpClient/library.properties new file mode 100644 index 000000000..55110c143 --- /dev/null +++ b/libraries/ESP8266httpClient/library.properties @@ -0,0 +1,9 @@ +name=ESP8266httpClient +version=1.0 +author=Markus Sattler +maintainer=Markus Sattler +sentence=http Client for ESP8266 +paragraph= +category=Communication +url=https://github.com/Links2004/Arduino/tree/libraries/ESP8266httpClient +architectures=esp8266 diff --git a/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp b/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp new file mode 100644 index 000000000..969f5fa02 --- /dev/null +++ b/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp @@ -0,0 +1,195 @@ +/** + * ESP8266httpClient.cpp + * + * Created on: 02.11.2015 + * + * Copyright (c) 2015 Markus Sattler. All rights reserved. + * This file is part of the ESP8266httpClient for Arduino. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include +#include + +#include "ESP8266httpClient.h" + +httpClient::httpClient() { + _tcp = NULL; + _tcps = NULL; +} + +httpClient::~httpClient() { + if(connected()) { + _tcp->stop(); + } +} + + +void httpClient::begin(const char *host, uint16_t port, const char * url, bool https, const char * httpsFingerprint) { + _host = host; + _port = port; + _url = url; + _https = https; + _httpsFingerprint = httpsFingerprint; +} + +void httpClient::begin(String host, uint16_t port, String url, bool https, String httpsFingerprint) { + begin(host.c_str(), port, url.c_str(), https, httpsFingerprint.c_str()); +} + +/** + * connected + * @return connected status + */ +bool httpClient::connected() { + if(_tcp) { + return _tcp->connected(); + } + return false; +} + +bool httpClient::GET() { + + bool status; + status = connect(); + if(status) { + status = sendHeader("GET"); + } + + return status; +} + +/** + * sends a post request to the server + * @param payload uint8_t * + * @param size size_t + * @return status + */ +bool httpClient::POST(uint8_t * payload, size_t size) { + + bool status; + status = connect(); + if(status) { + addHeader("Content-Length", String(size)); + status = sendHeader("POST"); + } + + if(status) { + status = _tcp->write(&payload[0], size); + } + + return status; +} + +bool httpClient::POST(String payload) { + return POST((uint8_t *) payload.c_str(), payload.length()); +} + +/** + * returns the stram of the tcp connection + * @return WiFiClient + */ +WiFiClient & httpClient::getStream(void) { + if(connected()) { + return *_tcp; + } + // todo return error? +} + +/** + * adds Headder to the request + * @param name + * @param value + * @param first + */ +void httpClient::addHeader(const String& name, const String& value, bool first) { + + String headerLine = name; + headerLine += ": "; + headerLine += value; + headerLine += "\r\n"; + + if(first) { + _Headers = headerLine + _Headers; + } else { + _Headers += headerLine; + } +} + +/** + * init TCP connection and handle ssl verify if needed + * @return true if connection is ok + */ +bool httpClient::connect(void) { + + if(connected()) { + DEBUG_HTTPCLIENT("[HTTP-Client] connect. already connected!\n"); + return true; + } + + if(_https) { + DEBUG_HTTPCLIENT("[HTTP-Client] connect https...\n"); + _tcps = new WiFiClientSecure(); + _tcp = _tcps; + } else { + DEBUG_HTTPCLIENT("[HTTP-Client] connect...\n"); + _tcp = new WiFiClient(); + } + + + if(!_tcp->connect(_host.c_str(), _port)) { + DEBUG_HTTPCLIENT("[HTTP-Client] failed connect to %s:%u.\n", _host.c_str(), _port); + return false; + } + + DEBUG_HTTPCLIENT("[HTTP-Client] connected to %s:%u.\n", _host.c_str(), _port); + + if(_https) { + if(_tcps->verify(_httpsFingerprint.c_str(), _host.c_str())) { + DEBUG_HTTPCLIENT("[HTTP-Client] https certificate matches\n"); + } else { + DEBUG_HTTPCLIENT("[HTTP-Client] https certificate doesn't match!\n"); + _tcp->stop(); + return false; + } + } + + // set Timeout for readBytesUntil and readStringUntil + _tcp->setTimeout(HTTPCLIENT_TCP_TIMEOUT); + +#ifdef ESP8266 + _tcp->setNoDelay(true); +#endif + return connected(); +} + +/** + * sends HTTP request header + * @param type (GET, POST, ...) + * @return status + */ +bool httpClient::sendHeader(const char * type) { + String header = String(type) + " " + _url + " HTTP/1.1\r\n" + "Host: " + _host + "\r\n" + "User-Agent: ESP8266httpClient\r\n" + "Connection: close\r\n" + + _Headers + + "\r\n"; + + return _tcp->write(header.c_str(), header.length()); +} diff --git a/libraries/ESP8266httpClient/src/ESP8266httpClient.h b/libraries/ESP8266httpClient/src/ESP8266httpClient.h new file mode 100644 index 000000000..e3e34312a --- /dev/null +++ b/libraries/ESP8266httpClient/src/ESP8266httpClient.h @@ -0,0 +1,78 @@ +/** + * ESP8266httpClient.h + * + * Created on: 02.11.2015 + * + * Copyright (c) 2015 Markus Sattler. All rights reserved. + * This file is part of the ESP8266httpClient for Arduino. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef ESP8266HTTPCLIENT_H_ +#define ESP8266HTTPCLIENT_H_ + +#define DEBUG_HTTPCLIENT(...) Serial1.printf( __VA_ARGS__ ) + +#ifndef DEBUG_HTTPCLIENT +#define DEBUG_HTTPCLIENT(...) +#endif + +#define HTTPCLIENT_TCP_TIMEOUT (1000) + +class httpClient { + public: + httpClient(); + ~httpClient(); + + void begin(const char *host, uint16_t port, const char * url = "/", bool https = false, const char * httpsFingerprint = ""); + void begin(String host, uint16_t port, String url = "/", bool https = false, String httpsFingerprint = ""); + + bool connected(void); + + bool GET(); + bool POST(uint8_t * payload, size_t size); + bool POST(String payload); + + void addHeader(const String& name, const String& value, bool first = false); + + + + WiFiClient & getStream(void); + + protected: + WiFiClient * _tcp; + WiFiClientSecure * _tcps; + + String _host; + uint16_t _port; + + String _url; + bool _https; + String _httpsFingerprint; + + String _Headers; + + bool connect(void); + + bool sendHeader(const char * type); + + +}; + + + +#endif /* ESP8266HTTPCLIENT_H_ */ From 70ca494a7f31eb6bdc59cb51e452652a297f9434 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Tue, 17 Nov 2015 17:40:14 +0100 Subject: [PATCH 02/18] add Response header handling --- .../src/ESP8266httpClient.cpp | 146 ++++++++++++++++-- .../ESP8266httpClient/src/ESP8266httpClient.h | 35 ++++- 2 files changed, 164 insertions(+), 17 deletions(-) diff --git a/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp b/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp index 969f5fa02..8be06cf3f 100644 --- a/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp +++ b/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp @@ -31,19 +31,29 @@ httpClient::httpClient() { _tcp = NULL; _tcps = NULL; + + _headerKeysCount = 0; + _currentHeaders = NULL; + + _returnCode = 0; + _size = 0; } httpClient::~httpClient() { if(connected()) { _tcp->stop(); } -} + if(_currentHeaders) { + delete[] _currentHeaders; + } + _headerKeysCount = 0; +} void httpClient::begin(const char *host, uint16_t port, const char * url, bool https, const char * httpsFingerprint) { _host = host; _port = port; - _url = url; + _url = url; _https = https; _httpsFingerprint = httpsFingerprint; } @@ -63,7 +73,11 @@ bool httpClient::connected() { return false; } -bool httpClient::GET() { +/** + * send a GET request + * @return http code + */ +int httpClient::GET() { bool status; status = connect(); @@ -71,16 +85,20 @@ bool httpClient::GET() { status = sendHeader("GET"); } - return status; + if(status) { + return handleHeaderResponse(); + } + + return 0; } /** * sends a post request to the server * @param payload uint8_t * * @param size size_t - * @return status + * @return http code */ -bool httpClient::POST(uint8_t * payload, size_t size) { +int httpClient::POST(uint8_t * payload, size_t size) { bool status; status = connect(); @@ -93,10 +111,13 @@ bool httpClient::POST(uint8_t * payload, size_t size) { status = _tcp->write(&payload[0], size); } - return status; + if(status) { + return handleHeaderResponse(); + } + return 0; } -bool httpClient::POST(String payload) { +int httpClient::POST(String payload) { return POST((uint8_t *) payload.c_str(), payload.length()); } @@ -131,6 +152,56 @@ void httpClient::addHeader(const String& name, const String& value, bool first) } } +void httpClient::collectHeaders(const char* headerKeys[], const size_t headerKeysCount) { + _headerKeysCount = headerKeysCount; + if(_currentHeaders) + delete[] _currentHeaders; + _currentHeaders = new RequestArgument[_headerKeysCount]; + for(int i = 0; i < _headerKeysCount; i++) { + _currentHeaders[i].key = headerKeys[i]; + } +} + +String httpClient::header(const char* name) { + for(int i = 0; i < _headerKeysCount; ++i) { + if(_currentHeaders[i].key == name) + return _currentHeaders[i].value; + } + return String(); +} + +String httpClient::header(int i) { + if(i < _headerKeysCount) + return _currentHeaders[i].value; + return String(); +} + +String httpClient::headerName(int i) { + if(i < _headerKeysCount) + return _currentHeaders[i].key; + return String(); +} + +int httpClient::headers() { + return _headerKeysCount; +} + +bool httpClient::hasHeader(const char* name) { + for(int i = 0; i < _headerKeysCount; ++i) { + if((_currentHeaders[i].key == name) && (_currentHeaders[i].value.length() > 0)) + return true; + } + return false; +} + +/** + * size of message body / payload + * @return 0 if no info or > 0 when Content-Length is set by server + */ +size_t httpClient::getSize(void) { + return _size; +} + /** * init TCP connection and handle ssl verify if needed * @return true if connection is ok @@ -151,7 +222,6 @@ bool httpClient::connect(void) { _tcp = new WiFiClient(); } - if(!_tcp->connect(_host.c_str(), _port)) { DEBUG_HTTPCLIENT("[HTTP-Client] failed connect to %s:%u.\n", _host.c_str(), _port); return false; @@ -184,12 +254,64 @@ bool httpClient::connect(void) { * @return status */ bool httpClient::sendHeader(const char * type) { + if(!connected()) { + return false; + } String header = String(type) + " " + _url + " HTTP/1.1\r\n" "Host: " + _host + "\r\n" "User-Agent: ESP8266httpClient\r\n" - "Connection: close\r\n" + - _Headers + - "\r\n"; + "Connection: close\r\n" + _Headers + "\r\n"; return _tcp->write(header.c_str(), header.length()); } + +/** + * reads the respone from the server + * @return int http code + */ +int httpClient::handleHeaderResponse() { + + if(!connected()) { + return false; + } + + while(connected()) { + size_t len = _tcp->available(); + if(len > 0) { + String headerLine = _tcp->readStringUntil('\n'); + headerLine.trim(); // remove \r + + DEBUG_HTTPCLIENT("[HTTP][handleHeaderResponse] RX: '%s'\n", headerLine.c_str()); + + if(headerLine.startsWith("HTTP/1.")) { + _returnCode = headerLine.substring(9, headerLine.indexOf(' ', 9)).toInt(); + } else if(headerLine.indexOf(':')) { + String headerName = headerLine.substring(0, headerLine.indexOf(':')); + String headerValue = headerLine.substring(headerLine.indexOf(':') + 2); + + if(headerName.equalsIgnoreCase("Content-Length")) { + _size = headerValue.toInt(); + } + + for(size_t i = 0; i < _headerKeysCount; i++) { + if(_currentHeaders[i].key == headerName) { + _currentHeaders[i].value = headerValue; + return true; + } + } + + } + + if(headerLine == "") { + DEBUG_HTTPCLIENT("[HTTP][handleHeaderResponse] code: '%s'\n", String(_returnCode).c_str()); + if(_size) { + DEBUG_HTTPCLIENT("[HTTP][handleHeaderResponse] size: '%s'\n", String(_size).c_str()); + } + return _returnCode; + } + + } else { + delay(0); + } + } +} diff --git a/libraries/ESP8266httpClient/src/ESP8266httpClient.h b/libraries/ESP8266httpClient/src/ESP8266httpClient.h index e3e34312a..1ffe8f094 100644 --- a/libraries/ESP8266httpClient/src/ESP8266httpClient.h +++ b/libraries/ESP8266httpClient/src/ESP8266httpClient.h @@ -43,20 +43,38 @@ class httpClient { bool connected(void); - bool GET(); - bool POST(uint8_t * payload, size_t size); - bool POST(String payload); + /// request handling + int GET(); + int POST(uint8_t * payload, size_t size); + int POST(String payload); void addHeader(const String& name, const String& value, bool first = false); + /// Response handling + void collectHeaders(const char* headerKeys[], const size_t headerKeysCount); + String header(const char* name); // get request header value by name + String header(int i); // get request header value by number + String headerName(int i); // get request header name by number + int headers(); // get header count + bool hasHeader(const char* name); // check if header exists + size_t getSize(void); + WiFiClient & getStream(void); protected: + + struct RequestArgument { + String key; + String value; + }; + + WiFiClient * _tcp; WiFiClientSecure * _tcps; + /// request handling String _host; uint16_t _port; @@ -66,10 +84,17 @@ class httpClient { String _Headers; + /// Response handling + RequestArgument* _currentHeaders; + size_t _headerKeysCount; + + int _returnCode; + size_t _size; + + bool connect(void); - bool sendHeader(const char * type); - + int handleHeaderResponse(); }; From 1e7b9688a53927f6f67dac80bac3fb51328ab4a2 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sun, 22 Nov 2015 11:09:48 +0100 Subject: [PATCH 03/18] add examples/BasicHttpClient/BasicHttpClient.ino fix get size only fingerprint when strlen > 0 --- .../BasicHttpClient/BasicHttpClient.ino | 77 +++++++++++++++++++ .../src/ESP8266httpClient.cpp | 30 +++++--- .../ESP8266httpClient/src/ESP8266httpClient.h | 4 +- 3 files changed, 99 insertions(+), 12 deletions(-) create mode 100644 libraries/ESP8266httpClient/examples/BasicHttpClient/BasicHttpClient.ino diff --git a/libraries/ESP8266httpClient/examples/BasicHttpClient/BasicHttpClient.ino b/libraries/ESP8266httpClient/examples/BasicHttpClient/BasicHttpClient.ino new file mode 100644 index 000000000..23a5e49da --- /dev/null +++ b/libraries/ESP8266httpClient/examples/BasicHttpClient/BasicHttpClient.ino @@ -0,0 +1,77 @@ +/** + * BasicHttpClient.ino + * + * Created on: 24.05.2015 + * + */ + +#include + +#include +#include + +#include + + +ESP8266WiFiMulti WiFiMulti; + +void setup() { + Serial.begin(115200); + + + Serial.println(); + Serial.println(); + Serial.println(); + + + for(uint8_t t = 4; t > 0; t--) { + Serial.printf("[SETUP] WAIT %d...\n", t); + Serial.flush(); + delay(1000); + } + + WiFiMulti.addAP("SSID", "PASSWORD"); + + //WiFi.disconnect(); + while(WiFiMulti.run() != WL_CONNECTED) { + delay(100); + } +} + +void loop() { + if((WiFiMulti.run() == WL_CONNECTED)) { + httpClient http; + + Serial.print("[HTTP] begin...\n"); + + http.begin("192.168.1.12", 80, "/test.html"); + + Serial.print("[HTTP] GET...\n"); + if(http.GET()) { + + Serial.print("[HTTP] GET... ok.\n"); + + size_t len = http.getSize(); + + uint8_t buff[128] = { 0 }; + WiFiClient stream = http.getStream(); + while(http.connected() && len > 0) { + size_t size = stream.available(); + int c = stream.readBytes(buff, ((size > 128) ? 128 : size)); + + Serial.write(buff, c); + len -= c; + + delay(0); + } + Serial.println(); + Serial.print("[HTTP] connection closed or file end.\n"); + + } else { + + Serial.print("[HTTP] GET... fail.\n"); + } + + delay(10000); + } +} diff --git a/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp b/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp index 8be06cf3f..125f363e1 100644 --- a/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp +++ b/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp @@ -36,7 +36,7 @@ httpClient::httpClient() { _currentHeaders = NULL; _returnCode = 0; - _size = 0; + _size = -1; } httpClient::~httpClient() { @@ -51,11 +51,18 @@ httpClient::~httpClient() { } void httpClient::begin(const char *host, uint16_t port, const char * url, bool https, const char * httpsFingerprint) { + _host = host; _port = port; _url = url; _https = https; _httpsFingerprint = httpsFingerprint; + + _returnCode = 0; + _size = -1; + + _Headers = ""; + } void httpClient::begin(String host, uint16_t port, String url, bool https, String httpsFingerprint) { @@ -121,6 +128,15 @@ int httpClient::POST(String payload) { return POST((uint8_t *) payload.c_str(), payload.length()); } + +/** + * size of message body / payload + * @return -1 if no info or > 0 when Content-Length is set by server + */ +int httpClient::getSize(void) { + return _size; +} + /** * returns the stram of the tcp connection * @return WiFiClient @@ -194,13 +210,7 @@ bool httpClient::hasHeader(const char* name) { return false; } -/** - * size of message body / payload - * @return 0 if no info or > 0 when Content-Length is set by server - */ -size_t httpClient::getSize(void) { - return _size; -} + /** * init TCP connection and handle ssl verify if needed @@ -209,7 +219,7 @@ size_t httpClient::getSize(void) { bool httpClient::connect(void) { if(connected()) { - DEBUG_HTTPCLIENT("[HTTP-Client] connect. already connected!\n"); + DEBUG_HTTPCLIENT("[HTTP-Client] connect. already connected, reuse!\n"); return true; } @@ -229,7 +239,7 @@ bool httpClient::connect(void) { DEBUG_HTTPCLIENT("[HTTP-Client] connected to %s:%u.\n", _host.c_str(), _port); - if(_https) { + if(_https && _httpsFingerprint.length() > 0) { if(_tcps->verify(_httpsFingerprint.c_str(), _host.c_str())) { DEBUG_HTTPCLIENT("[HTTP-Client] https certificate matches\n"); } else { diff --git a/libraries/ESP8266httpClient/src/ESP8266httpClient.h b/libraries/ESP8266httpClient/src/ESP8266httpClient.h index 1ffe8f094..57f186912 100644 --- a/libraries/ESP8266httpClient/src/ESP8266httpClient.h +++ b/libraries/ESP8266httpClient/src/ESP8266httpClient.h @@ -59,7 +59,7 @@ class httpClient { bool hasHeader(const char* name); // check if header exists - size_t getSize(void); + int getSize(void); WiFiClient & getStream(void); @@ -89,7 +89,7 @@ class httpClient { size_t _headerKeysCount; int _returnCode; - size_t _size; + int _size; bool connect(void); From 0a8f5be2575d0e6f354082e4b5ea35181949f7a7 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sun, 22 Nov 2015 11:27:32 +0100 Subject: [PATCH 04/18] add more documentation and cleanup the example --- .../BasicHttpClient/BasicHttpClient.ino | 91 ++++++++++++------- 1 file changed, 56 insertions(+), 35 deletions(-) diff --git a/libraries/ESP8266httpClient/examples/BasicHttpClient/BasicHttpClient.ino b/libraries/ESP8266httpClient/examples/BasicHttpClient/BasicHttpClient.ino index 23a5e49da..99df11e76 100644 --- a/libraries/ESP8266httpClient/examples/BasicHttpClient/BasicHttpClient.ino +++ b/libraries/ESP8266httpClient/examples/BasicHttpClient/BasicHttpClient.ino @@ -12,66 +12,87 @@ #include +#define USE_SERIAL Serial1 ESP8266WiFiMulti WiFiMulti; void setup() { - Serial.begin(115200); + USE_SERIAL.begin(115200); + // USE_SERIAL.setDebugOutput(true); - Serial.println(); - Serial.println(); - Serial.println(); + USE_SERIAL.println(); + USE_SERIAL.println(); + USE_SERIAL.println(); - - for(uint8_t t = 4; t > 0; t--) { - Serial.printf("[SETUP] WAIT %d...\n", t); - Serial.flush(); - delay(1000); - } + for(uint8_t t = 4; t > 0; t--) { + USE_SERIAL.printf("[SETUP] WAIT %d...\n", t); + USE_SERIAL.flush(); + delay(1000); + } WiFiMulti.addAP("SSID", "PASSWORD"); - //WiFi.disconnect(); - while(WiFiMulti.run() != WL_CONNECTED) { - delay(100); - } } void loop() { + // wait for WiFi connection if((WiFiMulti.run() == WL_CONNECTED)) { + httpClient http; - Serial.print("[HTTP] begin...\n"); - + USE_SERIAL.print("[HTTP] begin...\n"); + // configure traged server and url http.begin("192.168.1.12", 80, "/test.html"); - Serial.print("[HTTP] GET...\n"); - if(http.GET()) { + USE_SERIAL.print("[HTTP] GET...\n"); + // start connection and send HTTP header + int httpCode = http.GET(); + if(httpCode) { + // HTTP header has been send and Server response header has been handled - Serial.print("[HTTP] GET... ok.\n"); + USE_SERIAL.printf("[HTTP] GET... code: %d\n", httpCode); - size_t len = http.getSize(); + // file found at server + if(httpCode == 200) { - uint8_t buff[128] = { 0 }; - WiFiClient stream = http.getStream(); - while(http.connected() && len > 0) { - size_t size = stream.available(); - int c = stream.readBytes(buff, ((size > 128) ? 128 : size)); + // get lenght of document (is -1 when Server sends no Content-Length header) + int len = http.getSize(); - Serial.write(buff, c); - len -= c; + // create buffer for read + uint8_t buff[128] = { 0 }; + + // get tcp stream + WiFiClient stream = http.getStream(); + + // read all data from server + while(http.connected() && (len > 0 || len == -1)) { + // get available data size + size_t size = stream.available(); + + if(size) { + // read up to 128 byte + int c = stream.readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size)); + + // write it to Serial + USE_SERIAL.write(buff, c); + + if(len > 0) { + len -= c; + } + } + delay(1); + } + + USE_SERIAL.println(); + USE_SERIAL.print("[HTTP] connection closed or file end.\n"); - delay(0); } - Serial.println(); - Serial.print("[HTTP] connection closed or file end.\n"); - } else { - - Serial.print("[HTTP] GET... fail.\n"); + USE_SERIAL.print("[HTTP] GET... faild, no connection or no HTTP server\n"); } - - delay(10000); } + + delay(10000); } + From 464b9f2bfbf6499b80b783d8dd7192d7a8bfb55c Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sun, 22 Nov 2015 15:00:14 +0100 Subject: [PATCH 05/18] improve error handling add httpClient::sendRequest ( universal request send ) --- .../src/ESP8266httpClient.cpp | 79 +++++++++++-------- .../ESP8266httpClient/src/ESP8266httpClient.h | 9 +++ 2 files changed, 53 insertions(+), 35 deletions(-) diff --git a/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp b/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp index 125f363e1..3bca9b596 100644 --- a/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp +++ b/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp @@ -85,18 +85,7 @@ bool httpClient::connected() { * @return http code */ int httpClient::GET() { - - bool status; - status = connect(); - if(status) { - status = sendHeader("GET"); - } - - if(status) { - return handleHeaderResponse(); - } - - return 0; + return sendRequest("GET"); } /** @@ -106,28 +95,45 @@ int httpClient::GET() { * @return http code */ int httpClient::POST(uint8_t * payload, size_t size) { - - bool status; - status = connect(); - if(status) { - addHeader("Content-Length", String(size)); - status = sendHeader("POST"); - } - - if(status) { - status = _tcp->write(&payload[0], size); - } - - if(status) { - return handleHeaderResponse(); - } - return 0; + return sendRequest("POST", payload, size); } int httpClient::POST(String payload) { return POST((uint8_t *) payload.c_str(), payload.length()); } +/** + * sendRequest + * @param type const char * "GET", "POST", .... + * @param payload uint8_t * data for the message body if null not send + * @param size size_t size for the message body if 0 not send + * @return -1 if no info or > 0 when Content-Length is set by server + */ +int httpClient::sendRequest(const char * type, uint8_t * payload, size_t size) { + // connect ro server + if(!connect()) { + return HTTPC_ERROR_CONNECTION_REFUSED; + } + + if(payload && size > 0) { + addHeader("Content-Length", String(size)); + } + + // send Header + if(!sendHeader(type)) { + return HTTPC_ERROR_SEND_HEADER_FAILD; + } + + // send Payload if needed + if(payload && size > 0) { + if(_tcp->write(&payload[0], size) != size) { + return HTTPC_ERROR_SEND_PAYLOAD_FAILD; + } + } + + // handle Server Response (Header) + return handleHeaderResponse(); +} /** * size of message body / payload @@ -145,6 +151,9 @@ WiFiClient & httpClient::getStream(void) { if(connected()) { return *_tcp; } + + DEBUG_HTTPCLIENT("[HTTP-Client] no stream to return!?\n"); + // todo return error? } @@ -210,8 +219,6 @@ bool httpClient::hasHeader(const char* name) { return false; } - - /** * init TCP connection and handle ssl verify if needed * @return true if connection is ok @@ -282,7 +289,7 @@ bool httpClient::sendHeader(const char * type) { int httpClient::handleHeaderResponse() { if(!connected()) { - return false; + return HTTPC_ERROR_NOT_CONNECTED; } while(connected()) { @@ -291,7 +298,7 @@ int httpClient::handleHeaderResponse() { String headerLine = _tcp->readStringUntil('\n'); headerLine.trim(); // remove \r - DEBUG_HTTPCLIENT("[HTTP][handleHeaderResponse] RX: '%s'\n", headerLine.c_str()); + DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] RX: '%s'\n", headerLine.c_str()); if(headerLine.startsWith("HTTP/1.")) { _returnCode = headerLine.substring(9, headerLine.indexOf(' ', 9)).toInt(); @@ -306,16 +313,16 @@ int httpClient::handleHeaderResponse() { for(size_t i = 0; i < _headerKeysCount; i++) { if(_currentHeaders[i].key == headerName) { _currentHeaders[i].value = headerValue; - return true; + break; } } } if(headerLine == "") { - DEBUG_HTTPCLIENT("[HTTP][handleHeaderResponse] code: '%s'\n", String(_returnCode).c_str()); + DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] code: '%s'\n", String(_returnCode).c_str()); if(_size) { - DEBUG_HTTPCLIENT("[HTTP][handleHeaderResponse] size: '%s'\n", String(_size).c_str()); + DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] size: '%s'\n", String(_size).c_str()); } return _returnCode; } @@ -324,4 +331,6 @@ int httpClient::handleHeaderResponse() { delay(0); } } + + return HTTPC_ERROR_CONNECTION_LOST; } diff --git a/libraries/ESP8266httpClient/src/ESP8266httpClient.h b/libraries/ESP8266httpClient/src/ESP8266httpClient.h index 57f186912..59399b8da 100644 --- a/libraries/ESP8266httpClient/src/ESP8266httpClient.h +++ b/libraries/ESP8266httpClient/src/ESP8266httpClient.h @@ -33,6 +33,14 @@ #define HTTPCLIENT_TCP_TIMEOUT (1000) +/// HTTP client errors +#define HTTPC_ERROR_CONNECTION_REFUSED (-1) +#define HTTPC_ERROR_SEND_HEADER_FAILD (-2) +#define HTTPC_ERROR_SEND_PAYLOAD_FAILD (-3) +#define HTTPC_ERROR_NOT_CONNECTED (-4) +#define HTTPC_ERROR_CONNECTION_LOST (-5) + + class httpClient { public: httpClient(); @@ -47,6 +55,7 @@ class httpClient { int GET(); int POST(uint8_t * payload, size_t size); int POST(String payload); + int sendRequest(const char * type, uint8_t * payload = NULL, size_t size = 0); void addHeader(const String& name, const String& value, bool first = false); From ca092f47541c4229cf2130f387ecec62ef169f03 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sun, 22 Nov 2015 15:01:38 +0100 Subject: [PATCH 06/18] fix warnings --- libraries/ESP8266httpClient/src/ESP8266httpClient.cpp | 10 +++++----- libraries/ESP8266httpClient/src/ESP8266httpClient.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp b/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp index 3bca9b596..b5030de58 100644 --- a/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp +++ b/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp @@ -182,26 +182,26 @@ void httpClient::collectHeaders(const char* headerKeys[], const size_t headerKey if(_currentHeaders) delete[] _currentHeaders; _currentHeaders = new RequestArgument[_headerKeysCount]; - for(int i = 0; i < _headerKeysCount; i++) { + for(size_t i = 0; i < _headerKeysCount; i++) { _currentHeaders[i].key = headerKeys[i]; } } String httpClient::header(const char* name) { - for(int i = 0; i < _headerKeysCount; ++i) { + for(size_t i = 0; i < _headerKeysCount; ++i) { if(_currentHeaders[i].key == name) return _currentHeaders[i].value; } return String(); } -String httpClient::header(int i) { +String httpClient::header(size_t i) { if(i < _headerKeysCount) return _currentHeaders[i].value; return String(); } -String httpClient::headerName(int i) { +String httpClient::headerName(size_t i) { if(i < _headerKeysCount) return _currentHeaders[i].key; return String(); @@ -212,7 +212,7 @@ int httpClient::headers() { } bool httpClient::hasHeader(const char* name) { - for(int i = 0; i < _headerKeysCount; ++i) { + for(size_t i = 0; i < _headerKeysCount; ++i) { if((_currentHeaders[i].key == name) && (_currentHeaders[i].value.length() > 0)) return true; } diff --git a/libraries/ESP8266httpClient/src/ESP8266httpClient.h b/libraries/ESP8266httpClient/src/ESP8266httpClient.h index 59399b8da..802a484f7 100644 --- a/libraries/ESP8266httpClient/src/ESP8266httpClient.h +++ b/libraries/ESP8266httpClient/src/ESP8266httpClient.h @@ -62,8 +62,8 @@ class httpClient { /// Response handling void collectHeaders(const char* headerKeys[], const size_t headerKeysCount); String header(const char* name); // get request header value by name - String header(int i); // get request header value by number - String headerName(int i); // get request header name by number + String header(size_t i); // get request header value by number + String headerName(size_t i); // get request header name by number int headers(); // get header count bool hasHeader(const char* name); // check if header exists From e6c661e7bafe7720725c83e6852ace17e009f892 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sun, 22 Nov 2015 15:34:10 +0100 Subject: [PATCH 07/18] allow reuse of tcp connection to send multiple request to one server add writeToStream function for easy payload usage --- .../reuseConnection/reuseConnection.ino | 65 ++++++++++++ .../src/ESP8266httpClient.cpp | 100 ++++++++++++++++-- .../ESP8266httpClient/src/ESP8266httpClient.h | 8 +- 3 files changed, 165 insertions(+), 8 deletions(-) create mode 100644 libraries/ESP8266httpClient/examples/reuseConnection/reuseConnection.ino diff --git a/libraries/ESP8266httpClient/examples/reuseConnection/reuseConnection.ino b/libraries/ESP8266httpClient/examples/reuseConnection/reuseConnection.ino new file mode 100644 index 000000000..7179b1f82 --- /dev/null +++ b/libraries/ESP8266httpClient/examples/reuseConnection/reuseConnection.ino @@ -0,0 +1,65 @@ +/** + * reuseConnection.ino + * + * Created on: 22.11.2015 + * + */ + + +#include + +#include +#include + +#include + +#define USE_SERIAL Serial1 + +ESP8266WiFiMulti WiFiMulti; + +httpClient http; + +void setup() { + + USE_SERIAL.begin(115200); + // USE_SERIAL.setDebugOutput(true); + + USE_SERIAL.println(); + USE_SERIAL.println(); + USE_SERIAL.println(); + + for(uint8_t t = 4; t > 0; t--) { + USE_SERIAL.printf("[SETUP] WAIT %d...\n", t); + USE_SERIAL.flush(); + delay(1000); + } + + WiFiMulti.addAP("SSID", "PASSWORD"); + + +} + +void loop() { + // wait for WiFi connection + if((WiFiMulti.run() == WL_CONNECTED)) { + + http.begin("192.168.1.12", 80, "/test.html"); + + int httpCode = http.GET(); + if(httpCode) { + USE_SERIAL.printf("[HTTP] GET... code: %d\n", httpCode); + + // file found at server + if(httpCode == 200) { + http.writeToStream(&USE_SERIAL); + } + } else { + USE_SERIAL.print("[HTTP] GET... faild, no connection or no HTTP server\n"); + } + } + + delay(1000); +} + + + diff --git a/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp b/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp index b5030de58..41e3cd7f4 100644 --- a/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp +++ b/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp @@ -32,11 +32,15 @@ httpClient::httpClient() { _tcp = NULL; _tcps = NULL; + _reuse = false; + _headerKeysCount = 0; _currentHeaders = NULL; _returnCode = 0; _size = -1; + _canReuse = false; + } httpClient::~httpClient() { @@ -52,6 +56,8 @@ httpClient::~httpClient() { void httpClient::begin(const char *host, uint16_t port, const char * url, bool https, const char * httpsFingerprint) { + DEBUG_HTTPCLIENT("[HTTP-Client][begin] host: %s port:%d url: %s https: %d httpsFingerprint: %s\n", host, port, url, https, httpsFingerprint); + _host = host; _port = port; _url = url; @@ -69,6 +75,19 @@ void httpClient::begin(String host, uint16_t port, String url, bool https, Strin begin(host.c_str(), port, url.c_str(), https, httpsFingerprint.c_str()); } +/** + * end + * called after the payload is handeld + */ +void httpClient::end(void) { + if((!_reuse || !_canReuse) && connected()) { + DEBUG_HTTPCLIENT("[HTTP-Client][end] tcp stop \n"); + _tcp->stop(); + } else { + DEBUG_HTTPCLIENT("[HTTP-Client][end] tcp keep open for reuse\n"); + } +} + /** * connected * @return connected status @@ -80,6 +99,16 @@ bool httpClient::connected() { return false; } + +/** + * try to reuse the connection to the server + * keep-alive + * @param reuse bool + */ +void httpClient::setReuse(bool reuse) { + _reuse = reuse; +} + /** * send a GET request * @return http code @@ -157,6 +186,53 @@ WiFiClient & httpClient::getStream(void) { // todo return error? } +/** + * write all message body / payload to Stream + * @param stream Stream * + * @return bytes written + */ +int httpClient::writeToStream(Stream * stream) { + + if(!stream) { + return -1; + } + + // get lenght of document (is -1 when Server sends no Content-Length header) + int len = _size; + int bytesWritten = 0; + + // create buffer for read + uint8_t buff[1460] = { 0 }; + + // read all data from server + while(connected() && (len > 0 || len == -1)) { + + // get available data size + size_t size = _tcp->available(); + + if(size) { + int c = _tcp->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size)); + + // write it to Stream + bytesWritten += stream->write(buff, c); + + if(len > 0) { + len -= c; + } + } + delay(1); + } + + DEBUG_HTTPCLIENT("[HTTP-Client] connection closed or file end.\n"); + + if(_size && _size != bytesWritten) { + DEBUG_HTTPCLIENT("[HTTP-Client] bytesWritten %d and size %d missmatch!.\n", bytesWritten, _size); + } + + end(); + return bytesWritten; +} + /** * adds Headder to the request * @param name @@ -226,7 +302,7 @@ bool httpClient::hasHeader(const char* name) { bool httpClient::connect(void) { if(connected()) { - DEBUG_HTTPCLIENT("[HTTP-Client] connect. already connected, reuse!\n"); + DEBUG_HTTPCLIENT("[HTTP-Client] connect. already connected, try reuse!\n"); return true; } @@ -235,7 +311,7 @@ bool httpClient::connect(void) { _tcps = new WiFiClientSecure(); _tcp = _tcps; } else { - DEBUG_HTTPCLIENT("[HTTP-Client] connect...\n"); + DEBUG_HTTPCLIENT("[HTTP-Client] connect http...\n"); _tcp = new WiFiClient(); } @@ -277,7 +353,14 @@ bool httpClient::sendHeader(const char * type) { String header = String(type) + " " + _url + " HTTP/1.1\r\n" "Host: " + _host + "\r\n" "User-Agent: ESP8266httpClient\r\n" - "Connection: close\r\n" + _Headers + "\r\n"; + "Connection: "; + + if(_reuse) { + header += "keep-alive"; + } else { + header += "close"; + } + header += "\r\n" + _Headers + "\r\n"; return _tcp->write(header.c_str(), header.length()); } @@ -310,19 +393,22 @@ int httpClient::handleHeaderResponse() { _size = headerValue.toInt(); } + if(headerName.equalsIgnoreCase("Connection")) { + _canReuse = headerValue.equalsIgnoreCase("keep-alive"); + } + for(size_t i = 0; i < _headerKeysCount; i++) { - if(_currentHeaders[i].key == headerName) { + if(_currentHeaders[i].key.equalsIgnoreCase(headerName)) { _currentHeaders[i].value = headerValue; break; } } - } if(headerLine == "") { - DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] code: '%s'\n", String(_returnCode).c_str()); + DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] code: %d\n", _returnCode); if(_size) { - DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] size: '%s'\n", String(_size).c_str()); + DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] size: %d\n", _size); } return _returnCode; } diff --git a/libraries/ESP8266httpClient/src/ESP8266httpClient.h b/libraries/ESP8266httpClient/src/ESP8266httpClient.h index 802a484f7..794b5c63d 100644 --- a/libraries/ESP8266httpClient/src/ESP8266httpClient.h +++ b/libraries/ESP8266httpClient/src/ESP8266httpClient.h @@ -48,9 +48,12 @@ class httpClient { void begin(const char *host, uint16_t port, const char * url = "/", bool https = false, const char * httpsFingerprint = ""); void begin(String host, uint16_t port, String url = "/", bool https = false, String httpsFingerprint = ""); + void end(void); bool connected(void); + void setReuse(bool reuse); /// keep-alive + /// request handling int GET(); int POST(uint8_t * payload, size_t size); @@ -71,6 +74,7 @@ class httpClient { int getSize(void); WiFiClient & getStream(void); + int writeToStream(Stream * stream); protected: @@ -86,6 +90,8 @@ class httpClient { /// request handling String _host; uint16_t _port; + bool _reuse; + String _url; bool _https; @@ -99,7 +105,7 @@ class httpClient { int _returnCode; int _size; - + bool _canReuse; bool connect(void); bool sendHeader(const char * type); From be91d96774850155922604b9415678245231eaad Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sun, 22 Nov 2015 15:46:23 +0100 Subject: [PATCH 08/18] improve debug out and error handling --- .../src/ESP8266httpClient.cpp | 29 +++++++++++++------ .../ESP8266httpClient/src/ESP8266httpClient.h | 1 + 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp b/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp index 41e3cd7f4..117901d40 100644 --- a/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp +++ b/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp @@ -80,11 +80,15 @@ void httpClient::begin(String host, uint16_t port, String url, bool https, Strin * called after the payload is handeld */ void httpClient::end(void) { - if((!_reuse || !_canReuse) && connected()) { - DEBUG_HTTPCLIENT("[HTTP-Client][end] tcp stop \n"); - _tcp->stop(); + if(connected()) { + if(_reuse && _canReuse) { + DEBUG_HTTPCLIENT("[HTTP-Client][end] tcp keep open for reuse\n"); + } else { + DEBUG_HTTPCLIENT("[HTTP-Client][end] tcp stop\n"); + _tcp->stop(); + } } else { - DEBUG_HTTPCLIENT("[HTTP-Client][end] tcp keep open for reuse\n"); + DEBUG_HTTPCLIENT("[HTTP-Client][end] tcp is closed\n"); } } @@ -189,12 +193,16 @@ WiFiClient & httpClient::getStream(void) { /** * write all message body / payload to Stream * @param stream Stream * - * @return bytes written + * @return bytes written ( negative values are error codes ) */ int httpClient::writeToStream(Stream * stream) { if(!stream) { - return -1; + return HTTPC_ERROR_NO_STREAM; + } + + if(!connected()) { + return HTTPC_ERROR_NOT_CONNECTED; } // get lenght of document (is -1 when Server sends no Content-Length header) @@ -219,14 +227,17 @@ int httpClient::writeToStream(Stream * stream) { if(len > 0) { len -= c; } + + delay(0); + } else { + delay(1); } - delay(1); } - DEBUG_HTTPCLIENT("[HTTP-Client] connection closed or file end.\n"); + DEBUG_HTTPCLIENT("[HTTP-Client][writeToStream] connection closed or file end (written: %d).\n", bytesWritten); if(_size && _size != bytesWritten) { - DEBUG_HTTPCLIENT("[HTTP-Client] bytesWritten %d and size %d missmatch!.\n", bytesWritten, _size); + DEBUG_HTTPCLIENT("[HTTP-Client][writeToStream] bytesWritten %d and size %d missmatch!.\n", bytesWritten, _size); } end(); diff --git a/libraries/ESP8266httpClient/src/ESP8266httpClient.h b/libraries/ESP8266httpClient/src/ESP8266httpClient.h index 794b5c63d..5421acf22 100644 --- a/libraries/ESP8266httpClient/src/ESP8266httpClient.h +++ b/libraries/ESP8266httpClient/src/ESP8266httpClient.h @@ -39,6 +39,7 @@ #define HTTPC_ERROR_SEND_PAYLOAD_FAILD (-3) #define HTTPC_ERROR_NOT_CONNECTED (-4) #define HTTPC_ERROR_CONNECTION_LOST (-5) +#define HTTPC_ERROR_NO_STREAM (-6) class httpClient { From 6ed7dfe537da5d7a2ae08dab08ba6655f4d084b7 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sun, 22 Nov 2015 15:58:15 +0100 Subject: [PATCH 09/18] improve handling of non http servers --- libraries/ESP8266httpClient/src/ESP8266httpClient.cpp | 10 +++++++++- libraries/ESP8266httpClient/src/ESP8266httpClient.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp b/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp index 117901d40..d7f5ec80d 100644 --- a/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp +++ b/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp @@ -386,6 +386,9 @@ int httpClient::handleHeaderResponse() { return HTTPC_ERROR_NOT_CONNECTED; } + _returnCode = -1; + _size = -1; + while(connected()) { size_t len = _tcp->available(); if(len > 0) { @@ -421,7 +424,12 @@ int httpClient::handleHeaderResponse() { if(_size) { DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] size: %d\n", _size); } - return _returnCode; + if(_returnCode) { + return _returnCode; + } else { + DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] Remote host is not an HTTP Server!"); + return HTTPC_ERROR_NO_HTTP_SERVER; + } } } else { diff --git a/libraries/ESP8266httpClient/src/ESP8266httpClient.h b/libraries/ESP8266httpClient/src/ESP8266httpClient.h index 5421acf22..ddc0cea35 100644 --- a/libraries/ESP8266httpClient/src/ESP8266httpClient.h +++ b/libraries/ESP8266httpClient/src/ESP8266httpClient.h @@ -40,6 +40,7 @@ #define HTTPC_ERROR_NOT_CONNECTED (-4) #define HTTPC_ERROR_CONNECTION_LOST (-5) #define HTTPC_ERROR_NO_STREAM (-6) +#define HTTPC_ERROR_NO_HTTP_SERVER (-7) class httpClient { From 497ab250406c8591ab1abb620c16224588ff7517 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sun, 22 Nov 2015 16:37:29 +0100 Subject: [PATCH 10/18] fix some memory leek still looses 40Byte some where?! --- .../src/ESP8266httpClient.cpp | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp b/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp index d7f5ec80d..1e27af2a3 100644 --- a/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp +++ b/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp @@ -28,6 +28,9 @@ #include "ESP8266httpClient.h" +/** + * constractor + */ httpClient::httpClient() { _tcp = NULL; _tcps = NULL; @@ -43,17 +46,35 @@ httpClient::httpClient() { } +/** + * deconstractor + */ httpClient::~httpClient() { - if(connected()) { + + if(_tcps) { + _tcps->stop(); + _tcps->~WiFiClientSecure(); + _tcps = NULL; + _tcp = NULL; + } else if(_tcp) { _tcp->stop(); + _tcp->~WiFiClient(); + _tcp = NULL; } if(_currentHeaders) { delete[] _currentHeaders; } - _headerKeysCount = 0; } +/** + * begin + * @param host const char * + * @param port uint16_t + * @param url const char * + * @param https bool + * @param httpsFingerprint const char * + */ void httpClient::begin(const char *host, uint16_t port, const char * url, bool https, const char * httpsFingerprint) { DEBUG_HTTPCLIENT("[HTTP-Client][begin] host: %s port:%d url: %s https: %d httpsFingerprint: %s\n", host, port, url, https, httpsFingerprint); @@ -98,7 +119,7 @@ void httpClient::end(void) { */ bool httpClient::connected() { if(_tcp) { - return _tcp->connected(); + return (_tcp->connected() || (_tcp->available() > 0)); } return false; } @@ -317,12 +338,22 @@ bool httpClient::connect(void) { return true; } + if(_https) { DEBUG_HTTPCLIENT("[HTTP-Client] connect https...\n"); + if(_tcps) { + _tcps->~WiFiClient(); + _tcps = NULL; + _tcp = NULL; + } _tcps = new WiFiClientSecure(); _tcp = _tcps; } else { DEBUG_HTTPCLIENT("[HTTP-Client] connect http...\n"); + if(_tcp) { + _tcp->~WiFiClient(); + _tcp = NULL; + } _tcp = new WiFiClient(); } From a5aa33f81a5eecb1aaca36a3481e27e54f7838b2 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sun, 22 Nov 2015 22:39:31 +0100 Subject: [PATCH 11/18] disable DEBUGV --- cores/esp8266/debug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/esp8266/debug.h b/cores/esp8266/debug.h index 9cf5980ef..98bdaf03c 100644 --- a/cores/esp8266/debug.h +++ b/cores/esp8266/debug.h @@ -4,7 +4,7 @@ #include #include -#define DEBUGV(...) ets_printf(__VA_ARGS__) +//#define DEBUGV(...) ets_printf(__VA_ARGS__) #ifndef DEBUGV #define DEBUGV(...) From c8aac83c4723601ce4ff97db619eafb3a80d9435 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sun, 22 Nov 2015 22:39:58 +0100 Subject: [PATCH 12/18] add :del message to unref --- libraries/ESP8266WiFi/src/include/ClientContext.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/ESP8266WiFi/src/include/ClientContext.h b/libraries/ESP8266WiFi/src/include/ClientContext.h index f4dfae09d..283fa1057 100644 --- a/libraries/ESP8266WiFi/src/include/ClientContext.h +++ b/libraries/ESP8266WiFi/src/include/ClientContext.h @@ -97,6 +97,7 @@ class ClientContext { close(); if(_discard_cb) _discard_cb(_discard_cb_arg, this); + DEBUGV(":del\r\n"); delete this; } } From 8b67051d1ea9c108b8d27df7a7412504236fcb1e Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Wed, 25 Nov 2015 12:33:33 +0100 Subject: [PATCH 13/18] add StreamString class (implement the Stream interface for String) --- cores/esp8266/StreamString.cpp | 68 ++++++++++++++++++++++++++++++++++ cores/esp8266/StreamString.h | 40 ++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 cores/esp8266/StreamString.cpp create mode 100644 cores/esp8266/StreamString.h diff --git a/cores/esp8266/StreamString.cpp b/cores/esp8266/StreamString.cpp new file mode 100644 index 000000000..9aace2b47 --- /dev/null +++ b/cores/esp8266/StreamString.cpp @@ -0,0 +1,68 @@ +/** + StreamString.cpp + + Copyright (c) 2015 Markus Sattler. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + */ + +#include +#include "StreamString.h" + +size_t StreamString::write(const uint8_t *buffer, size_t size) { + if(reserve(length() + size + 1)) { + for(size_t i = 0; i < size; i++) { + if(write(*buffer)) { + buffer++; + } else { + return i; + } + } + + } + return 0; +} + +size_t StreamString::write(uint8_t data) { + return concat((char) data); +} + +int StreamString::available() { + return length(); +} + +int StreamString::read() { + if(length()) { + char c = charAt(0); + remove(0, 1); + return c; + + } + return -1; +} + +int StreamString::peek() { + if(length()) { + char c = charAt(0); + return c; + } + return -1; +} + +void StreamString::flush() { +} + diff --git a/cores/esp8266/StreamString.h b/cores/esp8266/StreamString.h new file mode 100644 index 000000000..4f9f458ae --- /dev/null +++ b/cores/esp8266/StreamString.h @@ -0,0 +1,40 @@ +/** + StreamString.h + + Copyright (c) 2015 Markus Sattler. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef STREAMSTRING_H_ +#define STREAMSTRING_H_ + + +class StreamString: public Stream, public String { + + size_t write(const uint8_t *buffer, size_t size); + size_t write(uint8_t data); + + int available(); + int read(); + int peek(); + void flush(); + +}; + + +#endif /* STREAMSTRING_H_ */ From e4a5250a1aa7253208ae27b9d5e74aca4106374d Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Wed, 25 Nov 2015 12:33:59 +0100 Subject: [PATCH 14/18] add getString function --- .../src/ESP8266httpClient.cpp | 35 +++++++++++++++++++ .../ESP8266httpClient/src/ESP8266httpClient.h | 4 ++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp b/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp index 1e27af2a3..7e3fd6fec 100644 --- a/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp +++ b/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include "ESP8266httpClient.h" @@ -198,6 +199,7 @@ int httpClient::getSize(void) { } /** + * deprecated Note: this is not working with https! * returns the stram of the tcp connection * @return WiFiClient */ @@ -211,6 +213,20 @@ WiFiClient & httpClient::getStream(void) { // todo return error? } +/** + * returns the stram of the tcp connection + * @return WiFiClient * + */ +WiFiClient * httpClient::getStreamPtr(void) { + if(connected()) { + return _tcp; + } + + DEBUG_HTTPCLIENT("[HTTP-Client] no stream to return!?\n"); + return NULL; +} + +WiFiClient * getStreamPtr(void); /** * write all message body / payload to Stream * @param stream Stream * @@ -265,6 +281,25 @@ int httpClient::writeToStream(Stream * stream) { return bytesWritten; } +/** + * return all payload as String (may need lot of ram or trigger out of memmory!) + * @return String + */ +String httpClient::getString(void) { + StreamString sstring; + + if(_size) { + // try to reserve needed memmory + if(!sstring.reserve((_size + 1))) { + DEBUG_HTTPCLIENT("[HTTP-Client][getString] too less memory to resive as string! need: %d\n", (_size + 1)); + return String("--too less memory--"); + } + } + + writeToStream(&sstring); + return sstring; +} + /** * adds Headder to the request * @param name diff --git a/libraries/ESP8266httpClient/src/ESP8266httpClient.h b/libraries/ESP8266httpClient/src/ESP8266httpClient.h index ddc0cea35..9d69f3ed3 100644 --- a/libraries/ESP8266httpClient/src/ESP8266httpClient.h +++ b/libraries/ESP8266httpClient/src/ESP8266httpClient.h @@ -75,8 +75,10 @@ class httpClient { int getSize(void); - WiFiClient & getStream(void); + WiFiClient & getStream(void) __attribute__ ((deprecated)) ; + WiFiClient * getStreamPtr(void); int writeToStream(Stream * stream); + String getString(void); protected: From 59b4c82d60854234a80e4fa3bd0d1619e9690700 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Wed, 25 Nov 2015 12:40:25 +0100 Subject: [PATCH 15/18] add new Basic example based of getString note: keep in mind the ram usage! --- .../BasicHttpClient/BasicHttpClient.ino | 38 +------ .../StreamHttpClient/StreamHttpClient.ino | 98 +++++++++++++++++++ 2 files changed, 102 insertions(+), 34 deletions(-) create mode 100644 libraries/ESP8266httpClient/examples/StreamHttpClient/StreamHttpClient.ino diff --git a/libraries/ESP8266httpClient/examples/BasicHttpClient/BasicHttpClient.ino b/libraries/ESP8266httpClient/examples/BasicHttpClient/BasicHttpClient.ino index 99df11e76..0cdceb975 100644 --- a/libraries/ESP8266httpClient/examples/BasicHttpClient/BasicHttpClient.ino +++ b/libraries/ESP8266httpClient/examples/BasicHttpClient/BasicHttpClient.ino @@ -43,50 +43,20 @@ void loop() { USE_SERIAL.print("[HTTP] begin...\n"); // configure traged server and url - http.begin("192.168.1.12", 80, "/test.html"); + //http.begin("192.168.1.12", 443, "/test.html", true, "7a 9c f4 db 40 d3 62 5a 6e 21 bc 5c cc 66 c8 3e a1 45 59 38"); //HTTPS + http.begin("192.168.1.12", 80, "/test.html"); //HTTP USE_SERIAL.print("[HTTP] GET...\n"); // start connection and send HTTP header int httpCode = http.GET(); if(httpCode) { // HTTP header has been send and Server response header has been handled - USE_SERIAL.printf("[HTTP] GET... code: %d\n", httpCode); // file found at server if(httpCode == 200) { - - // get lenght of document (is -1 when Server sends no Content-Length header) - int len = http.getSize(); - - // create buffer for read - uint8_t buff[128] = { 0 }; - - // get tcp stream - WiFiClient stream = http.getStream(); - - // read all data from server - while(http.connected() && (len > 0 || len == -1)) { - // get available data size - size_t size = stream.available(); - - if(size) { - // read up to 128 byte - int c = stream.readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size)); - - // write it to Serial - USE_SERIAL.write(buff, c); - - if(len > 0) { - len -= c; - } - } - delay(1); - } - - USE_SERIAL.println(); - USE_SERIAL.print("[HTTP] connection closed or file end.\n"); - + String payload = http.getString(); + USE_SERIAL.println(payload); } } else { USE_SERIAL.print("[HTTP] GET... faild, no connection or no HTTP server\n"); diff --git a/libraries/ESP8266httpClient/examples/StreamHttpClient/StreamHttpClient.ino b/libraries/ESP8266httpClient/examples/StreamHttpClient/StreamHttpClient.ino new file mode 100644 index 000000000..a9aa981be --- /dev/null +++ b/libraries/ESP8266httpClient/examples/StreamHttpClient/StreamHttpClient.ino @@ -0,0 +1,98 @@ +/** + * StreamHttpClient.ino + * + * Created on: 24.05.2015 + * + */ + +#include + +#include +#include + +#include + +#define USE_SERIAL Serial + +ESP8266WiFiMulti WiFiMulti; + +void setup() { + + USE_SERIAL.begin(115200); + // USE_SERIAL.setDebugOutput(true); + + USE_SERIAL.println(); + USE_SERIAL.println(); + USE_SERIAL.println(); + + for(uint8_t t = 4; t > 0; t--) { + USE_SERIAL.printf("[SETUP] WAIT %d...\n", t); + USE_SERIAL.flush(); + delay(1000); + } + + WiFiMulti.addAP("SSID", "PASSWORD"); + +} + +void loop() { + // wait for WiFi connection + if((WiFiMulti.run() == WL_CONNECTED)) { + + httpClient http; + + USE_SERIAL.print("[HTTP] begin...\n"); + // configure traged server and url + http.begin("192.168.1.12", 80, "/test.html"); + + USE_SERIAL.print("[HTTP] GET...\n"); + // start connection and send HTTP header + int httpCode = http.GET(); + if(httpCode) { + // HTTP header has been send and Server response header has been handled + + USE_SERIAL.printf("[HTTP] GET... code: %d\n", httpCode); + + // file found at server + if(httpCode == 200) { + + // get lenght of document (is -1 when Server sends no Content-Length header) + int len = http.getSize(); + + // create buffer for read + uint8_t buff[128] = { 0 }; + + // get tcp stream + WiFiClient * stream = http.getStream(); + + // read all data from server + while(http.connected() && (len > 0 || len == -1)) { + // get available data size + size_t size = stream->available(); + + if(size) { + // read up to 128 byte + int c = stream->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size)); + + // write it to Serial + USE_SERIAL.write(buff, c); + + if(len > 0) { + len -= c; + } + } + delay(1); + } + + USE_SERIAL.println(); + USE_SERIAL.print("[HTTP] connection closed or file end.\n"); + + } + } else { + USE_SERIAL.print("[HTTP] GET... faild, no connection or no HTTP server\n"); + } + } + + delay(10000); +} + From 761b73c5ad35e6d28683bd4a163ca8bd0fc7bed5 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Wed, 25 Nov 2015 12:42:24 +0100 Subject: [PATCH 16/18] correct StreamHttpClient.ino example --- .../examples/StreamHttpClient/StreamHttpClient.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266httpClient/examples/StreamHttpClient/StreamHttpClient.ino b/libraries/ESP8266httpClient/examples/StreamHttpClient/StreamHttpClient.ino index a9aa981be..f64599fbb 100644 --- a/libraries/ESP8266httpClient/examples/StreamHttpClient/StreamHttpClient.ino +++ b/libraries/ESP8266httpClient/examples/StreamHttpClient/StreamHttpClient.ino @@ -63,7 +63,7 @@ void loop() { uint8_t buff[128] = { 0 }; // get tcp stream - WiFiClient * stream = http.getStream(); + WiFiClient * stream = http.getStreamPtr(); // read all data from server while(http.connected() && (len > 0 || len == -1)) { From 75fb6e200276210b235019d1f49ddd91c12c4b3c Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Wed, 25 Nov 2015 12:50:49 +0100 Subject: [PATCH 17/18] disable DEBUG_HTTPCLIENT --- .../examples/StreamHttpClient/StreamHttpClient.ino | 2 +- libraries/ESP8266httpClient/src/ESP8266httpClient.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266httpClient/examples/StreamHttpClient/StreamHttpClient.ino b/libraries/ESP8266httpClient/examples/StreamHttpClient/StreamHttpClient.ino index f64599fbb..9b64dab1c 100644 --- a/libraries/ESP8266httpClient/examples/StreamHttpClient/StreamHttpClient.ino +++ b/libraries/ESP8266httpClient/examples/StreamHttpClient/StreamHttpClient.ino @@ -19,7 +19,7 @@ ESP8266WiFiMulti WiFiMulti; void setup() { USE_SERIAL.begin(115200); - // USE_SERIAL.setDebugOutput(true); + // USE_SERIAL.setDebugOutput(true); USE_SERIAL.println(); USE_SERIAL.println(); diff --git a/libraries/ESP8266httpClient/src/ESP8266httpClient.h b/libraries/ESP8266httpClient/src/ESP8266httpClient.h index 9d69f3ed3..60a765f82 100644 --- a/libraries/ESP8266httpClient/src/ESP8266httpClient.h +++ b/libraries/ESP8266httpClient/src/ESP8266httpClient.h @@ -25,7 +25,7 @@ #ifndef ESP8266HTTPCLIENT_H_ #define ESP8266HTTPCLIENT_H_ -#define DEBUG_HTTPCLIENT(...) Serial1.printf( __VA_ARGS__ ) +//#define DEBUG_HTTPCLIENT(...) Serial1.printf( __VA_ARGS__ ) #ifndef DEBUG_HTTPCLIENT #define DEBUG_HTTPCLIENT(...) From 9089448d2574366d2fa7f69df5d39c5094eaa40a Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Wed, 25 Nov 2015 12:53:28 +0100 Subject: [PATCH 18/18] fixed typo --- .../BasicHttpClient/BasicHttpClient.ino | 4 ++-- .../StreamHttpClient/StreamHttpClient.ino | 2 +- .../reuseConnection/reuseConnection.ino | 4 ++-- .../src/ESP8266httpClient.cpp | 19 ++++++++++--------- .../ESP8266httpClient/src/ESP8266httpClient.h | 4 ++-- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/libraries/ESP8266httpClient/examples/BasicHttpClient/BasicHttpClient.ino b/libraries/ESP8266httpClient/examples/BasicHttpClient/BasicHttpClient.ino index 0cdceb975..15526e096 100644 --- a/libraries/ESP8266httpClient/examples/BasicHttpClient/BasicHttpClient.ino +++ b/libraries/ESP8266httpClient/examples/BasicHttpClient/BasicHttpClient.ino @@ -12,7 +12,7 @@ #include -#define USE_SERIAL Serial1 +#define USE_SERIAL Serial ESP8266WiFiMulti WiFiMulti; @@ -59,7 +59,7 @@ void loop() { USE_SERIAL.println(payload); } } else { - USE_SERIAL.print("[HTTP] GET... faild, no connection or no HTTP server\n"); + USE_SERIAL.print("[HTTP] GET... failed, no connection or no HTTP server\n"); } } diff --git a/libraries/ESP8266httpClient/examples/StreamHttpClient/StreamHttpClient.ino b/libraries/ESP8266httpClient/examples/StreamHttpClient/StreamHttpClient.ino index 9b64dab1c..43b6d4d8b 100644 --- a/libraries/ESP8266httpClient/examples/StreamHttpClient/StreamHttpClient.ino +++ b/libraries/ESP8266httpClient/examples/StreamHttpClient/StreamHttpClient.ino @@ -89,7 +89,7 @@ void loop() { } } else { - USE_SERIAL.print("[HTTP] GET... faild, no connection or no HTTP server\n"); + USE_SERIAL.print("[HTTP] GET... failed, no connection or no HTTP server\n"); } } diff --git a/libraries/ESP8266httpClient/examples/reuseConnection/reuseConnection.ino b/libraries/ESP8266httpClient/examples/reuseConnection/reuseConnection.ino index 7179b1f82..4610cb972 100644 --- a/libraries/ESP8266httpClient/examples/reuseConnection/reuseConnection.ino +++ b/libraries/ESP8266httpClient/examples/reuseConnection/reuseConnection.ino @@ -13,7 +13,7 @@ #include -#define USE_SERIAL Serial1 +#define USE_SERIAL Serial ESP8266WiFiMulti WiFiMulti; @@ -54,7 +54,7 @@ void loop() { http.writeToStream(&USE_SERIAL); } } else { - USE_SERIAL.print("[HTTP] GET... faild, no connection or no HTTP server\n"); + USE_SERIAL.print("[HTTP] GET... failed, no connection or no HTTP server\n"); } } diff --git a/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp b/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp index 7e3fd6fec..69becd195 100644 --- a/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp +++ b/libraries/ESP8266httpClient/src/ESP8266httpClient.cpp @@ -99,7 +99,7 @@ void httpClient::begin(String host, uint16_t port, String url, bool https, Strin /** * end - * called after the payload is handeld + * called after the payload is handled */ void httpClient::end(void) { if(connected()) { @@ -176,13 +176,13 @@ int httpClient::sendRequest(const char * type, uint8_t * payload, size_t size) { // send Header if(!sendHeader(type)) { - return HTTPC_ERROR_SEND_HEADER_FAILD; + return HTTPC_ERROR_SEND_HEADER_FAILED; } // send Payload if needed if(payload && size > 0) { if(_tcp->write(&payload[0], size) != size) { - return HTTPC_ERROR_SEND_PAYLOAD_FAILD; + return HTTPC_ERROR_SEND_PAYLOAD_FAILED; } } @@ -200,7 +200,7 @@ int httpClient::getSize(void) { /** * deprecated Note: this is not working with https! - * returns the stram of the tcp connection + * returns the stream of the tcp connection * @return WiFiClient */ WiFiClient & httpClient::getStream(void) { @@ -214,7 +214,7 @@ WiFiClient & httpClient::getStream(void) { } /** - * returns the stram of the tcp connection + * returns the stream of the tcp connection * @return WiFiClient * */ WiFiClient * httpClient::getStreamPtr(void) { @@ -242,7 +242,7 @@ int httpClient::writeToStream(Stream * stream) { return HTTPC_ERROR_NOT_CONNECTED; } - // get lenght of document (is -1 when Server sends no Content-Length header) + // get length of document (is -1 when Server sends no Content-Length header) int len = _size; int bytesWritten = 0; @@ -282,7 +282,7 @@ int httpClient::writeToStream(Stream * stream) { } /** - * return all payload as String (may need lot of ram or trigger out of memmory!) + * return all payload as String (may need lot of ram or trigger out of memory!) * @return String */ String httpClient::getString(void) { @@ -300,8 +300,9 @@ String httpClient::getString(void) { return sstring; } + /** - * adds Headder to the request + * adds Header to the request * @param name * @param value * @param first @@ -443,7 +444,7 @@ bool httpClient::sendHeader(const char * type) { } /** - * reads the respone from the server + * reads the response from the server * @return int http code */ int httpClient::handleHeaderResponse() { diff --git a/libraries/ESP8266httpClient/src/ESP8266httpClient.h b/libraries/ESP8266httpClient/src/ESP8266httpClient.h index 60a765f82..1f3d33bd5 100644 --- a/libraries/ESP8266httpClient/src/ESP8266httpClient.h +++ b/libraries/ESP8266httpClient/src/ESP8266httpClient.h @@ -35,8 +35,8 @@ /// HTTP client errors #define HTTPC_ERROR_CONNECTION_REFUSED (-1) -#define HTTPC_ERROR_SEND_HEADER_FAILD (-2) -#define HTTPC_ERROR_SEND_PAYLOAD_FAILD (-3) +#define HTTPC_ERROR_SEND_HEADER_FAILED (-2) +#define HTTPC_ERROR_SEND_PAYLOAD_FAILED (-3) #define HTTPC_ERROR_NOT_CONNECTED (-4) #define HTTPC_ERROR_CONNECTION_LOST (-5) #define HTTPC_ERROR_NO_STREAM (-6)