60 if (container ==
nullptr || container->status_code !=
HTTP_STATUS_OK) {
61 ESP_LOGE(TAG,
"Failed to fetch manifest from %s", this_update->
source_url_.c_str());
63 this_update->
defer([this_update]() { this_update->
status_set_error(LOG_STR(
"Failed to fetch manifest")); });
68 uint8_t *data = allocator.
allocate(container->content_length);
69 if (data ==
nullptr) {
70 ESP_LOGE(TAG,
"Failed to allocate %zu bytes for manifest", container->content_length);
73 [this_update]() { this_update->
status_set_error(LOG_STR(
"Failed to allocate memory for manifest")); });
78 auto read_result =
http_read_fully(container.get(), data, container->content_length, MAX_READ_SIZE,
82 ESP_LOGE(TAG,
"Timeout reading manifest");
84 ESP_LOGE(TAG,
"Error reading manifest: %d", read_result.error_code);
87 this_update->
defer([this_update]() { this_update->
status_set_error(LOG_STR(
"Failed to read manifest")); });
88 allocator.
deallocate(data, container->content_length);
92 size_t read_index = container->get_bytes_read();
96 std::string response((
char *) data, read_index);
97 allocator.
deallocate(data, container->content_length);
103 if (!root[ESPHOME_F(
"name")].is<const char *>() || !root[ESPHOME_F(
"version")].is<const char *>() ||
104 !root[ESPHOME_F(
"builds")].is<JsonArray>()) {
105 ESP_LOGE(TAG,
"Manifest does not contain required fields");
111 for (
auto build : root[ESPHOME_F(
"builds")].as<JsonArray>()) {
112 if (!build[ESPHOME_F(
"chipFamily")].is<const char *>()) {
113 ESP_LOGE(TAG,
"Manifest does not contain required fields");
116 if (build[ESPHOME_F(
"chipFamily")] == ESPHOME_VARIANT) {
117 if (!build[ESPHOME_F(
"ota")].is<JsonObject>()) {
118 ESP_LOGE(TAG,
"Manifest does not contain required fields");
121 JsonObject ota = build[ESPHOME_F(
"ota")].as<JsonObject>();
122 if (!ota[ESPHOME_F(
"path")].is<const char *>() || !ota[ESPHOME_F(
"md5")].is<const char *>()) {
123 ESP_LOGE(TAG,
"Manifest does not contain required fields");
127 this_update->
update_info_.
md5 = ota[ESPHOME_F(
"md5")].as<std::string>();
129 if (ota[ESPHOME_F(
"summary")].is<const char *>())
131 if (ota[ESPHOME_F(
"release_url")].is<const char *>())
142 ESP_LOGE(TAG,
"Failed to parse JSON from %s", this_update->
source_url_.c_str());
144 this_update->
defer([this_update]() { this_update->
status_set_error(LOG_STR(
"Failed to parse manifest JSON")); });
151 if (path[0] ==
'/') {
161 std::string current_version;
162#ifdef ESPHOME_PROJECT_VERSION
163 current_version = ESPHOME_PROJECT_VERSION;
165 current_version = ESPHOME_VERSION;
171 bool trigger_update_available =
false;
178 trigger_update_available =
true;
188 this_update->
defer([this_update, trigger_update_available]() {
195 if (trigger_update_available) {
ESPDEPRECATED("Use const char* overload instead. Removed in 2026.7.0", "2026.1.0") void defer(const std voi defer)(const char *name, std::function< void()> &&f)
Defer a callback to the next loop() call.
HttpReadResult http_read_fully(HttpContainer *container, uint8_t *buffer, size_t total_size, size_t chunk_size, uint32_t timeout_ms)
Read data from HTTP container into buffer with timeout handling Handles feed_wdt, yield,...