Added HTTP OTA updater for ESP32
Added Easter Egg Improved ArduinoOTA stability on ESP8266 Added function that starts the AP if you press the button for 7 secs Added yet unused methods for color conversion
This commit is contained in:
parent
3db38726ca
commit
e97a739f03
@ -15,7 +15,7 @@ Now also with experimental ESP32 support.
|
|||||||
- Notifier function (multiple ESPs sync color via UDP broadcast)
|
- Notifier function (multiple ESPs sync color via UDP broadcast)
|
||||||
- Support for power pushbutton
|
- Support for power pushbutton
|
||||||
- Custom Theater Chase
|
- Custom Theater Chase
|
||||||
- Full OTA software update capability (only ESP8266)
|
- Full OTA software update capability (HTTP and ArduinoOTA)
|
||||||
- Password protected OTA page for added security (OTA lock)
|
- Password protected OTA page for added security (OTA lock)
|
||||||
- Alexa smart home device server (including dimming)
|
- Alexa smart home device server (including dimming)
|
||||||
- NTP and experimental analog clock function
|
- NTP and experimental analog clock function
|
||||||
|
104
wled00/src/dependencies/webserver/ESP8266HTTPUpdateServer.cpp
Normal file
104
wled00/src/dependencies/webserver/ESP8266HTTPUpdateServer.cpp
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
#include <WiFiClient.h>
|
||||||
|
#include <WiFiServer.h>
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
#include "WebServer.h"
|
||||||
|
#include <Update.h>
|
||||||
|
#else
|
||||||
|
#include <ESP8266WebServer.h>
|
||||||
|
#endif
|
||||||
|
#include <WiFiUdp.h>
|
||||||
|
#include "ESP8266HTTPUpdateServer.h"
|
||||||
|
|
||||||
|
|
||||||
|
const char* ESP8266HTTPUpdateServer::_serverIndex =
|
||||||
|
R"(<html><body><h2>WLED Software Update</h2><br>Get the latest binaries on the <a href="https://github.com/Aircoookie/WLED/tree/master/bin">project GitHub page</a>!<br>
|
||||||
|
<i>Unsure which binary is correct? Go to the <a href="./build">/build subpage</a> to find the details of this version.</i><br>
|
||||||
|
<b>Double check to be sure to upload a valid .bin firmware file for your ESP! Otherwise you'll need USB recovery!</b><br><br>
|
||||||
|
<form method='POST' action='' enctype='multipart/form-data'>
|
||||||
|
<input type='file' name='update'>
|
||||||
|
<input type='submit' value='Update!'>
|
||||||
|
</form>
|
||||||
|
</body></html>)";
|
||||||
|
const char* ESP8266HTTPUpdateServer::_failedResponse = R"(Update Failed!)";
|
||||||
|
const char* ESP8266HTTPUpdateServer::_successResponse = "<META http-equiv=\"refresh\" content=\"15;URL=./\">Update Successful! Rebooting, please wait for redirect...";
|
||||||
|
|
||||||
|
ESP8266HTTPUpdateServer::ESP8266HTTPUpdateServer(bool serial_debug)
|
||||||
|
{
|
||||||
|
_serial_output = serial_debug;
|
||||||
|
_server = NULL;
|
||||||
|
_username = NULL;
|
||||||
|
_password = NULL;
|
||||||
|
_authenticated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
void ESP8266HTTPUpdateServer::setup(WebServer *server, const char * path, const char * username, const char * password)
|
||||||
|
#else
|
||||||
|
void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server, const char * path, const char * username, const char * password)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
_server = server;
|
||||||
|
_username = (char *)username;
|
||||||
|
_password = (char *)password;
|
||||||
|
|
||||||
|
// handler for the /update form page
|
||||||
|
_server->on(path, HTTP_GET, [&](){
|
||||||
|
if(_username != NULL && _password != NULL && !_server->authenticate(_username, _password))
|
||||||
|
return _server->requestAuthentication();
|
||||||
|
_server->send(200, "text/html", _serverIndex);
|
||||||
|
});
|
||||||
|
|
||||||
|
// handler for the /update form POST (once file upload finishes)
|
||||||
|
_server->on(path, HTTP_POST, [&](){
|
||||||
|
if(!_authenticated)
|
||||||
|
return _server->requestAuthentication();
|
||||||
|
_server->send(200, "text/html", Update.hasError() ? _failedResponse : _successResponse);
|
||||||
|
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){
|
||||||
|
if (_serial_output)
|
||||||
|
Serial.setDebugOutput(true);
|
||||||
|
|
||||||
|
_authenticated = (_username == NULL || _password == NULL || _server->authenticate(_username, _password));
|
||||||
|
if(!_authenticated){
|
||||||
|
if (_serial_output)
|
||||||
|
Serial.printf("Unauthenticated Update\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#ifndef ARDUINO_ARCH_ESP32
|
||||||
|
WiFiUDP::stopAll();
|
||||||
|
#endif
|
||||||
|
if (_serial_output)
|
||||||
|
Serial.printf("Update: %s\n", upload.filename.c_str());
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
uint32_t maxSketchSpace = 0x100000; //dirty workaround, limit to 1MB
|
||||||
|
#else
|
||||||
|
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
|
||||||
|
#endif
|
||||||
|
if(!Update.begin(maxSketchSpace)){//start with max available size
|
||||||
|
if (_serial_output) Update.printError(Serial);
|
||||||
|
}
|
||||||
|
} else if(_authenticated && upload.status == UPLOAD_FILE_WRITE){
|
||||||
|
if (_serial_output) Serial.printf(".");
|
||||||
|
if(Update.write(upload.buf, upload.currentSize) != upload.currentSize){
|
||||||
|
if (_serial_output) Update.printError(Serial);
|
||||||
|
|
||||||
|
}
|
||||||
|
} else if(_authenticated && upload.status == UPLOAD_FILE_END){
|
||||||
|
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 {
|
||||||
|
if (_serial_output) Update.printError(Serial);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
}
|
74
wled00/src/dependencies/webserver/ESP8266HTTPUpdateServer.h
Normal file
74
wled00/src/dependencies/webserver/ESP8266HTTPUpdateServer.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#ifndef __HTTP_UPDATE_SERVER_H
|
||||||
|
#define __HTTP_UPDATE_SERVER_H
|
||||||
|
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
class WebServer;
|
||||||
|
|
||||||
|
class ESP8266HTTPUpdateServer
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool _serial_output;
|
||||||
|
WebServer *_server;
|
||||||
|
static const char *_serverIndex;
|
||||||
|
static const char *_failedResponse;
|
||||||
|
static const char *_successResponse;
|
||||||
|
char * _username;
|
||||||
|
char * _password;
|
||||||
|
bool _authenticated;
|
||||||
|
public:
|
||||||
|
ESP8266HTTPUpdateServer(bool serial_debug=false);
|
||||||
|
|
||||||
|
void setup(WebServer *server)
|
||||||
|
{
|
||||||
|
setup(server, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup(WebServer *server, const char * path)
|
||||||
|
{
|
||||||
|
setup(server, path, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup(WebServer *server, const char * username, const char * password)
|
||||||
|
{
|
||||||
|
setup(server, "/update", username, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup(WebServer *server, const char * path, const char * username, const char * password);
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
class ESP8266WebServer;
|
||||||
|
|
||||||
|
class ESP8266HTTPUpdateServer
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool _serial_output;
|
||||||
|
ESP8266WebServer *_server;
|
||||||
|
static const char *_serverIndex;
|
||||||
|
static const char *_failedResponse;
|
||||||
|
static const char *_successResponse;
|
||||||
|
char * _username;
|
||||||
|
char * _password;
|
||||||
|
bool _authenticated;
|
||||||
|
public:
|
||||||
|
ESP8266HTTPUpdateServer(bool serial_debug=false);
|
||||||
|
|
||||||
|
void setup(ESP8266WebServer *server)
|
||||||
|
{
|
||||||
|
setup(server, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup(ESP8266WebServer *server, const char * path)
|
||||||
|
{
|
||||||
|
setup(server, path, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup(ESP8266WebServer *server, const char * username, const char * password)
|
||||||
|
{
|
||||||
|
setup(server, "/update", username, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup(ESP8266WebServer *server, const char * path, const char * username, const char * password);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -1,3 +1,5 @@
|
|||||||
|
Notice by Aircoookie: Port of the ESP8266HTTPUpdateServer for ESP32 is also included in this directory.
|
||||||
|
|
||||||
# WebServer
|
# WebServer
|
||||||
ESP8266/ESP32 WebServer library
|
ESP8266/ESP32 WebServer library
|
||||||
|
|
||||||
|
@ -16,11 +16,11 @@
|
|||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include <ESP8266mDNS.h>
|
#include <ESP8266mDNS.h>
|
||||||
#include <ESP8266WebServer.h>
|
#include <ESP8266WebServer.h>
|
||||||
#include <ESP8266HTTPUpdateServer.h>
|
|
||||||
#endif
|
#endif
|
||||||
#include <EEPROM.h>
|
#include <EEPROM.h>
|
||||||
#include <ArduinoOTA.h>
|
#include <ArduinoOTA.h>
|
||||||
#include <WiFiUDP.h>
|
#include <WiFiUDP.h>
|
||||||
|
#include "src/dependencies/webserver/ESP8266HTTPUpdateServer.h"
|
||||||
#include "src/dependencies/time/Time.h"
|
#include "src/dependencies/time/Time.h"
|
||||||
#include "src/dependencies/time/TimeLib.h"
|
#include "src/dependencies/time/TimeLib.h"
|
||||||
#include "src/dependencies/timezone/Timezone.h"
|
#include "src/dependencies/timezone/Timezone.h"
|
||||||
@ -29,7 +29,7 @@
|
|||||||
#include "WS2812FX.h"
|
#include "WS2812FX.h"
|
||||||
|
|
||||||
//version in format yymmddb (b = daily build)
|
//version in format yymmddb (b = daily build)
|
||||||
#define VERSION 1801140
|
#define VERSION 1801150
|
||||||
const String versionName = "WLED 0.5dev";
|
const String versionName = "WLED 0.5dev";
|
||||||
|
|
||||||
//AP and OTA default passwords (change them!)
|
//AP and OTA default passwords (change them!)
|
||||||
@ -171,6 +171,7 @@ byte bri_it = 0;
|
|||||||
byte bri_last = 127;
|
byte bri_last = 127;
|
||||||
boolean transitionActive = false;
|
boolean transitionActive = false;
|
||||||
boolean buttonPressedBefore = false;
|
boolean buttonPressedBefore = false;
|
||||||
|
long buttonPressedTime = 0;
|
||||||
boolean nightlightActive = false;
|
boolean nightlightActive = false;
|
||||||
boolean nightlightActive_old = false;
|
boolean nightlightActive_old = false;
|
||||||
int nightlightDelayMs;
|
int nightlightDelayMs;
|
||||||
@ -234,8 +235,8 @@ String escapedMac;
|
|||||||
WebServer server(80);
|
WebServer server(80);
|
||||||
#else
|
#else
|
||||||
ESP8266WebServer server(80);
|
ESP8266WebServer server(80);
|
||||||
ESP8266HTTPUpdateServer httpUpdater; //only for ESP8266
|
|
||||||
#endif
|
#endif
|
||||||
|
ESP8266HTTPUpdateServer httpUpdater;
|
||||||
WiFiUDP notifierUdp;
|
WiFiUDP notifierUdp;
|
||||||
WiFiUDP ntpUdp;
|
WiFiUDP ntpUdp;
|
||||||
|
|
||||||
|
@ -122,6 +122,9 @@ void wledInit()
|
|||||||
val += "mA currently\nNotice: This is just an estimate which does not take into account several factors (like effects and wire resistance). It is NOT an accurate measurement!";
|
val += "mA currently\nNotice: This is just an estimate which does not take into account several factors (like effects and wire resistance). It is NOT an accurate measurement!";
|
||||||
server.send(200, "text/plain", val);
|
server.send(200, "text/plain", val);
|
||||||
});
|
});
|
||||||
|
server.on("/teapot", HTTP_GET, [](){
|
||||||
|
server.send(418, "text/plain", "418. I'm a teapot. (Tangible Embedded Advanced Project Of Twinkling)");
|
||||||
|
});
|
||||||
server.on("/build", HTTP_GET, [](){
|
server.on("/build", HTTP_GET, [](){
|
||||||
String info = "hard-coded build info:\r\n\n";
|
String info = "hard-coded build info:\r\n\n";
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
@ -166,6 +169,7 @@ void wledInit()
|
|||||||
#endif
|
#endif
|
||||||
server.send(200, "text/plain", info);
|
server.send(200, "text/plain", info);
|
||||||
});
|
});
|
||||||
|
//if OTA is allowed
|
||||||
if (!otaLock){
|
if (!otaLock){
|
||||||
server.on("/edit", HTTP_GET, [](){
|
server.on("/edit", HTTP_GET, [](){
|
||||||
if(!handleFileRead("/edit.htm")) server.send(200, "text/html", PAGE_edit);
|
if(!handleFileRead("/edit.htm")) server.send(200, "text/html", PAGE_edit);
|
||||||
@ -179,14 +183,14 @@ void wledInit()
|
|||||||
server.on("/down", HTTP_GET, down);
|
server.on("/down", HTTP_GET, down);
|
||||||
server.on("/cleareeprom", HTTP_GET, clearEEPROM);
|
server.on("/cleareeprom", HTTP_GET, clearEEPROM);
|
||||||
//init ota page
|
//init ota page
|
||||||
#ifndef ARDUINO_ARCH_ESP32
|
|
||||||
httpUpdater.setup(&server); //only for ESP8266
|
httpUpdater.setup(&server); //only for ESP8266
|
||||||
#else
|
|
||||||
server.on("/update", HTTP_GET, [](){
|
|
||||||
server.send(200, "text/plain", "OTA update is not supported on ESP32 at this time. You may want to use ArduinoOTA.");
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
//init ArduinoOTA
|
//init ArduinoOTA
|
||||||
|
ArduinoOTA.onStart([]() {
|
||||||
|
#ifndef ARDUINO_ARCH_ESP32
|
||||||
|
wifi_set_sleep_type(NONE_SLEEP_T);
|
||||||
|
#endif
|
||||||
|
DEBUG_PRINTLN("Start ArduinoOTA");
|
||||||
|
});
|
||||||
ArduinoOTA.begin();
|
ArduinoOTA.begin();
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
@ -233,7 +237,7 @@ void wledInit()
|
|||||||
strip.setBrightness(255);
|
strip.setBrightness(255);
|
||||||
strip.start();
|
strip.start();
|
||||||
|
|
||||||
|
pinMode(buttonPin, INPUT_PULLUP);
|
||||||
#ifdef CRONIXIE
|
#ifdef CRONIXIE
|
||||||
strip.driverModeCronixie(true);
|
strip.driverModeCronixie(true);
|
||||||
strip.setCronixieBacklight(cronixieBacklight);
|
strip.setCronixieBacklight(cronixieBacklight);
|
||||||
@ -241,11 +245,18 @@ void wledInit()
|
|||||||
#endif
|
#endif
|
||||||
if (bootPreset>0) applyPreset(bootPreset, turnOnAtBoot, true, true);
|
if (bootPreset>0) applyPreset(bootPreset, turnOnAtBoot, true, true);
|
||||||
colorUpdated(0);
|
colorUpdated(0);
|
||||||
pinMode(buttonPin, INPUT_PULLUP);
|
if(digitalRead(buttonPin) == LOW) buttonEnabled = false; //disable button if it is "pressed" unintentionally
|
||||||
}
|
}
|
||||||
|
|
||||||
void initAP(){
|
void initAP(){
|
||||||
|
String save = apssid;
|
||||||
|
#ifdef CRONIXIE
|
||||||
|
if (apssid.length() <1) apssid = "CRONIXIE-AP";
|
||||||
|
#else
|
||||||
|
if (apssid.length() <1) apssid = "WLED-AP";
|
||||||
|
#endif
|
||||||
WiFi.softAP(apssid.c_str(), appass.c_str(), apchannel, aphide);
|
WiFi.softAP(apssid.c_str(), appass.c_str(), apchannel, aphide);
|
||||||
|
apssid = save;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initCon()
|
void initCon()
|
||||||
@ -261,15 +272,8 @@ void initCon()
|
|||||||
{
|
{
|
||||||
WiFi.disconnect();
|
WiFi.disconnect();
|
||||||
DEBUG_PRINTLN("Can't connect. Opening AP...");
|
DEBUG_PRINTLN("Can't connect. Opening AP...");
|
||||||
String save = apssid;
|
|
||||||
onlyAP = true;
|
onlyAP = true;
|
||||||
#ifdef CRONIXIE
|
|
||||||
if (apssid.length() <1) apssid = "CRONIXIE-AP";
|
|
||||||
#else
|
|
||||||
if (apssid.length() <1) apssid = "WLED-AP";
|
|
||||||
#endif
|
|
||||||
initAP();
|
initAP();
|
||||||
apssid = save;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ void handleButton()
|
|||||||
{
|
{
|
||||||
if (digitalRead(buttonPin) == LOW && !buttonPressedBefore)
|
if (digitalRead(buttonPin) == LOW && !buttonPressedBefore)
|
||||||
{
|
{
|
||||||
|
buttonPressedTime = millis();
|
||||||
buttonPressedBefore = true;
|
buttonPressedBefore = true;
|
||||||
if (buttonMacro == 255)
|
if (buttonMacro == 255)
|
||||||
{
|
{
|
||||||
@ -29,6 +30,7 @@ void handleButton()
|
|||||||
delay(15); //debounce
|
delay(15); //debounce
|
||||||
if (digitalRead(buttonPin) == HIGH)
|
if (digitalRead(buttonPin) == HIGH)
|
||||||
{
|
{
|
||||||
|
if (millis() - buttonPressedTime > 7000) initAP();
|
||||||
buttonPressedBefore = false;
|
buttonPressedBefore = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
27
wled00/wled14_colors.ino
Normal file
27
wled00/wled14_colors.ino
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Color conversion methods
|
||||||
|
*/
|
||||||
|
void colorCTtoRGB(uint16_t mired, uint8_t* rgb) //white spectrum to rgb
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void colorHSBtoRGB(uint16_t hue, uint8_t sat, uint8_t bri, uint8_t* rgb) //hue, sat, bri to rgb
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void colorXYtoRGB(float x, float y, uint8_t* rgb) //coordinates to rgb (https://www.developers.meethue.com/documentation/color-conversions-rgb-xy)
|
||||||
|
{
|
||||||
|
float z = 1.0f - x - y;
|
||||||
|
//float Y = 1.0f; // Brightness, we handle this separately
|
||||||
|
float X = (1.0f / y) * x;
|
||||||
|
float Z = (1.0f / y) * z;
|
||||||
|
rgb[0] = (int)(X * 1.656492f - 0.354851f - Z * 0.255038f);
|
||||||
|
rgb[1] = (int)(-X * 0.707196f + 1.655397f + Z * 0.036152f);
|
||||||
|
rgb[2] = (int)(X * 0.051713f - 0.121364f + Z * 1.011530f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void colorRGBtoXY(uint8_t* rgb, float* xy){} //rgb to coordinates (https://www.developers.meethue.com/documentation/color-conversions-rgb-xy)
|
||||||
|
|
||||||
|
void colorRGBtoRGBW(uint8_t* rgb, uint8_t* rgbw){} //rgb to rgbw, not imlemented yet
|
Loading…
Reference in New Issue
Block a user