一、简介
将ESP32——WEB服务程序测试项目移植到一个现有项目中,现有项目包括基于固定IP的WIFI连接、OTA升级、Websocket等功能。
二、移植
2.1 参考restful_server项目下分区表文件partitions_example.csv修改项目分区
因模块采用ESP32-WROVER-E(4MB),故分区表内容修改如下(后发现问题,下面会提到)。
# Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x4000 otadata, data, ota, 0xd000, 0x2000 phy_init, data, phy, 0xf000, 0x1000 ota_0, app, ota_0, 0x10000, 1M ota_1, app, ota_1, , 1M www, data, spiffs, , 1M
并修改配置如下图项。
2.2 复制前端代码
将restful_server项目front目录及其下所有内容复制到现有项目根目录下。
2.3 复制rest_server.c文件到现有项目main目录下
并在main目录下CMakeLists.txt文件中添加 "rest_server.c"
idf_component_register(SRCS "ota.c" "wifi.c" "websocket.c" "rest_server.c" "main.c"
INCLUDE_DIRS "."
# Embed the server root certificate into the final binary
EMBED_TXTFILES ${project_dir}/server_certs/ca_cert.pem)
2.4 复制esp_rest_main.c文件中如下内容到现有项目main.c文件中
//此处略去了必要的头文件和变量定义
esp_err_t start_rest_server(const char *base_path);
#if CONFIG_EXAMPLE_WEB_DEPLOY_SF
esp_err_t init_fs(void)
{
esp_vfs_spiffs_conf_t conf = {
.base_path = CONFIG_EXAMPLE_WEB_MOUNT_POINT,
.partition_label = NULL,
.max_files = 5,
.format_if_mount_failed = false
};
esp_err_t ret = esp_vfs_spiffs_register(&conf);
if (ret != ESP_OK) {
if (ret == ESP_FAIL) {
ESP_LOGE(TAG, "Failed to mount or format filesystem");
} else if (ret == ESP_ERR_NOT_FOUND) {
ESP_LOGE(TAG, "Failed to find SPIFFS partition");
} else {
ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret));
}
return ESP_FAIL;
}
size_t total = 0, used = 0;
ret = esp_spiffs_info(NULL, &total, &used);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s)", esp_err_to_name(ret));
} else {
ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used);
}
return ESP_OK;
}
#endif
void app_main(void)
{
esp_err_t err = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
err = nvs_flash_init();
}
ESP_ERROR_CHECK( err );
IO_Init();
ip_set();
wifi_init_sta();
xTaskCreate(&advanced_ota_example_task, "advanced_ota_example_task", 1024 * 8, service_ip, 5, NULL);
websocket_app_start(service_ip);
ESP_ERROR_CHECK(init_fs());
ESP_ERROR_CHECK(start_rest_server(CONFIG_EXAMPLE_WEB_MOUNT_POINT));
// tasklist_show();
while (1)
{
LED_Run();
Key_Read();
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}
2.5 复制main目录下Kconfig.projbuild中如下内容到现有项目对应文件中
注:项目Kconfig.projbuild中原来的内容因实际未用到,故删除了。
menu "Example Configuration"
config EXAMPLE_MDNS_HOST_NAME
string "mDNS Host Name"
default "esp-home"
help
Specify the domain name used in the mDNS service.
Note that webpage also take it as a part of URL where it will send GET/POST requests to.
choice EXAMPLE_WEB_DEPLOY_MODE
prompt "Website deploy mode"
default EXAMPLE_WEB_DEPLOY_SEMIHOST
help
Select website deploy mode.
You can deploy website to host, and ESP32 will retrieve them in a semihost way (JTAG is needed).
You can deploy website to SD card or SPI flash, and ESP32 will retrieve them via SDIO/SPI interface.
Detailed operation steps are listed in the example README file.
config EXAMPLE_WEB_DEPLOY_SEMIHOST
bool "Deploy website to host (JTAG is needed)"
help
Deploy website to host.
It is recommended to choose this mode during developing.
config EXAMPLE_WEB_DEPLOY_SD
depends on IDF_TARGET_ESP32
bool "Deploy website to SD card"
help
Deploy website to SD card.
Choose this production mode if the size of website is too large (bigger than 2MB).
config EXAMPLE_WEB_DEPLOY_SF
bool "Deploy website to SPI Nor Flash"
help
Deploy website to SPI Nor Flash.
Choose this production mode if the size of website is small (less than 2MB).
endchoice
if EXAMPLE_WEB_DEPLOY_SEMIHOST
config EXAMPLE_HOST_PATH_TO_MOUNT
string "Host path to mount (e.g. absolute path to web dist directory)"
default "PATH-TO-WEB-DIST_DIR"
help
When using semihost in ESP32, you should specify the host path which will be mounted to VFS.
Note that only absolute path is acceptable.
endif
config EXAMPLE_WEB_MOUNT_POINT
string "Website mount point in VFS"
default "/www"
help
Specify the mount point in VFS.
endmenu
保存后,重新打开配置出现如下选项,并做如下设置
2.6 复制main目录下CMakeLists.txt中如下内容到现有项目对应文件中
if(CONFIG_EXAMPLE_WEB_DEPLOY_SF)
set(WEB_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../front/web-demo")
if(EXISTS ${WEB_SRC_DIR}/dist)
spiffs_create_partition_image(www ${WEB_SRC_DIR}/dist FLASH_IN_PROJECT)
else()
message(FATAL_ERROR "${WEB_SRC_DIR}/dist doesn't exit. Please run 'npm run build' in ${WEB_SRC_DIR}")
endif()
endif()
2.7 复制根目录下Makefilet中如下内容到现有项目对应文件中
ifdef CONFIG_EXAMPLE_WEB_DEPLOY_SF
WEB_SRC_DIR = $(shell pwd)/front/web-demo
ifneq ($(wildcard $(WEB_SRC_DIR)/dist/.*),)
SPIFFS_IMAGE_FLASH_IN_PROJECT := 1
$(eval $(call spiffs_create_partition_image,www,$(WEB_SRC_DIR)/dist))
else
$(error $(WEB_SRC_DIR)/dist doesn't exist. Please run 'npm run build' in $(WEB_SRC_DIR))
endif
endif
2.8 修改配置如下部分:
此处文件名长度如设置太小,编译项目时会报错(前端部分生成的文件名比较长)。
三、调试
项目修改完成后,编译出现下图错误
后来发现是因为前端生成的dist目录内容占用存储空间超过1M,调整分区大小后正常。