安信可ESP32-CAM摄像头开发demo--广域网远程实时查看视频流

安信可 ESP32 专题 专栏收录该内容
21 篇文章 14 订阅

一、实际效果

该demo演示的在基于广域网使用APP实现远程实时查看ESP32-CAM所拍摄的视频流
拍照

二、准备工作

1.ESP32-CAM开发板 样品链接
2.USB TO TTL和杜邦线
4.安卓APP----链接:https://pan.baidu.com/s/1ZxIVD3EKzHdn6UchkXcnrw
提取码:n6tp

三、开发环境搭建

3.1 获取SDK

获取ESP32 SDK esp-idf,版本为v4.0

git clone -b release/v4.0 --recurse-submodules https://github.com/espressif/esp-idf

设置 IDF_PATH 路径

vim ~/.bashrc

之后按下 i 嵌入代码,任意一处添加路径,以我的路径为例

export IDF_PATH=/mnt/hgfs/share/Ai-Thinker-Open_ESP32-CAMERA_LAN/esp-idf  

按下esc 再 :wq 表示写入保存
更新一下路径:

 source ~/.bashrc

IDF_PATH 路径测试是否设置成功: echo $IDF_PATH
除了 ESP-IDF 本身,您还需要安装 ESP-IDF 使用的各种工具,比如编译器、调试器、Python 包等!

cd /mnt/hgfs/share/esp-idf    //以我的路径为例
sudo ./install.sh

出现这个 , 表示 安装成功
在这里插入图片描述
此时,您刚刚安装的工具尚未添加至 PATH 环境变量,无法通过“命令窗口”使用这些工具。因此,必须设置一些环境变量,这可以通过 ESP-IDF 提供的另一个脚本完成。
注意下面命令2个小数点中间有一个空格!

. ./export.sh

成功后,便这样提示:
在这里插入图片描述

获取广域网CAM SDK

cd esp-idf
git clone --recurse-submodules https://github.com/Ai-Thinker-Open/Ai-Thinker-Open_ESP32-CAMERA_WAN

3.2 编译下载

cd Ai-Thinker-Open_ESP32-CAMERA_WAN
make menuconfig

进入Camera configuration —>
输入Nabto ID 为"asrrmhso.zuzcni.trial.nabto.net"
Nabto key为"337acb58e15b72117a49bf779d90cb29"
在这里插入图片描述
进入Setup correct wiring of camera ,选择Seedstudios/AI.Tinker
在这里插入图片描述
使能smartconfig,进入 smart config,输入Y使能,上电即可使用app配网,配网app获取
在这里插入图片描述
如果固定使用一个WiFi,可在WIFI access point name (SSID)输入WiFi名字,在 WIFI password输入WiFi密码,写死WiFi信息后无需app配网。

make  //编译
make flash  //下载
make monitor  //串口打印

四、配网 && APP查看视频

  1. 如果写死wifi信息可略过此配网步骤。smartconfig配网过程如下图:
    在这里插入图片描述
  2. 确保手机和设备接入同一WiFi,进入app,点击discover and auto pair with device
    在这里插入图片描述
  3. 发现设备后点击右侧箭头进入
    在这里插入图片描述
  4. 确认配对
    在这里插入图片描述
  5. 进入设备即可查看视频
    在这里插入图片描述
  6. 配对过后下次进入app直接在首页点击进入即可,如果没有发现设备,点击REFRESH刷新一下
    在这里插入图片描述

五、smartconfig配网后SSID,password保存

截至2020/12/2 在sdk里面仅提供smartconfig示例,配网成功后并没有保存WiFi信息。这里提供smartconfig配网成功后保存SSID、Password的示例,配网成功后自动保存ssid和password,上电自动连接上一次连接的WiFi。

  1. 配网成功后将WiFi信息写入flash
 void router_wifi_save_info(uint8_t *ssid, uint8_t *password)
{
    nvs_handle out_handle;
    char data[65];
    if (nvs_open("wifi_info", NVS_READWRITE, &out_handle) != ESP_OK)
    {
        return;
    }

    memset(data, 0x0, sizeof(data));
    strncpy(data, (char *)ssid, strlen((char *)ssid));
    if (nvs_set_str(out_handle, "ssid", data) != ESP_OK)
    {
        ESP_LOGI(TAG,"--set ssid fail");
    }

    memset(data, 0x0, sizeof(data));
    strncpy(data, (char *)password, strlen((char *)password));
    if (nvs_set_str(out_handle, "password", data) != ESP_OK)
    {
        ESP_LOGI(TAG,"--set password fail");
    }
    nvs_commit(out_handle);
    nvs_close(out_handle);
}
  1. 上电后将flash中的WiFi信息读出
