mirror of
https://github.com/MrUnknownDE/OpenIris-ESPIDF.git
synced 2026-04-14 12:13:45 +02:00
PoC wired mode over UVC, add logs over websockets, needs cleanup
This commit is contained in:
11
bootloader_components/CMakeLists.txt
Normal file
11
bootloader_components/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
# source: https://github.com/espressif/esp-iot-solution/blob/4730d91db70df7e6e0a3191d725ab1c5f98ff9ce/examples/usb/device/usb_webcam/bootloader_components/boot_hooks/CMakeLists.txt
|
||||
if("$ENV{IDF_TARGET}" STREQUAL "esp32s3")
|
||||
idf_component_register(SRCS "boot_hooks.c")
|
||||
endif()
|
||||
|
||||
# We need to force GCC to integrate this static library into the
|
||||
# bootloader link. Indeed, by default, as the hooks in the bootloader are weak,
|
||||
# the linker would just ignore the symbols in the extra. (i.e. not strictly
|
||||
# required)
|
||||
# To do so, we need to define the symbol (function) `bootloader_hooks_include`
|
||||
# within hooks.c source file.
|
||||
24
bootloader_components/boot_hooks.c
Normal file
24
bootloader_components/boot_hooks.c
Normal file
@@ -0,0 +1,24 @@
|
||||
// source: https://github.com/espressif/esp-iot-solution/blob/4730d91db70df7e6e0a3191d725ab1c5f98ff9ce/examples/usb/device/usb_webcam/bootloader_components/boot_hooks/boot_hooks.c
|
||||
|
||||
#ifdef CONFIG_WIRED_MODE
|
||||
#include "esp_log.h"
|
||||
#include "soc/rtc_cntl_struct.h"
|
||||
#include "soc/usb_serial_jtag_reg.h"
|
||||
|
||||
/* Function used to tell the linker to include this file
|
||||
* with all its symbols.
|
||||
*/
|
||||
|
||||
void bootloader_hooks_include(void)
|
||||
{
|
||||
}
|
||||
|
||||
void bootloader_before_init(void)
|
||||
{
|
||||
|
||||
// Disable D+ pullup, to prevent the USB host from retrieving USB-Serial-JTAG's descriptor.
|
||||
SET_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_PAD_PULL_OVERRIDE);
|
||||
CLEAR_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_DP_PULLUP);
|
||||
CLEAR_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_USB_PAD_ENABLE);
|
||||
}
|
||||
#endif
|
||||
@@ -51,40 +51,6 @@ void CameraManager::setupCameraPinout()
|
||||
#if ETVR_EYE_TRACKER_USB_API
|
||||
xclk_freq_hz = USB_DEFAULT_XCLK_FREQ_HZ;
|
||||
#endif
|
||||
|
||||
// config = {
|
||||
// .pin_pwdn = CAM_PIN_PWDN,
|
||||
// .pin_reset = CAM_PIN_RESET,
|
||||
// .pin_xclk = CAM_PIN_XCLK,
|
||||
// .pin_sccb_sda = CAM_PIN_SIOD,
|
||||
// .pin_sccb_scl = CAM_PIN_SIOC,
|
||||
|
||||
// .pin_d7 = CAM_PIN_D7,
|
||||
// .pin_d6 = CAM_PIN_D6,
|
||||
// .pin_d5 = CAM_PIN_D5,
|
||||
// .pin_d4 = CAM_PIN_D4,
|
||||
// .pin_d3 = CAM_PIN_D3,
|
||||
// .pin_d2 = CAM_PIN_D2,
|
||||
// .pin_d1 = CAM_PIN_D1,
|
||||
// .pin_d0 = CAM_PIN_D0,
|
||||
// .pin_vsync = CAM_PIN_VSYNC,
|
||||
// .pin_href = CAM_PIN_HREF,
|
||||
// .pin_pclk = CAM_PIN_PCLK,
|
||||
|
||||
// // XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental)
|
||||
// .xclk_freq_hz = 20000000,
|
||||
// .ledc_timer = LEDC_TIMER_0,
|
||||
// .ledc_channel = LEDC_CHANNEL_0,
|
||||
|
||||
// .pixel_format = PIXFORMAT_RGB565, // YUV422,GRAYSCALE,RGB565,JPEG
|
||||
// .frame_size = FRAMESIZE_QVGA, // QQVGA-UXGA, For ESP32, do not use sizes above QVGA when not JPEG. The performance of the ESP32-S series has improved a lot, but JPEG mode always gives better frame rates.
|
||||
|
||||
// .jpeg_quality = 12, // 0-63, for OV series camera sensors, lower number means higher quality
|
||||
// .fb_count = 1, // When jpeg mode is used, if fb_count more than one, the driver will work in continuous mode.
|
||||
// .fb_location = CAMERA_FB_IN_PSRAM,
|
||||
// .grab_mode = CAMERA_GRAB_WHEN_EMPTY,
|
||||
// };
|
||||
|
||||
// todo fix pinout in sdkconfig lmao
|
||||
config = {
|
||||
.pin_pwdn = -1, // CAM_PIN_PWDN,
|
||||
@@ -118,37 +84,6 @@ void CameraManager::setupCameraPinout()
|
||||
.fb_count = 2, // 3 // When jpeg mode is used, if fb_count more than one, the driver will work in continuous mode.
|
||||
.fb_location = CAMERA_FB_IN_PSRAM, // maybe it cannot put them fully in psram?
|
||||
.grab_mode = CAMERA_GRAB_WHEN_EMPTY, // CAMERA_GRAB_LATEST
|
||||
|
||||
// .pin_pwdn = CONFIG_PWDN_GPIO_NUM,
|
||||
// .pin_reset = CONFIG_RESET_GPIO_NUM,
|
||||
// .pin_xclk = CONFIG_XCLK_GPIO_NUM,
|
||||
// .pin_sccb_sda = CONFIG_SIOD_GPIO_NUM,
|
||||
// .pin_sccb_scl = CONFIG_SIOC_GPIO_NUM,
|
||||
|
||||
// .pin_d7 = CONFIG_Y2_GPIO_NUM,
|
||||
// .pin_d6 = CONFIG_Y3_GPIO_NUM,
|
||||
// .pin_d5 = CONFIG_Y4_GPIO_NUM,
|
||||
// .pin_d4 = CONFIG_Y5_GPIO_NUM,
|
||||
// .pin_d3 = CONFIG_Y6_GPIO_NUM,
|
||||
// .pin_d2 = CONFIG_Y7_GPIO_NUM,
|
||||
// .pin_d1 = CONFIG_Y8_GPIO_NUM,
|
||||
// .pin_d0 = CONFIG_Y9_GPIO_NUM,
|
||||
|
||||
// .pin_vsync = CONFIG_VSYNC_GPIO_NUM,
|
||||
// .pin_href = CONFIG_HREF_GPIO_NUM,
|
||||
// .pin_pclk = CONFIG_PCLK_GPIO_NUM,
|
||||
|
||||
// .xclk_freq_hz = xclk_freq_hz,
|
||||
|
||||
// .ledc_timer = LEDC_TIMER_0,
|
||||
// .ledc_channel = LEDC_CHANNEL_0,
|
||||
|
||||
// .pixel_format = PIXFORMAT_JPEG,
|
||||
// .frame_size = FRAMESIZE_240X240,
|
||||
// .jpeg_quality = 7,
|
||||
// .fb_count = 3,
|
||||
// .fb_location = CAMERA_FB_IN_PSRAM,
|
||||
// .grab_mode = CAMERA_GRAB_LATEST,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// ported by: Lorow, do not trust this please
|
||||
|
||||
#pragma once
|
||||
#ifndef _PREFERENCES_HPP_
|
||||
#define _PREFERENCES_HPP_
|
||||
#ifndef PREFERENCES_HPP
|
||||
#define PREFERENCES_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
@@ -84,4 +84,4 @@ public:
|
||||
size_t freeEntries();
|
||||
};
|
||||
|
||||
#endif _PREFERENCES_HPP_
|
||||
#endif PREFERENCES_HPP
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
idf_component_register(SRCS "StreamServer/StreamServer.cpp"
|
||||
INCLUDE_DIRS "StreamServer"
|
||||
REQUIRES esp32-camera StateManager ProjectConfig esp_http_server Helpers
|
||||
REQUIRES esp32-camera StateManager ProjectConfig esp_http_server Helpers WebSocketLogger
|
||||
)
|
||||
@@ -6,7 +6,10 @@ constexpr static const char *STREAM_PART = "Content-Type: image/jpeg\r\nContent-
|
||||
|
||||
static const char *STREAM_SERVER_TAG = "[STREAM_SERVER]";
|
||||
|
||||
// the stream is super low FPS, find out why
|
||||
StreamServer::StreamServer(const int STREAM_PORT) : STREAM_SERVER_PORT(STREAM_PORT)
|
||||
{
|
||||
}
|
||||
|
||||
esp_err_t StreamHelpers::stream(httpd_req_t *req)
|
||||
{
|
||||
long last_request_time = 0;
|
||||
@@ -76,15 +79,14 @@ esp_err_t StreamHelpers::stream(httpd_req_t *req)
|
||||
return response;
|
||||
}
|
||||
|
||||
StreamServer::StreamServer(const int STREAM_PORT) : STREAM_SERVER_PORT(STREAM_PORT) {}
|
||||
esp_err_t StreamHelpers::ws_logs_handle(httpd_req_t *req)
|
||||
{
|
||||
auto ret = webSocketLogger.register_socket_client(req);
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t StreamServer::startStreamServer()
|
||||
{
|
||||
if (cameraStateManager.getCurrentState() != CameraState_e::Camera_Success)
|
||||
{
|
||||
ESP_LOGE(STREAM_SERVER_TAG, "Camera not initialized. Cannot start stream server.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||
config.stack_size = 20480;
|
||||
@@ -99,6 +101,14 @@ esp_err_t StreamServer::startStreamServer()
|
||||
.user_ctx = nullptr,
|
||||
};
|
||||
|
||||
httpd_uri_t logs_ws = {
|
||||
.uri = "/ws",
|
||||
.method = HTTP_GET,
|
||||
.handler = &StreamHelpers::ws_logs_handle,
|
||||
.user_ctx = nullptr,
|
||||
.is_websocket = true,
|
||||
};
|
||||
|
||||
int status = httpd_start(&camera_stream, &config);
|
||||
|
||||
if (status != ESP_OK)
|
||||
@@ -107,7 +117,15 @@ esp_err_t StreamServer::startStreamServer()
|
||||
return status;
|
||||
}
|
||||
|
||||
httpd_register_uri_handler(camera_stream, &logs_ws);
|
||||
if (cameraStateManager.getCurrentState() != CameraState_e::Camera_Success)
|
||||
{
|
||||
ESP_LOGE(STREAM_SERVER_TAG, "Camera not initialized. Cannot start stream server. Logs server will be running.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
httpd_register_uri_handler(camera_stream, &stream_page);
|
||||
|
||||
ESP_LOGI(STREAM_SERVER_TAG, "Stream server started on port %d", STREAM_SERVER_PORT);
|
||||
// todo add printing IP addr here
|
||||
|
||||
|
||||
@@ -9,22 +9,29 @@
|
||||
#include "esp_http_server.h"
|
||||
#include "esp_timer.h"
|
||||
#include <StateManager.hpp>
|
||||
#include <WebSocketLogger.hpp >
|
||||
#include <Helpers.hpp>
|
||||
|
||||
extern WebSocketLogger webSocketLogger;
|
||||
|
||||
namespace StreamHelpers
|
||||
{
|
||||
esp_err_t stream(httpd_req_t *req);
|
||||
esp_err_t ws_logs_handle(httpd_req_t *req);
|
||||
}
|
||||
|
||||
class StreamServer
|
||||
{
|
||||
private:
|
||||
httpd_handle_t camera_stream = nullptr;
|
||||
int STREAM_SERVER_PORT;
|
||||
httpd_handle_t camera_stream = nullptr;
|
||||
|
||||
public:
|
||||
StreamServer(const int STREAM_PORT = 80);
|
||||
StreamServer(const int STREAM_PORT);
|
||||
esp_err_t startStreamServer();
|
||||
|
||||
esp_err_t stream(httpd_req_t *req);
|
||||
esp_err_t ws_logs_handle(httpd_req_t *req);
|
||||
};
|
||||
|
||||
#endif
|
||||
4
components/UVCStream/CMakeLists.txt
Normal file
4
components/UVCStream/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
idf_component_register(SRCS "UVCStream/UVCStream.cpp"
|
||||
INCLUDE_DIRS "UVCStream"
|
||||
REQUIRES esp_timer esp32-camera StateManager usb_device_uvc
|
||||
)
|
||||
239
components/UVCStream/UVCStream/UVCStream.cpp
Normal file
239
components/UVCStream/UVCStream/UVCStream.cpp
Normal file
@@ -0,0 +1,239 @@
|
||||
#include "UVCStream.hpp"
|
||||
constexpr int UVC_MAX_FRAMESIZE_SIZE(75 * 1024);
|
||||
|
||||
static const char *UVC_STREAM_TAG = "[UVC DEVICE]";
|
||||
|
||||
// debug only
|
||||
static esp_err_t camera_init(int xclk_freq_hz, pixformat_t pixel_format, framesize_t frame_size, int jpeg_quality, uint8_t fb_count)
|
||||
{
|
||||
static bool inited = false;
|
||||
static int cur_xclk_freq_hz = 20000000;
|
||||
static pixformat_t cur_pixel_format = PIXFORMAT_JPEG;
|
||||
static framesize_t cur_frame_size = FRAMESIZE_96X96;
|
||||
static int cur_jpeg_quality = 0;
|
||||
static uint8_t cur_fb_count = 0;
|
||||
|
||||
if ((inited && cur_xclk_freq_hz == xclk_freq_hz && cur_pixel_format == pixel_format && cur_frame_size == frame_size && cur_fb_count == fb_count && cur_jpeg_quality == jpeg_quality))
|
||||
{
|
||||
ESP_LOGD(UVC_STREAM_TAG, "camera already inited");
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (inited)
|
||||
{
|
||||
esp_camera_return_all();
|
||||
esp_camera_deinit();
|
||||
inited = false;
|
||||
ESP_LOGI(UVC_STREAM_TAG, "camera RESTART");
|
||||
}
|
||||
|
||||
camera_config_t camera_config = {
|
||||
.pin_pwdn = -1, // CAM_PIN_PWDN,
|
||||
.pin_reset = -1, // CAM_PIN_RESET,
|
||||
.pin_xclk = 10, // CAM_PIN_XCLK,
|
||||
.pin_sccb_sda = 40, // CAM_PIN_SIOD,
|
||||
.pin_sccb_scl = 39, // CAM_PIN_SIOC,
|
||||
|
||||
.pin_d7 = 48, /// CAM_PIN_D7,
|
||||
.pin_d6 = 11, /// CAM_PIN_D6,
|
||||
.pin_d5 = 12, // CAM_PIN_D5,
|
||||
.pin_d4 = 14, // CAM_PIN_D4,
|
||||
.pin_d3 = 16, // CAM_PIN_D3,
|
||||
.pin_d2 = 18, // CAM_PIN_D2,
|
||||
.pin_d1 = 17, // CAM_PIN_D1,
|
||||
.pin_d0 = 15, // CAM_PIN_D0,
|
||||
.pin_vsync = 38, // CAM_PIN_VSYNC,
|
||||
.pin_href = 47, // CAM_PIN_HREF,
|
||||
.pin_pclk = 13, // CAM_PIN_PCLK,
|
||||
|
||||
.xclk_freq_hz = xclk_freq_hz,
|
||||
.ledc_timer = LEDC_TIMER_0,
|
||||
.ledc_channel = LEDC_CHANNEL_0,
|
||||
|
||||
.pixel_format = pixel_format,
|
||||
.frame_size = frame_size,
|
||||
|
||||
.jpeg_quality = jpeg_quality,
|
||||
.fb_count = fb_count,
|
||||
.fb_location = CAMERA_FB_IN_PSRAM,
|
||||
.grab_mode = CAMERA_GRAB_WHEN_EMPTY,
|
||||
};
|
||||
|
||||
// initialize the camera sensor
|
||||
esp_err_t ret = esp_camera_init(&camera_config);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Get the sensor object, and then use some of its functions to adjust the parameters when taking a photo.
|
||||
// Note: Do not call functions that set resolution, set picture format and PLL clock,
|
||||
// If you need to reset the appeal parameters, please reinitialize the sensor.
|
||||
sensor_t *s = esp_camera_sensor_get();
|
||||
s->set_vflip(s, 1); // flip it back
|
||||
// initial sensors are flipped vertically and colors are a bit saturated
|
||||
if (s->id.PID == OV3660_PID)
|
||||
{
|
||||
s->set_brightness(s, 1); // up the blightness just a bit
|
||||
s->set_saturation(s, -2); // lower the saturation
|
||||
}
|
||||
|
||||
if (s->id.PID == OV3660_PID || s->id.PID == OV2640_PID)
|
||||
{
|
||||
s->set_vflip(s, 1); // flip it back
|
||||
}
|
||||
else if (s->id.PID == GC0308_PID)
|
||||
{
|
||||
s->set_hmirror(s, 0);
|
||||
}
|
||||
else if (s->id.PID == GC032A_PID)
|
||||
{
|
||||
s->set_vflip(s, 1);
|
||||
}
|
||||
|
||||
// Get the basic information of the sensor.
|
||||
camera_sensor_info_t *s_info = esp_camera_sensor_get_info(&(s->id));
|
||||
|
||||
if (ESP_OK == ret && PIXFORMAT_JPEG == pixel_format && s_info->support_jpeg == true)
|
||||
{
|
||||
cur_xclk_freq_hz = xclk_freq_hz;
|
||||
cur_pixel_format = pixel_format;
|
||||
cur_frame_size = frame_size;
|
||||
cur_jpeg_quality = jpeg_quality;
|
||||
cur_fb_count = fb_count;
|
||||
inited = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(UVC_STREAM_TAG, "JPEG format is not supported");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t UVCStreamHelpers::camera_start_cb(uvc_format_t format, int width, int height, int rate, void *cb_ctx)
|
||||
{
|
||||
(void)cb_ctx;
|
||||
ESP_LOGI(UVC_STREAM_TAG, "Camera Start");
|
||||
ESP_LOGI(UVC_STREAM_TAG, "Format: %d, width: %d, height: %d, rate: %d", format, width, height, rate);
|
||||
framesize_t frame_size = FRAMESIZE_QVGA;
|
||||
int jpeg_quality = 10;
|
||||
|
||||
if (format != UVC_FORMAT_JPEG)
|
||||
{
|
||||
ESP_LOGE(UVC_STREAM_TAG, "Only support MJPEG format");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (width == 240 && height == 240)
|
||||
{
|
||||
frame_size = FRAMESIZE_240X240;
|
||||
jpeg_quality = 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(UVC_STREAM_TAG, "Unsupported frame size %dx%d", width, height);
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_err_t ret = camera_init(20000000, PIXFORMAT_JPEG, frame_size, jpeg_quality, 2);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(UVC_STREAM_TAG, "camera init failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void UVCStreamHelpers::camera_stop_cb(void *cb_ctx)
|
||||
{
|
||||
(void)cb_ctx;
|
||||
if (s_fb.cam_fb_p)
|
||||
{
|
||||
esp_camera_fb_return(s_fb.cam_fb_p);
|
||||
s_fb.cam_fb_p = nullptr;
|
||||
}
|
||||
|
||||
ESP_LOGI(UVC_STREAM_TAG, "Camera Stop");
|
||||
}
|
||||
|
||||
static uvc_fb_t *UVCStreamHelpers::camera_fb_get_cb(void *cb_ctx)
|
||||
{
|
||||
(void)cb_ctx;
|
||||
s_fb.cam_fb_p = esp_camera_fb_get();
|
||||
|
||||
if (!s_fb.cam_fb_p)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
s_fb.uvc_fb.buf = s_fb.cam_fb_p->buf;
|
||||
s_fb.uvc_fb.len = s_fb.cam_fb_p->len;
|
||||
s_fb.uvc_fb.width = s_fb.cam_fb_p->width;
|
||||
s_fb.uvc_fb.height = s_fb.cam_fb_p->height;
|
||||
s_fb.uvc_fb.format = UVC_FORMAT_JPEG; // we gotta make sure we're ALWAYS using JPEG
|
||||
s_fb.uvc_fb.timestamp = s_fb.cam_fb_p->timestamp;
|
||||
|
||||
if (s_fb.uvc_fb.len > UVC_MAX_FRAMESIZE_SIZE)
|
||||
{
|
||||
ESP_LOGE(UVC_STREAM_TAG, "Frame size %d is larger than max frame size %d", s_fb.uvc_fb.len, UVC_MAX_FRAMESIZE_SIZE);
|
||||
esp_camera_fb_return(s_fb.cam_fb_p);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &s_fb.uvc_fb;
|
||||
}
|
||||
|
||||
static void UVCStreamHelpers::camera_fb_return_cb(uvc_fb_t *fb, void *cb_ctx)
|
||||
{
|
||||
(void)cb_ctx;
|
||||
assert(fb == &s_fb.uvc_fb);
|
||||
esp_camera_fb_return(s_fb.cam_fb_p);
|
||||
}
|
||||
|
||||
esp_err_t UVCStreamManager::setup()
|
||||
{
|
||||
ESP_LOGI(UVC_STREAM_TAG, "Setting up UVC Stream");
|
||||
|
||||
uvc_buffer = (uint8_t *)malloc(UVC_MAX_FRAMESIZE_SIZE);
|
||||
if (uvc_buffer == nullptr)
|
||||
{
|
||||
ESP_LOGE(UVC_STREAM_TAG, "Allocating buffer for UVC Device failed");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
uvc_device_config_t config = {
|
||||
.uvc_buffer = uvc_buffer,
|
||||
.uvc_buffer_size = UVC_MAX_FRAMESIZE_SIZE,
|
||||
.start_cb = UVCStreamHelpers::camera_start_cb,
|
||||
.fb_get_cb = UVCStreamHelpers::camera_fb_get_cb,
|
||||
.fb_return_cb = UVCStreamHelpers::camera_fb_return_cb,
|
||||
.stop_cb = UVCStreamHelpers::camera_stop_cb,
|
||||
};
|
||||
|
||||
esp_err_t ret = uvc_device_config(0, &config);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(UVC_STREAM_TAG, "Configuring UVC Device failed: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(UVC_STREAM_TAG, "Configured UVC Device");
|
||||
}
|
||||
|
||||
ESP_LOGI(UVC_STREAM_TAG, "Initializing UVC Device");
|
||||
ret = uvc_device_init();
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(UVC_STREAM_TAG, "Initializing UVC Device failed: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(UVC_STREAM_TAG, "Initialized UVC Device");
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
37
components/UVCStream/UVCStream/UVCStream.hpp
Normal file
37
components/UVCStream/UVCStream/UVCStream.hpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
#ifndef UVCSTREAM_HPP
|
||||
#define UVCSTREAM_HPP
|
||||
#include "esp_timer.h"
|
||||
#include "esp_camera.h"
|
||||
#include "esp_log.h"
|
||||
#include "usb_device_uvc.h"
|
||||
|
||||
namespace UVCStreamHelpers
|
||||
{
|
||||
// TODO move the camera handling code to the camera manager and have the uvc maanger initialize it in wired mode
|
||||
|
||||
typedef struct
|
||||
{
|
||||
camera_fb_t *cam_fb_p;
|
||||
uvc_fb_t uvc_fb;
|
||||
} fb_t;
|
||||
|
||||
static fb_t s_fb;
|
||||
|
||||
static esp_err_t camera_start_cb(uvc_format_t format, int width, int height, int rate, void *cb_ctx);
|
||||
static void camera_stop_cb(void *cb_ctx);
|
||||
static esp_err_t camera_start_cb(uvc_format_t format, int width, int height, int rate, void *cb_ctx);
|
||||
static uvc_fb_t *camera_fb_get_cb(void *cb_ctx);
|
||||
static void camera_fb_return_cb(uvc_fb_t *fb, void *cb_ctx);
|
||||
}
|
||||
|
||||
class UVCStreamManager
|
||||
{
|
||||
private:
|
||||
uint8_t *uvc_buffer;
|
||||
|
||||
public:
|
||||
esp_err_t setup();
|
||||
};
|
||||
|
||||
#endif // UVCSTREAM_HPP
|
||||
4
components/WebSocketLogger/CMakeLists.txt
Normal file
4
components/WebSocketLogger/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
idf_component_register(SRCS "WebSocketLogger/WebSocketLogger.cpp"
|
||||
INCLUDE_DIRS "WebSocketLogger"
|
||||
REQUIRES esp_http_server
|
||||
)
|
||||
@@ -0,0 +1,71 @@
|
||||
#include "WebSocketLogger.hpp"
|
||||
|
||||
WebSocketLogger::WebSocketLogger()
|
||||
{
|
||||
this->connected_socket_client = async_resp_arg{
|
||||
.hd = nullptr,
|
||||
.fd = -1,
|
||||
};
|
||||
|
||||
this->ws_log_buffer[0] = '\0';
|
||||
}
|
||||
|
||||
void LoggerHelpers::ws_async_send(void *arg)
|
||||
{
|
||||
char *log_buffer = webSocketLogger.get_websocket_log_buffer();
|
||||
|
||||
struct async_resp_arg *resp_arg = (struct async_resp_arg *)arg;
|
||||
httpd_handle_t hd = resp_arg->hd;
|
||||
int fd = resp_arg->fd;
|
||||
|
||||
httpd_ws_frame_t websocket_packet = httpd_ws_frame_t{};
|
||||
|
||||
websocket_packet.payload = (uint8_t *)log_buffer;
|
||||
websocket_packet.len = strlen(log_buffer);
|
||||
websocket_packet.type = HTTPD_WS_TYPE_TEXT;
|
||||
|
||||
httpd_ws_send_frame_async(hd, fd, &websocket_packet);
|
||||
}
|
||||
|
||||
esp_err_t WebSocketLogger::log_message(const char *format, va_list args)
|
||||
{
|
||||
vsnprintf(this->ws_log_buffer, 100, format, args);
|
||||
|
||||
if (connected_socket_client.fd == -1 || connected_socket_client.hd == nullptr)
|
||||
{
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t ret = httpd_queue_work(connected_socket_client.hd, LoggerHelpers::ws_async_send, &connected_socket_client);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
connected_socket_client.fd = -1;
|
||||
connected_socket_client.hd = nullptr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t WebSocketLogger::register_socket_client(httpd_req_t *req)
|
||||
{
|
||||
if (connected_socket_client.fd != -1 && connected_socket_client.hd != nullptr)
|
||||
{
|
||||
// we're already connected
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
connected_socket_client.hd = req->handle;
|
||||
connected_socket_client.fd = httpd_req_to_sockfd(req);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void WebSocketLogger::unregister_socket_client()
|
||||
{
|
||||
connected_socket_client.fd = -1;
|
||||
connected_socket_client.hd = nullptr;
|
||||
}
|
||||
|
||||
char *WebSocketLogger::get_websocket_log_buffer()
|
||||
{
|
||||
return this->ws_log_buffer;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
#ifndef WEBSOCKETLOGGER_HPP
|
||||
#define WEBSOCKETLOGGER_HPP
|
||||
|
||||
#include "esp_http_server.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#define WS_LOG_BUFFER_LEN 1024
|
||||
|
||||
struct async_resp_arg
|
||||
{
|
||||
httpd_handle_t hd;
|
||||
int fd;
|
||||
};
|
||||
|
||||
namespace LoggerHelpers
|
||||
{
|
||||
void ws_async_send(void *arg);
|
||||
}
|
||||
|
||||
class WebSocketLogger
|
||||
{
|
||||
private:
|
||||
async_resp_arg connected_socket_client;
|
||||
char ws_log_buffer[WS_LOG_BUFFER_LEN];
|
||||
|
||||
public:
|
||||
WebSocketLogger();
|
||||
|
||||
esp_err_t log_message(const char *format, va_list args);
|
||||
esp_err_t register_socket_client(httpd_req_t *req);
|
||||
void unregister_socket_client();
|
||||
bool is_client_connected();
|
||||
char *get_websocket_log_buffer();
|
||||
};
|
||||
|
||||
extern WebSocketLogger webSocketLogger;
|
||||
|
||||
#endif
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "esp_log.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_camera.h"
|
||||
#include "esp_log.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_psram.h"
|
||||
|
||||
@@ -16,12 +15,40 @@
|
||||
#include <LEDManager.hpp>
|
||||
#include <MDNSManager.hpp>
|
||||
#include <CameraManager.hpp>
|
||||
#include <WebSocketLogger.hpp>
|
||||
#include <StreamServer.hpp>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef CONFIG_WIRED_MODE
|
||||
#include <UVCStream.hpp>
|
||||
#endif
|
||||
|
||||
#define BLINK_GPIO (gpio_num_t) CONFIG_BLINK_GPIO
|
||||
|
||||
static const char *TAG = "[MAIN]";
|
||||
|
||||
WebSocketLogger webSocketLogger;
|
||||
|
||||
// TODO add this option
|
||||
// ProjectConfig deviceConfig("openiris", MDNS_HOSTNAME);
|
||||
ProjectConfig deviceConfig("openiris", "openiristracker");
|
||||
WiFiManager wifiManager;
|
||||
MDNSManager mdnsManager(deviceConfig);
|
||||
CameraManager cameraHandler(deviceConfig);
|
||||
StreamServer streamServer(80);
|
||||
|
||||
#ifdef CONFIG_WIRED_MODE
|
||||
UVCStreamManager uvcStream;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USE_ILLUMNATIOR_PIN
|
||||
// LEDManager ledManager(BLINK_GPIO, ILLUMINATOR_PIN);
|
||||
LEDManager ledManager(BLINK_GPIO, 1);
|
||||
#else
|
||||
LEDManager ledManager(BLINK_GPIO);
|
||||
#endif
|
||||
|
||||
static void initNVSStorage()
|
||||
{
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
@@ -33,8 +60,22 @@ static void initNVSStorage()
|
||||
ESP_ERROR_CHECK(ret);
|
||||
}
|
||||
|
||||
int test_log(const char *format, va_list args)
|
||||
{
|
||||
webSocketLogger.log_message(format, args);
|
||||
return vprintf(format, args);
|
||||
}
|
||||
|
||||
void mylog(const char *format, ...);
|
||||
|
||||
extern "C" void app_main(void)
|
||||
{
|
||||
// uvc plan
|
||||
|
||||
// cleanup the logs - done
|
||||
// prepare the camera to be initialized with UVC
|
||||
// debug uvc performance - done
|
||||
|
||||
// porting plan:
|
||||
// port the wifi manager first. - worky!!!
|
||||
// get it connect to the network and setup an AP with hardcoded creds first -- connects. AP will be next
|
||||
@@ -52,35 +93,24 @@ extern "C" void app_main(void)
|
||||
// then port the Elegant OTA stuff
|
||||
// then port the serial manager
|
||||
|
||||
// TODO add this option
|
||||
// ProjectConfig deviceConfig("openiris", MDNS_HOSTNAME);
|
||||
ProjectConfig deviceConfig("openiris", "openiristracker");
|
||||
WiFiManager wifiManager;
|
||||
MDNSManager mdnsManager(deviceConfig);
|
||||
CameraManager cameraHandler(deviceConfig);
|
||||
StreamServer streamServer;
|
||||
|
||||
#ifdef CONFIG_USE_ILLUMNATIOR_PIN
|
||||
// LEDManager ledManager(BLINK_GPIO, ILLUMINATOR_PIN);
|
||||
LEDManager ledManager(BLINK_GPIO, 1);
|
||||
#else
|
||||
LEDManager ledManager(BLINK_GPIO);
|
||||
#endif
|
||||
|
||||
Logo::printASCII();
|
||||
initNVSStorage();
|
||||
|
||||
esp_log_set_vprintf(&test_log);
|
||||
ledManager.setup();
|
||||
deviceConfig.load();
|
||||
wifiManager.Begin();
|
||||
mdnsManager.start();
|
||||
cameraHandler.setupCamera();
|
||||
// cameraHandler.setupCamera();
|
||||
streamServer.startStreamServer();
|
||||
|
||||
#ifdef CONFIG_WIRED_MODE
|
||||
uvcStream.setup();
|
||||
#endif
|
||||
|
||||
while (1)
|
||||
{
|
||||
ledManager.handleLED();
|
||||
|
||||
vTaskDelay(CONFIG_BLINK_PERIOD / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
34
sdkconfig
34
sdkconfig
@@ -539,7 +539,7 @@ CONFIG_BLINK_LED_GPIO=y
|
||||
# CONFIG_BLINK_LED_STRIP is not set
|
||||
CONFIG_BLINK_GPIO=21
|
||||
CONFIG_BLINK_PERIOD=1000
|
||||
# CONFIG_WIRED_MODE is not set
|
||||
CONFIG_WIRED_MODE=y
|
||||
CONFIG_WIFI_SSID="UPC7878684"
|
||||
CONFIG_WIFI_PASSOWRD="j3ttQPpfvhep"
|
||||
# end of OpenIris basic configuration
|
||||
@@ -882,7 +882,7 @@ CONFIG_HTTPD_MAX_URI_LEN=512
|
||||
CONFIG_HTTPD_ERR_RESP_NO_DELAY=y
|
||||
CONFIG_HTTPD_PURGE_BUF_LEN=32
|
||||
# CONFIG_HTTPD_LOG_PURGE_DATA is not set
|
||||
# CONFIG_HTTPD_WS_SUPPORT is not set
|
||||
CONFIG_HTTPD_WS_SUPPORT=y
|
||||
# CONFIG_HTTPD_QUEUE_WORK_BLOCKING is not set
|
||||
# end of HTTP Server
|
||||
|
||||
@@ -2142,17 +2142,17 @@ CONFIG_TUSB_SERIAL_NUM="12345678"
|
||||
CONFIG_FORMAT_MJPEG_CAM1=y
|
||||
# CONFIG_FORMAT_H264_CAM1 is not set
|
||||
# CONFIG_FORMAT_UNCOMPR_CAM1 is not set
|
||||
CONFIG_UVC_MODE_ISOC_CAM1=y
|
||||
# CONFIG_UVC_MODE_BULK_CAM1 is not set
|
||||
# CONFIG_UVC_MODE_ISOC_CAM1 is not set
|
||||
CONFIG_UVC_MODE_BULK_CAM1=y
|
||||
CONFIG_FRAMESIZE_QVGA=y
|
||||
# CONFIG_FRAMESIZE_HVGA is not set
|
||||
# CONFIG_FRAMESIZE_VGA is not set
|
||||
# CONFIG_FRAMESIZE_SVGA is not set
|
||||
# CONFIG_FRAMESIZE_HD is not set
|
||||
# CONFIG_FRAMESIZE_FHD is not set
|
||||
CONFIG_UVC_CAM1_FRAMERATE=70
|
||||
CONFIG_UVC_CAM1_FRAMESIZE_WIDTH=1280
|
||||
CONFIG_UVC_CAM1_FRAMESIZE_HEIGT=720
|
||||
CONFIG_UVC_CAM1_FRAMERATE=60
|
||||
CONFIG_UVC_CAM1_FRAMESIZE_WIDTH=240
|
||||
CONFIG_UVC_CAM1_FRAMESIZE_HEIGT=240
|
||||
CONFIG_UVC_CAM1_MULTI_FRAMESIZE=y
|
||||
# end of USB Cam1 Config
|
||||
|
||||
@@ -2163,34 +2163,34 @@ CONFIG_UVC_CAM1_MULTI_FRAMESIZE=y
|
||||
#
|
||||
# FRAME_SIZE_1
|
||||
#
|
||||
CONFIG_UVC_MULTI_FRAME_WIDTH_1=640
|
||||
CONFIG_UVC_MULTI_FRAME_HEIGHT_1=480
|
||||
CONFIG_UVC_MULTI_FRAME_FPS_1=15
|
||||
CONFIG_UVC_MULTI_FRAME_WIDTH_1=240
|
||||
CONFIG_UVC_MULTI_FRAME_HEIGHT_1=240
|
||||
CONFIG_UVC_MULTI_FRAME_FPS_1=60
|
||||
# end of FRAME_SIZE_1
|
||||
|
||||
#
|
||||
# FRAME_SIZE_2
|
||||
#
|
||||
CONFIG_UVC_MULTI_FRAME_WIDTH_2=480
|
||||
CONFIG_UVC_MULTI_FRAME_HEIGHT_2=320
|
||||
CONFIG_UVC_MULTI_FRAME_FPS_2=30
|
||||
CONFIG_UVC_MULTI_FRAME_WIDTH_2=240
|
||||
CONFIG_UVC_MULTI_FRAME_HEIGHT_2=240
|
||||
CONFIG_UVC_MULTI_FRAME_FPS_2=60
|
||||
# end of FRAME_SIZE_2
|
||||
|
||||
#
|
||||
# FRAME_SIZE_3
|
||||
#
|
||||
CONFIG_UVC_MULTI_FRAME_WIDTH_3=320
|
||||
CONFIG_UVC_MULTI_FRAME_WIDTH_3=240
|
||||
CONFIG_UVC_MULTI_FRAME_HEIGHT_3=240
|
||||
CONFIG_UVC_MULTI_FRAME_FPS_3=30
|
||||
CONFIG_UVC_MULTI_FRAME_FPS_3=60
|
||||
# end of FRAME_SIZE_3
|
||||
# end of UVC_MULTI_FRAME_CONFIG
|
||||
|
||||
#
|
||||
# UVC Task Config
|
||||
#
|
||||
CONFIG_UVC_TINYUSB_TASK_PRIORITY=5
|
||||
CONFIG_UVC_TINYUSB_TASK_PRIORITY=4
|
||||
CONFIG_UVC_TINYUSB_TASK_CORE=-1
|
||||
CONFIG_UVC_CAM1_TASK_PRIORITY=4
|
||||
CONFIG_UVC_CAM1_TASK_PRIORITY=3
|
||||
CONFIG_UVC_CAM1_TASK_CORE=-1
|
||||
# end of UVC Task Config
|
||||
# end of USB Device UVC
|
||||
|
||||
@@ -539,7 +539,7 @@ CONFIG_BLINK_LED_GPIO=y
|
||||
# CONFIG_BLINK_LED_STRIP is not set
|
||||
CONFIG_BLINK_GPIO=21
|
||||
CONFIG_BLINK_PERIOD=1000
|
||||
# CONFIG_WIRED_MODE is not set
|
||||
CONFIG_WIRED_MODE=y
|
||||
CONFIG_WIFI_SSID="UPC7878684"
|
||||
CONFIG_WIFI_PASSOWRD="j3ttQPpfvhep"
|
||||
# end of OpenIris basic configuration
|
||||
@@ -882,7 +882,7 @@ CONFIG_HTTPD_MAX_URI_LEN=512
|
||||
CONFIG_HTTPD_ERR_RESP_NO_DELAY=y
|
||||
CONFIG_HTTPD_PURGE_BUF_LEN=32
|
||||
# CONFIG_HTTPD_LOG_PURGE_DATA is not set
|
||||
# CONFIG_HTTPD_WS_SUPPORT is not set
|
||||
CONFIG_HTTPD_WS_SUPPORT=y
|
||||
# CONFIG_HTTPD_QUEUE_WORK_BLOCKING is not set
|
||||
# end of HTTP Server
|
||||
|
||||
@@ -1433,15 +1433,13 @@ CONFIG_HEAP_TRACING_OFF=y
|
||||
# Log output
|
||||
#
|
||||
# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set
|
||||
CONFIG_LOG_DEFAULT_LEVEL_ERROR=y
|
||||
# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set
|
||||
# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set
|
||||
# CONFIG_LOG_DEFAULT_LEVEL_INFO is not set
|
||||
CONFIG_LOG_DEFAULT_LEVEL_INFO=y
|
||||
# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set
|
||||
# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set
|
||||
CONFIG_LOG_DEFAULT_LEVEL=1
|
||||
CONFIG_LOG_DEFAULT_LEVEL=3
|
||||
# CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT is not set
|
||||
# CONFIG_LOG_MAXIMUM_LEVEL_WARN is not set
|
||||
# CONFIG_LOG_MAXIMUM_LEVEL_INFO is not set
|
||||
# CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set
|
||||
CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE=y
|
||||
CONFIG_LOG_MAXIMUM_LEVEL=5
|
||||
@@ -2152,9 +2150,9 @@ CONFIG_FRAMESIZE_QVGA=y
|
||||
# CONFIG_FRAMESIZE_SVGA is not set
|
||||
# CONFIG_FRAMESIZE_HD is not set
|
||||
# CONFIG_FRAMESIZE_FHD is not set
|
||||
CONFIG_UVC_CAM1_FRAMERATE=70
|
||||
CONFIG_UVC_CAM1_FRAMESIZE_WIDTH=1280
|
||||
CONFIG_UVC_CAM1_FRAMESIZE_HEIGT=720
|
||||
CONFIG_UVC_CAM1_FRAMERATE=60
|
||||
CONFIG_UVC_CAM1_FRAMESIZE_WIDTH=240
|
||||
CONFIG_UVC_CAM1_FRAMESIZE_HEIGT=240
|
||||
CONFIG_UVC_CAM1_MULTI_FRAMESIZE=y
|
||||
# end of USB Cam1 Config
|
||||
|
||||
@@ -2165,25 +2163,25 @@ CONFIG_UVC_CAM1_MULTI_FRAMESIZE=y
|
||||
#
|
||||
# FRAME_SIZE_1
|
||||
#
|
||||
CONFIG_UVC_MULTI_FRAME_WIDTH_1=640
|
||||
CONFIG_UVC_MULTI_FRAME_HEIGHT_1=480
|
||||
CONFIG_UVC_MULTI_FRAME_FPS_1=15
|
||||
CONFIG_UVC_MULTI_FRAME_WIDTH_1=240
|
||||
CONFIG_UVC_MULTI_FRAME_HEIGHT_1=240
|
||||
CONFIG_UVC_MULTI_FRAME_FPS_1=60
|
||||
# end of FRAME_SIZE_1
|
||||
|
||||
#
|
||||
# FRAME_SIZE_2
|
||||
#
|
||||
CONFIG_UVC_MULTI_FRAME_WIDTH_2=480
|
||||
CONFIG_UVC_MULTI_FRAME_HEIGHT_2=320
|
||||
CONFIG_UVC_MULTI_FRAME_FPS_2=30
|
||||
CONFIG_UVC_MULTI_FRAME_WIDTH_2=240
|
||||
CONFIG_UVC_MULTI_FRAME_HEIGHT_2=240
|
||||
CONFIG_UVC_MULTI_FRAME_FPS_2=60
|
||||
# end of FRAME_SIZE_2
|
||||
|
||||
#
|
||||
# FRAME_SIZE_3
|
||||
#
|
||||
CONFIG_UVC_MULTI_FRAME_WIDTH_3=320
|
||||
CONFIG_UVC_MULTI_FRAME_WIDTH_3=240
|
||||
CONFIG_UVC_MULTI_FRAME_HEIGHT_3=240
|
||||
CONFIG_UVC_MULTI_FRAME_FPS_3=30
|
||||
CONFIG_UVC_MULTI_FRAME_FPS_3=60
|
||||
# end of FRAME_SIZE_3
|
||||
# end of UVC_MULTI_FRAME_CONFIG
|
||||
|
||||
|
||||
Reference in New Issue
Block a user