Skip to content

Commit b76fffd

Browse files
committed
Initial abstraction/addition of code to allow the EVSE to download the firmware from a server rather than a file upload.
Needed for #229, needs additional work in ArduinoMongoose to support downloading large files
1 parent 2b1fcf1 commit b76fffd

File tree

6 files changed

+356
-145
lines changed

6 files changed

+356
-145
lines changed

src/http_update.cpp

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#include "http_update.h"
2+
#include "lcd.h"
3+
#include "debug.h"
4+
5+
#include <MongooseHttpClient.h>
6+
#include <Update.h>
7+
8+
MongooseHttpClient client;
9+
static int lastPercent = -1;
10+
static size_t update_total_size = 0;
11+
static size_t update_position = 0;
12+
13+
bool http_update_from_url(String url,
14+
std::function<void(size_t complete, size_t total)> progress,
15+
std::function<void(int)> success,
16+
std::function<void(int)> error)
17+
{
18+
MongooseHttpClientRequest *request =
19+
client.beginRequest(url.c_str())
20+
->setMethod(HTTP_GET)
21+
// ->onBody([progress, error](const uint8_t *data, size_t len) {
22+
// if(http_update_write(data, len)) {
23+
// progress(len, update_total_size);
24+
// } else {
25+
// error(HTTP_UPDATE_ERROR_WRITE_FAILED);
26+
// }
27+
// }
28+
->onResponse([url,error](MongooseHttpClientResponse *response)
29+
{
30+
if(response->respCode() == 200)
31+
{
32+
size_t total = response->contentLength();
33+
if(!http_update_start(url, total)) {
34+
error(HTTP_UPDATE_ERROR_FAILED_TO_START_UPDATE);
35+
}
36+
} else {
37+
error(response->respCode());
38+
}
39+
})
40+
->onClose([success, error](MongooseHttpClientResponse *response) {
41+
if(http_update_end()) {
42+
success(HTTP_UPDATE_OK);
43+
} else {
44+
error(HTTP_UPDATE_ERROR_FAILED_TO_END_UPDATE);
45+
}
46+
});
47+
client.send(request);
48+
49+
return true;
50+
}
51+
52+
bool http_update_start(String source, size_t total)
53+
{
54+
update_total_size = total;
55+
if(Update.begin())
56+
{
57+
DEBUG_PORT.printf("Update Start: %s\n", source.c_str());
58+
59+
lcd.display(F("Updating WiFi"), 0, 0, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW);
60+
lcd.display(F(""), 0, 1, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW);
61+
62+
return true;
63+
}
64+
65+
return false;
66+
}
67+
68+
bool http_update_write(uint8_t *data, size_t len)
69+
{
70+
DBUGF("Update Writing %u", update_position);
71+
if(Update.write(data, len) == len)
72+
{
73+
update_position += len;
74+
if(update_total_size > 0)
75+
{
76+
int percent = update_position / (update_total_size / 100);
77+
DBUGVAR(percent);
78+
DBUGVAR(lastPercent);
79+
if(percent != lastPercent)
80+
{
81+
String text = String(percent) + F("%");
82+
lcd.display(text, 0, 1, 10 * 1000, LCD_DISPLAY_NOW);
83+
DEBUG_PORT.printf("Update: %d%%\n", percent);
84+
lastPercent = percent;
85+
}
86+
}
87+
88+
return true;
89+
}
90+
91+
return false;
92+
}
93+
94+
bool http_update_end()
95+
{
96+
DBUGLN("Upload finished");
97+
if(Update.end(true))
98+
{
99+
DBUGF("Update Success: %uB", update_position);
100+
lcd.display(F("Complete"), 0, 1, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW);
101+
} else {
102+
DBUGF("Update failed: %d", Update.getError());
103+
lcd.display(F("Error"), 0, 1, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW);
104+
}
105+
106+
return false;
107+
}

