diff --git a/app_httpd.cpp b/app_httpd.cpp
index 05df2c5..edec7e3 100644
--- a/app_httpd.cpp
+++ b/app_httpd.cpp
@@ -19,7 +19,7 @@
#include "index_ov2640.h"
#include "index_ov3660.h"
-#include "miniviewer.h"
+#include "viewers.h"
#include "css.h"
#include "favicon/favicons.h"
@@ -592,7 +592,6 @@ static esp_err_t cmd_handler(httpd_req_t *req){
static esp_err_t status_handler(httpd_req_t *req){
-
static char json_response[1024];
sensor_t * s = esp_camera_sensor_get();
char * p = json_response;
@@ -629,8 +628,22 @@ static esp_err_t status_handler(httpd_req_t *req){
p+=sprintf(p, "\"cam_name\":\"%s\",", myName);
p+=sprintf(p, "\"code_ver\":\"%s\",", myVer);
p+=sprintf(p, "\"rotate\":\"%s\",", myRotation);
- p+=sprintf(p, "\"stream_url\":\"%s\",", streamURL);
- p+=sprintf(p, "\"http\":%i", 80);
+ p+=sprintf(p, "\"stream_url\":\"%s\"", streamURL);
+ *p++ = '}';
+ *p++ = 0;
+ httpd_resp_set_type(req, "application/json");
+ httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
+ return httpd_resp_send(req, json_response, strlen(json_response));
+}
+
+static esp_err_t info_handler(httpd_req_t *req){
+ static char json_response[256];
+ char * p = json_response;
+ *p++ = '{';
+ p+=sprintf(p, "\"cam_name\":\"%s\",", myName);
+ p+=sprintf(p, "\"code_ver\":\"%s\",", myVer);
+ p+=sprintf(p, "\"rotate\":\"%s\",", myRotation);
+ p+=sprintf(p, "\"stream_url\":\"%s\"", streamURL);
*p++ = '}';
*p++ = 0;
httpd_resp_set_type(req, "application/json");
@@ -683,6 +696,15 @@ static esp_err_t miniviewer_handler(httpd_req_t *req){
return httpd_resp_send(req, (const char *)miniviewer_html, miniviewer_html_len);
}
+static esp_err_t streamviewer_handler(httpd_req_t *req){
+ flashLED(75); // a little feedback to user
+ delay(75);
+ flashLED(75);
+ httpd_resp_set_type(req, "text/html");
+ httpd_resp_set_hdr(req, "Content-Encoding", "identity");
+ return httpd_resp_send(req, (const char *)streamviewer_html, streamviewer_html_len);
+}
+
static esp_err_t index_handler(httpd_req_t *req){
flashLED(75); // a little feedback to user
delay(75);
@@ -769,6 +791,19 @@ void startCameraServer(int hPort, int sPort){
.user_ctx = NULL
};
+ httpd_uri_t streamviewer_uri = {
+ .uri = "/view",
+ .method = HTTP_GET,
+ .handler = streamviewer_handler,
+ .user_ctx = NULL
+ };
+
+ httpd_uri_t info_uri = {
+ .uri = "/info",
+ .method = HTTP_GET,
+ .handler = info_handler,
+ .user_ctx = NULL
+ };
ra_filter_init(&ra_filter, 20);
@@ -809,6 +844,8 @@ void startCameraServer(int hPort, int sPort){
Serial.printf("Starting stream server on port: '%d'\n", config.server_port);
if (httpd_start(&stream_httpd, &config) == ESP_OK) {
httpd_register_uri_handler(stream_httpd, &stream_uri);
+ httpd_register_uri_handler(stream_httpd, &info_uri);
+ httpd_register_uri_handler(stream_httpd, &streamviewer_uri);
httpd_register_uri_handler(stream_httpd, &favicon_16x16_uri);
httpd_register_uri_handler(stream_httpd, &favicon_32x32_uri);
httpd_register_uri_handler(stream_httpd, &favicon_ico_uri);
diff --git a/css.h b/css.h
index 657e2d5..409c30a 100644
--- a/css.h
+++ b/css.h
@@ -34,7 +34,7 @@ section.main {
#menu {
display: none;
flex-wrap: nowrap;
- width: 340px;
+ width: 380px;
background: #363636;
padding: 8px;
border-radius: 4px;
@@ -63,10 +63,6 @@ figure {
figure img {
display: block;
-/*
- no max-width:
- width: 100%;
-*/
max-width: 100%;
width: auto;
height: auto;
diff --git a/index_ov2640.h b/index_ov2640.h
index 47038d2..d2535e6 100644
--- a/index_ov2640.h
+++ b/index_ov2640.h
@@ -8,7 +8,7 @@ const uint8_t index_ov2640_html[] = R"=====(
- ESP32 OV3660
+ ESP32 OV2640
@@ -19,15 +19,14 @@ const uint8_t index_ov2640_html[] = R"=====(
flex-wrap: nowrap;
align-items: stretch
}
-
-
+
figure img {
display: block;
max-width: 100%;
width: auto;
height: auto
}
-
+
figure {
padding: 0 0 0 0px;
margin: 0;
@@ -270,11 +269,11 @@ const uint8_t index_ov2640_html[] = R"=====(
@@ -307,7 +306,7 @@ const uint8_t index_ov2640_html[] = R"=====(
const streamButton = document.getElementById('toggle-stream')
const enrollButton = document.getElementById('face_enroll')
const closeButton = document.getElementById('close-stream')
- const streamLink = document.getElementById('stream_url')
+ const streamLink = document.getElementById('stream_link')
const detect = document.getElementById('face_detect')
const recognize = document.getElementById('face_recognize')
const framesize = document.getElementById('framesize')
@@ -341,7 +340,7 @@ const uint8_t index_ov2640_html[] = R"=====(
initialValue = el.value
el.value = value
}
-
+
if (updateRemote && initialValue !== value) {
updateConfig(el);
} else if(!updateRemote){
@@ -377,9 +376,9 @@ const uint8_t index_ov2640_html[] = R"=====(
applyRotation();
} else if(el.id === "stream_url"){
stream_url.innerHTML = value;
- stream_url.setAttribute("title", "Open raw stream URL in new window");
- stream_url.style.textDecoration = "underline";
- stream_url.style.cursor = "pointer";
+ stream_link.setAttribute("title", "Open stream viewer ( " + value + "view )");
+ stream_link.style.textDecoration = "underline";
+ stream_link.style.cursor = "pointer";
streamURL = value;
streamButton.setAttribute("title", `You can also browse to '${streamURL}' for a raw stream`);
show(streamGroup)
@@ -479,7 +478,7 @@ const uint8_t index_ov2640_html[] = R"=====(
// Attach actions to controls
streamLink.onclick = () => {
- window.open(streamURL, "_blank");
+ window.open(streamURL + "view", "_blank");
}
stillButton.onclick = () => {
@@ -529,7 +528,7 @@ const uint8_t index_ov2640_html[] = R"=====(
show(agcGain)
}
}
-
+
// Exposure
const aec = document.getElementById('aec')
const exposure = document.getElementById('aec_value-group')
@@ -537,7 +536,7 @@ const uint8_t index_ov2640_html[] = R"=====(
updateConfig(aec)
aec.checked ? hide(exposure) : show(exposure)
}
-
+
// AWB
const awb = document.getElementById('awb_gain')
const wb = document.getElementById('wb_mode-group')
@@ -545,7 +544,7 @@ const uint8_t index_ov2640_html[] = R"=====(
updateConfig(awb)
awb.checked ? show(wb) : hide(wb)
}
-
+
// Detection and framesize
rotate.onchange = () => {
applyRotation();
@@ -559,7 +558,7 @@ const uint8_t index_ov2640_html[] = R"=====(
updateValue(recognize, false)
}
}
-
+
detect.onchange = () => {
if (framesize.value > 5) {
alert("Please select CIF or lower resolution before enabling this feature!");
@@ -572,7 +571,7 @@ const uint8_t index_ov2640_html[] = R"=====(
updateValue(recognize, false)
}
}
-
+
recognize.onchange = () => {
if (framesize.value > 5) {
alert("Please select CIF or lower resolution before enabling this feature!");
diff --git a/index_ov3660.h b/index_ov3660.h
index 5b3c043..70126b3 100644
--- a/index_ov3660.h
+++ b/index_ov3660.h
@@ -19,15 +19,14 @@ const uint8_t index_ov3660_html[] = R"=====(
flex-wrap: nowrap;
align-items: stretch
}
-
-
+
figure img {
display: block;
max-width: 100%;
width: auto;
height: auto
}
-
+
figure {
padding: 0 0 0 0px;
margin: 0;
@@ -283,11 +282,11 @@ const uint8_t index_ov3660_html[] = R"=====(
@@ -320,7 +319,7 @@ const uint8_t index_ov3660_html[] = R"=====(
const streamButton = document.getElementById('toggle-stream')
const enrollButton = document.getElementById('face_enroll')
const closeButton = document.getElementById('close-stream')
- const streamLink = document.getElementById('stream_url')
+ const streamLink = document.getElementById('stream_link')
const detect = document.getElementById('face_detect')
const recognize = document.getElementById('face_recognize')
const framesize = document.getElementById('framesize')
@@ -354,7 +353,7 @@ const uint8_t index_ov3660_html[] = R"=====(
initialValue = el.value
el.value = value
}
-
+
if (updateRemote && initialValue !== value) {
updateConfig(el);
} else if(!updateRemote){
@@ -388,9 +387,9 @@ const uint8_t index_ov3660_html[] = R"=====(
applyRotation();
} else if(el.id === "stream_url"){
stream_url.innerHTML = value;
- stream_url.setAttribute("title", "Open raw stream URL in new window");
- stream_url.style.textDecoration = "underline";
- stream_url.style.cursor = "pointer";
+ stream_link.setAttribute("title", "Open stream viewer ( " + value + "view )");
+ stream_link.style.textDecoration = "underline";
+ stream_link.style.cursor = "pointer";
streamURL = value;
streamButton.setAttribute("title", `You can also browse to '${streamURL}' for a raw stream`);
show(streamGroup)
@@ -490,7 +489,7 @@ const uint8_t index_ov3660_html[] = R"=====(
// Attach actions to controls
streamLink.onclick = () => {
- window.open(streamURL, "_blank");
+ window.open(streamURL + "view", "_blank");
}
stillButton.onclick = () => {
@@ -537,7 +536,7 @@ const uint8_t index_ov3660_html[] = R"=====(
show(agcGain)
}
}
-
+
// Exposure
const aec = document.getElementById('aec')
const exposure = document.getElementById('aec_value-group')
@@ -545,7 +544,7 @@ const uint8_t index_ov3660_html[] = R"=====(
updateConfig(aec)
aec.checked ? hide(exposure) : show(exposure)
}
-
+
// AWB
const awb = document.getElementById('awb_gain')
const wb = document.getElementById('wb_mode-group')
@@ -553,7 +552,7 @@ const uint8_t index_ov3660_html[] = R"=====(
updateConfig(awb)
awb.checked ? show(wb) : hide(wb)
}
-
+
// Detection and framesize
rotate.onchange = () => {
applyRotation();
@@ -567,7 +566,7 @@ const uint8_t index_ov3660_html[] = R"=====(
updateValue(recognize, false)
}
}
-
+
detect.onchange = () => {
if (framesize.value > 5) {
alert("Please select CIF or lower resolution before enabling this feature!");
@@ -580,7 +579,7 @@ const uint8_t index_ov3660_html[] = R"=====(
updateValue(recognize, false)
}
}
-
+
recognize.onchange = () => {
if (framesize.value > 5) {
alert("Please select CIF or lower resolution before enabling this feature!");
@@ -597,7 +596,7 @@ const uint8_t index_ov3660_html[] = R"=====(
}
swapButton.onclick = () => {
- window.open('/','_self');
+ window.open('/view','_self');
}
})
diff --git a/miniviewer.h b/viewers.h
similarity index 61%
rename from miniviewer.h
rename to viewers.h
index 71b0664..3276510 100644
--- a/miniviewer.h
+++ b/viewers.h
@@ -1,5 +1,8 @@
-//File: index_ov2640.html
-const uint8_t miniviewer_html[] = R"=====(
+/*
+ * Miniviewer and streamviewer
+ */
+
+ const uint8_t miniviewer_html[] = R"=====(
@@ -110,7 +113,7 @@ const uint8_t miniviewer_html[] = R"=====(
initialValue = el.value
el.value = value
}
-
+
if (updateRemote && initialValue !== value) {
updateConfig(el);
} else if(!updateRemote){
@@ -279,3 +282,185 @@ const uint8_t miniviewer_html[] = R"=====(
)=====";
size_t miniviewer_html_len = sizeof(miniviewer_html);
+
+/* Stream Viewer */
+
+ const uint8_t streamviewer_html[] = R"=====(
+
+
+
+
+
+ ESP32-CAM StreamViewer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+)=====";
+
+size_t streamviewer_html_len = sizeof(streamviewer_html);