网上的SPIFFS看了好多没看到具体的SPIFFS文件配置 找了半天给我找红温了

SPIFFS

它是ESP32的一个文件系统 VSCODE的IDF是自带的,但是需要配置,搞得不是很明白但是最后还是能跑了 以后再细研究.

用这个的目的主要是需要搞一个网页配网的功能,因为HTML的功能很少只用写个ssid和password就能行,所以ChatGPT给我写的是字符串格式的HTML

 const char *html_content = "<!DOCTYPE html>\
 <html>\
 <head><title>WiFi Setup</title></head>\     
 <body>\
 <h2>WiFi Configuration</h2>\
 <form method=\"POST\" action=\"/config\">\
   <label for=\"ssid\">SSID:</label><br>\
   <input type=\"text\" id=\"ssid\" name=\"ssid\" required><br><br>\
   <label for=\"password\">Password:</label><br>\
   <input type=\"password\" id=\"password\" name=\"password\" required><br><br>\
   <input type=\"submit\" value=\"Submit\">\
 </form>\
 </body>\
 </html>";

这么写肯定不利于维护啊,我以后想加个图片都费劲,所以就要给他搞成一个文件,SPIFFS就可以将这些静态文件写入ESP32的flash里
一开始查的是要配置镜像啥的 
后来一查发现 
如果是我自己创建好的一个.bin文件,  那就不用创建   
如果是我要再构建过程中,我才要创建镜像

所以我们是要创建这个镜像的   

这个镜像需要在CMakeLists里写的 我是写在main文件夹里注意路径名称             

spiffs_create_partition_image(spiffs ../Web FLASH_IN_PROJECT)

这个也是有讲究的 他是需要一个分区表

partitions1.csv

# Name,   Type,   SubType,   Offset,    Size,     Flags
nvs,      data,   nvs,       0x9000,    24K,
phy_init, data,   phy,       0xf000,    4K,
factory,  app,    factory,   0x10000,   1M,
spiffs,   data,   spiffs,    0x110000,  512K,

当然 这也是ChatGPT生成的 

这个spiffs一定要对着下面的这个分区表

然后我们要在menuconfig里面找到这个分区表的配置

配好之后我们要进行build啦  先build一下源代码
然后在终端上写 idf.py -p COM4 spiffs-flash  这个COM4是我当前的端口 Linux和MAC都不一样的 这个就是将镜像部署到固件里 (现在我发现不写也没事)

最后就烧录主程序就成拉 

一开始我连idf.py都打不了 后来才知道要去把IDF配置一下环境变量

差点忘记写源码了
 

#include <string.h>
#include <stdio.h>
#include "esp_log.h"
#include "esp_http_server.h"
#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_event.h"
#include "nvs_flash.h"
#include "esp_err.h"
#include "esp_spiffs.h"
esp_err_t init_spiffs() ;
void wifi_event_handler(void* event_handler_arg,esp_event_base_t event_base,int32_t event_id,void* event_data);
esp_err_t root_get_handler(httpd_req_t *req) ;
void start_sta_mode(const char *ssid, const char *password) ;
esp_err_t form_post_handler(httpd_req_t *req);
void create_httpd_server();
void start_ap_mode();
esp_err_t root_get_handler(httpd_req_t *req);
static const char *AP_TAG = "WIFI_AP";
static const char *STA_TAG = "WIFI_STA";
httpd_handle_t server = NULL;
 
esp_err_t init_spiffs() {
    esp_vfs_spiffs_conf_t conf = {
        .base_path = "/Web",
        .partition_label = NULL,
        .max_files = 5,
        .format_if_mount_failed = true
    };
    esp_err_t ret = esp_vfs_spiffs_register(&conf);
    if (ret != ESP_OK) {
        ESP_LOGE(AP_TAG, "Failed to mount or format SPIFFS");
        return ret;
    }
    return ESP_OK;
}
 
esp_err_t root_get_handler(httpd_req_t *req) {
    ESP_LOGI(AP_TAG, "Serving HTML page");
 
    // 打开 SPIFFS 中的 HTML 文件
    FILE* f = fopen("/Web/DistributeWifi.html", "r");
    if (f == NULL) {
        ESP_LOGE(AP_TAG, "Failed to open file for reading");
        return ESP_FAIL;
    }
 
    // 计算文件的大小
    fseek(f, 0, SEEK_END);
    size_t file_size = ftell(f);
    fseek(f, 0, SEEK_SET);
 
    // 读取文件内容并发送到客户端
    char* buf = malloc(file_size + 1);
    fread(buf, 1, file_size, f);
    fclose(f);
 
    buf[file_size] = '\0'; // 确保字符串结尾
 
    httpd_resp_send(req, buf, file_size);
    free(buf);
    return ESP_OK;
}
 
 
// WiFi事件处理函数
void wifi_event_handler(void* event_handler_arg,esp_event_base_t event_base,int32_t event_id,void* event_data)
{
   if(event_base == WIFI_EVENT)
   {
       switch(event_id)
       {
           case WIFI_EVENT_STA_START:
                esp_wifi_connect(); // 连接wifi
                break;
           case WIFI_EVENT_STA_CONNECTED:
                ESP_LOGI(STA_TAG,"esp32 connected to sta!");
                break;
            case WIFI_EVENT_STA_DISCONNECTED:
                ESP_LOGI(STA_TAG,"esp32 connect fail please retry~~~");
                vTaskDelay(1000 / portTICK_PERIOD_MS); // 1秒后重试
                esp_wifi_connect(); // 重试连接wifi
                break;
            default:
                break;
       }
   }
   else if(event_base == IP_EVENT){
        switch(event_id){
            case IP_EVENT_STA_GOT_IP:
            ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
                ESP_LOGI(STA_TAG, "STA Got IP: "IPSTR, IP2STR(&event->ip_info.ip));
                if(server != NULL)
                {
                    httpd_stop(server);
                    server = NULL;
                }
                create_httpd_server();
            
                break;
        }
   } 
 
}
 
