# ESP OTA Service

[English]

## 简介

OTA Service 是 ESP Service 的一个子类，实现了一套模块化、可扩展的空中固件升级流水线。它把升级过程拆成数据源、写入目标、版本检查器和完整性校验器四个独立的抽象层，因此 HTTP/HTTPS、文件系统、BLE 等传输方式可以和应用分区、数据分区、Bootloader 等写入目标任意组合，无需修改服务主体代码。

## 功能清单

- 多数据源下载：HTTP/HTTPS、本地文件系统、遵循官方 ESP BLE OTA APP 协议的 BLE GATT 外设（可选），也可以通过 `esp_ota_service_source_t` 接口接入 UART、SPI 等自定义传输

- 多目标写入：应用分区、原始数据分区、Bootloader（可选），也可以通过 `esp_ota_service_target_t` 接入自定义写入目标

- 下载前版本检查：应用镜像头、语义版本头、JSON 清单三种内置检查器，已是最新版本的条目自动跳过

- 流式完整性校验：SHA-256 和 MD5 内置校验器，也可以通过 `esp_ota_service_verifier_t` 接入签名或 CRC 方案

- 基于 NVS 的断点续传：每若干 KB 保存一次下载偏移，故障或重启后从断点恢复

- 回滚支持：`esp_ota_service_confirm_update()` / `esp_ota_service_rollback()` 及待验证状态检测（需要 `CONFIG_OTA_ENABLE_ROLLBACK`）

- 下载中可暂停/恢复：运行中的会话可直接调用 `esp_service_pause()` / `esp_service_resume()`

- 事件总线覆盖会话开始、版本检查、条目开始/进度/结束和会话结束共 6 种类型，不强制规定重启策略

## 技术拆解

### 流水线抽象

每个 `esp_ota_upgrade_item_t` 描述一次分区升级，由 `source`、`target` 两个必填接口和 `checker`、`verifier` 两个可选接口组成；四类接口都是函数指针结构体，实现后即可自由组合。服务通过 `esp_ota_service_set_upgrade_list()` 接管列表中每个组件的所有权，不应由调用方再直接调用它们的 `destroy()`。

            flowchart TD
        Start([条目开始]) --> Chk{checker?}
        Chk -- 无 --> Open[source.open]
        Chk -- 有 --> Check[checker.check]
        Check -- 非更新版本 --> Skip([跳过])
        Check -- 有新版本 --> Open
        Open --> Vb{verifier?}
        Vb -- 无 --> TOpen[target.open]
        Vb -- 有 --> VBegin[verifier.verify_begin]
        VBegin -- 拒绝 --> Skip
        VBegin -- 通过 --> TOpen
        TOpen --> Loop{source.read 循环}
        Loop --> Update[verifier.verify_update]
        Update -- 校验失败 --> Fail([中止])
        Update -- 通过 --> Write[target.write] --> Loop
        Loop -- EOF --> Vf{verifier?}
        Vf -- 无 --> Commit[target.commit]
        Vf -- 有 --> VFinish[verifier.verify_finish]
        VFinish -- 校验失败 --> Fail
        VFinish -- 通过 --> Commit

调用 `esp_service_start()` 后立即返回，工作任务在后台运行并通过事件上报进度，不会阻塞调用方任务。

    #include "esp_ota_service_default.h"  /* 汇总内置 source/target/checker/verifier 头文件 */

    esp_ota_service_t *svc = NULL;
    esp_ota_service_create(&(esp_ota_service_cfg_t)ESP_OTA_SERVICE_CFG_DEFAULT(), &svc);

    esp_ota_upgrade_item_t item = {
        .uri      = "http://example.com/firmware.bin",
        .source   = http_source,
        .target   = app_target,
        .checker  = manifest_checker,
        .verifier = sha256_verifier,
    };
    esp_ota_service_set_upgrade_list(svc, &item, 1);

    esp_service_event_subscribe((esp_service_t *)svc, &sub);
    esp_service_start((esp_service_t *)svc);

