Skip to content

Commit 68780d3

Browse files
authored
Merge pull request #258 from jeremypoulter/jeremypoulter/issue59
Added support for downloading firmware update
2 parents cc433bc + 3feea52 commit 68780d3

File tree

10 files changed

+431
-151
lines changed

10 files changed

+431
-151
lines changed

platformio.ini

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ version = -D BUILD_TAG=4.1.0
3333
monitor_speed = 115200
3434
lib_deps =
3535
36-
jeremypoulter/[email protected].16
36+
jeremypoulter/[email protected].17
3737
jeremypoulter/Micro [email protected]
3838
jeremypoulter/[email protected]
3939
jeremypoulter/[email protected]
@@ -141,6 +141,7 @@ build_flags =
141141
-D TX1=27
142142
-ggdb
143143
#upload_port = openevse.local
144+
#upload_protocol = espota
144145
upload_speed = 2000000
145146
#upload_protocol = ftdi
146147
monitor_speed = 115200

src/emoncms.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,19 @@ const char *post_path = "/input/post?";
2323

2424
static MongooseHttpClient client;
2525

26+
struct EmonCmsClientState {
27+
bool connected;
28+
};
29+
2630
static void emoncms_result(bool success, String message)
2731
{
2832
StaticJsonDocument<128> event;
29-
33+
34+
if(emoncms_connected && success) {
35+
// Don't send events if we have already reported success
36+
return;
37+
}
38+
3039
emoncms_connected = success;
3140
event["emoncms_connected"] = (int)emoncms_connected;
3241
event["emoncms_message"] = message.substring(0, 64);
@@ -54,11 +63,17 @@ void emoncms_publish(JsonDocument &data)
5463
DBUGVAR(url);
5564
packets_sent++;
5665

57-
client.get(url, [](MongooseHttpClientResponse *response)
66+
auto state = new EmonCmsClientState;
67+
68+
state->connected = false;
69+
70+
client.get(url, [state](MongooseHttpClientResponse *response)
5871
{
5972
MongooseString result = response->body();
6073
DBUGF("result = %.*s", result.length(), result.c_str());
6174

75+
state->connected = true;
76+
6277
const size_t capacity = JSON_OBJECT_SIZE(2) + result.length();
6378
DynamicJsonDocument doc(capacity);
6479
if(DeserializationError::Code::Ok == deserializeJson(doc, result.c_str(), result.length()))
@@ -77,12 +92,13 @@ void emoncms_publish(JsonDocument &data)
7792
DEBUG.printf("%.*s\n", result.length(), (const char *)result);
7893
emoncms_result(false, result.toString());
7994
}
80-
}, [](MongooseHttpClientResponse *response)
95+
}, [state]()
8196
{
82-
DBUGF("onClose %p", response);
83-
if(NULL == response) {
97+
DBUGF("onClose");
98+
if(false == state->connected) {
8499
emoncms_result(false, String("Failed to connect"));
85100
}
101+
delete state;
86102
});
87103
} else {
88104
if(false != emoncms_connected) {

src/emonesp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,6 @@
161161
extern String currentfirmware;
162162
extern String buildenv;
163163

164+
void restart_system();
165+
164166
#endif // _EMONESP_H

src/http_update.cpp

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

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/main.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,3 +256,19 @@ void hardware_setup()
256256

257257
enableLoopWDT();
258258
}
259+
260+
class SystemRestart : public MicroTasks::Alarm
261+
{
262+
public:
263+
void Trigger()
264+
{
265+
DBUGLN("Restarting...");
266+
net_wifi_disconnect();
267+
ESPAL.reset();
268+
}
269+
} systemRestartAlarm;
270+
271+
void restart_system()
272+
{
273+
systemRestartAlarm.Set(1000, false);
274+
}

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
});

0 commit comments

Comments
 (0)