wifi_config_t wifi_config;
bool router_wifi_read()
{
    nvs_handle out_handle;
    size_t size = 0;
    nvs_open("wifi_info", NVS_READONLY, &out_handle);
    memset(&wifi_config, 0x0, sizeof(wifi_config));
    size = sizeof(wifi_config.sta.ssid);
    if(nvs_get_str(out_handle, "ssid", (char *)wifi_config.sta.ssid, &size) == ESP_OK)
    {
        if (size > 0)
        {
            size = sizeof(wifi_config.sta.password);
            if (nvs_get_str(out_handle, "password", (char *)wifi_config.sta.password, &size) == ESP_OK)
            {
                ESP_LOGI(TAG,"-- get ssid: %s", wifi_config.sta.ssid);
                ESP_LOGI(TAG,"-- get password: %s", wifi_config.sta.password);
                return 1;
            }
        }
    }
    nvs_close(out_handle);
    return 0;
}
  1. 修改后的main.c
#include <stdio.h>
#include <ctype.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_camera.h"
#include <driver/gpio.h>


#include <esp_http_server.h>

#include "demo_application.h"
#include <unabto_aes_cbc_test.h>
//#include <unabto_hmac_sha256_test.h>

#include <unabto/unabto_common_main.h>
#include <unabto/unabto_app.h>
#include <unabto_tunnel_select.h>

#include "app_smart_wifi.h"
#include "nvs_flash.h"
#include <stdbool.h>
#include "esp_wifi.h"
#include "esp_log.h"
#include "esp_err.h"


// Set in menuconfig .. or override here
#define WIFI_SSID CONFIG_SSID
#define WIFI_PASS CONFIG_SSID_PASSWORD
#define NABTO_ID CONFIG_NABTO_ID
#define NABTO_KEY CONFIG_NABTO_KEY


// Event group
//static EventGroupHandle_t wifi_event_group;
EventGroupHandle_t wifi_event_group;

const int CONNECTED_BIT = BIT0;

bool router_wifi_read();
void router_wifi_save_info(uint8_t *ssid, uint8_t *password);
wifi_config_t wifi_config;

static const char *TAG = "main";

#ifdef CONFIG_ESP_EYE

// ESP-EYE wiring
#define CAM_PIN_PWDN    -1 //power down is not used
#define CAM_PIN_RESET   -1 //software reset will be performed
#define CAM_PIN_XCLK    4
#define CAM_PIN_SIOD    18
#define CAM_PIN_SIOC    23

#define CAM_PIN_D7      36
#define CAM_PIN_D6      37
#define CAM_PIN_D5      38
#define CAM_PIN_D4      39
#define CAM_PIN_D3      35
#define CAM_PIN_D2      14
#define CAM_PIN_D1      13
#define CAM_PIN_D0      34
#define CAM_PIN_VSYNC    5
#define CAM_PIN_HREF    27
#define CAM_PIN_PCLK    25

#elif defined CONFIG_ESP_TINKER

// Ai Thinker CAM 32 wiring 
#define CAM_PIN_PWDN    32 
#define CAM_PIN_RESET   -1 
#define CAM_PIN_XCLK    0
#define CAM_PIN_SIOD    26
#define CAM_PIN_SIOC    27

#define CAM_PIN_D7      35
#define CAM_PIN_D6      34
#define CAM_PIN_D5      39
#define CAM_PIN_D4      36
#define CAM_PIN_D3      21
#define CAM_PIN_D2      19
#define CAM_PIN_D1      18
#define CAM_PIN_D0       5
#define CAM_PIN_VSYNC   25
#define CAM_PIN_HREF    23
#define CAM_PIN_PCLK    22

#elif CONFIG_M5CAMERA_A
#define CAM_PIN_PWDN    -1 //power down is not used
#define CAM_PIN_RESET   15 //software reset will be performed
#define CAM_PIN_XCLK    27
#define CAM_PIN_SIOD    25
#define CAM_PIN_SIOC    23

