Skip to content

Commit 8f5a859

Browse files
author
Patrick Lapointe
committed
Initial Commit
1 parent 0df6c11 commit 8f5a859

9 files changed

Lines changed: 1049 additions & 2 deletions

File tree

.gitattributes

Lines changed: 0 additions & 2 deletions
This file was deleted.

LICENSE

Lines changed: 674 additions & 0 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Simple remote program update handling for ESP8266 and ESP32
2+
3+
Simple remote update management for ESP8266 and ESP32.
4+
Allow to easily set a light Web updater and/or OTA update. Intended to be used with an ESP8266 or ESP32.
5+
6+
What this library can do:
7+
- Can host and manage a minimal web GUI to upload a new program (web updater)
8+
- Can enable and manage Arduino OTA
9+
- Automatically restart these services when a WiFI connection is lost.
10+
11+
I took some code from palpointe6/EspMQTTClient. So, thanks to the contributors that worked on this part from EspMQTTClient: @EdJoPaTo, @hallard.
12+
13+
14+
# Get started
15+
16+
```c++
17+
#include "EspSimpleRemoteUpdate.h"
18+
19+
EspSimpleRemoteUpdate updater;
20+
21+
void setup() {
22+
updater.enableHTTPWebUpdater("USERNAME", "PASSWORD");
23+
updater.enableOTA("PASSWORD");
24+
25+
// Obiviously, you need to do some WiFi connection stuff.
26+
// EspSimpleRemoteUpdate will automatically detect a new WiFI connection and will start the enabled features automatically.
27+
}
28+
29+
void loop() {
30+
updater.handle(); // Calling this at every loop() is mandatory.
31+
}
32+
```
33+
34+
# Some documentation
35+
36+
```c++
37+
// Enable debugging messages (sent to Serial)
38+
enableDebuggingMessages();
39+
40+
// Set the hostname
41+
setHostname(const char* hostname);
42+
43+
// Enable the web updater
44+
enableHTTPWebUpdater(const char* username = "", const char* password = "", const char* baseAddr = "/");
45+
46+
// Enable Arduino OTA
47+
enableOTA(const char* password, const uint16_t port = 0);
48+
49+
// Calling this at every loop() is mandatory.
50+
handle();
51+
```
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#include "EspSimpleWifiHandler.h"
2+
#include "EspSimpleRemoteUpdate.h"
3+
4+
// Automatic WiFI management with EspSimpleWifiHandler.
5+
// You can use whatever you want for the WiFi management. Here I choose EspSimpleWifiHandler for simplicity.
6+
EspSimpleWifiHandler wifiHandler("WIFI_SSID", "WIFI_PASSWORD", "HOSTNAME");
7+
8+
// The updater.
9+
EspSimpleRemoteUpdate updater;
10+
11+
void setup() {
12+
Serial.begin(115200);
13+
wifiHandler.enableDebuggingMessages();
14+
updater.enableDebuggingMessages();
15+
16+
updater.enableHTTPWebUpdater("USERNAME", "PASSWORD");
17+
updater.enableOTA("PASSWORD");
18+
}
19+
20+
void loop() {
21+
updater.handle();
22+
}

keywords.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#######################################
2+
# Syntax Coloring Map For EspSimpleMQTTClient
3+
#######################################
4+
5+
#######################################
6+
# Datatypes (KEYWORD1)
7+
#######################################
8+
9+
EspSimpleRemoteUpdate KEYWORD1
10+
11+
#######################################
12+
# Methods and Functions (KEYWORD2)
13+
#######################################
14+
15+
enableDebuggingMessages KEYWORD2
16+
setHostname KEYWORD2
17+
enableHTTPWebUpdater KEYWORD2
18+
enableOTA KEYWORD2
19+
handle KEYWORD2
20+

library.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name":"EspSimpleRemoteUpdate",
3+
"description":"Simple remote update handling for ESP8266/ESP32",
4+
"keywords":"update,wifi,iot",
5+
"authors": [
6+
{
7+
"name": "Patrick Lapointe",
8+
"maintainer": true
9+
}
10+
],
11+
"repository":
12+
{
13+
"type": "git",
14+
"url": "https://github.com/plapointe6/EspSimpleRemoteUpdate.git"
15+
},
16+
"version": "0.1.0",
17+
"frameworks": "arduino",
18+
"platforms": ["espressif8266", "espressif32"]
19+
}

library.properties

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name=EspSimpleRemoteUpdate
2+
version=0.1.0
3+
author=Patrick Lapointe <patrick.lapointe@hotmail.ca>
4+
maintainer=Patrick Lapointe <patrick.lapointe@hotmail.ca>
5+
sentence=Simple remote update handling for ESP8266/ESP32
6+
paragraph=Allow to easily set a Web updater and/or OTA update. Intended to be used with an ESP8266 or ESP32.
7+
category=Communication
8+
url=https://github.com/plapointe6/EspSimpleRemoteUpdate
9+
architectures=*

