11#include <esp_http_server.h>
15namespace esp32_camera_web_server {
17static const int IMAGE_REQUEST_TIMEOUT = 5000;
18static const char *
const TAG =
"esp32_camera_web_server";
20#define PART_BOUNDARY "123456789000000000000987654321"
21#define CONTENT_TYPE "image/jpeg"
22#define CONTENT_LENGTH "Content-Length"
24static const char *
const STREAM_HEADER =
"HTTP/1.0 200 OK\r\n"
25 "Access-Control-Allow-Origin: *\r\n"
26 "Connection: close\r\n"
27 "Content-Type: multipart/x-mixed-replace;boundary=" PART_BOUNDARY
"\r\n"
29 "--" PART_BOUNDARY
"\r\n";
30static const char *
const STREAM_ERROR =
"Content-Type: text/plain\r\n"
33 "--" PART_BOUNDARY
"\r\n";
34static const char *
const STREAM_PART =
"Content-Type: " CONTENT_TYPE
"\r\n" CONTENT_LENGTH
": %u\r\n\r\n";
35static const char *
const STREAM_BOUNDARY =
"\r\n"
36 "--" PART_BOUNDARY
"\r\n";
50 httpd_config_t config = HTTPD_DEFAULT_CONFIG();
51 config.server_port = this->
port_;
52 config.ctrl_port = this->
port_;
53 config.max_open_sockets = 1;
54 config.backlog_conn = 2;
55 config.lru_purge_enable =
true;
57 if (httpd_start(&this->
httpd_, &config) != ESP_OK) {
65 .handler = [](
struct httpd_req *req) {
return ((
CameraWebServer *) req->user_ctx)->handler_(req); },
68 httpd_register_uri_handler(this->
httpd_, &uri);
91 "ESP32 Camera Web Server:\n"
95 ESP_LOGCONFIG(TAG,
" Mode: stream");
97 ESP_LOGCONFIG(TAG,
" Mode: snapshot");
101 ESP_LOGE(TAG,
" Setup Failed");
114 std::shared_ptr<esphome::camera::CameraImage> image;
119 xSemaphoreTake(this->
semaphore_, IMAGE_REQUEST_TIMEOUT / portTICK_PERIOD_MS);
127 esp_err_t res = ESP_FAIL;
132 switch (this->
mode_) {
147static esp_err_t httpd_send_all(httpd_req_t *r,
const char *buf,
size_t buf_len) {
150 while (buf_len > 0) {
151 ret = httpd_send(r, buf, buf_len);
162 esp_err_t res = ESP_OK;
168 res = httpd_send_all(req, STREAM_HEADER, strlen(STREAM_HEADER));
170 ESP_LOGW(TAG,
"STREAM: failed to set HTTP header");
174 uint32_t last_frame =
millis();
179 while (res == ESP_OK && this->
running_) {
183 ESP_LOGW(TAG,
"STREAM: failed to acquire frame");
187 size_t hlen = snprintf(part_buf, 64, STREAM_PART, image->get_data_length());
188 res = httpd_send_all(req, part_buf, hlen);
191 res = httpd_send_all(req, (
const char *) image->get_data_buffer(), image->get_data_length());
194 res = httpd_send_all(req, STREAM_BOUNDARY, strlen(STREAM_BOUNDARY));
198 int64_t frame_time =
millis() - last_frame;
201 ESP_LOGD(TAG,
"MJPG: %" PRIu32
"B %" PRIu32
"ms (%.1ffps)", (uint32_t) image->get_data_length(),
202 (uint32_t) frame_time, 1000.0 / (uint32_t) frame_time);
207 res = httpd_send_all(req, STREAM_ERROR, strlen(STREAM_ERROR));
212 ESP_LOGI(TAG,
"STREAM: closed. Frames: %" PRIu32, frames);
218 esp_err_t res = ESP_OK;
225 ESP_LOGW(TAG,
"SNAPSHOT: failed to acquire frame");
226 httpd_resp_send_500(req);
231 res = httpd_resp_set_type(req, CONTENT_TYPE);
233 ESP_LOGW(TAG,
"SNAPSHOT: failed to set HTTP response type");
237 httpd_resp_set_hdr(req,
"Content-Disposition",
"inline; filename=capture.jpg");
240 res = httpd_resp_send(req, (
const char *) image->get_data_buffer(), image->get_data_length());
virtual void mark_failed()
Mark this component as failed.
virtual void start_stream(CameraRequester requester)=0
virtual void stop_stream(CameraRequester requester)=0
virtual void add_listener(CameraListener *listener)=0
Add a listener to receive camera events.
virtual void request_image(CameraRequester requester)=0
static Camera * instance()
The singleton instance of the camera implementation.
void on_camera_image(const std::shared_ptr< camera::CameraImage > &image) override
CameraListener interface.
float get_setup_priority() const override
void dump_config() override
std::shared_ptr< camera::CameraImage > image_
SemaphoreHandle_t semaphore_
esp_err_t handler_(struct httpd_req *req)
void on_shutdown() override
std::shared_ptr< camera::CameraImage > wait_for_image_()
esp_err_t streaming_handler_(struct httpd_req *req)
esp_err_t snapshot_handler_(struct httpd_req *req)
const float LATE
For components that should be initialized at the very end of the setup process.
Providing packet encoding functions for exchanging data with a remote host.
uint32_t IRAM_ATTR HOT millis()