Browse Source

* OTA update for ESP32 targets

pull/135/head
Scott Powell 1 year ago
parent
commit
a4bb3782a4
  1. 21
      arch/esp32/AsyncElegantOTA/LICENSE
  2. 2
      arch/esp32/AsyncElegantOTA/keywords.txt
  3. 9
      arch/esp32/AsyncElegantOTA/library.properties
  4. 129
      arch/esp32/AsyncElegantOTA/src/AsyncElegantOTA.cpp
  5. 52
      arch/esp32/AsyncElegantOTA/src/AsyncElegantOTA.h
  6. 38
      arch/esp32/AsyncElegantOTA/src/Hash.h
  7. 1799
      arch/esp32/AsyncElegantOTA/src/elegantWebpage.h
  8. 5
      platformio.ini
  9. 2
      src/MeshCore.h
  10. 4
      src/helpers/CommonCLI.cpp
  11. 32
      src/helpers/ESP32Board.cpp
  12. 2
      src/helpers/ESP32Board.h
  13. 3
      src/helpers/nrf52/RAK4631Board.cpp
  14. 2
      src/helpers/nrf52/RAK4631Board.h
  15. 3
      src/helpers/nrf52/T1000eBoard.cpp
  16. 2
      src/helpers/nrf52/T1000eBoard.h
  17. 3
      src/helpers/nrf52/T114Board.cpp
  18. 2
      src/helpers/nrf52/T114Board.h
  19. 3
      src/helpers/nrf52/TechoBoard.cpp
  20. 2
      src/helpers/nrf52/TechoBoard.h
  21. 3
      src/helpers/nrf52/faketecBoard.cpp
  22. 2
      src/helpers/nrf52/faketecBoard.h

21
arch/esp32/AsyncElegantOTA/LICENSE

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Ayush Sharma
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

2
arch/esp32/AsyncElegantOTA/keywords.txt

@ -0,0 +1,2 @@
AsyncElegantOTA KEYWORD1
begin KEYWORD2

9
arch/esp32/AsyncElegantOTA/library.properties

@ -0,0 +1,9 @@
name=AsyncElegantOTA
version=2.2.8
author=Ayush Sharma
category=Communication
maintainer=Ayush Sharma <[email protected]>
sentence=Perform OTAs for ESP8266 & ESP32 Asynchronously.
paragraph=A User Interface Library which provides interactive elements for your Over the Air Updates on ESP8266/ESP32.
url=https://github.com/ayushsharma82/AsyncElegantOTA
architectures=esp8266,esp32

129
arch/esp32/AsyncElegantOTA/src/AsyncElegantOTA.cpp

