Implement basic web server

This commit is contained in:
2020-05-22 23:53:30 +02:00
parent 2d5b1a5c9d
commit 2ee7d5b531
8 changed files with 169 additions and 0 deletions

View File

@@ -14,6 +14,9 @@ class ChangeValueDisplayInterface : public Display, public virtual TextInterface
public:
void initScreen() override;
TextInterface *asTextInterface() override { return this; }
const TextInterface *asTextInterface() const override { return this; }
ChangeValueDisplayInterface *asChangeValueDisplayInterface() override { return this; }
const ChangeValueDisplayInterface *asChangeValueDisplayInterface() const override { return this; }

View File

@@ -3,6 +3,7 @@
#include <WString.h>
namespace {
class TextInterface;
class MenuDisplay;
class ChangeValueDisplayInterface;
}
@@ -21,6 +22,9 @@ public:
virtual void rotate(int offset) {}
virtual void button() {}
virtual TextInterface *asTextInterface() { return nullptr; }
virtual const TextInterface *asTextInterface() const { return nullptr; }
virtual MenuDisplay *asMenuDisplay() { return nullptr; }
virtual const MenuDisplay *asMenuDisplay() const { return nullptr; }

View File

@@ -36,6 +36,13 @@ public:
callback(m_backItem);
}
void runForEveryMenuItem(std::function<void(const MenuItem&)> &&callback) const override
{
for (auto &item : vec)
callback(item);
callback(m_backItem);
}
private:
makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<WifiSettingsMenu>, StaticMenuItemIcon<&icons::back>> m_backItem;

View File

@@ -18,6 +18,7 @@
#include "statistics.h"
#include "actions/bluetoothbeginmasteraction.h"
#include "actions/bluetoothconnectbmsaction.h"
#include "webserver.h"
namespace {
ModeInterface *lastMode{};
@@ -84,6 +85,8 @@ void setup()
initOta();
initWebserver();
readPotis();
if (gas > 200.f || brems > 200.f)
@@ -159,5 +162,7 @@ void loop()
handleOta();
handleWebserver();
bms::update();
}

View File

@@ -9,5 +9,6 @@ class MenuDefinitionInterface
{
public:
virtual void runForEveryMenuItem(std::function<void(MenuItem&)> &&callback) = 0;
virtual void runForEveryMenuItem(std::function<void(const MenuItem&)> &&callback) const = 0;
};
}

View File

@@ -26,6 +26,9 @@ public:
virtual void itemPressed(int index);
TextInterface *asTextInterface() override { return this; }
const TextInterface *asTextInterface() const override { return this; }
MenuDisplay *asMenuDisplay() override { return this; }
const MenuDisplay *asMenuDisplay() const override { return this; }

View File

@@ -15,6 +15,11 @@ public:
callback(item);
}
void runForEveryMenuItem(std::function<void(const MenuItem&)> &&callback) const override
{
callback(item);
}
private:
T item;
};
@@ -31,6 +36,12 @@ public:
Base::runForEveryMenuItem(std::move(callback));
}
void runForEveryMenuItem(std::function<void(const MenuItem&)> &&callback) const override
{
callback(item);
Base::runForEveryMenuItem(std::move(callback));
}
private:
T item;
};

135
src/webserver.h Normal file
View File

@@ -0,0 +1,135 @@
#pragma once
#include <WebServer.h>
#include "screens.h"
namespace {
WebServer webServer{80};
class HtmlTag {
public:
HtmlTag(const String &tagName, String &content) :
m_tagName{tagName},
m_content{content}
{
content += "<" + tagName + ">";
}
~HtmlTag()
{
m_content += "</" + m_tagName + ">";
}
private:
const String m_tagName;
String &m_content;
};
void initWebserver()
{
webServer.on("/", HTTP_GET, [](){
webServer.sendHeader("Connection", "close");
String content;
{
HtmlTag htmlTag{"html", content};
{
HtmlTag headTag{"head", content};
HtmlTag titleTag{"title", content};
content += "Bobbycar remote";
}
{
HtmlTag bodyTag{"body", content};
{
HtmlTag h1Tag{"h1", content};
content += "Bobbycar remote";
}
{
HtmlTag pTag{"p", content};
content += "<a href=\"/up\">Up</a> <a href=\"/down\">Down</a> <a href=\"/confirm\">Confirm</a>";
}
if (auto constCurrentDisplay = static_cast<const Display *>(currentDisplay))
{
if (const auto *textInterface = currentDisplay->asTextInterface())
{
HtmlTag h2Tag{"h2", content};
content += textInterface->text();
}
if (const auto *menuDisplay = currentDisplay->asMenuDisplay())
{
HtmlTag ulTag{"ul", content};
int i{0};
menuDisplay->runForEveryMenuItem([&,selectedIndex=menuDisplay->selectedIndex()](const MenuItem &menuItem){
content += "<li";
if (i == selectedIndex)
content += " style=\"border: 1px solid black;\"";
content += '>' + menuItem.text() + "</li>";
i++;
});
}
else if (const auto *changeValueDisplay = currentDisplay->asChangeValueDisplayInterface())
{
content += "<input type=\"number\" value=\"" + String{changeValueDisplay->shownValue()} + "\" />";
}
else
{
content += "No web control implemented for current display.";
}
}
else
{
content += "Currently no screen instantiated.";
}
}
}
webServer.send(200, "text/html", content);
});
webServer.on("/up", HTTP_GET, [](){
InputDispatcher::rotate(-1);
webServer.sendHeader("Connection", "close");
webServer.sendHeader("Location", "/");
webServer.send(302, "text/html", "ok");
});
webServer.on("/down", HTTP_GET, [](){
InputDispatcher::rotate(1);
webServer.sendHeader("Connection", "close");
webServer.sendHeader("Location", "/");
webServer.send(302, "text/html", "ok");
});
webServer.on("/confirm", HTTP_GET, [](){
InputDispatcher::button(true);
InputDispatcher::button(false);
webServer.sendHeader("Connection", "close");
webServer.sendHeader("Location", "/");
webServer.send(302, "text/html", "ok");
});
webServer.begin();
}
void handleWebserver()
{
webServer.handleClient();
}
}