Skip to content

Commit

Permalink
Added OTA and MDNS
Browse files Browse the repository at this point in the history
Added OTA update functionality and MDNS transponder.
  • Loading branch information
Tobalation committed Apr 3, 2020
1 parent 0f7e57c commit c67c107
Show file tree
Hide file tree
Showing 3 changed files with 210 additions and 8 deletions.
135 changes: 135 additions & 0 deletions Node main module/src/HTTPUpdateServer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/**
* Ported the ESP8266HTTPUpdateServer published by Arduino-core to
* provide the web browser based OTA update on the ESP32 platform.
* @file HTTPUpdateServer.cpp
* @author hieromon@gmail.com
* @version 0.9.10
* @date 2019-06-06
* @copyright MIT license.
*/

#ifdef ARDUINO_ARCH_ESP32
// This class will available only EPS32 actually.

#include <Arduino.h>
#include <WiFiClient.h>
#include <WiFiServer.h>
#include <WebServer.h>
#include <WiFiUdp.h>
#include <Update.h>
#include "StreamString.h"
#include "HTTPUpdateServer.h"

static const char serverIndex[] PROGMEM = R"(
<html><body>
<form method='POST' action='' enctype='multipart/form-data'>
<input type='file' name='update'>
<input type='submit' value='Update'>
</form>
</body></html>
)";

static const char successResponse[] PROGMEM =
"<meta http-equiv=\"refresh\" content=\"15;URL=/\">Update Success! Rebooting...\n";

/**
* Setup for the web update. Register the authentication procedure and
* binary file upload handler required to update the actual sketch binary by OTA.
* @param server A pointer to the WebServer instance
* @param path URI of the update handler
* @param username Username for authentication
* @arama password Password for authentication
*/
void HTTPUpdateServer::setup(WebServer* server, const String& path, const String& username, const String& password) {
_server = server;
_username = username;
_password = password;

// handler for the /update form page
_server->on(path.c_str(), HTTP_GET, [&] () {
if (_username != _emptyString && _password != _emptyString && !_server->authenticate(_username.c_str(), _password.c_str()))
return _server->requestAuthentication();
_server->send_P(200, PSTR("text/html"), serverIndex);
});

// handler for the /update form POST (once file upload finishes)
_server->on(path.c_str(), HTTP_POST, [&] () {
if(!_authenticated)
return _server->requestAuthentication();
if (Update.hasError()) {
_server->send(200, F("text/html"), String(F("Update error: ")) + _updaterError);
}
else {
_server->client().setNoDelay(true);
_server->send_P(200, PSTR("text/html"), successResponse);
delay(100);
_server->client().stop();
ESP.restart();
}
}, [&] () {
// handler for the file upload, get's the sketch bytes, and writes
// them through the Update object
HTTPUpload& upload = _server->upload();

if (upload.status == UPLOAD_FILE_START) {
_updaterError = String();
if (_serial_output)
Serial.setDebugOutput(true);

_authenticated = (_username == _emptyString || _password == _emptyString || _server->authenticate(_username.c_str(), _password.c_str()));
if (!_authenticated) {
if (_serial_output)
Serial.println("Unauthenticated Update");
return;
}

if (_serial_output)
Serial.printf("Update: %s\n", upload.filename.c_str());
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
if (!Update.begin(maxSketchSpace)) { //start with max available size
_setUpdaterError();
}
}
else if (_authenticated && upload.status == UPLOAD_FILE_WRITE && !_updaterError.length()) {
if (_serial_output)
Serial.print('.');
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize)
_setUpdaterError();
}
else if (_authenticated && upload.status == UPLOAD_FILE_END && !_updaterError.length()) {
if (Update.end(true)) { //true to set the size to the current progress
if (_serial_output)
Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
}
else {
_setUpdaterError();
}
if (_serial_output)
Serial.setDebugOutput(false);
}
else if (_authenticated && upload.status == UPLOAD_FILE_ABORTED) {
Update.end();
if (_serial_output)
Serial.println("Update was aborted");
}
delay(0);
});
}

/**
* Convert the update error code to string for notation.
*/
void HTTPUpdateServer::_setUpdaterError() {
if (_serial_output)
Update.printError(Serial);
StreamString str;
Update.printError(str);
_updaterError = str.c_str();
}

/**
* Shared empty String instance
*/
const String HTTPUpdateServer::_emptyString;

#endif // !ARDUINO_ARCH_ESP32
43 changes: 43 additions & 0 deletions Node main module/src/HTTPUpdateServer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Ported the ESP8266HTTPUpdateServer published by Arduino-core to
* provide the web browser based OTA update on the ESP32 platform.
* @file HTTPUpdateServer.h
* @author hieromon@gmail.com
* @version 0.9.10
* @date 2019-06-06
* @copyright MIT license.
*/

#ifndef __HTTP_UPDATE_SERVER_H
#define __HTTP_UPDATE_SERVER_H

#ifdef ARDUINO_ARCH_ESP32
// This class will available only EPS32 actually.

class WebServer;

class HTTPUpdateServer {
public:
explicit HTTPUpdateServer(bool serial_debug = false) : _serial_output(serial_debug), _server(nullptr), _username(_emptyString), _password(_emptyString), _authenticated(false) {}
~HTTPUpdateServer() {}
void setup(WebServer* server) { setup(server, _emptyString, _emptyString); }
void setup(WebServer* server, const String& path) { setup(server, path, _emptyString, _emptyString); }
void setup(WebServer* server, const String& username, const String& password) { setup(server, "/update", username, password); }
void setup(WebServer* server, const String& path, const String& username, const String& password);
void updateCredentials(const String& username, const String& password) { _username = username; _password = password; }

protected:
void _setUpdaterError();

private:
bool _serial_output;
WebServer* _server;
String _username;
String _password;
bool _authenticated;
String _updaterError;
static const String _emptyString;
};