src/http_update.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#ifndef _HTTP_UPDATE_H
2+
#define _HTTP_UPDATE_H
3+
4+
// -------------------------------------------------------------------
5+
// Support for updating the fitmware os the ESP8266
6+
// -------------------------------------------------------------------
7+
8+
#include <Arduino.h>
9+
#include <functional>
10+
11+
#define HTTP_UPDATE_ERROR_FAILED_TO_START_UPDATE -1
12+
#define HTTP_UPDATE_ERROR_WRITE_FAILED -2
13+
#define HTTP_UPDATE_ERROR_FAILED_TO_END_UPDATE -3
14+
15+
#define HTTP_UPDATE_OK 0
16+
17+
bool http_update_from_url(String url,
18+
std::function<void(size_t complete, size_t total)> progress,
19+
std::function<void(int)> success,
20+
std::function<void(int)> error);
21+
22+
bool http_update_start(String source, size_t total);
23+
bool http_update_write(uint8_t *data, size_t len);
24+
bool http_update_end();
25+
26+
#endif // _HTTP_UPDATE_H

src/ota.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include "lcd.h"
99
#include "app_config.h"
1010

11-
static int lastPercent = -1;
11+
static int last_percent = -1;
1212

1313
void ota_setup()
1414
{
@@ -26,12 +26,12 @@ void ota_setup()
2626

2727
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
2828
int percent = progress / (total / 100);
29-
if (percent != lastPercent)
29+
if (percent != last_percent)
3030
{
3131
DBUGF("ArduinoOTA progress %d%%", percent);
3232
String text = String(percent) + F("%");
3333
lcd.display(text, 0, 1, 10 * 1000, LCD_DISPLAY_NOW);
34-
lastPercent = percent;
34+
last_percent = percent;
3535
feedLoopWDT();
3636
}
3737
});

src/web_server.cpp

Lines changed: 7 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ bool streamDebug = false;
4545

4646
// Event timeouts
4747
static unsigned long wifiRestartTime = 0;
48-
static unsigned long systemRebootTime = 0;
4948
static unsigned long apOffTime = 0;
5049

5150
// Content Types
@@ -64,6 +63,10 @@ void handleConfig(MongooseHttpServerRequest *request);
6463
void handleEvseClaims(MongooseHttpServerRequest *request);
6564
void handleEventLogs(MongooseHttpServerRequest *request);
6665

