mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-23 10:46:31 +00:00
commit
0f11b28a94
@ -70,6 +70,8 @@ uint32_t DecodeLightId(uint32_t hue_id);
|
|||||||
|
|
||||||
#include "FS.h"
|
#include "FS.h"
|
||||||
#include "SPIFFS.h"
|
#include "SPIFFS.h"
|
||||||
|
|
||||||
|
|
||||||
void SaveFile(const char *name,const uint8_t *buf,uint32_t len) {
|
void SaveFile(const char *name,const uint8_t *buf,uint32_t len) {
|
||||||
File file = SPIFFS.open(name, FILE_WRITE);
|
File file = SPIFFS.open(name, FILE_WRITE);
|
||||||
if (!file) return;
|
if (!file) return;
|
||||||
@ -2048,7 +2050,14 @@ chknext:
|
|||||||
fvar=wc_set_motion_detect(fvar2);
|
fvar=wc_set_motion_detect(fvar2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#ifdef USE_FACE_DETECT
|
||||||
|
case 7:
|
||||||
|
{ float fvar2;
|
||||||
|
lp=GetNumericResult(lp,OPER_EQU,&fvar2,0);
|
||||||
|
fvar=wc_set_face_detect(fvar2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
fvar=0;
|
fvar=0;
|
||||||
}
|
}
|
||||||
@ -5224,10 +5233,11 @@ bool Xdrv10(uint8_t function)
|
|||||||
case FUNC_WEB_ADD_BUTTON:
|
case FUNC_WEB_ADD_BUTTON:
|
||||||
WSContentSend_P(HTTP_BTN_MENU_RULES);
|
WSContentSend_P(HTTP_BTN_MENU_RULES);
|
||||||
break;
|
break;
|
||||||
|
#ifdef USE_SCRIPT_WEB_DISPLAY
|
||||||
case FUNC_WEB_ADD_MAIN_BUTTON:
|
case FUNC_WEB_ADD_MAIN_BUTTON:
|
||||||
ScriptWebShow('&');
|
ScriptWebShow('&');
|
||||||
break;
|
break;
|
||||||
|
#endif // USE_SCRIPT_WEB_DISPLAY
|
||||||
case FUNC_WEB_ADD_HANDLER:
|
case FUNC_WEB_ADD_HANDLER:
|
||||||
Webserver->on("/" WEB_HANDLE_SCRIPT, HandleScriptConfiguration);
|
Webserver->on("/" WEB_HANDLE_SCRIPT, HandleScriptConfiguration);
|
||||||
Webserver->on("/ta",HTTP_POST, HandleScriptTextareaConfiguration);
|
Webserver->on("/ta",HTTP_POST, HandleScriptTextareaConfiguration);
|
||||||
|
@ -53,7 +53,9 @@
|
|||||||
//#define USE_TEMPLATE
|
//#define USE_TEMPLATE
|
||||||
|
|
||||||
#define WC_LOGLEVEL LOG_LEVEL_INFO
|
#define WC_LOGLEVEL LOG_LEVEL_INFO
|
||||||
|
#include "fb_gfx.h"
|
||||||
|
#include "fd_forward.h"
|
||||||
|
#include "fr_forward.h"
|
||||||
|
|
||||||
#define PWDN_GPIO_NUM 32
|
#define PWDN_GPIO_NUM 32
|
||||||
#define RESET_GPIO_NUM -1
|
#define RESET_GPIO_NUM -1
|
||||||
@ -81,6 +83,10 @@ uint8_t wc_up;
|
|||||||
uint16_t wc_width;
|
uint16_t wc_width;
|
||||||
uint16_t wc_height;
|
uint16_t wc_height;
|
||||||
uint8_t wc_stream_active;
|
uint8_t wc_stream_active;
|
||||||
|
#ifdef USE_FACE_DETECT
|
||||||
|
uint8_t faces;
|
||||||
|
uint16_t face_detect_time;
|
||||||
|
#endif
|
||||||
|
|
||||||
uint32_t wc_setup(int32_t fsiz) {
|
uint32_t wc_setup(int32_t fsiz) {
|
||||||
if (fsiz > 10) { fsiz = 10; }
|
if (fsiz > 10) { fsiz = 10; }
|
||||||
@ -89,11 +95,13 @@ uint32_t wc_setup(int32_t fsiz) {
|
|||||||
|
|
||||||
if (fsiz < 0) {
|
if (fsiz < 0) {
|
||||||
esp_camera_deinit();
|
esp_camera_deinit();
|
||||||
|
wc_up = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wc_up) {
|
if (wc_up) {
|
||||||
esp_camera_deinit();
|
esp_camera_deinit();
|
||||||
|
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: deinit"));
|
||||||
//return wc_up;
|
//return wc_up;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,6 +229,11 @@ uint32_t wc_setup(int32_t fsiz) {
|
|||||||
wc_height = wc_fb->height;
|
wc_height = wc_fb->height;
|
||||||
esp_camera_fb_return(wc_fb);
|
esp_camera_fb_return(wc_fb);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_FACE_DETECT
|
||||||
|
fd_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Initialized"));
|
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: Initialized"));
|
||||||
|
|
||||||
wc_up = 1;
|
wc_up = 1;
|
||||||
@ -441,6 +454,141 @@ void handleMjpeg(void) {
|
|||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_FACE_DETECT
|
||||||
|
|
||||||
|
static mtmn_config_t mtmn_config = {0};
|
||||||
|
|
||||||
|
void fd_init(void) {
|
||||||
|
mtmn_config.type = FAST;
|
||||||
|
mtmn_config.min_face = 80;
|
||||||
|
mtmn_config.pyramid = 0.707;
|
||||||
|
mtmn_config.pyramid_times = 4;
|
||||||
|
mtmn_config.p_threshold.score = 0.6;
|
||||||
|
mtmn_config.p_threshold.nms = 0.7;
|
||||||
|
mtmn_config.p_threshold.candidate_number = 20;
|
||||||
|
mtmn_config.r_threshold.score = 0.7;
|
||||||
|
mtmn_config.r_threshold.nms = 0.7;
|
||||||
|
mtmn_config.r_threshold.candidate_number = 10;
|
||||||
|
mtmn_config.o_threshold.score = 0.7;
|
||||||
|
mtmn_config.o_threshold.nms = 0.7;
|
||||||
|
mtmn_config.o_threshold.candidate_number = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FACE_COLOR_WHITE 0x00FFFFFF
|
||||||
|
#define FACE_COLOR_BLACK 0x00000000
|
||||||
|
#define FACE_COLOR_RED 0x000000FF
|
||||||
|
#define FACE_COLOR_GREEN 0x0000FF00
|
||||||
|
#define FACE_COLOR_BLUE 0x00FF0000
|
||||||
|
#define FACE_COLOR_YELLOW (FACE_COLOR_RED | FACE_COLOR_GREEN)
|
||||||
|
#define FACE_COLOR_CYAN (FACE_COLOR_BLUE | FACE_COLOR_GREEN)
|
||||||
|
#define FACE_COLOR_PURPLE (FACE_COLOR_BLUE | FACE_COLOR_RED)
|
||||||
|
void draw_face_boxes(dl_matrix3du_t *image_matrix, box_array_t *boxes, int face_id);
|
||||||
|
|
||||||
|
/*
|
||||||
|
void draw_face_boxes(dl_matrix3du_t *image_matrix, box_array_t *boxes, int face_id) {
|
||||||
|
int x, y, w, h, i;
|
||||||
|
uint32_t color = FACE_COLOR_YELLOW;
|
||||||
|
if(face_id < 0){
|
||||||
|
color = FACE_COLOR_RED;
|
||||||
|
} else if(face_id > 0){
|
||||||
|
color = FACE_COLOR_GREEN;
|
||||||
|
}
|
||||||
|
fb_data_t fb;
|
||||||
|
fb.width = image_matrix->w;
|
||||||
|
fb.height = image_matrix->h;
|
||||||
|
fb.data = image_matrix->item;
|
||||||
|
fb.bytes_per_pixel = 3;
|
||||||
|
fb.format = FB_BGR888;
|
||||||
|
for (i = 0; i < boxes->len; i++){
|
||||||
|
// rectangle box
|
||||||
|
x = (int)boxes->box[i].box_p[0];
|
||||||
|
y = (int)boxes->box[i].box_p[1];
|
||||||
|
w = (int)boxes->box[i].box_p[2] - x + 1;
|
||||||
|
h = (int)boxes->box[i].box_p[3] - y + 1;
|
||||||
|
fb_gfx_drawFastHLine(&fb, x, y, w, color);
|
||||||
|
fb_gfx_drawFastHLine(&fb, x, y+h-1, w, color);
|
||||||
|
fb_gfx_drawFastVLine(&fb, x, y, h, color);
|
||||||
|
fb_gfx_drawFastVLine(&fb, x+w-1, y, h, color);
|
||||||
|
#if 0
|
||||||
|
// landmark
|
||||||
|
int x0, y0, j;
|
||||||
|
for (j = 0; j < 10; j+=2) {
|
||||||
|
x0 = (int)boxes->landmark[i].landmark_p[j];
|
||||||
|
y0 = (int)boxes->landmark[i].landmark_p[j+1];
|
||||||
|
fb_gfx_fillRect(&fb, x0, y0, 3, 3, color);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DL_SPIRAM_SUPPORT
|
||||||
|
|
||||||
|
uint32_t wc_set_face_detect(int32_t value) {
|
||||||
|
if (value >= 0) { face_detect_time = value; }
|
||||||
|
return faces;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t face_ltime;
|
||||||
|
|
||||||
|
uint32_t detect_face(void);
|
||||||
|
|
||||||
|
uint32_t detect_face(void) {
|
||||||
|
dl_matrix3du_t *image_matrix;
|
||||||
|
size_t out_len, out_width, out_height;
|
||||||
|
uint8_t * out_buf;
|
||||||
|
bool s;
|
||||||
|
bool detected = false;
|
||||||
|
int face_id = 0;
|
||||||
|
camera_fb_t *fb;
|
||||||
|
|
||||||
|
if ((millis() - face_ltime) > face_detect_time) {
|
||||||
|
face_ltime = millis();
|
||||||
|
fb = esp_camera_fb_get();
|
||||||
|
if (!fb) { return ESP_FAIL; }
|
||||||
|
|
||||||
|
image_matrix = dl_matrix3du_alloc(1, fb->width, fb->height, 3);
|
||||||
|
if (!image_matrix) {
|
||||||
|
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: dl_matrix3du_alloc failed"));
|
||||||
|
esp_camera_fb_return(fb);
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_buf = image_matrix->item;
|
||||||
|
//out_len = fb->width * fb->height * 3;
|
||||||
|
//out_width = fb->width;
|
||||||
|
//out_height = fb->height;
|
||||||
|
|
||||||
|
s = fmt2rgb888(fb->buf, fb->len, fb->format, out_buf);
|
||||||
|
esp_camera_fb_return(fb);
|
||||||
|
if (!s){
|
||||||
|
dl_matrix3du_free(image_matrix);
|
||||||
|
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: to rgb888 failed"));
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
box_array_t *net_boxes = face_detect(image_matrix, &mtmn_config);
|
||||||
|
if (net_boxes){
|
||||||
|
detected = true;
|
||||||
|
faces = net_boxes->len;
|
||||||
|
//if(recognition_enabled){
|
||||||
|
// face_id = run_face_recognition(image_matrix, net_boxes);
|
||||||
|
//}
|
||||||
|
//draw_face_boxes(image_matrix, net_boxes, face_id);
|
||||||
|
free(net_boxes->score);
|
||||||
|
free(net_boxes->box);
|
||||||
|
free(net_boxes->landmark);
|
||||||
|
free(net_boxes);
|
||||||
|
} else {
|
||||||
|
faces = 0;
|
||||||
|
}
|
||||||
|
dl_matrix3du_free(image_matrix);
|
||||||
|
//Serial.printf("face detected: %d",faces);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void handleMjpeg_task(void) {
|
void handleMjpeg_task(void) {
|
||||||
camera_fb_t *wc_fb;
|
camera_fb_t *wc_fb;
|
||||||
size_t _jpg_buf_len = 0;
|
size_t _jpg_buf_len = 0;
|
||||||
@ -472,6 +620,7 @@ void handleMjpeg_task(void) {
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (wc_fb->format != PIXFORMAT_JPEG) {
|
if (wc_fb->format != PIXFORMAT_JPEG) {
|
||||||
jpeg_converted = frame2jpg(wc_fb, 80, &_jpg_buf, &_jpg_buf_len);
|
jpeg_converted = frame2jpg(wc_fb, 80, &_jpg_buf, &_jpg_buf_len);
|
||||||
if (!jpeg_converted){
|
if (!jpeg_converted){
|
||||||
@ -524,7 +673,6 @@ void CamHandleRoot(void) {
|
|||||||
//CamServer->redirect("http://" + String(ip) + ":81/cam.mjpeg");
|
//CamServer->redirect("http://" + String(ip) + ":81/cam.mjpeg");
|
||||||
CamServer->sendHeader("Location", WiFi.localIP().toString() + ":81/cam.mjpeg");
|
CamServer->sendHeader("Location", WiFi.localIP().toString() + ":81/cam.mjpeg");
|
||||||
CamServer->send(302, "", "");
|
CamServer->send(302, "", "");
|
||||||
//Serial.printf("WC root called");
|
|
||||||
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: root called"));
|
AddLog_P2(WC_LOGLEVEL, PSTR("CAM: root called"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -535,10 +683,10 @@ uint32_t motion_brightness;
|
|||||||
uint8_t *last_motion_buffer;
|
uint8_t *last_motion_buffer;
|
||||||
|
|
||||||
uint32_t wc_set_motion_detect(int32_t value) {
|
uint32_t wc_set_motion_detect(int32_t value) {
|
||||||
if (value >= 0) { motion_detect=value; }
|
if (value >= 0) { motion_detect = value; }
|
||||||
if (-1 == value) {
|
if (-1 == value) {
|
||||||
return motion_trigger;
|
return motion_trigger;
|
||||||
} else {
|
} else {
|
||||||
return motion_brightness;
|
return motion_brightness;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -546,7 +694,7 @@ uint32_t wc_set_motion_detect(int32_t value) {
|
|||||||
// optional motion detector
|
// optional motion detector
|
||||||
void detect_motion(void) {
|
void detect_motion(void) {
|
||||||
camera_fb_t *wc_fb;
|
camera_fb_t *wc_fb;
|
||||||
uint8_t *out_buf=0;
|
uint8_t *out_buf = 0;
|
||||||
|
|
||||||
if ((millis()-motion_ltime) > motion_detect) {
|
if ((millis()-motion_ltime) > motion_detect) {
|
||||||
motion_ltime = millis();
|
motion_ltime = millis();
|
||||||
@ -589,12 +737,10 @@ void detect_motion(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void wc_show_stream(void) {
|
void wc_show_stream(void) {
|
||||||
#ifndef USE_SCRIPT
|
|
||||||
if (CamServer) {
|
if (CamServer) {
|
||||||
WSContentSend_P(PSTR("<p></p><center><img src='http://%s:81/stream' alt='Webcam stream' style='width:99%%;'></center><p></p>"),
|
WSContentSend_P(PSTR("<p></p><center><img src='http://%s:81/stream' alt='Webcam stream' style='width:99%%;'></center><p></p>"),
|
||||||
WiFi.localIP().toString().c_str());
|
WiFi.localIP().toString().c_str());
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t wc_set_streamserver(uint32_t flag) {
|
uint32_t wc_set_streamserver(uint32_t flag) {
|
||||||
@ -625,6 +771,9 @@ uint32_t wc_set_streamserver(uint32_t flag) {
|
|||||||
|
|
||||||
void WcStreamControl(uint32_t resolution) {
|
void WcStreamControl(uint32_t resolution) {
|
||||||
wc_set_streamserver(resolution);
|
wc_set_streamserver(resolution);
|
||||||
|
/*if (0 == resolution) {
|
||||||
|
resolution=-1;
|
||||||
|
}*/
|
||||||
wc_setup(resolution);
|
wc_setup(resolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -632,6 +781,9 @@ void wc_loop(void) {
|
|||||||
if (CamServer) { CamServer->handleClient(); }
|
if (CamServer) { CamServer->handleClient(); }
|
||||||
if (wc_stream_active) { handleMjpeg_task(); }
|
if (wc_stream_active) { handleMjpeg_task(); }
|
||||||
if (motion_detect) { detect_motion(); }
|
if (motion_detect) { detect_motion(); }
|
||||||
|
#ifdef USE_FACE_DETECT
|
||||||
|
if (face_detect_time) { detect_face(); }
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void wc_pic_setup(void) {
|
void wc_pic_setup(void) {
|
||||||
@ -672,6 +824,7 @@ void WcInit(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Commands
|
* Commands
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
@ -689,7 +842,7 @@ void (* const WCCommand[])(void) PROGMEM = {
|
|||||||
void CmndWebcam(void) {
|
void CmndWebcam(void) {
|
||||||
uint32_t flag = 0;
|
uint32_t flag = 0;
|
||||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 10)) {
|
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 10)) {
|
||||||
Settings.esp32_webcam_resolution = XdrvMailbox.payload;
|
Settings.esp32_webcam_resolution=XdrvMailbox.payload;
|
||||||
WcStreamControl(Settings.esp32_webcam_resolution);
|
WcStreamControl(Settings.esp32_webcam_resolution);
|
||||||
}
|
}
|
||||||
if (CamServer) { flag = 1; }
|
if (CamServer) { flag = 1; }
|
||||||
@ -711,15 +864,20 @@ bool Xdrv39(uint8_t function) {
|
|||||||
wc_pic_setup();
|
wc_pic_setup();
|
||||||
break;
|
break;
|
||||||
case FUNC_WEB_ADD_MAIN_BUTTON:
|
case FUNC_WEB_ADD_MAIN_BUTTON:
|
||||||
WcStreamControl(Settings.esp32_webcam_resolution);
|
//if (Settings.esp32_webcam_resolution) {
|
||||||
wc_show_stream();
|
#ifndef USE_SCRIPT
|
||||||
break;
|
WcStreamControl(Settings.esp32_webcam_resolution);
|
||||||
|
wc_show_stream();
|
||||||
|
#endif
|
||||||
|
//}
|
||||||
|
break;
|
||||||
case FUNC_COMMAND:
|
case FUNC_COMMAND:
|
||||||
result = DecodeCommand(kWCCommands, WCCommand);
|
result = DecodeCommand(kWCCommands, WCCommand);
|
||||||
break;
|
break;
|
||||||
case FUNC_PRE_INIT:
|
case FUNC_PRE_INIT:
|
||||||
WcInit();
|
WcInit();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user