首页 > 其他分享 >四博智联 Esp-32CAM 图像识别接入燃气数据 本地识别及百度数字识别

四博智联 Esp-32CAM 图像识别接入燃气数据 本地识别及百度数字识别

时间:2024-08-27 13:53:52浏览次数:13  
标签:include 图像识别 esp NUM 智联 GPIO 识别 config define

接到一个客户需求,利用ESP32+摄像头完成家庭燃气表数据的采集接入,大概流程:

一、设备配网:

   通过微信小程序BLE连接到ESP32配网,配网完成后,把设备id绑定到相应的账号下。

让ChatGPT设计协议及代码如下:

设计一个通过微信小程序和BLE(蓝牙低功耗)给ESP32设备配网的协议需要考虑数据安全性、网络配置的有效性以及用户体验的流畅性。以下是一个建议的协议设计步骤:

1. 总体流程概述

  • 用户通过微信小程序扫描设备的二维码:获取设备的蓝牙MAC地址或设备唯一标识。
  • 微信小程序通过BLE与ESP32设备建立连接:启动BLE连接,进行初步的设备认证和握手。
  • 传输Wi-Fi配置信息:将Wi-Fi的SSID和密码加密后通过BLE发送到ESP32。
  • ESP32连接Wi-Fi并返回结果:ESP32尝试连接Wi-Fi,并通过BLE将连接结果返回给微信小程序。
  • 小程序显示连接结果:如果连接成功,小程序显示成功页面;如果失败,显示错误信息。

2. 协议设计详细步骤

Step 1: 设备扫描和BLE连接
  • 设备二维码扫描
    • 用户通过微信小程序扫描设备上的二维码,获取设备的蓝牙MAC地址或者设备唯一标识符。
  • BLE连接
    • 小程序通过获取到的蓝牙MAC地址与ESP32设备建立BLE连接。
    • 使用标准的BLE连接过程,建立GATT(通用属性协议)会话,选择适当的服务和特征值来进行数据传输。
Step 2: 设备认证与握手
  • 设备身份认证
    • ESP32生成一个随机数(nonce),通过BLE发送给小程序。
    • 小程序接收到nonce后,使用设备提供的公钥对其进行签名并将签名返回ESP32。
    • ESP32验证签名是否正确,以此确认微信小程序的合法性。
  • 握手完成
    • 认证成功后,双方交换加密密钥(如AES对称密钥)以保护后续的数据传输。
Step 3: Wi-Fi配置信息传输
  • 数据加密

    • 小程序加密Wi-Fi的SSID和密码,确保传输过程中的数据安全。
    • 可以使用AES对称加密算法来加密SSID和密码。
  • 传输Wi-Fi配置信息

    • 小程序将加密后的Wi-Fi SSID和密码通过BLE发送给ESP32设备。
    • 建议分块传输数据,以确保每个BLE包大小不超过BLE的最大传输单元(MTU)。
  • 配置确认

    • ESP32接收到数据后解密并验证配置。
    • ESP32确认数据完整性后,通过BLE发送一个确认信号给小程序。
Step 4: Wi-Fi连接尝试与结果返回
  • ESP32连接Wi-Fi
    • ESP32使用接收到的SSID和密码尝试连接指定的Wi-Fi网络。
  • 连接结果返回
    • 连接成功时,ESP32发送成功状态和IP地址回微信小程序。
    • 连接失败时,ESP32发送错误代码或错误信息回微信小程序,指出具体的失败原因(如密码错误、网络不可达等)。
Step 5: 小程序显示结果
  • 成功界面
    • 如果ESP32成功连接Wi-Fi,小程序显示成功界面,并提示用户设备已成功连接至Wi-Fi网络。
  • 失败处理
    • 如果连接失败,小程序根据ESP32返回的错误信息提示用户重新尝试,或者手动输入Wi-Fi信息进行再次配置。

3. 通信数据包结构

握手阶段数据包
  • 请求握手(微信小程序 -> ESP32):
    • Opcode: 0x01 (握手请求)
    • Nonce: 16字节的随机数
  • 握手响应(ESP32 -> 微信小程序):
    • Opcode: 0x02 (握手响应)
    • Nonce: 16字节的随机数
    • Signature: 使用设备私钥签名的Nonce
  • 密钥交换(微信小程序 -> ESP32):
    • Opcode: 0x03 (密钥交换)
    • Encrypted_Key: AES加密的对称密钥
Wi-Fi配置阶段数据包
  • 传输Wi-Fi信息(微信小程序 -> ESP32):
    • Opcode: 0x10 (Wi-Fi信息传输)
    • SSID_Length: SSID的长度
    • SSID: 加密后的SSID
    • Password_Length: 密码的长度
    • Password: 加密后的密码
  • 确认Wi-Fi配置(ESP32 -> 微信小程序):
    • Opcode: 0x11 (配置确认)
    • Status: 0x00(成功),0x01(失败)
  • 连接结果返回(ESP32 -> 微信小程序):
    • Opcode: 0x12 (连接结果)
    • Status: 0x00(成功),0x01(失败)
    • IP_Address: 成功连接时返回的IP地址(可选)

4. 安全性考虑

  • 数据加密:确保所有的Wi-Fi配置数据都经过AES加密,以防止中间人攻击。
  • 认证机制:使用设备证书或公钥进行认证,防止非法设备或程序的接入。
  • 重放攻击防护:使用随机数(Nonce)来防止重放攻击,确保每次会话都是唯一的。

5. 用户体验优化

  • 自动重连:如果连接失败,微信小程序可以提示用户重新尝试或自动重试。
  • 详细提示:对于常见的错误情况(如密码错误、网络不可达),提供详细的错误提示和解决建议。
  • 配网状态监控:在小程序中显示配网进度,让用户清楚知道配网过程的每一步。

6. 测试与验证

  • 多设备测试:确保该协议在不同的手机、不同的ESP32设备上均能正常工作。
  • 极端情况测试:测试低信号强度、网络拥塞等情况下的配网成功率。
  • 兼容性测试:确保协议在微信小程序的不同版本和操作系统版本(iOS、Android)上都能正常使用。

通过这个协议设计,微信小程序可以通过BLE给ESP32设备配网,实现设备联网的便捷体验。这种方法不仅安全可靠,还能提供良好的用户体验。

下面是基于所设计的协议,实现 ESP32 配网功能的代码。我们将分别提供基于 Arduino 版本和 ESP-IDF 版本的实现。

1. Arduino 版本

Arduino 版本的代码使用 BLE 库进行蓝牙通信,使用 WiFi 库进行网络连接。

a. Arduino BLE 代码实现
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <WiFi.h>

// BLE UUIDs
#define SERVICE_UUID "6e400001-b5a3-f393-e0a9-e50e24dcca9e"
#define CHARACTERISTIC_UUID_RX "6e400002-b5a3-f393-e0a9-e50e24dcca9e"
#define CHARACTERISTIC_UUID_TX "6e400003-b5a3-f393-e0a9-e50e24dcca9e"

// WiFi SSID and Password
char ssid[32] = {0};
char password[32] = {0};

BLECharacteristic *pTxCharacteristic;
bool deviceConnected = false;

class MyBLEServerCallbacks: public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
    deviceConnected = true;
  }

  void onDisconnect(BLEServer* pServer) {
    deviceConnected = false;
  }
};

class MyBLECallbacks: public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic *pCharacteristic) {
    std::string rxValue = pCharacteristic->getValue();

    if (rxValue.length() > 0) {
      Serial.println("Received Wi-Fi Credentials");

      // Assume SSID and Password are separated by a comma
      int commaIndex = rxValue.find(",");
      if (commaIndex != std::string::npos) {
        strncpy(ssid, rxValue.substr(0, commaIndex).c_str(), sizeof(ssid));
        strncpy(password, rxValue.substr(commaIndex + 1).c_str(), sizeof(password));
        
        Serial.print("SSID: ");
        Serial.println(ssid);
        Serial.print("Password: ");
        Serial.println(password);

        // Try to connect to Wi-Fi
        WiFi.begin(ssid, password);

        if (WiFi.waitForConnectResult() != WL_CONNECTED) {
          Serial.println("WiFi Connection Failed!");
          pTxCharacteristic->setValue("FAIL");
        } else {
          Serial.println("WiFi Connected");
          pTxCharacteristic->setValue(WiFi.localIP().toString().c_str());
        }
        pTxCharacteristic->notify();
      }
    }
  }
};

