Commit Graph
25481 Commits
Author SHA1 Message Date
J. Nick Koston 0c81963eb9 Merge remote-tracking branch 'upstream/inline-wifi-ap-channel-accessors' into integration 2026-03-21 20:24:54 -10:00
J. Nick Koston 1db789313b [wifi] Inline WiFiAP::get_channel() and has_channel() in header
These trivial accessors (12 bytes each) benefit from inlining,
matching the style of the adjacent get_priority() accessor.
2026-03-21 20:21:20 -10:00
J. Nick Koston a87b5ed534 Merge remote-tracking branch 'upstream/fix-logger-task-log-buffer-race' into integration 2026-03-21 17:04:32 -10:00
J. Nick Koston e32565b36a Inline init_log_buffer_ into constructor 2026-03-21 17:00:26 -10:00
J. Nick Koston b0e6f57bc2 Remove disable_loop from init_log_buffer_ to avoid ESP_LOGVV before global_logger is set
Since init_log_buffer_ is now called from the constructor (before
pre_setup sets global_logger), calling disable_loop() would trigger
ESP_LOGVV which dereferences the null global_logger pointer.

The loop self-disables on its first iteration when no messages are
found, so the explicit disable in init_log_buffer_ was unnecessary.
2026-03-21 16:58:55 -10:00
pre-commit-ci-lite[bot] cbea4e0ccf [pre-commit.ci lite] apply automatic fixes 2026-03-22 02:56:50 +00:00
J. Nick KostonandCopilot 44ea4a2235 Update esphome/components/logger/logger.cpp
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-21 16:55:15 -10:00
J. Nick Koston 6576e88df0 Rename init_log_buffer to init_log_buffer_ for clang-tidy naming 2026-03-21 16:53:25 -10:00
J. Nick Koston 1ccfd0b3cd [logger] Fix race condition in task log buffer initialization
Move TaskLogBuffer allocation from init_log_buffer() (called at
DIAGNOSTICS priority) into the Logger constructor (called at
EARLY_INIT priority). This ensures the buffer exists before
global_logger is set, eliminating a window where another FreeRTOS
task could dereference a null log_buffer_ pointer.

