2021-11-21 00:56:28 +01:00
#include "webserver_displaycontrol.h"
2022-06-25 22:16:21 +02:00
// system includes
#include <utility>
2021-12-28 20:27:16 +01:00
// esp-idf includes
#include <esp_http_server.h>
#include <esp_log.h>
// 3rdparty lib includes
#include <htmlbuilder.h>
#include <fmt/core.h>
#include <espcppmacros.h>
#include <numberparsing.h>
#include <esphttpdutils.h>
#include <textinterface.h>
#include <menudisplay.h>
#include <changevaluedisplay.h>
2021-12-30 00:00:31 +01:00
#include <changevaluedisplay_string.h>
2021-12-28 20:27:16 +01:00
#include <lockhelper.h>
#include <tickchrono.h>
#include <screenmanager.h>
// local includes
2021-12-30 00:00:31 +01:00
#include "bobbybuttons.h"
2022-06-23 21:50:58 +02:00
#include "globals.h"
2021-12-29 06:19:09 +01:00
#include "newsettings.h"
2022-06-23 21:50:58 +02:00
#include "webserver_lock.h"
2021-12-28 20:27:16 +01:00
2021-11-21 00:56:28 +01:00
using esphttpdutils :: HtmlTag ;
2021-12-14 12:23:54 +01:00
using namespace std :: chrono_literals ;
2021-11-21 00:56:28 +01:00
namespace {
constexpr const char * const TAG = "BOBBYWEB" ;
} // namespace
esp_err_t webserver_root_handler ( httpd_req_t * req )
{
std :: string body ;
2021-12-09 00:33:40 +01:00
std :: string wants_json_query ;
if ( auto result = esphttpdutils :: webserver_get_query ( req ))
wants_json_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 ());
}
char tmpBuf [ 256 ];
const auto key_result = httpd_query_key_value ( wants_json_query . data (), "json" , tmpBuf , 256 );
2022-04-29 22:40:49 +02:00
if ( key_result == ESP_OK && ( configs . webserverPassword . value (). empty () || configs . webserverPassword . value () == tmpBuf ))
2021-12-09 00:33:40 +01:00
{
2021-12-11 05:05:46 +01:00
2021-12-09 00:33:40 +01:00
body += "{" ;
if ( auto currentDisplay = static_cast < const espgui :: Display *> ( espgui :: currentDisplay . get ()))
{
body . reserve ( 4096 );
if ( const auto * textInterface = currentDisplay -> asTextInterface ())
{
2021-12-10 07:25:16 +01:00
body += fmt :: format ( " \" name \" : \" {} \" ," , textInterface -> text ());
2021-12-09 00:33:40 +01:00
}
if ( const auto * menuDisplay = currentDisplay -> asMenuDisplay ())
{
body += fmt :: format ( " \" index \" :{}, \" items \" :[" , menuDisplay -> selectedIndex ());
menuDisplay -> runForEveryMenuItem ([ & , selectedIndex = menuDisplay -> selectedIndex ()]( const espgui :: MenuItem & menuItem ){
body += "{" ;
2021-12-10 10:01:49 +01:00
const auto itemName = menuItem . text ();
std :: string color {};
std :: string font {};
switch ( menuItem . color ()) {
case TFT_RED :
color = "&1" ;
break ;
case TFT_GREEN :
color = "&2" ;
break ;
case TFT_BLUE :
color = "&3" ;
break ;
case TFT_YELLOW :
color = "&4" ;
break ;
case TFT_BLACK :
color = "&5" ;
break ;
case TFT_WHITE :
color = "&6" ;
break ;
case TFT_GREY :
case TFT_DARKGREY :
color = "&7" ;
break ;
default :
color = "" ;
break ;
}
switch ( menuItem . font ())
{
case 2 :
font = "&s" ;
break ;
case 4 :
font = "&m" ;
break ;
default :
font = "" ;
break ;
}
std :: string menuItemName = font + color + itemName ;
body += fmt :: format ( " \" name \" : \" {} \" , \" icon \" : \" {} \" , \" index \" :{}" , menuItemName , ( menuItem . icon ()) ? menuItem . icon () -> name : "" , selectedIndex );
2021-12-09 00:33:40 +01:00
body += "}," ;
});
body += "]," ;
}
else if ( const auto * changeValueDisplay = currentDisplay -> asChangeValueDisplayInterface ())
{
body += fmt :: format ( " \" value \" : \" {} \" ," , changeValueDisplay -> shownValue ());
}
else
{
2021-12-11 01:28:57 +01:00
body += " \" err \" : \" Screen not implemented yet. \" " ;
2021-12-09 00:33:40 +01:00
}
}
else
{
2021-12-11 01:28:57 +01:00
body += " \" err \" : \" Currently no screen instantiated. \" " ;
2021-12-09 00:33:40 +01:00
}
body += "}" ;
2021-12-10 10:01:49 +01:00
size_t lastGesch = body . rfind ( "}," );
if ( std :: string :: npos != lastGesch )
body = body . erase ( lastGesch + 1 , 1 );
size_t lastEckig = body . rfind ( "]," );
if ( std :: string :: npos != lastEckig )
body = body . erase ( lastEckig + 1 , 1 );
2021-12-11 01:28:57 +01:00
2021-12-09 00:33:40 +01:00
}
2022-04-29 22:40:49 +02:00
else if ( key_result != ESP_ERR_NOT_FOUND && tmpBuf != configs . webserverPassword . value ())
2021-12-09 14:56:06 +01:00
{
CALL_AND_EXIT ( esphttpdutils :: webserver_resp_send , req , esphttpdutils :: ResponseStatus :: Unauthorized , "text/plain" , "" );
}
2021-12-09 00:33:40 +01:00
else
2021-11-21 00:56:28 +01:00
{
HtmlTag htmlTag { "html" , body };
{
HtmlTag headTag { "head" , body };
{
HtmlTag titleTag { "title" , body };
body += "Display control" ;
}
body += "<meta name= \" viewport \" content= \" width=device-width, initial-scale=1, shrink-to-fit=no \" />" ;
}
{
HtmlTag bodyTag { "body" , body };
{
HtmlTag h1Tag { "h1" , body };
body += "Display control" ;
}
{
HtmlTag pTag { "p" , body };
body += "<b>Display control</b> - "
"<a href= \" /ota \" >Update</a> - "
"<a href= \" /settings \" >Settings</a> - "
2021-12-28 22:01:49 +01:00
"<a href= \" /newSettings \" >New Settings</a> - "
2021-11-21 00:56:28 +01:00
"<a href= \" /dumpnvs \" >Dump NVS</a>" ;
}
{
HtmlTag pTag { "p" , body };
2021-12-30 00:00:31 +01:00
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> "
2022-06-12 20:15:31 +02:00
"<a href= \" /triggerRawButton?button=11 \" >Button11</a> "
"<a href= \" /triggerRawButton?button=12 \" >Button12</a> "
"<a href= \" /triggerRawButton?button=13 \" >Button13</a> "
"<a href= \" /triggerRawButton?button=14 \" >Button14</a> "
"<a href= \" /triggerRawButton?button=15 \" >Button15</a>" ;
2021-12-30 00:00:31 +01:00
}
{
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> "
2022-06-12 20:15:31 +02:00
"<a href= \" /triggerButton?button={} \" >Down2</a>"
"<a href= \" /triggerButton?button={} \" >Extra1</a>"
"<a href= \" /triggerButton?button={} \" >Extra2</a>"
"<a href= \" /triggerButton?button={} \" >Extra3</a>"
"<a href= \" /triggerButton?button={} \" >Extra4</a>" ,
2021-12-30 00:00:31 +01:00
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 ),
2022-06-12 20:15:31 +02:00
std :: to_underlying ( BobbyButton :: Down2 ),
std :: to_underlying ( BobbyButton :: Extra1 ),
std :: to_underlying ( BobbyButton :: Extra2 ),
std :: to_underlying ( BobbyButton :: Extra3 ),
std :: to_underlying ( BobbyButton :: Extra4 ));
2021-11-21 00:56:28 +01:00
}
if ( auto currentDisplay = static_cast < const espgui :: Display *> ( espgui :: currentDisplay . get ()))
{
if ( const auto * textInterface = currentDisplay -> asTextInterface ())
{
HtmlTag h2Tag { "h2" , body };
body += esphttpdutils :: htmlentities ( textInterface -> text ());
}
if ( const auto * menuDisplay = currentDisplay -> asMenuDisplay ())
{
HtmlTag ulTag { "ul" , body };
int i { 0 };
menuDisplay -> runForEveryMenuItem ([ & , selectedIndex = menuDisplay -> selectedIndex ()]( const espgui :: MenuItem & menuItem ){
HtmlTag liTag = i == selectedIndex ?
HtmlTag { "li" , "style= \" border: 1px solid black; \" " , body } :
HtmlTag { "li" , body };
body += fmt :: format ( "<a href= \" /triggerItem?index={} \" >{}</a>" , i , esphttpdutils :: htmlentities ( menuItem . text ()));
i ++ ;
});
}
else if ( const auto * changeValueDisplay = currentDisplay -> asChangeValueDisplayInterface ())
{
HtmlTag formTag { "form" , "action= \" /setValue \" method= \" GET \" " , body };
body += fmt :: format ( "<input type= \" number \" name= \" value \" value= \" {} \" />" , changeValueDisplay -> shownValue ());
body += "<button type= \" submit \" >Update</button>" ;
}
2021-12-30 00:00:31 +01:00
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>" ;
}
2021-11-21 00:56:28 +01:00
else
{
body += "No web control implemented for current display." ;
}
}
else
{
body += "Currently no screen instantiated." ;
}
}
}
2022-01-29 03:28:40 +01:00
CALL_AND_EXIT_ON_ERROR ( httpd_resp_set_hdr , req , "Access-Control-Allow-Origin" , "http://web.bobbycar.cloud" );
2021-12-09 00:33:40 +01:00
CALL_AND_EXIT ( esphttpdutils :: webserver_resp_send , req , esphttpdutils :: ResponseStatus :: Ok , ( key_result == ESP_OK ) ? "application/json" : "text/html" , body )
2021-11-21 00:56:28 +01:00
}
2021-12-30 00:00:31 +01:00
esp_err_t webserver_triggerRawButton_handler ( httpd_req_t * req )
2021-11-21 00:56:28 +01:00
{
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 ());
}
2022-06-23 21:50:58 +02:00
int8_t button ;
2021-11-21 00:56:28 +01:00
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 );
2021-12-30 00:00:31 +01:00
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 );
}
2021-11-21 00:56:28 +01:00
}
2022-06-23 21:50:58 +02:00
rawButtonRequest . store ( button );
2021-12-30 00:00:31 +01:00
CALL_AND_EXIT_ON_ERROR ( httpd_resp_set_hdr , req , "Location" , "/" )
2022-01-29 03:28:40 +01:00
CALL_AND_EXIT_ON_ERROR ( httpd_resp_set_hdr , req , "Access-Control-Allow-Origin" , "http://web.bobbycar.cloud" );
2021-12-30 00:00:31 +01:00
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 )
{
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 ());
}
2022-06-23 21:50:58 +02:00
int8_t button ;
2021-12-30 00:00:31 +01:00
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 };
2022-06-23 21:50:58 +02:00
if ( auto parsed = cpputils :: fromString < int8_t > ( value ))
2021-12-30 00:00:31 +01:00
{
2022-06-23 21:50:58 +02:00
button = * parsed ;
2021-12-30 00:00:31 +01:00
}
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 );
}
}
2022-06-23 21:50:58 +02:00
buttonRequest . store ( button );
2021-12-30 00:00:31 +01:00
CALL_AND_EXIT_ON_ERROR ( httpd_resp_set_hdr , req , "Location" , "/" )
2022-01-29 03:28:40 +01:00
CALL_AND_EXIT_ON_ERROR ( httpd_resp_set_hdr , req , "Access-Control-Allow-Origin" , "http://web.bobbycar.cloud" );
2021-12-30 00:00:31 +01:00
CALL_AND_EXIT ( esphttpdutils :: webserver_resp_send , req , esphttpdutils :: ResponseStatus :: TemporaryRedirect , "text/html" , "Ok, continue at <a href= \" / \" >/</a>" )
2021-11-21 00:56:28 +01:00
}
esp_err_t webserver_triggerItem_handler ( httpd_req_t * req )
{
2022-01-17 11:23:22 +01:00
2022-01-29 03:28:40 +01:00
CALL_AND_EXIT_ON_ERROR ( httpd_resp_set_hdr , req , "Access-Control-Allow-Origin" , "http://web.bobbycar.cloud" );
2021-11-21 00:56:28 +01:00
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 ());
}
std :: size_t index ;
constexpr const std :: string_view indexParamName { "index" };
{
char valueBufEncoded [ 256 ];
if ( const auto result = httpd_query_key_value ( query . data (), indexParamName . data (), valueBufEncoded , 256 ); result != ESP_OK )
{
if ( result == ESP_ERR_NOT_FOUND )
{
const auto msg = fmt :: format ( "{} not set" , indexParamName );
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 {}" , indexParamName , 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 < typeof ( index ) > ( value ))
{
index = * parsed ;
}
else
{
const auto msg = fmt :: format ( "could not parse {} {}" , indexParamName , 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 );
}
auto * menuDisplay = espgui :: currentDisplay -> asMenuDisplay ();
if ( ! menuDisplay )
{
constexpr const std :: string_view msg = "espgui::currentDisplay is not a menu display" ;
ESP_LOGW ( TAG , "%.*s" , msg . size (), msg . data ());
CALL_AND_EXIT ( esphttpdutils :: webserver_resp_send , req , esphttpdutils :: ResponseStatus :: BadRequest , "text/plain" , msg );
}
if ( /*index < 0 ||*/ index >= menuDisplay -> menuItemCount ())
{
const auto msg = fmt :: format ( "{} {} out of range (must be smaller than {})" , indexParamName , index , menuDisplay -> menuItemCount ());
ESP_LOGW ( TAG , "%.*s" , msg . size (), msg . data ());
CALL_AND_EXIT ( esphttpdutils :: webserver_resp_send , req , esphttpdutils :: ResponseStatus :: BadRequest , "text/plain" , msg );
}
menuDisplay -> getMenuItem ( index ). triggered ();
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_setValue_handler ( httpd_req_t * req )
{
2022-01-29 03:28:40 +01:00
CALL_AND_EXIT_ON_ERROR ( httpd_resp_set_hdr , req , "Access-Control-Allow-Origin" , "http://web.bobbycar.cloud" );
2021-11-21 00:56:28 +01:00
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 ());
}
2021-12-30 00:00:31 +01:00
char valueBuf [ 257 ];
2021-11-21 00:56:28 +01:00
constexpr const std :: string_view valueParamName { "value" };
{
char valueBufEncoded [ 256 ];
if ( const auto result = httpd_query_key_value ( query . data (), valueParamName . data (), valueBufEncoded , 256 ); result != ESP_OK )
{
if ( result == ESP_ERR_NOT_FOUND )
{
const auto msg = fmt :: format ( "{} not set" , valueParamName );
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 {}" , valueParamName , 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 );
}
}
esphttpdutils :: urldecode ( valueBuf , valueBufEncoded );
2021-12-30 00:00:31 +01:00
}
2021-11-21 00:56:28 +01:00
2021-12-30 00:00:31 +01:00
std :: string_view value { valueBuf };
2021-11-21 00:56:28 +01:00
2021-12-30 00:00:31 +01:00
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 ;
2021-11-21 00:56:28 +01:00
if ( auto parsed = cpputils :: fromString < typeof ( newValue ) > ( value ))
{
newValue = * parsed ;
}
else
{
const auto msg = fmt :: format ( "could not parse {} {}" , valueParamName , value );
ESP_LOGW ( TAG , "%.*s" , msg . size (), msg . data ());
CALL_AND_EXIT ( esphttpdutils :: webserver_resp_send , req , esphttpdutils :: ResponseStatus :: BadRequest , "text/plain" , msg );
}
2021-12-30 00:00:31 +01:00
changeValueDisplay -> setShownValue ( newValue );
}
else if ( auto * changeValueDisplay = espgui :: currentDisplay -> asChangeValueDisplayString ())
2021-11-21 00:56:28 +01:00
{
2021-12-30 00:00:31 +01:00
changeValueDisplay -> setShownValue ( std :: string { value });
2021-11-21 00:56:28 +01:00
}
2021-12-30 00:00:31 +01:00
else
2021-11-21 00:56:28 +01:00
{
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 );
}
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>" )
}