Reverts the frame header synchronization added in #14135 and #14136
in favor of a simpler fix: increasing MAX_LINE_LENGTH so that the
existing footer-based resynchronization can recover after losing sync.
Both components already check for frame footers at every byte position,
which naturally resyncs the parser. The problem was that the buffers
were sized exactly to fit the largest frame, so a desynced parser's
footer could land at the overflow boundary and get discarded. Increasing
the buffer by 4 bytes (footer size) ensures the footer always lands
inside the buffer.
- ld2450: 41 -> 45 (zone query response = 40 bytes + 1 null + 4 footer)
- ld2410: 46 -> 50 (engineering data frame = 45 bytes + 1 null + 4 footer)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add frame header validation to prevent the parser from getting stuck
in an overflow loop when it loses sync with the UART byte stream
(e.g. after module restart or UART noise). This is the same latent
bug fixed in ld2450 (PR #14135) and present in ld2420.
The fix validates the first 4 bytes of each frame match a known
header (DATA or CMD) before accumulating data. On header byte
mismatch, the buffer resets and checks if the mismatched byte starts
a new frame. Also adds a return after buffer overflow reset to
prevent immediately re-accumulating the overflowed byte.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
The batch UART read change in #13818 exposed a latent bug where the
UART parser could start accumulating bytes mid-frame after module
restart, causing an infinite cycle of "Max command length exceeded"
warnings that prevented initialization.
Add header validation for the first 4 bytes of each frame, ensuring
the parser only accumulates data starting from a valid DATA_FRAME_HEADER
(AA FF 03 00) or CMD_FRAME_HEADER (FD FC FB FA). Non-matching bytes are
discarded until a valid frame start is found.
Fixes#14131
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix get_varint64_ifdef() to return unconditional guard when any 64-bit
varint field has no ifdef (None in ifdefs set)
- Wrap USE_API_VARINT64 define with #ifndef to avoid redefinition warnings
when esphome/core/defines.h also defines it (test/IDE builds)
- Clarify proto.h comment about uint32_t shift behavior at byte 4
- Add namespace to generated api_pb2_defines.h for linter compliance
USE_API_VARINT64 was only defined in api_pb2.h, but proto.cpp (where
decode() and parse_wide() live) includes proto.h directly. This caused:
1. parse_wide() not compiled in proto.cpp (guarded by #ifdef)
2. decode() used 32-bit-only parse(), returning {} for varints > 5 bytes
3. ODR violation: ProtoVarInt was 4 bytes in proto.cpp but 8 bytes in
api_pb2*.cpp translation units
For bluetooth_proxy, 48-bit BLE addresses encode as 7-byte varints.
The failed parse caused decode() to return early, leaving request_type
at its default value of 0 (BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT),
producing spurious "V1 connections removed" errors.
Fix: Generate api_pb2_defines.h with the USE_API_VARINT64 define and
include it from proto.h, ensuring all translation units see a consistent
ProtoVarInt layout.
Previously the BSD socket path read only one UDP packet per loop()
call. With multi-universe setups (e.g. 380 RGBW LEDs across 3
universes), this caused the light to re-render the entire strip
for each universe packet separately, resulting in visible tearing
and ~3x unnecessary RMT writes.
Now both socket backends drain all available packets before returning,
so multi-universe frames are applied atomically and the light only
writes once per frame. The duplicated packet processing logic is
consolidated into a shared loop with a platform-specific read_()
helper.
Tested on ESP32-IDF with 380 SK6812 RGBW LEDs (3 universes):
- Light total CPU dropped from 5820ms to 1108ms per 60s (~5x)
- Combined e131+light dropped from 6944ms to 4811ms per 60s
- Visible tearing eliminated
Fix UART0 communication failure on ESP-IDF 5.4.2+ that affected LD2410
and other UART sensors on default UART0 pins across all ESP32 variants.
The gpio_reset_pin() workaround from PR #12519 sets GPIO_MODE_DISABLE
which disables the input buffer. Without a subsequent pin->setup() call,
uart_set_pin() on IOMUX-connected UART0 default pins does not re-enable
the input buffer, so the RX pin cannot receive data.
PR #11914 made pin->setup() conditional on pull/open-drain flags, which
meant most users' UART0 RX pins never got their input buffer re-enabled.
The fix: always call pin->setup() for pins matching U0TXD_GPIO_NUM or
U0RXD_GPIO_NUM to restore proper GPIO direction after gpio_reset_pin().
For non-UART0 pins, the conditional behavior is preserved to avoid
breaking external components (issue #11823).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix UART0 communication failure on ESP-IDF 5.4.2+ that affected LD2410
and other UART sensors on default UART0 pins across all ESP32 variants.
The gpio_reset_pin() workaround from PR #12519 sets GPIO_MODE_DISABLE
which disables the input buffer. Without a subsequent pin->setup() call,
uart_set_pin() on IOMUX-connected UART0 default pins does not re-enable
the input buffer, so the RX pin cannot receive data.
PR #11914 made pin->setup() conditional on pull/open-drain flags, which
meant most users' UART0 RX pins never got their input buffer re-enabled.
The fix: always call pin->setup() for pins matching U0TXD_GPIO_NUM or
U0RXD_GPIO_NUM to restore proper GPIO direction after gpio_reset_pin().
For non-UART0 pins, the conditional behavior is preserved to avoid
breaking external components (issue #11823).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Change progmem_array codegen from `static const` to `static constexpr`.
This ensures the compiler evaluates the array at compile time with no
runtime initialization, and is the correct qualifier for constant data
known at compile time.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Change progmem_array codegen from `static const` to `static constexpr`.
This ensures the compiler evaluates the array at compile time with no
runtime initialization, and is the correct qualifier for constant data
known at compile time.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Only set when at least one light has gamma_correct configured.
On-off lights with no gamma get inline passthrough that the
compiler eliminates entirely — zero gamma code in the binary.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use the pow10_int() helper to replace the remaining powf(10, exp)
calls in dlms_meter and kamstrup_kmp components.
Also removes the now-unused <cmath> include from dlms_meter.
On builds where these are the only remaining powf call sites,
this eliminates powf/__ieee754_powf from the binary entirely.