Fixes crash: Guru Meditation Error: Core 0 panic'ed (Load access fault)
in TaskLogBuffer::send_message_thread_safe when a task logs before
init_log_buffer() is called.
2026-03-21 16:48:50 -10:00
J. Nick Koston c48fd0738b [mqtt] Rate-limit component resends to prevent task WDT on reconnect (#15061) 2026-03-21 15:33:42 -10:00
J. Nick Koston 8224da3460 [core] Inline Component::get_component_log_str() (#15068) 2026-03-21 15:32:24 -10:00
Clyde Stubbs dd82a91d8f [lvgl] Don't animate page change when not requested (#15069) 2026-03-22 11:13:17 +11:00
J. Nick Koston 86ec218f75 [benchmark] Add plaintext API frame write benchmarks (#15036) 2026-03-21 13:15:35 -10:00
J. Nick Koston f6c0e28db8 Merge remote-tracking branch 'upstream/inline-get-component-log-str' into integration 2026-03-21 12:12:21 -10:00
J. Nick Koston 30b4508320 [core] Inline Component::get_component_log_str()
Move trivial null-check getter from component.cpp to component.h
so the compiler can inline it at call sites, eliminating function
call overhead in hot logging paths.
2026-03-21 12:04:46 -10:00
J. Nick Koston 8978ea7479 Merge remote-tracking branch 'upstream/precompute-tag-forced-varint-fields' into integration 2026-03-21 11:49:43 -10:00
J. Nick Koston da926d904e [api] Precompute tag bytes for forced varint and length-delimited fields
Extend the precomputed-tag approach from fixed32 key fields to all forced
fields with single-byte tags (field IDs 1-15). The code generator now
emits write_raw_byte(tag) followed by the raw encode primitive instead
of calling the full encode_* method.

For varint types (uint32, uint64, sint32, sint64, int64, bool, enum),
this eliminates the zero-check branch and encode_field_raw indirection.
For length-delimited types (bytes, string), it additionally skips the
encode_string wrapper.

Benchmarked on real hardware with BluetoothLERawAdvertisementsResponse
(12 advertisements per message, 10000 iterations):

ESP32 (Xtensa dual-core 240MHz):
  encode: 38498 -> 30460 ns/op (-20.9%)
  calc+encode: 48479 -> 40458 ns/op (-16.6%)

ESP32-C3 (RISC-V single-core 160MHz):
  encode: 54199 -> 40342 ns/op (-25.6%)
  calc+encode: 57800 -> 51365 ns/op (-11.1%)
2026-03-21 11:48:28 -10:00
J. Nick Koston cb1eb0555d Merge remote-tracking branch 'upstream/mqtt-reconnect-wdt-fix' into integration 2026-03-21 10:32:35 -10:00
J. Nick Koston a3f64b6583 Merge remote-tracking branch 'upstream/fix-uart-rtl87xx-success-macro' into integration 2026-03-21 10:32:31 -10:00
J. Nick Koston 3f1bf4cd69 Merge remote-tracking branch 'upstream/fix-gamma-lut-zero-quantization' into integration 2026-03-21 10:32:28 -10:00
J. Nick Koston 6db577f1f2 Merge remote-tracking branch 'upstream/api/peel-first-write-iteration' into integration 2026-03-21 10:32:18 -10:00
J. Nick Koston 21ca02dd3d [api] Peel first iteration of write_protobuf_messages for single-message fast path
The single-message case (via write_protobuf_packet) is the most common
path. Peeling the first loop iteration and outlining the multi-message
batch path avoids the ~300-byte StaticVector<iovec> stack allocation
on the hot path.

Plaintext write_protobuf_messages:
- Stack frame: 352 → 64 bytes
- Code size: 246 → 127 bytes

Noise write_protobuf_messages:
- Extracted encrypt_noise_message_ helper for reuse
- Same peeling pattern with outlined batch path
2026-03-21 09:38:35 -10:00
J. Nick Koston 44e1a86819 [benchmark] Use TCP loopback sockets and correct message type
Use real TCP sockets instead of AF_UNIX socketpair so TCP_NODELAY
succeeds during init() and the benchmark exercises the full write
path. Replace hardcoded message type 38 with SensorStateResponse::MESSAGE_TYPE.
2026-03-21 09:02:17 -10:00
J. Nick Koston 135c599561 [benchmark] Pre-init APIBuffer to 1460 bytes in plaintext frame benchmarks
Avoid benchmarking heap allocation by pre-reserving the buffer
to typical TCP MSS size and reusing it across iterations, matching
real-world usage where the buffer persists across writes.
2026-03-21 08:48:15 -10:00
J. Nick Koston cb2fef8b6c Increase MAX_RESENDS_PER_LOOP from 4 to 8 2026-03-21 08:27:45 -10:00
J. Nick Koston 2b95852b6c Rename resend_pending() to is_resend_pending() for consistency 2026-03-21 08:26:23 -10:00
J. Nick Koston 41ff09d18a [light] Extract generate_gamma_table and add tests
Extract the gamma table generation into a public generate_gamma_table()
function and add unit tests covering table properties and the
zero_means_zero regression from #15055.
2026-03-21 08:23:52 -10:00
J. Nick Koston 427a49959a [mqtt] Rate-limit component resends to prevent task WDT on reconnect
When MQTT reconnects, all components have their discovery and state
republished. With many components, processing all of them in a single
loop iteration blocks the main loop long enough to trigger the task
watchdog timer. Limit to 4 resends per loop iteration to spread the
work across multiple cycles.

Closes https://github.com/esphome/esphome/issues/15057
2026-03-21 08:16:42 -10:00
J. Nick Koston eaef098d96 [light] Fix gamma LUT quantizing small brightness to zero
The gamma LUT refactor (#14123) introduced a regression where small
brightness values (e.g. 1%) get quantized to exactly 0.0 because
the uint16 LUT entries round down to 0 for indices 1-3 with the
default gamma of 2.8.

This breaks zero_means_zero: true in FloatOutput because the
min_power scaling is skipped when state == 0.0, causing LEDs to
turn off completely instead of respecting the configured min_power.

Fix by clamping non-zero LUT entries to a minimum of 1, preserving
the invariant that non-zero input always produces non-zero output.

Fixes #15055
2026-03-21 08:14:06 -10:00
Samuel Sieb 2a6ec597b4 [analog_threshhold] add missing header (#15058) 2026-03-21 18:13:08 +00:00
J. Nick Koston b9679f6caf Merge branch 'dev' into benchmark/plaintext-frame-v2 2026-03-21 08:09:51 -10:00
J. Nick Koston 0bcb85cc72 [uart] Fix RTL87xx compilation failure due to SUCCESS macro collision
The Realtek SDK defines `#define SUCCESS 0` in basic_types.h which
collides with the FlushResult::SUCCESS enum value, breaking compilation
on RTL87xx devices when api/wifi components pull in the SDK headers.

Add `#undef SUCCESS` before the enum definition, following the same
pattern used elsewhere in the codebase for vendor SDK macro collisions.

Also add RTL87xx UART compilation test.
2026-03-21 01:06:06 -10:00
dependabot[bot] 8dd69207ea Bump aioesphomeapi from 44.6.2 to 44.7.0 (#15052)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-21 10:24:56 +00:00
J. Nick Koston 5e5079ec56 Merge remote-tracking branch 'upstream/remove-noinline-encode-fixed32' into integration 2026-03-21 00:07:05 -10:00
J. Nick Koston d8d5619ba7 [api] Use write_tag_and_fixed32 and extract calculate_tag helper
- Combine tag byte + fixed32 value into single write_tag_and_fixed32()
  method: pos[0] = tag, memcpy(pos+1, &value, 4), pos += 5
- Extract calculate_tag() from duplicated computation in
  calculate_field_id_size() and encode_content
2026-03-21 00:05:53 -10:00
J. Nick Koston 2a379490e8 Merge remote-tracking branch 'upstream/remove-noinline-encode-fixed32' into integration 2026-03-20 23:57:37 -10:00
J. Nick Koston 225c770b1b [api] Use write_tag_and_fixed32 and extract calculate_tag helper
- Combine tag byte + fixed32 value into single write_tag_and_fixed32()
  method: pos[0] = tag, memcpy(pos+1, &value, 4), pos += 5
- Extract calculate_tag() from duplicated computation in
  calculate_field_id_size() and encode_content
2026-03-20 23:45:23 -10:00
J. Nick Koston 21725983fd [api] Emit raw tag+value writes for force=true fixed32 fields
Instead of ALWAYS_INLINE on encode_field_raw (which bloated all
callers), have the code generator precompute the tag byte and emit
write_raw_byte(tag) + write_fixed32_raw(value) directly.

This gives the same tight codegen (single byte store + memcpy) for
key fields without inflating encode_bool/encode_uint32/etc.

+108 bytes flash vs baseline, -48 bytes vs the ALWAYS_INLINE approach.
2026-03-20 23:28:19 -10:00
J. Nick Koston 7ce24edabb [api] Force-inline encode_fixed32 and add force=true to all key fields
- Add ESPHOME_ALWAYS_INLINE to encode_fixed32 so the compiler inlines it
  on hot paths despite -Os heuristics (removing noinline alone was not
  enough — gcc still chose not to inline at 51 call sites)
- Mark all fixed32 key fields in api.proto with [(force) = true] since
  entity keys are FNV hashes and never zero, eliminating the zero-check
  branch and making calculate_size() use constants

+96 bytes flash (555167 → 555263) on ESP32 — negligible for removing
branch + call overhead on every sensor state encode.
2026-03-20 23:17:11 -10:00
J. Nick Koston 21929eb157 [api] Remove noinline from encode_fixed32
Profiling showed the noinline call overhead dominated hot paths like
SensorStateResponse encoding, where encode_fixed32 is called twice
per message (once for key, once via encode_float for state).

The function body is trivial (tag byte + 4-byte memcpy), so the
function call prologue/epilogue cost exceeded the actual work.

Despite 51 call sites, removing noinline shows no measurable flash
size increase (555167 bytes before and after on ESP32).
2026-03-20 23:07:12 -10:00
J. Nick Koston 0761170514 Merge remote-tracking branch 'upstream/fix-esp32-efuse-mac-validation' into integration 2026-03-20 22:14:39 -10:00
J. Nick Koston b08de20e6d Merge remote-tracking branch 'upstream/fix-constant-brightness-gamma' into integration 2026-03-20 22:14:36 -10:00
J. Nick Koston 935ab42b1e [esp32] Validate eFuse MAC reads and reject garbage MACs
On some ESP32 boards (especially cheap clones), the eFuse custom MAC
area contains random garbage that passes the existing all-zeros/all-ones
validation. Additionally, esp_efuse_mac_get_default() can fail with CRC
errors, but the return value was being ignored, causing garbage MAC
addresses to be advertised via mDNS.

This caused Home Assistant to report false "MAC address changed" device
conflicts on every boot.

Two fixes:
- Check return values from eFuse MAC read functions and add a fallback
  chain: custom MAC -> default MAC -> raw eFuse bytes -> zeroed MAC.
- Reject multicast MACs (bit 0 of first byte set) in mac_address_is_valid()
  since device MACs must always be unicast.

Closes https://github.com/esphome/esphome/issues/14501
2026-03-20 22:13:01 -10:00
J. Nick KostonandCopilot 4ae1043c2e Update esphome/components/light/light_color_values.h
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-20 22:06:11 -10:00
J. Nick KostonandCopilot 4d805e2d30 Update tests/integration/test_light_constant_brightness.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-20 22:06:03 -10:00
J. Nick Koston f50720a3c5 [light] Add integration tests for constant_brightness with gamma
Regression tests for #15040 using a single compiled binary with two
cwww lights to verify:
- constant_brightness: true maintains constant total CW+WW power
  output across all color temperatures with gamma correction
- constant_brightness: false correctly varies total power (higher
  at mid-range where both channels contribute)
2026-03-20 22:00:44 -10:00
J. Nick Koston 22c338c724 [light] Fix constant_brightness broken by gamma LUT refactor
The gamma LUT refactor (#14123) moved gamma correction to after
the constant_brightness balancing formula (max/sum ratio). This
broke constant_brightness because gamma is nonlinear and does not
commute with the ratio calculation, causing a severe brightness
dip at mid-range color temperatures.

Fix by applying gamma to individual CW/WW/brightness values
before the constant_brightness formula, restoring the original
behavior where total power output remains constant across all
color temperatures.

Closes #15040
2026-03-20 21:46:03 -10:00
J. Nick Koston 7c1b30f37f Merge remote-tracking branch 'upstream/devirtualize-api-dispatch' into integration 2026-03-20 21:31:54 -10:00
J. Nick Koston 1d191d2461 [api] Fix review comments and add USE_API guards
- Update comments to reflect that ProtoService methods moved to
  APIConnection, not APIServerConnectionBase
- Fix comment referring to read_message as "override"
- Wrap #include "api_connection.h" and read_message_ implementation
  in #ifdef USE_API guards
2026-03-20 21:29:42 -10:00
J. Nick Koston 7d8eba85c6 Merge remote-tracking branch 'upstream/devirtualize-api-dispatch' into integration 2026-03-20 21:21:56 -10:00