重要

调用 `esp_ota_service_set_upgrade_list()` 之后，列表中每个 `source`、`target`、`checker`、`verifier` 的所有权都转移给服务，即使调用失败也是如此；不要再直接调用它们的 `destroy()`，`esp_ota_service_destroy()` 会负责统一释放。

### 选择合适的组合

常见场景对应的组件选择：HTTP OTA 配合版本清单检查和 SHA-256 校验时，使用 `esp_ota_service_source_http_create()` + `esp_ota_service_checker_manifest_create()` + `esp_ota_service_verifier_sha256_create()` + `esp_ota_service_target_app_create()`；仅需版本检查而不做流式校验时可以省去 `verifier`；SD 卡或 U 盘部署使用 `esp_ota_service_source_fs_create()` 搭配同样的应用目标；数据分区升级则改用 `esp_ota_service_checker_data_version_create()` 和 `esp_ota_service_target_data_create()`。多分区批量升级时，一次会话可以为应用分区、数据分区分别配置独立的条目，共用同一个事件流。

### 事件与进度

通过 `esp_service_event_subscribe()` 订阅后，每次回调收到的 `adf_event_t` 中 `payload` 指向 `esp_ota_service_event_t`，需要先读取 `id` 字段，再访问对应的联合体分支：`ESP_OTA_SERVICE_EVT_ITEM_VER_CHECK` 报告版本检查结果，`ESP_OTA_SERVICE_EVT_ITEM_PROGRESS` 约每秒更新一次下载字节数，`ESP_OTA_SERVICE_EVT_ITEM_END` 携带单个分区的成功/跳过/失败结果，`ESP_OTA_SERVICE_EVT_SESSION_END` 携带整个会话的汇总统计。调用方也可以直接用 `esp_ota_service_get_progress()` 轮询当前条目的下载进度百分比。

### 断点续传与回滚

启用 `CONFIG_OTA_ENABLE_RESUME`（默认开启）后，服务每隔固定字节数把下载偏移保存到 NVS；对没有实现 `seek()` 的数据源（如 BLE）或没有 `set_write_offset()` 的目标（数据分区、Bootloader），必须把对应条目的 `resumable` 设为 `false`，否则 `esp_ota_service_set_upgrade_list()` 会返回 `ESP_ERR_NOT_SUPPORTED`。启用 `CONFIG_OTA_ENABLE_ROLLBACK` 后，新固件启动后应先用 `esp_ota_service_is_pending_verify()` 检查是否处于待验证状态，自测通过后调用 `esp_ota_service_confirm_update()` 取消回滚计时器；否则每次重启都会触发自动回滚。

## 应用示例

- `examples/ota_http/` 演示 HTTP + 清单版本检查 + SHA-256 校验 + 断点续传

- `examples/ota_fs/` 演示 SD 卡/U 盘离线部署与多分区批量升级

- `examples/ota_ble/` 演示无 Wi-Fi 场景下的 BLE GATT 固件推送

## FAQ

Q1：resumable 设为 true 但仍返回 ESP_ERR_NOT_SUPPORTED，是什么原因？

数据源没有实现 `seek()`，或写入目标没有实现 `set_write_offset()`。数据分区和 Bootloader 目标在 `open()` 时会整片擦除，天然不支持续传；目前只有应用分区目标，以及支持随机访问 `seek` 的数据源才能续传。

Q2：升级失败后要如何避免设备变砖？

应用分区升级依赖 A/B 双镜像机制，失败时可以回退到旧分区；但 Bootloader OTA（`CONFIG_OTA_ENABLE_BOOTLOADER_OTA`）通过暂存分区写入，没有原子性保证，拷贝过程中断电存在变砖风险，量产前需要额外评估并做好回退预案。

## API 参考

### Header File

- components/esp_ota_service/include/esp_ota_service.h

### Functions