#define CAM_PIN_D7      19
#define CAM_PIN_D6      36
#define CAM_PIN_D5      18
#define CAM_PIN_D4      39
#define CAM_PIN_D3      5
#define CAM_PIN_D2      34
#define CAM_PIN_D1      35
#define CAM_PIN_D0      32
#define CAM_PIN_VSYNC   22
#define CAM_PIN_HREF    26
#define CAM_PIN_PCLK    21

#else
#error "Not defined - this should not happed!"
#endif

#define CAM_XCLK_FREQ   20000000

static camera_config_t camera_config = {
    .pin_pwdn  = CAM_PIN_PWDN,
    .pin_reset = CAM_PIN_RESET,
    .pin_xclk = CAM_PIN_XCLK,
    .pin_sscb_sda = CAM_PIN_SIOD,
    .pin_sscb_scl = CAM_PIN_SIOC,

    .pin_d7 = CAM_PIN_D7,
    .pin_d6 = CAM_PIN_D6,
    .pin_d5 = CAM_PIN_D5,
    .pin_d4 = CAM_PIN_D4,
    .pin_d3 = CAM_PIN_D3,
    .pin_d2 = CAM_PIN_D2,
    .pin_d1 = CAM_PIN_D1,
    .pin_d0 = CAM_PIN_D0,
    .pin_vsync = CAM_PIN_VSYNC,
    .pin_href = CAM_PIN_HREF,
    .pin_pclk = CAM_PIN_PCLK,

    //XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental)
    .xclk_freq_hz = CAM_XCLK_FREQ,
    .ledc_timer = LEDC_TIMER_0,
    .ledc_channel = LEDC_CHANNEL_0,

    .pixel_format = PIXFORMAT_JPEG,//YUV422,GRAYSCALE,RGB565,JPEG
    .frame_size = FRAMESIZE_VGA,//QQVGA-QXGA Do not use sizes above QVGA when not JPEG

    .jpeg_quality = 10, //0-63 lower number means higher quality
    .fb_count = 5 //if more than one, i2s runs in continuous mode. Use only with JPEG  //{ 2
};


// #ifndef CONFIG_ESP_SMAERT_CONFIG

/*
 * WIFI event handler
 */
static esp_err_t event_handler(void *ctx, system_event_t *event)
{
    switch(event->event_id) {
        
    case SYSTEM_EVENT_STA_START:
        esp_wifi_connect();
        break;
        
    case SYSTEM_EVENT_STA_GOT_IP:
        NABTO_LOG_INFO(("connected1!\n"));
        xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
        break;
        
    case SYSTEM_EVENT_STA_DISCONNECTED:
        xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
        esp_wifi_connect();
        break;
        
    default:
        break;
    }
    
    return ESP_OK;
}
// #endif
/*
 * Convert hex to i (for converting the hex key to bytebuffer)
 */
int hctoi(const unsigned char h) {
  if (isdigit(h)) {
    return h - '0';
  } else {
    return toupper(h) - 'A' + 10;
  }
}



#define PART_BOUNDARY "123456789000000000000987654321"
static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";
static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n";

/*
 * MJPEG stream handler on http://<host>/
 */
esp_err_t jpg_stream_httpd_handler(httpd_req_t *req){
    camera_fb_t * fb = NULL;
    esp_err_t res = ESP_OK;
    size_t _jpg_buf_len;
    uint8_t * _jpg_buf;
    char * part_buf[64];
    static int64_t last_frame = 0;
    if(!last_frame) {
        last_frame = esp_timer_get_time();
    }
    
    res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE);
    if(res != ESP_OK){
        return res;
    }
    
    while(true){
        fb = esp_camera_fb_get();
        if (!fb) {
            NABTO_LOG_ERROR(("Camera capture failed"));
            res = ESP_FAIL;
        } else {
            if(fb->format != PIXFORMAT_JPEG){
                bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len);
                if(!jpeg_converted){
                    NABTO_LOG_ERROR(("JPEG compression failed"));
                    esp_camera_fb_return(fb);
                    res = ESP_FAIL;
                }
            } else {
                _jpg_buf_len = fb->len;
                _jpg_buf = fb->buf;
            }
        }
        if(res == ESP_OK){
            size_t hlen = snprintf((char *)part_buf, 64, _STREAM_PART, _jpg_buf_len);

            res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen);
        }
        if(res == ESP_OK){
            res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len);
        }
        if(res == ESP_OK){
            res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));
        }
        if(fb->format != PIXFORMAT_JPEG){
            free(_jpg_buf);
        }
        esp_camera_fb_return(fb);
        if(res != ESP_OK){
            break;
        }
        int64_t fr_end = esp_timer_get_time();
        int64_t frame_time = fr_end - last_frame;
        last_frame = fr_end;
        frame_time /= 1000;
        NABTO_LOG_INFO(("MJPG: %uKB %ums (%.1ffps)",
            (uint32_t)(_jpg_buf_len/1024),
                        (uint32_t)frame_time, 1000.0 / (uint32_t)frame_time));
    }

    last_frame = 0;
    return res;
}