@ -0,0 +1,129 @@
#include <AsyncElegantOTA.h>
AsyncElegantOtaClass AsyncElegantOTA;
void AsyncElegantOtaClass::setID(const char* id){
_id = id;
}
void AsyncElegantOtaClass::begin(AsyncWebServer *server, const char* username, const char* password){
_server = server;
if(strlen(username) > 0){
_authRequired = true;
_username = username;
_password = password;
}else{
_authRequired = false;
_username = "";
_password = "";
}
_server->on("/update/identity", HTTP_GET, [&](AsyncWebServerRequest *request){
if(_authRequired){
if(!request->authenticate(_username.c_str(), _password.c_str())){
return request->requestAuthentication();
}
}
#if defined(ESP8266)
request->send(200, "application/json", "{\"id\": \""+_id+"\", \"hardware\": \"ESP8266\"}");
#elif defined(ESP32)
request->send(200, "application/json", "{\"id\": \""+_id+"\", \"hardware\": \"ESP32\"}");
#endif
});
_server->on("/update", HTTP_GET, [&](AsyncWebServerRequest *request){
if(_authRequired){
if(!request->authenticate(_username.c_str(), _password.c_str())){
return request->requestAuthentication();
}
}
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", ELEGANT_HTML, ELEGANT_HTML_SIZE);
response->addHeader("Content-Encoding", "gzip");
request->send(response);
});
_server->on("/update", HTTP_POST, [&](AsyncWebServerRequest *request) {
if(_authRequired){
if(!request->authenticate(_username.c_str(), _password.c_str())){
return request->requestAuthentication();
}
}
// the request handler is triggered after the upload has finished...
// create the response, add header, and send response
AsyncWebServerResponse *response = request->beginResponse((Update.hasError())?500:200, "text/plain", (Update.hasError())?"FAIL":"OK");
response->addHeader("Connection", "close");
response->addHeader("Access-Control-Allow-Origin", "*");
request->send(response);
restart();
}, [&](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
//Upload handler chunks in data
if(_authRequired){
if(!request->authenticate(_username.c_str(), _password.c_str())){
return request->requestAuthentication();
}
}
if (!index) {
if(!request->hasParam("MD5", true)) {
return request->send(400, "text/plain", "MD5 parameter missing");
}
if(!Update.setMD5(request->getParam("MD5", true)->value().c_str())) {
return request->send(400, "text/plain", "MD5 parameter invalid");
}
#if defined(ESP8266)
int cmd = (filename == "filesystem") ? U_FS : U_FLASH;
Update.runAsync(true);
size_t fsSize = ((size_t) &_FS_end - (size_t) &_FS_start);
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
if (!Update.begin((cmd == U_FS)?fsSize:maxSketchSpace, cmd)){ // Start with max available size
#elif defined(ESP32)
int cmd = (filename == "filesystem") ? U_SPIFFS : U_FLASH;
if (!Update.begin(UPDATE_SIZE_UNKNOWN, cmd)) { // Start with max available size
#endif
Update.printError(Serial);
return request->send(400, "text/plain", "OTA could not begin");
}
}
// Write chunked data to the free sketch space
if(len){
if (Update.write(data, len) != len) {
return request->send(400, "text/plain", "OTA could not begin");
}
}
if (final) { // if the final flag is set then this is the last frame of data
if (!Update.end(true)) { //true to set the size to the current progress
Update.printError(Serial);
return request->send(400, "text/plain", "Could not end OTA");
}
}else{
return;
}
});
}
// deprecated, keeping for backward compatibility
void AsyncElegantOtaClass::loop() {
}
void AsyncElegantOtaClass::restart() {
yield();
delay(1000);
yield();
ESP.restart();
}
String AsyncElegantOtaClass::getID(){
String id = "";
#if defined(ESP8266)
id = String(ESP.getChipId());
#elif defined(ESP32)
id = String((uint32_t)ESP.getEfuseMac(), HEX);
#endif
id.toUpperCase();
return id;
}

52
arch/esp32/AsyncElegantOTA/src/AsyncElegantOTA.h

@ -0,0 +1,52 @@
#ifndef AsyncElegantOTA_h
#define AsyncElegantOTA_h
#warning AsyncElegantOTA library is deprecated, Please consider moving to newer ElegantOTA library which now comes with an Async Mode. Learn More: https://docs.elegantota.pro/async-mode/
#include "Arduino.h"
#include "stdlib_noniso.h"
#if defined(ESP8266)
#include "ESP8266WiFi.h"
#include "ESPAsyncTCP.h"
#include "flash_hal.h"
#include "FS.h"
#elif defined(ESP32)
#include "WiFi.h"
#include "AsyncTCP.h"
#include "Update.h"
#include "esp_int_wdt.h"
#include "esp_task_wdt.h"
#endif
#include "Hash.h"
#include "ESPAsyncWebServer.h"
#include "FS.h"
#include "elegantWebpage.h"
class AsyncElegantOtaClass{
public:
void
setID(const char* id),
begin(AsyncWebServer *server, const char* username = "", const char* password = ""),
loop(),
restart();
private:
AsyncWebServer *_server;
String getID();
String _id = getID();
String _username = "";
String _password = "";
bool _authRequired = false;
};
extern AsyncElegantOtaClass AsyncElegantOTA;
#endif

38
arch/esp32/AsyncElegantOTA/src/Hash.h

@ -0,0 +1,38 @@
/**
* @file Hash.h
* @date 20.05.2015
* @author Markus Sattler
*
* Copyright (c) 2015 Markus Sattler. All rights reserved.
* This file is part of the esp8266 core for Arduino environment.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef HASH_H_
#define HASH_H_
//#define DEBUG_SHA1
void sha1(const uint8_t* data, uint32_t size, uint8_t hash[20]);
void sha1(const char* data, uint32_t size, uint8_t hash[20]);
void sha1(const String& data, uint8_t hash[20]);
String sha1(const uint8_t* data, uint32_t size);
String sha1(const char* data, uint32_t size);
String sha1(const String& data);
#endif /* HASH_H_ */

1799
arch/esp32/AsyncElegantOTA/src/elegantWebpage.h

File diff suppressed because it is too large

5
platformio.ini

@ -40,7 +40,10 @@ extra_scripts = merge-bin.py
build_flags = ${arduino_base.build_flags}
; -D ESP32_CPU_FREQ=80 ; change it to your need
build_src_filter = ${arduino_base.build_src_filter}
lib_deps =
${arduino_base.lib_deps}
me-no-dev/ESPAsyncWebServer @ ^3.6.0
file://arch/esp32/AsyncElegantOTA
; ----------------- NRF52 ---------------------
[nrf52_base]

2
src/MeshCore.h

@ -42,7 +42,7 @@ public:
virtual void reboot() = 0;
virtual void powerOff() { /* no op */ }
virtual uint8_t getStartupReason() const = 0;
virtual bool startOTAUpdate() { return false; } // not supported
virtual bool startOTAUpdate(const char* id, char reply[]) { return false; } // not supported
};
/**

4
src/helpers/CommonCLI.cpp

@ -129,9 +129,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
strcpy(reply, "ERR: clock cannot go backwards");
}
} else if (memcmp(command, "start ota", 9) == 0) {
if (_board->startOTAUpdate()) {
strcpy(reply, "OK");
} else {
if (!_board->startOTAUpdate(_prefs->node_name, reply)) {
strcpy(reply, "Error");
}
} else if (memcmp(command, "clock", 5) == 0) {

32
src/helpers/ESP32Board.cpp

@ -0,0 +1,32 @@
#ifdef ESP_PLATFORM
#include "ESP32Board.h"
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <AsyncElegantOTA.h>
bool ESP32Board::startOTAUpdate(const char* id, char reply[]) {
WiFi.softAP("MeshCore-OTA", NULL);
sprintf(reply, "Started: http://%s/update", WiFi.softAPIP().toString().c_str());
MESH_DEBUG_PRINTLN("startOTAUpdate: %s", reply);
static char id_buf[60];
sprintf(id_buf, "%s (%s)", id, getManufacturerName());
static char home_buf[90];
sprintf(home_buf, "<H2>Hi! I am a MeshCore Repeater. ID: %s</H2>", id);
AsyncWebServer* server = new AsyncWebServer(80);
server->on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(200, "text/html", home_buf);
});
AsyncElegantOTA.setID(id_buf);
AsyncElegantOTA.begin(server); // Start ElegantOTA
server->begin();
return true;
}
#endif

2
src/helpers/ESP32Board.h

@ -74,6 +74,8 @@ public:
void reboot() override {
esp_restart();
}
bool startOTAUpdate(const char* id, char reply[]) override;
};
class ESP32RTCClock : public mesh::RTCClock {

3
src/helpers/nrf52/RAK4631Board.cpp

@ -37,7 +37,7 @@ void RAK4631Board::begin() {
delay(10); // give sx1262 some time to power up
}
bool RAK4631Board::startOTAUpdate() {
bool RAK4631Board::startOTAUpdate(const char* id, char reply[]) {
// Config the peripheral connection with maximum bandwidth
// more SRAM required by SoftDevice
// Note: All config***() function must be called before begin()
@ -76,5 +76,6 @@ bool RAK4631Board::startOTAUpdate() {
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
strcpy(reply, "OK - started");
return true;
}

2
src/helpers/nrf52/RAK4631Board.h

@ -50,5 +50,5 @@ public:
NVIC_SystemReset();
}
bool startOTAUpdate() override;
bool startOTAUpdate(const char* id, char reply[]) override;
};

3
src/helpers/nrf52/T1000eBoard.cpp

@ -42,7 +42,7 @@ static void disconnect_callback(uint16_t conn_handle, uint8_t reason) {
}
bool TrackerT1000eBoard::startOTAUpdate() {
bool TrackerT1000eBoard::startOTAUpdate(const char* id, char reply[]) {
// Config the peripheral connection with maximum bandwidth
// more SRAM required by SoftDevice
// Note: All config***() function must be called before begin()
@ -81,6 +81,7 @@ bool TrackerT1000eBoard::startOTAUpdate() {
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
strcpy(reply, "OK - started");
return true;
}
#endif

2
src/helpers/nrf52/T1000eBoard.h

@ -90,5 +90,5 @@ public:
NVIC_SystemReset();
}
// bool startOTAUpdate() override;
// bool startOTAUpdate(const char* id, char reply[]) override;
};

3
src/helpers/nrf52/T114Board.cpp

@ -42,7 +42,7 @@ void T114Board::begin() {
delay(10); // give sx1262 some time to power up
}
bool T114Board::startOTAUpdate() {
bool T114Board::startOTAUpdate(const char* id, char reply[]) {
// Config the peripheral connection with maximum bandwidth
// more SRAM required by SoftDevice
// Note: All config***() function must be called before begin()
@ -81,5 +81,6 @@ bool T114Board::startOTAUpdate() {
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
strcpy(reply, "OK - started");
return true;
}

2
src/helpers/nrf52/T114Board.h

@ -60,5 +60,5 @@ public:
NVIC_SystemReset();
}
bool startOTAUpdate() override;
bool startOTAUpdate(const char* id, char reply[]) override;
};

3
src/helpers/nrf52/TechoBoard.cpp

@ -35,7 +35,7 @@ void TechoBoard::begin() {
delay(10); // give sx1262 some time to power up
}
bool TechoBoard::startOTAUpdate() {
bool TechoBoard::startOTAUpdate(const char* id, char reply[]) {
// Config the peripheral connection with maximum bandwidth
// more SRAM required by SoftDevice
// Note: All config***() function must be called before begin()
@ -74,5 +74,6 @@ bool TechoBoard::startOTAUpdate() {
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
strcpy(reply, "OK - started");
return true;
}

2
src/helpers/nrf52/TechoBoard.h

@ -49,5 +49,5 @@ public:
NVIC_SystemReset();
}
bool startOTAUpdate() override;
bool startOTAUpdate(const char* id, char reply[]) override;
};

3
src/helpers/nrf52/faketecBoard.cpp

@ -39,7 +39,7 @@ static void disconnect_callback(uint16_t conn_handle, uint8_t reason) {
MESH_DEBUG_PRINTLN("BLE client disconnected");
}
bool FaketecBoard::startOTAUpdate() {
bool FaketecBoard::startOTAUpdate(const char* id, char reply[]) {
// Config the peripheral connection with maximum bandwidth
// more SRAM required by SoftDevice
// Note: All config***() function must be called before begin()
@ -78,5 +78,6 @@ bool FaketecBoard::startOTAUpdate() {
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
strcpy(reply, "OK - started");
return true;
}

2
src/helpers/nrf52/faketecBoard.h

@ -61,5 +61,5 @@ public:
NVIC_SystemReset();
}
bool startOTAUpdate() override;
bool startOTAUpdate(const char* id, char reply[]) override;
};

Loading…
Cancel
Save