@@ -6,15 +6,12 @@ static const char FRONTPAGE[] = R"EOT(
66<title>esp32cam AsyncCam example</title>
77<body>
88<h1>esp32cam AsyncCam example</h1>
9- <form><p>
10- Resolution
11- <select id="resolution" required>%RESOLUTION_OPTIONS%</select>
12- <input type="submit" value="change">
9+ <form id="update"><p>
10+ <select name="resolution" required>%resolution%</select>
11+ %hmirror%
12+ %vflip%
13+ <input type="submit" value="update">
1314</p></form>
14- <p id="toggles">
15- <label><input type="checkbox" data-act="hmirror">hmirror</label>
16- <label><input type="checkbox" data-act="vflip">vflip</label>
17- </p>
1815<p id="controls">
1916<button data-act="mjpeg">show Motion JPEG stream</button>
2017<button data-act="jpg">show still JPEG image</button>
@@ -32,36 +29,18 @@ async function fetchText(uri, init) {
3229}
3330
3431const $display = document.querySelector("#display");
35- const $resolution = document.querySelector("#resolution");
36-
37- $resolution.form.addEventListener("submit", async (evt) => {
32+ document.querySelector("#update").addEventListener("submit", async (evt) => {
3833 evt.preventDefault();
39- const [width, height] = $resolution.value.split("x");
4034 try {
41- await fetchText("/change-resolution .cgi", {
35+ await fetchText("/update .cgi", {
4236 method: "POST",
43- body: new URLSearchParams({ width, height } ),
37+ body: new URLSearchParams(new FormData(evt.target) ),
4438 });
4539 } catch (err) {
4640 $display.textContent = err.toString();
4741 }
4842});
4943
50- for (const $ctrl of document.querySelectorAll("#toggles input[type=checkbox]")) {
51- $ctrl.addEventListener("change", async (evt) => {
52- evt.preventDefault();
53- const act = evt.target.getAttribute("data-act");
54- try {
55- await fetchText(`/set-${act}.cgi`, {
56- method: "POST",
57- body: new URLSearchParams({ enable: Number(evt.target.checked) }),
58- });
59- } catch (err) {
60- $display.textContent = err.toString();
61- }
62- });
63- }
64-
6544for (const $ctrl of document.querySelectorAll("#controls button")) {
6645 $ctrl.addEventListener("click", (evt) => {
6746 evt.preventDefault();
@@ -83,78 +62,66 @@ for (const $ctrl of document.querySelectorAll("#controls button")) {
8362)EOT" ;
8463
8564static String
86- rewriteFrontpage (const String& var) {
65+ rewriteFrontpage (const esp32cam::Settings& settings, const String& var) {
8766 StreamString b;
88- if (var == " RESOLUTION_OPTIONS" ) {
67+
68+ if (var == " resolution" ) {
8969 for (const auto & r : esp32cam::Camera.listResolutions ()) {
90- b.print (" <option" );
91- if (r == currentResolution) {
92- b.print (" selected" );
93- }
94- if (r > initialResolution) {
95- b.print (" disabled" );
96- }
97- b.print (' >' );
70+ b.printf (" <option value=\" %d\" %s>" , r.as <int >(),
71+ r > initialResolution ? " disabled"
72+ : r == settings.resolution ? " selected"
73+ : " " );
9874 b.print (r);
9975 b.print (" </option>" );
10076 }
10177 }
102- return b;
103- }
10478
105- void
106- addRequestHandlers () {
107- server.on (" /" , HTTP_GET, [](AsyncWebServerRequest* request) {
108- request->send (200 , " text/html" , reinterpret_cast <const uint8_t *>(FRONTPAGE), sizeof (FRONTPAGE),
109- rewriteFrontpage);
110- });
79+ #define SETTING_BOOL (MEM ) \
80+ else if (var == #MEM) { \
81+ b.printf (" <label><input type=\" checkbox\" name=\" " #MEM " \" value=\" 1\" %s>" #MEM " </label>" , \
82+ settings.MEM ? " checked" : " " ); \
83+ }
11184
112- server.on (" /robots.txt" , HTTP_GET, [](AsyncWebServerRequest* request) {
113- request->send (200 , " text/plain" , " User-Agent: *\n Disallow: /\n " );
114- });
85+ SETTING_BOOL (hmirror)
86+ SETTING_BOOL (vflip)
11587
116- server.on (" /change-resolution.cgi" , HTTP_POST, [](AsyncWebServerRequest* request) {
117- long width = request->arg (" width" ).toInt ();
118- long height = request->arg (" height" ).toInt ();
119- auto r = esp32cam::Camera.listResolutions ().find (width, height);
120- if (!(r.isValid () && r.getWidth () == width && r.getHeight () == height)) {
121- request->send (404 , " text/plain" , " non-existent resolution\n " );
122- return ;
123- }
88+ #undef SETTING_BOOL
12489
125- if (!esp32cam::Camera.changeResolution (r, 0 )) {
126- Serial.printf (" changeResolution(%ld,%ld) failure\n " , width, height);
127- request->send (500 , " text/plain" , " changeResolution error\n " );
128- return ;
129- }
90+ return b;
91+ }
13092
131- currentResolution = r;
132- Serial. printf ( " changeResolution(%ld,%ld) success \n " , width, height);
133- StreamString b ;
134- b. print (currentResolution);
135- request-> send ( 200 , " text/plain " , static_cast < String>(b) );
136- });
93+ static void
94+ handleFrontpage (AsyncWebServerRequest* request) {
95+ 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); } );
98+ }
13799
138- server.on (" /set-hmirror.cgi" , HTTP_POST, [](AsyncWebServerRequest* request) {
139- long enable = request->arg (" enable" ).toInt ();
140- if (!esp32cam::Camera.update (esp32cam::SetHmirror (enable != 0 ))) {
141- request->send (500 , " text/plain" , " SetHmirror error\n " );
142- return ;
143- }
144- Serial.printf (" SetHmirror(%ld) success\n " , enable);
145- request->send (200 , " text/plain" , " SetHmirror success\n " );
100+ static 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 ;
146107 });
147108
148- server.on (" /set-vflip.cgi" , HTTP_POST, [](AsyncWebServerRequest* request) {
149- long enable = request->arg (" enable" ).toInt ();
150- if (!esp32cam::Camera.update (esp32cam::SetVflip (enable != 0 ))) {
151- request->send (500 , " text/plain" , " SetVflip error\n " );
152- return ;
153- }
154- Serial.printf (" SetVflip(%ld) success\n " , enable);
155- request->send (200 , " text/plain" , " SetVflip success\n " );
109+ if (!ok) {
110+ request->send (500 , " text/plain" , " update settings error\n " );
111+ return ;
112+ }
113+ request->send (204 );
114+ }
115+
116+ void
117+ addRequestHandlers () {
118+ server.on (" /robots.txt" , HTTP_GET, [](AsyncWebServerRequest* request) {
119+ request->send (200 , " text/plain" , " User-Agent: *\n Disallow: /\n " );
156120 });
157121
122+ server.on (" /" , HTTP_GET, handleFrontpage);
123+ server.on (" /update.cgi" , HTTP_POST, handleUpdate);
124+
158125 server.on (" /cam.jpg" , esp32cam::asyncweb::handleStill);
159126 server.on (" /cam.mjpeg" , esp32cam::asyncweb::handleMjpeg);
160127}
0 commit comments