Add the missing Save button to the web UI for OV5640 (#136)
* Add the missing Save button to the web UI for OV5640 * Add MDNS feature that allows the cameras to be found * Add mDNS Camera Queryov5640-save-button^2
parent
7937d37e14
commit
67a57377cf
|
@ -1,4 +1,4 @@
|
||||||
set(COMPONENT_SRCS "app_main.c" "app_wifi.c" "app_camera.c" "app_httpd.c")
|
set(COMPONENT_SRCS "app_main.c" "app_wifi.c" "app_camera.c" "app_httpd.c" "app_mdns.c")
|
||||||
set(COMPONENT_ADD_INCLUDEDIRS "include")
|
set(COMPONENT_ADD_INCLUDEDIRS "include")
|
||||||
|
|
||||||
set(COMPONENT_REQUIRES
|
set(COMPONENT_REQUIRES
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "driver/ledc.h"
|
#include "driver/ledc.h"
|
||||||
//#include "camera_index.h"
|
//#include "camera_index.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
#include "app_mdns.h"
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
|
#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
|
||||||
#include "esp32-hal-log.h"
|
#include "esp32-hal-log.h"
|
||||||
|
@ -705,8 +706,12 @@ static esp_err_t cmd_handler(httpd_req_t *req)
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
if (!strcmp(variable, "framesize")) {
|
if (!strcmp(variable, "framesize")) {
|
||||||
if (s->pixformat == PIXFORMAT_JPEG)
|
if (s->pixformat == PIXFORMAT_JPEG) {
|
||||||
res = s->set_framesize(s, (framesize_t)val);
|
res = s->set_framesize(s, (framesize_t)val);
|
||||||
|
if (res == 0) {
|
||||||
|
app_mdns_update_framesize(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!strcmp(variable, "quality"))
|
else if (!strcmp(variable, "quality"))
|
||||||
res = s->set_quality(s, val);
|
res = s->set_quality(s, val);
|
||||||
|
@ -878,6 +883,15 @@ static esp_err_t status_handler(httpd_req_t *req)
|
||||||
return httpd_resp_send(req, json_response, strlen(json_response));
|
return httpd_resp_send(req, json_response, strlen(json_response));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static esp_err_t mdns_handler(httpd_req_t *req)
|
||||||
|
{
|
||||||
|
size_t json_len = 0;
|
||||||
|
const char * json_response = app_mdns_query(&json_len);
|
||||||
|
httpd_resp_set_type(req, "application/json");
|
||||||
|
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||||
|
return httpd_resp_send(req, json_response, json_len);
|
||||||
|
}
|
||||||
|
|
||||||
static esp_err_t xclk_handler(httpd_req_t *req)
|
static esp_err_t xclk_handler(httpd_req_t *req)
|
||||||
{
|
{
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
|
@ -1137,6 +1151,12 @@ void app_httpd_main()
|
||||||
.handler = win_handler,
|
.handler = win_handler,
|
||||||
.user_ctx = NULL};
|
.user_ctx = NULL};
|
||||||
|
|
||||||
|
httpd_uri_t mdns_uri = {
|
||||||
|
.uri = "/mdns",
|
||||||
|
.method = HTTP_GET,
|
||||||
|
.handler = mdns_handler,
|
||||||
|
.user_ctx = NULL};
|
||||||
|
|
||||||
ra_filter_init(&ra_filter, 20);
|
ra_filter_init(&ra_filter, 20);
|
||||||
|
|
||||||
#if CONFIG_ESP_FACE_DETECT_ENABLED
|
#if CONFIG_ESP_FACE_DETECT_ENABLED
|
||||||
|
@ -1179,6 +1199,8 @@ void app_httpd_main()
|
||||||
httpd_register_uri_handler(camera_httpd, &greg_uri);
|
httpd_register_uri_handler(camera_httpd, &greg_uri);
|
||||||
httpd_register_uri_handler(camera_httpd, &pll_uri);
|
httpd_register_uri_handler(camera_httpd, &pll_uri);
|
||||||
httpd_register_uri_handler(camera_httpd, &win_uri);
|
httpd_register_uri_handler(camera_httpd, &win_uri);
|
||||||
|
|
||||||
|
httpd_register_uri_handler(camera_httpd, &mdns_uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
config.server_port += 1;
|
config.server_port += 1;
|
||||||
|
|
|
@ -23,10 +23,12 @@
|
||||||
#include "app_camera.h"
|
#include "app_camera.h"
|
||||||
#include "app_wifi.h"
|
#include "app_wifi.h"
|
||||||
#include "app_httpd.h"
|
#include "app_httpd.h"
|
||||||
|
#include "app_mdns.h"
|
||||||
|
|
||||||
void app_main()
|
void app_main()
|
||||||
{
|
{
|
||||||
app_wifi_main();
|
app_wifi_main();
|
||||||
app_camera_main();
|
app_camera_main();
|
||||||
app_httpd_main();
|
app_httpd_main();
|
||||||
|
app_mdns_main();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,242 @@
|
||||||
|
/*
|
||||||
|
* ESPRESSIF MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case,
|
||||||
|
* it is free of charge, to any person obtaining a copy of this software and associated
|
||||||
|
* documentation files (the "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
|
||||||
|
* to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all copies or
|
||||||
|
* substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <string.h>
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/semphr.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_wifi.h"
|
||||||
|
#include "esp_camera.h"
|
||||||
|
#include "mdns.h"
|
||||||
|
#include "app_camera.h"
|
||||||
|
|
||||||
|
static const char *TAG = "camera mdns";
|
||||||
|
|
||||||
|
static const char * service_name = "_esp-cam";
|
||||||
|
static const char * proto = "_tcp";
|
||||||
|
static mdns_result_t * found_cams = NULL;
|
||||||
|
static SemaphoreHandle_t query_lock = NULL;
|
||||||
|
static char iname[64];
|
||||||
|
static char hname[64];
|
||||||
|
static char framesize[4];
|
||||||
|
static char pixformat[4];
|
||||||
|
static const char * model = NULL;
|
||||||
|
|
||||||
|
static void mdns_query_for_cams()
|
||||||
|
{
|
||||||
|
mdns_result_t * new_cams = NULL;
|
||||||
|
esp_err_t err = mdns_query_ptr(service_name, proto, 5000, 4, &new_cams);
|
||||||
|
if(err){
|
||||||
|
ESP_LOGE(TAG, "MDNS Query Failed: %s", esp_err_to_name(err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xSemaphoreTake(query_lock, portMAX_DELAY);
|
||||||
|
if (found_cams != NULL) {
|
||||||
|
mdns_query_results_free(found_cams);
|
||||||
|
}
|
||||||
|
found_cams = new_cams;
|
||||||
|
xSemaphoreGive(query_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mdns_task(void * arg)
|
||||||
|
{
|
||||||
|
for (;;) {
|
||||||
|
mdns_query_for_cams();
|
||||||
|
//delay 55 seconds
|
||||||
|
vTaskDelay((55 * 1000) / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Public Functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
const char * app_mdns_query(size_t * out_len)
|
||||||
|
{
|
||||||
|
//build JSON
|
||||||
|
static char json_response[2048];
|
||||||
|
char *p = json_response;
|
||||||
|
*p++ = '[';
|
||||||
|
|
||||||
|
//add own data first
|
||||||
|
tcpip_adapter_ip_info_t ip;
|
||||||
|
if (strlen(CONFIG_ESP_WIFI_SSID)) {
|
||||||
|
tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip);
|
||||||
|
} else {
|
||||||
|
tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ip);
|
||||||
|
}
|
||||||
|
*p++ = '{';
|
||||||
|
p += sprintf(p, "\"instance\":\"%s\",", iname);
|
||||||
|
p += sprintf(p, "\"host\":\"%s.local\",", hname);
|
||||||
|
p += sprintf(p, "\"port\":80,");
|
||||||
|
p += sprintf(p, "\"txt\":{");
|
||||||
|
p += sprintf(p, "\"pixformat\":\"%s\",", pixformat);
|
||||||
|
p += sprintf(p, "\"framesize\":\"%s\",", framesize);
|
||||||
|
p += sprintf(p, "\"stream_port\":\"81\",");
|
||||||
|
p += sprintf(p, "\"board\":\"%s\",", CAM_BOARD);
|
||||||
|
p += sprintf(p, "\"model\":\"%s\",", model);
|
||||||
|
*p++ = '}';
|
||||||
|
*p++ = ',';
|
||||||
|
p += sprintf(p, "\"ip\":\"" IPSTR "\",", IP2STR(&(ip.ip)));
|
||||||
|
p += sprintf(p, "\"id\":\"" IPSTR ":80\",", IP2STR(&(ip.ip)));
|
||||||
|
p += sprintf(p, "\"service\":\"%s\",", service_name);
|
||||||
|
p += sprintf(p, "\"proto\":\"%s\"", proto);
|
||||||
|
*p++ = '}';
|
||||||
|
|
||||||
|
xSemaphoreTake(query_lock, portMAX_DELAY);
|
||||||
|
if (found_cams) {
|
||||||
|
*p++ = ',';
|
||||||
|
}
|
||||||
|
mdns_result_t * r = found_cams;
|
||||||
|
mdns_ip_addr_t * a = NULL;
|
||||||
|
int t;
|
||||||
|
while(r){
|
||||||
|
*p++ = '{';
|
||||||
|
if(r->instance_name){
|
||||||
|
p += sprintf(p, "\"instance\":\"%s\",", r->instance_name);
|
||||||
|
}
|
||||||
|
if(r->hostname){
|
||||||
|
p += sprintf(p, "\"host\":\"%s.local\",", r->hostname);
|
||||||
|
p += sprintf(p, "\"port\":%u,", r->port);
|
||||||
|
}
|
||||||
|
if(r->txt_count){
|
||||||
|
p += sprintf(p, "\"txt\":{");
|
||||||
|
for(t=0; t<r->txt_count; t++){
|
||||||
|
if (t > 0) {
|
||||||
|
*p++ = ',';
|
||||||
|
}
|
||||||
|
p += sprintf(p, "\"%s\":\"%s\"", r->txt[t].key, r->txt[t].value?r->txt[t].value:"NULL");
|
||||||
|
}
|
||||||
|
*p++ = '}';
|
||||||
|
*p++ = ',';
|
||||||
|
}
|
||||||
|
a = r->addr;
|
||||||
|
while(a){
|
||||||
|
if(a->addr.type != IPADDR_TYPE_V6){
|
||||||
|
p += sprintf(p, "\"ip\":\"" IPSTR "\",", IP2STR(&(a->addr.u_addr.ip4)));
|
||||||
|
p += sprintf(p, "\"id\":\"" IPSTR ":%u\",", IP2STR(&(a->addr.u_addr.ip4)), r->port);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
a = a->next;
|
||||||
|
}
|
||||||
|
p += sprintf(p, "\"service\":\"%s\",", service_name);
|
||||||
|
p += sprintf(p, "\"proto\":\"%s\"", proto);
|
||||||
|
*p++ = '}';
|
||||||
|
r = r->next;
|
||||||
|
if (r) {
|
||||||
|
*p++ = ',';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xSemaphoreGive(query_lock);
|
||||||
|
*p++ = ']';
|
||||||
|
*out_len = (uint32_t)p - (uint32_t)json_response;
|
||||||
|
*p++ = '\0';
|
||||||
|
ESP_LOGI(TAG, "JSON: %uB", *out_len);
|
||||||
|
return (const char *)json_response;
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_mdns_update_framesize(int size)
|
||||||
|
{
|
||||||
|
snprintf(framesize, 4, "%d", size);
|
||||||
|
if(mdns_service_txt_item_set(service_name, proto, "framesize", (char*)framesize)){
|
||||||
|
ESP_LOGE(TAG, "mdns_service_txt_item_set() framesize Failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_mdns_main()
|
||||||
|
{
|
||||||
|
uint8_t mac[6];
|
||||||
|
|
||||||
|
query_lock = xSemaphoreCreateBinary();
|
||||||
|
if (query_lock == NULL) {
|
||||||
|
ESP_LOGE(TAG, "xSemaphoreCreateMutex() Failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xSemaphoreGive(query_lock);
|
||||||
|
|
||||||
|
if (esp_read_mac(mac, ESP_MAC_WIFI_STA) != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "esp_read_mac() Failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sensor_t * s = esp_camera_sensor_get();
|
||||||
|
switch(s->id.PID){
|
||||||
|
case OV2640_PID: model = "OV2640"; break;
|
||||||
|
case OV3660_PID: model = "OV3660"; break;
|
||||||
|
case OV5640_PID: model = "OV5640"; break;
|
||||||
|
case OV7725_PID: model = "OV7725"; break;
|
||||||
|
default: model = "UNKNOWN"; break;
|
||||||
|
}
|
||||||
|
snprintf(iname, 64, "%s-%s-%02X%02X%02X", CAM_BOARD, model, mac[3], mac[4], mac[5]);
|
||||||
|
snprintf(framesize, 4, "%d", s->status.framesize);
|
||||||
|
snprintf(pixformat, 4, "%d", s->pixformat);
|
||||||
|
|
||||||
|
char * src = iname, * dst = hname, c;
|
||||||
|
while (*src) {
|
||||||
|
c = *src++;
|
||||||
|
if (c >= 'A' && c <= 'Z') {
|
||||||
|
c -= 'A' - 'a';
|
||||||
|
}
|
||||||
|
*dst++ = c;
|
||||||
|
}
|
||||||
|
*dst++ = '\0';
|
||||||
|
|
||||||
|
if(mdns_init() != ESP_OK){
|
||||||
|
ESP_LOGE(TAG, "mdns_init() Failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mdns_hostname_set(hname) != ESP_OK){
|
||||||
|
ESP_LOGE(TAG, "mdns_hostname_set(\"%s\") Failed", hname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mdns_instance_name_set(iname) != ESP_OK){
|
||||||
|
ESP_LOGE(TAG, "mdns_instance_name_set(\"%s\") Failed", iname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mdns_service_add(NULL, "_http", "_tcp", 80, NULL, 0) != ESP_OK){
|
||||||
|
ESP_LOGE(TAG, "mdns_service_add() HTTP Failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mdns_txt_item_t camera_txt_data[] = {
|
||||||
|
{(char*)"board" ,(char*)CAM_BOARD},
|
||||||
|
{(char*)"model" ,(char*)model},
|
||||||
|
{(char*)"stream_port" ,(char*)"81"},
|
||||||
|
{(char*)"framesize" ,(char*)framesize},
|
||||||
|
{(char*)"pixformat" ,(char*)pixformat}
|
||||||
|
};
|
||||||
|
|
||||||
|
if(mdns_service_add(NULL, service_name, proto, 80, camera_txt_data, 5)) {
|
||||||
|
ESP_LOGE(TAG, "mdns_service_add() ESP-CAM Failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xTaskCreate(mdns_task, "mdns-cam", 2048, NULL, 2, NULL);
|
||||||
|
}
|
|
@ -33,6 +33,8 @@
|
||||||
#include "lwip/err.h"
|
#include "lwip/err.h"
|
||||||
#include "lwip/sys.h"
|
#include "lwip/sys.h"
|
||||||
|
|
||||||
|
#include "mdns.h"
|
||||||
|
|
||||||
/* The examples use WiFi configuration that you can set via 'make menuconfig'.
|
/* The examples use WiFi configuration that you can set via 'make menuconfig'.
|
||||||
|
|
||||||
If you'd rather not, just change the below entries to strings with
|
If you'd rather not, just change the below entries to strings with
|
||||||
|
@ -83,6 +85,7 @@ static esp_err_t event_handler(void *ctx, system_event_t *event)
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
mdns_handle_system_event(ctx, event);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,4 +172,5 @@ void app_wifi_main()
|
||||||
wifi_init_sta();
|
wifi_init_sta();
|
||||||
}
|
}
|
||||||
ESP_ERROR_CHECK(esp_wifi_start());
|
ESP_ERROR_CHECK(esp_wifi_start());
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#define _APP_CAMERA_H_
|
#define _APP_CAMERA_H_
|
||||||
|
|
||||||
#if CONFIG_CAMERA_MODEL_WROVER_KIT
|
#if CONFIG_CAMERA_MODEL_WROVER_KIT
|
||||||
|
#define CAM_BOARD "WROVER-KIT"
|
||||||
#define PWDN_GPIO_NUM -1
|
#define PWDN_GPIO_NUM -1
|
||||||
#define RESET_GPIO_NUM -1
|
#define RESET_GPIO_NUM -1
|
||||||
#define XCLK_GPIO_NUM 21
|
#define XCLK_GPIO_NUM 21
|
||||||
|
@ -44,6 +45,7 @@
|
||||||
#define PCLK_GPIO_NUM 22
|
#define PCLK_GPIO_NUM 22
|
||||||
|
|
||||||
#elif CONFIG_CAMERA_MODEL_ESP32_CAM_BOARD
|
#elif CONFIG_CAMERA_MODEL_ESP32_CAM_BOARD
|
||||||
|
#define CAM_BOARD "ESP-DEVCAM"
|
||||||
#define PWDN_GPIO_NUM 32
|
#define PWDN_GPIO_NUM 32
|
||||||
#define RESET_GPIO_NUM 33
|
#define RESET_GPIO_NUM 33
|
||||||
#define XCLK_GPIO_NUM 4
|
#define XCLK_GPIO_NUM 4
|
||||||
|
@ -63,6 +65,7 @@
|
||||||
#define PCLK_GPIO_NUM 25
|
#define PCLK_GPIO_NUM 25
|
||||||
|
|
||||||
#elif CONFIG_CAMERA_MODEL_ESP_EYE
|
#elif CONFIG_CAMERA_MODEL_ESP_EYE
|
||||||
|
#define CAM_BOARD "ESP-EYE"
|
||||||
#define PWDN_GPIO_NUM -1
|
#define PWDN_GPIO_NUM -1
|
||||||
#define RESET_GPIO_NUM -1
|
#define RESET_GPIO_NUM -1
|
||||||
#define XCLK_GPIO_NUM 4
|
#define XCLK_GPIO_NUM 4
|
||||||
|
@ -82,6 +85,7 @@
|
||||||
#define PCLK_GPIO_NUM 25
|
#define PCLK_GPIO_NUM 25
|
||||||
|
|
||||||
#elif CONFIG_CAMERA_MODEL_M5STACK_PSRAM
|
#elif CONFIG_CAMERA_MODEL_M5STACK_PSRAM
|
||||||
|
#define CAM_BOARD "M5CAM"
|
||||||
#define PWDN_GPIO_NUM -1
|
#define PWDN_GPIO_NUM -1
|
||||||
#define RESET_GPIO_NUM 15
|
#define RESET_GPIO_NUM 15
|
||||||
#define XCLK_GPIO_NUM 27
|
#define XCLK_GPIO_NUM 27
|
||||||
|
@ -101,6 +105,7 @@
|
||||||
#define PCLK_GPIO_NUM 21
|
#define PCLK_GPIO_NUM 21
|
||||||
|
|
||||||
#elif CONFIG_CAMERA_MODEL_M5STACK_WIDE
|
#elif CONFIG_CAMERA_MODEL_M5STACK_WIDE
|
||||||
|
#define CAM_BOARD "M5CAMW"
|
||||||
#define PWDN_GPIO_NUM -1
|
#define PWDN_GPIO_NUM -1
|
||||||
#define RESET_GPIO_NUM 15
|
#define RESET_GPIO_NUM 15
|
||||||
#define XCLK_GPIO_NUM 27
|
#define XCLK_GPIO_NUM 27
|
||||||
|
@ -120,6 +125,7 @@
|
||||||
#define PCLK_GPIO_NUM 21
|
#define PCLK_GPIO_NUM 21
|
||||||
|
|
||||||
#elif CONFIG_CAMERA_MODEL_AI_THINKER
|
#elif CONFIG_CAMERA_MODEL_AI_THINKER
|
||||||
|
#define CAM_BOARD "AI-THINKER"
|
||||||
#define PWDN_GPIO_NUM 32
|
#define PWDN_GPIO_NUM 32
|
||||||
#define RESET_GPIO_NUM -1
|
#define RESET_GPIO_NUM -1
|
||||||
#define XCLK_GPIO_NUM 0
|
#define XCLK_GPIO_NUM 0
|
||||||
|
@ -140,23 +146,24 @@
|
||||||
|
|
||||||
|
|
||||||
#elif CONFIG_CAMERA_MODEL_CUSTOM
|
#elif CONFIG_CAMERA_MODEL_CUSTOM
|
||||||
#define PWDN_GPIO_NUM CONFIG_CAMERA_PIN_PWDN
|
#define CAM_BOARD "CUSTOM"
|
||||||
#define RESET_GPIO_NUM CONFIG_CAMERA_PIN_RESET
|
#define PWDN_GPIO_NUM CONFIG_CAMERA_PIN_PWDN
|
||||||
#define XCLK_GPIO_NUM CONFIG_CAMERA_PIN_XCLK
|
#define RESET_GPIO_NUM CONFIG_CAMERA_PIN_RESET
|
||||||
#define SIOD_GPIO_NUM CONFIG_CAMERA_PIN_SIOD
|
#define XCLK_GPIO_NUM CONFIG_CAMERA_PIN_XCLK
|
||||||
#define SIOC_GPIO_NUM CONFIG_CAMERA_PIN_SIOC
|
#define SIOD_GPIO_NUM CONFIG_CAMERA_PIN_SIOD
|
||||||
|
#define SIOC_GPIO_NUM CONFIG_CAMERA_PIN_SIOC
|
||||||
|
|
||||||
#define Y9_GPIO_NUM CONFIG_CAMERA_PIN_Y9
|
#define Y9_GPIO_NUM CONFIG_CAMERA_PIN_Y9
|
||||||
#define Y8_GPIO_NUM CONFIG_CAMERA_PIN_Y8
|
#define Y8_GPIO_NUM CONFIG_CAMERA_PIN_Y8
|
||||||
#define Y7_GPIO_NUM CONFIG_CAMERA_PIN_Y7
|
#define Y7_GPIO_NUM CONFIG_CAMERA_PIN_Y7
|
||||||
#define Y6_GPIO_NUM CONFIG_CAMERA_PIN_Y6
|
#define Y6_GPIO_NUM CONFIG_CAMERA_PIN_Y6
|
||||||
#define Y5_GPIO_NUM CONFIG_CAMERA_PIN_Y5
|
#define Y5_GPIO_NUM CONFIG_CAMERA_PIN_Y5
|
||||||
#define Y4_GPIO_NUM CONFIG_CAMERA_PIN_Y4
|
#define Y4_GPIO_NUM CONFIG_CAMERA_PIN_Y4
|
||||||
#define Y3_GPIO_NUM CONFIG_CAMERA_PIN_Y3
|
#define Y3_GPIO_NUM CONFIG_CAMERA_PIN_Y3
|
||||||
#define Y2_GPIO_NUM CONFIG_CAMERA_PIN_Y2
|
#define Y2_GPIO_NUM CONFIG_CAMERA_PIN_Y2
|
||||||
#define VSYNC_GPIO_NUM CONFIG_CAMERA_PIN_VSYNC
|
#define VSYNC_GPIO_NUM CONFIG_CAMERA_PIN_VSYNC
|
||||||
#define HREF_GPIO_NUM CONFIG_CAMERA_PIN_HREF
|
#define HREF_GPIO_NUM CONFIG_CAMERA_PIN_HREF
|
||||||
#define PCLK_GPIO_NUM CONFIG_CAMERA_PIN_PCLK
|
#define PCLK_GPIO_NUM CONFIG_CAMERA_PIN_PCLK
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright 2015-2020 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.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// 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.
|
||||||
|
#ifndef _CAMERA_MDNS_H_
|
||||||
|
#define _CAMERA_MDNS_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
void app_mdns_main();
|
||||||
|
void app_mdns_update_framesize(int size);
|
||||||
|
const char * app_mdns_query(size_t * out_len);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _CAMERA_MDNS_H_ */
|
|
@ -135,7 +135,7 @@
|
||||||
padding: 0 5px
|
padding: 0 5px
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button, .button {
|
||||||
display: block;
|
display: block;
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
|
@ -335,6 +335,17 @@
|
||||||
display: none
|
display: none
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.save {
|
||||||
|
position: absolute;
|
||||||
|
right: 25px;
|
||||||
|
top: 0px;
|
||||||
|
height: 16px;
|
||||||
|
line-height: 16px;
|
||||||
|
padding: 0 4px;
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer
|
||||||
|
}
|
||||||
|
|
||||||
input[type=text] {
|
input[type=text] {
|
||||||
border: 1px solid #363636;
|
border: 1px solid #363636;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
@ -391,7 +402,7 @@
|
||||||
<div class="input-group" id="framesize-group">
|
<div class="input-group" id="framesize-group">
|
||||||
<label for="framesize">Resolution</label>
|
<label for="framesize">Resolution</label>
|
||||||
<select id="framesize" class="default-action">
|
<select id="framesize" class="default-action">
|
||||||
<!-- 5MP -->
|
<!-- 5MP -->
|
||||||
<option value="21" selected="selected">QSXGA(2560x1920)</option>
|
<option value="21" selected="selected">QSXGA(2560x1920)</option>
|
||||||
<option value="20">P FHD(1080x1920)</option>
|
<option value="20">P FHD(1080x1920)</option>
|
||||||
<option value="19">WQXGA(2560x1600)</option>
|
<option value="19">WQXGA(2560x1600)</option>
|
||||||
|
@ -895,8 +906,9 @@
|
||||||
</div>
|
</div>
|
||||||
<figure>
|
<figure>
|
||||||
<div id="stream-container" class="image-container hidden">
|
<div id="stream-container" class="image-container hidden">
|
||||||
|
<a id="save-still" href="#" class="button save" download="capture.jpg">Save</a>
|
||||||
<div class="close" id="close-stream">×</div>
|
<div class="close" id="close-stream">×</div>
|
||||||
<img id="stream" src="">
|
<img id="stream" src="" crossorigin>
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
</div>
|
</div>
|
||||||
|
@ -987,15 +999,15 @@ document.addEventListener('DOMContentLoaded', function (event) {
|
||||||
document
|
document
|
||||||
.querySelectorAll('.reg-action')
|
.querySelectorAll('.reg-action')
|
||||||
.forEach(el => {
|
.forEach(el => {
|
||||||
if (el.type === 'text') {
|
if (el.type === 'text') {
|
||||||
el.onkeyup = function(e){
|
el.onkeyup = function(e){
|
||||||
if(e.keyCode == 13){
|
if(e.keyCode == 13){
|
||||||
setRegValue(el);
|
setRegValue(el);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
el.onchange = () => setRegValue(el)
|
el.onchange = () => setRegValue(el)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@ -1124,6 +1136,26 @@ document.addEventListener('DOMContentLoaded', function (event) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const saveButton = document.getElementById('save-still');
|
||||||
|
|
||||||
|
saveButton.onclick = () => {
|
||||||
|
var canvas = document.createElement("canvas");
|
||||||
|
canvas.width = view.width;
|
||||||
|
canvas.height = view.height;
|
||||||
|
document.body.appendChild(canvas);
|
||||||
|
var context = canvas.getContext('2d');
|
||||||
|
context.drawImage(view,0,0);
|
||||||
|
try {
|
||||||
|
var dataURL = canvas.toDataURL('image/jpeg');
|
||||||
|
saveButton.href = dataURL;
|
||||||
|
var d = new Date();
|
||||||
|
saveButton.download = d.getFullYear() + ("0"+(d.getMonth()+1)).slice(-2) + ("0" + d.getDate()).slice(-2) + ("0" + d.getHours()).slice(-2) + ("0" + d.getMinutes()).slice(-2) + ("0" + d.getSeconds()).slice(-2) + ".jpg";
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
canvas.parentNode.removeChild(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
const hide = el => {
|
const hide = el => {
|
||||||
el.classList.add('hidden')
|
el.classList.add('hidden')
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue