Files
LedController/src/main.cpp
T

365 lines
12 KiB
C++
Raw Normal View History

2019-05-02 21:12:18 +02:00
#include <array>
#include <functional>
#include <Arduino.h>
2019-05-04 08:28:44 +02:00
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
2019-05-02 21:12:18 +02:00
2019-05-04 08:28:44 +02:00
#include "ledcontroller.h"
constexpr auto WIFI_SSID = "McDonalds Free WiFi 2.4GHz";
constexpr auto WIFI_PASSWD = "Passwort_123";
LedController ledController;
ESP8266WebServer server(80);
2019-05-19 21:37:33 +02:00
WiFiClient m_client;
2019-05-04 08:28:44 +02:00
2019-05-04 11:45:24 +02:00
bool power = true;
2019-05-04 08:28:44 +02:00
bool rotatePattern = true;
2019-05-02 21:12:18 +02:00
void setup()
{
2019-05-04 12:51:55 +02:00
Serial.begin(115200);
Serial.setDebugOutput(true);
2019-05-04 08:28:44 +02:00
WiFi.begin(WIFI_SSID, WIFI_PASSWD);
2019-05-02 21:12:18 +02:00
2019-05-04 11:28:57 +02:00
server.on("/", HTTP_GET, []()
{
server.sendHeader("Connection", "close");
server.send(200, "text/html",
"<!doctype html>"
"<html lang=\"en\">"
"<head>"
"<!-- Required meta tags -->"
"<meta charset=\"utf-8\">"
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">"
"<!-- Bootstrap CSS -->"
"<link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css\" integrity=\"sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T\" crossorigin=\"anonymous\">"
"<style>"
".hidden {"
"display: none;"
"}"
"</style>"
2019-05-04 12:51:55 +02:00
"<title>LED-Control</title>"
2019-05-04 11:28:57 +02:00
"</head>"
"<body>"
"<div class=\"container\">"
2019-05-04 12:51:55 +02:00
"<h1>LED-Control</h1>"
2019-05-04 11:28:57 +02:00
"<p>"
2019-05-04 11:45:24 +02:00
"<a href=\"setPower?val=true\" id=\"enablePower\" class=\"softLink\">Turn LEDs on</a> "
"<a href=\"setPower?val=false\" id=\"disablePower\" class=\"softLink\">Turn LEDs off</a> "
"<a href=\"nextPattern\" id=\"nextPattern\" class=\"softLink\">Next pattern</a> "
"<a href=\"setPatternRotate?val=true\" id=\"enableRotate\" class=\"softLink\">Enable automatic pattern rotate</a> "
2019-05-04 11:28:57 +02:00
"<a href=\"setPatternRotate?val=false\" id=\"disableRotate\" class=\"softLink\">Disable automatic pattern rotate</a>"
"</p>"
"<select id=\"patternSelect\"></select>"
"<input type=\"range\" min=\"0\" max=\"255\" id=\"brightness\" />"
"</div>"
"<script src=\"https://code.jquery.com/jquery-3.3.1.slim.min.js\" integrity=\"sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo\" crossorigin=\"anonymous\"></script>"
"<script>"
"jQuery(document).ready(function($){"
"$('.softLink').click(function(){"
"var xhr = new XMLHttpRequest();"
"xhr.open('GET', this.getAttribute('href'));"
"xhr.send();"
"return false;"
"});"
"$('#patternSelect').change(function(){"
"var xhr = new XMLHttpRequest();"
"xhr.open('GET', 'setPattern?val=' + this.selectedIndex);"
"xhr.send();"
"});"
"$('#brightness').change(function(){"
"var xhr = new XMLHttpRequest();"
"xhr.open('GET', 'setBrightness?val=' + this.value);"
"xhr.send();"
"});"
"var refreshStatus = function() {"
"var xhr = new XMLHttpRequest();"
"xhr.open('GET', 'status');"
"xhr.onload = function() {"
"var parsed = JSON.parse(xhr.responseText);"
2019-05-04 11:45:24 +02:00
"function setHidden(element, hidden) {"
"if (hidden) {"
"element.addClass('hidden');"
"} else {"
"element.removeClass('hidden');"
"}"
2019-05-04 11:28:57 +02:00
"}"
2019-05-04 11:45:24 +02:00
"setHidden($('#enablePower'), parsed.power);"
"setHidden($('#disablePower'), !parsed.power);"
"setHidden($('#nextPattern'), !parsed.power);"
"setHidden($('#enableRotate'), !parsed.power || parsed.autoRotate);"
"setHidden($('#disableRotate'), !parsed.power || !parsed.autoRotate);"
"setHidden($('#patternSelect'), !parsed.power);"
"setHidden($('#brightness'), !parsed.power);"
2019-05-04 11:28:57 +02:00
"var select = $('#patternSelect');"
"select.empty();"
"select.attr('size', parsed.patterns.length);"
"for (var pattern of parsed.patterns) {"
"select.append($('<option>')"
".text(pattern.name)"
".attr('selected', pattern.selected)"
");"
"}"
"$('#brightness').val(parsed.brightness)"
"};"
"xhr.send();"
"};"
"refreshStatus();"
"setInterval(refreshStatus, 1000);"
"});"
"</script>"
"</body>"
"</html>"
);
});
2019-05-04 12:51:55 +02:00
server.on("/update", HTTP_GET, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/html",
2019-05-19 21:37:33 +02:00
"<form method=\"POST\" enctype=\"multipart/form-data\">"
2019-05-04 12:51:55 +02:00
"<input type=\"file\" name=\"update\" />"
"<button type=\"submit\">Install</button>"
"</form>");
});
server.on("/update", HTTP_POST, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
ESP.restart();
}, []() {
HTTPUpload& upload = server.upload();
if (upload.status == UPLOAD_FILE_START) {
Serial.setDebugOutput(true);
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
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_WRITE) {
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_END) {
if (Update.end(true)) { //true to set the size to the current progress
Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
} else {
Update.printError(Serial);
}
Serial.setDebugOutput(false);
}
yield();
});
2019-05-19 21:37:33 +02:00
server.on("/reboot", HTTP_GET, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/html",
"<form method=\"POST\">"
"<button type=\"submit\">Perform reboot</button>"
"</form>");
});
server.on("/reboot", HTTP_POST, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/plain", "OK");
ESP.restart();
});
2019-05-04 11:28:57 +02:00
server.on("/status", HTTP_GET, []()
{
server.sendHeader("Connection", "close");
server.sendHeader("Access-Control-Allow-Origin", "*");
String str = "{";
str += "\"patterns\":[";
bool first = true;
for (auto pattern : ledController.patterns)
{
if (first)
first = false;
else
str += ',';
str += "{\"name\":\"";
str += pattern->name();
str += "\",\"selected\":";
str += (*ledController.iter) == pattern ? "true" : "false";
str += '}';
}
str += "],";
2019-05-04 11:45:24 +02:00
str += "\"power\":";
str += power ? "true" : "false";
str += ",";
2019-05-04 11:28:57 +02:00
str += "\"autoRotate\":";
str += rotatePattern ? "true" : "false";
str += ",";
str += "\"brightness\":";
str += String(int(FastLED.getBrightness()));
str += "}";
server.send(200, "text/json", str.c_str());
});
server.on("/nextPattern", HTTP_GET, []()
{
ledController.nextPattern();
server.send(200, "text/html", "ok");
});
server.on("/setPattern", HTTP_GET, []()
{
const String *val = nullptr;
for (int i = 0; i < server.args(); i++)
if (server.argName(i) == "val")
val = &server.arg(i);
if (!val)
{
server.send(400, "text/html", "val missing");
return;
}
const auto index = atoi(val->c_str());
if (index < 0 || index >= ledController.patterns.size())
{
server.send(400, "text/html", "out of range");
return;
}
ledController.iter = ledController.patterns.begin() + index;
server.send(200, "text/html", "ok");
});
2019-05-04 11:45:24 +02:00
server.on("/setPower", HTTP_GET, []()
{
const String *val = nullptr;
for (int i = 0; i < server.args(); i++)
if (server.argName(i) == "val")
val = &server.arg(i);
if (!val)
{
server.send(400, "text/html", "val missing");
return;
}
if (*val != "true" && *val != "false")
{
server.send(400, "text/html", "invalid val");
return;
}
power = *val == "true";
server.send(200, "text/html", "ok");
});
2019-05-04 11:28:57 +02:00
server.on("/setPatternRotate", HTTP_GET, []()
{
const String *val = nullptr;
for (int i = 0; i < server.args(); i++)
if (server.argName(i) == "val")
val = &server.arg(i);
if (!val)
{
server.send(400, "text/html", "val missing");
return;
}
if (*val != "true" && *val != "false")
{
server.send(400, "text/html", "invalid val");
return;
}
rotatePattern = *val == "true";
server.send(200, "text/html", "ok");
});
server.on("/setBrightness", HTTP_GET, []()
{
const String *val = nullptr;
for (int i = 0; i < server.args(); i++)
if (server.argName(i) == "val")
val = &server.arg(i);
if (!val)
{
server.send(400, "text/html", "val missing");
return;
}
const auto brightness = atoi(val->c_str());
if (brightness < 0 || brightness > 255)
{
server.send(400, "text/html", "out of range");
return;
}
FastLED.setBrightness(brightness);
server.send(200, "text/html", "ok");
});
2019-05-02 21:12:18 +02:00
2019-05-04 08:28:44 +02:00
server.begin();
2019-05-02 21:12:18 +02:00
}
void loop()
{
EVERY_N_MILLISECONDS(20)
{
2019-05-04 11:45:24 +02:00
if (power)
ledController.run();
else
ledController.poweroff();
FastLED.show();
2019-05-02 21:12:18 +02:00
}
2019-05-04 11:45:24 +02:00
if (power && rotatePattern)
2019-05-02 21:12:18 +02:00
{
EVERY_N_SECONDS(10)
{
2019-05-04 11:28:57 +02:00
ledController.nextPattern();
2019-05-02 21:12:18 +02:00
}
}
2019-05-04 08:28:44 +02:00
server.handleClient();
2019-05-02 21:12:18 +02:00
}