String inputs in webserver implemented
This commit is contained in:
Submodule components/bobbycar-protocol updated: a331746ede...9e256acdaa
@ -1,23 +1,39 @@
|
||||
#include "bobbybuttons.h"
|
||||
|
||||
// local includes
|
||||
#include "newsettings.h"
|
||||
|
||||
[[nodiscard]] std::optional<espgui::Button> translateRawButton(uint8_t button)
|
||||
{
|
||||
switch (button)
|
||||
{
|
||||
// Invalid
|
||||
if (button == INPUT_MAPPING_NONE)
|
||||
return std::nullopt;
|
||||
|
||||
using espgui::Button;
|
||||
case 0: return Button::Left;
|
||||
case 1: return Button::Right;
|
||||
case 2: return Button::Up;
|
||||
case 3: return Button::Down;
|
||||
case 4: return Button(BobbyButton::Profile0);
|
||||
case 5: return Button(BobbyButton::Profile1);
|
||||
case 6: return Button(BobbyButton::Profile2);
|
||||
case 7: return Button(BobbyButton::Profile3);
|
||||
case 8: return Button(BobbyButton::Left2);
|
||||
case 9: return Button(BobbyButton::Right2);
|
||||
case 10: return Button(BobbyButton::Up2);
|
||||
case 11: return Button(BobbyButton::Down2);
|
||||
}
|
||||
if (configs.dpadMappingLeft.value == button)
|
||||
return Button::Left;
|
||||
if (configs.dpadMappingRight.value == button)
|
||||
return Button::Right;
|
||||
if (configs.dpadMappingUp.value == button)
|
||||
return Button::Up;
|
||||
if (configs.dpadMappingDown.value == button)
|
||||
return Button::Down;
|
||||
if (configs.dpadMappingProfile0.value == button)
|
||||
return Button(BobbyButton::Profile0);
|
||||
if (configs.dpadMappingProfile1.value == button)
|
||||
return Button(BobbyButton::Profile1);
|
||||
if (configs.dpadMappingProfile2.value == button)
|
||||
return Button(BobbyButton::Profile2);
|
||||
if (configs.dpadMappingProfile3.value == button)
|
||||
return Button(BobbyButton::Profile3);
|
||||
if (configs.dpadMappingLeft2.value == button)
|
||||
return Button(BobbyButton::Left2);
|
||||
if (configs.dpadMappingRight2.value == button)
|
||||
return Button(BobbyButton::Right2);
|
||||
if (configs.dpadMappingUp2.value == button)
|
||||
return Button(BobbyButton::Up2);
|
||||
if (configs.dpadMappingDown2.value == button)
|
||||
return Button(BobbyButton::Down2);
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
59
main/can.cpp
59
main/can.cpp
@ -13,12 +13,13 @@
|
||||
// 3rdparty lib includes
|
||||
#include <espchrono.h>
|
||||
#include <tickchrono.h>
|
||||
#include <screenmanager.h>
|
||||
|
||||
// local includes
|
||||
#include "bobbycar-can.h"
|
||||
#include "globals.h"
|
||||
#include "buttons.h"
|
||||
#include "newsettings.h"
|
||||
#include "bobbybuttons.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
@ -29,7 +30,6 @@ constexpr const char * const TAG = "BOBBYCAN";
|
||||
|
||||
std::optional<int16_t> can_gas, can_brems;
|
||||
espchrono::millis_clock::time_point last_can_gas{}, last_can_brems{};
|
||||
CanButtonsState lastButtonsState;
|
||||
|
||||
void initCan()
|
||||
{
|
||||
@ -160,47 +160,22 @@ bool parseBoardcomputerCanMessage(const twai_message_t &message)
|
||||
switch (message.identifier)
|
||||
{
|
||||
using namespace bobbycar::protocol::can;
|
||||
case Boardcomputer::Command::ButtonPress:
|
||||
{
|
||||
const auto canButtonBits = *((uint16_t*)message.data);
|
||||
CanButtonsState newState {
|
||||
.up = bool(canButtonBits & Boardcomputer::ButtonUp),
|
||||
.down = bool(canButtonBits & Boardcomputer::ButtonDown),
|
||||
.confirm = bool(canButtonBits & Boardcomputer::ButtonConfirm),
|
||||
.back = bool(canButtonBits & Boardcomputer::ButtonBack),
|
||||
.profile0 = bool(canButtonBits & Boardcomputer::ButtonProfile0),
|
||||
.profile1 = bool(canButtonBits & Boardcomputer::ButtonProfile1),
|
||||
.profile2 = bool(canButtonBits & Boardcomputer::ButtonProfile2),
|
||||
.profile3 = bool(canButtonBits & Boardcomputer::ButtonProfile3),
|
||||
};
|
||||
|
||||
if (lastButtonsState.up != newState.up)
|
||||
InputDispatcher::upButton(newState.up);
|
||||
|
||||
if (lastButtonsState.down != newState.down)
|
||||
InputDispatcher::downButton(newState.down);
|
||||
|
||||
if (lastButtonsState.confirm != newState.confirm)
|
||||
InputDispatcher::confirmButton(newState.confirm);
|
||||
|
||||
if (lastButtonsState.back != newState.back)
|
||||
InputDispatcher::backButton(newState.back);
|
||||
|
||||
if (lastButtonsState.profile0 != newState.profile0)
|
||||
InputDispatcher::profileButton(0, newState.profile0);
|
||||
|
||||
if (lastButtonsState.profile1 != newState.profile1)
|
||||
InputDispatcher::profileButton(1, newState.profile1);
|
||||
|
||||
if (lastButtonsState.profile2 != newState.profile2)
|
||||
InputDispatcher::profileButton(2, newState.profile2);
|
||||
|
||||
if (lastButtonsState.profile3 != newState.profile3)
|
||||
InputDispatcher::profileButton(3, newState.profile3);
|
||||
|
||||
lastButtonsState = newState;
|
||||
case Boardcomputer::Command::RawButtonPressed:
|
||||
if (espgui::currentDisplay)
|
||||
espgui::currentDisplay->rawButtonPressed(*((const uint8_t*)message.data));
|
||||
break;
|
||||
case Boardcomputer::Command::RawButtonReleased:
|
||||
if (espgui::currentDisplay)
|
||||
espgui::currentDisplay->rawButtonReleased(*((const uint8_t*)message.data));
|
||||
break;
|
||||
case Boardcomputer::Command::ButtonPressed:
|
||||
if (espgui::currentDisplay)
|
||||
espgui::currentDisplay->rawButtonPressed(espgui::Button(*((const uint8_t*)message.data)));
|
||||
break;
|
||||
case Boardcomputer::Command::ButtonReleased:
|
||||
if (espgui::currentDisplay)
|
||||
espgui::currentDisplay->rawButtonPressed(espgui::Button(*((const uint8_t*)message.data)));
|
||||
break;
|
||||
}
|
||||
case Boardcomputer::Command::RawGas:
|
||||
can_gas = *((int16_t*)message.data);
|
||||
last_can_gas = espchrono::millis_clock::now();
|
||||
|
@ -10,12 +10,12 @@
|
||||
// 3rdparty lib includes
|
||||
#include <tftinstance.h>
|
||||
#include <esp32-hal-gpio.h>
|
||||
#include <screenmanager.h>
|
||||
|
||||
// local includes
|
||||
#include "globals.h"
|
||||
#include "utils.h"
|
||||
#include "screens.h"
|
||||
#include "buttons.h"
|
||||
#include "bobbybuttons.h"
|
||||
|
||||
namespace {
|
||||
constexpr const char * const TAG = "DEBUG";
|
||||
@ -54,83 +54,127 @@ void handleDebugInput()
|
||||
|
||||
for (char c : std::string_view{data, length})
|
||||
{
|
||||
switch (c)
|
||||
if (consoleControlCharsReceived < 2)
|
||||
{
|
||||
case 'i':
|
||||
case 'I':
|
||||
espgui::tft.init();
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
{
|
||||
const auto firstPower = controllers.front.command.poweroff;
|
||||
for (Controller &controller : controllers)
|
||||
controller.command.poweroff = !firstPower;
|
||||
break;
|
||||
switch (c)
|
||||
{
|
||||
case '\x1b':
|
||||
if (consoleControlCharsReceived == 0)
|
||||
consoleControlCharsReceived = 1;
|
||||
else
|
||||
consoleControlCharsReceived = 0;
|
||||
break;
|
||||
case '\x5b':
|
||||
if (consoleControlCharsReceived == 1)
|
||||
consoleControlCharsReceived = 2;
|
||||
else
|
||||
consoleControlCharsReceived = 0;
|
||||
break;
|
||||
case 'i':
|
||||
case 'I':
|
||||
consoleControlCharsReceived = 0;
|
||||
espgui::tft.init();
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
{
|
||||
consoleControlCharsReceived = 0;
|
||||
const auto firstPower = controllers.front.command.poweroff;
|
||||
for (Controller &controller : controllers)
|
||||
controller.command.poweroff = !firstPower;
|
||||
break;
|
||||
}
|
||||
case 'l':
|
||||
case 'L':
|
||||
{
|
||||
consoleControlCharsReceived = 0;
|
||||
const auto firstLed = controllers.front.command.led;
|
||||
for (Controller &controller : controllers)
|
||||
controller.command.led = !firstLed;
|
||||
break;
|
||||
}
|
||||
case 'r':
|
||||
case 'R':
|
||||
consoleControlCharsReceived = 0;
|
||||
loadSettings();
|
||||
break;
|
||||
case 's':
|
||||
case 'S':
|
||||
consoleControlCharsReceived = 0;
|
||||
saveSettings();
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
consoleControlCharsReceived = 0;
|
||||
for (Controller &controller : controllers)
|
||||
controller.command.buzzer.freq = c-'0';
|
||||
break;
|
||||
case 'z':
|
||||
case 'Z':
|
||||
consoleControlCharsReceived = 0;
|
||||
if (espgui::currentDisplay)
|
||||
{
|
||||
espgui::currentDisplay->buttonPressed(espgui::Button(BobbyButton::Left2));
|
||||
espgui::currentDisplay->buttonReleased(espgui::Button(BobbyButton::Left2));
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
case 'U':
|
||||
consoleControlCharsReceived = 0;
|
||||
if (espgui::currentDisplay)
|
||||
{
|
||||
espgui::currentDisplay->buttonPressed(espgui::Button(BobbyButton::Right2));
|
||||
espgui::currentDisplay->buttonReleased(espgui::Button(BobbyButton::Right2));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
consoleControlCharsReceived = 0;
|
||||
}
|
||||
}
|
||||
case 'l':
|
||||
case 'L':
|
||||
else
|
||||
{
|
||||
const auto firstLed = controllers.front.command.led;
|
||||
for (Controller &controller : controllers)
|
||||
controller.command.led = !firstLed;
|
||||
break;
|
||||
}
|
||||
case 'r':
|
||||
case 'R':
|
||||
loadSettings();
|
||||
break;
|
||||
case 's':
|
||||
case 'S':
|
||||
saveSettings();
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
for (Controller &controller : controllers)
|
||||
controller.command.buzzer.freq = c-'0';
|
||||
break;
|
||||
case 'A':
|
||||
InputDispatcher::rotate(-1);
|
||||
break;
|
||||
case 'B':
|
||||
InputDispatcher::rotate(1);
|
||||
break;
|
||||
case 'C':
|
||||
InputDispatcher::confirmButton(true);
|
||||
InputDispatcher::confirmButton(false);
|
||||
break;
|
||||
case 'D':
|
||||
InputDispatcher::backButton(true);
|
||||
InputDispatcher::backButton(false);
|
||||
break;
|
||||
case 'z':
|
||||
case 'Z':
|
||||
#ifndef LEDSTRIP_WRONG_DIRECTION
|
||||
InputDispatcher::blinkLeftButton(true);
|
||||
InputDispatcher::blinkLeftButton(false);
|
||||
#else
|
||||
InputDispatcher::blinkRightButton(true);
|
||||
InputDispatcher::blinkRightButton(false);
|
||||
#endif
|
||||
break;
|
||||
case 'u':
|
||||
case 'U':
|
||||
#ifndef LEDSTRIP_WRONG_DIRECTION
|
||||
InputDispatcher::blinkRightButton(true);
|
||||
InputDispatcher::blinkRightButton(false);
|
||||
#else
|
||||
InputDispatcher::blinkLeftButton(true);
|
||||
InputDispatcher::blinkLeftButton(false);
|
||||
#endif
|
||||
break;
|
||||
consoleControlCharsReceived = 0;
|
||||
switch (c)
|
||||
{
|
||||
case 'A': // Up arrow pressed
|
||||
if (espgui::currentDisplay)
|
||||
{
|
||||
espgui::currentDisplay->buttonPressed(espgui::Button::Up);
|
||||
espgui::currentDisplay->buttonReleased(espgui::Button::Up);
|
||||
}
|
||||
break;
|
||||
case 'B': // Down arrow pressed
|
||||
if (espgui::currentDisplay)
|
||||
{
|
||||
espgui::currentDisplay->buttonPressed(espgui::Button::Down);
|
||||
espgui::currentDisplay->buttonReleased(espgui::Button::Down);
|
||||
}
|
||||
break;
|
||||
case 'C': // Right arrow pressed
|
||||
if (espgui::currentDisplay)
|
||||
{
|
||||
espgui::currentDisplay->buttonPressed(espgui::Button::Right);
|
||||
espgui::currentDisplay->buttonReleased(espgui::Button::Right);
|
||||
}
|
||||
break;
|
||||
case 'D': // Left arrow pressed
|
||||
if (espgui::currentDisplay)
|
||||
{
|
||||
espgui::currentDisplay->buttonPressed(espgui::Button::Left);
|
||||
espgui::currentDisplay->buttonReleased(espgui::Button::Left);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ESP_LOGI(TAG, "unknown control char received: %hhx", c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,9 @@
|
||||
#include "globals.h"
|
||||
#include "utils.h"
|
||||
#include "texts.h"
|
||||
#include "buttons.h"
|
||||
#include "displays/menus/mainmenu.h"
|
||||
#include "displays/calibratedisplay.h"
|
||||
#include "bobbybuttons.h"
|
||||
|
||||
void Lockscreen::start()
|
||||
{
|
||||
@ -24,7 +24,6 @@ void Lockscreen::start()
|
||||
m_oldMode = currentMode;
|
||||
currentMode = &m_mode;
|
||||
|
||||
profileButtonDisabled = !settings.lockscreen.allowPresetSwitch;
|
||||
isLocked = true;
|
||||
if (settings.lockscreen.keepLockedAfterReboot && !settings.lockscreen.locked)
|
||||
{
|
||||
@ -71,9 +70,6 @@ void Lockscreen::initScreen()
|
||||
void Lockscreen::update()
|
||||
{
|
||||
Base::update();
|
||||
|
||||
// just in case someone changes that settings somehow
|
||||
profileButtonDisabled = !settings.lockscreen.allowPresetSwitch;
|
||||
}
|
||||
|
||||
void Lockscreen::redraw()
|
||||
@ -147,7 +143,6 @@ void Lockscreen::stop()
|
||||
currentMode = m_oldMode;
|
||||
}
|
||||
|
||||
profileButtonDisabled = false;
|
||||
isLocked = false;
|
||||
if (!(!gas || !brems || *gas > 200.f || *brems > 200.f))
|
||||
{
|
||||
@ -161,6 +156,8 @@ void Lockscreen::stop()
|
||||
|
||||
void Lockscreen::buttonPressed(espgui::Button button)
|
||||
{
|
||||
if (settings.lockscreen.allowPresetSwitch ||
|
||||
!cpputils::is_in(button, BobbyButton::Profile0, BobbyButton::Profile1, BobbyButton::Profile2, BobbyButton::Profile3))
|
||||
Base::buttonPressed(button);
|
||||
|
||||
switch (button)
|
||||
|
@ -24,6 +24,8 @@ using namespace espconfig;
|
||||
|
||||
std::string defaultHostname();
|
||||
|
||||
constexpr const auto INPUT_MAPPING_NONE = std::numeric_limits<uint8_t>::max();
|
||||
|
||||
class WiFiConfig
|
||||
{
|
||||
public:
|
||||
@ -126,6 +128,19 @@ public:
|
||||
|
||||
ConfigWrapper<uint8_t> dpadDebounce {25, DoReset, {}, "dpadDebounce" };
|
||||
|
||||
ConfigWrapper<uint8_t> dpadMappingLeft {INPUT_MAPPING_NONE, DoReset, {}, "dpadMapLeft" };
|
||||
ConfigWrapper<uint8_t> dpadMappingRight {INPUT_MAPPING_NONE, DoReset, {}, "dpadMapRight" };
|
||||
ConfigWrapper<uint8_t> dpadMappingUp {INPUT_MAPPING_NONE, DoReset, {}, "dpadMapUp" };
|
||||
ConfigWrapper<uint8_t> dpadMappingDown {INPUT_MAPPING_NONE, DoReset, {}, "dpadMapDown" };
|
||||
ConfigWrapper<uint8_t> dpadMappingProfile0{INPUT_MAPPING_NONE, DoReset, {}, "dpadMapProfile0" };
|
||||
ConfigWrapper<uint8_t> dpadMappingProfile1{INPUT_MAPPING_NONE, DoReset, {}, "dpadMapProfile1" };
|
||||
ConfigWrapper<uint8_t> dpadMappingProfile2{INPUT_MAPPING_NONE, DoReset, {}, "dpadMapProfile2" };
|
||||
ConfigWrapper<uint8_t> dpadMappingProfile3{INPUT_MAPPING_NONE, DoReset, {}, "dpadMapProfile3" };
|
||||
ConfigWrapper<uint8_t> dpadMappingLeft2 {INPUT_MAPPING_NONE, DoReset, {}, "dpadMapLeft2" };
|
||||
ConfigWrapper<uint8_t> dpadMappingRight2 {INPUT_MAPPING_NONE, DoReset, {}, "dpadMapRight2" };
|
||||
ConfigWrapper<uint8_t> dpadMappingUp2 {INPUT_MAPPING_NONE, DoReset, {}, "dpadMapUp2" };
|
||||
ConfigWrapper<uint8_t> dpadMappingDown2 {INPUT_MAPPING_NONE, DoReset, {}, "dpadMapDown2" };
|
||||
|
||||
std::array<WirelessDoorsConfig, 5> wireless_door_configs {
|
||||
WirelessDoorsConfig { "door_id0", "door_token0" },
|
||||
WirelessDoorsConfig { "door_id1", "door_token1" },
|
||||
@ -294,6 +309,19 @@ public:
|
||||
\
|
||||
x(dpadDebounce) \
|
||||
\
|
||||
x(dpadMappingLeft) \
|
||||
x(dpadMappingRight) \
|
||||
x(dpadMappingUp) \
|
||||
x(dpadMappingDown) \
|
||||
x(dpadMappingProfile0) \
|
||||
x(dpadMappingProfile1) \
|
||||
x(dpadMappingProfile2) \
|
||||
x(dpadMappingProfile3) \
|
||||
x(dpadMappingLeft2) \
|
||||
x(dpadMappingRight2) \
|
||||
x(dpadMappingUp2) \
|
||||
x(dpadMappingDown2) \
|
||||
\
|
||||
x(wireless_door_configs[0].doorId) \
|
||||
x(wireless_door_configs[0].doorToken) \
|
||||
x(wireless_door_configs[1].doorId) \
|
||||
|
@ -1,121 +0,0 @@
|
||||
#include "serialhandler.h"
|
||||
|
||||
// Arduino includes
|
||||
#include <HardwareSerial.h>
|
||||
|
||||
// 3rdparty lib includes
|
||||
#include <tftinstance.h>
|
||||
|
||||
// local includes
|
||||
#include "globals.h"
|
||||
#include "utils.h"
|
||||
#include "screens.h"
|
||||
#include "buttons.h"
|
||||
|
||||
using namespace espgui;
|
||||
|
||||
//wl_status_t last_status;
|
||||
//IPAddress last_ip;
|
||||
|
||||
void handleSerial()
|
||||
{
|
||||
//const auto status = WiFi.status();
|
||||
//if (last_status != status)
|
||||
//{
|
||||
//Serial.print("Status changed to: ");
|
||||
//Serial.println(to_string(status).c_str());
|
||||
//last_status = status;
|
||||
//}
|
||||
|
||||
//const auto ip = WiFi.localIP();
|
||||
//if (last_ip != ip)
|
||||
//{
|
||||
//Serial.print("IP changed to: ");
|
||||
//Serial.println(to_string(ip).c_str());
|
||||
//last_ip = ip;
|
||||
//}
|
||||
|
||||
while(Serial.available())
|
||||
{
|
||||
const auto c = Serial.read();
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 'i':
|
||||
case 'I':
|
||||
tft.init();
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
{
|
||||
const auto firstPower = controllers.front.command.poweroff;
|
||||
for (Controller &controller : controllers)
|
||||
controller.command.poweroff = !firstPower;
|
||||
break;
|
||||
}
|
||||
case 'l':
|
||||
case 'L':
|
||||
{
|
||||
const auto firstLed = controllers.front.command.led;
|
||||
for (Controller &controller : controllers)
|
||||
controller.command.led = !firstLed;
|
||||
break;
|
||||
}
|
||||
case 'r':
|
||||
case 'R':
|
||||
loadSettings();
|
||||
break;
|
||||
case 's':
|
||||
case 'S':
|
||||
saveSettings();
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
for (Controller &controller : controllers)
|
||||
controller.command.buzzer.freq = c-'0';
|
||||
break;
|
||||
case 'A':
|
||||
InputDispatcher::rotate(-1);
|
||||
break;
|
||||
case 'B':
|
||||
InputDispatcher::rotate(1);
|
||||
break;
|
||||
case 'C':
|
||||
InputDispatcher::confirmButton(true);
|
||||
InputDispatcher::confirmButton(false);
|
||||
break;
|
||||
case 'D':
|
||||
InputDispatcher::backButton(true);
|
||||
InputDispatcher::backButton(false);
|
||||
break;
|
||||
case 'z':
|
||||
case 'Z':
|
||||
#ifndef LEDSTRIP_WRONG_DIRECTION
|
||||
InputDispatcher::blinkLeftButton(true);
|
||||
InputDispatcher::blinkLeftButton(false);
|
||||
#else
|
||||
InputDispatcher::blinkRightButton(true);
|
||||
InputDispatcher::blinkRightButton(false);
|
||||
#endif
|
||||
break;
|
||||
case 'u':
|
||||
case 'U':
|
||||
#ifndef LEDSTRIP_WRONG_DIRECTION
|
||||
InputDispatcher::blinkRightButton(true);
|
||||
InputDispatcher::blinkRightButton(false);
|
||||
#else
|
||||
InputDispatcher::blinkLeftButton(true);
|
||||
InputDispatcher::blinkLeftButton(false);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -59,7 +59,7 @@ void initWebserver()
|
||||
{
|
||||
httpd_config_t httpConfig HTTPD_DEFAULT_CONFIG();
|
||||
httpConfig.core_id = 1;
|
||||
httpConfig.max_uri_handlers = 15;
|
||||
httpConfig.max_uri_handlers = 16;
|
||||
httpConfig.stack_size = 8192;
|
||||
|
||||
const auto result = httpd_start(&httpdHandle, &httpConfig);
|
||||
@ -70,6 +70,7 @@ void initWebserver()
|
||||
|
||||
for (const httpd_uri_t &uri : {
|
||||
httpd_uri_t { .uri = "/", .method = HTTP_GET, .handler = webserver_root_handler, .user_ctx = NULL },
|
||||
httpd_uri_t { .uri = "/triggerRawButton", .method = HTTP_GET, .handler = webserver_triggerRawButton_handler, .user_ctx = NULL },
|
||||
httpd_uri_t { .uri = "/triggerButton", .method = HTTP_GET, .handler = webserver_triggerButton_handler, .user_ctx = NULL },
|
||||
httpd_uri_t { .uri = "/triggerItem", .method = HTTP_GET, .handler = webserver_triggerItem_handler, .user_ctx = NULL },
|
||||
httpd_uri_t { .uri = "/setValue", .method = HTTP_GET, .handler = webserver_setValue_handler, .user_ctx = NULL },
|
||||
|
@ -15,13 +15,14 @@
|
||||
#include <textinterface.h>
|
||||
#include <menudisplay.h>
|
||||
#include <changevaluedisplay.h>
|
||||
#include <changevaluedisplay_string.h>
|
||||
#include <lockhelper.h>
|
||||
#include <tickchrono.h>
|
||||
#include <screenmanager.h>
|
||||
#include <futurecpp.h>
|
||||
|
||||
// local includes
|
||||
#include "buttons.h"
|
||||
#include "globals.h"
|
||||
#include "bobbybuttons.h"
|
||||
#include "webserver_lock.h"
|
||||
#include "newsettings.h"
|
||||
|
||||
@ -190,14 +191,48 @@ esp_err_t webserver_root_handler(httpd_req_t *req)
|
||||
|
||||
{
|
||||
HtmlTag pTag{"p", body};
|
||||
body += "<a href=\"/triggerButton?button=up\">Up</a> "
|
||||
"<a href=\"/triggerButton?button=down\">Down</a> "
|
||||
"<a href=\"/triggerButton?button=confirm\">Confirm</a> "
|
||||
"<a href=\"/triggerButton?button=back\">Back</a> "
|
||||
"<a href=\"/triggerButton?button=profile0\">Profile0</a> "
|
||||
"<a href=\"/triggerButton?button=profile1\">Profile1</a> "
|
||||
"<a href=\"/triggerButton?button=profile2\">Profile2</a> "
|
||||
"<a href=\"/triggerButton?button=profile3\">Profile3</a> ";
|
||||
body += "Trigger raw button: "
|
||||
"<a href=\"/triggerRawButton?button=0\">Button0</a> "
|
||||
"<a href=\"/triggerRawButton?button=1\">Button1</a> "
|
||||
"<a href=\"/triggerRawButton?button=2\">Button2</a> "
|
||||
"<a href=\"/triggerRawButton?button=3\">Button3</a> "
|
||||
"<a href=\"/triggerRawButton?button=4\">Button4</a> "
|
||||
"<a href=\"/triggerRawButton?button=5\">Button5</a> "
|
||||
"<a href=\"/triggerRawButton?button=6\">Button6</a> "
|
||||
"<a href=\"/triggerRawButton?button=7\">Button7</a> "
|
||||
"<a href=\"/triggerRawButton?button=8\">Button8</a> "
|
||||
"<a href=\"/triggerRawButton?button=9\">Button9</a> "
|
||||
"<a href=\"/triggerRawButton?button=10\">Button10</a> "
|
||||
"<a href=\"/triggerRawButton?button=11\">Button11</a>";
|
||||
}
|
||||
|
||||
{
|
||||
HtmlTag pTag{"p", body};
|
||||
body += fmt::format("Trigger button: "
|
||||
"<a href=\"/triggerButton?button={}\">Left</a> "
|
||||
"<a href=\"/triggerButton?button={}\">Right</a> "
|
||||
"<a href=\"/triggerButton?button={}\">Up</a> "
|
||||
"<a href=\"/triggerButton?button={}\">Down</a> "
|
||||
"<a href=\"/triggerButton?button={}\">Profile0</a> "
|
||||
"<a href=\"/triggerButton?button={}\">Profile1</a> "
|
||||
"<a href=\"/triggerButton?button={}\">Profile2</a> "
|
||||
"<a href=\"/triggerButton?button={}\">Profile3</a> "
|
||||
"<a href=\"/triggerButton?button={}\">Left2</a> "
|
||||
"<a href=\"/triggerButton?button={}\">Right2</a> "
|
||||
"<a href=\"/triggerButton?button={}\">Up2</a> "
|
||||
"<a href=\"/triggerButton?button={}\">Down2</a>",
|
||||
std::to_underlying(espgui::Button::Left),
|
||||
std::to_underlying(espgui::Button::Right),
|
||||
std::to_underlying(espgui::Button::Up),
|
||||
std::to_underlying(espgui::Button::Down),
|
||||
std::to_underlying(BobbyButton::Profile0),
|
||||
std::to_underlying(BobbyButton::Profile1),
|
||||
std::to_underlying(BobbyButton::Profile2),
|
||||
std::to_underlying(BobbyButton::Profile3),
|
||||
std::to_underlying(BobbyButton::Left2),
|
||||
std::to_underlying(BobbyButton::Right2),
|
||||
std::to_underlying(BobbyButton::Up2),
|
||||
std::to_underlying(BobbyButton::Down2));
|
||||
}
|
||||
|
||||
if (auto currentDisplay = static_cast<const espgui::Display *>(espgui::currentDisplay.get()))
|
||||
@ -228,6 +263,12 @@ esp_err_t webserver_root_handler(httpd_req_t *req)
|
||||
body += fmt::format("<input type=\"number\" name=\"value\" value=\"{}\" />", changeValueDisplay->shownValue());
|
||||
body += "<button type=\"submit\">Update</button>";
|
||||
}
|
||||
else if (const auto *changeValueDisplay = currentDisplay->asChangeValueDisplayString())
|
||||
{
|
||||
HtmlTag formTag{"form", "action=\"/setValue\" method=\"GET\"", body};
|
||||
body += fmt::format("<input type=\"text\" name=\"value\" value=\"{}\" />", changeValueDisplay->shownValue());
|
||||
body += "<button type=\"submit\">Update</button>";
|
||||
}
|
||||
else
|
||||
{
|
||||
body += "No web control implemented for current display.";
|
||||
@ -243,9 +284,8 @@ esp_err_t webserver_root_handler(httpd_req_t *req)
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::Ok, (key_result == ESP_OK) ? "application/json":"text/html", body)
|
||||
}
|
||||
|
||||
esp_err_t webserver_triggerButton_handler(httpd_req_t *req)
|
||||
esp_err_t webserver_triggerRawButton_handler(httpd_req_t *req)
|
||||
{
|
||||
|
||||
#ifndef FEATURE_IS_MIR_EGAL_OB_DER_WEBSERVER_KORREKT_ARBEITET
|
||||
espcpputils::LockHelper helper{webserver_lock->handle, std::chrono::ceil<espcpputils::ticks>(5s).count()};
|
||||
if (!helper.locked())
|
||||
@ -265,7 +305,7 @@ esp_err_t webserver_triggerButton_handler(httpd_req_t *req)
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", result.error());
|
||||
}
|
||||
|
||||
std::string button;
|
||||
uint8_t button;
|
||||
constexpr const std::string_view buttonParamName{"button"};
|
||||
|
||||
{
|
||||
@ -289,77 +329,105 @@ esp_err_t webserver_triggerButton_handler(httpd_req_t *req)
|
||||
char valueBuf[257];
|
||||
esphttpdutils::urldecode(valueBuf, valueBufEncoded);
|
||||
|
||||
button = valueBuf;
|
||||
std::string_view value{valueBuf};
|
||||
|
||||
if (auto parsed = cpputils::fromString<decltype(button)>(value))
|
||||
{
|
||||
button = *parsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto msg = fmt::format("could not parse {} {}", buttonParamName, value);
|
||||
ESP_LOGW(TAG, "%.*s", msg.size(), msg.data());
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (button == "up")
|
||||
if (!espgui::currentDisplay)
|
||||
{
|
||||
InputDispatcher::rotate(-1);
|
||||
|
||||
CALL_AND_EXIT_ON_ERROR(httpd_resp_set_hdr, req, "Location", "/")
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::TemporaryRedirect, "text/html", "Ok, continue at <a href=\"/\">/</a>")
|
||||
}
|
||||
else if (button == "down")
|
||||
{
|
||||
InputDispatcher::rotate(1);
|
||||
|
||||
CALL_AND_EXIT_ON_ERROR(httpd_resp_set_hdr, req, "Location", "/")
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::TemporaryRedirect, "text/html", "Ok, continue at <a href=\"/\">/</a>")
|
||||
}
|
||||
else if (button == "confirm")
|
||||
{
|
||||
InputDispatcher::confirmButton(true);
|
||||
InputDispatcher::confirmButton(false);
|
||||
|
||||
CALL_AND_EXIT_ON_ERROR(httpd_resp_set_hdr, req, "Location", "/")
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::TemporaryRedirect, "text/html", "Ok, continue at <a href=\"/\">/</a>")
|
||||
}
|
||||
else if (button == "back")
|
||||
{
|
||||
InputDispatcher::backButton(true);
|
||||
InputDispatcher::backButton(false);
|
||||
|
||||
CALL_AND_EXIT_ON_ERROR(httpd_resp_set_hdr, req, "Location", "/")
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::TemporaryRedirect, "text/html", "Ok, continue at <a href=\"/\">/</a>")
|
||||
}
|
||||
else if (button == "profile0")
|
||||
{
|
||||
InputDispatcher::profileButton(0, true);
|
||||
InputDispatcher::profileButton(0, false);
|
||||
|
||||
CALL_AND_EXIT_ON_ERROR(httpd_resp_set_hdr, req, "Location", "/")
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::TemporaryRedirect, "text/html", "Ok, continue at <a href=\"/\">/</a>")
|
||||
}
|
||||
else if (button == "profile1")
|
||||
{
|
||||
InputDispatcher::profileButton(1, true);
|
||||
InputDispatcher::profileButton(1, false);
|
||||
|
||||
CALL_AND_EXIT_ON_ERROR(httpd_resp_set_hdr, req, "Location", "/")
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::TemporaryRedirect, "text/html", "Ok, continue at <a href=\"/\">/</a>")
|
||||
}
|
||||
else if (button == "profile2")
|
||||
{
|
||||
InputDispatcher::profileButton(2, true);
|
||||
InputDispatcher::profileButton(2, false);
|
||||
|
||||
CALL_AND_EXIT_ON_ERROR(httpd_resp_set_hdr, req, "Location", "/")
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::TemporaryRedirect, "text/html", "Ok, continue at <a href=\"/\">/</a>")
|
||||
}
|
||||
else if (button == "profile3")
|
||||
{
|
||||
InputDispatcher::profileButton(3, true);
|
||||
InputDispatcher::profileButton(3, false);
|
||||
|
||||
CALL_AND_EXIT_ON_ERROR(httpd_resp_set_hdr, req, "Location", "/")
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::TemporaryRedirect, "text/html", "Ok, continue at <a href=\"/\">/</a>")
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto msg = fmt::format("invalid {} {}", buttonParamName, button);
|
||||
constexpr const std::string_view msg = "espgui::currentDisplay is null";
|
||||
ESP_LOGW(TAG, "%.*s", msg.size(), msg.data());
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
|
||||
}
|
||||
|
||||
espgui::currentDisplay->rawButtonPressed(button);
|
||||
espgui::currentDisplay->rawButtonReleased(button);
|
||||
|
||||
CALL_AND_EXIT_ON_ERROR(httpd_resp_set_hdr, req, "Location", "/")
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::TemporaryRedirect, "text/html", "Ok, continue at <a href=\"/\">/</a>")
|
||||
}
|
||||
|
||||
esp_err_t webserver_triggerButton_handler(httpd_req_t *req)
|
||||
{
|
||||
#ifndef FEATURE_IS_MIR_EGAL_OB_DER_WEBSERVER_KORREKT_ARBEITET
|
||||
espcpputils::LockHelper helper{webserver_lock->handle, std::chrono::ceil<espcpputils::ticks>(5s).count()};
|
||||
if (!helper.locked())
|
||||
{
|
||||
constexpr const std::string_view msg = "could not lock webserver_lock";
|
||||
ESP_LOGE(TAG, "%.*s", msg.size(), msg.data());
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string query;
|
||||
if (auto result = esphttpdutils::webserver_get_query(req))
|
||||
query = *result;
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG, "%.*s", result.error().size(), result.error().data());
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", result.error());
|
||||
}
|
||||
|
||||
espgui::Button button;
|
||||
constexpr const std::string_view buttonParamName{"button"};
|
||||
|
||||
{
|
||||
char valueBufEncoded[256];
|
||||
if (const auto result = httpd_query_key_value(query.data(), buttonParamName.data(), valueBufEncoded, 256); result != ESP_OK)
|
||||
{
|
||||
if (result == ESP_ERR_NOT_FOUND)
|
||||
{
|
||||
const auto msg = fmt::format("{} not set", buttonParamName);
|
||||
ESP_LOGW(TAG, "%.*s", msg.size(), msg.data());
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto msg = fmt::format("httpd_query_key_value() {} failed with {}", buttonParamName, esp_err_to_name(result));
|
||||
ESP_LOGE(TAG, "%.*s", msg.size(), msg.data());
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
|
||||
}
|
||||
}
|
||||
|
||||
char valueBuf[257];
|
||||
esphttpdutils::urldecode(valueBuf, valueBufEncoded);
|
||||
|
||||
std::string_view value{valueBuf};
|
||||
|
||||
if (auto parsed = cpputils::fromString<std::underlying_type_t<espgui::Button>>(value))
|
||||
{
|
||||
button = espgui::Button(*parsed);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto msg = fmt::format("could not parse {} {}", buttonParamName, value);
|
||||
ESP_LOGW(TAG, "%.*s", msg.size(), msg.data());
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (!espgui::currentDisplay)
|
||||
{
|
||||
constexpr const std::string_view msg = "espgui::currentDisplay is null";
|
||||
ESP_LOGW(TAG, "%.*s", msg.size(), msg.data());
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
|
||||
}
|
||||
|
||||
espgui::currentDisplay->buttonPressed(button);
|
||||
espgui::currentDisplay->buttonReleased(button);
|
||||
|
||||
CALL_AND_EXIT_ON_ERROR(httpd_resp_set_hdr, req, "Location", "/")
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::TemporaryRedirect, "text/html", "Ok, continue at <a href=\"/\">/</a>")
|
||||
}
|
||||
|
||||
esp_err_t webserver_triggerItem_handler(httpd_req_t *req)
|
||||
@ -471,8 +539,7 @@ esp_err_t webserver_setValue_handler(httpd_req_t *req)
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", result.error());
|
||||
}
|
||||
|
||||
int newValue;
|
||||
|
||||
char valueBuf[257];
|
||||
constexpr const std::string_view valueParamName{"value"};
|
||||
|
||||
{
|
||||
@ -493,11 +560,21 @@ esp_err_t webserver_setValue_handler(httpd_req_t *req)
|
||||
}
|
||||
}
|
||||
|
||||
char valueBuf[257];
|
||||
esphttpdutils::urldecode(valueBuf, valueBufEncoded);
|
||||
}
|
||||
|
||||
std::string_view value{valueBuf};
|
||||
std::string_view value{valueBuf};
|
||||
|
||||
if (!espgui::currentDisplay)
|
||||
{
|
||||
constexpr const std::string_view msg = "espgui::currentDisplay is null";
|
||||
ESP_LOGW(TAG, "%.*s", msg.size(), msg.data());
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
|
||||
}
|
||||
|
||||
if (auto *changeValueDisplay = espgui::currentDisplay->asChangeValueDisplayInterface())
|
||||
{
|
||||
int newValue;
|
||||
if (auto parsed = cpputils::fromString<typeof(newValue)>(value))
|
||||
{
|
||||
newValue = *parsed;
|
||||
@ -508,24 +585,20 @@ esp_err_t webserver_setValue_handler(httpd_req_t *req)
|
||||
ESP_LOGW(TAG, "%.*s", msg.size(), msg.data());
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (!espgui::currentDisplay)
|
||||
changeValueDisplay->setShownValue(newValue);
|
||||
}
|
||||
else if (auto *changeValueDisplay = espgui::currentDisplay->asChangeValueDisplayString())
|
||||
{
|
||||
constexpr const std::string_view msg = "espgui::currentDisplay is null";
|
||||
ESP_LOGW(TAG, "%.*s", msg.size(), msg.data());
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
|
||||
changeValueDisplay->setShownValue(std::string{value});
|
||||
}
|
||||
|
||||
auto *changeValueDisplay = espgui::currentDisplay->asChangeValueDisplayInterface();
|
||||
if (!changeValueDisplay)
|
||||
else
|
||||
{
|
||||
constexpr const std::string_view msg = "espgui::currentDisplay is not a change value display";
|
||||
ESP_LOGW(TAG, "%.*s", msg.size(), msg.data());
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
|
||||
}
|
||||
|
||||
changeValueDisplay->setShownValue(newValue);
|
||||
|
||||
CALL_AND_EXIT_ON_ERROR(httpd_resp_set_hdr, req, "Location", "/")
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::TemporaryRedirect, "text/html", "Ok, continue at <a href=\"/\">/</a>")
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#ifdef FEATURE_WEBSERVER
|
||||
esp_err_t webserver_root_handler(httpd_req_t *req);
|
||||
esp_err_t webserver_triggerRawButton_handler(httpd_req_t *req);
|
||||
esp_err_t webserver_triggerButton_handler(httpd_req_t *req);
|
||||
esp_err_t webserver_triggerItem_handler(httpd_req_t *req);
|
||||
esp_err_t webserver_setValue_handler(httpd_req_t *req);
|
||||
|
Reference in New Issue
Block a user