From 12c71aa8995b481faf09ebcf21d7bbaf9309c588 Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Mon, 30 Nov 2015 15:00:47 +0200 Subject: [PATCH 01/57] memory housekeeping --- .../ESP8266WebServer/src/ESP8266WebServer.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp index bc9a3fa3a..e9f88684f 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp @@ -87,17 +87,25 @@ bool ESP8266WebServer::authenticate(const char * username, const char * password authReq.trim(); char toencodeLen = strlen(username)+strlen(password)+1; char *toencode = new char[toencodeLen]; - if(toencode == NULL) + if(toencode == NULL){ + authReq = String(); return false; + } char *encoded = new char[base64_encode_expected_len(toencodeLen)+1]; - if(encoded == NULL) + if(encoded == NULL){ + authReq = String(); + delete[] toencode; return false; - + } sprintf(toencode, "%s:%s", username, password); if(base64_encode_chars(toencode, toencodeLen, encoded) > 0 && authReq.equals(encoded)){ authReq = String(); + delete[] toencode; + delete[] encoded; return true; } + delete[] toencode; + delete[] encoded; } authReq = String(); } From ee77b6fafed8dc6d4ab8fe362b53abb78bb67a91 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Mon, 30 Nov 2015 19:58:05 +0100 Subject: [PATCH 02/57] add core_esp8266_features.h to be able to detect the features and librarys included in the ESP core --- cores/esp8266/core_esp8266_features.h | 32 +++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 cores/esp8266/core_esp8266_features.h diff --git a/cores/esp8266/core_esp8266_features.h b/cores/esp8266/core_esp8266_features.h new file mode 100644 index 000000000..bafcd3aee --- /dev/null +++ b/cores/esp8266/core_esp8266_features.h @@ -0,0 +1,32 @@ +/* + core_esp8266_features.h - list of features integrated in to ESP8266 core + + Copyright (c) 2014 Ivan Grokhotkov. 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 CORE_ESP8266_FEATURES_H +#define CORE_ESP8266_FEATURES_H + + +#define CORE_HAS_LIBB64 + + +#endif + From 1da7f91a080e6b68bf3e9efbe2005bb826a4460f Mon Sep 17 00:00:00 2001 From: Stavros Korokithakis Date: Tue, 1 Dec 2015 05:26:05 +0200 Subject: [PATCH 03/57] Make progress print on the same line. --- libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino b/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino index ec621bb79..21e6761a1 100644 --- a/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino +++ b/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino @@ -33,7 +33,7 @@ void setup() { Serial.println("End"); }); ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { - Serial.printf("Progress: %u%%\n", (progress / (total / 100))); + Serial.printf("Progress: %u%%\r", (progress / (total / 100))); }); ArduinoOTA.onError([](ota_error_t error) { Serial.printf("Error[%u]: ", error); From 239352b7cfc0168f64b164333699d7a7e7e54b97 Mon Sep 17 00:00:00 2001 From: Stavros Korokithakis Date: Tue, 1 Dec 2015 05:27:06 +0200 Subject: [PATCH 04/57] Add linebreak. --- libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino b/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino index 21e6761a1..e0e98c150 100644 --- a/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino +++ b/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino @@ -35,6 +35,7 @@ void setup() { ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { Serial.printf("Progress: %u%%\r", (progress / (total / 100))); }); + Serial.println("") ArduinoOTA.onError([](ota_error_t error) { Serial.printf("Error[%u]: ", error); if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); From c2c7cc3a7145f80d6d289bc85626b7e9faccc994 Mon Sep 17 00:00:00 2001 From: Stavros Korokithakis Date: Tue, 1 Dec 2015 05:32:42 +0200 Subject: [PATCH 05/57] Print a newline properly. --- libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino b/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino index e0e98c150..50e926efe 100644 --- a/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino +++ b/libraries/ArduinoOTA/examples/BasicOTA/BasicOTA.ino @@ -30,12 +30,11 @@ void setup() { Serial.println("Start"); }); ArduinoOTA.onEnd([]() { - Serial.println("End"); + Serial.println("\nEnd"); }); ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { Serial.printf("Progress: %u%%\r", (progress / (total / 100))); }); - Serial.println("") ArduinoOTA.onError([](ota_error_t error) { Serial.printf("Error[%u]: ", error); if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); From ac143b463bb20cec30f5d8b4cd6ce0610ab35862 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Tue, 1 Dec 2015 17:13:00 +0100 Subject: [PATCH 06/57] improve docs see #1120 --- doc/ota_updates/ota_updates.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/doc/ota_updates/ota_updates.md b/doc/ota_updates/ota_updates.md index 8071a2303..d0fdf50a3 100644 --- a/doc/ota_updates/ota_updates.md +++ b/doc/ota_updates/ota_updates.md @@ -79,7 +79,13 @@ void onError(OTA_CALLBACK_ERROR (fn)); ### Basic Requirements -- Flash chip size is 2x the size of the sketch. +Flash chip size needs a size thats is able to hold the old sketch (currently running) and the new sketch (OTA) at the same time. +keep in mind that the File system and EEPROM for example needs space too (one time) see [flash layout](https://github.com/esp8266/Arduino/blob/master/doc/filesystem.md#flash-layout). +```cpp +ESP.getFreeSketchSpace(); +``` +can be used for checking the free space for the new sketch. + The following chapters provide more details and specific methods of doing OTA. @@ -318,7 +324,7 @@ Example header data: [HTTP_X_ESP8266_AP_MAC] => 1A:FE:AA:AA:AA:AA [HTTP_X_ESP8266_FREE_SPACE] => 671744 [HTTP_X_ESP8266_SKETCH_SIZE] => 373940 - [HTTP_X_ESP8266_CHIP_SIZE] => 524288 + [HTTP_X_ESP8266_CHIP_SIZE] => 4194304 [HTTP_X_ESP8266_SDK_VERSION] => 1.3.0 [HTTP_X_ESP8266_VERSION] => DOOR-7-g14f53a19 ``` From 6a9f044f873fa0e0cf6655127f593dfc55ac5c4c Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Tue, 1 Dec 2015 17:26:45 +0100 Subject: [PATCH 07/57] relative link --- doc/ota_updates/ota_updates.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ota_updates/ota_updates.md b/doc/ota_updates/ota_updates.md index d0fdf50a3..42bcb06ac 100644 --- a/doc/ota_updates/ota_updates.md +++ b/doc/ota_updates/ota_updates.md @@ -80,7 +80,7 @@ void onError(OTA_CALLBACK_ERROR (fn)); ### Basic Requirements Flash chip size needs a size thats is able to hold the old sketch (currently running) and the new sketch (OTA) at the same time. -keep in mind that the File system and EEPROM for example needs space too (one time) see [flash layout](https://github.com/esp8266/Arduino/blob/master/doc/filesystem.md#flash-layout). +keep in mind that the File system and EEPROM for example needs space too (one time) see [flash layout](../filesystem.md#flash-layout). ```cpp ESP.getFreeSketchSpace(); ``` From c12fc967f7811d4bccbf6cb7cc97f29c73e01e1e Mon Sep 17 00:00:00 2001 From: Dimitris Lampridis Date: Wed, 2 Dec 2015 16:12:41 +0200 Subject: [PATCH 08/57] added UTFT-ESP8266 to the list of compatible third-party libraries --- doc/libraries.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/libraries.md b/doc/libraries.md index cb6ad3272..314b1aa51 100644 --- a/doc/libraries.md +++ b/doc/libraries.md @@ -151,3 +151,4 @@ Libraries that don't rely on low-level access to AVR registers should work well. - [RTC](https://github.com/Makuna/Rtc) - Arduino Library for Ds1307 & Ds3231 compatible with ESP8266. - [Souliss, Smart Home](https://github.com/souliss/souliss) - Framework for Smart Home based on Arduino, Android and openHAB. - [ST7735](https://github.com/nzmichaelh/Adafruit-ST7735-Library) - Adafruit's ST7735 library modified to be compatible with ESP8266. Just make sure to modify the pins in the examples as they are still AVR specific. +- [UTFT-ESP8266](https://github.com/gnulabis/UTFT-ESP8266) - UTFT display library with support for ESP8266. Only serial interface (SPI) displays are supported for now (no 8-bit parallel mode, etc). Also includes support for the hardware SPI controller of the ESP8266. From 6620ec6e3610e30639d1eae1b6a3f60e93c26f70 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 3 Dec 2015 09:08:42 +0300 Subject: [PATCH 09/57] Set CPU frequency before running setup --- cores/esp8266/core_esp8266_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index 92c48312d..5913fa5c2 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -98,11 +98,11 @@ extern "C" void optimistic_yield(uint32_t interval_us) { static void loop_wrapper() { static bool setup_done = false; + preloop_update_frequency(); if(!setup_done) { setup(); setup_done = true; } - preloop_update_frequency(); loop(); esp_schedule(); } From 655437752b5b8548cce67048b8e828b62a3fb95d Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 3 Dec 2015 09:09:40 +0300 Subject: [PATCH 10/57] Update axTLS to 34ff442 Use hardware RNG --- tools/sdk/lib/libaxtls.a | Bin 557778 -> 556130 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tools/sdk/lib/libaxtls.a b/tools/sdk/lib/libaxtls.a index e8c08dc1ef1362b14282637413af332fba65dd98..b74d97cc434d721102ac4874ea72865d8ff219f8 100644 GIT binary patch delta 10024 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 E3tcVo8~^|S From 14b70e9328e78c94ba0c0042766a11854ac389de Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 4 Dec 2015 19:02:46 +0300 Subject: [PATCH 11/57] Allow setting client side TLS key and certificate --- .../examples/HTTPSRequest/HTTPSRequest.ino | 4 +- .../ESP8266WiFi/src/WiFiClientSecure.cpp | 74 ++++++++++++++++++ libraries/ESP8266WiFi/src/WiFiClientSecure.h | 16 ++++ tools/sdk/lib/libaxtls.a | Bin 556130 -> 554486 bytes 4 files changed, 92 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266WiFi/examples/HTTPSRequest/HTTPSRequest.ino b/libraries/ESP8266WiFi/examples/HTTPSRequest/HTTPSRequest.ino index 975fe13ef..6d10d5115 100644 --- a/libraries/ESP8266WiFi/examples/HTTPSRequest/HTTPSRequest.ino +++ b/libraries/ESP8266WiFi/examples/HTTPSRequest/HTTPSRequest.ino @@ -4,7 +4,7 @@ * This example demonstrates how to use * WiFiClientSecure class to access HTTPS API. * We fetch and display the status of - * esp8266/Arduino project continous integration + * esp8266/Arduino project continuous integration * build. * * Created by Ivan Grokhotkov, 2015. @@ -54,7 +54,7 @@ void setup() { Serial.println("certificate doesn't match"); } - String url = "/repos/esp8266/Arduino/commits/esp8266/status"; + String url = "/repos/esp8266/Arduino/commits/master/status"; Serial.print("requesting URL: "); Serial.println(url); diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp b/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp index 6d4365221..247701acd 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp @@ -50,6 +50,17 @@ extern "C" #define SSL_DEBUG_OPTS 0 #endif +uint8_t* default_private_key = 0; +uint32_t default_private_key_len = 0; +static bool default_private_key_dynamic = false; +// +uint8_t* default_certificate = 0; +uint32_t default_certificate_len = 0; +static bool default_certificate_dynamic = false; + +static void clear_private_key(); +static void clear_certificate(); + class SSLContext { public: @@ -70,6 +81,9 @@ public: if (_ssl_ctx_refcnt == 0) { ssl_ctx_free(_ssl_ctx); } + + clear_private_key(); + clear_certificate(); } void ref() { @@ -337,6 +351,66 @@ bool WiFiClientSecure::verify(const char* fp, const char* url) { return true; } +void WiFiClientSecure::setCertificate(const uint8_t* cert_data, size_t size) { + clear_certificate(); + default_certificate = (uint8_t*) cert_data; + default_certificate_len = size; +} + +void WiFiClientSecure::setPrivateKey(const uint8_t* pk, size_t size) { + clear_private_key(); + default_private_key = (uint8_t*) pk; + default_private_key_len = size; +} + +bool WiFiClientSecure::loadCertificate(Stream& stream, size_t size) { + clear_certificate(); + default_certificate = new uint8_t[size]; + if (!default_certificate) { + return false; + } + if (stream.readBytes(default_certificate, size) != size) { + delete[] default_certificate; + return false; + } + default_certificate_dynamic = true; + default_certificate_len = size; + return true; +} + +bool WiFiClientSecure::loadPrivateKey(Stream& stream, size_t size) { + clear_private_key(); + default_private_key = new uint8_t[size]; + if (!default_private_key) { + return false; + } + if (stream.readBytes(default_private_key, size) != size) { + delete[] default_private_key; + return false; + } + default_private_key_dynamic = true; + default_private_key_len = size; + return true; +} + +static void clear_private_key() { + if (default_private_key && default_private_key_dynamic) { + delete[] default_private_key; + default_private_key_dynamic = false; + } + default_private_key = 0; + default_private_key_len = 0; +} + +static void clear_certificate() { + if (default_certificate && default_certificate_dynamic) { + delete[] default_certificate; + default_certificate_dynamic = false; + } + default_certificate = 0; + default_certificate_len = 0; +} + extern "C" int ax_port_read(int fd, uint8_t* buffer, size_t count) { ClientContext* _client = reinterpret_cast(fd); if (_client->state() != ESTABLISHED && !_client->getSize()) { diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecure.h b/libraries/ESP8266WiFi/src/WiFiClientSecure.h index 8ce11f939..07b111e1a 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecure.h +++ b/libraries/ESP8266WiFi/src/WiFiClientSecure.h @@ -48,6 +48,22 @@ public: int peek() override; void stop() override; + void setCertificate(const uint8_t* cert_data, size_t size); + void setPrivateKey(const uint8_t* pk, size_t size); + + bool loadCertificate(Stream& stream, size_t size); + bool loadPrivateKey(Stream& stream, size_t size); + + template + bool loadCertificate(TFile& file) { + return loadCertificate(file, file.size()); + } + + template + bool loadPrivateKey(TFile& file) { + return loadPrivateKey(file, file.size()); + } + protected: int _connectSSL(); diff --git a/tools/sdk/lib/libaxtls.a b/tools/sdk/lib/libaxtls.a index b74d97cc434d721102ac4874ea72865d8ff219f8..9e29c802bd67ed9c543db86b405a38974432558f 100644 GIT binary patch delta 19157 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 delta 21805 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 From 8cec66b23ba3b78e9abec9cd918b1b9cced5266c Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Fri, 4 Dec 2015 18:16:05 +0100 Subject: [PATCH 12/57] add a simple TCP example --- .../examples/WiFiClientMin/WiFiClientMin.ino | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 libraries/ESP8266WiFi/examples/WiFiClientMin/WiFiClientMin.ino diff --git a/libraries/ESP8266WiFi/examples/WiFiClientMin/WiFiClientMin.ino b/libraries/ESP8266WiFi/examples/WiFiClientMin/WiFiClientMin.ino new file mode 100644 index 000000000..9386362ff --- /dev/null +++ b/libraries/ESP8266WiFi/examples/WiFiClientMin/WiFiClientMin.ino @@ -0,0 +1,68 @@ +/* + * This sketch sends a message to a TCP server + * + */ + +#include +#include + +ESP8266WiFiMulti WiFiMulti; + +void setup() { + Serial.begin(115200); + delay(10); + + // We start by connecting to a WiFi network + WiFiMulti.addAP("SSID", "passpasspass"); + + Serial.println(); + Serial.println(); + Serial.print("Wait for WiFi... "); + + while(WiFiMulti.run() != WL_CONNECTED) { + Serial.print("."); + delay(500); + } + + Serial.println(""); + Serial.println("WiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); + + delay(500); +} + + +void loop() { + const uint16_t port = 80; + const char * host = "192.168.1.1"; // ip or dns + + + + Serial.print("connecting to "); + Serial.println(host); + + // Use WiFiClient class to create TCP connections + WiFiClient client; + + if (!client.connect(host, port)) { + Serial.println("connection failed"); + Serial.println("wait 5 sec..."); + delay(5000); + return; + } + + // This will send the request to the server + client.print("Send this data to server"); + + //read back one line from server + String line = client.readStringUntil('\r'); + client.println(line); + + Serial.println("closing connection"); + client.stop(); + + Serial.println("wait 5 sec..."); + delay(5000); +} + From 34571a0e9d2bfa69aa855c9b283cb7bc4abf0515 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Fri, 4 Dec 2015 18:20:40 +0100 Subject: [PATCH 13/57] typo --- .../examples/WiFiClientMin/WiFiClientMin.ino | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/ESP8266WiFi/examples/WiFiClientMin/WiFiClientMin.ino b/libraries/ESP8266WiFi/examples/WiFiClientMin/WiFiClientMin.ino index 9386362ff..accb37bf8 100644 --- a/libraries/ESP8266WiFi/examples/WiFiClientMin/WiFiClientMin.ino +++ b/libraries/ESP8266WiFi/examples/WiFiClientMin/WiFiClientMin.ino @@ -37,8 +37,8 @@ void loop() { const uint16_t port = 80; const char * host = "192.168.1.1"; // ip or dns - - + + Serial.print("connecting to "); Serial.println(host); @@ -47,8 +47,8 @@ void loop() { if (!client.connect(host, port)) { Serial.println("connection failed"); - Serial.println("wait 5 sec..."); - delay(5000); + Serial.println("wait 5 sec..."); + delay(5000); return; } @@ -61,8 +61,8 @@ void loop() { Serial.println("closing connection"); client.stop(); - + Serial.println("wait 5 sec..."); - delay(5000); + delay(5000); } From cedce24bf39171d2d74eab2d6aead61108a88530 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Fri, 4 Dec 2015 19:07:51 +0100 Subject: [PATCH 14/57] rename to WiFiClientBasic --- .../WiFiClientMin.ino => WiFiClientBasic/WiFiClientBasic.ino} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename libraries/ESP8266WiFi/examples/{WiFiClientMin/WiFiClientMin.ino => WiFiClientBasic/WiFiClientBasic.ino} (100%) diff --git a/libraries/ESP8266WiFi/examples/WiFiClientMin/WiFiClientMin.ino b/libraries/ESP8266WiFi/examples/WiFiClientBasic/WiFiClientBasic.ino similarity index 100% rename from libraries/ESP8266WiFi/examples/WiFiClientMin/WiFiClientMin.ino rename to libraries/ESP8266WiFi/examples/WiFiClientBasic/WiFiClientBasic.ino From e3137a0b559aeda228718fde4f46c0ff70786610 Mon Sep 17 00:00:00 2001 From: Rodrigo Mendez Date: Fri, 4 Dec 2015 18:24:08 -0600 Subject: [PATCH 15/57] added ESPino to supported boards --- boards.txt | 85 ++++++++++++++++++++++++++++++++++ variants/espino/pins_arduino.h | 73 +++++++++++++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 variants/espino/pins_arduino.h diff --git a/boards.txt b/boards.txt index 8ed16f539..5b8505dd2 100644 --- a/boards.txt +++ b/boards.txt @@ -691,3 +691,88 @@ d1_mini.menu.FlashSize.4M1M.build.spiffs_start=0x300000 d1_mini.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 d1_mini.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 d1_mini.menu.FlashSize.4M1M.build.spiffs_pagesize=256 + + +############################################################## +espino.name=ESPino + +espino.upload.tool=esptool +espino.upload.speed=115200 +espino.upload.resetmethod=ck +espino.upload.maximum_size=434160 +espino.upload.maximum_data_size=81920 +espino.upload.wait_for_upload_port=true +espino.serial.disableDTR=true +espino.serial.disableRTS=true + +espino.build.mcu=esp8266 +espino.build.f_cpu=80000000L +espino.build.board=ESP8266_ESP12 +espino.build.core=esp8266 +espino.build.variant=generic +espino.build.flash_mode=qio +espino.build.flash_size=4M +espino.build.flash_freq=40 +espino.build.spiffs_pagesize=256 + +espino.menu.UploadTool.esptool=Serial +espino.menu.UploadTool.esptool.upload.tool=esptool +espino.menu.UploadTool.esptool.upload.verbose=-vv +espino.menu.UploadTool.espota=OTA +espino.menu.UploadTool.espota.upload.tool=espota + +espino.menu.CpuFrequency.80=80 MHz +espino.menu.CpuFrequency.80.build.f_cpu=80000000L +espino.menu.CpuFrequency.160=160 MHz +espino.menu.CpuFrequency.160.build.f_cpu=160000000L + +espino.menu.FlashFreq.40=40MHz +espino.menu.FlashFreq.40.build.flash_freq=40 +espino.menu.FlashFreq.80=80MHz +espino.menu.FlashFreq.80.build.flash_freq=80 + +espino.menu.FlashMode.dio=DIO +espino.menu.FlashMode.dio.build.flash_mode=dio +espino.menu.FlashMode.qio=QIO +espino.menu.FlashMode.qio.build.flash_mode=qio + +espino.menu.UploadSpeed.115200=115200 +espino.menu.UploadSpeed.115200.upload.speed=115200 +espino.menu.UploadSpeed.9600=9600 +espino.menu.UploadSpeed.9600.upload.speed=9600 +espino.menu.UploadSpeed.57600=57600 +espino.menu.UploadSpeed.57600.upload.speed=57600 +espino.menu.UploadSpeed.256000.windows=256000 +espino.menu.UploadSpeed.256000.upload.speed=256000 +espino.menu.UploadSpeed.230400.linux=230400 +espino.menu.UploadSpeed.230400.macosx=230400 +espino.menu.UploadSpeed.230400.upload.speed=230400 +espino.menu.UploadSpeed.460800.linux=460800 +espino.menu.UploadSpeed.460800.macosx=460800 +espino.menu.UploadSpeed.460800.upload.speed=460800 +espino.menu.UploadSpeed.512000.windows=512000 +espino.menu.UploadSpeed.512000.upload.speed=512000 +espino.menu.UploadSpeed.921600=921600 +espino.menu.UploadSpeed.921600.upload.speed=921600 + +espino.menu.FlashSize.4M1M=4M (1M SPIFFS) +espino.menu.FlashSize.4M1M.build.flash_size=4M +espino.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espino.menu.FlashSize.4M1M.build.spiffs_start=0x300000 +espino.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 +espino.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 +espino.menu.FlashSize.4M1M.build.spiffs_pagesize=256 +espino.menu.FlashSize.4M1M.upload.maximum_size=1044464 + +espino.menu.FlashSize.4M3M=4M (3M SPIFFS) +espino.menu.FlashSize.4M3M.build.flash_size=4M +espino.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld +espino.menu.FlashSize.4M3M.build.spiffs_start=0x100000 +espino.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 +espino.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 +espino.menu.FlashSize.4M3M.upload.maximum_size=1044464 + +espino.menu.ResetMethod.ck=ck +espino.menu.ResetMethod.ck.upload.resetmethod=ck +espino.menu.ResetMethod.nodemcu=nodemcu +espino.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu diff --git a/variants/espino/pins_arduino.h b/variants/espino/pins_arduino.h new file mode 100644 index 000000000..2efad2db3 --- /dev/null +++ b/variants/espino/pins_arduino.h @@ -0,0 +1,73 @@ +/* + pins_arduino.h - Pin definition functions for Arduino + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2007 David A. Mellis + Modified for ESP8266 platform by Ivan Grokhotkov, 2014-2015. + + 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., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $ +*/ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#define EXTERNAL_NUM_INTERRUPTS 16 +#define NUM_DIGITAL_PINS 17 +#define NUM_ANALOG_INPUTS 1 + +#define analogInputToDigitalPin(p) ((p > 0)?NOT_A_PIN:0) +#define digitalPinToInterrupt(p) (((p) < EXTERNAL_NUM_INTERRUPTS)?p:NOT_A_PIN) +#define digitalPinHasPWM(p) (((p) < NUM_DIGITAL_PINS)?p:NOT_A_PIN) + +static const uint8_t SDA = 4; +static const uint8_t SCL = 5; + +static const uint8_t SS = 15; +static const uint8_t MOSI = 13; +static const uint8_t MISO = 12; +static const uint8_t SCK = 14; + +static const uint8_t BUILTIN_LED = 2; +static const uint8_t BUILTIN_LEDR = 2; +static const uint8_t BUILTIN_LEDG = 4; +static const uint8_t BUILTIN_LEDB = 5; +static const uint8_t BUILTIN_BUTTON = 0; + +static const uint8_t A0 = 17; + +// These serial port names are intended to allow libraries and architecture-neutral +// sketches to automatically default to the correct port name for a particular type +// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN, +// the first hardware serial port whose RX/TX pins are not dedicated to another use. +// +// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor +// +// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial +// +// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library +// +// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins. +// +// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX +// pins are NOT connected to anything by default. +#define SERIAL_PORT_MONITOR Serial +#define SERIAL_PORT_USBVIRTUAL Serial +#define SERIAL_PORT_HARDWARE Serial +#define SERIAL_PORT_HARDWARE_OPEN Serial + +#endif /* Pins_Arduino_h */ From d076012cc8b0a8d3c0917795ff56bad9205c526d Mon Sep 17 00:00:00 2001 From: Rodrigo Mendez Date: Fri, 4 Dec 2015 18:40:21 -0600 Subject: [PATCH 16/57] variant and maxium_size for ESPino board wasn't correct, fixed --- boards.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/boards.txt b/boards.txt index 5b8505dd2..b24d084de 100644 --- a/boards.txt +++ b/boards.txt @@ -699,7 +699,7 @@ espino.name=ESPino espino.upload.tool=esptool espino.upload.speed=115200 espino.upload.resetmethod=ck -espino.upload.maximum_size=434160 +espino.upload.maximum_size=1044464 espino.upload.maximum_data_size=81920 espino.upload.wait_for_upload_port=true espino.serial.disableDTR=true @@ -709,7 +709,7 @@ espino.build.mcu=esp8266 espino.build.f_cpu=80000000L espino.build.board=ESP8266_ESP12 espino.build.core=esp8266 -espino.build.variant=generic +espino.build.variant=espino espino.build.flash_mode=qio espino.build.flash_size=4M espino.build.flash_freq=40 From ac0264767ae932e57c95f6a233689863f455c641 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sat, 5 Dec 2015 13:04:24 +0100 Subject: [PATCH 17/57] #1151 SPI definition correction - SPILADDR --- cores/esp8266/esp8266_peri.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/esp8266/esp8266_peri.h b/cores/esp8266/esp8266_peri.h index 64c1f30b5..4fd057009 100644 --- a/cores/esp8266/esp8266_peri.h +++ b/cores/esp8266/esp8266_peri.h @@ -494,7 +494,7 @@ extern uint8_t esp8266_gpioToFn[16]; //SPI Phase Length Locations #define SPILCOMMAND 28 //4 bit in SPIxU2 default 7 (8bit) -#define SPILADDR 16 //6 bit in SPIxU1 default:23 (24bit) +#define SPILADDR 26 //6 bit in SPIxU1 default:23 (24bit) #define SPILDUMMY 0 //8 bit in SPIxU1 default:0 (0 cycles) #define SPILMISO 8 //9 bit in SPIxU1 default:0 (1bit) #define SPILMOSI 17 //9 bit in SPIxU1 default:0 (1bit) From f7bbea407e484771ca6ab9813990d20ccbb17f23 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Sat, 5 Dec 2015 16:29:37 +0300 Subject: [PATCH 18/57] Fix failure when trying to open empty file (#1126) --- cores/esp8266/spiffs_api.cpp | 11 +++++++++++ tests/FSWrapper/FSWrapper.ino | 10 +++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/cores/esp8266/spiffs_api.cpp b/cores/esp8266/spiffs_api.cpp index 978e2ea0d..f1689cbfe 100644 --- a/cores/esp8266/spiffs_api.cpp +++ b/cores/esp8266/spiffs_api.cpp @@ -410,6 +410,17 @@ protected: FileImplPtr SPIFFSImpl::open(const char* path, OpenMode openMode, AccessMode accessMode) { int mode = getSpiffsMode(openMode, accessMode); int fd = SPIFFS_open(&_fs, path, mode, 0); + if (fd < 0 && _fs.err_code == SPIFFS_ERR_DELETED && (openMode & OM_CREATE)) { + DEBUGV("SPIFFSImpl::open: fd=%d path=`%s` openMode=%d accessMode=%d err=%d, trying to remove\r\n", + fd, path, openMode, accessMode, _fs.err_code); + auto rc = SPIFFS_remove(&_fs, path); + if (rc != SPIFFS_OK) { + DEBUGV("SPIFFSImpl::open: SPIFFS_ERR_DELETED, but failed to remove path=`%s` openMode=%d accessMode=%d err=%d\r\n", + path, openMode, accessMode, _fs.err_code); + return FileImplPtr(); + } + fd = SPIFFS_open(&_fs, path, mode, 0); + } if (fd < 0) { DEBUGV("SPIFFSImpl::open: fd=%d path=`%s` openMode=%d accessMode=%d err=%d\r\n", fd, path, openMode, accessMode, _fs.err_code); diff --git a/tests/FSWrapper/FSWrapper.ino b/tests/FSWrapper/FSWrapper.ino index b152093d5..099065f4f 100644 --- a/tests/FSWrapper/FSWrapper.ino +++ b/tests/FSWrapper/FSWrapper.ino @@ -139,7 +139,15 @@ void setup() { fail("some files left after format"); } } - + { + File tmp = SPIFFS.open("/tmp.txt", "w"); + } + { + File tmp = SPIFFS.open("/tmp.txt", "w"); + if (!tmp) { + fail("failed to re-open empty file"); + } + } Serial.println("success"); } From 68a406274af6dbcbecf5aaeae5c97654aee35b14 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sat, 5 Dec 2015 17:16:53 +0100 Subject: [PATCH 19/57] add parameter name to h for better reading --- cores/esp8266/Updater.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/esp8266/Updater.h b/cores/esp8266/Updater.h index b9f1b3d06..a25cb081b 100644 --- a/cores/esp8266/Updater.h +++ b/cores/esp8266/Updater.h @@ -26,7 +26,7 @@ class UpdaterClass { Call this to check the space needed for the update Will return false if there is not enough space */ - bool begin(size_t size, int = U_FLASH); + bool begin(size_t size, int command = U_FLASH); /* Writes a buffer to the flash and increments the address From 02366bb9352f0ac6a7ae4a394ab17f8a66a18240 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sat, 5 Dec 2015 17:17:24 +0100 Subject: [PATCH 20/57] add example makefile.init file for eclipse --- doc/eclipse/makefile.init | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 doc/eclipse/makefile.init diff --git a/doc/eclipse/makefile.init b/doc/eclipse/makefile.init new file mode 100644 index 000000000..f8e6d9daa --- /dev/null +++ b/doc/eclipse/makefile.init @@ -0,0 +1,39 @@ +vecho := @echo +Q := @ + +PROJECT_NAME=project_name + +OTA_IP=192.168.254.100 +OTA_PORT=8266 + +SERIAL_PORT=COM3 +SERIAL_BAUD=230400 + +ARDUINO_BASE = D:/Coding/avr/Programme/arduino-nightly +ESP8266_BASE = $(ARDUINO_BASE)/hardware/esp8266com/esp8266 +ESP8266_TOOLS = $(ESP8266_BASE)/tools +XTENSA_TOOLS_ROOT = $(ESP8266_TOOLS)/xtensa-lx106-elf/bin + +PYTHON_BIN = python +ESPTOOL_PY_BIN = $(ESP8266_TOOLS)/esptool.py +ESPOTA_PY_BIN = $(ESP8266_TOOLS)/espota.py +ESPTOOL_BIN = $(ESP8266_TOOLS)/esptool/esptool.exe + +ota: + $(vecho) ota... + $(PYTHON_BIN) $(ESPOTA_PY_BIN) -i $(OTA_IP) -p $(OTA_PORT) --auth= -f ./$(PROJECT_NAME).bin + +ota_spiffs: + $(vecho) ota spiffs... + $(PYTHON_BIN) $(ESPOTA_PY_BIN) -i $(OTA_IP) -p $(OTA_PORT) --auth= -s -f ./$(PROJECT_NAME)_spiffs.bin + +erase_flash: + $(vecho) "Erase Flash" + $(PYTHON_BIN) $(ESPTOOL_PY_BIN) -p $(ESPPORT) -b $(SERIAL_BAUD) erase_flash + +dumpmem: + $(vecho) "Read Flash need some time..." + $(PYTHON_BIN) $(ESPTOOL_PY_BIN) -p $(ESPPORT) -b $(ESPBAUD) read_flash 0 4194304 dump.bin + +objdump: + "$(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-objdump" -S $(PROJECT_NAME).elf > $(PROJECT_NAME).dobj From d06b9105d56470a6fb3749600d543406247ba046 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sat, 5 Dec 2015 17:22:28 +0100 Subject: [PATCH 21/57] fix C&P... --- doc/eclipse/makefile.init | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/eclipse/makefile.init b/doc/eclipse/makefile.init index f8e6d9daa..76438d62c 100644 --- a/doc/eclipse/makefile.init +++ b/doc/eclipse/makefile.init @@ -29,11 +29,11 @@ ota_spiffs: erase_flash: $(vecho) "Erase Flash" - $(PYTHON_BIN) $(ESPTOOL_PY_BIN) -p $(ESPPORT) -b $(SERIAL_BAUD) erase_flash + $(PYTHON_BIN) $(ESPTOOL_PY_BIN) -p $(SERIAL_PORT) -b $(SERIAL_BAUD) erase_flash dumpmem: $(vecho) "Read Flash need some time..." - $(PYTHON_BIN) $(ESPTOOL_PY_BIN) -p $(ESPPORT) -b $(ESPBAUD) read_flash 0 4194304 dump.bin + $(PYTHON_BIN) $(ESPTOOL_PY_BIN) -p $(SERIAL_PORT) -b $(SERIAL_BAUD) read_flash 0 4194304 dump.bin objdump: "$(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-objdump" -S $(PROJECT_NAME).elf > $(PROJECT_NAME).dobj From ecce35d24058e3a6b77a86f845c732f2592b5540 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sat, 5 Dec 2015 20:33:08 +0100 Subject: [PATCH 22/57] allow SPIFFS --- .../src/ESP8266httpUpdate.cpp | 61 ++++++++++++++++--- .../ESP8266httpUpdate/src/ESP8266httpUpdate.h | 6 +- 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp index 39ba0555c..8907df24a 100644 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp @@ -23,9 +23,10 @@ * */ - #include "ESP8266httpUpdate.h" +extern "C" uint32_t _SPIFFS_start; +extern "C" uint32_t _SPIFFS_end; ESP8266HTTPUpdate::ESP8266HTTPUpdate(void) { } @@ -46,6 +47,19 @@ t_httpUpdate_return ESP8266HTTPUpdate::update(const char * url, const char * cur return handleUpdate(&http, current_version); } +/** + * + * @param url const char * + * @param current_version const char * + * @param httpsFingerprint const char * + * @return t_httpUpdate_return + */ +t_httpUpdate_return ESP8266HTTPUpdate::updateSpiffs(const char * url, const char * current_version, const char * httpsFingerprint) { + HTTPClient http; + http.begin(url, httpsFingerprint); + return handleUpdate(&http, current_version, false, true); +} + /** * * @param host const char * @@ -73,7 +87,7 @@ t_httpUpdate_return ESP8266HTTPUpdate::update(String host, uint16_t port, String * @param current_version const char * * @return t_httpUpdate_return */ -t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient * http, const char * current_version) { +t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient * http, const char * current_version, bool reboot, bool spiffs) { t_httpUpdate_return ret = HTTP_UPDATE_FAILED; @@ -85,6 +99,12 @@ t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient * http, const cha http->addHeader("x-ESP8266-chip-size", String(ESP.getFlashChipRealSize())); http->addHeader("x-ESP8266-sdk-version", ESP.getSdkVersion()); + if(spiffs) { + http->addHeader("x-ESP8266-mode", "spiffs"); + } else { + http->addHeader("x-ESP8266-mode", "sketch"); + } + if(current_version && current_version[0] != 0x00) { http->addHeader("x-ESP8266-version", current_version); } @@ -119,9 +139,20 @@ t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient * http, const cha switch(code) { case 200: ///< OK (Start Update) if(len > 0) { - if(len > ESP.getFreeSketchSpace()) { + bool startUpdate = false; + if(spiffs) { + size_t spiffsSize = ((size_t) &_SPIFFS_end - (size_t) &_SPIFFS_start); + if(len > (int) spiffsSize) { + DEBUG_HTTP_UPDATE("[httpUpdate] spiffsSize to low (%d) needed: %d\n", ESP.getFreeSketchSpace(), len); + } + } else { + if(len > (int) ESP.getFreeSketchSpace()) { + DEBUG_HTTP_UPDATE("[httpUpdate] FreeSketchSpace to low (%d) needed: %d\n", ESP.getFreeSketchSpace(), len); + } + } + + if(!startUpdate) { ret = HTTP_UPDATE_FAILED; - DEBUG_HTTP_UPDATE("[httpUpdate] FreeSketchSpace to low (%d) needed: %d\n", ESP.getFreeSketchSpace(), len); } else { WiFiClient * tcp = http->getStreamPtr(); @@ -131,11 +162,25 @@ t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient * http, const cha delay(100); - if(runUpdate(*tcp, len, http->header("x-MD5"))) { + int command; + + if(spiffs) { + command = U_SPIFFS; + DEBUG_HTTP_UPDATE("[httpUpdate] runUpdate spiffs...\n"); + } else { + command = U_FLASH; + DEBUG_HTTP_UPDATE("[httpUpdate] runUpdate flash...\n"); + } + + if(runUpdate(*tcp, len, http->header("x-MD5"), command)) { ret = HTTP_UPDATE_OK; DEBUG_HTTP_UPDATE("[httpUpdate] Update ok\n"); http->end(); - ESP.restart(); + + if(reboot) { + ESP.restart(); + } + } else { ret = HTTP_UPDATE_FAILED; DEBUG_HTTP_UPDATE("[httpUpdate] Update failed\n"); @@ -171,9 +216,9 @@ t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient * http, const cha * @param md5 String * @return true if Update ok */ -bool ESP8266HTTPUpdate::runUpdate(Stream& in, uint32_t size, String md5) { +bool ESP8266HTTPUpdate::runUpdate(Stream& in, uint32_t size, String md5, int command) { - if(!Update.begin(size)) { + if(!Update.begin(size, command)) { DEBUG_HTTP_UPDATE("[httpUpdate] Update.begin failed!\n"); return false; } diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h index a494695ff..f9a4d8030 100644 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h @@ -53,9 +53,11 @@ class ESP8266HTTPUpdate { t_httpUpdate_return update(const char * host, uint16_t port, const char * url = "/", const char * current_version = "", bool https = false, const char * httpsFingerprint = ""); t_httpUpdate_return update(String host, uint16_t port, String url = "/", String current_version = "", bool https = false, String httpsFingerprint = ""); + t_httpUpdate_return updateSpiffs(const char * url, const char * current_version, const char * httpsFingerprint); + protected: - t_httpUpdate_return handleUpdate(HTTPClient * http, const char * current_version); - bool runUpdate(Stream& in, uint32_t size, String md5); + t_httpUpdate_return handleUpdate(HTTPClient * http, const char * current_version, bool reboot = true, bool spiffs = false); + bool runUpdate(Stream& in, uint32_t size, String md5, int command = U_FLASH); }; extern ESP8266HTTPUpdate ESPhttpUpdate; From 95d53c37c381536cb9e87a0516082b1f5c2f26ba Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sat, 5 Dec 2015 20:47:58 +0100 Subject: [PATCH 23/57] add httpUpdateSPIFFS.ino example --- .../httpUpdateSPIFFS/httpUpdateSPIFFS.ino | 65 +++++++++++++++++++ .../src/ESP8266httpUpdate.cpp | 2 +- 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 libraries/ESP8266httpUpdate/examples/httpUpdateSPIFFS/httpUpdateSPIFFS.ino diff --git a/libraries/ESP8266httpUpdate/examples/httpUpdateSPIFFS/httpUpdateSPIFFS.ino b/libraries/ESP8266httpUpdate/examples/httpUpdateSPIFFS/httpUpdateSPIFFS.ino new file mode 100644 index 000000000..3d746af6c --- /dev/null +++ b/libraries/ESP8266httpUpdate/examples/httpUpdateSPIFFS/httpUpdateSPIFFS.ino @@ -0,0 +1,65 @@ +/** + * httpUpdateSPIFFS.ino + * + * Created on: 05.12.2015 + * + */ + +#include + +#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)) { + + USE_SERIAL.println("Update SPIFFS..."); + t_httpUpdate_return ret = ESPhttpUpdate.updateSpiffs("https://server/spiffs.bin"); + if(ret == HTTP_UPDATE_OK) { + USE_SERIAL.println("Update sketch..."); + 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; + } + } + } +} + diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp index 8907df24a..52a094c69 100644 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp @@ -143,7 +143,7 @@ t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient * http, const cha if(spiffs) { size_t spiffsSize = ((size_t) &_SPIFFS_end - (size_t) &_SPIFFS_start); if(len > (int) spiffsSize) { - DEBUG_HTTP_UPDATE("[httpUpdate] spiffsSize to low (%d) needed: %d\n", ESP.getFreeSketchSpace(), len); + DEBUG_HTTP_UPDATE("[httpUpdate] spiffsSize to low (%d) needed: %d\n", spiffsSize, len); } } else { if(len > (int) ESP.getFreeSketchSpace()) { From d8e3c766a33041158af3f97499742ee4eb522e0c Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sun, 6 Dec 2015 11:07:25 +0100 Subject: [PATCH 24/57] ESP8266HTTPUpdate - improve error displaying --- .../ESP8266httpUpdate/src/ESP8266httpUpdate.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp index 52a094c69..92b047b30 100644 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp @@ -24,6 +24,7 @@ */ #include "ESP8266httpUpdate.h" +#include extern "C" uint32_t _SPIFFS_start; extern "C" uint32_t _SPIFFS_end; @@ -218,8 +219,12 @@ t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient * http, const cha */ bool ESP8266HTTPUpdate::runUpdate(Stream& in, uint32_t size, String md5, int command) { + StreamString error; + if(!Update.begin(size, command)) { - DEBUG_HTTP_UPDATE("[httpUpdate] Update.begin failed!\n"); + Update.printError(error); + error.trim(); // remove line ending + DEBUG_HTTP_UPDATE("[httpUpdate] Update.begin failed! (%s)\n", error.c_str()); return false; } @@ -228,12 +233,16 @@ bool ESP8266HTTPUpdate::runUpdate(Stream& in, uint32_t size, String md5, int com } if(Update.writeStream(in) != size) { - DEBUG_HTTP_UPDATE("[httpUpdate] Update.writeStream failed!\n"); + Update.printError(error); + error.trim(); // remove line ending + DEBUG_HTTP_UPDATE("[httpUpdate] Update.writeStream failed! (%s)\n", error.c_str()); return false; } if(!Update.end()) { - DEBUG_HTTP_UPDATE("[httpUpdate] Update.end failed!\n"); + Update.printError(error); + error.trim(); // remove line ending + DEBUG_HTTP_UPDATE("[httpUpdate] Update.end failed! (%s)\n", error.c_str()); return false; } From 6fa70bda011419520c1484ab7f861114a827e45a Mon Sep 17 00:00:00 2001 From: Martin Ayotte Date: Sun, 6 Dec 2015 09:42:51 -0500 Subject: [PATCH 25/57] replace delay with while loop in WiFiClient.ino --- libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino b/libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino index 7ffc78acd..8ed67168a 100644 --- a/libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino +++ b/libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino @@ -71,7 +71,13 @@ void loop() { client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); - delay(10); + while (client.available() == 0) { + if (timeout - millis() < 0) { + Serial.println(">>> Client Timeout !"); + client.stop(); + return; + } + } // Read all the lines of the reply from server and print them to Serial while(client.available()){ From e166e85f739758a258567b2f49834b05dd8dbd16 Mon Sep 17 00:00:00 2001 From: Martin Ayotte Date: Sun, 6 Dec 2015 09:47:00 -0500 Subject: [PATCH 26/57] oupps ! I forgot to set the timout value --- libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino b/libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino index 8ed67168a..eb7c02eff 100644 --- a/libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino +++ b/libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino @@ -71,6 +71,7 @@ void loop() { client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); + int timeout = millis() + 5000; while (client.available() == 0) { if (timeout - millis() < 0) { Serial.println(">>> Client Timeout !"); From 3d1fbc60ab5c96294a6c68ea6bb9f292cb11aead Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Sun, 6 Dec 2015 20:22:54 +0300 Subject: [PATCH 27/57] Replace chain of UDP pbufs with a single pbuf before sending (#1009) Packets up to 1492 bytes may be sent this way. Also reduced pbuf_unit_size to 128 bytes. --- .../ESP8266WiFi/src/include/UdpContext.h | 58 ++++++++----------- 1 file changed, 23 insertions(+), 35 deletions(-) diff --git a/libraries/ESP8266WiFi/src/include/UdpContext.h b/libraries/ESP8266WiFi/src/include/UdpContext.h index d9347fd34..708007036 100644 --- a/libraries/ESP8266WiFi/src/include/UdpContext.h +++ b/libraries/ESP8266WiFi/src/include/UdpContext.h @@ -1,9 +1,9 @@ -/* +/* UdpContext.h - UDP connection handling on top of lwIP Copyright (c) 2014 Ivan Grokhotkov. 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 @@ -206,10 +206,10 @@ public: size_t max_size = _rx_buf->len - _rx_buf_offset; size = (size < max_size) ? size : max_size; DEBUGV(":urd %d, %d, %d\r\n", size, _rx_buf->len, _rx_buf_offset); - - os_memcpy(dst, reinterpret_cast(_rx_buf->payload) + _rx_buf_offset, size); + + memcpy(dst, reinterpret_cast(_rx_buf->payload) + _rx_buf_offset, size); _consume(size); - + return size; } @@ -236,7 +236,7 @@ public: { _reserve(_tx_buf_offset + size); } - + size_t left_to_copy = size; while(left_to_copy) { @@ -249,7 +249,7 @@ public: continue; } size_t will_copy = (left_to_copy < free_cur) ? left_to_copy : free_cur; - os_memcpy(reinterpret_cast(_tx_buf_cur->payload) + used_cur, data, will_copy); + memcpy(reinterpret_cast(_tx_buf_cur->payload) + used_cur, data, will_copy); _tx_buf_offset += will_copy; left_to_copy -= will_copy; data += will_copy; @@ -259,18 +259,20 @@ public: void send(ip_addr_t* addr = 0, uint16_t port = 0) { - size_t orig_size = _tx_buf_head->tot_len; - size_t data_size = _tx_buf_offset; - size_t size_adjustment = orig_size - data_size; - for (pbuf* p = _tx_buf_head; p; p = p->next) - { - p->tot_len -= size_adjustment; - if (!p->next) - { - p->len = p->tot_len; - } + pbuf* tx_copy = pbuf_alloc(PBUF_TRANSPORT, data_size, PBUF_RAM); + uint8_t* dst = reinterpret_cast(tx_copy->payload); + for (pbuf* p = _tx_buf_head; p; p = p->next) { + size_t will_copy = (data_size < p->len) ? data_size : p->len; + memcpy(dst, p->payload, will_copy); + dst += will_copy; + data_size -= will_copy; } + pbuf_free(_tx_buf_head); + _tx_buf_head = 0; + _tx_buf_cur = 0; + _tx_buf_offset = 0; + if (!addr) { addr = &_dest_addr; @@ -282,30 +284,16 @@ public: _pcb->ttl = _multicast_ttl; } - udp_sendto(_pcb, _tx_buf_head, addr, port); - + udp_sendto(_pcb, tx_copy, addr, port); _pcb->ttl = old_ttl; - - for (pbuf* p = _tx_buf_head; p; p = p->next) - { - p->tot_len += size_adjustment; - if (!p->next) - { - p->len = p->tot_len; - } - } - - pbuf_free(_tx_buf_head); - _tx_buf_head = 0; - _tx_buf_cur = 0; - _tx_buf_offset = 0; + pbuf_free(tx_copy); } private: void _reserve(size_t size) { - const size_t pbuf_unit_size = 512; + const size_t pbuf_unit_size = 128; if (!_tx_buf_head) { _tx_buf_head = pbuf_alloc(PBUF_TRANSPORT, pbuf_unit_size, PBUF_RAM); @@ -357,7 +345,7 @@ private: } - static void _s_recv(void *arg, + static void _s_recv(void *arg, udp_pcb *upcb, pbuf *p, ip_addr_t *addr, u16_t port) { From c6c7d2475059fff19f7127b0a4aba082c7ca7200 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Sun, 6 Dec 2015 20:39:54 +0300 Subject: [PATCH 28/57] Add __throw_logic_error (#1136) --- cores/esp8266/abi.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cores/esp8266/abi.cpp b/cores/esp8266/abi.cpp index b38f16453..ff865d9ca 100644 --- a/cores/esp8266/abi.cpp +++ b/cores/esp8266/abi.cpp @@ -68,6 +68,10 @@ void __throw_length_error(char const*) { void __throw_bad_alloc() { panic(); } + +void __throw_logic_error(const char* str) { + panic(); +} } // TODO: rebuild windows toolchain to make this unnecessary: From ee314f2cdc1890997516338491aeea4e4510ef71 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Sun, 6 Dec 2015 20:54:35 +0300 Subject: [PATCH 29/57] fix portInput(Output, Mode)Register definitions to return pointers (#1110) --- cores/esp8266/Arduino.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/cores/esp8266/Arduino.h b/cores/esp8266/Arduino.h index 7e06e0058..10c6ebd44 100644 --- a/cores/esp8266/Arduino.h +++ b/cores/esp8266/Arduino.h @@ -219,14 +219,12 @@ void loop(void); void yield(void); void optimistic_yield(uint32_t interval_us); -// Get the bit location within the hardware port of the given virtual pin. -// This comes from the pins_*.c file for the active board configuration. #define digitalPinToPort(pin) (0) #define digitalPinToBitMask(pin) (1UL << (pin)) #define digitalPinToTimer(pin) (0) -#define portOutputRegister(port) ((volatile uint32_t*) GPO) -#define portInputRegister(port) ((volatile uint32_t*) GPI) -#define portModeRegister(port) ((volatile uint32_t*) GPE) +#define portOutputRegister(port) ((volatile uint32_t*) &GPO) +#define portInputRegister(port) ((volatile uint32_t*) &GPI) +#define portModeRegister(port) ((volatile uint32_t*) &GPE) #define NOT_A_PIN -1 #define NOT_A_PORT -1 From cc0a8ead55ce756103ff47146cdbd499cd1a2d77 Mon Sep 17 00:00:00 2001 From: Christopher Pascoe Date: Sun, 6 Dec 2015 21:03:05 -0800 Subject: [PATCH 30/57] Always arm the "TX FIFO Empty" interrupt after we write into _tx_buffer. This avoids a race where the interrupt handler detects an empty _tx_buffer just before we write data into it. Note that commit d6f62943d4b511e7d5fe6147096c8979890416f5 works around this race when data is continually added to _tx_buffer in the hung state. We revert that change here as the race should no longer occur. Testing performed: - set UART_CONF1.txfifo_empty_thrhd=0x70 (which exacerbates the issue) - generate a ~240 byte burst of data, sent in back-to-back Serial1.write(, 4) calls, optionally followed by a Serial1.flush() Test results: - before this change, observe occasional unsent data and hang in flush() (if used). - after this change, data is sent as expected. --- cores/esp8266/HardwareSerial.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cores/esp8266/HardwareSerial.cpp b/cores/esp8266/HardwareSerial.cpp index 2e93f8aee..78108bee7 100644 --- a/cores/esp8266/HardwareSerial.cpp +++ b/cores/esp8266/HardwareSerial.cpp @@ -617,18 +617,15 @@ size_t HardwareSerial::write(uint8_t c) { size_t room = uart_get_tx_fifo_room(_uart); if(room > 0 && _tx_buffer->empty()) { uart_transmit_char(_uart, c); - if(room < 10) { - uart_arm_tx_interrupt(_uart); - } return 1; } while(_tx_buffer->room() == 0) { yield(); - uart_arm_tx_interrupt(_uart); } _tx_buffer->write(c); + uart_arm_tx_interrupt(_uart); return 1; } From 7133a6c1f99b74986586c56a9a2ab7013cdc7cb9 Mon Sep 17 00:00:00 2001 From: Christopher Pascoe Date: Mon, 7 Dec 2015 00:23:46 -0800 Subject: [PATCH 31/57] Ensure that we never write an out of bounds value (_bufend) to _begin or _end, even temporarily. Testing: - Boot tested, ran basic serial I/O code Notes: - Before this change, there are instruction like "s32i.n , , <_begin>" in the disassembled output, followed by an overwrite if turns out to be _bufend. After this change, there is only one store instruction to <_begin> per function. --- cores/esp8266/cbuf.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/cores/esp8266/cbuf.h b/cores/esp8266/cbuf.h index fee98a94b..ce3ac5c64 100644 --- a/cores/esp8266/cbuf.h +++ b/cores/esp8266/cbuf.h @@ -62,7 +62,7 @@ class cbuf { if(getSize() == 0) return -1; char result = *_begin; - if(++_begin == _bufend) _begin = _buf; + _begin = wrap_if_bufend(_begin + 1); return static_cast(result); } @@ -78,8 +78,7 @@ class cbuf { dst += top_size; } memcpy(dst, _begin, size_to_read); - _begin += size_to_read; - if(_begin == _bufend) _begin = _buf; + _begin = wrap_if_bufend(_begin + size_to_read); return size_read; } @@ -87,7 +86,7 @@ class cbuf { if(room() == 0) return 0; *_end = c; - if(++_end == _bufend) _end = _buf; + _end = wrap_if_bufend(_end + 1); return 1; } @@ -103,8 +102,7 @@ class cbuf { src += top_size; } memcpy(_end, src, size_to_write); - _end += size_to_write; - if(_end == _bufend) _end = _buf; + _end = wrap_if_bufend(_end + size_to_write); return size_written; } @@ -114,6 +112,10 @@ class cbuf { } private: + inline char* wrap_if_bufend(char* ptr) { + return (ptr == _bufend) ? _buf : ptr; + } + size_t _size; char* _buf; char* _bufend; From d8417c2855b685e31d1d5796c5a89e5a70d49e84 Mon Sep 17 00:00:00 2001 From: Christopher Pascoe Date: Mon, 7 Dec 2015 00:31:46 -0800 Subject: [PATCH 32/57] Remove a check in room() for (_begin == _end). It's covered by the (_end >= _begin) case. --- cores/esp8266/cbuf.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/cores/esp8266/cbuf.h b/cores/esp8266/cbuf.h index ce3ac5c64..087e7200b 100644 --- a/cores/esp8266/cbuf.h +++ b/cores/esp8266/cbuf.h @@ -42,9 +42,6 @@ class cbuf { if(_end >= _begin) { return _size - (_end - _begin) - 1; } - if(_begin == _end) { - return _size; - } return _begin - _end - 1; } From dd89de4dad042a427c7e7399d6bb2a1a1b5cc537 Mon Sep 17 00:00:00 2001 From: Jens Hauke Date: Mon, 7 Dec 2015 18:01:15 +0100 Subject: [PATCH 33/57] Make pgm_read_byte() and pgm_read_word() usable from c files. The two defines used reinterpret_cast<> which is only available when compiling with c++. Now using plain old c casts instead. --- cores/esp8266/pgmspace.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cores/esp8266/pgmspace.h b/cores/esp8266/pgmspace.h index 4ee599557..c9e83fa05 100644 --- a/cores/esp8266/pgmspace.h +++ b/cores/esp8266/pgmspace.h @@ -78,7 +78,7 @@ int vsnprintf_P(char *str, size_t strSize, PGM_P formatP, va_list ap) __attribut (__extension__({ \ PGM_P __local = (PGM_P)(addr); /* isolate varible for macro expansion */ \ ptrdiff_t __offset = ((uint32_t)__local & 0x00000003); /* byte aligned mask */ \ - const uint32_t* __addr32 = reinterpret_cast(reinterpret_cast(__local)-__offset); \ + const uint32_t* __addr32 = (const uint32_t*)((const uint8_t*)(__local)-__offset); \ uint8_t __result = ((*__addr32) >> (__offset * 8)); \ __result; \ })) @@ -87,7 +87,7 @@ int vsnprintf_P(char *str, size_t strSize, PGM_P formatP, va_list ap) __attribut (__extension__({ \ PGM_P __local = (PGM_P)(addr); /* isolate varible for macro expansion */ \ ptrdiff_t __offset = ((uint32_t)__local & 0x00000002); /* word aligned mask */ \ - const uint32_t* __addr32 = reinterpret_cast(reinterpret_cast(__local) - __offset); \ + const uint32_t* __addr32 = (const uint32_t*)((const uint8_t*)(__local) - __offset); \ uint16_t __result = ((*__addr32) >> (__offset * 8)); \ __result; \ })) From 8847d7ab1af8e4572b4a2afe5fcc0443cf22b338 Mon Sep 17 00:00:00 2001 From: Rodrigo Mendez Date: Mon, 7 Dec 2015 17:35:30 -0600 Subject: [PATCH 34/57] added ESPino to dox/boards.md and package_esp8266com_index.template.json. removed flash speed selection --- boards.txt | 5 ----- doc/boards.md | 9 +++++++++ package/package_esp8266com_index.template.json | 7 +++++-- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/boards.txt b/boards.txt index b24d084de..248622f74 100644 --- a/boards.txt +++ b/boards.txt @@ -726,11 +726,6 @@ espino.menu.CpuFrequency.80.build.f_cpu=80000000L espino.menu.CpuFrequency.160=160 MHz espino.menu.CpuFrequency.160.build.f_cpu=160000000L -espino.menu.FlashFreq.40=40MHz -espino.menu.FlashFreq.40.build.flash_freq=40 -espino.menu.FlashFreq.80=80MHz -espino.menu.FlashFreq.80.build.flash_freq=80 - espino.menu.FlashMode.dio=DIO espino.menu.FlashMode.dio.build.flash_mode=dio espino.menu.FlashMode.qio=QIO diff --git a/doc/boards.md b/doc/boards.md index e92c4c591..578ea319d 100644 --- a/doc/boards.md +++ b/doc/boards.md @@ -11,6 +11,7 @@ title: Supported Hardware * [Olimex MOD\-WIFI\-ESP8266](#olimex-mod-wifi-esp8266) * [SparkFun ESP8266 Thing](#sparkfun-esp8266-thing) * [SweetPea ESP\-210](#sweetpea-esp-210) + * [ESPino](#espino) * [Generic ESP8266 modules](#generic-esp8266-modules) * [Serial Adapter](#serial-adapter) * [Minimal Hardware Setup for Bootloading and Usage](#minimal-hardware-setup-for-bootloading-and-usage) @@ -91,6 +92,14 @@ Product page: https://www.sparkfun.com/products/13231 *TODO: add notes* +## ESPino + +ESPino integrates the ESP-12 module with a 3.3v regulator, CP2104 USB-Serial bridge and a micro USB connector for easy programming. It is designed for fitting in a breadboard and has an RGB Led and two buttons for easy prototyping. + +For more information about the hardware, pinout diagram and programming procedures, please see the [datasheet](https://github.com/makerlabmx/ESPino-tools/raw/master/Docs/ESPino-Datasheet-EN.pdf). + +Product page: http://www.espino.io/en + ## Generic ESP8266 modules These modules come in different form factors and pinouts. See the page at ESP8266 community wiki for more info: diff --git a/package/package_esp8266com_index.template.json b/package/package_esp8266com_index.template.json index ee1042450..d070d4809 100644 --- a/package/package_esp8266com_index.template.json +++ b/package/package_esp8266com_index.template.json @@ -43,11 +43,14 @@ { "name": "SweetPea ESP-210" }, - { + { "name": "WeMos D1" }, - { + { "name": "WeMos D1 mini" + }, + { + "name": "ESPino" } ], "toolsDependencies": [ From a3c3c934bcfae34dc4cac04f010dda7bc6bd44b2 Mon Sep 17 00:00:00 2001 From: tzapu Date: Tue, 8 Dec 2015 08:49:40 +0200 Subject: [PATCH 35/57] Update libraries.md Added link to WiFiManager --- doc/libraries.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/libraries.md b/doc/libraries.md index 314b1aa51..894143815 100644 --- a/doc/libraries.md +++ b/doc/libraries.md @@ -152,3 +152,4 @@ Libraries that don't rely on low-level access to AVR registers should work well. - [Souliss, Smart Home](https://github.com/souliss/souliss) - Framework for Smart Home based on Arduino, Android and openHAB. - [ST7735](https://github.com/nzmichaelh/Adafruit-ST7735-Library) - Adafruit's ST7735 library modified to be compatible with ESP8266. Just make sure to modify the pins in the examples as they are still AVR specific. - [UTFT-ESP8266](https://github.com/gnulabis/UTFT-ESP8266) - UTFT display library with support for ESP8266. Only serial interface (SPI) displays are supported for now (no 8-bit parallel mode, etc). Also includes support for the hardware SPI controller of the ESP8266. +- [WiFiManager](https://github.com/tzapu/WiFiManager) - WiFi Connection manager with web captive portal. If it can't connect, it starts AP mode and a configuration portal so you can choose and enter WiFi credentials. From 02e22b38cb17697d43f347478d63530c72b61e7d Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Tue, 8 Dec 2015 11:33:15 +0100 Subject: [PATCH 36/57] add define RANDOM_REG32 ESP8266_DREG(0x20E44) --- cores/esp8266/esp8266_peri.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cores/esp8266/esp8266_peri.h b/cores/esp8266/esp8266_peri.h index 4fd057009..e7aab1f03 100644 --- a/cores/esp8266/esp8266_peri.h +++ b/cores/esp8266/esp8266_peri.h @@ -834,4 +834,10 @@ extern uint8_t esp8266_gpioToFn[16]; #define I2STXCMM (0x7) //I2S_TX_CHAN_MOD #define I2STXCM (0) //I2S_TX_CHAN_MOD_S +/** + Random Number Generator 32bit + http://esp8266-re.foogod.com/wiki/Random_Number_Generator +**/ +#define RANDOM_REG32 ESP8266_DREG(0x20E44) + #endif From 22af40af184b28c64b31031a6b0a0edd407c80a7 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Tue, 8 Dec 2015 11:35:14 +0100 Subject: [PATCH 37/57] add note about Adafruit_ILI9341 --- doc/libraries.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/libraries.md b/doc/libraries.md index 314b1aa51..756293ef7 100644 --- a/doc/libraries.md +++ b/doc/libraries.md @@ -140,14 +140,15 @@ While many RC servo motors will accept the 3.3V IO data pin from a ESP8266, most Libraries that don't rely on low-level access to AVR registers should work well. Here are a few libraries that were verified to work: +- [Adafruit_ILI9341](https://github.com/Links2004/Adafruit_ILI9341) - Port of the Adafruit ILI9341 for the ESP8266 - [arduinoWebSockets](https://github.com/Links2004/arduinoWebSockets) - WebSocket Server and Client compatible with ESP8266 (RFC6455) -- [aREST](https://github.com/marcoschwartz/aREST) REST API handler library. +- [aREST](https://github.com/marcoschwartz/aREST) - REST API handler library. - [Blynk](https://github.com/blynkkk/blynk-library) - easy IoT framework for Makers (check out the [Kickstarter page](http://tiny.cc/blynk-kick)). - [DallasTemperature](https://github.com/milesburton/Arduino-Temperature-Control-Library.git) - [DHT-sensor-library](https://github.com/adafruit/DHT-sensor-library) - Arduino library for the DHT11/DHT22 temperature and humidity sensors. Download latest v1.1.1 library and no changes are necessary. Older versions should initialize DHT as follows: `DHT dht(DHTPIN, DHTTYPE, 15)` - [NeoPixel](https://github.com/adafruit/Adafruit_NeoPixel) - Adafruit's NeoPixel library, now with support for the ESP8266 (use version 1.0.2 or higher from Arduino's library manager). - [NeoPixelBus](https://github.com/Makuna/NeoPixelBus) - Arduino NeoPixel library compatible with ESP8266. Use the "NeoPixelAnimator" branch for ESP8266 to get HSL color support and more. -- [PubSubClient](https://github.com/Imroy/pubsubclient) MQTT library by @Imroy. +- [PubSubClient](https://github.com/Imroy/pubsubclient) - MQTT library by @Imroy. - [RTC](https://github.com/Makuna/Rtc) - Arduino Library for Ds1307 & Ds3231 compatible with ESP8266. - [Souliss, Smart Home](https://github.com/souliss/souliss) - Framework for Smart Home based on Arduino, Android and openHAB. - [ST7735](https://github.com/nzmichaelh/Adafruit-ST7735-Library) - Adafruit's ST7735 library modified to be compatible with ESP8266. Just make sure to modify the pins in the examples as they are still AVR specific. From 5cd42a0316b528fca61482ef41b6d75431e8f399 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 9 Dec 2015 09:23:47 +0300 Subject: [PATCH 38/57] WiFiClientSecure: don't trash certificate and private key on stop() --- libraries/ESP8266WiFi/src/WiFiClientSecure.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp b/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp index 247701acd..997fe5ccb 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp @@ -53,7 +53,7 @@ extern "C" uint8_t* default_private_key = 0; uint32_t default_private_key_len = 0; static bool default_private_key_dynamic = false; -// +static int s_pk_refcnt = 0; uint8_t* default_certificate = 0; uint32_t default_certificate_len = 0; static bool default_certificate_dynamic = false; @@ -81,9 +81,6 @@ public: if (_ssl_ctx_refcnt == 0) { ssl_ctx_free(_ssl_ctx); } - - clear_private_key(); - clear_certificate(); } void ref() { @@ -186,12 +183,17 @@ int SSLContext::_ssl_ctx_refcnt = 0; WiFiClientSecure::WiFiClientSecure() { + ++s_pk_refcnt; } WiFiClientSecure::~WiFiClientSecure() { if (_ssl) { _ssl->unref(); } + if (--s_pk_refcnt == 0) { + clear_private_key(); + clear_certificate(); + } } WiFiClientSecure::WiFiClientSecure(const WiFiClientSecure& other) From 8b161ecf16e4ef0250fa0e1164c4c746c2685034 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Wed, 9 Dec 2015 12:47:23 +0100 Subject: [PATCH 39/57] add http codes as enum t_http_codes --- .../ESP8266HTTPClient/src/ESP8266HTTPClient.h | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h index 2d1312a29..46c3de415 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h @@ -42,6 +42,71 @@ #define HTTPC_ERROR_NO_STREAM (-6) #define HTTPC_ERROR_NO_HTTP_SERVER (-7) +/// HTTP codes see RFC7231 +typedef enum { + HTTP_CODE_CONTINUE = 100, + HTTP_CODE_SWITCHING_PROTOCOLS = 101, + HTTP_CODE_PROCESSING = 102, + HTTP_CODE_OK = 200, + HTTP_CODE_CREATED = 201, + HTTP_CODE_ACCEPTED = 202, + HTTP_CODE_NON_AUTHORITATIVE_INFORMATION = 203, + HTTP_CODE_NO_CONTENT = 204, + HTTP_CODE_RESET_CONTENT = 205, + HTTP_CODE_PARTIAL_CONTENT = 206, + HTTP_CODE_MULTI_STATUS = 207, + HTTP_CODE_ALREADY_REPORTED = 208, + HTTP_CODE_IM_USED = 226, + HTTP_CODE_MULTIPLE_CHOICES = 300, + HTTP_CODE_MOVED_PERMANENTLY = 301, + HTTP_CODE_FOUND = 302, + HTTP_CODE_SEE_OTHER = 303, + HTTP_CODE_NOT_MODIFIED = 304, + HTTP_CODE_USE_PROXY = 305, + HTTP_CODE_TEMPORARY_REDIRECT = 307, + HTTP_CODE_PERMANENT_REDIRECT = 308, + HTTP_CODE_BAD_REQUEST = 400, + HTTP_CODE_UNAUTHORIZED = 401, + HTTP_CODE_PAYMENT_REQUIRED = 402, + HTTP_CODE_FORBIDDEN = 403, + HTTP_CODE_NOT_FOUND = 404, + HTTP_CODE_METHOD_NOT_ALLOWED = 405, + HTTP_CODE_NOT_ACCEPTABLE = 406, + HTTP_CODE_PROXY_AUTHENTICATION_REQUIRED = 407, + HTTP_CODE_REQUEST_TIMEOUT = 408, + HTTP_CODE_CONFLICT = 409, + HTTP_CODE_GONE = 410, + HTTP_CODE_LENGTH_REQUIRED = 411, + HTTP_CODE_PRECONDITION_FAILED = 412, + HTTP_CODE_PAYLOAD_TOO_LARGE = 413, + HTTP_CODE_URI_TOO_LONG = 414, + HTTP_CODE_UNSUPPORTED_MEDIA_TYPE = 415, + HTTP_CODE_RANGE_NOT_SATISFIABLE = 416, + HTTP_CODE_EXPECTATION_FAILED = 417, + HTTP_CODE_MISDIRECTED_REQUEST = 421, + HTTP_CODE_UNPROCESSABLE_ENTITY = 422, + HTTP_CODE_LOCKED = 423, + HTTP_CODE_FAILED_DEPENDENCY = 424, + HTTP_CODE_UNASSIGNED = 425, + HTTP_CODE_UPGRADE_REQUIRED = 426, + HTTP_CODE_UNASSIGNED = 427, + HTTP_CODE_PRECONDITION_REQUIRED = 428, + HTTP_CODE_TOO_MANY_REQUESTS = 429, + HTTP_CODE_UNASSIGNED = 430, + HTTP_CODE_REQUEST_HEADER_FIELDS_TOO_LARGE = 431, + HTTP_CODE_INTERNAL_SERVER_ERROR = 500, + HTTP_CODE_NOT_IMPLEMENTED = 501, + HTTP_CODE_BAD_GATEWAY = 502, + HTTP_CODE_SERVICE_UNAVAILABLE = 503, + HTTP_CODE_GATEWAY_TIMEOUT = 504, + HTTP_CODE_HTTP_VERSION_NOT_SUPPORTED = 505, + HTTP_CODE_VARIANT_ALSO_NEGOTIATES = 506, + HTTP_CODE_INSUFFICIENT_STORAGE = 507, + HTTP_CODE_LOOP_DETECTED = 508, + HTTP_CODE_UNASSIGNED = 509, + HTTP_CODE_NOT_EXTENDED = 510, + HTTP_CODE_NETWORK_AUTHENTICATION_REQUIRED = 511 +} t_http_codes; class HTTPClient { public: From e15c745e6f27ccf8cf8d2bcd3e42cb03857c8447 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Wed, 9 Dec 2015 12:50:55 +0100 Subject: [PATCH 40/57] remove some HTTP_CODE_UNASSIGNED --- libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h index 46c3de415..a455192ed 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h @@ -87,12 +87,9 @@ typedef enum { HTTP_CODE_UNPROCESSABLE_ENTITY = 422, HTTP_CODE_LOCKED = 423, HTTP_CODE_FAILED_DEPENDENCY = 424, - HTTP_CODE_UNASSIGNED = 425, HTTP_CODE_UPGRADE_REQUIRED = 426, - HTTP_CODE_UNASSIGNED = 427, HTTP_CODE_PRECONDITION_REQUIRED = 428, HTTP_CODE_TOO_MANY_REQUESTS = 429, - HTTP_CODE_UNASSIGNED = 430, HTTP_CODE_REQUEST_HEADER_FIELDS_TOO_LARGE = 431, HTTP_CODE_INTERNAL_SERVER_ERROR = 500, HTTP_CODE_NOT_IMPLEMENTED = 501, @@ -103,7 +100,6 @@ typedef enum { HTTP_CODE_VARIANT_ALSO_NEGOTIATES = 506, HTTP_CODE_INSUFFICIENT_STORAGE = 507, HTTP_CODE_LOOP_DETECTED = 508, - HTTP_CODE_UNASSIGNED = 509, HTTP_CODE_NOT_EXTENDED = 510, HTTP_CODE_NETWORK_AUTHENTICATION_REQUIRED = 511 } t_http_codes; From 1dabac60a925b0b548b78e49489cdac6ed5fd391 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Wed, 9 Dec 2015 12:56:49 +0100 Subject: [PATCH 41/57] rework HTTPclient examples --- .../examples/BasicHttpClient/BasicHttpClient.ino | 10 +++++++--- .../examples/ReuseConnection/ReuseConnection.ino | 11 ++++++++--- .../examples/StreamHttpClient/StreamHttpClient.ino | 11 +++++++---- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/libraries/ESP8266HTTPClient/examples/BasicHttpClient/BasicHttpClient.ino b/libraries/ESP8266HTTPClient/examples/BasicHttpClient/BasicHttpClient.ino index 3c722556b..8e2b5d2f4 100644 --- a/libraries/ESP8266HTTPClient/examples/BasicHttpClient/BasicHttpClient.ino +++ b/libraries/ESP8266HTTPClient/examples/BasicHttpClient/BasicHttpClient.ino @@ -43,24 +43,28 @@ void loop() { USE_SERIAL.print("[HTTP] begin...\n"); // configure traged server and url - //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 + //http.begin("https://192.168.1.12/test.html", "7a 9c f4 db 40 d3 62 5a 6e 21 bc 5c cc 66 c8 3e a1 45 59 38"); //HTTPS + http.begin("http://192.168.1.12/test.html"); //HTTP USE_SERIAL.print("[HTTP] GET...\n"); // start connection and send HTTP header int httpCode = http.GET(); + + // httpCode will be negative on error 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) { + if(httpCode == HTTP_CODE_OK) { String payload = http.getString(); USE_SERIAL.println(payload); } } else { USE_SERIAL.print("[HTTP] GET... failed, no connection or no HTTP server\n"); } + + http.end(); } delay(10000); diff --git a/libraries/ESP8266HTTPClient/examples/ReuseConnection/ReuseConnection.ino b/libraries/ESP8266HTTPClient/examples/ReuseConnection/ReuseConnection.ino index e725a1f76..36c189cb3 100644 --- a/libraries/ESP8266HTTPClient/examples/ReuseConnection/ReuseConnection.ino +++ b/libraries/ESP8266HTTPClient/examples/ReuseConnection/ReuseConnection.ino @@ -36,26 +36,31 @@ void setup() { WiFiMulti.addAP("SSID", "PASSWORD"); - + // allow reuse (if server supports it) + http.setReuse(true); } void loop() { // wait for WiFi connection if((WiFiMulti.run() == WL_CONNECTED)) { - http.begin("192.168.1.12", 80, "/test.html"); + http.begin("http://192.168.1.12/test.html"); + //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) { + if(httpCode == HTTP_CODE_OK) { http.writeToStream(&USE_SERIAL); } } else { USE_SERIAL.print("[HTTP] GET... failed, no connection or no HTTP server\n"); } + + http.end(); + } delay(1000); diff --git a/libraries/ESP8266HTTPClient/examples/StreamHttpClient/StreamHttpClient.ino b/libraries/ESP8266HTTPClient/examples/StreamHttpClient/StreamHttpClient.ino index 442fa6547..7f6c37872 100644 --- a/libraries/ESP8266HTTPClient/examples/StreamHttpClient/StreamHttpClient.ino +++ b/libraries/ESP8266HTTPClient/examples/StreamHttpClient/StreamHttpClient.ino @@ -42,19 +42,20 @@ void loop() { HTTPClient http; USE_SERIAL.print("[HTTP] begin...\n"); - // configure traged server and url - http.begin("192.168.1.12", 80, "/test.html"); + + // configure server and url + http.begin("http://192.168.1.12/test.html"); + //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) { + if(httpCode == HTTP_CODE_OK) { // get lenght of document (is -1 when Server sends no Content-Length header) int len = http.getSize(); @@ -91,6 +92,8 @@ void loop() { } else { USE_SERIAL.print("[HTTP] GET... failed, no connection or no HTTP server\n"); } + + http.end(); } delay(10000); From b1e3d2256a3f891909dacaa229551ba79151cae5 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Wed, 9 Dec 2015 13:01:08 +0100 Subject: [PATCH 42/57] add errorToString function --- .../BasicHttpClient/BasicHttpClient.ino | 2 +- .../ReuseConnection/ReuseConnection.ino | 2 +- .../StreamHttpClient/StreamHttpClient.ino | 2 +- .../src/ESP8266HTTPClient.cpp | 27 +++++++++++++++++++ .../ESP8266HTTPClient/src/ESP8266HTTPClient.h | 2 ++ 5 files changed, 32 insertions(+), 3 deletions(-) diff --git a/libraries/ESP8266HTTPClient/examples/BasicHttpClient/BasicHttpClient.ino b/libraries/ESP8266HTTPClient/examples/BasicHttpClient/BasicHttpClient.ino index 8e2b5d2f4..d3a5fbc7d 100644 --- a/libraries/ESP8266HTTPClient/examples/BasicHttpClient/BasicHttpClient.ino +++ b/libraries/ESP8266HTTPClient/examples/BasicHttpClient/BasicHttpClient.ino @@ -61,7 +61,7 @@ void loop() { USE_SERIAL.println(payload); } } else { - USE_SERIAL.print("[HTTP] GET... failed, no connection or no HTTP server\n"); + USE_SERIAL.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); } http.end(); diff --git a/libraries/ESP8266HTTPClient/examples/ReuseConnection/ReuseConnection.ino b/libraries/ESP8266HTTPClient/examples/ReuseConnection/ReuseConnection.ino index 36c189cb3..35babdc33 100644 --- a/libraries/ESP8266HTTPClient/examples/ReuseConnection/ReuseConnection.ino +++ b/libraries/ESP8266HTTPClient/examples/ReuseConnection/ReuseConnection.ino @@ -56,7 +56,7 @@ void loop() { http.writeToStream(&USE_SERIAL); } } else { - USE_SERIAL.print("[HTTP] GET... failed, no connection or no HTTP server\n"); + USE_SERIAL.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); } http.end(); diff --git a/libraries/ESP8266HTTPClient/examples/StreamHttpClient/StreamHttpClient.ino b/libraries/ESP8266HTTPClient/examples/StreamHttpClient/StreamHttpClient.ino index 7f6c37872..2e7f4487d 100644 --- a/libraries/ESP8266HTTPClient/examples/StreamHttpClient/StreamHttpClient.ino +++ b/libraries/ESP8266HTTPClient/examples/StreamHttpClient/StreamHttpClient.ino @@ -90,7 +90,7 @@ void loop() { } } else { - USE_SERIAL.print("[HTTP] GET... failed, no connection or no HTTP server\n"); + USE_SERIAL.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); } http.end(); diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp index 37b71dbc1..5561c62ae 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp @@ -454,6 +454,33 @@ String HTTPClient::getString(void) { return sstring; } +/** + * converts error code to String + * @param error int + * @return String + */ +String HTTPClient::errorToString(int error) { + switch(error) { + case HTTPC_ERROR_CONNECTION_REFUSED: + return String("connection refused"); + case HTTPC_ERROR_SEND_HEADER_FAILED: + return String("send header failed"); + case HTTPC_ERROR_SEND_PAYLOAD_FAILED: + return String("send payload failed"); + case HTTPC_ERROR_NOT_CONNECTED: + return String("not connected"); + case HTTPC_ERROR_CONNECTION_LOST: + return String("connection lost"); + case HTTPC_ERROR_NO_STREAM: + return String("no stream"); + case HTTPC_ERROR_NO_HTTP_SERVER: + return String("no HTTP server"); + default: + return String(); + } +} + + /** * adds Header to the request * @param name diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h index a455192ed..5d3fc51bc 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h @@ -147,6 +147,8 @@ class HTTPClient { int writeToStream(Stream * stream); String getString(void); + String errorToString(int error); + protected: struct RequestArgument { From 62f38bfef3681209933c88702ed3ad26db911cb6 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Wed, 9 Dec 2015 13:51:39 +0100 Subject: [PATCH 43/57] add base64 class --- cores/esp8266/base64.cpp | 63 ++++++++++++++++++++++++++++++++++++++++ cores/esp8266/base64.h | 36 +++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 cores/esp8266/base64.cpp create mode 100644 cores/esp8266/base64.h diff --git a/cores/esp8266/base64.cpp b/cores/esp8266/base64.cpp new file mode 100644 index 000000000..11deb0af0 --- /dev/null +++ b/cores/esp8266/base64.cpp @@ -0,0 +1,63 @@ +/** + * base64.cpp + * + * Created on: 09.12.2015 + * + * Copyright (c) 2015 Markus Sattler. All rights reserved. + * This file is part of the ESP8266 core 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 "Arduino.h" +extern "C" { +#include "libb64/cdecode.h" +#include "libb64/cencode.h" +} +#include "base64.h" + +/** + * convert input data to base64 + * @param data uint8_t * + * @param length size_t + * @return String + */ +String base64::encode(uint8_t * data, size_t length) { + // base64 needs more size then the source data + size_t size = ((length * 1.6f) + 1); + char * buffer = (char *) malloc(size); + if(buffer) { + base64_encodestate _state; + base64_init_encodestate(&_state); + int len = base64_encode_block((const char *) &data[0], length, &buffer[0], &_state); + len = base64_encode_blockend((buffer + len), &_state); + + String base64 = String(buffer); + free(buffer); + return base64; + } + return String("-FAIL-"); +} + +/** + * convert input data to base64 + * @param text String + * @return String + */ +String base64::encode(String text) { + return base64::encode((uint8_t *) text.c_str(), text.length()); +} + diff --git a/cores/esp8266/base64.h b/cores/esp8266/base64.h new file mode 100644 index 000000000..39be2d397 --- /dev/null +++ b/cores/esp8266/base64.h @@ -0,0 +1,36 @@ +/** + * base64.h + * + * Created on: 09.12.2015 + * + * Copyright (c) 2015 Markus Sattler. All rights reserved. + * This file is part of the ESP8266 core 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 CORE_BASE64_H_ +#define CORE_BASE64_H_ + +class base64 { + public: + static String encode(uint8_t * data, size_t length); + static String encode(String text); + private: +}; + + +#endif /* CORE_BASE64_H_ */ From a9ce1b4f2ebb774d69aab6573bd474d5d704ff4e Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Wed, 9 Dec 2015 13:51:55 +0100 Subject: [PATCH 44/57] add Authorization support for HTTP client --- cores/esp8266/core_esp8266_features.h | 1 + .../src/ESP8266HTTPClient.cpp | 26 +++++++++++++++++-- .../ESP8266HTTPClient/src/ESP8266HTTPClient.h | 4 ++- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/cores/esp8266/core_esp8266_features.h b/cores/esp8266/core_esp8266_features.h index bafcd3aee..ae5d58539 100644 --- a/cores/esp8266/core_esp8266_features.h +++ b/cores/esp8266/core_esp8266_features.h @@ -26,6 +26,7 @@ #define CORE_HAS_LIBB64 +#define CORE_HAS_BASE64_CLASS #endif diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp index 5561c62ae..357aebda3 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp @@ -26,9 +26,11 @@ #include #include #include +#include #include "ESP8266HTTPClient.h" + /** * constractor */ @@ -219,6 +221,20 @@ void HTTPClient::setUserAgent(const char * userAgent) { _userAgent = userAgent; } +/** + * set the Authorizatio for the http request + * @param user const char * + * @param password const char * + */ +void HTTPClient::setAuthorization(const char * user, const char * password) { + if(user && password) { + String auth = user; + auth += ":"; + auth += password; + _base64Authorization = base64::encode(auth); + } +} + /** * send a GET request * @return http code @@ -490,7 +506,7 @@ String HTTPClient::errorToString(int error) { void HTTPClient::addHeader(const String& name, const String& value, bool first) { // not allow set of Header handled by code - if(!name.equalsIgnoreCase("Connection") && !name.equalsIgnoreCase("User-Agent") && !name.equalsIgnoreCase("Host")) { + if(!name.equalsIgnoreCase("Connection") && !name.equalsIgnoreCase("User-Agent") && !name.equalsIgnoreCase("Host") && !(_base64Authorization.length() && name.equalsIgnoreCase("Authorization"))) { String headerLine = name; headerLine += ": "; headerLine += value; @@ -622,7 +638,13 @@ bool HTTPClient::sendHeader(const char * type) { } else { header += "close"; } - header += "\r\n" + _Headers + "\r\n"; + header += "\r\n"; + + if(_base64Authorization.length()) { + header += "Authorization: Basic " + _base64Authorization + "\r\n"; + } + + header += _Headers + "\r\n"; return (_tcp->write(header.c_str(), header.length()) == header.length()); } diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h index 5d3fc51bc..f6c4bba6a 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(...) @@ -121,6 +121,7 @@ class HTTPClient { void setReuse(bool reuse); /// keep-alive void setUserAgent(const char * userAgent); + void setAuthorization(const char * user, const char * password); /// request handling int GET(); @@ -172,6 +173,7 @@ class HTTPClient { String _Headers; String _userAgent; + String _base64Authorization; /// Response handling RequestArgument* _currentHeaders; From 85341ff25a0a144a3095b8a6f20fdd07f825fdf4 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Wed, 9 Dec 2015 14:19:28 +0100 Subject: [PATCH 45/57] HTTPClient phasing username + password from url --- .../src/ESP8266HTTPClient.cpp | 42 +++++++++++++------ .../ESP8266HTTPClient/src/ESP8266HTTPClient.h | 3 +- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp index 357aebda3..6a8d010e1 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp @@ -102,27 +102,34 @@ void HTTPClient::begin(String url, String httpsFingerprint) { String protocol; // check for : (http: or https: int index = url.indexOf(':'); - int index2; + //int index2; bool hasPort = false; if(index) { protocol = url.substring(0, index); url.remove(0, (index + 3)); // remove http:// or https:// - index = url.indexOf(':'); - index2 = url.indexOf('/'); + index = url.indexOf('/'); + String host = url.substring(0, index); + url.remove(0, index); // remove host part - if(index >= 0 && ((index2 >= 0 && index < index2) || index2 == 0)) { // do we have a port? - _host = url.substring(0, index); // hostname - url.remove(0, (index + 1)); // remove hostname + : + // get Authorization + index = host.indexOf('@'); + if(index >= 0) { + // auth info + String auth = host.substring(0, index); + host.remove(0, index +1); // remove auth part including @ + _base64Authorization = base64::encode(auth); + } - index = url.indexOf('/'); - _port = url.substring(0, index).toInt(); // get port - url.remove(0, index); // remove port + // get port + index = host.indexOf(':'); + if(index >= 0) { + _host = host.substring(0, index); // hostname + host.remove(0, (index + 1)); // remove hostname + : + _port = host.toInt(); // get port hasPort = true; } else { - index = index2; - _host = url.substring(0, index); - url.remove(0, index); // remove hostname + _host = host; } _url = url; @@ -141,6 +148,7 @@ void HTTPClient::begin(String url, String httpsFingerprint) { DEBUG_HTTPCLIENT("[HTTP-Client][begin] protocol: %s unknown?!\n", protocol.c_str()); return; } + } DEBUG_HTTPCLIENT("[HTTP-Client][begin] host: %s port: %d url: %s https: %d httpsFingerprint: %s\n", _host.c_str(), _port, _url.c_str(), _https, _httpsFingerprint.c_str()); @@ -235,6 +243,16 @@ void HTTPClient::setAuthorization(const char * user, const char * password) { } } +/** + * set the Authorizatio for the http request + * @param auth const char * base64 + */ +void HTTPClient::setAuthorization(const char * auth) { + if(auth) { + _base64Authorization = auth; + } +} + /** * send a GET request * @return http code diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h index f6c4bba6a..2bf6d0565 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(...) @@ -122,6 +122,7 @@ class HTTPClient { void setReuse(bool reuse); /// keep-alive void setUserAgent(const char * userAgent); void setAuthorization(const char * user, const char * password); + void setAuthorization(const char * auth); /// request handling int GET(); From 0a4da83243bdbcc30cd36639765ca966d7aeb268 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Wed, 9 Dec 2015 14:19:49 +0100 Subject: [PATCH 46/57] HTTPClient add Authorization example --- .../examples/Authorization/Authorization.ino | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 libraries/ESP8266HTTPClient/examples/Authorization/Authorization.ino diff --git a/libraries/ESP8266HTTPClient/examples/Authorization/Authorization.ino b/libraries/ESP8266HTTPClient/examples/Authorization/Authorization.ino new file mode 100644 index 000000000..79a4c3fdf --- /dev/null +++ b/libraries/ESP8266HTTPClient/examples/Authorization/Authorization.ino @@ -0,0 +1,84 @@ +/** + * Authorization.ino + * + * Created on: 09.12.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("http://user:password@192.168.1.12/test.html"); + + /* + // or + http.begin("http://192.168.1.12/test.html"); + http.setAuthorization("user", "password"); + + // or + http.begin("http://192.168.1.12/test.html"); + http.setAuthorization("dXNlcjpwYXN3b3Jk"); + */ + + + USE_SERIAL.print("[HTTP] GET...\n"); + // start connection and send HTTP header + int httpCode = http.GET(); + + // httpCode will be negative on error + 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 == HTTP_CODE_OK) { + String payload = http.getString(); + USE_SERIAL.println(payload); + } + } else { + USE_SERIAL.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); + } + + http.end(); + } + + delay(10000); +} + From b1ea7b602e3b731f7b9e5f666aabfe7d5e743d41 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Wed, 9 Dec 2015 16:27:04 +0100 Subject: [PATCH 47/57] httpUpdate Improve error handling --- .../ESP8266httpUpdate/src/ESP8266httpUpdate.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp index 92b047b30..763efea4b 100644 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp @@ -120,6 +120,12 @@ t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient * http, const cha int code = http->GET(); int len = http->getSize(); + if(code <= 0) { + DEBUG_HTTP_UPDATE("[httpUpdate] HTTP error: %s\n", http->errorToString(code).c_str()); + http->end(); + return HTTP_UPDATE_FAILED; + } + DEBUG_HTTP_UPDATE("[httpUpdate] Header read fin.\n"); DEBUG_HTTP_UPDATE("[httpUpdate] Server header:\n"); DEBUG_HTTP_UPDATE("[httpUpdate] - code: %d\n", code); @@ -138,7 +144,7 @@ t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient * http, const cha } switch(code) { - case 200: ///< OK (Start Update) + case HTTP_CODE_OK: ///< OK (Start Update) if(len > 0) { bool startUpdate = false; if(spiffs) { @@ -192,19 +198,18 @@ t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient * http, const cha DEBUG_HTTP_UPDATE("[httpUpdate] Content-Length is 0 or not set by Server?!\n"); } break; - case 304: + case HTTP_CODE_NOT_MODIFIED: ///< Not Modified (No updates) ret = HTTP_UPDATE_NO_UPDATES; break; - case 403: - ///< Forbidden - // todo handle login default: ret = HTTP_UPDATE_FAILED; - DEBUG_HTTP_UPDATE("[httpUpdate] Code is (%d)\n", code); + DEBUG_HTTP_UPDATE("[httpUpdate] HTTP Code is (%d)\n", code); + //http->writeToStream(&Serial1); break; } + http->end(); return ret; From 95089b75b909da9828f81047d90162a272b548dd Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Wed, 9 Dec 2015 19:56:14 +0100 Subject: [PATCH 48/57] fix startUpdate always false --- libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp index 763efea4b..785258de9 100644 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.cpp @@ -146,15 +146,17 @@ t_httpUpdate_return ESP8266HTTPUpdate::handleUpdate(HTTPClient * http, const cha switch(code) { case HTTP_CODE_OK: ///< OK (Start Update) if(len > 0) { - bool startUpdate = false; + bool startUpdate = true; if(spiffs) { size_t spiffsSize = ((size_t) &_SPIFFS_end - (size_t) &_SPIFFS_start); if(len > (int) spiffsSize) { DEBUG_HTTP_UPDATE("[httpUpdate] spiffsSize to low (%d) needed: %d\n", spiffsSize, len); + startUpdate = false; } } else { if(len > (int) ESP.getFreeSketchSpace()) { DEBUG_HTTP_UPDATE("[httpUpdate] FreeSketchSpace to low (%d) needed: %d\n", ESP.getFreeSketchSpace(), len); + startUpdate = false; } } From a7609bce35ee36cd02b5026df4fff1a7dca5079b Mon Sep 17 00:00:00 2001 From: Christopher Pascoe Date: Wed, 9 Dec 2015 22:17:50 -0800 Subject: [PATCH 49/57] Remove double include of cbuf.h. --- libraries/ESP8266WiFi/src/WiFiClientSecure.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp b/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp index 997fe5ccb..f141a0909 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp @@ -29,7 +29,6 @@ extern "C" } #include #include "debug.h" -#include "cbuf.h" #include "ESP8266WiFi.h" #include "WiFiClientSecure.h" #include "WiFiClient.h" From 55afeba174ae00b4ca1ea0bcc104642bea92e683 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Thu, 10 Dec 2015 12:00:28 +0100 Subject: [PATCH 50/57] see #1167 add close and stop as alias --- libraries/ESP8266WebServer/src/ESP8266WebServer.cpp | 9 +++++++++ libraries/ESP8266WebServer/src/ESP8266WebServer.h | 3 +++ libraries/ESP8266WiFi/src/WiFiServer.cpp | 10 ++++++++++ libraries/ESP8266WiFi/src/WiFiServer.h | 2 ++ 4 files changed, 24 insertions(+) diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp index cecc8eabc..a2c8a9866 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp @@ -71,6 +71,7 @@ ESP8266WebServer::~ESP8266WebServer() { delete handler; handler = next; } + close(); } void ESP8266WebServer::begin() { @@ -173,6 +174,14 @@ void ESP8266WebServer::handleClient() { _handleRequest(); } +void ESP8266WebServer::close() { + _server.close(); +} + +void ESP8266WebServer::stop() { + close(); +} + void ESP8266WebServer::sendHeader(const String& name, const String& value, bool first) { String headerLine = name; headerLine += ": "; diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.h b/libraries/ESP8266WebServer/src/ESP8266WebServer.h index 40172e92a..e9ea8f1a1 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.h @@ -66,6 +66,9 @@ public: void begin(); void handleClient(); + void close(); + void stop(); + bool authenticate(const char * username, const char * password); void requestAuthentication(); diff --git a/libraries/ESP8266WiFi/src/WiFiServer.cpp b/libraries/ESP8266WiFi/src/WiFiServer.cpp index 5de2d4ac7..462e7d7de 100644 --- a/libraries/ESP8266WiFi/src/WiFiServer.cpp +++ b/libraries/ESP8266WiFi/src/WiFiServer.cpp @@ -121,6 +121,16 @@ uint8_t WiFiServer::status() { return _pcb->state; } +void WiFiServer::close() { + if (!_pcb) { + return; + } + tcp_close(_pcb); +} + +void WiFiServer::stop() { + close(); +} size_t WiFiServer::write(uint8_t b) { return write(&b, 1); diff --git a/libraries/ESP8266WiFi/src/WiFiServer.h b/libraries/ESP8266WiFi/src/WiFiServer.h index 263bcbcdf..424a2331d 100644 --- a/libraries/ESP8266WiFi/src/WiFiServer.h +++ b/libraries/ESP8266WiFi/src/WiFiServer.h @@ -54,6 +54,8 @@ public: virtual size_t write(uint8_t); virtual size_t write(const uint8_t *buf, size_t size); uint8_t status(); + void close(); + void stop(); using Print::write; From fdadadc7875386b749ee23728bc6abc31accc259 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Thu, 10 Dec 2015 12:03:53 +0100 Subject: [PATCH 51/57] add default values for updateSpiffs --- libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h index f9a4d8030..d3fe4ca19 100644 --- a/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h +++ b/libraries/ESP8266httpUpdate/src/ESP8266httpUpdate.h @@ -53,7 +53,7 @@ class ESP8266HTTPUpdate { t_httpUpdate_return update(const char * host, uint16_t port, const char * url = "/", const char * current_version = "", bool https = false, const char * httpsFingerprint = ""); t_httpUpdate_return update(String host, uint16_t port, String url = "/", String current_version = "", bool https = false, String httpsFingerprint = ""); - t_httpUpdate_return updateSpiffs(const char * url, const char * current_version, const char * httpsFingerprint); + t_httpUpdate_return updateSpiffs(const char * url, const char * current_version = "", const char * httpsFingerprint = ""); protected: t_httpUpdate_return handleUpdate(HTTPClient * http, const char * current_version, bool reboot = true, bool spiffs = false); From 0389657614e954ef19ab585cd198c0e59a107dfc Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Thu, 10 Dec 2015 12:35:24 +0100 Subject: [PATCH 52/57] give the IP stack more time to handle the data may help with #1157 --- cores/esp8266/Updater.cpp | 50 +++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/cores/esp8266/Updater.cpp b/cores/esp8266/Updater.cpp index 28830fba5..f4b0fd862 100644 --- a/cores/esp8266/Updater.cpp +++ b/cores/esp8266/Updater.cpp @@ -168,9 +168,14 @@ bool UpdaterClass::end(bool evenIfRemaining){ } bool UpdaterClass::_writeBuffer(){ + + yield(); + bool result = ESP.flashEraseSector(_currentAddress/FLASH_SECTOR_SIZE); + yield(); + if (result) { + result = ESP.flashWrite(_currentAddress, (uint32_t*) _buffer, _bufferLen); + } yield(); - bool result = ESP.flashEraseSector(_currentAddress/FLASH_SECTOR_SIZE) && - ESP.flashWrite(_currentAddress, (uint32_t*) _buffer, _bufferLen); if (!result) { _error = UPDATE_ERROR_WRITE; @@ -217,29 +222,32 @@ size_t UpdaterClass::write(uint8_t *data, size_t len) { } size_t UpdaterClass::writeStream(Stream &data) { - size_t written = 0; - size_t toRead = 0; - if(hasError() || !isRunning()) - return 0; + size_t written = 0; + size_t toRead = 0; + if(hasError() || !isRunning()) + return 0; - while(remaining()) { - toRead = FLASH_SECTOR_SIZE - _bufferLen; - toRead = data.readBytes(_buffer + _bufferLen, toRead); - if(toRead == 0){ //Timeout - _error = UPDATE_ERROR_STREAM; - _currentAddress = (_startAddress + _size); + while(remaining()) { + toRead = data.readBytes(_buffer + _bufferLen, (FLASH_SECTOR_SIZE - _bufferLen)); + if(toRead == 0) { //Timeout + delay(100); + toRead = data.readBytes(_buffer + _bufferLen, (FLASH_SECTOR_SIZE - _bufferLen)); + if(toRead == 0) { //Timeout + _error = UPDATE_ERROR_STREAM; + _currentAddress = (_startAddress + _size); #ifdef DEBUG_UPDATER - printError(DEBUG_UPDATER); + printError(DEBUG_UPDATER); #endif - return written; + } + return written; + } + _bufferLen += toRead; + if((_bufferLen == remaining() || _bufferLen == FLASH_SECTOR_SIZE) && !_writeBuffer()) + return written; + written += toRead; + yield(); } - _bufferLen += toRead; - if((_bufferLen == remaining() || _bufferLen == FLASH_SECTOR_SIZE) && !_writeBuffer()) - return written; - written += toRead; - yield(); - } - return written; + return written; } void UpdaterClass::printError(Stream &out){ From 38427333c5e22fc1360ccbabf3fdae8500b7ce56 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Thu, 10 Dec 2015 17:05:00 +0100 Subject: [PATCH 53/57] update ota docs --- doc/ota_updates/ota_updates.md | 13 +++++++++++-- doc/ota_updates/update_memory_copy.png | Bin 0 -> 4920 bytes 2 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 doc/ota_updates/update_memory_copy.png diff --git a/doc/ota_updates/ota_updates.md b/doc/ota_updates/ota_updates.md index 42bcb06ac..28aed2c9f 100644 --- a/doc/ota_updates/ota_updates.md +++ b/doc/ota_updates/ota_updates.md @@ -405,6 +405,15 @@ The Stream Interface is the base for all other update modes like OTA, http Serve ## Updater class -TODO describe Updater class +Updater is in the Core and deals with writing the firmware to the flash, +checking its integrity and telling the bootloader to load the new firmware on the next boot. + +### Update process - memory view + + - The new sketch will be stored in the space between the old sketch and the spiff. + - on the next reboot the "eboot" bootloader check for commands. + - the new sketch is now copied "over" the old one. + - the new sketch is started. + +![Memory Copy](update_memory_copy.png) -Updater is in the Core and deals with writing the firmware to the flash, checking its integrity and telling the bootloader to load the new firmware on the next boot. diff --git a/doc/ota_updates/update_memory_copy.png b/doc/ota_updates/update_memory_copy.png new file mode 100644 index 0000000000000000000000000000000000000000..724637485d94cc200e56b53b02de51640de00ae3 GIT binary patch literal 4920 zcmeI0dsI``p2rVWftFWa7epT6E+14cf(Rmygp}3_$Uv-mMG+Dyq9CvE5CVh*Obeab z5`-31B=HeJr4mG*2_!&@(dP0>ga{!72pB>P;gN)pkT56r&YCsrc4pT6aXbIq*=wD( z&)H|M-~O$=&+qs7eb2uhj|jGUZ^wH809b{F96131?{ERYB--2*9GUYyO9nfW%oD+% z0SyC=Qt)BxrJ(R20C-BY*ofT*KEI0&IhzRp)-2;?!cKd50RTSi4?Ple3WJnS#HP-? zur2&@*U#ofuSY_j)zppg1uUJXZYA?4PWu7=jbiJk)tMATXmaDtPa=fA(lHazPAruJ%;CukSxlnIwv*&6oz|-YyrBj##IyxPh=*uP1-Nx6A;1!*g)?{!5XSg znVl2pJYHbX4Ef}W7{U_v_R_92n_$)<0B|^D`JDABR(pA+&_NhJz*;$Q9HF)$Wci=Y z{Dep>jV&_;rV!{3Rdw*x@q*+~4j=R_>Y{wftxean*D zzr1pW;0*wfX=TeGD_!eFOfYv=+u&&*OkVc^om_gCi^i^-5h|Ef4Q6x7ba+Tr&w5tp z#{J%oApe`ragGh_6ws`n`24xYiccap3mZ2Dl32`Q(k*X{2tr9C8a?_wTH#N=$pM<3V%WEQtP%x@FQZRFCd)cYyxJ>8f53gm*A%#8@y zWz!mL0mOX|-v(e0jEAdT7Vek+U$p+IiF|?L%CRJ9bnnhkAt}4Ih z0nhd6yjH1j{sI407sQ5(z>1l0@Kyc3RdZFE{gU4Q z)zy0O{;t|zoDzY__*DHqI>*3Y4B_8X?ZEV+J%t9jqT`9jD-PmmJSyvh=K^h-c_w^4 z5E?Rw^?EqM{%(@F(dO1!J9|+>(nI$%aX`Ck^s`##?kA%^@y(=y77NS?eLYFr>r~9f z<@22DudNIR`P(!1o{A}b2K{zY_vcf%q-1hSY{vqXm%bsoB#&vHq%4^z+4U50p7z;Y}#1u3N7CSi?WrMfj8c$QGQQ$TWah$&Qjx_*?-V6uP z1c&SkU3DdY)ExA#(n~dmw`AbW^0dpUb#@ASPhKhb-4#NVOD-|R)5;q>eqdLB&V!O3 zKdZ4s5%-S3rjPZM5R|u)S3d2iia~>4?Uz(bZX%{ZgwWj!qCrTqMN4i4e9I#*Fqt>* z5ETT|aLMCLOmJQX6adaVSWdgc5xJli%@L;3gAlPQ;# zn#6PaX<{n?fX^%p?xhuJwp%f)HXVXd`b)MpFgylX;e5_&faQWD2{!NlB9kb8>JhqF z0o}IW6O@`dCvXSfF){|)0}lQpTX+3H-O2pdit#t-R8DQ$a>Hu3ZTsTXB}@L1wN$zQ zGR~7u92Kk(iUu>Z<8AaenlKT7j7fmN>b5x@Z3w^+<1%56WSj7{)ByYDLtG@VC!R?Yc**4D(CkpQy41Io7P_Dg- zSosF)H_%vEYL}(aEQq6+FOXypd%N*P$BI5^$J#A-NTjYR5V3}YW2=H2$aKDFR_k{K zzEx2#!>P3y!X8d#!+otR0Oc?eSBFxlw9!7oSe6q&dZI)v((-q|ZXwY-A zV}V%R8m{;bB*vm16NH~xJ>}EWcBV4|qKQISWYAJqRDyzjiDXtHa;Col7ZB1*8yE~% znaqoj^4_#@Q#HT0(wbFg;P(F^A z#eQVF;5Xa?I*s}W8Nd^boTuZKHyv}JU+a@Sq zuKsLf&X;5Hm0nwW4gFV=-GhN73;NF_D^aWrsh%yhkY>N=psfZ(NAi+#r;K}#3a&VW z$?G@FxWID$hBx>p?*M=WSo{D>Ta5t<;3)>k4r3C|Yjzv|BZ#>~#?Sge{AML?7gEWr zq5Poc!#9tOpHIwokDo5w*|ih-vD-j->zB=+hDG83fAIfkLsX{V$%Jy^hpmnM>VKg- z{*g)ccd|8+9_S>v*p`%|`#j&jM$lvr0PPaGnRHe9%2_R3&I!-=ehA8sx&uZLvOK{4 zoUSOI(ev*@N;ymZ*3UlIsnKss#`DSoy~T02SiVZ6b7mqIcd%_!-5Ha69@2_}m;nIp zmjfX=3Z&`ueCd*>&0kn$FzX(vpIBTHi+K%q`V}I?=NqJPTptjdo>f6Kt=A8n);AdY zGlM02x=^N)gXWQgpnzcO=bq}Qyt#Fjp*bZTZ}h19@r1*z`<13rZ*#t)t{@Z!^^hMn z5;kwmRGK&Rq$?v>dslBP97o+9DXw@{v=8cgoomiRj<}AX&N_e`Cl3s7hO0GeL*lrN zAHdlA)B9H3P?#Gr#->+Cjk8bHagPhT`rX-GS+E~BxdtfO0jxTHk9Oy`I!csshDXa0 z2n|D|2#L>lCB$;01L=fDpmf=MM>}#-nd$lZ(tZ^h)T=^4E$lQaquENs0?VQ){_Ne{ z48GsE>BdFzr@6`1N*Q^A0duUs_7qy1-{x)jIsn8S+=PtKr{6C+1kcGBkQNFcX;@e$ zbuL@iAjH>j1;TYq!rF*B>us=sZZZ|nPbEn8>#Dt?>+VSkm8Vud+`5>8VKh5oxV|9q zP8AgG;SpEA@!haG?R-MkLrYv!xj@I@H-tEQG(8USSCP~KiX@2XI_G#z-~bV2P?#1f znwqUgWheipl_H4~*GWd)<)QaiH@Gtly>#b`y6I-oX;JzjaU_N!TrKIj;{V!OD@KwJ zcXX1dQ=Jyn-33^$5J~KYp&RM*jp$ooD!{FQpwfDum61T0(JN(Z6ME!%YjvxCh znkg!? Date: Thu, 10 Dec 2015 17:24:39 +0100 Subject: [PATCH 54/57] add more debug to Updater.cpp --- cores/esp8266/Updater.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/cores/esp8266/Updater.cpp b/cores/esp8266/Updater.cpp index f4b0fd862..7ad21300a 100644 --- a/cores/esp8266/Updater.cpp +++ b/cores/esp8266/Updater.cpp @@ -38,14 +38,14 @@ void UpdaterClass::_reset() { bool UpdaterClass::begin(size_t size, int command) { if(_size > 0){ #ifdef DEBUG_UPDATER - DEBUG_UPDATER.println("already running"); + DEBUG_UPDATER.println("[begin] already running"); #endif return false; } #ifdef DEBUG_UPDATER if (command == U_SPIFFS) { - DEBUG_UPDATER.println("Update SPIFFS."); + DEBUG_UPDATER.println("[begin] Update SPIFFS."); } #endif @@ -73,6 +73,12 @@ bool UpdaterClass::begin(size_t size, int command) { //address where we will start writing the update updateStartAddress = updateEndAddress - roundedSize; +#ifdef DEBUG_UPDATER + DEBUG_UPDATER.printf("[begin] roundedSize: 0x%08X (%d)\n", roundedSize, roundedSize); + DEBUG_UPDATER.printf("[begin] updateEndAddress: 0x%08X (%d)\n", updateEndAddress, updateEndAddress); + DEBUG_UPDATER.printf("[begin] currentSketchSize: 0x%08X (%d)\n", currentSketchSize, currentSketchSize); +#endif + //make sure that the size of both sketches is less than the total space (updateEndAddress) if(updateStartAddress < currentSketchSize) { _error = UPDATE_ERROR_SPACE; @@ -88,7 +94,7 @@ bool UpdaterClass::begin(size_t size, int command) { else { // unknown command #ifdef DEBUG_UPDATER - DEBUG_UPDATER.println("Unknown update command."); + DEBUG_UPDATER.println("[begin] Unknown update command."); #endif return false; } @@ -100,6 +106,12 @@ bool UpdaterClass::begin(size_t size, int command) { _buffer = new uint8_t[FLASH_SECTOR_SIZE]; _command = command; +#ifdef DEBUG_UPDATER + DEBUG_UPDATER.printf("[begin] _startAddress: 0x%08X (%d)\n", _startAddress, _startAddress); + DEBUG_UPDATER.printf("[begin] _currentAddress: 0x%08X (%d)\n", _currentAddress, _currentAddress); + DEBUG_UPDATER.printf("[begin] _size: 0x%08X (%d)\n", _size, _size); +#endif + _md5.begin(); return true; } From 7ea4eb452da62b8564855a62e824d97187604946 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Thu, 10 Dec 2015 17:37:09 +0100 Subject: [PATCH 55/57] fix String bug length where returning something that is not 0 while buffer where NULL!? --- cores/esp8266/WString.cpp | 4 ++-- cores/esp8266/WString.h | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/cores/esp8266/WString.cpp b/cores/esp8266/WString.cpp index f92344b84..4ba4b1f9f 100644 --- a/cores/esp8266/WString.cpp +++ b/cores/esp8266/WString.cpp @@ -121,6 +121,7 @@ ICACHE_FLASH_ATTR String::~String() { if(buffer) { free(buffer); } + init(); } // /*********************************************/ @@ -136,8 +137,7 @@ inline void String::init(void) { void ICACHE_FLASH_ATTR String::invalidate(void) { if(buffer) free(buffer); - buffer = NULL; - capacity = len = 0; + init(); } unsigned char ICACHE_FLASH_ATTR String::reserve(unsigned int size) { diff --git a/cores/esp8266/WString.h b/cores/esp8266/WString.h index 4c502bfe5..3f216cee4 100644 --- a/cores/esp8266/WString.h +++ b/cores/esp8266/WString.h @@ -76,7 +76,11 @@ class String { // invalid string (i.e., "if (s)" will be true afterwards) unsigned char reserve(unsigned int size); inline unsigned int length(void) const { - return len; + if(buffer) { + return len; + } else { + return 0; + } } // creates a copy of the assigned value. if the value is null or From 6aa4f9e48100bf4b185044aacf9d369af4616862 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Thu, 10 Dec 2015 18:06:56 +0100 Subject: [PATCH 56/57] doc better quality of update_memory_copy.png --- doc/ota_updates/update_memory_copy.png | Bin 4920 -> 5249 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/ota_updates/update_memory_copy.png b/doc/ota_updates/update_memory_copy.png index 724637485d94cc200e56b53b02de51640de00ae3..c708f5f4cdf7d787da29dab5d0cdbf19630159d7 100644 GIT binary patch literal 5249 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 literal 4920 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 Date: Thu, 10 Dec 2015 23:25:54 +0300 Subject: [PATCH 57/57] SPIFFS: check if path length is valid (#1089) --- cores/esp8266/spiffs_api.cpp | 39 +++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/cores/esp8266/spiffs_api.cpp b/cores/esp8266/spiffs_api.cpp index f1689cbfe..f189b4d4e 100644 --- a/cores/esp8266/spiffs_api.cpp +++ b/cores/esp8266/spiffs_api.cpp @@ -41,11 +41,13 @@ extern int32_t spiffs_hal_write(uint32_t addr, uint32_t size, uint8_t *src); extern int32_t spiffs_hal_erase(uint32_t addr, uint32_t size); extern int32_t spiffs_hal_read(uint32_t addr, uint32_t size, uint8_t *dst); -int getSpiffsMode(OpenMode openMode, AccessMode accessMode); +static int getSpiffsMode(OpenMode openMode, AccessMode accessMode); +static bool isSpiffsFilenameValid(const char* name); class SPIFFSFileImpl; class SPIFFSDirImpl; + class SPIFFSImpl : public FSImpl { public: SPIFFSImpl(uint32_t start, uint32_t size, uint32_t pageSize, uint32_t blockSize, uint32_t maxOpenFds) @@ -63,6 +65,14 @@ public: DirImplPtr openDir(const char* path) override; bool rename(const char* pathFrom, const char* pathTo) override { + if (!isSpiffsFilenameValid(pathFrom)) { + DEBUGV("SPIFFSImpl::rename: invalid pathFrom=`%s`\r\n", path); + return false; + } + if (!isSpiffsFilenameValid(pathTo)) { + DEBUGV("SPIFFSImpl::rename: invalid pathTo=`%s` \r\n", path); + return false; + } auto rc = SPIFFS_rename(&_fs, pathFrom, pathTo); if (rc != SPIFFS_OK) { DEBUGV("SPIFFS_rename: rc=%d, from=`%s`, to=`%s`\r\n", rc, @@ -86,6 +96,10 @@ public: } bool remove(const char* path) override { + if (!isSpiffsFilenameValid(path)) { + DEBUGV("SPIFFSImpl::remove: invalid path=`%s`\r\n", path); + return false; + } auto rc = SPIFFS_remove(&_fs, path); if (rc != SPIFFS_OK) { DEBUGV("SPIFFS_remove: rc=%d path=`%s`\r\n", rc, path); @@ -229,7 +243,7 @@ protected: std::unique_ptr _cacheBuf; }; -#define CHECKFD() while (_fd == 0) { DEBUGV("SPIFFSFileImpl(%d) _fd == 0\r\n", __LINE__); abort(); } +#define CHECKFD() while (_fd == 0) { panic(); } class SPIFFSFileImpl : public FileImpl { public: @@ -408,6 +422,10 @@ protected: FileImplPtr SPIFFSImpl::open(const char* path, OpenMode openMode, AccessMode accessMode) { + if (!isSpiffsFilenameValid(path)) { + DEBUGV("SPIFFSImpl::open: invalid path=`%s` \r\n", path); + return FileImplPtr(); + } int mode = getSpiffsMode(openMode, accessMode); int fd = SPIFFS_open(&_fs, path, mode, 0); if (fd < 0 && _fs.err_code == SPIFFS_ERR_DELETED && (openMode & OM_CREATE)) { @@ -430,12 +448,20 @@ FileImplPtr SPIFFSImpl::open(const char* path, OpenMode openMode, AccessMode acc } bool SPIFFSImpl::exists(const char* path) { + if (!isSpiffsFilenameValid(path)) { + DEBUGV("SPIFFSImpl::exists: invalid path=`%s` \r\n", path); + return false; + } spiffs_stat stat; int rc = SPIFFS_stat(&_fs, path, &stat); return rc == SPIFFS_OK; } DirImplPtr SPIFFSImpl::openDir(const char* path) { + if (!isSpiffsFilenameValid(path)) { + DEBUGV("SPIFFSImpl::openDir: invalid path=`%s` \r\n", path); + return DirImplPtr(); + } spiffs_DIR dir; spiffs_DIR* result = SPIFFS_opendir(&_fs, path, &dir); if (!result) { @@ -445,7 +471,7 @@ DirImplPtr SPIFFSImpl::openDir(const char* path) { return std::make_shared(path, this, dir); } -int getSpiffsMode(OpenMode openMode, AccessMode accessMode) { +static int getSpiffsMode(OpenMode openMode, AccessMode accessMode) { int mode = 0; if (openMode & OM_CREATE) { mode |= SPIFFS_CREAT; @@ -465,6 +491,13 @@ int getSpiffsMode(OpenMode openMode, AccessMode accessMode) { return mode; } +static bool isSpiffsFilenameValid(const char* name) { + if (name == nullptr) + return false; + auto len = strlen(name); + return len > 0 && len <= SPIFFS_OBJ_NAME_LEN; +} + // these symbols should be defined in the linker script for each flash layout extern "C" uint32_t _SPIFFS_start; extern "C" uint32_t _SPIFFS_end;