The multi-message batch path in process_batch_multi_ bypassed
set_nodelay_for_message(), so batch data written to the socket would
sit in LWIP's Nagle buffer when log messages had previously enabled
Nagle. The remote wouldn't ACK until it sent its own data (e.g. a
ping), which could take 20+ seconds. This caused log-only API clients
(like esphome logs) to time out waiting for ListEntitiesDoneResponse.
Additionally, when LIST_ENTITIES completed without a state subscription,
the batched entity listing responses were never explicitly flushed —
they waited for the 100ms batch timer instead of being sent immediately
like the INITIAL_STATE completion path already did.
Fixes both issues:
- Call set_nodelay_for_message(false) before write_protobuf_messages
in process_batch_multi_ to ensure TCP_NODELAY is on
- Extract finalize_iterator_sync_() helper and call it when
LIST_ENTITIES completes without state_subscription
Don't reset s_crash_data_valid in crash_handler_clear() so that
additional API clients connecting during the same boot session
can still receive the crash log.
Don't clear the crash data magic marker at boot time. Previously,
crash_handler_read_and_clear() would clear the magic immediately,
so if OTA rollback triggered a reboot before an API client connected,
the crash trace was lost.
Now the magic is only cleared after crash_handler_log() delivers the
data to an API client via crash_handler_clear().
On dual-core ESP32 chips, the crash handler now captures the backtrace
from both cores during a panic. This is especially useful for interrupt
WDT crashes where the panic runs on CPU0 (idle task) but the actual
problem is on CPU1 (where ESPHome's main loop runs).
The IncludeFile representer added in #15549 defers !include resolution,
but the component test scripts assumed load_yaml always returns a dict.
Test files using top-level !include (e.g. usb_uart) caused a TypeError:
'argument of type IncludeFile is not iterable'.
Resolve IncludeFile objects by calling .load() before processing.
Add explicit Storage union with trivial ctor/dtor so that
TemplatableValue works with non-trivially-constructible types like
std::vector<uint8_t>. The union's value_ lifetime is managed
externally via placement new and destroy_().
Reverts esp32_ble_server back to TEMPLATABLE_VALUE macro.
TemplatableStorage now selects TemplatableFn (4 bytes) for trivially
copyable types and TemplatableValue (8 bytes) for non-trivial types.
This automatically handles std::string (PROGMEM support) and
std::vector<uint8_t> (raw value assignment from C++) without
special-casing.
Reverts esp32_ble_server back to TEMPLATABLE_VALUE macro since
std::vector<uint8_t> now correctly gets TemplatableValue.