esp_err_t esp_ota_service_create(const esp_ota_service_cfg_t *cfg, esp_ota_service_t **out_svc)

  Create and initialise an OTA service instance.

          Allocates the service object, initialises the ADF service base, and
          creates the internal stop semaphore.  No network or flash operations occur.

  参数:

    - cfg – [in] Service configuration

    - out_svc – [out] Receives the created service handle

  返回:

    - ESP_OK On success

    - ESP_ERR_NO_MEM On allocation failure (service object or stop semaphore)

    - ESP_ERR_INVALID_ARG If cfg or out_svc is NULL, or write_chunk_size / stop_timeout_ms in cfg is invalid

    - Other Error code returned by esp_service_init() on ADF base initialisation failure

esp_err_t esp_ota_service_destroy(esp_ota_service_t *svc)

  Destroy an OTA service instance and free all resources.

          Calls esp_service_stop() to abort any in-progress upgrade, destroys the
          source/target/verifier/checker instances in the current upgrade list, deinits the
          ADF service base, and frees the service object.

  参数:

    svc – [in] Service handle obtained from esp_ota_service_create()

  返回:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If svc is NULL

esp_err_t esp_ota_service_set_upgrade_list(esp_ota_service_t *svc, const esp_ota_upgrade_item_t *list, int count)

  Set (or replace) the upgrade item list.

          The service makes a shallow copy of the list array and deep-copies the
          @c uri and @c partition_label strings. The @c source / @c target /
          @c verifier / @c checker pointers inside each item are owned by the
          service from the moment this function is ENTERED — the caller must not
          destroy them afterwards, even if the call fails. If validation or
          allocation fails, the service destroys every item's source/target/
          verifier/checker before returning.

          If a previous list exists, its source/target/verifier/checker destroy()
          functions are called before the list is replaced. Any saved NVS resume
          records are cleared at this point, because the new list may not match
          the previous item layout.

          Allowed only while the service is in INITIALIZED or PAUSED. Not allowed
          in RUNNING while the worker is downloading.

  参数:

    - svc – [in] Service instance

    - list – [in] Array of upgrade item descriptors

    - count – [in] Number of items in the array (must be > 0)

  返回:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If svc/list is NULL, count <= 0, item uri/source/target is NULL, or a uri exceeds the resume store’s capacity (255 chars)

    - ESP_ERR_INVALID_STATE If called while the service is neither INITIALIZED nor PAUSED

    - ESP_ERR_NOT_SUPPORTED If item.resumable=true but the source has no seek() or the target has no set_write_offset() (data / bootloader targets cannot resume)

    - ESP_ERR_NO_MEM If the list or deep-copied strings cannot be allocated

esp_err_t esp_ota_service_check_update(esp_ota_service_t *svc, int item_index, esp_ota_service_update_info_t *out_info)

  Check if a newer firmware is available without performing OTA.

          Calls @c checker->check() on the item at @a item_index. No flash write.
          Requires @c esp_ota_service_set_upgrade_list() first, and the item must have a
          non-NULL @c checker.

  参数:

    - svc – [in] Service instance

    - item_index – [in] Index into the upgrade list (0-based)

    - out_info – [out] Receives update information

  返回:

    - ESP_OK On success (inspect `out_info->upgrade_available`)

    - ESP_ERR_INVALID_ARG If svc or out_info is NULL, item_index is invalid, upgrade list is unset, or item’s `checker` is NULL

    - Other Error from `checker->check()`

esp_err_t esp_ota_service_get_progress(const esp_ota_service_t *svc, uint32_t *out_written, uint32_t *out_total, int32_t *out_percent)

  Query current download progress.

          Values reflect the item currently being processed.

  参数:

    - svc – [in] Service instance

    - out_written – [out] Bytes written so far for the current item; NULL to omit

    - out_total – [out] Total bytes for the current item (UINT32_MAX if unknown); NULL to omit

    - out_percent – [out] Approximate progress 0–100 for the current item from out_written / out_total; -1 if total size is unknown; NULL to omit

  返回:

    - ESP_OK On success

    - ESP_ERR_INVALID_ARG If svc is NULL