void start_sta_mode(const char *ssid, const char *password) {
    esp_wifi_stop();
    esp_wifi_deinit();
    // 配置STA模式
     ESP_ERROR_CHECK(esp_netif_init());//初始化TCP / IP堆栈和esp-netif
    
    esp_netif_create_default_wifi_sta();
    
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
 
      // 检查是否已经注册了事件处理器,避免重复注册
    static bool handler_registered = false;
    if (!handler_registered) {
        ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, NULL));
        ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL, NULL));
        handler_registered = true;
    }
 
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = {0},
            .password = {0},
            .threshold = {
                .authmode = WIFI_AUTH_WPA2_PSK
            },
        },
    };
 
 
    // 设置WiFi配置
    strncpy((char *)wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid) - 1);
    strncpy((char *)wifi_config.sta.password, password, sizeof(wifi_config.sta.password) - 1);
 
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
    ESP_ERROR_CHECK(esp_wifi_start());
 
    ESP_LOGE(STA_TAG, "Connecting to WiFi SSID: %s", ssid);
 
}
 
// 处理POST请求,解析WiFi配置数据
esp_err_t form_post_handler(httpd_req_t *req) {
    char buf[512];  // 假设请求体最大长度为512字节
    int ret, remaining = req->content_len;
    memset(buf, 0, sizeof(buf));
    // 检查请求的内容长度
    if (remaining > sizeof(buf)) {
        ESP_LOGE(AP_TAG, "Content too long");
        return ESP_ERR_HTTPD_INVALID_REQ;
    }
 
    // 读取HTTP请求的内容
    ret = httpd_req_recv(req, buf, remaining);
    if (ret < 0) {
        ESP_LOGE(AP_TAG, "Failed to read the request body");
        return ESP_FAIL;
    }
 
    // 打印接收到的请求内容,方便调试
    ESP_LOGI(AP_TAG, "Received POST data: %s", buf);
    // 解析表单数据
    char ssid[32] = {0};
    char password[10] = {0};
 
    // 使用简单的字符串处理来解析数据
    char *ssid_start = strstr(buf, "ssid=");
    char *password_start = strstr(buf, "password=");
 
    if (ssid_start != NULL && password_start != NULL) {
        // 获取SSID值
        ssid_start += strlen("ssid="); // 跳过"ssid="部分
        char *ssid_end = strchr(ssid_start, '&');
        if (ssid_end != NULL) {
            strncpy(ssid, ssid_start, ssid_end - ssid_start);
        } else {
            strcpy(ssid, ssid_start);
        }
 
        // 获取Password值
        password_start += strlen("password="); // 跳过"password="部分
        char *password_end = strchr(password_start, '&');
        if (password_end != NULL) {
            strncpy(password, password_start, password_end - password_start);
        } else {
            strcpy(password, password_start);
        }
 
        ESP_LOGI(AP_TAG, "Received SSID: %s", ssid);
        ESP_LOGI(AP_TAG, "Received Password: %s", password);
   
        // 将接收到的SSID和Password用于WiFi连接
        start_sta_mode(ssid, password);
    } else {
        ESP_LOGE(AP_TAG, "Invalid data format");
        return ESP_ERR_HTTPD_INVALID_REQ;
    }
 
    // 回应客户端,告知配置完成
    const char *resp_str = "WiFi configuration complete! Rebooting...";
    httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN);
 
  
    return ESP_OK;
}
 
 
void create_httpd_server() {
    // 启动Web服务器
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();
    config.uri_match_fn = httpd_uri_match_wildcard;
    if (httpd_start(&server, &config) == ESP_OK) {
        httpd_uri_t root_uri = {
            .uri = "/",
            .method = HTTP_GET,
            .handler = root_get_handler,
            .user_ctx = NULL
        };
        httpd_register_uri_handler(server, &root_uri);
 
        httpd_uri_t post_uri = {
            .uri = "/config",
            .method = HTTP_POST,
            .handler = form_post_handler,
            .user_ctx = NULL
        };
        httpd_register_uri_handler(server, &post_uri);
    }
}
 
 
 
// 配置AP模式并启动Web服务器
void start_ap_mode() {
    ESP_ERROR_CHECK(esp_netif_init());//初始化TCP / IP堆栈和esp-netif
    ESP_ERROR_CHECK(esp_event_loop_create_default()); //创建默认event loop
    esp_netif_create_default_wifi_ap();
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
 
    wifi_config_t ap_config = {
        .ap = {
            .ssid = "ESP32",
            .ssid_len = strlen("ESP32"),
            .password = "123456789",
            .max_connection = 4,
            .authmode = WIFI_AUTH_WPA2_PSK
        },
    };
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &ap_config));
    ESP_ERROR_CHECK(esp_wifi_start());
 
    ESP_LOGI(AP_TAG, "AP mode started. SSID: ESP32_Config, password: 123456789");
 
    create_httpd_server();
}
 
void app_main() {
    ESP_LOGI(AP_TAG, "Starting WiFi Config AP mode...");
 
    // 初始化NVS(用于存储WiFi配置等)
    esp_err_t 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);
  ESP_ERROR_CHECK(init_spiffs());
    // 启动AP模式并启动Web服务器
    start_ap_mode();
}

全都糊在一个文件上 看懂可太费劲了