void setup() {
  Serial.begin(115200);

  // Initialize BLE
  BLEDevice::init("ESP32_BLE_WIFI_SETUP");
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyBLEServerCallbacks());

  BLEService *pService = pServer->createService(SERVICE_UUID);
  pTxCharacteristic = pService->createCharacteristic(
                        CHARACTERISTIC_UUID_TX,
                        BLECharacteristic::PROPERTY_NOTIFY
                      );
  pTxCharacteristic->addDescriptor(new BLE2902());

  BLECharacteristic *pRxCharacteristic = pService->createCharacteristic(
                                            CHARACTERISTIC_UUID_RX,
                                            BLECharacteristic::PROPERTY_WRITE
                                          );

  pRxCharacteristic->setCallbacks(new MyBLECallbacks());

  pService->start();

  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->setScanResponse(true);
  pAdvertising->setMinPreferred(0x06);  // functions that help with iPhone connections issue
  pAdvertising->setMinPreferred(0x12);
  BLEDevice::startAdvertising();

  Serial.println("Waiting for a client connection to notify...");
}

void loop() {
  // do nothing
}

2. ESP-IDF 版本

ESP-IDF 版本的代码使用官方的 ESP32 BLEWi-Fi 库进行实现。

a. ESP-IDF BLE 代码实现
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_bt.h"
#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
#include "esp_bt_main.h"
#include "esp_gatt_common_api.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "nvs_flash.h"
#include "lwip/err.h"
#include "lwip/sys.h"

#define TAG "BLE_WIFI_SETUP"

// BLE UUIDs
#define GATTS_SERVICE_UUID   0x00FF
#define GATTS_CHAR_UUID_RX   0xFF01
#define GATTS_CHAR_UUID_TX   0xFF02

#define DEVICE_NAME "ESP32_BLE_SETUP"
#define CHAR_VAL_LEN_MAX 0x40

static uint8_t adv_config_done = 0;
#define adv_config_flag      (1 << 0)
#define scan_rsp_config_flag (1 << 1)

static uint8_t char1_str[] = {0x11, 0x22, 0x33};
static esp_gatt_char_prop_t a_property = 0;

static esp_attr_value_t gatts_demo_char1_val = {
    .attr_max_len = CHAR_VAL_LEN_MAX,
    .attr_len     = sizeof(char1_str),
    .attr_value   = char1_str,
};

static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);

static struct gatts_profile_inst {
    esp_gatts_cb_t gatts_cb;
    uint16_t gatts_if;
    uint16_t app_id;
    uint16_t conn_id;
    uint16_t service_handle;
    esp_gatt_srvc_id_t service_id;
    uint16_t char_handle;
    esp_bt_uuid_t char_uuid;
    esp_gatt_perm_t perm;
    esp_gatt_char_prop_t property;
    uint16_t descr_handle;
    esp_bt_uuid_t descr_uuid;
} gatts_profile = {
    .gatts_cb = gatts_profile_event_handler,
    .gatts_if = ESP_GATT_IF_NONE,
};

// WiFi SSID and Password
char ssid[32] = {0};
char password[32] = {0};

// WiFi connection handler
void wifi_init_sta(char *ssid, char *password) {
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    wifi_config_t wifi_config = {
        .sta = {
            .ssid = "",
            .password = "",
        },
    };
    strncpy((char *)wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid));
    strncpy((char *)wifi_config.sta.password, password, sizeof(wifi_config.sta.password));

    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
    ESP_ERROR_CHECK(esp_wifi_start());

    esp_wifi_connect();
}

// BLE events handler
static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) {
    switch (event) {
        case ESP_GATTS_REG_EVT:
            esp_ble_gap_set_device_name(DEVICE_NAME);
            esp_ble_gap_config_adv_data(&adv_data);
            break;

        case ESP_GATTS_WRITE_EVT:
            if (!param->write.is_prep) {
                // Received data
                esp_log_buffer_hex(TAG, param->write.value, param->write.len);

                // Process received data
                // Assume SSID and Password are separated by a comma
                char *received_data = (char *)param->write.value;
                char *comma_pos = strchr(received_data, ',');
                if (comma_pos) {
                    strncpy(ssid, received_data, comma_pos - received_data);
                    strncpy(password, comma_pos + 1, sizeof(password));

                    // Connect to WiFi
                    wifi_init_sta(ssid, password);

                    // Notify result back
                    // You would need to implement logic to handle the connection status and notify the client.
                }
            }
            break;

        // Other BLE event cases...
        default:
            break;
    }
}

