Implement basic web server
This commit is contained in:
@@ -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; }
|
||||
|
||||
|
@@ -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; }
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -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;
|
||||
};
|
||||
}
|
||||
|
@@ -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; }
|
||||
|
||||
|
@@ -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
135
src/webserver.h
Normal 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();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user