Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions application/edge_agent/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
set(main_requires
app_claw
app_config
app_ota
captive_dns
http_server
wifi_manager
Expand Down
3 changes: 3 additions & 0 deletions application/edge_agent/main/idf_component.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ dependencies:
app_config:
path: ../components/app_config

app_ota:
path: ../../../components/common/app_ota

cap_im_wechat:
path: ../../../components/claw_capabilities/cap_im_wechat
rules:
Expand Down
27 changes: 27 additions & 0 deletions application/edge_agent/main/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "esp_board_manager_includes.h"
#include "captive_dns.h"
#include "cmd_wifi.h"
#include "app_ota.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#if CONFIG_APP_CLAW_CAP_IM_WECHAT
Expand Down Expand Up @@ -325,7 +326,24 @@ void app_main(void)
init_timezone(app_config_get_timezone(s_config)); // no need to check error
ESP_ERROR_CHECK(esp_board_manager_init());
ESP_ERROR_CHECK(app_claw_ui_start());
#if CONFIG_APP_OTA_FS_ENABLE && CONFIG_APP_OTA_FS_TRY_SDCARD_AT_BOOT && CONFIG_APP_OTA_FS_RUN_AT_BOOT
{
esp_err_t ota_sd_err =
app_ota_fs_boot_flow_at(CONFIG_APP_OTA_FS_SDCARD_FIRMWARE_ABS_PATH);
if (ota_sd_err != ESP_OK) {
ESP_LOGW(TAG, "SD FS OTA: %s", esp_err_to_name(ota_sd_err));
}
}
#endif
ESP_ERROR_CHECK(init_fatfs());
#if CONFIG_APP_OTA_FS_ENABLE
{
esp_err_t ota_fs_err = app_ota_fs_boot_flow();
if (ota_fs_err != ESP_OK) {
ESP_LOGW(TAG, "FS OTA: %s", esp_err_to_name(ota_fs_err));
}
}
#endif
ESP_ERROR_CHECK(wifi_manager_init());
ESP_ERROR_CHECK(http_server_init(&(http_server_config_t) {
.storage_base_path = app_fatfs_base_path,
Expand Down Expand Up @@ -378,6 +396,15 @@ void app_main(void)
status.ap_ip);
}

{
wifi_manager_status_t wm_ota = {0};
wifi_manager_get_status(&wm_ota);
esp_err_t ota_err = app_ota_http_boot_flow(wm_ota.sta_connected);
if (ota_err != ESP_OK) {
ESP_LOGW(TAG, "OTA bootstrap: %s", esp_err_to_name(ota_err));
}
}

ESP_ERROR_CHECK(app_claw_init_storage_paths(s_claw_paths));
ESP_ERROR_CHECK(app_claw_start(s_claw_config, s_claw_paths));
#if CONFIG_APP_CLAW_CAP_IM_LOCAL
Expand Down
9 changes: 6 additions & 3 deletions application/edge_agent/partitions_8MB.csv
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
nvs, data, nvs, 0x9000, 0x6000
otadata, data, ota, 0xF000, 0x2000
phy_init, data, phy, 0x11000, 0x1000
ota_0, app, ota_0, , 3M
emote, data, spiffs, , 3M
storage, data, fat, , 1500K
# OTA slots slightly larger than 2560K for edge_agent ~0x288210 (tools/ota_sdcard_hil builds fat claw).
# Keep total app+emote+storage = 8064K like older layout; shrink emote when HIL disables APP_CLAW_ENABLE_EMOTE (see ota_sdcard_hil.py overlay).
ota_0, app, ota_0, , 2624K
ota_1, app, ota_1, , 2624K
emote, data, spiffs, , 1792K
storage, data, fat, , 1024K
2 changes: 2 additions & 0 deletions application/edge_agent/sdkconfig.defaults
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# This file was generated using idf.py save-defconfig. It can be edited manually.
# Espressif IoT Development Framework (ESP-IDF) 5.5.1 Project Minimal Configuration
#
# Match on-module flash and partitions_8MB.csv (overrides board_manager 2MB default for HIL / fresh sdkconfig)
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_8MB.csv"
CONFIG_HTTPD_WS_SUPPORT=y
Expand Down
41 changes: 33 additions & 8 deletions components/common/app_claw/app_claw_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,7 @@ esp_err_t app_claw_cli_start(void)
{
esp_console_repl_t *repl = NULL;
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
esp_err_t err = ESP_OK;

ESP_LOGI(TAG, "Starting console REPL");

Expand All @@ -749,18 +750,22 @@ esp_err_t app_claw_cli_start(void)

#if CONFIG_ESP_CONSOLE_UART_DEFAULT || CONFIG_ESP_CONSOLE_UART_CUSTOM
esp_console_dev_uart_config_t hw_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_console_new_repl_uart(&hw_config, &repl_config, &repl));
err = esp_console_new_repl_uart(&hw_config, &repl_config, &repl);
#elif CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
esp_console_dev_usb_serial_jtag_config_t hw_config =
ESP_CONSOLE_DEV_USB_SERIAL_JTAG_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_console_new_repl_usb_serial_jtag(&hw_config, &repl_config, &repl));
err = esp_console_new_repl_usb_serial_jtag(&hw_config, &repl_config, &repl);
#elif CONFIG_ESP_CONSOLE_USB_CDC
esp_console_dev_usb_cdc_config_t hw_config = ESP_CONSOLE_DEV_CDC_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_console_new_repl_usb_cdc(&hw_config, &repl_config, &repl));
err = esp_console_new_repl_usb_cdc(&hw_config, &repl_config, &repl);
#else
ESP_LOGE(TAG, "No supported console backend is enabled");
return ESP_ERR_NOT_SUPPORTED;
#endif
if (err != ESP_OK) {
ESP_LOGE(TAG, "Create REPL failed: %s", esp_err_to_name(err));
return err;
}

