Compare commits

...

1876 Commits

Author SHA1 Message Date
J. Nick Koston
b58b2045f0 Merge remote-tracking branch 'origin/web_server_match_flash' into integration 2026-01-14 01:21:13 -10:00
J. Nick Koston
ee08953e5c [web_server] Store method/domain comparison strings in flash on ESP8266 2026-01-14 01:17:22 -10:00
tomaszduda23
9c5f4e5288 [usb_cdc_acm] move esp32 implementation to new file (#12824)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2026-01-14 04:07:18 -06:00
J. Nick Koston
49cae5eda8 Merge branch 'scheduler_no_heap' into integration 2026-01-13 22:39:53 -10:00
J. Nick Koston
5541a7f043 one more place to log 2026-01-13 22:36:37 -10:00
J. Nick Koston
1210512286 fix double dep warning 2026-01-13 22:33:32 -10:00
J. Nick Koston
c73a412537 tweaks 2026-01-13 22:30:17 -10:00
J. Nick Koston
4e2c635d14 no ram increase 2026-01-13 22:21:29 -10:00
J. Nick Koston
edde7194c9 no ram increase 2026-01-13 22:19:40 -10:00
J. Nick Koston
bf6d75fd5e fix 2026-01-13 22:08:57 -10:00
J. Nick Koston
38c5421d54 name log 2026-01-13 21:56:06 -10:00
J. Nick Koston
25b7d1ea15 minimize diff 2026-01-13 21:50:03 -10:00
J. Nick Koston
4520f7f646 minimize diff 2026-01-13 21:47:27 -10:00
J. Nick Koston
ba36934f91 minimize diff 2026-01-13 21:46:19 -10:00
J. Nick Koston
16d7342772 cleanup 2026-01-13 21:37:24 -10:00
J. Nick Koston
c8fcc258c3 cleanup 2026-01-13 21:32:24 -10:00
J. Nick Koston
42f98ebc80 [scheduler] Eliminate heap allocations for std::string names and add uint32_t ID API 2026-01-13 20:16:59 -10:00
J. Nick Koston
c8cc29a991 [api] Reduce batch RAM usage by 33% via switch dispatch (#13199) 2026-01-14 03:58:06 +00:00
J. Nick Koston
8b49d465f8 [bh1750] Eliminate heap allocations by replacing callbacks with state machine (#11950) 2026-01-13 17:44:43 -10:00
J. Nick Koston
0a25eae420 Merge branch 'reduce_batch_size' into integration 2026-01-13 17:17:25 -10:00
J. Nick Koston
52088009e4 bot comment 2026-01-13 17:16:41 -10:00
J. Nick Koston
44f9e8507a safety 2026-01-13 17:12:03 -10:00
J. Nick Koston
02b2d4f1a2 fix events 2026-01-13 17:05:45 -10:00
J. Nick Koston
23e6a9a27a narrow 2026-01-13 17:04:50 -10:00
J. Nick Koston
f027b32c18 fix events 2026-01-13 17:00:43 -10:00
J. Nick Koston
54665edd18 use push_back, generates much simpler code for pod types 2026-01-13 16:57:34 -10:00
J. Nick Koston
5580d11a2e tweak 2026-01-13 16:53:41 -10:00
J. Nick Koston
a3061a7488 [api] Reduce BatchItem size from 12 to 8 bytes using switch dispatch 2026-01-13 16:47:55 -10:00
J. Nick Koston
47ee2f4ad9 [wifi] Use StaticVector for WiFi listeners with per-type compile-time sizing (#13197) 2026-01-14 02:20:39 +00:00
J. Nick Koston
2efc51b28c Merge remote-tracking branch 'upstream/dev' into integration 2026-01-13 15:46:38 -10:00
J. Nick Koston
2793e33baf [logger] Use StaticVector for log listeners with compile-time sizing (#13196)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-13 15:43:17 -10:00
J. Nick Koston
5dfdd05122 [logger] Use RAII guards for recursion protection and optimize hot path (#13194)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-13 15:43:02 -10:00
J. Nick Koston
316b41710c Merge remote-tracking branch 'origin/request_log_listener' into integration 2026-01-13 14:28:14 -10:00
J. Nick Koston
32fe66c2ae Merge branch 'wifi_listeners_static_vector' into integration 2026-01-13 14:28:04 -10:00
J. Nick Koston
ad64a1b7b4 document, document, documet 2026-01-13 14:21:35 -10:00
J. Nick Koston
9567046e9c [wifi] Use StaticVector for WiFi listeners with per-type compile-time sizing 2026-01-13 14:20:04 -10:00
J. Nick Koston
e01e616aad address bot comments 2026-01-13 14:18:58 -10:00
J. Nick Koston
52574e2fd4 Update esphome/components/logger/__init__.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-13 14:12:48 -10:00
J. Nick Koston
3f3d2b3df2 Merge branch 'request_log_listener' into integration 2026-01-13 14:00:40 -10:00
J. Nick Koston
1d2fa12911 [logger] Use StaticVector for log listeners with compile-time sizing 2026-01-13 13:59:37 -10:00
J. Nick Koston
bc035e06fd Merge branch 'logger_raii' into integration 2026-01-13 13:40:25 -10:00
J. Nick Koston
6ed7412634 Update esphome/components/logger/logger.h
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-13 13:36:18 -10:00
J. Nick Koston
fdb7b800df Update esphome/components/logger/logger.h
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-13 13:36:12 -10:00
J. Nick Koston
c2c616a2ec Merge branch 'logger_raii' into integration 2026-01-13 13:34:48 -10:00
Cougar
be12e3667a [ssd1306_i2c] fix "SSD1306 72x40" display initialization (add SSD1306B Iref setup) (#13148) 2026-01-13 18:30:15 -05:00
J. Nick Koston
421646030b Merge branch 'dev' into logger_raii 2026-01-13 13:29:24 -10:00
Clyde Stubbs
52c631384a [epaper_spi] Add Waveshare 2.13v3 (#13117) 2026-01-13 18:28:24 -05:00
Jonathan Swoboda
45e000f091 [ota] Mark partition valid when OTA begins to prevent rollback blocking (#13195)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 18:27:45 -05:00
tomaszduda23
e45cad45fe [nrf52,zigbee] Add binary output as switch (#13083)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-01-13 17:39:28 -05:00
J. Nick Koston
f852fb4300 tweak 2026-01-13 12:14:49 -10:00
J. Nick Koston
92f15e82d7 [logger] Use RAII guards for recursion protection and optimize hot path 2026-01-13 12:11:38 -10:00
J. Nick Koston
3d74d1e7f0 [libretiny] Regenerate boards, enable Cortex-M4 atomics, and consolidate platform code (#13191) 2026-01-13 21:39:11 +00:00
J. Nick Koston
a060d1d044 [wifi] Fix ESP8266 disconnect callback order to set error flag before notifying listeners (#13189) 2026-01-13 11:33:36 -10:00
J. Nick Koston
52c34441b1 Merge branch 'libretiny_regen_fixes' into integration 2026-01-13 09:50:52 -10:00
Kevin Ahrendt
733f57da50 [i2s_audio] Bugfix: Buffer overflow in software volume control (#13190) 2026-01-13 09:42:36 -10:00
dependabot[bot]
4d96c60696 Bump yamllint from 1.37.1 to 1.38.0 (#13192)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-13 09:36:58 -10:00
J. Nick Koston
ae2575b33f fix 2026-01-13 09:34:43 -10:00
J. Nick Koston
3d51413706 lets not miss it 2026-01-13 09:33:46 -10:00
J. Nick Koston
6fd6b46ef8 [libretiny] Regenerate boards, enable Cortex-M4 atomics, and consolidate platform code 2026-01-13 09:31:05 -10:00
J. Nick Koston
ec38ffc310 [libretiny] Regenerate boards, enable Cortex-M4 atomics, and consolidate platform code 2026-01-13 09:09:49 -10:00
J. Nick Koston
a45cbc6595 [libretiny] Regenerate boards, enable Cortex-M4 atomics, and consolidate platform code 2026-01-13 09:07:04 -10:00
J. Nick Koston
62bce73b7e Merge branch 'fix_callback_order_wifi_8266' into integration 2026-01-13 08:39:42 -10:00
J. Nick Koston
39f77a3315 [wifi] Fix ESP8266 disconnect callback order to set error flag before notifying listeners 2026-01-13 08:14:46 -10:00
J. Nick Koston
714188cfd8 [wifi] Fix ESP8266 disconnect callback order to set error flag before notifying listeners 2026-01-13 08:13:37 -10:00
J. Nick Koston
3d40979c96 [mqtt] Avoid intermediate string allocations in publish calls (#13174) 2026-01-13 08:05:04 -10:00
J. Nick Koston
7fed9144a6 [api] Use stack buffer for VERY_VERBOSE proto message dumps (#13176) 2026-01-13 08:04:48 -10:00
J. Nick Koston
7abb374f2a [improv_serial] Use stack buffers for webserver URL formatting (#13175) 2026-01-13 08:04:33 -10:00
Jonathan Swoboda
5d90f170e5 Merge branch 'release' into dev 2026-01-13 11:55:58 -05:00
Jonathan Swoboda
6e01c4f86e Merge pull request #13188 from esphome/bump-2025.12.6
2025.12.6
2026-01-13 11:55:44 -05:00
Jonathan Swoboda
f4c17e15ea Bump version to 2025.12.6 2026-01-13 11:01:21 -05:00
J. Nick Koston
d6507ce329 [esphome] Fix OTA backend abort not being called on error (#13182) 2026-01-13 11:01:21 -05:00
Jonathan Swoboda
9504e92458 [remote_transmitter] Fix ESP8266 timing by using busy loop (#13172)
Co-authored-by: Claude <noreply@anthropic.com>
2026-01-13 11:01:21 -05:00
Jonathan Swoboda
3911991de2 [packet_transport] Fix packet size check to account for round4 padding (#13165)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 11:01:21 -05:00
Jonathan Swoboda
dede47477b [ltr_als_ps] Remove incorrect device_class from count sensors (#13167)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 11:01:21 -05:00
Jonathan Swoboda
dca8def0f2 [seeed_mr24hpc1] Add ifdef guards for conditional entity types (#13147)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 11:01:21 -05:00
Samuel Sieb
a1727a8901 [espnow] fix channel validation (#13057) 2026-01-13 11:01:20 -05:00
J. Nick Koston
d49f176f31 Merge remote-tracking branch 'upstream/dev' into integration 2026-01-12 22:33:50 -10:00
Samuel Sieb
48f5296d24 [ld24xx] add id to support extending (#13183)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2026-01-12 22:32:20 -10:00
Samuel Sieb
1327776d5b [bme68x_bsec2] use EntityBase instead of Component for the id (#13185)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2026-01-12 22:32:11 -10:00
J. Nick Koston
d378b40235 Merge remote-tracking branch 'upstream/dev' into integration 2026-01-12 21:54:44 -10:00
J. Nick Koston
df4a3e8915 [socket] Call lwip_read/lwip_write directly on ESP32 to reduce network I/O latency (#13179) 2026-01-13 01:47:11 -06:00
Keith Burzinski
6823e17b3b [ir_rf_proxy] New component (#12985)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-01-13 07:44:24 +00:00
J. Nick Koston
eb4d6ce29f Merge remote-tracking branch 'upstream/dev' into integration 2026-01-12 20:56:10 -10:00
J. Nick Koston
675103bed0 [esphome] Fix OTA backend abort not being called on error (#13182) 2026-01-12 20:55:40 -10:00
J. Nick Koston
6c043be4d3 [ci] Add format_hex_pretty to heap-allocating helper lint check (#13178) 2026-01-12 20:55:23 -10:00
J. Nick Koston
a95f2fb002 Merge remote-tracking branch 'origin/ota_fix_abort' into integration 2026-01-12 20:18:30 -10:00
J. Nick Koston
1a30851b0a [esphome] Fix OTA backend abort not being called on error 2026-01-12 20:17:38 -10:00
J. Nick Koston
a74cba61df Merge branch 'lwip_read_write' into integration 2026-01-12 20:04:18 -10:00
J. Nick Koston
47f32d60b5 [socket] Call lwip_read/lwip_write directly on ESP32 to reduce network I/O latency 2026-01-12 20:03:45 -10:00
J. Nick Koston
e5e977c054 Merge remote-tracking branch 'upstream/dev' into integration 2026-01-12 17:41:28 -10:00
Rodrigo Martín
e9469cbe48 [mqtt] templatable state and command topics (#12441)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-01-12 17:40:27 -10:00
J. Nick Koston
5046ca164a fix packed buffer 2026-01-12 17:23:09 -10:00
J. Nick Koston
3a7cf3ac95 Merge branch 'improv_serial_webserver' into integration 2026-01-12 17:17:09 -10:00
J. Nick Koston
6e82606419 cleanup 2026-01-12 17:10:21 -10:00
J. Nick Koston
26ed3d24c1 Merge branch 'api_debug_logging' into integration 2026-01-12 17:07:10 -10:00
J. Nick Koston
b24a1a9e25 cleanup 2026-01-12 17:06:49 -10:00
J. Nick Koston
5e911e20bc tweaks 2026-01-12 17:00:26 -10:00
J. Nick Koston
3206c5664f Merge branch 'api_debug_logging' into integration 2026-01-12 16:55:03 -10:00
J. Nick Koston
b5f6a6e24d [api] Use stack buffer for VERY_VERBOSE proto message dumps 2026-01-12 16:51:52 -10:00
dependabot[bot]
5890cdf69a Bump github/codeql-action from 4.31.9 to 4.31.10 (#13173)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-12 16:31:51 -10:00
J. Nick Koston
e1a0398160 [improv_serial] Use stack buffers for webserver URL formatting 2026-01-12 16:27:38 -10:00
J. Nick Koston
9876788e65 Merge branch 'more_heap_cleanup' into integration 2026-01-12 15:52:46 -10:00
J. Nick Koston
4a03ff898f Merge remote-tracking branch 'upstream/dev' into integration 2026-01-12 15:52:36 -10:00
J. Nick Koston
410507d476 [mqtt] Avoid intermediate string allocations in publish calls 2026-01-12 15:46:16 -10:00
lullius
297f05d600 [tuya] add color_type_lowercase option (#13101)
Co-authored-by: lullius <>
2026-01-12 18:08:33 -05:00
Jonathan Swoboda
54fc10714d [remote_transmitter] Fix ESP8266 timing by using busy loop (#13172)
Co-authored-by: Claude <noreply@anthropic.com>
2026-01-12 18:06:41 -05:00
J. Nick Koston
889886909b [core] Soft deprecate heap-allocating string helpers to prevent fragmentation patterns (#13156) 2026-01-12 12:48:54 -10:00
J. Nick Koston
655e2b43cb [infrared] Use set_data() for vector timings in control() (#13171) 2026-01-12 15:27:42 -06:00
J. Nick Koston
81e639a6ba [core] Migrate callers and soft deprecate get_mac_address()/get_mac_address_pretty() (#13157) 2026-01-12 19:35:49 +00:00
Jonathan Swoboda
f9ffd134df [packet_transport] Fix packet size check to account for round4 padding (#13165)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 14:10:15 -05:00
Jonathan Swoboda
c50bf45496 [ltr_als_ps] Remove incorrect device_class from count sensors (#13167)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 14:09:54 -05:00
J. Nick Koston
9f9341a700 [web_server] Fix select compilation error in v1 (#13169) 2026-01-12 18:42:10 +00:00
tomaszduda23
71d532a349 [nrf52,sdk] Add framework version support (#12489) 2026-01-12 13:31:09 -05:00
Jasper van der Neut - Stulen
61a89a97d7 [deep_sleep] Fix GPIO wakeup on ESP32-C3/C6 (#12803) 2026-01-12 13:03:13 -05:00
Jasper van der Neut - Stulen
0c3433d056 [deep_sleep] Fix GPIO wakeup comment (#12815) 2026-01-12 12:57:58 -05:00
mikaabra
7e1cda8f9f [esp32_can] Add listen-only mode to esp32_can component (#13084)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 12:50:59 -05:00
J. Nick Koston
7f0e4eaa84 [nfc] Use stack-based hex formatting in pn7150/pn7160 components (#13163) 2026-01-12 07:38:39 -10:00
J. Nick Koston
8cccfa5369 [mqtt][prometheus][graph] Migrate value_accuracy_to_string() to stack-based alternative (#13159)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-12 07:38:20 -10:00
J. Nick Koston
7ea6bcef88 [api] Use stack buffer for bytes field dumping in proto message logs (#13162) 2026-01-12 07:37:58 -10:00
tomaszduda23
353daa97d0 [nrf52,zigbee] Warning if spaces in description (#13114)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-01-12 14:45:15 +00:00
Jas Strong
6c68ebe86e [rd03d] Filter targets with sentinel speed values (#13146)
Co-authored-by: jas <jas@asspa.in>
2026-01-12 09:25:43 -05:00
J. Nick Koston
62565304e4 Merge branch 'nfc_hex' into integration 2026-01-12 00:33:54 -10:00
J. Nick Koston
51dfb3af5e [nfc] Use stack-based hex formatting in pn7150/pn7160 components 2026-01-12 00:23:09 -10:00
J. Nick Koston
40b278f485 [nfc] Use stack-based hex formatting in pn7150/pn7160 components 2026-01-12 00:21:40 -10:00
J. Nick Koston
ed34a98f48 Merge branch 'api_format_hex_pretty_to' into integration 2026-01-12 00:04:50 -10:00
J. Nick Koston
d7e7e7849f [api] Use stack buffer for bytes field dumping in proto message logs 2026-01-11 19:59:05 -10:00
dependabot[bot]
29cef3bc5d Bump aioesphomeapi from 43.12.0 to 43.13.0 (#13160)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-11 19:26:40 -10:00
Keith Burzinski
83eebdf15d [infrared] Implement experimental API/Core/component for new component/entity type (#13129)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-01-12 05:01:23 +00:00
J. Nick Koston
595217786c [tuya][rc522][remote_base] Migrate format_hex_pretty() to stack-based alternatives (#13158) 2026-01-12 04:47:57 +00:00
J. Nick Koston
f22e42addc Merge branch 'dep_heap_fragmenting_helpers' into integration 2026-01-11 18:28:51 -10:00
J. Nick Koston
f70cb78d52 fix 2026-01-11 18:28:37 -10:00
J. Nick Koston
25e9e84ca5 Merge branch 'dep_heap_fragmenting_helpers' into integration 2026-01-11 18:27:29 -10:00
J. Nick Koston
d807f93c66 cleanup 2026-01-11 18:27:05 -10:00
J. Nick Koston
7a33793304 Merge branch 'format_hex_to_more' into integration 2026-01-11 18:24:55 -10:00
J. Nick Koston
f4437c9eaa Merge branch 'value_accuracy_to_string_to' into integration 2026-01-11 18:24:50 -10:00
J. Nick Koston
d52ea47552 [mqtt][prometheus][graph] Migrate value_accuracy_to_string() to stack-based alternative 2026-01-11 17:54:48 -10:00
J. Nick Koston
912f94d1e8 [api] Use StringRef for HomeassistantServiceMap.value to eliminate heap allocations (#13154)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-11 17:54:06 -10:00
J. Nick Koston
ea8ae2ae60 [climate] Return StringRef from get_custom_fan_mode() and get_custom_preset() (#13103) 2026-01-11 17:53:06 -10:00
J. Nick Koston
e1aac7601d [event] Return StringRef from get_last_event_type() (#13104) 2026-01-11 17:52:54 -10:00
J. Nick Koston
f1b11b1855 [light] Return StringRef from LightEffect::get_name() and LightState::get_effect_name() (#13105) 2026-01-11 17:52:39 -10:00
J. Nick Koston
6e6d545963 [tuya][rc522][remote_base] Migrate format_hex_pretty() to stack-based alternatives 2026-01-11 17:44:43 -10:00
J. Nick Koston
23f9f70b71 [select] Return StringRef from current_option() (#13095) 2026-01-11 17:40:43 -10:00
J. Nick Koston
eeeae53f76 [fan] Return StringRef from get_preset_mode() for safety and modern API (#13092) 2026-01-11 17:40:09 -10:00
J. Nick Koston
a29ad99661 Merge branch 'mac_address_stack' into integration 2026-01-11 17:35:18 -10:00
J. Nick Koston
c8fabf214e Merge branch 'dep_heap_fragmenting_helpers' into integration 2026-01-11 17:35:09 -10:00
J. Nick Koston
291db7c5a9 [core] Migrate callers and deprecate get_mac_address()/get_mac_address_pretty() 2026-01-11 17:34:03 -10:00
J. Nick Koston
cea8c9b212 [core] Deprecate heap-allocating string helpers to prevent fragmentation patterns 2026-01-11 17:26:42 -10:00
J. Nick Koston
45c0796e40 [ci] Add RP2040 to memory impact analysis (#13134) 2026-01-11 17:19:00 -10:00
J. Nick Koston
38e2e4a56d [runtime_stats] Fix log output formatting alignment (#13155) 2026-01-11 17:18:49 -10:00
J. Nick Koston
52132ea3bc [ch422g][lc709203f][qmc5883l] Avoid heap allocation in status_set_warning calls (#13152) 2026-01-11 17:18:37 -10:00
J. Nick Koston
ace3ff2170 [safe_mode] Conditionally compile callback when on_safe_mode is configured (#13136) 2026-01-11 17:18:24 -10:00
J. Nick Koston
26e90b4ca6 [light] Move LightColorValues::lerp() out of header to reduce code duplication (#13138) 2026-01-11 17:18:13 -10:00
J. Nick Koston
684790c2ab [web_server_idf] Reduce heap usage in DefaultHeaders and auth (#13141) 2026-01-11 17:17:57 -10:00
J. Nick Koston
6a3737bac3 [improv_serial] Use int8_to_str to avoid heap allocation for RSSI formatting (#13149) 2026-01-11 17:17:44 -10:00
J. Nick Koston
723ca57617 [uptime] Format text sensor output on stack to avoid heap allocations (#13150)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-11 17:17:32 -10:00
J. Nick Koston
909bd1074a [wifi] Fix captive portal/improv only attempting last configured network (#13086)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-11 17:17:18 -10:00
J. Nick Koston
68064dc974 [web_server] Fix v1 compilation on ESP-IDF by adding missing write method (#13153) 2026-01-11 17:17:07 -10:00
Jonathan Swoboda
742d724e65 [seeed_mr24hpc1] Add ifdef guards for conditional entity types (#13147)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 22:16:55 -05:00
J. Nick Koston
69dd056516 Merge branch 'complete_removal_no_zero_copy' into integration 2026-01-11 16:12:57 -10:00
J. Nick Koston
024097b635 cleanup 2026-01-11 16:05:33 -10:00
J. Nick Koston
0d30c2cdfd drop no zero copy 2026-01-11 16:03:26 -10:00
J. Nick Koston
2c0954c03c [api] Use StringRef for HomeassistantServiceMap.value to eliminate heap allocations 2026-01-11 16:00:44 -10:00
J. Nick Koston
f6eebe9b27 Merge branch 'web_server_1' into integration 2026-01-11 15:40:15 -10:00
J. Nick Koston
78edba8db5 [web_server] Fix v1 compilation on ESP-IDF by adding missing write method 2026-01-11 15:39:09 -10:00
J. Nick Koston
1cf3a2bc47 [web_server] Fix v1 compilation on ESP-IDF by adding missing write method 2026-01-11 15:37:22 -10:00
J. Nick Koston
3bd5dc7a8e Merge branch 'status_set_warning_str_print' into integration 2026-01-11 15:10:12 -10:00
J. Nick Koston
3e2f12d5d6 [ch422g][lc709203f][qmc5883l] Avoid heap allocation in status_set_warning calls 2026-01-11 15:09:30 -10:00
J. Nick Koston
ce79556cbd Merge remote-tracking branch 'origin/uptime_sensor_text' into integration 2026-01-11 14:52:53 -10:00
J. Nick Koston
a36b3fc81b Merge remote-tracking branch 'origin/improv_serial_format' into integration 2026-01-11 14:52:48 -10:00
J. Nick Koston
cdd09bdb94 preen 2026-01-11 14:46:14 -10:00
J. Nick Koston
c19e129821 another pass at reducing the logic 2026-01-11 14:40:50 -10:00
J. Nick Koston
f14d1edcc9 [uptime] Format text sensor output on stack to avoid heap allocations 2026-01-11 14:33:31 -10:00
J. Nick Koston
cda750e6b7 [improv_serial] Use int8_to_str to avoid heap allocation for RSSI formatting 2026-01-11 14:04:48 -10:00
dependabot[bot]
5ae46a4369 Bump aioesphomeapi from 43.11.0 to 43.12.0 (#13139)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-11 09:49:17 -10:00
J. Nick Koston
7666644ad8 Merge branch 'web_server_idf_cleanup_strings' into integration 2026-01-11 09:01:16 -10:00
J. Nick Koston
d7dd6a5cb8 static, less heap 2026-01-11 09:00:20 -10:00
J. Nick Koston
1fa86a7505 tweak comment 2026-01-11 08:46:02 -10:00
J. Nick Koston
c6bb62cc36 tweak comment 2026-01-11 08:45:54 -10:00
J. Nick Koston
0e6a798b2f Merge branch 'web_server_idf_cleanup_strings' into integration 2026-01-11 08:42:02 -10:00
J. Nick Koston
cd37e3c1f6 [web_server_idf] Reduce string allocations in HTTP header storage and auth 2026-01-11 08:39:11 -10:00
J. Nick Koston
5ca7b885e8 Merge branch 'light_color_values' into integration 2026-01-11 01:18:54 -10:00
J. Nick Koston
bc91fbec83 [light] Move LightColorValues::lerp() out of header to reduce code duplication 2026-01-11 01:03:08 -10:00
J. Nick Koston
31c63ef2b4 Merge branch 'safe_mode_ifdef' into integration 2026-01-10 21:06:01 -10:00
J. Nick Koston
ce336b7745 [safe_mode] Conditionally compile callback when on_safe_mode is configured 2026-01-10 20:35:11 -10:00
J. Nick Koston
a30d12fb89 [safe_mode] Conditionally compile callback when on_safe_mode is configured 2026-01-10 20:34:05 -10:00
J. Nick Koston
b480b8f572 Merge remote-tracking branch 'upstream/dev' into integration 2026-01-10 17:09:03 -10:00
J. Nick Koston
a1395af763 [helpers] Add format_hex_prefixed_to for "0x" prefixed hex formatting (#13115) 2026-01-10 17:07:21 -10:00
J. Nick Koston
6222fae907 [libretiny] Disable BLE stack on BK7231N to save ~21KB RAM (#13131) 2026-01-10 16:43:15 -10:00
J. Nick Koston
e34532f283 [sensor] Use C++17 nested namespace syntax (#13116) 2026-01-10 21:42:35 -05:00
Keith Burzinski
f2eb61a767 [api] Proto code generator changes for #12985 (#13100)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-01-10 15:43:27 -10:00
dependabot[bot]
5725a4840e Bump aioesphomeapi from 43.10.1 to 43.11.0 (#13132)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-11 01:09:25 +00:00
J. Nick Koston
de82f96ccb [core] Rename FixedVector::shrink_to_fit() to release() for clarity (#13130) 2026-01-11 00:43:31 +00:00
J. Nick Koston
a295a552f9 Merge remote-tracking branch 'upstream/dev' into integration 2026-01-10 13:06:24 -10:00
Jonathan Swoboda
6c981d8b71 [esp32_hosted] Bump component versions (#13118)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 10:26:42 -10:00
Jas Strong
c03faf2d9a [aqi] Fix precision loss for low PM concentration values (#13120)
Co-authored-by: jas <jas@asspa.in>
2026-01-10 09:40:14 -10:00
J. Nick Koston
dff01ab8f3 Merge branch 'sensor_ns' into integration 2026-01-09 23:14:36 -10:00
J. Nick Koston
3392216b0b [sensor] Use C++17 nested namespace syntax 2026-01-09 23:12:27 -10:00
J. Nick Koston
523e27e103 Merge branch 'fan_get_preset_mode_safer' into integration 2026-01-09 22:01:43 -10:00
J. Nick Koston
4289ba23f2 Merge branch 'light_std_string' into integration 2026-01-09 22:01:32 -10:00
J. Nick Koston
90e6ff2922 Merge branch 'select_current_option' into integration 2026-01-09 22:01:17 -10:00
J. Nick Koston
c20d20bf73 Merge branch 'climate_string_view' into integration 2026-01-09 22:01:10 -10:00
J. Nick Koston
6a280f8e2b Merge branch 'event_string_view' into integration 2026-01-09 22:01:04 -10:00
J. Nick Koston
3fd31581d6 cleanup 2026-01-09 21:59:19 -10:00
J. Nick Koston
3178ae32dd missed some 2026-01-09 21:56:14 -10:00
J. Nick Koston
3b5b9445fe Merge remote-tracking branch 'origin/integration' into integration 2026-01-09 17:05:11 -10:00
J. Nick Koston
db7bba744d Merge remote-tracking branch 'upstream/dev' into integration 2026-01-09 17:05:03 -10:00
J. Nick Koston
54668648df fix 2026-01-09 16:56:02 -10:00
J. Nick Koston
54d3ea4098 fix: use simple .c_str() for ESP8266 compatibility 2026-01-09 16:54:21 -10:00
J. Nick Koston
08bd49c038 fix 2026-01-09 16:50:42 -10:00
J. Nick Koston
a3a4c12f3e try 2026-01-09 16:47:40 -10:00
J. Nick Koston
2eb98c19f7 strinferf 2026-01-09 16:43:28 -10:00
J. Nick Koston
fef7b6093d Merge branch 'dev' into event_string_view 2026-01-09 16:40:12 -10:00
J. Nick Koston
74f2619097 Merge branch 'dev' into select_current_option 2026-01-09 16:39:43 -10:00
J. Nick Koston
1593b6f10d Merge branch 'dev' into climate_string_view 2026-01-09 16:39:08 -10:00
J. Nick Koston
0aab72a462 Merge remote-tracking branch 'upstream/dev' into integration 2026-01-09 16:38:32 -10:00
esphomebot
da7680f7d9 Update webserver local assets to 20260110-013228 (#13113)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-01-09 16:38:01 -10:00
J. Nick Koston
2034e7d39c Merge remote-tracking branch 'origin/climate_string_view' into climate_string_view 2026-01-09 16:36:59 -10:00
J. Nick Koston
f01aeded4d tests update 2026-01-09 16:36:17 -10:00
J. Nick Koston
cacbb017c0 fix 2026-01-09 16:35:04 -10:00
J. Nick Koston
682b2104f2 tweak comments 2026-01-09 16:31:01 -10:00
J. Nick Koston
7bc970809a tweak comments 2026-01-09 16:29:38 -10:00
J. Nick Koston
3dbca6692e stringref 2026-01-09 16:28:21 -10:00
J. Nick Koston
48906aaa51 Merge remote-tracking branch 'origin/dev' into integration 2026-01-09 16:21:50 -10:00
J. Nick Koston
7a64d834d1 Merge remote-tracking branch 'origin/light_std_string' into light_std_string 2026-01-09 16:19:56 -10:00
J. Nick Koston
dc49f4c180 fix 2026-01-09 16:19:43 -10:00
J. Nick Koston
15734c63a1 back to print 2026-01-09 16:18:35 -10:00
J. Nick Koston
33d2140f1c stringref 2026-01-09 16:13:17 -10:00
J. Nick Koston
606ce9cfd2 stringref 2026-01-09 16:12:12 -10:00
J. Nick Koston
aa760446af Merge branch 'dev' into select_current_option 2026-01-09 16:07:32 -10:00
J. Nick Koston
60a06a5aac Merge branch 'dev' into light_std_string 2026-01-09 16:01:07 -10:00
J. Nick Koston
c8f86f0a94 stringref 2026-01-09 15:57:20 -10:00
J. Nick Koston
ca31c975be stringref 2026-01-09 15:57:06 -10:00
J. Nick Koston
ec03a0155b stringref 2026-01-09 15:52:11 -10:00
J. Nick Koston
5f6cfb4feb Merge remote-tracking branch 'origin/fan_get_preset_mode_safer' into fan_get_preset_mode_safer 2026-01-09 15:40:31 -10:00
J. Nick Koston
1fdacd9d22 use stringref 2026-01-09 15:40:18 -10:00
J. Nick Koston
ab3ab6f521 Merge remote-tracking branch 'upstream/dev' into fan_get_preset_mode_safer 2026-01-09 15:36:04 -10:00
J. Nick Koston
9ef492e95a Merge branch 'dev' into fan_get_preset_mode_safer 2026-01-09 15:35:19 -10:00
Douwe
cea2878b55 [water_heater] (3/4) Implement web_server for new water_heater component (#12511)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-01-09 15:25:42 -10:00
J. Nick Koston
a5b906516d Merge branch 'dev' into light_std_string 2026-01-09 14:03:26 -10:00
J. Nick Koston
2e6b22aa62 Merge remote-tracking branch 'origin/light_std_string' into light_std_string 2026-01-09 14:02:57 -10:00
J. Nick Koston
66d978ade1 comment 2026-01-09 14:02:37 -10:00
Jonathan Swoboda
e0ff7fdaa1 [esp32_hosted] Add HTTP-based coprocessor firmware update support (#13090)
Co-authored-by: Claude <noreply@anthropic.com>
2026-01-09 17:36:56 -05:00
tomaszduda23
3c9b300c46 [CI] skip endpoint check due to test grouping (#13111) 2026-01-09 22:13:37 +00:00
J. Nick Koston
9bcdcedd94 Merge branch 'dev' into light_std_string 2026-01-09 09:48:20 -10:00
J. Nick Koston
ed07c7c7ee cleanups 2026-01-09 09:47:43 -10:00
J. Nick Koston
32f90b2855 [mdns] Remove deprecated api password from test configuration (#13107) 2026-01-09 09:40:24 -10:00
J. Nick Koston
2fb7c0d453 [mapping] Fix test SPI data rate for RP2040 (#13108) 2026-01-09 09:39:53 -10:00
dependabot[bot]
7935fba4b1 Bump esphome-dashboard from 20251013.0 to 20260110.0 (#13109)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-09 14:37:53 -05:00
Stuart Parmenter
ab32b93928 [hub75] Fix gamma_correct to use enum value instead of key string (#13102)
Co-authored-by: Claude <noreply@anthropic.com>
2026-01-09 13:34:04 -06:00
J. Nick Koston
999d2d7f7e [light] Return std::string_view from LightEffect::get_name() and LightState::get_effect_name() 2026-01-09 09:11:58 -10:00
J. Nick Koston
a693e631bb [light] Return std::string_view from LightEffect::get_name() and LightState::get_effect_name() 2026-01-09 08:38:08 -10:00
J. Nick Koston
775c6a077d [light] Return std::string_view from LightEffect::get_name() and LightState::get_effect_name() 2026-01-09 08:35:37 -10:00
J. Nick Koston
8a3e26e6e9 [event] Return std::string_view from get_last_event_type() 2026-01-09 08:07:57 -10:00
J. Nick Koston
56ced4a403 [climate] Return std::string_view from get_custom_fan_mode() and get_custom_preset() 2026-01-09 07:47:42 -10:00
J. Nick Koston
265bc55c28 [climate] Return std::string_view from get_custom_fan_mode() and get_custom_preset() 2026-01-09 07:43:52 -10:00
J. Nick Koston
6dcbc24864 [climate] Return std::string_view from get_custom_fan_mode() and get_custom_preset() 2026-01-09 07:43:01 -10:00
J. Nick Koston
3d54ccac65 Revert "[wifi] Disable SoftAP support on Arduino ESP32 when ap: not configured" (#13099) 2026-01-09 09:35:19 -05:00
Keith Burzinski
c40f44f4bd [remote_base] Add zero-copy packed sint32 decoder for #12985 (#13093) 2026-01-09 04:06:03 -06:00
Keith Burzinski
62cb08c3dc [api] Add methods supporting efficient packed repeated sint32 field encoding for #12985 (#13094) 2026-01-09 04:05:47 -06:00
J. Nick Koston
26671cb1ee [select] Return std::string_view from current_option() 2026-01-08 23:05:30 -10:00
J. Nick Koston
6596186240 actually commit thte tests 2026-01-08 23:00:34 -10:00
J. Nick Koston
e8465bfcda [select] Return std::string_view from current_option() 2026-01-08 22:58:49 -10:00
J. Nick Koston
b9b3adae0d Merge branch 'dev' into fan_get_preset_mode_safer 2026-01-08 22:26:49 -10:00
J. Nick Koston
872b2ec7db address copilot review comments 2026-01-08 22:25:16 -10:00
J. Nick Koston
a3553dab1c address copilot review comments 2026-01-08 22:24:38 -10:00
J. Nick Koston
cd76747b25 tests 2026-01-08 22:19:52 -10:00
J. Nick Koston
0ebe99ccf5 tests 2026-01-08 22:00:04 -10:00
J. Nick Koston
04eba0563a tests 2026-01-08 21:58:20 -10:00
Stuart Parmenter
7576e032f8 [hub75] Fix depth and gamma mode defines (#13091) 2026-01-09 01:56:51 -06:00
J. Nick Koston
1e30f54dff cleanup 2026-01-08 21:49:59 -10:00
J. Nick Koston
6c502d879b cleanup 2026-01-08 21:49:15 -10:00
J. Nick Koston
04ffa74643 if we are going ot break it, string view 2026-01-08 21:44:40 -10:00
J. Nick Koston
ff0b1a24c7 [fan] Make get_preset_mode() return empty string instead of nullptr for safety 2026-01-08 21:35:18 -10:00
J. Nick Koston
b24dbf77e4 Merge remote-tracking branch 'upstream/dev' into integration 2026-01-08 21:01:17 -10:00
J. Nick Koston
cd43b4114e [api] Fire on_client_disconnected trigger after removing client from list (#13088) 2026-01-08 20:36:24 -10:00
J. Nick Koston
2c165e4817 [web_server] Use centralized length constants for buffer sizing (#13073) 2026-01-08 20:36:08 -10:00
J. Nick Koston
5afe4b7b12 [wifi] Warn when AP is configured without captive_portal or web_server (#13087) 2026-01-08 16:41:34 -10:00
Anton Viktorov
dcb8c994cc [ac_dimmer] Added support for ESP-IDF (5+) (#7072)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: J. Nick Koston <nick+github@koston.org>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-08 15:24:01 -10:00
J. Nick Koston
7f5887581d Merge branch 'ap_misconfigured_warn' into integration 2026-01-08 14:55:32 -10:00
J. Nick Koston
12be08f85e [wifi] Warn when AP is configured without captive_portal or web_server 2026-01-08 14:54:41 -10:00
J. Nick Koston
8c6a3f8d62 Merge branch 'blind_retry' into integration 2026-01-08 14:27:48 -10:00
J. Nick Koston
23eec55ed3 [wifi] Fix captive portal/improv only attempting last configured network 2026-01-08 14:26:24 -10:00
J. Nick Koston
cb383c8049 [wifi] Fix captive portal/improv only attempting last configured network 2026-01-08 14:23:44 -10:00
J. Nick Koston
ca45c0de66 Merge remote-tracking branch 'upstream/dev' into integration 2026-01-08 12:16:22 -10:00
Rodrigo Martín
012a1e2afd [mqtt] Include session_present and reason parameters in connection callbacks (#12413)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-01-08 22:05:53 +00:00
J. Nick Koston
d4969f581a [wifi] Limit ignored disconnect events on LibreTiny to speed up AP failover (#13070) 2026-01-08 11:42:30 -10:00
J. Nick Koston
40f108116b [mqtt] Reduce heap allocations in topic string building (#13072) 2026-01-08 11:42:18 -10:00
J. Nick Koston
52459d1bc7 [wifi] Fix infinite roaming when best-signal AP is crashed/broken (#13071) 2026-01-08 11:42:06 -10:00
dependabot[bot]
325c938074 Bump ruff from 0.14.10 to 0.14.11 (#13082)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-01-08 20:57:30 +00:00
J. Nick Koston
423a617b15 [core] Improve minimum_chip_revision warning for PSRAM users (#13074) 2026-01-08 10:52:27 -10:00
J. Nick Koston
eb5c4f34e2 [wifi] Disable SoftAP support on Arduino ESP32 when ap: not configured (#13076) 2026-01-08 10:51:58 -10:00
J. Nick Koston
c9ab4ca018 [libretiny] Bump to 1.9.2 (#13077) 2026-01-08 10:51:35 -10:00
J. Nick Koston
da0b01f4d0 [logger] Enable loop disable optimization for LibreTiny task log buffer (#13078) 2026-01-08 10:51:18 -10:00
J. Nick Koston
7ff590e1da Merge branch 'disable_loop_when_buffer_empty_' into integration 2026-01-07 23:35:13 -10:00
J. Nick Koston
d402b0c391 [logger] Enable loop disable optimization for LibreTiny task log buffer 2026-01-07 23:34:39 -10:00
J. Nick Koston
ebd484495e Merge branch 'bump_libretiny_192' into integration 2026-01-07 23:07:52 -10:00
J. Nick Koston
36e748609e [libretiny] Bump to 1.9.2 2026-01-07 23:01:00 -10:00
J. Nick Koston
57152edf23 Merge branch 'wifi_ard_esp32' into integration 2026-01-07 22:50:06 -10:00
J. Nick Koston
1c3f421746 [wifi] Disable SoftAP support on Arduino ESP32 when ap: not configured 2026-01-07 22:42:49 -10:00
J. Nick Koston
182063d5c6 Merge remote-tracking branch 'origin/reuse_constexpr_web_server' into integration 2026-01-07 22:06:54 -10:00
J. Nick Koston
f8f6ad942b Merge branch 'min_chip_psram' into integration 2026-01-07 22:06:40 -10:00
J. Nick Koston
fd1ad89a33 [core] Improve minimum_chip_revision warning for PSRAM users 2026-01-07 22:05:40 -10:00
J. Nick Koston
735aca89ee [web_server] Use centralized length constants for buffer sizing 2026-01-07 20:03:18 -10:00
J. Nick Koston
aa3bed7089 [web_server] Use centralized length constants for buffer sizing 2026-01-07 20:01:54 -10:00
J. Nick Koston
40cd6aa18b [web_server] Use centralized length constants for buffer sizing 2026-01-07 20:01:23 -10:00
J. Nick Koston
b8da3b3265 [web_server] Use centralized length constants for buffer sizing 2026-01-07 20:00:40 -10:00
J. Nick Koston
9a3d1f5acc [web_server] Use centralized length constants for buffer sizing 2026-01-07 19:59:45 -10:00
J. Nick Koston
ec5290ef80 [web_server] Use centralized length constants for buffer sizing 2026-01-07 19:58:30 -10:00
J. Nick Koston
197cf6f445 [web_server] Use centralized length constants for buffer sizing 2026-01-07 19:56:16 -10:00
J. Nick Koston
8b46610281 tweaks 2026-01-07 19:39:11 -10:00
J. Nick Koston
3234f44660 Address Copilot review comments 2026-01-07 19:32:30 -10:00
J. Nick Koston
b5b78a674e [mqtt] Reduce heap allocations in topic string building 2026-01-07 18:42:58 -10:00
Keith Burzinski
e301b8d0e0 [thermostat] Allow heat_cool_mode without an automation (#13069)
Co-authored-by: J. Nick Koston <nick+github@koston.org>
2026-01-07 21:44:10 -06:00
J. Nick Koston
3a2f2aa6a8 Merge branch 'wifi_roaming_prevent_ping_pong_broken_ap' into integration 2026-01-07 16:37:48 -10:00
J. Nick Koston
d46b0c4abb tweak 2026-01-07 16:37:09 -10:00
J. Nick Koston
329e800684 more logging 2026-01-07 16:36:45 -10:00
J. Nick Koston
8aa77f7888 Merge branch 'wifi_roaming_prevent_ping_pong_broken_ap' into integration 2026-01-07 16:30:34 -10:00
J. Nick Koston
79c1680b80 show attempts remaining in logging 2026-01-07 16:30:25 -10:00
J. Nick Koston
d2347e1302 Merge branch 'wifi_roaming_prevent_ping_pong_broken_ap' into integration 2026-01-07 16:28:35 -10:00
J. Nick Koston
de1c213537 handle scan error 2026-01-07 16:27:27 -10:00
J. Nick Koston
1fb2eaa905 fixes 2026-01-07 16:24:55 -10:00
J. Nick Koston
b919cc584c fixes 2026-01-07 16:24:46 -10:00
J. Nick Koston
142b1640b6 Merge branch 'wifi_roaming_prevent_ping_pong_broken_ap' into integration 2026-01-07 16:18:21 -10:00
J. Nick Koston
fb4d50150a [wifi] Fix infinite roaming when best-signal AP is crashed/broken 2026-01-07 16:16:47 -10:00
J. Nick Koston
d0843d504e [wifi] Fix infinite roaming when best-signal AP is crashed/broken 2026-01-07 16:15:38 -10:00
J. Nick Koston
77077b470a Merge branch 'libretiny_limit_wifi_retries' into integration 2026-01-07 15:40:11 -10:00
J. Nick Koston
22af0b9eec [wifi] Limit ignored disconnect events on LibreTiny to speed up AP failover 2026-01-07 15:38:54 -10:00
Clyde Stubbs
738678e87b [image] Add define and core data (#13058) 2026-01-08 11:20:37 +11:00
J. Nick Koston
761aa2eecf Merge remote-tracking branch 'upstream/dev' into integration 2026-01-07 13:44:27 -10:00
J. Nick Koston
0ce3ac438b [logger] Add thread-safe logging support for LibreTiny platform (#13062) 2026-01-07 13:40:15 -10:00
marcbodea
afa4fe9820 [esp32_touch] Disable hardware timeout to prevent continuous interrupts (#13059)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick+github@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-01-07 18:37:47 -05:00
J. Nick Koston
cc08d17f85 Merge remote-tracking branch 'upstream/dev' into integration 2026-01-07 11:52:17 -10:00
esphomebot
a66df9ab0f Update webserver local assets to 20260107-214817 (#13064)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-01-07 11:52:02 -10:00
J. Nick Koston
4ad721f632 Merge remote-tracking branch 'upstream/dev' into integration 2026-01-07 11:51:46 -10:00
J. Nick Koston
1339f3e77e [web_server][captive_portal] Add Brotli compression (saves ~11KB flash when using local) (#12959) 2026-01-07 11:49:23 -10:00
J. Nick Koston
fb03947d28 Merge remote-tracking branch 'upstream/dev' into integration 2026-01-07 11:39:50 -10:00
J. Nick Koston
e29523e248 [abbwelcome] Use stack-based formatting to eliminate heap allocations (#12799) 2026-01-07 10:31:19 -10:00
J. Nick Koston
44eac36e05 [debug] Use stack buffers with buf_append helper instead of std::string (#13020) 2026-01-07 10:19:10 -10:00
J. Nick Koston
050e9b0d4a [wifi] Add basic post-connect roaming support for stationary devices (#12809) 2026-01-07 08:30:23 -10:00
J. Nick Koston
25ac89e9b5 [logger] Add thread-safe logging for host platform (#13010) 2026-01-07 08:29:50 -10:00
J. Nick Koston
d86d1f9f52 [modbus_controller] Replace format_hex_pretty with stack-based format_hex_pretty_to (#12781) 2026-01-07 08:29:28 -10:00
J. Nick Koston
fd19280df9 [es8388] Use index-based select publish_state to avoid heap allocations (#13053) 2026-01-07 08:29:00 -10:00
J. Nick Koston
b7dbda497a [core] Improve log timestamp accuracy by batching serial reads (#12750) 2026-01-07 08:28:31 -10:00
J. Nick Koston
815543b77e [tuya] Avoid heap allocation in text sensor enum publish (#13056) 2026-01-07 08:28:14 -10:00
J. Nick Koston
0948e0359f [core] Add integer overload for fnv1a_hash_extend (#13054) 2026-01-07 08:27:58 -10:00
J. Nick Koston
2830c7dab8 [ld2410/ld2412/ld2450] Use index-based select publish_state to avoid heap allocations (#13051) 2026-01-07 08:27:39 -10:00
J. Nick Koston
a03c13f304 [esp32_hosted] Add SHA256 alignment for hardware DMA compatibility (#13050) 2026-01-07 08:26:49 -10:00
J. Nick Koston
ef64226ed0 [mqtt] Use ESPHOME_F() for JSON strings to reduce ESP8266 RAM usage (#13049) 2026-01-07 08:26:21 -10:00
J. Nick Koston
ed39a130a8 [http_request] Store JSON keys in flash for ESP8266 (#13048) 2026-01-07 08:26:04 -10:00
J. Nick Koston
21687a1f58 [sun_gtil2] Eliminate heap allocations in text sensor publishing (#13047)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-07 08:25:33 -10:00
J. Nick Koston
bf75f77eee [preferences] Fix preferences not syncing in safe mode due to component registration order (#13041) 2026-01-07 08:25:08 -10:00
J. Nick Koston
39526e5360 [analyze-memory] Add RAM symbol analysis by component (#13040) 2026-01-07 08:24:44 -10:00
J. Nick Koston
8e40a55d5d [ble_client] Eliminate heap allocations in text sensor (#13038) 2026-01-07 08:24:22 -10:00
J. Nick Koston
20927674da [sun] Eliminate heap allocation in text sensor (#13037) 2026-01-07 08:24:09 -10:00
J. Nick Koston
8464307a43 [api] Coalesce log packets to reduce buffer pressure and prevent dropped state updates (#13026) 2026-01-07 08:23:50 -10:00
J. Nick Koston
546cdbde0d [api] Simplify string handling by removing bifurcated client/server storage (#12822) 2026-01-07 08:23:28 -10:00
tomaszduda23
ada4e6d5e9 [nrf52, zigbee] Add sensor (#12187)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-01-07 08:20:01 -10:00
Keith Burzinski
d6554702d8 [zwave_proxy] Make send_frame safer, make set_home_id protected (#13055) 2026-01-07 08:54:08 +00:00
Samuel Sieb
b083c33857 [espnow] fix channel validation (#13057) 2026-01-07 00:41:24 -08:00
J. Nick Koston
30cf47f737 Merge branch 'fnv_extend' into integration 2026-01-06 22:19:21 -10:00
J. Nick Koston
d2fb4b1af7 [core] Add integer overloads for fnv1_hash_extend and fnv1a_hash_extend 2026-01-06 22:17:44 -10:00
J. Nick Koston
062bb66943 Merge branch 'es8388' into integration 2026-01-06 21:45:02 -10:00
J. Nick Koston
7a300b04f0 [es8388] Use index-based select publish_state to avoid heap allocations 2026-01-06 21:44:21 -10:00
Keith Burzinski
f8309b007c [zwave_proxy] Add logging if client sends zero-length message (#13052) 2026-01-07 01:41:33 -06:00
J. Nick Koston
112cf35960 Merge branch 'ld24xx_select_heap' into integration 2026-01-06 21:36:13 -10:00
J. Nick Koston
899f40a024 fix up 2026-01-06 21:31:08 -10:00
J. Nick Koston
b128f1fb76 Merge branch 'ld24xx_select_heap' into integration 2026-01-06 21:22:10 -10:00
J. Nick Koston
255aa14aff [ld2410/ld2412/ld2450] Use index-based select publish_state to avoid heap allocations 2026-01-06 21:20:48 -10:00
Clyde Stubbs
ac672e4b8f [esp32] Don't warn about no ota rollback if no ota at all (#13045) 2026-01-07 18:19:46 +11:00
J. Nick Koston
7c0562b134 Merge branch 'esp_hosted_dma' into integration 2026-01-06 20:57:52 -10:00
J. Nick Koston
cf2beb40af [esp32_hosted] Add SHA256 alignment for hardware DMA compatibility 2026-01-06 20:56:20 -10:00
J. Nick Koston
631089b852 Merge branch 'debug_cleanup' into integration 2026-01-06 20:38:28 -10:00
J. Nick Koston
d02830307f missed one 2026-01-06 20:36:57 -10:00
J. Nick Koston
cd3b9fa268 Merge branch 'update_esp8266' into integration 2026-01-06 20:20:30 -10:00
J. Nick Koston
99171afd01 Merge branch 'mqtt_json_flash' into integration 2026-01-06 20:20:25 -10:00
J. Nick Koston
8c549d1ef3 [mqtt] Use ESPHOME_F() for JSON strings to reduce ESP8266 RAM usage 2026-01-06 20:19:48 -10:00
J. Nick Koston
e4a92989b3 [http_request] Store JSON keys in flash for ESP8266 2026-01-06 20:13:54 -10:00
J. Nick Koston
813099ace6 Merge branch 'debug_cleanup' into integration 2026-01-06 19:48:06 -10:00
J. Nick Koston
18b0f0965f Merge branch 'no_heap_no_change_text' into integration 2026-01-06 19:47:57 -10:00
J. Nick Koston
d7f832c1cd Merge branch 'sun_gtil2_heap' into integration 2026-01-06 19:47:52 -10:00
J. Nick Koston
f512882a38 Merge branch 'dev' into debug_cleanup 2026-01-06 19:31:49 -10:00
J. Nick Koston
499dbd9e91 [sun_gtil2] Eliminate heap allocations in text sensor publishing 2026-01-06 19:29:00 -10:00
J. Nick Koston
c387c03944 [text_sensor][text] Avoid heap allocation when state unchanged (#13044) 2026-01-06 19:22:04 -10:00
J. Nick Koston
0acd78612f [text_sensor][text] Avoid heap allocation when state unchanged 2026-01-06 18:06:08 -10:00
J. Nick Koston
22dea00d1b Merge remote-tracking branch 'upstream/dev' into integration 2026-01-06 17:57:17 -10:00
J. Nick Koston
906fb3213f Merge branch 'sun_heap_churn' into integration 2026-01-06 17:57:02 -10:00
J. Nick Koston
fb47bfe92a [dsmr] Eliminate heap allocation when publishing telegram (#13032) 2026-01-06 17:54:20 -10:00
J. Nick Koston
5b9be7c169 [ci] Add lint check to prevent usage of deprecated CORE.using_esp_idf (#13029) 2026-01-06 17:54:04 -10:00
J. Nick Koston
6d1f6a1084 [wifi_info] Eliminate heap churn in text sensors (#13031) 2026-01-06 17:53:54 -10:00
J. Nick Koston
f9ed2aa17f [pylontech] Eliminate heap allocations in text sensors (#13033) 2026-01-06 17:53:42 -10:00
J. Nick Koston
35118da606 [ethernet_info] Eliminate heap allocations in text sensors (#13034) 2026-01-06 17:53:29 -10:00
J. Nick Koston
498477c5a2 [homeassistant] Eliminate heap allocation in text sensor state updates (#13035) 2026-01-06 17:53:14 -10:00
J. Nick Koston
3a84e4a0b4 [openthread_info] Eliminate heap allocations in text sensors (#13036) 2026-01-06 17:53:00 -10:00
J. Nick Koston
bb1dcca39d lower case - clang-tidy 2026-01-06 17:52:38 -10:00
J. Nick Koston
4391457a96 [sml] Eliminate heap allocations in text sensor (#13039) 2026-01-06 17:51:26 -10:00
Kyrill
68b4bc9d9e Map HEAT_COOL to MODE_AUTO in HeatpumpIR component (#12058)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-06 21:28:41 -06:00
J. Nick Koston
b052c9f562 [esp32_camera][uart] Add missing wake_loop_threadsafe() preprocessor guards (#13043) 2026-01-07 03:22:10 +00:00
J. Nick Koston
c73d88ce33 enforce buffer size safety at compile time 2026-01-06 16:36:36 -10:00
J. Nick Koston
04057a59c6 tests 2026-01-06 16:35:05 -10:00
J. Nick Koston
c9f4a0e010 enforce buffer size safety at compile time 2026-01-06 16:27:12 -10:00
J. Nick Koston
2a89488cb6 enforce buffer size safety at compile time 2026-01-06 16:24:55 -10:00
J. Nick Koston
58375a3f36 Merge branch 'dev' into sun_heap_churn 2026-01-06 16:18:47 -10:00
J. Nick Koston
a19597626b [text_sensor][text] Add const char* overloads to publish_state to eliminate heap churn (#13030) 2026-01-06 16:16:37 -10:00
J. Nick Koston
609cb8f0fe Merge branch 'flash_write_after_ota_broken_libretiny' into integration 2026-01-06 16:12:56 -10:00
J. Nick Koston
46a85203e0 fix 2026-01-06 16:09:26 -10:00
J. Nick Koston
bf8caeb0a8 Merge branch 'flash_write_after_ota_broken_libretiny' into integration 2026-01-06 14:53:54 -10:00
J. Nick Koston
f54505243c [safe_mode] Fix devices getting stuck in safe mode on LibreTiny 2026-01-06 14:49:06 -10:00
J. Nick Koston
3aa396ceb6 Merge remote-tracking branch 'origin/ram_symbols' into integration 2026-01-06 14:37:01 -10:00
J. Nick Koston
b341374a5d Merge branch 'sml_fix_heap_churn' into integration 2026-01-06 14:36:46 -10:00
J. Nick Koston
34819881c6 Merge branch 'ble_client_heap_churn' into integration 2026-01-06 14:36:40 -10:00
J. Nick Koston
d9c9d21750 [analyze-memory] Add RAM symbol analysis by component 2026-01-06 14:35:35 -10:00
J. Nick Koston
aba4645d81 remove useless 2026-01-06 14:27:07 -10:00
J. Nick Koston
04d498eb41 [sml] Eliminate heap allocations in text sensor 2026-01-06 14:25:33 -10:00
J. Nick Koston
b6058e837b Merge branch 'ble_client_heap_churn' into integration 2026-01-06 14:18:02 -10:00
J. Nick Koston
6b088eac16 [ble_client] Eliminate heap allocations in text sensor 2026-01-06 14:16:19 -10:00
J. Nick Koston
7ec6f6ba76 Merge branch 'sun_heap_churn' into integration 2026-01-06 14:10:35 -10:00
J. Nick Koston
34de46ecec [sun] Eliminate heap allocation in text sensor 2026-01-06 14:08:58 -10:00
J. Nick Koston
a51c1ec9f8 Merge branch 'openthread_heap_churn' into integration 2026-01-06 13:03:15 -10:00
J. Nick Koston
97591a8743 [openthread_info] Eliminate heap allocations in text sensors 2026-01-06 13:02:24 -10:00
J. Nick Koston
6fe0f29bac Merge branch 'homeassistant_text_churn' into integration 2026-01-06 12:51:17 -10:00
J. Nick Koston
6b1a36b416 [homeassistant] Eliminate heap allocation in text sensor state updates 2026-01-06 12:49:56 -10:00
J. Nick Koston
d85c0ff4d5 Merge branch 'ethernet_text_churn' into integration 2026-01-06 12:45:31 -10:00
J. Nick Koston
319be3498a [ethernet_info] Eliminate heap allocations in text sensors 2026-01-06 12:44:47 -10:00
J. Nick Koston
5c482f0809 Merge branch 'pylontech_no_heap' into integration 2026-01-06 12:41:12 -10:00
J. Nick Koston
bdbd275dcc Merge branch 'dsmr_no_heap' into integration 2026-01-06 12:41:07 -10:00
J. Nick Koston
776b6a6cac [pylontech] Eliminate heap allocations in text sensors 2026-01-06 12:40:10 -10:00
J. Nick Koston
559f534f13 [dsmr] Eliminate heap allocation when publishing telegram 2026-01-06 12:37:25 -10:00
J. Nick Koston
be77f57fc3 Merge branch 'text_no_string' into integration 2026-01-06 12:33:33 -10:00
J. Nick Koston
45b195aba5 [wifi_info] Eliminate heap churn in text sensors 2026-01-06 12:32:41 -10:00
J. Nick Koston
d07772671e Merge branch 'fix_text_heap_churn' into integration 2026-01-06 12:19:41 -10:00
J. Nick Koston
9ee5c1bb27 wip 2026-01-06 12:19:32 -10:00
J. Nick Koston
3d1589a278 Merge branch 'fix_text_heap_churn' into integration 2026-01-06 12:17:32 -10:00
J. Nick Koston
227787ab95 [text_sensor][text] Add const char* overloads to publish_state to eliminate heap churn 2026-01-06 12:16:49 -10:00
J. Nick Koston
7bd77eec31 Merge remote-tracking branch 'upstream/dev' into integration 2026-01-06 11:52:26 -10:00
J. Nick Koston
2147ddf8c7 [api] Eliminate std::string from ClientInfo struct (#12566)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2026-01-06 21:32:23 +00:00
Jas Strong
412ab5dbbf [aqi] Implement a sensor that computes AQI (#12958)
Co-authored-by: jas <jas@asspa.in>
2026-01-06 16:31:50 -05:00
David Woodhouse
4419bf02b1 [async_tcp] Fix build conflicts and use IDF component for ESP32 (#13025)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-01-06 20:26:27 +00:00
J. Nick Koston
8eb28a7724 [neopixelbus] Fix ESP8266 compilation by enabling Serial/Serial1 for NeoPixelBus library (#13027) 2026-01-06 18:38:39 +00:00
J. Nick Koston
cf1444742b Merge branch 'log_coalesce' into integration 2026-01-06 08:30:57 -10:00
J. Nick Koston
195b606259 explain 2026-01-06 08:30:13 -10:00
J. Nick Koston
d6c2dd3c26 [wifi] Eliminate heap allocations in IP address logging (#13017) 2026-01-06 08:21:16 -10:00
J. Nick Koston
c4d3a56cc9 [api] Coalesce log packets to reduce buffer pressure and prevent dropped state updates 2026-01-06 08:13:35 -10:00
J. Nick Koston
ac42102320 [core] Auto-replace / in entity names with Unicode fraction slash during deprecation period (#13016) 2026-01-06 07:36:01 -10:00
J. Nick Koston
2c6584baf5 [xiaomi_ble] Simplify set_bindkey using parse_hex and const char* (#13014) 2026-01-06 07:35:40 -10:00
J. Nick Koston
c1ad39a072 [wifi] Clean up duplicate and empty logging output (#13018) 2026-01-06 07:35:16 -10:00
J. Nick Koston
d3e193cd71 [ota] Fix ESP32-S3 OTA crash with hardware SHA acceleration on IDF 5.5.x (#13021) 2026-01-06 07:34:58 -10:00
J. Nick Koston
11aed601b8 [ble_scanner] Use stack-based string formatting to reduce heap allocations (#13013) 2026-01-06 07:34:38 -10:00
J. Nick Koston
e0981323bd [mqtt] Move Home Assistant discovery keys to PROGMEM on ESP8266 (#13011) 2026-01-06 07:33:56 -10:00
J. Nick Koston
1e56325b33 [improv_base] Optimize next_url to avoid STL string operations (#13015) 2026-01-06 07:33:32 -10:00
J. Nick Koston
a8a26f4ea8 [opentherm][nau7802] Use direct format specifiers instead of to_string().c_str() (#13019) 2026-01-06 07:32:43 -10:00
Jonathan Swoboda
a94eef3a60 Merge branch 'release' into dev 2026-01-06 10:23:02 -05:00
Jonathan Swoboda
b6f3a5d8b7 Merge pull request #13024 from esphome/bump-2025.12.5
2025.12.5
2026-01-06 10:22:48 -05:00
Jonathan Swoboda
3322b04e00 Bump version to 2025.12.5 2026-01-06 09:35:38 -05:00
Jonathan Swoboda
47d0d3cfeb [cc1101] Add PLL lock verification and retry support (#13006) 2026-01-06 09:35:37 -05:00
Clyde Stubbs
8255c02d5d [esp32_ble] Remove requirement for configured network (#12891) 2026-01-06 09:35:37 -05:00
Conrad Juhl Andersen
8b4ba8dfe6 [wts01] Fix negative values for WTS01 sensor (#12835) 2026-01-06 09:35:37 -05:00
Artur
178a61b6fd [sn74hc595]: fix 'Attempted read from write-only channel' when using esp-idf framework (#12801) 2026-01-06 09:35:37 -05:00
Clyde Stubbs
b5df4cdf1d [lvgl] Fix arc background angles (#12773) 2026-01-06 09:35:37 -05:00
Jonathan Swoboda
484f4b3aad [cc1101] Add PLL lock verification and retry support (#13006) 2026-01-06 09:34:28 -05:00
J. Nick Koston
249d89cc5d Merge branch 'sha256_ota_fix' into integration 2026-01-06 00:51:09 -10:00
J. Nick Koston
ffb15b592c cleanup 2026-01-06 00:50:43 -10:00
J. Nick Koston
b40de61224 cleanup 2026-01-06 00:48:40 -10:00
J. Nick Koston
3e6d777439 fix 2026-01-06 00:46:15 -10:00
J. Nick Koston
f5ae09056c cleanup 2026-01-06 00:34:36 -10:00
J. Nick Koston
72892b8913 fix 2026-01-06 00:31:40 -10:00
J. Nick Koston
84e382387d [ota] Fix ESP32-S3 OTA crash with hardware SHA acceleration on IDF 5.5.x 2026-01-06 00:09:14 -10:00
J. Nick Koston
4e80a89f61 tidy 2026-01-05 23:44:22 -10:00
J. Nick Koston
b19918cdbf [debug] Use stack buffers with buf_append helper instead of std::string 2026-01-05 23:38:06 -10:00
J. Nick Koston
2288f8eb5e [debug] Use stack buffers with buf_append helper instead of std::string 2026-01-05 23:35:24 -10:00
J. Nick Koston
9420ae7795 [debug] Use stack buffers with buf_append helper instead of std::string 2026-01-05 23:32:36 -10:00
J. Nick Koston
5e573ee116 [debug] Use stack buffers with buf_append helper instead of std::string 2026-01-05 23:28:17 -10:00
J. Nick Koston
8046dc5ea5 Merge branch 'drop_to_string' into integration 2026-01-05 22:51:25 -10:00
J. Nick Koston
efbd14c15c [opentherm][nau7802] Use direct format specifiers instead of to_string().c_str() 2026-01-05 22:50:51 -10:00
J. Nick Koston
d51ee3d004 Merge branch 'wifi_logging_cleanup' into integration 2026-01-05 22:35:53 -10:00
J. Nick Koston
570ecd1842 tweak 2026-01-05 22:35:40 -10:00
J. Nick Koston
3502ac7bee tweak 2026-01-05 22:33:14 -10:00
J. Nick Koston
04cc713b0c Merge branch 'wifi_logging_cleanup' into integration 2026-01-05 22:29:04 -10:00
J. Nick Koston
63713cac57 [wifi] Clean up duplicate and empty logging output 2026-01-05 22:26:36 -10:00
J. Nick Koston
44ecdeb3b6 Merge branch 'wifi_fix_more_alloc' into integration 2026-01-05 19:35:52 -10:00
J. Nick Koston
913609d985 simplify code 2026-01-05 19:32:47 -10:00
J. Nick Koston
a7b4ae13a3 simplify code 2026-01-05 19:32:11 -10:00
J. Nick Koston
a02583028e Merge branch 'wifi_fix_more_alloc' into integration 2026-01-05 19:24:19 -10:00
J. Nick Koston
43e0f1fb35 [wifi] Eliminate heap allocations in IP address logging 2026-01-05 19:23:46 -10:00
J. Nick Koston
b8faecfd4e Merge branch 'slash_workaround' into integration 2026-01-05 18:49:34 -10:00
J. Nick Koston
4b4c1c1191 [core] Auto-replace / in entity names with Unicode fraction slash during deprecation period 2026-01-05 18:46:54 -10:00
J. Nick Koston
4a499054b7 Merge branch 'bind_key_simplify' into integration 2026-01-05 18:25:01 -10:00
J. Nick Koston
2d65717e43 Merge remote-tracking branch 'origin/improv_next_url' into integration 2026-01-05 18:24:55 -10:00
J. Nick Koston
d8731d376d fixes 2026-01-05 18:23:43 -10:00
J. Nick Koston
d42567c5b0 [improv_base] Optimize next_url to avoid STL string operations 2026-01-05 18:20:23 -10:00
J. Nick Koston
b5ea8a4627 [xiaomi_ble] Simplify set_bindkey using parse_hex and const char* 2026-01-05 18:17:58 -10:00
J. Nick Koston
bc54c5aff3 Merge branch 'ble_scanner_reduce_realloc' into integration 2026-01-05 18:02:40 -10:00
J. Nick Koston
442cd60341 [ble_scanner] Use stack-based string formatting to reduce heap allocations 2026-01-05 17:55:41 -10:00
J. Nick Koston
0a9287df33 Merge remote-tracking branch 'upstream/dev' into integration
# Conflicts:
#	esphome/components/bedjet/bedjet_hub.cpp
#	esphome/components/esp8266/preferences.cpp
#	esphome/components/radon_eye_ble/radon_eye_listener.cpp
#	esphome/components/radon_eye_rd200/radon_eye_rd200.cpp
2026-01-05 17:48:09 -10:00
J. Nick Koston
22cb0da903 [radon_eye_rd200, radon_eye_ble] Use stack-based string formatting in logging (#12991) 2026-01-05 17:45:51 -10:00
Jas Strong
28cf3b7a9b [rd03d] Add Ai-Thinker RD-03D mmWave radar component (#12764)
Co-authored-by: jas <jas@asspa.in>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-01-05 22:35:32 -05:00
J. Nick Koston
84dd17187d [pvvx_mithermometer] Reduce heap allocations with stack-based string formatting (#12994) 2026-01-05 17:35:22 -10:00
J. Nick Koston
110c892c3c [esp8266] Avoid heap allocation in preferences save/load (#12465)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-05 17:35:04 -10:00
J. Nick Koston
8518424a88 [esp8266] Add enable_serial/enable_serial1 helpers to exclude unused Serial objects (#12736) 2026-01-05 17:26:49 -10:00
J. Nick Koston
7ba4dc0f1a [airthings_wave_base, airthings_ble] Use stack-based string formatting in logging (#12989) 2026-01-05 17:22:27 -10:00
J. Nick Koston
95573bc106 [mopeka] Reduce heap allocations with stack-based string formatting (#12990) 2026-01-05 17:21:54 -10:00
J. Nick Koston
a6adc29b14 [xiaomi_ble] Reduce heap allocations with stack-based string formatting (#12992) 2026-01-05 17:20:51 -10:00
J. Nick Koston
8251513556 [bedjet] Use stack-based UUID formatting in logging (#12993) 2026-01-05 17:19:34 -10:00
J. Nick Koston
e6e0be3345 [bthome_mithermometer] Reduce heap allocations with stack-based string formatting (#12995) 2026-01-05 17:18:58 -10:00
J. Nick Koston
64da6d46e9 [ruuvi_ble] Reduce heap allocation with stack-based string formatting (#12997) 2026-01-05 17:18:06 -10:00
J. Nick Koston
9b9a341db0 [b_parasite] Reduce heap allocation with stack-based string formatting (#12998) 2026-01-05 17:17:37 -10:00
J. Nick Koston
18217fbe10 [atc_mithermometer] Reduce heap allocations with stack-based string formatting (#12996) 2026-01-05 17:16:47 -10:00
J. Nick Koston
c3e6a4178c [thermopro_ble] Reduce heap allocation with stack-based string formatting (#12999) 2026-01-05 17:16:14 -10:00
J. Nick Koston
2d4cd4ce7e [midea] Reduce heap allocations with stack-based string formatting (#13000) 2026-01-05 17:15:50 -10:00
J. Nick Koston
0290ed5d23 [voice_assistant] Reduce heap allocation with stack-based timer formatting (#13001) 2026-01-05 17:14:33 -10:00
Evaldas Auryla
b402e403a0 [radon_eye_rd200] update Radon Eye RD200 with v2/v3 support (#7962)
Co-authored-by: Artem Butusov <art.sormy@gmail.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-01-05 16:34:23 -10:00
J. Nick Koston
b34260d5c8 Merge remote-tracking branch 'upstream/dev' into integration 2026-01-05 16:21:07 -10:00
J. Nick Koston
4a97bd4859 Merge branch 'host_logger_thread_safe' into integration 2026-01-05 15:26:26 -10:00
J. Nick Koston
0453c74133 Address Copilot review: fix pthread_setname_np for Linux, simplify loop() condition 2026-01-05 15:14:24 -10:00
J. Nick Koston
a6a7b41b2e Merge remote-tracking branch 'origin/host_logger_thread_safe' into host_logger_thread_safe 2026-01-05 15:11:27 -10:00
J. Nick Koston
327458169c bot nits 2026-01-05 15:11:01 -10:00
Jonathan Swoboda
b2c22a02b1 [cc1101] Add freq_offset to on_packet trigger (#13008) 2026-01-05 20:08:07 -05:00
J. Nick Koston
f237d96121 Merge branch 'dev' into host_logger_thread_safe 2026-01-05 14:59:34 -10:00
J. Nick Koston
21b0955d4f [logger] Add thread-safe logging for host platform 2026-01-05 14:58:29 -10:00
J. Nick Koston
d3a128803c add diagram 2026-01-05 14:55:48 -10:00
J. Nick Koston
813012a65d remove dead code 2026-01-05 14:53:42 -10:00
J. Nick Koston
993070156a host has plenty of ram, do not give a knob, its not needed 2026-01-05 14:50:55 -10:00
J. Nick Koston
4a3e3a3b37 host has plenty of ram, do not give a knob, its not needed 2026-01-05 14:50:46 -10:00
J. Nick Koston
602bde0e5d reduce ram 2026-01-05 14:49:24 -10:00
J. Nick Koston
4c0e45ea5d wip 2026-01-05 14:43:48 -10:00
J. Nick Koston
707337d27a tweak 2026-01-05 14:33:40 -10:00
J. Nick Koston
6ea3dd8975 tweak 2026-01-05 14:33:00 -10:00
J. Nick Koston
c64514acdc tweak 2026-01-05 14:31:38 -10:00
J. Nick Koston
0d2c48a55a tweak 2026-01-05 14:29:52 -10:00
J. Nick Koston
b2f1f0faad tweak 2026-01-05 14:26:55 -10:00
J. Nick Koston
f0775d7ae0 host logger thread safe 2026-01-05 14:21:36 -10:00
PolarGoose
7ed4922d28 [dsmr] Remove dependency on Arduino framework. Various bug fixes. Add missing sensors. (#11036)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-01-06 00:18:54 +00:00
Clyde Stubbs
21aa245cff [image] Replace use of cairosvg with resvg-py (#12863)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-06 10:56:59 +11:00
David Woodhouse
94bedd83be async_tcp: Add AsyncClient for ESP-IDF and host (#12337)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: J. Nick Koston <nick+github@koston.org>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-05 23:37:38 +00:00
guillempages
c8f5a97cef [esphome OTA] Allow compilation on host platform (#11655)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-01-05 23:33:06 +00:00
J. Nick Koston
90597a1255 Merge branch 'esp8266_prefs_avoid_heap' into integration 2026-01-05 09:34:27 -10:00
J. Nick Koston
3fed238f79 Merge branch 'voice_assistant_format_stack' into integration 2026-01-05 09:28:10 -10:00
J. Nick Koston
cc8bd2d29d dry 2026-01-05 09:26:41 -10:00
J. Nick Koston
7a0d7c5ca1 [voice_assistant] Reduce heap allocation with stack-based timer formatting 2026-01-05 09:24:33 -10:00
J. Nick Koston
bc7b2d317c Merge branch 'midea_stack_format' into integration 2026-01-05 09:21:12 -10:00
J. Nick Koston
334b7168bd [midea] Reduce heap allocations with stack-based string formatting 2026-01-05 09:20:45 -10:00
J. Nick Koston
8aaa51e5c7 Merge branch 'thermopro_ble' into integration 2026-01-05 09:16:35 -10:00
J. Nick Koston
d9568251dc [thermopro_ble] Reduce heap allocation with stack-based string formatting 2026-01-05 09:16:04 -10:00
J. Nick Koston
652660ca57 Merge branch 'b_parasite' into integration 2026-01-05 09:14:55 -10:00
J. Nick Koston
6b9f105b0b [b_parasite] Reduce heap allocation with stack-based string formatting 2026-01-05 09:14:26 -10:00
J. Nick Koston
8751e00077 Merge branch 'ruuvi_ble' into integration 2026-01-05 09:13:04 -10:00
J. Nick Koston
647c727708 [ruuvi_ble] Reduce heap allocation with stack-based string formatting 2026-01-05 09:12:36 -10:00
J. Nick Koston
b376b78625 Merge branch 'atc_mithermometer' into integration 2026-01-05 09:10:41 -10:00
J. Nick Koston
fdb4d411ce [atc_mithermometer] Reduce heap allocations with stack-based string formatting 2026-01-05 09:09:11 -10:00
J. Nick Koston
a762590b35 Merge branch 'bthome_mithermometer_logging' into integration 2026-01-05 09:06:33 -10:00
J. Nick Koston
6f1185011f [bthome_mithermometer] Reduce heap allocations with stack-based string formatting 2026-01-05 09:04:12 -10:00
J. Nick Koston
8092215de1 [bthome_mithermometer] Reduce heap allocations with stack-based string formatting 2026-01-05 09:02:46 -10:00
J. Nick Koston
b4a1421c71 Merge branch 'pvvx_mithermometer_format' into integration 2026-01-05 08:58:43 -10:00
J. Nick Koston
fc9b0cd56c [pvvx_mithermometer] Reduce heap allocations with stack-based string formatting 2026-01-05 08:58:08 -10:00
J. Nick Koston
16c61afb15 Merge branch 'bedjet_logging' into integration 2026-01-05 08:55:52 -10:00
J. Nick Koston
754a34357d [bedjet] Use stack-based UUID formatting in logging 2026-01-05 08:55:14 -10:00
J. Nick Koston
dc7aeec9ee Merge branch 'xiaomi_heap_logging' into integration 2026-01-05 08:53:13 -10:00
J. Nick Koston
cc3e05dece Merge branch 'mopeka_stack_format' into integration 2026-01-05 08:53:08 -10:00
J. Nick Koston
92399e58fc Merge branch 'radon_eye_stack' into integration 2026-01-05 08:53:04 -10:00
J. Nick Koston
70792ac9c5 fix bug 2026-01-05 08:52:20 -10:00
J. Nick Koston
152a146946 reduce 2026-01-05 08:50:24 -10:00
J. Nick Koston
0184636cde [xiaomi_ble] Reduce heap allocations with stack-based string formatting 2026-01-05 08:48:29 -10:00
J. Nick Koston
215fa497d8 Merge branch 'radon_eye_stack' into integration 2026-01-05 08:38:11 -10:00
J. Nick Koston
6dbcb28012 [radon_eye_rd200, radon_eye_ble] Use stack-based string formatting in logging 2026-01-05 08:28:04 -10:00
J. Nick Koston
204a15d53f Merge branch 'airthings_stack_format_logs' into integration 2026-01-05 08:26:03 -10:00
J. Nick Koston
de060e3209 Merge branch 'mopeka_stack_format' into integration 2026-01-05 08:25:55 -10:00
J. Nick Koston
879c6b87bb [mopeka] Reduce heap allocations with stack-based string formatting 2026-01-05 08:25:16 -10:00
J. Nick Koston
bed16ee76a [airthings_wave_base, airthings_ble] Use stack-based string formatting in logging 2026-01-05 08:21:31 -10:00
J. Nick Koston
1be3cab71d Merge branch 'logger_esp8266' into integration 2026-01-05 08:15:34 -10:00
J. Nick Koston
4a31fd6a9c escape hatch 2026-01-05 08:10:13 -10:00
J. Nick Koston
6974e8b767 keep error log 2026-01-05 07:44:21 -10:00
J. Nick Koston
fc7e55bfdc [api] Avoid heap string copies in Home Assistant state subscription callbacks (#12506) 2026-01-05 07:42:18 -10:00
J. Nick Koston
54c9f0db42 Merge branch 'dev' into esp8266_prefs_avoid_heap 2026-01-05 07:41:25 -10:00
J. Nick Koston
6aaaae5d0e [ci] Add LibreTiny (BK72XX) to memory impact analysis (#12983)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-05 07:40:49 -10:00
J. Nick Koston
e87a3b3916 [light] Use zero-copy set_effect overload in JSON schema parsing (#12979) 2026-01-05 07:40:24 -10:00
J. Nick Koston
3fb5b28930 [captive_portal] Avoid defer overhead on ESP8266 when saving WiFi credentials (#12981) 2026-01-05 07:40:04 -10:00
J. Nick Koston
1bb4be435c [esp32_ble_tracker, ble_client] Reduce heap allocations with stack-based string formatting (#12982) 2026-01-05 07:39:37 -10:00
J. Nick Koston
0990a9c2b0 [esp32_ble] Avoid heap allocation in ESPBTUUID::from_raw for string literals (#12980) 2026-01-05 07:39:24 -10:00
Samuel Schultze
086eb4b930 [whirlpool] support for 14 byte whirlpool IR receiver messages (#12774)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-01-05 11:45:32 -05:00
J. Nick Koston
ed03b09b61 Merge remote-tracking branch 'upstream/avoid_heap_address_str' into integration 2026-01-04 19:30:02 -10:00
J. Nick Koston
f7109c6ced more 2026-01-04 19:28:10 -10:00
J. Nick Koston
d4e3396ce1 Merge remote-tracking branch 'upstream/avoid_heap_address_str' into integration 2026-01-04 19:20:31 -10:00
J. Nick Koston
dbfef45fbb [esp32_ble_tracker, ble_client] Reduce heap allocations with stack-based string formatting 2026-01-04 19:19:23 -10:00
J. Nick Koston
dc7b5a5498 Merge branch 'no_defer_cap_port_8266' into integration 2026-01-04 18:52:01 -10:00
J. Nick Koston
d46982a6af [captive_portal] Avoid defer overhead on ESP8266 when saving WiFi credentials 2026-01-04 18:51:13 -10:00
J. Nick Koston
454471d923 Merge remote-tracking branch 'origin/esp_btuid_from_raw_no_heap_alloc' into integration 2026-01-04 18:33:01 -10:00
J. Nick Koston
6dc8e8ce64 Revert "constexpr"
This reverts commit 5ed2043037.
2026-01-04 18:27:53 -10:00
J. Nick Koston
5ed2043037 constexpr 2026-01-04 18:21:06 -10:00
J. Nick Koston
bd8f9d5984 [esp32_ble] Avoid heap allocation in ESPBTUUID::from_raw for string literals 2026-01-04 18:14:55 -10:00
J. Nick Koston
851f3733db Merge branch 'avoid_forced_heap_alloc_light_json_schema' into integration 2026-01-04 18:06:14 -10:00
J. Nick Koston
690cf1aec9 [light] Use zero-copy set_effect overload in JSON schema parsing 2026-01-04 18:05:48 -10:00
J. Nick Koston
d107b37d3b [st7735] Combine log statements to reduce loop blocking (#12977) 2026-01-04 17:51:02 -10:00
J. Nick Koston
0aa8cfcff5 Merge remote-tracking branch 'upstream/dev' into integration 2026-01-04 17:03:54 -10:00
J. Nick Koston
80ab9485e0 [spi_led_strip] Combine log statements to reduce loop blocking (#12968) 2026-01-04 17:00:59 -10:00
J. Nick Koston
28d30fdddb [ssd1306_i2c] Combine log statements to reduce loop blocking (#12969) 2026-01-04 17:00:40 -10:00
J. Nick Koston
0bd8a7e1a0 [ssd1306_spi] Combine log statements to reduce loop blocking (#12970) 2026-01-04 17:00:21 -10:00
J. Nick Koston
2381ea7ff5 [ssd1322_spi] Combine log statements to reduce loop blocking (#12971) 2026-01-04 17:00:09 -10:00
J. Nick Koston
06101c54a5 [ssd1327_spi] Combine log statements to reduce loop blocking (#12973) 2026-01-04 16:59:52 -10:00
J. Nick Koston
ed332a034b [ssd1351_spi] Combine log statements to reduce loop blocking (#12974) 2026-01-04 16:59:36 -10:00
J. Nick Koston
a2bb9468ff [sm2235] Combine log statements to reduce loop blocking (#12964)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-01-05 02:57:43 +00:00
J. Nick Koston
d8387799d9 [sm2335] Combine log statements to reduce loop blocking (#12965) 2026-01-04 16:56:30 -10:00
J. Nick Koston
ae3cdeda99 [ssd1325_spi] Combine log statements to reduce loop blocking (#12972) 2026-01-04 16:55:55 -10:00
J. Nick Koston
9cd003034c [spi_device] Combine log statements to reduce loop blocking (#12967) 2026-01-04 16:55:31 -10:00
J. Nick Koston
f67a8d0d1f [sonoff_d1] Combine log statements to reduce loop blocking (#12966) 2026-01-04 16:55:11 -10:00
J. Nick Koston
47223965b6 [sm2135] Combine log statements to reduce loop blocking (#12963) 2026-01-04 16:54:17 -10:00
J. Nick Koston
9128fc3120 [sm16716] Combine log statements to reduce loop blocking (#12962) 2026-01-04 16:54:03 -10:00
J. Nick Koston
c742db48b8 [sim800l] Combine log statements to reduce loop blocking (#12961) 2026-01-04 16:52:57 -10:00
J. Nick Koston
4bc1a02fc2 [shtcx] Combine log statements to reduce loop blocking (#12960) 2026-01-04 16:52:03 -10:00
J. Nick Koston
1d0f36ba35 [st7789v] Combine log statements to reduce loop blocking (#12978) 2026-01-04 16:51:37 -10:00
J. Nick Koston
405b26426c [st7567_spi] Combine log statements to reduce loop blocking (#12976) 2026-01-04 16:51:24 -10:00
J. Nick Koston
2295f57dec [st7567_i2c] Combine log statements to reduce loop blocking (#12975) 2026-01-04 16:51:11 -10:00
J. Nick Koston
81a230284f Merge branch 'web_server_br' into integration 2026-01-04 16:28:36 -10:00
J. Nick Koston
a011d5ea96 [sht3xd] Combine log statements to reduce loop blocking (#12957) 2026-01-05 02:14:57 +00:00
tomaszduda23
12027569d3 [nrf52,zigbee] add support for binary_input (#11535)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick+github@koston.org>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-01-04 21:11:14 -05:00
J. Nick Koston
ab0e15e4bb [runtime_stats] Combine log statements to reduce loop blocking (#12954) 2026-01-04 16:10:51 -10:00
J. Nick Koston
9f7925c1d5 [safe_mode] Combine log statements to reduce loop blocking (#12955) 2026-01-04 16:10:19 -10:00
J. Nick Koston
7449421cea [shelly_dimmer] Combine log statements to reduce loop blocking (#12956) 2026-01-04 16:10:06 -10:00
J. Nick Koston
4f20c1ceb1 [rp2040_pwm] Combine log statements to reduce loop blocking (#12952) 2026-01-04 16:09:51 -10:00
J. Nick Koston
452fcd56dd [remote_receiver] Combine log statements to reduce loop blocking (#12951) 2026-01-04 16:08:45 -10:00
J. Nick Koston
44fc156ef6 [remote_base] Combine log statements to reduce loop blocking (#12950) 2026-01-04 16:07:50 -10:00
J. Nick Koston
3ec05a5a13 [radon_eye_rd200] Combine log statements to reduce loop blocking (#12949) 2026-01-04 16:06:55 -10:00
J. Nick Koston
e6a630ae64 [qmp6988] Combine log statements to reduce loop blocking (#12947) 2026-01-04 16:06:34 -10:00
J. Nick Koston
3c8fd5c5c0 [pulse_counter] Combine log statements to reduce loop blocking (#12946) 2026-01-04 16:05:05 -10:00
J. Nick Koston
a635c82830 [pid] Combine log statements to reduce loop blocking (#12942) 2026-01-04 16:04:50 -10:00
J. Nick Koston
b550e2f4f9 [web_server][captive_portal] Add Brotli compression (saves ~11KB flash) 2026-01-04 15:40:25 -10:00
J. Nick Koston
676517fff3 [web_server][captive_portal] Add Brotli compression (saves ~11KB flash) 2026-01-04 15:40:19 -10:00
J. Nick Koston
a16746d30a [web_server][captive_portal] Add Brotli compression (saves ~11KB flash) 2026-01-04 15:38:15 -10:00
J. Nick Koston
0b9fcf9ed3 [pn532] Combine log statements to reduce loop blocking (#12943) 2026-01-04 14:46:21 -10:00
J. Nick Koston
2d8abbb2ac [pn7150] Combine log statements to reduce loop blocking (#12944) 2026-01-04 14:46:09 -10:00
J. Nick Koston
6d8142c539 [rpi_dpi_rgb] Combine log statements to reduce loop blocking (#12953) 2026-01-04 14:45:52 -10:00
J. Nick Koston
50f27cdd77 [pn7160] Combine log statements to reduce loop blocking (#12945) 2026-01-04 14:45:38 -10:00
J. Nick Koston
6c809583d3 [qspi_dbi] Combine log statements to reduce loop blocking (#12948)
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-04 14:45:22 -10:00
J. Nick Koston
4e94d1ba58 Merge branch 'get_peername_stack_save_ram' into integration 2026-01-04 14:07:08 -10:00
J. Nick Koston
cd3f0e9fc4 Merge remote-tracking branch 'upstream/dev' into get_peername_stack_save_ram 2026-01-04 14:06:41 -10:00
J. Nick Koston
f41f0506c1 [pcf8574] Combine log statements to reduce loop blocking (#12941) 2026-01-04 14:05:17 -10:00
J. Nick Koston
850f189225 [api] Fix message batch size mismatch and improve naming consistency (#12940) 2026-01-04 23:44:49 +00:00
J. Nick Koston
a37d4b17eb [wifi] Combine log statements to reduce loop blocking (#12939) 2026-01-04 23:11:48 +00:00
J. Nick Koston
7309a65167 [tlc5971] Combine log statements to reduce loop blocking (#12922) 2026-01-04 13:11:08 -10:00
J. Nick Koston
6e391bb083 Merge branch 'get_peername_stack_save_ram' into integration 2026-01-04 13:07:32 -10:00
J. Nick Koston
8862fcac45 Merge remote-tracking branch 'upstream/dev' into get_peername_stack_save_ram
# Conflicts:
#	esphome/components/voice_assistant/voice_assistant.cpp
2026-01-04 13:05:42 -10:00
J. Nick Koston
7fde110ac5 [voice_assistant] Combine log statements to reduce loop blocking (#12930) 2026-01-04 13:04:22 -10:00
J. Nick Koston
9ed107bc33 [xgzp68xx] Combine log statements to reduce loop blocking (#12935) 2026-01-04 13:04:08 -10:00
J. Nick Koston
b291f359ae [x9c] Combine log statements to reduce loop blocking (#12934) 2026-01-04 13:03:56 -10:00
J. Nick Koston
161545584d [wl_134] Combine log statements to reduce loop blocking (#12933) 2026-01-04 13:03:42 -10:00
J. Nick Koston
3ea11d4e59 [xpt2046] Combine log statements to reduce loop blocking (#12937) 2026-01-04 13:03:22 -10:00
J. Nick Koston
5713d69efe [ufire_ec] Combine log statements to reduce loop blocking (#12925) 2026-01-04 13:03:06 -10:00
J. Nick Koston
9d9f9c3c84 [xiaomi_xmwsdj04mmc] Combine log statements to reduce loop blocking (#12936) 2026-01-04 13:02:52 -10:00
J. Nick Koston
29d332af92 [wireguard] Combine log statements to reduce loop blocking (#12932) 2026-01-04 13:02:02 -10:00
J. Nick Koston
c44d095f8a [usb_host] Combine log statements to reduce loop blocking (#12927) 2026-01-04 13:01:49 -10:00
J. Nick Koston
0b996616b8 [waveshare_epaper] Combine log statements to reduce loop blocking (#12931) 2026-01-04 13:01:33 -10:00
J. Nick Koston
557b6a9ef0 [sun] Combine log statements to reduce loop blocking (#12919) 2026-01-04 13:00:59 -10:00
J. Nick Koston
6e633f7f3b [usb_uart] Combine log statements to reduce loop blocking (#12928) 2026-01-04 13:00:03 -10:00
J. Nick Koston
c59455e445 [mqtt] Combine log statements to reduce loop blocking (#12938) 2026-01-04 12:59:47 -10:00
J. Nick Koston
32b3d27c7c [uln2003] Combine log statements to reduce loop blocking (#12926) 2026-01-04 12:58:42 -10:00
J. Nick Koston
88cb5d9671 [tmp1075] Combine log statements to reduce loop blocking (#12923) 2026-01-04 12:58:20 -10:00
J. Nick Koston
56d1d928f9 [tlc5947] Combine log statements to reduce loop blocking (#12921) 2026-01-04 12:57:10 -10:00
J. Nick Koston
e9cab96cb7 [sx1509] Combine log statements to reduce loop blocking (#12920) 2026-01-04 12:56:50 -10:00
J. Nick Koston
022c42f9ca [tuya] Combine log statements to reduce loop blocking (#12924) 2026-01-04 12:53:58 -10:00
J. Nick Koston
25ef9aff04 [vl53l0x] Combine log statements to reduce loop blocking (#12929) 2026-01-04 12:53:46 -10:00
J. Nick Koston
f4d2fa8da5 Merge branch 'align_max_messages' into integration 2026-01-04 12:47:06 -10:00
J. Nick Koston
1ef6c6a416 move const 2026-01-04 12:46:35 -10:00
J. Nick Koston
a1aaaedf3c Merge branch 'align_max_messages' into integration 2026-01-04 12:43:56 -10:00
J. Nick Koston
9297850afe [api] Fix message batch size mismatch and improve naming consistency 2026-01-04 12:41:01 -10:00
Clyde Stubbs
71940acc49 [esp32_ble] Remove requirement for configured network (#12891) 2026-01-04 22:37:44 +00:00
J. Nick Koston
4bffe5bd4a Merge remote-tracking branch 'upstream/dev' into integration 2026-01-04 11:56:33 -10:00
J. Nick Koston
05695affff [m5stack_8angle] Combine log statements to reduce loop blocking (#12908) 2026-01-04 11:55:31 -10:00
J. Nick Koston
f2308c77c6 [libretiny_pwm] Combine log statements to reduce loop blocking (#12907) 2026-01-04 11:55:18 -10:00
J. Nick Koston
a5368d1d95 [modbus] Combine log statements to reduce loop blocking (#12910) 2026-01-04 11:54:47 -10:00
J. Nick Koston
b8d93f2150 [mopeka_std_check] Combine log statements to reduce loop blocking (#12911) 2026-01-04 11:54:31 -10:00
J. Nick Koston
ca574a1550 [ledc] Combine log statements to reduce loop blocking (#12906) 2026-01-04 11:54:14 -10:00
J. Nick Koston
b0855b4a0e [lc709203f] Combine log statements to reduce loop blocking (#12905) 2026-01-04 11:53:50 -10:00
J. Nick Koston
1fccddf67f [ina2xx_base] Combine log statements to reduce loop blocking (#12904) 2026-01-04 11:52:56 -10:00
J. Nick Koston
548600b47a [ina260] Combine log statements to reduce loop blocking (#12903) 2026-01-04 11:52:34 -10:00
J. Nick Koston
9bbfad4a08 [honeywellabp] Combine log statements to reduce loop blocking (#12902) 2026-01-04 11:52:08 -10:00
J. Nick Koston
8ae1f26b6a [hlw8012] Combine log statements to reduce loop blocking (#12901) 2026-01-04 11:51:45 -10:00
J. Nick Koston
9b2a36a313 [hc8] Combine log statements to reduce loop blocking (#12900) 2026-01-04 11:51:33 -10:00
J. Nick Koston
aa4b274b3c [mcp3204] Combine log statements to reduce loop blocking (#12912) 2026-01-04 11:51:18 -10:00
J. Nick Koston
d1d5c942ec [mcp9600] Combine log statements to reduce loop blocking (#12913) 2026-01-04 11:51:01 -10:00
J. Nick Koston
a336cba035 Merge branch 'get_peername_stack_save_ram' into integration 2026-01-04 11:47:52 -10:00
J. Nick Koston
aa30a1d008 all 3 2026-01-04 11:47:34 -10:00
J. Nick Koston
591b5fa25b all 3 2026-01-04 11:45:27 -10:00
J. Nick Koston
96b59af983 all 3 2026-01-04 11:42:07 -10:00
J. Nick Koston
17250c7244 Merge remote-tracking branch 'upstream/get_peername_stack_save_ram' into integration 2026-01-04 11:28:41 -10:00
J. Nick Koston
ccc9d95c9d [mqtt] Combine log statements to reduce loop blocking (#12914) 2026-01-04 11:28:14 -10:00
J. Nick Koston
6d9d593e12 [my9231] Combine log statements to reduce loop blocking (#12915) 2026-01-04 11:27:14 -10:00
J. Nick Koston
fc9683f024 [opentherm] Combine log statements to reduce loop blocking (#12916) 2026-01-04 11:26:13 -10:00
J. Nick Koston
61ecfb5f2b [openthread] Combine log statements to reduce loop blocking (#12917) 2026-01-04 11:25:52 -10:00
J. Nick Koston
7e75826064 [wifi] Fix LibreTiny thread safety with queue-based event handling (#12833) 2026-01-04 11:25:24 -10:00
J. Nick Koston
8287484a36 [gl_r01_i2c] Combine log statements to reduce loop blocking (#12899) 2026-01-04 11:24:51 -10:00
J. Nick Koston
dd8259b2ce [gcja5] Combine log statements to reduce loop blocking (#12898) 2026-01-04 11:24:36 -10:00
J. Nick Koston
520f8eb9ef simplify 2026-01-04 11:18:44 -10:00
J. Nick Koston
2d0dd93ae8 Merge remote-tracking branch 'upstream/dev' into get_peername_stack_save_ram 2026-01-04 11:16:44 -10:00
J. Nick Koston
cb4a974144 simplify 2026-01-04 11:13:58 -10:00
J. Nick Koston
5143ef4f2d Merge remote-tracking branch 'upstream/dev' into integration 2026-01-04 10:56:13 -10:00
Stuart Parmenter
449e478bec [hub75] Bump esp-hub75 version to 0.2.2 (#12674) 2026-01-04 10:50:10 -10:00
Jonathan Swoboda
9ae19d53dc [ultrasonic] Fix timeout issues and deprecate timeout option (#12897)
Co-authored-by: Claude <noreply@anthropic.com>
2026-01-04 13:39:56 -05:00
J. Nick Koston
77b3ffee00 [factory_reset] Combine log statements to reduce loop blocking (#12866) 2026-01-04 08:34:16 -10:00
J. Nick Koston
dff8dc0ed1 [cc1101] Combine log statements to reduce loop blocking (#12869) 2026-01-04 08:34:07 -10:00
J. Nick Koston
5a8b0f59b8 [cd74hc4067] Combine log statements to reduce loop blocking (#12870) 2026-01-04 08:33:58 -10:00
J. Nick Koston
25a325da61 [current_based] Combine log statements to reduce loop blocking (#12873) 2026-01-04 08:33:49 -10:00
J. Nick Koston
a6db5a2ed8 [dfrobot_sen0395] Combine log statements to reduce loop blocking (#12876) 2026-01-04 08:33:38 -10:00
J. Nick Koston
9e5dbb073a [emmeti] Combine log statements to reduce loop blocking (#12878) 2026-01-04 08:31:14 -10:00
J. Nick Koston
cf513975f3 [ens160_base] Combine log statements to reduce loop blocking (#12880) 2026-01-04 08:30:45 -10:00
J. Nick Koston
1e70091a27 [esp32_hosted] Combine log statements to reduce loop blocking (#12884) 2026-01-04 08:28:17 -10:00
J. Nick Koston
766826cc9c [esp32][libretiny] Reuse preference buffer to avoid heap churn (#12890) 2026-01-04 08:28:01 -10:00
J. Nick Koston
8a4ee19c0b [es8388] Combine log statements to reduce loop blocking (#12882) 2026-01-04 08:26:19 -10:00
J. Nick Koston
b1f9c08f51 [esp32_ble_tracker] Make start_scan action idempotent (#12864) 2026-01-04 08:11:36 -10:00
J. Nick Koston
d328ccd1da Merge branch 'get_peername_stack_save_ram' into integration 2026-01-03 22:11:28 -10:00
J. Nick Koston
d7006a839b Merge remote-tracking branch 'upstream/get_peername_stack_save_ram' into get_peername_stack_save_ram 2026-01-03 22:01:59 -10:00
J. Nick Koston
156ef8df64 reduce 2026-01-03 22:01:25 -10:00
J. Nick Koston
cd5c04bc1e Merge branch 'dev' into get_peername_stack_save_ram 2026-01-03 21:55:03 -10:00
J. Nick Koston
a4accc14c4 Merge branch 'prefs_no_churn_reuse' into integration 2026-01-03 21:21:03 -10:00
J. Nick Koston
9c37443757 guard 2026-01-03 21:20:16 -10:00
J. Nick Koston
8ac16bac7d Merge branch 'prefs_no_churn_reuse' into integration 2026-01-03 21:17:02 -10:00
J. Nick Koston
0f6b9818e4 [esp32][libretiny] Reuse preference buffer to avoid heap churn 2026-01-03 21:16:25 -10:00
J. Nick Koston
facf4777a4 [ezo_pmp] Combine log statements to reduce loop blocking (#12888) 2026-01-03 18:04:00 -10:00
J. Nick Koston
096de869b6 [esp32_ble_client] Combine log statements to reduce loop blocking (#12883) 2026-01-03 18:01:55 -10:00
J. Nick Koston
c59314ec09 [debug] Combine log statements to reduce loop blocking (#12875) 2026-01-03 18:01:28 -10:00
J. Nick Koston
e94158a12f [fan] Combine log statements to reduce loop blocking (#12889) 2026-01-03 18:00:52 -10:00
J. Nick Koston
cb598c43e8 [endstop] Combine log statements to reduce loop blocking (#12879) 2026-01-03 18:00:31 -10:00
J. Nick Koston
6e8817cbc4 [esp8266_pwm] Combine log statements to reduce loop blocking (#12885) 2026-01-03 18:00:11 -10:00
J. Nick Koston
9f06f046d6 [espnow] Combine log statements to reduce loop blocking (#12887) 2026-01-03 17:59:53 -10:00
J. Nick Koston
44fa6bae95 [dht] Combine log statements to reduce loop blocking (#12877) 2026-01-03 17:57:53 -10:00
J. Nick Koston
bc9093127e [cap1188] Combine log statements to reduce loop blocking (#12868) 2026-01-03 17:00:14 -10:00
J. Nick Koston
cf93b66306 [chsc6x] Combine log statements to reduce loop blocking (#12871) 2026-01-03 16:59:55 -10:00
J. Nick Koston
16ada4d477 [epaper_spi] Combine log statements to reduce loop blocking (#12881) 2026-01-04 02:48:39 +00:00
J. Nick Koston
c96d0015a0 [esp_ldo] Combine log statements to reduce loop blocking (#12886) 2026-01-04 02:48:04 +00:00
J. Nick Koston
12c6f5749e [cst816] Combine log statements to reduce loop blocking (#12872) 2026-01-04 02:46:29 +00:00
Douwe
5f1eacf4ec [water_heater] (4/4) Implement tests for new water_heater component (#12517)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-01-03 16:43:31 -10:00
J. Nick Koston
5d384c77c5 [esp32] Move heap functions to flash, saving ~6KB (#12862) 2026-01-03 16:00:50 -10:00
dependabot[bot]
32562ca991 Bump aioesphomeapi from 43.10.0 to 43.10.1 (#12865)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-04 01:59:03 +00:00
J. Nick Koston
6b4b1272db [binary_sensor] Combine log statements to reduce loop blocking (#12849) 2026-01-04 01:56:52 +00:00
J. Nick Koston
7b74f94360 [wifi] Combine log statements to reduce loop blocking (#12856)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-01-04 01:54:56 +00:00
J. Nick Koston
79de1bc609 Merge branch 'esp32_ble_automations' into integration 2026-01-03 15:54:36 -10:00
J. Nick Koston
93adab389e [esp32_ble_tracker] Make start_scan action idempotent 2026-01-03 15:54:15 -10:00
J. Nick Koston
997ab553c1 [ac_dimmer] Combine log statements to reduce loop blocking (#12840)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-01-04 01:36:08 +00:00
Frederic Meeuwissen
8b80fe9c6b [esp32_rmt_led_strip] Support inverted logic (#12825)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-03 20:32:27 -05:00
J. Nick Koston
ee65f2f0cd [adc] Combine log statements to reduce loop blocking (#12841) 2026-01-03 15:24:41 -10:00
J. Nick Koston
c2c7d4e89d Merge branch 'heap-in-iram-flash' into integration 2026-01-03 15:22:29 -10:00
J. Nick Koston
ba1bbaf67d [esp32] Move heap functions to flash, saving ~6KB
This is the culmination of months of work to reduce heap churn
throughout the ESPHome codebase. By systematically eliminating
unnecessary dynamic allocations (StaticVector, FixedVector, const
char* instead of std::string, pre-allocated buffers, etc.), heap
functions are now called so infrequently that they can safely be
moved from IRAM to flash.

Enable CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH by default, which moves
malloc/free/realloc from IRAM to flash. This is safe because:
- Heap functions should never be called from ISRs
- CONFIG_SPI_MASTER_ISR_IN_IRAM is not enabled
- Audio/video use pre-allocated ring buffers, not dynamic allocation

Measured results: +6,124 bytes of heap freed.

Add heap_in_iram advanced option as an escape hatch for users who
need heap functions in IRAM for specific use cases.
2026-01-03 15:10:32 -10:00
J. Nick Koston
723ccd7547 [ade7880] Combine log statements to reduce loop blocking (#12842) 2026-01-03 15:05:41 -10:00
J. Nick Koston
102862e99d [ads1115] Combine log statements to reduce loop blocking (#12843) 2026-01-03 15:05:29 -10:00
J. Nick Koston
9cb265347c [ads1118] Combine log statements to reduce loop blocking (#12844) 2026-01-03 15:05:15 -10:00
J. Nick Koston
d84562f878 [anova] Combine log statements to reduce loop blocking (#12845) 2026-01-03 15:04:57 -10:00
J. Nick Koston
6bbee3cfc6 [as3935] Combine log statements to reduce loop blocking (#12846) 2026-01-03 15:04:38 -10:00
J. Nick Koston
41e7ecb29f [bedjet] Combine log statements to reduce loop blocking (#12848) 2026-01-03 15:04:21 -10:00
J. Nick Koston
0196d6ee55 [ble_nus] Combine log statements to reduce loop blocking (#12850) 2026-01-03 15:03:44 -10:00
J. Nick Koston
ea848db683 [bp1658cj] Combine log statements to reduce loop blocking (#12851) 2026-01-03 15:03:20 -10:00
J. Nick Koston
41a188ac35 [ac_dimmer] Fix ESP8266 build by requiring waveform support (#12852) 2026-01-03 15:03:01 -10:00
J. Nick Koston
8ddfeb2d38 [captive_portal] Combine log statements to reduce loop blocking (#12853) 2026-01-03 15:02:26 -10:00
J. Nick Koston
d364432e3a [uart] Combine log statements to reduce loop blocking (#12855) 2026-01-03 15:02:12 -10:00
J. Nick Koston
2a6b192af8 [ethernet] Combine log statements to reduce loop blocking (#12854) 2026-01-03 15:01:35 -10:00
J. Nick Koston
07a581e13a [update] Combine log statements to reduce loop blocking (#12857) 2026-01-03 15:01:24 -10:00
J. Nick Koston
5f5edf90e9 [water_heater] Combine log statements to reduce loop blocking (#12858) 2026-01-03 15:01:12 -10:00
J. Nick Koston
5e24469ce3 [http_request] Combine log statements to reduce loop blocking (#12859) 2026-01-03 15:01:01 -10:00
J. Nick Koston
d7a1ac83ca [esp32_ble_tracker] Combine log statements to reduce loop blocking (#12860) 2026-01-03 15:00:51 -10:00
Douwe
f11abc7dbf [water_heater] (2/4) Implement template for new water_heater component (#12516)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-01-03 14:45:49 -10:00
J. Nick Koston
f98cc96a6f Merge branch 'combine-logs-captive_portal' into integration 2026-01-03 14:35:05 -10:00
J. Nick Koston
dff89193dd Merge branch 'combine-logs-uart' into integration 2026-01-03 14:35:01 -10:00
J. Nick Koston
b868d0f254 Merge branch 'combine-logs-ethernet' into integration 2026-01-03 14:34:54 -10:00
tomaszduda23
ec05692f0d [nrf52] add printk doc (#12839) 2026-01-04 00:12:31 +00:00
J. Nick Koston
2e2e54811a [absolute_humidity] Combine log statements to reduce loop blocking (#12838) 2026-01-03 17:52:23 -06:00
J. Nick Koston
6d7949c686 [uart] Combine log statements to reduce loop blocking 2026-01-03 13:26:17 -10:00
J. Nick Koston
f78cf6d6b3 [ethernet] Combine log statements to reduce loop blocking 2026-01-03 13:25:58 -10:00
J. Nick Koston
8f77e0712e [captive_portal] Combine log statements to reduce loop blocking 2026-01-03 13:25:38 -10:00
Clyde Stubbs
c29aa61e2a [image] Use alternative version of CairoSVG on Windows (#12811) 2026-01-04 10:08:47 +11:00
J. Nick Koston
cb3edfc654 [wifi] Use stack-based MAC formatting in ESP8266 and IDF event handlers (#12834) 2026-01-03 12:32:22 -10:00
J. Nick Koston
6685fa1da9 [core] Fix startup delay from setup timing logs when console connected (#12832) 2026-01-03 12:32:10 -10:00
J. Nick Koston
d505f0316b [wifi] Combine scan result log lines to reduce loop blocking with many matching APs (#12830) 2026-01-03 12:31:58 -10:00
J. Nick Koston
9781073f2a [espnow] Use stack-based MAC formatting and remove dead code (#12836) 2026-01-03 12:31:38 -10:00
John Hollowell
0a0501c140 Fix comment typos (#12828) 2026-01-03 17:11:48 -05:00
Jasper van der Neut - Stulen
a6e9aa7876 [mhz19] Refactor Actions to Parented (#12837) 2026-01-03 17:11:02 -05:00
Conrad Juhl Andersen
ede7391582 [wts01] Fix negative values for WTS01 sensor (#12835) 2026-01-03 17:06:33 -05:00
J. Nick Koston
1a86f7c67c Merge branch 'espnow_mac_format' into integration 2026-01-03 11:05:42 -10:00
J. Nick Koston
8a59e13bbc [espnow] Use stack-based MAC formatting and remove dead code 2026-01-03 11:05:20 -10:00
J. Nick Koston
7e31e9823b Merge branch 'wifi_esp8266_idf_format_mac_address_pretty' into integration 2026-01-03 10:59:49 -10:00
J. Nick Koston
becab116c7 [wifi] Use stack-based MAC formatting in ESP8266 and IDF event handlers 2026-01-03 10:59:27 -10:00
J. Nick Koston
28bad19900 Merge branch 'libretiny_thread_safe_wifi' into integration 2026-01-03 10:52:10 -10:00
J. Nick Koston
eada23d587 optimize away 2026-01-03 10:51:56 -10:00
Jasper van der Neut - Stulen
5cfcf8d104 [mhz19] Make detection range configurable (#12677)
Co-authored-by: Fabio Pugliese Ornellas <fabio.ornellas@gmail.com>
2026-01-03 15:51:48 -05:00
J. Nick Koston
a1e5d59161 Merge branch 'libretiny_thread_safe_wifi' into integration 2026-01-03 10:48:33 -10:00
J. Nick Koston
2074447120 tune 2026-01-03 10:48:24 -10:00
J. Nick Koston
f267eac729 Merge branch 'libretiny_thread_safe_wifi' into integration 2026-01-03 10:42:23 -10:00
J. Nick Koston
9187bf52e6 tweak 2026-01-03 10:42:06 -10:00
J. Nick Koston
a95dcad380 Merge branch 'libretiny_thread_safe_wifi' into integration 2026-01-03 10:23:37 -10:00
J. Nick Koston
f0a496b08d [wifi] Fix LibreTiny thread safety with queue-based event handling 2026-01-03 10:22:08 -10:00
J. Nick Koston
cc56702e79 Merge branch 'no_delay_startup_many_entities' into integration 2026-01-03 09:34:22 -10:00
J. Nick Koston
a8e8c9d8b5 [core] Fix startup delay from setup timing logs when console connected 2026-01-03 09:33:43 -10:00
J. Nick Koston
846d46cd72 Merge branch 'wifi_roam' into integration 2026-01-03 09:27:51 -10:00
J. Nick Koston
6dbd0de0b5 tweak 2026-01-03 09:19:31 -10:00
J. Nick Koston
c34665f650 [api] Fix KeyError when running logs after password removal (#12831) 2026-01-03 19:13:07 +00:00
J. Nick Koston
fcab160049 Merge branch 'wifi_roam' into integration 2026-01-03 09:11:26 -10:00
J. Nick Koston
c809f86507 fix refactoring error 2026-01-03 09:11:18 -10:00
J. Nick Koston
a184b00051 Merge branch 'wifi_roam' into integration 2026-01-03 09:08:32 -10:00
J. Nick Koston
f7d9ebcf01 reduce 2026-01-03 09:08:23 -10:00
Mariusz Kryński
69867bf818 [nrf52, zephyr] move nrf52-specific code to nrf52 component (#12582)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick+github@koston.org>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-01-03 18:58:56 +00:00
J. Nick Koston
16f3605399 Merge branch 'dev' into get_peername_stack_save_ram 2026-01-03 08:02:34 -10:00
J. Nick Koston
c95b00e7fc Merge branch 'get_rid_of_complex_bifurcated_client_server_api_strings' into integration 2026-01-03 08:01:08 -10:00
J. Nick Koston
8cbb2eef84 merge 2026-01-03 08:00:56 -10:00
J. Nick Koston
21556e714b Merge remote-tracking branch 'upstream/dev' into get_rid_of_complex_bifurcated_client_server_api_strings 2026-01-03 08:00:17 -10:00
J. Nick Koston
dd9804aff4 Merge branch 'missing_password_removal' into integration 2026-01-03 07:56:51 -10:00
J. Nick Koston
b93817e872 [api] Fix KeyError when running logs after password removal 2026-01-03 07:42:46 -10:00
J. Nick Koston
af69ca58c6 Merge branch 'many_mesh_still_blocked_loop' into integration 2026-01-03 07:26:03 -10:00
J. Nick Koston
64261d9b04 [wifi] Combine scan result log lines to reduce loop blocking with many APs 2026-01-03 07:24:21 -10:00
J. Nick Koston
1d323c2d71 [api] Remove deprecated password authentication (#12819) 2026-01-03 07:14:48 -10:00
J. Nick Koston
e8de6627d8 document, document, document 2026-01-03 00:44:37 -10:00
J. Nick Koston
6029f24369 Merge branch 'wifi_roam' into integration 2026-01-03 00:42:31 -10:00
J. Nick Koston
b4f24f6a7f Merge remote-tracking branch 'origin/wifi_roam' into wifi_roam 2026-01-03 00:42:21 -10:00
J. Nick Koston
356e6a3c97 document roam fail path 2026-01-03 00:42:06 -10:00
J. Nick Koston
c4820fcc36 Merge branch 'logger_esp8266' into integration 2026-01-03 00:20:27 -10:00
J. Nick Koston
36d1ef9584 fixes 2026-01-03 00:20:02 -10:00
J. Nick Koston
a5269efd48 fixes 2026-01-03 00:16:07 -10:00
J. Nick Koston
46d9cdfe93 Merge branch 'dev' into logger_esp8266 2026-01-03 00:06:49 -10:00
J. Nick Koston
da34fca20c Merge branch 'dev' into wifi_roam 2026-01-02 23:57:41 -10:00
J. Nick Koston
dc159737ec Merge branch 'wifi_roam' into integration 2026-01-02 23:52:08 -10:00
J. Nick Koston
0ba1fe8457 -49 is the boundray for excellent 2026-01-02 23:51:02 -10:00
tomaszduda23
95a7356ea0 [uart] make sure that all variables are initialized (#12823) 2026-01-03 03:43:17 -06:00
J. Nick Koston
a46a51e885 tweak 2026-01-02 23:43:03 -10:00
J. Nick Koston
bb414f1745 Merge branch 'wifi_roam' into integration 2026-01-02 23:34:54 -10:00
J. Nick Koston
9d79a98c0d log cleanup 2026-01-02 23:34:45 -10:00
J. Nick Koston
cc7e075857 Merge branch 'wifi_roam' into integration 2026-01-02 23:24:41 -10:00
J. Nick Koston
b8c0dc7b04 stale comments 2026-01-02 23:24:22 -10:00
J. Nick Koston
7e313de1c1 Merge remote-tracking branch 'upstream/dev' into wifi_roam 2026-01-02 23:22:45 -10:00
J. Nick Koston
68ad5e457a fix stale comment 2026-01-02 23:22:10 -10:00
J. Nick Koston
a020a3421c Merge branch 'wifi_roam' into integration 2026-01-02 23:17:30 -10:00
J. Nick Koston
8fff7f6b85 len 1 2026-01-02 23:16:01 -10:00
J. Nick Koston
27ae2881de Merge branch 'wifi_roam' into integration 2026-01-02 23:11:42 -10:00
J. Nick Koston
2ab27a6ae2 avoid inlining expensive vector ops 2026-01-02 23:11:30 -10:00
J. Nick Koston
22ad0f2f2d handle race 2026-01-02 23:09:45 -10:00
J. Nick Koston
d99fd22f53 Merge branch 'wifi_roam' into integration 2026-01-02 23:06:01 -10:00
J. Nick Koston
f32c190905 optimize 2026-01-02 23:05:39 -10:00
J. Nick Koston
996bd12871 optimize 2026-01-02 23:03:52 -10:00
J. Nick Koston
516c074b8f optimize 2026-01-02 22:58:18 -10:00
J. Nick Koston
1c9e0f6b22 optimize 2026-01-02 22:56:48 -10:00
J. Nick Koston
828a27b1b6 reduce some code size 2026-01-02 22:53:42 -10:00
J. Nick Koston
039ae65ed8 Update esphome/components/wifi/wifi_component.cpp 2026-01-02 22:52:01 -10:00
J. Nick Koston
2275f638fb Merge remote-tracking branch 'origin/wifi_roam' into wifi_roam 2026-01-02 22:51:29 -10:00
J. Nick Koston
369f32b496 reduce some code size 2026-01-02 22:50:38 -10:00
J. Nick Koston
c6774d81cb Merge branch 'wifi_roam' into integration 2026-01-02 22:29:30 -10:00
J. Nick Koston
828e91a61b Merge remote-tracking branch 'origin/get_rid_of_complex_bifurcated_client_server_api_strings' into get_rid_of_complex_bifurcated_client_server_api_strings 2026-01-02 22:19:12 -10:00
J. Nick Koston
fb255d7e7c fixes 2026-01-02 22:19:01 -10:00
J. Nick Koston
c7e9eda5aa Merge branch 'dev' into get_rid_of_complex_bifurcated_client_server_api_strings 2026-01-02 22:11:24 -10:00
J. Nick Koston
979b96f7d4 cleanup 2026-01-02 21:56:38 -10:00
J. Nick Koston
af8c453f7c [api] Simplify string handling by removing bifurcated client/server storage 2026-01-02 21:52:20 -10:00
Keith Burzinski
5db4574cb8 Merge branch 'dev' into get_peername_stack_save_ram 2026-01-03 01:01:07 -06:00
J. Nick Koston
89b550b74a [tests] Remove reserved / character from entity names in component tests (#12820) 2026-01-03 01:00:46 -06:00
dependabot[bot]
538c6544a0 Bump ruamel-yaml from 0.18.17 to 0.19.1 (#12768)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-02 20:51:56 -10:00
dependabot[bot]
98e3695c89 Bump aioesphomeapi from 43.9.1 to 43.10.0 (#12821)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-03 06:45:17 +00:00
J. Nick Koston
ae1082e3e6 Merge branch 'get_peername_stack_save_ram' into integration 2026-01-02 20:31:10 -10:00
J. Nick Koston
a63ed0d616 fix merge conflict 2026-01-02 20:29:45 -10:00
J. Nick Koston
c2ffd4e49a fix merge conflict 2026-01-02 20:28:37 -10:00
J. Nick Koston
c2c513fd75 Merge branch 'dev' into get_peername_stack_save_ram 2026-01-02 20:26:30 -10:00
J. Nick Koston
2ed5015089 Merge branch 'api_avoid_copies' into integration 2026-01-02 20:21:47 -10:00
J. Nick Koston
48760ef927 match it to upstream change 2026-01-02 20:21:06 -10:00
J. Nick Koston
40b09e8cd4 match it to upstream change 2026-01-02 20:20:02 -10:00
J. Nick Koston
61692894e1 Merge branch 'dev' into api_avoid_copies 2026-01-02 20:19:11 -10:00
J. Nick Koston
00fd4f2fdd [esp8266] Exclude unused waveform code to save ~596 bytes RAM (#12690) 2026-01-02 19:51:07 -10:00
J. Nick Koston
2a5be725c8 [api] Enable zero-copy bytes SOURCE_BOTH messages (#12816) 2026-01-02 19:50:30 -10:00
Robert Klep
c4d339a4c9 [core] Add CONF_ON_START (#12439) (#12440) 2026-01-02 23:42:18 -05:00
J. Nick Koston
c25b732d39 Merge remote-tracking branch 'upstream/source_both_zero_copy' into integration 2026-01-02 17:02:10 -10:00
J. Nick Koston
3148cb2bdd Merge branch 'api_avoid_copies' into integration 2026-01-02 17:01:56 -10:00
J. Nick Koston
114624acbd fix conflicts 2026-01-02 16:57:41 -10:00
J. Nick Koston
c82ae34ccf Merge remote-tracking branch 'upstream/dev' into get_peername_stack_save_ram
# Conflicts:
#	esphome/components/api/api_connection.cpp
#	esphome/components/api/api_frame_helper.cpp
#	esphome/components/api/api_frame_helper_noise.cpp
#	esphome/components/api/api_frame_helper_plaintext.cpp
2026-01-02 16:52:04 -10:00
J. Nick Koston
cf46f71933 Merge branch 'dev' into source_both_zero_copy 2026-01-02 16:45:45 -10:00
J. Nick Koston
9fc78d424c Merge remote-tracking branch 'upstream/dev' into api_avoid_copies
# Conflicts:
#	esphome/components/api/api_connection.cpp
2026-01-02 16:44:53 -10:00
J. Nick Koston
6409970f6e [uponor_smatrix] Use stack-based hex formatting in verbose logging (#12797)
Co-authored-by: Stefan Rado <628587+kroimon@users.noreply.github.com>
2026-01-02 16:41:02 -10:00
J. Nick Koston
bc1af007b4 [vbus] Use stack-based hex formatting in verbose logging (#12796) 2026-01-02 16:40:47 -10:00
Thomas Rupprecht
c3ffc1635d [gps] add icon for HDOP and use correct state_class for longitude and… (#12718) 2026-01-02 21:40:28 -05:00
J. Nick Koston
016eeef04a [tee501] Use stack-based hex formatting in verbose logging (#12795) 2026-01-02 16:40:06 -10:00
J. Nick Koston
ace48464a8 [addressable_light] Use StringRef to avoid allocation when saving effect name (#12759) 2026-01-02 16:39:44 -10:00
J. Nick Koston
64ba376330 [hte501] Use stack-based hex formatting in verbose logging (#12794) 2026-01-02 16:37:38 -10:00
J. Nick Koston
d946ddabfd [xiaomi_ble] Use stack-based hex formatting in verbose logging (#12793) 2026-01-02 16:37:16 -10:00
J. Nick Koston
a57011b50b [kuntze] Use stack buffer for hex formatting in verbose logging (#12775) 2026-01-02 16:36:57 -10:00
J. Nick Koston
1240e7907e [api] Use stack-based format_hex_pretty_to for packet logging macros (#12788) 2026-01-02 16:35:44 -10:00
J. Nick Koston
d70b3091c9 Merge remote-tracking branch 'upstream/dev' into integration 2026-01-02 16:35:18 -10:00
J. Nick Koston
f0391f0213 [api] Remove object_id from API protocol - clients compute it from name #12698 (#12818) 2026-01-02 16:32:46 -10:00
J. Nick Koston
3cc6810be5 [core] Remove object_id RAM storage - no longer in hot path after #12627 (#12631) 2026-01-02 15:46:01 -10:00
J. Nick Koston
916370a943 [gpio] Avoid heap allocation in dump_summary (#12760) 2026-01-02 15:42:56 -10:00
J. Nick Koston
3d6c64b657 Merge branch 'dev' into wifi_roam 2026-01-02 14:28:59 -10:00
J. Nick Koston
e2f45c590e [esp32_improv] Use stack buffer for hex formatting in verbose logging (#12737) 2026-01-02 14:28:38 -10:00
J. Nick Koston
7d21411ca4 [epaper_spi] Use stack buffer for hex formatting in command logging (#12734) 2026-01-02 14:27:00 -10:00
J. Nick Koston
56ed5af27d [nextion] Use stack buffers for hex formatting in upload logging (#12733) 2026-01-02 14:26:14 -10:00
J. Nick Koston
c8241b0122 [sonoff_d1] Use stack buffer for hex formatting in logging (#12730) 2026-01-02 14:25:02 -10:00
J. Nick Koston
30efd7fb07 [jsn_sr04t] Use stack buffer for hex formatting in error logging (#12729) 2026-01-02 14:24:47 -10:00
J. Nick Koston
1703343694 [a02yyuw] Use stack buffer for hex formatting in error logging (#12728) 2026-01-02 14:24:30 -10:00
J. Nick Koston
7fa04b6c25 [a01nyub] Use stack buffer for hex formatting in error logging (#12727) 2026-01-02 14:23:33 -10:00
J. Nick Koston
61b6476de4 [opentherm] Replace heap-allocating format calls with printf format specifiers in debug_error (#12726) 2026-01-02 14:23:18 -10:00
J. Nick Koston
b4e5e0bc9b [rc522] Use stack buffers for hex formatting in tag logging (#12725) 2026-01-02 14:22:58 -10:00
J. Nick Koston
f9b4e0e489 [remote_base] Use stack buffer for hex formatting in haier protocol logging (#12723) 2026-01-02 14:22:26 -10:00
J. Nick Koston
9ccb100cca [remote_base] Use stack buffer for hex formatting in mirage protocol logging (#12722) 2026-01-02 14:21:42 -10:00
J. Nick Koston
20b66cba23 [shelly_dimmer] Use stack buffer for hex formatting in command logging (#12721) 2026-01-02 14:21:23 -10:00
J. Nick Koston
b711172b33 [wifi] Use precision format specifier for SSID logging to avoid stack copy (#12704) 2026-01-02 14:21:09 -10:00
J. Nick Koston
0c4184b129 [cse7766] Use stack buffer for hex formatting in debug logging (#12732) 2026-01-02 14:20:17 -10:00
J. Nick Koston
0e108c2178 [esp32] Add minimum_chip_revision setting and log chip revision at startup (#12696) 2026-01-02 14:14:52 -10:00
J. Nick Koston
2230e56347 [wifi] Use stack buffers for IP address logging to avoid heap allocations (#12680) 2026-01-02 14:14:24 -10:00
J. Nick Koston
2ff9535f5f [esp32_improv] Use stack buffer for URL formatting to avoid heap allocation (#12682) 2026-01-02 14:14:12 -10:00
J. Nick Koston
ddb6c6cfd4 [captive_portal] Use stack buffer for IP address logging in DNS server (#12679) 2026-01-02 14:13:59 -10:00
J. Nick Koston
00ab64a3c7 [wifi] Use wifi_ssid_to() to avoid heap allocations in automation and connection checks (#12678) 2026-01-02 14:13:43 -10:00
J. Nick Koston
e732f8469e [udp] Avoid heap allocations when joining multicast groups (#12685) 2026-01-02 14:13:26 -10:00
J. Nick Koston
023be88a87 [tuya] Use stack buffers for hex logging to avoid heap allocations (#12689) 2026-01-02 14:13:08 -10:00
J. Nick Koston
25e60d62cf [mqtt] Avoid heap allocations when logging IP addresses (#12686) 2026-01-02 14:12:04 -10:00
J. Nick Koston
167a42aa27 [api] Use StringRef in send_action_response and send_execute_service_response (#12658) 2026-01-02 14:11:45 -10:00
J. Nick Koston
0ef49a8b73 [ld2410][ld2412][ld2450] Use stack buffers for hex logging (#12688) 2026-01-02 14:11:31 -10:00
J. Nick Koston
e3fe738966 Merge branch 'dev' into source_both_zero_copy 2026-01-02 14:10:27 -10:00
J. Nick Koston
51259888bf [voice_assistant] Use zero-copy buffer access for audio data (#12656) 2026-01-02 14:10:21 -10:00
J. Nick Koston
0b7ff09657 [api] Use pointer to FixedVector for siren tones field (#12657) 2026-01-02 14:09:40 -10:00
J. Nick Koston
8a5e06b6d2 merge 2026-01-02 14:08:09 -10:00
J. Nick Koston
560966ad98 Merge remote-tracking branch 'upstream/dev' into source_both_zero_copy
# Conflicts:
#	script/api_protobuf/api_protobuf.py
2026-01-02 14:07:55 -10:00
J. Nick Koston
f394cf3f4d [packet_transport] Use stack-based format_hex_pretty_to for logging (#12791) 2026-01-02 14:06:03 -10:00
J. Nick Koston
4cb066bcbf [api] Use StringRef in handle_action_response to avoid temporary string (#12655) 2026-01-02 14:05:50 -10:00
J. Nick Koston
e7001c5eea [api] Auto-generate zero-copy pointer access for incoming API bytes fields (#12654) 2026-01-02 14:05:37 -10:00
esphomebot
5bb9ffa0cb Update webserver local assets to 20260102-230255 (#12817) 2026-01-02 23:14:11 +00:00
J. Nick Koston
7438034411 Merge remote-tracking branch 'upstream/dev' into integration 2026-01-02 13:09:46 -10:00
J. Nick Koston
c6713eaccb [web_server] Fix URL collisions with UTF-8 names and sub-devices (#12627) 2026-01-02 13:07:11 -10:00
J. Nick Koston
5b4bd555dd cleanup per bot 2026-01-02 12:36:44 -10:00
J. Nick Koston
9b02daae2b cleanup per bot 2026-01-02 12:35:05 -10:00
J. Nick Koston
d77fc596a9 its going to drop anyways 2026-01-02 11:37:56 -10:00
Jonathan Swoboda
087f521b19 [ultrasonic] Use interrupt-based measurement for reliability (#12617)
Co-authored-by: Claude <noreply@anthropic.com>
2026-01-02 15:58:53 -05:00
J. Nick Koston
9906724828 [api] Enable zero-copy bytes for VoiceAssistantAudio and other SOURCE_BOTH messages 2026-01-02 10:56:17 -10:00
Jonathan Swoboda
763515d3a1 [core] Remove unused USE_ESP32_FRAMEWORK_ARDUINO ifdefs (#12813)
Co-authored-by: Claude <noreply@anthropic.com>
2026-01-02 14:47:14 -05:00
J. Nick Koston
5c890fcfc4 add roam diagram 2026-01-02 09:29:59 -10:00
J. Nick Koston
5d8346cfb6 Merge branch 'dev' into bytes_zero_copy_default_api 2026-01-02 08:17:33 -10:00
J. Nick Koston
6d4f4d8d23 [api] Auto-generate StringRef for incoming API string fields (#12648) 2026-01-02 08:17:05 -10:00
J. Nick Koston
0a98f7877c tweak 2026-01-01 22:49:21 -10:00
Tobias Stanzel
d7fd85e610 [spi] Allow any achievable data rate (#12753)
Co-authored-by: clydebarrow <2366188+clydebarrow@users.noreply.github.com>
2026-01-02 18:10:30 +11:00
J. Nick Koston
8acaa16987 [usb_cdc_acm] Use stack-based hex formatting in verbose logging (#12792) 2026-01-02 01:04:11 -06:00
J. Nick Koston
4e8c02b396 [xiaomi_*] Use stack-based hex formatting for bindkey logging (#12798) 2026-01-01 20:25:12 -10:00
J. Nick Koston
a828abf53d [ota] Remove MD5 authentication support (#12707) 2026-01-01 20:24:31 -10:00
J. Nick Koston
ebfa0149cc [light] Use StringRef to avoid allocation in JSON effect name serialization (#12758) 2026-01-01 20:23:37 -10:00
J. Nick Koston
3a4cca0027 [ble_client] Use stack buffer for hex formatting in very verbose logging (#12744) 2026-01-01 20:22:48 -10:00
J. Nick Koston
7702a9ae85 [ethernet] Use stack buffer for hex formatting in very verbose logging (#12742) 2026-01-01 20:22:19 -10:00
J. Nick Koston
2e8baa0493 [esp32_ble_tracker] Use stack buffer for hex formatting in very verbose logging (#12741) 2026-01-01 20:21:33 -10:00
J. Nick Koston
69ec311d21 [hlk_fm22x] Use stack buffer for hex formatting in verbose logging (#12740) 2026-01-01 20:20:58 -10:00
J. Nick Koston
1cc18055ef [i2c] Use stack buffer for hex formatting in verbose logging (#12739) 2026-01-01 20:20:24 -10:00
J. Nick Koston
bcc6bbbf5f [espnow] Use stack buffer for hex formatting in verbose logging (#12738) 2026-01-01 20:19:49 -10:00
J. Nick Koston
71c3d4ca27 [mopeka_std_check] Use stack-based format_hex_pretty_to for very verbose logging (#12790) 2026-01-01 20:19:20 -10:00
J. Nick Koston
c6f3860f90 [ee895] Use stack-based format_hex_to for verbose logging (#12789) 2026-01-01 20:18:23 -10:00
J. Nick Koston
0049c8ad38 [zwave_proxy] Use stack-based format_hex_pretty_to for very verbose logging (#12786) 2026-01-01 20:17:51 -10:00
J. Nick Koston
e1788bba45 [seeed_mr60fda2] Use stack-based format_hex_pretty_to for verbose logging (#12785) 2026-01-01 20:17:22 -10:00
J. Nick Koston
4fcd263ea8 [seeed_mr60bha2] Replace format_hex_pretty with stack-based format_hex_pretty_to (#12784) 2026-01-01 20:16:40 -10:00
J. Nick Koston
c81ce243cc [qspi_dbi] Replace format_hex_pretty with stack-based format_hex_pretty_to (#12783) 2026-01-01 20:13:10 -10:00
J. Nick Koston
7df41124b2 [pn532_spi] Replace format_hex_pretty with stack-based format_hex_pretty_to (#12782) 2026-01-01 20:11:53 -10:00
J. Nick Koston
b5188731f8 [modbus] Use stack buffer for hex formatting in verbose logging (#12780) 2026-01-01 20:10:45 -10:00
J. Nick Koston
0924281545 [mitsubishi] Use stack buffer for hex formatting in verbose logging (#12779) 2026-01-01 20:10:08 -10:00
J. Nick Koston
14e97642f7 [mipi_rgb] Use stack buffer for hex formatting in init sequence logging (#12777) 2026-01-01 20:09:37 -10:00
J. Nick Koston
544aaeaa66 [mipi_dsi] Use stack buffer for hex formatting in very verbose logging (#12776) 2026-01-01 20:08:57 -10:00
Stuart Parmenter
7483bbd6ea [display] Ensure drivers respect clipping during fill() (#12808) 2026-01-02 16:34:39 +11:00
Artur
2841b5fe44 [sn74hc595]: fix 'Attempted read from write-only channel' when using esp-idf framework (#12801) 2026-01-01 23:28:10 -05:00
J. Nick Koston
dd6ed4aea6 [wifi] Add basic post-connect roaming support for stationary devices 2026-01-01 17:48:20 -10:00
J. Nick Koston
ab17775c3e tweaks 2026-01-01 17:45:05 -10:00
J. Nick Koston
dc07926a91 tweaks 2026-01-01 17:44:39 -10:00
J. Nick Koston
291722c50e tweak 2026-01-01 17:18:21 -10:00
J. Nick Koston
8b7bb4ecef wip 2026-01-01 14:59:19 -10:00
J. Nick Koston
1def4df146 wip 2026-01-01 14:57:28 -10:00
J. Nick Koston
ff33e362cf wifi roam 2026-01-01 14:55:16 -10:00
J. Nick Koston
ed435241b1 [mipi_spi] Use stack buffer for hex formatting in verbose logging (#12778) 2026-01-01 11:48:37 -10:00
H. Árkosi Róbert
9847e51fbc [bthome_mithermometer] Add BTHome parsing for Xiaomi Mijia BLE Sensors (#12635) 2026-01-02 08:40:18 +11:00
dependabot[bot]
dc320f455a Bump bleak from 2.1.0 to 2.1.1 (#12804)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-01 09:16:01 -10:00
Clyde Stubbs
1945e85ddc [core] Make LockFreeQueue more widely available (#12766) 2026-01-01 22:07:35 +11:00
J. Nick Koston
84e764fa87 Merge branch 'abbwelcome_format' into integration 2025-12-31 23:12:36 -10:00
J. Nick Koston
54a5c9d4af tweak 2025-12-31 23:09:51 -10:00
J. Nick Koston
1303dfa960 tweak 2025-12-31 23:09:39 -10:00
J. Nick Koston
7ce30b693e Merge branch 'abbwelcome_format' into integration 2025-12-31 23:07:18 -10:00
J. Nick Koston
5caa9b8140 snprintf 2025-12-31 23:03:55 -10:00
J. Nick Koston
42746b4b6f tweak 2025-12-31 22:59:44 -10:00
J. Nick Koston
47603de7ce handle truncate 2025-12-31 22:51:42 -10:00
J. Nick Koston
acb54ebb38 Merge branch 'abbwelcome_format' into integration 2025-12-31 22:46:16 -10:00
J. Nick Koston
819bc0a0f2 [abbwelcome] Use stack-based formatting to eliminate heap allocations 2025-12-31 22:45:45 -10:00
J. Nick Koston
b28385da40 Merge branch 'xiaomi_cgd1' into integration 2025-12-31 22:34:22 -10:00
J. Nick Koston
c6a612f580 fix seperator 2025-12-31 22:30:16 -10:00
J. Nick Koston
ad7f48f16d Merge branch 'xiaomi_cgd1' into integration 2025-12-31 22:25:00 -10:00
J. Nick Koston
22502983df [xiaomi_*] Use stack-based hex formatting for bindkey logging 2025-12-31 22:24:29 -10:00
J. Nick Koston
160e649d86 Merge branch 'xiaomi_ble' into integration 2025-12-31 22:16:46 -10:00
J. Nick Koston
259ca86ed7 fix 2025-12-31 22:09:32 -10:00
J. Nick Koston
4ee1358a9f Merge branch 'uponor_smatrix' into integration 2025-12-31 22:07:02 -10:00
J. Nick Koston
8e4913d78c [uponor_smatrix] Use stack-based hex formatting in verbose logging 2025-12-31 22:06:26 -10:00
J. Nick Koston
b6e05a0570 Merge branch 'vbus_hex' into integration 2025-12-31 22:04:11 -10:00
J. Nick Koston
d4e2d808d7 [vbus] Use stack-based hex formatting in verbose logging 2025-12-31 22:03:40 -10:00
J. Nick Koston
fd65ea1d05 Merge branch 'tee501' into integration 2025-12-31 22:00:13 -10:00
J. Nick Koston
91e9c8b63b [tee501] Use stack-based hex formatting in verbose logging 2025-12-31 21:58:37 -10:00
J. Nick Koston
22d2087563 Merge branch 'hte501' into integration 2025-12-31 21:56:43 -10:00
J. Nick Koston
7588f3b120 [hte501] Use stack-based hex formatting in verbose logging 2025-12-31 21:56:06 -10:00
J. Nick Koston
9e1c14dde5 Merge branch 'xiaomi_ble' into integration 2025-12-31 21:54:31 -10:00
J. Nick Koston
2a262babd3 Merge branch 'usb_cdc_acm_hex' into integration 2025-12-31 21:54:26 -10:00
J. Nick Koston
4ba89d9430 Merge branch 'packet_transport_hex' into integration 2025-12-31 21:54:21 -10:00
J. Nick Koston
22fff2b147 Merge branch 'seeed_mr60fda2' into integration 2025-12-31 21:54:14 -10:00
J. Nick Koston
9928e29f52 Merge branch 'zwave_proxy_hex' into integration 2025-12-31 21:54:09 -10:00
J. Nick Koston
59419a63bd Merge branch 'mopeka_std_check' into integration 2025-12-31 21:54:05 -10:00
J. Nick Koston
9501431908 [xiaomi_ble] Use stack-based hex formatting in verbose logging 2025-12-31 21:52:02 -10:00
J. Nick Koston
7c47c1e3b2 [usb_cdc_acm] Use stack-based hex formatting in verbose logging 2025-12-31 21:48:07 -10:00
J. Nick Koston
d93ed1982e [packet_transport] Use stack-based format_hex_pretty_to for logging 2025-12-31 21:42:13 -10:00
J. Nick Koston
df4ce52deb reduce 2025-12-31 21:37:05 -10:00
J. Nick Koston
fa5aa619ad reduce 2025-12-31 21:34:42 -10:00
J. Nick Koston
ecf6e62b86 [mopeka_std_check] Use stack-based format_hex_pretty_to for very verbose logging 2025-12-31 21:30:17 -10:00
Clyde Stubbs
4313130f2e [lvgl] Fix arc background angles (#12773) 2026-01-01 14:44:21 +11:00
J. Nick Koston
252e35c516 Merge branch 'ee895' into integration 2025-12-31 17:40:59 -10:00
J. Nick Koston
45124c05ad [ee895] Use stack-based format_hex_to for verbose logging 2025-12-31 17:40:25 -10:00
J. Nick Koston
77a95a5fd4 adjust 2025-12-31 17:30:44 -10:00
J. Nick Koston
8dd958fcd1 [api] Use stack-based format_hex_pretty_to for packet logging macros 2025-12-31 17:28:01 -10:00
J. Nick Koston
2a87a70963 Merge branch 'espnow' into integration 2025-12-31 17:25:34 -10:00
J. Nick Koston
5bfb020c1f Merge branch 'epaper_spi' into integration 2025-12-31 17:25:15 -10:00
J. Nick Koston
d2afa9a120 Merge branch 'zwave_proxy_hex' into integration 2025-12-31 17:16:17 -10:00
J. Nick Koston
aade54e3c9 [zwave_proxy] Use stack-based format_hex_pretty_to for very verbose logging 2025-12-31 17:10:52 -10:00
J. Nick Koston
4439d30d27 Merge branch 'seeed_mr60fda2' into integration 2025-12-31 17:04:14 -10:00
J. Nick Koston
38381a0d24 Merge branch 'seeed_mr60bha2' into integration 2025-12-31 17:04:10 -10:00
J. Nick Koston
eddb386277 [seeed_mr60fda2] Use stack-based format_hex_pretty_to for verbose logging 2025-12-31 17:03:32 -10:00
J. Nick Koston
dde20e82f7 [seeed_mr60bha2] Replace format_hex_pretty with stack-based format_hex_pretty_to 2025-12-31 16:58:19 -10:00
J. Nick Koston
8f856fab1b Merge branch 'qspi_dbi' into integration 2025-12-31 16:55:25 -10:00
J. Nick Koston
3e1f7a9cd8 Merge branch 'pn532_spi' into integration 2025-12-31 16:55:21 -10:00
J. Nick Koston
f8e56a8565 Merge branch 'modbus_controller' into integration 2025-12-31 16:55:16 -10:00
J. Nick Koston
a952d843e7 Merge branch 'modbus' into integration 2025-12-31 16:55:12 -10:00
J. Nick Koston
278fdae770 Merge branch 'mitsubishi' into integration 2025-12-31 16:55:08 -10:00
J. Nick Koston
6fc9c63f2d Merge branch 'mipi_spi' into integration 2025-12-31 16:55:03 -10:00
J. Nick Koston
be6ec974e1 Merge branch 'mipi_rgb_hex' into integration 2025-12-31 16:54:58 -10:00
J. Nick Koston
9de52fb9f5 Merge branch 'mipi_dsi' into integration 2025-12-31 16:54:54 -10:00
J. Nick Koston
7993ff7602 Merge branch 'hlk_fm22x_format' into integration 2025-12-31 16:54:49 -10:00
J. Nick Koston
253ce861ab [qspi_dbi] Replace format_hex_pretty with stack-based format_hex_pretty_to 2025-12-31 16:54:13 -10:00
J. Nick Koston
1fff2f503f [pn532_spi] Replace format_hex_pretty with stack-based format_hex_pretty_to 2025-12-31 16:52:24 -10:00
J. Nick Koston
6925ab3bf1 tweak 2025-12-31 16:46:57 -10:00
J. Nick Koston
d8a84e6f2b wip 2025-12-31 16:42:45 -10:00
J. Nick Koston
73b19bc5d1 [modbus_controller] Replace format_hex_pretty with stack-based format_hex_pretty_to 2025-12-31 16:38:58 -10:00
J. Nick Koston
528b374b3f [modbus] Use stack buffer for hex formatting in verbose logging 2025-12-31 16:34:36 -10:00
J. Nick Koston
b7d9e3e847 [mitsubishi] Use stack buffer for hex formatting in verbose logging 2025-12-31 16:31:18 -10:00
J. Nick Koston
afd4562062 [mipi_spi] Use stack buffer for hex formatting in verbose logging 2025-12-31 16:28:51 -10:00
J. Nick Koston
724829f5bd [mipi_rgb] Use stack buffer for hex formatting in init sequence logging 2025-12-31 16:25:08 -10:00
J. Nick Koston
4f1b1d7a1e [mipi_dsi] Use stack buffer for hex formatting in very verbose logging 2025-12-31 16:22:04 -10:00
J. Nick Koston
b1ebdabaa9 Merge branch 'kuntze' into integration 2025-12-31 16:18:12 -10:00
J. Nick Koston
b1e359750c [kuntze] Use stack buffer for hex formatting in verbose logging 2025-12-31 16:17:13 -10:00
Jonathan Swoboda
3c9ed126a6 Merge branch 'release' into dev 2025-12-31 17:42:51 -05:00
Jonathan Swoboda
d8c23d4fc9 Merge pull request #12772 from esphome/bump-2025.12.4
2025.12.4
2025-12-31 17:42:39 -05:00
Konstantin Tretyakov
1d96de986e [sdist] Include yaml files in components in source distribution package
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
2026-01-01 08:49:43 +11:00
Jonathan Swoboda
e9e0712959 Bump version to 2025.12.4 2025-12-31 16:07:00 -05:00
J. Nick Koston
062840dd7b [docker] Add build-essential to fix ruamel.yaml 0.19.0 compilation (#12769)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2025-12-31 16:07:00 -05:00
J. Nick Koston
f0f01c081a [wifi] Fix ESP-IDF reporting connected before DHCP completes on reconnect (#12755) 2025-12-31 16:07:00 -05:00
Stuart Parmenter
dd855985be [hub75] Add clipping check (#12762) 2025-12-31 16:06:59 -05:00
J. Nick Koston
4633803d5d [docker] Add build-essential to fix ruamel.yaml 0.19.0 compilation (#12769)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2025-12-31 16:05:58 -05:00
J. Nick Koston
476d00d0e5 [wifi] Fix ESP-IDF reporting connected before DHCP completes on reconnect (#12755) 2025-12-31 15:59:28 -05:00
Stuart Parmenter
98cdef2568 [hub75] Add clipping check (#12762) 2025-12-31 15:58:37 -05:00
J. Nick Koston
4bfc14fa0e Merge branch 'dump_summary' into integration 2025-12-30 13:46:48 -10:00
J. Nick Koston
71d9dff3fc fix 2025-12-30 13:46:36 -10:00
J. Nick Koston
6728a28e1d Merge branch 'dump_summary' into integration 2025-12-30 13:43:20 -10:00
J. Nick Koston
c716983d5c tweak 2025-12-30 13:41:29 -10:00
J. Nick Koston
2c0c5a1b09 Merge branch 'dump_summary' into integration 2025-12-30 13:29:31 -10:00
J. Nick Koston
c13bbd300d tweaks 2025-12-30 13:24:32 -10:00
J. Nick Koston
ac515d6d2e tweaks 2025-12-30 13:23:21 -10:00
J. Nick Koston
e7e83305e8 Merge branch 'dump_summary' into integration 2025-12-30 13:13:40 -10:00
J. Nick Koston
580498e06c missing ; 2025-12-30 13:13:31 -10:00
J. Nick Koston
2d4be9c96f Merge branch 'dump_summary' into integration 2025-12-30 13:10:03 -10:00
J. Nick Koston
52eda13ecd reduce 2025-12-30 13:09:35 -10:00
J. Nick Koston
8ab37379e8 reduce 2025-12-30 13:08:16 -10:00
J. Nick Koston
fcd49fd32d reduce 2025-12-30 13:08:05 -10:00
J. Nick Koston
22b01ad440 Merge branch 'dump_summary' into integration 2025-12-30 13:04:36 -10:00
J. Nick Koston
53aa3f539b copilot suggestion is overkill and breaks things 2025-12-30 13:04:26 -10:00
J. Nick Koston
f42af572b8 Merge branch 'dump_summary' into integration 2025-12-30 13:04:02 -10:00
J. Nick Koston
61b377140f copilot suggestion is overkill and breaks things 2025-12-30 13:03:48 -10:00
J. Nick Koston
957b4d532c Merge branch 'dump_summary' into integration 2025-12-30 12:06:56 -10:00
J. Nick Koston
354ca54a11 adjust 2025-12-30 12:05:36 -10:00
J. Nick Koston
f0be51a49f Merge branch 'dev' into hlk_fm22x_format 2025-12-30 12:02:58 -10:00
J. Nick Koston
9ca590a125 Merge branch 'dump_summary' into integration 2025-12-30 11:53:16 -10:00
J. Nick Koston
ebf5c2851b [gpio] Avoid heap allocation in dump_summary 2025-12-30 11:52:39 -10:00
J. Nick Koston
bd3ecad3a1 [core] Add format_hex_pretty_to buffer helper and reduce code duplication (#12687) 2025-12-30 11:51:51 -10:00
J. Nick Koston
0e725a35c9 Merge branch 'light_effect_ref' into integration 2025-12-30 11:20:08 -10:00
J. Nick Koston
c2865d040f Merge branch 'addressable_light_effect_ref' into integration 2025-12-30 11:19:55 -10:00
J. Nick Koston
5a4a58fd14 Merge branch 'api_avoid_copies' into integration 2025-12-30 11:19:51 -10:00
J. Nick Koston
00f4449cc0 fix ambiguous 2025-12-30 11:17:21 -10:00
J. Nick Koston
89e0797657 simple 2025-12-30 11:14:41 -10:00
J. Nick Koston
cc79334da7 [addressable_light] Use StringRef to avoid allocation when saving effect name 2025-12-30 11:11:53 -10:00
J. Nick Koston
8d61d83425 [light] Use StringRef to avoid allocation in JSON effect name serialization 2025-12-30 11:07:59 -10:00
J. Nick Koston
ac673852bd Merge branch 'api_avoid_copies' into integration 2025-12-30 10:50:32 -10:00
J. Nick Koston
a42820dc26 should never happen but ok 2025-12-30 10:49:02 -10:00
J. Nick Koston
80e03e3951 Merge branch 'api_avoid_copies' into integration 2025-12-30 10:44:37 -10:00
J. Nick Koston
f615409032 len known 2025-12-30 10:44:30 -10:00
J. Nick Koston
d357a62fec Merge branch 'api_avoid_copies' into integration 2025-12-30 10:42:26 -10:00
J. Nick Koston
089e21b15a tweaks 2025-12-30 10:37:03 -10:00
J. Nick Koston
3e8857b358 tweaks 2025-12-30 10:32:06 -10:00
J. Nick Koston
03c9107826 Merge remote-tracking branch 'upstream/dev' into api_avoid_copies 2025-12-30 10:28:51 -10:00
J. Nick Koston
dae7ba604a [ethernet_info] Eliminate heap allocations in DNS text sensor (#12756) 2025-12-30 10:25:51 -10:00
J. Nick Koston
201ae5801a Merge branch 'ethernet_info_no_heap' into integration 2025-12-30 09:59:49 -10:00
J. Nick Koston
a346b983a7 [ethernet_info] Eliminate heap allocations in DNS text sensor 2025-12-30 09:59:20 -10:00
J. Nick Koston
880cc841f4 Merge branch 'wifi_reconnect_esp_idf' into integration 2025-12-30 09:13:26 -10:00
J. Nick Koston
eea2037627 [wifi] Fix ESP-IDF reporting connected before DHCP completes on reconnect 2025-12-30 08:51:00 -10:00
Jonathan Swoboda
96c47f3b4d Merge branch 'release' into dev 2025-12-30 09:31:44 -05:00
Jonathan Swoboda
5b5cede5f9 Merge pull request #12752 from esphome/bump-2025.12.3
2025.12.3
2025-12-30 09:31:31 -05:00
Jonathan Swoboda
c737033cc4 Bump version to 2025.12.3 2025-12-30 09:22:03 -05:00
J. Nick Koston
0194bfd9ea [core] Fix incremental build failures when adding components on ESP32-Arduino (#12745) 2025-12-30 09:22:03 -05:00
J. Nick Koston
339399eb70 [lvgl] Fix lambdas in canvas actions called from outside LVGL context (#12671) 2025-12-30 09:22:03 -05:00
Samuel Sieb
a615b28ecf [bme68x_bsec2] add id: to allow extending (#12649) 2025-12-29 23:22:36 -08:00
J. Nick Koston
065d0541d1 Merge branch 'buffering' into integration 2025-12-29 21:16:25 -10:00
J. Nick Koston
25a4d7ffab tweak 2025-12-29 21:16:11 -10:00
J. Nick Koston
10b0308bc0 tests 2025-12-29 21:11:39 -10:00
J. Nick Koston
21bd6c5b18 [core] Improve log timestamp accuracy by batching serial reads 2025-12-29 20:59:03 -10:00
bakroistvan
468bd7b04f [dallas_temp] higher precision for logged temperature (#12695) 2025-12-29 22:53:28 -08:00
J. Nick Koston
fe7fa02a4e Merge remote-tracking branch 'upstream/dev' into integration 2025-12-29 17:43:52 -10:00
Jonathan Swoboda
4c16afeacb [esp32] Add IDF framework source for Arduino builds (#12731)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick+github@koston.org>
2025-12-29 22:25:26 -05:00
J. Nick Koston
d86c05bfe6 [esp32] Breaking Change: Change default framework to ESP-IDF (#12746)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-30 03:23:41 +00:00
J. Nick Koston
63464a13c3 [core] Fix incremental build failures when adding components on ESP32-Arduino (#12745) 2025-12-29 16:57:22 -10:00
J. Nick Koston
f2b1c51372 Merge remote-tracking branch 'upstream/esp32_default_framework_idf' into integration 2025-12-29 16:54:05 -10:00
J. Nick Koston
3903594bd3 Update esphome/components/esp32/__init__.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-29 16:53:51 -10:00
J. Nick Koston
c4d73a07b2 Merge branch 'storage_should_update_cmake_cache_arudino_fix' into integration 2025-12-29 16:49:26 -10:00
J. Nick Koston
148dbee6cb Merge branch 'esp32_default_framework_idf' into integration 2025-12-29 16:49:22 -10:00
J. Nick Koston
436b4c4217 [esp32] Change default framework to ESP-IDF 2025-12-29 16:38:11 -10:00
J. Nick Koston
2297d240be cleanup 2025-12-29 16:28:14 -10:00
J. Nick Koston
1d1f2a9877 cover 2025-12-29 16:25:17 -10:00
J. Nick Koston
1472914527 cover 2025-12-29 16:24:10 -10:00
J. Nick Koston
c9c0bdb1c6 Merge branch 'dev' into storage_should_update_cmake_cache_arudino_fix 2025-12-29 16:23:39 -10:00
J. Nick Koston
1e5739fb93 [core] Fix incremental build failures when adding components on ESP32-Arduino 2025-12-29 16:22:04 -10:00
Clyde Stubbs
20e43398fa [cli] Report program path on host (#12743) 2025-12-30 13:21:30 +11:00
J. Nick Koston
3053687273 Merge branch 'ble_client' into integration 2025-12-29 15:52:12 -10:00
J. Nick Koston
5e7d89f302 [ble_client] Use stack buffer for hex formatting in very verbose logging 2025-12-29 15:51:35 -10:00
J. Nick Koston
005dd1ea73 [ble_client] Use stack buffer for hex formatting in very verbose logging 2025-12-29 15:49:48 -10:00
J. Nick Koston
8477dfc6c2 Merge branch 'ethernet_format_hex' into integration 2025-12-29 14:55:28 -10:00
J. Nick Koston
7b274d3347 [ethernet] Use stack buffer for hex formatting in very verbose logging 2025-12-29 14:54:53 -10:00
J. Nick Koston
e844d5403e Merge branch 'esp32_ble_tracker' into integration 2025-12-29 14:37:45 -10:00
J. Nick Koston
d16b790243 [esp32_ble_tracker] Use stack buffer for hex formatting in very verbose logging 2025-12-29 14:34:08 -10:00
J. Nick Koston
2bcdee5a09 Merge branch 'hlk_fm22x_format' into integration 2025-12-29 14:25:27 -10:00
J. Nick Koston
c413b968f3 [hlk_fm22x] Use stack buffer for hex formatting in verbose logging 2025-12-29 14:23:39 -10:00
J. Nick Koston
f98ba2827c Merge branch 'i2c' into integration 2025-12-29 14:11:23 -10:00
J. Nick Koston
8f42b3d101 [i2c] Use stack buffer for hex formatting in verbose logging 2025-12-29 14:10:34 -10:00
J. Nick Koston
b7e27087b4 [espnow] Use stack buffer for hex formatting in verbose logging 2025-12-29 14:04:36 -10:00
J. Nick Koston
4230d39262 Merge branch 'esp32_improv' into integration 2025-12-29 13:58:27 -10:00
J. Nick Koston
fe9de00f54 [esp32_improv] Use stack buffer for hex formatting in verbose logging 2025-12-29 13:56:43 -10:00
J. Nick Koston
0aa275f475 Merge branch 'dev' into logger_esp8266 2025-12-29 13:08:24 -10:00
J. Nick Koston
c94f0e16ad Merge branch 'logger_esp8266' into integration 2025-12-29 13:07:19 -10:00
J. Nick Koston
c09f555e18 [logger] Exclude unused Arduino Serial objects on ESP8266 2025-12-29 13:06:33 -10:00
hsand
2e7cdad532 [pvvx_mithermometer] fix displaying negative numbers (#12735) 2025-12-29 13:58:38 -08:00
J. Nick Koston
70bd83f4f5 Merge remote-tracking branch 'swoboda1337/esp32-arduino-idf-source' into integration 2025-12-29 10:52:11 -10:00
J. Nick Koston
2e5403c743 [epaper_spi] Use stack buffer for hex formatting in command logging 2025-12-29 10:41:39 -10:00
J. Nick Koston
eafa86e227 Merge branch 'nextion' into integration 2025-12-29 10:30:49 -10:00
J. Nick Koston
4e93fdd37a [nextion] Use stack buffers for hex formatting in upload logging 2025-12-29 10:29:57 -10:00
J. Nick Koston
05761ba972 Merge branch 'tuya_format_hex' into integration 2025-12-29 10:25:22 -10:00
J. Nick Koston
6ca9220e5b Merge branch 'cse7766' into integration 2025-12-29 10:25:17 -10:00
J. Nick Koston
98f49fa970 [cse7766] Use stack buffer for hex formatting in debug logging 2025-12-29 10:24:32 -10:00
J. Nick Koston
22656095b6 missed one 2025-12-29 10:21:11 -10:00
J. Nick Koston
ede4511b12 Merge branch 'fix_opentherm_heap_alloc_logging' into integration 2025-12-29 10:15:47 -10:00
J. Nick Koston
33fafa2427 Merge branch 'shelly_dimmer' into integration 2025-12-29 10:15:37 -10:00
J. Nick Koston
5cd4df2de9 Merge branch 'mirage_protocol' into integration 2025-12-29 10:15:34 -10:00
J. Nick Koston
37b656323c Merge branch 'rc522' into integration 2025-12-29 10:15:31 -10:00
J. Nick Koston
b19f0b092a Merge branch 'haier_protocol' into integration 2025-12-29 10:15:27 -10:00
J. Nick Koston
f70b56bb04 Merge branch 'jsn_sr04t' into integration 2025-12-29 10:15:16 -10:00
J. Nick Koston
42333473c5 Merge branch 'a02yyuw' into integration 2025-12-29 10:15:11 -10:00
J. Nick Koston
159f9afcc0 Merge branch 'a01nyub' into integration 2025-12-29 10:15:08 -10:00
J. Nick Koston
9f0644cc02 Merge branch 'sonoff_d1' into integration 2025-12-29 10:14:52 -10:00
J. Nick Koston
b2b18b26c3 [sonoff_d1] Use stack buffer for hex formatting in logging 2025-12-29 10:14:17 -10:00
Jonathan Swoboda
c5be39f499 [esp32] Add IDF framework source for Arduino builds
Add ARDUINO_IDF_VERSION_LOOKUP table mapping Arduino framework versions
to their underlying ESP-IDF versions. When building with Arduino framework,
explicitly add the corresponding IDF framework source to platform_packages
to ensure consistent IDF versions are used.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 15:12:55 -05:00
J. Nick Koston
e1ce6b151d [jsn_sr04t] Use stack buffer for hex formatting in error logging 2025-12-29 10:09:27 -10:00
J. Nick Koston
0bc35f5086 [a02yyuw] Use stack buffer for hex formatting in error logging 2025-12-29 10:05:46 -10:00
J. Nick Koston
6ead7f82db [a01nyub] Use stack buffer for hex formatting in error logging 2025-12-29 10:03:25 -10:00
J. Nick Koston
1f832064d1 [opentherm] Replace heap-allocating format calls with printf format specifiers in debug_error 2025-12-29 09:58:13 -10:00
dependabot[bot]
636cccc6a3 Bump aioesphomeapi from 43.9.0 to 43.9.1 (#12724)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-29 09:55:26 -10:00
J. Nick Koston
b47462d64a [rc522] Use stack buffers for hex formatting in tag logging 2025-12-29 09:53:03 -10:00
J. Nick Koston
fdefbeb3dc [remote_base] Use stack buffer for hex formatting in haier protocol logging` 2025-12-29 09:44:08 -10:00
J. Nick Koston
3bd1a6fcf8 [remote_base] Use stack buffer for hex formatting in mirage protocol logging 2025-12-29 09:39:27 -10:00
J. Nick Koston
80551969f1 fix 2025-12-29 09:34:43 -10:00
J. Nick Koston
29a64b9113 [shelly_dimmer] Use stack buffer for hex formatting in command logging 2025-12-29 09:31:17 -10:00
Thomas Rupprecht
93e2a1bd1a [tests] improve mipi_spi variable naming (#12716) 2025-12-29 14:21:07 -05:00
Thomas Rupprecht
dd3beb5841 [tests] fix typo mipi tests (#12715) 2025-12-29 14:20:38 -05:00
Thomas Rupprecht
97af01c5ed [usb_host] sort esp32 variants (#12720) 2025-12-29 14:19:36 -05:00
J. Nick Koston
f1f0f9d7bf Merge remote-tracking branch 'upstream/ota_drop_md5' into integration 2025-12-29 08:45:46 -10:00
J. Nick Koston
8110d36f1c Merge branch 'dev' into ota_drop_md5 2025-12-29 08:45:00 -10:00
J. Nick Koston
7e362cdafc [ota] Use precision format specifier for auth logging (#12706)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-29 08:43:54 -10:00
Jonathan Swoboda
890d531cea [esp32] Bump to ESP-IDF 5.5.2, Arduino 3.3.5, platform 55.3.35 (#12681)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2025-12-29 11:35:54 -05:00
Swaptor
6a6c6b648f [internal_temperature] Add ESP32-C5 support (#12713)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2025-12-29 11:32:32 -05:00
J. Nick Koston
2f5e3193c7 Merge branch 'ota_drop_md5' into integration 2025-12-28 22:35:01 -10:00
J. Nick Koston
5f387e5d6c tweaks 2025-12-28 22:34:49 -10:00
J. Nick Koston
dbb87f53e1 Merge branch 'ota_drop_md5' into integration 2025-12-28 22:28:26 -10:00
J. Nick Koston
fe8f9c160d Merge branch 'ota_logging_cleanups' into integration 2025-12-28 22:27:29 -10:00
J. Nick Koston
d2217a2534 [ota] Remove MD5 authentication support 2025-12-28 22:26:04 -10:00
J. Nick Koston
8dd803a05e Update esphome/components/esphome/ota/ota_esphome.cpp
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-28 22:08:27 -10:00
J. Nick Koston
3ef0a7527f Merge branch 'ota_logging_cleanups' into integration 2025-12-28 22:03:11 -10:00
J. Nick Koston
bf1d3c534d [ota] Use precision format specifier for auth logging 2025-12-28 22:02:46 -10:00
J. Nick Koston
600c2453f4 Merge branch 'stack_copy_not_needed_wifi' into integration 2025-12-28 21:54:25 -10:00
J. Nick Koston
ab332b588f [wifi] Use precision format specifier for SSID logging to avoid stack copy 2025-12-28 21:53:53 -10:00
J. Nick Koston
495b128af9 Merge branch 'no_send_object_id' into integration 2025-12-28 21:41:59 -10:00
dependabot[bot]
d0673122a8 Bump aioesphomeapi from 43.8.0 to 43.9.0 (#12702) 2025-12-28 18:15:06 -10:00
J. Nick Koston
70038ea0a8 tweak 2025-12-28 17:42:31 -10:00
J. Nick Koston
463a5b6af9 tweak 2025-12-28 17:37:25 -10:00
J. Nick Koston
2756a027f7 Merge branch 'object_id_no_ram' into no_send_object_id 2025-12-28 17:17:05 -10:00
J. Nick Koston
64b61809a4 Merge branch 'dev' into object_id_no_ram 2025-12-28 17:16:35 -10:00
dependabot[bot]
5cbef3ef95 Bump aioesphomeapi from 43.7.0 to 43.8.0 (#12701) 2025-12-29 03:15:40 +00:00
dependabot[bot]
a1e0121330 Bump bleak from 2.0.0 to 2.1.0 (#12700)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-28 16:48:20 -10:00
dependabot[bot]
eb050ff13e Bump aioesphomeapi from 43.6.0 to 43.7.0 (#12699)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-28 16:48:08 -10:00
J. Nick Koston
d65284e760 Merge branch 'no_send_object_id' into integration 2025-12-28 15:34:55 -10:00
J. Nick Koston
7a091c0ac6 [api] Remove object_id from API protocol - clients compute it from name 2025-12-28 15:23:32 -10:00
J. Nick Koston
c81aec9e58 Merge branch 'dev' into object_id_no_ram 2025-12-28 14:51:14 -10:00
J. Nick Koston
550c8c40d3 Merge branch 'min_chip_revision' into integration 2025-12-28 13:43:22 -10:00
J. Nick Koston
cd3dadb3c9 reduce 2025-12-28 13:43:04 -10:00
J. Nick Koston
c6857cb5fe Merge branch 'min_chip_revision' into integration 2025-12-28 13:31:52 -10:00
J. Nick Koston
16315d72b6 define 2025-12-28 13:30:45 -10:00
J. Nick Koston
56a0fe0a1a Merge branch 'min_chip_revision' into integration 2025-12-28 13:26:08 -10:00
J. Nick Koston
90af7e3088 [esp32] Add minimum_chip_revision setting and log chip revision at startup 2025-12-28 13:20:06 -10:00
J. Nick Koston
07e844453d Merge branch 'esp8266_waveform' into integration 2025-12-27 22:02:28 -10:00
J. Nick Koston
080e461184 tweaks 2025-12-27 21:59:44 -10:00
J. Nick Koston
05f19ea644 tweaks 2025-12-27 21:56:02 -10:00
J. Nick Koston
8751c1d32c Merge branch 'esp8266_waveform' into integration 2025-12-27 21:38:58 -10:00
J. Nick Koston
ebe43228e3 tweaks 2025-12-27 21:33:08 -10:00
J. Nick Koston
0f8bef5543 fixes 2025-12-27 21:29:00 -10:00
J. Nick Koston
53fa89d0e3 tweaks 2025-12-27 21:27:34 -10:00
J. Nick Koston
ca3b9a0e55 [esp8266] Exclude unused waveform code to save ~596 bytes RAM 2025-12-27 21:24:24 -10:00
J. Nick Koston
f0894ab958 Merge branch 'get_peername_stack_save_ram' into integration 2025-12-27 19:06:25 -10:00
J. Nick Koston
c410171a63 remove old way 2025-12-27 19:06:09 -10:00
J. Nick Koston
5f7863af21 Merge branch 'get_peername_stack_save_ram' into integration 2025-12-27 18:58:47 -10:00
J. Nick Koston
95ae7caf24 mark final 2025-12-27 18:58:35 -10:00
J. Nick Koston
4d6bc262da Merge branch 'get_peername_stack_save_ram' into integration 2025-12-27 18:54:31 -10:00
J. Nick Koston
e698a88380 fix 2025-12-27 18:54:11 -10:00
J. Nick Koston
ee94ee7e59 Merge branch 'get_peername_stack_save_ram' into integration 2025-12-27 18:51:00 -10:00
J. Nick Koston
30b169a4cf fix 2025-12-27 18:50:34 -10:00
J. Nick Koston
47c475a03c wip 2025-12-27 18:40:14 -10:00
J. Nick Koston
a522447bed Merge branch 'get_peername_stack_save_ram' into integration 2025-12-27 18:36:10 -10:00
J. Nick Koston
e15bac46cb missed one 2025-12-27 18:35:57 -10:00
J. Nick Koston
6f5900713c wip 2025-12-27 18:32:14 -10:00
J. Nick Koston
dafe9da1eb Merge branch 'get_peername_stack_save_ram' into integration 2025-12-27 18:24:15 -10:00
J. Nick Koston
b8d246b706 fix 2025-12-27 18:24:01 -10:00
J. Nick Koston
23d88933fd Merge branch 'get_peername_stack_save_ram' into integration 2025-12-27 18:20:47 -10:00
J. Nick Koston
274b1e26ce tweak 2025-12-27 18:20:29 -10:00
J. Nick Koston
dc51abbd82 Merge branch 'get_peername_stack_save_ram' into integration 2025-12-27 18:18:55 -10:00
J. Nick Koston
0217c130dd tweak 2025-12-27 18:15:11 -10:00
J. Nick Koston
1290929684 tweak 2025-12-27 18:14:11 -10:00
J. Nick Koston
96b2888505 tweak 2025-12-27 18:06:57 -10:00
J. Nick Koston
d2bab26e67 tweak 2025-12-27 18:05:26 -10:00
J. Nick Koston
d404e37449 reduce 2025-12-27 17:49:25 -10:00
J. Nick Koston
f9659fc693 reduce 2025-12-27 17:49:04 -10:00
J. Nick Koston
ce71e7bccd Merge branch 'get_peername_stack_save_ram' into integration 2025-12-27 17:10:50 -10:00
J. Nick Koston
f4cb379d6b tweaks 2025-12-27 17:01:10 -10:00
J. Nick Koston
49e0e66aee Merge branch 'dev' into get_peername_stack_save_ram 2025-12-27 16:51:46 -10:00
J. Nick Koston
3d82118bd5 Merge branch 'dev' into api_avoid_copies 2025-12-27 16:45:43 -10:00
J. Nick Koston
92f44da2cf Merge branch 'tuya_format_hex' into integration 2025-12-27 16:34:37 -10:00
J. Nick Koston
db82a3f5f8 [tuya] Use stack buffers for hex logging to avoid heap allocations 2025-12-27 16:10:38 -10:00
J. Nick Koston
e6891d4027 Merge branch 'ldxxxx_no_heap' into integration 2025-12-27 15:54:01 -10:00
J. Nick Koston
60c6d94083 remove tests 2025-12-27 15:48:43 -10:00
J. Nick Koston
e1a5830d9f Merge branch 'zwave_no_alloc_hex' of https://github.com/esphome/esphome into zwave_no_alloc_hex 2025-12-27 15:46:23 -10:00
J. Nick Koston
783604b8b4 [ld2410][ld2412][ld2450] Use stack buffers for hex logging 2025-12-27 15:45:17 -10:00
J. Nick Koston
53ad49086d fixes 2025-12-27 15:40:32 -10:00
J. Nick Koston
a2d25b532a Merge branch 'zwave_no_alloc_hex' into integration 2025-12-27 15:23:43 -10:00
J. Nick Koston
05c51b6ced Add isolated tests for hex formatting functions 2025-12-27 15:18:47 -10:00
J. Nick Koston
89f326be30 reduce 2025-12-27 15:12:30 -10:00
J. Nick Koston
38850a9ab3 more dry 2025-12-27 15:08:44 -10:00
J. Nick Koston
4d4498e81f fix max 2025-12-27 14:57:42 -10:00
J. Nick Koston
d1707ac4d6 Merge branch 'zwave_no_alloc_hex' into integration 2025-12-27 14:39:36 -10:00
J. Nick Koston
61970bd1de [core] Add format_hex_pretty_to buffer helper and reduce code duplication 2025-12-27 14:34:33 -10:00
J. Nick Koston
09f03dcf0c Merge branch 'mqtt_ip_no_alloc' into integration 2025-12-27 14:08:18 -10:00
J. Nick Koston
adaebd4b4e [mqtt] Avoid heap allocations when logging IP addresses 2025-12-27 14:07:07 -10:00
J. Nick Koston
9f2d34bacb Merge remote-tracking branch 'origin/no_heap_alloc_start_dnsserver' into integration 2025-12-27 14:03:44 -10:00
J. Nick Koston
6f780a63ab Merge branch 'udp_multicast_avoid_heap' into integration 2025-12-27 14:02:12 -10:00
J. Nick Koston
9b2488cd8d [udp] Avoid heap allocations when joining multicast groups 2025-12-27 14:00:38 -10:00
J. Nick Koston
e76bc6b357 Merge remote-tracking branch 'origin/integration' into integration 2025-12-27 12:35:36 -10:00
J. Nick Koston
0867e96585 Merge branch 'esp-idf-5.5.2' into integration 2025-12-27 12:35:24 -10:00
J. Nick Koston
1618c69923 Merge remote-tracking branch 'upstream/dev' into esp-idf-5.5.2 2025-12-27 12:02:07 -10:00
Jonathan Swoboda
45e61f100c [core] Replace USE_ESP_IDF with USE_ESP32 across components (#12673)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-12-27 11:59:55 -10:00
J. Nick Koston
6dd1175fe7 Merge branch 'improv_stack_format' into integration 2025-12-27 11:30:02 -10:00
J. Nick Koston
fe651f1b8d Merge branch 'wifi_no_heap_logging_cap_portal' into integration 2025-12-27 11:29:53 -10:00
J. Nick Koston
3768a269ad nolint 2025-12-27 11:29:29 -10:00
J. Nick Koston
b9d80a5ef3 [esp32_improv] Use stack buffer for URL formatting to avoid heap allocation 2025-12-27 11:27:28 -10:00
J. Nick Koston
1aebe90ad5 [esp32_improv] Use stack buffer for URL formatting to avoid heap allocation 2025-12-27 11:26:24 -10:00
J. Nick Koston
06c4325525 lint 2025-12-27 11:21:44 -10:00
Jonathan Swoboda
343316ac2d [esp32] Bump to ESP-IDF 5.5.2, Arduino 3.3.5, platform 55.3.35
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-27 14:33:32 -05:00
J. Nick Koston
cc0b63a277 fix 2025-12-27 09:32:22 -10:00
J. Nick Koston
4271a64ce4 fix 2025-12-27 09:31:06 -10:00
J. Nick Koston
52c692c99b [wifi] Use stack buffers for IP address logging to avoid heap allocations 2025-12-27 09:26:44 -10:00
J. Nick Koston
a8fb40c946 [wifi] Use stack buffers for IP address logging to avoid heap allocations 2025-12-27 09:24:17 -10:00
J. Nick Koston
0b621bb0a3 [captive_portal] Use stack buffer for IP address logging in DNS server 2025-12-27 09:07:44 -10:00
J. Nick Koston
7bc7089fbe Merge branch 'wifi_alloc_during_connect' into integration 2025-12-27 08:58:11 -10:00
J. Nick Koston
32880e3d5a [wifi] Use wifi_ssid_to() to avoid heap allocations in automation and connection checks 2025-12-27 08:57:39 -10:00
J. Nick Koston
206793d4ab Merge remote-tracking branch 'upstream/dev' into integration 2025-12-27 08:52:13 -10:00
J. Nick Koston
5e99dd14ae [ethernet] Eliminate heap allocations in dump_config logging (#12665) 2025-12-27 08:36:35 -10:00
J. Nick Koston
a6097f4a0f [wifi] Eliminate heap allocations in dump_config logging (#12664)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-27 08:36:19 -10:00
J. Nick Koston
f243e609a5 [wifi] Use StringRef and std::span in WiFiConnectStateListener to avoid allocations (#12672) 2025-12-27 08:35:58 -10:00
J. Nick Koston
be0bf1e5b9 [lvgl] Fix lambdas in canvas actions called from outside LVGL context (#12671) 2025-12-27 08:35:36 -10:00
J. Nick Koston
a275f37135 [udp] Use stack buffer for listen address logging in dump_config (#12667) 2025-12-27 08:35:16 -10:00
J. Nick Koston
e9f2d75aab [core] Add format_hex_to helper for zero-allocation hex formatting (#12670) 2025-12-27 08:34:45 -10:00
J. Nick Koston
34067f8b15 [esp8266] Native OTA backend to reduce Arduino dependencies (#12675)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-27 08:29:15 -10:00
J. Nick Koston
47ae027026 Merge branch 'esp8266_native_framework_update' into integration 2025-12-26 23:04:31 -10:00
J. Nick Koston
cfe9e6204b preen 2025-12-26 23:01:18 -10:00
J. Nick Koston
547aa59c18 Merge branch 'esp8266_native_framework_update' into integration 2025-12-26 22:37:59 -10:00
J. Nick Koston
5b9c7d1322 Update esphome/components/ota/ota_backend_esp8266.h
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-26 22:36:12 -10:00
J. Nick Koston
d0ba608ffa add comment 2025-12-26 22:35:27 -10:00
J. Nick Koston
c91f56171b Update esphome/components/ota/ota_backend_esp8266.cpp
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-26 22:34:22 -10:00
J. Nick Koston
15ad89f66d Update esphome/components/ota/ota_backend_esp8266.cpp
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-26 22:33:38 -10:00
J. Nick Koston
8f0de69e9f Merge branch 'esp8266_native_framework_update' into integration 2025-12-26 22:23:40 -10:00
J. Nick Koston
37de782e3e guard 2025-12-26 22:13:10 -10:00
J. Nick Koston
a5574bbabe dry 2025-12-26 21:59:47 -10:00
J. Nick Koston
1bea4df45e guard 2025-12-26 21:51:09 -10:00
J. Nick Koston
57829ddd76 fixes 2025-12-26 20:23:13 -10:00
J. Nick Koston
99722fb04f fixes 2025-12-26 20:22:16 -10:00
J. Nick Koston
faa4cf7483 fixes 2025-12-26 20:19:25 -10:00
J. Nick Koston
16e96dfbc0 fixes 2025-12-26 20:18:25 -10:00
J. Nick Koston
062195be95 native framework updater PoC 2025-12-26 20:12:27 -10:00
J. Nick Koston
b2133c75f1 native framework updater PoC 2025-12-26 20:07:20 -10:00
J. Nick Koston
655a746e0d Merge branch 'wifi_listeners' into integration 2025-12-26 14:57:39 -10:00
J. Nick Koston
a2ea545e10 make the bot happy 2025-12-26 14:57:26 -10:00
J. Nick Koston
6fe5d14b3f Merge branch 'wifi_listeners' into integration 2025-12-26 14:44:41 -10:00
J. Nick Koston
f446860166 might as well make it span 2025-12-26 14:43:01 -10:00
J. Nick Koston
02e8603051 Merge branch 'wifi_listeners' into integration 2025-12-26 14:35:32 -10:00
J. Nick Koston
3fe4e18dc4 [wifi] Use StringRef for WiFiConnectStateListener to avoid heap allocation 2025-12-26 14:34:06 -10:00
J. Nick Koston
b221673ba7 Merge branch 'ethernet_logging_less_alloc' into integration 2025-12-26 13:44:44 -10:00
J. Nick Koston
e711cd0e41 dry it up 2025-12-26 13:39:57 -10:00
J. Nick Koston
307489cd59 missed one 2025-12-26 13:33:01 -10:00
J. Nick Koston
e7c0d13500 Merge branch 'dev' into ethernet_logging_less_alloc 2025-12-26 12:56:06 -10:00
J. Nick Koston
bdc087148a [wifi_info] Reduce heap allocations in text sensor formatting (#12660) 2025-12-26 12:52:41 -10:00
J. Nick Koston
5a2e0612a8 [web_server] Use C++17 nested namespace syntax (#12663) 2025-12-26 08:44:34 -10:00
J. Nick Koston
f1fecd22e3 [web_server] Move HTTP header strings to flash on ESP8266 (#12668) 2025-12-26 08:44:17 -10:00
J. Nick Koston
0919017d49 [wifi] Avoid unnecessary string copy in failed connection logging (#12659) 2025-12-26 08:44:03 -10:00
J. Nick Koston
963f594c9e [text_sensor] Return state by const reference to avoid copies (#12661) 2025-12-26 07:58:46 -10:00
J. Nick Koston
4f70663658 [alarm_control_panel] Use C++17 nested namespace and remove unused include (#12662) 2025-12-26 07:57:33 -10:00
J. Nick Koston
3f20a54240 Merge branch 'web_server_more_strings_ram' into integration 2025-12-25 23:07:17 -10:00
J. Nick Koston
e9e301c835 cleanup 2025-12-25 23:05:29 -10:00
J. Nick Koston
8c90477387 more 2025-12-25 23:02:22 -10:00
J. Nick Koston
a394fe8ad2 Merge branch 'web_server_more_strings_ram' into integration 2025-12-25 22:52:46 -10:00
J. Nick Koston
d642e9d85e [web_server] Move HTTP header strings to flash on ESP8266 2025-12-25 22:52:01 -10:00
J. Nick Koston
fa05018b2c Merge branch 'object_id_no_ram' into integration 2025-12-25 22:26:56 -10:00
J. Nick Koston
63d7ab0d40 Merge branch 'udp_listen_logging_alloc' into integration 2025-12-25 22:03:04 -10:00
J. Nick Koston
51f95c7f9a [udp] Use stack buffer for listen address logging in dump_config 2025-12-25 22:01:57 -10:00
J. Nick Koston
2ac67b59e8 Merge branch 'ethernet_logging_less_alloc' into integration 2025-12-25 21:51:39 -10:00
J. Nick Koston
0767df02d9 [ethernet] Eliminate heap allocations in dump_config logging 2025-12-25 21:50:54 -10:00
J. Nick Koston
984822388d Merge branch 'web_server_namespace' into integration 2025-12-25 21:25:32 -10:00
J. Nick Koston
cc49ec82bf [web_server] Use C++17 nested namespace syntax 2025-12-25 21:24:47 -10:00
J. Nick Koston
cc18092e7a Merge branch 'alarm_control_panel_cleanup' into integration 2025-12-25 21:17:59 -10:00
J. Nick Koston
825d12553e [alarm_control_panel] Use C++17 nested namespace and remove unused include 2025-12-25 21:17:13 -10:00
J. Nick Koston
0bd82b19b3 Merge branch 'text_sensor_avoid_copies' into integration 2025-12-25 21:10:41 -10:00
J. Nick Koston
460792e180 [text_sensor] Return state by const reference to avoid copies 2025-12-25 21:09:49 -10:00
J. Nick Koston
5411008c49 Merge branch 'wifi_info_less_alloc' into integration 2025-12-25 20:47:01 -10:00
J. Nick Koston
9e13f6ac4c copilot is wrong, add comment 2025-12-25 20:46:20 -10:00
J. Nick Koston
b8cb6fedb3 address copilot review comments 2025-12-25 20:38:50 -10:00
J. Nick Koston
68f36ae736 address copilot review comments 2025-12-25 20:38:38 -10:00
J. Nick Koston
6cbe3e306b Merge branch 'wifi_info_less_alloc' into integration 2025-12-25 16:03:31 -10:00
J. Nick Koston
cae7163741 fixes 2025-12-25 16:03:12 -10:00
J. Nick Koston
10aee92762 Merge branch 'wifi_avoid_copy_logging' into integration 2025-12-25 16:01:04 -10:00
J. Nick Koston
736a1bb019 Merge branch 'wifi_info_less_alloc' into integration 2025-12-25 16:00:58 -10:00
J. Nick Koston
ca652b2065 [wifi_info] Reduce heap allocations in text sensor formatting 2025-12-25 15:58:17 -10:00
J. Nick Koston
7608b8ee84 [wifi] Avoid unnecessary string copy in failed connection logging 2025-12-25 15:06:36 -10:00
J. Nick Koston
d490594609 Merge remote-tracking branch 'upstream/response_api' into integration 2025-12-25 14:51:28 -10:00
J. Nick Koston
8715a60b7a [api] Use StringRef in send_action_response and send_execute_service_response 2025-12-25 14:48:19 -10:00
J. Nick Koston
dd99c565ca Merge remote-tracking branch 'upstream/siren_zero_copy' into integration 2025-12-25 14:37:45 -10:00
J. Nick Koston
20df6a7f9a [api] Use pointer to FixedVector for siren tones field 2025-12-25 14:36:06 -10:00
J. Nick Koston
3e4631baa9 Merge remote-tracking branch 'upstream/bytes_zero_copy_default_api' into integration 2025-12-25 14:20:31 -10:00
J. Nick Koston
6af34f1e2a Merge remote-tracking branch 'upstream/handle_action_response_opt' into integration 2025-12-25 14:20:28 -10:00
J. Nick Koston
0ba15b51c6 Merge remote-tracking branch 'upstream/voice_assist_zero_copy' into integration 2025-12-25 14:20:22 -10:00
J. Nick Koston
8004602ef2 [voice_assistant] Use zero-copy buffer access for audio data` 2025-12-25 14:14:06 -10:00
J. Nick Koston
a3ec57eaf4 [api] Use StringRef in handle_action_response to avoid temporary string 2025-12-25 14:01:40 -10:00
J. Nick Koston
98460ac828 [api] Auto-generate zero-copy pointer access for incoming API bytes fields 2025-12-25 13:56:08 -10:00
J. Nick Koston
7c739592a8 Merge branch 'dev' into get_peername_stack_save_ram 2025-12-25 09:02:44 -10:00
J. Nick Koston
2b10408e28 Merge remote-tracking branch 'upstream/string_ref_for_all_incoming_api_strings' into integration 2025-12-25 09:02:03 -10:00
J. Nick Koston
33d1efe27c tidy 2025-12-24 22:21:00 -10:00
J. Nick Koston
0e9aaf1a8b fixes 2025-12-24 22:07:48 -10:00
J. Nick Koston
7f4fad74c2 fixes 2025-12-24 22:07:35 -10:00
J. Nick Koston
8b72c3c0ef [api] Auto-generate StringRef for incoming API string fields 2025-12-24 22:05:19 -10:00
dependabot[bot]
958a35e262 Bump aioesphomeapi from 43.5.0 to 43.6.0 (#12644)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-24 14:17:52 -10:00
J. Nick Koston
da1955fefc dry up tests 2025-12-23 07:54:52 -10:00
J. Nick Koston
8505a4dfaf dry up tests 2025-12-23 07:52:33 -10:00
J. Nick Koston
071e42d4e7 Merge remote-tracking branch 'origin/object_id_no_ram' into object_id_no_ram 2025-12-23 07:46:07 -10:00
J. Nick Koston
38beb613c2 simplify 2025-12-23 07:45:46 -10:00
J. Nick Koston
058c637b59 Merge branch 'dev' into object_id_no_ram 2025-12-23 06:59:16 -10:00
J. Nick Koston
0c566c6f00 [core] Deprecate get_object_id() and migrate remaining usages to get_object_id_to() (#12629) 2025-12-23 06:59:07 -10:00
Jonathan Swoboda
ba73289b28 Merge branch 'release' into dev 2025-12-23 11:17:15 -05:00
Jonathan Swoboda
99f7e9aeb7 Merge pull request #12632 from esphome/bump-2025.12.2
2025.12.2
2025-12-23 11:17:01 -05:00
Jonathan Swoboda
ebb6babb3d Fix hash 2025-12-23 09:26:38 -05:00
Jonathan Swoboda
0922f240e0 Bump version to 2025.12.2 2025-12-23 09:23:04 -05:00
Jonathan Swoboda
c8fb694dcb [cc1101] Fix packet mode RSSI/LQI (#12630)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-23 09:23:04 -05:00
J. Nick Koston
6054685dae [esp32_camera] Throttle frame logging to reduce overhead and improve throughput (#12586) 2025-12-23 09:23:04 -05:00
Anna Oake
61ec3508ed [cc1101] Fix option defaults and move them to YAML (#12608) 2025-12-23 09:23:04 -05:00
Leo Bergolth
086ec770ea send NIL ("-") as timestamp if time source is not valid (#12588) 2025-12-23 09:23:04 -05:00
Stuart Parmenter
b055f5b4bf [hub75] Bump esp-hub75 version to 0.1.7 (#12564) 2025-12-23 09:23:00 -05:00
Eduard Llull
726db746c8 [display_menu_base] Call on_value_ after updating the select (#12584) 2025-12-23 09:21:54 -05:00
Keith Burzinski
1922455fa7 [wifi] Fix for wifi_info when static IP is configured (#12576) 2025-12-23 09:21:54 -05:00
Thomas Rupprecht
dc943d7e7a [pca9685,sx126x,sx127x] Use frequency/float_range check (#12490)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2025-12-23 09:21:54 -05:00
Jonathan Swoboda
ffefa8929e [cc1101] Fix packet mode RSSI/LQI (#12630)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-23 09:05:48 -05:00
J. Nick Koston
89ef523990 tweak 2025-12-23 01:01:20 -10:00
J. Nick Koston
0ec741c425 one more case 2025-12-23 00:48:25 -10:00
J. Nick Koston
c265436b07 cover 2025-12-23 00:45:25 -10:00
J. Nick Koston
04a75cf200 cover 2025-12-23 00:24:45 -10:00
J. Nick Koston
83598d6798 cover 2025-12-23 00:21:20 -10:00
J. Nick Koston
fa39b6bebd fixes 2025-12-23 00:16:53 -10:00
J. Nick Koston
1beec0ecf1 bug for bug compat 2025-12-23 00:05:12 -10:00
J. Nick Koston
3ef4e0bc47 fixes 2025-12-23 00:00:03 -10:00
J. Nick Koston
bda2db9184 Merge branch 'migrate_remain_get_object_id' into object_id_no_ram 2025-12-22 23:19:25 -10:00
J. Nick Koston
3009da14f1 tweaks 2025-12-22 23:17:15 -10:00
J. Nick Koston
d334d0d458 tweaks 2025-12-22 23:16:28 -10:00
J. Nick Koston
25b340cbbf Merge branch 'migrate_remain_get_object_id' into object_id_no_ram 2025-12-22 23:13:47 -10:00
J. Nick Koston
fa2bc21d3d tweaks 2025-12-22 23:13:28 -10:00
J. Nick Koston
83d65cff5d Merge branch 'migrate_remain_get_object_id' into object_id_no_ram 2025-12-22 23:12:09 -10:00
J. Nick Koston
9205cb3d67 tweaks 2025-12-22 23:11:42 -10:00
J. Nick Koston
f9a4a8a82e tweaks 2025-12-22 23:11:12 -10:00
J. Nick Koston
2d6b9b3888 more cover 2025-12-22 22:06:48 -10:00
J. Nick Koston
da8e23f968 more cover 2025-12-22 21:58:58 -10:00
J. Nick Koston
4bec2dc75c tweak 2025-12-22 21:51:57 -10:00
J. Nick Koston
6d5ab00385 tweak 2025-12-22 21:42:50 -10:00
J. Nick Koston
3e1db740ea cover 2025-12-22 21:40:10 -10:00
J. Nick Koston
e13f48b348 preen 2025-12-22 20:10:36 -10:00
J. Nick Koston
9f2d2eed8c preen 2025-12-22 20:08:38 -10:00
J. Nick Koston
b6b871cb73 preen 2025-12-22 20:07:02 -10:00
J. Nick Koston
452246e1c5 [core] Remove object_id RAM storage - no longer in hot path after #12627 2025-12-22 20:01:57 -10:00
J. Nick Koston
7d5342bca5 [logger] Host: Use fwrite() with explicit length and remove platform branching (#12628) 2025-12-22 16:45:22 -10:00
J. Nick Koston
7944fe6993 [core] Deprecate get_object_id() and migrate remaining usages to get_object_id_to() 2025-12-22 15:13:59 -10:00
J. Nick Koston
b4c92dd8cb [logger] Zephyr: Use k_str_out() with known length instead of printk() (#12619) 2025-12-22 14:29:47 -10:00
eoasmxd
1b31253287 Add Event Component to UART (#11765)
Co-authored-by: J. Nick Koston <nick+github@koston.org>
2025-12-22 12:19:48 -10:00
J. Nick Koston
6ae3d9c769 Merge remote-tracking branch 'upstream/dev' into integration 2025-12-22 12:09:02 -10:00
J. Nick Koston
af0d4d2c2c [web_server] Use stack buffers for value formatting to reduce flash usage (#12575) 2025-12-22 21:56:07 +00:00
J. Nick Koston
f238f93312 [core] Move comment to PROGMEM on ESP8266 (#12554) 2025-12-22 21:37:51 +00:00
J. Nick Koston
bdbe72b7f1 [web_server] Make internal JSON helper methods private (#12624) 2025-12-22 11:14:11 -10:00
J. Nick Koston
c8b531ac06 [safe_mode] Defer preference sync in clean_rtc to avoid blocking event loop (#12625) 2025-12-22 11:13:51 -10:00
J. Nick Koston
689e1d6ca0 Merge branch 'web_server_stack_format' into integration 2025-12-22 11:11:56 -10:00
J. Nick Koston
7b82b3b584 reduce churn 2025-12-22 11:11:16 -10:00
J. Nick Koston
36c0553cf7 Merge branch 'web_server_stack_format' into integration 2025-12-22 11:09:56 -10:00
J. Nick Koston
d3b3358527 inline it 2025-12-22 11:09:38 -10:00
J. Nick Koston
b950d65a7b Merge branch 'move_comment_build_info' into integration 2025-12-22 10:56:34 -10:00
J. Nick Koston
b2a6e6e078 undeprecate get_comment 2025-12-22 10:53:11 -10:00
J. Nick Koston
972cf01763 Merge remote-tracking branch 'origin/safe_mode_blocking_on_success' into integration 2025-12-22 10:49:24 -10:00
J. Nick Koston
029df4ff3d [safe_mode] Remove unnecessary blocking sync from successful boot reset 2025-12-22 10:48:10 -10:00
J. Nick Koston
21ba0e5a2b Merge remote-tracking branch 'origin/safe_mode_blocking_on_success' into integration 2025-12-22 10:46:10 -10:00
J. Nick Koston
8bb57f90de Merge branch 'web_server_json_priv' into integration 2025-12-22 10:45:59 -10:00
J. Nick Koston
145d09c8dd [safe_mode] Remove unnecessary blocking sync from successful boot reset 2025-12-22 10:41:47 -10:00
Jonathan Swoboda
918bc4b74f [esp32] Remove remaining using_esp_idf checks (#12623)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-22 15:41:14 -05:00
J. Nick Koston
5373393714 [safe_mode] Remove unnecessary blocking sync from successful boot reset 2025-12-22 10:39:30 -10:00
J. Nick Koston
21f6fefd98 [web_server] Make internal JSON helper methods private 2025-12-22 10:31:24 -10:00
J. Nick Koston
efc30ed198 Merge remote-tracking branch 'upstream/dev' into integration 2025-12-22 10:13:57 -10:00
J. Nick Koston
63005eaa06 Merge remote-tracking branch 'swoboda1337/deprecate-using-esp-idf' into integration 2025-12-22 09:20:05 -10:00
Keith Burzinski
08c0f65f30 [sprinkler] Remove internal latching valve support (#12603) 2025-12-22 14:13:18 -05:00
Keith Burzinski
cd45fe0c3a [thermostat] Optimizations to reduce binary size (#12621) 2025-12-22 14:13:03 -05:00
Jonathan Swoboda
676fbf6161 Fix 2025-12-22 14:08:27 -05:00
Jonathan Swoboda
fb009f47f1 Deprecate again 2025-12-22 14:08:04 -05:00
Jonathan Swoboda
84b5d9b21c [core] Remove deprecated config options from before 2025 (#12622)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-22 14:00:12 -05:00
J. Nick Koston
b272966d19 Merge branch 'deprecate-using-esp-idf' into integration 2025-12-22 08:48:51 -10:00
J. Nick Koston
b0c99ec1ce Merge branch 'cleanup-old-deprecations' into integration 2025-12-22 08:48:47 -10:00
J. Nick Koston
218c8e4d75 Merge remote-tracking branch 'upstream/dev' into integration 2025-12-22 08:48:37 -10:00
J. Nick Koston
2a53a89cee Merge branch 'dev' into esp8266_prefs_avoid_heap 2025-12-22 07:58:00 -10:00
J. Nick Koston
b191461929 Merge branch 'dev' into move_comment_build_info 2025-12-22 07:57:34 -10:00
J. Nick Koston
6383fe4598 [core] Add zero-allocation object_id methods (#12578) 2025-12-22 07:56:33 -10:00
J. Nick Koston
265ad9d264 [esp32_camera] Reduce loop overhead and improve frame latency with wake_loop_threadsafe (#12601) 2025-12-22 07:55:28 -10:00
J. Nick Koston
1bdbc4cb85 [esp32_ble] Avoid string allocation when setting BLE device name (#12579) 2025-12-22 07:54:55 -10:00
J. Nick Koston
1756fc31b0 [api] Use union for iterators to reduce APIConnection size by ~16 bytes (#12563) 2025-12-22 07:54:17 -10:00
Jonathan Swoboda
03db8e4f54 Fix 2025-12-22 12:22:04 -05:00
J. Nick Koston
74b075d3cf [codegen] Add static storage class to global variables for size optimization (#12616) 2025-12-22 07:03:17 -10:00
Jonathan Swoboda
ce86f01cba Change 2025-12-22 12:02:26 -05:00
Jonathan Swoboda
bee5847464 Fix 2025-12-22 11:34:49 -05:00
Jonathan Swoboda
4ffbdd9a3a Fix 2025-12-22 11:23:43 -05:00
Jonathan Swoboda
c5ac62676c Fix 2025-12-22 11:19:56 -05:00
Jonathan Swoboda
63b8fa004c [core] Fix mdns and network for using_esp_idf deprecation
- mdns: Remove ESPmDNS Arduino library for ESP32, use IDF component for both frameworks
- network: Use using_arduino for IPv6 to maintain Arduino behavior (always True)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-22 11:09:37 -05:00
Jonathan Swoboda
66b46ea81e [core] Deprecate using_esp_idf, replace with is_esp32
Arduino on ESP32 now builds ESP-IDF as a component, so add_idf_sdkconfig_option()
and add_idf_component() work with both Arduino and ESP-IDF frameworks.

The using_esp_idf property is deprecated and now emits a warning. All internal
usages have been replaced with is_esp32.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-22 11:00:27 -05:00
Jonathan Swoboda
fc019bf3e3 [core] Remove deprecated config options from before 2025
Remove old deprecated configuration options that have been showing
error messages for years:

- bedjet/climate: ble_client_id, time_id, receive_timeout (2022)
- bh1750: resolution, measurement_duration (2022)
- ethernet: enable_mdns (2021)
- wifi: enable_mdns (2021)
- i2c: multiplexer (2021)
- uart: invert (2021)
- tca9548a: scan (2021)
- tuya/light: rgb_datapoint, hsv_datapoint (2023)
- remote_base: receiver_id in triggers/dumpers, coolix data (2020-2023)
- sensor: last_reset_type (2021)
- template/switch: restore_state (2023)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-22 10:46:53 -05:00
J. Nick Koston
da872dcbf3 Merge branch 'web_server_stack_format' into integration 2025-12-21 22:26:12 -10:00
J. Nick Koston
a015cbedfe Merge branch 'dev' into api_avoid_copies 2025-12-21 22:03:47 -10:00
J. Nick Koston
c7006f8c33 Merge remote-tracking branch 'upstream/dev' into web_server_stack_format 2025-12-21 22:01:29 -10:00
Clint Armstrong
52eb08f48f [thermostat] Enhance timer behavior for immediate response to duration changes (#12610) 2025-12-21 23:52:17 -06:00
J. Nick Koston
fe84aba2ee Merge branch 'storage_class_optimize' into integration 2025-12-21 19:30:10 -10:00
J. Nick Koston
0d993691d4 [logger] RP2040: Use write() with known length instead of println() (#12615) 2025-12-21 17:59:30 -10:00
J. Nick Koston
f17a0000aa lvgl has a special case 2025-12-21 17:41:48 -10:00
J. Nick Koston
8db6ff4039 Merge branch 'storage_class_optimize' into integration 2025-12-21 17:33:16 -10:00
J. Nick Koston
ff808618da better to be a kw 2025-12-21 17:27:49 -10:00
J. Nick Koston
57baf7ac7b [codegen] Add static storage class to global variables for size optimization 2025-12-21 17:20:01 -10:00
J. Nick Koston
da8c4cd654 Merge remote-tracking branch 'upstream/dev' into integration 2025-12-21 12:13:04 -10:00
Douwe
39926909af [water_heater] (1/4) Implement API/Core/component for new water_heater component (#12498)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick+github@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-12-21 11:36:34 -10:00
J. Nick Koston
637e032528 [esp32_camera] Throttle frame logging to reduce overhead and improve throughput (#12586) 2025-12-21 09:04:43 -10:00
Anna Oake
d89eaf5bf6 [cc1101] Fix option defaults and move them to YAML (#12608) 2025-12-21 13:04:17 -05:00
J. Nick Koston
9aff4a15a3 Merge branch 'esp32_camera_latancy_reduce' into integration 2025-12-21 07:53:18 -10:00
J. Nick Koston
dbf494fd98 Merge branch 'fix_slow_esp32_camera_at_high_fps' into esp32_camera_latancy_reduce 2025-12-21 07:53:07 -10:00
J. Nick Koston
219cf26d98 tweak logging 2025-12-21 07:36:25 -10:00
J. Nick Koston
bf617c3279 [web_server] Replace str_sprintf with stack buffers (#12592) 2025-12-21 07:32:05 -10:00
J. Nick Koston
c70eab931e [api] Add zero-copy support for Home Assistant state response messages (#12585) 2025-12-21 07:31:54 -10:00
J. Nick Koston
a799ac6488 [syslog] Eliminate heap allocations in log path (#12589) 2025-12-21 07:10:27 -10:00
polyfloyd
5a36cea5ec Add nix files to gitignore (#12604) 2025-12-21 09:26:03 -05:00
J. Nick Koston
60756db06d [syslog] Use C++17 nested namespace syntax (#12594) 2025-12-21 02:47:37 -06:00
Keith Burzinski
2113858f89 [sprinkler] Squash a few bugs + minor optimization (#12436) 2025-12-21 02:45:24 -06:00
J. Nick Koston
14ea235939 Merge branch 'esp32_camera_latancy_reduce' into integration 2025-12-20 21:59:01 -10:00
J. Nick Koston
26f1be40dc pro 2025-12-20 21:58:24 -10:00
J. Nick Koston
0467fdbb61 Merge branch 'esp32_camera_latancy_reduce' into integration 2025-12-20 21:31:46 -10:00
J. Nick Koston
c1463a569c reorder 2025-12-20 21:31:30 -10:00
J. Nick Koston
6dd41a14c4 try send right away 2025-12-20 21:17:19 -10:00
J. Nick Koston
9855d86616 try send right away 2025-12-20 21:10:22 -10:00
J. Nick Koston
ffe459e666 [esp32_camera] Reduce loop overhead and improve frame latency with wake_loop_threadsafe 2025-12-20 15:30:24 -10:00
J. Nick Koston
1f15023d30 Merge remote-tracking branch 'upstream/dev' into integration 2025-12-20 14:49:34 -10:00
dependabot[bot]
e89fe9b945 Bump aioesphomeapi from 43.4.0 to 43.5.0 (#12599)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-20 23:59:48 +00:00
dependabot[bot]
f1362cd9fe Bump aioesphomeapi from 43.3.0 to 43.4.0 (#12597)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-20 22:37:10 +00:00
Frédéric Metrich
bf554a58ef [const] Add CONF_ON_DATA and consolidate definitions (#12595)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 12:17:09 -10:00
J. Nick Koston
9d01357e8a Merge branch 'ha_state_only_copy_state' into integration 2025-12-20 11:46:04 -10:00
J. Nick Koston
d6cf80f95a Merge remote-tracking branch 'origin/syslog_no_heap' into integration 2025-12-20 11:26:06 -10:00
J. Nick Koston
8d14c1ceb1 Merge remote-tracking branch 'origin/no_alloc_object_id' into integration 2025-12-20 11:25:54 -10:00
J. Nick Koston
9ca2b0adb7 Merge remote-tracking branch 'origin/syslog_ns' into integration 2025-12-20 11:25:40 -10:00
J. Nick Koston
945d5890b5 Revert "[improv_serial] Use stack buffer for RSSI formatting"
This reverts commit c0ab783ba2.
2025-12-20 11:25:22 -10:00
J. Nick Koston
2b53976b0f [syslog] Use C++17 nested namespace syntax 2025-12-20 11:23:21 -10:00
J. Nick Koston
589942f52c simplify logic 2025-12-20 11:11:54 -10:00
J. Nick Koston
a9c294bc03 copilot edge cases 2025-12-20 11:09:52 -10:00
J. Nick Koston
a0d1a10d17 Update tests/integration/test_syslog.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-20 11:00:31 -10:00
J. Nick Koston
496c09b333 bounds fixes 2025-12-20 11:00:03 -10:00
J. Nick Koston
1dfb808590 Merge branch 'improv_serial_stack_format' into integration 2025-12-20 10:58:24 -10:00
J. Nick Koston
c0ab783ba2 [improv_serial] Use stack buffer for RSSI formatting 2025-12-20 10:55:16 -10:00
J. Nick Koston
6b7115f40e Merge branch 'web_server_no_heap_churn_prints' into integration 2025-12-20 10:49:46 -10:00
J. Nick Koston
42610d5a6f 8266 2025-12-20 10:48:52 -10:00
J. Nick Koston
ad17c8524c Merge branch 'web_server_no_heap_churn_prints' into integration 2025-12-20 10:41:15 -10:00
J. Nick Koston
1a60ce8cc6 Merge branch 'dev' into no_alloc_object_id 2025-12-20 10:40:52 -10:00
J. Nick Koston
644e806afd [zwave_proxy] Add missing USE_API guards for clang-tidy (#12590) 2025-12-20 10:40:43 -10:00
J. Nick Koston
de3e72af04 [web_server] Replace str_sprintf with stack buffers 2025-12-20 10:39:19 -10:00
J. Nick Koston
43046b2c55 Merge remote-tracking branch 'origin/syslog_no_heap' into integration 2025-12-20 10:31:48 -10:00
J. Nick Koston
808f1ac078 Merge branch 'no_alloc_object_id' into integration 2025-12-20 10:31:40 -10:00
J. Nick Koston
c22eff24d8 [syslog] Eliminate heap allocations in log path 2025-12-20 10:24:46 -10:00
J. Nick Koston
f470cf5c87 add missing USE_API guard 2025-12-20 10:05:50 -10:00
Leo Bergolth
6c2d255230 send NIL ("-") as timestamp if time source is not valid (#12588) 2025-12-20 10:04:59 -10:00
J. Nick Koston
832d232814 Merge branch 'fix_slow_esp32_camera_at_high_fps' into integration 2025-12-20 09:13:13 -10:00
J. Nick Koston
6efb167b65 edge case 2025-12-20 09:12:55 -10:00
J. Nick Koston
4d99632a61 [esp32_camera] Throttle frame logging to reduce overhead and improve throughput 2025-12-20 09:02:39 -10:00
J. Nick Koston
6cb66559bc fix test 2025-12-20 08:42:52 -10:00
Stuart Parmenter
6f3bfc2060 [hub75] Bump esp-hub75 version to 0.1.7 (#12564) 2025-12-20 13:18:20 -05:00
J. Nick Koston
e812d8683a tests 2025-12-20 07:23:55 -10:00
J. Nick Koston
cc9f42cc9a [api] Add zero-copy support for Home Assistant state response messages 2025-12-20 07:22:36 -10:00
J. Nick Koston
89012f80a9 Merge branch 'dev' into api_avoid_copies 2025-12-20 06:48:24 -10:00
J. Nick Koston
9a54cc12ba Merge branch 'dev' into no_alloc_object_id 2025-12-20 06:47:49 -10:00
J. Nick Koston
40eb898814 [api] Add zero-copy support for noise encryption key requests (#12405) 2025-12-20 06:47:30 -10:00
J. Nick Koston
64269334ce [text_sensor] Avoid string copies in callbacks by passing const ref (#12503)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2025-12-20 06:46:13 -10:00
Eduard Llull
121375ff39 [display_menu_base] Call on_value_ after updating the select (#12584) 2025-12-20 10:59:14 -05:00
J. Nick Koston
48cdf9e036 [tests] Fix race condition in alarm control panel state transitions test (#12581) 2025-12-20 10:47:29 -05:00
J. Nick Koston
bed779b1c9 Merge branch 'alarm_control_flakey' into integration 2025-12-19 21:18:08 -10:00
J. Nick Koston
a31bef5390 [tests] Fix race condition in alarm control panel state transitions test 2025-12-19 21:01:31 -10:00
J. Nick Koston
2d792ddf40 Merge branch 'noise_api_zero_copy' into integration 2025-12-19 20:12:58 -10:00
J. Nick Koston
7365885464 Merge branch 'dev' into noise_api_zero_copy 2025-12-19 20:12:47 -10:00
J. Nick Koston
df5193ff73 fix merge 2025-12-19 20:11:21 -10:00
J. Nick Koston
2d6103f0d0 Merge branch 'text_sensor_avoid_copies_const_ref' into integration 2025-12-19 20:07:35 -10:00
J. Nick Koston
4036671583 Update esphome/components/sensor/sensor.cpp 2025-12-19 20:06:22 -10:00
J. Nick Koston
4a1db67566 Update esphome/components/sensor/sensor.cpp 2025-12-19 20:06:10 -10:00
J. Nick Koston
0814419d61 Update esphome/components/text_sensor/text_sensor.h 2025-12-19 20:05:30 -10:00
J. Nick Koston
c799ce05f7 Update esphome/components/text_sensor/text_sensor.h
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-19 20:05:11 -10:00
J. Nick Koston
8088f09902 Update esphome/components/text_sensor/text_sensor.h 2025-12-19 20:05:05 -10:00
J. Nick Koston
0cff5326bc Update esphome/components/text_sensor/text_sensor.cpp 2025-12-19 20:04:36 -10:00
J. Nick Koston
60d66365ad Update esphome/components/sensor/sensor.cpp 2025-12-19 20:04:17 -10:00
J. Nick Koston
f727edab58 Update esphome/components/text_sensor/text_sensor.cpp 2025-12-19 20:03:43 -10:00
J. Nick Koston
a0647cbe71 Update esphome/components/text_sensor/text_sensor.cpp 2025-12-19 20:03:14 -10:00
J. Nick Koston
0543d65969 Update esphome/components/text_sensor/text_sensor.cpp
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-19 20:02:54 -10:00
J. Nick Koston
4bfe09768c Update esphome/components/sensor/sensor.h
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-19 20:02:31 -10:00
J. Nick Koston
4d0a54d9f0 Update esphome/components/sensor/sensor.cpp
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-19 20:02:24 -10:00
J. Nick Koston
4739e9cabe Merge branch 'dev' into text_sensor_avoid_copies_const_ref 2025-12-19 19:13:33 -10:00
J. Nick Koston
4c4c6fb257 Merge branch 'parition_callbacks' into text_sensor_avoid_copies_const_ref 2025-12-19 19:12:10 -10:00
J. Nick Koston
3e313014e1 [core] Migrate entities to use lazy callbacks (#12580) 2025-12-19 19:04:21 -10:00
J. Nick Koston
68b7fbdecf Merge branch 'lazy_allocate_entity_callbacks' - add LazyCallbackManager for other entities 2025-12-19 17:19:39 -10:00
J. Nick Koston
e7ea17fcba [core] Migrate entities to use lazy callbacks 2025-12-19 17:13:27 -10:00
Martin Ebner
be6c1e4ec0 [sen5x][sgp4x] Move configuration keys from SEN5x and SGP4x to const.py (#12567)
Co-authored-by: Martin Ebner <martinebner@me.com>
2025-12-19 21:29:02 -05:00
Keith Burzinski
730bf206de [wifi] Fix for wifi_info when static IP is configured (#12576) 2025-12-19 21:25:16 -05:00
J. Nick Koston
4eea8082cd Merge branch 'name_with_suffix_ble' into integration 2025-12-19 16:01:24 -10:00
J. Nick Koston
78899831cf dry 2025-12-19 15:55:20 -10:00
J. Nick Koston
6cac302c01 Merge branch 'name_with_suffix_ble' into integration 2025-12-19 15:52:45 -10:00
J. Nick Koston
a76461cf5f [esp32_ble] Avoid string allocation when setting BLE device name 2025-12-19 15:50:25 -10:00
J. Nick Koston
6a9a6554e1 Merge branch 'no_alloc_object_id' into integration 2025-12-19 15:25:38 -10:00
J. Nick Koston
6904f0f3c4 fix 2025-12-19 15:25:25 -10:00
J. Nick Koston
7eca8905ea refactor 2025-12-19 15:13:16 -10:00
J. Nick Koston
01224f25f7 tweak 2025-12-19 15:08:02 -10:00
J. Nick Koston
cd6240541b [core] Add zero-allocation get_object_id_to() method 2025-12-19 15:03:27 -10:00
J. Nick Koston
94fcd18306 Merge remote-tracking branch 'upstream/dev' into integration
# Conflicts:
#	esphome/components/fan/fan_traits.h
#	esphome/components/http_request/ota/ota_http_request.cpp
#	tests/integration/test_alarm_control_panel_state_transitions.py
2025-12-19 14:22:19 -10:00
J. Nick Koston
da472f3f79 Merge branch 'dev' into noise_api_zero_copy 2025-12-19 12:46:07 -10:00
J. Nick Koston
c9fccdff25 [fan] Add zero-copy support for API preset mode commands (#12404)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-19 22:05:52 +00:00
J. Nick Koston
ada6c42f3f [alarm_control_panel] Remove redundant per-state callbacks (#12171)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-19 11:48:14 -10:00
J. Nick Koston
988b888c63 [ota] Replace std::function callbacks with listener interface (#12167) 2025-12-19 11:19:07 -10:00
J. Nick Koston
940afdbb12 [climate] Add zero-copy support for API custom fan mode and preset commands (#12402) 2025-12-19 11:18:50 -10:00
J. Nick Koston
81e91c2a8f [esp32_ble] Add stack-based UUID formatting to avoid heap allocations (#12510) 2025-12-19 11:18:32 -10:00
J. Nick Koston
ebc3d28ade [wifi] Replace optional with sentinel values to reduce RAM and clarify API (#12446) 2025-12-19 11:18:15 -10:00
J. Nick Koston
3fff2f2f0a Merge branch 'web_server_stack_format' into integration 2025-12-19 10:50:16 -10:00
J. Nick Koston
04eb64f361 safer 2025-12-19 10:49:19 -10:00
J. Nick Koston
4464e464b6 safer 2025-12-19 10:48:52 -10:00
Rene Guca
25cebedcfc [dht] Fix "Falling edge for bit 39 failed!" for Sonoff THS01 (#9225)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2025-12-19 15:42:39 -05:00
J. Nick Koston
20a12ca02a Merge branch 'web_server_stack_format' into integration 2025-12-19 10:20:38 -10:00
J. Nick Koston
b2a43a3a69 [web_server] Use stack buffers for value formatting to reduce flash usage 2025-12-19 10:18:58 -10:00
dependabot[bot]
98ed679b19 Bump ruff from 0.14.9 to 0.14.10 (#12572)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2025-12-19 19:22:56 +00:00
J. Nick Koston
097617cb4e Merge remote-tracking branch 'upstream/dev' into integration 2025-12-19 09:22:29 -10:00
dependabot[bot]
59b38d79b4 Bump docker/setup-buildx-action from 3.11.1 to 3.12.0 in the docker-actions group (#12574)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-19 09:18:52 -10:00
dependabot[bot]
26c16f4ca2 Bump voluptuous from 0.15.2 to 0.16.0 (#12573)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-19 09:18:33 -10:00
Jas Strong
940e619481 [aqi, hm3301, pmsx003] Air Quality Index improvements (#12203)
Co-authored-by: jas <jas@asspa.in>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2025-12-19 13:42:11 -05:00
J. Nick Koston
043204baa6 Merge branch 'get_peername_stack_save_ram' into integration 2025-12-19 06:34:49 -10:00
J. Nick Koston
92157c89bc cleanup 2025-12-19 06:29:57 -10:00
J. Nick Koston
25f83384a4 cleanup 2025-12-19 06:29:36 -10:00
Jonathan Swoboda
eaca81c3ab Merge branch 'release' into dev 2025-12-19 10:53:18 -05:00
Jonathan Swoboda
93e38f2608 Merge pull request #12569 from esphome/bump-2025.12.1
2025.12.1
2025-12-19 10:53:05 -05:00
Jonathan Swoboda
3a888326d8 Bump version to 2025.12.1 2025-12-19 10:13:35 -05:00
Keith Burzinski
f0d0ea60a7 [esp32_ble, esp32_ble_tracker] Fix crash, error messages when ble.disable called during boot (#12560) 2025-12-19 10:13:35 -05:00
Jonathan Swoboda
7ca11764ab [template.alarm_control_panel] Fix compile without binary_sensor (#12548)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-19 10:13:35 -05:00
Jonathan Swoboda
3e38a5e630 [esp32_camera] Fix I2C driver conflict with other components (#12533)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-12-19 10:13:35 -05:00
Jonathan Swoboda
636be92c97 [bme68x_bsec2_i2c] Add MULTI_CONF support for multiple sensors (#12535)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-19 10:13:35 -05:00
Jack Wilsdon
195b1c6323 [pm1006] Fix "never" update interval detection (#12529) 2025-12-19 10:13:35 -05:00
Anna Oake
7e08092012 [cc1101] Fix default frequencies (#12539) 2025-12-19 10:13:35 -05:00
J. Nick Koston
86119c3439 Merge branch 'get_peername_stack_save_ram' into integration 2025-12-18 22:18:00 -10:00
J. Nick Koston
cf404c34d0 [api] Use stack buffers for peername logging to reduce per-connection memory 2025-12-18 22:13:27 -10:00
pixelgrb
f962497db1 [mmc5603] enable AUTO_SR_en to compensate for temperature drift (#12556)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2025-12-18 23:13:36 -05:00
J. Nick Koston
ce1c6721b1 Merge branch 'union_iter' into integration 2025-12-18 16:55:06 -10:00
J. Nick Koston
a7f82f5201 state machine 2025-12-18 16:50:41 -10:00
J. Nick Koston
38afc5149a [api] Use union for iterators to reduce APIConnection size by ~16 bytes 2025-12-18 16:18:45 -10:00
Keith Burzinski
7ae3a11d6b [esp32_ble, esp32_ble_tracker] Fix crash, error messages when ble.disable called during boot (#12560) 2025-12-18 19:42:47 -06:00
J. Nick Koston
7a5a768c04 Merge remote-tracking branch 'kbx81/20251218-ble-disable-fixes' into integration 2025-12-18 15:21:57 -10:00
kbx81
37e2a114db [esp32_ble, esp32_ble_tracker] Fix crash, error messages when ble.disable called during boot 2025-12-18 18:58:26 -06:00
J. Nick Koston
b5950d41b5 Merge remote-tracking branch 'upstream/move_comment_build_info' into integration 2025-12-18 11:19:51 -10:00
dependabot[bot]
1c50c2b672 Bump ruamel-yaml from 0.18.16 to 0.18.17 (#12555)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-18 11:19:19 -10:00
J. Nick Koston
3a69cb9c13 tidy 2025-12-18 07:53:48 -10:00
J. Nick Koston
5547f9f5d6 span 2025-12-18 06:58:32 -10:00
J. Nick Koston
12d8e2ada2 tweaks 2025-12-18 06:56:12 -10:00
J. Nick Koston
455091a03f tweaks 2025-12-18 06:55:02 -10:00
J. Nick Koston
23ee8bdcaf [core] Move comment to PROGMEM on ESP8266 2025-12-18 06:48:23 -10:00
Jonathan Swoboda
41fd1762e9 [core] Deprecate custom_components folder (#12552)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-18 11:46:16 -05:00
J. Nick Koston
cd93468225 [core] Move comment to PROGMEM on ESP8266 2025-12-18 06:41:23 -10:00
J. Nick Koston
2cf6ed2af7 [socket] Refactor socket implementations for memory efficiency and code quality (#12550) 2025-12-18 09:07:35 -07:00
J. Nick Koston
b47b7d43fd [api] Remove unused force parameter from encode_message (#12551) 2025-12-18 09:06:16 -07:00
Jonathan Swoboda
663a4304e0 [libretiny] Fix millis() ambiguity on BK72XX (#12534)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-18 07:50:31 -05:00
J. Nick Koston
bef017fd3e Merge branch 'encode_message_dead_code' into integration 2025-12-17 20:05:59 -10:00
J. Nick Koston
6707ac6a0f [api] Remove unused force parameter from encode_message 2025-12-17 20:03:40 -10:00
J. Nick Koston
ec55dcbe41 Merge branch 'socket_reorg_cleanup' into integration 2025-12-17 19:28:20 -10:00
J. Nick Koston
655f493eaa [socket] Refactor socket implementations for memory efficiency and code quality 2025-12-17 19:20:35 -10:00
J. Nick Koston
50f0f7595b Merge remote-tracking branch 'upstream/dev' into integration 2025-12-17 18:50:37 -10:00
Jonathan Swoboda
ca47bad90a [template.alarm_control_panel] Fix compile without binary_sensor (#12548)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-17 23:34:04 -05:00
J. Nick Koston
4f821a6d76 [wifi] Reduce scan logging to prevent blocking loop during connection (#12544) 2025-12-17 18:21:46 -10:00
J. Nick Koston
426305836d [esp32][libretiny] Avoid duplicate snprintf when syncing preferences (#12542) 2025-12-17 18:16:14 -10:00
J. Nick Koston
c6b33586c1 Merge remote-tracking branch 'upstream/dev' into integration 2025-12-17 15:54:10 -10:00
dependabot[bot]
1b5af7d21d Bump github/codeql-action from 4.31.8 to 4.31.9 (#12524)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-17 15:22:19 -10:00
J. Nick Koston
a97f637cb9 Merge branch 'wifi_connect_blocked_loop_logging' into integration 2025-12-17 14:14:11 -10:00
J. Nick Koston
0185541000 [wifi] Reduce scan logging to prevent blocking loop during connection 2025-12-17 14:13:37 -10:00
David Woodhouse
9de7df7b5b Add build info to image (#12425)
Co-authored-by: J. Nick Koston <nick+github@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-18 00:06:52 +00:00
J. Nick Koston
ce18b4c3ca Merge branch 'prefs_snprintf_once' into integration 2025-12-17 14:01:12 -10:00
J. Nick Koston
60b266e73d [esp32][libretiny] Avoid duplicate snprintf when syncing preferences 2025-12-17 14:00:19 -10:00
J. Nick Koston
4c8a2fe3d4 Merge branch 'fan_zero_copy' into noise_api_zero_copy 2025-12-17 16:41:26 -07:00
J. Nick Koston
190ebecd7b Merge branch 'climate_zero_copy' into fan_zero_copy 2025-12-17 16:41:18 -07:00
J. Nick Koston
71b6fc4baa Merge branch 'dev' into climate_zero_copy 2025-12-17 16:41:06 -07:00
J. Nick Koston
bec60c4da8 Merge branch 'dev' into api_avoid_copies 2025-12-17 16:40:39 -07:00
J. Nick Koston
df2936f686 Merge branch 'dev' into parition_callbacks 2025-12-17 16:40:30 -07:00
J. Nick Koston
1fb89e5223 Merge branch 'buildinfo' into integration 2025-12-17 13:27:58 -10:00
J. Nick Koston
8c185254ef give 6 months of get_compilation_time for back compat 2025-12-17 13:04:46 -10:00
David Woodhouse
14ecb906a1 Merge branch 'dev' into buildinfo 2025-12-17 22:59:57 +00:00
Jonathan Swoboda
2b337aa306 [esp32_camera] Fix I2C driver conflict with other components (#12533)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-12-17 17:37:59 -05:00
Jonathan Swoboda
4ddaff4027 [esp32] Dynamically embed managed component server certificates (#12509)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-12-17 17:26:56 -05:00
J. Nick Koston
91c504061b [select] Eliminate string allocation in state callbacks (#12505)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2025-12-17 12:19:26 -10:00
Jonathan Swoboda
dc8f7abce2 [bme68x_bsec2_i2c] Add MULTI_CONF support for multiple sensors (#12535)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-17 17:07:42 -05:00
Jonathan Swoboda
3d673ac55e [ci] Check changed headers in clang-tidy when using --changed (#12540)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-17 11:13:18 -10:00
Jack Wilsdon
b02696edc0 [pm1006] Fix "never" update interval detection (#12529) 2025-12-18 07:40:31 +11:00
David Woodhouse
0688abdbd8 Merge branch 'dev' into buildinfo 2025-12-17 20:35:06 +00:00
Anna Oake
f9720026d0 [cc1101] Fix default frequencies (#12539) 2025-12-17 14:19:18 -05:00
David Woodhouse
745f5b8dd2 Merge branch 'dev' into buildinfo 2025-12-17 19:15:48 +00:00
Jonathan Swoboda
d7b04a3d18 [nextion] Fix clang-tidy error on Zephyr for HTTPClient (#12538)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-17 13:59:49 -05:00
David Woodhouse
01d8775005 Merge branch 'dev' into buildinfo 2025-12-17 18:04:45 +00:00
Jonathan Swoboda
0e71fa97a7 [spi] Add SPIInterface stub for clang-tidy on unsupported platforms (#12532)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-17 12:18:25 -05:00
J. Nick Koston
7701371bb4 Merge branch 'fix-bk72xx-millis-ambiguity' into integration 2025-12-17 07:18:19 -10:00
J. Nick Koston
42e061c9ae [text] Avoid string copies in callbacks by passing const ref (#12504) 2025-12-17 12:00:19 -05:00
J. Nick Koston
94763ebdab [libretiny] Store preference keys as uint32_t, convert to string only at FlashDB boundary (#12500) 2025-12-17 11:59:40 -05:00
J. Nick Koston
f32bb618ac [esp32] Store preference keys as uint32_t, convert to string only at NVS boundary (#12494) 2025-12-17 11:59:35 -05:00
Edward Firmo
0707f383a6 [nextion] Use ESP-IDF for ESP32 Arduino (#9429)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2025-12-17 11:45:17 -05:00
Piotr Szulc
e91c6a79ea [deep_sleep] Deep sleep for BK72xx (#12267)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2025-12-17 11:45:05 -05:00
J. Nick Koston
63fc8b4e5a [core] Refactor str_snake_case and str_sanitize to use constexpr helpers (#12454) 2025-12-17 11:30:12 -05:00
J. Nick Koston
ab73ed76b8 [esphome] Improve OTA field alignment to save 4 bytes on 32-bit (#12461) 2025-12-17 11:29:58 -05:00
J. Nick Koston
bf6a03d1cf [factory_reset] Optimize memory by storing interval as uint16_t seconds (#12462) 2025-12-17 11:29:51 -05:00
J. Nick Koston
9928ab09cf [time] Convert to C++17 nested namespace syntax (#12463) 2025-12-17 11:29:43 -05:00
Jonathan Swoboda
eb2392b33a [libretiny] Fix millis() ambiguity on BK72XX
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-17 11:25:21 -05:00
David Woodhouse
7e36112687 Merge branch 'dev' into buildinfo 2025-12-17 09:32:40 +00:00
Thomas Rupprecht
56c1691d72 [pca9685,sx126x,sx127x] Use frequency/float_range check (#12490)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2025-12-16 22:52:28 -05:00
Roger Fachini
a065990ab9 [update] Add check action to trigger update checks (#12415) 2025-12-16 22:20:12 -05:00
Stuart Parmenter
084f517a20 [hub75] Add set_brightness action (#12521) 2025-12-16 22:12:33 -05:00
David Woodhouse
77d914e67f Merge branch 'dev' into buildinfo 2025-12-17 01:52:36 +00:00
Jonathan Swoboda
1122ec354f [esp32] Add OTA rollback support (#12460)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-16 20:07:57 -05:00
Jonathan Swoboda
431183eebc [ledc,mqtt,resampler] Remove unnecessary ESP-IDF framework restrictions (#12442)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-16 20:07:09 -05:00
Jonathan Swoboda
08beaf8750 [esp32] Remove Arduino-specific code from core.cpp (#12501)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-16 20:06:12 -05:00
David Woodhouse
f2f30337a0 Merge branch 'dev' into buildinfo 2025-12-17 00:44:15 +00:00
Jonathan Swoboda
18814f12dc [http_request] Use ESP-IDF for ESP32 Arduino (#12428)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-16 19:44:14 -05:00
Jonathan Swoboda
9cd888cef6 [spi] Use ESP-IDF driver for ESP32 Arduino (#12420)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-16 19:44:01 -05:00
Thomas Rupprecht
9727c7135c [openthread] channel range, fix typo, use C++17 nested namespace syntax (#12422) 2025-12-16 19:43:18 -05:00
Thomas Rupprecht
93621d85b0 [climate] Improve temperature unit regex (#12032) 2025-12-16 19:43:10 -05:00
Thomas Rupprecht
046ea922e8 [esp32] improve types and variable naming (#12423) 2025-12-16 19:42:52 -05:00
David Woodhouse
71f2331bc8 Fix clang-format: use lowercase buf_size variable name 2025-12-17 00:42:46 +00:00
Jeff Zigler
fab4efb469 [esp32] Fix serial logging on h2, c2 & c61 (#12522)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2025-12-16 19:42:12 -05:00
Jonathan Swoboda
efc5672567 Merge branch 'release' into dev 2025-12-16 18:57:37 -05:00
Jonathan Swoboda
0ea5f2fd81 Merge pull request #12525 from esphome/bump-2025.12.0
2025.12.0
2025-12-16 18:57:20 -05:00
David Woodhouse
8358ef0096 Use ESPHOME_strncpy_P in get_build_time_string()
Replace platform-specific ifdef with cross-platform ESPHOME_strncpy_P
macro for consistency.
2025-12-16 23:06:31 +00:00
David Woodhouse
f8c9cf8fd9 Use PROGMEM for version text sensor strings on ESP8266
Build version string incrementally from PROGMEM literals using
ESPHOME_strncpy_P and ESPHOME_strncat_P. Write hash and build time
directly into buffer without temporary variables. Calculate buffer
size based on actual components needed.

Add ESPHOME_strncat_P macro to progmem.h for cross-platform PROGMEM
string concatenation.
2025-12-16 23:05:07 +00:00
Jonathan Swoboda
fa3d998c3d Bump version to 2025.12.0 2025-12-16 17:15:50 -05:00
David Woodhouse
8429684fce Fix clang-format: use uppercase PREFIX constant name 2025-12-16 19:46:04 +00:00
David Woodhouse
a30052e7c0 Use PROGMEM for version text sensor strings on ESP8266
Build version string incrementally from PROGMEM literal prefix, avoiding
format strings in RAM. Copy from PROGMEM on ESP8266, use directly on
other platforms.
2025-12-16 19:22:42 +00:00
David Woodhouse
175250deb0 Use PROGMEM for MQTT version format string on ESP8266
Store format string in PROGMEM and copy to RAM buffer on ESP8266 before
use. On other platforms, use the format string directly. This saves RAM
on ESP8266 while maintaining the same functionality.
2025-12-16 19:20:50 +00:00
David Woodhouse
12734ba258 Revert "Use PROGMEM format strings to reduce RAM usage on ESP8266"
This reverts commit da67c47a76.
2025-12-16 19:03:13 +00:00
David Woodhouse
da67c47a76 Use PROGMEM format strings to reduce RAM usage on ESP8266
Replace str_sprintf() with snprintf_P() and PSTR() to keep format
strings in flash instead of RAM. Also removes 'config hash 0x' prefix
to save additional bytes.
2025-12-16 18:13:35 +00:00
David Woodhouse
38167c268f Add get_config_version_hash() and make hash functions constexpr
Add Application::get_config_version_hash() as a constexpr that returns
fnv1a_hash_extend(config_hash, ESPHOME_VERSION).

Make get_config_hash(), get_build_time(), fnv1a_hash(), and
fnv1a_hash_extend() constexpr inline functions.

Replace open-coded fnv1a_hash_extend(config_hash, ESPHOME_VERSION)
calls with get_config_version_hash() in sensor and wifi components.

Remove now-unnecessary version.h includes from component files.
2025-12-16 17:15:19 +00:00
David Woodhouse
7298db0a7e Add tests for source file removal detection in copy_src_tree
Add tests covering the logic that detects when source files are removed:
- test_copy_src_tree_detects_removed_source_file: Verifies that removing
  a regular source file triggers sources_changed flag
- test_copy_src_tree_ignores_removed_generated_file: Verifies that removing
  a generated file (like build_info_data.h) does not trigger sources_changed
2025-12-16 16:45:28 +00:00
J. Nick Koston
6eb8095480 Merge branch 'dev' into buildinfo 2025-12-16 10:29:51 -06:00
Jonathan Swoboda
5e630e9255 Merge branch 'beta' into dev 2025-12-16 11:26:08 -05:00
Jonathan Swoboda
864aaeec01 Merge pull request #12520 from esphome/bump-2025.12.0b5
2025.12.0b5
2025-12-16 11:25:57 -05:00
David Woodhouse
3679a81220 Merge branch 'dev' into buildinfo 2025-12-16 15:55:36 +00:00
Jonathan Swoboda
9c88e44300 Bump version to 2025.12.0b5 2025-12-16 10:35:31 -05:00
Jonathan Swoboda
4d6a93f92d [uart] Fix UART on default UART0 pins for ESP-IDF (#12519)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-16 10:35:31 -05:00
J. Nick Koston
7216120bfd [socket] Fix getpeername() returning local address instead of remote in LWIP raw TCP (#12475) 2025-12-16 10:35:31 -05:00
Jonathan Swoboda
1897551b28 [uart] Fix UART on default UART0 pins for ESP-IDF (#12519)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-16 10:17:17 -05:00
David Woodhouse
dfae9e5750 Merge branch 'dev' into buildinfo 2025-12-16 10:21:02 +00:00
J. Nick Koston
ead60bc5c4 [socket] Fix getpeername() returning local address instead of remote in LWIP raw TCP (#12475) 2025-12-16 00:48:30 -06:00
David Woodhouse
87f88b8a9a Add version.h includes to sensor components
Add missing version.h includes to sen5x, sgp30, and sgp4x components
for ESPHOME_VERSION definition.
2025-12-16 00:32:30 +00:00
David Woodhouse
ba79a8e6c8 Merge branch 'dev' into buildinfo 2025-12-16 00:19:29 +00:00
David Woodhouse
e8a3a8380d Remove stray debug 2025-12-16 00:18:56 +00:00
David Woodhouse
305a58cb84 Use config_hash in MQTT and version sensor
Change MQTT sw_version and version text sensor to display config_hash
instead of build_time_str. Format: "(config hash 0xXXXXXXXX)"

Version sensor with hide_timestamp=false also includes build time:
"(config hash 0xXXXXXXXX, built: YYYY-MM-DD HH:MM:SS +ZZZZ)"
2025-12-16 00:09:28 +00:00
David Woodhouse
f231fc856b Use fnv1a_hash_extend with config_hash and version for wifi preferences
Change wifi component to use fnv1a_hash_extend(config_hash, ESPHOME_VERSION)
instead of fnv1_hash(compilation_time) for the preferences hash.

This ensures wifi settings are invalidated on config or version changes,
not just on recompilation.
2025-12-16 00:05:43 +00:00
Jonathan Swoboda
7fe8e53f82 Merge branch 'beta' into dev 2025-12-15 19:01:12 -05:00
Jonathan Swoboda
8cf0ee38a3 Merge pull request #12513 from esphome/bump-2025.12.0b4
2025.12.0b4
2025-12-15 19:01:02 -05:00
David Woodhouse
69fa5020d2 Re-remove compilation_time_ from the app 2025-12-15 23:23:46 +00:00
David Woodhouse
f5592595bc Use fnv1a_hash_extend with config_hash and version for sensor baselines
Change sen5x, sgp30, and sgp4x components to use fnv1a_hash_extend()
starting with config_hash and ESPHOME_VERSION, then extending with the
sensor serial number. This replaces the previous use of fnv1_hash with
compilation_time.

This ensures baseline storage is invalidated on config or version
changes, not just on recompilation.
2025-12-15 23:22:23 +00:00
David Woodhouse
4a58ab6310 Restore switch to build_time_str in mqtt sw_version and version sensor 2025-12-15 23:14:25 +00:00
David Woodhouse
a5ff374540 Merge branch 'dev' of github.com:esphome/esphome into buildinfo 2025-12-15 23:12:40 +00:00
David Woodhouse
ffbbf37fc2 Revert "Revert API compilation_time to old locale-dependent format"
This reverts commit d2b5398fad.
2025-12-15 23:12:21 +00:00
Jonathan Swoboda
4c926cca60 Bump version to 2025.12.0b4 2025-12-15 18:09:42 -05:00
Pascal Vizeli
57634b612a [http_request] Fix infinite loop when server doesn't send Content-Length header (#12480)
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-15 18:09:42 -05:00
Jonathan Swoboda
8dff7ee746 [esp32] Support all IDF component version operators in shorthand syntax (#12499)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-15 18:09:42 -05:00
Jonathan Swoboda
803bb742c9 [remote_base] Fix crash when ABBWelcome action has no data field (#12493)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-15 18:09:42 -05:00
J. Nick Koston
682acf81b2 Merge remote-tracking branch 'upstream/dev' into integration 2025-12-15 15:35:46 -06:00
David Woodhouse
d2b5398fad Revert API compilation_time to old locale-dependent format
Keep the API DeviceInfo compilation_time field using the old
get_compilation_time_ref() format for backward compatibility.

The text sensor build_time_str continues to use the new ISO 8601 format.
2025-12-15 21:01:15 +00:00
David Woodhouse
839139df36 Add FNV-1a hash functions (#12502) 2025-12-15 20:23:54 +00:00
dependabot[bot]
24d7e9dd23 Bump tornado from 6.5.3 to 6.5.4 (#12508)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-15 20:08:16 +00:00
dependabot[bot]
1214bb6bad Bump aioesphomeapi from 43.2.1 to 43.3.0 (#12507)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-15 20:07:20 +00:00
J. Nick Koston
3ebbc1e769 overloads 2025-12-15 13:28:59 -06:00
J. Nick Koston
9578a02fe3 overloads 2025-12-15 13:27:51 -06:00
J. Nick Koston
68edb5c9a0 Merge branch 'noise_api_zero_copy' into integration 2025-12-15 13:19:52 -06:00
David Woodhouse
d911ae94fe Fix BUILD_TIME_STR_SIZE for ISO 8601 format
Increase buffer from 24 to 26 bytes to accommodate the ISO 8601 format
with timezone: "YYYY-MM-DD HH:MM:SS +ZZZZ" (25 chars + null terminator).

The old format "Dec 15 2025, 18:14:59" was 20 chars, but the new format
needs 25 chars. The 24-byte buffer was truncating the timezone to "+00"
instead of "+0000".
2025-12-15 18:53:56 +00:00
J. Nick Koston
487b66d92a Merge branch 'api_avoid_copies' into integration 2025-12-15 12:46:14 -06:00
J. Nick Koston
fc4869e2f9 Merge branch 'select_avoid_copies' into integration 2025-12-15 12:46:10 -06:00
J. Nick Koston
109e6c9719 Merge branch 'text_avoid_copies_const_ref' into integration 2025-12-15 12:46:06 -06:00
J. Nick Koston
3c42e534b3 Merge branch 'text_sensor_avoid_copies_const_ref' into integration 2025-12-15 12:46:02 -06:00
J. Nick Koston
b956c7798b [api] Avoid string copies in Home Assistant state subscription callbacks 2025-12-15 12:45:15 -06:00
J. Nick Koston
f8c0cd9ff6 [select] Eliminate string allocation in state callbacks 2025-12-15 12:39:52 -06:00
J. Nick Koston
e27c693051 [text] Avoid string copies in callbacks by passing const ref 2025-12-15 12:29:15 -06:00
J. Nick Koston
f6f1961e0e [text_sensor] Avoid string copies in callbacks by passing const ref 2025-12-15 12:24:34 -06:00
J. Nick Koston
ab0ca3006a Merge branch 'dev' into parition_callbacks 2025-12-15 12:20:54 -06:00
David Woodhouse
af1e0e6489 Merge branch 'dev' into buildinfo 2025-12-15 18:10:50 +00:00
Pascal Vizeli
260ffba2a5 [http_request] Fix infinite loop when server doesn't send Content-Length header (#12480)
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-15 12:54:12 -05:00
J. Nick Koston
dab6b54e97 Merge branch 'fix-http-request-content-length' into integration 2025-12-15 11:48:06 -06:00
David Woodhouse
fd32139d89 Use new ISO format for compilation_time in API DeviceInfo
Change the API's DeviceInfo response to use the new ISO 8601 format
with timezone for compilation_time field by calling get_build_time_string()
instead of get_compilation_time_ref().

Update the placeholder build_info_data.h to match the new format.

Update integration test to expect the new format for compilation_time.
2025-12-15 17:44:35 +00:00
J. Nick Koston
245e7682c1 Merge remote-tracking branch 'swoboda1337/esp32-remove-arduino-core' into integration 2025-12-15 11:32:08 -06:00
Jonathan Swoboda
2e899dd010 [esp32] Support all IDF component version operators in shorthand syntax (#12499)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-15 12:07:02 -05:00
David Woodhouse
93bf1c8452 Merge branch 'dev' into buildinfo 2025-12-15 17:00:31 +00:00
David Woodhouse
0a63c50e1e Add test for build_info regeneration behaviour
Test verifies that:
- When source files change, build_info is regenerated with new timestamp
- When no files change, build_info is preserved with same timestamp

The test runs copy_src_tree() three times in the same environment:
1. Initial run creates build_info
2. Second run with no changes preserves the timestamp
3. Third run with changed source file regenerates with new timestamp
2025-12-15 16:59:51 +00:00
David Woodhouse
61cbd07e1d Add hmac-sha256 support (#12437)
Co-authored-by: J. Nick Koston <nick+github@koston.org>
2025-12-15 10:55:03 -06:00
David Woodhouse
87a125f303 Add test coverage for build_info.json change detection
Add tests to cover:
- Detection of config_hash changes in existing build_info.json
- Detection of esphome_version changes in existing build_info.json
- Handling of invalid/corrupted build_info.json files

These tests cover the exception handling and change detection logic
in copy_src_tree() that checks the existing build_info.json.
2025-12-15 16:45:15 +00:00
Jonathan Swoboda
e57e1f5094 Fix 2025-12-15 11:44:14 -05:00
David Woodhouse
09e9b58eb6 Change build_time_str format to ISO 8601 with timezone
Use YYYY-MM-DD HH:MM:SS +ZZZZ format instead of the locale-dependent
'%b %d %Y, %H:%M:%S' format. This provides:
- Unambiguous date format (YYYY-MM-DD)
- Timezone information
- Locale-independent formatting
- Better sortability and parseability

Example: "2025-12-15 16:30:27 +0000" instead of "Dec 15 2025, 16:30:27"

Tests validate the format using strptime with '%Y-%m-%d %H:%M:%S %z'.
2025-12-15 16:38:44 +00:00
David Woodhouse
c451fbd697 Postpone breaking changes for another PR
I think we need to put a little more thought into whether we really
want the build time in each of these, or whether it should be just
the config_hash (perhaps extended with version, and in some cases
the component's own serial number or other identifier).

So put the old compilation_time_ and its access methods back, so
this PR only adds the *new* fields. We can migrate users over and
then remove the compilation_time_ separately.
2025-12-15 16:26:15 +00:00
Jonathan Swoboda
853372a814 Fix 2025-12-15 10:48:48 -05:00
Jonathan Swoboda
db91ac9c75 Fix 2025-12-15 10:45:59 -05:00
David Woodhouse
d83fd263b0 Don't rebuild build_time_str
It's already in the JSON now
2025-12-15 15:44:12 +00:00
Jonathan Swoboda
415a1dd75a Merge branch 'dev' into esp32-remove-arduino-core 2025-12-15 10:43:14 -05:00
J. Nick Koston
ed4f90db8f Merge remote-tracking branch 'upstream/libretiny_prefs' into integration 2025-12-15 09:21:51 -06:00
J. Nick Koston
9dc06f04b1 Merge branch 'dev' into libretiny_prefs 2025-12-15 09:21:36 -06:00
Jonathan Swoboda
fe315a4cf8 Clean 2025-12-15 10:20:52 -05:00
Jonathan Swoboda
b9d59f5a00 [esp32] Remove Arduino-specific code from core.cpp, use initArduino
- Remove all USE_ARDUINO conditionals from core.cpp
- Add weak initArduino() stub that gets overridden when Arduino is present
- Call initArduino() in app_main() to initialize Arduino framework
- Remove CONFIG_AUTOSTART_ARDUINO (no longer needed)
- Fix deprecated hal/cpu_hal.h include, use esp_cpu.h instead
- Remove old ESP-IDF version conditionals (now IDF 5.x+ only)
- Clean up and sort includes alphabetically

This unifies the ESP32 startup code path - Arduino initialization is now
handled by calling initArduino() rather than using CONFIG_AUTOSTART_ARDUINO
which would start Arduino's own main loop.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-15 10:19:20 -05:00
J. Nick Koston
efc53ddd77 Merge remote-tracking branch 'upstream/esp32_prefs_uint32_str' into integration 2025-12-15 09:11:16 -06:00
J. Nick Koston
0bc81633bf at boundry 2025-12-15 09:06:33 -06:00
J. Nick Koston
cf20e0d772 libretiny prefs 2025-12-15 09:03:42 -06:00
David Woodhouse
bc5444cbe1 Merge branch 'dev' into buildinfo 2025-12-15 14:40:52 +00:00
Jonathan Swoboda
450962850a [remote_base] Fix crash when ABBWelcome action has no data field (#12493)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-15 09:29:51 -05:00
Pascal Vizeli
2dbaedbda2 Simplify condition check - remove redundant bufsize > 0 check
The bufsize > 0 check is redundant because the previous if statement
already handles all cases where bufsize <= 0, ensuring that by the time
we reach this condition, bufsize is always positive.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-15 12:17:47 +00:00
David Woodhouse
5eab42441e Fix dummy_main.cpp to match new pre_setup signature
Remove compilation timestamp argument as build time is now handled
through build_info_data.h instead of being passed to pre_setup().
2025-12-15 09:06:49 +00:00
David Woodhouse
0f22b23d9a clang-tidy CI fix
...but this is weird. Why are we copying into a local buffer
at all instead of just using the original string?
2025-12-15 17:11:04 +09:00
David Woodhouse
b27229d9b9 Merge branch 'dev' into buildinfo 2025-12-15 08:11:00 +00:00
J. Nick Koston
6a5dc6e7f5 Merge branch 'esp32_prefs_uint32_str' into integration 2025-12-14 22:29:28 -06:00
J. Nick Koston
ee5a3088b9 tweak 2025-12-14 22:17:45 -06:00
J. Nick Koston
6c166c904c [esp32] Replace std::string with char[12] for NVS preference keys 2025-12-14 22:06:42 -06:00
J. Nick Koston
995cf8be9c Merge remote-tracking branch 'upstream/dev' into integration 2025-12-14 21:34:22 -06:00
Jonathan Swoboda
6b088caf5d Merge branch 'beta' into dev 2025-12-14 19:18:10 -05:00
Jonathan Swoboda
3e6a65e7dc Merge pull request #12488 from esphome/bump-2025.12.0b3
2025.12.0b3
2025-12-14 19:17:58 -05:00
Jonathan Swoboda
3a101d8886 Bump version to 2025.12.0b3 2025-12-14 18:17:00 -05:00
J. Nick Koston
fa0f07bfe9 [wifi] Fix WiFi recovery after failed connection attempts (#12483) 2025-12-14 18:17:00 -05:00
mbohdal
fffa16e4d8 [ethernet] fix used pins validation in configuration of RMII pins (#12486) 2025-12-14 18:17:00 -05:00
guillempages
734710d22a [core] Use Arduino string macros only on ESP8266 (#12471) 2025-12-14 18:17:00 -05:00
J. Nick Koston
3a1be6822e [ota] Match client timeout to device timeout to prevent premature failures (#12484) 2025-12-14 18:17:00 -05:00
J. Nick Koston
c85b1b8609 [web_server_idf] Always enable LRU purge to prevent socket exhaustion (#12481) 2025-12-14 18:17:00 -05:00
J. Nick Koston
2e9ddd967c [wifi_signal] Skip publishing disconnected RSSI value (#12482) 2025-12-14 18:17:00 -05:00
J. Nick Koston
078afe9656 [dashboard] Add ESPHOME_TRUSTED_DOMAINS support to events WebSocket (#12479) 2025-12-14 18:17:00 -05:00
Jonathan Swoboda
46574fcbec [cc1101] Add packet mode support (#12474)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-14 18:17:00 -05:00
Jonathan Swoboda
359f45400f [core] Fix polling_component_schema and type consistency (#12478)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-14 18:16:59 -05:00
Clyde Stubbs
4da95ccd7e [packet_transport] Ensure retransmission at update intervals (#12472)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-14 18:16:59 -05:00
J. Nick Koston
c69d58273a [core] Fix CORE.raw_config not updated after package merge (#12456) 2025-12-14 18:16:59 -05:00
J. Nick Koston
ffce80f96c [wifi] Fix WiFi recovery after failed connection attempts (#12483) 2025-12-14 16:26:34 -06:00
mbohdal
fa5b14fad4 [ethernet] fix used pins validation in configuration of RMII pins (#12486) 2025-12-14 16:40:08 -05:00
J. Nick Koston
45f413de0e Merge branch 'wifi_timeout' into integration 2025-12-14 15:30:58 -06:00
J. Nick Koston
24e490ef26 Merge branch 'wifi_fail_too_quickly_fix' into wifi_timeout 2025-12-14 15:17:05 -06:00
J. Nick Koston
d9296a907d Revert "recovery"
This reverts commit 712da5c2ae.
2025-12-14 15:13:22 -06:00
J. Nick Koston
0a979cf26a Merge branch 'wifi_fail_too_quickly_fix' into wifi_timeout 2025-12-14 15:07:48 -06:00
J. Nick Koston
712da5c2ae recovery 2025-12-14 15:07:22 -06:00
J. Nick Koston
09573b5e5f Merge branch 'wifi_fail_too_quickly_fix' into wifi_timeout 2025-12-14 14:40:38 -06:00
J. Nick Koston
11c9e974ac tweak 2025-12-14 14:38:02 -06:00
J. Nick Koston
3786c84bbe Merge branch 'wifi_fail_too_quickly_fix' into wifi_timeout 2025-12-14 14:32:02 -06:00
J. Nick Koston
c8b48df8f2 tweak 2025-12-14 14:31:41 -06:00
J. Nick Koston
1de743d85e Merge branch 'wifi_fail_too_quickly_fix' into wifi_timeout 2025-12-14 14:25:41 -06:00
J. Nick Koston
f22396a097 fixes 2025-12-14 14:25:23 -06:00
J. Nick Koston
8cdee86334 Merge branch 'wifi_fail_too_quickly_fix' into wifi_timeout 2025-12-14 14:20:19 -06:00
J. Nick Koston
7801420eca one more failure more 2025-12-14 14:18:59 -06:00
guillempages
cee532a1e3 [core] Use Arduino string macros only on ESP8266 (#12471) 2025-12-15 07:15:19 +11:00
J. Nick Koston
8524b894d6 [ota] Match client timeout to device timeout to prevent premature failures (#12484) 2025-12-14 13:47:11 -06:00
J. Nick Koston
4928862622 esp32 has same bug 2025-12-14 13:42:59 -06:00
J. Nick Koston
6939b67e47 esp32 has same bug 2025-12-14 13:42:10 -06:00
J. Nick Koston
0b32add874 Merge branch 'wifi_fail_too_quickly_fix' into wifi_timeout 2025-12-14 13:38:05 -06:00
J. Nick Koston
616dae5bf9 fix missing s_sta_connecting = false; 2025-12-14 13:37:48 -06:00
J. Nick Koston
3a5e708c13 [web_server_idf] Always enable LRU purge to prevent socket exhaustion (#12481) 2025-12-14 13:31:19 -06:00
J. Nick Koston
96e418a8ca [wifi_signal] Skip publishing disconnected RSSI value (#12482) 2025-12-14 13:31:07 -06:00
J. Nick Koston
780a407b10 [dashboard] Add ESPHOME_TRUSTED_DOMAINS support to events WebSocket (#12479) 2025-12-14 13:30:55 -06:00
J. Nick Koston
bd539fa34f Merge branch 'wifi_fail_too_quickly_fix' into wifi_timeout 2025-12-14 13:27:09 -06:00
J. Nick Koston
8ce2cc564f make sure we are disconnected on timeout 2025-12-14 13:26:54 -06:00
J. Nick Koston
2696297428 Merge branch 'ota_timeout_fix' into wifi_timeout 2025-12-14 12:45:57 -06:00
J. Nick Koston
7eff3217aa [ota] Match client timeout to device timeout to prevent premature failures 2025-12-14 12:34:54 -06:00
Jonathan Swoboda
cfc0d8bdfc [cc1101] Add packet mode support (#12474)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-14 13:22:55 -05:00
J. Nick Koston
af04eaaba0 [wifi] Fix premature connection timeout on LibreTiny/Beken 2025-12-14 12:19:58 -06:00
Jonathan Swoboda
786d7266f5 [core] Fix polling_component_schema and type consistency (#12478)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-14 12:47:52 -05:00
Clyde Stubbs
ede64a9f47 [packet_transport] Ensure retransmission at update intervals (#12472)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-14 12:47:15 -05:00
Pascal Vizeli
c4d9ed7b70 [http_request] Fix infinite loop on read error in update component
The update component had the same infinite loop issue as the OTA component
when network read errors occurred. If container->read() returned an error
(negative value), it would be added to read_index and the loop would continue
indefinitely since get_bytes_read() would never reach content_length.

This fix breaks out of the read loop on any read error (read_bytes <= 0),
preventing watchdog resets and infinite loops during manifest downloads.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-14 17:06:53 +00:00
Pascal Vizeli
f20f3e0525 [http_request] Fix infinite loop when server doesn't send Content-Length header
This commit fixes an issue where the http_request component would enter
an infinite loop when an HTTP server doesn't send a Content-Length header
or closes the connection prematurely.

The read loop was assuming read operations would always return data, but:
1. When the stream pointer becomes invalid (connection closed), read() returns -1
2. When no more data is available, read() returns 0

Without these checks, the loop would continue indefinitely, causing:
- "Stream pointer vanished!" errors (Arduino platform)
- CPU spinning on zero-byte reads
- Watchdog timeouts

The fix adds validation checks to break out of read loops when
read() returns <= 0 (covering both error and end-of-stream conditions).

This is applied to:
- Response capture loops (http_request.h)
- OTA firmware download loop (ota_http_request.cpp)
- MD5 verification download loop (ota_http_request.cpp)

This allows graceful handling of non-compliant HTTP servers while
maintaining compatibility with properly formatted responses.

Fixes esphome/issues#6682

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-14 16:18:37 +00:00
J. Nick Koston
2bfa1aacd8 Merge branch 'skip_wifi_rssi_publish_when_discoed' into integration 2025-12-14 09:55:42 -06:00
J. Nick Koston
1b551b0897 [wifi_signal] Skip publishing disconnected RSSI value 2025-12-14 09:55:09 -06:00
J. Nick Koston
7e1bd289b3 Merge branch 'fix-polling-component-schema' into integration 2025-12-14 09:38:15 -06:00
J. Nick Koston
cf373edd81 Merge branch 'lwip_raw_tcp_impl_getpeername' into integration 2025-12-14 09:38:07 -06:00
J. Nick Koston
0d7fbb79b3 Merge branch 'events_trusted_domains' into integration 2025-12-14 09:38:01 -06:00
J. Nick Koston
c87771184e Merge branch 'fix-epaper-spi-update-interval-never' into integration 2025-12-14 09:37:56 -06:00
J. Nick Koston
1185abadc1 Merge branch 'always_lru_enable_idf_web_server' into integration 2025-12-14 09:37:49 -06:00
J. Nick Koston
6f6c65509d [web_server_idf] Always enable LRU purge to prevent socket exhaustion 2025-12-14 09:37:11 -06:00
J. Nick Koston
f50ffb2b92 cover 2025-12-14 09:09:24 -06:00
J. Nick Koston
4892bfb6e4 [dashboard] Add ESPHOME_TRUSTED_DOMAINS support to events WebSocket 2025-12-14 09:00:27 -06:00
Jonathan Swoboda
586e82bfa5 [core] Fix polling_component_schema and use SCHEDULER_DONT_RUN constant
- Fix polling_component_schema to use update_interval validator when
  default_update_interval is None (was using None as validator)
- Replace hardcoded 4294967295 with SCHEDULER_DONT_RUN constant in
  update_interval function

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-14 09:41:56 -05:00
J. Nick Koston
512a7df007 [socket] Fix getpeername() returning local address instead of remote in LWIP raw TCP 2025-12-13 22:49:05 -06:00
J. Nick Koston
0e60aefdec Merge remote-tracking branch 'upstream/dev' into integration 2025-12-13 22:15:41 -06:00
David Woodhouse
1ebfd5b4eb Update test for new get_build_info behaviour
get_build_info() now always returns current time instead of preserving
the existing build_time. The timestamp preservation logic is now handled
in copy_src_tree() based on sources_changed flag.
2025-12-14 09:07:44 +09:00
David Woodhouse
4bde4dbdc8 Fix KeyError when build_info_data.h not in source_files_copy
Use pop(t, None) instead of pop(t) to handle case where
build_info_data.h might not be in the component resources.
2025-12-14 08:55:25 +09:00
David Woodhouse
841d9664d3 Fix build system to relink when source files change
- Make copy_file_if_changed() return bool indicating if file was copied
- Track sources_changed in copy_src_tree() to detect when source files change
- Only update build_info timestamp when sources/config/version change
- Exclude generated files (build_info_data.h) from sources_changed tracking
- Add build_info_data.h to ignore_targets to prevent copying from resources
- Track changes to generated headers (defines.h, esphome.h, version.h)
- Check for config_hash or version changes to trigger rebuild
- Pretty-print build_info.json with indentation and trailing newline
- Update mock_copy_file_if_changed to return True by default

This fixes the issue where changing a source file would recompile the .o
file but not relink the final program executable.
2025-12-14 08:51:59 +09:00
J. Nick Koston
16107ad788 bot comments 2025-12-13 10:34:09 -06:00
J. Nick Koston
8299656375 Update esphome/components/sgp4x/sgp4x.cpp
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-13 10:32:39 -06:00
J. Nick Koston
184ac0c1e7 Update esphome/components/sgp30/sgp30.cpp
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-13 10:32:33 -06:00
J. Nick Koston
6198618044 Update esphome/components/sen5x/sen5x.cpp
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-13 10:32:25 -06:00
J. Nick Koston
ba0f559856 better cover 2025-12-13 10:10:24 -06:00
J. Nick Koston
0539c5d4d2 cover 2025-12-13 10:02:54 -06:00
J. Nick Koston
bb35ed5f53 tidy 2025-12-13 09:54:07 -06:00
J. Nick Koston
de500450d9 coverage for hash order change 2025-12-13 09:45:17 -06:00
J. Nick Koston
b4a54f2df1 sort so config hash does not change 2025-12-13 09:40:26 -06:00
J. Nick Koston
cf8708b888 writer coverage 2025-12-13 09:28:52 -06:00
J. Nick Koston
15494c0d28 Merge branch 'buildinfo' of https://github.com/dwmw2/esphome into buildinfo 2025-12-13 09:25:32 -06:00
J. Nick Koston
4bf810fcd1 a bit of future proofing to avoid many dumps if it gets reused 2025-12-13 09:25:21 -06:00
J. Nick Koston
959a2e8ddd Merge branch 'dev' into buildinfo 2025-12-13 09:22:09 -06:00
J. Nick Koston
4b937b5228 some coverage 2025-12-13 09:21:53 -06:00
J. Nick Koston
0c7c1d3c57 check version as well 2025-12-13 09:13:28 -06:00
J. Nick Koston
d31be6ed9d check version as well 2025-12-13 09:10:40 -06:00
J. Nick Koston
dce5face4e simplify more 2025-12-13 09:01:39 -06:00
J. Nick Koston
6d91f1cd77 tests 2025-12-13 08:56:12 -06:00
J. Nick Koston
67937aeda4 tests 2025-12-13 08:55:26 -06:00
J. Nick Koston
1543f56f70 simplify approach 2025-12-13 08:53:51 -06:00
J. Nick Koston
e0ce66e011 [core] Fix CORE.raw_config not updated after package merge (#12456) 2025-12-13 07:38:31 -06:00
J. Nick Koston
2fc3ef61ea adjust 2025-12-12 21:42:07 -06:00
J. Nick Koston
145475e461 tidy 2025-12-12 21:31:43 -06:00
J. Nick Koston
b1fb705864 [esp8266] Avoid heap allocation in preferences save/load 2025-12-12 21:28:21 -06:00
David Woodhouse
15d2d3ff96 Update esphome/core/buildinfo.cpp
Co-authored-by: J. Nick Koston <nick+github@koston.org>
2025-12-13 12:13:01 +09:00
David Woodhouse
d016302e36 Convert buildinfo.h to C++17 nested namespace syntax 2025-12-13 12:05:05 +09:00
David Woodhouse
fe798dff81 Update esphome/writer.py
Co-authored-by: J. Nick Koston <nick+github@koston.org>
2025-12-13 12:03:43 +09:00
J. Nick Koston
75b8279361 Merge remote-tracking branch 'upstream/dev' into integration 2025-12-12 21:03:28 -06:00
David Woodhouse
17db6bee3c Update esphome/__main__.py
Co-authored-by: J. Nick Koston <nick+github@koston.org>
2025-12-13 12:03:12 +09:00
David Woodhouse
e7c8892d6d Merge branch 'dev' into buildinfo 2025-12-13 12:00:08 +09:00
David Woodhouse
12e0d6bdcc Create and use buildinfo.json instead of parsing linker script
Co-authored-by: J. Nick Koston <nick+github@koston.org>
2025-12-13 11:57:04 +09:00
David Woodhouse
d8c52297ab Add type hints to _encode_string_symbols function 2025-12-13 11:54:24 +09:00
David Woodhouse
6fce0a6104 Add host platform support to MD5 component (#12458) 2025-12-13 02:50:34 +00:00
David Woodhouse
eda0a391ca Extract duplicate string encoding logic into helper function 2025-12-13 11:26:37 +09:00
David Woodhouse
94fefb1405 Limit OSError exception catch to file open operation only 2025-12-13 11:26:37 +09:00
David Woodhouse
da96ffb923 Convert buildinfo to C++17 nested namespace syntax 2025-12-13 11:26:37 +09:00
David Woodhouse
d7451257a5 Merge branch 'dev' into buildinfo 2025-12-13 11:20:39 +09:00
J. Nick Koston
b10a87c1b0 Merge branch 'factory_reset_waste' into integration 2025-12-12 20:14:42 -06:00
J. Nick Koston
f2505ce453 tidy 2025-12-12 20:14:31 -06:00
David Woodhouse
32797fbe00 Generate buildinfo.ld directly, use fnv1a_32bit_hash()
Co-authored-by: J. Nick Koston <nick+github@koston.org>
2025-12-13 11:11:59 +09:00
J. Nick Koston
ec7143d835 Merge branch 'factory_reset_waste' into integration 2025-12-12 20:09:19 -06:00
J. Nick Koston
d77f9c96b9 [factory_reset] Optimize memory by storing interval as uint16_t seconds 2025-12-12 20:08:00 -06:00
J. Nick Koston
4329794924 Merge branch 'ota_align_password' into integration 2025-12-12 19:39:06 -06:00
J. Nick Koston
99b0b974ad [esphome] Improve OTA field alignment to save 4 bytes on 32-bit 2025-12-12 19:38:44 -06:00
J. Nick Koston
9dafafa07c Merge branch 'memory_api' into integration 2025-12-12 19:25:14 -06:00
J. Nick Koston
200cd8cace Merge branch 'str_helpers' into integration 2025-12-12 19:25:09 -06:00
Jonathan Swoboda
b8c00e6452 Merge branch 'dev' into fix-epaper-spi-update-interval-never 2025-12-12 17:25:02 -05:00
Jonathan Swoboda
1d081fd510 [epaper_spi] Fix update_interval: never validation error
- Add full_display_schema() function to display component to allow
  configurable default update_interval
- Fix epaper_spi to use 60s default update_interval instead of 1s
- Fix minimum update_interval validation to allow "never" value
- Keep FULL_DISPLAY_SCHEMA constant for backward compatibility

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-12 16:59:50 -05:00
David Woodhouse
a86095d865 Merge branch 'dev' into buildinfo 2025-12-13 06:24:20 +09:00
David Woodhouse
e728e8ed0c Apply clang-format suggestions to buildinfo.cpp
- Use <cstdint> instead of <stdint.h>
- Rename config_hash_struct to ConfigHashStruct for naming consistency
2025-12-13 06:17:28 +09:00
J. Nick Koston
80fda97c60 [core] Refactor str_snake_case and str_sanitize to use constexpr helpers 2025-12-12 13:13:07 -06:00
David Woodhouse
7d3afe5de0 Merge branch 'dev' into buildinfo 2025-12-13 01:45:43 +09:00
David Woodhouse
b5703523f9 nolint for the macros that have to be macros 2025-12-13 01:44:25 +09:00
David Woodhouse
07d784b0bf Pass config hash and build date in as strings via linker symbols
This saves the RAM we were using to build it at runtime.
2025-12-13 01:39:29 +09:00
David Woodhouse
25805da008 Merge branch 'dev' into buildinfo 2025-12-12 09:54:47 +09:00
David Woodhouse
ccebe613e2 Optimize buildinfo RAM usage on 32-bit platforms
Use direct symbol access on 32-bit platforms to avoid 8 bytes of RAM
overhead. Keep indirection workaround only on 64-bit platforms where
PC-relative relocations cause linking issues.
2025-12-12 01:51:12 +09:00
David Woodhouse
295b317809 Optimize get_build_time_string to avoid repeated formatting
Apply same concurrency fix as get_config_hash to prevent race
conditions when multiple threads access the function.
2025-12-11 22:54:19 +09:00
David Woodhouse
58fddeb74f Optimize get_config_hash to avoid repeated snprintf calls
Check if hash string is already formatted before calling snprintf,
since static variables in BSS are zero-initialized.
2025-12-11 22:53:03 +09:00
David Woodhouse
54ed6154eb Expand non-const comment 2025-12-11 22:49:32 +09:00
David Woodhouse
0b1ea8f2ca Add nolint for non-const buildinfo variables
Variables must remain non-const to prevent compiler optimization
that would bypass the indirection workaround for PC-relative
relocation issues.
2025-12-11 22:48:02 +09:00
David Woodhouse
478f12f75e Remove const from buildinfo static variables
The const qualifier allows compiler optimization that bypasses our
indirection workaround, causing PC-relative relocations that fail
on some platforms. Keep variables non-const to force data section
relocations.
2025-12-11 22:46:09 +09:00
David Woodhouse
cfdb5a82e2 Replace __DATE__/__TIME__ with buildinfo functions
- Add get_build_time_string() function to format build time consistently
- Replace __DATE__ ", " __TIME__ in App.pre_setup() with buildinfo call
- Eliminates dependency on compiler-provided date/time macros
- Ensures consistent build time across all build information displays
2025-12-11 22:24:30 +09:00
David Woodhouse
edc320fef8 Add buildinfo system with config hash and build time
To allow for more selective managed updates, allow the config hash and
build time to be built into the image itself.

To avoid triggering unneeded rebuilds, do this through a linker script
so that the new config hash and timestamp are included only if the
firmware is actually relinked.

Add a _check_and_emit_buildinfo() step after building, which prints
the information after the firmware was rebuilt. A subsequent commit
will emit a manifest here, or at least the HMAC-MD5 for signing OTA
updates using the hmac_key configured in this image.
2025-12-11 22:24:30 +09:00
J. Nick Koston
2d3ccab0b3 [api] Add zero-copy support for noise encryption key requests 2025-12-10 12:48:04 +01:00
J. Nick Koston
fdd560b165 [fan] Add zero-copy support for API preset mode commands 2025-12-10 12:40:35 +01:00
J. Nick Koston
6b810b340a fix 2025-12-10 12:38:04 +01:00
J. Nick Koston
3cd14fa39d [climate] Add zero-copy support for API custom fan mode and preset commands 2025-12-10 10:45:07 +01:00
1089 changed files with 41328 additions and 16782 deletions

View File

@@ -293,6 +293,12 @@ This document provides essential context for AI models interacting with this pro
* **Configuration Design:** Aim for simplicity with sensible defaults, while allowing for advanced customization.
* **Embedded Systems Optimization:** ESPHome targets resource-constrained microcontrollers. Be mindful of flash size and RAM usage.
**Why Heap Allocation Matters:**
ESP devices run for months with small heaps shared between Wi-Fi, BLE, LWIP, and application code. Over time, repeated allocations of different sizes fragment the heap. Failures happen when the largest contiguous block shrinks, even if total free heap is still large. We have seen field crashes caused by this.
**Heap allocation after `setup()` should be avoided unless absolutely unavoidable.** Every allocation/deallocation cycle contributes to fragmentation. ESPHome treats runtime heap allocation as a long-term reliability bug, not a performance issue. Helpers that hide allocation (`std::string`, `std::to_string`, string-returning helpers) are being deprecated and replaced with buffer and view based APIs.
**STL Container Guidelines:**
ESPHome runs on embedded systems with limited resources. Choose containers carefully:
@@ -322,15 +328,15 @@ This document provides essential context for AI models interacting with this pro
std::array<uint8_t, 256> buffer;
```
2. **Compile-time-known fixed sizes with vector-like API:** Use `StaticVector` from `esphome/core/helpers.h` for fixed-size stack allocation with `push_back()` interface.
2. **Compile-time-known fixed sizes with vector-like API:** Use `StaticVector` from `esphome/core/helpers.h` for compile-time fixed size with `push_back()` interface (no dynamic allocation).
```cpp
// Bad - generates STL realloc code (_M_realloc_insert)
std::vector<ServiceRecord> services;
services.reserve(5); // Still includes reallocation machinery
// Good - compile-time fixed size, stack allocated, no reallocation machinery
StaticVector<ServiceRecord, MAX_SERVICES> services; // Allocates all MAX_SERVICES on stack
services.push_back(record1); // Tracks count but all slots allocated
// Good - compile-time fixed size, no dynamic allocation
StaticVector<ServiceRecord, MAX_SERVICES> services;
services.push_back(record1);
```
Use `cg.add_define("MAX_SERVICES", count)` to set the size from Python configuration.
Like `std::array` but with vector-like API (`push_back()`, `size()`) and no STL reallocation code.
@@ -372,22 +378,21 @@ This document provides essential context for AI models interacting with this pro
```
Linear search on small datasets (1-16 elements) is often faster than hashing/tree overhead, but this depends on lookup frequency and access patterns. For frequent lookups in hot code paths, the O(1) vs O(n) complexity difference may still matter even for small datasets. `std::vector` with simple structs is usually fine—it's the heavy containers (`map`, `set`, `unordered_map`) that should be avoided for small datasets unless profiling shows otherwise.
5. **Detection:** Look for these patterns in compiler output:
5. **Avoid `std::deque`:** It allocates in 512-byte blocks regardless of element size, guaranteeing at least 512 bytes of RAM usage immediately. This is a major source of crashes on memory-constrained devices.
6. **Detection:** Look for these patterns in compiler output:
- Large code sections with STL symbols (vector, map, set)
- `alloc`, `realloc`, `dealloc` in symbol names
- `_M_realloc_insert`, `_M_default_append` (vector reallocation)
- Red-black tree code (`rb_tree`, `_Rb_tree`)
- Hash table infrastructure (`unordered_map`, `hash`)
**When to optimize:**
**Prioritize optimization effort for:**
- Core components (API, network, logger)
- Widely-used components (mdns, wifi, ble)
- Components causing flash size complaints
**When not to optimize:**
- Single-use niche components
- Code where readability matters more than bytes
- Already using appropriate containers
Note: Avoiding heap allocation after `setup()` is always required regardless of component type. The prioritization above is about the effort spent on container optimization (e.g., migrating from `std::vector` to `StaticVector`).
* **State Management:** Use `CORE.data` for component state that needs to persist during configuration generation. Avoid module-level mutable globals.

View File

@@ -1 +1 @@
766420905c06eeb6c5f360f68fd965e5ddd9c4a5db6b823263d3ad3accb64a07
d272a88e8ca28ae9340a9a03295a566432a52cb696501908f57764475bf7ca65

View File

@@ -27,6 +27,7 @@
- [ ] RP2040
- [ ] BK72xx
- [ ] RTL87xx
- [ ] LN882x
- [ ] nRF52840
## Example entry for `config.yaml`:

View File

@@ -49,7 +49,7 @@ jobs:
with:
python-version: "3.11"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
- name: Set TAG
run: |

View File

@@ -58,7 +58,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8
uses: github/codeql-action/init@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
@@ -86,6 +86,6 @@ jobs:
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8
uses: github/codeql-action/analyze@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10
with:
category: "/language:${{matrix.language}}"

View File

@@ -99,7 +99,7 @@ jobs:
python-version: "3.11"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
- name: Log in to docker hub
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
@@ -178,7 +178,7 @@ jobs:
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
- name: Log in to docker hub
if: matrix.registry == 'dockerhub'

4
.gitignore vendored
View File

@@ -91,6 +91,10 @@ venv-*/
# mypy
.mypy_cache/
# nix
/default.nix
/shell.nix
.pioenvs
.piolibdeps
.pio

View File

@@ -11,7 +11,7 @@ ci:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.14.9
rev: v0.14.11
hooks:
# Run the linter.
- id: ruff

View File

@@ -42,6 +42,7 @@ esphome/components/animation/* @syndlex
esphome/components/anova/* @buxtronix
esphome/components/apds9306/* @aodrenah
esphome/components/api/* @esphome/core
esphome/components/aqi/* @freekode @jasstrong @ximex
esphome/components/as5600/* @ammmze
esphome/components/as5600/sensor/* @ammmze
esphome/components/as7341/* @mrgnr
@@ -90,6 +91,7 @@ esphome/components/bmp3xx_spi/* @latonita
esphome/components/bmp581/* @kahrendt
esphome/components/bp1658cj/* @Cossid
esphome/components/bp5758d/* @Cossid
esphome/components/bthome_mithermometer/* @nagyrobi
esphome/components/button/* @esphome/core
esphome/components/bytebuffer/* @clydebarrow
esphome/components/camera/* @bdraco @DT-art1
@@ -133,7 +135,7 @@ esphome/components/display_menu_base/* @numo68
esphome/components/dps310/* @kbx81
esphome/components/ds1307/* @badbadc0ffee
esphome/components/ds2484/* @mrk-its
esphome/components/dsmr/* @glmnet @zuidwijk
esphome/components/dsmr/* @glmnet @PolarGoose @zuidwijk
esphome/components/duty_time/* @dudanov
esphome/components/ee895/* @Stock-M
esphome/components/ektf2232/touchscreen/* @jesserockz
@@ -215,6 +217,7 @@ esphome/components/hlk_fm22x/* @OnFreund
esphome/components/hlw8032/* @rici4kubicek
esphome/components/hm3301/* @freekode
esphome/components/hmac_md5/* @dwmw2
esphome/components/hmac_sha256/* @dwmw2
esphome/components/homeassistant/* @esphome/core @OttoWinter
esphome/components/homeassistant/number/* @landonr
esphome/components/homeassistant/switch/* @Links2004
@@ -246,11 +249,13 @@ esphome/components/ina260/* @mreditor97
esphome/components/ina2xx_base/* @latonita
esphome/components/ina2xx_i2c/* @latonita
esphome/components/ina2xx_spi/* @latonita
esphome/components/infrared/* @kbx81
esphome/components/inkbird_ibsth1_mini/* @fkirill
esphome/components/inkplate/* @jesserockz @JosipKuci
esphome/components/integration/* @OttoWinter
esphome/components/internal_temperature/* @Mat931
esphome/components/interval/* @esphome/core
esphome/components/ir_rf_proxy/* @kbx81
esphome/components/jsn_sr04t/* @Mafus1
esphome/components/json/* @esphome/core
esphome/components/kamstrup_kmp/* @cfeenstra1024
@@ -392,6 +397,7 @@ esphome/components/radon_eye_rd200/* @jeffeb3
esphome/components/rc522/* @glmnet
esphome/components/rc522_i2c/* @glmnet
esphome/components/rc522_spi/* @glmnet
esphome/components/rd03d/* @jasstrong
esphome/components/resampler/speaker/* @kahrendt
esphome/components/restart/* @esphome/core
esphome/components/rf_bridge/* @jesserockz
@@ -517,6 +523,7 @@ esphome/components/tuya/switch/* @jesserockz
esphome/components/tuya/text_sensor/* @dentra
esphome/components/uart/* @esphome/core
esphome/components/uart/button/* @ssieb
esphome/components/uart/event/* @eoasmxd
esphome/components/uart/packet_transport/* @clydebarrow
esphome/components/udp/* @clydebarrow
esphome/components/ufire_ec/* @pvizeli
@@ -535,6 +542,7 @@ esphome/components/version/* @esphome/core
esphome/components/voice_assistant/* @jesserockz @kahrendt
esphome/components/wake_on_lan/* @clydebarrow @willwill2will54
esphome/components/watchdog/* @oarcher
esphome/components/water_heater/* @dhoeben
esphome/components/waveshare_epaper/* @clydebarrow
esphome/components/web_server/ota/* @esphome/core
esphome/components/web_server_base/* @esphome/core
@@ -570,5 +578,6 @@ esphome/components/xpt2046/touchscreen/* @nielsnl68 @numo68
esphome/components/xxtea/* @clydebarrow
esphome/components/zephyr/* @tomaszduda23
esphome/components/zhlt01/* @cfeenstra1024
esphome/components/zigbee/* @tomaszduda23
esphome/components/zio_ultrasonic/* @kahrendt
esphome/components/zwave_proxy/* @kbx81

View File

@@ -1,6 +1,7 @@
include LICENSE
include README.md
include requirements.txt
recursive-include esphome *.yaml
recursive-include esphome *.cpp *.h *.tcc *.c
recursive-include esphome *.py.script
recursive-include esphome LICENSE.txt

View File

@@ -11,6 +11,16 @@ FROM base-source-${BUILD_TYPE} AS base
RUN git config --system --add safe.directory "*"
# Install build tools for Python packages that require compilation
# (e.g., ruamel.yaml.clibz used by ESP-IDF's idf-component-manager)
RUN if command -v apk > /dev/null; then \
apk add --no-cache build-base; \
else \
apt-get update \
&& apt-get install -y --no-install-recommends build-essential \
&& rm -rf /var/lib/apt/lists/*; \
fi
ENV PIP_DISABLE_PIP_VERSION_CHECK=1
RUN pip install --no-cache-dir -U pip uv==0.6.14

View File

@@ -62,6 +62,9 @@ from esphome.util import (
_LOGGER = logging.getLogger(__name__)
# Maximum buffer size for serial log reading to prevent unbounded memory growth
SERIAL_BUFFER_MAX_SIZE = 65536
# Special non-component keys that appear in configs
_NON_COMPONENT_KEYS = frozenset(
{
@@ -431,25 +434,37 @@ def run_miniterm(config: ConfigType, port: str, args) -> int:
while tries < 5:
try:
with ser:
buffer = b""
ser.timeout = 0.1 # 100ms timeout for non-blocking reads
while True:
try:
raw = ser.readline()
# Read all available data and timestamp it
chunk = ser.read(ser.in_waiting or 1)
if not chunk:
continue
time_ = datetime.now()
milliseconds = time_.microsecond // 1000
time_str = f"[{time_.hour:02}:{time_.minute:02}:{time_.second:02}.{milliseconds:03}]"
# Add to buffer and process complete lines
# Limit buffer size to prevent unbounded memory growth
# if device sends data without newlines
buffer += chunk
if len(buffer) > SERIAL_BUFFER_MAX_SIZE:
buffer = buffer[-SERIAL_BUFFER_MAX_SIZE:]
while b"\n" in buffer:
raw_line, buffer = buffer.split(b"\n", 1)
line = raw_line.replace(b"\r", b"").decode(
"utf8", "backslashreplace"
)
safe_print(parser.parse_line(line, time_str))
backtrace_state = platformio_api.process_stacktrace(
config, line, backtrace_state=backtrace_state
)
except serial.SerialException:
_LOGGER.error("Serial port closed!")
return 0
line = (
raw.replace(b"\r", b"")
.replace(b"\n", b"")
.decode("utf8", "backslashreplace")
)
time_ = datetime.now()
nanoseconds = time_.microsecond // 1000
time_str = f"[{time_.hour:02}:{time_.minute:02}:{time_.second:02}.{nanoseconds:03}]"
safe_print(parser.parse_line(line, time_str))
backtrace_state = platformio_api.process_stacktrace(
config, line, backtrace_state=backtrace_state
)
except serial.SerialException:
tries += 1
time.sleep(1)
@@ -518,10 +533,49 @@ def compile_program(args: ArgsProtocol, config: ConfigType) -> int:
rc = platformio_api.run_compile(config, CORE.verbose)
if rc != 0:
return rc
# Check if firmware was rebuilt and emit build_info + create manifest
_check_and_emit_build_info()
idedata = platformio_api.get_idedata(config)
return 0 if idedata is not None else 1
def _check_and_emit_build_info() -> None:
"""Check if firmware was rebuilt and emit build_info."""
import json
firmware_path = CORE.firmware_bin
build_info_json_path = CORE.relative_build_path("build_info.json")
# Check if both files exist
if not firmware_path.exists() or not build_info_json_path.exists():
return
# Check if firmware is newer than build_info (indicating a relink occurred)
if firmware_path.stat().st_mtime <= build_info_json_path.stat().st_mtime:
return
# Read build_info from JSON
try:
with open(build_info_json_path, encoding="utf-8") as f:
build_info = json.load(f)
except (OSError, json.JSONDecodeError) as e:
_LOGGER.debug("Failed to read build_info: %s", e)
return
config_hash = build_info.get("config_hash")
build_time_str = build_info.get("build_time_str")
if config_hash is None or build_time_str is None:
return
# Emit build_info with human-readable time
_LOGGER.info(
"Build Info: config_hash=0x%08x build_time_str=%s", config_hash, build_time_str
)
def upload_using_esptool(
config: ConfigType, port: str, file: str, speed: int
) -> str | int:
@@ -757,7 +811,13 @@ def command_compile(args: ArgsProtocol, config: ConfigType) -> int | None:
exit_code = compile_program(args, config)
if exit_code != 0:
return exit_code
_LOGGER.info("Successfully compiled program.")
if CORE.is_host:
from esphome.platformio_api import get_idedata
program_path = str(get_idedata(config).firmware_elf_path)
_LOGGER.info("Successfully compiled program to path '%s'", program_path)
else:
_LOGGER.info("Successfully compiled program.")
return 0
@@ -807,10 +867,8 @@ def command_run(args: ArgsProtocol, config: ConfigType) -> int | None:
if CORE.is_host:
from esphome.platformio_api import get_idedata
idedata = get_idedata(config)
if idedata is None:
return 1
program_path = idedata.raw["prog_path"]
program_path = str(get_idedata(config).firmware_elf_path)
_LOGGER.info("Running program from path '%s'", program_path)
return run_external_process(program_path)
# Get devices, resolving special identifiers like OTA
@@ -981,6 +1039,7 @@ def command_analyze_memory(args: ArgsProtocol, config: ConfigType) -> int:
idedata.objdump_path,
idedata.readelf_path,
external_components,
idedata=idedata,
)
analyzer.analyze()

View File

@@ -22,6 +22,7 @@ from .helpers import (
map_section_name,
parse_symbol_line,
)
from .toolchain import find_tool, run_tool
if TYPE_CHECKING:
from esphome.platformio_api import IDEData
@@ -53,6 +54,9 @@ _NAMESPACE_STD = "std::"
# Type alias for symbol information: (symbol_name, size, component)
SymbolInfoType = tuple[str, int, str]
# RAM sections - symbols in these sections consume RAM
RAM_SECTIONS = frozenset([".data", ".bss"])
@dataclass
class MemorySection:
@@ -60,7 +64,20 @@ class MemorySection:
name: str
symbols: list[SymbolInfoType] = field(default_factory=list)
total_size: int = 0
total_size: int = 0 # Actual section size from ELF headers
symbol_size: int = 0 # Sum of symbol sizes (may be less than total_size)
@dataclass
class SDKSymbol:
"""Represents a symbol from an SDK library that's not in the ELF symbol table."""
name: str
size: int
library: str # Name of the .a file (e.g., "libpp.a")
section: str # ".bss" or ".data"
is_local: bool # True if static/local symbol (lowercase in nm output)
demangled: str = "" # Demangled name (populated after analysis)
@dataclass
@@ -118,6 +135,10 @@ class MemoryAnalyzer:
self.objdump_path = objdump_path or "objdump"
self.readelf_path = readelf_path or "readelf"
self.external_components = external_components or set()
self._idedata = idedata
# Derive nm path from objdump path using shared toolchain utility
self.nm_path = find_tool("nm", self.objdump_path)
self.sections: dict[str, MemorySection] = {}
self.components: dict[str, ComponentMemory] = defaultdict(
@@ -128,15 +149,25 @@ class MemoryAnalyzer:
self._esphome_core_symbols: list[
tuple[str, str, int]
] = [] # Track core symbols
self._component_symbols: dict[str, list[tuple[str, str, int]]] = defaultdict(
# Track symbols for all components: (symbol_name, demangled, size, section)
self._component_symbols: dict[str, list[tuple[str, str, int, str]]] = (
defaultdict(list)
)
# Track RAM symbols separately for detailed analysis: (symbol_name, demangled, size, section)
self._ram_symbols: dict[str, list[tuple[str, str, int, str]]] = defaultdict(
list
) # Track symbols for all components
)
# Track ELF symbol names for SDK cross-reference
self._elf_symbol_names: set[str] = set()
# SDK symbols not in ELF (static/local symbols from closed-source libs)
self._sdk_symbols: list[SDKSymbol] = []
def analyze(self) -> dict[str, ComponentMemory]:
"""Analyze the ELF file and return component memory usage."""
self._parse_sections()
self._parse_symbols()
self._categorize_symbols()
self._analyze_sdk_libraries()
return dict(self.components)
def _parse_sections(self) -> None:
@@ -190,6 +221,8 @@ class MemoryAnalyzer:
continue
self.sections[section].symbols.append((name, size, ""))
self.sections[section].symbol_size += size
self._elf_symbol_names.add(name)
seen_addresses.add(address)
def _categorize_symbols(self) -> None:
@@ -233,8 +266,13 @@ class MemoryAnalyzer:
if size > 0:
demangled = self._demangle_symbol(symbol_name)
self._component_symbols[component].append(
(symbol_name, demangled, size)
(symbol_name, demangled, size, section_name)
)
# Track RAM symbols separately for detailed RAM analysis
if section_name in RAM_SECTIONS:
self._ram_symbols[component].append(
(symbol_name, demangled, size, section_name)
)
def _identify_component(self, symbol_name: str) -> str:
"""Identify which component a symbol belongs to."""
@@ -328,6 +366,247 @@ class MemoryAnalyzer:
return "Other Core"
def get_unattributed_ram(self) -> tuple[int, int, int]:
"""Get unattributed RAM sizes (SDK/framework overhead).
Returns:
Tuple of (unattributed_bss, unattributed_data, total_unattributed)
These are bytes in RAM sections that have no corresponding symbols.
"""
bss_section = self.sections.get(".bss")
data_section = self.sections.get(".data")
unattributed_bss = 0
unattributed_data = 0
if bss_section:
unattributed_bss = max(0, bss_section.total_size - bss_section.symbol_size)
if data_section:
unattributed_data = max(
0, data_section.total_size - data_section.symbol_size
)
return unattributed_bss, unattributed_data, unattributed_bss + unattributed_data
def _find_sdk_library_dirs(self) -> list[Path]:
"""Find SDK library directories based on platform.
Returns:
List of paths to SDK library directories containing .a files.
"""
sdk_dirs: list[Path] = []
if self._idedata is None:
return sdk_dirs
# Get the CC path to determine the framework location
cc_path = getattr(self._idedata, "cc_path", None)
if not cc_path:
return sdk_dirs
cc_path = Path(cc_path)
# For ESP8266 Arduino framework
# CC is like: ~/.platformio/packages/toolchain-xtensa/bin/xtensa-lx106-elf-gcc
# SDK libs are in: ~/.platformio/packages/framework-arduinoespressif8266/tools/sdk/lib/
if "xtensa-lx106" in str(cc_path):
platformio_dir = cc_path.parent.parent.parent
esp8266_sdk = (
platformio_dir
/ "framework-arduinoespressif8266"
/ "tools"
/ "sdk"
/ "lib"
)
if esp8266_sdk.exists():
sdk_dirs.append(esp8266_sdk)
# Also check for NONOSDK subdirectories (closed-source libs)
sdk_dirs.extend(
subdir
for subdir in esp8266_sdk.iterdir()
if subdir.is_dir() and subdir.name.startswith("NONOSDK")
)
# For ESP32 IDF framework
# CC is like: ~/.platformio/packages/toolchain-xtensa-esp-elf/bin/xtensa-esp32-elf-gcc
# or: ~/.platformio/packages/toolchain-riscv32-esp/bin/riscv32-esp-elf-gcc
elif "xtensa-esp" in str(cc_path) or "riscv32-esp" in str(cc_path):
# Detect ESP32 variant from CC path or defines
variant = self._detect_esp32_variant()
if variant:
platformio_dir = cc_path.parent.parent.parent
espidf_dir = platformio_dir / "framework-espidf" / "components"
if espidf_dir.exists():
# Find all directories named after the variant that contain .a files
# This handles various ESP-IDF library layouts:
# - components/*/lib/<variant>/
# - components/*/<variant>/
# - components/*/lib/lib/<variant>/
# - components/*/*/lib_*/<variant>/
sdk_dirs.extend(
variant_dir
for variant_dir in espidf_dir.rglob(variant)
if variant_dir.is_dir() and any(variant_dir.glob("*.a"))
)
return sdk_dirs
def _detect_esp32_variant(self) -> str | None:
"""Detect ESP32 variant from idedata defines.
Returns:
Variant string like 'esp32', 'esp32s2', 'esp32c3', etc. or None.
"""
if self._idedata is None:
return None
defines = getattr(self._idedata, "defines", [])
if not defines:
return None
# ESPHome always adds USE_ESP32_VARIANT_xxx defines
variant_prefix = "USE_ESP32_VARIANT_"
for define in defines:
if define.startswith(variant_prefix):
# Extract variant name and convert to lowercase
# USE_ESP32_VARIANT_ESP32 -> esp32
# USE_ESP32_VARIANT_ESP32S3 -> esp32s3
return define[len(variant_prefix) :].lower()
return None
def _parse_sdk_library(
self, lib_path: Path
) -> tuple[list[tuple[str, int, str, bool]], set[str]]:
"""Parse a single SDK library for symbols.
Args:
lib_path: Path to the .a library file
Returns:
Tuple of:
- List of BSS/DATA symbols: (symbol_name, size, section, is_local)
- Set of global BSS/DATA symbol names (for checking if RAM is linked)
"""
ram_symbols: list[tuple[str, int, str, bool]] = []
global_ram_symbols: set[str] = set()
result = run_tool([self.nm_path, "--size-sort", str(lib_path)], timeout=10)
if result is None:
return ram_symbols, global_ram_symbols
for line in result.stdout.splitlines():
parts = line.split()
if len(parts) < 3:
continue
try:
size = int(parts[0], 16)
sym_type = parts[1]
name = parts[2]
# Only collect BSS (b/B) and DATA (d/D) for RAM analysis
if sym_type in ("b", "B"):
section = ".bss"
is_local = sym_type == "b"
ram_symbols.append((name, size, section, is_local))
# Track global RAM symbols (B/D) for linking check
if sym_type == "B":
global_ram_symbols.add(name)
elif sym_type in ("d", "D"):
section = ".data"
is_local = sym_type == "d"
ram_symbols.append((name, size, section, is_local))
if sym_type == "D":
global_ram_symbols.add(name)
except (ValueError, IndexError):
continue
return ram_symbols, global_ram_symbols
def _analyze_sdk_libraries(self) -> None:
"""Analyze SDK libraries to find symbols not in the ELF.
This finds static/local symbols from closed-source SDK libraries
that consume RAM but don't appear in the final ELF symbol table.
Only includes symbols from libraries that have RAM actually linked
(at least one global BSS/DATA symbol in the ELF).
"""
sdk_dirs = self._find_sdk_library_dirs()
if not sdk_dirs:
_LOGGER.debug("No SDK library directories found")
return
_LOGGER.debug("Analyzing SDK libraries in %d directories", len(sdk_dirs))
# Track seen symbols to avoid duplicates from multiple SDK versions
seen_symbols: set[str] = set()
for sdk_dir in sdk_dirs:
for lib_path in sorted(sdk_dir.glob("*.a")):
lib_name = lib_path.name
ram_symbols, global_ram_symbols = self._parse_sdk_library(lib_path)
# Check if this library's RAM is actually linked by seeing if any
# of its global BSS/DATA symbols appear in the ELF
if not global_ram_symbols & self._elf_symbol_names:
# No RAM from this library is in the ELF - skip it
continue
for name, size, section, is_local in ram_symbols:
# Skip if already in ELF or already seen from another lib
if name in self._elf_symbol_names or name in seen_symbols:
continue
# Only track symbols with non-zero size
if size > 0:
self._sdk_symbols.append(
SDKSymbol(
name=name,
size=size,
library=lib_name,
section=section,
is_local=is_local,
)
)
seen_symbols.add(name)
# Demangle SDK symbols for better readability
if self._sdk_symbols:
sdk_names = [sym.name for sym in self._sdk_symbols]
demangled_map = batch_demangle(sdk_names, objdump_path=self.objdump_path)
for sym in self._sdk_symbols:
sym.demangled = demangled_map.get(sym.name, sym.name)
# Sort by size descending for reporting
self._sdk_symbols.sort(key=lambda s: s.size, reverse=True)
total_sdk_ram = sum(s.size for s in self._sdk_symbols)
_LOGGER.debug(
"Found %d SDK symbols not in ELF, totaling %d bytes",
len(self._sdk_symbols),
total_sdk_ram,
)
def get_sdk_ram_symbols(self) -> list[SDKSymbol]:
"""Get SDK symbols that consume RAM but aren't in the ELF symbol table.
Returns:
List of SDKSymbol objects sorted by size descending.
"""
return self._sdk_symbols
def get_sdk_ram_by_library(self) -> dict[str, list[SDKSymbol]]:
"""Get SDK RAM symbols grouped by library.
Returns:
Dictionary mapping library name to list of symbols.
"""
by_lib: dict[str, list[SDKSymbol]] = defaultdict(list)
for sym in self._sdk_symbols:
by_lib[sym.library].append(sym)
return dict(by_lib)
if __name__ == "__main__":
from .cli import main

View File

@@ -1,17 +1,25 @@
"""CLI interface for memory analysis with report generation."""
from __future__ import annotations
from collections import defaultdict
from collections.abc import Callable
import json
import sys
from typing import TYPE_CHECKING
from . import (
_COMPONENT_API,
_COMPONENT_CORE,
_COMPONENT_PREFIX_ESPHOME,
_COMPONENT_PREFIX_EXTERNAL,
RAM_SECTIONS,
MemoryAnalyzer,
)
if TYPE_CHECKING:
from . import ComponentMemory
class MemoryAnalyzerCLI(MemoryAnalyzer):
"""Memory analyzer with CLI-specific report generation."""
@@ -20,6 +28,8 @@ class MemoryAnalyzerCLI(MemoryAnalyzer):
SYMBOL_SIZE_THRESHOLD: int = (
100 # Show symbols larger than this in detailed analysis
)
# Lower threshold for RAM symbols (RAM is more constrained)
RAM_SYMBOL_SIZE_THRESHOLD: int = 24
# Column width constants
COL_COMPONENT: int = 29
@@ -84,6 +94,60 @@ class MemoryAnalyzerCLI(MemoryAnalyzer):
COL_CORE_PERCENT,
)
def _add_section_header(self, lines: list[str], title: str) -> None:
"""Add a section header with title centered between separator lines."""
lines.append("")
lines.append("=" * self.TABLE_WIDTH)
lines.append(title.center(self.TABLE_WIDTH))
lines.append("=" * self.TABLE_WIDTH)
lines.append("")
def _add_top_consumers(
self,
lines: list[str],
title: str,
components: list[tuple[str, ComponentMemory]],
get_size: Callable[[ComponentMemory], int],
total: int,
memory_type: str,
limit: int = 25,
) -> None:
"""Add a formatted list of top memory consumers to the report.
Args:
lines: List of report lines to append the output to.
title: Section title to print before the list.
components: Sequence of (name, ComponentMemory) tuples to analyze.
get_size: Callable that takes a ComponentMemory and returns the
size in bytes to use for ranking and display.
total: Total size in bytes for computing percentage usage.
memory_type: Label for the memory region (e.g., "flash" or "RAM").
limit: Maximum number of components to include in the list.
"""
lines.append("")
lines.append(f"{title}:")
for i, (name, mem) in enumerate(components[:limit]):
size = get_size(mem)
if size > 0:
percentage = (size / total * 100) if total > 0 else 0
lines.append(
f"{i + 1}. {name} ({size:,} B) - {percentage:.1f}% of analyzed {memory_type}"
)
def _format_symbol_with_section(
self, demangled: str, size: int, section: str | None = None
) -> str:
"""Format a symbol entry, optionally adding a RAM section label.
If section is one of the RAM sections (.data or .bss), a label like
" [data]" or " [bss]" is appended. For non-RAM sections or when
section is None, no section label is added.
"""
section_label = ""
if section in RAM_SECTIONS:
section_label = f" [{section[1:]}]" # .data -> [data], .bss -> [bss]
return f"{demangled} ({size:,} B){section_label}"
def generate_report(self, detailed: bool = False) -> str:
"""Generate a formatted memory report."""
components = sorted(
@@ -124,43 +188,70 @@ class MemoryAnalyzerCLI(MemoryAnalyzer):
f"{total_flash:>{self.COL_TOTAL_FLASH - 2},} B | {total_ram:>{self.COL_TOTAL_RAM - 2},} B"
)
# Top consumers
lines.append("")
lines.append("Top Flash Consumers:")
for i, (name, mem) in enumerate(components[:25]):
if mem.flash_total > 0:
percentage = (
(mem.flash_total / total_flash * 100) if total_flash > 0 else 0
)
lines.append(
f"{i + 1}. {name} ({mem.flash_total:,} B) - {percentage:.1f}% of analyzed flash"
)
lines.append("")
lines.append("Top RAM Consumers:")
ram_components = sorted(components, key=lambda x: x[1].ram_total, reverse=True)
for i, (name, mem) in enumerate(ram_components[:25]):
if mem.ram_total > 0:
percentage = (mem.ram_total / total_ram * 100) if total_ram > 0 else 0
lines.append(
f"{i + 1}. {name} ({mem.ram_total:,} B) - {percentage:.1f}% of analyzed RAM"
)
lines.append("")
lines.append(
"Note: This analysis covers symbols in the ELF file. Some runtime allocations may not be included."
# Show unattributed RAM (SDK/framework overhead)
unattributed_bss, unattributed_data, unattributed_total = (
self.get_unattributed_ram()
)
if unattributed_total > 0:
lines.append("")
lines.append(
f"Unattributed RAM: {unattributed_total:,} B (SDK/framework overhead)"
)
if unattributed_bss > 0 and unattributed_data > 0:
lines.append(
f" .bss: {unattributed_bss:,} B | .data: {unattributed_data:,} B"
)
# Show SDK symbol breakdown if available
sdk_by_lib = self.get_sdk_ram_by_library()
if sdk_by_lib:
lines.append("")
lines.append("SDK library breakdown (static symbols not in ELF):")
# Sort libraries by total size
lib_totals = [
(lib, sum(s.size for s in syms), syms)
for lib, syms in sdk_by_lib.items()
]
lib_totals.sort(key=lambda x: x[1], reverse=True)
for lib_name, lib_total, syms in lib_totals:
if lib_total == 0:
continue
lines.append(f" {lib_name}: {lib_total:,} B")
# Show top symbols from this library
for sym in sorted(syms, key=lambda s: s.size, reverse=True)[:3]:
section_label = sym.section.lstrip(".")
# Use demangled name (falls back to original if not demangled)
display_name = sym.demangled or sym.name
if len(display_name) > 50:
display_name = f"{display_name[:47]}..."
lines.append(
f" {sym.size:>6,} B [{section_label}] {display_name}"
)
# Top consumers
self._add_top_consumers(
lines,
"Top Flash Consumers",
components,
lambda m: m.flash_total,
total_flash,
"flash",
)
ram_components = sorted(components, key=lambda x: x[1].ram_total, reverse=True)
self._add_top_consumers(
lines,
"Top RAM Consumers",
ram_components,
lambda m: m.ram_total,
total_ram,
"RAM",
)
lines.append("=" * self.TABLE_WIDTH)
# Add ESPHome core detailed analysis if there are core symbols
if self._esphome_core_symbols:
lines.append("")
lines.append("=" * self.TABLE_WIDTH)
lines.append(
f"{_COMPONENT_CORE} Detailed Analysis".center(self.TABLE_WIDTH)
)
lines.append("=" * self.TABLE_WIDTH)
lines.append("")
self._add_section_header(lines, f"{_COMPONENT_CORE} Detailed Analysis")
# Group core symbols by subcategory
core_subcategories: dict[str, list[tuple[str, str, int]]] = defaultdict(
@@ -212,7 +303,11 @@ class MemoryAnalyzerCLI(MemoryAnalyzer):
f"{_COMPONENT_CORE} Symbols > {self.SYMBOL_SIZE_THRESHOLD} B ({len(large_core_symbols)} symbols):"
)
for i, (symbol, demangled, size) in enumerate(large_core_symbols):
lines.append(f"{i + 1}. {demangled} ({size:,} B)")
# Core symbols only track (symbol, demangled, size) without section info,
# so we don't show section labels here
lines.append(
f"{i + 1}. {self._format_symbol_with_section(demangled, size)}"
)
lines.append("=" * self.TABLE_WIDTH)
@@ -268,11 +363,7 @@ class MemoryAnalyzerCLI(MemoryAnalyzer):
for comp_name, comp_mem in components_to_analyze:
if not (comp_symbols := self._component_symbols.get(comp_name, [])):
continue
lines.append("")
lines.append("=" * self.TABLE_WIDTH)
lines.append(f"{comp_name} Detailed Analysis".center(self.TABLE_WIDTH))
lines.append("=" * self.TABLE_WIDTH)
lines.append("")
self._add_section_header(lines, f"{comp_name} Detailed Analysis")
# Sort symbols by size
sorted_symbols = sorted(comp_symbols, key=lambda x: x[2], reverse=True)
@@ -283,19 +374,69 @@ class MemoryAnalyzerCLI(MemoryAnalyzer):
# Show all symbols above threshold for better visibility
large_symbols = [
(sym, dem, size)
for sym, dem, size in sorted_symbols
(sym, dem, size, sec)
for sym, dem, size, sec in sorted_symbols
if size > self.SYMBOL_SIZE_THRESHOLD
]
lines.append(
f"{comp_name} Symbols > {self.SYMBOL_SIZE_THRESHOLD} B ({len(large_symbols)} symbols):"
)
for i, (symbol, demangled, size) in enumerate(large_symbols):
lines.append(f"{i + 1}. {demangled} ({size:,} B)")
for i, (symbol, demangled, size, section) in enumerate(large_symbols):
lines.append(
f"{i + 1}. {self._format_symbol_with_section(demangled, size, section)}"
)
lines.append("=" * self.TABLE_WIDTH)
# Detailed RAM analysis by component (at end, before RAM strings analysis)
self._add_section_header(lines, "RAM Symbol Analysis by Component")
# Show top 15 RAM consumers with their large symbols
for name, mem in ram_components[:15]:
if mem.ram_total == 0:
continue
ram_syms = self._ram_symbols.get(name, [])
if not ram_syms:
continue
# Sort by size descending
sorted_ram_syms = sorted(ram_syms, key=lambda x: x[2], reverse=True)
large_ram_syms = [
s for s in sorted_ram_syms if s[2] > self.RAM_SYMBOL_SIZE_THRESHOLD
]
lines.append(f"{name} ({mem.ram_total:,} B total RAM):")
# Show breakdown by section type
data_size = sum(s[2] for s in ram_syms if s[3] == ".data")
bss_size = sum(s[2] for s in ram_syms if s[3] == ".bss")
lines.append(f" .data (initialized): {data_size:,} B")
lines.append(f" .bss (uninitialized): {bss_size:,} B")
if large_ram_syms:
lines.append(
f" Symbols > {self.RAM_SYMBOL_SIZE_THRESHOLD} B ({len(large_ram_syms)}):"
)
for symbol, demangled, size, section in large_ram_syms[:10]:
# Format section label consistently by stripping leading dot
section_label = section.lstrip(".") if section else ""
# Add ellipsis if name is truncated
demangled_display = (
f"{demangled[:70]}..." if len(demangled) > 70 else demangled
)
lines.append(
f" {size:>6,} B [{section_label}] {demangled_display}"
)
if len(large_ram_syms) > 10:
lines.append(f" ... and {len(large_ram_syms) - 10} more")
lines.append("")
lines.append(
"Note: This analysis covers symbols in the ELF file. Some runtime allocations may not be included."
)
lines.append("=" * self.TABLE_WIDTH)
return "\n".join(lines)
def to_json(self) -> str:

View File

@@ -7,11 +7,13 @@ ESPHOME_COMPONENT_PATTERN = re.compile(r"esphome::([a-zA-Z0-9_]+)::")
# Section mapping for ELF file sections
# Maps standard section names to their various platform-specific variants
# Note: Order matters! More specific patterns (.bss) must come before general ones (.dram)
# because ESP-IDF uses names like ".dram0.bss" which would match ".dram" otherwise
SECTION_MAPPING = {
".text": frozenset([".text", ".iram"]),
".rodata": frozenset([".rodata"]),
".bss": frozenset([".bss"]), # Must be before .data to catch ".dram0.bss"
".data": frozenset([".data", ".dram"]),
".bss": frozenset([".bss"]),
}
# Section to ComponentMemory attribute mapping
@@ -88,6 +90,77 @@ SYMBOL_PATTERNS = {
"sys_mbox_new",
"sys_arch_mbox_tryfetch",
],
# LibreTiny/Beken BK7231 radio calibration
"bk_radio_cal": [
"bk7011_",
"calibration_main",
"gcali_",
"rwnx_cal",
],
# LibreTiny/Beken WiFi MAC layer
"bk_wifi_mac": [
"rxu_", # RX upper layer
"txu_", # TX upper layer
"txl_", # TX lower layer
"rxl_", # RX lower layer
"scanu_", # Scan unit
"mm_hw_", # MAC management hardware
"mm_bcn", # MAC management beacon
"mm_tim", # MAC management TIM
"mm_check", # MAC management checks
"sm_connect", # Station management
"me_beacon", # Management entity beacon
"me_build", # Management entity build
"hapd_", # Host AP daemon
"chan_pre_", # Channel management
"handle_probe_", # Probe handling
],
# LibreTiny/Beken system control
"bk_system": [
"sctrl_", # System control
"icu_ctrl", # Interrupt control unit
"gdma_ctrl", # DMA control
"mpb_ctrl", # MPB control
"uf2_", # UF2 OTA
"bkreg_", # Beken registers
],
# LibreTiny/Beken BLE stack
"bk_ble": [
"gapc_", # GAP client
"gattc_", # GATT client
"attc_", # ATT client
"attmdb_", # ATT database
"atts_", # ATT server
"l2cc_", # L2CAP
"prf_env", # Profile environment
],
# LibreTiny/Beken scheduler
"bk_scheduler": [
"sch_plan_", # Scheduler plan
"sch_prog_", # Scheduler program
"sch_arb_", # Scheduler arbiter
],
# LibreTiny/Beken DMA descriptors
"bk_dma": [
"rx_payload_desc",
"rx_dma_hdrdesc",
"tx_hw_desc",
"host_event_data",
"host_cmd_data",
],
# ARM EABI compiler runtime (LibreTiny uses ARM Cortex-M)
"arm_runtime": [
"__aeabi_",
"__adddf3",
"__subdf3",
"__muldf3",
"__divdf3",
"__addsf3",
"__subsf3",
"__mulsf3",
"__divsf3",
"__gnu_unwind",
],
"xtensa": ["xt_", "_xt_", "xPortEnterCriticalTimeout"],
"heap": ["heap_", "multi_heap"],
"spi_flash": ["spi_flash"],
@@ -782,7 +855,22 @@ SYMBOL_PATTERNS = {
"math_internal": ["__mdiff", "__lshift", "__mprec_tens", "quorem"],
"character_class": ["__chclass"],
"camellia": ["camellia_", "camellia_feistel"],
"crypto_tables": ["FSb", "FSb2", "FSb3", "FSb4"],
"crypto_tables": [
"FSb",
"FSb2",
"FSb3",
"FSb4",
"Te0", # AES encryption table
"Td0", # AES decryption table
"crc32_table", # CRC32 lookup table
"crc_tab", # CRC lookup table
],
"crypto_hash": [
"SHA1Transform", # SHA1 hash function
"MD5Transform", # MD5 hash function
"SHA256",
"SHA512",
],
"event_buffer": ["g_eb_list_desc", "eb_space"],
"base_node": ["base_node_", "base_node_add_handler"],
"file_descriptor": ["s_fd_table"],

View File

@@ -5,6 +5,10 @@ from __future__ import annotations
import logging
from pathlib import Path
import subprocess
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from collections.abc import Sequence
_LOGGER = logging.getLogger(__name__)
@@ -55,3 +59,35 @@ def find_tool(
_LOGGER.warning("Could not find %s tool", tool_name)
return None
def run_tool(
cmd: Sequence[str],
timeout: int = 30,
) -> subprocess.CompletedProcess[str] | None:
"""Run a toolchain command and return the result.
Args:
cmd: Command and arguments to run
timeout: Timeout in seconds
Returns:
CompletedProcess on success, None on failure
"""
try:
return subprocess.run(
cmd,
capture_output=True,
text=True,
timeout=timeout,
check=False,
)
except subprocess.TimeoutExpired:
_LOGGER.warning("Command timed out: %s", " ".join(cmd))
return None
except FileNotFoundError:
_LOGGER.warning("Command not found: %s", cmd[0])
return None
except OSError as e:
_LOGGER.warning("Failed to run command %s: %s", cmd[0], e)
return None

View File

@@ -30,7 +30,9 @@ void A01nyubComponent::check_buffer_() {
ESP_LOGV(TAG, "Distance from sensor: %f mm, %f m", distance, meters);
this->publish_state(meters);
} else {
ESP_LOGW(TAG, "Invalid data read from sensor: %s", format_hex_pretty(this->buffer_).c_str());
char hex_buf[format_hex_pretty_size(4)];
ESP_LOGW(TAG, "Invalid data read from sensor: %s",
format_hex_pretty_to(hex_buf, this->buffer_.data(), this->buffer_.size()));
}
} else {
ESP_LOGW(TAG, "checksum failed: %02x != %02x", checksum, this->buffer_[3]);

View File

@@ -29,7 +29,9 @@ void A02yyuwComponent::check_buffer_() {
ESP_LOGV(TAG, "Distance from sensor: %f mm", distance);
this->publish_state(distance);
} else {
ESP_LOGW(TAG, "Invalid data read from sensor: %s", format_hex_pretty(this->buffer_).c_str());
char hex_buf[format_hex_pretty_size(4)];
ESP_LOGW(TAG, "Invalid data read from sensor: %s",
format_hex_pretty_to(hex_buf, this->buffer_.data(), this->buffer_.size()));
}
} else {
ESP_LOGW(TAG, "checksum failed: %02x != %02x", checksum, this->buffer_[3]);

View File

@@ -90,13 +90,16 @@ void AbsoluteHumidityComponent::loop() {
this->status_set_error(LOG_STR("Invalid saturation vapor pressure equation selection!"));
return;
}
ESP_LOGD(TAG, "Saturation vapor pressure %f kPa", es);
// Calculate absolute humidity
const float absolute_humidity = vapor_density(es, hr, temperature_k);
ESP_LOGD(TAG,
"Saturation vapor pressure %f kPa\n"
"Publishing absolute humidity %f g/m³",
es, absolute_humidity);
// Publish absolute humidity
ESP_LOGD(TAG, "Publishing absolute humidity %f g/m³", absolute_humidity);
this->status_clear_warning();
this->publish_state(absolute_humidity);
}

View File

@@ -1,5 +1,3 @@
#ifdef USE_ARDUINO
#include "ac_dimmer.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
@@ -9,12 +7,12 @@
#ifdef USE_ESP8266
#include <core_esp8266_waveform.h>
#endif
#ifdef USE_ESP32_FRAMEWORK_ARDUINO
#include <esp32-hal-timer.h>
#ifdef USE_ESP32
#include "hw_timer_esp_idf.h"
#endif
namespace esphome {
namespace ac_dimmer {
namespace esphome::ac_dimmer {
static const char *const TAG = "ac_dimmer";
@@ -27,7 +25,14 @@ static AcDimmerDataStore *all_dimmers[32]; // NOLINT(cppcoreguidelines-avoid-no
/// However other factors like gate driver propagation time
/// are also considered and a really low value is not important
/// See also: https://github.com/esphome/issues/issues/1632
static const uint32_t GATE_ENABLE_TIME = 50;
static constexpr uint32_t GATE_ENABLE_TIME = 50;
#ifdef USE_ESP32
/// Timer frequency in Hz (1 MHz = 1µs resolution)
static constexpr uint32_t TIMER_FREQUENCY_HZ = 1000000;
/// Timer interrupt interval in microseconds
static constexpr uint64_t TIMER_INTERVAL_US = 50;
#endif
/// Function called from timer interrupt
/// Input is current time in microseconds (micros())
@@ -154,7 +159,7 @@ void IRAM_ATTR HOT AcDimmerDataStore::s_gpio_intr(AcDimmerDataStore *store) {
#ifdef USE_ESP32
// ESP32 implementation, uses basically the same code but needs to wrap
// timer_interrupt() function to auto-reschedule
static hw_timer_t *dimmer_timer = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
static HWTimer *dimmer_timer = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
void IRAM_ATTR HOT AcDimmerDataStore::s_timer_intr() { timer_interrupt(); }
#endif
@@ -194,15 +199,15 @@ void AcDimmer::setup() {
setTimer1Callback(&timer_interrupt);
#endif
#ifdef USE_ESP32
// timer frequency of 1mhz
dimmer_timer = timerBegin(1000000);
timerAttachInterrupt(dimmer_timer, &AcDimmerDataStore::s_timer_intr);
dimmer_timer = timer_begin(TIMER_FREQUENCY_HZ);
timer_attach_interrupt(dimmer_timer, &AcDimmerDataStore::s_timer_intr);
// For ESP32, we can't use dynamic interval calculation because the timerX functions
// are not callable from ISR (placed in flash storage).
// Here we just use an interrupt firing every 50 µs.
timerAlarm(dimmer_timer, 50, true, 0);
timer_alarm(dimmer_timer, TIMER_INTERVAL_US, true, 0);
#endif
}
void AcDimmer::write_state(float state) {
state = std::acos(1 - (2 * state)) / std::numbers::pi; // RMS power compensation
auto new_value = static_cast<uint16_t>(roundf(state * 65535));
@@ -210,14 +215,15 @@ void AcDimmer::write_state(float state) {
this->store_.init_cycle = this->init_with_half_cycle_;
this->store_.value = new_value;
}
void AcDimmer::dump_config() {
ESP_LOGCONFIG(TAG, "AcDimmer:");
LOG_PIN(" Output Pin: ", this->gate_pin_);
LOG_PIN(" Zero-Cross Pin: ", this->zero_cross_pin_);
ESP_LOGCONFIG(TAG,
"AcDimmer:\n"
" Min Power: %.1f%%\n"
" Init with half cycle: %s",
this->store_.min_power / 10.0f, YESNO(this->init_with_half_cycle_));
LOG_PIN(" Output Pin: ", this->gate_pin_);
LOG_PIN(" Zero-Cross Pin: ", this->zero_cross_pin_);
if (method_ == DIM_METHOD_LEADING_PULSE) {
ESP_LOGCONFIG(TAG, " Method: leading pulse");
} else if (method_ == DIM_METHOD_LEADING) {
@@ -230,7 +236,4 @@ void AcDimmer::dump_config() {
ESP_LOGV(TAG, " Estimated Frequency: %.3fHz", 1e6f / this->store_.cycle_time_us / 2);
}
} // namespace ac_dimmer
} // namespace esphome
#endif // USE_ARDUINO
} // namespace esphome::ac_dimmer

View File

@@ -1,13 +1,10 @@
#pragma once
#ifdef USE_ARDUINO
#include "esphome/core/component.h"
#include "esphome/core/hal.h"
#include "esphome/components/output/float_output.h"
namespace esphome {
namespace ac_dimmer {
namespace esphome::ac_dimmer {
enum DimMethod { DIM_METHOD_LEADING_PULSE = 0, DIM_METHOD_LEADING, DIM_METHOD_TRAILING };
@@ -64,7 +61,4 @@ class AcDimmer : public output::FloatOutput, public Component {
DimMethod method_;
};
} // namespace ac_dimmer
} // namespace esphome
#endif // USE_ARDUINO
} // namespace esphome::ac_dimmer

View File

@@ -0,0 +1,152 @@
#ifdef USE_ESP32
#include "hw_timer_esp_idf.h"
#include "freertos/FreeRTOS.h"
#include "esphome/core/log.h"
#include "driver/gptimer.h"
#include "esp_clk_tree.h"
#include "soc/clk_tree_defs.h"
static const char *const TAG = "hw_timer_esp_idf";
namespace esphome::ac_dimmer {
// GPTimer divider constraints from ESP-IDF documentation
static constexpr uint32_t GPTIMER_DIVIDER_MIN = 2;
static constexpr uint32_t GPTIMER_DIVIDER_MAX = 65536;
using voidFuncPtr = void (*)();
using voidFuncPtrArg = void (*)(void *);
struct InterruptConfigT {
voidFuncPtr fn{nullptr};
void *arg{nullptr};
};
struct HWTimer {
gptimer_handle_t timer_handle{nullptr};
InterruptConfigT interrupt_handle{};
bool timer_started{false};
};
HWTimer *timer_begin(uint32_t frequency) {
esp_err_t err = ESP_OK;
uint32_t counter_src_hz = 0;
uint32_t divider = 0;
soc_module_clk_t clk;
for (auto clk_candidate : SOC_GPTIMER_CLKS) {
clk = clk_candidate;
esp_clk_tree_src_get_freq_hz(clk, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &counter_src_hz);
divider = counter_src_hz / frequency;
if ((divider >= GPTIMER_DIVIDER_MIN) && (divider <= GPTIMER_DIVIDER_MAX)) {
break;
} else {
divider = 0;
}
}
if (divider == 0) {
ESP_LOGE(TAG, "Resolution not possible; aborting");
return nullptr;
}
gptimer_config_t config = {
.clk_src = static_cast<gptimer_clock_source_t>(clk),
.direction = GPTIMER_COUNT_UP,
.resolution_hz = frequency,
.flags = {.intr_shared = true},
};
HWTimer *timer = new HWTimer();
err = gptimer_new_timer(&config, &timer->timer_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "GPTimer creation failed; error %d", err);
delete timer;
return nullptr;
}
err = gptimer_enable(timer->timer_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "GPTimer enable failed; error %d", err);
gptimer_del_timer(timer->timer_handle);
delete timer;
return nullptr;
}
err = gptimer_start(timer->timer_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "GPTimer start failed; error %d", err);
gptimer_disable(timer->timer_handle);
gptimer_del_timer(timer->timer_handle);
delete timer;
return nullptr;
}
timer->timer_started = true;
return timer;
}
bool IRAM_ATTR timer_fn_wrapper(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *args) {
auto *isr = static_cast<InterruptConfigT *>(args);
if (isr->fn) {
if (isr->arg) {
reinterpret_cast<voidFuncPtrArg>(isr->fn)(isr->arg);
} else {
isr->fn();
}
}
// Return false to indicate that no higher-priority task was woken and no context switch is requested.
return false;
}
static void timer_attach_interrupt_functional_arg(HWTimer *timer, void (*user_func)(void *), void *arg) {
if (timer == nullptr) {
ESP_LOGE(TAG, "Timer handle is nullptr");
return;
}
gptimer_event_callbacks_t cbs = {
.on_alarm = timer_fn_wrapper,
};
timer->interrupt_handle.fn = reinterpret_cast<voidFuncPtr>(user_func);
timer->interrupt_handle.arg = arg;
if (timer->timer_started) {
gptimer_stop(timer->timer_handle);
}
gptimer_disable(timer->timer_handle);
esp_err_t err = gptimer_register_event_callbacks(timer->timer_handle, &cbs, &timer->interrupt_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Timer Attach Interrupt failed; error %d", err);
}
gptimer_enable(timer->timer_handle);
if (timer->timer_started) {
gptimer_start(timer->timer_handle);
}
}
void timer_attach_interrupt(HWTimer *timer, voidFuncPtr user_func) {
timer_attach_interrupt_functional_arg(timer, reinterpret_cast<voidFuncPtrArg>(user_func), nullptr);
}
void timer_alarm(HWTimer *timer, uint64_t alarm_value, bool autoreload, uint64_t reload_count) {
if (timer == nullptr) {
ESP_LOGE(TAG, "Timer handle is nullptr");
return;
}
gptimer_alarm_config_t alarm_cfg = {
.alarm_count = alarm_value,
.reload_count = reload_count,
.flags = {.auto_reload_on_alarm = autoreload},
};
esp_err_t err = gptimer_set_alarm_action(timer->timer_handle, &alarm_cfg);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Timer Alarm Write failed; error %d", err);
}
}
} // namespace esphome::ac_dimmer
#endif

View File

@@ -0,0 +1,17 @@
#pragma once
#ifdef USE_ESP32
#include "driver/gptimer_types.h"
namespace esphome::ac_dimmer {
struct HWTimer;
HWTimer *timer_begin(uint32_t frequency);
void timer_attach_interrupt(HWTimer *timer, void (*user_func)());
void timer_alarm(HWTimer *timer, uint64_t alarm_value, bool autoreload, uint64_t reload_count);
} // namespace esphome::ac_dimmer
#endif

View File

@@ -3,6 +3,7 @@ import esphome.codegen as cg
from esphome.components import output
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_METHOD, CONF_MIN_POWER
from esphome.core import CORE
CODEOWNERS = ["@glmnet"]
@@ -31,11 +32,16 @@ CONFIG_SCHEMA = cv.All(
),
}
).extend(cv.COMPONENT_SCHEMA),
cv.only_with_arduino,
)
async def to_code(config):
if CORE.is_esp8266:
# ac_dimmer uses setTimer1Callback which requires the waveform generator
from esphome.components.esp8266.const import require_waveform
require_waveform()
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)

View File

@@ -121,23 +121,21 @@ void ADCSensor::setup() {
void ADCSensor::dump_config() {
LOG_SENSOR("", "ADC Sensor", this);
LOG_PIN(" Pin: ", this->pin_);
ESP_LOGCONFIG(TAG,
" Channel: %d\n"
" Unit: %s\n"
" Attenuation: %s\n"
" Samples: %i\n"
" Sampling mode: %s",
this->channel_, LOG_STR_ARG(adc_unit_to_str(this->adc_unit_)),
this->autorange_ ? "Auto" : LOG_STR_ARG(attenuation_to_str(this->attenuation_)), this->sample_count_,
LOG_STR_ARG(sampling_mode_to_str(this->sampling_mode_)));
ESP_LOGCONFIG(
TAG,
" Channel: %d\n"
" Unit: %s\n"
" Attenuation: %s\n"
" Samples: %i\n"
" Sampling mode: %s\n"
" Setup Status:\n"
" Handle Init: %s\n"
" Config: %s\n"
" Calibration: %s\n"
" Overall Init: %s",
this->channel_, LOG_STR_ARG(adc_unit_to_str(this->adc_unit_)),
this->autorange_ ? "Auto" : LOG_STR_ARG(attenuation_to_str(this->attenuation_)), this->sample_count_,
LOG_STR_ARG(sampling_mode_to_str(this->sampling_mode_)),
this->setup_flags_.handle_init_complete ? "OK" : "FAILED", this->setup_flags_.config_complete ? "OK" : "FAILED",
this->setup_flags_.calibration_complete ? "OK" : "FAILED", this->setup_flags_.init_complete ? "OK" : "FAILED");

View File

@@ -25,11 +25,13 @@ class AddressableLightDisplay : public display::DisplayBuffer {
if (enabled_ && !enabled) { // enabled -> disabled
// - Tell the parent light to refresh, effectively wiping the display. Also
// restores the previous effect (if any).
light_state_->make_call().set_effect(this->last_effect_).perform();
if (this->last_effect_index_.has_value()) {
light_state_->make_call().set_effect(*this->last_effect_index_).perform();
}
} else if (!enabled_ && enabled) { // disabled -> enabled
// - Save the current effect.
this->last_effect_ = light_state_->get_effect_name();
// - Save the current effect index.
this->last_effect_index_ = light_state_->get_current_effect_index();
// - Disable any current effect.
light_state_->make_call().set_effect(0).perform();
}
@@ -56,7 +58,7 @@ class AddressableLightDisplay : public display::DisplayBuffer {
int32_t width_;
int32_t height_;
std::vector<Color> addressable_light_buffer_;
optional<std::string> last_effect_;
optional<uint32_t> last_effect_index_;
optional<std::function<int(int, int)>> pixel_mapper_f_;
};
} // namespace addressable_light

View File

@@ -162,11 +162,13 @@ void ADE7880::update() {
}
void ADE7880::dump_config() {
ESP_LOGCONFIG(TAG, "ADE7880:");
ESP_LOGCONFIG(TAG,
"ADE7880:\n"
" Frequency: %.0f Hz",
this->frequency_);
LOG_PIN(" IRQ0 Pin: ", this->irq0_pin_);
LOG_PIN(" IRQ1 Pin: ", this->irq1_pin_);
LOG_PIN(" RESET Pin: ", this->reset_pin_);
ESP_LOGCONFIG(TAG, " Frequency: %.0f Hz", this->frequency_);
if (this->channel_a_ != nullptr) {
ESP_LOGCONFIG(TAG, " Phase A:");

View File

@@ -227,7 +227,7 @@ CONFIG_SCHEMA = cv.All(
{
cv.GenerateID(): cv.declare_id(ADE7880),
cv.Optional(CONF_FREQUENCY, default="50Hz"): cv.All(
cv.frequency, cv.Range(min=45.0, max=66.0)
cv.frequency, cv.float_range(min=45.0, max=66.0)
),
cv.Optional(CONF_IRQ0_PIN): pins.internal_gpio_input_pin_schema,
cv.Required(CONF_IRQ1_PIN): pins.internal_gpio_input_pin_schema,

View File

@@ -21,10 +21,12 @@ void ADS1115Sensor::update() {
void ADS1115Sensor::dump_config() {
LOG_SENSOR(" ", "ADS1115 Sensor", this);
ESP_LOGCONFIG(TAG, " Multiplexer: %u", this->multiplexer_);
ESP_LOGCONFIG(TAG, " Gain: %u", this->gain_);
ESP_LOGCONFIG(TAG, " Resolution: %u", this->resolution_);
ESP_LOGCONFIG(TAG, " Sample rate: %u", this->samplerate_);
ESP_LOGCONFIG(TAG,
" Multiplexer: %u\n"
" Gain: %u\n"
" Resolution: %u\n"
" Sample rate: %u",
this->multiplexer_, this->gain_, this->resolution_, this->samplerate_);
}
} // namespace ads1115

View File

@@ -9,8 +9,10 @@ static const char *const TAG = "ads1118.sensor";
void ADS1118Sensor::dump_config() {
LOG_SENSOR(" ", "ADS1118 Sensor", this);
ESP_LOGCONFIG(TAG, " Multiplexer: %u", this->multiplexer_);
ESP_LOGCONFIG(TAG, " Gain: %u", this->gain_);
ESP_LOGCONFIG(TAG,
" Multiplexer: %u\n"
" Gain: %u",
this->multiplexer_, this->gain_);
}
float ADS1118Sensor::sample() {

View File

@@ -20,7 +20,8 @@ bool AirthingsListener::parse_device(const esp32_ble_tracker::ESPBTDevice &devic
sn |= ((uint32_t) it.data[2] << 16);
sn |= ((uint32_t) it.data[3] << 24);
ESP_LOGD(TAG, "Found AirThings device Serial:%" PRIu32 " (MAC: %s)", sn, device.address_str().c_str());
char addr_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
ESP_LOGD(TAG, "Found AirThings device Serial:%" PRIu32 " (MAC: %s)", sn, device.address_str_to(addr_buf));
return true;
}
}

View File

@@ -1,4 +1,5 @@
#include "airthings_wave_base.h"
#include "esphome/components/esp32_ble/ble_uuid.h"
// All information related to reading battery information came from the sensors.airthings_wave
// project by Sverre Hamre (https://github.com/sverrham/sensor.airthings_wave)
@@ -93,8 +94,10 @@ void AirthingsWaveBase::update() {
bool AirthingsWaveBase::request_read_values_() {
auto *chr = this->parent()->get_characteristic(this->service_uuid_, this->sensors_data_characteristic_uuid_);
if (chr == nullptr) {
ESP_LOGW(TAG, "No sensor characteristic found at service %s char %s", this->service_uuid_.to_string().c_str(),
this->sensors_data_characteristic_uuid_.to_string().c_str());
char service_buf[esp32_ble::UUID_STR_LEN];
char char_buf[esp32_ble::UUID_STR_LEN];
ESP_LOGW(TAG, "No sensor characteristic found at service %s char %s", this->service_uuid_.to_str(service_buf),
this->sensors_data_characteristic_uuid_.to_str(char_buf));
return false;
}
@@ -117,17 +120,20 @@ bool AirthingsWaveBase::request_battery_() {
auto *chr = this->parent()->get_characteristic(this->service_uuid_, this->access_control_point_characteristic_uuid_);
if (chr == nullptr) {
char service_buf[esp32_ble::UUID_STR_LEN];
char char_buf[esp32_ble::UUID_STR_LEN];
ESP_LOGW(TAG, "No access control point characteristic found at service %s char %s",
this->service_uuid_.to_string().c_str(),
this->access_control_point_characteristic_uuid_.to_string().c_str());
this->service_uuid_.to_str(service_buf), this->access_control_point_characteristic_uuid_.to_str(char_buf));
return false;
}
auto *descr = this->parent()->get_descriptor(this->service_uuid_, this->access_control_point_characteristic_uuid_,
CLIENT_CHARACTERISTIC_CONFIGURATION_DESCRIPTOR_UUID);
if (descr == nullptr) {
ESP_LOGW(TAG, "No CCC descriptor found at service %s char %s", this->service_uuid_.to_string().c_str(),
this->access_control_point_characteristic_uuid_.to_string().c_str());
char service_buf[esp32_ble::UUID_STR_LEN];
char char_buf[esp32_ble::UUID_STR_LEN];
ESP_LOGW(TAG, "No CCC descriptor found at service %s char %s", this->service_uuid_.to_str(service_buf),
this->access_control_point_characteristic_uuid_.to_str(char_buf));
return false;
}

View File

@@ -8,8 +8,7 @@
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
namespace esphome {
namespace alarm_control_panel {
namespace esphome::alarm_control_panel {
static const char *const TAG = "alarm_control_panel";
@@ -115,5 +114,4 @@ void AlarmControlPanel::disarm(optional<std::string> code) {
call.perform();
}
} // namespace alarm_control_panel
} // namespace esphome
} // namespace esphome::alarm_control_panel

View File

@@ -1,7 +1,5 @@
#pragma once
#include <map>
#include "alarm_control_panel_call.h"
#include "alarm_control_panel_state.h"
@@ -9,8 +7,7 @@
#include "esphome/core/entity_base.h"
#include "esphome/core/log.h"
namespace esphome {
namespace alarm_control_panel {
namespace esphome::alarm_control_panel {
enum AlarmControlPanelFeature : uint8_t {
// Matches Home Assistant values
@@ -132,14 +129,13 @@ class AlarmControlPanel : public EntityBase {
// the call control function
virtual void control(const AlarmControlPanelCall &call) = 0;
// state callback - triggers check get_state() for specific state
CallbackManager<void()> state_callback_{};
LazyCallbackManager<void()> state_callback_{};
// clear callback - fires when leaving TRIGGERED state
CallbackManager<void()> cleared_callback_{};
LazyCallbackManager<void()> cleared_callback_{};
// chime callback
CallbackManager<void()> chime_callback_{};
LazyCallbackManager<void()> chime_callback_{};
// ready callback
CallbackManager<void()> ready_callback_{};
LazyCallbackManager<void()> ready_callback_{};
};
} // namespace alarm_control_panel
} // namespace esphome
} // namespace esphome::alarm_control_panel

View File

@@ -4,8 +4,7 @@
#include "esphome/core/log.h"
namespace esphome {
namespace alarm_control_panel {
namespace esphome::alarm_control_panel {
static const char *const TAG = "alarm_control_panel";
@@ -99,5 +98,4 @@ void AlarmControlPanelCall::perform() {
}
}
} // namespace alarm_control_panel
} // namespace esphome
} // namespace esphome::alarm_control_panel

View File

@@ -6,8 +6,7 @@
#include "esphome/core/helpers.h"
namespace esphome {
namespace alarm_control_panel {
namespace esphome::alarm_control_panel {
class AlarmControlPanel;
@@ -36,5 +35,4 @@ class AlarmControlPanelCall {
void validate_();
};
} // namespace alarm_control_panel
} // namespace esphome
} // namespace esphome::alarm_control_panel

View File

@@ -1,7 +1,6 @@
#include "alarm_control_panel_state.h"
namespace esphome {
namespace alarm_control_panel {
namespace esphome::alarm_control_panel {
const LogString *alarm_control_panel_state_to_string(AlarmControlPanelState state) {
switch (state) {
@@ -30,5 +29,4 @@ const LogString *alarm_control_panel_state_to_string(AlarmControlPanelState stat
}
}
} // namespace alarm_control_panel
} // namespace esphome
} // namespace esphome::alarm_control_panel

View File

@@ -3,8 +3,7 @@
#include <cstdint>
#include "esphome/core/log.h"
namespace esphome {
namespace alarm_control_panel {
namespace esphome::alarm_control_panel {
enum AlarmControlPanelState : uint8_t {
ACP_STATE_DISARMED = 0,
@@ -25,5 +24,4 @@ enum AlarmControlPanelState : uint8_t {
*/
const LogString *alarm_control_panel_state_to_string(AlarmControlPanelState state);
} // namespace alarm_control_panel
} // namespace esphome
} // namespace esphome::alarm_control_panel

View File

@@ -3,8 +3,7 @@
#include "esphome/core/automation.h"
#include "alarm_control_panel.h"
namespace esphome {
namespace alarm_control_panel {
namespace esphome::alarm_control_panel {
/// Trigger on any state change
class StateTrigger : public Trigger<> {
@@ -165,5 +164,4 @@ template<typename... Ts> class AlarmControlPanelCondition : public Condition<Ts.
AlarmControlPanel *parent_;
};
} // namespace alarm_control_panel
} // namespace esphome
} // namespace esphome::alarm_control_panel

View File

@@ -15,10 +15,8 @@ namespace alpha3 {
namespace espbt = esphome::esp32_ble_tracker;
static const espbt::ESPBTUUID ALPHA3_GENI_SERVICE_UUID = espbt::ESPBTUUID::from_uint16(0xfe5d);
static const espbt::ESPBTUUID ALPHA3_GENI_CHARACTERISTIC_UUID =
espbt::ESPBTUUID::from_raw({static_cast<char>(0xa9), 0x7b, static_cast<char>(0xb8), static_cast<char>(0x85), 0x0,
0x1a, 0x28, static_cast<char>(0xaa), 0x2a, 0x43, 0x6e, 0x3, static_cast<char>(0xd1),
static_cast<char>(0xff), static_cast<char>(0x9c), static_cast<char>(0x85)});
static const espbt::ESPBTUUID ALPHA3_GENI_CHARACTERISTIC_UUID = espbt::ESPBTUUID::from_raw(
{0xa9, 0x7b, 0xb8, 0x85, 0x00, 0x1a, 0x28, 0xaa, 0x2a, 0x43, 0x6e, 0x03, 0xd1, 0xff, 0x9c, 0x85});
static const int16_t GENI_RESPONSE_HEADER_LENGTH = 13;
static const size_t GENI_RESPONSE_TYPE_LENGTH = 8;

View File

@@ -67,8 +67,10 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
case ESP_GATTC_SEARCH_CMPL_EVT: {
auto *chr = this->parent_->get_characteristic(ANOVA_SERVICE_UUID, ANOVA_CHARACTERISTIC_UUID);
if (chr == nullptr) {
ESP_LOGW(TAG, "[%s] No control service found at device, not an Anova..?", this->get_name().c_str());
ESP_LOGW(TAG, "[%s] Note, this component does not currently support Anova Nano.", this->get_name().c_str());
ESP_LOGW(TAG,
"[%s] No control service found at device, not an Anova..?\n"
"[%s] Note, this component does not currently support Anova Nano.",
this->get_name().c_str(), this->get_name().c_str());
break;
}
this->char_handle_ = chr->handle;

View File

@@ -4,6 +4,7 @@ import logging
from esphome import automation
from esphome.automation import Condition
import esphome.codegen as cg
from esphome.components.logger import request_log_listener
from esphome.config_helpers import get_logger_level
import esphome.config_validation as cv
from esphome.const import (
@@ -226,32 +227,6 @@ def _encryption_schema(config):
return ENCRYPTION_SCHEMA(config)
def _validate_api_config(config: ConfigType) -> ConfigType:
"""Validate API configuration with mutual exclusivity check and deprecation warning."""
# Check if both password and encryption are configured
has_password = CONF_PASSWORD in config and config[CONF_PASSWORD]
has_encryption = CONF_ENCRYPTION in config
if has_password and has_encryption:
raise cv.Invalid(
"The 'password' and 'encryption' options are mutually exclusive. "
"The API client only supports one authentication method at a time. "
"Please remove one of them. "
"Note: 'password' authentication is deprecated and will be removed in version 2026.1.0. "
"We strongly recommend using 'encryption' instead for better security."
)
# Warn about password deprecation
if has_password:
_LOGGER.warning(
"API 'password' authentication has been deprecated since May 2022 and will be removed in version 2026.1.0. "
"Please migrate to the 'encryption' configuration. "
"See https://esphome.io/components/api/#configuration-variables"
)
return config
def _consume_api_sockets(config: ConfigType) -> ConfigType:
"""Register socket needs for API component."""
from esphome.components import socket
@@ -268,7 +243,17 @@ CONFIG_SCHEMA = cv.All(
{
cv.GenerateID(): cv.declare_id(APIServer),
cv.Optional(CONF_PORT, default=6053): cv.port,
cv.Optional(CONF_PASSWORD, default=""): cv.string_strict,
# Removed in 2026.1.0 - kept to provide helpful error message
cv.Optional(CONF_PASSWORD): cv.invalid(
"The 'password' option has been removed in ESPHome 2026.1.0.\n"
"Password authentication was deprecated in May 2022.\n"
"Please migrate to encryption for secure API communication:\n\n"
"api:\n"
" encryption:\n"
" key: !secret api_encryption_key\n\n"
"Generate a key with: openssl rand -base64 32\n"
"Or visit https://esphome.io/components/api/#configuration-variables"
),
cv.Optional(
CONF_REBOOT_TIMEOUT, default="15min"
): cv.positive_time_period_milliseconds,
@@ -330,7 +315,6 @@ CONFIG_SCHEMA = cv.All(
}
).extend(cv.COMPONENT_SCHEMA),
cv.rename_key(CONF_SERVICES, CONF_ACTIONS),
_validate_api_config,
_consume_api_sockets,
)
@@ -343,10 +327,10 @@ async def to_code(config: ConfigType) -> None:
# Track controller registration for StaticVector sizing
CORE.register_controller()
# Request a log listener slot for API log streaming
request_log_listener()
cg.add(var.set_port(config[CONF_PORT]))
if config[CONF_PASSWORD]:
cg.add_define("USE_API_PASSWORD")
cg.add(var.set_password(config[CONF_PASSWORD]))
cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT]))
cg.add(var.set_batch_delay(config[CONF_BATCH_DELAY]))
if CONF_LISTEN_BACKLOG in config:

View File

@@ -7,10 +7,7 @@ service APIConnection {
option (needs_setup_connection) = false;
option (needs_authentication) = false;
}
rpc authenticate (AuthenticationRequest) returns (AuthenticationResponse) {
option (needs_setup_connection) = false;
option (needs_authentication) = false;
}
// REMOVED in ESPHome 2026.1.0: rpc authenticate (AuthenticationRequest) returns (AuthenticationResponse)
rpc disconnect (DisconnectRequest) returns (DisconnectResponse) {
option (needs_setup_connection) = false;
option (needs_authentication) = false;
@@ -69,6 +66,8 @@ service APIConnection {
rpc zwave_proxy_frame(ZWaveProxyFrame) returns (void) {}
rpc zwave_proxy_request(ZWaveProxyRequest) returns (void) {}
rpc infrared_rf_transmit_raw_timings(InfraredRFTransmitRawTimingsRequest) returns (void) {}
}
@@ -82,14 +81,13 @@ service APIConnection {
// * VarInt denoting the type of message.
// * The message object encoded as a ProtoBuf message
// The connection is established in 4 steps:
// The connection is established in 2 steps:
// * First, the client connects to the server and sends a "Hello Request" identifying itself
// * The server responds with a "Hello Response" and selects the protocol version
// * After receiving this message, the client attempts to authenticate itself using
// the password and a "Connect Request"
// * The server responds with a "Connect Response" and notifies of invalid password.
// * The server responds with a "Hello Response" and the connection is authenticated
// If anything in this initial process fails, the connection must immediately closed
// by both sides and _no_ disconnection message is to be sent.
// Note: Password authentication via AuthenticationRequest/AuthenticationResponse (message IDs 3, 4)
// was removed in ESPHome 2026.1.0. Those message IDs are reserved and should not be reused.
// Message sent at the beginning of each connection
// Can only be sent by the client and only at the beginning of the connection
@@ -102,7 +100,7 @@ message HelloRequest {
// For example "Home Assistant"
// Not strictly necessary to send but nice for debugging
// purposes.
string client_info = 1 [(pointer_to_buffer) = true];
string client_info = 1;
uint32 api_version_major = 2;
uint32 api_version_minor = 3;
}
@@ -130,25 +128,23 @@ message HelloResponse {
string name = 4;
}
// Message sent at the beginning of each connection to authenticate the client
// Can only be sent by the client and only at the beginning of the connection
// DEPRECATED in ESPHome 2026.1.0 - Password authentication is no longer supported.
// These messages are kept for protocol documentation but are not processed by the server.
// Use noise encryption instead: https://esphome.io/components/api/#configuration-variables
message AuthenticationRequest {
option (id) = 3;
option (source) = SOURCE_CLIENT;
option (no_delay) = true;
option (ifdef) = "USE_API_PASSWORD";
option deprecated = true;
// The password to log in with
string password = 1 [(pointer_to_buffer) = true];
string password = 1;
}
// Confirmation of successful connection. After this the connection is available for all traffic.
// Can only be sent by the server and only at the beginning of the connection
message AuthenticationResponse {
option (id) = 4;
option (source) = SOURCE_SERVER;
option (no_delay) = true;
option (ifdef) = "USE_API_PASSWORD";
option deprecated = true;
bool invalid_password = 1;
}
@@ -205,7 +201,9 @@ message DeviceInfoResponse {
option (id) = 10;
option (source) = SOURCE_SERVER;
bool uses_password = 1 [(field_ifdef) = "USE_API_PASSWORD"];
// Deprecated in ESPHome 2026.1.0, but kept for backward compatibility
// with older ESPHome versions that still send this field.
bool uses_password = 1 [deprecated = true];
// The name of the node, given by "App.set_name()"
string name = 2;
@@ -579,7 +577,7 @@ message LightCommandRequest {
bool has_flash_length = 16;
uint32 flash_length = 17;
bool has_effect = 18;
string effect = 19 [(pointer_to_buffer) = true];
string effect = 19;
uint32 device_id = 28 [(field_ifdef) = "USE_DEVICES"];
}
@@ -767,7 +765,7 @@ message SubscribeHomeassistantServicesRequest {
message HomeassistantServiceMap {
string key = 1;
string value = 2 [(no_zero_copy) = true];
string value = 2;
}
message HomeassistantActionRequest {
@@ -783,7 +781,7 @@ message HomeassistantActionRequest {
bool is_event = 5;
uint32 call_id = 6 [(field_ifdef) = "USE_API_HOMEASSISTANT_ACTION_RESPONSES"];
bool wants_response = 7 [(field_ifdef) = "USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON"];
string response_template = 8 [(no_zero_copy) = true, (field_ifdef) = "USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON"];
string response_template = 8 [(field_ifdef) = "USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON"];
}
// Message sent by Home Assistant to ESPHome with service call response data
@@ -796,7 +794,7 @@ message HomeassistantActionResponse {
uint32 call_id = 1; // Matches the call_id from HomeassistantActionRequest
bool success = 2; // Whether the service call succeeded
string error_message = 3; // Error message if success = false
bytes response_data = 4 [(pointer_to_buffer) = true, (field_ifdef) = "USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON"];
bytes response_data = 4 [(field_ifdef) = "USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON"];
}
// ==================== IMPORT HOME ASSISTANT STATES ====================
@@ -841,7 +839,7 @@ message GetTimeResponse {
option (no_delay) = true;
fixed32 epoch_seconds = 1;
string timezone = 2 [(pointer_to_buffer) = true];
string timezone = 2;
}
// ==================== USER-DEFINES SERVICES ====================
@@ -1101,6 +1099,85 @@ message ClimateCommandRequest {
uint32 device_id = 24 [(field_ifdef) = "USE_DEVICES"];
}
// ==================== WATER_HEATER ====================
enum WaterHeaterMode {
WATER_HEATER_MODE_OFF = 0;
WATER_HEATER_MODE_ECO = 1;
WATER_HEATER_MODE_ELECTRIC = 2;
WATER_HEATER_MODE_PERFORMANCE = 3;
WATER_HEATER_MODE_HIGH_DEMAND = 4;
WATER_HEATER_MODE_HEAT_PUMP = 5;
WATER_HEATER_MODE_GAS = 6;
}
message ListEntitiesWaterHeaterResponse {
option (id) = 132;
option (base_class) = "InfoResponseProtoMessage";
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_WATER_HEATER";
string object_id = 1;
fixed32 key = 2;
string name = 3;
string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON"];
bool disabled_by_default = 5;
EntityCategory entity_category = 6;
uint32 device_id = 7 [(field_ifdef) = "USE_DEVICES"];
float min_temperature = 8;
float max_temperature = 9;
float target_temperature_step = 10;
repeated WaterHeaterMode supported_modes = 11 [(container_pointer_no_template) = "water_heater::WaterHeaterModeMask"];
// Bitmask of WaterHeaterFeature flags
uint32 supported_features = 12;
}
message WaterHeaterStateResponse {
option (id) = 133;
option (base_class) = "StateResponseProtoMessage";
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_WATER_HEATER";
option (no_delay) = true;
fixed32 key = 1;
float current_temperature = 2;
float target_temperature = 3;
WaterHeaterMode mode = 4;
uint32 device_id = 5 [(field_ifdef) = "USE_DEVICES"];
// Bitmask of current state flags (bit 0 = away, bit 1 = on)
uint32 state = 6;
float target_temperature_low = 7;
float target_temperature_high = 8;
}
// Bitmask for WaterHeaterCommandRequest.has_fields
enum WaterHeaterCommandHasField {
WATER_HEATER_COMMAND_HAS_NONE = 0;
WATER_HEATER_COMMAND_HAS_MODE = 1;
WATER_HEATER_COMMAND_HAS_TARGET_TEMPERATURE = 2;
WATER_HEATER_COMMAND_HAS_STATE = 4;
WATER_HEATER_COMMAND_HAS_TARGET_TEMPERATURE_LOW = 8;
WATER_HEATER_COMMAND_HAS_TARGET_TEMPERATURE_HIGH = 16;
}
message WaterHeaterCommandRequest {
option (id) = 134;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_WATER_HEATER";
option (no_delay) = true;
option (base_class) = "CommandProtoMessage";
fixed32 key = 1;
// Bitmask of which fields are set (see WaterHeaterCommandHasField)
uint32 has_fields = 2;
WaterHeaterMode mode = 3;
float target_temperature = 4;
uint32 device_id = 5 [(field_ifdef) = "USE_DEVICES"];
// State flags bitmask (bit 0 = away, bit 1 = on)
uint32 state = 6;
float target_temperature_low = 7;
float target_temperature_high = 8;
}
// ==================== NUMBER ====================
enum NumberMode {
NUMBER_MODE_AUTO = 0;
@@ -1195,7 +1272,7 @@ message SelectCommandRequest {
option (base_class) = "CommandProtoMessage";
fixed32 key = 1;
string state = 2 [(pointer_to_buffer) = true];
string state = 2;
uint32 device_id = 3 [(field_ifdef) = "USE_DEVICES"];
}
@@ -1213,7 +1290,7 @@ message ListEntitiesSirenResponse {
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON"];
bool disabled_by_default = 6;
repeated string tones = 7;
repeated string tones = 7 [(container_pointer_no_template) = "FixedVector<const char *>"];
bool supports_duration = 8;
bool supports_volume = 9;
EntityCategory entity_category = 10;
@@ -1613,7 +1690,7 @@ message BluetoothGATTWriteRequest {
uint32 handle = 2;
bool response = 3;
bytes data = 4 [(pointer_to_buffer) = true];
bytes data = 4;
}
message BluetoothGATTReadDescriptorRequest {
@@ -1633,7 +1710,7 @@ message BluetoothGATTWriteDescriptorRequest {
uint64 address = 1;
uint32 handle = 2;
bytes data = 3 [(pointer_to_buffer) = true];
bytes data = 3;
}
message BluetoothGATTNotifyRequest {
@@ -1858,7 +1935,7 @@ message VoiceAssistantAudio {
option (source) = SOURCE_BOTH;
option (ifdef) = "USE_VOICE_ASSISTANT";
bytes data = 1;
bytes data = 1 [(pointer_to_buffer) = true];
bool end = 2;
}
@@ -2346,7 +2423,7 @@ message ZWaveProxyFrame {
option (ifdef) = "USE_ZWAVE_PROXY";
option (no_delay) = true;
bytes data = 1 [(pointer_to_buffer) = true];
bytes data = 1;
}
enum ZWaveProxyRequestType {
@@ -2360,5 +2437,51 @@ message ZWaveProxyRequest {
option (ifdef) = "USE_ZWAVE_PROXY";
ZWaveProxyRequestType type = 1;
bytes data = 2 [(pointer_to_buffer) = true];
bytes data = 2;
}
// ==================== INFRARED ====================
// Note: Feature and capability flag enums are defined in
// esphome/components/infrared/infrared.h
// Listing of infrared instances
message ListEntitiesInfraredResponse {
option (id) = 135;
option (base_class) = "InfoResponseProtoMessage";
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_INFRARED";
string object_id = 1;
fixed32 key = 2;
string name = 3;
string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON"];
bool disabled_by_default = 5;
EntityCategory entity_category = 6;
uint32 device_id = 7 [(field_ifdef) = "USE_DEVICES"];
uint32 capabilities = 8; // Bitfield of InfraredCapabilityFlags
}
// Command to transmit infrared/RF data using raw timings
message InfraredRFTransmitRawTimingsRequest {
option (id) = 136;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_IR_RF";
uint32 device_id = 1 [(field_ifdef) = "USE_DEVICES"];
fixed32 key = 2; // Key identifying the transmitter instance
uint32 carrier_frequency = 3; // Carrier frequency in Hz
uint32 repeat_count = 4; // Number of times to transmit (1 = once, 2 = twice, etc.)
repeated sint32 timings = 5 [packed = true, (packed_buffer) = true]; // Raw timings in microseconds (zigzag-encoded): positive = mark (LED/TX on), negative = space (LED/TX off)
}
// Event message for received infrared/RF data
message InfraredRFReceiveEvent {
option (id) = 137;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_IR_RF";
option (no_delay) = true;
uint32 device_id = 1 [(field_ifdef) = "USE_DEVICES"];
fixed32 key = 2; // Key identifying the receiver instance
repeated sint32 timings = 3 [packed = true, (container_pointer_no_template) = "std::vector<int32_t>"]; // Raw timings in microseconds (zigzag-encoded): alternating mark/space periods
}

File diff suppressed because it is too large Load Diff

View File

@@ -9,32 +9,24 @@
#include "esphome/core/application.h"
#include "esphome/core/component.h"
#include "esphome/core/entity_base.h"
#include "esphome/core/string_ref.h"
#include <functional>
#include <limits>
#include <vector>
namespace esphome::api {
// Client information structure
struct ClientInfo {
std::string name; // Client name from Hello message
std::string peername; // IP:port from socket
};
// Keepalive timeout in milliseconds
static constexpr uint32_t KEEPALIVE_TIMEOUT_MS = 60000;
// Maximum number of entities to process in a single batch during initial state/info sending
// This was increased from 20 to 24 after removing the unique_id field from entity info messages,
// which reduced message sizes allowing more entities per batch without exceeding packet limits
static constexpr size_t MAX_INITIAL_PER_BATCH = 24;
// Maximum number of packets to process in a single batch (platform-dependent)
// This limit exists to prevent stack overflow from the PacketInfo array in process_batch_
// Each PacketInfo is 8 bytes, so 64 * 8 = 512 bytes, 32 * 8 = 256 bytes
#if defined(USE_ESP32) || defined(USE_HOST)
static constexpr size_t MAX_PACKETS_PER_BATCH = 64; // ESP32 has 8KB+ stack, HOST has plenty
#else
static constexpr size_t MAX_PACKETS_PER_BATCH = 32; // ESP8266/RP2040/etc have smaller stacks
#endif
// API 1.14+ clients compute object_id client-side, so messages are smaller and we can fit more per batch
// TODO: Remove MAX_INITIAL_PER_BATCH_LEGACY before 2026.7.0 - all clients should support API 1.14 by then
static constexpr size_t MAX_INITIAL_PER_BATCH_LEGACY = 24; // For clients < API 1.14 (includes object_id)
static constexpr size_t MAX_INITIAL_PER_BATCH = 34; // For clients >= API 1.14 (no object_id)
// Verify MAX_MESSAGES_PER_BATCH (defined in api_frame_helper.h) can hold the initial batch
static_assert(MAX_MESSAGES_PER_BATCH >= MAX_INITIAL_PER_BATCH,
"MAX_MESSAGES_PER_BATCH must be >= MAX_INITIAL_PER_BATCH");
class APIConnection final : public APIServerConnection {
public:
@@ -47,8 +39,8 @@ class APIConnection final : public APIServerConnection {
void loop();
bool send_list_info_done() {
return this->schedule_message_(nullptr, &APIConnection::try_send_list_info_done,
ListEntitiesDoneResponse::MESSAGE_TYPE, ListEntitiesDoneResponse::ESTIMATED_SIZE);
return this->schedule_message_(nullptr, ListEntitiesDoneResponse::MESSAGE_TYPE,
ListEntitiesDoneResponse::ESTIMATED_SIZE);
}
#ifdef USE_BINARY_SENSOR
bool send_binary_sensor_state(binary_sensor::BinarySensor *binary_sensor);
@@ -176,8 +168,18 @@ class APIConnection final : public APIServerConnection {
void alarm_control_panel_command(const AlarmControlPanelCommandRequest &msg) override;
#endif
#ifdef USE_WATER_HEATER
bool send_water_heater_state(water_heater::WaterHeater *water_heater);
void on_water_heater_command_request(const WaterHeaterCommandRequest &msg) override;
#endif
#ifdef USE_IR_RF
void infrared_rf_transmit_raw_timings(const InfraredRFTransmitRawTimingsRequest &msg) override;
void send_infrared_rf_receive_event(const InfraredRFReceiveEvent &msg);
#endif
#ifdef USE_EVENT
void send_event(event::Event *event, const char *event_type);
void send_event(event::Event *event);
#endif
#ifdef USE_UPDATE
@@ -197,16 +199,17 @@ class APIConnection final : public APIServerConnection {
void on_get_time_response(const GetTimeResponse &value) override;
#endif
bool send_hello_response(const HelloRequest &msg) override;
#ifdef USE_API_PASSWORD
bool send_authenticate_response(const AuthenticationRequest &msg) override;
#endif
bool send_disconnect_response(const DisconnectRequest &msg) override;
bool send_ping_response(const PingRequest &msg) override;
bool send_device_info_response(const DeviceInfoRequest &msg) override;
void list_entities(const ListEntitiesRequest &msg) override { this->list_entities_iterator_.begin(); }
void list_entities(const ListEntitiesRequest &msg) override { this->begin_iterator_(ActiveIterator::LIST_ENTITIES); }
void subscribe_states(const SubscribeStatesRequest &msg) override {
this->flags_.state_subscription = true;
this->initial_state_iterator_.begin();
// Start initial state iterator only if no iterator is active
// If list_entities is running, we'll start initial_state when it completes
if (this->active_iterator_ == ActiveIterator::NONE) {
this->begin_iterator_(ActiveIterator::INITIAL_STATE);
}
}
void subscribe_logs(const SubscribeLogsRequest &msg) override {
this->flags_.log_subscription = msg.level;
@@ -224,9 +227,9 @@ class APIConnection final : public APIServerConnection {
#ifdef USE_API_USER_DEFINED_ACTIONS
void execute_service(const ExecuteServiceRequest &msg) override;
#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES
void send_execute_service_response(uint32_t call_id, bool success, const std::string &error_message);
void send_execute_service_response(uint32_t call_id, bool success, StringRef error_message);
#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES_JSON
void send_execute_service_response(uint32_t call_id, bool success, const std::string &error_message,
void send_execute_service_response(uint32_t call_id, bool success, StringRef error_message,
const uint8_t *response_data, size_t response_data_len);
#endif // USE_API_USER_DEFINED_ACTION_RESPONSES_JSON
#endif // USE_API_USER_DEFINED_ACTION_RESPONSES
@@ -251,9 +254,6 @@ class APIConnection final : public APIServerConnection {
}
void on_fatal_error() override;
#ifdef USE_API_PASSWORD
void on_unauthenticated_access() override;
#endif
void on_no_setup_connection() override;
ProtoWriteBuffer create_buffer(uint32_t reserve_size) override {
// FIXME: ensure no recursive writes can happen
@@ -280,13 +280,18 @@ class APIConnection final : public APIServerConnection {
bool try_to_clear_buffer(bool log_out_of_space);
bool send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) override;
const std::string &get_name() const { return this->client_info_.name; }
const std::string &get_peername() const { return this->client_info_.peername; }
const char *get_name() const { return this->helper_->get_client_name(); }
/// Get peer name (IP address) - cached at connection init time
const char *get_peername() const { return this->helper_->get_client_peername(); }
protected:
// Helper function to handle authentication completion
void complete_authentication_();
#ifdef USE_CAMERA
void try_send_camera_image_();
#endif
#ifdef USE_API_HOMEASSISTANT_STATES
void process_state_subscriptions_();
#endif
@@ -310,25 +315,24 @@ class APIConnection final : public APIServerConnection {
APIConnection *conn, uint32_t remaining_size, bool is_single) {
// Set common fields that are shared by all entity types
msg.key = entity->get_object_id_hash();
// Try to use static reference first to avoid allocation
StringRef static_ref = entity->get_object_id_ref_for_api_();
// Store dynamic string outside the if-else to maintain lifetime
std::string object_id;
if (!static_ref.empty()) {
msg.set_object_id(static_ref);
} else {
// Dynamic case - need to allocate
object_id = entity->get_object_id();
msg.set_object_id(StringRef(object_id));
// API 1.14+ clients compute object_id client-side from the entity name
// For older clients, we must send object_id for backward compatibility
// See: https://github.com/esphome/backlog/issues/76
// TODO: Remove this backward compat code before 2026.7.0 - all clients should support API 1.14 by then
// Buffer must remain in scope until encode_message_to_buffer is called
char object_id_buf[OBJECT_ID_MAX_LEN];
if (!conn->client_supports_api_version(1, 14)) {
msg.object_id = entity->get_object_id_to(object_id_buf);
}
if (entity->has_own_name()) {
msg.set_name(entity->get_name());
msg.name = entity->get_name();
}
// Set common EntityBase properties
#ifdef USE_ENTITY_ICON
msg.set_icon(entity->get_icon_ref());
msg.icon = entity->get_icon_ref();
#endif
msg.disabled_by_default = entity->is_disabled_by_default();
msg.entity_category = static_cast<enums::EntityCategory>(entity->get_entity_category());
@@ -343,16 +347,24 @@ class APIConnection final : public APIServerConnection {
inline bool check_voice_assistant_api_connection_() const;
#endif
// Get the max batch size based on client API version
// API 1.14+ clients don't receive object_id, so messages are smaller and more fit per batch
// TODO: Remove this method before 2026.7.0 and use MAX_INITIAL_PER_BATCH directly
size_t get_max_batch_size_() const {
return this->client_supports_api_version(1, 14) ? MAX_INITIAL_PER_BATCH : MAX_INITIAL_PER_BATCH_LEGACY;
}
// Helper method to process multiple entities from an iterator in a batch
template<typename Iterator> void process_iterator_batch_(Iterator &iterator) {
size_t initial_size = this->deferred_batch_.size();
while (!iterator.completed() && (this->deferred_batch_.size() - initial_size) < MAX_INITIAL_PER_BATCH) {
size_t max_batch = this->get_max_batch_size_();
while (!iterator.completed() && (this->deferred_batch_.size() - initial_size) < max_batch) {
iterator.advance();
}
// If the batch is full, process it immediately
// Note: iterator.advance() already calls schedule_batch_() via schedule_message_()
if (this->deferred_batch_.size() >= MAX_INITIAL_PER_BATCH) {
if (this->deferred_batch_.size() >= max_batch) {
this->process_batch_();
}
}
@@ -456,8 +468,18 @@ class APIConnection final : public APIServerConnection {
static uint16_t try_send_alarm_control_panel_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single);
#endif
#ifdef USE_WATER_HEATER
static uint16_t try_send_water_heater_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single);
static uint16_t try_send_water_heater_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single);
#endif
#ifdef USE_INFRARED
static uint16_t try_send_infrared_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single);
#endif
#ifdef USE_EVENT
static uint16_t try_send_event_response(event::Event *event, const char *event_type, APIConnection *conn,
static uint16_t try_send_event_response(event::Event *event, StringRef event_type, APIConnection *conn,
uint32_t remaining_size, bool is_single);
static uint16_t try_send_event_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single);
#endif
@@ -490,18 +512,27 @@ class APIConnection final : public APIServerConnection {
std::unique_ptr<APIFrameHelper> helper_;
APIServer *parent_;
// Group 2: Larger objects (must be 4-byte aligned)
// These contain vectors/pointers internally, so putting them early ensures good alignment
InitialStateIterator initial_state_iterator_;
ListEntitiesIterator list_entities_iterator_;
// Group 2: Iterator union (saves ~16 bytes vs separate iterators)
// These iterators are never active simultaneously - list_entities runs to completion
// before initial_state begins, so we use a union with explicit construction/destruction.
enum class ActiveIterator : uint8_t { NONE, LIST_ENTITIES, INITIAL_STATE };
union IteratorUnion {
ListEntitiesIterator list_entities;
InitialStateIterator initial_state;
// Constructor/destructor do nothing - use placement new/explicit destructor
IteratorUnion() {}
~IteratorUnion() {}
} iterator_storage_;
// Helper methods for iterator lifecycle management
void destroy_active_iterator_();
void begin_iterator_(ActiveIterator type);
#ifdef USE_CAMERA
std::unique_ptr<camera::CameraImageReader> image_reader_;
#endif
// Group 3: Client info struct (24 bytes on 32-bit: 2 strings × 12 bytes each)
ClientInfo client_info_;
// Group 4: 4-byte types
// Group 3: 4-byte types
uint32_t last_traffic_;
#ifdef USE_API_HOMEASSISTANT_STATES
int state_subs_at_ = -1;
@@ -510,33 +541,17 @@ class APIConnection final : public APIServerConnection {
// Function pointer type for message encoding
using MessageCreatorPtr = uint16_t (*)(EntityBase *, APIConnection *, uint32_t remaining_size, bool is_single);
class MessageCreator {
public:
MessageCreator(MessageCreatorPtr ptr) { data_.function_ptr = ptr; }
explicit MessageCreator(const char *str_value) { data_.const_char_ptr = str_value; }
// Call operator - uses message_type to determine union type
uint16_t operator()(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single,
uint8_t message_type) const;
private:
union Data {
MessageCreatorPtr function_ptr;
const char *const_char_ptr;
} data_; // 4 bytes on 32-bit, 8 bytes on 64-bit
};
// Generic batching mechanism for both state updates and entity info
struct DeferredBatch {
struct BatchItem {
EntityBase *entity; // Entity pointer
MessageCreator creator; // Function that creates the message when needed
uint8_t message_type; // Message type for overhead calculation (max 255)
uint8_t estimated_size; // Estimated message size (max 255 bytes)
// Sentinel value for unused aux_data_index
static constexpr uint8_t AUX_DATA_UNUSED = std::numeric_limits<uint8_t>::max();
// Constructor for creating BatchItem
BatchItem(EntityBase *entity, MessageCreator creator, uint8_t message_type, uint8_t estimated_size)
: entity(entity), creator(creator), message_type(message_type), estimated_size(estimated_size) {}
struct BatchItem {
EntityBase *entity; // 4 bytes - Entity pointer
uint8_t message_type; // 1 byte - Message type for protocol and dispatch
uint8_t estimated_size; // 1 byte - Estimated message size (max 255 bytes)
uint8_t aux_data_index{AUX_DATA_UNUSED}; // 1 byte - For events: index into entity's event_types
// 1 byte padding
};
std::vector<BatchItem> items;
@@ -545,10 +560,11 @@ class APIConnection final : public APIServerConnection {
// No pre-allocation - log connections never use batching, and for
// connections that do, buffers are released after initial sync anyway
// Add item to the batch
void add_item(EntityBase *entity, MessageCreator creator, uint8_t message_type, uint8_t estimated_size);
// Add item to the batch (with deduplication)
void add_item(EntityBase *entity, uint8_t message_type, uint8_t estimated_size,
uint8_t aux_data_index = AUX_DATA_UNUSED);
// Add item to the front of the batch (for high priority messages like ping)
void add_item_front(EntityBase *entity, MessageCreator creator, uint8_t message_type, uint8_t estimated_size);
void add_item_front(EntityBase *entity, uint8_t message_type, uint8_t estimated_size);
// Clear all items
void clear() {
@@ -562,6 +578,7 @@ class APIConnection final : public APIServerConnection {
bool empty() const { return items.empty(); }
size_t size() const { return items.size(); }
const BatchItem &operator[](size_t index) const { return items[index]; }
// Release excess capacity - only releases if items already empty
void release_buffer() {
// Safe to call: batch is processed before release_buffer is called,
@@ -608,7 +625,9 @@ class APIConnection final : public APIServerConnection {
// 2-byte types immediately after flags_ (no padding between them)
uint16_t client_api_version_major_{0};
uint16_t client_api_version_minor_{0};
// Total: 2 (flags) + 2 + 2 = 6 bytes, then 2 bytes padding to next 4-byte boundary
// 1-byte type to fill padding
ActiveIterator active_iterator_{ActiveIterator::NONE};
// Total: 2 (flags) + 2 + 2 + 1 = 7 bytes, then 1 byte padding to next 4-byte boundary
uint32_t get_batch_delay_ms_() const;
// Message will use 8 more bytes than the minimum size, and typical
@@ -631,17 +650,15 @@ class APIConnection final : public APIServerConnection {
this->flags_.batch_scheduled = false;
}
#ifdef HAS_PROTO_MESSAGE_DUMP
// Helper to log a proto message from a MessageCreator object
void log_proto_message_(EntityBase *entity, const MessageCreator &creator, uint8_t message_type) {
this->flags_.log_only_mode = true;
creator(entity, this, MAX_BATCH_PACKET_SIZE, true, message_type);
this->flags_.log_only_mode = false;
}
// Dispatch message encoding based on message_type - replaces function pointer storage
// Switch assigns pointer, single call site for smaller code size
uint16_t dispatch_message_(const DeferredBatch::BatchItem &item, uint32_t remaining_size, bool is_single);
#ifdef HAS_PROTO_MESSAGE_DUMP
void log_batch_item_(const DeferredBatch::BatchItem &item) {
// Use the helper to log the message
this->log_proto_message_(item.entity, item.creator, item.message_type);
this->flags_.log_only_mode = true;
this->dispatch_message_(item, MAX_BATCH_PACKET_SIZE, true);
this->flags_.log_only_mode = false;
}
#endif
@@ -666,66 +683,36 @@ class APIConnection final : public APIServerConnection {
// Helper method to send a message either immediately or via batching
// Tries immediate send if should_send_immediately_() returns true and buffer has space
// Falls back to batching if immediate send fails or isn't applicable
bool send_message_smart_(EntityBase *entity, MessageCreatorPtr creator, uint8_t message_type,
uint8_t estimated_size) {
bool send_message_smart_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size,
uint8_t aux_data_index = DeferredBatch::AUX_DATA_UNUSED) {
if (this->should_send_immediately_(message_type) && this->helper_->can_write_without_blocking()) {
// Now actually encode and send
if (creator(entity, this, MAX_BATCH_PACKET_SIZE, true) &&
DeferredBatch::BatchItem item{entity, message_type, estimated_size, aux_data_index};
if (this->dispatch_message_(item, MAX_BATCH_PACKET_SIZE, true) &&
this->send_buffer(ProtoWriteBuffer{&this->parent_->get_shared_buffer_ref()}, message_type)) {
#ifdef HAS_PROTO_MESSAGE_DUMP
// Log the message in verbose mode
this->log_proto_message_(entity, MessageCreator(creator), message_type);
this->log_batch_item_(item);
#endif
return true;
}
// If immediate send failed, fall through to batching
}
// Fall back to scheduled batching
return this->schedule_message_(entity, creator, message_type, estimated_size);
}
// Overload for MessageCreator (used by events which need to capture event_type)
bool send_message_smart_(EntityBase *entity, MessageCreator creator, uint8_t message_type, uint8_t estimated_size) {
// Try to send immediately if message type should bypass batching and buffer has space
if (this->should_send_immediately_(message_type) && this->helper_->can_write_without_blocking()) {
// Now actually encode and send
if (creator(entity, this, MAX_BATCH_PACKET_SIZE, true, message_type) &&
this->send_buffer(ProtoWriteBuffer{&this->parent_->get_shared_buffer_ref()}, message_type)) {
#ifdef HAS_PROTO_MESSAGE_DUMP
// Log the message in verbose mode
this->log_proto_message_(entity, creator, message_type);
#endif
return true;
}
// If immediate send failed, fall through to batching
}
// Fall back to scheduled batching
return this->schedule_message_(entity, creator, message_type, estimated_size);
return this->schedule_message_(entity, message_type, estimated_size, aux_data_index);
}
// Helper function to schedule a deferred message with known message type
bool schedule_message_(EntityBase *entity, MessageCreator creator, uint8_t message_type, uint8_t estimated_size) {
this->deferred_batch_.add_item(entity, creator, message_type, estimated_size);
bool schedule_message_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size,
uint8_t aux_data_index = DeferredBatch::AUX_DATA_UNUSED) {
this->deferred_batch_.add_item(entity, message_type, estimated_size, aux_data_index);
return this->schedule_batch_();
}
// Overload for function pointers (for info messages and current state reads)
bool schedule_message_(EntityBase *entity, MessageCreatorPtr function_ptr, uint8_t message_type,
uint8_t estimated_size) {
return schedule_message_(entity, MessageCreator(function_ptr), message_type, estimated_size);
}
// Helper function to schedule a high priority message at the front of the batch
bool schedule_message_front_(EntityBase *entity, MessageCreatorPtr function_ptr, uint8_t message_type,
uint8_t estimated_size) {
this->deferred_batch_.add_item_front(entity, MessageCreator(function_ptr), message_type, estimated_size);
bool schedule_message_front_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size) {
this->deferred_batch_.add_item_front(entity, message_type, estimated_size);
return this->schedule_batch_();
}
// Helper function to log client messages with name and peername
void log_client_(int level, const LogString *message);
// Helper function to log API errors with errno
void log_warning_(const LogString *message, APIError err);
// Helper to handle fatal errors with logging

View File

@@ -1,6 +1,5 @@
#include "api_frame_helper.h"
#ifdef USE_API
#include "api_connection.h" // For ClientInfo struct
#include "esphome/core/application.h"
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
@@ -13,12 +12,29 @@ namespace esphome::api {
static const char *const TAG = "api.frame_helper";
#define HELPER_LOG(msg, ...) \
ESP_LOGVV(TAG, "%s (%s): " msg, this->client_info_->name.c_str(), this->client_info_->peername.c_str(), ##__VA_ARGS__)
// Maximum bytes to log in hex format (168 * 3 = 504, under TX buffer size of 512)
static constexpr size_t API_MAX_LOG_BYTES = 168;
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE
#define HELPER_LOG(msg, ...) ESP_LOGVV(TAG, "%s (%s): " msg, this->client_name_, this->client_peername_, ##__VA_ARGS__)
#else
#define HELPER_LOG(msg, ...) ((void) 0)
#endif
#ifdef HELPER_LOG_PACKETS
#define LOG_PACKET_RECEIVED(buffer) ESP_LOGVV(TAG, "Received frame: %s", format_hex_pretty(buffer).c_str())
#define LOG_PACKET_SENDING(data, len) ESP_LOGVV(TAG, "Sending raw: %s", format_hex_pretty(data, len).c_str())
#define LOG_PACKET_RECEIVED(buffer) \
do { \
char hex_buf_[format_hex_pretty_size(API_MAX_LOG_BYTES)]; \
ESP_LOGVV(TAG, "Received frame: %s", \
format_hex_pretty_to(hex_buf_, (buffer).data(), \
(buffer).size() < API_MAX_LOG_BYTES ? (buffer).size() : API_MAX_LOG_BYTES)); \
} while (0)
#define LOG_PACKET_SENDING(data, len) \
do { \
char hex_buf_[format_hex_pretty_size(API_MAX_LOG_BYTES)]; \
ESP_LOGVV(TAG, "Sending raw: %s", \
format_hex_pretty_to(hex_buf_, data, (len) < API_MAX_LOG_BYTES ? (len) : API_MAX_LOG_BYTES)); \
} while (0)
#else
#define LOG_PACKET_RECEIVED(buffer) ((void) 0)
#define LOG_PACKET_SENDING(data, len) ((void) 0)
@@ -229,6 +245,8 @@ APIError APIFrameHelper::init_common_() {
HELPER_LOG("Bad state for init %d", (int) state_);
return APIError::BAD_STATE;
}
// Cache peername now while socket is valid - needed for error logging after socket failure
this->socket_->getpeername_to(this->client_peername_);
int err = this->socket_->setblocking(false);
if (err != 0) {
state_ = State::FAILED;

View File

@@ -29,24 +29,28 @@ static constexpr uint16_t MAX_MESSAGE_SIZE = 8192; // 8 KiB for ESP8266
static constexpr uint16_t MAX_MESSAGE_SIZE = 32768; // 32 KiB for ESP32 and other platforms
#endif
// Forward declaration
struct ClientInfo;
// Maximum number of messages to batch in a single write operation
// Must be >= MAX_INITIAL_PER_BATCH in api_connection.h (enforced by static_assert there)
static constexpr size_t MAX_MESSAGES_PER_BATCH = 34;
class ProtoWriteBuffer;
// Max client name length (e.g., "Home Assistant 2026.1.0.dev0" = 28 chars)
static constexpr size_t CLIENT_INFO_NAME_MAX_LEN = 32;
struct ReadPacketBuffer {
const uint8_t *data; // Points directly into frame helper's rx_buf_ (valid until next read_packet call)
uint16_t data_len;
uint16_t type;
};
// Packed packet info structure to minimize memory usage
struct PacketInfo {
// Packed message info structure to minimize memory usage
struct MessageInfo {
uint16_t offset; // Offset in buffer where message starts
uint16_t payload_size; // Size of the message payload
uint8_t message_type; // Message type (0-255)
PacketInfo(uint8_t type, uint16_t off, uint16_t size) : offset(off), payload_size(size), message_type(type) {}
MessageInfo(uint8_t type, uint16_t off, uint16_t size) : offset(off), payload_size(size), message_type(type) {}
};
enum class APIError : uint16_t {
@@ -82,14 +86,23 @@ const LogString *api_error_to_logstr(APIError err);
class APIFrameHelper {
public:
APIFrameHelper() = default;
explicit APIFrameHelper(std::unique_ptr<socket::Socket> socket, const ClientInfo *client_info)
: socket_(std::move(socket)), client_info_(client_info) {}
explicit APIFrameHelper(std::unique_ptr<socket::Socket> socket) : socket_(std::move(socket)) {}
// Get client name (null-terminated)
const char *get_client_name() const { return this->client_name_; }
// Get client peername/IP (null-terminated, cached at init time for availability after socket failure)
const char *get_client_peername() const { return this->client_peername_; }
// Set client name from buffer with length (truncates if needed)
void set_client_name(const char *name, size_t len) {
size_t copy_len = std::min(len, sizeof(this->client_name_) - 1);
memcpy(this->client_name_, name, copy_len);
this->client_name_[copy_len] = '\0';
}
virtual ~APIFrameHelper() = default;
virtual APIError init() = 0;
virtual APIError loop();
virtual APIError read_packet(ReadPacketBuffer *buffer) = 0;
bool can_write_without_blocking() { return this->state_ == State::DATA && this->tx_buf_count_ == 0; }
std::string getpeername() { return socket_->getpeername(); }
int getpeername(struct sockaddr *addr, socklen_t *addrlen) { return socket_->getpeername(addr, addrlen); }
APIError close() {
state_ = State::CLOSED;
@@ -107,11 +120,32 @@ class APIFrameHelper {
}
return APIError::OK;
}
/// Toggle TCP_NODELAY socket option to control Nagle's algorithm.
///
/// This is used to allow log messages to coalesce (Nagle enabled) while keeping
/// state updates low-latency (NODELAY enabled). Without this, many small log
/// packets fill the TCP send buffer, crowding out important state updates.
///
/// State is tracked to minimize setsockopt() overhead - on lwip_raw (ESP8266/RP2040)
/// this is just a boolean assignment; on other platforms it's a lightweight syscall.
///
/// @param enable true to enable NODELAY (disable Nagle), false to enable Nagle
/// @return true if successful or already in desired state
bool set_nodelay(bool enable) {
if (this->nodelay_enabled_ == enable)
return true;
int val = enable ? 1 : 0;
int err = this->socket_->setsockopt(IPPROTO_TCP, TCP_NODELAY, &val, sizeof(int));
if (err == 0) {
this->nodelay_enabled_ = enable;
}
return err == 0;
}
virtual APIError write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) = 0;
// Write multiple protobuf packets in a single operation
// packets contains (message_type, offset, length) for each message in the buffer
// Write multiple protobuf messages in a single operation
// messages contains (message_type, offset, length) for each message in the buffer
// The buffer contains all messages with appropriate padding before each
virtual APIError write_protobuf_packets(ProtoWriteBuffer buffer, std::span<const PacketInfo> packets) = 0;
virtual APIError write_protobuf_messages(ProtoWriteBuffer buffer, std::span<const MessageInfo> messages) = 0;
// Get the frame header padding required by this protocol
uint8_t frame_header_padding() const { return frame_header_padding_; }
// Get the frame footer size required by this protocol
@@ -127,12 +161,6 @@ class APIFrameHelper {
// Use swap trick since shrink_to_fit() is non-binding and may be ignored
std::vector<uint8_t>().swap(this->rx_buf_);
}
// reusable_iovs_: Safe to release unconditionally.
// Only used within write_protobuf_packets() calls - cleared at start,
// populated with pointers, used for writev(), then function returns.
// The iovecs contain stale pointers after the call (data was either sent
// or copied to tx_buf_), and are cleared on next write_protobuf_packets().
std::vector<struct iovec>().swap(this->reusable_iovs_);
}
protected:
@@ -186,12 +214,12 @@ class APIFrameHelper {
// Containers (size varies, but typically 12+ bytes on 32-bit)
std::array<std::unique_ptr<SendBuffer>, API_MAX_SEND_QUEUE> tx_buf_;
std::vector<struct iovec> reusable_iovs_;
std::vector<uint8_t> rx_buf_;
// Pointer to client info (4 bytes on 32-bit)
// Note: The pointed-to ClientInfo object must outlive this APIFrameHelper instance.
const ClientInfo *client_info_{nullptr};
// Client name buffer - stores name from Hello message or initial peername
char client_name_[CLIENT_INFO_NAME_MAX_LEN]{};
// Cached peername/IP address - captured at init time for availability after socket failure
char client_peername_[socket::SOCKADDR_STR_LEN]{};
// Group smaller types together
uint16_t rx_buf_len_ = 0;
@@ -201,7 +229,10 @@ class APIFrameHelper {
uint8_t tx_buf_head_{0};
uint8_t tx_buf_tail_{0};
uint8_t tx_buf_count_{0};
// 8 bytes total, 0 bytes padding
// Tracks TCP_NODELAY state to minimize setsockopt() calls. Initialized to true
// since init_common_() enables NODELAY. Used by set_nodelay() to allow log
// messages to coalesce while keeping state updates low-latency.
bool nodelay_enabled_{true};
// Common initialization for both plaintext and noise protocols
APIError init_common_();

View File

@@ -24,12 +24,29 @@ static const char *const PROLOGUE_INIT = "NoiseAPIInit";
#endif
static constexpr size_t PROLOGUE_INIT_LEN = 12; // strlen("NoiseAPIInit")
#define HELPER_LOG(msg, ...) \
ESP_LOGVV(TAG, "%s (%s): " msg, this->client_info_->name.c_str(), this->client_info_->peername.c_str(), ##__VA_ARGS__)
// Maximum bytes to log in hex format (168 * 3 = 504, under TX buffer size of 512)
static constexpr size_t API_MAX_LOG_BYTES = 168;
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE
#define HELPER_LOG(msg, ...) ESP_LOGVV(TAG, "%s (%s): " msg, this->client_name_, this->client_peername_, ##__VA_ARGS__)
#else
#define HELPER_LOG(msg, ...) ((void) 0)
#endif
#ifdef HELPER_LOG_PACKETS
#define LOG_PACKET_RECEIVED(buffer) ESP_LOGVV(TAG, "Received frame: %s", format_hex_pretty(buffer).c_str())
#define LOG_PACKET_SENDING(data, len) ESP_LOGVV(TAG, "Sending raw: %s", format_hex_pretty(data, len).c_str())
#define LOG_PACKET_RECEIVED(buffer) \
do { \
char hex_buf_[format_hex_pretty_size(API_MAX_LOG_BYTES)]; \
ESP_LOGVV(TAG, "Received frame: %s", \
format_hex_pretty_to(hex_buf_, (buffer).data(), \
(buffer).size() < API_MAX_LOG_BYTES ? (buffer).size() : API_MAX_LOG_BYTES)); \
} while (0)
#define LOG_PACKET_SENDING(data, len) \
do { \
char hex_buf_[format_hex_pretty_size(API_MAX_LOG_BYTES)]; \
ESP_LOGVV(TAG, "Sending raw: %s", \
format_hex_pretty_to(hex_buf_, data, (len) < API_MAX_LOG_BYTES ? (len) : API_MAX_LOG_BYTES)); \
} while (0)
#else
#define LOG_PACKET_RECEIVED(buffer) ((void) 0)
#define LOG_PACKET_SENDING(data, len) ((void) 0)
@@ -415,12 +432,12 @@ APIError APINoiseFrameHelper::read_packet(ReadPacketBuffer *buffer) {
APIError APINoiseFrameHelper::write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) {
// Resize to include MAC space (required for Noise encryption)
buffer.get_buffer()->resize(buffer.get_buffer()->size() + frame_footer_size_);
PacketInfo packet{type, 0,
static_cast<uint16_t>(buffer.get_buffer()->size() - frame_header_padding_ - frame_footer_size_)};
return write_protobuf_packets(buffer, std::span<const PacketInfo>(&packet, 1));
MessageInfo msg{type, 0,
static_cast<uint16_t>(buffer.get_buffer()->size() - frame_header_padding_ - frame_footer_size_)};
return write_protobuf_messages(buffer, std::span<const MessageInfo>(&msg, 1));
}
APIError APINoiseFrameHelper::write_protobuf_packets(ProtoWriteBuffer buffer, std::span<const PacketInfo> packets) {
APIError APINoiseFrameHelper::write_protobuf_messages(ProtoWriteBuffer buffer, std::span<const MessageInfo> messages) {
APIError aerr = state_action_();
if (aerr != APIError::OK) {
return aerr;
@@ -430,20 +447,20 @@ APIError APINoiseFrameHelper::write_protobuf_packets(ProtoWriteBuffer buffer, st
return APIError::WOULD_BLOCK;
}
if (packets.empty()) {
if (messages.empty()) {
return APIError::OK;
}
uint8_t *buffer_data = buffer.get_buffer()->data();
this->reusable_iovs_.clear();
this->reusable_iovs_.reserve(packets.size());
// Stack-allocated iovec array - no heap allocation
StaticVector<struct iovec, MAX_MESSAGES_PER_BATCH> iovs;
uint16_t total_write_len = 0;
// We need to encrypt each packet in place
for (const auto &packet : packets) {
// We need to encrypt each message in place
for (const auto &msg : messages) {
// The buffer already has padding at offset
uint8_t *buf_start = buffer_data + packet.offset;
uint8_t *buf_start = buffer_data + msg.offset;
// Write noise header
buf_start[0] = 0x01; // indicator
@@ -451,10 +468,10 @@ APIError APINoiseFrameHelper::write_protobuf_packets(ProtoWriteBuffer buffer, st
// Write message header (to be encrypted)
const uint8_t msg_offset = 3;
buf_start[msg_offset] = static_cast<uint8_t>(packet.message_type >> 8); // type high byte
buf_start[msg_offset + 1] = static_cast<uint8_t>(packet.message_type); // type low byte
buf_start[msg_offset + 2] = static_cast<uint8_t>(packet.payload_size >> 8); // data_len high byte
buf_start[msg_offset + 3] = static_cast<uint8_t>(packet.payload_size); // data_len low byte
buf_start[msg_offset] = static_cast<uint8_t>(msg.message_type >> 8); // type high byte
buf_start[msg_offset + 1] = static_cast<uint8_t>(msg.message_type); // type low byte
buf_start[msg_offset + 2] = static_cast<uint8_t>(msg.payload_size >> 8); // data_len high byte
buf_start[msg_offset + 3] = static_cast<uint8_t>(msg.payload_size); // data_len low byte
// payload data is already in the buffer starting at offset + 7
// Make sure we have space for MAC
@@ -463,8 +480,8 @@ APIError APINoiseFrameHelper::write_protobuf_packets(ProtoWriteBuffer buffer, st
// Encrypt the message in place
NoiseBuffer mbuf;
noise_buffer_init(mbuf);
noise_buffer_set_inout(mbuf, buf_start + msg_offset, 4 + packet.payload_size,
4 + packet.payload_size + frame_footer_size_);
noise_buffer_set_inout(mbuf, buf_start + msg_offset, 4 + msg.payload_size,
4 + msg.payload_size + frame_footer_size_);
int err = noise_cipherstate_encrypt(send_cipher_, &mbuf);
APIError aerr =
@@ -476,14 +493,14 @@ APIError APINoiseFrameHelper::write_protobuf_packets(ProtoWriteBuffer buffer, st
buf_start[1] = static_cast<uint8_t>(mbuf.size >> 8);
buf_start[2] = static_cast<uint8_t>(mbuf.size);
// Add iovec for this encrypted packet
size_t packet_len = static_cast<size_t>(3 + mbuf.size); // indicator + size + encrypted data
this->reusable_iovs_.push_back({buf_start, packet_len});
total_write_len += packet_len;
// Add iovec for this encrypted message
size_t msg_len = static_cast<size_t>(3 + mbuf.size); // indicator + size + encrypted data
iovs.push_back({buf_start, msg_len});
total_write_len += msg_len;
}
// Send all encrypted packets in one writev call
return this->write_raw_(this->reusable_iovs_.data(), this->reusable_iovs_.size(), total_write_len);
// Send all encrypted messages in one writev call
return this->write_raw_(iovs.data(), iovs.size(), total_write_len);
}
APIError APINoiseFrameHelper::write_frame_(const uint8_t *data, uint16_t len) {

View File

@@ -9,8 +9,8 @@ namespace esphome::api {
class APINoiseFrameHelper final : public APIFrameHelper {
public:
APINoiseFrameHelper(std::unique_ptr<socket::Socket> socket, APINoiseContext &ctx, const ClientInfo *client_info)
: APIFrameHelper(std::move(socket), client_info), ctx_(ctx) {
APINoiseFrameHelper(std::unique_ptr<socket::Socket> socket, APINoiseContext &ctx)
: APIFrameHelper(std::move(socket)), ctx_(ctx) {
// Noise header structure:
// Pos 0: indicator (0x01)
// Pos 1-2: encrypted payload size (16-bit big-endian)
@@ -23,7 +23,7 @@ class APINoiseFrameHelper final : public APIFrameHelper {
APIError loop() override;
APIError read_packet(ReadPacketBuffer *buffer) override;
APIError write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) override;
APIError write_protobuf_packets(ProtoWriteBuffer buffer, std::span<const PacketInfo> packets) override;
APIError write_protobuf_messages(ProtoWriteBuffer buffer, std::span<const MessageInfo> messages) override;
protected:
APIError state_action_();

View File

@@ -1,7 +1,6 @@
#include "api_frame_helper_plaintext.h"
#ifdef USE_API
#ifdef USE_API_PLAINTEXT
#include "api_connection.h" // For ClientInfo struct
#include "esphome/core/application.h"
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
@@ -18,12 +17,29 @@ namespace esphome::api {
static const char *const TAG = "api.plaintext";
#define HELPER_LOG(msg, ...) \
ESP_LOGVV(TAG, "%s (%s): " msg, this->client_info_->name.c_str(), this->client_info_->peername.c_str(), ##__VA_ARGS__)
// Maximum bytes to log in hex format (168 * 3 = 504, under TX buffer size of 512)
static constexpr size_t API_MAX_LOG_BYTES = 168;
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE
#define HELPER_LOG(msg, ...) ESP_LOGVV(TAG, "%s (%s): " msg, this->client_name_, this->client_peername_, ##__VA_ARGS__)
#else
#define HELPER_LOG(msg, ...) ((void) 0)
#endif
#ifdef HELPER_LOG_PACKETS
#define LOG_PACKET_RECEIVED(buffer) ESP_LOGVV(TAG, "Received frame: %s", format_hex_pretty(buffer).c_str())
#define LOG_PACKET_SENDING(data, len) ESP_LOGVV(TAG, "Sending raw: %s", format_hex_pretty(data, len).c_str())
#define LOG_PACKET_RECEIVED(buffer) \
do { \
char hex_buf_[format_hex_pretty_size(API_MAX_LOG_BYTES)]; \
ESP_LOGVV(TAG, "Received frame: %s", \
format_hex_pretty_to(hex_buf_, (buffer).data(), \
(buffer).size() < API_MAX_LOG_BYTES ? (buffer).size() : API_MAX_LOG_BYTES)); \
} while (0)
#define LOG_PACKET_SENDING(data, len) \
do { \
char hex_buf_[format_hex_pretty_size(API_MAX_LOG_BYTES)]; \
ESP_LOGVV(TAG, "Sending raw: %s", \
format_hex_pretty_to(hex_buf_, data, (len) < API_MAX_LOG_BYTES ? (len) : API_MAX_LOG_BYTES)); \
} while (0)
#else
#define LOG_PACKET_RECEIVED(buffer) ((void) 0)
#define LOG_PACKET_SENDING(data, len) ((void) 0)
@@ -216,29 +232,30 @@ APIError APIPlaintextFrameHelper::read_packet(ReadPacketBuffer *buffer) {
return APIError::OK;
}
APIError APIPlaintextFrameHelper::write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) {
PacketInfo packet{type, 0, static_cast<uint16_t>(buffer.get_buffer()->size() - frame_header_padding_)};
return write_protobuf_packets(buffer, std::span<const PacketInfo>(&packet, 1));
MessageInfo msg{type, 0, static_cast<uint16_t>(buffer.get_buffer()->size() - frame_header_padding_)};
return write_protobuf_messages(buffer, std::span<const MessageInfo>(&msg, 1));
}
APIError APIPlaintextFrameHelper::write_protobuf_packets(ProtoWriteBuffer buffer, std::span<const PacketInfo> packets) {
APIError APIPlaintextFrameHelper::write_protobuf_messages(ProtoWriteBuffer buffer,
std::span<const MessageInfo> messages) {
if (state_ != State::DATA) {
return APIError::BAD_STATE;
}
if (packets.empty()) {
if (messages.empty()) {
return APIError::OK;
}
uint8_t *buffer_data = buffer.get_buffer()->data();
this->reusable_iovs_.clear();
this->reusable_iovs_.reserve(packets.size());
// Stack-allocated iovec array - no heap allocation
StaticVector<struct iovec, MAX_MESSAGES_PER_BATCH> iovs;
uint16_t total_write_len = 0;
for (const auto &packet : packets) {
for (const auto &msg : messages) {
// Calculate varint sizes for header layout
uint8_t size_varint_len = api::ProtoSize::varint(static_cast<uint32_t>(packet.payload_size));
uint8_t type_varint_len = api::ProtoSize::varint(static_cast<uint32_t>(packet.message_type));
uint8_t size_varint_len = api::ProtoSize::varint(static_cast<uint32_t>(msg.payload_size));
uint8_t type_varint_len = api::ProtoSize::varint(static_cast<uint32_t>(msg.message_type));
uint8_t total_header_len = 1 + size_varint_len + type_varint_len;
// Calculate where to start writing the header
@@ -266,25 +283,25 @@ APIError APIPlaintextFrameHelper::write_protobuf_packets(ProtoWriteBuffer buffer
//
// The message starts at offset + frame_header_padding_
// So we write the header starting at offset + frame_header_padding_ - total_header_len
uint8_t *buf_start = buffer_data + packet.offset;
uint8_t *buf_start = buffer_data + msg.offset;
uint32_t header_offset = frame_header_padding_ - total_header_len;
// Write the plaintext header
buf_start[header_offset] = 0x00; // indicator
// Encode varints directly into buffer
ProtoVarInt(packet.payload_size).encode_to_buffer_unchecked(buf_start + header_offset + 1, size_varint_len);
ProtoVarInt(packet.message_type)
ProtoVarInt(msg.payload_size).encode_to_buffer_unchecked(buf_start + header_offset + 1, size_varint_len);
ProtoVarInt(msg.message_type)
.encode_to_buffer_unchecked(buf_start + header_offset + 1 + size_varint_len, type_varint_len);
// Add iovec for this packet (header + payload)
size_t packet_len = static_cast<size_t>(total_header_len + packet.payload_size);
this->reusable_iovs_.push_back({buf_start + header_offset, packet_len});
total_write_len += packet_len;
// Add iovec for this message (header + payload)
size_t msg_len = static_cast<size_t>(total_header_len + msg.payload_size);
iovs.push_back({buf_start + header_offset, msg_len});
total_write_len += msg_len;
}
// Send all packets in one writev call
return write_raw_(this->reusable_iovs_.data(), this->reusable_iovs_.size(), total_write_len);
// Send all messages in one writev call
return write_raw_(iovs.data(), iovs.size(), total_write_len);
}
} // namespace esphome::api

View File

@@ -7,8 +7,7 @@ namespace esphome::api {
class APIPlaintextFrameHelper final : public APIFrameHelper {
public:
APIPlaintextFrameHelper(std::unique_ptr<socket::Socket> socket, const ClientInfo *client_info)
: APIFrameHelper(std::move(socket), client_info) {
explicit APIPlaintextFrameHelper(std::unique_ptr<socket::Socket> socket) : APIFrameHelper(std::move(socket)) {
// Plaintext header structure (worst case):
// Pos 0: indicator (0x00)
// Pos 1-3: payload size varint (up to 3 bytes)
@@ -21,7 +20,7 @@ class APIPlaintextFrameHelper final : public APIFrameHelper {
APIError loop() override;
APIError read_packet(ReadPacketBuffer *buffer) override;
APIError write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) override;
APIError write_protobuf_packets(ProtoWriteBuffer buffer, std::span<const PacketInfo> packets) override;
APIError write_protobuf_messages(ProtoWriteBuffer buffer, std::span<const MessageInfo> messages) override;
protected:
APIError try_read_frame_();

View File

@@ -27,7 +27,6 @@ extend google.protobuf.MessageOptions {
extend google.protobuf.FieldOptions {
optional string field_ifdef = 1042;
optional uint32 fixed_array_size = 50007;
optional bool no_zero_copy = 50008 [default=false];
optional bool fixed_array_skip_zero = 50009 [default=false];
optional string fixed_array_size_define = 50010;
optional string fixed_array_with_length_define = 50011;
@@ -80,4 +79,15 @@ extend google.protobuf.FieldOptions {
// Example: [(container_pointer_no_template) = "light::ColorModeMask"]
// generates: const light::ColorModeMask *supported_color_modes{};
optional string container_pointer_no_template = 50014;
// packed_buffer: Expose raw packed buffer instead of decoding into container
// When set on a packed repeated field, the generated code stores a pointer
// to the raw protobuf buffer instead of decoding values. This enables
// zero-copy passthrough when the consumer can decode on-demand.
// The field must be a packed repeated field (packed=true).
// Generates three fields:
// - const uint8_t *<field>_data_{nullptr};
// - uint16_t <field>_length_{0};
// - uint16_t <field>_count_{0};
optional bool packed_buffer = 50015 [default=false];
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -10,6 +10,10 @@
#include "esphome/components/climate/climate_traits.h"
#endif
#ifdef USE_WATER_HEATER
#include "esphome/components/water_heater/water_heater.h"
#endif
#ifdef USE_LIGHT
#include "esphome/components/light/light_traits.h"
#endif

View File

@@ -8,8 +8,12 @@ namespace esphome::api {
static const char *const TAG = "api.service";
#ifdef HAS_PROTO_MESSAGE_DUMP
void APIServerConnectionBase::log_send_message_(const char *name, const std::string &dump) {
ESP_LOGVV(TAG, "send_message %s: %s", name, dump.c_str());
void APIServerConnectionBase::log_send_message_(const char *name, const char *dump) {
ESP_LOGVV(TAG, "send_message %s: %s", name, dump);
}
void APIServerConnectionBase::log_receive_message_(const LogString *name, const ProtoMessage &msg) {
DumpBuffer dump_buf;
ESP_LOGVV(TAG, "%s: %s", LOG_STR_ARG(name), msg.dump_to(dump_buf));
}
#endif
@@ -19,27 +23,16 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
HelloRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_hello_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_hello_request"), msg);
#endif
this->on_hello_request(msg);
break;
}
#ifdef USE_API_PASSWORD
case AuthenticationRequest::MESSAGE_TYPE: {
AuthenticationRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_authentication_request: %s", msg.dump().c_str());
#endif
this->on_authentication_request(msg);
break;
}
#endif
case DisconnectRequest::MESSAGE_TYPE: {
DisconnectRequest msg;
// Empty message: no decode needed
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_disconnect_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_disconnect_request"), msg);
#endif
this->on_disconnect_request(msg);
break;
@@ -48,7 +41,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
DisconnectResponse msg;
// Empty message: no decode needed
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_disconnect_response: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_disconnect_response"), msg);
#endif
this->on_disconnect_response(msg);
break;
@@ -57,7 +50,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
PingRequest msg;
// Empty message: no decode needed
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_ping_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_ping_request"), msg);
#endif
this->on_ping_request(msg);
break;
@@ -66,7 +59,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
PingResponse msg;
// Empty message: no decode needed
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_ping_response: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_ping_response"), msg);
#endif
this->on_ping_response(msg);
break;
@@ -75,7 +68,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
DeviceInfoRequest msg;
// Empty message: no decode needed
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_device_info_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_device_info_request"), msg);
#endif
this->on_device_info_request(msg);
break;
@@ -84,7 +77,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
ListEntitiesRequest msg;
// Empty message: no decode needed
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_list_entities_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_list_entities_request"), msg);
#endif
this->on_list_entities_request(msg);
break;
@@ -93,7 +86,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
SubscribeStatesRequest msg;
// Empty message: no decode needed
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_subscribe_states_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_subscribe_states_request"), msg);
#endif
this->on_subscribe_states_request(msg);
break;
@@ -102,7 +95,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
SubscribeLogsRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_subscribe_logs_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_subscribe_logs_request"), msg);
#endif
this->on_subscribe_logs_request(msg);
break;
@@ -112,7 +105,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
CoverCommandRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_cover_command_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_cover_command_request"), msg);
#endif
this->on_cover_command_request(msg);
break;
@@ -123,7 +116,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
FanCommandRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_fan_command_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_fan_command_request"), msg);
#endif
this->on_fan_command_request(msg);
break;
@@ -134,7 +127,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
LightCommandRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_light_command_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_light_command_request"), msg);
#endif
this->on_light_command_request(msg);
break;
@@ -145,7 +138,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
SwitchCommandRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_switch_command_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_switch_command_request"), msg);
#endif
this->on_switch_command_request(msg);
break;
@@ -156,7 +149,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
SubscribeHomeassistantServicesRequest msg;
// Empty message: no decode needed
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_subscribe_homeassistant_services_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_subscribe_homeassistant_services_request"), msg);
#endif
this->on_subscribe_homeassistant_services_request(msg);
break;
@@ -166,7 +159,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
GetTimeResponse msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_get_time_response: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_get_time_response"), msg);
#endif
this->on_get_time_response(msg);
break;
@@ -176,7 +169,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
SubscribeHomeAssistantStatesRequest msg;
// Empty message: no decode needed
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_subscribe_home_assistant_states_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_subscribe_home_assistant_states_request"), msg);
#endif
this->on_subscribe_home_assistant_states_request(msg);
break;
@@ -187,7 +180,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
HomeAssistantStateResponse msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_home_assistant_state_response: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_home_assistant_state_response"), msg);
#endif
this->on_home_assistant_state_response(msg);
break;
@@ -198,7 +191,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
ExecuteServiceRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_execute_service_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_execute_service_request"), msg);
#endif
this->on_execute_service_request(msg);
break;
@@ -209,7 +202,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
CameraImageRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_camera_image_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_camera_image_request"), msg);
#endif
this->on_camera_image_request(msg);
break;
@@ -220,7 +213,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
ClimateCommandRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_climate_command_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_climate_command_request"), msg);
#endif
this->on_climate_command_request(msg);
break;
@@ -231,7 +224,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
NumberCommandRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_number_command_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_number_command_request"), msg);
#endif
this->on_number_command_request(msg);
break;
@@ -242,7 +235,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
SelectCommandRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_select_command_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_select_command_request"), msg);
#endif
this->on_select_command_request(msg);
break;
@@ -253,7 +246,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
SirenCommandRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_siren_command_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_siren_command_request"), msg);
#endif
this->on_siren_command_request(msg);
break;
@@ -264,7 +257,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
LockCommandRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_lock_command_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_lock_command_request"), msg);
#endif
this->on_lock_command_request(msg);
break;
@@ -275,7 +268,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
ButtonCommandRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_button_command_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_button_command_request"), msg);
#endif
this->on_button_command_request(msg);
break;
@@ -286,7 +279,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
MediaPlayerCommandRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_media_player_command_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_media_player_command_request"), msg);
#endif
this->on_media_player_command_request(msg);
break;
@@ -297,7 +290,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
SubscribeBluetoothLEAdvertisementsRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_subscribe_bluetooth_le_advertisements_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_subscribe_bluetooth_le_advertisements_request"), msg);
#endif
this->on_subscribe_bluetooth_le_advertisements_request(msg);
break;
@@ -308,7 +301,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
BluetoothDeviceRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_bluetooth_device_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_bluetooth_device_request"), msg);
#endif
this->on_bluetooth_device_request(msg);
break;
@@ -319,7 +312,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
BluetoothGATTGetServicesRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_bluetooth_gatt_get_services_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_bluetooth_gatt_get_services_request"), msg);
#endif
this->on_bluetooth_gatt_get_services_request(msg);
break;
@@ -330,7 +323,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
BluetoothGATTReadRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_bluetooth_gatt_read_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_bluetooth_gatt_read_request"), msg);
#endif
this->on_bluetooth_gatt_read_request(msg);
break;
@@ -341,7 +334,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
BluetoothGATTWriteRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_bluetooth_gatt_write_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_bluetooth_gatt_write_request"), msg);
#endif
this->on_bluetooth_gatt_write_request(msg);
break;
@@ -352,7 +345,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
BluetoothGATTReadDescriptorRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_bluetooth_gatt_read_descriptor_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_bluetooth_gatt_read_descriptor_request"), msg);
#endif
this->on_bluetooth_gatt_read_descriptor_request(msg);
break;
@@ -363,7 +356,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
BluetoothGATTWriteDescriptorRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_bluetooth_gatt_write_descriptor_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_bluetooth_gatt_write_descriptor_request"), msg);
#endif
this->on_bluetooth_gatt_write_descriptor_request(msg);
break;
@@ -374,7 +367,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
BluetoothGATTNotifyRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_bluetooth_gatt_notify_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_bluetooth_gatt_notify_request"), msg);
#endif
this->on_bluetooth_gatt_notify_request(msg);
break;
@@ -385,7 +378,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
SubscribeBluetoothConnectionsFreeRequest msg;
// Empty message: no decode needed
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_subscribe_bluetooth_connections_free_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_subscribe_bluetooth_connections_free_request"), msg);
#endif
this->on_subscribe_bluetooth_connections_free_request(msg);
break;
@@ -396,7 +389,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
UnsubscribeBluetoothLEAdvertisementsRequest msg;
// Empty message: no decode needed
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_unsubscribe_bluetooth_le_advertisements_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_unsubscribe_bluetooth_le_advertisements_request"), msg);
#endif
this->on_unsubscribe_bluetooth_le_advertisements_request(msg);
break;
@@ -407,7 +400,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
SubscribeVoiceAssistantRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_subscribe_voice_assistant_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_subscribe_voice_assistant_request"), msg);
#endif
this->on_subscribe_voice_assistant_request(msg);
break;
@@ -418,7 +411,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
VoiceAssistantResponse msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_voice_assistant_response: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_voice_assistant_response"), msg);
#endif
this->on_voice_assistant_response(msg);
break;
@@ -429,7 +422,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
VoiceAssistantEventResponse msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_voice_assistant_event_response: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_voice_assistant_event_response"), msg);
#endif
this->on_voice_assistant_event_response(msg);
break;
@@ -440,7 +433,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
AlarmControlPanelCommandRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_alarm_control_panel_command_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_alarm_control_panel_command_request"), msg);
#endif
this->on_alarm_control_panel_command_request(msg);
break;
@@ -451,7 +444,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
TextCommandRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_text_command_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_text_command_request"), msg);
#endif
this->on_text_command_request(msg);
break;
@@ -462,7 +455,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
DateCommandRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_date_command_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_date_command_request"), msg);
#endif
this->on_date_command_request(msg);
break;
@@ -473,7 +466,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
TimeCommandRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_time_command_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_time_command_request"), msg);
#endif
this->on_time_command_request(msg);
break;
@@ -484,7 +477,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
VoiceAssistantAudio msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_voice_assistant_audio: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_voice_assistant_audio"), msg);
#endif
this->on_voice_assistant_audio(msg);
break;
@@ -495,7 +488,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
ValveCommandRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_valve_command_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_valve_command_request"), msg);
#endif
this->on_valve_command_request(msg);
break;
@@ -506,7 +499,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
DateTimeCommandRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_date_time_command_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_date_time_command_request"), msg);
#endif
this->on_date_time_command_request(msg);
break;
@@ -517,7 +510,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
VoiceAssistantTimerEventResponse msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_voice_assistant_timer_event_response: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_voice_assistant_timer_event_response"), msg);
#endif
this->on_voice_assistant_timer_event_response(msg);
break;
@@ -528,7 +521,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
UpdateCommandRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_update_command_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_update_command_request"), msg);
#endif
this->on_update_command_request(msg);
break;
@@ -539,7 +532,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
VoiceAssistantAnnounceRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_voice_assistant_announce_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_voice_assistant_announce_request"), msg);
#endif
this->on_voice_assistant_announce_request(msg);
break;
@@ -550,7 +543,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
VoiceAssistantConfigurationRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_voice_assistant_configuration_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_voice_assistant_configuration_request"), msg);
#endif
this->on_voice_assistant_configuration_request(msg);
break;
@@ -561,7 +554,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
VoiceAssistantSetConfiguration msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_voice_assistant_set_configuration: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_voice_assistant_set_configuration"), msg);
#endif
this->on_voice_assistant_set_configuration(msg);
break;
@@ -572,7 +565,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
NoiseEncryptionSetKeyRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_noise_encryption_set_key_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_noise_encryption_set_key_request"), msg);
#endif
this->on_noise_encryption_set_key_request(msg);
break;
@@ -583,7 +576,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
BluetoothScannerSetModeRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_bluetooth_scanner_set_mode_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_bluetooth_scanner_set_mode_request"), msg);
#endif
this->on_bluetooth_scanner_set_mode_request(msg);
break;
@@ -594,7 +587,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
ZWaveProxyFrame msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_z_wave_proxy_frame: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_z_wave_proxy_frame"), msg);
#endif
this->on_z_wave_proxy_frame(msg);
break;
@@ -605,7 +598,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
ZWaveProxyRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_z_wave_proxy_request: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_z_wave_proxy_request"), msg);
#endif
this->on_z_wave_proxy_request(msg);
break;
@@ -616,11 +609,33 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
HomeassistantActionResponse msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_homeassistant_action_response: %s", msg.dump().c_str());
this->log_receive_message_(LOG_STR("on_homeassistant_action_response"), msg);
#endif
this->on_homeassistant_action_response(msg);
break;
}
#endif
#ifdef USE_WATER_HEATER
case WaterHeaterCommandRequest::MESSAGE_TYPE: {
WaterHeaterCommandRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
this->log_receive_message_(LOG_STR("on_water_heater_command_request"), msg);
#endif
this->on_water_heater_command_request(msg);
break;
}
#endif
#ifdef USE_IR_RF
case InfraredRFTransmitRawTimingsRequest::MESSAGE_TYPE: {
InfraredRFTransmitRawTimingsRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
this->log_receive_message_(LOG_STR("on_infrared_rf_transmit_raw_timings_request"), msg);
#endif
this->on_infrared_rf_transmit_raw_timings_request(msg);
break;
}
#endif
default:
break;
@@ -632,13 +647,6 @@ void APIServerConnection::on_hello_request(const HelloRequest &msg) {
this->on_fatal_error();
}
}
#ifdef USE_API_PASSWORD
void APIServerConnection::on_authentication_request(const AuthenticationRequest &msg) {
if (!this->send_authenticate_response(msg)) {
this->on_fatal_error();
}
}
#endif
void APIServerConnection::on_disconnect_request(const DisconnectRequest &msg) {
if (!this->send_disconnect_response(msg)) {
this->on_fatal_error();
@@ -826,14 +834,16 @@ void APIServerConnection::on_z_wave_proxy_frame(const ZWaveProxyFrame &msg) { th
#ifdef USE_ZWAVE_PROXY
void APIServerConnection::on_z_wave_proxy_request(const ZWaveProxyRequest &msg) { this->zwave_proxy_request(msg); }
#endif
#ifdef USE_IR_RF
void APIServerConnection::on_infrared_rf_transmit_raw_timings_request(const InfraredRFTransmitRawTimingsRequest &msg) {
this->infrared_rf_transmit_raw_timings(msg);
}
#endif
void APIServerConnection::read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) {
// Check authentication/connection requirements for messages
switch (msg_type) {
case HelloRequest::MESSAGE_TYPE: // No setup required
#ifdef USE_API_PASSWORD
case AuthenticationRequest::MESSAGE_TYPE: // No setup required
#endif
case HelloRequest::MESSAGE_TYPE: // No setup required
case DisconnectRequest::MESSAGE_TYPE: // No setup required
case PingRequest::MESSAGE_TYPE: // No setup required
break; // Skip all checks for these messages

View File

@@ -12,24 +12,22 @@ class APIServerConnectionBase : public ProtoService {
public:
#ifdef HAS_PROTO_MESSAGE_DUMP
protected:
void log_send_message_(const char *name, const std::string &dump);
void log_send_message_(const char *name, const char *dump);
void log_receive_message_(const LogString *name, const ProtoMessage &msg);
public:
#endif
bool send_message(const ProtoMessage &msg, uint8_t message_type) {
#ifdef HAS_PROTO_MESSAGE_DUMP
this->log_send_message_(msg.message_name(), msg.dump());
DumpBuffer dump_buf;
this->log_send_message_(msg.message_name(), msg.dump_to(dump_buf));
#endif
return this->send_message_(msg, message_type);
}
virtual void on_hello_request(const HelloRequest &value){};
#ifdef USE_API_PASSWORD
virtual void on_authentication_request(const AuthenticationRequest &value){};
#endif
virtual void on_disconnect_request(const DisconnectRequest &value){};
virtual void on_disconnect_response(const DisconnectResponse &value){};
virtual void on_ping_request(const PingRequest &value){};
@@ -91,6 +89,10 @@ class APIServerConnectionBase : public ProtoService {
virtual void on_climate_command_request(const ClimateCommandRequest &value){};
#endif
#ifdef USE_WATER_HEATER
virtual void on_water_heater_command_request(const WaterHeaterCommandRequest &value){};
#endif
#ifdef USE_NUMBER
virtual void on_number_command_request(const NumberCommandRequest &value){};
#endif
@@ -217,6 +219,11 @@ class APIServerConnectionBase : public ProtoService {
#ifdef USE_ZWAVE_PROXY
virtual void on_z_wave_proxy_request(const ZWaveProxyRequest &value){};
#endif
#ifdef USE_IR_RF
virtual void on_infrared_rf_transmit_raw_timings_request(const InfraredRFTransmitRawTimingsRequest &value){};
#endif
protected:
void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) override;
};
@@ -224,9 +231,6 @@ class APIServerConnectionBase : public ProtoService {
class APIServerConnection : public APIServerConnectionBase {
public:
virtual bool send_hello_response(const HelloRequest &msg) = 0;
#ifdef USE_API_PASSWORD
virtual bool send_authenticate_response(const AuthenticationRequest &msg) = 0;
#endif
virtual bool send_disconnect_response(const DisconnectRequest &msg) = 0;
virtual bool send_ping_response(const PingRequest &msg) = 0;
virtual bool send_device_info_response(const DeviceInfoRequest &msg) = 0;
@@ -350,12 +354,12 @@ class APIServerConnection : public APIServerConnectionBase {
#endif
#ifdef USE_ZWAVE_PROXY
virtual void zwave_proxy_request(const ZWaveProxyRequest &msg) = 0;
#endif
#ifdef USE_IR_RF
virtual void infrared_rf_transmit_raw_timings(const InfraredRFTransmitRawTimingsRequest &msg) = 0;
#endif
protected:
void on_hello_request(const HelloRequest &msg) override;
#ifdef USE_API_PASSWORD
void on_authentication_request(const AuthenticationRequest &msg) override;
#endif
void on_disconnect_request(const DisconnectRequest &msg) override;
void on_ping_request(const PingRequest &msg) override;
void on_device_info_request(const DeviceInfoRequest &msg) override;
@@ -479,6 +483,9 @@ class APIServerConnection : public APIServerConnectionBase {
#endif
#ifdef USE_ZWAVE_PROXY
void on_z_wave_proxy_request(const ZWaveProxyRequest &msg) override;
#endif
#ifdef USE_IR_RF
void on_infrared_rf_transmit_raw_timings_request(const InfraredRFTransmitRawTimingsRequest &msg) override;
#endif
void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) override;
};

View File

@@ -125,15 +125,18 @@ void APIServer::loop() {
if (!sock)
break;
char peername[socket::SOCKADDR_STR_LEN];
sock->getpeername_to(peername);
// Check if we're at the connection limit
if (this->clients_.size() >= this->max_connections_) {
ESP_LOGW(TAG, "Max connections (%d), rejecting %s", this->max_connections_, sock->getpeername().c_str());
ESP_LOGW(TAG, "Max connections (%d), rejecting %s", this->max_connections_, peername);
// Immediately close - socket destructor will handle cleanup
sock.reset();
continue;
}
ESP_LOGD(TAG, "Accept %s", sock->getpeername().c_str());
ESP_LOGD(TAG, "Accept %s", peername);
auto *conn = new APIConnection(std::move(sock), this);
this->clients_.emplace_back(conn);
@@ -166,8 +169,7 @@ void APIServer::loop() {
// Network is down - disconnect all clients
for (auto &client : this->clients_) {
client->on_fatal_error();
ESP_LOGW(TAG, "%s (%s): Network down; disconnect", client->client_info_.name.c_str(),
client->client_info_.peername.c_str());
client->log_client_(ESPHOME_LOG_LEVEL_WARN, LOG_STR("Network down; disconnect"));
}
// Continue to process and clean up the clients below
}
@@ -184,13 +186,16 @@ void APIServer::loop() {
}
// Rare case: handle disconnection
#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER
this->client_disconnected_trigger_->trigger(client->client_info_.name, client->client_info_.peername);
#endif
#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES
this->unregister_active_action_calls_for_connection(client.get());
#endif
ESP_LOGV(TAG, "Remove connection %s", client->client_info_.name.c_str());
ESP_LOGV(TAG, "Remove connection %s", client->get_name());
#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER
// Save client info before removal for the trigger
std::string client_name(client->get_name());
std::string client_peername(client->get_peername());
#endif
// Swap with the last element and pop (avoids expensive vector shifts)
if (client_index < this->clients_.size() - 1) {
@@ -203,6 +208,11 @@ void APIServer::loop() {
this->status_set_warning();
this->last_connected_ = App.get_loop_component_start_time();
}
#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER
// Fire trigger after client is removed so api.connected reflects the true state
this->client_disconnected_trigger_->trigger(client_name, client_peername);
#endif
// Don't increment client_index since we need to process the swapped element
}
}
@@ -224,38 +234,6 @@ void APIServer::dump_config() {
#endif
}
#ifdef USE_API_PASSWORD
bool APIServer::check_password(const uint8_t *password_data, size_t password_len) const {
// depend only on input password length
const char *a = this->password_.c_str();
uint32_t len_a = this->password_.length();
const char *b = reinterpret_cast<const char *>(password_data);
uint32_t len_b = password_len;
// disable optimization with volatile
volatile uint32_t length = len_b;
volatile const char *left = nullptr;
volatile const char *right = b;
uint8_t result = 0;
if (len_a == length) {
left = *((volatile const char **) &a);
result = 0;
}
if (len_a != length) {
left = b;
result = 1;
}
for (size_t i = 0; i < length; i++) {
result |= *left++ ^ *right++; // NOLINT
}
return result == 0;
}
#endif
void APIServer::handle_disconnect(APIConnection *conn) {}
// Macro for controller update dispatch
@@ -335,14 +313,16 @@ API_DISPATCH_UPDATE(valve::Valve, valve)
API_DISPATCH_UPDATE(media_player::MediaPlayer, media_player)
#endif
#ifdef USE_WATER_HEATER
API_DISPATCH_UPDATE(water_heater::WaterHeater, water_heater)
#endif
#ifdef USE_EVENT
// Event is a special case - unlike other entities with simple state fields,
// events store their state in a member accessed via obj->get_last_event_type()
void APIServer::on_event(event::Event *obj) {
if (obj->is_internal())
return;
for (auto &c : this->clients_)
c->send_event(obj, obj->get_last_event_type());
c->send_event(obj);
}
#endif
@@ -365,6 +345,21 @@ void APIServer::on_zwave_proxy_request(const esphome::api::ProtoMessage &msg) {
}
#endif
#ifdef USE_IR_RF
void APIServer::send_infrared_rf_receive_event([[maybe_unused]] uint32_t device_id, uint32_t key,
const std::vector<int32_t> *timings) {
InfraredRFReceiveEvent resp{};
#ifdef USE_DEVICES
resp.device_id = device_id;
#endif
resp.key = key;
resp.timings = timings;
for (auto &c : this->clients_)
c->send_infrared_rf_receive_event(resp);
}
#endif
#ifdef USE_ALARM_CONTROL_PANEL
API_DISPATCH_UPDATE(alarm_control_panel::AlarmControlPanel, alarm_control_panel)
#endif
@@ -373,10 +368,6 @@ float APIServer::get_setup_priority() const { return setup_priority::AFTER_WIFI;
void APIServer::set_port(uint16_t port) { this->port_ = port; }
#ifdef USE_API_PASSWORD
void APIServer::set_password(const std::string &password) { this->password_ = password; }
#endif
void APIServer::set_batch_delay(uint16_t batch_delay) { this->batch_delay_ = batch_delay; }
#ifdef USE_API_HOMEASSISTANT_SERVICES
@@ -390,7 +381,7 @@ void APIServer::register_action_response_callback(uint32_t call_id, ActionRespon
this->action_response_callbacks_.push_back({call_id, std::move(callback)});
}
void APIServer::handle_action_response(uint32_t call_id, bool success, const std::string &error_message) {
void APIServer::handle_action_response(uint32_t call_id, bool success, StringRef error_message) {
for (auto it = this->action_response_callbacks_.begin(); it != this->action_response_callbacks_.end(); ++it) {
if (it->call_id == call_id) {
auto callback = std::move(it->callback);
@@ -402,7 +393,7 @@ void APIServer::handle_action_response(uint32_t call_id, bool success, const std
}
}
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
void APIServer::handle_action_response(uint32_t call_id, bool success, const std::string &error_message,
void APIServer::handle_action_response(uint32_t call_id, bool success, StringRef error_message,
const uint8_t *response_data, size_t response_data_len) {
for (auto it = this->action_response_callbacks_.begin(); it != this->action_response_callbacks_.end(); ++it) {
if (it->call_id == call_id) {
@@ -420,8 +411,8 @@ void APIServer::handle_action_response(uint32_t call_id, bool success, const std
#ifdef USE_API_HOMEASSISTANT_STATES
// Helper to add subscription (reduces duplication)
void APIServer::add_state_subscription_(const char *entity_id, const char *attribute,
std::function<void(std::string)> f, bool once) {
void APIServer::add_state_subscription_(const char *entity_id, const char *attribute, std::function<void(StringRef)> f,
bool once) {
this->state_subs_.push_back(HomeAssistantStateSubscription{
.entity_id = entity_id, .attribute = attribute, .callback = std::move(f), .once = once,
// entity_id_dynamic_storage and attribute_dynamic_storage remain nullptr (no heap allocation)
@@ -430,7 +421,7 @@ void APIServer::add_state_subscription_(const char *entity_id, const char *attri
// Helper to add subscription with heap-allocated strings (reduces duplication)
void APIServer::add_state_subscription_(std::string entity_id, optional<std::string> attribute,
std::function<void(std::string)> f, bool once) {
std::function<void(StringRef)> f, bool once) {
HomeAssistantStateSubscription sub;
// Allocate heap storage for the strings
sub.entity_id_dynamic_storage = std::make_unique<std::string>(std::move(entity_id));
@@ -450,23 +441,43 @@ void APIServer::add_state_subscription_(std::string entity_id, optional<std::str
// New const char* overload (for internal components - zero allocation)
void APIServer::subscribe_home_assistant_state(const char *entity_id, const char *attribute,
std::function<void(std::string)> f) {
std::function<void(StringRef)> f) {
this->add_state_subscription_(entity_id, attribute, std::move(f), false);
}
void APIServer::get_home_assistant_state(const char *entity_id, const char *attribute,
std::function<void(std::string)> f) {
std::function<void(StringRef)> f) {
this->add_state_subscription_(entity_id, attribute, std::move(f), true);
}
// Existing std::string overload (for custom_api_device.h - heap allocation)
// std::string overload with StringRef callback (zero-allocation callback)
void APIServer::subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute,
std::function<void(std::string)> f) {
std::function<void(StringRef)> f) {
this->add_state_subscription_(std::move(entity_id), std::move(attribute), std::move(f), false);
}
void APIServer::get_home_assistant_state(std::string entity_id, optional<std::string> attribute,
std::function<void(std::string)> f) {
std::function<void(StringRef)> f) {
this->add_state_subscription_(std::move(entity_id), std::move(attribute), std::move(f), true);
}
// Legacy helper: wraps std::string callback and delegates to StringRef version
void APIServer::add_state_subscription_(std::string entity_id, optional<std::string> attribute,
std::function<void(const std::string &)> f, bool once) {
// Wrap callback to convert StringRef -> std::string, then delegate
this->add_state_subscription_(std::move(entity_id), std::move(attribute),
std::function<void(StringRef)>([f = std::move(f)](StringRef state) { f(state.str()); }),
once);
}
// Legacy std::string overload (for custom_api_device.h - converts StringRef to std::string)
void APIServer::subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute,
std::function<void(const std::string &)> f) {
this->add_state_subscription_(std::move(entity_id), std::move(attribute), std::move(f), false);
}
void APIServer::get_home_assistant_state(std::string entity_id, optional<std::string> attribute,
std::function<void(const std::string &)> f) {
this->add_state_subscription_(std::move(entity_id), std::move(attribute), std::move(f), true);
}
@@ -602,8 +613,7 @@ void APIServer::on_shutdown() {
if (!c->send_message(req, DisconnectRequest::MESSAGE_TYPE)) {
// If we can't send the disconnect request directly (tx_buffer full),
// schedule it at the front of the batch so it will be sent with priority
c->schedule_message_front_(nullptr, &APIConnection::try_send_disconnect_request, DisconnectRequest::MESSAGE_TYPE,
DisconnectRequest::ESTIMATED_SIZE);
c->schedule_message_front_(nullptr, DisconnectRequest::MESSAGE_TYPE, DisconnectRequest::ESTIMATED_SIZE);
}
}
}
@@ -635,18 +645,18 @@ uint32_t APIServer::register_active_action_call(uint32_t client_call_id, APIConn
this->active_action_calls_.push_back({action_call_id, client_call_id, conn});
// Schedule automatic cleanup after timeout (client will have given up by then)
this->set_timeout(str_sprintf("action_call_%u", action_call_id), USE_API_ACTION_CALL_TIMEOUT_MS,
[this, action_call_id]() {
ESP_LOGD(TAG, "Action call %u timed out", action_call_id);
this->unregister_active_action_call(action_call_id);
});
// Uses numeric ID overload to avoid heap allocation from str_sprintf
this->set_timeout(action_call_id, USE_API_ACTION_CALL_TIMEOUT_MS, [this, action_call_id]() {
ESP_LOGD(TAG, "Action call %u timed out", action_call_id);
this->unregister_active_action_call(action_call_id);
});
return action_call_id;
}
void APIServer::unregister_active_action_call(uint32_t action_call_id) {
// Cancel the timeout for this action call
this->cancel_timeout(str_sprintf("action_call_%u", action_call_id));
// Cancel the timeout for this action call (uses numeric ID overload)
this->cancel_timeout(action_call_id);
// Swap-and-pop is more efficient than remove_if for unordered vectors
for (size_t i = 0; i < this->active_action_calls_.size(); i++) {
@@ -662,8 +672,8 @@ void APIServer::unregister_active_action_calls_for_connection(APIConnection *con
// Remove all active action calls for disconnected connection using swap-and-pop
for (size_t i = 0; i < this->active_action_calls_.size();) {
if (this->active_action_calls_[i].connection == conn) {
// Cancel the timeout for this action call
this->cancel_timeout(str_sprintf("action_call_%u", this->active_action_calls_[i].action_call_id));
// Cancel the timeout for this action call (uses numeric ID overload)
this->cancel_timeout(this->active_action_calls_[i].action_call_id);
std::swap(this->active_action_calls_[i], this->active_action_calls_.back());
this->active_action_calls_.pop_back();
@@ -674,7 +684,7 @@ void APIServer::unregister_active_action_calls_for_connection(APIConnection *con
}
}
void APIServer::send_action_response(uint32_t action_call_id, bool success, const std::string &error_message) {
void APIServer::send_action_response(uint32_t action_call_id, bool success, StringRef error_message) {
for (auto &call : this->active_action_calls_) {
if (call.action_call_id == action_call_id) {
call.connection->send_execute_service_response(call.client_call_id, success, error_message);
@@ -684,7 +694,7 @@ void APIServer::send_action_response(uint32_t action_call_id, bool success, cons
ESP_LOGW(TAG, "Cannot send response: no active call found for action_call_id %u", action_call_id);
}
#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES_JSON
void APIServer::send_action_response(uint32_t action_call_id, bool success, const std::string &error_message,
void APIServer::send_action_response(uint32_t action_call_id, bool success, StringRef error_message,
const uint8_t *response_data, size_t response_data_len) {
for (auto &call : this->active_action_calls_) {
if (call.action_call_id == action_call_id) {

View File

@@ -10,6 +10,7 @@
#include "esphome/core/component.h"
#include "esphome/core/controller.h"
#include "esphome/core/log.h"
#include "esphome/core/string_ref.h"
#include "list_entities.h"
#include "subscribe_state.h"
#ifdef USE_LOGGER
@@ -59,10 +60,6 @@ class APIServer : public Component,
#endif
#ifdef USE_CAMERA
void on_camera_image(const std::shared_ptr<camera::CameraImage> &image) override;
#endif
#ifdef USE_API_PASSWORD
bool check_password(const uint8_t *password_data, size_t password_len) const;
void set_password(const std::string &password);
#endif
void set_port(uint16_t port);
void set_reboot_timeout(uint32_t reboot_timeout);
@@ -133,6 +130,9 @@ class APIServer : public Component,
#ifdef USE_MEDIA_PLAYER
void on_media_player_update(media_player::MediaPlayer *obj) override;
#endif
#ifdef USE_WATER_HEATER
void on_water_heater_update(water_heater::WaterHeater *obj) override;
#endif
#ifdef USE_API_HOMEASSISTANT_SERVICES
void send_homeassistant_action(const HomeassistantActionRequest &call);
@@ -140,10 +140,10 @@ class APIServer : public Component,
// Action response handling
using ActionResponseCallback = std::function<void(const class ActionResponse &)>;
void register_action_response_callback(uint32_t call_id, ActionResponseCallback callback);
void handle_action_response(uint32_t call_id, bool success, const std::string &error_message);
void handle_action_response(uint32_t call_id, bool success, StringRef error_message);
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
void handle_action_response(uint32_t call_id, bool success, const std::string &error_message,
const uint8_t *response_data, size_t response_data_len);
void handle_action_response(uint32_t call_id, bool success, StringRef error_message, const uint8_t *response_data,
size_t response_data_len);
#endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
#endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES
#endif // USE_API_HOMEASSISTANT_SERVICES
@@ -162,9 +162,9 @@ class APIServer : public Component,
void unregister_active_action_call(uint32_t action_call_id);
void unregister_active_action_calls_for_connection(APIConnection *conn);
// Send response for a specific action call (uses action_call_id, sends client_call_id in response)
void send_action_response(uint32_t action_call_id, bool success, const std::string &error_message);
void send_action_response(uint32_t action_call_id, bool success, StringRef error_message);
#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES_JSON
void send_action_response(uint32_t action_call_id, bool success, const std::string &error_message,
void send_action_response(uint32_t action_call_id, bool success, StringRef error_message,
const uint8_t *response_data, size_t response_data_len);
#endif // USE_API_USER_DEFINED_ACTION_RESPONSES_JSON
#endif // USE_API_USER_DEFINED_ACTION_RESPONSES
@@ -185,6 +185,9 @@ class APIServer : public Component,
#ifdef USE_ZWAVE_PROXY
void on_zwave_proxy_request(const esphome::api::ProtoMessage &msg);
#endif
#ifdef USE_IR_RF
void send_infrared_rf_receive_event(uint32_t device_id, uint32_t key, const std::vector<int32_t> *timings);
#endif
bool is_connected(bool state_subscription_only = false) const;
@@ -192,7 +195,7 @@ class APIServer : public Component,
struct HomeAssistantStateSubscription {
const char *entity_id; // Pointer to flash (internal) or heap (external)
const char *attribute; // Pointer to flash or nullptr (nullptr means no attribute)
std::function<void(std::string)> callback;
std::function<void(StringRef)> callback;
bool once;
// Dynamic storage for external components using std::string API (custom_api_device.h)
@@ -202,14 +205,20 @@ class APIServer : public Component,
};
// New const char* overload (for internal components - zero allocation)
void subscribe_home_assistant_state(const char *entity_id, const char *attribute, std::function<void(std::string)> f);
void get_home_assistant_state(const char *entity_id, const char *attribute, std::function<void(std::string)> f);
void subscribe_home_assistant_state(const char *entity_id, const char *attribute, std::function<void(StringRef)> f);
void get_home_assistant_state(const char *entity_id, const char *attribute, std::function<void(StringRef)> f);
// Existing std::string overload (for custom_api_device.h - heap allocation)
// std::string overload with StringRef callback (for custom_api_device.h with zero-allocation callback)
void subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute,
std::function<void(std::string)> f);
std::function<void(StringRef)> f);
void get_home_assistant_state(std::string entity_id, optional<std::string> attribute,
std::function<void(std::string)> f);
std::function<void(StringRef)> f);
// Legacy std::string overload (for custom_api_device.h - converts StringRef to std::string for callback)
void subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute,
std::function<void(const std::string &)> f);
void get_home_assistant_state(std::string entity_id, optional<std::string> attribute,
std::function<void(const std::string &)> f);
const std::vector<HomeAssistantStateSubscription> &get_state_subs() const;
#endif
@@ -233,10 +242,13 @@ class APIServer : public Component,
#endif // USE_API_NOISE
#ifdef USE_API_HOMEASSISTANT_STATES
// Helper methods to reduce code duplication
void add_state_subscription_(const char *entity_id, const char *attribute, std::function<void(std::string)> f,
void add_state_subscription_(const char *entity_id, const char *attribute, std::function<void(StringRef)> f,
bool once);
void add_state_subscription_(std::string entity_id, optional<std::string> attribute, std::function<void(StringRef)> f,
bool once);
// Legacy helper: wraps std::string callback and delegates to StringRef version
void add_state_subscription_(std::string entity_id, optional<std::string> attribute,
std::function<void(std::string)> f, bool once);
std::function<void(const std::string &)> f, bool once);
#endif // USE_API_HOMEASSISTANT_STATES
// Pointers and pointer-like types first (4 bytes each)
std::unique_ptr<socket::Socket> socket_ = nullptr;
@@ -253,9 +265,6 @@ class APIServer : public Component,
// Vectors and strings (12 bytes each on 32-bit)
std::vector<std::unique_ptr<APIConnection>> clients_;
#ifdef USE_API_PASSWORD
std::string password_;
#endif
std::vector<uint8_t> shared_write_buffer_; // Shared proto write buffer for all connections
#ifdef USE_API_HOMEASSISTANT_STATES
std::vector<HomeAssistantStateSubscription> state_subs_;

View File

@@ -16,7 +16,7 @@ with warnings.catch_warnings():
import contextlib
from esphome.const import CONF_KEY, CONF_PASSWORD, CONF_PORT, __version__
from esphome.const import CONF_KEY, CONF_PORT, __version__
from esphome.core import CORE
from . import CONF_ENCRYPTION
@@ -35,7 +35,6 @@ async def async_run_logs(config: dict[str, Any], addresses: list[str]) -> None:
conf = config["api"]
name = config["esphome"]["name"]
port: int = int(conf[CONF_PORT])
password: str = conf[CONF_PASSWORD]
noise_psk: str | None = None
if (encryption := conf.get(CONF_ENCRYPTION)) and (key := encryption.get(CONF_KEY)):
noise_psk = key
@@ -50,7 +49,7 @@ async def async_run_logs(config: dict[str, Any], addresses: list[str]) -> None:
cli = APIClient(
addresses[0], # Primary address for compatibility
port,
password,
"", # Password auth removed in 2026.1.0
client_info=f"ESPHome Logs {__version__}",
noise_psk=noise_psk,
addresses=addresses, # Pass all addresses for automatic retry

View File

@@ -122,21 +122,36 @@ class CustomAPIDevice {
* subscribe_homeassistant_state(&CustomNativeAPI::on_state_changed, "climate.kitchen", "current_temperature");
* }
*
* void on_state_changed(std::string state) {
* // State of sensor.weather_forecast is `state`
* void on_state_changed(StringRef state) {
* // State of climate.kitchen current_temperature is `state`
* // Use state.c_str() for C string, state.str() for std::string
* }
* ```
*
* @tparam T The class type creating the service, automatically deduced from the function pointer.
* @param callback The member function to call when the entity state changes.
* @param callback The member function to call when the entity state changes (zero-allocation).
* @param entity_id The entity_id to track.
* @param attribute The entity state attribute to track.
*/
template<typename T>
void subscribe_homeassistant_state(void (T::*callback)(StringRef), const std::string &entity_id,
const std::string &attribute = "") {
auto f = std::bind(callback, (T *) this, std::placeholders::_1);
global_api_server->subscribe_home_assistant_state(entity_id, optional<std::string>(attribute), std::move(f));
}
/** Subscribe to the state (or attribute state) of an entity from Home Assistant (legacy std::string version).
*
* @deprecated Use the StringRef overload for zero-allocation callbacks. Will be removed in 2027.1.0.
*/
template<typename T>
ESPDEPRECATED("Use void callback(StringRef) instead. Will be removed in 2027.1.0.", "2026.1.0")
void subscribe_homeassistant_state(void (T::*callback)(std::string), const std::string &entity_id,
const std::string &attribute = "") {
auto f = std::bind(callback, (T *) this, std::placeholders::_1);
global_api_server->subscribe_home_assistant_state(entity_id, optional<std::string>(attribute), f);
// Explicit type to disambiguate overload resolution
global_api_server->subscribe_home_assistant_state(entity_id, optional<std::string>(attribute),
std::function<void(const std::string &)>(f));
}
/** Subscribe to the state (or attribute state) of an entity from Home Assistant.
@@ -148,23 +163,45 @@ class CustomAPIDevice {
* subscribe_homeassistant_state(&CustomNativeAPI::on_state_changed, "sensor.weather_forecast");
* }
*
* void on_state_changed(std::string entity_id, std::string state) {
* void on_state_changed(const std::string &entity_id, StringRef state) {
* // State of `entity_id` is `state`
* }
* ```
*
* @tparam T The class type creating the service, automatically deduced from the function pointer.
* @param callback The member function to call when the entity state changes.
* @param callback The member function to call when the entity state changes (zero-allocation for state).
* @param entity_id The entity_id to track.
* @param attribute The entity state attribute to track.
*/
template<typename T>
void subscribe_homeassistant_state(void (T::*callback)(const std::string &, StringRef), const std::string &entity_id,
const std::string &attribute = "") {
auto f = std::bind(callback, (T *) this, entity_id, std::placeholders::_1);
global_api_server->subscribe_home_assistant_state(entity_id, optional<std::string>(attribute), std::move(f));
}
/** Subscribe to the state (or attribute state) of an entity from Home Assistant (legacy std::string version).
*
* @deprecated Use the StringRef overload for zero-allocation callbacks. Will be removed in 2027.1.0.
*/
template<typename T>
ESPDEPRECATED("Use void callback(const std::string &, StringRef) instead. Will be removed in 2027.1.0.", "2026.1.0")
void subscribe_homeassistant_state(void (T::*callback)(std::string, std::string), const std::string &entity_id,
const std::string &attribute = "") {
auto f = std::bind(callback, (T *) this, entity_id, std::placeholders::_1);
global_api_server->subscribe_home_assistant_state(entity_id, optional<std::string>(attribute), f);
// Explicit type to disambiguate overload resolution
global_api_server->subscribe_home_assistant_state(entity_id, optional<std::string>(attribute),
std::function<void(const std::string &)>(f));
}
#else
template<typename T>
void subscribe_homeassistant_state(void (T::*callback)(StringRef), const std::string &entity_id,
const std::string &attribute = "") {
static_assert(sizeof(T) == 0,
"subscribe_homeassistant_state() requires 'homeassistant_states: true' in the 'api:' section "
"of your YAML configuration");
}
template<typename T>
void subscribe_homeassistant_state(void (T::*callback)(std::string), const std::string &entity_id,
const std::string &attribute = "") {
@@ -173,6 +210,14 @@ class CustomAPIDevice {
"of your YAML configuration");
}
template<typename T>
void subscribe_homeassistant_state(void (T::*callback)(const std::string &, StringRef), const std::string &entity_id,
const std::string &attribute = "") {
static_assert(sizeof(T) == 0,
"subscribe_homeassistant_state() requires 'homeassistant_states: true' in the 'api:' section "
"of your YAML configuration");
}
template<typename T>
void subscribe_homeassistant_state(void (T::*callback)(std::string, std::string), const std::string &entity_id,
const std::string &attribute = "") {
@@ -195,7 +240,7 @@ class CustomAPIDevice {
*/
void call_homeassistant_service(const std::string &service_name) {
HomeassistantActionRequest resp;
resp.set_service(StringRef(service_name));
resp.service = StringRef(service_name);
global_api_server->send_homeassistant_action(resp);
}
@@ -215,12 +260,12 @@ class CustomAPIDevice {
*/
void call_homeassistant_service(const std::string &service_name, const std::map<std::string, std::string> &data) {
HomeassistantActionRequest resp;
resp.set_service(StringRef(service_name));
resp.service = StringRef(service_name);
resp.data.init(data.size());
for (auto &it : data) {
auto &kv = resp.data.emplace_back();
kv.set_key(StringRef(it.first));
kv.value = it.second;
kv.key = StringRef(it.first);
kv.value = StringRef(it.second); // data map lives until send completes
}
global_api_server->send_homeassistant_action(resp);
}
@@ -237,7 +282,7 @@ class CustomAPIDevice {
*/
void fire_homeassistant_event(const std::string &event_name) {
HomeassistantActionRequest resp;
resp.set_service(StringRef(event_name));
resp.service = StringRef(event_name);
resp.is_event = true;
global_api_server->send_homeassistant_action(resp);
}
@@ -257,13 +302,13 @@ class CustomAPIDevice {
*/
void fire_homeassistant_event(const std::string &service_name, const std::map<std::string, std::string> &data) {
HomeassistantActionRequest resp;
resp.set_service(StringRef(service_name));
resp.service = StringRef(service_name);
resp.is_event = true;
resp.data.init(data.size());
for (auto &it : data) {
auto &kv = resp.data.emplace_back();
kv.set_key(StringRef(it.first));
kv.value = it.second;
kv.key = StringRef(it.first);
kv.value = StringRef(it.second); // data map lives until send completes
}
global_api_server->send_homeassistant_action(resp);
}

View File

@@ -67,10 +67,10 @@ template<typename... Ts> class TemplatableKeyValuePair {
// the callback is invoked synchronously while the message is on the stack).
class ActionResponse {
public:
ActionResponse(bool success, const std::string &error_message) : success_(success), error_message_(error_message) {}
ActionResponse(bool success, StringRef error_message) : success_(success), error_message_(error_message) {}
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
ActionResponse(bool success, const std::string &error_message, const uint8_t *data, size_t data_len)
ActionResponse(bool success, StringRef error_message, const uint8_t *data, size_t data_len)
: success_(success), error_message_(error_message) {
if (data == nullptr || data_len == 0)
return;
@@ -147,13 +147,23 @@ template<typename... Ts> class HomeAssistantServiceCallAction : public Action<Ts
void play(const Ts &...x) override {
HomeassistantActionRequest resp;
std::string service_value = this->service_.value(x...);
resp.set_service(StringRef(service_value));
resp.service = StringRef(service_value);
resp.is_event = this->flags_.is_event;
this->populate_service_map(resp.data, this->data_, x...);
this->populate_service_map(resp.data_template, this->data_template_, x...);
this->populate_service_map(resp.variables, this->variables_, x...);
// Local storage for lambda-evaluated strings - lives until after send
FixedVector<std::string> data_storage;
FixedVector<std::string> data_template_storage;
FixedVector<std::string> variables_storage;
this->populate_service_map(resp.data, this->data_, data_storage, x...);
this->populate_service_map(resp.data_template, this->data_template_, data_template_storage, x...);
this->populate_service_map(resp.variables, this->variables_, variables_storage, x...);
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
// IMPORTANT: Declare at outer scope so it lives until send_homeassistant_action returns.
std::string response_template_value;
#endif
if (this->flags_.wants_status) {
// Generate a unique call ID for this service call
static uint32_t call_id_counter = 1;
@@ -164,8 +174,8 @@ template<typename... Ts> class HomeAssistantServiceCallAction : public Action<Ts
resp.wants_response = true;
// Set response template if provided
if (this->flags_.has_response_template) {
std::string response_template_value = this->response_template_.value(x...);
resp.response_template = response_template_value;
response_template_value = this->response_template_.value(x...);
resp.response_template = StringRef(response_template_value);
}
}
#endif
@@ -205,12 +215,31 @@ template<typename... Ts> class HomeAssistantServiceCallAction : public Action<Ts
}
template<typename VectorType, typename SourceType>
static void populate_service_map(VectorType &dest, SourceType &source, Ts... x) {
static void populate_service_map(VectorType &dest, SourceType &source, FixedVector<std::string> &value_storage,
Ts... x) {
dest.init(source.size());
// Count non-static strings to allocate exact storage needed
size_t lambda_count = 0;
for (const auto &it : source) {
if (!it.value.is_static_string()) {
lambda_count++;
}
}
value_storage.init(lambda_count);
for (auto &it : source) {
auto &kv = dest.emplace_back();
kv.set_key(StringRef(it.key));
kv.value = it.value.value(x...);
kv.key = StringRef(it.key);
if (it.value.is_static_string()) {
// Static string from YAML - zero allocation
kv.value = StringRef(it.value.get_static_string());
} else {
// Lambda evaluation - store result, reference it
value_storage.push_back(it.value.value(x...));
kv.value = StringRef(value_storage.back());
}
}
}

View File

@@ -73,6 +73,12 @@ LIST_ENTITIES_HANDLER(media_player, media_player::MediaPlayer, ListEntitiesMedia
LIST_ENTITIES_HANDLER(alarm_control_panel, alarm_control_panel::AlarmControlPanel,
ListEntitiesAlarmControlPanelResponse)
#endif
#ifdef USE_WATER_HEATER
LIST_ENTITIES_HANDLER(water_heater, water_heater::WaterHeater, ListEntitiesWaterHeaterResponse)
#endif
#ifdef USE_INFRARED
LIST_ENTITIES_HANDLER(infrared, infrared::Infrared, ListEntitiesInfraredResponse)
#endif
#ifdef USE_EVENT
LIST_ENTITIES_HANDLER(event, event::Event, ListEntitiesEventResponse)
#endif

View File

@@ -9,11 +9,10 @@ namespace esphome::api {
class APIConnection;
// Macro for generating ListEntitiesIterator handlers
// Calls schedule_message_ with try_send_*_info
// Calls schedule_message_ which dispatches to try_send_*_info
#define LIST_ENTITIES_HANDLER(entity_type, EntityClass, ResponseType) \
bool ListEntitiesIterator::on_##entity_type(EntityClass *entity) { /* NOLINT(bugprone-macro-parentheses) */ \
return this->client_->schedule_message_(entity, &APIConnection::try_send_##entity_type##_info, \
ResponseType::MESSAGE_TYPE, ResponseType::ESTIMATED_SIZE); \
return this->client_->schedule_message_(entity, ResponseType::MESSAGE_TYPE, ResponseType::ESTIMATED_SIZE); \
}
class ListEntitiesIterator : public ComponentIterator {
@@ -82,6 +81,12 @@ class ListEntitiesIterator : public ComponentIterator {
#ifdef USE_ALARM_CONTROL_PANEL
bool on_alarm_control_panel(alarm_control_panel::AlarmControlPanel *entity) override;
#endif
#ifdef USE_WATER_HEATER
bool on_water_heater(water_heater::WaterHeater *entity) override;
#endif
#ifdef USE_INFRARED
bool on_infrared(infrared::Infrared *entity) override;
#endif
#ifdef USE_EVENT
bool on_event(event::Event *entity) override;
#endif

View File

@@ -139,12 +139,4 @@ void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) {
}
}
#ifdef HAS_PROTO_MESSAGE_DUMP
std::string ProtoMessage::dump() const {
std::string out;
this->dump_to(out);
return out;
}
#endif
} // namespace esphome::api

View File

@@ -39,6 +39,24 @@ inline constexpr int64_t decode_zigzag64(uint64_t value) {
return (value & 1) ? static_cast<int64_t>(~(value >> 1)) : static_cast<int64_t>(value >> 1);
}
/// Count number of varints in a packed buffer
inline uint16_t count_packed_varints(const uint8_t *data, size_t len) {
uint16_t count = 0;
while (len > 0) {
// Skip varint bytes until we find one without continuation bit
while (len > 0 && (*data & 0x80)) {
data++;
len--;
}
if (len > 0) {
data++;
len--;
count++;
}
}
return count;
}
/*
* StringRef Ownership Model for API Protocol Messages
* ===================================================
@@ -54,16 +72,16 @@ inline constexpr int64_t decode_zigzag64(uint64_t value) {
* 3. Global/static strings: StringRef(GLOBAL_CONSTANT) - Always safe
* 4. Local variables: Safe ONLY if encoding happens before function returns:
* std::string temp = compute_value();
* msg.set_field(StringRef(temp));
* msg.field = StringRef(temp);
* return this->send_message(msg); // temp is valid during encoding
*
* Unsafe Patterns (WILL cause crashes/corruption):
* 1. Temporaries: msg.set_field(StringRef(obj.get_string())) // get_string() returns by value
* 2. Concatenation: msg.set_field(StringRef(str1 + str2)) // Result is temporary
* 1. Temporaries: msg.field = StringRef(obj.get_string()) // get_string() returns by value
* 2. Concatenation: msg.field = StringRef(str1 + str2) // Result is temporary
*
* For unsafe patterns, store in a local variable first:
* std::string temp = get_string(); // or str1 + str2
* msg.set_field(StringRef(temp));
* msg.field = StringRef(temp);
*
* The send_*_response pattern ensures proper lifetime management by encoding
* within the same function scope where temporaries are created.
@@ -180,9 +198,10 @@ class ProtoVarInt {
uint64_t value_;
};
// Forward declaration for decode_to_message and encode_to_writer
class ProtoMessage;
// Forward declarations for decode_to_message, encode_message and encode_packed_sint32
class ProtoDecodableMessage;
class ProtoMessage;
class ProtoSize;
class ProtoLengthDelimited {
public:
@@ -334,15 +353,71 @@ class ProtoWriteBuffer {
void encode_sint64(uint32_t field_id, int64_t value, bool force = false) {
this->encode_uint64(field_id, encode_zigzag64(value), force);
}
void encode_message(uint32_t field_id, const ProtoMessage &value, bool force = false);
/// Encode a packed repeated sint32 field (zero-copy from vector)
void encode_packed_sint32(uint32_t field_id, const std::vector<int32_t> &values);
void encode_message(uint32_t field_id, const ProtoMessage &value);
std::vector<uint8_t> *get_buffer() const { return buffer_; }
protected:
std::vector<uint8_t> *buffer_;
};
// Forward declaration
class ProtoSize;
#ifdef HAS_PROTO_MESSAGE_DUMP
/**
* Fixed-size buffer for message dumps - avoids heap allocation.
* Sized to match the logger's default tx_buffer_size (512 bytes)
* since anything larger gets truncated anyway.
*/
class DumpBuffer {
public:
// Matches default tx_buffer_size in logger component
static constexpr size_t CAPACITY = 512;
DumpBuffer() : pos_(0) { buf_[0] = '\0'; }
DumpBuffer &append(const char *str) {
if (str) {
append_impl_(str, strlen(str));
}
return *this;
}
DumpBuffer &append(const char *str, size_t len) {
append_impl_(str, len);
return *this;
}
DumpBuffer &append(size_t n, char c) {
size_t space = CAPACITY - 1 - pos_;
if (n > space)
n = space;
if (n > 0) {
memset(buf_ + pos_, c, n);
pos_ += n;
buf_[pos_] = '\0';
}
return *this;
}
const char *c_str() const { return buf_; }
size_t size() const { return pos_; }
private:
void append_impl_(const char *str, size_t len) {
size_t space = CAPACITY - 1 - pos_;
if (len > space)
len = space;
if (len > 0) {
memcpy(buf_ + pos_, str, len);
pos_ += len;
buf_[pos_] = '\0';
}
}
char buf_[CAPACITY];
size_t pos_;
};
#endif
class ProtoMessage {
public:
@@ -352,8 +427,7 @@ class ProtoMessage {
// Default implementation for messages with no fields
virtual void calculate_size(ProtoSize &size) const {}
#ifdef HAS_PROTO_MESSAGE_DUMP
std::string dump() const;
virtual void dump_to(std::string &out) const = 0;
virtual const char *dump_to(DumpBuffer &out) const = 0;
virtual const char *message_name() const { return "unknown"; }
#endif
};
@@ -792,10 +866,45 @@ class ProtoSize {
}
}
}
/**
* @brief Calculate size of a packed repeated sint32 field
*/
inline void add_packed_sint32(uint32_t field_id_size, const std::vector<int32_t> &values) {
if (values.empty())
return;
size_t packed_size = 0;
for (int value : values) {
packed_size += varint(encode_zigzag32(value));
}
// field_id + length varint + packed data
total_size_ += field_id_size + varint(static_cast<uint32_t>(packed_size)) + static_cast<uint32_t>(packed_size);
}
};
// Implementation of encode_packed_sint32 - must be after ProtoSize is defined
inline void ProtoWriteBuffer::encode_packed_sint32(uint32_t field_id, const std::vector<int32_t> &values) {
if (values.empty())
return;
// Calculate packed size
size_t packed_size = 0;
for (int value : values) {
packed_size += ProtoSize::varint(encode_zigzag32(value));
}
// Write tag (LENGTH_DELIMITED) + length + all zigzag-encoded values
this->encode_field_raw(field_id, WIRE_TYPE_LENGTH_DELIMITED);
this->encode_varint_raw(packed_size);
for (int value : values) {
this->encode_varint_raw(encode_zigzag32(value));
}
}
// Implementation of encode_message - must be after ProtoMessage is defined
inline void ProtoWriteBuffer::encode_message(uint32_t field_id, const ProtoMessage &value, bool force) {
inline void ProtoWriteBuffer::encode_message(uint32_t field_id, const ProtoMessage &value) {
this->encode_field_raw(field_id, 2); // type 2: Length-delimited message
// Calculate the message size first
@@ -833,9 +942,6 @@ class ProtoService {
virtual bool is_authenticated() = 0;
virtual bool is_connection_setup() = 0;
virtual void on_fatal_error() = 0;
#ifdef USE_API_PASSWORD
virtual void on_unauthenticated_access() = 0;
#endif
virtual void on_no_setup_connection() = 0;
/**
* Create a buffer with a reserved size.
@@ -873,20 +979,7 @@ class ProtoService {
return true;
}
inline bool check_authenticated_() {
#ifdef USE_API_PASSWORD
if (!this->check_connection_setup_()) {
return false;
}
if (!this->is_authenticated()) {
this->on_unauthenticated_access();
return false;
}
return true;
#else
return this->check_connection_setup_();
#endif
}
inline bool check_authenticated_() { return this->check_connection_setup_(); }
};
} // namespace esphome::api

View File

@@ -60,6 +60,9 @@ INITIAL_STATE_HANDLER(media_player, media_player::MediaPlayer)
#ifdef USE_ALARM_CONTROL_PANEL
INITIAL_STATE_HANDLER(alarm_control_panel, alarm_control_panel::AlarmControlPanel)
#endif
#ifdef USE_WATER_HEATER
INITIAL_STATE_HANDLER(water_heater, water_heater::WaterHeater)
#endif
#ifdef USE_UPDATE
INITIAL_STATE_HANDLER(update, update::UpdateEntity)
#endif

View File

@@ -76,6 +76,12 @@ class InitialStateIterator : public ComponentIterator {
#ifdef USE_ALARM_CONTROL_PANEL
bool on_alarm_control_panel(alarm_control_panel::AlarmControlPanel *entity) override;
#endif
#ifdef USE_WATER_HEATER
bool on_water_heater(water_heater::WaterHeater *entity) override;
#endif
#ifdef USE_INFRARED
bool on_infrared(infrared::Infrared *infrared) override { return true; };
#endif
#ifdef USE_EVENT
bool on_event(event::Event *event) override { return true; };
#endif

View File

@@ -46,7 +46,7 @@ template<typename... Ts> class UserServiceBase : public UserServiceDescriptor {
ListEntitiesServicesResponse encode_list_service_response() override {
ListEntitiesServicesResponse msg;
msg.set_name(StringRef(this->name_));
msg.name = StringRef(this->name_);
msg.key = this->key_;
msg.supports_response = this->supports_response_;
std::array<enums::ServiceArgType, sizeof...(Ts)> arg_types = {to_service_arg_type<Ts>()...};
@@ -54,7 +54,7 @@ template<typename... Ts> class UserServiceBase : public UserServiceDescriptor {
for (size_t i = 0; i < sizeof...(Ts); i++) {
auto &arg = msg.args.emplace_back();
arg.type = arg_types[i];
arg.set_name(StringRef(this->arg_names_[i]));
arg.name = StringRef(this->arg_names_[i]);
}
return msg;
}
@@ -108,7 +108,7 @@ template<typename... Ts> class UserServiceDynamic : public UserServiceDescriptor
ListEntitiesServicesResponse encode_list_service_response() override {
ListEntitiesServicesResponse msg;
msg.set_name(StringRef(this->name_));
msg.name = StringRef(this->name_);
msg.key = this->key_;
msg.supports_response = enums::SUPPORTS_RESPONSE_NONE; // Dynamic services don't support responses yet
std::array<enums::ServiceArgType, sizeof...(Ts)> arg_types = {to_service_arg_type<Ts>()...};
@@ -116,7 +116,7 @@ template<typename... Ts> class UserServiceDynamic : public UserServiceDescriptor
for (size_t i = 0; i < sizeof...(Ts); i++) {
auto &arg = msg.args.emplace_back();
arg.type = arg_types[i];
arg.set_name(StringRef(this->arg_names_[i]));
arg.name = StringRef(this->arg_names_[i]);
}
return msg;
}
@@ -255,7 +255,7 @@ template<typename... Ts> class APIRespondAction : public Action<Ts...> {
bool return_response = std::get<1>(args);
if (!return_response) {
// Client doesn't want response data, just send success/error
this->parent_->send_action_response(call_id, success, error_message);
this->parent_->send_action_response(call_id, success, StringRef(error_message));
return;
}
}
@@ -265,12 +265,12 @@ template<typename... Ts> class APIRespondAction : public Action<Ts...> {
json::JsonBuilder builder;
this->json_builder_(x..., builder.root());
std::string json_str = builder.serialize();
this->parent_->send_action_response(call_id, success, error_message,
this->parent_->send_action_response(call_id, success, StringRef(error_message),
reinterpret_cast<const uint8_t *>(json_str.data()), json_str.size());
return;
}
#endif
this->parent_->send_action_response(call_id, success, error_message);
this->parent_->send_action_response(call_id, success, StringRef(error_message));
}
protected:

View File

@@ -0,0 +1,14 @@
import esphome.codegen as cg
CODEOWNERS = ["@jasstrong", "@ximex", "@freekode"]
aqi_ns = cg.esphome_ns.namespace("aqi")
AQICalculatorType = aqi_ns.enum("AQICalculatorType")
CONF_AQI = "aqi"
CONF_CALCULATION_TYPE = "calculation_type"
AQI_CALCULATION_TYPE = {
"CAQI": AQICalculatorType.CAQI_TYPE,
"AQI": AQICalculatorType.AQI_TYPE,
}

View File

@@ -0,0 +1,12 @@
#pragma once
#include <cstdint>
namespace esphome::aqi {
class AbstractAQICalculator {
public:
virtual uint16_t get_aqi(float pm2_5_value, float pm10_0_value) = 0;
};
} // namespace esphome::aqi

View File

@@ -0,0 +1,56 @@
#pragma once
#include <cmath>
#include <limits>
#include "abstract_aqi_calculator.h"
// https://document.airnow.gov/technical-assistance-document-for-the-reporting-of-daily-air-quailty.pdf
namespace esphome::aqi {
class AQICalculator : public AbstractAQICalculator {
public:
uint16_t get_aqi(float pm2_5_value, float pm10_0_value) override {
float pm2_5_index = calculate_index(pm2_5_value, PM2_5_GRID);
float pm10_0_index = calculate_index(pm10_0_value, PM10_0_GRID);
return static_cast<uint16_t>(std::round((pm2_5_index < pm10_0_index) ? pm10_0_index : pm2_5_index));
}
protected:
static constexpr int NUM_LEVELS = 6;
static constexpr int INDEX_GRID[NUM_LEVELS][2] = {{0, 50}, {51, 100}, {101, 150}, {151, 200}, {201, 300}, {301, 500}};
static constexpr float PM2_5_GRID[NUM_LEVELS][2] = {{0.0f, 9.0f}, {9.1f, 35.4f},
{35.5f, 55.4f}, {55.5f, 125.4f},
{125.5f, 225.4f}, {225.5f, std::numeric_limits<float>::max()}};
static constexpr float PM10_0_GRID[NUM_LEVELS][2] = {{0.0f, 54.0f}, {55.0f, 154.0f},
{155.0f, 254.0f}, {255.0f, 354.0f},
{355.0f, 424.0f}, {425.0f, std::numeric_limits<float>::max()}};
static float calculate_index(float value, const float array[NUM_LEVELS][2]) {
int grid_index = get_grid_index(value, array);
if (grid_index == -1) {
return -1.0f;
}
float aqi_lo = INDEX_GRID[grid_index][0];
float aqi_hi = INDEX_GRID[grid_index][1];
float conc_lo = array[grid_index][0];
float conc_hi = array[grid_index][1];
return (value - conc_lo) * (aqi_hi - aqi_lo) / (conc_hi - conc_lo) + aqi_lo;
}
static int get_grid_index(float value, const float array[NUM_LEVELS][2]) {
for (int i = 0; i < NUM_LEVELS; i++) {
if (value >= array[i][0] && value <= array[i][1]) {
return i;
}
}
return -1;
}
};
} // namespace esphome::aqi

View File

@@ -3,8 +3,7 @@
#include "caqi_calculator.h"
#include "aqi_calculator.h"
namespace esphome {
namespace hm3301 {
namespace esphome::aqi {
enum AQICalculatorType { CAQI_TYPE = 0, AQI_TYPE = 1 };
@@ -12,18 +11,17 @@ class AQICalculatorFactory {
public:
AbstractAQICalculator *get_calculator(AQICalculatorType type) {
if (type == 0) {
return caqi_calculator_;
return &this->caqi_calculator_;
} else if (type == 1) {
return aqi_calculator_;
return &this->aqi_calculator_;
}
return nullptr;
}
protected:
CAQICalculator *caqi_calculator_ = new CAQICalculator();
AQICalculator *aqi_calculator_ = new AQICalculator();
CAQICalculator caqi_calculator_;
AQICalculator aqi_calculator_;
};
} // namespace hm3301
} // namespace esphome
} // namespace esphome::aqi

View File

@@ -0,0 +1,51 @@
#include "aqi_sensor.h"
#include "esphome/core/log.h"
namespace esphome::aqi {
static const char *const TAG = "aqi";
void AQISensor::setup() {
if (this->pm_2_5_sensor_ != nullptr) {
this->pm_2_5_sensor_->add_on_state_callback([this](float value) {
this->pm_2_5_value_ = value;
// Defer calculation to avoid double-publishing if both sensors update in the same loop
this->defer("update", [this]() { this->calculate_aqi_(); });
});
}
if (this->pm_10_0_sensor_ != nullptr) {
this->pm_10_0_sensor_->add_on_state_callback([this](float value) {
this->pm_10_0_value_ = value;
this->defer("update", [this]() { this->calculate_aqi_(); });
});
}
}
void AQISensor::dump_config() {
ESP_LOGCONFIG(TAG, "AQI Sensor:");
ESP_LOGCONFIG(TAG, " Calculation Type: %s", this->aqi_calc_type_ == AQI_TYPE ? "AQI" : "CAQI");
if (this->pm_2_5_sensor_ != nullptr) {
ESP_LOGCONFIG(TAG, " PM2.5 Sensor: '%s'", this->pm_2_5_sensor_->get_name().c_str());
}
if (this->pm_10_0_sensor_ != nullptr) {
ESP_LOGCONFIG(TAG, " PM10 Sensor: '%s'", this->pm_10_0_sensor_->get_name().c_str());
}
LOG_SENSOR(" ", "AQI", this);
}
void AQISensor::calculate_aqi_() {
if (std::isnan(this->pm_2_5_value_) || std::isnan(this->pm_10_0_value_)) {
return;
}
AbstractAQICalculator *calculator = this->aqi_calculator_factory_.get_calculator(this->aqi_calc_type_);
if (calculator == nullptr) {
ESP_LOGW(TAG, "Unknown AQI calculator type");
return;
}
uint16_t aqi = calculator->get_aqi(this->pm_2_5_value_, this->pm_10_0_value_);
this->publish_state(aqi);
}
} // namespace esphome::aqi

View File

@@ -0,0 +1,31 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
#include "aqi_calculator_factory.h"
namespace esphome::aqi {
class AQISensor : public sensor::Sensor, public Component {
public:
void setup() override;
void dump_config() override;
float get_setup_priority() const override { return setup_priority::DATA; }
void set_pm_2_5_sensor(sensor::Sensor *sensor) { this->pm_2_5_sensor_ = sensor; }
void set_pm_10_0_sensor(sensor::Sensor *sensor) { this->pm_10_0_sensor_ = sensor; }
void set_aqi_calculation_type(AQICalculatorType type) { this->aqi_calc_type_ = type; }
protected:
void calculate_aqi_();
sensor::Sensor *pm_2_5_sensor_{nullptr};
sensor::Sensor *pm_10_0_sensor_{nullptr};
AQICalculatorType aqi_calc_type_{AQI_TYPE};
AQICalculatorFactory aqi_calculator_factory_;
float pm_2_5_value_{NAN};
float pm_10_0_value_{NAN};
};
} // namespace esphome::aqi

View File

@@ -0,0 +1,53 @@
#pragma once
#include <cmath>
#include <limits>
#include "abstract_aqi_calculator.h"
namespace esphome::aqi {
class CAQICalculator : public AbstractAQICalculator {
public:
uint16_t get_aqi(float pm2_5_value, float pm10_0_value) override {
float pm2_5_index = calculate_index(pm2_5_value, PM2_5_GRID);
float pm10_0_index = calculate_index(pm10_0_value, PM10_0_GRID);
return static_cast<uint16_t>(std::round((pm2_5_index < pm10_0_index) ? pm10_0_index : pm2_5_index));
}
protected:
static constexpr int NUM_LEVELS = 5;
static constexpr int INDEX_GRID[NUM_LEVELS][2] = {{0, 25}, {26, 50}, {51, 75}, {76, 100}, {101, 400}};
static constexpr float PM2_5_GRID[NUM_LEVELS][2] = {
{0.0f, 15.0f}, {15.1f, 30.0f}, {30.1f, 55.0f}, {55.1f, 110.0f}, {110.1f, std::numeric_limits<float>::max()}};
static constexpr float PM10_0_GRID[NUM_LEVELS][2] = {
{0.0f, 25.0f}, {25.1f, 50.0f}, {50.1f, 90.0f}, {90.1f, 180.0f}, {180.1f, std::numeric_limits<float>::max()}};
static float calculate_index(float value, const float array[NUM_LEVELS][2]) {
int grid_index = get_grid_index(value, array);
if (grid_index == -1) {
return -1.0f;
}
float aqi_lo = INDEX_GRID[grid_index][0];
float aqi_hi = INDEX_GRID[grid_index][1];
float conc_lo = array[grid_index][0];
float conc_hi = array[grid_index][1];
return (value - conc_lo) * (aqi_hi - aqi_lo) / (conc_hi - conc_lo) + aqi_lo;
}
static int get_grid_index(float value, const float array[NUM_LEVELS][2]) {
for (int i = 0; i < NUM_LEVELS; i++) {
if (value >= array[i][0] && value <= array[i][1]) {
return i;
}
}
return -1;
}
};
} // namespace esphome::aqi

View File

@@ -0,0 +1,51 @@
import esphome.codegen as cg
from esphome.components import sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_PM_2_5,
CONF_PM_10_0,
DEVICE_CLASS_AQI,
STATE_CLASS_MEASUREMENT,
)
from . import AQI_CALCULATION_TYPE, CONF_CALCULATION_TYPE, aqi_ns
CODEOWNERS = ["@jasstrong"]
DEPENDENCIES = ["sensor"]
UNIT_INDEX = "index"
AQISensor = aqi_ns.class_("AQISensor", sensor.Sensor, cg.Component)
CONFIG_SCHEMA = (
sensor.sensor_schema(
AQISensor,
unit_of_measurement=UNIT_INDEX,
accuracy_decimals=0,
device_class=DEVICE_CLASS_AQI,
state_class=STATE_CLASS_MEASUREMENT,
)
.extend(
{
cv.Required(CONF_PM_2_5): cv.use_id(sensor.Sensor),
cv.Required(CONF_PM_10_0): cv.use_id(sensor.Sensor),
cv.Required(CONF_CALCULATION_TYPE): cv.enum(
AQI_CALCULATION_TYPE, upper=True
),
}
)
.extend(cv.COMPONENT_SCHEMA)
)
async def to_code(config):
var = await sensor.new_sensor(config)
await cg.register_component(var, config)
pm_2_5_sensor = await cg.get_variable(config[CONF_PM_2_5])
cg.add(var.set_pm_2_5_sensor(pm_2_5_sensor))
pm_10_0_sensor = await cg.get_variable(config[CONF_PM_10_0])
cg.add(var.set_pm_10_0_sensor(pm_10_0_sensor))
cg.add(var.set_aqi_calculation_type(config[CONF_CALCULATION_TYPE]))

View File

@@ -305,12 +305,14 @@ bool AS3935Component::calibrate_oscillator() {
}
void AS3935Component::tune_antenna() {
ESP_LOGI(TAG, "Starting antenna tuning");
uint8_t div_ratio = this->read_div_ratio();
uint8_t tune_val = this->read_capacitance();
ESP_LOGI(TAG, "Division Ratio is set to: %d", div_ratio);
ESP_LOGI(TAG, "Internal Capacitor is set to: %d", tune_val);
ESP_LOGI(TAG, "Displaying oscillator on INT pin. Measure its frequency - multiply value by Division Ratio");
ESP_LOGI(TAG,
"Starting antenna tuning\n"
"Division Ratio is set to: %d\n"
"Internal Capacitor is set to: %d\n"
"Displaying oscillator on INT pin. Measure its frequency - multiply value by Division Ratio",
div_ratio, tune_val);
this->display_oscillator(true, ANTFREQ);
}

View File

@@ -1,37 +1,50 @@
# Dummy integration to allow relying on AsyncTCP
# Async TCP client support for all platforms
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.const import (
PLATFORM_BK72XX,
PLATFORM_ESP32,
PLATFORM_ESP8266,
PLATFORM_LN882X,
PLATFORM_RTL87XX,
)
from esphome.core import CORE, CoroPriority, coroutine_with_priority
CODEOWNERS = ["@esphome/core"]
DEPENDENCIES = ["network"]
CONFIG_SCHEMA = cv.All(
cv.Schema({}),
cv.only_with_arduino,
cv.only_on(
[
PLATFORM_ESP32,
PLATFORM_ESP8266,
PLATFORM_BK72XX,
PLATFORM_LN882X,
PLATFORM_RTL87XX,
]
),
)
def AUTO_LOAD() -> list[str]:
# Socket component needed for platforms using socket-based implementation
# ESP32, ESP8266, RP2040, and LibreTiny use AsyncTCP libraries, others use sockets
if (
not CORE.is_esp32
and not CORE.is_esp8266
and not CORE.is_rp2040
and not CORE.is_libretiny
):
return ["socket"]
return []
# Support all platforms - Arduino/ESP-IDF get libraries, other platforms use socket implementation
CONFIG_SCHEMA = cv.Schema({})
@coroutine_with_priority(CoroPriority.NETWORK_TRANSPORT)
async def to_code(config):
if CORE.is_esp32 or CORE.is_libretiny:
if CORE.is_esp32:
# https://github.com/ESP32Async/AsyncTCP
from esphome.components.esp32 import add_idf_component
add_idf_component(name="esp32async/asynctcp", ref="3.4.91")
elif CORE.is_libretiny:
# https://github.com/ESP32Async/AsyncTCP
cg.add_library("ESP32Async/AsyncTCP", "3.4.5")
elif CORE.is_esp8266:
# https://github.com/ESP32Async/ESPAsyncTCP
cg.add_library("ESP32Async/ESPAsyncTCP", "2.0.0")
elif CORE.is_rp2040:
# https://github.com/khoih-prog/AsyncTCP_RP2040W
cg.add_library("khoih-prog/AsyncTCP_RP2040W", "1.2.0")
# Other platforms (host, etc) use socket-based implementation
def FILTER_SOURCE_FILES() -> list[str]:
# Exclude socket implementation for platforms that use AsyncTCP libraries
if CORE.is_esp32 or CORE.is_esp8266 or CORE.is_rp2040 or CORE.is_libretiny:
return ["async_tcp_socket.cpp"]
return []

View File

@@ -0,0 +1,16 @@
#pragma once
#include "esphome/core/defines.h"
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
// Use AsyncTCP library for ESP32 (Arduino or ESP-IDF) and LibreTiny
#include <AsyncTCP.h>
#elif defined(USE_ESP8266)
// Use ESPAsyncTCP library for ESP8266 (always Arduino)
#include <ESPAsyncTCP.h>
#elif defined(USE_RP2040)
// Use AsyncTCP_RP2040W library for RP2040
#include <AsyncTCP_RP2040W.h>
#else
// Use socket-based implementation for other platforms
#include "async_tcp_socket.h"
#endif

View File

@@ -0,0 +1,162 @@
#include "async_tcp_socket.h"
#if !defined(USE_ESP32) && !defined(USE_ESP8266) && !defined(USE_RP2040) && !defined(USE_LIBRETINY) && \
(defined(USE_SOCKET_IMPL_LWIP_SOCKETS) || defined(USE_SOCKET_IMPL_BSD_SOCKETS))
#include "esphome/components/network/util.h"
#include "esphome/core/log.h"
#include <cerrno>
#include <sys/select.h>
namespace esphome::async_tcp {
static const char *const TAG = "async_tcp";
// Read buffer size matches TCP MSS (1500 MTU - 40 bytes IP/TCP headers).
// This implementation only runs on ESP-IDF and host which have ample stack.
static constexpr size_t READ_BUFFER_SIZE = 1460;
bool AsyncClient::connect(const char *host, uint16_t port) {
if (connected_ || connecting_) {
ESP_LOGW(TAG, "Already connected/connecting");
return false;
}
// Resolve address
struct sockaddr_storage addr;
socklen_t addrlen = esphome::socket::set_sockaddr((struct sockaddr *) &addr, sizeof(addr), host, port);
if (addrlen == 0) {
ESP_LOGE(TAG, "Invalid address: %s", host);
if (error_cb_)
error_cb_(error_arg_, this, -1);
return false;
}
// Create socket with loop monitoring
int family = ((struct sockaddr *) &addr)->sa_family;
socket_ = esphome::socket::socket_loop_monitored(family, SOCK_STREAM, IPPROTO_TCP);
if (!socket_) {
ESP_LOGE(TAG, "Failed to create socket");
if (error_cb_)
error_cb_(error_arg_, this, -1);
return false;
}
socket_->setblocking(false);
int err = socket_->connect((struct sockaddr *) &addr, addrlen);
if (err == 0) {
// Connection succeeded immediately (rare, but possible for localhost)
connected_ = true;
if (connect_cb_)
connect_cb_(connect_arg_, this);
return true;
}
if (errno != EINPROGRESS) {
ESP_LOGE(TAG, "Connect failed: %d", errno);
close();
if (error_cb_)
error_cb_(error_arg_, this, errno);
return false;
}
connecting_ = true;
return true;
}
void AsyncClient::close() {
socket_.reset();
bool was_connected = connected_;
connected_ = false;
connecting_ = false;
if (was_connected && disconnect_cb_)
disconnect_cb_(disconnect_arg_, this);
}
size_t AsyncClient::write(const char *data, size_t len) {
if (!socket_ || !connected_)
return 0;
ssize_t sent = socket_->write(data, len);
if (sent < 0) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
ESP_LOGE(TAG, "Write error: %d", errno);
close();
if (error_cb_)
error_cb_(error_arg_, this, errno);
}
return 0;
}
return sent;
}
void AsyncClient::loop() {
if (!socket_)
return;
if (connecting_) {
// For connecting, we need to check writability, not readability
// The Application's select() only monitors read FDs, so we do our own check here
// For ESP platforms lwip_select() might be faster, but this code isn't used
// on those platforms anyway. If it was, we'd fix the Application select()
// to report writability instead of doing it this way.
int fd = socket_->get_fd();
if (fd < 0) {
ESP_LOGW(TAG, "Invalid socket fd");
close();
return;
}
fd_set writefds;
FD_ZERO(&writefds);
FD_SET(fd, &writefds);
struct timeval tv = {0, 0};
int ret = select(fd + 1, nullptr, &writefds, nullptr, &tv);
if (ret > 0 && FD_ISSET(fd, &writefds)) {
int error = 0;
socklen_t len = sizeof(error);
if (socket_->getsockopt(SOL_SOCKET, SO_ERROR, &error, &len) == 0 && error == 0) {
connecting_ = false;
connected_ = true;
if (connect_cb_)
connect_cb_(connect_arg_, this);
} else {
ESP_LOGW(TAG, "Connection failed: %d", error);
close();
if (error_cb_)
error_cb_(error_arg_, this, error);
}
} else if (ret < 0) {
ESP_LOGE(TAG, "Select error: %d", errno);
close();
if (error_cb_)
error_cb_(error_arg_, this, errno);
}
} else if (connected_) {
// For connected sockets, use the Application's select() results
if (!socket_->ready())
return;
uint8_t buf[READ_BUFFER_SIZE];
ssize_t len = socket_->read(buf, READ_BUFFER_SIZE);
if (len == 0) {
ESP_LOGI(TAG, "Connection closed by peer");
close();
} else if (len > 0) {
if (data_cb_)
data_cb_(data_arg_, this, buf, len);
} else if (errno != EAGAIN && errno != EWOULDBLOCK) {
ESP_LOGW(TAG, "Read error: %d", errno);
close();
if (error_cb_)
error_cb_(error_arg_, this, errno);
}
}
}
} // namespace esphome::async_tcp
#endif

View File

@@ -0,0 +1,73 @@
#pragma once
#include "esphome/core/defines.h"
#if !defined(USE_ESP32) && !defined(USE_ESP8266) && !defined(USE_RP2040) && !defined(USE_LIBRETINY) && \
(defined(USE_SOCKET_IMPL_LWIP_SOCKETS) || defined(USE_SOCKET_IMPL_BSD_SOCKETS))
#include "esphome/components/socket/socket.h"
#include <functional>
#include <memory>
#include <string>
#include <utility>
namespace esphome::async_tcp {
/// AsyncClient API for platforms using sockets (ESP-IDF, host, etc.)
/// NOTE: This class is NOT thread-safe. All methods must be called from the main loop.
class AsyncClient {
public:
using AcConnectHandler = std::function<void(void *, AsyncClient *)>;
using AcDataHandler = std::function<void(void *, AsyncClient *, void *data, size_t len)>;
using AcErrorHandler = std::function<void(void *, AsyncClient *, int8_t error)>;
AsyncClient() = default;
~AsyncClient() = default;
[[nodiscard]] bool connect(const char *host, uint16_t port);
void close();
[[nodiscard]] bool connected() const { return connected_; }
size_t write(const char *data, size_t len);
void onConnect(AcConnectHandler cb, void *arg = nullptr) { // NOLINT(readability-identifier-naming)
connect_cb_ = std::move(cb);
connect_arg_ = arg;
}
void onDisconnect(AcConnectHandler cb, void *arg = nullptr) { // NOLINT(readability-identifier-naming)
disconnect_cb_ = std::move(cb);
disconnect_arg_ = arg;
}
/// Set data callback. NOTE: data pointer is only valid during callback execution.
void onData(AcDataHandler cb, void *arg = nullptr) { // NOLINT(readability-identifier-naming)
data_cb_ = std::move(cb);
data_arg_ = arg;
}
void onError(AcErrorHandler cb, void *arg = nullptr) { // NOLINT(readability-identifier-naming)
error_cb_ = std::move(cb);
error_arg_ = arg;
}
// Must be called from loop()
void loop();
private:
std::unique_ptr<esphome::socket::Socket> socket_;
AcConnectHandler connect_cb_{nullptr};
void *connect_arg_{nullptr};
AcConnectHandler disconnect_cb_{nullptr};
void *disconnect_arg_{nullptr};
AcDataHandler data_cb_{nullptr};
void *data_arg_{nullptr};
AcErrorHandler error_cb_{nullptr};
void *error_arg_{nullptr};
bool connected_{false};
bool connecting_{false};
};
} // namespace esphome::async_tcp
// Expose AsyncClient in global namespace to match library behavior
using esphome::async_tcp::AsyncClient; // NOLINT(google-global-names-in-headers)
#endif

View File

@@ -21,7 +21,9 @@ bool ATCMiThermometer::parse_device(const esp32_ble_tracker::ESPBTDevice &device
ESP_LOGVV(TAG, "parse_device(): unknown MAC address.");
return false;
}
ESP_LOGVV(TAG, "parse_device(): MAC address %s found.", device.address_str().c_str());
char addr_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
const char *addr_str = device.address_str_to(addr_buf);
ESP_LOGVV(TAG, "parse_device(): MAC address %s found.", addr_str);
bool success = false;
for (auto &service_data : device.get_service_datas()) {
@@ -32,7 +34,7 @@ bool ATCMiThermometer::parse_device(const esp32_ble_tracker::ESPBTDevice &device
if (!(parse_message_(service_data.data, *res))) {
continue;
}
if (!(report_results_(res, device.address_str()))) {
if (!(report_results_(res, addr_str))) {
continue;
}
if (res->temperature.has_value() && this->temperature_ != nullptr)
@@ -103,13 +105,13 @@ bool ATCMiThermometer::parse_message_(const std::vector<uint8_t> &message, Parse
return true;
}
bool ATCMiThermometer::report_results_(const optional<ParseResult> &result, const std::string &address) {
bool ATCMiThermometer::report_results_(const optional<ParseResult> &result, const char *address) {
if (!result.has_value()) {
ESP_LOGVV(TAG, "report_results(): no results available.");
return false;
}
ESP_LOGD(TAG, "Got ATC MiThermometer (%s):", address.c_str());
ESP_LOGD(TAG, "Got ATC MiThermometer (%s):", address);
if (result->temperature.has_value()) {
ESP_LOGD(TAG, " Temperature: %.1f °C", *result->temperature);

View File

@@ -41,7 +41,7 @@ class ATCMiThermometer : public Component, public esp32_ble_tracker::ESPBTDevice
optional<ParseResult> parse_header_(const esp32_ble_tracker::ServiceData &service_data);
bool parse_message_(const std::vector<uint8_t> &message, ParseResult &result);
bool report_results_(const optional<ParseResult> &result, const std::string &address);
bool report_results_(const optional<ParseResult> &result, const char *address);
};
} // namespace atc_mithermometer

View File

@@ -1,6 +1,6 @@
#include "audio_reader.h"
#ifdef USE_ESP_IDF
#ifdef USE_ESP32
#include "esphome/core/defines.h"
#include "esphome/core/hal.h"

View File

@@ -1,6 +1,6 @@
#pragma once
#ifdef USE_ESP_IDF
#ifdef USE_ESP32
#include "audio.h"
#include "audio_transfer_buffer.h"

View File

@@ -22,7 +22,8 @@ bool BParasite::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
ESP_LOGVV(TAG, "parse_device(): unknown MAC address.");
return false;
}
ESP_LOGVV(TAG, "parse_device(): MAC address %s found.", device.address_str().c_str());
char addr_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
ESP_LOGVV(TAG, "parse_device(): MAC address %s found.", device.address_str_to(addr_buf));
const auto &service_datas = device.get_service_datas();
if (service_datas.size() != 1) {
ESP_LOGE(TAG, "Unexpected service_datas size (%d)", service_datas.size());

View File

@@ -3,6 +3,7 @@
#include "bedjet_hub.h"
#include "bedjet_child.h"
#include "bedjet_const.h"
#include "esphome/components/esp32_ble/ble_uuid.h"
#include "esphome/core/application.h"
#include <cinttypes>
@@ -193,8 +194,9 @@ bool BedJetHub::discover_characteristics_() {
result = false;
} else if (descr->uuid.get_uuid().len != ESP_UUID_LEN_16 ||
descr->uuid.get_uuid().uuid.uuid16 != ESP_GATT_UUID_CHAR_CLIENT_CONFIG) {
char uuid_buf[espbt::UUID_STR_LEN];
ESP_LOGW(TAG, "Config descriptor 0x%x (uuid %s) is not a client config char uuid", this->char_handle_status_,
descr->uuid.to_string().c_str());
descr->uuid.to_str(uuid_buf));
result = false;
} else {
this->config_descr_status_ = descr->handle;
@@ -216,11 +218,14 @@ bool BedJetHub::discover_characteristics_() {
}
}
ESP_LOGI(TAG, "[%s] Discovered service characteristics: ", this->get_name().c_str());
ESP_LOGI(TAG, " - Command char: 0x%x", this->char_handle_cmd_);
ESP_LOGI(TAG, " - Status char: 0x%x", this->char_handle_status_);
ESP_LOGI(TAG, " - config descriptor: 0x%x", this->config_descr_status_);
ESP_LOGI(TAG, " - Name char: 0x%x", this->char_handle_name_);
ESP_LOGI(TAG,
"[%s] Discovered service characteristics:\n"
" - Command char: 0x%x\n"
" - Status char: 0x%x\n"
" - config descriptor: 0x%x\n"
" - Name char: 0x%x",
this->get_name().c_str(), this->char_handle_cmd_, this->char_handle_status_, this->config_descr_status_,
this->char_handle_name_);
return result;
}

View File

@@ -1,12 +1,7 @@
import esphome.codegen as cg
from esphome.components import ble_client, climate
from esphome.components import climate
import esphome.config_validation as cv
from esphome.const import (
CONF_HEAT_MODE,
CONF_RECEIVE_TIMEOUT,
CONF_TEMPERATURE_SOURCE,
CONF_TIME_ID,
)
from esphome.const import CONF_HEAT_MODE, CONF_TEMPERATURE_SOURCE
from .. import BEDJET_CLIENT_SCHEMA, bedjet_ns, register_bedjet_child
@@ -38,22 +33,6 @@ CONFIG_SCHEMA = (
}
)
.extend(cv.polling_component_schema("60s"))
.extend(
# TODO: remove compat layer.
{
cv.Optional(ble_client.CONF_BLE_CLIENT_ID): cv.invalid(
"The 'ble_client_id' option has been removed. Please migrate "
"to the new `bedjet_id` option in the `bedjet` component.\n"
"See https://esphome.io/components/climate/bedjet/"
),
cv.Optional(CONF_TIME_ID): cv.invalid(
"The 'time_id' option has been moved to the `bedjet` component."
),
cv.Optional(CONF_RECEIVE_TIMEOUT): cv.invalid(
"The 'receive_timeout' option has been moved to the `bedjet` component."
),
}
)
.extend(BEDJET_CLIENT_SCHEMA)
)

View File

@@ -164,21 +164,21 @@ void BedJetClimate::control(const ClimateCall &call) {
return;
}
} else if (call.has_custom_preset()) {
const char *preset = call.get_custom_preset();
auto preset = call.get_custom_preset();
bool result;
if (strcmp(preset, "M1") == 0) {
if (preset == "M1") {
result = this->parent_->button_memory1();
} else if (strcmp(preset, "M2") == 0) {
} else if (preset == "M2") {
result = this->parent_->button_memory2();
} else if (strcmp(preset, "M3") == 0) {
} else if (preset == "M3") {
result = this->parent_->button_memory3();
} else if (strcmp(preset, "LTD HT") == 0) {
} else if (preset == "LTD HT") {
result = this->parent_->button_heat();
} else if (strcmp(preset, "EXT HT") == 0) {
} else if (preset == "EXT HT") {
result = this->parent_->button_ext_heat();
} else {
ESP_LOGW(TAG, "Unsupported preset: %s", preset);
ESP_LOGW(TAG, "Unsupported preset: %.*s", (int) preset.size(), preset.c_str());
return;
}
@@ -208,10 +208,11 @@ void BedJetClimate::control(const ClimateCall &call) {
this->set_fan_mode_(fan_mode);
}
} else if (call.has_custom_fan_mode()) {
const char *fan_mode = call.get_custom_fan_mode();
auto fan_index = bedjet_fan_speed_to_step(fan_mode);
auto fan_mode = call.get_custom_fan_mode();
auto fan_index = bedjet_fan_speed_to_step(fan_mode.c_str());
if (fan_index <= 19) {
ESP_LOGV(TAG, "[%s] Converted fan mode %s to bedjet fan step %d", this->get_name().c_str(), fan_mode, fan_index);
ESP_LOGV(TAG, "[%s] Converted fan mode %.*s to bedjet fan step %d", this->get_name().c_str(),
(int) fan_mode.size(), fan_mode.c_str(), fan_index);
bool result = this->parent_->set_fan_index(fan_index);
if (result) {
this->set_custom_fan_mode_(fan_mode);

View File

@@ -20,16 +20,6 @@ CONFIG_SCHEMA = (
device_class=DEVICE_CLASS_ILLUMINANCE,
state_class=STATE_CLASS_MEASUREMENT,
)
.extend(
{
cv.Optional("resolution"): cv.invalid(
"The 'resolution' option has been removed. The optimal value is now dynamically calculated."
),
cv.Optional("measurement_duration"): cv.invalid(
"The 'measurement_duration' option has been removed. The optimal value is now dynamically calculated."
),
}
)
.extend(cv.polling_component_schema("60s"))
.extend(i2c.i2c_device_schema(0x23))
)

View File

@@ -3,7 +3,7 @@ from logging import getLogger
from esphome import automation, core
from esphome.automation import Condition, maybe_simple_id
import esphome.codegen as cg
from esphome.components import mqtt, web_server
from esphome.components import mqtt, web_server, zigbee
from esphome.components.const import CONF_ON_STATE_CHANGE
import esphome.config_validation as cv
from esphome.const import (
@@ -439,6 +439,7 @@ def validate_publish_initial_state(value):
_BINARY_SENSOR_SCHEMA = (
cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA)
.extend(cv.MQTT_COMPONENT_SCHEMA)
.extend(zigbee.BINARY_SENSOR_SCHEMA)
.extend(
{
cv.GenerateID(): cv.declare_id(BinarySensor),
@@ -520,6 +521,7 @@ _BINARY_SENSOR_SCHEMA = (
_BINARY_SENSOR_SCHEMA.add_extra(entity_duplicate_validator("binary_sensor"))
_BINARY_SENSOR_SCHEMA.add_extra(zigbee.validate_binary_sensor)
def binary_sensor_schema(
@@ -621,6 +623,8 @@ async def setup_binary_sensor_core_(var, config):
if web_server_config := config.get(CONF_WEB_SERVER):
await web_server.add_entity_config(var, web_server_config)
await zigbee.setup_binary_sensor(var, config)
async def register_binary_sensor(var, config):
if not CORE.has_id(config[CONF_ID]):

View File

@@ -21,8 +21,10 @@ void MultiClickTrigger::on_state_(bool state) {
// Start matching
MultiClickTriggerEvent evt = this->timing_[0];
if (evt.state == state) {
ESP_LOGV(TAG, "START min=%" PRIu32 " max=%" PRIu32, evt.min_length, evt.max_length);
ESP_LOGV(TAG, "Multi Click: Starting multi click action!");
ESP_LOGV(TAG,
"START min=%" PRIu32 " max=%" PRIu32 "\n"
"Multi Click: Starting multi click action!",
evt.min_length, evt.max_length);
this->at_index_ = 1;
if (this->timing_.size() == 1 && evt.max_length == 4294967294UL) {
this->set_timeout("trigger", evt.min_length, [this]() { this->trigger_(); });

View File

@@ -1,9 +1,23 @@
# This file was auto-generated by libretiny/generate_components.py
# Do not modify its contents.
# For custom pin validators, put validate_pin() or validate_usage()
# in gpio.py file in this directory.
# For changing schema/pin schema, put COMPONENT_SCHEMA or COMPONENT_PIN_SCHEMA
# in schema.py file in this directory.
"""
██╗ ██╗ █████╗ ██████╗ ███╗ ██╗██╗███╗ ██╗ ██████╗
██║ ██║██╔══██╗██╔══██╗████╗ ██║██║████╗ ██║██╔════╝
██║ █╗ ██║███████║██████╔╝██╔██╗ ██║██║██╔██╗ ██║██║ ███╗
██║███╗██║██╔══██║██╔══██╗██║╚██╗██║██║██║╚██╗██║██║ ██║
╚███╔███╔╝██║ ██║██║ ██║██║ ╚████║██║██║ ╚████║╚██████╔╝
╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═══╝ ╚═════╝
AUTO-GENERATED FILE - DO NOT EDIT!
This file was auto-generated by libretiny/generate_components.py.
Any manual changes WILL BE LOST on regeneration.
To customize this component:
- Pin validators: Create gpio.py with validate_pin() or validate_usage()
- Schema extensions: Create schema.py with COMPONENT_SCHEMA or COMPONENT_PIN_SCHEMA
Platform-specific code should be added to the main libretiny component
(__init__.py in esphome/components/libretiny/) rather than here.
"""
from esphome import pins
from esphome.components import libretiny
@@ -27,6 +41,7 @@ COMPONENT_DATA = LibreTinyComponent(
board_pins=BK72XX_BOARD_PINS,
pin_validation=None,
usage_validation=None,
supports_atomics=False,
)

File diff suppressed because it is too large Load Diff

View File

@@ -7,8 +7,12 @@
#include "esphome/core/automation.h"
#include "esphome/components/ble_client/ble_client.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
// Maximum bytes to log in hex format for BLE writes (many logging buffers are 256 chars)
static constexpr size_t BLE_WRITE_MAX_LOG_BYTES = 64;
namespace esphome::ble_client {
// placeholder class for static TAG .
@@ -151,7 +155,10 @@ template<typename... Ts> class BLEClientWriteAction : public Action<Ts...>, publ
esph_log_w(Automation::TAG, "Cannot write to BLE characteristic - not connected");
return false;
}
esph_log_vv(Automation::TAG, "Will write %d bytes: %s", len, format_hex_pretty(data, len).c_str());
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE
char hex_buf[format_hex_pretty_size(BLE_WRITE_MAX_LOG_BYTES)];
esph_log_vv(Automation::TAG, "Will write %d bytes: %s", len, format_hex_pretty_to(hex_buf, data, len));
#endif
esp_err_t err =
esp_ble_gattc_write_char(this->parent()->get_gattc_if(), this->parent()->get_conn_id(), this->char_handle_, len,
const_cast<uint8_t *>(data), this->write_type_, ESP_GATT_AUTH_REQ_NONE);
@@ -179,8 +186,10 @@ template<typename... Ts> class BLEClientWriteAction : public Action<Ts...>, publ
case ESP_GATTC_SEARCH_CMPL_EVT: {
auto *chr = this->parent()->get_characteristic(this->service_uuid_, this->char_uuid_);
if (chr == nullptr) {
char char_buf[esp32_ble::UUID_STR_LEN];
char service_buf[esp32_ble::UUID_STR_LEN];
esph_log_w("ble_write_action", "Characteristic %s was not found in service %s",
this->char_uuid_.to_string().c_str(), this->service_uuid_.to_string().c_str());
this->char_uuid_.to_str(char_buf), this->service_uuid_.to_str(service_buf));
break;
}
this->char_handle_ = chr->handle;
@@ -192,11 +201,13 @@ template<typename... Ts> class BLEClientWriteAction : public Action<Ts...>, publ
this->write_type_ = ESP_GATT_WRITE_TYPE_NO_RSP;
esph_log_d(Automation::TAG, "Write type: ESP_GATT_WRITE_TYPE_NO_RSP");
} else {
esph_log_e(Automation::TAG, "Characteristic %s does not allow writing", this->char_uuid_.to_string().c_str());
char char_buf[esp32_ble::UUID_STR_LEN];
esph_log_e(Automation::TAG, "Characteristic %s does not allow writing", this->char_uuid_.to_str(char_buf));
break;
}
this->node_state = espbt::ClientState::ESTABLISHED;
esph_log_d(Automation::TAG, "Found characteristic %s on device %s", this->char_uuid_.to_string().c_str(),
char char_buf[esp32_ble::UUID_STR_LEN];
esph_log_d(Automation::TAG, "Found characteristic %s on device %s", this->char_uuid_.to_str(char_buf),
ble_client_->address_str());
break;
}

View File

@@ -9,12 +9,15 @@ static const char *const TAG = "ble_binary_output";
void BLEBinaryOutput::dump_config() {
ESP_LOGCONFIG(TAG, "BLE Binary Output:");
char service_buf[esp32_ble::UUID_STR_LEN];
char char_buf[esp32_ble::UUID_STR_LEN];
this->service_uuid_.to_str(service_buf);
this->char_uuid_.to_str(char_buf);
ESP_LOGCONFIG(TAG,
" MAC address : %s\n"
" Service UUID : %s\n"
" Characteristic UUID: %s",
this->parent_->address_str(), this->service_uuid_.to_string().c_str(),
this->char_uuid_.to_string().c_str());
this->parent_->address_str(), service_buf, char_buf);
LOG_BINARY_OUTPUT(this);
}
@@ -24,8 +27,10 @@ void BLEBinaryOutput::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_i
case ESP_GATTC_SEARCH_CMPL_EVT: {
auto *chr = this->parent()->get_characteristic(this->service_uuid_, this->char_uuid_);
if (chr == nullptr) {
ESP_LOGW(TAG, "Characteristic %s was not found in service %s", this->char_uuid_.to_string().c_str(),
this->service_uuid_.to_string().c_str());
char char_buf[esp32_ble::UUID_STR_LEN];
char service_buf[esp32_ble::UUID_STR_LEN];
ESP_LOGW(TAG, "Characteristic %s was not found in service %s", this->char_uuid_.to_str(char_buf),
this->service_uuid_.to_str(service_buf));
break;
}
this->char_handle_ = chr->handle;
@@ -37,20 +42,24 @@ void BLEBinaryOutput::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_i
this->write_type_ = ESP_GATT_WRITE_TYPE_NO_RSP;
ESP_LOGD(TAG, "Write type: ESP_GATT_WRITE_TYPE_NO_RSP");
} else {
ESP_LOGE(TAG, "Characteristic %s does not allow writing with%s response", this->char_uuid_.to_string().c_str(),
char char_buf[esp32_ble::UUID_STR_LEN];
ESP_LOGE(TAG, "Characteristic %s does not allow writing with%s response", this->char_uuid_.to_str(char_buf),
this->require_response_ ? "" : "out");
break;
}
this->node_state = espbt::ClientState::ESTABLISHED;
ESP_LOGD(TAG, "Found characteristic %s on device %s", this->char_uuid_.to_string().c_str(),
char char_buf[esp32_ble::UUID_STR_LEN];
ESP_LOGD(TAG, "Found characteristic %s on device %s", this->char_uuid_.to_str(char_buf),
this->parent()->address_str());
this->node_state = espbt::ClientState::ESTABLISHED;
break;
}
case ESP_GATTC_WRITE_CHAR_EVT: {
if (param->write.handle == this->char_handle_) {
if (param->write.status != 0)
ESP_LOGW(TAG, "[%s] Write error, status=%d", this->char_uuid_.to_string().c_str(), param->write.status);
if (param->write.status != 0) {
char char_buf[esp32_ble::UUID_STR_LEN];
ESP_LOGW(TAG, "[%s] Write error, status=%d", this->char_uuid_.to_str(char_buf), param->write.status);
}
}
break;
}
@@ -60,18 +69,19 @@ void BLEBinaryOutput::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_i
}
void BLEBinaryOutput::write_state(bool state) {
char char_buf[esp32_ble::UUID_STR_LEN];
if (this->node_state != espbt::ClientState::ESTABLISHED) {
ESP_LOGW(TAG, "[%s] Not connected to BLE client. State update can not be written.",
this->char_uuid_.to_string().c_str());
this->char_uuid_.to_str(char_buf));
return;
}
uint8_t state_as_uint = (uint8_t) state;
ESP_LOGV(TAG, "[%s] Write State: %d", this->char_uuid_.to_string().c_str(), state_as_uint);
ESP_LOGV(TAG, "[%s] Write State: %d", this->char_uuid_.to_str(char_buf), state_as_uint);
esp_err_t err =
esp_ble_gattc_write_char(this->parent()->get_gattc_if(), this->parent()->get_conn_id(), this->char_handle_,
sizeof(state_as_uint), &state_as_uint, this->write_type_, ESP_GATT_AUTH_REQ_NONE);
if (err != ESP_GATT_OK)
ESP_LOGW(TAG, "[%s] Write error, err=%d", this->char_uuid_.to_string().c_str(), err);
ESP_LOGW(TAG, "[%s] Write error, err=%d", this->char_uuid_.to_str(char_buf), err);
}
} // namespace esphome::ble_client

View File

@@ -18,14 +18,17 @@ void BLESensor::loop() {
void BLESensor::dump_config() {
LOG_SENSOR("", "BLE Sensor", this);
char service_buf[esp32_ble::UUID_STR_LEN];
char char_buf[esp32_ble::UUID_STR_LEN];
char descr_buf[esp32_ble::UUID_STR_LEN];
ESP_LOGCONFIG(TAG,
" MAC address : %s\n"
" Service UUID : %s\n"
" Characteristic UUID: %s\n"
" Descriptor UUID : %s\n"
" Notifications : %s",
this->parent()->address_str(), this->service_uuid_.to_string().c_str(),
this->char_uuid_.to_string().c_str(), this->descr_uuid_.to_string().c_str(), YESNO(this->notify_));
this->parent()->address_str(), this->service_uuid_.to_str(service_buf),
this->char_uuid_.to_str(char_buf), this->descr_uuid_.to_str(descr_buf), YESNO(this->notify_));
LOG_UPDATE_INTERVAL(this);
}
@@ -51,8 +54,10 @@ void BLESensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t ga
if (chr == nullptr) {
this->status_set_warning();
this->publish_state(NAN);
ESP_LOGW(TAG, "No sensor characteristic found at service %s char %s", this->service_uuid_.to_string().c_str(),
this->char_uuid_.to_string().c_str());
char service_buf[esp32_ble::UUID_STR_LEN];
char char_buf[esp32_ble::UUID_STR_LEN];
ESP_LOGW(TAG, "No sensor characteristic found at service %s char %s", this->service_uuid_.to_str(service_buf),
this->char_uuid_.to_str(char_buf));
break;
}
this->handle = chr->handle;
@@ -61,9 +66,12 @@ void BLESensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t ga
if (descr == nullptr) {
this->status_set_warning();
this->publish_state(NAN);
char service_buf[esp32_ble::UUID_STR_LEN];
char char_buf[esp32_ble::UUID_STR_LEN];
char descr_buf[esp32_ble::UUID_STR_LEN];
ESP_LOGW(TAG, "No sensor descriptor found at service %s char %s descr %s",
this->service_uuid_.to_string().c_str(), this->char_uuid_.to_string().c_str(),
this->descr_uuid_.to_string().c_str());
this->service_uuid_.to_str(service_buf), this->char_uuid_.to_str(char_buf),
this->descr_uuid_.to_str(descr_buf));
break;
}
this->handle = descr->handle;
@@ -109,7 +117,8 @@ void BLESensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t ga
break;
}
this->node_state = espbt::ClientState::ESTABLISHED;
ESP_LOGD(TAG, "Register for notify on %s complete", this->char_uuid_.to_string().c_str());
char char_buf[esp32_ble::UUID_STR_LEN];
ESP_LOGD(TAG, "Register for notify on %s complete", this->char_uuid_.to_str(char_buf));
}
break;
}

View File

@@ -21,7 +21,7 @@ class BLETextSensorNotifyTrigger : public Trigger<std::string>, public BLETextSe
if (param->notify.conn_id != this->sensor_->parent()->get_conn_id() ||
param->notify.handle != this->sensor_->handle)
break;
this->trigger(this->sensor_->parse_data(param->notify.value, param->notify.value_len));
this->trigger(std::string(reinterpret_cast<const char *>(param->notify.value), param->notify.value_len));
}
default:
break;

Some files were not shown because too many files have changed in this diff Show More