src/ESP32HTTPUpdateServer.h

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#ifndef ESP32_HTTP_UPDATE_SERVER_H
2+
#define ESP32_HTTP_UPDATE_SERVER_H
3+
4+
/*
5+
Based on the HTTP update exemple of ESP32 core
6+
*/
7+
8+
#include <WebServer.h>
9+
#include <Update.h>
10+
11+
#define ESP32_WEB_UPDATE_HTML "<html><body><form method='POST' action='' enctype='multipart/form-data'><input type='file' name='update'><input type='submit' value='Update'></form></body></html>"
12+
#define ESP32_WEB_UPDATE_SUCCESS_RESPONSE "<META http-equiv=\"refresh\" content=\"10;URL=/\">Update Success! Rebooting...\n"
13+
14+
class ESP32HTTPUpdateServer
15+
{
16+
private:
17+
WebServer* _server;
18+
19+
String _username;
20+
String _password;
21+
bool _serialDebugging;
22+
23+
public:
24+
ESP32HTTPUpdateServer(bool serialDebugging = false)
25+
{
26+
_server = NULL;
27+
_username = "";
28+
_password = "";
29+
}
30+
31+
void setup(WebServer* server, const char* path = "/", const char* username = "", const char* password = "")
32+
{
33+
_server = server;
34+
_username = username;
35+
_password = password;
36+
37+
// Get of the index handling
38+
_server->on(path, HTTP_GET, [&]() {
39+
// Force authentication if a user and password are defined
40+
if (_username.length() > 0 && _password.length() > 0 && !_server->authenticate(_username.c_str(), _password.c_str()))
41+
return _server->requestAuthentication();
42+
43+
_server->sendHeader("Connection", "close");
44+
_server->send(200, "text/html", ESP32_WEB_UPDATE_HTML);
45+
});
46+
47+
// Post of the file handling
48+
_server->on(path, HTTP_POST, [&]() {
49+
_server->client().setNoDelay(true);
50+
_server->send_P(200, "text/html", (Update.hasError()) ? "FAIL" : ESP32_WEB_UPDATE_SUCCESS_RESPONSE);
51+
delay(100);
52+
_server->client().stop();
53+
ESP.restart();
54+
}, [&]() {
55+
HTTPUpload& upload = _server->upload();
56+
57+
if (upload.status == UPLOAD_FILE_START)
58+
{
59+
// Check if we are authenticated
60+
if (!(_username.length() == 0 || _password.length() == 0 || _server->authenticate(_username.c_str(), _password.c_str())))
61+
{
62+
if (_serialDebugging)
63+
Serial.printf("Unauthenticated Update\n");
64+
65+
return;
66+
}
67+
68+
// Debugging message for upload start
69+
if (_serialDebugging)
70+
{
71+
Serial.setDebugOutput(true);
72+
Serial.printf("Update: %s\n", upload.filename.c_str());
73+
}
74+
75+
// Starting update
76+
bool error = Update.begin(UPDATE_SIZE_UNKNOWN);
77+
if (_serialDebugging && error)
78+
Update.printError(Serial);
79+
}
80+
else if (upload.status == UPLOAD_FILE_WRITE)
81+
{
82+
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize && _serialDebugging)
83+
Update.printError(Serial);
84+
}
85+
else if (upload.status == UPLOAD_FILE_END)
86+
{
87+
if (Update.end(true) && _serialDebugging)
88+
Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
89+
else if(_serialDebugging)
90+
Update.printError(Serial);
91+
92+
if(_serialDebugging)
93+
Serial.setDebugOutput(false);
94+
}
95+
else if(_serialDebugging)
96+
Serial.printf("Update Failed Unexpectedly (likely broken connection): status=%d\n", upload.status);
97+
});
98+
99+
_server->begin();
100+
}
101+
};
102+
103+
#endif