/* 
 * Hello world on http://<host>/uri
 */
esp_err_t get_handler(httpd_req_t *req)
{
    /* Send a simple response */
    const char* resp = "Hello world test!";
    httpd_resp_send(req, resp, strlen(resp));
    return ESP_OK;
}

/* 
 * 1m stream of bytes on http://<host>/1m for stream performance testing
 */
esp_err_t get_handler_1m(httpd_req_t *req)
{
    /* Send a simple response */
    const char* resp =
        "0123456789012345678901234567890123456789012345678\n"           \
        "0123456789012345678901234567890123456789012345678\n"           \
        "0123456789012345678901234567890123456789012345678\n"           \
        "0123456789012345678901234567890123456789012345678\n"           \
        "0123456789012345678901234567890123456789012345678\n"           \
        "0123456789012345678901234567890123456789012345678\n"           \
        "0123456789012345678901234567890123456789012345678\n"           \
        "0123456789012345678901234567890123456789012345678\n"           \
        "0123456789012345678901234567890123456789012345678\n"           \
        "0123456789012345678901234567890123456789012345678\n"           \
        "0123456789012345678901234567890123456789012345678\n"           \
        "0123456789012345678901234567890123456789012345678\n"           \
        "0123456789012345678901234567890123456789012345678\n"           \
        "0123456789012345678901234567890123456789012345678\n"           \
        "0123456789012345678901234567890123456789012345678\n"           \
        "0123456789012345678901234567890123456789012345678\n"           \
        "0123456789012345678901234567890123456789012345678\n"           \
        "0123456789012345678901234567890123456789012345678\n"           \
        "0123456789012345678901234567890123456789012345678\n"           \
        "0123456789012345678901234567890123456789012345678\n";

    // Create a 1k byte buffer chuck
    char resp_1k[1000];
    int len = 1000;
    for(int i=0;i<10;i++) {
        memcpy(resp_1k+(i*100), resp, 100);
    }
    resp_1k[999]=0;
    
    NABTO_LOG_INFO(("strlen:%d 1000000/len:%d", len, 1000000/len));    
    
    int64_t start_time = esp_timer_get_time();

    // Send 1m chunk
    for(int t=0; t< 1000000/len; t++) {
        int res = httpd_resp_send_chunk(req, (const char *) resp_1k, len);
        if(res != ESP_OK) {
            NABTO_LOG_INFO(("Could not send chunk %i", t));
            return ESP_FAIL;
        }
        
    }
    // send last 0 chunk to end the stream
    httpd_resp_send_chunk(req, (const char *) resp, 0);

    int64_t end_time = esp_timer_get_time();
    int64_t time = end_time - start_time;
    float kb = 1000000/1024;
    
    NABTO_LOG_INFO(("Finished in %lldms kb=%f kb/s=%f", time/1000, kb, kb/((float)time/1000000)));

    return ESP_OK;
}


/* URI handler structure for GET /uri */
httpd_uri_t uri_get = {
    .uri      = "/uri",
    .method   = HTTP_GET,
    .handler  = get_handler,
    .user_ctx = NULL
};


/* URI handler structure for GET /1m */
httpd_uri_t uri_get_1m = {
    .uri      = "/1m",
    .method   = HTTP_GET,
    .handler  = get_handler_1m,
    .user_ctx = NULL
};

/* URI handler structure for GET / */
httpd_uri_t uri_get_mjpeg = {
    .uri      = "/",
    .method   = HTTP_GET,
    .handler  = jpg_stream_httpd_handler,
    .user_ctx = NULL
};


