mirror of
https://github.com/easytarget/esp32-cam-webserver.git
synced 2024-02-16 18:18:24 +08:00
Ui timers (#78)
Adds a 1-minute auto-refresh to the dump page When a reboot is triggered from the UI better feedback is given and a timer started to refresh the page after 30s The reboot is now done by a watchdog timer to ensure a hard reboot. Error page: - Reboots seem to occasionally leave the camera hardware in a bad state (I2C comms failed, it's a common problem with no real solutions yet) - I now catch these errors and still start the web server; giving an error page that advises a hard restart (power off/on). But the esp module will also reboot once every minute since these errors also tend to spontaneously clear after a while.
This commit is contained in:
10
README.md
10
README.md
@ -31,7 +31,7 @@ https://wiki.ai-thinker.com/esp32-cam
|
||||
|
||||
## Troubleshooting:
|
||||
|
||||
Please read this excellent guide for help with all the common issues:
|
||||
Please read this excellent guide for help with some common issues seen with the camera modules:
|
||||
https://randomnerdtutorials.com/esp32-cam-troubleshooting-guide/
|
||||
|
||||
## Setup:
|
||||
@ -102,12 +102,6 @@ Contributions are welcome; please see the [Contribution guidelines](CONTRIBUTING
|
||||
|
||||
Time allowing; my Current plan is:
|
||||
|
||||
V3 Options, UI and server enhancements;
|
||||
* All the primary config options moved to the `myconfig.h` file.
|
||||
* Miniviewer, favicons
|
||||
* UI now shows stream links and build info
|
||||
* Nearly Complete
|
||||
|
||||
V4 Remove face recognition entirely;
|
||||
* Dont try to make it optional, this is a code and maintenance nightmare. V3 can be maintained on a branch for those who need it.
|
||||
* Investigate using SD card to capture images
|
||||
@ -115,5 +109,3 @@ V4 Remove face recognition entirely;
|
||||
* UI Skinning/Theming
|
||||
|
||||
You can check the [enhancement list](https://github.com/easytarget/esp32-cam-webserver/issues?q=is%3Aissue+label%3Aenhancement) (past and present), and add any thoghts you may have there. Things that have occurred to me are, in no particular order:
|
||||
* The module has a SD/TF card slot; this is currently unused, but I would like to add the ability to store snapshots; recording Video at low resolution may be possible, but the card interface is too slow for HD video as far as I know.
|
||||
* Remove face rcognition to save a Mb+ of code space and then implement over the air updates.
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
// Original Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -11,11 +11,14 @@
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "esp_http_server.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_camera.h"
|
||||
#include "img_converters.h"
|
||||
#include "Arduino.h"
|
||||
|
||||
#include <esp_http_server.h>
|
||||
#include <esp_timer.h>
|
||||
#include <esp_camera.h>
|
||||
#include <esp_int_wdt.h>
|
||||
#include <esp_task_wdt.h>
|
||||
#include <img_converters.h>
|
||||
#include <Arduino.h>
|
||||
#include <WiFi.h>
|
||||
|
||||
#include "index_ov2640.h"
|
||||
@ -52,6 +55,7 @@ extern bool autoLamp;
|
||||
extern int8_t detection_enabled;
|
||||
extern int8_t recognition_enabled;
|
||||
extern bool filesystem;
|
||||
extern String critERR;
|
||||
extern bool debugData;
|
||||
extern int sketchSize;
|
||||
extern int sketchSpace;
|
||||
@ -622,14 +626,18 @@ static esp_err_t cmd_handler(httpd_req_t *req){
|
||||
if (filesystem) removePrefs(SPIFFS);
|
||||
}
|
||||
else if(!strcmp(variable, "reboot")) {
|
||||
esp_task_wdt_init(3,true); // schedule a a watchdog panic event for 3 seconds in the future
|
||||
esp_task_wdt_add(NULL);
|
||||
periph_module_disable(PERIPH_I2C0_MODULE); // try to shut I2C down properly
|
||||
periph_module_disable(PERIPH_I2C1_MODULE);
|
||||
periph_module_reset(PERIPH_I2C0_MODULE);
|
||||
periph_module_reset(PERIPH_I2C1_MODULE);
|
||||
Serial.print("REBOOT requested");
|
||||
for (int i=0; i<20; i++) {
|
||||
while(true) {
|
||||
flashLED(50);
|
||||
delay(150);
|
||||
Serial.print('.');
|
||||
}
|
||||
Serial.printf(" Thats all folks!\n\n");
|
||||
ESP.restart();
|
||||
}
|
||||
else {
|
||||
res = -1;
|
||||
@ -730,7 +738,7 @@ static esp_err_t dump_handler(httpd_req_t *req){
|
||||
Serial.println("\nDump Requested");
|
||||
Serial.print("Preferences file: ");
|
||||
dumpPrefs(SPIFFS);
|
||||
static char dumpOut[1200] = "";
|
||||
static char dumpOut[2000] = "";
|
||||
char * d = dumpOut;
|
||||
// Header
|
||||
d+= sprintf(d,"<html><head><meta charset=\"utf-8\">\n");
|
||||
@ -739,9 +747,14 @@ static esp_err_t dump_handler(httpd_req_t *req){
|
||||
d+= sprintf(d,"<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/favicon-32x32.png\">\n");
|
||||
d+= sprintf(d,"<link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/favicon-16x16.png\">\n");
|
||||
d+= sprintf(d,"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\">\n");
|
||||
d+= sprintf(d,"</head>\n<body>\n");
|
||||
d+= sprintf(d,"</head>\n");
|
||||
d+= sprintf(d,"<body>\n");
|
||||
d+= sprintf(d,"<img src=\"/logo.svg\" style=\"position: relative; float: right;\">\n");
|
||||
d+= sprintf(d,"<h1>ESP32 Cam Webserver</h1>\n");
|
||||
if (critERR.length() > 0) {
|
||||
d+= sprintf(d,"%s<hr>\n", critERR.c_str());
|
||||
Serial.printf("\n\nA critical error has occurred when initialising Hardware, see startup megssages\n\n\n");
|
||||
}
|
||||
d+= sprintf(d,"<h1>ESP32 Cam Webserver</h1>\n");
|
||||
// Module
|
||||
d+= sprintf(d,"Name: %s<br>\n", myName);
|
||||
Serial.printf("Name: %s\n", myName);
|
||||
@ -817,9 +830,12 @@ static esp_err_t dump_handler(httpd_req_t *req){
|
||||
|
||||
// Footer
|
||||
d+= sprintf(d,"<br><div class=\"input-group\">\n");
|
||||
d+= sprintf(d,"<button title=\"Refresh this page\" onclick=\"location.replace(document.URL)\">Refresh</button>\n");
|
||||
d+= sprintf(d,"<button title=\"Instant Refresh; the page reloads every minute anyway\" onclick=\"location.replace(document.URL)\">Refresh</button>\n");
|
||||
d+= sprintf(d,"<button title=\"Close this page\" onclick=\"javascript:window.close()\">Close</button>\n");
|
||||
d+= sprintf(d,"</div>\n</body>\n</html>\n");
|
||||
d+= sprintf(d,"</div>\n</body>\n");
|
||||
// A javascript timer to refresh the page every minute.
|
||||
d+= sprintf(d,"<script>\nsetTimeout(function(){\nlocation.replace(document.URL);\n}, 60000);\n");
|
||||
d+= sprintf(d,"</script>\n</html>\n");
|
||||
*d++ = 0;
|
||||
httpd_resp_set_type(req, "text/html");
|
||||
httpd_resp_set_hdr(req, "Content-Encoding", "identity");
|
||||
@ -840,6 +856,22 @@ static esp_err_t streamviewer_handler(httpd_req_t *req){
|
||||
return httpd_resp_send(req, (const char *)streamviewer_html, streamviewer_html_len);
|
||||
}
|
||||
|
||||
static esp_err_t error_handler(httpd_req_t *req){
|
||||
flashLED(75);
|
||||
Serial.println("Sending Error page");
|
||||
std::string s(error_html);
|
||||
size_t index;
|
||||
while ((index = s.find("<APPURL>")) != std::string::npos)
|
||||
s.replace(index, strlen("<APPURL>"), httpURL);
|
||||
while ((index = s.find("<CAMNAME>")) != std::string::npos)
|
||||
s.replace(index, strlen("<CAMNAME>"), myName);
|
||||
while ((index = s.find("<ERRORTEXT>")) != std::string::npos)
|
||||
s.replace(index, strlen("<ERRORTEXT>"), critERR.c_str());
|
||||
httpd_resp_set_type(req, "text/html");
|
||||
httpd_resp_set_hdr(req, "Content-Encoding", "identity");
|
||||
return httpd_resp_send(req, (const char *)s.c_str(), s.length());
|
||||
}
|
||||
|
||||
static esp_err_t index_handler(httpd_req_t *req){
|
||||
char* buf;
|
||||
size_t buf_len;
|
||||
@ -994,6 +1026,18 @@ void startCameraServer(int hPort, int sPort){
|
||||
.handler = info_handler,
|
||||
.user_ctx = NULL
|
||||
};
|
||||
httpd_uri_t error_uri = {
|
||||
.uri = "/",
|
||||
.method = HTTP_GET,
|
||||
.handler = error_handler,
|
||||
.user_ctx = NULL
|
||||
};
|
||||
httpd_uri_t viewerror_uri = {
|
||||
.uri = "/view",
|
||||
.method = HTTP_GET,
|
||||
.handler = error_handler,
|
||||
.user_ctx = NULL
|
||||
};
|
||||
|
||||
// Filter list; used during face detection
|
||||
ra_filter_init(&ra_filter, 20);
|
||||
@ -1017,15 +1061,20 @@ void startCameraServer(int hPort, int sPort){
|
||||
face_id_init(&id_list, FACE_ID_SAVE_NUMBER, ENROLL_CONFIRM_TIMES);
|
||||
// The size of the allocated data block; calculated in dl_lib_calloc()
|
||||
|
||||
|
||||
// Request Handlers; config.max_uri_handlers (above) must be >= the number of handlers
|
||||
config.server_port = hPort;
|
||||
config.ctrl_port = hPort;
|
||||
Serial.printf("Starting web server on port: '%d'\n", config.server_port);
|
||||
if (httpd_start(&camera_httpd, &config) == ESP_OK) {
|
||||
// Note; config.max_uri_handlers (above) must be >= the number of handlers
|
||||
httpd_register_uri_handler(camera_httpd, &index_uri);
|
||||
httpd_register_uri_handler(camera_httpd, &cmd_uri);
|
||||
httpd_register_uri_handler(camera_httpd, &status_uri);
|
||||
httpd_register_uri_handler(camera_httpd, &capture_uri);
|
||||
if (critERR.length() > 0) {
|
||||
httpd_register_uri_handler(camera_httpd, &error_uri);
|
||||
} else {
|
||||
httpd_register_uri_handler(camera_httpd, &index_uri);
|
||||
httpd_register_uri_handler(camera_httpd, &cmd_uri);
|
||||
httpd_register_uri_handler(camera_httpd, &status_uri);
|
||||
httpd_register_uri_handler(camera_httpd, &capture_uri);
|
||||
}
|
||||
httpd_register_uri_handler(camera_httpd, &style_uri);
|
||||
httpd_register_uri_handler(camera_httpd, &favicon_16x16_uri);
|
||||
httpd_register_uri_handler(camera_httpd, &favicon_32x32_uri);
|
||||
@ -1034,14 +1083,18 @@ void startCameraServer(int hPort, int sPort){
|
||||
httpd_register_uri_handler(camera_httpd, &dump_uri);
|
||||
}
|
||||
|
||||
|
||||
config.server_port = sPort;
|
||||
config.ctrl_port = 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);
|
||||
if (critERR.length() > 0) {
|
||||
httpd_register_uri_handler(camera_httpd, &error_uri);
|
||||
httpd_register_uri_handler(camera_httpd, &viewerror_uri);
|
||||
} else {
|
||||
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);
|
||||
|
@ -1,8 +1,11 @@
|
||||
#include "esp_camera.h"
|
||||
#include <esp_camera.h>
|
||||
#include <esp_int_wdt.h>
|
||||
#include <esp_task_wdt.h>
|
||||
#include <WiFi.h>
|
||||
#include <DNSServer.h>
|
||||
#include "src/parsebytes.h"
|
||||
|
||||
|
||||
/* This sketch is a extension/expansion/reork of the 'official' ESP32 Camera example
|
||||
* sketch from Expressif:
|
||||
* https://github.com/espressif/arduino-esp32/tree/master/libraries/ESP32/examples/Camera/CameraWebServer
|
||||
@ -169,6 +172,10 @@ const int pwmMax = pow(2,pwmresolution)-1;
|
||||
int8_t recognition_enabled = 0;
|
||||
#endif
|
||||
|
||||
// Critical error string; if set during init (camera hardware failure) it
|
||||
// will be returned for all http requests
|
||||
String critERR = "";
|
||||
|
||||
// Debug Data for stream and capture
|
||||
#if defined(DEBUG_DEFAULT_ON)
|
||||
bool debugData = true;
|
||||
@ -185,7 +192,7 @@ void flashLED(int flashtime) {
|
||||
#else
|
||||
return; // No notifcation LED, do nothing, no delay
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Lamp Control
|
||||
void setLamp(int newVal) {
|
||||
@ -381,6 +388,8 @@ void WifiSetup() {
|
||||
}
|
||||
|
||||
void setup() {
|
||||
// This might reduce boot loops caused by camera init failures when soft rebooting
|
||||
// See, for instance, https://esp32.com/viewtopic.php?t=3152
|
||||
Serial.begin(115200);
|
||||
Serial.setDebugOutput(true);
|
||||
Serial.println();
|
||||
@ -443,96 +452,108 @@ void setup() {
|
||||
|
||||
// camera init
|
||||
esp_err_t err = esp_camera_init(&config);
|
||||
if (err == ESP_OK) {
|
||||
Serial.println("Camera init succeeded");
|
||||
} else {
|
||||
if (err != ESP_OK) {
|
||||
delay(100); // need a delay here or the next serial o/p gets missed
|
||||
Serial.println("Halted: Camera sensor failed to initialise");
|
||||
Serial.println("Will reboot to try again in 10s\n");
|
||||
delay(10000);
|
||||
ESP.restart();
|
||||
}
|
||||
sensor_t * s = esp_camera_sensor_get();
|
||||
|
||||
// Dump camera module, warn for unsupported modules.
|
||||
switch (s->id.PID) {
|
||||
case OV9650_PID: Serial.println("WARNING: OV9650 camera module is not properly supported, will fallback to OV2640 operation"); break;
|
||||
case OV7725_PID: Serial.println("WARNING: OV7725 camera module is not properly supported, will fallback to OV2640 operation"); break;
|
||||
case OV2640_PID: Serial.println("OV2640 camera module detected"); break;
|
||||
case OV3660_PID: Serial.println("OV3660 camera module detected"); break;
|
||||
default: Serial.println("WARNING: Camera module is unknown and not properly supported, will fallback to OV2640 operation");
|
||||
}
|
||||
|
||||
// OV3660 initial sensors are flipped vertically and colors are a bit saturated
|
||||
if (s->id.PID == OV3660_PID) {
|
||||
s->set_vflip(s, 1); //flip it back
|
||||
s->set_brightness(s, 1); //up the blightness just a bit
|
||||
s->set_saturation(s, -2); //lower the saturation
|
||||
}
|
||||
|
||||
// M5 Stack Wide has special needs
|
||||
#if defined(CAMERA_MODEL_M5STACK_WIDE)
|
||||
s->set_vflip(s, 1);
|
||||
s->set_hmirror(s, 1);
|
||||
#endif
|
||||
|
||||
// Config can override mirror and flip
|
||||
#if defined(H_MIRROR)
|
||||
s->set_hmirror(s, H_MIRROR);
|
||||
#endif
|
||||
#if defined(V_FLIP)
|
||||
s->set_vflip(s, V_FLIP);
|
||||
#endif
|
||||
|
||||
// set initial frame rate
|
||||
#if defined(DEFAULT_RESOLUTION)
|
||||
s->set_framesize(s, DEFAULT_RESOLUTION);
|
||||
#else
|
||||
s->set_framesize(s, FRAMESIZE_SVGA);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Add any other defaults you want to apply at startup here:
|
||||
* uncomment the line and set the value as desired (see the comments)
|
||||
*
|
||||
* these are defined in the esp headers here:
|
||||
* https://github.com/espressif/esp32-camera/blob/master/driver/include/sensor.h#L149
|
||||
*/
|
||||
|
||||
//s->set_framesize(s, FRAMESIZE_SVGA); // FRAMESIZE_[QQVGA|HQVGA|QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA|QXGA(ov3660)]);
|
||||
//s->set_quality(s, val); // 10 to 63
|
||||
//s->set_brightness(s, 0); // -2 to 2
|
||||
//s->set_contrast(s, 0); // -2 to 2
|
||||
//s->set_saturation(s, 0); // -2 to 2
|
||||
//s->set_special_effect(s, 0); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
|
||||
//s->set_whitebal(s, 1); // aka 'awb' in the UI; 0 = disable , 1 = enable
|
||||
//s->set_awb_gain(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_wb_mode(s, 0); // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
|
||||
//s->set_exposure_ctrl(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_aec2(s, 0); // 0 = disable , 1 = enable
|
||||
//s->set_ae_level(s, 0); // -2 to 2
|
||||
//s->set_aec_value(s, 300); // 0 to 1200
|
||||
//s->set_gain_ctrl(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_agc_gain(s, 0); // 0 to 30
|
||||
//s->set_gainceiling(s, (gainceiling_t)0); // 0 to 6
|
||||
//s->set_bpc(s, 0); // 0 = disable , 1 = enable
|
||||
//s->set_wpc(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_raw_gma(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_lenc(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_hmirror(s, 0); // 0 = disable , 1 = enable
|
||||
//s->set_vflip(s, 0); // 0 = disable , 1 = enable
|
||||
//s->set_dcw(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_colorbar(s, 0); // 0 = disable , 1 = enable
|
||||
|
||||
// We now have camera with default init
|
||||
// check for saved preferences and apply them
|
||||
|
||||
if (filesystem) {
|
||||
filesystemStart();
|
||||
loadPrefs(SPIFFS);
|
||||
loadFaceDB(SPIFFS);
|
||||
Serial.printf("\n\nCRITICAL FAILURE: Camera sensor failed to initialise.\n\n");
|
||||
Serial.printf("A full (hard, power off/on) reboot will probably be needed to recover from this.\n");
|
||||
Serial.printf("Meanwhile; this unit will reboot in 1 minute since these errors sometime clear automatically\n");
|
||||
// Reset the I2C bus.. may help when rebooting.
|
||||
periph_module_disable(PERIPH_I2C0_MODULE); // try to shut I2C down properly in case that is the problem
|
||||
periph_module_disable(PERIPH_I2C1_MODULE);
|
||||
periph_module_reset(PERIPH_I2C0_MODULE);
|
||||
periph_module_reset(PERIPH_I2C1_MODULE);
|
||||
// And set the error text for the UI
|
||||
critERR = "<h1>Error!</h1><hr><p>Camera module failed to initialise!</p><p>Please reset (power off/on) the camera.</p>";
|
||||
critERR += "<p>We will continue to reboot once per minute since this error sometimes clears automatically.</p>";
|
||||
// Start a 60 second watchdog timer
|
||||
esp_task_wdt_init(60,true);
|
||||
esp_task_wdt_add(NULL);
|
||||
} else {
|
||||
Serial.println("No Internal Filesystem, cannot save preferences or face DB");
|
||||
Serial.println("Camera init succeeded");
|
||||
|
||||
// Get a reference to the sensor
|
||||
sensor_t * s = esp_camera_sensor_get();
|
||||
|
||||
// Dump camera module, warn for unsupported modules.
|
||||
switch (s->id.PID) {
|
||||
case OV9650_PID: Serial.println("WARNING: OV9650 camera module is not properly supported, will fallback to OV2640 operation"); break;
|
||||
case OV7725_PID: Serial.println("WARNING: OV7725 camera module is not properly supported, will fallback to OV2640 operation"); break;
|
||||
case OV2640_PID: Serial.println("OV2640 camera module detected"); break;
|
||||
case OV3660_PID: Serial.println("OV3660 camera module detected"); break;
|
||||
default: Serial.println("WARNING: Camera module is unknown and not properly supported, will fallback to OV2640 operation");
|
||||
}
|
||||
|
||||
// OV3660 initial sensors are flipped vertically and colors are a bit saturated
|
||||
if (s->id.PID == OV3660_PID) {
|
||||
s->set_vflip(s, 1); //flip it back
|
||||
s->set_brightness(s, 1); //up the blightness just a bit
|
||||
s->set_saturation(s, -2); //lower the saturation
|
||||
}
|
||||
|
||||
// M5 Stack Wide has special needs
|
||||
#if defined(CAMERA_MODEL_M5STACK_WIDE)
|
||||
s->set_vflip(s, 1);
|
||||
s->set_hmirror(s, 1);
|
||||
#endif
|
||||
|
||||
// Config can override mirror and flip
|
||||
#if defined(H_MIRROR)
|
||||
s->set_hmirror(s, H_MIRROR);
|
||||
#endif
|
||||
#if defined(V_FLIP)
|
||||
s->set_vflip(s, V_FLIP);
|
||||
#endif
|
||||
|
||||
// set initial frame rate
|
||||
#if defined(DEFAULT_RESOLUTION)
|
||||
s->set_framesize(s, DEFAULT_RESOLUTION);
|
||||
#else
|
||||
s->set_framesize(s, FRAMESIZE_SVGA);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Add any other defaults you want to apply at startup here:
|
||||
* uncomment the line and set the value as desired (see the comments)
|
||||
*
|
||||
* these are defined in the esp headers here:
|
||||
* https://github.com/espressif/esp32-camera/blob/master/driver/include/sensor.h#L149
|
||||
*/
|
||||
|
||||
//s->set_framesize(s, FRAMESIZE_SVGA); // FRAMESIZE_[QQVGA|HQVGA|QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA|QXGA(ov3660)]);
|
||||
//s->set_quality(s, val); // 10 to 63
|
||||
//s->set_brightness(s, 0); // -2 to 2
|
||||
//s->set_contrast(s, 0); // -2 to 2
|
||||
//s->set_saturation(s, 0); // -2 to 2
|
||||
//s->set_special_effect(s, 0); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
|
||||
//s->set_whitebal(s, 1); // aka 'awb' in the UI; 0 = disable , 1 = enable
|
||||
//s->set_awb_gain(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_wb_mode(s, 0); // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
|
||||
//s->set_exposure_ctrl(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_aec2(s, 0); // 0 = disable , 1 = enable
|
||||
//s->set_ae_level(s, 0); // -2 to 2
|
||||
//s->set_aec_value(s, 300); // 0 to 1200
|
||||
//s->set_gain_ctrl(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_agc_gain(s, 0); // 0 to 30
|
||||
//s->set_gainceiling(s, (gainceiling_t)0); // 0 to 6
|
||||
//s->set_bpc(s, 0); // 0 = disable , 1 = enable
|
||||
//s->set_wpc(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_raw_gma(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_lenc(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_hmirror(s, 0); // 0 = disable , 1 = enable
|
||||
//s->set_vflip(s, 0); // 0 = disable , 1 = enable
|
||||
//s->set_dcw(s, 1); // 0 = disable , 1 = enable
|
||||
//s->set_colorbar(s, 0); // 0 = disable , 1 = enable
|
||||
|
||||
// We now have camera with default init
|
||||
// check for saved preferences and apply them
|
||||
|
||||
if (filesystem) {
|
||||
filesystemStart();
|
||||
loadPrefs(SPIFFS);
|
||||
loadFaceDB(SPIFFS);
|
||||
} else {
|
||||
Serial.println("No Internal Filesystem, cannot save preferences or face DB");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -573,12 +594,15 @@ void setup() {
|
||||
}
|
||||
sprintf(streamURL, "http://%d.%d.%d.%d:%d/", ip[0], ip[1], ip[2], ip[3], streamPort);
|
||||
#endif
|
||||
Serial.printf("\nCamera Ready!\nUse '%s' to connect\n", httpURL);
|
||||
Serial.printf("Stream viewer available at '%sview'\n", streamURL);
|
||||
Serial.printf("Raw stream URL is '%s'\n", streamURL);
|
||||
|
||||
if (debugData) Serial.println("Camera debug data is enabled (send any char to disable)");
|
||||
else Serial.println("Camera debug data is disabled (send any char to enable)");
|
||||
if (critERR.length() == 0) {
|
||||
Serial.printf("\nCamera Ready!\nUse '%s' to connect\n", httpURL);
|
||||
Serial.printf("Stream viewer available at '%sview'\n", streamURL);
|
||||
Serial.printf("Raw stream URL is '%s'\n", streamURL);
|
||||
if (debugData) Serial.println("Camera debug data is enabled (send any char to disable)");
|
||||
else Serial.println("Camera debug data is disabled (send any char to enable)");
|
||||
} else {
|
||||
Serial.printf("\nCamera unavailable due to initialisation errors.\n\n");
|
||||
}
|
||||
|
||||
// Used when dumping status; these are slow functions, so just do them once during startup
|
||||
sketchSize = ESP.getSketchSize();
|
||||
|
@ -435,7 +435,7 @@ const uint8_t streamviewer_html[] = R"=====(<!doctype html>
|
||||
|
||||
size_t streamviewer_html_len = sizeof(streamviewer_html)-1;
|
||||
|
||||
/* Prototype Captive Portal page
|
||||
/* Captive Portal page
|
||||
we replace the <> delimited strings with correct values as it is served */
|
||||
|
||||
const std::string portal_html = R"=====(<!doctype html>
|
||||
@ -463,3 +463,28 @@ const std::string portal_html = R"=====(<!doctype html>
|
||||
<a href="<APPURL>dump" title="Information dump page" target="_blank">Camera Details</a><br>
|
||||
</body>
|
||||
</html>)=====";
|
||||
|
||||
/* Error page
|
||||
we replace the <> delimited strings with correct values as it is served */
|
||||
|
||||
const std::string error_html = R"=====(<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title id="title"><CAMNAME> - Error</title>
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
|
||||
<link rel="ico\" type="image/png" sizes="16x16" href="/favicon-16x16.png">
|
||||
<link rel="stylesheet" type="text/css" href="<APPURL>style.css">
|
||||
</head>
|
||||
<body style="text-align: center;">
|
||||
<img src="<APPURL>logo.svg" style="position: relative; float: right;">
|
||||
<h1><CAMNAME></h1>
|
||||
<ERRORTEXT>
|
||||
</body>
|
||||
<script>
|
||||
setTimeout(function(){
|
||||
location.replace(document.URL);
|
||||
}, 60000);
|
||||
</script>
|
||||
</html>)=====";
|
||||
|
@ -293,6 +293,7 @@ const uint8_t index_ov2640_html[] = R"=====(<!doctype html>
|
||||
var streamURL = 'Undefined';
|
||||
var viewerURL = 'Undefined';
|
||||
|
||||
const header = document.getElementById('logo')
|
||||
const settings = document.getElementById('sidebar')
|
||||
const waitSettings = document.getElementById('wait-settings')
|
||||
const lampGroup = document.getElementById('lamp-group')
|
||||
@ -632,7 +633,12 @@ const uint8_t index_ov2640_html[] = R"=====(<!doctype html>
|
||||
if (confirm("Reboot the Camera Module?")) {
|
||||
updateConfig(rebootButton);
|
||||
// Some sort of countdown here?
|
||||
location.reload();
|
||||
hide(settings);
|
||||
hide(viewContainer);
|
||||
header.innerHTML = '<h1>Rebooting!</h1><hr>Page will reload after 30 seconds.';
|
||||
setTimeout(function() {
|
||||
location.replace(document.URL);
|
||||
}, 30000);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user