@@ -8,6 +8,9 @@ static const char FRONTPAGE[] = R"EOT(
88<h1>esp32cam AsyncCam example</h1>
99<form id="update"><p>
1010<select name="resolution" required>%resolution%</select>
11+ %brightness%
12+ %contrast%
13+ %saturation%
1114%hmirror%
1215%vflip%
1316<input type="submit" value="update">
@@ -28,18 +31,20 @@ async function fetchText(uri, init) {
2831 return (await response.text()).trim().replaceAll("\r\n", "\n");
2932}
3033
34+ const $update = document.querySelector("#update");
3135const $display = document.querySelector("#display");
32- document.querySelector("# update") .addEventListener("submit", async (evt) => {
36+ $ update.addEventListener("submit", async (evt) => {
3337 evt.preventDefault();
3438 try {
3539 await fetchText("/update.cgi", {
3640 method: "POST",
37- body: new URLSearchParams(new FormData(evt.target )),
41+ body: new URLSearchParams(new FormData($update )),
3842 });
3943 } catch (err) {
4044 $display.textContent = err.toString();
4145 }
4246});
47+ $update.reset();
4348
4449for (const $ctrl of document.querySelectorAll("#controls button")) {
4550 $ctrl.addEventListener("click", (evt) => {
@@ -62,61 +67,84 @@ for (const $ctrl of document.querySelectorAll("#controls button")) {
6267)EOT" ;
6368
6469static String
65- rewriteFrontpage (const esp32cam::Settings& settings , const String& var) {
70+ rewriteFrontpage (const esp32cam::Settings& s , const String& var) {
6671 StreamString b;
6772
6873 if (var == " resolution" ) {
6974 for (const auto & r : esp32cam::Camera.listResolutions ()) {
7075 b.printf (" <option value=\" %d\" %s>" , r.as <int >(),
71- r > initialResolution ? " disabled"
72- : r == settings .resolution ? " selected"
73- : " " );
76+ r > initialResolution ? " disabled"
77+ : r == s .resolution ? " selected"
78+ : " " );
7479 b.print (r);
7580 b.print (" </option>" );
7681 }
7782 }
7883
84+ #define SETTING_INT (MEM, MIN, MAX ) \
85+ else if (var == #MEM) { \
86+ b.printf (" <label>" #MEM " =<input type=\" number\" name=\" " #MEM \
87+ " \" value=\" %d\" min=\" %d\" max=\" %d\" ></label>" , \
88+ s.MEM , MIN, MAX); \
89+ }
90+
7991#define SETTING_BOOL (MEM ) \
8092 else if (var == #MEM) { \
8193 b.printf (" <label><input type=\" checkbox\" name=\" " #MEM " \" value=\" 1\" %s>" #MEM " </label>" , \
82- settings .MEM ? " checked" : " " ); \
94+ s .MEM ? " checked" : " " ); \
8395 }
8496
97+ SETTING_INT (brightness, -2 , 2 )
98+ SETTING_INT (contrast, -2 , 2 )
99+ SETTING_INT (saturation, -2 , 2 )
85100 SETTING_BOOL (hmirror)
86101 SETTING_BOOL (vflip)
87102
103+ #undef SETTING_INT
88104#undef SETTING_BOOL
89105
90106 return b;
91107}
92108
93109static void
94- handleFrontpage (AsyncWebServerRequest* request ) {
110+ handleFrontpage (AsyncWebServerRequest* req ) {
95111 auto settings = esp32cam::Camera.status ();
96- request ->send (200 , " text/html" , reinterpret_cast <const uint8_t *>(FRONTPAGE), sizeof (FRONTPAGE),
97- [=](const String& var) { return rewriteFrontpage (settings, var); });
112+ req ->send (200 , " text/html" , reinterpret_cast <const uint8_t *>(FRONTPAGE), sizeof (FRONTPAGE),
113+ [=](const String& var) { return rewriteFrontpage (settings, var); });
98114}
99115
100116static void
101- handleUpdate (AsyncWebServerRequest* request) {
102- bool ok = esp32cam::Camera.update ([=](esp32cam::Settings& settings) {
103- settings.resolution =
104- esp32cam::Resolution (static_cast <int >(request->arg (" resolution" ).toInt ()));
105- settings.hmirror = request->arg (" hmirror" ).toInt () != 0 ;
106- settings.vflip = request->arg (" vflip" ).toInt () != 0 ;
117+ handleUpdate (AsyncWebServerRequest* req) {
118+ bool ok = esp32cam::Camera.update ([=](esp32cam::Settings& s) {
119+ #define UPDATE (MEM ) \
120+ do { \
121+ if constexpr (std::is_same_v<decltype (s.MEM ), bool >) { \
122+ s.MEM = req->hasArg (#MEM); \
123+ } else { \
124+ s.MEM = static_cast <decltype (s.MEM )>(req->arg (#MEM).toInt ()); \
125+ } \
126+ } while (false )
127+ s.resolution = esp32cam::Resolution (static_cast <int >(req->arg (" resolution" ).toInt ()));
128+ UPDATE (brightness);
129+ UPDATE (contrast);
130+ UPDATE (saturation);
131+ UPDATE (hmirror);
132+ UPDATE (vflip);
133+
134+ #undef UPDATE
107135 });
108136
109137 if (!ok) {
110- request ->send (500 , " text/plain" , " update settings error\n " );
138+ req ->send (500 , " text/plain" , " update settings error\n " );
111139 return ;
112140 }
113- request ->send (204 );
141+ req ->send (204 );
114142}
115143
116144void
117145addRequestHandlers () {
118- server.on (" /robots.txt" , HTTP_GET, [](AsyncWebServerRequest* request ) {
119- request ->send (200 , " text/plain" , " User-Agent: *\n Disallow: /\n " );
146+ server.on (" /robots.txt" , HTTP_GET, [](AsyncWebServerRequest* req ) {
147+ req ->send (200 , " text/plain" , " User-Agent: *\n Disallow: /\n " );
120148 });
121149
122150 server.on (" /" , HTTP_GET, handleFrontpage);
0 commit comments