src/EspSimpleRemoteUpdate.h

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/*
2+
EspSimpleRemoteUpdate.h
3+
Goal: Provide utilities to update your program wirelessly. Works with both ESP32 and ESP8266
4+
Github: https://github.com/plapointe6/EspSimpleRemoteUpdate
5+
*/
6+
7+
#ifndef ESP_SIMPLE_REMOTE_UPDATE_H
8+
#define ESP_SIMPLE_REMOTE_UPDATE_H
9+
10+
#include <ArduinoOTA.h>
11+
12+
#ifdef ESP8266
13+
#include <ESP8266WebServer.h>
14+
#include <ESP8266HTTPUpdateServer.h>
15+
#include <ESP8266mDNS.h>
16+
#define ESPHTTPUpdateServer ESP8266HTTPUpdateServer
17+
#define WebServer ESP8266WebServer
18+
#define ESPmDNS ESP8266mDNS
19+
#else // for ESP32
20+
#include <WebServer.h>
21+
#include "ESP32HTTPUpdateServer.h"
22+
#include <ESPmDNS.h>
23+
#define ESPHTTPUpdateServer ESP32HTTPUpdateServer
24+
#endif
25+
26+
class EspSimpleRemoteUpdate {
27+
28+
private:
29+
// Http updater related
30+
WebServer* _httpServer = nullptr;
31+
ESPHTTPUpdateServer* _httpUpdater = nullptr;
32+
const char* _httpUpdaterUsername;
33+
const char* _httpUpdaterPassword;
34+
const char* _httpUpdaterBaseAddr = "/";
35+
36+
// OTA related
37+
bool _enableOTA = false;
38+
39+
// WiFI connection monitoring
40+
bool _wifiConnected = false;
41+
42+
// Other
43+
const char* _hostname = nullptr;
44+
bool _enableDebugMessages = false;
45+
46+
public:
47+
EspSimpleRemoteUpdate() {};
48+
49+
~EspSimpleRemoteUpdate() {
50+
if (_httpServer)
51+
delete _httpServer;
52+
if (_httpUpdater)
53+
delete _httpUpdater;
54+
};
55+
56+
inline void enableDebuggingMessages(bool enabled = true) {
57+
_enableDebugMessages = enabled;
58+
}
59+
60+
inline void setHostname(const char* hostname) {
61+
_hostname = hostname;
62+
}
63+
64+
void enableHTTPWebUpdater(const char* username = "", const char* password = "", const char* baseAddr = "/") {
65+
if (!_httpServer) {
66+
if (_enableDebugMessages)
67+
Serial.printf("UPDATER: Enabling web updater ...\n");
68+
69+
_httpServer = new WebServer(80);
70+
_httpUpdater = new ESPHTTPUpdateServer(_enableDebugMessages);
71+
_httpUpdaterUsername = username;
72+
_httpUpdaterPassword = password;
73+
_httpUpdaterBaseAddr = baseAddr;
74+
}
75+
else if(_enableDebugMessages) {
76+
Serial.printf("UPDATER: Web updater already enabled.\n");
77+
}
78+
}
79+
80+
void enableOTA(const char* password, const uint16_t port = 0) {
81+
if(_enableDebugMessages)
82+
Serial.printf("UPDATER: Enabling Arduino OTA ...\n");
83+
84+
_enableOTA = true;
85+
86+
if (password)
87+
ArduinoOTA.setPassword(password);
88+
89+
if (port)
90+
ArduinoOTA.setPort(port);
91+
};
92+
93+
void handle() {
94+
const bool wifiConnected = WiFi.status() == WL_CONNECTED;
95+
96+
// A WiFi connection has occured
97+
if (wifiConnected && !_wifiConnected) {
98+
99+
// Take the WiFi hostname if none is provided
100+
if (!_hostname) {
101+
_hostname = WiFi.getHostname();
102+
}
103+
104+
// Enable mdns
105+
MDNS.begin(_hostname);
106+
107+
// Init the web updater
108+
if (_httpServer)
109+
{
110+
_httpUpdater->setup(_httpServer, _httpUpdaterBaseAddr, _httpUpdaterUsername, _httpUpdaterPassword);
111+
_httpServer->begin();
112+
MDNS.addService("http", "tcp", 80);
113+
114+
if (_enableDebugMessages) {
115+
Serial.printf("UPDATER: Updater ready, open http://%s.local in your browser and login with username '%s' and password '%s'.\n", _hostname, _httpUpdaterUsername, _httpUpdaterPassword);
116+
}
117+
}
118+
119+
// Init arduino OTA
120+
if (_enableOTA) {
121+
ArduinoOTA.setHostname(_hostname);
122+
ArduinoOTA.begin();
123+
124+
if (_enableDebugMessages) {
125+
Serial.printf("UPDATER: Arduino OTA ready.\n");
126+
}
127+
}
128+
}
129+
// WiFi has disconnected
130+
else if (!wifiConnected && _wifiConnected) {
131+
MDNS.end();
132+
}
133+
// We are connected to WiFi
134+
else if(wifiConnected && _wifiConnected) {
135+
136+
if(_httpServer) {
137+
_httpServer->handleClient();
138+
#ifdef ESP8266
139+
MDNS.update();
140+
#endif
141+
}
142+
143+
if (_enableOTA)
144+
ArduinoOTA.handle();
145+
}
146+
147+
_wifiConnected = wifiConnected;
148+
};
149+
};
150+
151+
#endif

0 commit comments

Comments
 (0)