158 lines
6.4 KiB
C++
158 lines
6.4 KiB
C++
|
#include "WebDuino/WebDuino.h"
|
||
|
#include "Figments/Figments.h"
|
||
|
#include "Figments/Input.h"
|
||
|
#include "colors.h"
|
||
|
#include "Sequencer.h"
|
||
|
|
||
|
class WebTelemetry : public Task {
|
||
|
private:
|
||
|
TCPServer m_server;
|
||
|
TCPClient m_client;
|
||
|
Sequencer& m_sequencer;
|
||
|
|
||
|
void onConnected() {
|
||
|
m_server.begin();
|
||
|
Log.info("HTTP server started on %s:80", WiFi.localIP().toString().c_str());
|
||
|
}
|
||
|
|
||
|
void redirectToRoot() {
|
||
|
m_server.write("HTTP/1.1 303 Redirect\n");
|
||
|
m_server.write("Location: /\n");
|
||
|
m_server.write("Connection: close\n\n");
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
WebTelemetry(Sequencer& sequencer) : Task("WebTelemetry"), m_server(80), m_sequencer(sequencer) {
|
||
|
}
|
||
|
|
||
|
void handleEvent(const InputEvent &evt) {
|
||
|
if (evt.intent == InputEvent::NetworkStatus) {
|
||
|
onConnected();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void loop() override {
|
||
|
static String taskName;
|
||
|
if (m_client.connected()) {
|
||
|
if (m_client.available()) {
|
||
|
MainLoop::instance()->dispatch(InputEvent::NetworkActivity);
|
||
|
String requestLine = m_client.readStringUntil('\n');
|
||
|
Log.info("%s %s", m_client.remoteIP().toString().c_str(), requestLine.c_str());
|
||
|
if (requestLine.startsWith("GET")) {
|
||
|
int httpVersionIdx = requestLine.lastIndexOf(" ");
|
||
|
String uri = requestLine.substring(4, httpVersionIdx);
|
||
|
if (uri.equals("/")) {
|
||
|
m_server.write("HTTP/1.1 200 Renderbug is here!\n");
|
||
|
m_server.write("Connection: close\n\n");
|
||
|
m_server.write("<!DOCTYPE HTML><html><body>");
|
||
|
m_server.write("<p>Scenes</p><table>");
|
||
|
auto curScene = m_sequencer.currentSceneName();
|
||
|
for(auto scene : m_sequencer.scenes()) {
|
||
|
bool isEnabled = strcmp(curScene, scene.name) == 0;
|
||
|
m_server.write("<tr><td>");
|
||
|
if (isEnabled) {
|
||
|
m_server.write("<strong>");
|
||
|
}
|
||
|
m_server.write(scene.name);
|
||
|
if (isEnabled) {
|
||
|
m_server.write("</strong>");
|
||
|
}
|
||
|
m_server.write("</td><td><ul>");
|
||
|
for(auto patternName : scene.patterns) {
|
||
|
m_server.write("<li>");
|
||
|
m_server.write(patternName);
|
||
|
m_server.write("</li>");
|
||
|
}
|
||
|
m_server.write("</ul></td></tr>");
|
||
|
}
|
||
|
m_server.write("</table>");
|
||
|
m_server.write("<form><button name=\"pattern\" value=\"prev\">Previous pattern</button><button name=\"pattern\" value=\"next\">Next pattern</button></form>");
|
||
|
m_server.write("<form><select name=\"color\">");
|
||
|
const ColorInfo* colors = allColors();
|
||
|
for(int i = 0; colors[i].name != 0;i++) {
|
||
|
m_server.write("<option>");
|
||
|
m_server.write(colors[i].name);
|
||
|
m_server.write("</option>");
|
||
|
}
|
||
|
m_server.write("</select>");
|
||
|
m_server.write("<button>Set Color</button>");
|
||
|
m_server.write("</form>");
|
||
|
m_server.write("<p>Tasks</p><table>");
|
||
|
auto sched = MainLoop::instance()->scheduler;
|
||
|
for(auto task : sched.tasks) {
|
||
|
bool isFigment = task->isFigment();
|
||
|
|
||
|
m_server.write("<tr><td>");
|
||
|
if (isFigment) {
|
||
|
m_server.write("<strong>");
|
||
|
}
|
||
|
m_server.write(task->name);
|
||
|
if (isFigment) {
|
||
|
m_server.write("</strong>");
|
||
|
}
|
||
|
m_server.write("</td><td>");
|
||
|
if (task->state == Task::Running) {
|
||
|
m_server.write("Running");
|
||
|
} else {
|
||
|
m_server.write("Paused");
|
||
|
}
|
||
|
m_server.write("</td><td>");
|
||
|
m_server.write("<a href=\"/?stop=");
|
||
|
m_server.write(task->name);
|
||
|
m_server.write("\">Stop</a></td><td>");
|
||
|
m_server.write("<a href=\"/?start=");
|
||
|
m_server.write(task->name);
|
||
|
m_server.write("\">Start</a></td></tr>");
|
||
|
}
|
||
|
m_server.write("</table>");
|
||
|
m_server.write("<a href='/reboot'>Reboot Renderbug</a>");
|
||
|
m_server.write("<a href='/save'>Save configuration</a>");
|
||
|
} else if (uri.startsWith("/save")) {
|
||
|
MainLoop::instance()->dispatch(InputEvent::SaveConfigurationRequest);
|
||
|
redirectToRoot();
|
||
|
} else if (uri.startsWith("/?color=")) {
|
||
|
int varStart = uri.indexOf("=");
|
||
|
String colorName = uri.substring(varStart + 1);
|
||
|
colorName.replace('+', ' ');
|
||
|
colorName.replace("%20", " ");
|
||
|
ColorInfo nextColor = colorForName(colorName);
|
||
|
MainLoop::instance()->dispatch(InputEvent{InputEvent::SetColor, nextColor.rgb});
|
||
|
redirectToRoot();
|
||
|
} else if (uri.startsWith("/?start=")) {
|
||
|
int varStart = uri.indexOf("=");
|
||
|
taskName = uri.substring(varStart + 1);
|
||
|
MainLoop::instance()->dispatch(InputEvent{InputEvent::StartThing, taskName.c_str()});
|
||
|
redirectToRoot();
|
||
|
} else if (uri.startsWith("/?stop=")) {
|
||
|
int varStart = uri.indexOf("=");
|
||
|
taskName = uri.substring(varStart + 1);
|
||
|
MainLoop::instance()->dispatch(InputEvent{InputEvent::StopThing, taskName.c_str()});
|
||
|
redirectToRoot();
|
||
|
} else if (uri.equals("/?pattern=prev")) {
|
||
|
redirectToRoot();
|
||
|
MainLoop::instance()->dispatch(InputEvent::PreviousPattern);
|
||
|
} else if (uri.equals("/?pattern=next")) {
|
||
|
redirectToRoot();
|
||
|
MainLoop::instance()->dispatch(InputEvent::NextPattern);
|
||
|
} else if (uri.equals("/reboot")) {
|
||
|
m_server.write("HTTP/1.1 200 Ok\n");
|
||
|
m_server.write("Connection: close\n\n");
|
||
|
m_server.write("Rebooting!");
|
||
|
} else {
|
||
|
m_server.write("HTTP/1.1 404 Not found\n");
|
||
|
m_server.write("Connection: close\n\n");
|
||
|
}
|
||
|
} else {
|
||
|
m_server.write("HTTP/1.1 501 Not Implemented\n");
|
||
|
m_server.write("Connection: close\n\n");
|
||
|
}
|
||
|
}
|
||
|
m_client.stop();
|
||
|
} else {
|
||
|
m_client = m_server.available();
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|