diff --git a/esphome/components/esphome/ota/ota_esphome.cpp b/esphome/components/esphome/ota/ota_esphome.cpp index 5ebab7a838..a3d8897969 100644 --- a/esphome/components/esphome/ota/ota_esphome.cpp +++ b/esphome/components/esphome/ota/ota_esphome.cpp @@ -537,7 +537,7 @@ void ESPHomeOTAComponent::handle_data_() { error_code = this->write_flash_(buf, read); if (error_code != ota::OTA_RESPONSE_OK) goto error; // NOLINT(cppcoreguidelines-avoid-goto) - this->send_chunk_acks_(xfer); + this->ack_written_(xfer); } } @@ -794,6 +794,7 @@ ssize_t ESPHomeOTAComponent::receive_data_(uint8_t *buf, DataTransfer &xfer) { const uint32_t now = millis(); xfer.last_data_ms = now; xfer.total += read; + this->ack_received_(xfer); if (now - xfer.last_progress > OTA_PROGRESS_INTERVAL_MS) { xfer.last_progress = now; float percentage = (xfer.total * 100.0f) / xfer.ota_size; @@ -850,14 +851,14 @@ ota::OTAResponseTypes ESPHomeOTAComponent::inflate_data_(uint8_t *in, size_t ima session.error = ota::OTA_RESPONSE_OK; ota_inflate_init(&session, session.window, OTA_INFLATE_WINDOW_SIZE); // Pulls the next compressed chunk when the decoder runs dry. Everything - // received so far is decoded by then, so it is written and acked first, - // keeping a chunk ack meaning "in flash" as on the uncompressed path. + // received so far is decoded by then, so it is written first and, on the + // platforms that ack after the write, acked. session.source_read_cb = [](OtaInflateState *d) -> int { auto *s = static_cast(d); s->error = s->self->inflate_flush_(*s); if (s->error != ota::OTA_RESPONSE_OK) return -1; - s->self->send_chunk_acks_(*s->xfer); + s->self->ack_written_(*s->xfer); if (s->xfer->total >= s->xfer->ota_size) { ESP_LOGW(TAG, "Inflate size mismatch"); return -1; @@ -889,7 +890,7 @@ ota::OTAResponseTypes ESPHomeOTAComponent::inflate_data_(uint8_t *in, size_t ima ota::OTAResponseTypes flush_result = this->inflate_flush_(session); if (flush_result != ota::OTA_RESPONSE_OK) return flush_result; - this->send_chunk_acks_(xfer); + this->ack_written_(xfer); } while (res != OTA_INFLATE_DONE); if (session.written != image_size || xfer.total != xfer.ota_size) { diff --git a/esphome/components/esphome/ota/ota_esphome.h b/esphome/components/esphome/ota/ota_esphome.h index 63bb3c3075..68d9df3253 100644 --- a/esphome/components/esphome/ota/ota_esphome.h +++ b/esphome/components/esphome/ota/ota_esphome.h @@ -135,8 +135,23 @@ class ESPHomeOTAComponent final : public ota::OTAComponent { // Receives up to OTA_BUFFER_SIZE bytes of upload data into buf, waiting up to // the data timeout, and updates xfer. Returns bytes read, -1 on failure (logged). inline ssize_t receive_data_(uint8_t *buf, DataTransfer &xfer); - // Acks every received block once it is in flash, so an ack means written + // When lwIP runs in this loop the radio is deaf while a sector is written, so + // the client is kept quiet until the block is in flash; with a socket task the + // ack goes out on receipt so the next block arrives while this one is written +#ifdef USE_SOCKET_IMPL_LWIP_TCP + static constexpr bool ACK_AFTER_WRITE = true; +#else + static constexpr bool ACK_AFTER_WRITE = false; +#endif inline void send_chunk_acks_(DataTransfer &xfer); + inline void ack_received_(DataTransfer &xfer) { + if (!ACK_AFTER_WRITE) + this->send_chunk_acks_(xfer); + } + inline void ack_written_(DataTransfer &xfer) { + if (ACK_AFTER_WRITE) + this->send_chunk_acks_(xfer); + } // Reads a 4 byte MSB first size field into size inline bool read_size_(uint8_t *buf, size_t &size, const LogString *desc); // Writes to the backend and logs a failure