/* 
 * Function for starting the webserver
 */
httpd_handle_t start_webserver(void)
{
    /* Generate default configuration */
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();
    config.server_port = 8081;

    
    /* Empty handle to esp_http_server */
    httpd_handle_t server = NULL;

    /* Start the httpd server */
    if (httpd_start(&server, &config) == ESP_OK) {
        /* Register URI handlers */
        httpd_register_uri_handler(server, &uri_get);
        httpd_register_uri_handler(server, &uri_get_1m);
        httpd_register_uri_handler(server, &uri_get_mjpeg);
    }
    /* If server failed to start, handle will be NULL */
    return server;
}

/*
 * Function for stopping the webserver (not used)
 */
void stop_webserver(httpd_handle_t server)
{
    if (server) {
        /* Stop the httpd server */
        httpd_stop(server);
    }
}


/*
 * Main task - initialize WIFI and start Nabto tick
 */
void main_task(void *pvParameter)
{
  // device id and key from developer.nabto.com
  const char* nabtoId = NABTO_ID;
  const char* presharedKey = NABTO_KEY;
  NABTO_LOG_INFO(("NabtoId:%s", nabtoId));
  NABTO_LOG_INFO(("NabtoKey:%s", presharedKey));
  
  // wait for connection
  NABTO_LOG_INFO(("Main task: waiting for connection to the wifi network... "));
  xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
  NABTO_LOG_INFO(("connected!\n"));
  
  // print the local IP address
  tcpip_adapter_ip_info_t ip_info;
  ESP_ERROR_CHECK(tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info));
  
  NABTO_LOG_INFO(("IP Address:  %s", ip4addr_ntoa(&ip_info.ip)));
  NABTO_LOG_INFO(("Subnet mask: %s", ip4addr_ntoa(&ip_info.netmask)));
  NABTO_LOG_INFO(("Gateway:     %s", ip4addr_ntoa(&ip_info.gw)));

  // Start the webserver thread
  start_webserver();
  
  // Configure Nabto with the right configuration
  nabto_main_setup* nms = unabto_init_context();
  nms->id = NABTO_ID;
  //nms->ipAddress = ip_info.ip.addr;
  nms->id = nabtoId;
  nms->secureAttach = 1;
  nms->secureData = 1;
  nms->cryptoSuite = CRYPT_W_AES_CBC_HMAC_SHA256;

  const char* p;
  unsigned char* up;
  for (p = presharedKey, up = nms->presharedKey; *p; p += 2, ++up) {
    *up = hctoi(p[0]) * 16 + hctoi(p[1]);  // hex string to byte array
  }

  // Init demo application
  demo_init();

  tunnel_loop_select();

}


void router_wifi_save_info(uint8_t *ssid, uint8_t *password)
{
    nvs_handle out_handle;
    char data[65];
    if (nvs_open("wifi_info", NVS_READWRITE, &out_handle) != ESP_OK)
    {
        return;
    }

    memset(data, 0x0, sizeof(data));
    strncpy(data, (char *)ssid, strlen((char *)ssid));
    if (nvs_set_str(out_handle, "ssid", data) != ESP_OK)
    {
        ESP_LOGI(TAG,"--set ssid fail");
    }

    memset(data, 0x0, sizeof(data));
    strncpy(data, (char *)password, strlen((char *)password));
    if (nvs_set_str(out_handle, "password", data) != ESP_OK)
    {
        ESP_LOGI(TAG,"--set password fail");
    }
    nvs_commit(out_handle);
    nvs_close(out_handle);
}

bool router_wifi_read()
{
    nvs_handle out_handle;
    size_t size = 0;
    nvs_open("wifi_info", NVS_READONLY, &out_handle);
    memset(&wifi_config, 0x0, sizeof(wifi_config));
    size = sizeof(wifi_config.sta.ssid);
    if(nvs_get_str(out_handle, "ssid", (char *)wifi_config.sta.ssid, &size) == ESP_OK)
    {
        if (size > 0)
        {
            size = sizeof(wifi_config.sta.password);
            if (nvs_get_str(out_handle, "password", (char *)wifi_config.sta.password, &size) == ESP_OK)
            {
                ESP_LOGI(TAG,"-- get ssid: %s", wifi_config.sta.ssid);
                ESP_LOGI(TAG,"-- get password: %s", wifi_config.sta.password);
                return 1;
            }
        }
    }
    nvs_close(out_handle);
    return 0;
}