esp_err_t esp_ota_service_confirm_update(void)

  Confirm that the currently running OTA image is valid.

          Call this after verifying that the new firmware works correctly.
          Cancels the automatic rollback that would occur on next reboot.
          Operates only on the currently running application partition (no slot
          or item index is passed); IDF must report ESP_OTA_IMG_PENDING_VERIFY there.
          Only effective when CONFIG_OTA_ENABLE_ROLLBACK is enabled.

  返回:

    - ESP_OK On success (rollback cancelled)

    - ESP_ERR_INVALID_STATE If the running image is not pending verification

    - ESP_ERR_NOT_SUPPORTED If CONFIG_OTA_ENABLE_ROLLBACK is disabled

    - Other Error code returned by esp_ota_mark_app_valid_cancel_rollback() on failure

esp_err_t esp_ota_service_rollback(void)

  Mark current image as invalid and reboot to the previous firmware.

  备注

  Does not return on success — the device reboots.

  返回:

    - ESP_ERR_NOT_SUPPORTED If CONFIG_OTA_ENABLE_ROLLBACK is disabled

    - Other Error code returned by esp_ota_mark_app_invalid_rollback_and_reboot() on failure

esp_err_t esp_ota_service_is_pending_verify(bool *out_pending)

  Check whether the currently running image is in ESP_OTA_IMG_PENDING_VERIFY.

          Safe to call at any time from any task.  Does not depend on an OTA service handle
          and does not allocate.  Intended to be called early in @c app_main() so the
          application can run its self-test and resolve the state with
          @c esp_ota_service_confirm_update() or @c esp_ota_service_rollback() before any
          subsequent reset would otherwise trigger bootloader auto-rollback.

  参数:

    out_pending – [out] Receives `true` when the running image needs confirmation.

  返回:

    - ESP_OK On success (inspect `*out_pending`)

    - ESP_ERR_INVALID_ARG If out_pending is NULL

    - ESP_ERR_INVALID_STATE If esp_ota_get_running_partition() returned NULL

    - ESP_ERR_NOT_SUPPORTED If CONFIG_OTA_ENABLE_ROLLBACK is disabled; `*out_pending` is set to `false` for caller convenience

    - Other Error returned by esp_ota_get_state_partition() on failure

### Structures

struct esp_ota_service_event_t

  OTA service event payload.

          Published on the service-bound Event Hub; subscribe with
          esp_service_event_subscribe((esp_service_t *)svc, &info).  The handler's
          @c adf_event_t::payload is a heap @c esp_ota_service_event_t owned by the hub (including
          a deep copy of @c item_label); both stay valid until the hub releases it.

          @c item_index == -1 marks a session-scoped event (@c SESSION_BEGIN, and
          @c SESSION_END on normal completion); when @c session_end.aborted is true,
          @c item_index carries the in-progress list index.

          Inspect @c id first, then read the matching union branch (reading the wrong
          branch is undefined):

           - SESSION_BEGIN  : no union field
           - ITEM_VER_CHECK : @c ver_check, @c error (checker outcome)
           - ITEM_BEGIN     : no union field
           - ITEM_PROGRESS  : @c progress
           - ITEM_END       : @c item_end, @c error
           - SESSION_END    : @c session_end, @c error

  Public Members

  esp_ota_service_event_id_t id

    Event identifier

  esp_err_t error

    Semantics depend on `id` (e.g. `ITEM_VER_CHECK` checker result; `ITEM_PROGRESS` is `ESP_OK`; `ITEM_END` carries skip / fail / OK).

  int item_index

    Upgrade-list index; `-1` when the event is session-scoped (`SESSION_BEGIN`, and `SESSION_END` on normal completion).

  const char *item_label

    Partition label for that item; deep copy in payload. May be `NULL`.

  uint32_t bytes_written

    Bytes written so far for the current item.

  uint32_t total_bytes

    Total bytes for the current item (UINT32_MAX if unknown).

  struct esp_ota_service_event_t::[anonymous]::[anonymous] progress

    ESP_OTA_SERVICE_EVT_ITEM_PROGRESS

  esp_ota_service_item_status_t status

    OK / SKIPPED / FAILED

  esp_ota_service_item_end_reason_t reason

    `ESP_OTA_SERVICE_ITEM_END_REASON_NONE` when `status` is OK; otherwise coarse class

  struct esp_ota_service_event_t::[anonymous]::[anonymous] item_end

    ESP_OTA_SERVICE_EVT_ITEM_END

  uint16_t success_count

    Items with ESP_OTA_SERVICE_ITEM_STATUS_OK

  uint16_t failed_count

    Items with ESP_OTA_SERVICE_ITEM_STATUS_FAILED

  uint16_t skipped_count

    Items with ESP_OTA_SERVICE_ITEM_STATUS_SKIPPED

  bool aborted

    True when stopped by esp_service_stop()

  struct esp_ota_service_event_t::[anonymous]::[anonymous] session_end

    ESP_OTA_SERVICE_EVT_SESSION_END

  uint32_t image_size

    Incoming image size, or UINT32_MAX if unknown.

  bool upgrade_available

    If `error` != ESP_OK: always false (ignore for outcome). If `error` == ESP_OK: true = will upgrade, false = not newer.

  struct esp_ota_service_event_t::[anonymous]::[anonymous] ver_check

    `ESP_OTA_SERVICE_EVT_ITEM_VER_CHECK`

