mirror of
https://github.com/easytarget/esp32-cam-webserver.git
synced 2024-02-16 18:18:24 +08:00
Xclock in gui and stream stop button
This commit is contained in:
@ -63,7 +63,7 @@ extern int sketchSpace;
|
||||
extern String sketchMD5;
|
||||
extern bool otaEnabled;
|
||||
extern char otaPassword[];
|
||||
extern unsigned long xclkFreqHz;
|
||||
extern unsigned long xclk;
|
||||
|
||||
typedef struct {
|
||||
httpd_req_t *req;
|
||||
@ -78,6 +78,9 @@ static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %
|
||||
httpd_handle_t stream_httpd = NULL;
|
||||
httpd_handle_t camera_httpd = NULL;
|
||||
|
||||
// Flag that can be set to kill all active streams
|
||||
bool streamKill;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -141,10 +144,9 @@ void serialDump() {
|
||||
int upSec = sec % 60;
|
||||
int McuTc = (temprature_sens_read() - 32) / 1.8; // celsius
|
||||
int McuTf = temprature_sens_read(); // fahrenheit
|
||||
float xclk = xclkFreqHz/1000000;
|
||||
Serial.printf("System up: %" PRId64 ":%02i:%02i:%02i (d:h:m:s)\r\n", upDays, upHours, upMin, upSec);
|
||||
Serial.printf("Active streams: %i, Previous streams: %lu, Images captured: %lu\r\n", streamCount, streamsServed, imagesServed);
|
||||
Serial.printf("CPU Freq: %i MHz, Xclk Freq: %.1f MHz\r\n", ESP.getCpuFreqMHz(), xclk);
|
||||
Serial.printf("CPU Freq: %i MHz, Xclk Freq: %i MHz\r\n", ESP.getCpuFreqMHz(), xclk);
|
||||
Serial.printf("MCU temperature : %i C, %i F (approximate)\r\n", McuTc, McuTf);
|
||||
Serial.printf("Heap: %i, free: %i, min free: %i, max block: %i\r\n", ESP.getHeapSize(), ESP.getFreeHeap(), ESP.getMinFreeHeap(), ESP.getMaxAllocHeap());
|
||||
if(psramFound()) {
|
||||
@ -223,6 +225,8 @@ static esp_err_t stream_handler(httpd_req_t *req){
|
||||
uint8_t * _jpg_buf = NULL;
|
||||
char * part_buf[64];
|
||||
|
||||
streamKill = false;
|
||||
|
||||
Serial.println("Stream requested");
|
||||
if (autoLamp && (lampVal != -1)) setLamp(lampVal);
|
||||
streamCount = 1; // at present we only have one stream handler, so values are 0 or 1..
|
||||
@ -277,7 +281,7 @@ static esp_err_t stream_handler(httpd_req_t *req){
|
||||
free(_jpg_buf);
|
||||
_jpg_buf = NULL;
|
||||
}
|
||||
if(res != ESP_OK){
|
||||
if((res != ESP_OK) || streamKill){
|
||||
// This is the only exit point from the stream loop.
|
||||
// We end the stream here only if a Hard failure has been encountered or the connection has been interrupted.
|
||||
break;
|
||||
@ -341,6 +345,7 @@ static esp_err_t cmd_handler(httpd_req_t *req){
|
||||
if(s->pixformat == PIXFORMAT_JPEG) res = s->set_framesize(s, (framesize_t)val);
|
||||
}
|
||||
else if(!strcmp(variable, "quality")) res = s->set_quality(s, val);
|
||||
else if(!strcmp(variable, "xclk")) { xclk = val; res = s->set_xclk(s, LEDC_TIMER_0, val); }
|
||||
else if(!strcmp(variable, "contrast")) res = s->set_contrast(s, val);
|
||||
else if(!strcmp(variable, "brightness")) res = s->set_brightness(s, val);
|
||||
else if(!strcmp(variable, "saturation")) res = s->set_saturation(s, val);
|
||||
@ -421,6 +426,7 @@ static esp_err_t status_handler(httpd_req_t *req){
|
||||
p+=sprintf(p, "\"autolamp\":%d,", autoLamp);
|
||||
p+=sprintf(p, "\"framesize\":%u,", s->status.framesize);
|
||||
p+=sprintf(p, "\"quality\":%u,", s->status.quality);
|
||||
p+=sprintf(p, "\"xclk\":%u,", xclk);
|
||||
p+=sprintf(p, "\"brightness\":%d,", s->status.brightness);
|
||||
p+=sprintf(p, "\"contrast\":%d,", s->status.contrast);
|
||||
p+=sprintf(p, "\"saturation\":%d,", s->status.saturation);
|
||||
@ -495,7 +501,7 @@ static esp_err_t logo_svg_handler(httpd_req_t *req){
|
||||
|
||||
static esp_err_t dump_handler(httpd_req_t *req){
|
||||
flashLED(75);
|
||||
Serial.println("\r\nDump Requested via Web");
|
||||
Serial.println("\r\nDump requested via Web");
|
||||
serialDump();
|
||||
static char dumpOut[2000] = "";
|
||||
char * d = dumpOut;
|
||||
@ -566,11 +572,10 @@ static esp_err_t dump_handler(httpd_req_t *req){
|
||||
int upSec = sec % 60;
|
||||
int McuTc = (temprature_sens_read() - 32) / 1.8; // celsius
|
||||
int McuTf = temprature_sens_read(); // fahrenheit
|
||||
float xclk = xclkFreqHz/1000000;
|
||||
|
||||
d+= sprintf(d,"Up: %" PRId64 ":%02i:%02i:%02i (d:h:m:s)<br>\n", upDays, upHours, upMin, upSec);
|
||||
d+= sprintf(d,"Active streams: %i, Previous streams: %lu, Images captured: %lu<br>\n", streamCount, streamsServed, imagesServed);
|
||||
d+= sprintf(d,"CPU Freq: %i MHz, Xclk Freq: %.1f MHz<br>\n", ESP.getCpuFreqMHz(), xclk);
|
||||
d+= sprintf(d,"CPU Freq: %i MHz, Xclk Freq: %i MHz<br>\n", ESP.getCpuFreqMHz(), xclk);
|
||||
d+= sprintf(d,"<span title=\"NOTE: Internal temperature sensor readings can be innacurate on the ESP32-c1 chipset, and may vary significantly between devices!\">");
|
||||
d+= sprintf(d,"MCU temperature : %i °C, %i °F</span>\n<br>", McuTc, McuTf);
|
||||
d+= sprintf(d,"Heap: %i, free: %i, min free: %i, max block: %i<br>\n", ESP.getHeapSize(), ESP.getFreeHeap(), ESP.getMinFreeHeap(), ESP.getMaxAllocHeap());
|
||||
@ -590,6 +595,7 @@ 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=\"Instant Refresh; the page reloads every minute anyway\" onclick=\"location.replace(document.URL)\">Refresh</button>\n");
|
||||
d+= sprintf(d,"<button title=\"Stop any active streams\" onclick=\"let throwaway = fetch('stop');setTimeout(function(){\nlocation.replace(document.URL);\n}, 200);\">Stop Stream</button>\n");
|
||||
d+= sprintf(d,"<button title=\"Close this page\" onclick=\"javascript:window.close()\">Close</button>\n");
|
||||
d+= sprintf(d,"</div>\n</body>\n");
|
||||
// A javascript timer to refresh the page every minute.
|
||||
@ -601,6 +607,15 @@ static esp_err_t dump_handler(httpd_req_t *req){
|
||||
return httpd_resp_send(req, dumpOut, strlen(dumpOut));
|
||||
}
|
||||
|
||||
static esp_err_t stop_handler(httpd_req_t *req){
|
||||
flashLED(75);
|
||||
Serial.println("\r\nStream stop requested via Web");
|
||||
streamKill = true;
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
return httpd_resp_send(req, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
static esp_err_t style_handler(httpd_req_t *req){
|
||||
httpd_resp_set_type(req, "text/css");
|
||||
httpd_resp_set_hdr(req, "Content-Encoding", "identity");
|
||||
@ -609,7 +624,7 @@ static esp_err_t style_handler(httpd_req_t *req){
|
||||
|
||||
static esp_err_t streamviewer_handler(httpd_req_t *req){
|
||||
flashLED(75);
|
||||
Serial.println("Stream Viewer requested");
|
||||
Serial.println("Stream viewer requested");
|
||||
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);
|
||||
@ -617,7 +632,7 @@ static esp_err_t streamviewer_handler(httpd_req_t *req){
|
||||
|
||||
static esp_err_t error_handler(httpd_req_t *req){
|
||||
flashLED(75);
|
||||
Serial.println("Sending Error page");
|
||||
Serial.println("Sending error page");
|
||||
std::string s(error_html);
|
||||
size_t index;
|
||||
while ((index = s.find("<APPURL>")) != std::string::npos)
|
||||
@ -705,7 +720,7 @@ static esp_err_t index_handler(httpd_req_t *req){
|
||||
|
||||
void startCameraServer(int hPort, int sPort){
|
||||
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||
config.max_uri_handlers = 12; // we use more than the default 8 (on port 80)
|
||||
config.max_uri_handlers = 16; // we use more than the default 8 (on port 80)
|
||||
|
||||
httpd_uri_t index_uri = {
|
||||
.uri = "/",
|
||||
@ -767,6 +782,12 @@ void startCameraServer(int hPort, int sPort){
|
||||
.handler = dump_handler,
|
||||
.user_ctx = NULL
|
||||
};
|
||||
httpd_uri_t stop_uri = {
|
||||
.uri = "/stop",
|
||||
.method = HTTP_GET,
|
||||
.handler = stop_handler,
|
||||
.user_ctx = NULL
|
||||
};
|
||||
httpd_uri_t stream_uri = {
|
||||
.uri = "/",
|
||||
.method = HTTP_GET,
|
||||
@ -817,6 +838,7 @@ void startCameraServer(int hPort, int sPort){
|
||||
httpd_register_uri_handler(camera_httpd, &favicon_ico_uri);
|
||||
httpd_register_uri_handler(camera_httpd, &logo_svg_uri);
|
||||
httpd_register_uri_handler(camera_httpd, &dump_uri);
|
||||
httpd_register_uri_handler(camera_httpd, &stop_uri);
|
||||
}
|
||||
|
||||
config.server_port = sPort;
|
||||
|
@ -134,12 +134,12 @@ unsigned long imagesServed = 0; // Total image requests
|
||||
char myVer[] PROGMEM = __DATE__ " @ " __TIME__;
|
||||
|
||||
// Camera module bus communications frequency.
|
||||
// Originally: config.xclk_freq_hz = 20000000, but this lead to visual artifacts on many modules.
|
||||
// Originally: config.xclk_freq_mhz = 20000000, but this lead to visual artifacts on many modules.
|
||||
// See https://github.com/espressif/esp32-camera/issues/150#issuecomment-726473652 et al.
|
||||
#if !defined (XCLK_FREQ_HZ)
|
||||
unsigned long xclkFreqHz = 16500000;
|
||||
#if !defined (XCLK_FREQ_MHZ)
|
||||
unsigned long xclk = 16;
|
||||
#else
|
||||
unsigned long xclkFreqHz = XCLK_FREQ_HZ;
|
||||
unsigned long xclk = XCLK_FREQ_MHZ;
|
||||
#endif
|
||||
|
||||
// initial rotation
|
||||
@ -524,7 +524,7 @@ void setup() {
|
||||
config.pin_sscb_scl = SIOC_GPIO_NUM;
|
||||
config.pin_pwdn = PWDN_GPIO_NUM;
|
||||
config.pin_reset = RESET_GPIO_NUM;
|
||||
config.xclk_freq_hz = xclkFreqHz;
|
||||
config.xclk_freq_hz = xclk * 1000000;
|
||||
config.pixel_format = PIXFORMAT_JPEG;
|
||||
config.grab_mode = CAMERA_GRAB_LATEST;
|
||||
// Pre-allocate large buffers
|
||||
|
@ -74,6 +74,13 @@ const uint8_t index_ov2640_html[] = R"=====(<!doctype html>
|
||||
<input type="range" id="quality" min="6" max="63" value="10" class="default-action">
|
||||
<div class="range-max">High<br><span style="font-size: 80%;">(slow)</span></div>
|
||||
</div>
|
||||
<div class="input-group" id="set-xclk-group">
|
||||
<label for="set-xclk">XCLK</label>
|
||||
<div class="text">
|
||||
<input id="xclk" type="number" min="2" max="32" size="4" step="1" class="default-action">
|
||||
<div class="range-max">MHz</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group" id="brightness-group">
|
||||
<label for="brightness">Brightness</label>
|
||||
<div class="range-min">-2</div>
|
||||
@ -292,6 +299,7 @@ const uint8_t index_ov2640_html[] = R"=====(<!doctype html>
|
||||
const closeButton = document.getElementById('close-stream')
|
||||
const streamLink = document.getElementById('stream_link')
|
||||
const framesize = document.getElementById('framesize')
|
||||
const xclk = document.getElementById('xclk')
|
||||
const swapButton = document.getElementById('swap-viewer')
|
||||
const savePrefsButton = document.getElementById('save_prefs')
|
||||
const clearPrefsButton = document.getElementById('clear_prefs')
|
||||
@ -395,6 +403,7 @@ const uint8_t index_ov2640_html[] = R"=====(<!doctype html>
|
||||
value = el.checked ? 1 : 0
|
||||
break
|
||||
case 'range':
|
||||
case 'number':
|
||||
case 'select-one':
|
||||
value = el.value
|
||||
break
|
||||
@ -562,6 +571,11 @@ const uint8_t index_ov2640_html[] = R"=====(<!doctype html>
|
||||
updateConfig(framesize)
|
||||
}
|
||||
|
||||
xclk.onchange = () => {
|
||||
console.log("xclk:" , xclk);
|
||||
updateConfig(xclk)
|
||||
}
|
||||
|
||||
swapButton.onclick = () => {
|
||||
window.open('/?view=simple','_self');
|
||||
}
|
||||
|
@ -76,6 +76,13 @@ const uint8_t index_ov3660_html[] = R"=====(<!doctype html>
|
||||
<input type="range" id="quality" min="4" max="63" value="10" class="default-action">
|
||||
<div class="range-max">High<br><span style="font-size: 80%;">(slow)</span></div>
|
||||
</div>
|
||||
<div class="input-group" id="set-xclk-group">
|
||||
<label for="set-xclk">XCLK</label>
|
||||
<div class="text">
|
||||
<input id="xclk" type="number" min="2" max="32" size="4" step="1" class="default-action">
|
||||
<div class="range-max">MHz</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group" id="brightness-group">
|
||||
<label for="brightness">Brightness</label>
|
||||
<div class="range-min">-3</div>
|
||||
@ -306,6 +313,7 @@ const uint8_t index_ov3660_html[] = R"=====(<!doctype html>
|
||||
const closeButton = document.getElementById('close-stream')
|
||||
const streamLink = document.getElementById('stream_link')
|
||||
const framesize = document.getElementById('framesize')
|
||||
const xclk = document.getElementById('xclk')
|
||||
const swapButton = document.getElementById('swap-viewer')
|
||||
const savePrefsButton = document.getElementById('save_prefs')
|
||||
const clearPrefsButton = document.getElementById('clear_prefs')
|
||||
@ -407,6 +415,7 @@ const uint8_t index_ov3660_html[] = R"=====(<!doctype html>
|
||||
value = el.checked ? 1 : 0
|
||||
break
|
||||
case 'range':
|
||||
case 'number':
|
||||
case 'select-one':
|
||||
value = el.value
|
||||
break
|
||||
@ -571,6 +580,11 @@ const uint8_t index_ov3660_html[] = R"=====(<!doctype html>
|
||||
updateConfig(framesize)
|
||||
}
|
||||
|
||||
xclk.onchange = () => {
|
||||
console.log("xclk:" , xclk);
|
||||
updateConfig(xclk)
|
||||
}
|
||||
|
||||
swapButton.onclick = () => {
|
||||
window.open('/?view=simple','_self');
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
/*
|
||||
* Rename this example to 'myconfig.h' and fill in your details.
|
||||
*
|
||||
*
|
||||
* The local config is in the '.gitignore' file, which helps to keep details secret.
|
||||
*/
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
|
||||
/*
|
||||
* WiFi Settings
|
||||
*
|
||||
*
|
||||
* For the simplest connection to an existing network
|
||||
* just replace your ssid and password in the line below.
|
||||
*/
|
||||
@ -31,18 +31,18 @@ struct station stationList[] = {{"ssid1", "pass1", true},
|
||||
* it will be used for the AccessPoint ssid and password. See the comments there for more.
|
||||
*
|
||||
* The 'dhcp' setting controls whether the station uses DHCP or static IP settings; if in doubt leave 'true'
|
||||
*
|
||||
*
|
||||
* You can also use a BSSID (eg: "2F:67:94:F5:BB:6A", a colon separated mac address string) in place of
|
||||
* the ssid to force connections to specific networks even when the ssid's collide,
|
||||
*/
|
||||
|
||||
/* Extended WiFi Settings */
|
||||
|
||||
/*
|
||||
/*
|
||||
* Hostname. Optional, uncomment and set if desired
|
||||
* - used in DHCP request when connecting to networks, not used in AP mode
|
||||
* - Most useful when used with a static netwrk config, not all routers respect this setting
|
||||
*
|
||||
*
|
||||
* The URL_HOSTNAME will be used in place of the IP address in internal URL's
|
||||
*/
|
||||
|
||||
@ -51,22 +51,22 @@ struct station stationList[] = {{"ssid1", "pass1", true},
|
||||
|
||||
/*
|
||||
* Static network settings for client mode
|
||||
*
|
||||
*
|
||||
* Note: The same settings will be applied to all client connections where the dhcp setting is 'false'
|
||||
* You must define all three: IP, Gateway and NetMask
|
||||
*/
|
||||
// warning - IP addresses must be separated with commas (,) and not decimals (.)
|
||||
// #define ST_IP 192,168,0,123
|
||||
// #define ST_GATEWAY 192,168,0,2
|
||||
// #define ST_GATEWAY 192,168,0,2
|
||||
// #define ST_NETMASK 255,255,255,0
|
||||
// One or two DNS servers can be supplied, only the NTP code currently uses them
|
||||
// #define ST_DNS1 192,168,0,2
|
||||
// #define ST_DNS2 8,8,8,8
|
||||
|
||||
/*
|
||||
* AccessPoint;
|
||||
/*
|
||||
* AccessPoint;
|
||||
*
|
||||
* Uncomment to enable AP mode;
|
||||
* Uncomment to enable AP mode;
|
||||
*
|
||||
*/
|
||||
// #define WIFI_AP_ENABLE
|
||||
@ -79,7 +79,7 @@ struct station stationList[] = {{"ssid1", "pass1", true},
|
||||
* if they are found. AP then works as a fallback mode for when there are no 'real' networks available.
|
||||
*
|
||||
* Setting the 'dhcp' field to true for the AP enables a captive portal and attempts to send
|
||||
* all visitors to the webcam page, with varying degrees of success depending on the visitors
|
||||
* all visitors to the webcam page, with varying degrees of success depending on the visitors
|
||||
* browser and other settings.
|
||||
*/
|
||||
// Optionally change the AccessPoint ip address (default = 192.168.4.1)
|
||||
@ -184,9 +184,10 @@ struct station stationList[] = {{"ssid1", "pass1", true},
|
||||
// #define CAMERA_MODEL_TTGO_T_JOURNAL
|
||||
// #define CAMERA_MODEL_ARDUCAM_ESP32S_UNO
|
||||
|
||||
// Camera module bus communications frequency, setting too high can cause visual artifacts.
|
||||
// Currently defaults to 16.5MHz, but some (non-clone) modules may be able to use the
|
||||
// original frequency of 20MHz for to allow higher framerates etc.
|
||||
// #define XCLK_FREQ_HZ 20000000;
|
||||
// For clone modules that have camera module artifacts and SPIFFS issues; try setting this very low:
|
||||
// #define XCLK_FREQ_HZ 3000000;
|
||||
// Initial Camera module bus communications frequency
|
||||
// Currently defaults to 8MHz
|
||||
// The post-initialisation (runtime) value can be set and edited by the user in the UI
|
||||
// For clone modules that have camera module and SPIFFS startup issues try setting
|
||||
// this very low (start at 2MHZ and increase):
|
||||
// #define XCLK_FREQ_MHZ 2
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Version of upstream code */
|
||||
|
||||
char baseVersion[] = "4.0.beta3";
|
||||
char baseVersion[] = "4.0.rc1";
|
||||
|
||||
|
@ -7,6 +7,7 @@ extern void flashLED(int flashtime);
|
||||
extern int myRotation; // Rotation
|
||||
extern int lampVal; // The current Lamp value
|
||||
extern int autoLamp; // Automatic lamp mode
|
||||
extern int xclk; // Camera module clock speed
|
||||
|
||||
/*
|
||||
* Useful utility when debugging...
|
||||
@ -90,8 +91,11 @@ void loadPrefs(fs::FS &fs){
|
||||
// process all the settings
|
||||
lampVal = jsonExtract(prefs, "lamp").toInt();
|
||||
autoLamp = jsonExtract(prefs, "autolamp").toInt();
|
||||
int xclkPref = jsonExtract(prefs, "xclk").toInt();
|
||||
if (xclkPref != 0) xclk = xclkPref;
|
||||
s->set_framesize(s, (framesize_t)jsonExtract(prefs, "framesize").toInt());
|
||||
s->set_quality(s, jsonExtract(prefs, "quality").toInt());
|
||||
s->set_xclk(s, LEDC_TIMER_0, xclk);
|
||||
s->set_brightness(s, jsonExtract(prefs, "brightness").toInt());
|
||||
s->set_contrast(s, jsonExtract(prefs, "contrast").toInt());
|
||||
s->set_saturation(s, jsonExtract(prefs, "saturation").toInt());
|
||||
@ -138,6 +142,7 @@ void savePrefs(fs::FS &fs){
|
||||
p+=sprintf(p, "\"autolamp\":%u,", autoLamp);
|
||||
p+=sprintf(p, "\"framesize\":%u,", s->status.framesize);
|
||||
p+=sprintf(p, "\"quality\":%u,", s->status.quality);
|
||||
p+=sprintf(p, "\"xclk\":%u,", xclk);
|
||||
p+=sprintf(p, "\"brightness\":%d,", s->status.brightness);
|
||||
p+=sprintf(p, "\"contrast\":%d,", s->status.contrast);
|
||||
p+=sprintf(p, "\"saturation\":%d,", s->status.saturation);
|
||||
|
Reference in New Issue
Block a user