Skip to content

rework ESP8266HTTPUpdate to use httpClient and allow https updates #1091

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Nov 27, 2015
Merged
1 change: 1 addition & 0 deletions doc/ota_updates/ota_updates.md
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ function sendFile($path) {
header('Content-Type: application/octet-stream', true);
header('Content-Disposition: attachment; filename='.basename($path));
header('Content-Length: '.filesize($path), true);
header('x-MD5: '.md5_file($path), true);
readfile($path);
}

Expand Down
113 changes: 98 additions & 15 deletions libraries/ESP8266httpClient/src/ESP8266httpClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ httpClient::httpClient() {
_reuse = false;
_https = false;

_userAgent = "ESP8266httpClient";

_headerKeysCount = 0;
_currentHeaders = NULL;

Expand Down Expand Up @@ -77,7 +79,7 @@ httpClient::~httpClient() {
* @param httpsFingerprint const char *
*/
void httpClient::begin(const char *url, const char * httpsFingerprint) {
begin(String(url), String(httpsFingerprint));
begin(String(url), String(httpsFingerprint));
}

/**
Expand Down Expand Up @@ -111,7 +113,7 @@ void httpClient::begin(String url, String httpsFingerprint) {
_host = url.substring(0, index); // hostname
url.remove(0, (index + 1)); // remove hostname + :

index = url.indexOf('/');
index = url.indexOf('/');
_port = url.substring(0, index).toInt(); // get port
url.remove(0, index); // remove port
hasPort = true;
Expand Down Expand Up @@ -200,7 +202,6 @@ bool httpClient::connected() {
return false;
}


/**
* try to reuse the connection to the server
* keep-alive
Expand All @@ -210,6 +211,14 @@ void httpClient::setReuse(bool reuse) {
_reuse = reuse;
}

/**
* set User Agent
* @param userAgent const char *
*/
void httpClient::setUserAgent(const char * userAgent) {
_userAgent = userAgent;
}

/**
* send a GET request
* @return http code
Expand Down Expand Up @@ -240,7 +249,7 @@ int httpClient::POST(String payload) {
* @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
// connect to server
if(!connect()) {
return HTTPC_ERROR_CONNECTION_REFUSED;
}
Expand All @@ -265,6 +274,77 @@ int httpClient::sendRequest(const char * type, uint8_t * payload, size_t size) {
return handleHeaderResponse();
}

/**
* sendRequest
* @param type const char * "GET", "POST", ....
* @param stream Stream * data stream for the message body
* @param size size_t size for the message body if 0 not Content-Length is send
* @return -1 if no info or > 0 when Content-Length is set by server
*/
int httpClient::sendRequest(const char * type, Stream * stream, size_t size) {

if(!stream) {
return HTTPC_ERROR_NO_STREAM;
}

// connect to server
if(!connect()) {
return HTTPC_ERROR_CONNECTION_REFUSED;
}

if(size > 0) {
addHeader("Content-Length", String(size));
}

// send Header
if(!sendHeader(type)) {
return HTTPC_ERROR_SEND_HEADER_FAILED;
}

// create buffer for read
uint8_t buff[1460] = { 0 };

int len = size;
int bytesWritten = 0;

if(len == 0) {
len = -1;
}

// read all data from stream and send it to server
while(connected() && stream->available() && (len > 0 || len == -1)) {

// get available data size
size_t s = stream->available();

if(s) {
int c = stream->readBytes(buff, ((s > sizeof(buff)) ? sizeof(buff) : s));

// write it to Stream
bytesWritten += _tcp->write((const uint8_t *)buff, c);

if(len > 0) {
len -= c;
}

delay(0);
} else {
delay(1);
}
}

if(size && (int)size != bytesWritten) {
DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] Stream payload bytesWritten %d and size %d mismatch!.\n", bytesWritten, _size);
DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] ERROR SEND PAYLOAD FAILED!");
return HTTPC_ERROR_SEND_PAYLOAD_FAILED;
} else {
DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] Stream payload written: %d\n", bytesWritten);
}

// handle Server Response (Header)
return handleHeaderResponse();
}

/**
* size of message body / payload
* @return -1 if no info or > 0 when Content-Length is set by server
Expand Down Expand Up @@ -374,7 +454,6 @@ String httpClient::getString(void) {
return sstring;
}


/**
* adds Header to the request
* @param name
Expand All @@ -383,16 +462,20 @@ String httpClient::getString(void) {
*/
void httpClient::addHeader(const String& name, const String& value, bool first) {

String headerLine = name;
headerLine += ": ";
headerLine += value;
headerLine += "\r\n";
// not allow set of Header handled by code
if(!name.equalsIgnoreCase("Connection") && !name.equalsIgnoreCase("User-Agent") && !name.equalsIgnoreCase("Host")) {
String headerLine = name;
headerLine += ": ";
headerLine += value;
headerLine += "\r\n";

if(first) {
_Headers = headerLine + _Headers;
} else {
_Headers += headerLine;
if(first) {
_Headers = headerLine + _Headers;
} else {
_Headers += headerLine;
}
}

}

void httpClient::collectHeaders(const char* headerKeys[], const size_t headerKeysCount) {
Expand Down Expand Up @@ -448,7 +531,6 @@ bool httpClient::connect(void) {
return true;
}


if(_https) {
DEBUG_HTTPCLIENT("[HTTP-Client] connect https...\n");
if(_tcps) {
Expand Down Expand Up @@ -502,9 +584,10 @@ 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"
"User-Agent: " + _userAgent + "\r\n"
"Connection: ";

if(_reuse) {
Expand Down
5 changes: 4 additions & 1 deletion libraries/ESP8266httpClient/src/ESP8266httpClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,14 @@ class httpClient {
bool connected(void);

void setReuse(bool reuse); /// keep-alive
void setUserAgent(const char * userAgent);

/// request handling
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);
int sendRequest(const char * type, Stream * stream, size_t size = 0);

void addHeader(const String& name, const String& value, bool first = false);

Expand Down Expand Up @@ -105,7 +107,8 @@ class httpClient {
bool _https;
String _httpsFingerprint;

String _Headers;
String _Headers;
String _userAgent;

/// Response handling
RequestArgument* _currentHeaders;
Expand Down
61 changes: 61 additions & 0 deletions libraries/ESP8266httpUpdate/examples/httpUpdate/httpUpdate.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* httpUpdate.ino
*
* Created on: 27.11.2015
*
*/

#include <Arduino.h>

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>

#include <ESP8266httpClient.h>
#include <ESP8266httpUpdate.h>

#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)) {

t_httpUpdate_return ret = ESPhttpUpdate.update("http://server/file.bin");
//t_httpUpdate_return ret = ESPhttpUpdate.update("https://server/file.bin");

switch(ret) {
case HTTP_UPDATE_FAILED:
USE_SERIAL.println("HTTP_UPDATE_FAILD");
break;

case HTTP_UPDATE_NO_UPDATES:
USE_SERIAL.println("HTTP_UPDATE_NO_UPDATES");
break;

case HTTP_UPDATE_OK:
USE_SERIAL.println("HTTP_UPDATE_OK");
break;
}
}
}

Loading