struct esp_ota_upgrade_item

  Descriptor for a single partition upgrade.

          @c uri and @c partition_label are deep-copied, so stack-allocated items
          are safe.  Ownership of @c source / @c target / @c verifier / @c checker
          transfers to the service when @c esp_ota_service_set_upgrade_list() is entered:
          their @c destroy() runs when the list is replaced, the service is destroyed,
          or validation fails (set @c destroy = NULL to opt out).

          When @c checker is non-NULL, the worker runs a header-only version check
          before downloading and emits @c ESP_OTA_SERVICE_EVT_ITEM_VER_CHECK.  If the check
          reports @c !upgrade_available with @c error == ESP_OK, the item skips
          @c ITEM_BEGIN / @c ITEM_END.  The worker never loops on a single item.

  Public Members

  const char *uri

    Passed to source->open(). Deep-copied. Required.

  const char *partition_label

    Passed to target->open(). Deep-copied. NULL selects the next OTA app slot. For `esp_ota_service_target_data_create()`, a typical image prefixes the payload with a 4-byte little-endian header: `esp_ota_service_version_pack_semver()` of the same semver string as `esp_app_desc_t::version` (see `examples/ota_fs`).

  esp_ota_service_source_t *source

    Data stream source for download. Required.

  esp_ota_service_target_t *target

    Write target. Required.

  esp_ota_service_verifier_t *verifier

    Optional streaming integrity verifier (SHA256, signature, etc.). NULL = no integrity verification during download.

  esp_ota_service_checker_t *checker

    Optional pre-download update checker. NULL = skip version check. Use `esp_ota_service_checker_app_create()` for app images, `esp_ota_service_checker_data_version_create()` for data partitions, `esp_ota_service_checker_manifest_create()` for JSON manifests, or implement `esp_ota_service_checker_t` for custom formats.

  bool skip_on_fail

    If true, continue to the next item on failure. If false (default), abort the entire session.

  bool resumable

    Enable NVS-based resume on failure/reboot. Requires `source->seek` and `target->set_write_offset` to be implemented; otherwise `esp_ota_service_set_upgrade_list()` returns ESP_ERR_NOT_SUPPORTED. Data-partition and bootloader targets erase the whole partition on open() and therefore cannot be resumed: only the app target and sources with random-access seek currently qualify.

