camera.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. #include <esp_log.h>
  2. #include <esp_system.h>
  3. #include <nvs_flash.h>
  4. #include <sys/param.h>
  5. #include <string.h>
  6. #include "freertos/FreeRTOS.h"
  7. #include "freertos/task.h"
  8. #include "esp_http_client.h"
  9. #include "esp_camera.h"
  10. #define ESP32_S3_KORVO 1 // ESP32-S3-KORVO-2_V3.0配套的自定义引脚
  11. // ESP32-S3-KORVO-2_V3.0 音频开发版
  12. #ifdef ESP32_S3_KORVO
  13. #define CAM_PIN_PWDN -1 //没用直接接高
  14. #define CAM_PIN_RESET -1 //software reset will be performed
  15. #define CAM_PIN_VSYNC 21
  16. #define CAM_PIN_HREF 38
  17. #define CAM_PIN_PCLK 42
  18. #define CAM_PIN_XCLK 40
  19. #define CAM_PIN_SIOD 17
  20. #define CAM_PIN_SIOC 18
  21. #define CAM_PIN_D0 13
  22. #define CAM_PIN_D1 47
  23. #define CAM_PIN_D2 14
  24. #define CAM_PIN_D3 3
  25. #define CAM_PIN_D4 12
  26. #define CAM_PIN_D5 11
  27. #define CAM_PIN_D6 41
  28. #define CAM_PIN_D7 39
  29. #endif
  30. // ESP32-S3-合宙的开发板
  31. #ifdef ESP32_S3_HEZHOU
  32. #define CAM_PIN_PWDN -1 // 没用直接接高
  33. #define CAM_PIN_RESET -1 // software reset will be performed
  34. #define CAM_PIN_VSYNC 42
  35. #define CAM_PIN_HREF 41
  36. #define CAM_PIN_PCLK 36
  37. #define CAM_PIN_XCLK 39
  38. #define CAM_PIN_SIOD 21
  39. #define CAM_PIN_SIOC 46
  40. #define CAM_PIN_D0 34
  41. #define CAM_PIN_D1 47
  42. #define CAM_PIN_D2 48
  43. #define CAM_PIN_D3 33
  44. #define CAM_PIN_D4 35
  45. #define CAM_PIN_D5 37
  46. #define CAM_PIN_D6 38
  47. #define CAM_PIN_D7 40
  48. #endif
  49. static const char *TAG = "example:take_picture";
  50. #define BOUNDARY "----ESP32Boundary"
  51. static camera_config_t camera_config = {
  52. .pin_pwdn = CAM_PIN_PWDN,
  53. .pin_reset = CAM_PIN_RESET,
  54. .pin_xclk = CAM_PIN_XCLK,
  55. .pin_sccb_sda = CAM_PIN_SIOD,
  56. .pin_sccb_scl = CAM_PIN_SIOC,
  57. .pin_d7 = CAM_PIN_D7,
  58. .pin_d6 = CAM_PIN_D6,
  59. .pin_d5 = CAM_PIN_D5,
  60. .pin_d4 = CAM_PIN_D4,
  61. .pin_d3 = CAM_PIN_D3,
  62. .pin_d2 = CAM_PIN_D2,
  63. .pin_d1 = CAM_PIN_D1,
  64. .pin_d0 = CAM_PIN_D0,
  65. .pin_vsync = CAM_PIN_VSYNC,
  66. .pin_href = CAM_PIN_HREF,
  67. .pin_pclk = CAM_PIN_PCLK,
  68. .xclk_freq_hz = 20000000, // XCLK 设置为 20MHz
  69. .ledc_timer = LEDC_TIMER_0,
  70. .ledc_channel = LEDC_CHANNEL_0,
  71. .pixel_format = PIXFORMAT_JPEG, // 使用 JPEG 格式
  72. .frame_size = FRAMESIZE_SVGA, // 使用 QVGA (320x240)
  73. .jpeg_quality = 60, // JPEG 质量 (0-63, 低值=高质量)
  74. .fb_count = 1, // 帧缓存数量
  75. .fb_location = CAMERA_FB_IN_DRAM, // 使用 DRAM
  76. .grab_mode = CAMERA_GRAB_WHEN_EMPTY,
  77. };
  78. static esp_err_t init_camera(void)
  79. {
  80. esp_err_t err = esp_camera_init(&camera_config);
  81. if (err != ESP_OK)
  82. {
  83. ESP_LOGE(TAG, "Camera Init Failed");
  84. return err;
  85. }
  86. return ESP_OK;
  87. }
  88. // 上传图片到服务器
  89. #define MULTIPART_BOUNDARY "----WebKitFormBoundary7MA4YWxkTrZu0gW" // 多部分表单的边界
  90. esp_err_t upload_picture(camera_fb_t *pic, long image_size)
  91. {
  92. esp_http_client_config_t config = {
  93. .url = "http://60.204.139.57:7002/upload", // 服务器地址
  94. .timeout_ms = 20000,
  95. .buffer_size = 1024 * 20,
  96. };
  97. // 初始化 HTTP 客户端
  98. esp_http_client_handle_t client = esp_http_client_init(&config);
  99. if (client == NULL) {
  100. ESP_LOGE(TAG, "Failed to initialize HTTP client");
  101. return ESP_FAIL;
  102. }
  103. esp_http_client_set_method(client, HTTP_METHOD_POST);
  104. // 设置请求头(multipart/form-data)
  105. esp_http_client_set_header(client, "Content-Type", "multipart/form-data; boundary=" MULTIPART_BOUNDARY);
  106. // 请求头开始部分
  107. char part1[256];
  108. int part1_len = snprintf(part1, sizeof(part1),
  109. "--" MULTIPART_BOUNDARY "\r\n"
  110. "Content-Disposition: form-data; name=\"file\"; filename=\"image.jpg\"\r\n"
  111. "Content-Type: image/jpeg\r\n\r\n");
  112. // 构建多部分表单数据的结束部分
  113. char part2[64];
  114. int part2_len = snprintf(part2, sizeof(part2), "\r\n--" MULTIPART_BOUNDARY "--\r\n");
  115. // 设置总的Content-Length
  116. long content_length = part1_len + image_size + part2_len;
  117. char content_length_str[32];
  118. snprintf(content_length_str, sizeof(content_length_str), "%ld", content_length);
  119. esp_http_client_set_header(client, "Content-Length", content_length_str);
  120. // 开始发送请求
  121. int err = esp_http_client_open(client, content_length);
  122. if (err != ESP_OK)
  123. {
  124. ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
  125. esp_http_client_cleanup(client); // 清理 HTTP 客户端
  126. return ESP_FAIL;
  127. }
  128. // 发送多部分表单数据的开始部分
  129. esp_http_client_write(client, part1, part1_len);
  130. // 发送文件数据
  131. char buffer[1024];
  132. size_t bytes_sent = 0;
  133. while (bytes_sent < pic->len)
  134. {
  135. size_t to_send = (pic->len - bytes_sent < sizeof(buffer)) ? (pic->len - bytes_sent) : sizeof(buffer);
  136. esp_http_client_write(client, (const char *)(pic->buf + bytes_sent), to_send);
  137. bytes_sent += to_send;
  138. }
  139. // 发送多部分表单数据的结束部分
  140. esp_http_client_write(client, part2, part2_len);
  141. int response_length = esp_http_client_fetch_headers(client);
  142. if (response_length < 0)
  143. {
  144. ESP_LOGE(TAG, "HTTP client fetch headers failed");
  145. }
  146. else
  147. {
  148. ESP_LOGI(TAG, "HTTP client fetch headers succeeded, length=%d", response_length);
  149. }
  150. // 动态分配初始缓冲区
  151. char *response_buffer = (char *)malloc(1024);
  152. if (response_buffer == NULL)
  153. {
  154. ESP_LOGE(TAG, "Failed to allocate memory for response buffer");
  155. esp_http_client_cleanup(client);
  156. return ESP_FAIL;
  157. }
  158. // 读取响应内容
  159. int read_len = esp_http_client_read(client, response_buffer, 1024 - 1);
  160. if (read_len >= 0)
  161. {
  162. response_buffer[read_len] = '\0'; // 确保字符串以null字符结尾
  163. ESP_LOGI(TAG, "HTTP Response: %s", response_buffer);
  164. }
  165. else
  166. {
  167. ESP_LOGE(TAG, "Failed to read response");
  168. }
  169. // 释放分配的内存
  170. free(response_buffer);
  171. // 清理
  172. esp_http_client_close(client);
  173. esp_http_client_cleanup(client);
  174. return err;
  175. }
  176. // 拍照并上传
  177. void take_photo(void *param)
  178. {
  179. if (ESP_OK != init_camera())
  180. {
  181. return;
  182. }
  183. while (true)
  184. {
  185. /* code */
  186. ESP_LOGI(TAG, "Taking picture...");
  187. camera_fb_t *pic = esp_camera_fb_get();
  188. if (pic == NULL)
  189. {
  190. ESP_LOGE(TAG, "Camera capture failed");
  191. return;
  192. }
  193. ESP_LOGI(TAG, "Picture taken! Its size was: %zu bytes", pic->len);
  194. // 上传图片
  195. esp_err_t err = upload_picture(pic,pic->len);
  196. if (err != ESP_OK)
  197. {
  198. ESP_LOGE(TAG, "Failed to upload picture");
  199. }
  200. esp_camera_fb_return(pic);
  201. vTaskDelay(10*60*1000 / portTICK_PERIOD_MS);
  202. }
  203. vTaskDelete(NULL);
  204. }