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)
|
||||
- Support for power pushbutton
|
||||
- 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)
|
||||
- Alexa smart home device server (including dimming)
|
||||
- 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
|
||||
ESP8266/ESP32 WebServer library
|
||||
|
||||
|
@ -16,11 +16,11 @@
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <ESP8266HTTPUpdateServer.h>
|
||||
#endif
|
||||
#include <EEPROM.h>
|
||||
#include <ArduinoOTA.h>
|
||||
#include <WiFiUDP.h>
|
||||
#include "src/dependencies/webserver/ESP8266HTTPUpdateServer.h"
|
||||
#include "src/dependencies/time/Time.h"
|
||||
#include "src/dependencies/time/TimeLib.h"
|
||||
#include "src/dependencies/timezone/Timezone.h"
|
||||
@ -29,7 +29,7 @@
|
||||
#include "WS2812FX.h"
|
||||
|
||||
//version in format yymmddb (b = daily build)
|
||||
#define VERSION 1801140
|
||||
#define VERSION 1801150
|
||||
const String versionName = "WLED 0.5dev";
|
||||
|
||||
//AP and OTA default passwords (change them!)
|
||||
@ -171,6 +171,7 @@ byte bri_it = 0;
|
||||
byte bri_last = 127;
|
||||
boolean transitionActive = false;
|
||||
boolean buttonPressedBefore = false;
|
||||
long buttonPressedTime = 0;
|
||||
boolean nightlightActive = false;
|
||||
boolean nightlightActive_old = false;
|
||||
int nightlightDelayMs;
|
||||
@ -234,8 +235,8 @@ String escapedMac;
|
||||
WebServer server(80);
|
||||
#else
|
||||
ESP8266WebServer server(80);
|
||||
ESP8266HTTPUpdateServer httpUpdater; //only for ESP8266
|
||||
#endif
|
||||
ESP8266HTTPUpdateServer httpUpdater;
|
||||
WiFiUDP notifierUdp;
|
||||
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!";
|
||||
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, [](){
|
||||
String info = "hard-coded build info:\r\n\n";
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
@ -166,6 +169,7 @@ void wledInit()
|
||||
#endif
|
||||
server.send(200, "text/plain", info);
|
||||
});
|
||||
//if OTA is allowed
|
||||
if (!otaLock){
|
||||
server.on("/edit", HTTP_GET, [](){
|
||||
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("/cleareeprom", HTTP_GET, clearEEPROM);
|
||||
//init ota page
|
||||
#ifndef ARDUINO_ARCH_ESP32
|
||||
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
|
||||
ArduinoOTA.onStart([]() {
|
||||
#ifndef ARDUINO_ARCH_ESP32
|
||||
wifi_set_sleep_type(NONE_SLEEP_T);
|
||||
#endif
|
||||
DEBUG_PRINTLN("Start ArduinoOTA");
|
||||
});
|
||||
ArduinoOTA.begin();
|
||||
} else
|
||||
{
|
||||
@ -233,7 +237,7 @@ void wledInit()
|
||||
strip.setBrightness(255);
|
||||
strip.start();
|
||||
|
||||
|
||||
pinMode(buttonPin, INPUT_PULLUP);
|
||||
#ifdef CRONIXIE
|
||||
strip.driverModeCronixie(true);
|
||||
strip.setCronixieBacklight(cronixieBacklight);
|
||||
@ -241,11 +245,18 @@ void wledInit()
|
||||
#endif
|
||||
if (bootPreset>0) applyPreset(bootPreset, turnOnAtBoot, true, true);
|
||||
colorUpdated(0);
|
||||
pinMode(buttonPin, INPUT_PULLUP);
|
||||
if(digitalRead(buttonPin) == LOW) buttonEnabled = false; //disable button if it is "pressed" unintentionally
|
||||
}
|
||||
|
||||
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);
|
||||
apssid = save;
|
||||
}
|
||||
|
||||
void initCon()
|
||||
@ -261,15 +272,8 @@ void initCon()
|
||||
{
|
||||
WiFi.disconnect();
|
||||
DEBUG_PRINTLN("Can't connect. Opening AP...");
|
||||
String save = apssid;
|
||||
onlyAP = true;
|
||||
#ifdef CRONIXIE
|
||||
if (apssid.length() <1) apssid = "CRONIXIE-AP";
|
||||
#else
|
||||
if (apssid.length() <1) apssid = "WLED-AP";
|
||||
#endif
|
||||
initAP();
|
||||
apssid = save;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ void handleButton()
|
||||
{
|
||||
if (digitalRead(buttonPin) == LOW && !buttonPressedBefore)
|
||||
{
|
||||
buttonPressedTime = millis();
|
||||
buttonPressedBefore = true;
|
||||
if (buttonMacro == 255)
|
||||
{
|
||||
@ -29,6 +30,7 @@ void handleButton()
|
||||
delay(15); //debounce
|
||||
if (digitalRead(buttonPin) == HIGH)
|
||||
{
|
||||
if (millis() - buttonPressedTime > 7000) initAP();
|
||||
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