struct esp_ota_service_task_cfg_t

  Worker task configuration for the OTA download task.

          This task is distinct from the ADF service command-processing task.
          It performs the actual source read, verifier update, and target write loop.

  Public Members

  uint32_t stack_size

    Worker task stack size in bytes. 0 = use ESP_OTA_SERVICE_DEFAULT_WORKER_STACK_SIZE.

  uint8_t priority

    Worker task FreeRTOS priority. 0 = use ESP_OTA_SERVICE_DEFAULT_WORKER_PRIORITY.

  int8_t core_id

    Core affinity. -1 = any core.

struct esp_ota_service_cfg_t

  OTA service configuration.

  Public Members

  const char *name

    ADF service / Event Hub domain name; NULL = ESP_OTA_SERVICE_DOMAIN

  esp_ota_service_task_cfg_t worker_task

    OTA download worker task config.

  uint32_t write_chunk_size

    Per-chunk read/write buffer size in bytes. 0 = ESP_OTA_SERVICE_DEFAULT_WRITE_CHUNK_SIZE. Valid range when non-zero: 512-65536.

  uint32_t stop_timeout_ms

    Max wait in ms for worker to exit in esp_service_stop(). 0 = ESP_OTA_SERVICE_DEFAULT_STOP_TIMEOUT_MS. Minimum when non-zero: 1000.

### Macros

ESP_OTA_SERVICE_DOMAIN

  Event Hub domain name for OTA service.

ESP_OTA_SERVICE_DEFAULT_WORKER_STACK_SIZE

  Default OTA worker stack when esp_ota_service_task_cfg_t.stack_size is 0.

ESP_OTA_SERVICE_DEFAULT_WORKER_PRIORITY

  Default OTA worker priority when esp_ota_service_task_cfg_t.priority is 0.

ESP_OTA_SERVICE_DEFAULT_WRITE_CHUNK_SIZE

  Default read/write chunk size when esp_ota_service_cfg_t.write_chunk_size is 0.

ESP_OTA_SERVICE_DEFAULT_STOP_TIMEOUT_MS

  Default esp_service_stop() wait when esp_ota_service_cfg_t.stop_timeout_ms is 0.

ESP_OTA_SERVICE_CFG_DEFAULT()

  Convenience initialiser for esp_ota_service_cfg_t.

### Type Definitions

typedef struct esp_ota_service esp_ota_service_t

  Opaque OTA service handle (definition in esp_ota_service.c)

          The concrete object embeds @c esp_service_t as its first member: the handle pointer
          has the same address as that base.  ADF entry points take @c esp_service_t *, so use
          @c (esp_service_t *)svc only to satisfy the C type system (e.g. esp_service_event_subscribe()).

typedef struct esp_ota_upgrade_item esp_ota_upgrade_item_t

  Descriptor for a single partition upgrade.

          @c uri and @c partition_label are deep-copied, so stack-allocated items
          are safe.  Ownership of @c source / @c target / @c verifier / @c checker
          transfers to the service when @c esp_ota_service_set_upgrade_list() is entered:
          their @c destroy() runs when the list is replaced, the service is destroyed,
          or validation fails (set @c destroy = NULL to opt out).

          When @c checker is non-NULL, the worker runs a header-only version check
          before downloading and emits @c ESP_OTA_SERVICE_EVT_ITEM_VER_CHECK.  If the check
          reports @c !upgrade_available with @c error == ESP_OK, the item skips
          @c ITEM_BEGIN / @c ITEM_END.  The worker never loops on a single item.

typedef esp_ota_service_check_result_t esp_ota_service_update_info_t

  Information about available firmware update.

          Same layout as @c esp_ota_service_check_result_t.

### Enumerations

