Add a 15-second timeout for completing the API handshake (Noise
transport + HelloRequest). Previously, a client could connect and
stall mid-handshake, holding a connection slot for up to 150 seconds
(the keepalive disconnect timeout). With max_connections defaulting
to 8 on ESP32, this allowed all slots to be blocked with minimal
effort.
Normal clients complete the full handshake in milliseconds, so 15
seconds is generous. The check short-circuits for authenticated
connections (single bitfield compare) so there is no overhead for
established sessions.
Add a 15-second timeout for completing the API handshake (Noise
transport + HelloRequest). Previously, a client could connect and
stall mid-handshake, holding a connection slot for up to 150 seconds
(the keepalive disconnect timeout). With max_connections defaulting
to 8 on ESP32, this allowed all slots to be blocked with minimal
effort.
Normal clients complete the full handshake in milliseconds, so 15
seconds is generous. The check short-circuits for authenticated
connections (single bitfield compare) so there is no overhead for
established sessions.
Single-byte varints (0-127) are the most common case in protobuf
messages (booleans, small enums, field tags). Skip the loop entirely
for these values by checking the first byte before entering the
multi-byte parsing loop.
Device IDs are FNV hashes (uint32) that frequently exceed 2^28,
requiring 5 varint bytes. This test verifies the firmware correctly
decodes these values in incoming SwitchCommandRequest messages and
encodes them in state responses.
The fix is already in the ESP-IDF release/v5.5 branch (merged Dec 3,
2025) and will be in v5.5.3.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Convert COLOR_OFF and COLOR_ON from extern const to inline constexpr.
The Color class already has constexpr constructors so these can be
compile-time constants, allowing the compiler to optimize default
parameter values and eliminate the runtime storage.
The new touch_volt_lim_h_t enum combines high_voltage_reference and
voltage_attenuation into a single value. Map the two user-facing config
options to the correct combined enum using a lookup table.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Split the rarely-taken warning path into a separate noinline cold
function so the hot path (called every component every loop iteration)
is minimal. Also make WARN_IF_BLOCKING_OVER_MS constexpr so the
compiler uses an immediate compare instead of a memory load, and
merge the two ESP_LOGW calls into one.
finish() shrinks from 108 to 30 bytes. Total flash savings: -116 bytes.
When a preset is cleared, the field was omitted entirely from the JSON.
Since the frontend uses Object.assign to merge state updates, the old
preset value was never removed. Now we always send the field (empty
string when no preset is active) so the UI updates correctly.
Convert setup_priority floats, component state uint8_t constants, and
status LED constants from extern const (defined in component.cpp) to
inline constexpr in the header. This lets the compiler use immediate
values instead of memory loads across all translation units.
Also removes the dead HARDWARE_LATE declaration (declared extern but
never defined).
Saves ~364 bytes flash on ESP32-S3.
On 32-bit platforms (ESP32 Xtensa), 64-bit shifts in varint parsing
compile to __ashldi3 library calls. Since the vast majority of protobuf
varint fields (message types, sizes, enum values, sensor readings) fit
in 4 bytes, the 64-bit arithmetic is unnecessary overhead on the common
path.
Split parse() into two phases:
- Bytes 0-3: uint32_t loop with native 32-bit shifts (0, 7, 14, 21)
- Bytes 4-9: noinline parse_wide_() with uint64_t, only for BLE
addresses and other 64-bit fields
The code generator auto-detects which proto messages use int64/uint64/
sint64 fields and emits USE_API_VARINT64 conditionally. On non-BLE
configs, parse_wide_() and the 64-bit accessors (as_uint64, as_int64,
as_sint64) are compiled out entirely.
Saves ~40 bytes flash on non-BLE configs. Benchmark shows 25-50%
faster parsing for 1-4 byte varints (the common case).
Work around ESP-IDF bug where touch_ll_enable_channel_mask() and
touch_ll_set_charge_speed() don't apply the channel 8/9 bit swap
required by the ESP32 hardware. The legacy driver's equivalent
functions (touch_ll_set_channel_mask, etc.) correctly applied
TOUCH_LL_BITS_SWAP, but the new unified API omits it.
This caused channels 8 (GPIO33) and 9 (GPIO32) to not be properly
enabled for measurement, resulting in reads always returning zero.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The web server's handle_climate_request() parsed mode, fan_mode, and
swing_mode but did not parse preset, making it impossible to set climate
presets via the REST API or web UI.
Also fix the JSON response to always include the presets and
custom_presets arrays when the climate entity supports them, rather than
only when a preset is currently active. This matches how swing_modes is
already handled and ensures the frontend can render preset controls
before one is selected.
Migrate from deprecated driver/touch_sensor.h to the new unified
driver/touch_sens.h API, eliminating deprecation warnings on ESP-IDF v5.5
and adding ESP32-P4 touch support.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>