66+
void handleUpdateRequest(MongooseHttpServerRequest *request);
67+
size_t handleUpdateUpload(MongooseHttpServerRequest *request, int ev, MongooseString filename, uint64_t index, uint8_t *data, size_t len);
68+
void handleUpdateClose(MongooseHttpServerRequest *request);
69+
6770
void dumpRequest(MongooseHttpServerRequest *request)
6871
{
6972
#ifdef ENABLE_DEBUG_WEB_REQUEST
@@ -849,7 +852,7 @@ handleRst(MongooseHttpServerRequest *request) {
849852
response->print("1");
850853
request->send(response);
851854

852-
systemRebootTime = millis() + 1000;
855+
restart_system();
853856
}
854857

855858

@@ -868,7 +871,7 @@ handleRestart(MongooseHttpServerRequest *request) {
868871
response->print("1");
869872
request->send(response);
870873

871-
systemRebootTime = millis() + 1000;
874+
restart_system();
872875
}
873876

874877

@@ -886,131 +889,6 @@ void handleDescribe(MongooseHttpServerRequest *request) {
886889
request->send(response);
887890
}
888891

889-
// -------------------------------------------------------------------
890-
// Update firmware
891-
// url: /update
892-
// -------------------------------------------------------------------
893-
void
894-
handleUpdateGet(MongooseHttpServerRequest *request) {
895-
MongooseHttpServerResponseStream *response;
896-
if(false == requestPreProcess(request, response, CONTENT_TYPE_HTML)) {
897-
return;
898-
}
899-
900-
response->setCode(200);
901-
response->print(
902-
F("<html><form method='POST' action='/update' enctype='multipart/form-data'>"
903-
"<input type='file' name='firmware'> "
904-
"<input type='submit' value='Update'>"
905-
"</form></html>"));
906-
request->send(response);
907-
}
908-
909-
static MongooseHttpServerResponseStream *upgradeResponse = NULL;
910-
911-
void
912-
handleUpdatePost(MongooseHttpServerRequest *request) {
913-
if(NULL != upgradeResponse) {
914-
request->send(500, CONTENT_TYPE_TEXT, "Error: Upgrade in progress");
915-
return;
916-
}
917-
918-
if(false == requestPreProcess(request, upgradeResponse, CONTENT_TYPE_TEXT)) {
919-
return;
920-
}
921-
922-
// TODO: Add support for returning 100: Continue
923-
}
924-
925-
static int lastPercent = -1;
926-
927-
static void handleUpdateError(MongooseHttpServerRequest *request)
928-
{
929-
upgradeResponse->setCode(500);
930-
upgradeResponse->printf("Error: %d", Update.getError());
931-
request->send(upgradeResponse);
932-
upgradeResponse = NULL;
933-
934-
// Anoyingly this uses Stream rather than Print...
935-
#ifdef ENABLE_DEBUG
936-
Update.printError(DEBUG_PORT);
937-
#endif
938-
}
939-
940-
size_t
941-
handleUpdateUpload(MongooseHttpServerRequest *request, int ev, MongooseString filename, uint64_t index, uint8_t *data, size_t len)
942-
{
943-
if(MG_EV_HTTP_PART_BEGIN == ev)
944-
{
945-
// dumpRequest(request);
946-
947-
DEBUG_PORT.printf("Update Start: %s\n", filename.c_str());
948-
949-
lcd.display(F("Updating WiFi"), 0, 0, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW);
950-
lcd.display(F(""), 0, 1, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW);
951-
952-
if(!Update.begin()) {
953-
handleUpdateError(request);
954-
}
955-
}
956-
957-
if(!Update.hasError())
958-
{
959-
DBUGF("Update Writing %llu", index);
960-
961-
size_t contentLength = request->contentLength();
962-
DBUGVAR(contentLength);
963-
if(contentLength > 0)
964-
{
965-
int percent = index / (contentLength / 100);
966-
DBUGVAR(percent);
967-
DBUGVAR(lastPercent);
968-
if(percent != lastPercent) {
969-
String text = String(percent) + F("%");
970-
lcd.display(text, 0, 1, 10 * 1000, LCD_DISPLAY_NOW);
971-
DEBUG_PORT.printf("Update: %d%%\n", percent);
972-
lastPercent = percent;
973-
}
974-
}
975-
if(Update.write(data, len) != len) {
976-
handleUpdateError(request);
977-
}
978-
}
979-
980-
if(MG_EV_HTTP_PART_END == ev)
981-
{
982-
DBUGLN("Upload finished");
983-
if(Update.end(true)) {
984-
DBUGF("Update Success: %lluB", index+len);
985-
lcd.display(F("Complete"), 0, 1, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW);
986-
upgradeResponse->setCode(200);
987-
upgradeResponse->print("OK");
988-
request->send(upgradeResponse);
989-
upgradeResponse = NULL;
990-
} else {
991-
DBUGF("Update failed: %d", Update.getError());
992-
lcd.display(F("Error"), 0, 1, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW);
993-
handleUpdateError(request);
994-
}
995-
}
996-
997-
return len;
998-
}
999-
1000-
static void handleUpdateClose(MongooseHttpServerRequest *request)
1001-
{
1002-
DBUGLN("Update close");
1003-
1004-
if(upgradeResponse) {
1005-
delete upgradeResponse;
1006-
upgradeResponse = NULL;
1007-
}
1008-
1009-
if(Update.isFinished() && !Update.hasError()) {
1010-
systemRebootTime = millis() + 1000;
1011-
}
1012-
}
1013-
1014892
String delayTimer = "0 0 0 0";
1015893

1016894
void
@@ -1209,13 +1087,7 @@ web_server_setup() {
12091087

12101088
// Simple Firmware Update Form
12111089
server.on("/update$")->
1212-
onRequest([](MongooseHttpServerRequest *request) {
1213-
if(HTTP_GET == request->method()) {
1214-
handleUpdateGet(request);
1215-
} else if(HTTP_POST == request->method()) {
1216-
handleUpdatePost(request);
1217-
}
1218-
})->
1090+
onRequest(handleUpdateRequest)->
12191091
onUpload(handleUpdateUpload)->
12201092
onClose(handleUpdateClose);
12211093

@@ -1286,13 +1158,6 @@ web_server_loop() {
12861158
net_wifi_turn_off_ap();
12871159
}
12881160

1289-
// Do we need to reboot the system?
1290-
if(systemRebootTime > 0 && millis() > systemRebootTime) {
1291-
systemRebootTime = 0;
1292-
net_wifi_disconnect();
1293-
ESPAL.reset();
1294-
}
1295-
12961161
Profile_End(web_server_loop, 5);
12971162
}
12981163

0 commit comments

Comments
 (0)