enum esp_ota_service_event_id_t

  OTA service event identifiers.

          Enumerators are listed in the typical emission order within one session.
          IDs start at 2 (0 is invalid for @c esp_service_publish_event(), 1 is
          reserved for @c ESP_SERVICE_EVENT_STATE_CHANGED); use the symbols — numeric
          values are not stable across releases.  @c ESP_OTA_SERVICE_EVT_MAX is a non-event
          upper-bound sentinel and is never published.

          @c ESP_OTA_SERVICE_EVT_ITEM_VER_CHECK fires only when @c checker is non-NULL; read
          @c error first, then @c ver_check.upgrade_available:
            - @c error != ESP_OK            — check failed; @c ITEM_END follows (no @c ITEM_BEGIN).
            - @c error == ESP_OK, not newer — skipped; neither @c ITEM_BEGIN nor @c ITEM_END.
            - @c error == ESP_OK, newer     — download proceeds with @c ITEM_BEGIN.

  Values:

  enumerator ESP_OTA_SERVICE_EVT_SESSION_BEGIN

    OTA session started (before first item)

  enumerator ESP_OTA_SERVICE_EVT_ITEM_VER_CHECK

    Pre-download checker finished; see `ver_check` and `error`.

  enumerator ESP_OTA_SERVICE_EVT_ITEM_BEGIN

    Read/write loop about to start (after source/target `open()`, optional verifier `verify_begin()`, and internal resume setup). No union payload; only `item_index` / `item_label`.

  enumerator ESP_OTA_SERVICE_EVT_ITEM_PROGRESS

    Progress update for the current item (throttled, ~1s)

  enumerator ESP_OTA_SERVICE_EVT_ITEM_END

    Single partition upgrade finished. Payload carries `item_end.status` (OK / SKIPPED / FAILED), `item_end.reason` (classification when status is not OK), and `error` (`ESP_OK` for OK and SKIPPED; pipeline / checker / abort codes when `FAILED`).

  enumerator ESP_OTA_SERVICE_EVT_SESSION_END

    OTA session finished. Payload carries success/failed/skipped counts and aborted flag; consumers should handle this single event instead of three disjoint outcomes.

  enumerator ESP_OTA_SERVICE_EVT_MAX

    Sentinel; not a real event.

enum esp_ota_service_item_status_t

  Per-item outcome reported in ESP_OTA_SERVICE_EVT_ITEM_END.

  Values:

  enumerator ESP_OTA_SERVICE_ITEM_STATUS_OK

    Item written and committed successfully.

  enumerator ESP_OTA_SERVICE_ITEM_STATUS_SKIPPED

    Item was deliberately not applied; see `esp_ota_service_item_end_reason_t`.

  enumerator ESP_OTA_SERVICE_ITEM_STATUS_FAILED

    Item failed; `esp_ota_service_event_t::error` carries the reason.

enum esp_ota_service_item_end_reason_t

  Coarse outcome detail for `ESP_OTA_SERVICE_EVT_ITEM_END`.

          When @c item_end.status is @c ESP_OTA_SERVICE_ITEM_STATUS_OK, the value is @c ESP_OTA_SERVICE_ITEM_END_REASON_NONE.
          For @c ESP_OTA_SERVICE_ITEM_STATUS_FAILED and @c ESP_OTA_SERVICE_ITEM_STATUS_SKIPPED, use @c reason together with
          @c esp_ota_service_event_t::error (especially for failures — @c error holds the precise @c esp_err_t).

  Values:

  enumerator ESP_OTA_SERVICE_ITEM_END_REASON_NONE

    No extra classification (success path).

  enumerator ESP_OTA_SERVICE_ITEM_END_REASON_VERIFIER_REJECTED

    SKIPPED: streaming verifier rejected the image at verify_begin() or verify_finish().

  enumerator ESP_OTA_SERVICE_ITEM_END_REASON_CHECK_FAILED

    FAILED: pre-download checker returned an error.

  enumerator ESP_OTA_SERVICE_ITEM_END_REASON_ABORTED

    FAILED: session stop / user abort before item finished.

  enumerator ESP_OTA_SERVICE_ITEM_END_REASON_PIPELINE

    FAILED: download / write / commit path (`error`).

### Header File

- components/esp_ota_service/include/esp_ota_service_default.h

提供有关此文档的反馈