void wifi_connet(void)
{
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    tcpip_adapter_init();
    ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    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());
}



/*
 * Main application entry
 */
void app_main()
{

  NABTO_LOG_INFO(("Nabto ESP32 demo starting up!!!"));

  NABTO_LOG_INFO(("Initializing nvs flash"));
    
  // Initialize NVS
  esp_err_t ret = nvs_flash_init();
  if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
      NABTO_LOG_INFO(("Erasing flash"));
      ESP_ERROR_CHECK(nvs_flash_erase());
      ret = nvs_flash_init();
  }
  ESP_ERROR_CHECK( ret );

  //initialize the camera
  NABTO_LOG_INFO(("Initializing camera"));
  
#if CAMERA_WIRING==ESP_EYE
    /* IO13, IO14 is designed for JTAG by default,
     * to use it as generalized input,
     * firstly declair it as pullup input */
    gpio_config_t conf;
    conf.mode = GPIO_MODE_INPUT;
    conf.pull_up_en = GPIO_PULLUP_ENABLE;
    conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    conf.intr_type = GPIO_INTR_DISABLE;
    conf.pin_bit_mask = 1LL << 13;
    gpio_config(&conf);
    conf.pin_bit_mask = 1LL << 14;
    gpio_config(&conf);
#endif

  ret = esp_camera_init(&camera_config);
  if (ret != ESP_OK) {
      NABTO_LOG_ERROR(("Camera Init Failed"));
  }

  // disable stdout buffering
  setvbuf(stdout, NULL, _IONBF, 0);
 


  /*
  NABTO_LOG_INFO(("Testing AES adapter"));
  if(!aes_cbc_test()) {
      NABTO_LOG_ERROR(("!!!!!WARNING... AES test not completed"));
  }

  NABTO_LOG_INFO(("Testing SHA adapter"));
  if(!hmac_sha256_test()) {
      NABTO_LOG_ERROR(("!!!!!WARNING... HMAC_SHA256 test not completed"));
  }
  */
  // create the event group to handle wifi events
  wifi_event_group = xEventGroupCreate();
#ifdef CONFIG_ESP_SMAERT_CONFIG
        if(router_wifi_read()==0){
                initialise_wifi();
        }
        else{
                wifi_connet();
        }
#else 
  // initialize the tcp stack
  tcpip_adapter_init();
  
  // initialize the wifi event handler
  ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
  
  // initialize the wifi stack in STAtion mode with config in RAM
  wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT();
  ESP_ERROR_CHECK(esp_wifi_init(&wifi_init_config));
  ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
  ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
  
  // configure the wifi connection and start the interface
  wifi_config_t wifi_config = {
    .sta = {
      .ssid = WIFI_SSID,
      .password = WIFI_PASS,
    },
  };
  ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
  ESP_ERROR_CHECK(esp_wifi_start());

#endif
  NABTO_LOG_INFO(("Connecting to %s\n", WIFI_SSID));
  // start the main task
  xTaskCreate(&main_task, "main_task", 8192, NULL, 5, NULL);

  // Go do something else here
}
  1. 修改后的app_smart_wifi.c
/* Esptouch example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/

#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_wpa2.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "tcpip_adapter.h"
#include "esp_smartconfig.h"

#include <time.h>
#include <sys/time.h>
#include "esp_sntp.h"
#include "sdkconfig.h"

extern void router_wifi_save_info(uint8_t *ssid, uint8_t *password);

/* FreeRTOS event group to signal when we are connected & ready to make a request */
static EventGroupHandle_t s_wifi_event_group;
extern EventGroupHandle_t wifi_event_group;
/* The event group allows multiple bits for each event,
   but we only care about one event - are we connected
   to the AP with an IP? */
static const int CONNECTED_BIT = BIT0;
static const int ESPTOUCH_DONE_BIT = BIT1;
static const char *TAG = "smartconfig_example";

static void smartconfig_example_task(void * parm);

uint8_t ssid[33] = { 0 };
uint8_t password[65] = { 0 };

