diff --git a/components/common/CMakeLists.txt b/components/common/CMakeLists.txt deleted file mode 100644 index f676e21..0000000 --- a/components/common/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -idf_component_register(SRC_DIRS . INCLUDE_DIRS include wallpaper REQUIRES esp32-camera esp-dl bus screen) - -component_compile_options(-ffast-math -O3) diff --git a/components/common/include/app_camera.hpp b/components/common/include/app_camera.hpp deleted file mode 100644 index 2f23e17..0000000 --- a/components/common/include/app_camera.hpp +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once - -#include "esp_camera.h" -#include "app_define.h" - -/** - * @brief Initialize camera - * - * @param pixformat One of - * - PIXFORMAT_RGB565 - * - PIXFORMAT_YUV422 - * - PIXFORMAT_GRAYSC - * - PIXFORMAT_JPEG - * - PIXFORMAT_RGB888 - * - PIXFORMAT_RAW - * - PIXFORMAT_RGB444 - * - PIXFORMAT_RGB555 - * @param frame_size One of - * - FRAMESIZE_96X96, // 96x96 - * - FRAMESIZE_QQVGA, // 160x120 - * - FRAMESIZE_QCIF, // 176x144 - * - FRAMESIZE_HQVGA, // 240x176 - * - FRAMESIZE_240X240, // 240x240 - * - FRAMESIZE_QVGA, // 320x240 - * - FRAMESIZE_CIF, // 400x296 - * - FRAMESIZE_HVGA, // 480x320 - * - FRAMESIZE_VGA, // 640x480 - * - FRAMESIZE_SVGA, // 800x600 - * - FRAMESIZE_XGA, // 1024x768 - * - FRAMESIZE_HD, // 1280x720 - * - FRAMESIZE_SXGA, // 1280x1024 - * - FRAMESIZE_UXGA, // 1600x1200 - * - FRAMESIZE_FHD, // 1920x1080 - * - FRAMESIZE_P_HD, // 720x1280 - * - FRAMESIZE_P_3MP, // 864x1536 - * - FRAMESIZE_QXGA, // 2048x1536 - * - FRAMESIZE_QHD, // 2560x1440 - * - FRAMESIZE_WQXGA, // 2560x1600 - * - FRAMESIZE_P_FHD, // 1080x1920 - * - FRAMESIZE_QSXGA, // 2560x1920 - * @param fb_count Number of frame buffers to be allocated. If more than one, then each frame will be acquired (double speed) - * @param jpeg_quality Quality of JPEG output. 0-63 lower means higher quality - */ -void app_camera_init(const pixformat_t pixel_fromat, const framesize_t frame_size, const uint8_t fb_count, const uint8_t jpeg_quality = 12); - -/** - * @brief Decode fb , - * - if fb->format == PIXFORMAT_RGB565, then return fb->buf - * - else, then return a new memory with RGB888, don't forget to free it - * - * @param fb - */ -void *app_camera_decode(camera_fb_t *fb); diff --git a/components/common/include/app_lcd.h b/components/common/include/app_lcd.h deleted file mode 100644 index cc3c5f1..0000000 --- a/components/common/include/app_lcd.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include -#include "esp_log.h" -#include "screen_driver.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - - esp_err_t app_lcd_init(); - void app_lcd_draw_wallpaper(); - void app_lcd_set_color(int color); - void app_lcd_draw_bitmap(uint16_t *image_ptr, const uint16_t image_height, const uint16_t image_width); - -#ifdef __cplusplus -} -#endif diff --git a/components/modules/CMakeLists.txt b/components/modules/CMakeLists.txt new file mode 100644 index 0000000..b06f3ea --- /dev/null +++ b/components/modules/CMakeLists.txt @@ -0,0 +1,31 @@ +set(embed_files "web/www/index_ov2640.html.gz" + "web/www/index_ov3660.html.gz" + "web/www/index_ov5640.html.gz" + "web/www/monitor.html.gz") + +set(src_dirs + ai + camera + lcd + led + web) + +set(include_dirs + ai + camera + lcd + led + web) + +set(requires esp32-camera + esp-dl + bus + screen + esp_http_server + nvs_flash + mdns + fb_gfx) + +idf_component_register(SRC_DIRS ${src_dirs} INCLUDE_DIRS ${include_dirs} REQUIRES ${requires} EMBED_FILES ${embed_files}) + +component_compile_options(-ffast-math -O3) diff --git a/components/common/Kconfig b/components/modules/Kconfig similarity index 65% rename from components/common/Kconfig rename to components/modules/Kconfig index 675f6ae..35724cb 100644 --- a/components/common/Kconfig +++ b/components/modules/Kconfig @@ -1,30 +1,64 @@ menu "ESP-WHO General Configuration" - menu "Camera Configuration" - - choice PIXEL_FORMAT - bool "Select Camera Pixel Format" - default CAMERA_PIXEL_FORMAT_RGB565 - help - Select Camera Pixel Format. - - config CAMERA_PIXEL_FORMAT_RGB565 - bool "RGB565" - config CAMERA_PIXEL_FORMAT_YUV422 - bool "YUV422" - config CAMERA_PIXEL_FORMAT_GRAYSCALE - bool "GRAYSCALE" - config CAMERA_PIXEL_FORMAT_JPEG - bool "JPEG" - config CAMERA_PIXEL_FORMAT_RGB888 - bool "RGB888" - config CAMERA_PIXEL_FORMAT_RAW - bool "RAW" - config CAMERA_PIXEL_FORMAT_RGB444 - bool "RGB444" - config CAMERA_PIXEL_FORMAT_RGB555 - bool "RGB555" + + menu "WiFi Configuration" - endchoice + config ESP_HOST_NAME + string "Camera Host Name" + default "" + help + Hostname that the camera will advertise over mDNS. + + config ESP_WIFI_SSID + string "WiFi STA SSID" + default "" + help + WiFi SSID (network name) to connect to or empty for Off. + + config ESP_WIFI_PASSWORD + string "WiFi STA Password" + default "" + help + WiFi Password if WEP/WPA/WPA2 or empty if Open. + + config ESP_WIFI_AP_SSID + string "WiFi AP SSID" + default "ESP32-Camera" + help + AP SSID (network name) to create or empty for Off. + + config ESP_WIFI_AP_PASSWORD + string "WiFi AP Password" + default "" + help + AP password for WPA2 or empty for Open. + + config MAX_STA_CONN + int "Maximal STA connections" + default 1 + help + Max number of the STA connects to AP. + + config ESP_WIFI_AP_CHANNEL + string "WiFi AP Channel" + default "" + help + AP channel for better connection performance. + + config SERVER_IP + string "WiFi AP IP Address" + default "192.168.4.1" + help + IP address that the ESP will assign to it's AP interface. You can use this IP to connect to the camera after flashing. + + config ESP_MAXIMUM_RETRY + int "Maximum retry" + default 5 + help + Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent. + + endmenu + + menu "Camera Configuration" choice CAMERA_MODULE bool "Select Camera Pinout" @@ -36,6 +70,8 @@ menu "ESP-WHO General Configuration" bool "WROVER-KIT With OV2640 Module" config CAMERA_MODULE_ESP_EYE bool "ESP-EYE DevKit" + config CAMERA_MODULE_ESP_S2_KALUGA + bool "ESP32-S2-Kaluga-1 V1.3" config CAMERA_MODULE_ESP_S3_EYE bool "ESP-S3-EYE DevKit" config CAMERA_MODEL_ESP32_CAM_BOARD @@ -232,84 +268,4 @@ menu "ESP-WHO General Configuration" help Select the LEDC Channel (0-7) endmenu - - - - menu "DL Configuration" - - config DL_ENABLED - bool "Enable Deep-Learning Application" - default y - - choice DL_SELECT_APP - bool "Select Application" - depends on DL_ENABLED - default DL_HUMAN_FACE - - config DL_HUMAN_FACE - bool "Human Face" - config DL_CAT_FACE - bool "Cat Face" - config DL_HUMAN_HAND - bool "Human Hand" - endchoice - - # Human Face Series - choice DL_HUMAN_FACE_DETECTION_S1_MODEL - bool "Select Human Face Detection Stage-1 Model" - depends on DL_HUMAN_FACE - default DL_HUMAN_FACE_DETECTION_S1_MSR01 - - config DL_HUMAN_FACE_DETECTION_S1_MSR01 - bool "HumanFaceDetectMSR01" - endchoice - - config DL_HUMAN_FACE_DETECTION_S2_ENABLED - bool "Enable Human Face Detection Stage-2" - depends on DL_HUMAN_FACE - default y - - choice DL_HUMAN_FACE_DETECTION_S2_MODEL - bool "Select Human Face Detection Stage-2 Model" - depends on DL_HUMAN_FACE_DETECTION_S2_ENABLED - default DL_HUMAN_FACE_DETECTION_S2_MNP01 - - config DL_HUMAN_FACE_DETECTION_S2_MNP01 - bool "HumanFaceDetectMNP01" - endchoice - - - config DL_HUMAN_FACE_RECOGNITION_ENABLED - bool "Enable Human Face Recognition" - depends on DL_HUMAN_FACE_DETECTION_S2_ENABLED - default y - - choice DL_HUMAN_FACE_RECOGNITION_MODEL - bool "Select Human Face Recognition Model" - depends on DL_HUMAN_FACE_RECOGNITION_ENABLED - default DL_HUMAN_FACE_RECOGNITION_XXX - - config DL_HUMAN_FACE_RECOGNITION_XXX - bool "HumanFaceRecognizeXXX" - endchoice - - # Cat Face Series - choice DL_CAT_FACE_DETECTION_MODEL - bool "Select Cat Face Detection Model" - depends on DL_CAT_FACE - default DL_CAT_FACE_DETECTION_MN03 - - config DL_CAT_FACE_DETECTION_MN03 - bool "CatFaceDetectMN03" - endchoice - - - # Human Hand Series - - - config DL_MOVING_TARGET_DETECTION_ENABLED - bool "Enable Moving Target Detection" - default y - - endmenu endmenu \ No newline at end of file diff --git a/components/common/app_common.cpp b/components/modules/ai/app_common.cpp similarity index 83% rename from components/common/app_common.cpp rename to components/modules/ai/app_common.cpp index eb07fa9..4c3cf49 100644 --- a/components/common/app_common.cpp +++ b/components/modules/ai/app_common.cpp @@ -1,7 +1,10 @@ #include "app_common.hpp" -#include "dl_image.hpp" #include "esp_log.h" +#include "esp_camera.h" + +#include "dl_image.hpp" + void draw_detection_result(uint16_t *image_ptr, int image_height, int image_width, std::list &results) { @@ -52,7 +55,7 @@ void print_detection_result(std::list &results) { ESP_LOGI("detection_result", "[%d]: (%3d, %3d, %3d, %3d)" #if CONFIG_DL_HUMAN_FACE_DETECTION_S2_ENABLED - " | left eye: (%3d, %3d), right eye: (%3d, %3d), nose: (%3d, %3d), mouth left: (%3d, %3d), mouth right: (%3d, %3d)" + " | left eye: (%3d, %3d), right eye: (%3d, %3d), nose: (%3d, %3d), mouth left: (%3d, %3d), mouth right: (%3d, %3d)" #endif , i, @@ -67,4 +70,33 @@ void print_detection_result(std::list &results) #endif ); } +} + +void *app_camera_decode(camera_fb_t *fb) +{ + if (fb->format == PIXFORMAT_RGB565) + { + return (void *)fb->buf; + } + else + { + uint8_t *image_ptr = (uint8_t *)malloc(fb->height * fb->width * 3 * sizeof(uint8_t)); + if (image_ptr) + { + if (fmt2rgb888(fb->buf, fb->len, fb->format, image_ptr)) + { + return (void *)image_ptr; + } + else + { + ESP_LOGE(TAG, "fmt2rgb888 failed"); + dl::tool::free_aligned(image_ptr); + } + } + else + { + ESP_LOGE(TAG, "malloc memory for image rgb888 failed"); + } + } + return NULL; } \ No newline at end of file diff --git a/components/common/include/app_common.hpp b/components/modules/ai/app_common.hpp similarity index 56% rename from components/common/include/app_common.hpp rename to components/modules/ai/app_common.hpp index 6f344e3..216414e 100644 --- a/components/common/include/app_common.hpp +++ b/components/modules/ai/app_common.hpp @@ -2,7 +2,25 @@ #include #include "dl_detect_define.hpp" -#include "app_define.h" +#include "esp_camera.h" +// #include "who_define.h" + +#if CONFIG_CAMERA_PIXEL_FORMAT_RGB565 +#define IMAGE_T uint16_t +#define COLOR_RED 0b0000000011111000 +#define COLOR_GREEN 0b1110000000000111 +#define COLOR_BLUE 0b0001111100000000 +#define COLOR_BLACK 0b0000000000000000 +#else +#define IMAGE_T uint8_t +#define COLOR_RED 0x0000FF +#define COLOR_GREEN 0x00FF00 +#define COLOR_BLUE 0xFF0000 +#define COLOR_BLACK 0x000000 +#endif + +static const char *TAG = "app_common"; + /** * @brief Draw detection result on RGB565 image. @@ -31,3 +49,12 @@ void draw_detection_result(uint8_t *image_ptr, int image_height, int image_width * @param results detection results */ void print_detection_result(std::list &results); + +/** + * @brief Decode fb , + * - if fb->format == PIXFORMAT_RGB565, then return fb->buf + * - else, then return a new memory with RGB888, don't forget to free it + * + * @param fb + */ +void *app_camera_decode(camera_fb_t *fb); diff --git a/components/common/app_dl.cpp b/components/modules/ai/who_cat_face_detection.cpp similarity index 100% rename from components/common/app_dl.cpp rename to components/modules/ai/who_cat_face_detection.cpp diff --git a/components/modules/ai/who_cat_face_detection.hpp b/components/modules/ai/who_cat_face_detection.hpp new file mode 100644 index 0000000..9da6717 --- /dev/null +++ b/components/modules/ai/who_cat_face_detection.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/task.h" +#include "freertos/semphr.h" + +void register_cat_face_detection(QueueHandle_t frame_i, QueueHandle_t event, + QueueHandle_t result, QueueHandle_t frame_o = NULL); diff --git a/components/modules/ai/who_motion_detection.hpp b/components/modules/ai/who_motion_detection.hpp new file mode 100644 index 0000000..88a219f --- /dev/null +++ b/components/modules/ai/who_motion_detection.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/task.h" +#include "freertos/semphr.h" + +void register_motion_detection(QueueHandle_t frame_i, QueueHandle_t event, + QueueHandle_t result, QueueHandle_t frame_o = NULL); diff --git a/components/common/app_camera.cpp b/components/modules/camera/who_camera.c similarity index 68% rename from components/common/app_camera.cpp rename to components/modules/camera/who_camera.c index 65823a1..c6d8a8d 100644 --- a/components/common/app_camera.cpp +++ b/components/modules/camera/who_camera.c @@ -1,14 +1,25 @@ -#include "app_camera.hpp" +#include "who_camera.h" #include "esp_log.h" #include "esp_system.h" -#include "app_define.h" -#include "dl_tool.hpp" +static const char *TAG = "who_camera"; +static QueueHandle_t xQueueFrameO = NULL; -static const char *TAG = "app_camera"; +static void task_process_handler(void *arg) +{ + while (true) + { + camera_fb_t *frame = esp_camera_fb_get(); + if (frame) + xQueueSend(xQueueFrameO, &frame, portMAX_DELAY); + } +} -void app_camera_init(const pixformat_t pixel_fromat, const framesize_t frame_size, const uint8_t fb_count, const uint8_t jpeg_quality) +void register_camera(const pixformat_t pixel_fromat, + const framesize_t frame_size, + const uint8_t fb_count, + const QueueHandle_t frame_o) { ESP_LOGI(TAG, "Camera module is %s", CAMERA_MODULE_NAME); @@ -49,8 +60,9 @@ void app_camera_init(const pixformat_t pixel_fromat, const framesize_t frame_siz config.xclk_freq_hz = XCLK_FREQ_HZ; config.pixel_format = pixel_fromat; config.frame_size = frame_size; - config.jpeg_quality = jpeg_quality; + config.jpeg_quality = 12; config.fb_count = fb_count; + config.fb_location = CAMERA_FB_IN_PSRAM; config.grab_mode = CAMERA_GRAB_WHEN_EMPTY; // camera init @@ -69,33 +81,7 @@ void app_camera_init(const pixformat_t pixel_fromat, const framesize_t frame_siz s->set_brightness(s, 1); //up the blightness just a bit s->set_saturation(s, -2); //lower the saturation } -} -void *app_camera_decode(camera_fb_t *fb) -{ - if (fb->format == PIXFORMAT_RGB565) - { - return (void *)fb->buf; - } - else - { - uint8_t *image_ptr = (uint8_t *)malloc(fb->height * fb->width * 3 * sizeof(uint8_t)); - if (image_ptr) - { - if (fmt2rgb888(fb->buf, fb->len, fb->format, image_ptr)) - { - return (void *)image_ptr; - } - else - { - ESP_LOGE(TAG, "fmt2rgb888 failed"); - dl::tool::free_aligned(image_ptr); - } - } - else - { - ESP_LOGE(TAG, "malloc memory for image rgb888 failed"); - } - } - return NULL; + xQueueFrameO = frame_o; + xTaskCreatePinnedToCore(task_process_handler, TAG, 2 * 1024, NULL, 5, NULL, 1); } diff --git a/components/common/include/app_define.h b/components/modules/camera/who_camera.h similarity index 60% rename from components/common/include/app_define.h rename to components/modules/camera/who_camera.h index fc62241..188bd9c 100644 --- a/components/common/include/app_define.h +++ b/components/modules/camera/who_camera.h @@ -1,22 +1,11 @@ #pragma once -#include -#include "esp_camera.h" -#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/task.h" +#include "freertos/semphr.h" -#if CONFIG_CAMERA_PIXEL_FORMAT_RGB565 -#define IMAGE_T uint16_t -#define COLOR_RED 0b0000000011111000 -#define COLOR_GREEN 0b1110000000000111 -#define COLOR_BLUE 0b0001111100000000 -#define COLOR_BLACK 0b0000000000000000 -#else -#define IMAGE_T uint8_t -#define COLOR_RED 0x0000FF -#define COLOR_GREEN 0x00FF00 -#define COLOR_BLUE 0xFF0000 -#define COLOR_BLACK 0x000000 -#endif +#include "esp_camera.h" #if CONFIG_CAMERA_MODULE_WROVER_KIT #define CAMERA_MODULE_NAME "Wrover Kit" @@ -58,10 +47,30 @@ #define CAMERA_PIN_HREF 27 #define CAMERA_PIN_PCLK 25 +#elif CONFIG_CAMERA_MODULE_ESP_S2_KALUGA +#define CAMERA_MODULE_NAME "ESP-S2-KALUGA" +#define CAMERA_PIN_PWDN -1 +#define CAMERA_PIN_RESET -1 +#define CAMERA_PIN_XCLK 1 +#define CAMERA_PIN_SIOD 8 +#define CAMERA_PIN_SIOC 7 + +#define CAMERA_PIN_D7 38 +#define CAMERA_PIN_D6 21 +#define CAMERA_PIN_D5 40 +#define CAMERA_PIN_D4 39 +#define CAMERA_PIN_D3 42 +#define CAMERA_PIN_D2 41 +#define CAMERA_PIN_D1 37 +#define CAMERA_PIN_D0 36 +#define CAMERA_PIN_VSYNC 2 +#define CAMERA_PIN_HREF 3 +#define CAMERA_PIN_PCLK 33 + #elif CONFIG_CAMERA_MODULE_ESP_S3_EYE #define CAMERA_MODULE_NAME "ESP-S3-EYE" -#define CAMERA_PIN_PWDN 43 -#define CAMERA_PIN_RESET 44 +#define CAMERA_PIN_PWDN -1 +#define CAMERA_PIN_RESET -1 #define CAMERA_PIN_VSYNC 6 #define CAMERA_PIN_HREF 7 @@ -185,27 +194,52 @@ #define XCLK_FREQ_HZ 20000000 -#if CONFIG_CAMERA_PIXEL_FORMAT_RGB565 -#define CAMERA_PIXEL_FORMAT PIXFORMAT_RGB565 +#ifdef __cplusplus +extern "C" +{ #endif -#if CONFIG_CAMERA_PIXEL_FORMAT_YUV422 -#define CAMERA_PIXEL_FORMAT PIXFORMAT_YUV422 -#endif -#if CONFIG_CAMERA_PIXEL_FORMAT_GRAYSCALE -#define CAMERA_PIXEL_FORMAT PIXFORMAT_GRAYSCALE -#endif -#if CONFIG_CAMERA_PIXEL_FORMAT_JPEG -#define CAMERA_PIXEL_FORMAT PIXFORMAT_JPEG -#endif -#if CONFIG_CAMERA_PIXEL_FORMAT_RGB888 -#define CAMERA_PIXEL_FORMAT PIXFORMAT_RGB888 -#endif -#if CONFIG_CAMERA_PIXEL_FORMAT_RAW -#define CAMERA_PIXEL_FORMAT PIXFORMAT_RAW -#endif -#if CONFIG_CAMERA_PIXEL_FORMAT_RGB444 -#define CAMERA_PIXEL_FORMAT PIXFORMAT_RGB444 -#endif -#if CONFIG_CAMERA_PIXEL_FORMAT_RGB555 -#define CAMERA_PIXEL_FORMAT PIXFORMAT_RGB555 + /** + * @brief Initialize camera + * + * @param pixformat One of + * - PIXFORMAT_RGB565 + * - PIXFORMAT_YUV422 + * - PIXFORMAT_GRAYSC + * - PIXFORMAT_JPEG + * - PIXFORMAT_RGB888 + * - PIXFORMAT_RAW + * - PIXFORMAT_RGB444 + * - PIXFORMAT_RGB555 + * @param frame_size One of + * - FRAMESIZE_96X96, // 96x96 + * - FRAMESIZE_QQVGA, // 160x120 + * - FRAMESIZE_QCIF, // 176x144 + * - FRAMESIZE_HQVGA, // 240x176 + * - FRAMESIZE_240X240, // 240x240 + * - FRAMESIZE_QVGA, // 320x240 + * - FRAMESIZE_CIF, // 400x296 + * - FRAMESIZE_HVGA, // 480x320 + * - FRAMESIZE_VGA, // 640x480 + * - FRAMESIZE_SVGA, // 800x600 + * - FRAMESIZE_XGA, // 1024x768 + * - FRAMESIZE_HD, // 1280x720 + * - FRAMESIZE_SXGA, // 1280x1024 + * - FRAMESIZE_UXGA, // 1600x1200 + * - FRAMESIZE_FHD, // 1920x1080 + * - FRAMESIZE_P_HD, // 720x1280 + * - FRAMESIZE_P_3MP, // 864x1536 + * - FRAMESIZE_QXGA, // 2048x1536 + * - FRAMESIZE_QHD, // 2560x1440 + * - FRAMESIZE_WQXGA, // 2560x1600 + * - FRAMESIZE_P_FHD, // 1080x1920 + * - FRAMESIZE_QSXGA, // 2560x1920 + * @param fb_count Number of frame buffers to be allocated. If more than one, then each frame will be acquired (double speed) + */ + void register_camera(const pixformat_t pixel_fromat, + const framesize_t frame_size, + const uint8_t fb_count, + const QueueHandle_t frame_o); + +#ifdef __cplusplus +} #endif diff --git a/components/common/wallpaper/wallpaper_128x240_rgb565.h b/components/modules/lcd/wallpaper_128x240_rgb565.h similarity index 100% rename from components/common/wallpaper/wallpaper_128x240_rgb565.h rename to components/modules/lcd/wallpaper_128x240_rgb565.h diff --git a/components/common/app_lcd.c b/components/modules/lcd/who_lcd.c similarity index 63% rename from components/common/app_lcd.c rename to components/modules/lcd/who_lcd.c index 3eee8f5..fa4d3ff 100644 --- a/components/common/app_lcd.c +++ b/components/modules/lcd/who_lcd.c @@ -1,26 +1,57 @@ -#include "app_lcd.h" +#include "who_lcd.h" +#include "esp_camera.h" #include #include "wallpaper_128x240_rgb565.h" -static const char *TAG = "app_lcd"; +static const char *TAG = "who_lcd"; static scr_driver_t g_lcd; static scr_info_t g_lcd_info; -esp_err_t app_lcd_init() +static QueueHandle_t xQueueFrameI = NULL; +static QueueHandle_t xQueueFrameO = NULL; +static bool gReturnFB = true; + +static void task_process_handler(void *arg) +{ + camera_fb_t *frame = NULL; + + while (true) + { + if (xQueueReceive(xQueueFrameI, &frame, portMAX_DELAY)) + { + g_lcd.draw_bitmap(0, 0, frame->width, frame->height, (uint16_t *)frame->buf); + + if (xQueueFrameO) + { + xQueueSend(xQueueFrameO, &frame, portMAX_DELAY); + } + else if (gReturnFB) + { + esp_camera_fb_return(frame); + } + else + { + free(frame); + } + } + } +} + +esp_err_t register_lcd(const QueueHandle_t frame_i, const QueueHandle_t frame_o, const bool return_fb) { spi_config_t bus_conf = { - .miso_io_num = -1, - .mosi_io_num = 48, - .sclk_io_num = 21, + .miso_io_num = BOARD_LCD_MISO, + .mosi_io_num = BOARD_LCD_MOSI, + .sclk_io_num = BOARD_LCD_SCK, .max_transfer_sz = 2 * 240 * 240 + 10, }; spi_bus_handle_t spi_bus = spi_bus_create(SPI2_HOST, &bus_conf); scr_interface_spi_config_t spi_lcd_cfg = { .spi_bus = spi_bus, - .pin_num_cs = 43, - .pin_num_dc = 47, + .pin_num_cs = BOARD_LCD_CS, + .pin_num_dc = BOARD_LCD_DC, .clk_freq = 40 * 1000000, .swap_data = 0, }; @@ -36,10 +67,10 @@ esp_err_t app_lcd_init() scr_controller_config_t lcd_cfg = { .interface_drv = iface_drv, - .pin_num_rst = -1, - .pin_num_bckl = -1, + .pin_num_rst = BOARD_LCD_RST, + .pin_num_bckl = BOARD_LCD_BL, .rst_active_level = 0, - .bckl_active_level = 1, + .bckl_active_level = 0, .offset_hor = 0, .offset_ver = 0, .width = 240, @@ -55,6 +86,17 @@ esp_err_t app_lcd_init() g_lcd.get_info(&g_lcd_info); ESP_LOGI(TAG, "Screen name:%s | width:%d | height:%d", g_lcd_info.name, g_lcd_info.width, g_lcd_info.height); + + app_lcd_set_color(0x000000); + vTaskDelay(pdMS_TO_TICKS(500)); + app_lcd_draw_wallpaper(); + vTaskDelay(pdMS_TO_TICKS(500)); + + xQueueFrameI = frame_i; + xQueueFrameO = frame_o; + gReturnFB = return_fb; + xTaskCreatePinnedToCore(task_process_handler, TAG, 4 * 1024, NULL, 5, NULL, 1); + return ESP_OK; } @@ -104,8 +146,3 @@ void app_lcd_set_color(int color) free(buffer); } } - -void app_lcd_draw_bitmap(uint16_t *image_ptr, const uint16_t image_height, const uint16_t image_width) -{ - g_lcd.draw_bitmap(0, 0, image_width, image_height, image_ptr); -} \ No newline at end of file diff --git a/components/modules/lcd/who_lcd.h b/components/modules/lcd/who_lcd.h new file mode 100644 index 0000000..3b0c9da --- /dev/null +++ b/components/modules/lcd/who_lcd.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include "esp_log.h" +#include "screen_driver.h" + +#define BOARD_LCD_MOSI 46 +#define BOARD_LCD_MISO -1 +#define BOARD_LCD_SCK 21 +#define BOARD_LCD_CS 44 +#define BOARD_LCD_DC 47 +#define BOARD_LCD_RST -1 +#define BOARD_LCD_BL 48 + +#ifdef __cplusplus +extern "C" +{ +#endif + + esp_err_t register_lcd(const QueueHandle_t frame_i, const QueueHandle_t frame_o, const bool return_fb); + + void app_lcd_draw_wallpaper(); + void app_lcd_set_color(int color); + +#ifdef __cplusplus +} +#endif diff --git a/components/common/app_led.c b/components/modules/led/who_led.c similarity index 98% rename from components/common/app_led.c rename to components/modules/led/who_led.c index 115c8c6..0fb3e3b 100644 --- a/components/common/app_led.c +++ b/components/modules/led/who_led.c @@ -1,4 +1,4 @@ -#include "app_led.h" +#include "who_led.h" #if CONFIG_LED_ILLUMINATOR_ENABLED #include "esp_log.h" diff --git a/components/common/include/app_led.h b/components/modules/led/who_led.h similarity index 100% rename from components/common/include/app_led.h rename to components/modules/led/who_led.h diff --git a/components/modules/web/app_httpd.cpp b/components/modules/web/app_httpd.cpp new file mode 100644 index 0000000..d571c9b --- /dev/null +++ b/components/modules/web/app_httpd.cpp @@ -0,0 +1,778 @@ +// 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. +// 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. + +#include "app_httpd.hpp" + +#include +#include "esp_http_server.h" +#include "esp_timer.h" +#include "img_converters.h" +#include "fb_gfx.h" +#include "app_mdns.h" +#include "sdkconfig.h" + +#include "who_camera.h" + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#define TAG "" +#else +#include "esp_log.h" +static const char *TAG = "camera_httpd"; +#endif + +static QueueHandle_t xQueueFrameI = NULL; +static QueueHandle_t xQueueFrameO = NULL; +static bool gReturnFB = true; + +static int8_t detection_enabled = 0; +static int8_t recognition_enabled = 0; +static int8_t is_enrolling = 0; + +typedef struct +{ + httpd_req_t *req; + size_t len; +} jpg_chunking_t; + +#define PART_BOUNDARY "123456789000000000000987654321" +static const char *_STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY; +static const char *_STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n"; +static const char *_STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\nX-Timestamp: %d.%06d\r\n\r\n"; + +httpd_handle_t stream_httpd = NULL; +httpd_handle_t camera_httpd = NULL; + +static size_t jpg_encode_stream(void *arg, size_t index, const void *data, size_t len) +{ + jpg_chunking_t *j = (jpg_chunking_t *)arg; + if (!index) + { + j->len = 0; + } + if (httpd_resp_send_chunk(j->req, (const char *)data, len) != ESP_OK) + { + return 0; + } + j->len += len; + return len; +} + +static esp_err_t capture_handler(httpd_req_t *req) +{ + camera_fb_t *frame = NULL; + esp_err_t res = ESP_OK; + + if (xQueueReceive(xQueueFrameI, &frame, portMAX_DELAY)) + { + httpd_resp_set_type(req, "image/jpeg"); + httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg"); + httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); + + char ts[32]; + snprintf(ts, 32, "%ld.%06ld", frame->timestamp.tv_sec, frame->timestamp.tv_usec); + httpd_resp_set_hdr(req, "X-Timestamp", (const char *)ts); + + // size_t fb_len = 0; + if (frame->format == PIXFORMAT_JPEG) + { + // fb_len = frame->len; + res = httpd_resp_send(req, (const char *)frame->buf, frame->len); + } + else + { + jpg_chunking_t jchunk = {req, 0}; + res = frame2jpg_cb(frame, 80, jpg_encode_stream, &jchunk) ? ESP_OK : ESP_FAIL; + httpd_resp_send_chunk(req, NULL, 0); + // fb_len = jchunk.len; + } + + if (xQueueFrameO) + { + xQueueSend(xQueueFrameO, &frame, portMAX_DELAY); + } + else if (gReturnFB) + { + esp_camera_fb_return(frame); + } + else + { + free(frame); + } + } + else + { + ESP_LOGE(TAG, "Camera capture failed"); + httpd_resp_send_500(req); + return ESP_FAIL; + } + + return res; +} + +static esp_err_t stream_handler(httpd_req_t *req) +{ + camera_fb_t *frame = NULL; + struct timeval _timestamp; + esp_err_t res = ESP_OK; + size_t _jpg_buf_len = 0; + uint8_t *_jpg_buf = NULL; + char *part_buf[128]; + + res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE); + if (res != ESP_OK) + { + return res; + } + + httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); + httpd_resp_set_hdr(req, "X-Framerate", "60"); + + while (true) + { + if (xQueueReceive(xQueueFrameI, &frame, portMAX_DELAY)) + { + _timestamp.tv_sec = frame->timestamp.tv_sec; + _timestamp.tv_usec = frame->timestamp.tv_usec; + + if (frame->format == PIXFORMAT_JPEG) + { + _jpg_buf = frame->buf; + _jpg_buf_len = frame->len; + } + else if (!frame2jpg(frame, 80, &_jpg_buf, &_jpg_buf_len)) + { + ESP_LOGE(TAG, "JPEG compression failed"); + res = ESP_FAIL; + } + } + else + { + res = ESP_FAIL; + } + + if (res == ESP_OK) + { + res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY)); + } + + if (res == ESP_OK) + { + size_t hlen = snprintf((char *)part_buf, 128, _STREAM_PART, _jpg_buf_len, _timestamp.tv_sec, _timestamp.tv_usec); + res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen); + } + + if (res == ESP_OK) + { + res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len); + } + + if (frame->format != PIXFORMAT_JPEG) + { + free(_jpg_buf); + _jpg_buf = NULL; + } + + if (xQueueFrameO) + { + xQueueSend(xQueueFrameO, &frame, portMAX_DELAY); + } + else if (gReturnFB) + { + esp_camera_fb_return(frame); + } + else + { + free(frame); + } + + if (res != ESP_OK) + { + break; + } + } + + return res; +} + +static esp_err_t parse_get(httpd_req_t *req, char **obuf) +{ + char *buf = NULL; + size_t buf_len = 0; + + buf_len = httpd_req_get_url_query_len(req) + 1; + if (buf_len > 1) + { + buf = (char *)malloc(buf_len); + if (!buf) + { + httpd_resp_send_500(req); + return ESP_FAIL; + } + if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) + { + *obuf = buf; + return ESP_OK; + } + free(buf); + } + httpd_resp_send_404(req); + return ESP_FAIL; +} + +static esp_err_t cmd_handler(httpd_req_t *req) +{ + char *buf = NULL; + char variable[32]; + char value[32]; + + if (parse_get(req, &buf) != ESP_OK || + httpd_query_key_value(buf, "var", variable, sizeof(variable)) != ESP_OK || + httpd_query_key_value(buf, "val", value, sizeof(value)) != ESP_OK) + { + free(buf); + httpd_resp_send_404(req); + return ESP_FAIL; + } + free(buf); + + int val = atoi(value); + ESP_LOGI(TAG, "%s = %d", variable, val); + sensor_t *s = esp_camera_sensor_get(); + int res = 0; + + if (!strcmp(variable, "framesize")) + { + if (s->pixformat == PIXFORMAT_JPEG) + { + res = s->set_framesize(s, (framesize_t)val); + if (res == 0) + { + app_mdns_update_framesize(val); + } + } + } + else if (!strcmp(variable, "quality")) + res = s->set_quality(s, 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); + else if (!strcmp(variable, "gainceiling")) + res = s->set_gainceiling(s, (gainceiling_t)val); + else if (!strcmp(variable, "colorbar")) + res = s->set_colorbar(s, val); + else if (!strcmp(variable, "awb")) + res = s->set_whitebal(s, val); + else if (!strcmp(variable, "agc")) + res = s->set_gain_ctrl(s, val); + else if (!strcmp(variable, "aec")) + res = s->set_exposure_ctrl(s, val); + else if (!strcmp(variable, "hmirror")) + res = s->set_hmirror(s, val); + else if (!strcmp(variable, "vflip")) + res = s->set_vflip(s, val); + else if (!strcmp(variable, "awb_gain")) + res = s->set_awb_gain(s, val); + else if (!strcmp(variable, "agc_gain")) + res = s->set_agc_gain(s, val); + else if (!strcmp(variable, "aec_value")) + res = s->set_aec_value(s, val); + else if (!strcmp(variable, "aec2")) + res = s->set_aec2(s, val); + else if (!strcmp(variable, "dcw")) + res = s->set_dcw(s, val); + else if (!strcmp(variable, "bpc")) + res = s->set_bpc(s, val); + else if (!strcmp(variable, "wpc")) + res = s->set_wpc(s, val); + else if (!strcmp(variable, "raw_gma")) + res = s->set_raw_gma(s, val); + else if (!strcmp(variable, "lenc")) + res = s->set_lenc(s, val); + else if (!strcmp(variable, "special_effect")) + res = s->set_special_effect(s, val); + else if (!strcmp(variable, "wb_mode")) + res = s->set_wb_mode(s, val); + else if (!strcmp(variable, "ae_level")) + res = s->set_ae_level(s, val); +#ifdef CONFIG_LED_ILLUMINATOR_ENABLED + else if (!strcmp(variable, "led_intensity")) + led_duty = val; +#endif + + else if (!strcmp(variable, "face_detect")) + { + detection_enabled = val; + if (!detection_enabled) + { + recognition_enabled = 0; + } + } + else if (!strcmp(variable, "face_enroll")) + is_enrolling = val; + else if (!strcmp(variable, "face_recognize")) + { + recognition_enabled = val; + if (recognition_enabled) + { + detection_enabled = val; + } + } + else + { + res = -1; + } + + if (res) + { + return httpd_resp_send_500(req); + } + + httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); + return httpd_resp_send(req, NULL, 0); +} + +static int print_reg(char *p, sensor_t *s, uint16_t reg, uint32_t mask) +{ + return sprintf(p, "\"0x%x\":%u,", reg, s->get_reg(s, reg, mask)); +} + +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; + *p++ = '{'; + + if (s->id.PID == OV5640_PID || s->id.PID == OV3660_PID) + { + for (int reg = 0x3400; reg < 0x3406; reg += 2) + { + p += print_reg(p, s, reg, 0xFFF); //12 bit + } + p += print_reg(p, s, 0x3406, 0xFF); + + p += print_reg(p, s, 0x3500, 0xFFFF0); //16 bit + p += print_reg(p, s, 0x3503, 0xFF); + p += print_reg(p, s, 0x350a, 0x3FF); //10 bit + p += print_reg(p, s, 0x350c, 0xFFFF); //16 bit + + for (int reg = 0x5480; reg <= 0x5490; reg++) + { + p += print_reg(p, s, reg, 0xFF); + } + + for (int reg = 0x5380; reg <= 0x538b; reg++) + { + p += print_reg(p, s, reg, 0xFF); + } + + for (int reg = 0x5580; reg < 0x558a; reg++) + { + p += print_reg(p, s, reg, 0xFF); + } + p += print_reg(p, s, 0x558a, 0x1FF); //9 bit + } + else + { + p += print_reg(p, s, 0xd3, 0xFF); + p += print_reg(p, s, 0x111, 0xFF); + p += print_reg(p, s, 0x132, 0xFF); + } + + p += sprintf(p, "\"board\":\"%s\",", CAMERA_MODULE_NAME); + p += sprintf(p, "\"xclk\":%u,", s->xclk_freq_hz / 1000000); + p += sprintf(p, "\"pixformat\":%u,", s->pixformat); + p += sprintf(p, "\"framesize\":%u,", s->status.framesize); + p += sprintf(p, "\"quality\":%u,", s->status.quality); + p += sprintf(p, "\"brightness\":%d,", s->status.brightness); + p += sprintf(p, "\"contrast\":%d,", s->status.contrast); + p += sprintf(p, "\"saturation\":%d,", s->status.saturation); + p += sprintf(p, "\"sharpness\":%d,", s->status.sharpness); + p += sprintf(p, "\"special_effect\":%u,", s->status.special_effect); + p += sprintf(p, "\"wb_mode\":%u,", s->status.wb_mode); + p += sprintf(p, "\"awb\":%u,", s->status.awb); + p += sprintf(p, "\"awb_gain\":%u,", s->status.awb_gain); + p += sprintf(p, "\"aec\":%u,", s->status.aec); + p += sprintf(p, "\"aec2\":%u,", s->status.aec2); + p += sprintf(p, "\"ae_level\":%d,", s->status.ae_level); + p += sprintf(p, "\"aec_value\":%u,", s->status.aec_value); + p += sprintf(p, "\"agc\":%u,", s->status.agc); + p += sprintf(p, "\"agc_gain\":%u,", s->status.agc_gain); + p += sprintf(p, "\"gainceiling\":%u,", s->status.gainceiling); + p += sprintf(p, "\"bpc\":%u,", s->status.bpc); + p += sprintf(p, "\"wpc\":%u,", s->status.wpc); + p += sprintf(p, "\"raw_gma\":%u,", s->status.raw_gma); + p += sprintf(p, "\"lenc\":%u,", s->status.lenc); + p += sprintf(p, "\"hmirror\":%u,", s->status.hmirror); + p += sprintf(p, "\"dcw\":%u,", s->status.dcw); + p += sprintf(p, "\"colorbar\":%u", s->status.colorbar); +#ifdef CONFIG_LED_ILLUMINATOR_ENABLED + p += sprintf(p, ",\"led_intensity\":%u", led_duty); +#else + p += sprintf(p, ",\"led_intensity\":%d", -1); +#endif + p += sprintf(p, ",\"face_detect\":%u", detection_enabled); + p += sprintf(p, ",\"face_enroll\":%u,", is_enrolling); + p += sprintf(p, "\"face_recognize\":%u", recognition_enabled); + *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 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) +{ + char *buf = NULL; + char _xclk[32]; + + if (parse_get(req, &buf) != ESP_OK || + httpd_query_key_value(buf, "xclk", _xclk, sizeof(_xclk)) != ESP_OK) + { + free(buf); + httpd_resp_send_404(req); + return ESP_FAIL; + } + free(buf); + + int xclk = atoi(_xclk); + ESP_LOGI(TAG, "Set XCLK: %d MHz", xclk); + + sensor_t *s = esp_camera_sensor_get(); + int res = s->set_xclk(s, LEDC_TIMER_0, xclk); + if (res) + { + return httpd_resp_send_500(req); + } + + httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); + return httpd_resp_send(req, NULL, 0); +} + +static esp_err_t reg_handler(httpd_req_t *req) +{ + char *buf = NULL; + char _reg[32]; + char _mask[32]; + char _val[32]; + + if (parse_get(req, &buf) != ESP_OK || + httpd_query_key_value(buf, "reg", _reg, sizeof(_reg)) != ESP_OK || + httpd_query_key_value(buf, "mask", _mask, sizeof(_mask)) != ESP_OK || + httpd_query_key_value(buf, "val", _val, sizeof(_val)) != ESP_OK) + { + free(buf); + httpd_resp_send_404(req); + return ESP_FAIL; + } + free(buf); + + int reg = atoi(_reg); + int mask = atoi(_mask); + int val = atoi(_val); + ESP_LOGI(TAG, "Set Register: reg: 0x%02x, mask: 0x%02x, value: 0x%02x", reg, mask, val); + + sensor_t *s = esp_camera_sensor_get(); + int res = s->set_reg(s, reg, mask, val); + if (res) + { + return httpd_resp_send_500(req); + } + + httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); + return httpd_resp_send(req, NULL, 0); +} + +static esp_err_t greg_handler(httpd_req_t *req) +{ + char *buf = NULL; + char _reg[32]; + char _mask[32]; + + if (parse_get(req, &buf) != ESP_OK || + httpd_query_key_value(buf, "reg", _reg, sizeof(_reg)) != ESP_OK || + httpd_query_key_value(buf, "mask", _mask, sizeof(_mask)) != ESP_OK) + { + free(buf); + httpd_resp_send_404(req); + return ESP_FAIL; + } + free(buf); + + int reg = atoi(_reg); + int mask = atoi(_mask); + sensor_t *s = esp_camera_sensor_get(); + int res = s->get_reg(s, reg, mask); + if (res < 0) + { + return httpd_resp_send_500(req); + } + ESP_LOGI(TAG, "Get Register: reg: 0x%02x, mask: 0x%02x, value: 0x%02x", reg, mask, res); + + char buffer[20]; + const char *val = itoa(res, buffer, 10); + httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); + return httpd_resp_send(req, val, strlen(val)); +} + +static int parse_get_var(char *buf, const char *key, int def) +{ + char _int[16]; + if (httpd_query_key_value(buf, key, _int, sizeof(_int)) != ESP_OK) + { + return def; + } + return atoi(_int); +} + +static esp_err_t pll_handler(httpd_req_t *req) +{ + char *buf = NULL; + + if (parse_get(req, &buf) != ESP_OK) + { + free(buf); + httpd_resp_send_404(req); + return ESP_FAIL; + } + + int bypass = parse_get_var(buf, "bypass", 0); + int mul = parse_get_var(buf, "mul", 0); + int sys = parse_get_var(buf, "sys", 0); + int root = parse_get_var(buf, "root", 0); + int pre = parse_get_var(buf, "pre", 0); + int seld5 = parse_get_var(buf, "seld5", 0); + int pclken = parse_get_var(buf, "pclken", 0); + int pclk = parse_get_var(buf, "pclk", 0); + free(buf); + + ESP_LOGI(TAG, "Set Pll: bypass: %d, mul: %d, sys: %d, root: %d, pre: %d, seld5: %d, pclken: %d, pclk: %d", bypass, mul, sys, root, pre, seld5, pclken, pclk); + sensor_t *s = esp_camera_sensor_get(); + int res = s->set_pll(s, bypass, mul, sys, root, pre, seld5, pclken, pclk); + if (res) + { + return httpd_resp_send_500(req); + } + + httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); + return httpd_resp_send(req, NULL, 0); +} + +static esp_err_t win_handler(httpd_req_t *req) +{ + char *buf = NULL; + + if (parse_get(req, &buf) != ESP_OK) + { + free(buf); + httpd_resp_send_404(req); + return ESP_FAIL; + } + + int startX = parse_get_var(buf, "sx", 0); + int startY = parse_get_var(buf, "sy", 0); + int endX = parse_get_var(buf, "ex", 0); + int endY = parse_get_var(buf, "ey", 0); + int offsetX = parse_get_var(buf, "offx", 0); + int offsetY = parse_get_var(buf, "offy", 0); + int totalX = parse_get_var(buf, "tx", 0); + int totalY = parse_get_var(buf, "ty", 0); + int outputX = parse_get_var(buf, "ox", 0); + int outputY = parse_get_var(buf, "oy", 0); + bool scale = parse_get_var(buf, "scale", 0) == 1; + bool binning = parse_get_var(buf, "binning", 0) == 1; + free(buf); + + ESP_LOGI(TAG, "Set Window: Start: %d %d, End: %d %d, Offset: %d %d, Total: %d %d, Output: %d %d, Scale: %u, Binning: %u", startX, startY, endX, endY, offsetX, offsetY, totalX, totalY, outputX, outputY, scale, binning); + sensor_t *s = esp_camera_sensor_get(); + int res = s->set_res_raw(s, startX, startY, endX, endY, offsetX, offsetY, totalX, totalY, outputX, outputY, scale, binning); + if (res) + { + return httpd_resp_send_500(req); + } + + httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); + return httpd_resp_send(req, NULL, 0); +} + +static esp_err_t index_handler(httpd_req_t *req) +{ + extern const unsigned char index_ov2640_html_gz_start[] asm("_binary_index_ov2640_html_gz_start"); + extern const unsigned char index_ov2640_html_gz_end[] asm("_binary_index_ov2640_html_gz_end"); + size_t index_ov2640_html_gz_len = index_ov2640_html_gz_end - index_ov2640_html_gz_start; + + extern const unsigned char index_ov3660_html_gz_start[] asm("_binary_index_ov3660_html_gz_start"); + extern const unsigned char index_ov3660_html_gz_end[] asm("_binary_index_ov3660_html_gz_end"); + size_t index_ov3660_html_gz_len = index_ov3660_html_gz_end - index_ov3660_html_gz_start; + + extern const unsigned char index_ov5640_html_gz_start[] asm("_binary_index_ov5640_html_gz_start"); + extern const unsigned char index_ov5640_html_gz_end[] asm("_binary_index_ov5640_html_gz_end"); + size_t index_ov5640_html_gz_len = index_ov5640_html_gz_end - index_ov5640_html_gz_start; + + httpd_resp_set_type(req, "text/html"); + httpd_resp_set_hdr(req, "Content-Encoding", "gzip"); + sensor_t *s = esp_camera_sensor_get(); + if (s != NULL) + { + if (s->id.PID == OV3660_PID) + { + return httpd_resp_send(req, (const char *)index_ov3660_html_gz_start, index_ov3660_html_gz_len); + } + else if (s->id.PID == OV5640_PID) + { + return httpd_resp_send(req, (const char *)index_ov5640_html_gz_start, index_ov5640_html_gz_len); + } + else + { + return httpd_resp_send(req, (const char *)index_ov2640_html_gz_start, index_ov2640_html_gz_len); + } + } + else + { + ESP_LOGE(TAG, "Camera sensor not found"); + return httpd_resp_send_500(req); + } +} + +static esp_err_t monitor_handler(httpd_req_t *req) +{ + extern const unsigned char monitor_html_gz_start[] asm("_binary_monitor_html_gz_start"); + extern const unsigned char monitor_html_gz_end[] asm("_binary_monitor_html_gz_end"); + size_t monitor_html_gz_len = monitor_html_gz_end - monitor_html_gz_start; + httpd_resp_set_type(req, "text/html"); + httpd_resp_set_hdr(req, "Content-Encoding", "gzip"); + return httpd_resp_send(req, (const char *)monitor_html_gz_start, monitor_html_gz_len); +} + +void register_httpd(const QueueHandle_t frame_i, const QueueHandle_t frame_o, const bool return_fb) +{ + xQueueFrameI = frame_i; + xQueueFrameO = frame_o; + gReturnFB = return_fb; + + httpd_config_t config = HTTPD_DEFAULT_CONFIG(); + config.max_uri_handlers = 12; + + httpd_uri_t index_uri = { + .uri = "/", + .method = HTTP_GET, + .handler = index_handler, + .user_ctx = NULL}; + + httpd_uri_t status_uri = { + .uri = "/status", + .method = HTTP_GET, + .handler = status_handler, + .user_ctx = NULL}; + + httpd_uri_t cmd_uri = { + .uri = "/control", + .method = HTTP_GET, + .handler = cmd_handler, + .user_ctx = NULL}; + + httpd_uri_t capture_uri = { + .uri = "/capture", + .method = HTTP_GET, + .handler = capture_handler, + .user_ctx = NULL}; + + httpd_uri_t stream_uri = { + .uri = "/stream", + .method = HTTP_GET, + .handler = stream_handler, + .user_ctx = NULL}; + + httpd_uri_t xclk_uri = { + .uri = "/xclk", + .method = HTTP_GET, + .handler = xclk_handler, + .user_ctx = NULL}; + + httpd_uri_t reg_uri = { + .uri = "/reg", + .method = HTTP_GET, + .handler = reg_handler, + .user_ctx = NULL}; + + httpd_uri_t greg_uri = { + .uri = "/greg", + .method = HTTP_GET, + .handler = greg_handler, + .user_ctx = NULL}; + + httpd_uri_t pll_uri = { + .uri = "/pll", + .method = HTTP_GET, + .handler = pll_handler, + .user_ctx = NULL}; + + httpd_uri_t win_uri = { + .uri = "/resolution", + .method = HTTP_GET, + .handler = win_handler, + .user_ctx = NULL}; + + httpd_uri_t mdns_uri = { + .uri = "/mdns", + .method = HTTP_GET, + .handler = mdns_handler, + .user_ctx = NULL}; + + httpd_uri_t monitor_uri = { + .uri = "/monitor", + .method = HTTP_GET, + .handler = monitor_handler, + .user_ctx = NULL}; + + ESP_LOGI(TAG, "Starting web server on port: '%d'", config.server_port); + if (httpd_start(&camera_httpd, &config) == ESP_OK) + { + 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, &xclk_uri); + httpd_register_uri_handler(camera_httpd, ®_uri); + httpd_register_uri_handler(camera_httpd, &greg_uri); + httpd_register_uri_handler(camera_httpd, &pll_uri); + httpd_register_uri_handler(camera_httpd, &win_uri); + + httpd_register_uri_handler(camera_httpd, &mdns_uri); + httpd_register_uri_handler(camera_httpd, &monitor_uri); + } + + config.server_port += 1; + config.ctrl_port += 1; + ESP_LOGI(TAG, "Starting stream server on port: '%d'", config.server_port); + if (httpd_start(&stream_httpd, &config) == ESP_OK) + { + httpd_register_uri_handler(stream_httpd, &stream_uri); + } +} diff --git a/components/modules/web/app_httpd.hpp b/components/modules/web/app_httpd.hpp new file mode 100644 index 0000000..28d08da --- /dev/null +++ b/components/modules/web/app_httpd.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/task.h" +#include "freertos/semphr.h" + +void register_httpd(const QueueHandle_t frame_i, const QueueHandle_t frame_o, const bool return_fb); diff --git a/components/modules/web/app_mdns.c b/components/modules/web/app_mdns.c new file mode 100644 index 0000000..ad9f6da --- /dev/null +++ b/components/modules/web/app_mdns.c @@ -0,0 +1,250 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2020 + * + * 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 +#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 "who_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\",", CAMERA_MODULE_NAME); + 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; ttxt_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); + + sensor_t * s = esp_camera_sensor_get(); + if(s == NULL){ + return; + } + 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; + } + + if (strlen(CONFIG_ESP_HOST_NAME) > 0) { + snprintf(iname, 64, "%s", CONFIG_ESP_HOST_NAME); + } else { + if (esp_read_mac(mac, ESP_MAC_WIFI_STA) != ESP_OK) { + ESP_LOGE(TAG, "esp_read_mac() Failed"); + return; + } + snprintf(iname, 64, "%s-%s-%02X%02X%02X", CAMERA_MODULE_NAME, 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*)CAMERA_MODULE_NAME}, + {(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); +} \ No newline at end of file diff --git a/components/modules/web/app_mdns.h b/components/modules/web/app_mdns.h new file mode 100644 index 0000000..002a448 --- /dev/null +++ b/components/modules/web/app_mdns.h @@ -0,0 +1,16 @@ +#pragma once + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + + void app_mdns_main(); + void app_mdns_update_framesize(int size); + const char *app_mdns_query(size_t *out_len); + +#ifdef __cplusplus +} +#endif diff --git a/components/modules/web/app_wifi.c b/components/modules/web/app_wifi.c new file mode 100644 index 0000000..9a6a5bb --- /dev/null +++ b/components/modules/web/app_wifi.c @@ -0,0 +1,196 @@ +/* ESPRESSIF MIT License + * + * Copyright (c) 2018 + * + * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, 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 +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "sdkconfig.h" + +#include "lwip/err.h" +#include "lwip/sys.h" + +#include "mdns.h" + +/* 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 + the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" +*/ +#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID +#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD +#define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY +#define EXAMPLE_ESP_WIFI_AP_SSID CONFIG_ESP_WIFI_AP_SSID +#define EXAMPLE_ESP_WIFI_AP_PASS CONFIG_ESP_WIFI_AP_PASSWORD +#define EXAMPLE_MAX_STA_CONN CONFIG_MAX_STA_CONN +#define EXAMPLE_IP_ADDR CONFIG_SERVER_IP +#define EXAMPLE_ESP_WIFI_AP_CHANNEL CONFIG_ESP_WIFI_AP_CHANNEL + +static const char *TAG = "camera wifi"; + +static int s_retry_num = 0; + +static esp_err_t event_handler(void *ctx, system_event_t *event) +{ + switch (event->event_id) + { + case SYSTEM_EVENT_AP_STACONNECTED: + ESP_LOGI(TAG, "station:" MACSTR " join, AID=%d", + MAC2STR(event->event_info.sta_connected.mac), + event->event_info.sta_connected.aid); + break; + case SYSTEM_EVENT_AP_STADISCONNECTED: + ESP_LOGI(TAG, "station:" MACSTR "leave, AID=%d", + MAC2STR(event->event_info.sta_disconnected.mac), + event->event_info.sta_disconnected.aid); + break; + case SYSTEM_EVENT_STA_START: + esp_wifi_connect(); + break; + case SYSTEM_EVENT_STA_GOT_IP: + ESP_LOGI(TAG, "got ip:%s", + ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); + s_retry_num = 0; + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + { + if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) + { + esp_wifi_connect(); + s_retry_num++; + ESP_LOGI(TAG, "retry to connect to the AP"); + } + ESP_LOGI(TAG, "connect to the AP fail"); + break; + } + default: + break; + } + mdns_handle_system_event(ctx, event); + return ESP_OK; +} + +void wifi_init_softap() +{ + if (strcmp(EXAMPLE_IP_ADDR, "192.168.4.1")) + { + int a, b, c, d; + sscanf(EXAMPLE_IP_ADDR, "%d.%d.%d.%d", &a, &b, &c, &d); + tcpip_adapter_ip_info_t ip_info; + IP4_ADDR(&ip_info.ip, a, b, c, d); + IP4_ADDR(&ip_info.gw, a, b, c, d); + IP4_ADDR(&ip_info.netmask, 255, 255, 255, 0); + ESP_ERROR_CHECK(tcpip_adapter_dhcps_stop(WIFI_IF_AP)); + ESP_ERROR_CHECK(tcpip_adapter_set_ip_info(WIFI_IF_AP, &ip_info)); + ESP_ERROR_CHECK(tcpip_adapter_dhcps_start(WIFI_IF_AP)); + } + wifi_config_t wifi_config; + memset(&wifi_config, 0, sizeof(wifi_config_t)); + snprintf((char *)wifi_config.ap.ssid, 32, "%s", EXAMPLE_ESP_WIFI_AP_SSID); + wifi_config.ap.ssid_len = strlen((char *)wifi_config.ap.ssid); + snprintf((char *)wifi_config.ap.password, 64, "%s", EXAMPLE_ESP_WIFI_AP_PASS); + wifi_config.ap.max_connection = EXAMPLE_MAX_STA_CONN; + wifi_config.ap.authmode = WIFI_AUTH_WPA_WPA2_PSK; + if (strlen(EXAMPLE_ESP_WIFI_AP_PASS) == 0) + { + wifi_config.ap.authmode = WIFI_AUTH_OPEN; + } + if (strlen(EXAMPLE_ESP_WIFI_AP_CHANNEL)) + { + int channel; + sscanf(EXAMPLE_ESP_WIFI_AP_CHANNEL, "%d", &channel); + wifi_config.ap.channel = channel; + } + + ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config)); + + ESP_LOGI(TAG, "wifi_init_softap finished.SSID:%s password:%s", + EXAMPLE_ESP_WIFI_AP_SSID, EXAMPLE_ESP_WIFI_AP_PASS); +} + +void wifi_init_sta() +{ + wifi_config_t wifi_config; + memset(&wifi_config, 0, sizeof(wifi_config_t)); + snprintf((char *)wifi_config.sta.ssid, 32, "%s", EXAMPLE_ESP_WIFI_SSID); + snprintf((char *)wifi_config.sta.password, 64, "%s", EXAMPLE_ESP_WIFI_PASS); + + ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); + + ESP_LOGI(TAG, "wifi_init_sta finished."); + ESP_LOGI(TAG, "connect to ap SSID:%s password:%s", + EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); +} + +void app_wifi_main() +{ + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + wifi_mode_t mode = WIFI_MODE_NULL; + + if (strlen(EXAMPLE_ESP_WIFI_AP_SSID) && strlen(EXAMPLE_ESP_WIFI_SSID)) + { + mode = WIFI_MODE_APSTA; + } + else if (strlen(EXAMPLE_ESP_WIFI_AP_SSID)) + { + mode = WIFI_MODE_AP; + } + else if (strlen(EXAMPLE_ESP_WIFI_SSID)) + { + mode = WIFI_MODE_STA; + } + + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) + { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + if (mode == WIFI_MODE_NULL) + { + ESP_LOGW(TAG, "Neither AP or STA have been configured. WiFi will be off."); + return; + } + + tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + ESP_ERROR_CHECK(esp_wifi_set_mode(mode)); + + if (mode & WIFI_MODE_AP) + { + wifi_init_softap(); + } + + if (mode & WIFI_MODE_STA) + { + wifi_init_sta(); + } + ESP_ERROR_CHECK(esp_wifi_start()); + ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE)); +} diff --git a/components/modules/web/app_wifi.h b/components/modules/web/app_wifi.h new file mode 100644 index 0000000..dc164e9 --- /dev/null +++ b/components/modules/web/app_wifi.h @@ -0,0 +1,37 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2017 + * + * 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. + * + */ +#ifndef _APP_WIFI_H_ +#define _APP_WIFI_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void app_wifi_main(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/modules/web/www/compress_pages.sh b/components/modules/web/www/compress_pages.sh new file mode 100755 index 0000000..f7c13fb --- /dev/null +++ b/components/modules/web/www/compress_pages.sh @@ -0,0 +1,7 @@ +#!/bin/bash +for file in `ls *.html`; do + echo "Compressing: $file" + cp "$file" "copy_$file" && \ + gzip -f "$file" && \ + mv "copy_$file" "$file" +done diff --git a/components/modules/web/www/index_ov2640.html b/components/modules/web/www/index_ov2640.html new file mode 100644 index 0000000..cac38f9 --- /dev/null +++ b/components/modules/web/www/index_ov2640.html @@ -0,0 +1,1152 @@ + + + + + + ESP32 OV2460 + + + +
+ +
+ +
+ +
+
+
+ + + diff --git a/components/modules/web/www/index_ov2640.html.gz b/components/modules/web/www/index_ov2640.html.gz new file mode 100644 index 0000000..b0e1ddb Binary files /dev/null and b/components/modules/web/www/index_ov2640.html.gz differ diff --git a/components/modules/web/www/index_ov3660.html b/components/modules/web/www/index_ov3660.html new file mode 100644 index 0000000..e7b71cf --- /dev/null +++ b/components/modules/web/www/index_ov3660.html @@ -0,0 +1,1368 @@ + + + + + + ESP32 OV3660 + + + +
+ +
+ +
+ +
+
+
+ + + diff --git a/components/modules/web/www/index_ov3660.html.gz b/components/modules/web/www/index_ov3660.html.gz new file mode 100644 index 0000000..8274a21 Binary files /dev/null and b/components/modules/web/www/index_ov3660.html.gz differ diff --git a/components/modules/web/www/index_ov5640.html b/components/modules/web/www/index_ov5640.html new file mode 100644 index 0000000..a6c01f9 --- /dev/null +++ b/components/modules/web/www/index_ov5640.html @@ -0,0 +1,1391 @@ + + + + + + ESP32 OV5640 + + + +
+ +
+ +
+ +
+
+
+ + + diff --git a/components/modules/web/www/index_ov5640.html.gz b/components/modules/web/www/index_ov5640.html.gz new file mode 100644 index 0000000..b5f4f48 Binary files /dev/null and b/components/modules/web/www/index_ov5640.html.gz differ diff --git a/components/modules/web/www/monitor.html b/components/modules/web/www/monitor.html new file mode 100755 index 0000000..1b98342 --- /dev/null +++ b/components/modules/web/www/monitor.html @@ -0,0 +1,1012 @@ + + + + + + + ESP-EYE Monitor + + +
+
+
+
+ + + + + + + + + +
+
+
+
+ + + + + + + + +
+
+
+ +
+
+
+

Console

+
+
+
+
+
+ + diff --git a/components/modules/web/www/monitor.html.gz b/components/modules/web/www/monitor.html.gz new file mode 100755 index 0000000..ef4a8fc Binary files /dev/null and b/components/modules/web/www/monitor.html.gz differ