renderbug-cpp/firmware/WebTelemetry.cpp

158 lines
6.4 KiB
C++
Raw Normal View History

2021-03-28 01:19:55 +00:00
#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();
}
}
};