static void event_handler(void* arg, esp_event_base_t event_base, 
                                int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        xTaskCreate(smartconfig_example_task, "smartconfig_example_task", 4096, NULL, 3, NULL);
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        //esp_wifi_connect();
        xEventGroupClearBits(s_wifi_event_group, CONNECTED_BIT);
        xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        xEventGroupSetBits(s_wifi_event_group, CONNECTED_BIT);
		//xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
    } else if (event_base == SC_EVENT && event_id == SC_EVENT_SCAN_DONE) {
        ESP_LOGI(TAG, "Scan done");
    } else if (event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL) {
        ESP_LOGI(TAG, "Found channel");
    } else if (event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD) {
        ESP_LOGI(TAG, "Got SSID and password");

        smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)event_data;
        wifi_config_t wifi_config;

        bzero(&wifi_config, sizeof(wifi_config_t));
        memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));
        memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));
        wifi_config.sta.bssid_set = evt->bssid_set;
        if (wifi_config.sta.bssid_set == true) {
            memcpy(wifi_config.sta.bssid, evt->bssid, sizeof(wifi_config.sta.bssid));
        }

        memcpy(ssid, evt->ssid, sizeof(evt->ssid));
        memcpy(password, evt->password, sizeof(evt->password));
        ESP_LOGI(TAG, "SSID:%s", ssid);
        ESP_LOGI(TAG, "PASSWORD:%s", password);
        // router_wifi_save_info(ssid,password);

        ESP_ERROR_CHECK( esp_wifi_disconnect() );
        ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
        ESP_ERROR_CHECK( esp_wifi_connect() );
    } else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE) {
        xEventGroupSetBits(s_wifi_event_group, ESPTOUCH_DONE_BIT);
    }
}
void time_sync_notification_cb(struct timeval *tv)
{
    ESP_LOGI(TAG, "SNTP OK ");
}
static void initialize_sntp(void)
{
    ESP_LOGI(TAG, "Initializing SNTP");
    sntp_setoperatingmode(SNTP_OPMODE_POLL);
    sntp_setservername(0, "pool.ntp.org");
    sntp_set_time_sync_notification_cb(time_sync_notification_cb);
#ifdef CONFIG_SNTP_TIME_SYNC_METHOD_SMOOTH
    sntp_set_sync_mode(SNTP_SYNC_MODE_SMOOTH);
#endif
    sntp_init();
}

static void smartconfig_example_task(void * parm)
{
    EventBits_t uxBits;
    ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH) );
    smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();
    ESP_ERROR_CHECK( esp_smartconfig_start(&cfg) );
    while (1) {
        uxBits = xEventGroupWaitBits(s_wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY); 
        if(uxBits & CONNECTED_BIT) {
            ESP_LOGI(TAG, "WiFi Connected to ap");
        }
        if(uxBits & ESPTOUCH_DONE_BIT) {
            ESP_LOGI(TAG, "smartconfig over");
            router_wifi_save_info(ssid,password);
#if CONFIG_ESP_SNTP_ENABLED
            {
            initialize_sntp();

            // wait for time to be set
            time_t now = 0;
            struct tm timeinfo = { 0 };
            int retry = 0;
            const int retry_count = 10;
            while (sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET && ++retry < retry_count) {
                //ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
                vTaskDelay(1000 / portTICK_PERIOD_MS);
            }
            
            time(&now);
            localtime_r(&now, &timeinfo);
            }
#endif
			//LOG_INFO(("connected1!\n"));
        	xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
            esp_smartconfig_stop();
            vTaskDelete(NULL);
        }
    }
}

void initialise_wifi(void)
{
    tcpip_adapter_init();
    s_wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );

    ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );
    ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL) );
    ESP_ERROR_CHECK( esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );

    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
    ESP_ERROR_CHECK( esp_wifi_start() );
}

六、总结

ESP32-S模组驱动摄像头ov2640,20MHz的时钟频率,图像格式为JPEG,分辨率VGA 640*480,帧率

平均15帧/s,上传速率为150KB/s~300KB/s(此数据是接入手机的热点,网络环境良好情况下更佳);

同时拍照图片时最大的分辨率为1600*1200;总体来说此次demo还是比较理想,同时还有很多优化的空

间留给码友们。
在这里插入图片描述
测试固件(smartconfig配网),点我下载

  • 8
    点赞
  • 11
    评论
  • 68
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值