You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

778 lines
23 KiB

3 years ago
  1. // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "app_httpd.hpp"
  15. #include <list>
  16. #include "esp_http_server.h"
  17. #include "esp_timer.h"
  18. #include "img_converters.h"
  19. #include "fb_gfx.h"
  20. #include "app_mdns.h"
  21. #include "sdkconfig.h"
  22. #include "who_camera.h"
  23. #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
  24. #include "esp32-hal-log.h"
  25. #define TAG ""
  26. #else
  27. #include "esp_log.h"
  28. static const char *TAG = "camera_httpd";
  29. #endif
  30. static QueueHandle_t xQueueFrameI = NULL;
  31. static QueueHandle_t xQueueFrameO = NULL;
  32. static bool gReturnFB = true;
  33. static int8_t detection_enabled = 0;
  34. static int8_t recognition_enabled = 0;
  35. static int8_t is_enrolling = 0;
  36. typedef struct
  37. {
  38. httpd_req_t *req;
  39. size_t len;
  40. } jpg_chunking_t;
  41. #define PART_BOUNDARY "123456789000000000000987654321"
  42. static const char *_STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
  43. static const char *_STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";
  44. static const char *_STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\nX-Timestamp: %d.%06d\r\n\r\n";
  45. httpd_handle_t stream_httpd = NULL;
  46. httpd_handle_t camera_httpd = NULL;
  47. static size_t jpg_encode_stream(void *arg, size_t index, const void *data, size_t len)
  48. {
  49. jpg_chunking_t *j = (jpg_chunking_t *)arg;
  50. if (!index)
  51. {
  52. j->len = 0;
  53. }
  54. if (httpd_resp_send_chunk(j->req, (const char *)data, len) != ESP_OK)
  55. {
  56. return 0;
  57. }
  58. j->len += len;
  59. return len;
  60. }
  61. static esp_err_t capture_handler(httpd_req_t *req)
  62. {
  63. camera_fb_t *frame = NULL;
  64. esp_err_t res = ESP_OK;
  65. if (xQueueReceive(xQueueFrameI, &frame, portMAX_DELAY))
  66. {
  67. httpd_resp_set_type(req, "image/jpeg");
  68. httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg");
  69. httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
  70. char ts[32];
  71. snprintf(ts, 32, "%ld.%06ld", frame->timestamp.tv_sec, frame->timestamp.tv_usec);
  72. httpd_resp_set_hdr(req, "X-Timestamp", (const char *)ts);
  73. // size_t fb_len = 0;
  74. if (frame->format == PIXFORMAT_JPEG)
  75. {
  76. // fb_len = frame->len;
  77. res = httpd_resp_send(req, (const char *)frame->buf, frame->len);
  78. }
  79. else
  80. {
  81. jpg_chunking_t jchunk = {req, 0};
  82. res = frame2jpg_cb(frame, 80, jpg_encode_stream, &jchunk) ? ESP_OK : ESP_FAIL;
  83. httpd_resp_send_chunk(req, NULL, 0);
  84. // fb_len = jchunk.len;
  85. }
  86. if (xQueueFrameO)
  87. {
  88. xQueueSend(xQueueFrameO, &frame, portMAX_DELAY);
  89. }
  90. else if (gReturnFB)
  91. {
  92. esp_camera_fb_return(frame);
  93. }
  94. else
  95. {
  96. free(frame);
  97. }
  98. }
  99. else
  100. {
  101. ESP_LOGE(TAG, "Camera capture failed");
  102. httpd_resp_send_500(req);
  103. return ESP_FAIL;
  104. }
  105. return res;
  106. }
  107. static esp_err_t stream_handler(httpd_req_t *req)
  108. {
  109. camera_fb_t *frame = NULL;
  110. struct timeval _timestamp;
  111. esp_err_t res = ESP_OK;
  112. size_t _jpg_buf_len = 0;
  113. uint8_t *_jpg_buf = NULL;
  114. char *part_buf[128];
  115. res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE);
  116. if (res != ESP_OK)
  117. {
  118. return res;
  119. }
  120. httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
  121. httpd_resp_set_hdr(req, "X-Framerate", "60");
  122. while (true)
  123. {
  124. if (xQueueReceive(xQueueFrameI, &frame, portMAX_DELAY))
  125. {
  126. _timestamp.tv_sec = frame->timestamp.tv_sec;
  127. _timestamp.tv_usec = frame->timestamp.tv_usec;
  128. if (frame->format == PIXFORMAT_JPEG)
  129. {
  130. _jpg_buf = frame->buf;
  131. _jpg_buf_len = frame->len;
  132. }
  133. else if (!frame2jpg(frame, 80, &_jpg_buf, &_jpg_buf_len))
  134. {
  135. ESP_LOGE(TAG, "JPEG compression failed");
  136. res = ESP_FAIL;
  137. }
  138. }
  139. else
  140. {
  141. res = ESP_FAIL;
  142. }
  143. if (res == ESP_OK)
  144. {
  145. res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));
  146. }
  147. if (res == ESP_OK)
  148. {
  149. size_t hlen = snprintf((char *)part_buf, 128, _STREAM_PART, _jpg_buf_len, _timestamp.tv_sec, _timestamp.tv_usec);
  150. res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen);
  151. }
  152. if (res == ESP_OK)
  153. {
  154. res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len);
  155. }
  156. if (frame->format != PIXFORMAT_JPEG)
  157. {
  158. free(_jpg_buf);
  159. _jpg_buf = NULL;
  160. }
  161. if (xQueueFrameO)
  162. {
  163. xQueueSend(xQueueFrameO, &frame, portMAX_DELAY);
  164. }
  165. else if (gReturnFB)
  166. {
  167. esp_camera_fb_return(frame);
  168. }
  169. else
  170. {
  171. free(frame);
  172. }
  173. if (res != ESP_OK)
  174. {
  175. break;
  176. }
  177. }
  178. return res;
  179. }
  180. static esp_err_t parse_get(httpd_req_t *req, char **obuf)
  181. {
  182. char *buf = NULL;
  183. size_t buf_len = 0;
  184. buf_len = httpd_req_get_url_query_len(req) + 1;
  185. if (buf_len > 1)
  186. {
  187. buf = (char *)malloc(buf_len);
  188. if (!buf)
  189. {
  190. httpd_resp_send_500(req);
  191. return ESP_FAIL;
  192. }
  193. if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK)
  194. {
  195. *obuf = buf;
  196. return ESP_OK;
  197. }
  198. free(buf);
  199. }
  200. httpd_resp_send_404(req);
  201. return ESP_FAIL;
  202. }
  203. static esp_err_t cmd_handler(httpd_req_t *req)
  204. {
  205. char *buf = NULL;
  206. char variable[32];
  207. char value[32];
  208. if (parse_get(req, &buf) != ESP_OK ||
  209. httpd_query_key_value(buf, "var", variable, sizeof(variable)) != ESP_OK ||
  210. httpd_query_key_value(buf, "val", value, sizeof(value)) != ESP_OK)
  211. {
  212. free(buf);
  213. httpd_resp_send_404(req);
  214. return ESP_FAIL;
  215. }
  216. free(buf);
  217. int val = atoi(value);
  218. ESP_LOGI(TAG, "%s = %d", variable, val);
  219. sensor_t *s = esp_camera_sensor_get();
  220. int res = 0;
  221. if (!strcmp(variable, "framesize"))
  222. {
  223. if (s->pixformat == PIXFORMAT_JPEG)
  224. {
  225. res = s->set_framesize(s, (framesize_t)val);
  226. if (res == 0)
  227. {
  228. app_mdns_update_framesize(val);
  229. }
  230. }
  231. }
  232. else if (!strcmp(variable, "quality"))
  233. res = s->set_quality(s, val);
  234. else if (!strcmp(variable, "contrast"))
  235. res = s->set_contrast(s, val);
  236. else if (!strcmp(variable, "brightness"))
  237. res = s->set_brightness(s, val);
  238. else if (!strcmp(variable, "saturation"))
  239. res = s->set_saturation(s, val);
  240. else if (!strcmp(variable, "gainceiling"))
  241. res = s->set_gainceiling(s, (gainceiling_t)val);
  242. else if (!strcmp(variable, "colorbar"))
  243. res = s->set_colorbar(s, val);
  244. else if (!strcmp(variable, "awb"))
  245. res = s->set_whitebal(s, val);
  246. else if (!strcmp(variable, "agc"))
  247. res = s->set_gain_ctrl(s, val);
  248. else if (!strcmp(variable, "aec"))
  249. res = s->set_exposure_ctrl(s, val);
  250. else if (!strcmp(variable, "hmirror"))
  251. res = s->set_hmirror(s, val);
  252. else if (!strcmp(variable, "vflip"))
  253. res = s->set_vflip(s, val);
  254. else if (!strcmp(variable, "awb_gain"))
  255. res = s->set_awb_gain(s, val);
  256. else if (!strcmp(variable, "agc_gain"))
  257. res = s->set_agc_gain(s, val);
  258. else if (!strcmp(variable, "aec_value"))
  259. res = s->set_aec_value(s, val);
  260. else if (!strcmp(variable, "aec2"))
  261. res = s->set_aec2(s, val);
  262. else if (!strcmp(variable, "dcw"))
  263. res = s->set_dcw(s, val);
  264. else if (!strcmp(variable, "bpc"))
  265. res = s->set_bpc(s, val);
  266. else if (!strcmp(variable, "wpc"))
  267. res = s->set_wpc(s, val);
  268. else if (!strcmp(variable, "raw_gma"))
  269. res = s->set_raw_gma(s, val);
  270. else if (!strcmp(variable, "lenc"))
  271. res = s->set_lenc(s, val);
  272. else if (!strcmp(variable, "special_effect"))
  273. res = s->set_special_effect(s, val);
  274. else if (!strcmp(variable, "wb_mode"))
  275. res = s->set_wb_mode(s, val);
  276. else if (!strcmp(variable, "ae_level"))
  277. res = s->set_ae_level(s, val);
  278. #ifdef CONFIG_LED_ILLUMINATOR_ENABLED
  279. else if (!strcmp(variable, "led_intensity"))
  280. led_duty = val;
  281. #endif
  282. else if (!strcmp(variable, "face_detect"))
  283. {
  284. detection_enabled = val;
  285. if (!detection_enabled)
  286. {
  287. recognition_enabled = 0;
  288. }
  289. }
  290. else if (!strcmp(variable, "face_enroll"))
  291. is_enrolling = val;
  292. else if (!strcmp(variable, "face_recognize"))
  293. {
  294. recognition_enabled = val;
  295. if (recognition_enabled)
  296. {
  297. detection_enabled = val;
  298. }
  299. }
  300. else
  301. {
  302. res = -1;
  303. }
  304. if (res)
  305. {
  306. return httpd_resp_send_500(req);
  307. }
  308. httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
  309. return httpd_resp_send(req, NULL, 0);
  310. }
  311. static int print_reg(char *p, sensor_t *s, uint16_t reg, uint32_t mask)
  312. {
  313. return sprintf(p, "\"0x%x\":%u,", reg, s->get_reg(s, reg, mask));
  314. }
  315. static esp_err_t status_handler(httpd_req_t *req)
  316. {
  317. static char json_response[1024];
  318. sensor_t *s = esp_camera_sensor_get();
  319. char *p = json_response;
  320. *p++ = '{';
  321. if (s->id.PID == OV5640_PID || s->id.PID == OV3660_PID)
  322. {
  323. for (int reg = 0x3400; reg < 0x3406; reg += 2)
  324. {
  325. p += print_reg(p, s, reg, 0xFFF); //12 bit
  326. }
  327. p += print_reg(p, s, 0x3406, 0xFF);
  328. p += print_reg(p, s, 0x3500, 0xFFFF0); //16 bit
  329. p += print_reg(p, s, 0x3503, 0xFF);
  330. p += print_reg(p, s, 0x350a, 0x3FF); //10 bit
  331. p += print_reg(p, s, 0x350c, 0xFFFF); //16 bit
  332. for (int reg = 0x5480; reg <= 0x5490; reg++)
  333. {
  334. p += print_reg(p, s, reg, 0xFF);
  335. }
  336. for (int reg = 0x5380; reg <= 0x538b; reg++)
  337. {
  338. p += print_reg(p, s, reg, 0xFF);
  339. }
  340. for (int reg = 0x5580; reg < 0x558a; reg++)
  341. {
  342. p += print_reg(p, s, reg, 0xFF);
  343. }
  344. p += print_reg(p, s, 0x558a, 0x1FF); //9 bit
  345. }
  346. else
  347. {
  348. p += print_reg(p, s, 0xd3, 0xFF);
  349. p += print_reg(p, s, 0x111, 0xFF);
  350. p += print_reg(p, s, 0x132, 0xFF);
  351. }
  352. p += sprintf(p, "\"board\":\"%s\",", CAMERA_MODULE_NAME);
  353. p += sprintf(p, "\"xclk\":%u,", s->xclk_freq_hz / 1000000);
  354. p += sprintf(p, "\"pixformat\":%u,", s->pixformat);
  355. p += sprintf(p, "\"framesize\":%u,", s->status.framesize);
  356. p += sprintf(p, "\"quality\":%u,", s->status.quality);
  357. p += sprintf(p, "\"brightness\":%d,", s->status.brightness);
  358. p += sprintf(p, "\"contrast\":%d,", s->status.contrast);
  359. p += sprintf(p, "\"saturation\":%d,", s->status.saturation);
  360. p += sprintf(p, "\"sharpness\":%d,", s->status.sharpness);
  361. p += sprintf(p, "\"special_effect\":%u,", s->status.special_effect);
  362. p += sprintf(p, "\"wb_mode\":%u,", s->status.wb_mode);
  363. p += sprintf(p, "\"awb\":%u,", s->status.awb);
  364. p += sprintf(p, "\"awb_gain\":%u,", s->status.awb_gain);
  365. p += sprintf(p, "\"aec\":%u,", s->status.aec);
  366. p += sprintf(p, "\"aec2\":%u,", s->status.aec2);
  367. p += sprintf(p, "\"ae_level\":%d,", s->status.ae_level);
  368. p += sprintf(p, "\"aec_value\":%u,", s->status.aec_value);
  369. p += sprintf(p, "\"agc\":%u,", s->status.agc);
  370. p += sprintf(p, "\"agc_gain\":%u,", s->status.agc_gain);
  371. p += sprintf(p, "\"gainceiling\":%u,", s->status.gainceiling);
  372. p += sprintf(p, "\"bpc\":%u,", s->status.bpc);
  373. p += sprintf(p, "\"wpc\":%u,", s->status.wpc);
  374. p += sprintf(p, "\"raw_gma\":%u,", s->status.raw_gma);
  375. p += sprintf(p, "\"lenc\":%u,", s->status.lenc);
  376. p += sprintf(p, "\"hmirror\":%u,", s->status.hmirror);
  377. p += sprintf(p, "\"dcw\":%u,", s->status.dcw);
  378. p += sprintf(p, "\"colorbar\":%u", s->status.colorbar);
  379. #ifdef CONFIG_LED_ILLUMINATOR_ENABLED
  380. p += sprintf(p, ",\"led_intensity\":%u", led_duty);
  381. #else
  382. p += sprintf(p, ",\"led_intensity\":%d", -1);
  383. #endif
  384. p += sprintf(p, ",\"face_detect\":%u", detection_enabled);
  385. p += sprintf(p, ",\"face_enroll\":%u,", is_enrolling);
  386. p += sprintf(p, "\"face_recognize\":%u", recognition_enabled);
  387. *p++ = '}';
  388. *p++ = 0;
  389. httpd_resp_set_type(req, "application/json");
  390. httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
  391. return httpd_resp_send(req, json_response, strlen(json_response));
  392. }
  393. static esp_err_t mdns_handler(httpd_req_t *req)
  394. {
  395. size_t json_len = 0;
  396. const char *json_response = app_mdns_query(&json_len);
  397. httpd_resp_set_type(req, "application/json");
  398. httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
  399. return httpd_resp_send(req, json_response, json_len);
  400. }
  401. static esp_err_t xclk_handler(httpd_req_t *req)
  402. {
  403. char *buf = NULL;
  404. char _xclk[32];
  405. if (parse_get(req, &buf) != ESP_OK ||
  406. httpd_query_key_value(buf, "xclk", _xclk, sizeof(_xclk)) != ESP_OK)
  407. {
  408. free(buf);
  409. httpd_resp_send_404(req);
  410. return ESP_FAIL;
  411. }
  412. free(buf);
  413. int xclk = atoi(_xclk);
  414. ESP_LOGI(TAG, "Set XCLK: %d MHz", xclk);
  415. sensor_t *s = esp_camera_sensor_get();
  416. int res = s->set_xclk(s, LEDC_TIMER_0, xclk);
  417. if (res)
  418. {
  419. return httpd_resp_send_500(req);
  420. }
  421. httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
  422. return httpd_resp_send(req, NULL, 0);
  423. }
  424. static esp_err_t reg_handler(httpd_req_t *req)
  425. {
  426. char *buf = NULL;
  427. char _reg[32];
  428. char _mask[32];
  429. char _val[32];
  430. if (parse_get(req, &buf) != ESP_OK ||
  431. httpd_query_key_value(buf, "reg", _reg, sizeof(_reg)) != ESP_OK ||
  432. httpd_query_key_value(buf, "mask", _mask, sizeof(_mask)) != ESP_OK ||
  433. httpd_query_key_value(buf, "val", _val, sizeof(_val)) != ESP_OK)
  434. {
  435. free(buf);
  436. httpd_resp_send_404(req);
  437. return ESP_FAIL;
  438. }
  439. free(buf);
  440. int reg = atoi(_reg);
  441. int mask = atoi(_mask);
  442. int val = atoi(_val);
  443. ESP_LOGI(TAG, "Set Register: reg: 0x%02x, mask: 0x%02x, value: 0x%02x", reg, mask, val);
  444. sensor_t *s = esp_camera_sensor_get();
  445. int res = s->set_reg(s, reg, mask, val);
  446. if (res)
  447. {
  448. return httpd_resp_send_500(req);
  449. }
  450. httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
  451. return httpd_resp_send(req, NULL, 0);
  452. }
  453. static esp_err_t greg_handler(httpd_req_t *req)
  454. {
  455. char *buf = NULL;
  456. char _reg[32];
  457. char _mask[32];
  458. if (parse_get(req, &buf) != ESP_OK ||
  459. httpd_query_key_value(buf, "reg", _reg, sizeof(_reg)) != ESP_OK ||
  460. httpd_query_key_value(buf, "mask", _mask, sizeof(_mask)) != ESP_OK)
  461. {
  462. free(buf);
  463. httpd_resp_send_404(req);
  464. return ESP_FAIL;
  465. }
  466. free(buf);
  467. int reg = atoi(_reg);
  468. int mask = atoi(_mask);
  469. sensor_t *s = esp_camera_sensor_get();
  470. int res = s->get_reg(s, reg, mask);
  471. if (res < 0)
  472. {
  473. return httpd_resp_send_500(req);
  474. }
  475. ESP_LOGI(TAG, "Get Register: reg: 0x%02x, mask: 0x%02x, value: 0x%02x", reg, mask, res);
  476. char buffer[20];
  477. const char *val = itoa(res, buffer, 10);
  478. httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
  479. return httpd_resp_send(req, val, strlen(val));
  480. }
  481. static int parse_get_var(char *buf, const char *key, int def)
  482. {
  483. char _int[16];
  484. if (httpd_query_key_value(buf, key, _int, sizeof(_int)) != ESP_OK)
  485. {
  486. return def;
  487. }
  488. return atoi(_int);
  489. }
  490. static esp_err_t pll_handler(httpd_req_t *req)
  491. {
  492. char *buf = NULL;
  493. if (parse_get(req, &buf) != ESP_OK)
  494. {
  495. free(buf);
  496. httpd_resp_send_404(req);
  497. return ESP_FAIL;
  498. }
  499. int bypass = parse_get_var(buf, "bypass", 0);
  500. int mul = parse_get_var(buf, "mul", 0);
  501. int sys = parse_get_var(buf, "sys", 0);
  502. int root = parse_get_var(buf, "root", 0);
  503. int pre = parse_get_var(buf, "pre", 0);
  504. int seld5 = parse_get_var(buf, "seld5", 0);
  505. int pclken = parse_get_var(buf, "pclken", 0);
  506. int pclk = parse_get_var(buf, "pclk", 0);
  507. free(buf);
  508. 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);
  509. sensor_t *s = esp_camera_sensor_get();
  510. int res = s->set_pll(s, bypass, mul, sys, root, pre, seld5, pclken, pclk);
  511. if (res)
  512. {
  513. return httpd_resp_send_500(req);
  514. }
  515. httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
  516. return httpd_resp_send(req, NULL, 0);
  517. }
  518. static esp_err_t win_handler(httpd_req_t *req)
  519. {
  520. char *buf = NULL;
  521. if (parse_get(req, &buf) != ESP_OK)
  522. {
  523. free(buf);
  524. httpd_resp_send_404(req);
  525. return ESP_FAIL;
  526. }
  527. int startX = parse_get_var(buf, "sx", 0);
  528. int startY = parse_get_var(buf, "sy", 0);
  529. int endX = parse_get_var(buf, "ex", 0);
  530. int endY = parse_get_var(buf, "ey", 0);
  531. int offsetX = parse_get_var(buf, "offx", 0);
  532. int offsetY = parse_get_var(buf, "offy", 0);
  533. int totalX = parse_get_var(buf, "tx", 0);
  534. int totalY = parse_get_var(buf, "ty", 0);
  535. int outputX = parse_get_var(buf, "ox", 0);
  536. int outputY = parse_get_var(buf, "oy", 0);
  537. bool scale = parse_get_var(buf, "scale", 0) == 1;
  538. bool binning = parse_get_var(buf, "binning", 0) == 1;
  539. free(buf);
  540. 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);
  541. sensor_t *s = esp_camera_sensor_get();
  542. int res = s->set_res_raw(s, startX, startY, endX, endY, offsetX, offsetY, totalX, totalY, outputX, outputY, scale, binning);
  543. if (res)
  544. {
  545. return httpd_resp_send_500(req);
  546. }
  547. httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
  548. return httpd_resp_send(req, NULL, 0);
  549. }
  550. static esp_err_t index_handler(httpd_req_t *req)
  551. {
  552. extern const unsigned char index_ov2640_html_gz_start[] asm("_binary_index_ov2640_html_gz_start");
  553. extern const unsigned char index_ov2640_html_gz_end[] asm("_binary_index_ov2640_html_gz_end");
  554. size_t index_ov2640_html_gz_len = index_ov2640_html_gz_end - index_ov2640_html_gz_start;
  555. extern const unsigned char index_ov3660_html_gz_start[] asm("_binary_index_ov3660_html_gz_start");
  556. extern const unsigned char index_ov3660_html_gz_end[] asm("_binary_index_ov3660_html_gz_end");
  557. size_t index_ov3660_html_gz_len = index_ov3660_html_gz_end - index_ov3660_html_gz_start;
  558. extern const unsigned char index_ov5640_html_gz_start[] asm("_binary_index_ov5640_html_gz_start");
  559. extern const unsigned char index_ov5640_html_gz_end[] asm("_binary_index_ov5640_html_gz_end");
  560. size_t index_ov5640_html_gz_len = index_ov5640_html_gz_end - index_ov5640_html_gz_start;
  561. httpd_resp_set_type(req, "text/html");
  562. httpd_resp_set_hdr(req, "Content-Encoding", "gzip");
  563. sensor_t *s = esp_camera_sensor_get();
  564. if (s != NULL)
  565. {
  566. if (s->id.PID == OV3660_PID)
  567. {
  568. return httpd_resp_send(req, (const char *)index_ov3660_html_gz_start, index_ov3660_html_gz_len);
  569. }
  570. else if (s->id.PID == OV5640_PID)
  571. {
  572. return httpd_resp_send(req, (const char *)index_ov5640_html_gz_start, index_ov5640_html_gz_len);
  573. }
  574. else
  575. {
  576. return httpd_resp_send(req, (const char *)index_ov2640_html_gz_start, index_ov2640_html_gz_len);
  577. }
  578. }
  579. else
  580. {
  581. ESP_LOGE(TAG, "Camera sensor not found");
  582. return httpd_resp_send_500(req);
  583. }
  584. }
  585. static esp_err_t monitor_handler(httpd_req_t *req)
  586. {
  587. extern const unsigned char monitor_html_gz_start[] asm("_binary_monitor_html_gz_start");
  588. extern const unsigned char monitor_html_gz_end[] asm("_binary_monitor_html_gz_end");
  589. size_t monitor_html_gz_len = monitor_html_gz_end - monitor_html_gz_start;
  590. httpd_resp_set_type(req, "text/html");
  591. httpd_resp_set_hdr(req, "Content-Encoding", "gzip");
  592. return httpd_resp_send(req, (const char *)monitor_html_gz_start, monitor_html_gz_len);
  593. }
  594. void register_httpd(const QueueHandle_t frame_i, const QueueHandle_t frame_o, const bool return_fb)
  595. {
  596. xQueueFrameI = frame_i;
  597. xQueueFrameO = frame_o;
  598. gReturnFB = return_fb;
  599. httpd_config_t config = HTTPD_DEFAULT_CONFIG();
  600. config.max_uri_handlers = 12;
  601. httpd_uri_t index_uri = {
  602. .uri = "/",
  603. .method = HTTP_GET,
  604. .handler = index_handler,
  605. .user_ctx = NULL};
  606. httpd_uri_t status_uri = {
  607. .uri = "/status",
  608. .method = HTTP_GET,
  609. .handler = status_handler,
  610. .user_ctx = NULL};
  611. httpd_uri_t cmd_uri = {
  612. .uri = "/control",
  613. .method = HTTP_GET,
  614. .handler = cmd_handler,
  615. .user_ctx = NULL};
  616. httpd_uri_t capture_uri = {
  617. .uri = "/capture",
  618. .method = HTTP_GET,
  619. .handler = capture_handler,
  620. .user_ctx = NULL};
  621. httpd_uri_t stream_uri = {
  622. .uri = "/stream",
  623. .method = HTTP_GET,
  624. .handler = stream_handler,
  625. .user_ctx = NULL};
  626. httpd_uri_t xclk_uri = {
  627. .uri = "/xclk",
  628. .method = HTTP_GET,
  629. .handler = xclk_handler,
  630. .user_ctx = NULL};
  631. httpd_uri_t reg_uri = {
  632. .uri = "/reg",
  633. .method = HTTP_GET,
  634. .handler = reg_handler,
  635. .user_ctx = NULL};
  636. httpd_uri_t greg_uri = {
  637. .uri = "/greg",
  638. .method = HTTP_GET,
  639. .handler = greg_handler,
  640. .user_ctx = NULL};
  641. httpd_uri_t pll_uri = {
  642. .uri = "/pll",
  643. .method = HTTP_GET,
  644. .handler = pll_handler,
  645. .user_ctx = NULL};
  646. httpd_uri_t win_uri = {
  647. .uri = "/resolution",
  648. .method = HTTP_GET,
  649. .handler = win_handler,
  650. .user_ctx = NULL};
  651. httpd_uri_t mdns_uri = {
  652. .uri = "/mdns",
  653. .method = HTTP_GET,
  654. .handler = mdns_handler,
  655. .user_ctx = NULL};
  656. httpd_uri_t monitor_uri = {
  657. .uri = "/monitor",
  658. .method = HTTP_GET,
  659. .handler = monitor_handler,
  660. .user_ctx = NULL};
  661. ESP_LOGI(TAG, "Starting web server on port: '%d'", config.server_port);
  662. if (httpd_start(&camera_httpd, &config) == ESP_OK)
  663. {
  664. httpd_register_uri_handler(camera_httpd, &index_uri);
  665. httpd_register_uri_handler(camera_httpd, &cmd_uri);
  666. httpd_register_uri_handler(camera_httpd, &status_uri);
  667. httpd_register_uri_handler(camera_httpd, &capture_uri);
  668. httpd_register_uri_handler(camera_httpd, &xclk_uri);
  669. httpd_register_uri_handler(camera_httpd, &reg_uri);
  670. httpd_register_uri_handler(camera_httpd, &greg_uri);
  671. httpd_register_uri_handler(camera_httpd, &pll_uri);
  672. httpd_register_uri_handler(camera_httpd, &win_uri);
  673. httpd_register_uri_handler(camera_httpd, &mdns_uri);
  674. httpd_register_uri_handler(camera_httpd, &monitor_uri);
  675. }
  676. config.server_port += 1;
  677. config.ctrl_port += 1;
  678. ESP_LOGI(TAG, "Starting stream server on port: '%d'", config.server_port);
  679. if (httpd_start(&stream_httpd, &config) == ESP_OK)
  680. {
  681. httpd_register_uri_handler(stream_httpd, &stream_uri);
  682. }
  683. }