esp_console_register_help_command();
register_cap_cli_commands();
Expand All @@ -771,7 +776,11 @@ esp_err_t app_claw_cli_start(void)
.help = "Submit a multi-turn prompt using the current session: ask <prompt>",
.func = cmd_ask,
};
ESP_ERROR_CHECK(esp_console_cmd_register(&ask_cmd));
err = esp_console_cmd_register(&ask_cmd);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Register 'ask' failed: %s", esp_err_to_name(err));
return err;
}
}

{
Expand All @@ -780,7 +789,11 @@ esp_err_t app_claw_cli_start(void)
.help = "Submit a single-turn prompt without session history: ask_once <prompt>",
.func = cmd_ask_once,
};
ESP_ERROR_CHECK(esp_console_cmd_register(&ask_once_cmd));
err = esp_console_cmd_register(&ask_once_cmd);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Register 'ask_once' failed: %s", esp_err_to_name(err));
return err;
}
}

{
Expand All @@ -789,7 +802,11 @@ esp_err_t app_claw_cli_start(void)
.help = "Show or switch the current session: session [id]",
.func = cmd_session,
};
ESP_ERROR_CHECK(esp_console_cmd_register(&session_cmd));
err = esp_console_cmd_register(&session_cmd);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Register 'session' failed: %s", esp_err_to_name(err));
return err;
}
}

{
Expand All @@ -798,7 +815,11 @@ esp_err_t app_claw_cli_start(void)
.help = "cap operations: cap <list|call|groups|enable|disable|unload|load> ...",
.func = cmd_cap,
};
ESP_ERROR_CHECK(esp_console_cmd_register(&cap_cmd));
err = esp_console_cmd_register(&cap_cmd);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Register 'cap' failed: %s", esp_err_to_name(err));
return err;
}
}

{
Expand All @@ -807,7 +828,11 @@ esp_err_t app_claw_cli_start(void)
.help = "Automation operations: auto <reload|rules|rule|add_rule|update_rule|delete_rule|last|emit_message|emit_trigger> ...",
.func = cmd_auto,
};
ESP_ERROR_CHECK(esp_console_cmd_register(&auto_cmd));
err = esp_console_cmd_register(&auto_cmd);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Register 'auto' failed: %s", esp_err_to_name(err));
return err;
}
}

