camera.c 6.0 KB

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