void app_main(void) {
    esp_err_t ret;

    // Initialize NVS
    ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
      ESP_ERROR_CHECK(nvs_flash_erase());
      ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    // Initialize Bluetooth
    ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));
    esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
    ret = esp_bt_controller_init(&bt_cfg);
    if (ret) {
        ESP_LOGE(TAG, "%s initialize controller failed: %s\n", __func__, esp_err_to_name(ret));
        return;
    }

    ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
    if (ret) {
        ESP_LOGE(TAG, "%s enable controller failed: %s\n", __func__, esp_err_to_name(ret));
        return;
    }

    ret = esp_bluedroid_init();
    if (ret) {
        ESP_LOGE(TAG, "%s init bluedroid failed: %s\n", __func__, esp_err_to_name(ret));
        return;
    }

    ret = esp_bluedroid_enable();
    if (ret) {
        ESP_LOGE(TAG, "%s enable bluedroid failed: %s\n", __func__, esp_err_to_name(ret));
        return;
    }

    // Register BLE GATT server
    esp_ble_gatts_register_callback(gatts_event_handler);
    esp_ble_gap_register_callback(gap_event_handler);
    esp_ble_gatts_app_register(PROFILE_A_APP_ID);

    // Initialize WiFi
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
}

3. 总结

  • Arduino 版本:更易于理解和开发,适合快速原型和小型项目。
  • ESP-IDF 版本:提供更高的灵活性和控制,更适合复杂的项目和商业产品。

这些代码示例提供了基本的 BLE 和 Wi-Fi 配网逻辑,您可以根据具体需求进一步扩展和优化功能

二、拍照上传,后台调用baidu的图片接口

以下是如何在ESP32上通过HTTP POST上传拍照所得图片文件的完整代码实现。这个示例将继续基于之前的Arduino版本和ESP-IDF版本。

1. Arduino 版本

Arduino版本中,我们将使用ESP32-Camera库进行拍照,然后使用HTTPClient库将图片通过HTTP POST上传。

a. Arduino 代码实现
#include <WiFi.h>
#include <HTTPClient.h>
#include "esp_camera.h"

// Replace with your network credentials
const char* ssid = "your_SSID";
const char* password = "your_PASSWORD";

// Replace with your server's URL
const char* serverName = "http://yourserver.com/upload";

// Camera Pin configuration
#define PWDN_GPIO_NUM    -1
#define RESET_GPIO_NUM   -1
#define XCLK_GPIO_NUM    21
#define SIOD_GPIO_NUM    26
#define SIOC_GPIO_NUM    27

#define Y9_GPIO_NUM      35
#define Y8_GPIO_NUM      34
#define Y7_GPIO_NUM      39
#define Y6_GPIO_NUM      36
#define Y5_GPIO_NUM      19
#define Y4_GPIO_NUM      18
#define Y3_GPIO_NUM      5
#define Y2_GPIO_NUM      4
#define VSYNC_GPIO_NUM   25
#define HREF_GPIO_NUM    23
#define PCLK_GPIO_NUM    22

void setup() {
  Serial.begin(115200);
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");

  // Camera configuration
  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;

  // Init with high specs to pre-allocate larger buffers
  if(psramFound()){
    config.frame_size = FRAMESIZE_UXGA;
    config.jpeg_quality = 10;
    config.fb_count = 2;
  } else {
    config.frame_size = FRAMESIZE_SVGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;
  }

  // Camera init
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    return;
  }
}

void loop() {
  // Capture a photo
  camera_fb_t * fb = esp_camera_fb_get();
  if (!fb) {
    Serial.println("Camera capture failed");
    return;
  }

  // Create HTTP client and set the target URL
  HTTPClient http;
  http.begin(serverName);

  // Set headers for multipart/form-data POST request
  String boundary = "----WebKitFormBoundary7MA4YWxkTrZu0gW";
  http.addHeader("Content-Type", "multipart/form-data; boundary=" + boundary);

  // Build the multipart form data body
  String body = "--" + boundary + "\r\n";
  body += "Content-Disposition: form-data; name=\"file\"; filename=\"photo.jpg\"\r\n";
  body += "Content-Type: image/jpeg\r\n\r\n";
  
  // Send the HTTP POST request
  http.addHeader("Content-Length", String(fb->len + body.length() + boundary.length() + 6));
  int httpResponseCode = http.POST((uint8_t*)body.c_str(), body.length());
  httpResponseCode += http.POST(fb->buf, fb->len);
  
  // Send the closing boundary
  String endBoundary = "\r\n--" + boundary + "--\r\n";
  httpResponseCode += http.POST((uint8_t*)endBoundary.c_str(), endBoundary.length());

  if (httpResponseCode > 0) {
    String response = http.getString();
    Serial.println(httpResponseCode);
    Serial.println(response);
  }
  else {
    Serial.print("Error on sending POST: ");
    Serial.println(httpResponseCode);
  }

  // End the HTTP request
  http.end();

  // Return the frame buffer back to the driver for reuse
  esp_camera_fb_return(fb);

  // Wait a few seconds before taking another photo
  delay(10000);
}