printf("Type 'help', 'auto rules', 'auto last', or 'auto emit_message qq_gateway qq 123 hello'\n");
Expand Down
8 changes: 8 additions & 0 deletions components/common/app_ota/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
idf_component_register(
SRCS
"app_ota.c"
INCLUDE_DIRS
"include"
REQUIRES
esp_ota_service
)
94 changes: 94 additions & 0 deletions components/common/app_ota/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
menu "App OTA (esp_ota_service)"

menu "HTTP OTA bootstrap"

config APP_OTA_HTTP_ENABLE
bool "Enable optional HTTP firmware OTA bootstrap"
default n
help
When enabled and manifest/firmware URLs are non-empty (menuconfig below),
the device runs one HTTP OTA check after Wi‑Fi STA is connected during boot.

if APP_OTA_HTTP_ENABLE

config APP_OTA_HTTP_RUN_AT_BOOT
bool "Run HTTP OTA check once at startup (after STA online)"
default y

config APP_OTA_HTTP_MANIFEST_URL
string "Firmware manifest JSON URL (http/https)"
default ""
help
JSON manifest consumed by esp_ota_service_checker_manifest (version, optional sha256, size).

config APP_OTA_HTTP_FIRMWARE_URL
string "Firmware binary URL (must match manifest server)"
default ""
help
Absolute URL for the downloadable app image (paired with APP_OTA_HTTP_MANIFEST_URL).

config APP_OTA_HTTP_CHUNK_TIMEOUT_MS
int "HTTP read timeout per chunk (milliseconds)"
default 30000
range 3000 120000

endif # APP_OTA_HTTP_ENABLE

endmenu

menu "Filesystem OTA bootstrap"

config APP_OTA_FS_ENABLE
bool "Enable optional filesystem (VFS) app OTA bootstrap"
default y
help
After SPI flash FAT mounts (typically /fatfs), read a staged edge_agent.bin from an absolute path
using esp_ota_service_source_fs. Runs **before Wi-Fi**. File must expose a higher semver than running
image when APP_OTA_FS_REQUIRE_NEWER_SEMVER=y.

if APP_OTA_FS_ENABLE

config APP_OTA_FS_RUN_AT_BOOT
bool "Run FS OTA when candidate file exists at boot"
default y

config APP_OTA_FS_FIRMWARE_ABS_PATH
string "Absolute filesystem path (VFS fopen) for app binary"
default "/fatfs/ota/firmware.bin"
help
Typical layout: mkdir /fatfs/ota via host mount and drop edge_agent.bin renamed to firmware.bin.

config APP_OTA_FS_TRY_SDCARD_AT_BOOT
bool "Before SPI flash FAT, try app OTA from SD (board_manager fs_sdcard)"
default n
help
After esp_board_manager_init(), if the board exposes fs_sdcard (usually mounted at /sdcard),
probe APP_OTA_FS_SDCARD_FIRMWARE_ABS_PATH for a newer app image.
Matches esp_ota_service tools/sdcard_writer output name firmware.bin.
Use together with tools/ota_sdcard_hil.py and ota_fs_flash_sdcard.py from ADF.

config APP_OTA_FS_SDCARD_FIRMWARE_ABS_PATH
string "Absolute path on SD mount for app binary"
default "/sdcard/firmware.bin"
depends on APP_OTA_FS_TRY_SDCARD_AT_BOOT
help
Default matches sdcard_writer (components/esp_ota_service/tools/sdcard_writer).

config APP_OTA_FS_READ_BUF_BYTES
int "Read buffer chunk size passed to filesystem source"
default 4096
range 512 8192

config APP_OTA_FS_REQUIRE_NEWER_SEMVER
bool "Reject candidate whose esp_app_desc_t version is not strictly higher"
default y

config APP_OTA_FS_CHECK_PROJECT_NAME
bool "Reject candidate when esp_app_desc_t project_name differs from running firmware"
default y

endif # APP_OTA_FS_ENABLE

endmenu

endmenu
Loading