Remove the FreeRTOS mutex (lock_) that wrapped all ESP-IDF UART driver
calls. A codebase audit confirmed all UART wrapper methods (read_array,
write_array, peek_byte, available, flush) are called exclusively from
the cooperative main loop. The lock was protecting single-threaded code
from itself and added 4 unnecessary semaphore operations per read_array
call on the hot path.
Fix a race condition in rx_event_task_func where uart_flush_input() was
called from a separate FreeRTOS task without taking the lock, racing
with read_array() on the main loop. This could destroy ring buffer data
mid-read, causing data loss. The flush was also unnecessary since the
ESP-IDF driver self-heals the buffer-full condition: uart_read_bytes()
internally calls uart_check_buf_full() which moves stashed FIFO bytes
back into the ring buffer and re-enables RX interrupts.
Move the event queue allocation behind USE_UART_WAKE_LOOP_ON_RX. When
the feature is disabled, uart_driver_install is called with queue_size=0
and uart_queue=NULL (the documented API for skipping the event queue).
This saves ~320 bytes of RAM per UART instance and reduces ISR overhead
since the driver skips xQueueSendFromISR when no queue exists.
Add thread safety documentation to the class and rx_event_task.
The regex matches `scanf (` in comments too since `\s*\(` matches the
space before the parenthesized size note.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move `packet$` pattern from `wifi_config` to `mdns_lib` category.
The `packet$` static buffer is the mDNS packet assembly buffer used
by ESP-IDF's mDNS component, not a WiFi config symbol. This was
causing 1,460 B of mDNS RAM to appear under wifi_config in
ethernet-only builds.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Skip emitting the "icon" key in set_json_id() when USE_ENTITY_ICON
is not defined. This avoids the ArduinoJson .set() call overhead and
sending empty "icon":"" in every JSON response for builds without icons.
Extend the per-PHY compile guard pattern (already used by KSZ8081 and
LAN8670) to all RMII PHY types: LAN8720, RTL8201, DP83848, IP101, and
JL1101. This allows the linker to strip unused PHY driver code, saving
~7.5 KB flash per build since only one PHY is ever used per device.
Extend the per-PHY compile guard pattern (already used by KSZ8081 and
LAN8670) to all RMII PHY types: LAN8720, RTL8201, DP83848, IP101, and
JL1101. This allows the linker to strip unused PHY driver code, saving
~7.5 KB flash per build since only one PHY is ever used per device.
Instead of treating any non-ESP_ERR_NOT_FOUND result as key-present,
explicitly check for the two success codes. This avoids false positives
from unexpected error codes like ESP_ERR_INVALID_ARG.
Instead of treating any non-ESP_ERR_NOT_FOUND result as key-present,
explicitly check for the two success codes. This avoids false positives
from unexpected error codes like ESP_ERR_INVALID_ARG.
The query string already lives in req->uri. Access it via strchr('?')
instead of copying into a 513-byte stack buffer via httpd_req_get_url_query_str.
This is the same pattern url_to() uses — http_parser identifies URI
components by offset/length without modifying the source string.
Eliminates 513 bytes of stack usage on the httpd task, leaving only
the 128-byte value extraction buffer in query_key_value.
The query string already lives in req->uri. Access it via strchr('?')
instead of copying into a 513-byte stack buffer via httpd_req_get_url_query_str.
This is the same pattern url_to() uses — http_parser identifies URI
components by offset/length without modifying the source string.
Eliminates 513 bytes of stack usage on the httpd task, leaving only
the 128-byte value extraction buffer in query_key_value.
768 bytes on the httpd task stack contributes to stack overflow when
combined with other stack-allocated buffers (query string parsing, etc.).
512 bytes still covers all typical JSON payloads (sensors ~200B, lights
~170B, climate ~500-700B). Only extreme edge cases with 40+ options
trigger heap fallback.
768 bytes on the httpd task stack contributes to stack overflow when
combined with other stack-allocated buffers (query string parsing, etc.).
512 bytes still covers all typical JSON payloads (sensors ~200B, lights
~170B, climate ~500-700B). Only extreme edge cases with 40+ options
trigger heap fallback.
Revert direct req->uri access (unsafe — ESP-IDF uses parsed offsets,
not strchr). Instead fix the root cause: query_key_value used a full
CONFIG_HTTPD_MAX_URI_LEN+1 (513 byte) stack buffer while
search_query_sources had another 513 byte buffer on the stack
simultaneously, totaling ~1KB on the httpd thread's limited stack.
Use SmallBufferWithHeapFallback<128> for the value extraction buffer.
128 bytes covers typical parameter values on stack; longer values
(e.g. base64 IR data) fall back to heap.
search_query_sources was copying the URL query string into a 513-byte
stack buffer, then query_key_value added another 513-byte buffer for
the extracted value — 1026 bytes simultaneously on the httpd thread's
limited stack, causing a crash in lwip_select.
The query string already lives in req->uri after the '?'. Access it
directly via pointer instead of copying, eliminating one buffer entirely.
Query strings cannot exceed the max URI length, so SmallBufferWithHeapFallback
is unnecessary. Use a plain stack array instead for zero heap allocation.
- Add early return for empty post_query (common GET request path)
- Refactor getParam to use find_query_value_ instead of duplicating search logic
- Remove now-unused request_get_url_query (and its heap allocation)
- Remove unused std::string overload of query_key_value
Replace request_get_url_query (returns std::string) with inline
httpd_req_get_url_query_str into a SmallBufferWithHeapFallback
stack buffer. Typical query strings (<256 bytes) now use zero
heap allocations for parameter lookups.
Both methods iterated post_query_ then url_query with the same
pattern. Extracted a file-local template that takes a callback,
avoiding duplicated request_get_url_query heap allocation logic.
hasArg only needs to know if a key exists, not its value.
query_has_key uses a 1-byte buffer and checks the return code
from httpd_query_key_value — no url_decode, no std::string.
Use const auto& to bind arg() result directly, avoiding
unnecessary std::string intermediate copies. Construct
std::string only where needed (lambda capture, setter call).
Use const auto& to bind directly to arg() result (std::string on
IDF, Arduino String on Arduino) and pass c_str()/length() to the
setter. No intermediate std::string copy needed.