Implement basic web server
This commit is contained in:
@@ -14,6 +14,9 @@ class ChangeValueDisplayInterface : public Display, public virtual TextInterface
|
|||||||
public:
|
public:
|
||||||
void initScreen() override;
|
void initScreen() override;
|
||||||
|
|
||||||
|
TextInterface *asTextInterface() override { return this; }
|
||||||
|
const TextInterface *asTextInterface() const override { return this; }
|
||||||
|
|
||||||
ChangeValueDisplayInterface *asChangeValueDisplayInterface() override { return this; }
|
ChangeValueDisplayInterface *asChangeValueDisplayInterface() override { return this; }
|
||||||
const ChangeValueDisplayInterface *asChangeValueDisplayInterface() const override { return this; }
|
const ChangeValueDisplayInterface *asChangeValueDisplayInterface() const override { return this; }
|
||||||
|
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
#include <WString.h>
|
#include <WString.h>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
class TextInterface;
|
||||||
class MenuDisplay;
|
class MenuDisplay;
|
||||||
class ChangeValueDisplayInterface;
|
class ChangeValueDisplayInterface;
|
||||||
}
|
}
|
||||||
@@ -21,6 +22,9 @@ public:
|
|||||||
virtual void rotate(int offset) {}
|
virtual void rotate(int offset) {}
|
||||||
virtual void button() {}
|
virtual void button() {}
|
||||||
|
|
||||||
|
virtual TextInterface *asTextInterface() { return nullptr; }
|
||||||
|
virtual const TextInterface *asTextInterface() const { return nullptr; }
|
||||||
|
|
||||||
virtual MenuDisplay *asMenuDisplay() { return nullptr; }
|
virtual MenuDisplay *asMenuDisplay() { return nullptr; }
|
||||||
virtual const MenuDisplay *asMenuDisplay() const { return nullptr; }
|
virtual const MenuDisplay *asMenuDisplay() const { return nullptr; }
|
||||||
|
|
||||||
|
@@ -36,6 +36,13 @@ public:
|
|||||||
callback(m_backItem);
|
callback(m_backItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void runForEveryMenuItem(std::function<void(const MenuItem&)> &&callback) const override
|
||||||
|
{
|
||||||
|
for (auto &item : vec)
|
||||||
|
callback(item);
|
||||||
|
callback(m_backItem);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<WifiSettingsMenu>, StaticMenuItemIcon<&icons::back>> m_backItem;
|
makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<WifiSettingsMenu>, StaticMenuItemIcon<&icons::back>> m_backItem;
|
||||||
|
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
#include "statistics.h"
|
#include "statistics.h"
|
||||||
#include "actions/bluetoothbeginmasteraction.h"
|
#include "actions/bluetoothbeginmasteraction.h"
|
||||||
#include "actions/bluetoothconnectbmsaction.h"
|
#include "actions/bluetoothconnectbmsaction.h"
|
||||||
|
#include "webserver.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
ModeInterface *lastMode{};
|
ModeInterface *lastMode{};
|
||||||
@@ -84,6 +85,8 @@ void setup()
|
|||||||
|
|
||||||
initOta();
|
initOta();
|
||||||
|
|
||||||
|
initWebserver();
|
||||||
|
|
||||||
readPotis();
|
readPotis();
|
||||||
|
|
||||||
if (gas > 200.f || brems > 200.f)
|
if (gas > 200.f || brems > 200.f)
|
||||||
@@ -159,5 +162,7 @@ void loop()
|
|||||||
|
|
||||||
handleOta();
|
handleOta();
|
||||||
|
|
||||||
|
handleWebserver();
|
||||||
|
|
||||||
bms::update();
|
bms::update();
|
||||||
}
|
}
|
||||||
|
@@ -9,5 +9,6 @@ class MenuDefinitionInterface
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void runForEveryMenuItem(std::function<void(MenuItem&)> &&callback) = 0;
|
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);
|
virtual void itemPressed(int index);
|
||||||
|
|
||||||
|
TextInterface *asTextInterface() override { return this; }
|
||||||
|
const TextInterface *asTextInterface() const override { return this; }
|
||||||
|
|
||||||
MenuDisplay *asMenuDisplay() override { return this; }
|
MenuDisplay *asMenuDisplay() override { return this; }
|
||||||
const MenuDisplay *asMenuDisplay() const override { return this; }
|
const MenuDisplay *asMenuDisplay() const override { return this; }
|
||||||
|
|
||||||
|
@@ -15,6 +15,11 @@ public:
|
|||||||
callback(item);
|
callback(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void runForEveryMenuItem(std::function<void(const MenuItem&)> &&callback) const override
|
||||||
|
{
|
||||||
|
callback(item);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T item;
|
T item;
|
||||||
};
|
};
|
||||||
@@ -31,6 +36,12 @@ public:
|
|||||||
Base::runForEveryMenuItem(std::move(callback));
|
Base::runForEveryMenuItem(std::move(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void runForEveryMenuItem(std::function<void(const MenuItem&)> &&callback) const override
|
||||||
|
{
|
||||||
|
callback(item);
|
||||||
|
Base::runForEveryMenuItem(std::move(callback));
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T item;
|
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