2. ESP-IDF 版本

ESP-IDF版本会稍微复杂一些,需要手动构建HTTP请求并处理相应的Wi-Fi连接。

a. ESP-IDF 代码实现
#include <stdio.h>
#include <string.h>
#include "esp_camera.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_wifi.h"
#include "esp_http_client.h"
#include "esp_system.h"
#include "esp_event.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "nvs_flash.h"
#include "esp_netif.h"

// Camera Pin configuration (same as Arduino example)
#define PWDN_GPIO_NUM    -1
#define RESET_GPIO_NUM   -1
#define XCLK_GPIO_NUM    21
#define SIOD_GPIO_NUM    26
#define SIOC_GPIO_NUM    27

#define Y9_GPIO_NUM      35
#define Y8_GPIO_NUM      34
#define Y7_GPIO_NUM      39
#define Y6_GPIO_NUM      36
#define Y5_GPIO_NUM      19
#define Y4_GPIO_NUM      18
#define Y3_GPIO_NUM      5
#define Y2_GPIO_NUM      4
#define VSYNC_GPIO_NUM   25
#define HREF_GPIO_NUM    23
#define PCLK_GPIO_NUM    22

#define TAG "HTTP_POST_IMAGE"

static const char *post_url = "http://yourserver.com/upload";

void take_and_send_photo() {
    // Initialize camera
    camera_config_t config;
    config.ledc_channel = LEDC_CHANNEL_0;
    config.ledc_timer = LEDC_TIMER_0;
    config.pin_d0 = Y2_GPIO_NUM;
    config.pin_d1 = Y3_GPIO_NUM;
    config.pin_d2 = Y4_GPIO_NUM;
    config.pin_d3 = Y5_GPIO_NUM;
    config.pin_d4 = Y6_GPIO_NUM;
    config.pin_d5 = Y7_GPIO_NUM;
    config.pin_d6 = Y8_GPIO_NUM;
    config.pin_d7 = Y9_GPIO_NUM;
    config.pin_xclk = XCLK_GPIO_NUM;
    config.pin_pclk = PCLK_GPIO_NUM;
    config.pin_vsync = VSYNC_GPIO_NUM;
    config.pin_href = HREF_GPIO_NUM;
    config.pin_sscb_sda = SIOD_GPIO_NUM;
    config.pin_sscb_scl = SIOC_GPIO_NUM;
    config.pin_pwdn = PWDN_GPIO_NUM;
    config.pin_reset = RESET_GPIO_NUM;
    config.xclk_freq_hz = 20000000;
    config.pixel_format = PIXFORMAT_JPEG;

    if(psramFound()){
        config.frame_size = FRAMESIZE_UXGA;
        config.jpeg_quality = 10;
        config.fb_count = 2;
    } else {
        config.frame_size = FRAMESIZE_SVGA;
        config.jpeg_quality = 12;
        config.fb_count = 1;
    }

    esp_err_t err = esp_camera_init(&config);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Camera Init Failed");
        return;
    }

    // Take picture
    camera_fb_t *fb = esp_camera_fb_get();
    if (!fb) {
        ESP_LOGE(TAG, "Camera Capture Failed");
        return;
    }

    // Create HTTP client config
    esp_http_client_config_t config_client = {
        .url = post_url,
        .method = HTTP_METHOD_POST,
    };
    esp_http_client_handle_t client = esp_http_client_init(&config_client);

    // Prepare headers for multipart form data
    esp_http_client_set_header(client, "Content-Type", "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW");

    // Build body content
    char *body_start = "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\n"
                       "Content-Disposition: form-data; name=\"file\"; filename=\"photo.jpg\"\r\n"
                       "Content-Type: image/jpeg\r\n\r\n";

    esp_http_client_set_post_field(client, body_start, strlen(body_start));
    esp_http_client_perform(client);

    // Send image data
    esp_http_client_write(client, (const char *)fb->buf, fb->len);

    // End of body content
   

三、经过测试,稍微修改就可以工作,AI真是太强大了,

注意:

当然,也可以本地识别,需要设定的参数比较多,具体见:

