Replace brace-initialization `{}` with explicit `nullopt` for
optional<size_t> returns and assignments. Older GCC on ESP8266
falsely warns about uninitialized values with `return {}`.
message_type is uint8_t (max 255), which fits in at most 2 varint
bytes. Simplify the ternary to reflect this constraint. Also revert
unnecessary comment split.
- Replace ProtoSize::varint() call for message_type with inline
ternary using named constants, avoiding the noinline varint_slow
call overhead in the write_protobuf_messages loop (-32 bytes on
ESP8266 Xtensa).
- Add named varint threshold constants (VARINT_MAX_1_BYTE, etc.)
to ProtoSize class, used by both varint() and varint_wide().
- Devirtualize write_protobuf_packet by moving it to the base class
as a non-virtual inline method. The plaintext and noise
implementations only differed in footer handling, which is now
unified via a conditional resize based on frame_footer_size_.
This eliminates one vtable slot and allows the compiler to fully
inline the thin wrapper into callers (-192 bytes total flash on
ESP8266).
- Include proto.h from api_frame_helper.h (no circular dependency)
to support the inline definition, replacing the forward declaration
of ProtoWriteBuffer.
GCC's std::function::operator=(function&&) implements move-assignment as
a swap dance: construct temporary, swap with *this, destroy temporary.
This generates two std::swap<_Any_data> calls plus a destructor even
when the target is known to be empty.
Since scheduler items returned from the pool or freshly allocated always
have an empty callback, we can use explicit destroy + placement
move-construct to bypass the swap overhead.
Measured savings in set_timer_common_:
- ESP8266 (Xtensa LX106): 473 → 421 bytes (-52 B, -11%)
- ESP32-S3 (Xtensa LX7): 412 → 376 bytes (-36 B, -9%)
When USE_ESP8266 or USE_RP2040 is defined, provide a fully inline
no-op Mutex class in the header. This allows the compiler to
eliminate all lock/unlock call overhead instead of generating
calls to empty function stubs.
Replace floating-point random offset calculation with integer
multiply-and-shift, eliminating soft-float calls on ESP8266 and
FPU instructions on ESP32/RP2040.
Add generate-rp2040-boards.py script that clones the arduino-pico
repository at the recommended framework version and regenerates
boards.py, matching the existing ESP32 board generation CI check
pattern.
This ensures boards.py stays in sync when the arduino-pico
framework version is updated.
Follow-up to #14528.
TextSaver::save() returned false for both unchanged values and
values that are too long, causing a misleading warning on every
duplicate save. Return true early when the value hasn't changed.
Add integration test for template text save/restore persistence.
Increase LOG_NAGLE_COUNT from 2 to 3 on ESP32 and RP2040, which have
larger TCP send buffers (64KB and 11.7KB respectively). This coalesces
4 log messages per Nagle cycle instead of 3, reducing the number of
individual write() calls and significantly reducing EWOULDBLOCK hits
on the log subscriber connection.
Tested on ESP32 and RP2040: buffered writes dropped from ~15% to near
zero with this change. ESP8266 and LibreTiny remain at LOG_NAGLE_COUNT=2
due to tighter buffer constraints.
On embedded targets (ESP32, RP2040, ESP8266), errno expands to
(*__errno()) - a function call returning a pointer to thread-local
storage. The compiler cannot optimize away repeated accesses since
errno is treated as volatile. Cache it once into a const int local
to avoid redundant calls.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The template water_heater component was setting the supported modes
list but not setting the WATER_HEATER_SUPPORTS_OPERATION_MODE feature
flag, causing Home Assistant to not know that mode selection is
supported.
Fixes https://github.com/esphome/esphome/issues/14605