#endif // !ARDUINO_ARCH_ESP32
#endif // !__HTTP_UPDATE_SERVER_H
40 changes: 32 additions & 8 deletions Node main module/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
#include <WiFi.h>
#include <HTTPClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <AutoConnect.h>
#include "HTTPUpdateServer.h"
#include <AutoConnectCredential.h>
#include <ArduinoJson.h>

Expand All @@ -16,16 +18,16 @@

// Time is in milliseconds
#define LED_TICKER 33
#define LED_BUILTIN 2
#define BUTTON_PIN 32
#define DEFAULT_UPDATE_INTERVAL 60000
#define LIVE_SENSOR_INTERVAL 1000
#define SETTINGS_FILE "/settings.txt"
#define DATA_TRANSMISSION_TIMEOUT 20 // arbitrary number
#define DATA_TRANSMISSION_TIMEOUT 32 // arbitrary number
#define REBOOT_BUTTON_HOLD_DURATION 3000
#define FACTORY_RESET_BUTTON_HOLD_DURATION 10000



byte modules[MAX_SENSORS]; // array with address listings of connected sensor modules
AsyncDelay delay_sensor_update; // delay timer for asynchronous update interval
AsyncDelay delay_sensor_view; // 1 second delay for real time sensor viewing
Expand All @@ -44,6 +46,8 @@ String nodeLEDSetting = "On";
unsigned long currentUpdateRate = DEFAULT_UPDATE_INTERVAL;

WebServer server; // HTTP server to serve web UI
HTTPUpdateServer updateServer(true); // OTA update handler, true param is for serial debug
AutoConnectAux update("/update", "Update");
AutoConnect Portal(server); // AutoConnect handler object
AutoConnectConfig portalConfig("MainModuleAP", "12345678");

Expand Down Expand Up @@ -130,17 +134,17 @@ void asyncBlink(unsigned long ms = 0)

// Button input checking function
void checkButton(){
static unsigned long pushedDownTime = NULL;
if (pushedDownTime == NULL && digitalRead(BUTTON_PIN) == LOW){ // Button being pressed
static unsigned long pushedDownTime = 0;
if (pushedDownTime == 0 && digitalRead(BUTTON_PIN) == LOW){ // Button being pressed
pushedDownTime = millis();

}else if (pushedDownTime != NULL && digitalRead(BUTTON_PIN) == LOW){ // Pressing the button, change the LED light according to the pressing time.
}else if (pushedDownTime != 0 && digitalRead(BUTTON_PIN) == LOW){ // Pressing the button, change the LED light according to the pressing time.
unsigned int pressingDuration = millis() - pushedDownTime;
if (pressingDuration > REBOOT_BUTTON_HOLD_DURATION && pressingDuration < FACTORY_RESET_BUTTON_HOLD_DURATION){
asyncBlink(FACTORY_RESET_BUTTON_HOLD_DURATION - pressingDuration);
}
}
else if (pushedDownTime != NULL && digitalRead(BUTTON_PIN) == HIGH ){ // Button released, check the pressed duration and peform action
else if (pushedDownTime != 0 && digitalRead(BUTTON_PIN) == HIGH ){ // Button released, check the pressed duration and peform action
unsigned int pressingDuration = millis() - pushedDownTime;

if (pressingDuration > FACTORY_RESET_BUTTON_HOLD_DURATION){
Expand All @@ -153,7 +157,7 @@ void checkButton(){
ESP.restart();
}

pushedDownTime = NULL;
pushedDownTime = 0;
}
}

Expand Down Expand Up @@ -618,6 +622,10 @@ void setup()
server.on("/save_settings", handle_SaveSettings);
server.on("/getJSON", handle_getSensorJSON);

// setup update server
updateServer.setup(&server);
Serial.println("OTA update server started.");

// setup AutoConnect with a configuration
portalConfig.title = "Main Module v1.0";
portalConfig.apid = "MainModule-" + String((uint32_t)(ESP.getEfuseMac() >> 32), HEX);
Expand All @@ -628,6 +636,8 @@ void setup()
portalConfig.tickerPort = LED_TICKER;
portalConfig.tickerOn = HIGH;
Portal.config(portalConfig);
// add update page aux
Portal.join({update});

// load custom page JSON and build pages into memory
if(!Portal.load(customPageJSON))
Expand All @@ -653,10 +663,24 @@ void setup()
Serial.print("IP: ");
Serial.println(WiFi.localIP());
Serial.println();
// initialize MDNS
String mdnshostname = nodeName;
mdnshostname.toLowerCase();
if(MDNS.begin(mdnshostname.c_str()))
{
MDNS.addService("http","tcp",80);
Serial.println("MDNS transponder started.");
Serial.println("Access at http://" + mdnshostname + ".local");
}
else
{
Serial.println("MDNS Initialization failed. Service will not be available.");
}

}
else
{
Serial.println("Connection failed, rebooting.");
Serial.println("Portal initialization failed, rebooting.");
ESP.restart();
}

Expand Down

0 comments on commit c67c107

Please sign in to comment.