String inputs in webserver implemented

This commit is contained in:
2021-12-30 00:00:31 +01:00
parent 68e8c9ea4a
commit 81701b4096
10 changed files with 367 additions and 353 deletions

View File

@ -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;
}

View File

@ -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();

View File

@ -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);
}
}
}
}

View File

@ -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)

View File

@ -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) \

View File

@ -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;
}
}
}

View File

@ -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 },

View File

@ -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>")

View File

@ -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);