GitHub - jomjol/AI-on-the-edge-device: Easy to use device for connecting "old" measuring units (water, power, gas, ...) to the digital world

 这个项目允许你使用廉价且易于获取的硬件,将你的模拟水表、煤气表、电表以及其他表进行数字化。

标签:include,图像识别,esp,NUM,智联,GPIO,识别,config,define
From: https://blog.csdn.net/weixin_37694490/article/details/141566562

相关文章

  • 基于OpenCV-Python实现人脸识别-----摄像头捕获人脸图像显示中文乱码问题
    基于OpenCV-Python实现人脸识别时,为了使图像上显示识别到人员的中文名字,做了几次尝试,使用PIL.Image和OpenCV图像格式相互转换解决:使用OpenCV将图片灰度化,对加载的灰度化图使用分类器中的detectMultiScale()函数查找目标人脸,并使用for循环实现矩形框和圆形框框住查找到的人脸。......
  • 【故障识别与诊断】基于EEMD-MPE-KPCA-BILSTM(集合经验模态分解-多尺度排列嫡-核主元
      ......
  • 如何本地搭建 Whisper 语音识别模型?一文解决
    Whisper是OpenAI开发的强大语音识别模型,适用于多种语言的语音转文字任务。要在本地搭建Whisper模型,需要完成以下几个步骤,确保模型在你的设备上顺利运行。1.准备环境首先,确保你的系统上安装了Python(版本3.8到3.11之间)。此外,还需要安装PyTorch,这是Whisper依赖......
  • Python从0到100(五十四):K近邻算法及⼿写数字识别数据集分类
    K最近邻(K-NearestNeighbors,简称KNN)是⼀种常⽤的监督学习算法,主要⽤于分类和回归问题。KNN的基本原理是基于特征空间中样本点的距离来进⾏预测或分类。对于分类问题,KNN找到与待分类样本在特征空间中最近的K个训练样本,并基于它们的类别标签进⾏投票决策。对于回归问题,KNN找......
  • 电子工程师提升计划-常用半导体器件 的种类、识别与 检测【4.6】
    ④气敏电阻器的识别气敏电阻器的型号有很多种,了解型号中各字母或数字的意义,对选用和识别气敏电阻器将很有帮助。气敏电阻器型号的识读方法见表2-15。气敏电阻器标识的具体含义见表2-16。⑤压敏电阻器的识别压敏电阻器的型号有很多种,了解型号中各字母或数字的意义,对......
  • 云语音识别震撼升级,高准确率、多语种覆盖,超低开发成本
    在人工智能技术日新月异的时代,语音识别作为AI领域的重要分支,正以前所未有的速度改变着我们的生活方式和工作模式。腾讯云语音识别,凭借其高准确率、多语种支持以及超低开发成本的优势,正逐步成为市场中的佼佼者,引领AI应用的新潮流。本文将深入探讨腾讯云语音识别的独特魅力,揭示其......
  • 使用AI识别语音和B站视频并通过GPT生成思维导图
    AI脑图除了对文本、网页链接和文件生成思维导图外,现在也支持了对语音和B站视频的内容识别,并自动生成思维导图。语音生成思维导图直接发送语音:对AI脑图公众号直接发送语音(如使用语音说厦门三天两夜的旅行攻略),AI脑图会自动识别语音内容然后根据内容要求生成思维导图思维导图效果......
  • 数据库不可见的特殊符号识别
     在数据库数据存储的数据,会存在部分体现为空格或者?等特殊符号,有些字符复制出来后,某些软件甚至无法解析会和谐成空格;部分可显形的方法:粘贴到notepad++,然后选择 视图->显示符号->显示所有字符 在数据库处理方法:1.使用unicode()进行字符显形,由于部分字符无法粘贴,可以通过数......
  • Java 调用电脑中安装的tesseract.exe进行图片中的文本方向识别
    StringimagePath="测试图片完整地址";StringtesseractPath="Tesseract安装路径\\tesseract.exe";ProcessBuilderprocessBuilder=newProcessBuilder(tesseractPath,imagePath,"stdout","--......
  • 京东中文点选验证码识别方案
     一、验证码介绍这款验证码防御能力还是很强,主要是中文字体特殊,颜色和背景融合度很高,以至于人都很难看清楚。有些文字甚至进行了模糊处理,人都很难识别是上面字。所以给机器识别造成了很大困扰。二、识别代码1、识别参数介绍京东中文点选验证码识别,我们需要两种图片才能完......