Compare commits

..
Author SHA1 Message Date
J. Nick Koston d759c2df17 [template] Use a user provided default constructor for TemplateDate 2026-09-12 05:12:28 -05:00
J. Nick Koston 2378962512 [datetime] Drop the inert constructors, keep the initializers 2026-09-12 04:56:11 -05:00
J. Nick Koston c4d89c89ff [datetime] Use user provided default constructors for the date and time entities 2026-09-11 21:30:30 -05:00
Clyde StubbsandClaude Sonnet 5 eecea15f4f [core][lvgl] Migrate codegen helpers from LVGL to core code (#19105)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-11 23:42:08 +00:00
J. Nick Koston ff9b2a1c83 [remote_receiver] Size the RMT ring buffer from receive symbols by default (#19100) 2026-09-11 18:20:40 -05:00
esphome[bot] 9f9df85aa0 Bump aioesphomeapi from 46.4.0 to 46.4.1 (#19104) 2026-09-11 23:04:48 +00:00
puddly 2b71d5496d [const] Centralize definition of CONF_MANUFACTURER (#19098) 2026-09-11 15:45:02 -05:00
esphome[bot] 2578f17dc8 Bump bundled esphome-device-builder to 1.14.7 (#19096) 2026-09-11 14:25:41 -05:00
J. Nick Koston 37e9b2b7af [remote_base] Make protocol methods non-virtual and size receiver lists from codegen (#19084) 2026-09-11 14:12:40 -05:00
Jesse Hills 6a21ab4ea7 [esp32] Trim mbedTLS to client-only defaults and stub vasprintf on the C6 (#19088) 2026-09-11 08:30:51 +00:00
Keith BurzinskiandClaude Fable 5.1 380938177c [uart] Add apply_settings_live() for in-place ESP-IDF reconfiguration (#19087)
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 03:25:52 -05:00
J. Nick Koston f66ef23256 [core] Support set_internal() during setup, log error after setup (#19069) 2026-09-11 03:20:30 -05:00
esphome[bot] 3e3822e554 Bump bundled esphome-device-builder to 1.14.6 (#19072) 2026-09-10 16:22:30 +00:00
Kevin AhrendtandJ. Nick Koston 7564f5ff1a [sendspin] Add manufacturer, model, and firmware version options (#18792)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-09-10 11:06:58 -05:00
matt123p a807a8f945 [es7210] Fix 4 channel microphone support (#19034) 2026-09-10 11:11:43 -04:00
Keith Burzinskiandpuddly 280fac11e6 [serial_proxy] Add tap interface and port mode (#18955)
Co-authored-by: puddly <32534428+puddly@users.noreply.github.com>
2026-09-10 10:03:33 -05:00
esphome[bot] 9924148302 Bump aioesphomeapi from 46.3.0 to 46.4.0 (#19071) 2026-09-10 14:59:23 +00:00
luar123 66f829c760 [zigbee] wake loop on defer/set_timeout (#19050) 2026-09-10 08:08:07 -05:00
luar123 a88ec7d90b [logger] Flush uart before sleep in idf 6 (#18975) 2026-09-10 13:07:09 +00:00
luar123 54706e869c [deep_sleep] disable loop (#18962) 2026-09-10 07:18:15 -05:00
05f7d5e4f1 [mlx90614] pec validation (#6689)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-09-10 16:14:43 +12:00
Robin ThoniandJesse Hills ddbd89dd2a [network] Improve network::is_connected() to better handle multiple interfaces (#18999)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-09-10 04:06:44 +00:00
Jesse Hills 5ed59af920 [template] Surface value metadata on template entity forms (#17545) 2026-09-10 14:11:13 +12:00
Jesse Hills 4868b498cf [ci] Ask stale PR authors to merge dev instead of rebasing (#19064) 2026-09-10 14:09:58 +12:00
Jesse Hills c66fa81208 [core] Consolidate setup scripts into a cross-platform setup.py (#18856) 2026-09-10 14:09:49 +12:00
esphome[bot] 58ca345684 [ci] Refresh integration test durations (#19049) 2026-09-09 13:42:09 -04:00
Remco van Essen fd598057ef [sendspin] Fix codec enum codegen when codecs is not set (#19055) 2026-09-09 08:22:23 -04:00
Jesse Hills ef7279341f Merge branch 'beta' into dev 2026-09-09 12:18:55 +12:00
Jesse Hills 69f2a7d556 Merge pull request #19051 from esphome/bump-2026.9.0b3
2026.9.0b3
2026-09-09 12:18:36 +12:00
Jesse Hills 008677298a Bump version to 2026.9.0b3 2026-09-09 09:54:44 +12:00
Kevin AhrendtandJesse Hills d2bc056f0a [sendspin] Add codec preference list to the media source (#19047)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-09-09 09:54:42 +12:00
J. Nick Koston 42fffd16fe [esphome][core] Give a lost OTA chunk ack time to be retransmitted (#19041) 2026-09-09 09:54:42 +12:00
J. Nick Koston 9c16aba6f7 [noise] Bump noise-c to 0.1.26 and libsodium to 1.10021.8 (#19030) 2026-09-09 09:54:42 +12:00
Kevin Ahrendt ac79173f4a [i2s_audio] Fix spurious driver failure (#19045) 2026-09-09 09:54:42 +12:00
Kevin Ahrendt 0a1e2acbcb [audio][i2s_audio][micro_wake_word][microphone][mixer][resampler][speaker] Replace use_count() checks with lock and null test (#19046) 2026-09-09 09:54:42 +12:00
Kevin AhrendtandCopilot Autofix powered by AI 9b6facb20d [core] Fix use-after-free when deleting a running StaticTask (#19048)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-09-09 09:54:42 +12:00
esphome[bot] f89b9e704c Bump bundled esphome-device-builder to 1.14.5 (#19040) 2026-09-09 09:54:42 +12:00
Johnandpre-commit-ci-lite[bot] f8b2e53609 [atm90e32] Verify offset calibration writes (#18701)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-09-09 09:54:42 +12:00
raykholo 7660dd7fa7 [anova] Re-assert temperature unit on every poll cycle (#17141) 2026-09-09 09:54:42 +12:00
c3ce07755f [rf_bridge] Fix bucket sniffing with Portisch firmware (#17683)
Co-authored-by: Bryan Li <bryanli@Bryans-MacBook-Pro.local>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 09:54:42 +12:00
Gytis f8a4cfa945 [lvgl] Add missing label dependency to qrcode, keyboard and tabview (#18387) 2026-09-09 09:54:42 +12:00
J. Nick Koston 866ddb6e57 [core] Skip PlatformIO's private-package authorization probe (#18823) 2026-09-09 09:54:42 +12:00
Jonathan Swoboda ca864c22b4 [tuya] Build without a network component (#18948) 2026-09-09 09:54:42 +12:00
Jesse Hills c9729244af [udp] Use cv.invalid for relocated packet_transport options (#19032) 2026-09-09 09:54:42 +12:00
Davide D M 442e4a1ec2 [debug] Check reboot source pref on ESP_RST_WDT and guard against empty source (#17537) 2026-09-09 09:54:41 +12:00
Pieter ViljoenandJesse Hills 199acdf522 [ble_client] Report Established from nodes that never read services (#17920)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-09-09 09:54:41 +12:00
Samuel SiebandSamuel Sieb 9340863652 [dallas_temp] filter 85 temp from sensor reset (#17877)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2026-09-09 09:54:41 +12:00
AndreKR d5cff6e9df [logger] Fix garbled stack traces (#17939) 2026-09-09 09:54:41 +12:00
Ryan Ronnander e7f45a0d31 [mqtt] Restore brightness flag in light discovery (#18950) 2026-09-09 09:54:41 +12:00
mipa87andClaude 628ebe23ec [audio] Do not treat MP3_STREAM_INFO_CHANGED as a fatal decoder error (#19028)
Co-authored-by: Claude <noreply@anthropic.com>
2026-09-09 09:54:41 +12:00
823d79c948 [i2s_audio] Keep a start request that arrives while the speaker task stops (#19027)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-09-09 09:54:41 +12:00
Kevin AhrendtandJesse Hills b947094f45 [sendspin] Add codec preference list to the media source (#19047)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-09-09 09:31:18 +12:00
J. Nick Koston 6c5ab89d5f [esphome][core] Give a lost OTA chunk ack time to be retransmitted (#19041) 2026-09-09 09:08:16 +12:00
J. Nick Koston 8f511a365a [noise] Bump noise-c to 0.1.26 and libsodium to 1.10021.8 (#19030) 2026-09-09 09:07:06 +12:00
Kevin Ahrendt 006f31af93 [i2s_audio] Fix spurious driver failure (#19045) 2026-09-09 09:05:02 +12:00
Kevin Ahrendt 5bb112f407 [audio][i2s_audio][micro_wake_word][microphone][mixer][resampler][speaker] Replace use_count() checks with lock and null test (#19046) 2026-09-09 09:04:34 +12:00
dependabot[bot] 4ab9298ab3 Bump esptool from 5.3.1 to 5.4.0 (#19023) 2026-09-08 22:11:36 +02:00
Kevin AhrendtandCopilot Autofix powered by AI 3926612281 [core] Fix use-after-free when deleting a running StaticTask (#19048)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-09-09 07:46:17 +12:00
J. Nick Koston 1ce0bed3f6 [core] Share compiled binaries across modbus integration tests (#18945) 2026-09-08 18:10:45 +02:00
esphome[bot] f91486305f Bump bundled esphome-device-builder to 1.14.5 (#19040) 2026-09-08 15:21:48 +02:00
Johnandpre-commit-ci-lite[bot] f191d5e0c3 [atm90e32] Verify offset calibration writes (#18701)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-09-08 20:02:49 +12:00
Jesse Hills 227ca90aad [core] Restore the shared git hooks after post-checkout runs script/setup (#19036) 2026-09-08 20:00:08 +12:00
Jesse Hills 1700a40b7c [core] Restore the shared git hooks after post-checkout runs script/setup (#19036) 2026-09-08 19:59:55 +12:00
raykholo 28588310e7 [anova] Re-assert temperature unit on every poll cycle (#17141) 2026-09-08 18:57:33 +12:00
10a9baff74 [rf_bridge] Fix bucket sniffing with Portisch firmware (#17683)
Co-authored-by: Bryan Li <bryanli@Bryans-MacBook-Pro.local>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-09-08 18:36:42 +12:00
Gytis a23f7bb569 [lvgl] Add missing label dependency to qrcode, keyboard and tabview (#18387) 2026-09-08 18:31:30 +12:00
J. Nick Koston 53075e4139 [core] Skip PlatformIO's private-package authorization probe (#18823) 2026-09-08 16:42:30 +12:00
Jonathan Swoboda 5722ccba37 [tuya] Build without a network component (#18948) 2026-09-08 16:36:04 +12:00
Jesse Hills 94e5c3839d [udp] Use cv.invalid for relocated packet_transport options (#19032) 2026-09-08 16:17:22 +12:00
Davide D M 574762f078 [debug] Check reboot source pref on ESP_RST_WDT and guard against empty source (#17537) 2026-09-08 13:59:05 +12:00
Pieter ViljoenandJesse Hills d34ffaf392 [ble_client] Report Established from nodes that never read services (#17920)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-09-08 01:57:50 +00:00
Samuel SiebandSamuel Sieb e6aa575f2e [dallas_temp] filter 85 temp from sensor reset (#17877)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2026-09-08 13:27:49 +12:00
AndreKR 639ce609bf [logger] Fix garbled stack traces (#17939) 2026-09-08 13:13:51 +12:00
Ryan Ronnander 62eafc477d [mqtt] Restore brightness flag in light discovery (#18950) 2026-09-08 13:09:02 +12:00
mipa87andClaude 56c3361b9a [audio] Do not treat MP3_STREAM_INFO_CHANGED as a fatal decoder error (#19028)
Co-authored-by: Claude <noreply@anthropic.com>
2026-09-08 12:13:03 +12:00
50ca381198 [i2s_audio] Keep a start request that arrives while the speaker task stops (#19027)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-09-08 12:10:55 +12:00
dependabot[bot] 89a56298c2 Bump prek from 0.5.1 to 0.5.2 (#19021)
Signed-off-by: dependabot[bot] <support@github.com>
2026-09-08 00:00:28 +00:00
390742cf9b Bump ruff from 0.16.5 to 0.16.6 (#19022)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Signed-off-by: dependabot[bot] <support@github.com>
2026-09-07 23:47:46 +00:00
Jesse Hillsandpre-commit-ci-lite[bot] 5e37872da2 [ci] Sync pre-commit revs and prek version from requirements files (#19026)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-09-08 10:32:18 +12:00
Jesse Hills d34d3994e1 Merge branch 'beta' into dev 2026-09-07 12:50:44 +12:00
Jesse Hills 9a877a067c Merge pull request #19007 from esphome/bump-2026.9.0b2
2026.9.0b2
2026-09-07 12:50:25 +12:00
Jesse Hills 9ba4477ada Bump version to 2026.9.0b2 2026-09-07 10:46:22 +12:00
Jesse Hills 8434dc5474 [esp32_hosted] Add ESP-NOW-over-hosted shim for the ESP32-P4 (#17712) 2026-09-07 10:46:21 +12:00
J. Nick Koston e0e85db822 [core] Show the other downloader's progress while a prefetch job waits on its lock (#18983) 2026-09-07 10:46:21 +12:00
J. Nick Koston 5d2ddc658c [mdns] Guard LEAmDNS main loop calls against lwIP re-entrancy on ESP8266 (#18990) 2026-09-07 10:46:21 +12:00
J. Nick Koston c1aa41f276 [noise] Bump noise-c to 0.1.24 and libsodium to 1.10021.6 (#18989) 2026-09-07 10:46:21 +12:00
esphome[bot] 96b1a03ea4 Bump bundled esphome-device-builder to 1.14.4 (#19006) 2026-09-07 10:46:21 +12:00
J. Nick Koston 95ab3fb4f2 [ota] Offer encryption with the api key so enabling it works over OTA (#18979) 2026-09-07 10:46:21 +12:00
Ricardo Sanz 18220e0b39 [climate][template] New template climate component (#14455) 2026-09-07 10:46:21 +12:00
esphome[bot] 011497d6ee Bump bundled esphome-device-builder to 1.14.3 (#18996) 2026-09-07 10:46:20 +12:00
esphome[bot] 7089dae3b6 Bump bundled esphome-device-builder to 1.14.2 (#18988) 2026-09-07 10:46:20 +12:00
esphome[bot] 745eb30109 Bump bundled esphome-device-builder to 1.14.1 (#18981) 2026-09-07 10:46:20 +12:00
Keith Burzinski e36445fa5f [usb_uart] Keep the comm interface number valid when its claim fails (#18968) 2026-09-07 10:46:20 +12:00
Jesse Hills cb0c2bdaca [esp32_ble] Reference count BLE advertising (#18943) 2026-09-07 10:46:20 +12:00
J. Nick Kostonandpre-commit-ci-lite[bot] e47247486b [esp8266] Drop Arduino framework versions before 3.0.0 (#18917) to
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-09-07 10:46:20 +12:00
esphome[bot]andJonathan Swoboda 657116a213 Bump bundled esphome-device-builder to 1.14.0 (#18960)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-09-07 10:46:20 +12:00
Keith Burzinski 3321566cc0 [remote_transmitter] Fix BK7231N build by limiting the PWM path to BK7238 (#18958) 2026-09-07 10:46:20 +12:00
Jesse Hills d58b37faa1 [esp32_hosted] Add ESP-NOW-over-hosted shim for the ESP32-P4 (#17712) 2026-09-07 10:29:20 +12:00
J. Nick Koston 8966567be0 [core] Show the other downloader's progress while a prefetch job waits on its lock (#18983) 2026-09-07 10:28:31 +12:00
J. Nick Koston 20c7dcb1dd [mdns] Guard LEAmDNS main loop calls against lwIP re-entrancy on ESP8266 (#18990) 2026-09-07 10:26:44 +12:00
J. Nick Koston 688af60cbf [noise] Bump noise-c to 0.1.24 and libsodium to 1.10021.6 (#18989) 2026-09-07 10:12:52 +12:00
esphome[bot] 9c00f13606 Bump bundled esphome-device-builder to 1.14.4 (#19006) 2026-09-06 22:05:16 +00:00
J. Nick Koston 833dd0e812 [ota] Offer encryption with the api key so enabling it works over OTA (#18979) 2026-09-06 23:59:40 +02:00
Ricardo Sanz 8e1044e8ea [climate][template] New template climate component (#14455) 2026-09-06 14:03:07 -07:00
esphome[bot] e5200db6fd Bump bundled esphome-device-builder to 1.14.3 (#18996) 2026-09-06 09:28:02 +02:00
e3dd2f44a4 [mipi_dsi] Let IDF pick the DPHY PLL reference clock (#18984)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
2026-09-05 21:08:21 +00:00
esphome[bot] 3ef7460fca Bump bundled esphome-device-builder to 1.14.2 (#18988) 2026-09-05 15:25:58 +00:00
ae187f81f2 [wifi] Allow a forced roam check (#17349)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-09-05 21:44:37 +10:00
esphome[bot] 84f78831f9 Bump bundled esphome-device-builder to 1.14.1 (#18981) 2026-09-05 13:07:15 +02:00
Keith Burzinski 13dbbcaa32 [usb_uart] Keep the comm interface number valid when its claim fails (#18968) 2026-09-05 13:00:25 +02:00
Clyde Stubbs b66822d9bd [ai] Advice to agents to limit verbiage (#18980) 2026-09-05 12:21:47 +02:00
dependabot[bot] d1829c495d Bump prek from 0.5.0 to 0.5.1 (#18977)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-04 19:05:36 -04:00
dependabot[bot] ce87bf9b17 Bump platformdirs from 4.11.5 to 4.11.7 (#18976)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-04 19:05:26 -04:00
Jesse Hills 51ea97deff [esp32_ble] Reference count BLE advertising (#18943) 2026-09-05 08:38:55 +12:00
dependabot[bot] ab800dc09d Bump filelock from 3.32.4 to 3.32.5 (#18963)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-03 17:19:29 -04:00
J. Nick Kostonandpre-commit-ci-lite[bot] f65ab5629e [esp8266] Drop Arduino framework versions before 3.0.0 (#18917) to
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-09-03 15:16:36 -04:00
esphome[bot]andJonathan Swoboda b84532d254 Bump bundled esphome-device-builder to 1.14.0 (#18960)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-09-03 12:15:06 +00:00
Keith Burzinski 6b11636491 [remote_transmitter] Fix BK7231N build by limiting the PWM path to BK7238 (#18958) 2026-09-03 08:12:36 -04:00
Jesse Hills 2bb98f2d64 Merge branch 'beta' into dev 2026-09-03 14:07:41 +12:00
Jesse Hills 25c29fd9e0 Merge pull request #18957 from esphome/bump-2026.9.0b1
2026.9.0b1
2026-09-03 14:07:19 +12:00
Jesse Hills f3c786c784 Bump version to 2026.10.0-dev 2026-09-03 13:07:21 +12:00
dependabot[bot] 2250430999 Bump zeroconf from 0.151.2 to 0.151.3 (#18951)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-02 20:56:51 -04:00
dependabot[bot] d1068d582f Bump ninja from 1.13.0 to 1.13.2 (#18952)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-02 20:56:42 -04:00
Jesse Hills 567a981078 Bump version to 2026.9.0b1 2026-09-03 12:16:25 +12:00
Jesse Hills 81ecb87253 Bump version to 2026.10.0-dev 2026-09-03 12:11:56 +12:00
f0e2eb96bd [snapshot][SDL] Display headless mode and snapshots (#17917)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-09-03 09:39:32 +12:00
Keith Burzinskiandpuddly 567f7f9196 [serial_proxy] Skip no-op reconfigure requests (#18953)
Co-authored-by: puddly <32534428+puddly@users.noreply.github.com>
2026-09-02 15:01:23 -05:00
Jesse Hills ecbde8ddf4 [uart] Migrate check_uart_settings to final validation (#18940) 2026-09-03 07:25:08 +12:00
esphome[bot] da16c01351 [ci] Refresh integration test durations (#18944) 2026-09-02 09:32:47 +00:00
Jesse Hills 6099ac7b53 [core] Document C++ conventions in AGENTS.md that reviews keep catching (#18941) 2026-09-02 11:17:22 +02:00
dependabot[bot] b8480b8424 Bump pylint from 4.0.7 to 4.0.8 (#18935)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-01 21:36:49 -04:00
dependabot[bot] 8bef5b22e1 Bump zeroconf from 0.150.4 to 0.151.2 (#18934)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-01 21:36:04 -04:00
379e077b5f [ds1603l] New sensor DS1603L V1.0 (#13133)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-09-02 10:05:56 +12:00
J. Nick KostonandJesse Hills 3f68930001 [ota] Add Noise encryption to the OTA platform (#18489)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-09-02 08:11:57 +12:00
0aff9e1c54 [d01] add D01 pm2.5 sensor support (#17788)
Co-authored-by: Andrej Walilko <awalilko@liquidweb.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-09-02 07:33:35 +12:00
ZebbleandClaude f9824ee83f [core] Move CONF_KEYS to the shared component constants (#18933)
Co-authored-by: Claude <noreply@anthropic.com>
2026-09-01 14:23:21 -04:00
68ffd5a773 [safe_mode] Uncover silent error in safe-mode (#18749)
Co-authored-by: Oliver Kleinecke <kleinecke.oliver@googlemail.com>
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>
2026-09-01 09:12:49 -04:00
fe3788ff47 [esp32][mipi_rgb] Add ESP32-S31 support for execute_from_psram (#18929)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-09-01 08:56:03 -04:00
J. Nick Koston d6758377d1 [core] Clone git libraries in parallel in the library prefetch (#18836) 2026-09-01 14:25:58 +12:00
Jesse Hills 5dbc8ffe4c [epaper_spi] Add UC8179 mono driver and Seeed reTerminal E1001 model (#17568) 2026-09-01 14:17:52 +12:00
J. Nick Koston 0f982f03b2 [core] Prefetch tool-scons by PlatformIO's core spec (#18831) 2026-09-01 11:55:53 +12:00
Bonne Eggleston afb0022dd0 [core] Lint: require braces around single ESP_LOG control-statement bodies (#18727) 2026-09-01 11:53:39 +12:00
dependabot[bot]andJonathan Swoboda 081ef3d30d Bump prek from 0.4.14 to 0.5.0 (#18921)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-08-31 17:46:47 -04:00
Jonathan Swoboda ca44db107c [docker] Fix generate_tags.py formatting (#18928) 2026-08-31 17:33:52 -04:00
dependabot[bot] d437869373 Bump cryptography from 48.0.1 to 50.0.1 (#18922)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-31 17:23:29 -04:00
dependabot[bot] c20b619684 Bump platformdirs from 4.11.4 to 4.11.5 (#18923)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-31 17:20:43 -04:00
dependabot[bot] ebe6c2d049 Bump github/codeql-action/init from 4.37.8 to 4.37.9 (#18927)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-31 17:20:12 -04:00
dependabot[bot] 78beb75b3b Bump github/codeql-action/analyze from 4.37.8 to 4.37.9 (#18926)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-31 17:20:00 -04:00
dependabot[bot] fc9afcb201 Bump ruff from 0.16.4 to 0.16.5 (#18920)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-31 17:17:58 -04:00
dependabot[bot] 7a784d1135 Bump zeroconf from 0.150.0 to 0.150.4 (#18924)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-31 17:16:22 -04:00
Clyde Stubbs 24af3fd834 [lvgl] Fix user_ flags (#18902) 2026-09-01 07:13:36 +10:00
Clyde Stubbs 61e37cfc86 [docker] Use GITHUB_REPOSITORY instead of hardcoded esphome/esphome (#18916) 2026-09-01 07:01:53 +10:00
J. Nick Koston ea1e0c6f68 [core] Keep scheduler dump cancelled marker string in flash on ESP8266 (#18906) 2026-08-31 13:27:53 -05:00
J. Nick Koston 1ba1aebfa1 [ci] Balance integration test buckets by recorded durations (#18895) 2026-08-31 13:20:47 -05:00
J. Nick Koston 5d56517e14 [api] Keep action dropped warning strings in flash on ESP8266 (#18905) 2026-08-31 13:19:49 -05:00
J. Nick Koston ad69718ecc [core] Configure the platform again after prefetching its packages (#18830) 2026-08-31 13:01:13 -05:00
mfishmaandpre-commit-ci-lite[bot] 06d477bea7 [whynter] Fix truncating Fahrenheit temps that should be rounded (#18813)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-08-31 13:47:55 -04:00
Brandon Harvey bbe806f1e6 [sen6x] Add VOC/NOx algorithm tuning (#18779) 2026-08-31 13:45:38 -04:00
Jonathan Swoboda 813c000684 [adc] Add ESP32-S31 support (#18887) 2026-08-31 08:51:33 -04:00
2890afe0e5 [esp32] Fix S31 reserved pins (#18915)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-08-31 12:38:20 +00:00
Clyde Stubbs 5e58b312e2 [mipi_rgb] Add ESP32S31 support (#18914) 2026-08-31 07:20:20 -04:00
Jonathan Swoboda 575a540c9f [esp32] Fix ESP32-S31 GPIO validation (#18904) 2026-08-31 07:19:20 -04:00
J. Nick Koston 404da26a37 [core] Keep conditional log string literals in flash on ESP8266 (#18907) 2026-08-31 21:08:05 +12:00
Jesse Hills be54a5c403 Merge branch 'release' into dev 2026-08-31 14:23:06 +12:00
Jesse Hills 8b5c06add6 Merge pull request #18900 from esphome/bump-2026.8.2
2026.8.2
2026-08-31 14:22:42 +12:00
Keith BurzinskiandJ. Nick Koston 7b97c87390 [improv_serial] Support non-Wi-Fi network interfaces (#17598)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-30 20:43:59 -05:00
J. Nick Koston fbe306f00b [homeassistant] Add integration test for binary sensor initial state triggers (#18894) 2026-08-30 19:30:40 -05:00
Jesse Hills 0e4f460013 Bump version to 2026.8.2 2026-08-31 11:25:12 +12:00
esphome[bot] 4e0a5e5a5b Bump bundled esphome-device-builder to 1.13.1 (#18807) 2026-08-31 11:25:10 +12:00
J. Nick Koston 20d4fe1a41 [mdns] Skip MDNS.update() while the ESP8266 radio cannot transmit (#18785) 2026-08-31 11:25:10 +12:00
Clyde Stubbs 8929fc43d8 [mipi_spi] Fix dimensions for jc3636518v2 (#18786) 2026-08-31 11:25:10 +12:00
J. Nick KostonandCopilot Autofix powered by AI c75252d425 [http_request] Default watchdog_timeout from timeout on ESP32 (#18732)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-08-31 11:24:51 +12:00
Clyde StubbsandClaude Sonnet 5 ae460b430c [lvgl] Fix on_value/on_update triggers for LVGL select entities (#18778)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-31 11:22:13 +12:00
esphome[bot] 82ca5365c9 Bump bundled esphome-device-builder to 1.13.0 (#18743) 2026-08-31 11:22:13 +12:00
J. Nick Koston a5d8c45b67 [gpio] Fix one_wire reset busy-waiting with interrupts off when delay wraps (#18733) 2026-08-31 11:22:13 +12:00
J. Nick Koston 67f7532940 [espidf] Always reconfigure after component discovery (#18730) 2026-08-31 11:22:06 +12:00
J. Nick Koston fc977b7b5e [ci] Cache the integration test PlatformIO dir (#18896) 2026-08-30 17:34:32 -05:00
J. Nick Koston 2f1d3f8299 [core] Deduplicate the host program path lookup (#18897) 2026-08-30 17:34:16 -05:00
Bonne Eggleston cb54e57d84 [modbus] Yield the whole-millisecond part of the interframe wait (#18898) 2026-08-30 16:43:28 -05:00
Brandon HarveyandJ. Nick Koston fb65096ea3 [api] Add description and example metadata to user-defined actions (#18881)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-08-30 13:52:51 -05:00
esphome[bot] 0607c228f5 Bump aioesphomeapi from 46.2.1 to 46.3.0 (#18892) 2026-08-30 17:25:29 +00:00
Clyde Stubbs b9eda644cd [lvgl] Add radial and conical gradients (#18818) 2026-08-30 21:21:07 +10:00
Bonne Eggleston a811aa840c [modbus] Speed up the bus with microsecond-accurate timing (#12421) 2026-08-30 03:14:12 -05:00
J. Nick Koston cd28a8a03e [internal_temperature] Re-include esp_phy on the original ESP32 so the PHY blob links (#18884) 2026-08-29 23:25:25 -05:00
J. Nick Koston 6957576867 [esp32] Skip full rebuild on sdkconfig change with the esp-idf toolchain (#18876) 2026-08-29 03:09:12 +00:00
J. Nick Koston 3fea080ed8 [core] Hash downloaded file paths at the default data dir location (#18824) 2026-08-28 21:08:15 -05:00
Clyde Stubbs 06bc3d70c2 [mipi_rgb] Add Elecrow Crowpanel Advance 7 (#18810) 2026-08-28 22:02:27 -04:00
J. Nick Koston 2576a0e340 [ci] Drop picolibc from the cached ESP-IDF toolchains (#18871) 2026-08-29 01:50:24 +00:00
J. Nick Koston ce163b8258 [ci] Cache clang-tidy idedata and key ESP-IDF cache on Python version (#18868) 2026-08-28 20:41:57 -05:00
Bonne Eggleston bcec1d6cb8 [modbus] Decode by register address in the modbus sensor components (#18874) 2026-08-28 18:44:37 -05:00
Bonne Eggleston 1c44cec343 [modbus] Add value_at() and decode registers without the byte round-trip (#18873) 2026-08-28 17:44:00 -05:00
Clyde Stubbs c9848d8fa6 [light] Fix gamma table dead zone collapsing to 0 (#18845) 2026-08-29 08:37:20 +10:00
0dc0cf83de [mk2pvrouter] Add Mk2PVRouter component with sensor support (#8487)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick+github@koston.org>
2026-08-28 21:02:32 +00:00
dependabot[bot] ed3429d372 Bump resvg-py from 0.4.0 to 0.5.0 (#18864)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-28 15:43:52 -05:00
Bonne EgglestonandJ. Nick Koston dfac9e1f11 [pzemac] Use the typed modbus read callback with address-based extraction (#18855)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-28 15:35:10 -05:00
Bonne EgglestonandJ. Nick Koston 7255315ce2 [sdm_meter] Use the typed modbus read callback with address-based extraction (#18849)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-28 15:34:23 -05:00
Bonne EgglestonandJ. Nick Koston 346c250901 [selec_meter] Use the typed modbus read callback with address-based extraction (#18854)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-28 15:34:03 -05:00
Bonne EgglestonandJ. Nick Koston 5fc9bff371 [pzemdc] Use the typed modbus read callback with address-based extraction (#18853)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-28 15:27:45 -05:00
Bonne EgglestonandJ. Nick Koston 97f643574c [kuntze] Use the typed modbus read callback and queue all reads at once (#18852)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-28 15:27:01 -05:00
Bonne EgglestonandJ. Nick Koston e8d76b735b [havells_solar] Use the typed modbus read callback with address-based extraction (#18851)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-28 15:21:52 -05:00
J. Nick Koston 03147bc3b1 [core] Avoid double promotion in update interval and step formatting (#18825) 2026-08-28 15:12:50 -05:00
Bonne Eggleston d4348335dd [growatt_solar] Use the typed modbus read callback and drop the send-pacing state machine (#18850) 2026-08-28 15:11:42 -05:00
Bonne Eggleston 246670e22b [modbus] Add a compile-time register value decoder (#18863) 2026-08-28 14:54:31 -05:00
J. Nick Koston 0dce7f4845 [esp8266] Add the native library backend (#18558) 2026-08-28 13:50:52 -05:00
J. Nick Koston 1623fe0852 [esp32] Exclude the WiFi and Bluetooth stacks from builds that do not use them (#18599) 2026-08-28 18:49:21 +00:00
J. Nick Koston 4333870590 [core] Use uv for the ESP-IDF Python environment when available (#18838) 2026-08-28 13:43:48 -05:00
J. Nick Koston cc41fd0beb [core] Make rmtree tolerate missing paths and concurrent directory changes (#18846) 2026-08-28 13:42:42 -05:00
Bonne EgglestonandJ. Nick Koston 59397b4e28 [modbus] Build single-value register writes on a right-sized stack buffer (#18844)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-28 18:36:24 +00:00
Bonne Eggleston 768ab5b672 [modbus] Hub and helpers cleanup; tighten queue_pdu validation (#18847) 2026-08-28 13:16:41 -05:00
J. Nick Koston 8db07d0de5 [mdns] Bump espressif/mdns to 1.12.0 (#18861) 2026-08-28 12:57:45 -05:00
a1515ec662 [modbus_controller] Replace register_count/force_new_range with reuse_previous_range (#18085)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-28 11:54:06 -05:00
Jesse Hills 2031be0c23 [core] Make script/setup idempotent and prepare new worktrees (#18843) 2026-08-28 14:11:38 +12:00
esphome[bot] 708b7bfb53 Update webserver local assets to 20260824-021242 (#18704) 2026-08-28 11:39:30 +12:00
J. Nick Koston 7782bc11c6 [core] Remove make_name_with_suffix std::string overloads (#18828) 2026-08-27 15:29:43 -05:00
J. Nick Koston a9a66baeba [ci] Compress the compile-test image with zstd (#18812) 2026-08-27 15:29:23 -05:00
J. Nick Koston 16d0fa1165 [core] Add step_to_accuracy_decimals benchmarks (#18826) 2026-08-27 15:28:04 -05:00
25d5cd3e14 [modbus_controller] Poll through PollingDevice; deprecate ModbusCommandItem (#18071)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-27 14:38:13 -05:00
dependabot[bot] 9598449b6b Bump CodSpeedHQ/action from 5.0.3 to 5.2.1 (#18834)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-27 14:31:11 -05:00
dependabot[bot] a8c7279b3b Bump platformdirs from 4.11.3 to 4.11.4 (#18835)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-27 14:30:53 -05:00
c3c69c730c [openthread] fix shutdown (#16332)
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: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-27 12:59:17 -05:00
Bonne EgglestonandJ. Nick Koston a8c8827a5b [modbus_controller] Switch write_lambda return value is the wire value only (#18788)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-27 10:33:16 -05:00
Bonne EgglestonandJ. Nick Koston 18b7002604 [modbus_controller] Apply the write offset byte-accurately on switch and output (#18787)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-27 08:43:51 -05:00
51105a25db [tuya] Add water_heater platform (#17323)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-08-27 20:55:51 +12:00
J. Nick Koston fb132b4421 [improv_serial][esp32_improv] Use buffer based RPC response builder (#18793) 2026-08-27 01:01:35 -05:00
guillempages 20b38ac8b0 [runtime_image] Add support for QOI images (#16945) 2026-08-27 16:37:20 +12:00
Keith BurzinskiandJ. Nick Koston cdd892a526 [provisioning] Shut down the Wi-Fi AP and captive portal when the window closes (#17466)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-27 15:16:25 +12:00
J. Nick Koston b99e7f5ae2 [core] Install prefetched PlatformIO packages with parallel extraction (#18775) 2026-08-27 03:02:02 +00:00
J. Nick Koston e55a8aeabe [api] Drop connection instead of crashing when buffer allocation fails (#18803) 2026-08-27 14:49:12 +12:00
J. Nick Koston a8094ed548 [docker] Parallelize the image's PlatformIO library preinstall (#18777) 2026-08-27 14:45:47 +12:00
J. Nick Koston 2104096f02 [core] Prefetch PlatformIO packages in parallel (#18769) 2026-08-27 14:42:30 +12:00
J. Nick Koston e53870085b [improv_serial] Add uart bus support and host integration test (#18794) 2026-08-26 21:13:47 -05:00
J. Nick Koston b62305793d [improv_base] Bump Improv library to 1.2.7 (#18809) 2026-08-27 01:40:12 +00:00
Jonathan Swoboda a1b29b0d0b [external_components] Log when a source overrides built-in components (#18805) 2026-08-26 20:56:57 -04:00
n-IA-hane e458a38f89 [spi] Use PSRAM DMA for external buffers (#18699) 2026-08-27 10:55:39 +10:00
J. Nick Koston 39177402dd [api] Deprecate media player supports_pause field (#18801) 2026-08-26 19:46:28 -05:00
J. Nick Koston 3361d031de [api] Drop connection instead of crashing when overflow buffer allocation fails (#18802) 2026-08-26 19:46:13 -05:00
Bonne EgglestonandJ. Nick Koston 5df1c7f1d3 [modbus_controller] Writer entities as their own hub device; heap-free, byte-accurate write path (#18082)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-26 18:24:09 -05:00
guillempages 9508165797 [runtime_image] Add check for dimensions in BMP (#18800) 2026-08-26 16:36:47 -05:00
esphome[bot] 5878406918 Bump bundled esphome-device-builder to 1.13.1 (#18807) 2026-08-26 16:33:52 -05:00
esphome[bot] fedd46e648 Bump aioesphomeapi from 46.2.0 to 46.2.1 (#18804) 2026-08-26 20:55:29 +00:00
dependabot[bot] d28b17c619 Bump filelock from 3.32.3 to 3.32.4 (#18799)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-26 19:26:45 +00:00
Josef Zweck f17ef133f3 [hoermann_hcp] Add buttons to hoermann_hcp (#18544) 2026-08-26 14:27:16 -04:00
Leonardo Rivera 34e7453677 [climate] Don't restore a saved mode the device no longer supports (#18296) 2026-08-26 14:26:31 -04:00
Frédéric Metrich 8a89f3075f [emontx] Fix sensor storage initialization ordering (#18771) 2026-08-26 14:03:10 -04:00
MakerYuichianddoraemon2200 5328813814 [time] Silence compiler warning by initializing transit variables (#18715) (#18723)
Co-authored-by: doraemon2200 <106516578+doraemon2200@users.noreply.github.com>
2026-08-26 12:43:55 -04:00
Keith Burzinski 1cbe3a49b2 [remote_transmitter] ISR-driven transmission and non_blocking support on BK7231N/BK7238 (#18660) 2026-08-26 11:30:07 -05:00
guillempages 5c79c92c06 [runtime_image] Add FILTER_SOURCE_FILES (#18768) 2026-08-26 11:26:39 -05:00
J. Nick Koston 7b4894da03 [mdns] Skip MDNS.update() while the ESP8266 radio cannot transmit (#18785) 2026-08-26 15:16:44 +00:00
Clyde Stubbs 4eb85a24c2 [mipi_spi] Fix dimensions for jc3636518v2 (#18786) 2026-08-26 10:04:57 -05:00
Bonne Eggleston 1e7c48e2cf [modbus_controller] Add integration tests for register offset, response size and write buffer (#18741) 2026-08-26 08:35:46 -05:00
IreuN 6ef13cc8de [climate_ir_lg] advanced vert. swing, setting temp. in heat/cool mode, jet mode decoding, other fixes + refactor (#10875) 2026-08-25 22:26:50 -07:00
Keith Burzinski e37a540fb7 [esp32] Apply custom eFuse MAC as base MAC for all interfaces (#18452) 2026-08-25 23:59:37 -05:00
J. Nick Koston 9baff76520 [api] Treat homeassistant.event variables as lambdas (#18759) 2026-08-26 16:29:14 +12:00
J. Nick KostonandCopilot Autofix powered by AI 612d58ec37 [http_request] Default watchdog_timeout from timeout on ESP32 (#18732)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-08-26 16:11:26 +12:00
Keith Burzinski cb981c2930 [remote_transmitter] ISR-driven transmission and non_blocking support on RTL8720C (#18648) 2026-08-25 22:19:54 -05:00
Clyde StubbsandClaude Sonnet 5 8b8de0c9c6 [lvgl] Fix on_value/on_update triggers for LVGL select entities (#18778)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-26 13:33:39 +12:00
J. Nick Koston 9e4c52989c [esp8266] Add the native framework and toolchain installer (#18557) 2026-08-25 20:24:47 -05:00
J. Nick Koston 7ff56c62f9 [core] Add shared registry, ninja, and cache infrastructure for native toolchains (#18570) 2026-08-26 13:23:16 +12:00
J. Nick Koston 370e8fffed [core] Add the arduino toolchain seam and validate --toolchain on every platform (#18556) 2026-08-26 11:16:02 +12:00
c272c4c1a6 [lvgl] Add table widget (#18422)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick+github@koston.org>
2026-08-26 08:44:42 +10:00
J. Nick Koston 150f75d8f6 [esp8266] Add linker-script surgery and board build metadata for the native toolchain (#18555) 2026-08-26 10:29:57 +12:00
Jonathan Swoboda cf5ec2d277 [ci] Remove the remaining max-parallel caps (#18762) 2026-08-25 14:42:32 -04:00
J. Nick Koston 145373ed13 [api] Widen message type storage to uint16_t (#18526) 2026-08-25 18:04:41 +00:00
J. Nick Koston 8749c3d18d [esp32_ble_tracker] Warn when the scan window is above 600ms with wifi (#18725) 2026-08-25 12:40:57 -05:00
J. Nick Koston 688e833413 [core] Consolidate HTTP download paths (#18742) 2026-08-25 12:38:20 -05:00
J. Nick Kostonandpre-commit-ci-lite[bot] 19b434f99c [espidf] Cache the discovered component list to skip the discovery configure (#18752)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-08-25 12:36:57 -05:00
0b78800e3d [emontx] Add apparent power (AP) and frequency (F) sensor support (#18586)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-08-25 11:07:18 -05:00
Jesse Hills 6a86ef0ee0 [ethernet] Add spi_id option to attach to an existing SPI bus (#18530) 2026-08-25 10:45:38 -05:00
Frédéric Metrich 4eba9ee41a [core] Fix false-positive readability-non-const-parameter in string_ref.h (#18758) 2026-08-25 10:36:00 -05:00
NoQuarrelandpre-commit-ci-lite[bot] b579751bdf [sfa40] Add SFA40 sensor support (#17815)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-08-25 07:55:19 -04:00
J. Nick Koston bc8d0840eb [time] Skip automation.cpp when no on_time or on_time_sync automation is configured (#18750) 2026-08-25 19:50:43 +12:00
J. Nick KostonandJesse Hills 3f615f87cf [esp32] Exclude esp_http_server and nvs_sec_provider from IDF builds by default (#18748)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-08-25 06:16:32 +00:00
J. Nick Koston c6d423159c [esp32] Only build the mbedTLS certificate bundle when a component needs it (#18747) 2026-08-25 17:26:18 +12:00
J. Nick Koston 791590c8a3 [uptime] Skip the timestamp sensor source unless a timestamp sensor is configured (#18746) 2026-08-25 17:24:20 +12:00
J. Nick Koston 036e5cda7e [core] Remove empty automation.cpp files from sensor, switch and output (#18745) 2026-08-25 17:24:14 +12:00
J. Nick Koston 44860ff512 [time] Skip posix_tz.cpp when no timezone is configured (#18680) 2026-08-25 17:22:41 +12:00
Edvard Filistovič 90927ba788 [rp2_ble_tracker] Automation triggers and scan actions (#18717) 2026-08-24 22:57:01 -05:00
Edvard Filistovič 169c055011 [wifi] libretiny: reset the STA state on synchronous connect failure (#18719) 2026-08-25 01:25:44 +00:00
esphome[bot] 8623b6836d Bump bundled esphome-device-builder to 1.13.0 (#18743) 2026-08-25 00:44:28 +00:00
J. Nick Koston b3d9aa2d84 [core] Log which source change triggered a rebuild (#18552) 2026-08-24 18:46:43 -05:00
acd3c4f156 [lvgl] Implement list widget (#18018)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-24 23:20:20 +00:00
luar123andJ. Nick Koston 37b78ad46a [zigbee][time] Add zigbee time component on esp32 (#18656)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-24 17:24:57 -05:00
esphome[bot] a15fae6a1e Bump aioesphomeapi from 46.1.0 to 46.2.0 (#18740) 2026-08-24 22:15:09 +00:00
guillempagesandJ. Nick Koston c866add320 [runtime_image] Fix include (#18738)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-24 16:23:07 -05:00
J. Nick Koston 2a05372a51 [gpio] Fix one_wire reset busy-waiting with interrupts off when delay wraps (#18733) 2026-08-24 16:20:25 -05:00
J. Nick Koston 19866c60ee [core] Parallelize registry and tool downloads (#18662) 2026-08-24 15:59:00 -05:00
J. Nick Koston 3f0ec0b157 [espidf] Always reconfigure after component discovery (#18730) 2026-08-25 08:56:59 +12:00
Clyde Stubbs 7c5105b16e [key_collector][mipi_rgb] Suppress compilation warnings (#18721) 2026-08-25 06:36:06 +10:00
Keith BurzinskiandJ. Nick Koston b97c877992 [api] Acknowledge proxy subscribe and configuration requests (#18312)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-24 20:27:24 +00:00
ca96365143 [runtime_image] Add MIME types to image formats (#16361)
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: J. Nick Koston <nick@home-assistant.io>
2026-08-24 15:07:01 -05:00
esphome[bot] 3b6c6e3dad Bump aioesphomeapi from 46.0.0 to 46.1.0 (#18737) 2026-08-24 14:50:35 -05:00
dependabot[bot] ad508d79af Bump github/codeql-action/init from 4.37.7 to 4.37.8 (#18736)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-24 14:33:52 -05:00
dependabot[bot] 32a0a5c55c Bump github/codeql-action/analyze from 4.37.7 to 4.37.8 (#18735)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-24 14:33:39 -05:00
dependabot[bot] b103df1bb1 Bump ruff from 0.16.3 to 0.16.4 (#18734)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-24 14:33:24 -05:00
Bonne Eggleston c2a153a946 [modbus_controller] Add continuous polling option (#18080) 2026-08-24 13:26:26 -05:00
J. Nick Koston 49fc4be861 [ci] Run C++ unit tests when a component's Python or test override changes (#18706) 2026-08-24 12:18:17 -05:00
GafieltandJ. Nick Koston b8408e14b9 [uart] Delete ESP32 UART driver on shutdown to keep ROM output off the bus (#18684)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-08-24 11:36:23 -05:00
Boris Krivonog b11a34af5c [mitsubishi_cn105] Defer status requests after responses (#18227) 2026-08-24 10:51:09 -05:00
n-IA-haneandn-IA-hane 5ed20805ce [audio_http] Add persistent ring buffer option (#18708)
Co-authored-by: n-IA-hane <n-IA-hane@users.noreply.github.com>
2026-08-24 11:35:59 -04:00
Bonne Eggleston 7674477dd0 [modbus_controller] Brace poll-refused log to fix -Wempty-body warning (#18724) 2026-08-24 09:05:00 -05:00
2b11fbe164 [preferences] modify IntervalSyncer to be a PollingComponent (#14370)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-23 22:50:19 -05:00
J. Nick Koston 5f6a910e2d [core] Harden the shared library converter (#18685) 2026-08-23 22:24:12 -05:00
J. Nick Koston 9974ad97fa [core] Extract the shared idedata and size-summary helpers into build_helpers (#18661) 2026-08-23 21:59:19 -05:00
Jesse Hills c8ebe461d1 [ci] Skip CodSpeed benchmarks on beta and release pull requests (#18703) 2026-08-24 14:11:35 +12:00
Jesse HillsandJ. Nick Koston de1361ac0e [core] Add type annotations to component Python (#18697)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-23 20:50:27 -05:00
J. Nick Koston d877fb021c [time] Remove C++ POSIX TZ string parser (#18383) 2026-08-24 13:24:00 +12:00
3c56b9e66e [wifi] Share the scan list dedupe helper with improv_serial (#18612)
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: Bluetooth Devices Bot <bluetooth@koston.org>
2026-08-24 01:05:35 +00:00
Bonne Eggleston 1ceaf699c2 [modbus_controller] Rename custom_command to custom_pdu; reject address 0; retire skip_updates (#18652) 2026-08-23 19:33:53 -05:00
J. Nick Koston d75f85b089 [network] Add tcp_send_buffer option (#18610) 2026-08-23 19:23:08 -05:00
J. Nick KostonandJesse Hills 34c1a009b6 [core] Use filter_source_files_from_defines in api, socket and ethernet (#18674)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-08-24 00:20:00 +00:00
c9e91be35f [web_server_idf] Skip multipart parser sources when OTA upload is disabled (#18534)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-08-23 23:45:26 +00:00
J. Nick Koston 31afd94a30 [noise] Declare libsodium as a direct dependency (#18692) 2026-08-23 23:35:45 +00:00
J. Nick Koston 6f7b9a1482 [gpio] Fix linker error when binary sensor only uses expander pins (#18698) 2026-08-24 11:31:48 +12:00
J. Nick Koston 6c23ad661d [bluetooth_proxy] Warn once per transaction when the TCP buffer is congested (#18605) 2026-08-24 11:30:11 +12:00
J. Nick Koston 41171e61d1 [core] Keep str_contains_ignore_case needle literals in flash on ESP8266 (#18574) 2026-08-24 11:29:05 +12:00
J. Nick Koston bdf8dec028 [i2s_audio] Skip SPDIF speaker sources when spdif_mode is off (#18676) 2026-08-24 11:16:03 +12:00
J. Nick Koston a872626fba [esp32_ble] Skip ble_advertising.cpp when advertising is not used (#18679) 2026-08-24 11:15:54 +12:00
J. Nick Koston 00bdbf8ed1 [uart] Skip uart_debugger.cpp when no debug block is configured (#18678) 2026-08-24 11:15:21 +12:00
J. Nick Koston 25fb3983cb [mqtt] Skip entity sources for entity types not in the config (#18677) 2026-08-24 11:14:40 +12:00
J. Nick Koston 4510f10491 [core] Treat a malformed build_info.json as stale instead of crashing (#18669) 2026-08-24 11:13:57 +12:00
J. Nick Koston 0ecc7045fa [core] Parse the common on/off spellings in boolean env vars (#18667) 2026-08-24 11:13:34 +12:00
J. Nick Koston 5cc1f001fa [light] Skip light_json_schema.cpp when json is not used (#18675) 2026-08-24 11:12:58 +12:00
J. Nick Koston 76caadc594 [noise] Add shared noise component and move api noise primitives (#18490) 2026-08-24 11:03:44 +12:00
Jesse Hills 7d34efecf2 Merge branch 'release' into dev 2026-08-24 10:37:28 +12:00
Jesse Hills c4096d44d8 Merge pull request #18696 from esphome/bump-2026.8.1
2026.8.1
2026-08-24 10:37:06 +12:00
Jesse Hills 68f3a6b9a5 Bump version to 2026.8.1 2026-08-24 09:19:29 +12:00
J. Nick Koston 662bf7d7f0 [esp32_ble_tracker] Scan at the default window while a GATT connection is active (#18609) 2026-08-24 09:19:28 +12:00
J. Nick Koston 0d71ab8efb [api] Fix loop stall that triggers the task watchdog when entity list sends block (#18577) 2026-08-24 09:19:28 +12:00
J. Nick Koston 4ce4768ebd [core] Retry transient network errors when downloading external files (#18538) 2026-08-24 09:19:28 +12:00
J. Nick Koston fb13327922 [esp32] Report abort and task watchdog panics correctly in crash handler (#18575) 2026-08-24 09:19:28 +12:00
J. Nick Koston 4c62420f1b [core] Dump the main.cpp config comment with sorted keys (#18653) 2026-08-24 09:19:28 +12:00
J. Nick Koston ca3f31643f [esp8266] Don't report stale crash state after hardware WDT resets (#18597) 2026-08-24 09:19:28 +12:00
J. Nick Koston d770004e0e [esp32_ble] Log connection parameter update results (#18607) 2026-08-24 09:19:28 +12:00
J. Nick Koston b28efcd545 [bk72xx_ble] Block BK7238 until the LibreTiny bonding partition fix lands (#18649) 2026-08-24 09:19:28 +12:00
esphome[bot] 6b6d27f905 Bump bundled esphome-device-builder to 1.12.4 (#18651) 2026-08-24 09:19:28 +12:00
esphome[bot] 603c3539a3 Bump bundled esphome-device-builder to 1.12.3 (#18601) 2026-08-24 09:19:28 +12:00
Jonathan Swoboda f248a85b51 [esp32_hosted] Fire on_update_available trigger when update is detected (#18591) 2026-08-24 09:19:28 +12:00
5a3d7e3292 [emontx] Fix sensor state_class defaults not being applied correctly (#17610)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-24 09:19:28 +12:00
J. Nick Koston c6d329db64 [espnow] Fix dump_config crash when enable_on_boot is false (#18572) 2026-08-24 09:19:28 +12:00
esphome[bot] bdb203d742 Bump bundled esphome-device-builder to 1.12.2 (#18573) 2026-08-24 09:19:27 +12:00
J. Nick Koston f509516d60 [core] Keep templated !include filenames as strings so Windows path normalization cannot corrupt them (#18549) 2026-08-24 09:19:27 +12:00
J. Nick Koston 4c856949c2 [nrf52] Rebuild the Python env when its interpreter symlink dangles (#18540) 2026-08-24 09:19:27 +12:00
esphome[bot] c90a5f4cff Bump bundled esphome-device-builder to 1.12.1 (#18541) 2026-08-24 09:19:27 +12:00
Markus Häll 964fc1ef3f [wifi] Take the lwIP core lock around sntp_servermode_dhcp() (#18511) 2026-08-24 09:19:27 +12:00
J. Nick Koston 98f138f6b2 [esp32_ble_tracker] Scan at the default window while a GATT connection is active (#18609) 2026-08-24 09:16:01 +12:00
J. Nick Koston 9179fe26ce [api] Fix loop stall that triggers the task watchdog when entity list sends block (#18577) 2026-08-24 08:38:19 +12:00
J. Nick Koston e6c49e2bd9 [core] Retry transient network errors when downloading external files (#18538) 2026-08-24 08:25:39 +12:00
d84293931b [online_image] Support image format auto-detection (#16337)
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: J. Nick Koston <nick@home-assistant.io>
2026-08-23 19:58:01 +00:00
Boris Krivonog 2c32ac2221 [mitsubishi_cn105] Mark configurable classes as final (#18272) 2026-08-23 19:40:08 +00:00
Bonne EgglestonandClaude dde6906f98 [modbus_client] Add continuous option to the read and send actions (#18542)
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-23 13:01:34 -05:00
J. Nick Koston 4efd308345 [tests] Fix flaky pty log probe test on macOS (#18681) 2026-08-23 11:26:55 -05:00
esphome[bot] f741c274d5 Bump aioesphomeapi from 45.13.1 to 46.0.0 (#18683) 2026-08-23 15:55:42 +00:00
J. Nick Koston cf31c08a5c [core] Skip copying entity automation and filter sources when unused (#18602) 2026-08-23 09:05:04 -05:00
J. Nick Koston e7574a574b [ota] Restore lazy flash erase for ESP32 OTA with 64 KiB block erase (#18580) 2026-08-23 09:04:48 -05:00
J. Nick Koston 33484108a9 [core] Replace a damaged existing file in write_file_if_changed (#18665) 2026-08-23 09:04:24 -05:00
J. Nick Koston e697a40fda [core] Register the OTA component in dummy_main like its siblings (#18666) 2026-08-23 09:04:06 -05:00
J. Nick Koston d1f065671e [http_request] Abort OTA backend when update fails before first write (#18581) 2026-08-22 22:21:04 -05:00
J. Nick Koston 02da5c6484 [ethernet] Remove deprecated get_eth_mac_address_pretty() (#18379) 2026-08-22 22:02:41 -05:00
J. Nick Koston b2440cb655 [modbus] Remove deprecated waiting_for_response() (#18381) 2026-08-22 22:02:22 -05:00
J. Nick Koston 160d8b8f0c [web_server_idf] Remove deprecated AsyncWebServerRequest::url() (#18382) 2026-08-22 22:02:05 -05:00
J. Nick Koston 8899713ef9 [core] Remove deprecated gamma_correct and gamma_uncorrect (#18376) 2026-08-22 22:00:53 -05:00
J. Nick Koston f3cdefce21 [wifi] Remove deprecated wifi_ssid() (#18378) 2026-08-22 22:00:38 -05:00
J. Nick Koston b115813fbe [esp32] Report abort and task watchdog panics correctly in crash handler (#18575) 2026-08-22 22:00:17 -05:00
J. Nick Koston ab45ab316a [core] Remove deprecated entity_base getters (#18375) 2026-08-22 22:00:02 -05:00
J. Nick Koston 5b3a6c05bf [core] Remove deprecated esp_log_vprintf_ flash-string overload (#18377) 2026-08-22 21:59:47 -05:00
J. Nick Koston cd53681787 [wifi] Inline the remaining trivial WiFiAP and WiFiComponent accessors (#18617) 2026-08-23 02:51:39 +00:00
J. Nick Koston f0651e5c9b [radio_frequency] Inline the trivial make_call helper (#18645) 2026-08-22 21:07:34 -05:00
J. Nick Koston f24b731f95 [infrared] Inline the trivial make_call helper (#18644) 2026-08-22 21:07:14 -05:00
J. Nick Koston 01ad424d12 [datetime] Inline the trivial make_call helpers (#18643) 2026-08-22 21:07:03 -05:00
J. Nick Koston 435d522683 [text] Inline the trivial Text publish_state forwarding overloads (#18642) 2026-08-22 21:06:47 -05:00
J. Nick Koston a63c3bc0c7 [valve] Inline the trivial Valve and ValveCall accessors (#18641) 2026-08-22 21:06:31 -05:00
J. Nick Koston b83ce91528 [display] Inline the trivial DisplayPage setters and page navigation helpers (#18639) 2026-08-22 21:06:03 -05:00
J. Nick Koston a30238aab6 [wireguard] Inline the trivial Wireguard setters (#18638) 2026-08-22 21:05:51 -05:00
J. Nick Koston 47156c9a5b [mqtt] Inline the trivial MQTT client, component and sensor accessors (#18637) 2026-08-22 21:05:39 -05:00
J. Nick Koston 78240c9a46 [sprinkler] Inline the trivial Sprinkler accessors (#18636) 2026-08-22 21:04:57 -05:00
J. Nick Koston 5a9f06e584 [thermostat] Inline the trivial ThermostatClimate setters and getters (#18635) 2026-08-22 21:04:41 -05:00
J. Nick Koston ecb007da70 [deep_sleep] Inline the trivial DeepSleepComponent setters (#18634) 2026-08-22 21:04:23 -05:00
J. Nick Koston ad1a4fca36 [version] Inline the trivial VersionTextSensor setters (#18633) 2026-08-22 21:04:08 -05:00
J. Nick Koston 832a738588 [switch] Inline the trivial inverted accessors (#18632) 2026-08-22 21:03:51 -05:00
J. Nick Koston fedb3ac5c1 [fan] Inline the trivial Fan call helpers (#18631) 2026-08-22 21:03:38 -05:00
J. Nick Koston cb4e55e444 [cover] Inline the trivial Cover and CoverCall accessors (#18630) 2026-08-22 21:03:15 -05:00
J. Nick Koston 3ef5a8e6a4 [water_heater] Inline the trivial visual override setters (#18629) 2026-08-22 21:03:07 -05:00
J. Nick Koston 0e915e9b8b [core] Inline the ESPTime::strftime std::string overload (#18628) 2026-08-22 21:02:58 -05:00
J. Nick Koston dba3b287dd [api] Inline the trivial APIServer accessors (#18627) 2026-08-22 21:02:14 -05:00
J. Nick Koston ce019f508d [safe_mode] Inline the trivial set_safe_mode setters (#18626) 2026-08-22 21:02:04 -05:00
J. Nick Koston 5c2286cc4a [climate] Inline the trivial visual override setters (#18624) 2026-08-22 21:01:55 -05:00
J. Nick Koston efc0a94112 [text_sensor] Inline the trivial TextSensor forwarding overloads (#18623) 2026-08-22 21:01:42 -05:00
J. Nick Koston c60062c418 [sensor] Inline the trivial ExponentialMovingAverageFilter setters (#18622) 2026-08-22 21:01:28 -05:00
J. Nick Koston 763a1d9371 [select] Inline the trivial Select accessors (#18621) 2026-08-22 21:01:16 -05:00
J. Nick Koston 4db1666024 [light] Inline the trivial LightState accessors (#18620) 2026-08-22 21:00:59 -05:00
J. Nick Koston 0dc69aab1e [logger] Inline the trivial Logger accessors (#18619) 2026-08-22 21:00:49 -05:00
J. Nick Koston a282cb095e [ethernet] Inline the trivial EthernetComponent setters (#18618) 2026-08-22 21:00:39 -05:00
J. Nick Koston 259e7182a3 [esp32] Exclude esp_gdbstub from the build by default (#18604) 2026-08-22 20:59:55 -05:00
J. Nick Koston 74bdf275d2 [core] Dump the main.cpp config comment with sorted keys (#18653) 2026-08-22 20:58:28 -05:00
J. Nick Koston 14499223fd [esp8266] Don't report stale crash state after hardware WDT resets (#18597) 2026-08-22 20:58:13 -05:00
J. Nick Koston 6aab523dd9 [esp32_ble] Log connection parameter update results (#18607) 2026-08-22 20:57:58 -05:00
J. Nick Koston 1f31e51446 [esphome] Inline the trivial OTA port accessors (#18625) 2026-08-22 20:57:37 -05:00
J. Nick Koston c062d0c717 [ota] Log prepare, upload, and total OTA timing in espota2 (#18582) 2026-08-22 20:57:13 -05:00
J. Nick Koston dcabaedff1 [bk72xx_ble] Block BK7238 until the LibreTiny bonding partition fix lands (#18649) 2026-08-23 11:59:24 +12:00
Oliver Kleineckeandp1ngb4ck d119ad6c60 [usb_uart] Extract non-final USBUartChannelBase from USBUartChannel (#17472)
Co-authored-by: p1ngb4ck <p@local>
2026-08-22 10:47:46 -05:00
esphome[bot] 74fc2e367a Bump bundled esphome-device-builder to 1.12.4 (#18651) 2026-08-22 15:42:53 +00:00
Jesse HillsandJonathan Swoboda ea10f94376 [core] Add type annotations to component Python (10/11) (#18347)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-08-22 10:31:47 -05:00
ef1d77885d [captive_portal] Show each network once in the scan list (#17847)
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: Bluetooth Devices Bot <bluetooth@koston.org>
2026-08-22 05:04:08 +00:00
Keith Burzinski dccf55eadc [remote_transmitter] Use hardware PWM on rtl87xx to fix watchdog crash (#18579) 2026-08-21 23:53:16 -05:00
Boris KrivonogandJ. Nick Koston 65704e881f [mitsubishi_cn105] Add Fahrenheit support (#15488)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-21 23:52:18 -05:00
Brandon Harvey a30e82459f [deep_sleep] Reject wakeup_pin_mode at both levels on BK72xx (#18615) 2026-08-21 23:51:19 -05:00
Brandon Harvey 5a300e92f1 [wifi] Inline the trivial WiFiScanResult accessors (#18613) 2026-08-22 04:14:56 +00:00
Keith BurzinskiandJ. Nick Koston 8e9fb0f93c [remote_transmitter] Fix repeat gap timing on LibreTiny Beken (#18585)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-21 23:10:47 -05:00
esphome[bot] 11ea819bc7 Bump aioesphomeapi from 45.12.0 to 45.13.1 (#18600) 2026-08-21 14:36:47 -05:00
esphome[bot] abc9098bd8 Bump bundled esphome-device-builder to 1.12.3 (#18601) 2026-08-21 14:05:00 -05:00
Kevin Ahrendt 00cffa09a2 [sendspin] Convert tests to package-style includes (#18588) 2026-08-21 13:05:07 -05:00
Jesse Hills aa944456e0 [core] Add type annotations to component Python (6/11) (#18343) 2026-08-21 11:11:52 -05:00
Jonathan Swoboda 409d74a48d [esp32_hosted] Fire on_update_available trigger when update is detected (#18591) 2026-08-21 11:53:44 -04:00
7957808f00 [emontx] Fix sensor state_class defaults not being applied correctly (#17610)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-21 09:57:58 -05:00
J. Nick Koston 52bfc0efb1 [espnow] Fix dump_config crash when enable_on_boot is false (#18572) 2026-08-20 18:06:23 -05:00
guillempagesandJ. Nick Koston 46f90d0c54 [core] Add portable strcasestr implementation named str_contains_ignore_case (#18497)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-20 17:28:17 -05:00
5177972c04 [runtime_image] keep decoder allocated (#18488)
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>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-20 17:27:44 -05:00
esphome[bot] ece90ee97b Bump bundled esphome-device-builder to 1.12.2 (#18573) 2026-08-20 16:59:30 -05:00
dependabot[bot] 4cfa4893ef Bump docker/setup-buildx-action from 4.2.0 to 4.3.0 in the docker-actions group (#18564)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-20 15:24:28 -05:00
dependabot[bot] edd4a86d14 Bump prek from 0.4.13 to 0.4.14 (#18563)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-20 15:02:15 -05:00
Jesse Hills 44dcd82d78 [mipi_spi] Toggle D/C only while holding the SPI bus (#18529) 2026-08-21 07:58:11 +12:00
Jesse Hills 12da2140cf [core] Add type annotations to component Python (11/11) (#18348) 2026-08-21 07:57:14 +12:00
Jesse Hills c006e9804a [core] Add type annotations to component Python (9/11) (#18346) 2026-08-21 07:56:48 +12:00
Jesse HillsandJonathan Swoboda 6343c11873 [core] Add type annotations to component Python (5/11) (#18342)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-08-21 07:56:02 +12:00
David van 't Wout 2ab09e1a77 [core] Add add_cmake_arg (#18498) 2026-08-20 12:30:33 -05:00
J. Nick Koston a3ea77c2f1 [core] Keep templated !include filenames as strings so Windows path normalization cannot corrupt them (#18549) 2026-08-20 11:32:15 -05:00
J. Nick Koston 7fe4399b94 [esp32] Grow the default IDF component exclusion list (#18536) 2026-08-20 16:11:53 +00:00
Jesse Hills 545f762568 [core] Add type annotations to component Python (8/11) (#18345) 2026-08-20 12:08:26 -04:00
Jesse Hills e83439eaae [core] Add type annotations to component Python (7/11) (#18344) 2026-08-20 12:07:10 -04:00
Jesse Hills b6a9761dae [core] Add type annotations to component Python (4/11) (#18341) 2026-08-20 10:59:51 -04:00
Jesse Hills fbe4b39a16 [core] Add type annotations to component Python (3/11) (#18340) 2026-08-20 10:58:58 -04:00
Jesse HillsandJonathan Swoboda ecca240eef [core] Add type annotations to component Python (2/11) (#18339)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-08-20 14:26:16 +00:00
J. Nick Koston 347a6155f8 [uptime] Skip the timestamp sensor source when no time component is configured (#18535) 2026-08-20 10:07:17 -04:00
J. Nick Koston a8e721abeb [esp32] Apply IDF component exclusions to native toolchain builds (#18531) 2026-08-20 10:03:49 -04:00
J. Nick Koston 2d62ea78d2 [ota] Skip partition-access OTA sources when the feature is disabled (#18532) 2026-08-20 10:00:11 -04:00
J. Nick Koston 8ef0f38f4e [ethernet] Skip the custom W5500 SPI driver for other ethernet types (#18533) 2026-08-20 09:59:30 -04:00
Jesse Hills 3c47ab42d6 [core] Add type annotations to component Python (1/11) (#18338) 2026-08-20 09:55:15 -04:00
Alar Aun aafeca5859 [modbus_controller] Brace single-statement log bodies to fix -Wempty-body (#18543) 2026-08-20 09:54:28 -04:00
J. Nick Koston 132f494195 [nrf52] Rebuild the Python env when its interpreter symlink dangles (#18540) 2026-08-20 07:59:57 -04:00
esphome[bot] 5e9de7c94b Bump bundled esphome-device-builder to 1.12.1 (#18541) 2026-08-20 00:00:44 -05:00
Markus Häll b7d0b676fc [wifi] Take the lwIP core lock around sntp_servermode_dhcp() (#18511) 2026-08-19 23:31:27 -05:00
Jesse Hills 55b45fc6fb Merge branch 'release' into dev 2026-08-20 14:32:46 +12:00
Jesse Hills 6f8dbb6fbc Merge pull request #18527 from esphome/bump-2026.8.0
2026.8.0
2026-08-20 14:32:15 +12:00
J. Nick Koston ca97c86d65 [ci] Install requirements_dev.txt when the venv cache misses (#18502) 2026-08-20 13:12:33 +12:00
Jesse Hills 828eac90f3 Bump version to 2026.8.0 2026-08-20 11:51:59 +12:00
J. Nick Koston d9359a70c1 [tests] Keep PlatformIO libdeps per xdist worker to stop a compile race (#18524) 2026-08-20 11:51:57 +12:00
Jesse Hills 29404a782c Merge branch 'beta' into dev 2026-08-20 10:32:46 +12:00
Jesse Hills e75a7a61fa Merge pull request #18523 from esphome/bump-2026.8.0b6
2026.8.0b6
2026-08-20 10:32:26 +12:00
J. Nick Koston 185f12266a [tests] Keep PlatformIO libdeps per xdist worker to stop a compile race (#18524) 2026-08-19 17:29:10 -05:00
J. Nick Koston c455991962 [ci] Key PlatformIO cache on the Python version so a runner image bump does not serve a broken LibreTiny venv (#18512) 2026-08-20 09:38:44 +12:00
Jesse Hills f735dcadc0 Bump version to 2026.8.0b6 2026-08-20 09:33:05 +12:00
J. Nick Koston 78a65eabdc [ci] Stop jobs hanging on apt by restoring the cached apt action and bounding raw apt calls (#18518) 2026-08-20 09:33:03 +12:00
b3fda9973e [image] Restore defaults:/files: support for platform entries (#18032)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-20 09:33:03 +12:00
esphome[bot] 4a85c98285 Bump bundled esphome-device-builder to 1.12.0 (#18514) 2026-08-20 09:33:03 +12:00
esphome[bot] 2c92a2498e Bump bundled esphome-device-builder to 1.11.5 (#18507) 2026-08-20 09:33:03 +12:00
esphome[bot] 74e22b5ad7 Bump bundled esphome-device-builder to 1.11.4 (#18506) 2026-08-20 09:33:03 +12:00
esphome[bot] e9e77d02a0 Bump bundled esphome-device-builder to 1.11.3 (#18505) 2026-08-20 09:33:03 +12:00
Jonathan Swoboda 7418fcce8d [ci] Stop persisting the integration test ccache (#18504) 2026-08-20 09:33:03 +12:00
Jonathan Swoboda b768e2a1ce [esp32] Fix ESP32-P4 bootloop on rev3 (v3.x) chips when only variant is set (#18500) 2026-08-20 09:33:03 +12:00
J. Nick Koston 6084314cc9 [vscode] Report the origin of an unexpected exception during validation (#18494) 2026-08-20 09:33:03 +12:00
J. Nick Koston 2df953f3d7 [platformio] Give the ccache wrapper a cmd.exe safe path (#18495) 2026-08-20 09:33:03 +12:00
Bonne EgglestonandClaude Opus 4.8 10e592fa3a [modbus] CRC scan all unknown function codes (#18483)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-20 09:33:03 +12:00
J. Nick Koston a99a8f364e [api] Bump noise-c to 0.1.21 (#18484) 2026-08-20 09:33:03 +12:00
J. Nick Koston 200a1644a5 [ci] Fail the benchmark job when the C++ benchmark build fails (#18480) 2026-08-20 09:33:03 +12:00
J. Nick Koston 9daae377fc [api] Bump noise-c to 0.1.20 (#18482) 2026-08-20 09:33:02 +12:00
J. Nick Koston 0b1065feee [ci] Stop jobs hanging on apt by restoring the cached apt action and bounding raw apt calls (#18518) 2026-08-20 09:30:34 +12:00
Clyde Stubbs 47da743d11 [ai] Add instructions for concise comments (#18522) 2026-08-19 16:09:12 -05:00
470226ca03 [image] Restore defaults:/files: support for platform entries (#18032)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-19 12:30:12 -05:00
esphome[bot] 7b7107556f Bump bundled esphome-device-builder to 1.12.0 (#18514) 2026-08-19 12:21:58 -05:00
J. Nick Koston f90b776071 [ci] Key PlatformIO cache on the Python version so a runner image bump does not serve a broken LibreTiny venv (#18512) 2026-08-19 16:39:01 +00:00
esphome[bot] e26237e57d Bump bundled esphome-device-builder to 1.11.5 (#18507) 2026-08-19 00:42:05 -05:00
esphome[bot] d2c3f749ab Bump bundled esphome-device-builder to 1.11.4 (#18506) 2026-08-18 23:24:23 -05:00
esphome[bot] b7cc271219 Bump bundled esphome-device-builder to 1.11.3 (#18505) 2026-08-18 21:57:51 -05:00
dependabot[bot] 17eed7055b Bump resvg-py from 0.3.4 to 0.4.0 (#18460)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-18 22:22:51 -04:00
dependabot[bot] b7121940c8 Update wheel requirement from <0.48,>=0.43 to >=0.43,<0.49 (#18459)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-18 22:08:23 -04:00
Jonathan Swoboda 07fa16e2e7 [ci] Stop persisting the integration test ccache (#18504) 2026-08-18 21:38:18 -04:00
Jonathan Swoboda 8aa7db15e5 [esp32] Fix ESP32-P4 bootloop on rev3 (v3.x) chips when only variant is set (#18500) 2026-08-18 21:25:09 -04:00
J. Nick Koston 8b637b339b [vscode] Report the origin of an unexpected exception during validation (#18494) 2026-08-18 19:37:10 -05:00
J. Nick Koston 4f866c563b [platformio] Give the ccache wrapper a cmd.exe safe path (#18495) 2026-08-18 19:36:57 -05:00
J. Nick Koston 7a999f9a48 [ci] Install requirements_dev.txt when the venv cache misses (#18502) 2026-08-18 19:06:55 -05:00
esphome[bot] 0a88c81d95 Bump aioesphomeapi from 45.11.0 to 45.12.0 (#18501) 2026-08-18 18:38:23 -05:00
J. Nick Koston 804e8fb856 [socket] Remove constant duplicated by the beta merge (#18496) 2026-08-18 15:44:38 -05:00
Jesse Hills 43939a9199 Merge branch 'beta' into dev 2026-08-19 08:01:33 +12:00
Jesse Hills f414a07bcd Merge pull request #18481 from esphome/bump-2026.8.0b5
2026.8.0b5
2026-08-19 08:01:14 +12:00
esphome[bot] 5c9d050ebe Bump aioesphomeapi from 45.10.3 to 45.11.0 (#18493) 2026-08-18 17:02:54 +00:00
Bonne EgglestonandClaude Opus 4.8 285a508e09 [modbus] CRC scan all unknown function codes (#18483)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-18 11:09:12 -05:00
J. Nick Koston 92f55f721f [api] Bump noise-c to 0.1.21 (#18484) 2026-08-18 14:32:37 +00:00
Jonathan Swoboda 476d540065 [ci] Fall back to files API when PR diff exceeds GitHub line limit (#18486) 2026-08-18 10:22:28 -04:00
J. Nick Koston ae730d6357 [ci] Fail the benchmark job when the C++ benchmark build fails (#18480) 2026-08-18 09:03:33 -05:00
J. Nick Koston 9823205ef3 [api] Bump noise-c to 0.1.20 (#18482) 2026-08-18 09:03:14 -05:00
Jesse Hills d1391c2b10 Bump version to 2026.8.0b5 2026-08-18 16:04:49 +12:00
J. Nick Koston 8b888f31e0 [gpio_expander][pcf8574][pca9554][tca9555][pca6416a][pi4ioe5v6408][mcp23016][mcp23xxx_base] Reject unsupported interrupt_pin options (inverted, allow_other_uses) (#18472) 2026-08-18 16:04:47 +12:00
Jesse Hills 6a247dfe91 [light] Replace rgb_order/is_rgbw/is_wrgb with channel_colors (#18474) 2026-08-18 16:01:54 +12:00
J. Nick Koston 482869fbbe [socket] Fix multi-second TCP stalls on ESP8266 by yielding to the SYS context (#18455) 2026-08-18 14:27:54 +12:00
esphome[bot] 4dea147386 Bump bundled esphome-device-builder to 1.11.2 (#18477) 2026-08-18 14:27:54 +12:00
J. Nick Koston 1fd6337254 [api] Bump noise-c to 0.1.19 (#18473) 2026-08-18 14:27:54 +12:00
esphome[bot] 4ce6d59484 Bump bundled esphome-device-builder to 1.11.1 (#18475) 2026-08-18 14:27:54 +12:00
J. Nick Koston 014cc19902 [api] Bump noise-c to 0.1.18 (#18451) 2026-08-18 14:27:54 +12:00
esphome[bot] b9041566ea Bump aioesphomeapi from 45.10.2 to 45.10.3 (#18433)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-08-18 14:27:54 +12:00
J. Nick Koston 3a403c40d5 [ld2420] Drop the setup priority override so setup runs after the UART bus (#18428) 2026-08-18 14:27:54 +12:00
esphome[bot] 096e71bd67 Bump aioesphomeapi from 45.10.1 to 45.10.2 (#18357) 2026-08-18 14:27:54 +12:00
J. Nick Koston fffa902a1a [gpio_expander][pcf8574][pca9554][tca9555][pca6416a][pi4ioe5v6408][mcp23016][mcp23xxx_base] Reject unsupported interrupt_pin options (inverted, allow_other_uses) (#18472) 2026-08-18 13:32:03 +12:00
Jesse Hills 463e3833da [light] Replace rgb_order/is_rgbw/is_wrgb with channel_colors (#18474) 2026-08-18 13:19:48 +12:00
J. Nick Koston 4416aacebb [socket] Fix multi-second TCP stalls on ESP8266 by yielding to the SYS context (#18455) 2026-08-18 13:09:29 +12:00
esphome[bot] 15a626bcf3 Bump bundled esphome-device-builder to 1.11.2 (#18477) 2026-08-17 19:16:38 -05:00
J. Nick Koston a347a2e879 [api] Bump noise-c to 0.1.19 (#18473) 2026-08-17 18:58:11 -05:00
dependabot[bot] 7be4566b41 Bump platformdirs from 4.11.2 to 4.11.3 (#18468)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-17 18:33:13 -05:00
esphome[bot] 96e26c6a5f Bump bundled esphome-device-builder to 1.11.1 (#18475) 2026-08-17 17:54:23 -05:00
J. Nick Koston 7362c01c67 [core] Replace base64 lookup tables with arithmetic mapping (#18454) 2026-08-17 16:14:06 -05:00
Jesse Hills e45b4e4938 [core] Make FINAL_VALIDATE_SCHEMA functions return None (#18457) 2026-08-18 08:26:24 +12:00
J. Nick Koston e32329cc11 [core] Sync pre-commit ruff hook with requirements (0.16.3) (#18469) 2026-08-17 15:00:37 -05:00
dependabot[bot] 199e368fe2 Bump astral-sh/setup-uv from 9.0.0 to 10.0.1 (#18463)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-17 14:57:50 -05:00
dependabot[bot] 55726120db Bump esphome/workflows/.github/workflows/lock.yml from 2026.7.0 to 2026.8.1 (#18465)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-17 14:47:28 -05:00
dependabot[bot] 346ba7e831 Bump github/codeql-action/analyze from 4.37.6 to 4.37.7 (#18467)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-17 14:47:18 -05:00
dependabot[bot] 9518006724 Bump ruff from 0.16.2 to 0.16.3 (#18458)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-17 14:46:04 -05:00
dependabot[bot] 3d5f6f692f Bump filelock from 3.32.2 to 3.32.3 (#18461)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-17 14:45:41 -05:00
dependabot[bot] 4712c15c75 Bump github/codeql-action/init from 4.37.6 to 4.37.7 (#18466)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-17 14:42:24 -05:00
dependabot[bot] 9bc72529a6 Bump astral-sh/setup-uv from 9.0.0 to 10.0.1 in /.github/actions/restore-python (#18462)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-17 14:42:08 -05:00
dependabot[bot] 6d20943a9c Bump esphome/workflows/.github/workflows/stale.yml from 61fd37a044cad4e9aa4303027b2a61b6a34da855 to a1c1485ab46ef41a84a6a9d8abd7fa4b7628fd70 (#18464)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-17 15:38:06 -04:00
J. Nick Koston a3af82867b [api] Bump noise-c to 0.1.18 (#18451) 2026-08-17 14:00:39 -05:00
J. Nick Koston 27483a4101 [core] Retry gh CLI calls on transient network errors in CI scripts (#18292) 2026-08-17 13:15:31 -05:00
J. Nick Koston 6d20ebc66b [socket] Shorten lwip TAG string (#18450) 2026-08-17 17:18:43 +00:00
J. Nick Koston 031a038b49 [deep_sleep] Shorten bk72xx TAG string (#18445) 2026-08-17 11:56:37 -05:00
J. Nick Koston f6c7434b2a [i2c] Shorten platform backend TAG strings (#18440) 2026-08-17 11:54:55 -05:00
J. Nick Koston 3d9fecb562 [remote_receiver] Shorten esp32 TAG string (#18447) 2026-08-17 11:54:52 -05:00
J. Nick Koston ebe93e2c68 [bluetooth_connection] Shorten platform TAG strings (#18449) 2026-08-17 11:54:35 -05:00
J. Nick Koston 1f4fcead38 [nextion] Shorten upload TAG strings (#18448) 2026-08-17 11:54:29 -05:00
J. Nick Koston 1f000ba668 [mqtt] Shorten esp32 backend TAG string (#18446) 2026-08-17 11:54:17 -05:00
J. Nick Koston e0d28d7f5c [http_request] Shorten platform backend TAG strings (#18444) 2026-08-17 11:54:03 -05:00
J. Nick Koston 47a58dd799 [internal_temperature] Shorten platform TAG strings (#18443) 2026-08-17 11:53:56 -05:00
J. Nick Koston 37bea1c153 [spi] Shorten platform backend TAG strings (#18442) 2026-08-17 11:53:48 -05:00
J. Nick Koston d1a7b8df8b [adc] Shorten platform TAG strings (#18441) 2026-08-17 11:53:42 -05:00
J. Nick Koston c01f24553c [uart] Shorten platform backend TAG strings (#18439) 2026-08-17 11:53:29 -05:00
J. Nick Koston 07e8b303b9 [ota] Shorten platform backend TAG strings (#18438) 2026-08-17 11:52:56 -05:00
esphome[bot] ebb0923362 Bump aioesphomeapi from 45.10.2 to 45.10.3 (#18433)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-08-16 22:34:00 -05:00
J. Nick Koston e1c279718f [ld2420] Drop the setup priority override so setup runs after the UART bus (#18428) 2026-08-16 21:57:12 -05:00
J. Nick Koston cf764740cf [api] Create the camera image reader lazily (#18421) 2026-08-16 21:56:58 -05:00
J. Nick Koston 58d549ed4c [api] Move NoiseProtocolId off the connection object (#18420) 2026-08-16 21:56:37 -05:00
Jesse Hills 6b22d8068d Merge branch 'beta' into dev 2026-08-17 11:36:10 +12:00
Jesse Hills 443d8f1f28 Merge pull request #18424 from esphome/bump-2026.8.0b4
2026.8.0b4
2026-08-17 11:33:27 +12:00
Jesse Hills 1ec21a2245 Bump version to 2026.8.0b4 2026-08-17 10:22:41 +12:00
J. Nick Koston bb7d4c3630 [esp32] Split crash handler addr2line hint per core (#18418) 2026-08-17 10:22:39 +12:00
J. Nick Koston f42fe9af29 [core] Skip redundant ESP8266 main loop wake posts from ISR context (#18416) 2026-08-17 10:22:39 +12:00
J. Nick Koston 0bc2d71370 [bk72xx_ble] Fail early with a clear error on non BLE 5.x SoCs (#18406) 2026-08-17 10:22:39 +12:00
luar123 594c12b3d9 [zigbee] bump esp-zigbee-sdk to 2.0.4 (#18415) 2026-08-17 10:22:39 +12:00
Jonathan Swoboda bca72e9b6d [sensor] Pass NaN through the delta filter again (#18400) 2026-08-17 10:22:39 +12:00
J. Nick Koston ce09504c92 [platformio] Skip ccache when the binary on PATH fails to run (#18407) 2026-08-17 10:22:39 +12:00
esphome[bot] dda4566b9e Bump bundled esphome-device-builder to 1.11.0 (#18403) 2026-08-17 10:22:39 +12:00
Samuel Sieb 46a5665a66 [rotary_encoder] account for min and max value when resetting (#18197) 2026-08-17 10:22:39 +12:00
esphome[bot] 9161f74bb1 Bump bundled esphome-device-builder to 1.10.0 (#18389) 2026-08-17 10:22:39 +12:00
J. Nick Koston 3f01f9895f [esp32_hosted] Require ESP-IDF 5.3 or newer (#18417) 2026-08-16 12:44:49 -07:00
J. Nick Koston 801a1817b5 [esp32] Split crash handler addr2line hint per core (#18418) 2026-08-16 12:44:00 -07:00
J. Nick Koston 32c76ae828 [core] Skip redundant ESP8266 main loop wake posts from ISR context (#18416) 2026-08-16 12:43:27 -07:00
J. Nick Koston c664f5fc95 [bk72xx_ble] Fail early with a clear error on non BLE 5.x SoCs (#18406) 2026-08-16 11:06:22 -07:00
luar123 2bc4681fd6 [zigbee] bump esp-zigbee-sdk to 2.0.4 (#18415) 2026-08-16 13:33:25 -04:00
Jonathan Swoboda 646501b0ef [sensor] Pass NaN through the delta filter again (#18400) 2026-08-16 12:36:51 -04:00
J. Nick Koston de3e657d8b [platformio] Skip ccache when the binary on PATH fails to run (#18407) 2026-08-16 08:42:47 -07:00
esphome[bot] 1add726892 Bump bundled esphome-device-builder to 1.11.0 (#18403) 2026-08-15 13:36:52 -07:00
Samuel Sieb 5a000cf5e4 [rotary_encoder] account for min and max value when resetting (#18197) 2026-08-15 11:16:04 -07:00
Joppy Furr 6ed676fe32 [lvgl] Restore long_press_repeat_time functionality (#18393) 2026-08-14 23:14:53 -07:00
esphome[bot] 7cceddb8a3 Bump bundled esphome-device-builder to 1.10.0 (#18389) 2026-08-15 01:48:27 +00:00
J. Nick Koston 039b897e7b [ethernet] Defer clk_mode removal to 2026.11.0 (#18380) 2026-08-14 18:45:36 -07:00
J. Nick Koston b178f74e5d [core] Save the validated config cache on the first upload or logs run (#18367) 2026-08-14 18:45:23 -07:00
Clyde Stubbs e5224e22ae [ci] Compare merge-branch base ref against the default branch (#18385) 2026-08-15 06:18:22 +10:00
Clyde Stubbs be66e8b99c [ci] Disable CodSpeed benchmarks job outside esphome/esphome (#18372) 2026-08-15 04:33:47 +10:00
Jesse Hills 4b91c8aff4 Merge branch 'beta' into dev 2026-08-14 23:15:57 +12:00
Jesse Hills 9d7997f55a Merge pull request #18368 from esphome/bump-2026.8.0b3
2026.8.0b3
2026-08-14 22:49:40 +12:00
Jesse Hills 4db47de556 Bump version to 2026.8.0b3 2026-08-14 17:36:56 +12:00
Karl Beecken c8de632764 [core] fix PYTHONPATH leak (#18360) 2026-08-14 17:36:54 +12:00
J. Nick Koston b794b7b1d1 [core] Restore cv.parse_esphome_version as a deprecated helper (#18366) 2026-08-14 17:36:54 +12:00
J. Nick Koston add18d4e35 [core] Partially revert "Hash entity keys from the raw name to fix collisions" (#18361) 2026-08-14 17:36:54 +12:00
J. Nick Koston 02c1810c3a [core] Load component aliases from a generated registry (#18335) 2026-08-14 17:36:54 +12:00
J. Nick Koston 4f3153375a [ota] Retry uploads that fail from network errors (#18332) 2026-08-14 17:36:54 +12:00
J. Nick Koston 1c3a67b5e8 [wifi] Fix ESP8266 crash in cnx_node_search when lwIP transmits after disconnect (#18333) 2026-08-14 17:36:54 +12:00
J. Nick Koston 236ff33a09 [esp32_ble] Silence spurious warnings for local key GAP events (#18359) 2026-08-14 17:36:54 +12:00
J. Nick Koston 7c07fb48c5 [esp32_ble_tracker] Fix missed BLE advertisements with WiFi on ESP-IDF 5.5.5 (#18356) 2026-08-14 17:36:54 +12:00
J. Nick Koston d72bab79d7 [web_server_base] Stop deleting the web server on captive portal teardown (#18324) 2026-08-14 17:36:54 +12:00
Karl Beecken 617e2ec1e0 [core] fix PYTHONPATH leak (#18360) 2026-08-14 17:23:34 +12:00
J. Nick Koston 1afac0312d [core] Restore cv.parse_esphome_version as a deprecated helper (#18366) 2026-08-14 17:22:22 +12:00
J. Nick Koston b05465145f [core] Add preference key stability integration test (#18364) 2026-08-13 21:14:30 -05:00
dependabot[bot] 990fc402fd Bump bleak from 2.1.1 to 3.0.2 (#16246)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-13 20:24:02 -05:00
J. Nick Koston dd51624fbb [core] Partially revert "Hash entity keys from the raw name to fix collisions" (#18361) 2026-08-13 20:06:48 -05:00
dependabot[bot] 45a056e337 Bump platformdirs from 4.11.1 to 4.11.2 (#18363)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-13 18:54:51 -05:00
dependabot[bot] 37782f7206 Bump prek from 0.4.12 to 0.4.13 (#18362)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-13 18:54:37 -05:00
J. Nick Koston 945c2458b3 [core] Load component aliases from a generated registry (#18335) 2026-08-13 13:31:19 -05:00
J. Nick Koston 7420d23867 [ota] Retry uploads that fail from network errors (#18332) 2026-08-13 13:31:06 -05:00
J. Nick Koston 191686c5b3 [wifi] Fix ESP8266 crash in cnx_node_search when lwIP transmits after disconnect (#18333) 2026-08-13 13:30:53 -05:00
J. Nick Koston 137351fa8d [esp32_ble] Silence spurious warnings for local key GAP events (#18359) 2026-08-13 13:27:01 -05:00
J. Nick Koston db5173697a [esp32_ble_tracker] Fix missed BLE advertisements with WiFi on ESP-IDF 5.5.5 (#18356) 2026-08-13 13:22:48 -05:00
c7940382a9 [const] move CONF_LABEL to components/const (#18354)
Co-authored-by: Oliver Kleinecke <kleinecke.oliver@googlemail.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-08-13 14:18:22 -04:00
esphome[bot] 87045ab9c0 Bump aioesphomeapi from 45.10.1 to 45.10.2 (#18357) 2026-08-13 11:14:14 -05:00
Oliver KleineckeandOliver Kleinecke f1c4086778 [const] Move CONF_SLOT to components/const (#18350)
Co-authored-by: Oliver Kleinecke <p1ngb4ck@users.noreply.github.com>
2026-08-13 23:36:11 +12:00
dependabot[bot]andJonathan Swoboda f337d0acff Bump pylint from 4.0.6 to 4.0.7 (#18320)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-08-13 02:13:29 +00:00
J. Nick Koston 9cc05b30d4 [web_server_base] Stop deleting the web server on captive portal teardown (#18324) 2026-08-12 21:09:01 -05:00
Jesse Hills e0b68c4d6d Merge branch 'beta' into dev 2026-08-13 14:06:46 +12:00
Jesse Hills 9c3407cfdd Merge pull request #18334 from esphome/bump-2026.8.0b2
2026.8.0b2
2026-08-13 14:06:28 +12:00
Jesse Hills d3e27054f6 Bump version to 2026.8.0b2 2026-08-13 13:30:47 +12:00
J. Nick Koston bd58b5c8b3 [core] Retry framework downloads on transient network errors (#18330) 2026-08-13 13:30:46 +12:00
J. Nick Koston c1a326f32e [core] Don't block logs startup on MQTT IP discovery when addresses are known (#18313) 2026-08-13 13:30:46 +12:00
J. Nick Koston a14ea0e8fa [ld2420] Fix out-of-bounds read when device reports unknown command error (#18322) 2026-08-13 13:30:46 +12:00
esphome[bot] 48d6368ff9 Bump bundled esphome-device-builder to 1.9.6 (#18328) 2026-08-13 13:30:46 +12:00
Kevin Ahrendt 83cff59fdd [sendspin] Bump sendspin-cpp to v0.7.2 (#18316) 2026-08-13 13:30:46 +12:00
esphome[bot] 89489b1f0d Bump aioesphomeapi from 45.10.0 to 45.10.1 (#18318) 2026-08-13 13:30:46 +12:00
J. Nick Koston 7569a7b5ce [usb_uart] Fix uint32_t format specifier warning in pl2303 (#18310) 2026-08-13 13:30:45 +12:00
J. Nick Koston 8e624b4117 [core] Retry framework downloads on transient network errors (#18330) 2026-08-13 12:14:50 +12:00
J. Nick Koston 787a909aa4 [core] Don't block logs startup on MQTT IP discovery when addresses are known (#18313) 2026-08-13 12:11:32 +12:00
J. Nick Koston 905485b673 [ld2420] Fix out-of-bounds read when device reports unknown command error (#18322) 2026-08-13 11:49:34 +12:00
esphome[bot] 99677390e0 Bump bundled esphome-device-builder to 1.9.6 (#18328) 2026-08-12 16:27:14 -05:00
Kevin Ahrendt f2121130f9 [sendspin] Bump sendspin-cpp to v0.7.2 (#18316) 2026-08-12 12:49:54 -04:00
esphome[bot] 1a01c34ec4 Bump aioesphomeapi from 45.10.0 to 45.10.1 (#18318) 2026-08-12 16:33:45 +00:00
J. Nick Koston 3c46cc9c35 [usb_uart] Fix uint32_t format specifier warning in pl2303 (#18310) 2026-08-12 10:59:24 -04:00
Jesse Hills e192ec8fee Merge branch 'beta' into dev 2026-08-13 00:29:08 +12:00
Jesse Hills ec6b4263a2 Merge pull request #18314 from esphome/bump-2026.8.0b1
2026.8.0b1
2026-08-13 00:28:40 +12:00
Jesse Hills 8a1aa5753d Bump version to 2026.9.0-dev 2026-08-12 22:53:42 +12:00
Jesse Hills 3e4661fe1e Bump version to 2026.8.0b1 2026-08-12 22:53:42 +12:00
J. Nick Koston 22153be4cd [core] Add esphome logs over web_server HTTP SSE (#17110) 2026-08-12 22:00:07 +12:00
3f490fe1ed [internal_temperature] Read the RP2 on-die sensor directly instead of via the Arduino API (#18262)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-08-12 21:42:05 +12:00
J. Nick Koston 58a42fe5c2 [core] Batch remote file downloads during config validation (#18069) 2026-08-12 18:44:35 +12:00
25c0c2c97b [hoermann_hcp] Add garage light control (#18190)
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>
2026-08-12 06:10:23 +00:00
J. Nick Koston 622942482c [rp2] Size the lwIP segment pool and heap for concurrent senders (#18257) 2026-08-12 17:30:17 +12:00
Keith Burzinski cffd775450 [ethernet][network][wifi] Arbitrate the default route from the network priority list (#17797) 2026-08-12 16:21:37 +12:00
J. Nick Koston 8d87ba34d9 [api] Move the generic buffer-full log to very verbose (#18300) 2026-08-12 04:04:07 +00:00
J. Nick Koston 08c6585915 [esp32_ble_tracker] Don't log an error when a scan stop is already in flight (#18306) 2026-08-12 16:03:28 +12:00
J. Nick Koston 3ef74d17af [bluetooth_proxy] Give partial advertisement batches 200ms to fill on Wi-Fi (#18303) 2026-08-12 16:02:51 +12:00
J. Nick Koston 5d04c1dc18 [esp32_ble_tracker] Demote scan-state echoes to verbose (#18302) 2026-08-12 16:01:45 +12:00
J. Nick Koston a3d599ac69 [bluetooth_connection] Demote rp2 backend connection logs to verbose (#18301) 2026-08-12 16:00:37 +12:00
J. Nick Koston a4e05cd1c8 [bluetooth_proxy] Move per-advertisement logging to very verbose (#18299) 2026-08-12 15:59:41 +12:00
J. Nick Koston 1758653330 [voice_assistant] Do not consume the audio chunk when the send is refused (#18295) 2026-08-12 15:59:26 +12:00
J. Nick Koston a2feff8f68 [api] Mark send_message nodiscard so refused frames are never silent (#18293) 2026-08-11 22:23:08 -05:00
J. Nick Koston 37eae9b466 [api] Gate the bluetooth connection messages on their own define (#18281) 2026-08-11 21:31:13 -05:00
Jesse Hills 9605b34c69 [adc] Deprecate pin: TEMPERATURE in favour of internal_temperature (#18304) 2026-08-12 14:20:41 +12:00
Jesse Hills bab62b345b [adc] Fix internal temperature channel on RP2350A under arduino-pico (#18307) 2026-08-12 14:19:59 +12:00
Jesse Hills 3349046c5d [rp2] Record the RP2350 die on generated board entries (#18305) 2026-08-12 01:56:05 +00:00
J. Nick Koston 3f5b8139f3 [bluetooth_proxy] Latch the connection replies and tighten the send paths (#18278) 2026-08-12 13:52:25 +12:00
Jonathan SwobodaandJ. Nick Koston be5e28ea9e [core] Warn when running a different source tree than the one you are in (#18288)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-11 21:06:57 -04:00
J. Nick Koston 9f28638ee7 [bluetooth_proxy] Reset every owed reply in one place (#18276) 2026-08-11 19:15:21 -05:00
J. Nick Koston 201f843e95 [bluetooth_proxy] Latch the unpair reply (#18274) 2026-08-11 18:57:51 -05:00
J. Nick Koston 37a59a07bc [bluetooth_proxy] Retry dropped GATT acks and stop the retry log spam (#18259) 2026-08-11 18:40:47 -05:00
Boris KrivonogandJ. Nick Koston 9556c2bc4c [mitsubishi_cn105] Add vertical vane control action (#16737)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-11 18:39:05 -05:00
Bonne EgglestonandJonathan Swoboda 3540012529 [tests] Build tests from the tree they run in, not the venv's editable install (#18248)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-08-11 19:09:51 -04:00
Kevin AhrendtandJ. Nick Koston e0b112c584 [sendspin] Clear metadata and controller state on disconnect (#18289)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-11 21:03:27 +00:00
Kevin Ahrendt 7f0d6a8696 [sendspin] Add image platform for artwork (#17937) 2026-08-11 15:49:08 -05:00
Kevin Ahrendt 4a7de87bff [audio] Bump microDecoder to v0.4.0 (#18291) 2026-08-11 15:33:37 -05:00
esphome[bot] b9d1d2f06b Bump aioesphomeapi from 45.9.0 to 45.10.0 (#18294) 2026-08-11 20:02:53 +00:00
dependabot[bot] 74c30c62ef Bump setuptools from 83.0.0 to 84.0.0 (#18290)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-11 14:36:59 -05:00
J. Nick Koston 94fbfa05de [core] Show the out-of-flash tip instead of crashing the build (#18280) 2026-08-11 14:35:06 -05:00
Boris KrivonogandJ. Nick Koston 55bd63732d [mitsubishi_cn105] Add vertical vane state trigger (#16727)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-11 13:56:12 -05:00
J. Nick Koston 3ae651af7b [core] Stop dropping complete lines behind an unfinished one (#18279) 2026-08-11 12:38:55 -05:00
esphome[bot] 55e8bc3b14 Bump aioesphomeapi from 45.8.0 to 45.9.0 (#18283) 2026-08-11 17:23:36 +00:00
J. Nick Koston 9938a2487d [core] Show the last line when output stops without a newline (#18265) 2026-08-11 10:55:42 -05:00
J. Nick Koston aee41d64c2 [rp2040_ble][bluetooth_connection] 3 connection slots on rp2 with esp32 parity (#18247) 2026-08-11 08:43:08 -05:00
J. Nick Koston f3a5a9fbd5 [core] Retry transient git network failures with backoff (#18242) 2026-08-11 08:41:55 -05:00
Bonne EgglestonandJ. Nick Koston 8ee3c8d41d [modbus] Properly support client-mode broadcast sends (#17467)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-11 08:31:15 -05:00
J. Nick Koston eefd2a00c7 [espidf] Flush the runner's output so dashboard builds stream (#18264) 2026-08-11 08:11:42 -05:00
J. Nick Koston e8852c5950 [core] Flush stdout in safe_print so logs stream live (#18261) 2026-08-11 08:11:23 -05:00
Josef ZweckandJ. Nick Koston 069f40f653 [hoermann_hcp] Add connectivity binary sensor (#18189)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-11 08:09:33 -05:00
Jesse Hills 04dd6b3a55 [core] Use MAC address size constants instead of literals (#18254) 2026-08-11 08:27:32 -04:00
Jesse Hills 2ff55e3058 [rp2] Use SDK clock query directly in arch_get_cpu_freq_hz (#18269) 2026-08-11 08:23:08 -04:00
Jesse Hills e5cdda9ee5 [adc] Fix RP2350B internal temperature reading wrong ADC channel (#18270) 2026-08-11 08:22:52 -04:00
Jesse Hills ecec3a19c7 [debug] Remove Arduino core dependency from RP2 platform code (#18267) 2026-08-11 08:22:20 -04:00
J. Nick Koston 9823ad6abc [tests] Fix flaky modbus server/controller integration tests (#18258) 2026-08-10 23:56:32 -05:00
J. Nick Koston 51b0240fb8 [rp2] Fix %f formatting in logs (#18256) 2026-08-10 22:05:19 -05:00
Jesse Hills f697cf2011 [api] Add DeviceCapabilities message for optional-feature flags (#17984) 2026-08-11 14:52:19 +12:00
Jesse Hills 8728aaa616 [core] Use MAC address size constants in BLE components (#18252) 2026-08-11 14:21:03 +12:00
J. Nick Koston eab9a47aa2 [bluetooth_proxy] Retry dropped services-done, disconnect and scanner-state notifications (#18225) 2026-08-11 14:20:39 +12:00
Jesse Hills c2ba2fbfc4 [ld24xx] Use MAC address size constants instead of literals (#18253) 2026-08-11 14:18:09 +12:00
J. Nick Koston 3de01d2a2e Bump aioesphomeapi to 45.8.0 (#18251) 2026-08-10 19:56:35 -05:00
dependabot[bot] 791d6659c0 Bump platformdirs from 4.11.0 to 4.11.1 (#18250)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-11 00:43:35 +00:00
Boris KrivonogandJ. Nick Koston 007c677da1 [mitsubishi_cn105] Refactor property encoding/decoding (#16709)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-10 18:58:34 -05:00
Bonne EgglestonandClaude Fable 5 2a0f2d59f0 [modbus_server] Add coil/discrete-input support (#17464)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-10 18:13:12 -05:00
c8d2c3691a [mitsubishi_cn105] Add vertical vane direction select (#16723)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-08-10 17:58:37 -05:00
Josef ZweckandJ. Nick Koston 82a63658f9 [hoermann_hcp] Add Hörmann HCP garage door component (#17355)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-10 17:20:20 -05:00
Bonne Eggleston 596827c51c [modbus_client] Add read/write multiple registers (FC 0x17) (#18215) 2026-08-10 15:18:48 -05:00
J. Nick Koston 8a16ead8ce [web_server] Fix basic auth with long credentials (#18237) 2026-08-10 14:49:14 -05:00
dependabot[bot] 334afdefb5 Update argcomplete requirement from >=3.7.0 to >=3.7.2 (#18243)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 15:44:32 -04:00
dependabot[bot] e7a2980b9c Bump ruff from 0.16.1 to 0.16.2 (#18245)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-10 15:44:30 -04:00
dependabot[bot] b5a78c6c46 Bump CodSpeedHQ/action from 5.0.2 to 5.0.3 (#18246)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-10 19:36:22 +00:00
dependabot[bot] 8650d175f4 Bump aiohappyeyeballs from 2.6.2 to 2.7.1 (#18244)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-10 14:26:41 -05:00
2999e7b925 [modbus] Add API for reading/writing coils and discrete inputs in server mode (#17264)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-10 14:23:49 -05:00
207ae2e4cb [bk72xx_ble] Support active scanning by packing the GAPM start command (#18169)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: bdraco <663432+bdraco@users.noreply.github.com>
2026-08-10 14:02:37 -05:00
Boris Krivonog 9e78a768a2 [mitsubishi_cn105] Extract top-level hub (#16987) 2026-08-10 14:02:16 -05:00
J. Nick Koston e4d08a73b0 [ufm01] Prefix PassiveReadResult enumerators to avoid Realtek SDK macro collision (#18240) 2026-08-10 13:03:01 -05:00
J. Nick Koston 4cf7ad9c63 [ble_device_base] Treat a partially bound merger as unbound (#18235) 2026-08-10 13:02:27 -05:00
J. Nick Koston 293d0b90d9 [core] Document enum class value naming to avoid platform SDK macro collisions (#18241) 2026-08-10 13:02:02 -05:00
J. Nick Koston 8f1e439792 [bluetooth_proxy] Finish the connection scan before reserving a slot (#18239) 2026-08-10 12:56:16 -05:00
J. Nick Koston ad733272e5 [bluetooth_proxy] Pair the advertisement flush time with hub_ to close alignment holes (#18234) 2026-08-10 12:40:22 -05:00
J. Nick Koston b7c6245388 [wifi] Save fast connect settings and reset roaming bookkeeping after driver initiated roams (#18167) 2026-08-10 12:39:32 -05:00
2184ec2928 [ethernet] Add CH390 SPI ethernet support (#18226)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-10 12:24:16 -05:00
J. Nick Koston bae7f19323 [core] Extend '/' in names deprecation window to 2027.7.0 (#18236) 2026-08-10 11:32:02 -05:00
56ec21d950 [ufm01] Improve startup with reset retry and passive polling fallback (#17567)
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-08-10 12:31:31 -04:00
J. Nick Koston 2798ef4de2 [ota] Enforce the backend contract with a concept (#18192) 2026-08-10 11:20:38 -05:00
J. Nick Koston e90b4abe9c [core] Enforce the preferences contracts with concepts (#18191) 2026-08-10 11:20:24 -05:00
J. Nick Koston f3d1fc0d64 [bluetooth_proxy] Migrate esp32 onto the neutral GATT backend (#18198) 2026-08-10 10:47:56 -05:00
J. Nick Koston c8c929d487 [ble_device_base] Merge adv and scan response before delivery on rp2 (#18217) 2026-08-10 10:06:06 -05:00
J. Nick Koston d9567b2974 Normalize marker-wrapped callable keys in the schema dump (#18218) 2026-08-10 10:05:37 -05:00
J. Nick Koston 02fa18b74f [core] Skip colorama init for terminal and dashboard runs (#18224) 2026-08-10 09:44:01 -05:00
Kevin Ahrendt 3656375516 [sendspin] Bump sendspin-cpp to v0.7.1 (#18232) 2026-08-10 09:00:29 -05:00
Mustafa KURUandJonathan Swoboda b0a9bfd381 [ld6002b] Add area and zone configuration (5/5) (#17823)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-08-10 09:59:32 -04:00
J. Nick Koston 25cb440005 [core] Use Happy Eyeballs for remote file downloads (#18050) 2026-08-10 17:29:00 +12:00
J. Nick Koston 0f59ef36a9 [core] Store the validated-config cache as JSON to drop YAML off the upload fast path (#18106) 2026-08-10 17:26:41 +12:00
esphome[bot] 3de8c7f95c Bump bundled esphome-device-builder to 1.9.5 (#18223) 2026-08-10 01:49:54 +00:00
Jesse Hills 989dbd7550 [ci] Name release runs after the version or dev tag they build (#18110) 2026-08-10 10:10:38 +12:00
ab12e5490f [modbus] Rename send_pdu() to queue_pdu() (#18196)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-09 17:00:44 -05:00
J. Nick Koston e9f428983e [ble_device_base] Bind BLEHub to the build's tracker at compile time (#18181) 2026-08-09 08:57:31 -05:00
J. Nick Koston 862b13c8dd [esp32_ble_tracker] Retire the scanner-state listener interface (#18179) 2026-08-08 20:58:48 -05:00
Edu_Coder 2bb01853e0 [tuya] GMT time 0x0C command handler (#17158) 2026-08-08 17:53:10 -07:00
J. Nick Koston c7d6b4aaa4 [esp32_ble_tracker] Retire the raw listener path and parser-type enum (#18177) 2026-08-08 19:13:07 -05:00
J. Nick Koston 8c74e3d5ef [bluetooth_proxy] Deliver scanner state through the hub callback (#18175) 2026-08-08 15:59:49 -05:00
J. Nick Koston 04384e0f5b [ble_device_base] Bind the GATT backend at compile time (#18185) 2026-08-08 15:59:32 -05:00
J. Nick Koston 7218aa4803 [bluetooth_connection] Explicit pairing for rp2 (#18166) 2026-08-08 09:51:12 -05:00
J. Nick Koston 9cb46aa584 [bluetooth_proxy] Deliver esp32 advertisements through the hub callback (#18173) 2026-08-08 09:50:32 -05:00
Josef Zweck 747c5c3e40 [modbus] Make sure we log on no accepting device (#18187) 2026-08-08 09:34:59 -05:00
Edvard Filistovič 68acc055bf [ble_device_base] Migrate BLE sensor platforms to the neutral layer (batch 13: xiaomi_rtcgq02lm, xiaomi_wx08zm, xiaomi_xmwsdj04mmc) (#18183) 2026-08-08 02:06:40 -05:00
2730c10c2c [modbus] Route broadcast writes (address 0) to all server devices (#17387)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-08 01:35:49 -05:00
Edvard Filistovič 252bb3333e [ble_device_base] Migrate BLE sensor platforms to the neutral layer (batch 12: xiaomi_miscale, xiaomi_mjyd02yla, xiaomi_mue4094rt) (#18180) 2026-08-08 01:34:08 -05:00
Edvard Filistovič 98f4854ecd [ble_device_base] Migrate BLE sensor platforms to the neutral layer (batch 11: xiaomi_lywsdcgq, xiaomi_mhoc303, xiaomi_mhoc401) (#18178) 2026-08-08 01:01:24 -05:00
Edvard Filistovič 413a4c5885 [ble_device_base] Migrate BLE sensor platforms to the neutral layer (batch 10: xiaomi_lywsd02, xiaomi_lywsd02mmc, xiaomi_lywsd03mmc) (#18174) 2026-08-08 00:27:44 -05:00
Edvard Filistovič 087b80eeb5 [ble_device_base] Migrate BLE sensor platforms to the neutral layer (batch 9: xiaomi_hhccjcy10, xiaomi_hhccpot002, xiaomi_jqjcy01ym) (#18172) 2026-08-07 23:42:37 -05:00
745dee0734 [usb_cdc_acm] Don't discard queued TX data when USB flush times out (#17637)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-07 23:24:56 -05:00
Edvard Filistovič b986530efc [ble_device_base] Migrate BLE sensor platforms to the neutral layer (batch 8: xiaomi_cgpr1, xiaomi_gcls002, xiaomi_hhccjcy01) (#18171) 2026-08-07 22:51:33 -05:00
Edvard Filistovič 3aaea907ba [ble_device_base] Migrate BLE sensor platforms to the neutral layer (batch 7: xiaomi_cgd1, xiaomi_cgdk2, xiaomi_cgg1) (#18170) 2026-08-07 21:59:21 -05:00
Edvard Filistovič 1d184b43eb [ble_device_base] Migrate BLE sensor platforms to the neutral layer (batch 6: thermopro_ble, exposure_notifications, xiaomi_ble) (#18168) 2026-08-07 20:47:52 -05:00
J. Nick Koston 8d494a84c5 [bluetooth_connection] Engine follow-ups from the rp2 GATT series (#18159) 2026-08-07 16:25:55 -05:00
Bonne EgglestonandClaude b0aec6dc2f [modbus_client] Lambda sugar (#18146)
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-07 16:09:15 -05:00
Edvard FilistovičandJ. Nick Koston 4a7d270494 [ble_device_base] Migrate BLE sensor platforms to the neutral layer (batch 5: airthings_ble, inkbird_ibsth1_mini, radon_eye_ble) (#18165)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-08-07 20:46:43 +00:00
dependabot[bot] ae26483be6 Bump github/codeql-action/init from 4.37.5 to 4.37.6 (#18164)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-07 19:27:57 +00:00
dependabot[bot] 5d7bd179b1 Bump github/codeql-action/analyze from 4.37.5 to 4.37.6 (#18163)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-07 14:27:09 -05:00
Edvard Filistovič 23a3454551 [ble_device_base] Migrate BLE sensor platforms to the neutral layer (batch 4: ruuvi_ble, ruuvitag, b_parasite) (#18161) 2026-08-07 14:21:46 -05:00
f5ee72753d [modbus_client] Add typed read/write actions (#18078)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-07 14:18:20 -05:00
esphome[bot] ee13996ee6 Bump bundled esphome-device-builder to 1.9.4 (#18162) 2026-08-07 19:17:26 +00:00
Josef ZweckandJ. Nick Koston c24e61439b [modbus] Add server support for read/write multiple registers (0x17) (#17357)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-07 14:17:11 -05:00
J. Nick Koston 2e1c517821 [bluetooth_proxy] Enable active connections on rp2 (#18132) 2026-08-07 13:51:41 -05:00
Mustafa KURUandJonathan Swoboda 950cfc4da3 [ld6002b] Add select and button platforms (4/5) (#17822)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-08-07 14:33:37 -04:00
Edvard FilistovičandJ. Nick Koston 715b14aeba [ble_device_base] Migrate BLE sensor platforms to the neutral layer (batch 3: mopeka_ble, mopeka_pro_check, mopeka_std_check) (#17951)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-07 12:59:27 -05:00
J. Nick Koston d7b5ad77da [bluetooth_connection] Add BTstack GATT client backend for rp2 (#18131) 2026-08-07 12:53:09 -05:00
Edvard Filistovič 77bfda6f1f [ble_device_base] Migrate BLE sensor platforms to the neutral layer (batch 2: atc_mithermometer, pvvx_mithermometer, bthome_mithermometer) (#17950) 2026-08-07 12:48:18 -05:00
b326cefea7 [esp32] refactor esp32-vfs default configs to FINAL co-routine & add some defaults (#17337)
Co-authored-by: Oliver Kleinecke <kleinecke.oliver@googlemail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: storage split <ai@local>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-08-07 12:36:59 -05:00
J. Nick Koston c0e70d9beb [rp2040_ble] Add scan arbitration and GATT client hooks (#18155) 2026-08-07 11:50:18 -05:00
J. Nick Koston c5e165d062 [bluetooth_proxy] Make the GATT dispatch platform neutral (#18130) 2026-08-07 11:29:19 -05:00
Edvard Filistovič 5f483b11b6 [ble_device_base] Migrate BLE sensor platforms to the neutral layer (batch 1: ble_presence, ble_rssi, ble_scanner) (#17716) 2026-08-07 16:19:08 +00:00
Mustafa KURUandJonathan Swoboda b802740997 [ld6002b] Add switch, number and text sensor platforms (3/5) (#17821)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-08-07 11:11:29 -04:00
Edvard Filistovič 1bbe8b415f [bluetooth_proxy] Only advance the scanner-state detector when the frame was sent (#18154) 2026-08-07 15:01:50 +00:00
Edvard FilistovičandJ. Nick Koston 8b0e23d55b [bluetooth_proxy] Fold scanner-state bookkeeping into the sender; extend platform-gate tests (#18150)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-08-07 14:30:00 +00:00
J. Nick Koston 2f2634bf6b [bluetooth_connection] Move BluetoothConnection out of bluetooth_proxy (#18129) 2026-08-07 08:54:28 -05:00
Jonathan Swoboda 9c93d8925f [ota] Use PSA crypto for signature verification on ESP-IDF 6 (#18145) 2026-08-07 07:41:48 -04:00
J. Nick Koston 634515ecc5 [ble_device_base] Add platform-neutral GATT client contract (#18128) 2026-08-06 21:45:57 -05:00
J. Nick Koston e58ba59288 [core] Add StringRef::starts_with (#18142) 2026-08-06 20:58:41 -05:00
Jonathan Swoboda bf95be5550 [opentherm] Initialize output state before the first write (#18126) 2026-08-06 21:46:37 -04:00
Jonathan Swoboda 96f0ea10f4 [midea] Bump MideaUART so its ESP-IDF shims stop shadowing millis() (#18119) 2026-08-06 21:46:28 -04:00
J. Nick Koston 97558ce64a [core] Add EventPool::warm() (#18127) 2026-08-06 20:40:04 -05:00
dependabot[bot]andJonathan Swoboda 4301e5a2a2 Bump resvg-py from 0.3.3 to 0.3.4 (#18137)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-08-06 19:58:52 -04:00
dependabot[bot]andJonathan Swoboda 09ecfa58de Bump prek from 0.4.11 to 0.4.12 (#18138)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-08-06 19:57:03 -04:00
dependabot[bot]andJonathan Swoboda 27f6ced1a9 Bump github/codeql-action/analyze from 4.37.4 to 4.37.5 (#18139)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-08-06 19:49:40 -04:00
dependabot[bot]andJonathan Swoboda 9802c7f32f Bump github/codeql-action/init from 4.37.4 to 4.37.5 (#18140)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-08-06 19:49:32 -04:00
Jonathan Swoboda bf36a62f62 [ci] Raise runner-concurrency caps for the OHF enterprise pool (#18125) 2026-08-06 19:47:12 -04:00
luar123andJonathan Swoboda 4c47051da9 [zigbee] Add on_start automation (3/3) (#18009)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-08-06 19:45:44 -04:00
56682534f8 [modbus_client] Add component for ad-hoc modbus request/response (#17676)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-06 14:52:23 -05:00
Mustafa KURUandJonathan Swoboda 53b1b3a253 [ld6002b] Add target sensors (2/5) (#17820)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-08-06 15:36:32 -04:00
zerafachris 4ccf4210be [epaper_spi] Do not yield on the final row of a T133A01 transfer phase (#17709) 2026-08-07 03:34:33 +10:00
Edvard FilistovičandJ. Nick Koston 3221ed2bad [ble_device_base] Hub provider registry and shared consumer helpers (#18081)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-06 12:13:30 -05:00
J. Nick Koston abc13a7c0a [script] Disable queued script polling while the queue is empty (#18121) 2026-08-06 10:00:46 -05:00
luar123 3353e71f9a [zigbee] Improve network handling on esp32 (2/3) (#18008) 2026-08-06 10:34:32 -04:00
J. Nick Koston 73689f8d8b [rp2] Limit pin validation to GPIO 0-29 on RP2350A boards (#18102) 2026-08-06 08:55:24 -05:00
Mustafa KURU ba86685361 [const] Move CONF_TARGET_COUNT to components/const (#18120) 2026-08-06 09:37:36 -04:00
Keith Burzinskiandpre-commit-ci-lite[bot] a16c2e2b04 [esp32] Use constants for the signing scheme identifiers (#18118)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-08-06 01:54:21 -05:00
J. Nick Koston eb0fac9cbf [core] Only snapshot the user config when esphome config --no-defaults asks for it (#18113) 2026-08-05 21:20:52 -05:00
Bonne Eggleston 3b6f45894b [core] StaticVector converting ctor (#18117) 2026-08-05 21:20:37 -05:00
Mustafa KURUandJonathan Swoboda f8cabc9d1f [ld6002b] Add LD6002B 60GHz presence radar (1/5) (#17819)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-08-05 22:18:51 -04:00
J. Nick Koston a7740091ec [ci] Run CodSpeed benchmarks when top-level esphome Python modules change (#18114) 2026-08-05 20:50:13 -05:00
esphome[bot] 0fcc2a6ff1 Bump bundled esphome-device-builder to 1.9.3 (#18116) 2026-08-05 20:50:00 -05:00
J. Nick Kostonandcopilot-swe-agent[bot] 0d192e8334 [rp2] Bump arduino-pico framework to 6.0.0 (#18101)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-08-06 01:21:35 +00:00
J. Nick Koston 2dfcde477f [ble_client] Reject descriptor_uuid combined with notify at validation time (#18109) 2026-08-05 19:09:45 -05:00
J. Nick Koston f971e404c7 [core] Resolve GCC multilib include dirs for clang-tidy (#18111) 2026-08-05 19:09:13 -05:00
J. Nick Koston 524b278811 [core] Defer stdlib imports out of the upload and logs fast path (#18105) 2026-08-05 19:09:00 -05:00
J. Nick Koston 7f80276cf4 [ble_device_base] Document the None output for unset UUIDs in to_str() (#18108) 2026-08-05 23:02:13 +00:00
J. Nick Koston 26256d3d2e [ble_device_base] [ble_client] Restore unset UUID state so notify sensors set up again (#18098) 2026-08-05 22:21:24 +00:00
Edvard Filistovič 1bd94bb805 [bluetooth_proxy] Scanner-state sync in set_mode; platform-gate tests (#18100) 2026-08-05 21:41:07 +00:00
J. Nick Koston 28aedc2b14 [core] Drop the duplicated FileLock import from a merge collision (#18103) 2026-08-05 16:08:06 -05:00
J. Nick Koston b700193a0a [core] Generalize the resolver's async thread dispatch into run_async (#18088) 2026-08-05 20:57:08 +00:00
J. Nick Koston 4fd2ddee55 [core] Trim the stacktrace gate commentary (#18097) 2026-08-05 20:50:48 +00:00
J. Nick Koston a2d1f73bca [core] Defer voluptuous and bundle imports out of the upload and logs fast path (#18093) 2026-08-05 20:39:19 +00:00
Jesse Hills f2472563f4 Merge branch 'release' into dev 2026-08-06 08:09:23 +12:00
Jesse Hills 90d6d8f5ca Merge pull request #18083 from esphome/bump-2026.7.4
2026.7.4
2026-08-06 08:08:37 +12:00
Jesse Hills d4b3d37165 Update URL for ESPHome Builder issue reporting (#16250) 2026-08-06 08:07:30 +12:00
Edvard FilistovičandJ. Nick Koston 563b6ade0f [bluetooth_proxy] Platform-neutral advertisement proxy via ble_device_base (#17880)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-05 15:06:01 -05:00
dependabot[bot] 17f3c9d780 Bump CodSpeedHQ/action from 5.0.1 to 5.0.2 (#18094)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-05 15:50:57 -04:00
dependabot[bot] 98622bd029 Bump esphome/workflows/.github/workflows/stale.yml from 203cea60ebfd18e2b966e57750750e0417a9feec to 61fd37a044cad4e9aa4303027b2a61b6a34da855 (#18095)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-05 15:50:36 -04:00
J. Nick Koston 253ecdd145 [core] Resolve the stacktrace decoder lazily behind an address gate (#18048) 2026-08-05 14:34:16 -05:00
Keith Burzinskiandpre-commit-ci-lite[bot] 1cc83172ab [ota] Multi-key OTA signature verification for external RSA signing (#17981)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-08-05 14:24:38 -05:00
Marek PilchandJonathan Swoboda b521b5e1ca [modbus_server] Add tests for U_WORD_S and S_WORD_S (#17832)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-08-05 14:47:48 -04:00
J. Nick Koston 202b31f711 [ble_device_base] Deprecate address_str in favor of address_str_to (#18092) 2026-08-05 18:33:32 +00:00
Marek Pilch fc682dc75b [modbus_server] Support byte-swapped word types U_WORD_S and S_WORD_S (#17829) 2026-08-05 14:11:37 -04:00
4627f07a7b [mcp4461] nonvolatile-by-default persistence, TCON boot sync, wiper actions (#17561)
Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: Oliver Kleinecke <kleinecke.oliver@googlemail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-08-05 14:11:03 -04:00
Edvard Filistovič 9bfce75bc5 [ln882h_ble_tracker] Use the shared ble_device_base automation layer (#18089) 2026-08-05 16:46:01 +00:00
Bonne EgglestonandClaude Fable 5 b93b21eab1 [modbus_controller] Refactor to simplify message handling (#11781)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-05 11:02:56 -05:00
youkorrandClaude e31a43af17 [esp32_camera_web_server] Fix MJPEG stream ending on a stale semaphore (#18052)
Co-authored-by: Claude <noreply@anthropic.com>
2026-08-05 11:40:15 -04:00
Edvard Filistovič 0496627d2b [bk72xx_ble_tracker] Automation triggers and actions (#17776) 2026-08-05 09:31:51 -05:00
d548454dbe [ln882h_ble_tracker] Automation triggers and actions (#17778)
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-08-05 09:30:46 -05:00
Kevin Ahrendt 64f0e38a51 [micro_wake_word] Support adding and removing wake word models at runtime (#17927) 2026-08-05 10:24:46 -04:00
3964ef61f8 [zigbee] Resolution attribute for esp32 sensors (#17973)
Co-authored-by: root <root@core-ssh.local.hass.io>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-08-05 10:23:57 -04:00
luar123andCopilot Autofix powered by AI 2d5d34d33f [zigbee] cleanup, docstrings, refactor connected state on esp32 (1/3) (#18007)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-08-05 10:19:57 -04:00
J. Nick Koston 6bcbdd79c3 [core] Lift the log line processor into esphome/stacktrace.py (#18076) 2026-08-05 08:43:14 -05:00
Pete Keen 3d093c0ae8 [esp32_rmt_led_strip] Add RGBW channel ordering (#18028) 2026-08-05 07:57:59 -04:00
Edvard Filistovič 450232964b [tests] Unignore component-test config fixture directories (#18084) 2026-08-04 21:58:31 -05:00
J. Nick Koston 112d8b26ee [core] Skip source range tracking when loading the validated config cache (#18046) 2026-08-04 21:24:38 -05:00
Clyde Stubbs 27dcf64b45 [lvgl] Add pause option to round_trip animation timing (#17574) 2026-08-05 14:16:22 +12:00
Clyde StubbsandClaude Sonnet 5 97d33a5679 [lvgl] Add lvgl.widget.set_z_index action (#17993)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-05 14:14:32 +12:00
Edvard Filistovič 0a99b007a9 [ble_device_base] Advertise runtime scan-mode switching in HubCapabilities (#18079) 2026-08-05 01:56:32 +00:00
Jesse Hills e2ca80ec41 Bump version to 2026.7.4 2026-08-05 13:19:43 +12:00
Samuel SiebandSamuel Sieb 920ff9c25f [esp32] explicitly disable BLE 5.0 (#18047)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2026-08-05 13:19:42 +12:00
esphome[bot] 56a90d2b25 Bump bundled esphome-device-builder to 1.9.2 (#18051) 2026-08-05 13:19:42 +12:00
esphome[bot] b4166a883e Bump bundled esphome-device-builder to 1.9.1 (#18025) 2026-08-05 13:19:42 +12:00
esphome[bot] b8703a8a1b Bump bundled esphome-device-builder to 1.9.0 (#18017) 2026-08-05 13:19:42 +12:00
esphome[bot] 57bb4e4e77 Bump bundled esphome-device-builder to 1.8.2 (#17995) 2026-08-05 13:19:42 +12:00
J. Nick Koston de93815c6b [api] Fix double free when overflow buffer drain is re-entered (#17969) 2026-08-05 13:19:42 +12:00
Jesse Hills d4372ed008 [esp32] Restrict toolchain validation to supported values (#17972) 2026-08-05 13:19:42 +12:00
Jonathan SwobodaandJ. Nick Koston a199ac41ee [espidf] Use forward slashes in generated component CMakeLists (#17965)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-05 13:19:42 +12:00
J. Nick Koston c0f494450d [git] Fix device adoption failing on first attempt: lock the clone cache against concurrent resolutions (#17923) 2026-08-05 13:19:42 +12:00
Clyde StubbsandClaude Sonnet 5 6b6903e568 [epaper_spi] Default init sequence to empty not None (#17966)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-05 13:19:42 +12:00
esphome[bot] d0f68802b9 Bump bundled esphome-device-builder to 1.8.1 (#17964) 2026-08-05 13:19:42 +12:00
esphome[bot] 7862520450 Bump bundled esphome-device-builder to 1.8.0 (#17953)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-08-05 13:19:42 +12:00
dependabot[bot] cbdddc8020 Bump platformdirs from 4.10.0 to 4.11.0 (#17756)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-05 13:19:41 +12:00
dependabot[bot] 7d1317ad53 Bump filelock from 3.29.0 to 3.32.0 (#17759)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-05 13:19:41 +12:00
J. Nick Koston ad18bbc644 [esp32_ble] Migrate the BLE count machinery to the shared slot counter factory (#18059) 2026-08-05 00:54:07 +00:00
Edvard FilistovičandJ. Nick Koston 1bae91abaa [ln882h_ble_tracker] BLE 5.x scanner for LN882H (#16691)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-08-04 22:45:47 +00:00
J. Nick Koston 1f5df20cb2 [rp2040_ble] Codegen sized StaticVector for scan listeners (#18058) 2026-08-04 21:04:22 +00:00
J. Nick Koston d47acf5d0b [core] Read the mqtt IP discovery flag without importing the mqtt component (#18066) 2026-08-04 15:12:57 -05:00
J. Nick Koston 79a305d69a [core] Drop the duplicate ESPHome version parser (#18065) 2026-08-04 14:48:39 -05:00
J. Nick Koston d344fd74d1 [core] Read the esp32 variant for esptool without importing the esp32 package (#18067) 2026-08-04 19:47:07 +00:00
J. Nick Koston 68640f8074 [core] Shared slot count factory for codegen sized listener storage (#18057) 2026-08-04 19:46:44 +00:00
J. Nick Koston 342f3d6994 [core] Share the stacktrace analyzer resolution in platform_hooks (#18075) 2026-08-04 14:38:28 -05:00
J. Nick Koston a904426431 [core] Unbind the esp-idf toolchain from the esp32 component package (#18068) 2026-08-04 14:38:10 -05:00
Edvard Filistovič b00f32db8a [bthome_mithermometer] Gate log-only MAC helper by log level (#18064) 2026-08-04 18:59:11 +00:00
Edvard Filistovič 914cab301f [rp2_ble_tracker] Extract stamp-and-start helper; pin capability/switch independence (#18072) 2026-08-04 18:20:57 +00:00
Marek Pilch 8bd9f213e5 [modbus] Add unit tests for U_WORD_S and S_WORD_S (#17831) 2026-08-04 12:17:27 -04:00
J. Nick Koston 5abd100b53 [core] Resolve platform CLI hooks from a registry instead of importing the platform package (#18044) 2026-08-04 11:08:56 -05:00
J. Nick Koston adb86a052c [core] Ship secrets referenced by remote package files in config bundles (#18053) 2026-08-04 11:05:52 -05:00
J. Nick Koston c2ddc17063 [libretiny] Give each platform its own CONFIG_SCHEMA instance (#18056) 2026-08-04 11:05:04 -05:00
Edvard Filistovič 37b6578259 [bk72xx_ble_tracker] Brace single-statement loop flagged by clang-tidy (#18070) 2026-08-04 15:57:42 +00:00
Edvard Filistovič c6a37847e6 [ble_device_base] Scan-mode request contract on BLEHub (#18061) 2026-08-04 15:18:31 +00:00
Bonne EgglestonandClaude Opus 4.8 61a4722c93 [modbus_controller] Add bus-fairness integration test (xfail until #11781) (#17345)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 09:15:31 -05:00
Edvard Filistovič dbf7167622 [bk72xx_ble] Codegen-sized StaticVector for scan listeners (#18055) 2026-08-04 04:31:43 +00:00
Jesse Hills 4ceae9cf85 [ci] Replace pre-commit with prek (#18029) 2026-08-04 16:18:46 +12:00
Samuel SiebandSamuel Sieb dafc86d960 [esp32] explicitly disable BLE 5.0 (#18047)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2026-08-03 22:36:52 -05:00
Edvard Filistovič 56b1c59eb2 [ln882h_ble] Scan primitives and main-task scan report queue (#17835) 2026-08-03 21:54:07 -05:00
J. Nick Koston 1b3891866c [core] Parse stored framework versions without importing the validation stack (#18045) 2026-08-03 20:59:38 -05:00
J. Nick Koston 11c3c06b12 [rp2_ble_tracker] Add active scanning support (#18035) 2026-08-03 20:51:17 -05:00
Jonathan Swoboda 735c64d138 [core] Support local library directories via file:// on the native toolchain (#18005) 2026-08-03 21:48:57 -04:00
J. Nick Koston 4f67932e0d [substitutions][core] Expand templated !include paths to on-disk candidates during bundle discovery (#17647) 2026-08-03 20:48:11 -05:00
esphome[bot] 25d5985775 Bump bundled esphome-device-builder to 1.9.2 (#18051) 2026-08-04 01:29:21 +00:00
J. Nick Koston a1c2983394 [core] Hash entity keys from the raw name to fix collisions (#17949) 2026-08-03 20:05:25 -05:00
J. Nick Koston 4424af8c5b [api] Move runtime log client out of the component package (#18043) 2026-08-03 19:57:52 -05:00
J. Nick Koston e8dadf2852 [esp32] Flag crash records captured by a different firmware build (#17770) 2026-08-03 19:56:20 -05:00
J. Nick Koston 2b6bf1f0fe [esp8266] Move wifi rate tables to DRAM to fix beacon parse crash (#17968) 2026-08-03 19:54:43 -05:00
J. Nick Koston 644f279972 [logger] Stub out ROM ets_putc on ESP8266 when serial logging is disabled (#17970) 2026-08-03 19:53:51 -05:00
J. Nick Koston 43deec3063 [espnow] Stop polling the Wi-Fi driver every loop and disable loop when idle (#18027) 2026-08-03 19:53:37 -05:00
J. Nick Koston a50369fc0e [rp2_ble_tracker] BLE tracker for Raspberry Pi Pico W (#18002) 2026-08-03 19:53:07 -05:00
Bonne EgglestonandClaude Opus 4.8 5d89e432da [modbus_controller] Span response path; keep sensor addresses as configured (#17677)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-03 19:15:00 -05:00
0b34c97742 [midea] Add ESP-IDF framework support (#12646)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-08-03 19:21:27 -04:00
dependabot[bot] 66db4fdd61 Bump github/codeql-action/analyze from 4.37.3 to 4.37.4 (#18041)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-03 15:14:07 -05:00
dependabot[bot] 9931647a8c Bump ruff from 0.16.0 to 0.16.1 (#18038)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-03 15:13:51 -05:00
dependabot[bot] 77546b6111 Bump github/codeql-action/init from 4.37.3 to 4.37.4 (#18040)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-03 15:13:39 -05:00
dependabot[bot] 050b4c3c94 Bump cryptography from 48.0.1 to 50.0.0 (#18037)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-03 15:13:26 -05:00
dependabot[bot] 3be32846e4 Bump filelock from 3.32.0 to 3.32.2 (#18039)
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-03 15:13:02 -05:00
J. Nick Koston f8b83cc8a2 [wifi] Notify connect state listeners after driver initiated roams (#18034) 2026-08-03 16:39:14 +00:00
J. Nick Koston 4f058585bb [rp2040_ble] Add controller scan primitives (#18001) 2026-08-03 11:14:34 -05:00
Egor Vorontsovandpre-commit-ci-lite[bot] 4d9c514a1a [i2s_audio] Implemented I2S PDM Microphone DSR selection (#17751)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-08-03 09:22:03 -04:00
Jonathan Swoboda 6b10e8bd15 [esp32_hosted] Bump esp_hosted to 2.12.12, esp_wifi_remote to 1.6.3 (#18030) 2026-08-02 23:58:47 -04:00
Edvard Filistovič 67654fd1e1 [bk72xx_ble_tracker] Fix scan start retry and stale-millis underflow (#17992) 2026-08-03 02:55:20 +00:00
esphome[bot] 2604169080 Bump bundled esphome-device-builder to 1.9.1 (#18025) 2026-08-02 19:46:03 -05:00
J. Nick KostonandCopilot Autofix powered by AI 74fbee7d8d [ble_device_base] Share scan parameter validation between trackers (#18003)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-08-02 19:28:22 -05:00
d6ad1560fa [nrf52] feat: add support for zephyr pwm (#16483)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
Co-authored-by: tomaszduda23 <tomaszduda23@gmail.com>
2026-08-02 21:16:21 +00:00
Bonne Eggleston fcc2c26367 [modbus] Restore function code byte for custom codes in deprecated on_modbus_data (#18006) 2026-08-02 11:40:34 -05:00
esphome[bot] e36d7fe82b Bump bundled esphome-device-builder to 1.9.0 (#18017) 2026-08-01 22:08:57 -05:00
d38a458de9 [modbus] Rework the client queue as a per-frame state machine (#17922)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-08-01 21:34:36 -05:00
Jonathan Swoboda 5821915aad [heatpumpir] Expose configured min/max as the visual temperature range (#17985) 2026-08-01 12:37:44 -04:00
esphome[bot] fae2f7a11d Bump bundled esphome-device-builder to 1.8.2 (#17995) 2026-08-01 08:52:42 -05:00
Keith Burzinski 1df2759db6 [nextion] Reconnect stale HTTP connection during TFT upload (#17824) 2026-07-31 23:05:45 -05:00
Keith Burzinski ce9b221be4 [serial_proxy] Restrict port operations to the subscriber and harden subscription handling (#17796) 2026-07-31 23:05:06 -05:00
Edvard Filistovič e50fae3f46 [ln882h_ble] BLE controller support for LN882H (#17777) 2026-07-31 22:40:57 +00:00
Ardumine 15711f8112 [openthread_info] Add more sensors for Openthread info (#17276) 2026-07-31 12:13:44 -04:00
Jesse Hills 7ad662781d [ci] Order jobs to follow the CI flow and close ci-status gaps (#17979) 2026-07-31 07:53:59 -04:00
2d1530adf7 [zigbee] Add more units (#17982)
Co-authored-by: root <root@core-ssh.local.hass.io>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-07-31 07:16:07 -04:00
Jesse Hills 40b4cd8e9b [ci] Drop the unused Codecov upload token (#17977) 2026-07-31 06:32:33 -04:00
Jesse Hills e11a295680 [ci] Report an empty Codecov upload when pytest is skipped (#17976) 2026-07-31 16:27:05 +12:00
Jesse Hills f9cd789f7c [ci] Tell stacked pull requests apart from hand-built chains (#17980) 2026-07-31 15:39:36 +12:00
Jesse Hills 80c17fb2cd [ci] Authenticate the stale workflow as esphome[bot] (#17974) 2026-07-31 13:52:01 +12:00
J. Nick Koston fb21320826 [api] Fix double free when overflow buffer drain is re-entered (#17969) 2026-07-30 14:48:17 -10:00
Jesse Hills 3899429cfa [esp32] Restrict toolchain validation to supported values (#17972) 2026-07-30 20:34:44 -04:00
Jonathan SwobodaandJ. Nick Koston 44f08d15db [espidf] Use forward slashes in generated component CMakeLists (#17965)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-07-30 20:34:04 -04:00
J. Nick Koston 963a3379a6 [core] Log when a git source update is skipped and when it will next refresh (#17943) 2026-07-30 13:06:32 -10:00
J. Nick Koston 4951f4fc2e [git] Fix device adoption failing on first attempt: lock the clone cache against concurrent resolutions (#17923) 2026-07-30 11:44:12 -10:00
Clyde StubbsandClaude Sonnet 5 a87ad66746 [epaper_spi] Default init sequence to empty not None (#17966)
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 16:25:17 -04:00
Jonathan Swoboda 60662830dc [ci] Switch stale to the shared real-activity workflow (#17960) 2026-07-30 15:41:10 -04:00
esphome[bot] 33ccaf8a85 Bump bundled esphome-device-builder to 1.8.1 (#17964) 2026-07-30 08:54:39 -10:00
Pieter Viljoen d64e1ebba3 [ble_client] Do not walk the GATT cache after releasing services (#17919) 2026-07-30 08:31:32 -10:00
esphome[bot] 6733e930eb Bump bundled esphome-device-builder to 1.8.0 (#17953)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-07-30 08:01:17 -04:00
Jesse Hills c23a107a87 [config_validation] Add underscore/hyphen normalization to one_of (#17792) 2026-07-30 18:36:28 +12:00
Kevin Ahrendt 4224d90567 [runtime_image] Allow decoding into a caller-owned buffer (#17936) 2026-07-29 23:32:21 -04:00
Jonathan Swoboda fb1b1db87f [esp32][mdns][runtime_image] Bump recommended Arduino to 3.3.11 and platform to 55.03.311 (#17875) 2026-07-29 18:04:36 -04:00
Jonathan Swoboda be78b8011d [esp32] Add platformio toolchain deprecation warning (#17947) 2026-07-29 17:17:39 -04:00
dependabot[bot] a99d03e172 Bump docker/login-action from 4.5.2 to 4.6.0 in the docker-actions group (#17944)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-29 15:49:19 -04:00
matt123pandKevin Ahrendt c7d16dde15 [voice_assistant] Fix playback when CPU is loaded (#17043)
Co-authored-by: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org>
2026-07-29 19:48:43 +00:00
dependabot[bot] be7748ccb6 Bump CodSpeedHQ/action from 4.19.1 to 5.0.1 (#17946)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-29 15:35:07 -04:00
dependabot[bot] 41902d7538 Bump pypa/gh-action-pypi-publish from 1.14.1 to 1.14.2 (#17945)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-29 15:30:49 -04:00
J. Nick Koston ca1f89e500 [ci] Enable the ruff rule requiring explicit encoding on text file I/O (#17897) 2026-07-29 13:44:39 -04:00
Kevin Ahrendt 306d200b02 [api] Stop advertising external wake words the device cannot load (#17926) 2026-07-29 13:27:06 -04:00
98ee7e0f82 [lvgl] Add lvgl.theme.update action (#17678)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-29 13:08:52 -04:00
ad3e2f83b8 [sgp4x] Fix datasheet conformance issues (#17828)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-29 12:57:54 -04:00
Jeroenandjeroen85 33dacb06ff [opentherm] Restore idle output when stopped (#17834)
Co-authored-by: jeroen85 <26403565+jeroen85@users.noreply.github.com>
2026-07-29 12:57:03 -04:00
Fran Fodor 363a91c185 [epaper_spi] Add Inkplate 6COLOR support (#17717) 2026-07-30 00:31:22 +10:00
Clyde Stubbs 4209f242e5 [mipi_spi] Add Waveshare ESP32-S3-Touch-LCD-3.5B (#17513) 2026-07-28 23:18:49 -04:00
Brandon HarveyandClyde Stubbs 9af0302bb9 [core] Expand AGENTS.md AI contributor guidance (#17741)
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
2026-07-28 22:47:43 -04:00
Brandon Harvey 4c571c3ec7 [sen6x] Rename voc/nox sensor keys to voc_index/nox_index (#17725) 2026-07-28 22:35:53 -04:00
Brandon Harvey a9df82fa0a [sen5x] Rename voc/nox sensor keys to voc_index/nox_index (#17724) 2026-07-28 22:35:34 -04:00
Brandon Harvey 6ad804fbc5 [sgp4x] Rename voc/nox sensor keys to voc_index/nox_index (#17723) 2026-07-28 22:35:07 -04:00
Brandon Harvey 227f1d3842 [core] Reject configs that set both keys in cv.rename_key (#17916) 2026-07-28 22:32:59 -04:00
dependabot[bot] 72f904dcfb Bump docker/login-action from 4.5.1 to 4.5.2 in the docker-actions group (#17912)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-28 15:41:50 -04:00
J. Nick Koston 324e222bd2 [improv_serial] Reduce per-loop overhead (#16019) 2026-07-28 15:38:29 -04:00
dependabot[bot] 7b1d70c2c0 Bump actions/stale from 10.4.0 to 11.0.0 (#17913)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-28 15:28:01 -04:00
Kobi Hikri b80fa4ae19 [ci] Bind the branch name to env before sanitising it into a docker tag (#17910) 2026-07-28 12:17:50 -04:00
Edvard Filistovič a4611907a9 [captive_portal] Re-apply json_escape move lost in release merge (#17906) 2026-07-28 08:23:01 -04:00
Jesse Hills 17bd1b2a42 Merge branch 'release' into dev 2026-07-28 22:44:03 +12:00
Jesse Hills 985a08e247 Merge pull request #17905 from esphome/bump-2026.7.3
2026.7.3
2026-07-28 22:43:16 +12:00
Edvard Filistovič 95786459c1 [ble_device_base] Replace raw-advertisement std::function with a lightweight callback slot (#17902) 2026-07-28 09:54:58 +00:00
Jesse Hills 4f3db4c15a Bump version to 2026.7.3 2026-07-28 21:32:52 +12:00
esphome[bot]andJesse Hills 56512abb7e Update webserver local assets to 20260728-053845 (#17899)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-07-28 21:32:51 +12:00
Clyde Stubbs 71349a6feb [light] Ensure binary light is off with brightness 0 (#17893) 2026-07-28 21:32:51 +12:00
Jonathan Swoboda 489e3d17ca [ethernet] Set SPI CS hold time for ENC28J60 (#17885) 2026-07-28 21:32:51 +12:00
Jesse Hills d93772fed6 [captive_portal] Escape SSID when building config JSON (#17872) 2026-07-28 21:32:51 +12:00
J. Nick Koston 50f02aa523 [git] Fix submodule update failure when cloning libraries on the esp-idf toolchain (#17862) 2026-07-28 21:32:51 +12:00
J. Nick Koston 5a87ad8fc0 [wifi] Lock scan results shared with the captive portal web task (#17850) 2026-07-28 21:32:51 +12:00
esphome[bot] e40579ad93 Bump bundled esphome-device-builder to 1.7.0 (#17871) 2026-07-28 21:32:51 +12:00
Rui Marinho 37fe59dc37 [espidf] Include .cc, .cxx and .c++ sources in the app source glob (#17754) 2026-07-28 21:32:51 +12:00
Jonathan Swoboda 3829d368ff [espidf] Honor compile_process_limit in native ESP-IDF builds (#17857) 2026-07-28 21:32:42 +12:00
Marcus Voß 013c5d7217 [esp32_ble] Forward ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT to GAP handlers (#17833) 2026-07-28 21:29:28 +12:00
esphome[bot] e38ae51de2 Bump bundled esphome-device-builder to 1.6.10 (#17801) 2026-07-28 21:29:28 +12:00
esphome[bot]andJesse Hills 333ad42e29 Update webserver local assets to 20260728-053845 (#17899)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-07-28 21:28:23 +12:00
Edvard Filistovič bb8ffac269 [const] Move CONF_SCAN_PARAMETERS and CONF_WINDOW to components/const (#17900) 2026-07-27 21:19:17 -10:00
Edvard Filistovič 10303b3fa7 [ble_device_base] Add mac_lsb_first_to_uint64 address-packing helper (#17901) 2026-07-27 21:17:40 -10:00
Jesse Hills 93eec5c961 [ci] Attribute device class sync commits to the esphome[bot] account (#17898) 2026-07-28 16:19:00 +12:00
J. Nick Koston 16930c4e2c [ci] Read the GitHub event file as UTF-8 (#17896) 2026-07-27 17:33:08 -10:00
Edvard Filistovič c2476911a3 [bluetooth_proxy] Answer UNPAIR with BluetoothDeviceUnpairingResponse (#17895) 2026-07-27 17:14:37 -10:00
Clyde Stubbs 98d99fb9fd [light] Ensure binary light is off with brightness 0 (#17893) 2026-07-28 14:19:44 +12:00
Jesse Hills ce6c122449 [core] Move JSON string escaping into helpers (#17879) 2026-07-27 22:16:57 -04:00
Brandon Harvey f1f8b102e2 [core] Add optional deprecation warning to cv.rename_key (#17740) 2026-07-27 22:10:34 -04:00
Egor Vorontsov e1ab5a85bb [i2s_audio] Eliminated a double unit conversion in read_() (#17752) 2026-07-27 20:28:40 -04:00
0959141f88 [nrf52] Clone the sdk-nrf manifest repository shallow (#17892)
Co-authored-by: esphbot <esphome@openhomefoundation.org>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-07-27 19:58:50 -04:00
Edvard Filistovič 01616c4f30 [bk72xx_ble_tracker] BLE 5.x scanner for BK72xx (#17135) 2026-07-27 11:58:29 -10:00
J. Nick Kostonandcopilot-swe-agent[bot] 7c89e81449 [ci] Persist the integration test ccache across runs (#17735)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-07-27 11:26:49 -10:00
Jonathan Swoboda 6420de53f0 [ethernet] Set SPI CS hold time for ENC28J60 (#17885) 2026-07-27 17:24:53 -04:00
J. Nick Kostonandcopilot-swe-agent[bot] fa8c7e60da [host] Speed up builds with ccache when available (#17728)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-07-27 20:47:12 +00:00
Bonne EgglestonandClaude Fable 5 5eeb780538 [modbus] Fold the repeated PDU validation idioms into shared helpers (#17888)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 10:44:15 -10:00
Bonne EgglestonandClaude Fable 5 19511f5787 [modbus] Command lifecycle: PDU-carrying callbacks, on_sent(), notified queue clearing (#17886)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 10:35:51 -10:00
Jesse Hills 56028d0932 [safe_mode] Prevent OTA rollback when entering deep sleep (#17699) 2026-07-27 16:30:52 -04:00
tomaszduda23andJonathan Swoboda ca08803425 [nrf52] add OTA for Adafruit_nRF52_Bootloader (#17381)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-07-27 16:03:22 -04:00
Samuel SiebandSamuel Sieb e209bbb5ae [logger] flush lines for host logger (#17878)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2026-07-27 15:48:29 -04:00
dependabot[bot] 580b3a1a69 Bump CodSpeedHQ/action from 4.18.5 to 4.19.1 (#17890)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-27 15:35:53 -04:00
J. Nick Koston c395ea00cc [libretiny] Speed up builds with ccache when available (#17726) 2026-07-27 18:54:32 +00:00
J. Nick Koston 89654fea66 [rp2] Speed up builds with ccache when available (#17727) 2026-07-27 18:52:29 +00:00
J. Nick Koston 700c0b0460 [esp8266] Speed up builds with ccache when available (#17722) 2026-07-27 08:42:52 -10:00
J. Nick Koston c0aa121c3d [espidf] Install only the toolchains for the variants being built (#17688) 2026-07-27 08:39:03 -10:00
dependabot[bot]andJonathan Swoboda 345bd11a2c Bump ruff from 0.15.22 to 0.16.0 (#17818)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-07-27 12:08:51 -04:00
dependabot[bot] 071ef5016d Bump actions/setup-python from 6.3.0 to 7.0.0 in /.github/actions/restore-python (#17732)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-27 11:47:45 -04:00
dependabot[bot] fdc2974c0d Bump docker/login-action from 4.4.0 to 4.5.1 in the docker-actions group across 1 directory (#17817)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-27 11:47:31 -04:00
Samuel SiebandSamuel Sieb 899ed02ef2 [remote_base] support haier short IR message (#17826)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2026-07-27 09:52:15 -04:00
Jesse Hills a930baab7c [captive_portal] Escape SSID when building config JSON (#17872) 2026-07-27 19:42:44 +12:00
J. Nick Koston 43526a815e [git] Fix submodule update failure when cloning libraries on the esp-idf toolchain (#17862) 2026-07-27 19:42:21 +12:00
J. Nick Koston 8f321bf346 [wifi] Lock scan results shared with the captive portal web task (#17850) 2026-07-27 17:31:24 +12:00
Daniele PalumboandJesse Hills 91cbcab25e [web_server] Add assumed_state to cover JSON detail (#16800)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-07-27 14:01:45 +12:00
Bonne EgglestonandClaude Fable 5 67e0058e72 [modbus] Typed client send helpers and response callbacks (#17435)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 13:14:54 -10:00
esphome[bot] b395a87cad Bump bundled esphome-device-builder to 1.7.0 (#17871) 2026-07-26 13:13:55 -10:00
Jonathan Swoboda 8a7d2d0ca0 [ci] Enforce list form for platform domains in test fixtures (#17869) 2026-07-26 19:01:15 -04:00
Rui Marinho ed066cf0fe [espidf] Include .cc, .cxx and .c++ sources in the app source glob (#17754) 2026-07-27 10:34:29 +12:00
Jonathan Swoboda 741fbbff5a [dallas_temp][ds2484] Fix one_wire test configs for grouped CI batches (#17868) 2026-07-26 17:49:57 -04:00
Edvard Filistovič cf17749307 [ble_device_base] Shared address-type string and discovered-device log (#17861) 2026-07-26 00:49:29 -10:00
Bonne Eggleston 98f2a0b4a4 [modbus] Typed send helpers; migrate in-tree callers off send() (#17859) 2026-07-25 21:57:35 -10:00
J. Nick Kostonandcopilot-swe-agent[bot] 9dd7dcb06d [espidf] Also skip installing gdb and ULP toolchains ESPHome never runs (#17687)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-07-25 20:07:14 -10:00
Thomas RupprechtandClaude Opus 4.8 559614077d [ezo_pmp] Fix ml/min and ml unit capitalization (#17803)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-26 00:22:49 -04:00
Thomas RupprechtandClaude Opus 4.8 b5e18eb101 [opentherm] Fix l/min unit capitalization to L/min (#17804)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-26 00:16:07 -04:00
J. Nick Koston e0644ab20a [esp32] Capture fault address and raw cause in crash handler (#17769) 2026-07-25 18:12:53 -10:00
dependabot[bot] 98e9dd7954 Bump github/codeql-action/init from 4.37.2 to 4.37.3 (#17785)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-26 00:09:46 -04:00
dependabot[bot] fbb1a76e2a Bump github/codeql-action/analyze from 4.37.2 to 4.37.3 (#17786)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-26 00:09:37 -04:00
Jonathan Swoboda 7fbb647c65 [espidf] Honor compile_process_limit in native ESP-IDF builds (#17857) 2026-07-25 23:59:33 -04:00
a2c749c277 [modbus] PackedBits and right-sized typed PDU builders (#17848)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-07-25 11:18:46 -10:00
Bonne EgglestonandClaude Fable 5 0833e91fb5 [modbus] Turn the ModbusDevice alias into a working compatibility shim (#17854)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 09:39:07 -10:00
Bonne EgglestonandClaude Fable 5 eaa79b3696 [modbus] Frame accessors, PDU-relative lengths, and span-based send_pdu (#17846)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 03:09:05 +00:00
Ryan Gammon 58385bebff [mipi_spi] Add ST77916 / ESP-VoCat model (#17679) 2026-07-25 02:57:17 +00:00
Michael Pöttgen eb7575f59e [gsl3670] Add a model configuration for the Guition JC8012P4A1 (#17843) 2026-07-25 11:33:17 +10:00
Bonne EgglestonandClaude Fable 5 6648ccc278 [modbus_controller] Qualify modbus::EntityType at use sites (#17845)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 14:01:53 -10:00
Bonne EgglestonandClaude Fable 5 9ac4039c01 [modbus] Rename core enums to EntityType, FunctionCode and ExceptionCode (#17844)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 13:28:22 -10:00
5e2d428e69 [modbus] Heap-free response path (#17377)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-07-24 11:45:59 -10:00
Edvard FilistovičandJ. Nick Koston d12300679e [bk72xx_ble] Scan primitives and main-task scan report queue (#17802)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-07-24 00:26:33 -10:00
Marcus Voß e224a781ff [esp32_ble] Forward ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT to GAP handlers (#17833) 2026-07-23 23:47:27 -10:00
Johan HenkensandClaude Sonnet 4.6 a210c27d14 [api][climate][water_heater][core] Add temperature unit support to climate and water heater c++ entities (#16477)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-23 13:58:39 -10:00
esphome[bot] f0800336b8 Bump bundled esphome-device-builder to 1.6.10 (#17801) 2026-07-23 00:02:31 -10:00
Edvard Filistovič 33fa9f5069 [bk72xx_ble] BLE controller support for BK72xx (BLE 5.x) (#17775) 2026-07-23 08:54:30 +00:00
427a504308 [sgp4x] Fix sgp4x VOC baseline restoration (#15667)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-07-23 02:49:38 -05:00
Jesse Hills dd2fbdd43a [github] Add developer-facing feature PR classification (#17795) 2026-07-23 14:48:25 +12:00
Jesse Hills d7d1e5c2f6 Merge branch 'release' into dev 2026-07-23 14:42:36 +12:00
Jesse Hills b832e135cb Merge pull request #17794 from esphome/bump-2026.7.2
2026.7.2
2026-07-23 14:41:52 +12:00
Jesse Hills 66615a24a7 Bump version to 2026.7.2 2026-07-23 13:55:39 +12:00
esphome[bot] 52ace9c448 Bump bundled esphome-device-builder to 1.6.9 (#17793) 2026-07-23 13:55:39 +12:00
J. Nick Koston e1cedaba87 [bundle] Remap absolute file paths when compiling an extracted bundle (#17765) 2026-07-23 13:55:38 +12:00
Flautzandclyde f7bf4e9727 [mipi_spi] fix partial update bug (#17747)
Co-authored-by: clyde <2366188+clydebarrow@users.noreply.github.com>
2026-07-23 13:55:38 +12:00
Kevin Ahrendt e46bdf9e18 [sendspin] Bump sendspin-cpp to v0.7.0 (#17781) 2026-07-23 13:55:38 +12:00
Brandon Harvey a08070a836 [sen5x] Add model option to override autodetection (#17764) 2026-07-23 13:55:38 +12:00
dependabot[bot] 18f93c0e41 Bump aioesphomeapi from 45.6.2 to 45.7.0 (#17768)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-23 13:55:38 +12:00
deba7a1f0c [ethernet][network][wifi] Add network priority for multi-interface support (#14255)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: kbx81 <kbx81x@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-07-22 20:55:04 -05:00
esphome[bot] 4817904637 Bump bundled esphome-device-builder to 1.6.9 (#17793) 2026-07-22 15:49:38 -10:00
J. Nick Koston 98c6fa294a [bundle] Remap absolute file paths when compiling an extracted bundle (#17765) 2026-07-23 11:28:22 +12:00
Flautzandclyde 312b0c53c2 [mipi_spi] fix partial update bug (#17747)
Co-authored-by: clyde <2366188+clydebarrow@users.noreply.github.com>
2026-07-22 20:50:11 +00:00
Kevin Ahrendt 5dfce9b90c [sendspin] Bump sendspin-cpp to v0.7.0 (#17781) 2026-07-22 08:41:33 -10:00
Brandon Harvey 69085a7a42 [sen5x] Add model option to override autodetection (#17764) 2026-07-21 13:18:21 -10:00
dependabot[bot] 2edb089f71 Bump pypa/gh-action-pypi-publish from 1.14.0 to 1.14.1 (#17734)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 13:09:45 -10:00
dependabot[bot] 078b1aa1d6 Bump aioesphomeapi from 45.6.2 to 45.7.0 (#17768)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 23:02:30 +00:00
dependabot[bot] 1f8fea5379 Bump actions/checkout from 7.0.0 to 7.0.1 (#17733)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 12:58:29 -10:00
dependabot[bot] 9c211abc54 Bump github/codeql-action/analyze from 4.37.1 to 4.37.2 (#17761)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 12:37:31 -10:00
dependabot[bot] 4afb619672 Bump actions/setup-python from 6.3.0 to 7.0.0 (#17731)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 12:32:31 -10:00
Edvard Filistovič 4d3b4659d7 [ble_device_base] Platform-neutral BLE layer; esp32_ble_tracker implements BLEHub (#17150) 2026-07-21 12:32:14 -10:00
J. Nick Koston 37be04f58e [core] Reduce memory footprint of esphome upload (#17684) 2026-07-21 12:21:12 -10:00
dependabot[bot] 1e4bf48ea3 Bump github/codeql-action/init from 4.37.1 to 4.37.2 (#17758)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 11:45:39 -10:00
dependabot[bot] 52c6a50b6d Bump astral-sh/setup-uv from 8.3.2 to 9.0.0 (#17760)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 11:45:27 -10:00
dependabot[bot] 008c85c7d5 Bump astral-sh/setup-uv from 8.3.2 to 9.0.0 in /.github/actions/restore-python (#17757)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 11:34:03 -10:00
dependabot[bot] e84880e4ec Bump platformdirs from 4.10.0 to 4.11.0 (#17756)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 11:33:49 -10:00
dependabot[bot] a30f9f7c65 Bump filelock from 3.29.0 to 3.32.0 (#17759)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 10:39:43 -10:00
Jesse Hills e931919fb4 Merge branch 'release' into dev 2026-07-21 10:45:17 +12:00
Jesse Hills bbc5669efa Merge pull request #17739 from esphome/bump-2026.7.1
2026.7.1
2026-07-21 10:44:34 +12:00
Guanzhong Chen 718b04c15a [zephyr] implement ISRInternalGPIOPin::digital_write (#17601) 2026-07-21 09:27:55 +12:00
Jonathan Swoboda 24a8634a4b [haier] Fix outdoor defrost temperature reporting the coil temperature (#17492) 2026-07-21 09:27:55 +12:00
Jonathan Swoboda fc6664d737 [emc2101] Fix negative external temperatures reported as large positives (#17494) 2026-07-21 09:27:55 +12:00
dependabot[bot] 388e411469 Bump aioesphomeapi from 45.6.1 to 45.6.2 (#17654)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 09:17:18 +12:00
Jesse Hills a8ebdcb8f2 Bump version to 2026.7.1 2026-07-21 08:25:51 +12:00
J. Nick Koston f5f1c48f51 [esp8266] Fail fast when Rosetta 2 is missing on Apple Silicon Macs (#17737) 2026-07-21 08:25:51 +12:00
J. Nick Koston 7c55de311f [wireguard] Mark private keys sensitive, stop redacting public keys (#17736) 2026-07-21 08:25:46 +12:00
J. Nick Koston 307faa6c38 [espidf] Resume interrupted toolchain downloads instead of restarting (#17706) 2026-07-21 08:18:16 +12:00
J. Nick Koston 5f2adcf9b3 [platformio] Include cache path in invalid library error (#17692) 2026-07-21 08:18:16 +12:00
Grégoire SeuxandJ. Nick Koston 7738464f0b [http_request] Fix usage of http response body (#17713)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-07-21 08:18:16 +12:00
J. Nick KostonandJesse Hills 5a86e26f68 [platformio] Re-download library when cached copy is missing its manifest (#17691)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-07-21 08:18:16 +12:00
J. Nick Kostonandpre-commit-ci-lite[bot] 786b47d8c2 [core] Auto-clean the PlatformIO build environment when the Python version changes (#17671)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-07-21 08:18:15 +12:00
esphome[bot] 83092ea05c Bump bundled esphome-device-builder to 1.6.8 (#17708) 2026-07-21 08:18:15 +12:00
629afd38f6 [light] Fix pulse and other effects (#17645)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-07-21 08:18:15 +12:00
J. Nick Koston 3ffc3a9610 [espidf] Make openocd-esp32 optional so its libusb check cannot break installs (#17686) 2026-07-21 08:18:15 +12:00
J. Nick Koston 9de7bd7461 [git] Detect interrupted clones and re-clone automatically (#17690) 2026-07-21 08:18:15 +12:00
J. Nick Koston 5df922e0df [platformio] Accept git URLs passed as the library name (#17697) 2026-07-21 08:18:15 +12:00
J. Nick Koston b571d2a5ab [micro_wake_word] Download models in parallel (#17701) 2026-07-21 08:18:15 +12:00
Jesse Hills 231a2897c0 [ssd1306] Fix offset_x being ignored on SH1106/SH1107 displays (#17700) 2026-07-21 08:18:15 +12:00
Brandon Harvey 2223b14794 Split multi-token build.flags entries when generating ESP-IDF component CMakeLists (#17649) 2026-07-21 08:18:15 +12:00
esphome[bot] 3d340f4d90 Bump bundled esphome-device-builder to 1.6.7 (#17696) 2026-07-21 08:18:15 +12:00
esphome[bot] 2f99466f3a Bump bundled esphome-device-builder to 1.6.6 (#17681) 2026-07-21 08:18:15 +12:00
esphome[bot] f05e15522c Bump bundled esphome-device-builder to 1.6.5 (#17675) 2026-07-21 08:18:15 +12:00
Jonathan Swoboda f37dad683b [esp32] Bump recommended ESP-IDF to 5.5.5 and Arduino to 3.3.10 (#17669) 2026-07-21 08:18:15 +12:00
esphome[bot] a0fb14bf54 Bump bundled esphome-device-builder to 1.6.4 (#17662) 2026-07-21 08:18:15 +12:00
Jesse Hills d4443be0c1 [nrf52] Install PlatformIO toolchain Python packages into a dedicated venv (#17635) 2026-07-21 08:18:15 +12:00
J. Nick Koston 0dfb573e18 [logs] Cap the logs reconnect backoff for deep-sleep devices (#17656) 2026-07-21 08:18:15 +12:00
J. Nick Koston 572fc033cd Ship component requirements.txt files in the sdist and wheel (#17660) 2026-07-21 08:18:15 +12:00
J. Nick Koston 4062f0a323 Pin cryptography to 48.0.1 on Intel macOS (#17658) 2026-07-21 08:18:15 +12:00
Brandon Harvey cd40fb1c68 [core] Fix srcFilter exclusions being silently ignored on Windows (#17648) 2026-07-21 08:18:15 +12:00
Jonathan Swoboda 7afe7750cd [espidf] Suggest installing missing system libraries when the tools install fails (#17619) 2026-07-21 08:18:15 +12:00
esphome[bot] e08bdf8cca Bump bundled esphome-device-builder to 1.6.3 (#17651) 2026-07-21 08:18:15 +12:00
dependabot[bot] b3172ecae8 Bump aioesphomeapi from 45.6.0 to 45.6.1 (#17653)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-21 08:18:14 +12:00
esphome[bot] 2b4d9c0af9 Bump bundled esphome-device-builder to 1.6.2 (#17640)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-07-21 08:18:14 +12:00
Jesse Hills 3a10d2c187 [nrf52] Set ZEPHYR_SDK_INSTALL_DIR for Zephyr SDK discovery (#17633) 2026-07-21 08:18:14 +12:00
Jonathan Swoboda 05e2c6b133 [web_server_idf] Use core format_hex_to helper for digest auth (fixes Arduino build) (#17608) 2026-07-21 08:18:14 +12:00
Jonathan Swoboda 2797349c75 [http_request] Fix use-after-return of header collection state in IDF backend (#17627) 2026-07-21 08:18:14 +12:00
Jonathan Swoboda 95a01ac2ab [core] Improve framework mirror selection, download errors, and version parsing (#17615) 2026-07-21 08:18:14 +12:00
J. Nick Koston ea01c909b7 [micro_wake_word] Include the local model file in bundles (#17604) 2026-07-21 08:18:14 +12:00
Jonathan Swoboda d3655597ea [as3935_i2c] Use repeated start when reading registers (#17584) 2026-07-21 08:18:14 +12:00
J. Nick Koston cd8d76fa34 [esp8266] Fail fast when Rosetta 2 is missing on Apple Silicon Macs (#17737) 2026-07-21 08:17:01 +12:00
J. Nick Koston 500d4aa9e9 [wireguard] Mark private keys sensitive, stop redacting public keys (#17736) 2026-07-20 20:13:56 +00:00
J. Nick Koston 271c1b409a [espidf] Resume interrupted toolchain downloads instead of restarting (#17706) 2026-07-21 08:12:17 +12:00
J. Nick Koston 9a0e8606cd [platformio] Include cache path in invalid library error (#17692) 2026-07-21 08:08:46 +12:00
tomaszduda23 d5681ac6a0 [nrf52] add platformio deprecation warning (#17705) 2026-07-20 20:29:00 +02:00
057143838d [network] Fix IPAddress IPv6 support on HOST platform (#17067)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-07-20 18:18:37 +00:00
Grégoire SeuxandJ. Nick Koston 4268d91da3 [http_request] Fix usage of http response body (#17713)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-07-20 17:07:28 +00:00
JeroenandJeroen Jansen 6f39030b41 [core] Prevent blocking-warning log time from cascading (#17710)
Co-authored-by: Jeroen Jansen <jeroen@Jeroens-MacBook-Air.local>
2026-07-20 06:28:56 -10:00
J. Nick KostonandJesse Hills 3e1a9e8a3a [platformio] Re-download library when cached copy is missing its manifest (#17691)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-07-19 19:34:56 -10:00
J. Nick Kostonandpre-commit-ci-lite[bot] bb1318dce1 [core] Auto-clean the PlatformIO build environment when the Python version changes (#17671)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-07-19 19:32:38 -10:00
esphome[bot] 26fcc068b6 Bump bundled esphome-device-builder to 1.6.8 (#17708) 2026-07-19 19:32:22 -10:00
2a96fa44ff [light] Fix pulse and other effects (#17645)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-07-20 17:09:02 +12:00
J. Nick Koston 5fa93513f2 [espidf] Make openocd-esp32 optional so its libusb check cannot break installs (#17686) 2026-07-20 17:05:50 +12:00
J. Nick Koston 4a1f54ce4b [git] Detect interrupted clones and re-clone automatically (#17690) 2026-07-20 16:34:29 +12:00
J. Nick Koston 76655cf951 [platformio] Accept git URLs passed as the library name (#17697) 2026-07-20 16:32:20 +12:00
J. Nick Koston dfb988c563 [micro_wake_word] Download models in parallel (#17701) 2026-07-20 16:16:15 +12:00
Jesse Hills 0443b4849b [ssd1306] Fix offset_x being ignored on SH1106/SH1107 displays (#17700) 2026-07-20 15:51:46 +12:00
Brandon Harvey 977376d55c Split multi-token build.flags entries when generating ESP-IDF component CMakeLists (#17649) 2026-07-19 12:20:43 -10:00
esphome[bot] 1f93345af8 Bump bundled esphome-device-builder to 1.6.7 (#17696) 2026-07-19 09:17:53 -10:00
esphome[bot] 96dd2382c1 Bump bundled esphome-device-builder to 1.6.6 (#17681) 2026-07-18 21:25:56 -10:00
esphome[bot] 3064fb0d48 Bump bundled esphome-device-builder to 1.6.5 (#17675) 2026-07-18 11:46:14 -10:00
Jonathan Swoboda 4c9dab9c98 [esp32] Bump recommended ESP-IDF to 5.5.5 and Arduino to 3.3.10 (#17669) 2026-07-18 11:14:42 -10:00
tomaszduda23 0b0e706349 [nrf52] add platform: ultrasonic test (#17665) 2026-07-18 08:05:19 -04:00
tomaszduda23 017040ec8e [zigbee] add radio power off stats (#17521) 2026-07-18 09:09:52 +02:00
Tom 52fe461e9c [ds248x] Add OneWireBus platform for DS248x I2C-to-1Wire bridges (#12717) 2026-07-17 22:01:15 -07:00
esphome[bot] a7dad14449 Bump bundled esphome-device-builder to 1.6.4 (#17662) 2026-07-17 17:44:52 -10:00
Jesse Hills 1493a09521 [nrf52] Install PlatformIO toolchain Python packages into a dedicated venv (#17635) 2026-07-17 23:22:23 -04:00
J. Nick Koston 2a59c0ad9e [logs] Cap the logs reconnect backoff for deep-sleep devices (#17656) 2026-07-17 17:16:14 -10:00
Jonathan Swoboda 70421fb14b [espidf] Prune tool download cache after install to shrink the ESP-IDF cache (#17661) 2026-07-17 22:49:50 -04:00
J. Nick Koston bacc223360 Ship component requirements.txt files in the sdist and wheel (#17660) 2026-07-17 15:59:12 -10:00
J. Nick Koston 94be1da893 Pin cryptography to 48.0.1 on Intel macOS (#17658) 2026-07-17 15:46:16 -10:00
Brandon Harvey cb66dc01ab [core] Fix srcFilter exclusions being silently ignored on Windows (#17648) 2026-07-17 21:45:13 -04:00
Jonathan Swoboda ebaf32c82a [ci] Add LibreTiny clang-tidy environments (#17491) 2026-07-17 21:38:55 -04:00
Jonathan Swoboda f918c299b1 [espidf] Suggest installing missing system libraries when the tools install fails (#17619) 2026-07-17 19:46:45 -04:00
dependabot[bot] 328a2018d2 Bump aioesphomeapi from 45.6.1 to 45.6.2 (#17654)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-17 13:32:47 -10:00
dependabot[bot] a4a9feac16 Bump esphome/workflows/.github/workflows/lock.yml from 2026.4.1 to 2026.7.0 (#17652)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-17 12:26:04 -10:00
esphome[bot] 6f27c7f3fe Bump bundled esphome-device-builder to 1.6.3 (#17651) 2026-07-17 12:25:18 -10:00
dependabot[bot] 300ab1be35 Bump aioesphomeapi from 45.6.0 to 45.6.1 (#17653)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-17 12:00:54 -10:00
esphome[bot] 7aed5fb94b Bump bundled esphome-device-builder to 1.6.2 (#17640)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-07-17 08:08:28 -04:00
Keith Burzinski 2132cae1c9 [nextion] Fix RP2040 clang-tidy failure from TFT upload guard mismatch (#17638) 2026-07-17 08:07:38 -04:00
Jesse Hills 735f8d607d [nrf52] Set ZEPHYR_SDK_INSTALL_DIR for Zephyr SDK discovery (#17633) 2026-07-18 00:04:35 +12:00
Jonathan Swoboda cc6392785f [runtime_image] Prevent integer overflow in image buffer size calculation (#17624) 2026-07-16 18:36:18 -04:00
Jonathan Swoboda 7a2d13da90 [web_server_idf] Use core format_hex_to helper for digest auth (fixes Arduino build) (#17608) 2026-07-16 15:59:53 -04:00
dependabot[bot] e2df9fb554 Bump ruff from 0.15.21 to 0.15.22 (#17628)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-16 15:43:43 -04:00
Jonathan Swoboda 4507d05822 [http_request] Fix use-after-return of header collection state in IDF backend (#17627) 2026-07-16 15:34:49 -04:00
dependabot[bot] 3caae3031a Bump github/codeql-action/init from 4.37.0 to 4.37.1 (#17629)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-16 15:33:38 -04:00
dependabot[bot] a624659856 Bump github/codeql-action/analyze from 4.37.0 to 4.37.1 (#17630)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-16 15:33:30 -04:00
Jonathan Swoboda 6c8d0050ab [esp32_ble_server] Validate descriptor write length before copying (#17626) 2026-07-16 15:32:44 -04:00
Jonathan Swoboda 09da2766ed [bluetooth_proxy] Bound GATT characteristic/descriptor enumeration to allocated size (#17625) 2026-07-16 15:32:09 -04:00
Jonathan SwobodaandCopilot Autofix powered by AI 72bd45538e [opentherm] Rename OpenthermData accessors that collide with vendor SDK type macros (#17611)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-16 15:25:45 -04:00
Jonathan Swoboda 5b37049dff [midea] Restrict to platforms where MideaUART actually builds (#17613) 2026-07-16 15:23:46 -04:00
Jonathan Swoboda c0e78a5574 [core] Improve framework mirror selection, download errors, and version parsing (#17615) 2026-07-16 15:22:19 -04:00
Jonathan Swoboda f53394e46f [mlx90393] Compile out on BK72xx where the bundled library cannot build (#17614) 2026-07-16 15:14:18 -04:00
J. Nick Koston 2218edf20c [web_server] Switch entity id to the new format and drop name_id (#17586) 2026-07-16 08:49:43 -10:00
J. Nick Koston dcdd044234 [web_server] Use alarm_control_panel as the domain in JSON (#17594) 2026-07-16 08:48:47 -10:00
J. Nick Koston bc8510c6d8 [micro_wake_word] Include the local model file in bundles (#17604) 2026-07-16 08:09:30 -04:00
J. Nick Koston 5b4ae22f58 [api] Don't spam tracebacks when decoding a crash without a local build (#17597) 2026-07-16 08:08:28 -04:00
J. Nick Koston 14e71e190c [ci] Restore memory impact detail for ESP-IDF builds (#17587) 2026-07-16 08:00:19 -04:00
Guanzhong Chen 2333e6eef5 [zephyr] implement ISRInternalGPIOPin::digital_write (#17601) 2026-07-16 07:57:30 -04:00
Jonathan Swoboda d748c04b28 [libretiny] Code fixes for upcoming LibreTiny clang-tidy scans (#17596) 2026-07-16 07:25:46 -04:00
Jonathan Swoboda 8d1a0446a2 [haier][teleinfo][hlk_fm22x][rp2040_ble] Rename enum members that collide with vendor SDK macros (#17595) 2026-07-16 07:25:37 -04:00
Keith BurzinskiandClaude Opus 4.8 0887e01828 [improv_base] Bump Improv library to 1.2.6 (#17599)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 05:17:01 +00:00
J. Nick Koston f88621f2e1 [network] Remove deprecated IPAddress::str() (#17589) 2026-07-16 05:12:06 +00:00
J. Nick Koston ec3f7ec16e [api] Remove outdated API version warning (#17593) 2026-07-16 05:07:26 +00:00
J. Nick Koston 880cb1db43 [voice_assistant] Remove deprecated Timer::to_string() (#17591) 2026-07-16 05:06:49 +00:00
J. Nick Koston f336c45177 [water_heater] Remove deprecated WaterHeaterCall::get_state() (#17592) 2026-07-16 05:06:38 +00:00
J. Nick Koston b12d392e02 [esp32_ble] Remove deprecated ESPBTUUID::to_string() (#17590) 2026-07-16 05:06:30 +00:00
Keith BurzinskiandClaude Fable 5 49a1d2bb1b [veml3235] Overhaul auto-gain and fix latent config bugs (#17551)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 23:08:14 -05:00
J. Nick Koston e327a7f52f [scheduler] Remove deprecated set_retry/cancel_retry (#17585) 2026-07-15 17:58:41 -10:00
Jonathan Swoboda 90e838d327 [ci] Extend variant clang-tidy scans to USB logger, tsens and LP peripheral code (#17580) 2026-07-15 23:07:34 -04:00
Jonathan Swoboda f91aa7aa13 [as3935_i2c] Use repeated start when reading registers (#17584) 2026-07-16 14:26:23 +12:00
lsellens be3b27f378 [rc522_i2c] Change default address to match whats in the docs (#17566) 2026-07-15 21:20:07 -04:00
Jesse Hills 3439a08b68 [deep_sleep] Add on_wake automation triggers (#17569) 2026-07-15 21:19:41 -04:00
dedca344f9 [aqi] Add extended_range option for over-range AQI values (#17570)
Co-authored-by: jas <jas@asspa.in>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 21:17:58 -04:00
Hajo Noerenberg c4975e1870 [cc1101] Add FOCCFG and BSCFG config options (#17577) 2026-07-15 21:17:39 -04:00
Jonathan Swoboda 5a3c2f4d11 [ci] Add rp2 clang-tidy environment (#17486) 2026-07-15 21:17:21 -04:00
Jonathan Swoboda e700b01406 [haier] Fix outdoor defrost temperature reporting the coil temperature (#17492) 2026-07-15 21:16:38 -04:00
Jonathan Swoboda d53d4c5b58 [emc2101] Fix negative external temperatures reported as large positives (#17494) 2026-07-15 21:16:24 -04:00
Jesse Hills 3c34fc950e Merge branch 'release' into dev 2026-07-16 12:59:58 +12:00
Jesse Hills 920a8b761b Merge pull request #17583 from esphome/bump-2026.7.0
2026.7.0
2026-07-16 12:59:09 +12:00
Jonathan Swoboda 5d2372937e [ci] Stop per-PR cache copies from crowding the 10GB Actions cache quota (#17463) 2026-07-16 10:16:18 +12:00
Jesse Hills 6c401d406f Bump version to 2026.7.0 2026-07-16 09:52:34 +12:00
Jesse Hills b0489e21b2 Merge branch 'beta' into dev 2026-07-16 09:45:16 +12:00
Jesse Hills 78180a40c4 Merge pull request #17582 from esphome/bump-2026.7.0b4
2026.7.0b4
2026-07-16 09:44:41 +12:00
Jesse Hills 63fae2c36a Bump version to 2026.7.0b4 2026-07-16 08:23:57 +12:00
Jesse Hills 878d8a2f6a [core] Fix wait_until crash when re-entered from its own continuation (#17571) 2026-07-16 08:23:57 +12:00
esphome[bot] e056e99fd4 Bump bundled esphome-device-builder to 1.6.1 (#17575)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-07-16 08:23:57 +12:00
Jesse Hills 3b915cf16b [api] Warn when Home Assistant actions are sent with no subscribed client (#17560) 2026-07-16 08:23:57 +12:00
esphome[bot] d1150d148d Bump bundled esphome-device-builder to 1.6.0 (#17573) 2026-07-16 08:23:57 +12:00
luar123 b5b426492a [zigbee] bump esp-zigbee-sdk to 2.0.3 (#17564) 2026-07-16 08:23:57 +12:00
Jonathan Swoboda 724df7b11e [atc_mithermometer] Make duplicate-packet counter per-instance (#17496) 2026-07-16 08:23:57 +12:00
Daniele PalumboandJesse Hills 26db22546d [mcp23017] reset IPOL registers to 0x00 on setup (#17177)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-07-16 08:23:57 +12:00
Jesse Hills a3ab7961e0 [core] Fix wait_until crash when re-entered from its own continuation (#17571) 2026-07-16 08:14:55 +12:00
Hajo Noerenberg 54987d7d23 [cc1101] Export CC1101Listener to Python (#17576) 2026-07-15 12:38:08 -04:00
esphome[bot] 053ce39fc6 Bump bundled esphome-device-builder to 1.6.1 (#17575)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-07-15 08:51:50 -04:00
Jesse Hills b295b8d5a2 [api] Warn when Home Assistant actions are sent with no subscribed client (#17560) 2026-07-15 23:11:47 +12:00
esphome[bot] 4d3d06959b Bump bundled esphome-device-builder to 1.6.0 (#17573) 2026-07-14 23:59:19 -10:00
Jesse Hills a5583dcba6 [tests] Add test_display component to free touchscreen tests from display pins (#17540) 2026-07-15 11:22:47 +12:00
luar123 e2b62bcd00 [zigbee] bump esp-zigbee-sdk to 2.0.3 (#17564) 2026-07-14 17:27:17 -04:00
Jonathan Swoboda 4275343231 [atc_mithermometer] Make duplicate-packet counter per-instance (#17496) 2026-07-15 09:23:37 +12:00
dependabot[bot] 4ebe49b141 Bump clang-tidy from 22.1.7 to 22.1.8 (#17565)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-14 09:54:02 -10:00
Jesse Hills d3adb6fb81 Merge branch 'beta' into dev 2026-07-14 16:46:31 +12:00
Jesse Hills 00d2d55e09 Merge pull request #17556 from esphome/bump-2026.7.0b3
2026.7.0b3
2026-07-14 16:45:55 +12:00
esphome[bot] a833685a73 Bump bundled esphome-device-builder to 1.5.0 (#17558) 2026-07-14 14:51:55 +12:00
esphome[bot] 2753ab1f45 Bump bundled esphome-device-builder to 1.5.0 (#17558) 2026-07-13 16:50:08 -10:00
Daniele PalumboandJesse Hills b6b5b61640 [mcp23017] reset IPOL registers to 0x00 on setup (#17177)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-07-14 02:38:07 +00:00
Jesse Hills 0a1065da75 [script] Recursively expand nested packages when merging component tests (#17557) 2026-07-14 14:11:18 +12:00
Jesse Hills db9a09d05a [script] Recursively expand nested packages when merging component tests (#17557) 2026-07-14 14:11:03 +12:00
Jesse Hills 6fadf353b1 Bump version to 2026.7.0b3 2026-07-14 12:40:45 +12:00
Keith Burzinski 8da377ab43 [nextion] Fix unbounded queue growth and OOM crash when display sends no data (#17553) 2026-07-14 12:40:45 +12:00
Jonathan Swoboda 1da8900ffc [veml7700][as7341][ltr501] Fix device class on raw-count sensors (#17549) 2026-07-14 12:40:45 +12:00
J. Nick Koston 519ce38b79 [libretiny] Keep renamed board generic-ln882hki validating against generic-ln882h (#17542) 2026-07-14 12:40:45 +12:00
Jesse Hills 989797be53 [web_server] Add HTTP digest authentication with selectable scheme (#17541) 2026-07-14 12:40:45 +12:00
Jesse Hills 583adc9e69 [web_server] Use dict-style packages in tests so they can be batch-grouped (#17544) 2026-07-14 12:40:45 +12:00
Keith Burzinski af9a0404d9 [esp32] Do not require verification_key with Secure Boot V2 signing schemes (#17497) 2026-07-14 12:40:45 +12:00
Jesse Hills f38e7f2de2 [web_server] Add CORS origin checking with allowed_origins (#17530) 2026-07-14 12:40:22 +12:00
Jesse Hills 3e75020007 [gsl3670] Fix i2c package variant in esp32-s3-idf test (#17535) 2026-07-14 12:39:14 +12:00
Keith Burzinski ca77cc585c [nextion] Fix unbounded queue growth and OOM crash when display sends no data (#17553) 2026-07-14 11:56:03 +12:00
Jonathan Swoboda f1e4726f4e [veml7700][as7341][ltr501] Fix device class on raw-count sensors (#17549) 2026-07-14 11:53:31 +12:00
J. Nick Koston 49bbceb1da [libretiny] Keep renamed board generic-ln882hki validating against generic-ln882h (#17542) 2026-07-14 11:51:54 +12:00
Jesse Hills 65d6c028ce [web_server] Add HTTP digest authentication with selectable scheme (#17541) 2026-07-14 10:33:44 +12:00
Clyde Stubbs 5e3e2f82c9 [script] Fix duplicate import in build_codeowners.py (#17543) 2026-07-13 10:16:53 -04:00
Jesse Hills d78cb09b17 [web_server] Use dict-style packages in tests so they can be batch-grouped (#17544) 2026-07-13 23:23:55 +12:00
Keith Burzinski bcfb438a81 [esp32] Do not require verification_key with Secure Boot V2 signing schemes (#17497) 2026-07-13 16:23:40 +12:00
Jesse Hills a8dfd00cc6 [web_server] Add CORS origin checking with allowed_origins (#17530) 2026-07-13 15:38:48 +12:00
Jesse Hills 4a82b10783 [ci] Group component test output into collapsible CI log sections (#17536) 2026-07-13 15:29:35 +12:00
Jesse Hills 07460ebee4 [gsl3670] Fix i2c package variant in esp32-s3-idf test (#17535) 2026-07-13 15:28:55 +12:00
Jesse Hills cdc42e5e55 Merge branch 'beta' into dev 2026-07-13 13:25:21 +12:00
Jesse Hills feb53a209b Merge pull request #17532 from esphome/bump-2026.7.0b2
2026.7.0b2
2026-07-13 13:24:45 +12:00
Jonathan Swoboda c607f64288 [mipi_rgb] Test in isolation to avoid bus/pin merge conflicts (#17534) 2026-07-13 12:01:24 +12:00
Jonathan Swoboda b3e03868b3 [mipi_rgb] Test in isolation to avoid bus/pin merge conflicts (#17534) 2026-07-13 12:00:22 +12:00
Jesse Hills 7ee7a26cad [mipi_rgb] Use dict-style packages in test so it can be batch-grouped
Convert the i2c include to a named dict-style package key so CI can group
this component's build with others sharing the same bus, instead of flagging
it as needing migration.
2026-07-12 18:47:28 -04:00
Jesse Hills 0ff11674ef [mipi_rgb] Use dict-style packages in test so it can be batch-grouped (#17533) 2026-07-12 18:38:38 -04:00
Jesse Hills 2a67e5c599 Bump version to 2026.7.0b2 2026-07-13 09:19:24 +12:00
Keith Burzinski a9591d7aac [zwave_proxy] Fix parser gaps and harden frame and subscription handling (#17461) 2026-07-13 09:19:24 +12:00
J. Nick Koston bcac3ebe2b [api] Provision encryption keys over an encrypted zero-PSK noise connection (#17482) 2026-07-13 09:19:23 +12:00
Jesse Hills 27b598c5aa [core] Classify entity metadata visibility for the visual editor (#17503) 2026-07-13 09:19:23 +12:00
luar123 9ba2cbbfdd [zigbee] prevent task watchdog trigger with large configs. (#17506) 2026-07-13 09:19:23 +12:00
luar123 a4650a2345 [zigbee] Fix merge endpoint (#17511) 2026-07-13 09:19:23 +12:00
J. Nick Koston 1e5cfe6b0f [web_server] Fix unused function warning for json_state_str (#17524) 2026-07-13 09:19:23 +12:00
J. Nick Koston 665e788cc9 [mdns] Fix missing device info TXT records when native API is not enabled (#17520) 2026-07-13 09:19:23 +12:00
J. Nick Koston d89b4c0b59 [core] Make config-hash independent of machine-local paths (#17523) 2026-07-13 09:19:23 +12:00
esphome[bot] 5afe418a8e Bump bundled esphome-device-builder to 1.4.3 (#17522) 2026-07-13 09:19:23 +12:00
tomaszduda23 312f6f2049 [deep_sleep] feed watchdog in deep sleep (#17516) 2026-07-13 09:19:23 +12:00
Clyde StubbsandClaude Opus 4.8 eb0848d538 [mipi_dsi] New model for M5Stack Tab5 (#17500)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 09:19:23 +12:00
Clyde Stubbsandpre-commit-ci-lite[bot] 1a573919d1 [mipi][mipi_spi] SWRESET handling improved (#17504)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-07-13 09:19:23 +12:00
esphome[bot] 692cf7abd1 Bump bundled esphome-device-builder to 1.4.2 (#17512) 2026-07-13 09:19:23 +12:00
Clyde StubbsandClaude Opus 4.8 f0afd9e660 [mipi][mipi_spi][mipi_dsi][mipi_rgb] Transform cleanup (#17405)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 09:19:23 +12:00
esphome[bot] 262ee421f6 Bump bundled esphome-device-builder to 1.4.1 (#17507) 2026-07-13 09:19:23 +12:00
esphome[bot] 050a006459 Bump bundled esphome-device-builder to 1.4.0 (#17495) 2026-07-13 09:19:23 +12:00
Jonathan Swoboda 8518d0633b [web_server] Serialize entity state strings without a copy buffer (#17488) 2026-07-13 09:19:23 +12:00
dependabot[bot] 284fe85271 Bump aioesphomeapi from 45.5.2 to 45.6.0 (#17490)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-13 09:19:23 +12:00
Jonathan Swoboda 020a6a8fd1 [mcp4461] Fix wiper increment/decrement write length (#17487) 2026-07-13 09:19:23 +12:00
Jonathan Swoboda 196b979df8 [usb_uart] Fix output chunk length truncated to 8 bits (#17480) 2026-07-13 09:19:23 +12:00
Keith Burzinski 434cffb745 [zwave_proxy] Fix parser gaps and harden frame and subscription handling (#17461) 2026-07-13 08:58:17 +12:00
J. Nick Koston 2b3027a7fd [api] Provision encryption keys over an encrypted zero-PSK noise connection (#17482) 2026-07-13 08:55:30 +12:00
Jesse Hills e27a14ec70 [core] Classify entity metadata visibility for the visual editor (#17503) 2026-07-12 08:33:29 -04:00
luar123 91c42381f6 [zigbee] prevent task watchdog trigger with large configs. (#17506) 2026-07-12 08:32:01 -04:00
luar123 a39607476a [zigbee] Fix merge endpoint (#17511) 2026-07-12 08:31:39 -04:00
J. Nick Koston b098571a6f [web_server] Fix unused function warning for json_state_str (#17524) 2026-07-11 14:31:14 -10:00
J. Nick Koston 614fd88829 [mdns] Fix missing device info TXT records when native API is not enabled (#17520) 2026-07-11 14:31:01 -10:00
J. Nick Koston c0636e2bf7 [core] Make config-hash independent of machine-local paths (#17523) 2026-07-11 14:30:47 -10:00
esphome[bot] 65353006c8 Bump bundled esphome-device-builder to 1.4.3 (#17522) 2026-07-11 13:32:45 -10:00
tomaszduda23 35a99f478e [deep_sleep] feed watchdog in deep sleep (#17516) 2026-07-11 09:48:11 -04:00
dependabot[bot] b6a4dd237e Update tzdata requirement from >=2026.2 to >=2026.3 (#17510)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-11 09:45:42 -04:00
dependabot[bot] 0ef85783dc Bump actions/stale from 10.3.0 to 10.4.0 (#17509)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-11 09:45:23 -04:00
dependabot[bot] 5020179210 Bump ruff from 0.15.20 to 0.15.21 (#17508)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-11 09:45:02 -04:00
Clyde StubbsandClaude Opus 4.8 54529412dc [mipi_dsi] New model for M5Stack Tab5 (#17500)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 09:38:01 -04:00
Clyde Stubbsandpre-commit-ci-lite[bot] e6525b5d93 [mipi][mipi_spi] SWRESET handling improved (#17504)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-07-11 09:36:26 -04:00
Raymond 9f62cf9243 [mipi_dsi] Add JC8012P4A1-V2 (#17457) 2026-07-11 21:24:00 +10:00
esphome[bot] 478bca026c Bump bundled esphome-device-builder to 1.4.2 (#17512) 2026-07-10 16:37:00 -10:00
Clyde StubbsandClaude Opus 4.8 e1719cd85d [mipi][mipi_spi][mipi_dsi][mipi_rgb] Transform cleanup (#17405)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 22:06:40 -04:00
esphome[bot] 83aaed71e1 Bump bundled esphome-device-builder to 1.4.1 (#17507) 2026-07-10 10:30:19 -10:00
Jesse Hills 88ca0d44e0 [docs] Document web server as an open HTTP API by design in threat model (#17465) 2026-07-10 16:38:23 +12:00
esphome[bot] 7a1e0bbbec Bump bundled esphome-device-builder to 1.4.0 (#17495) 2026-07-09 15:36:42 -10:00
Jonathan Swoboda b2226b91ff [web_server] Serialize entity state strings without a copy buffer (#17488) 2026-07-09 16:51:04 -04:00
dependabot[bot] ba84f2ec55 Bump aioesphomeapi from 45.5.2 to 45.6.0 (#17490)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-09 19:53:42 +00:00
dependabot[bot] 4b19de0c1a Bump CodSpeedHQ/action from 4.18.4 to 4.18.5 (#17489)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-09 19:35:16 +00:00
Jonathan Swoboda 4292e7988e [mcp4461] Fix wiper increment/decrement write length (#17487) 2026-07-09 15:27:05 -04:00
Jonathan Swoboda 9f21fd0b55 [usb_uart] Fix output chunk length truncated to 8 bits (#17480) 2026-07-09 15:04:42 -04:00
Jesse Hills 9327d011fc Merge branch 'beta' into dev 2026-07-09 16:54:49 +12:00
Jesse Hills 6c4640f4f1 Merge pull request #17460 from esphome/bump-2026.7.0b1
2026.7.0b1
2026-07-09 16:54:10 +12:00
Jonathan Swoboda 435dde67d0 [ci] Stop per-PR cache copies from crowding the 10GB Actions cache quota (#17463) 2026-07-08 23:29:23 -04:00
Jonathan Swoboda 19e89aa7f2 [gsl3670] Reference the test display explicitly so grouped CI builds validate (#17462) 2026-07-09 13:44:40 +12:00
Jonathan Swoboda 9c92ab63fb [gsl3670] Reference the test display explicitly so grouped CI builds validate (#17462) 2026-07-09 13:43:56 +12:00
Elvin Luff acc8381cbb [epaper_spi] Remove noop deep sleep command (#15595) 2026-07-09 11:29:39 +10:00
Jesse Hills 0a8a7e22d2 Bump version to 2026.8.0-dev 2026-07-09 12:30:54 +12:00
Jesse Hills f1622ac96a Bump version to 2026.7.0b1 2026-07-09 12:30:53 +12:00
Jesse Hills c66f4d667e Merge branch 'release' into dev 2026-07-09 12:21:34 +12:00
Jesse Hills 3bfbaaebf3 Merge pull request #17459 from esphome/bump-2026.6.5
2026.6.5
2026-07-09 12:20:50 +12:00
Jesse Hills 98b79b132a Bump version to 2026.6.5 2026-07-09 12:09:05 +12:00
esphome[bot] f6221f0007 Bump bundled esphome-device-builder to 1.1.0 (#17412)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-07-09 12:09:05 +12:00
esphome[bot] 263b375088 Bump bundled esphome-device-builder to 1.0.29 (#17384) 2026-07-09 12:09:05 +12:00
esphome[bot] a1f819e9b8 Bump bundled esphome-device-builder to 1.0.28 (#17382) 2026-07-09 12:09:05 +12:00
esphome[bot]andJonathan Swoboda ca7f50f37f Bump bundled esphome-device-builder to 1.0.27 (#17370)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-07-09 12:09:05 +12:00
esphome[bot] 7b92fe95af Bump bundled esphome-device-builder to 1.0.26 (#17369) 2026-07-09 12:09:05 +12:00
esphome[bot] 42ddf0870c Bump bundled esphome-device-builder to 1.0.25 (#17333) 2026-07-09 12:09:05 +12:00
esphome[bot] 0512dd2339 Bump bundled esphome-device-builder to 1.0.24 (#17332) 2026-07-09 12:09:05 +12:00
Clyde Stubbs 8ccf0dbd37 [gsl3670] Add new touchscreen component (#16285) 2026-07-09 12:04:43 +12:00
Jesse Hills 7c130fc970 [core] Hide build & framework internals from the visual editor (#17449) 2026-07-09 11:58:40 +12:00
Clyde Stubbs 640e0973ac [lvgl] Dynamic rotation features (#16773) 2026-07-08 15:54:28 -04:00
dependabot[bot] 9088875491 Bump github/codeql-action/analyze from 4.36.3 to 4.37.0 (#17456)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-08 15:42:48 -04:00
dependabot[bot] 99ec2cc00a Bump CodSpeedHQ/action from 4.18.2 to 4.18.4 (#17455)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-08 15:42:38 -04:00
dependabot[bot] 99ff7e198a Bump astral-sh/setup-uv from 8.3.1 to 8.3.2 (#17454)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-08 15:42:18 -04:00
dependabot[bot] d4bb20d34b Bump github/codeql-action/init from 4.36.3 to 4.37.0 (#17453)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-08 15:42:05 -04:00
dependabot[bot] 2db001710c Bump astral-sh/setup-uv from 8.3.1 to 8.3.2 in /.github/actions/restore-python (#17452)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-08 15:41:50 -04:00
Jesse Hills dd0d0942f5 [image] Restructure into a platform component (#17416) 2026-07-09 07:38:58 +12:00
Jonathan Swoboda 26f48ee9ea [lvgl] Fix ImageValidator.process signature to match base (#17451) 2026-07-09 07:21:23 +12:00
luar123 84f4fbeaa8 [zigbee] Allow to combine and merge endpoints on esp32 (#17402) 2026-07-08 14:41:36 -04:00
ce46895270 [uart][usb_uart] Implement runtime settings update (#16990)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2026-07-08 13:30:49 -04:00
esphome[bot] e7933a5387 Bump bundled esphome-device-builder to 1.3.1 (#17450)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-07-08 13:06:38 -04:00
Clyde Stubbs b787281388 [lvgl] Add direct use of mapping (#15863) 2026-07-08 13:00:42 -04:00
bba3a9657b [lvgl] Add animations (#16796)
Co-authored-by: clydeps <U5yx99dok9>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-07-08 12:17:57 -04:00
Kevin Ahrendt 2f5465c0e8 [sendspin] Suppress WiFi roam scanning while playing (#17133) 2026-07-08 12:07:42 -04:00
Keith BurzinskiandClaude Opus 4.8 9c40ed5d71 [provisioning] Add provisioning window (#17152)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 01:01:20 -05:00
esphome[bot] 93bc02b308 Bump bundled esphome-device-builder to 1.3.0 (#17448)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-07-07 20:39:55 -05:00
Jesse Hills b8af90750f [web_server_idf] Map more common HTTP status codes in responses (#17447) 2026-07-08 13:18:46 +12:00
Jesse Hills 65ef05dd1f [web_server_idf] Deliver raw POST bodies to custom handlers via handleBody() (#17433) 2026-07-07 20:51:00 -04:00
Bonne EgglestonandClaude Fable 5 731486d9b0 [modbus] Finalize unreleased API surface before 2026.7 (#17434)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 00:20:14 +00:00
Jonathan Swoboda 731e9fda03 [internal_temperature] Support all ESP32 variants with a temperature sensor (#17438) 2026-07-08 09:12:57 +12:00
dependabot[bot] 35c7496cd7 Bump CodSpeedHQ/action from 4.18.1 to 4.18.2 (#17445)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-07 16:02:38 -05:00
dependabot[bot] 71b746b6fa Bump astral-sh/setup-uv from 8.3.0 to 8.3.1 (#17444)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-07 16:02:26 -05:00
dependabot[bot] 1913818b1c Bump astral-sh/setup-uv from 8.3.0 to 8.3.1 in /.github/actions/restore-python (#17442)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-07 16:02:16 -05:00
J. Nick Koston b4ad0eb86b [esp32_ble] Fix boot loop when the hosted co-processor does not answer BT bring-up (#17429) 2026-07-07 14:59:18 +00:00
Clyde StubbsandJonathan Swoboda 7f0e826c32 [lvgl] Add paused option to suppress updates on boot (#16973)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-07-07 14:50:36 +00:00
76ee3fe887 [audio_file] Accept mp1/mp2 puremagic detections as MP3 (#17436)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-07 08:56:48 -04:00
af4a6e7ec3 [usb_uart] Fix FTDI RX data stall / corruption and input restart reliability (#17348)
Co-authored-by: Oliver Kleinecke <kleinecke.oliver@googlemail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-07 21:55:49 +10:00
luar123andCopilot Autofix powered by AI 40c3a4320f [core] add const for litre per hour (#17389)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-07 21:44:44 +10:00
J. Nick Koston 3c2dad67f4 [network] Fix logged use_address with MAC suffix and build it at runtime (#17432) 2026-07-07 02:07:34 -05:00
Remco van Essen f823a23ea4 [pcm5122] Add analog gain, channel mixing, volume range, standby/powerdown switch, and XSMT enable pin support (#17313) 2026-07-07 00:15:37 -05:00
Keith Burzinski 9aed1d2700 [esp32] Add NVS encryption (HMAC scheme) (#17004) 2026-07-07 16:04:38 +12:00
Clyde StubbsandCopilot Autofix powered by AI 9857d508d9 [light] Preserve brightness on turn-off. (#17103)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-07 15:57:06 +12:00
Clyde Stubbs ad7c980c4b [lvgl] Continue activity while display busy (#17374) 2026-07-07 03:16:29 +00:00
J. Nick Koston e8d37e5bd3 [libretiny] Use standard logger tag names (#17431) 2026-07-06 20:55:12 -04:00
J. Nick Koston a36c3063b2 [web_server] Use known message length in SSE send path (#17400) 2026-07-06 20:55:02 -04:00
J. Nick Koston 902cf6a679 [analyze_memory] Report aliased RAM symbols once in the RAM strings report (#17397) 2026-07-06 20:54:53 -04:00
J. Nick Koston a10e005bb4 [esp8266] Strip lwIP glue dhcp stub message strings from DRAM (#17395) 2026-07-06 20:54:44 -04:00
Keith BurzinskiandClaude Opus 4.8 d9998eff20 [esp32] Add software OTA downgrade protection (#17315)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 20:39:18 -04:00
Clyde Stubbs 2dd7ac090f [mipi_spi] Add M5STACK ATOM3SR display (#17344) 2026-07-06 20:37:44 -04:00
Jesse Hills c4689989c7 Mark configurable classes as final (20/21: wts01-zephyr_ble_server) (#16971) 2026-07-06 19:42:18 -04:00
Bonne EgglestonandClaude ebff49072e [modbus] Store ModbusFrame inline to cut per-frame heap churn (#17282)
Co-authored-by: Claude <noreply@anthropic.com>
2026-07-06 23:12:25 +00:00
esphome[bot] 0b311962b5 Bump bundled esphome-device-builder to 1.2.0 (#17430) 2026-07-06 17:09:51 -05:00
Jonathan Swoboda b22def399f [espnow] Add max_payload_size option for ESP-NOW v2 frames (#17360) 2026-07-06 17:08:56 -04:00
Jesse HillsandJonathan Swoboda cdd334284e [rp2] Rename rp2040 platform to rp2 (#17145)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-07-07 08:20:24 +12:00
Jesse Hills 9caf431740 [tests] Document dict-style packages requirement for batch grouping (#17420) 2026-07-07 07:55:53 +12:00
tomaszduda23 468b32b986 [nrf52] add better error message for OTA error (#17407) 2026-07-06 15:50:57 -04:00
tomaszduda23andJonathan Swoboda 39ad583b39 [nrf52] allow to build for non nrf52840 boards (#17373)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-07-06 15:48:24 -04:00
J. Nick Koston 90403576c4 [wifi] Accept boolean-like strings for fast_connect again (#17414) 2026-07-06 14:42:30 -05:00
J. Nick Koston 51fa25856d [bluetooth_proxy] Take over stale advertisement subscription instead of rejecting the new subscriber (#17423) 2026-07-06 14:42:14 -05:00
dependabot[bot] 27d4b63a8a Bump astral-sh/setup-uv from 8.2.0 to 8.3.0 (#17428)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-06 14:41:55 -05:00
dependabot[bot] 104c2f86f6 Bump astral-sh/setup-uv from 8.2.0 to 8.3.0 in /.github/actions/restore-python (#17427)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-06 14:41:43 -05:00
dependabot[bot] e64a79f431 Bump setuptools from 82.0.1 to 83.0.0 (#17426)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-06 14:41:29 -05:00
Oliver Kleinecke b79db76099 [core] helpers.h - Implement pop_back method for vector (#17390) 2026-07-06 13:54:20 -05:00
Bonne EgglestonandClaude Fable 5 66ab807596 [modbus] API naming (#17378)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 11:43:31 -05:00
Jesse Hills 2067da4ff5 Mark configurable classes as final (11/21: microphone-ms8607) (#16962) 2026-07-06 16:33:07 +12:00
Jesse Hills cfdd6d383f Mark configurable classes as final (19/21: uart-wl_134) (#16970) 2026-07-06 16:32:42 +12:00
Jesse Hills bdd51bd476 Mark configurable classes as final (16/21: sm10bit_base-ssd1331_spi) (#16967) 2026-07-06 16:32:35 +12:00
Jesse Hills af7b6e3589 Mark configurable classes as final (17/21: ssd1351_spi-tem3200) (#16968) 2026-07-06 16:32:26 +12:00
Jesse Hills fd86417bf5 [cst328] Update test package (#17415) 2026-07-06 16:29:45 +12:00
J. Nick Koston e095c457ff [esp32] Suppress -Wvolatile in the direct ESP-IDF build (#17404) 2026-07-06 03:02:12 +00:00
Jesse Hills 39c0f9cc84 [cst328] Use dict-style packages so batch grouping deduplicates the i2c bus (#17413) 2026-07-05 22:57:56 -04:00
tomaszduda23 3f94e6dcbb [nrf52] let user select libc version (#17408) 2026-07-05 19:52:39 -04:00
crimikeandclydebarrow b9588a8984 [mipi_spi] Add Waveshare-ESP32-S3-TOUCH-AMOLED-1.64 (#17386)
Co-authored-by: clydebarrow <2366188+clydebarrow@users.noreply.github.com>
2026-07-06 09:29:03 +10:00
esphome[bot] 105d1362a2 Bump bundled esphome-device-builder to 1.1.0 (#17412)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-07-05 15:31:07 -05:00
Clyde Stubbs f6c260a2c5 [ci] Make import time budget more realistic (#17406) 2026-07-05 08:01:48 -04:00
dependabot[bot] c720186170 Bump smpclient from 6.0.0 to 7.2.0 (#16928)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-05 06:50:13 +02:00
Chris BootandClaude Opus 4.8 8ab19c0242 [esp32] Add RTC-backed preferences (honor in_flash flag) (#17073)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 11:48:30 +10:00
esphome[bot] 2c24e82ba3 Bump bundled esphome-device-builder to 1.0.29 (#17384) 2026-07-04 15:20:48 -05:00
Jonathan Swoboda fcfaa43e1e [ci] Name the sdk-nrf cache steps after the nRF Connect SDK (#17392) 2026-07-04 12:46:16 -04:00
esphome[bot] 4c8e45a222 Bump bundled esphome-device-builder to 1.0.28 (#17382) 2026-07-03 23:17:49 -05:00
7878052533 [epaper_spi] Add T133A01 6-color e-paper driver for reTerminal E1004 (#16706)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
2026-07-04 03:50:54 +00:00
Anton ViktorovandClyde Stubbs e94fcda8b7 [cst328] Touch screen (Waveshare ESP32-S3-Touch-LCD-2.8) (#8011)
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
2026-07-04 12:13:22 +10:00
Jonathan Swoboda 5738c60206 [nrf52] Run clang-tidy against the native sdk-nrf toolchain (#17364) 2026-07-03 18:09:01 -04:00
dependabot[bot] a035d84474 Bump docker/login-action from 4.3.0 to 4.4.0 in the docker-actions group (#17380)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-03 16:55:47 -04:00
luar123andJonathan Swoboda 7ad43358c2 [zigbee] Bump zigbee sdk to 2.0.2 (#16869)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-07-03 14:28:29 -04:00
Jonathan Swoboda 187cd51867 [ci] Carry native-toolchain needs on component test batches (#17359) 2026-07-03 13:47:08 -04:00
fd16eec416 [nrf52] switch nrf52 builds to native sdk by default (#17319)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
Co-authored-by: ESPHome Device Builder <device-builder@esphome.io>
2026-07-03 12:16:55 -04:00
tomaszduda23 ea14a93e67 [nrf52] fix crash report for native build (#17371) 2026-07-03 09:33:42 -04:00
esphome[bot]andJonathan Swoboda c456fc98ab Bump bundled esphome-device-builder to 1.0.27 (#17370)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-07-03 09:31:21 -04:00
esphome[bot]andesphomebot 711d8bb0ad Synchronise Device Classes from Home Assistant (#17372)
Co-authored-by: esphomebot <esphome@openhomefoundation.org>
2026-07-03 08:33:00 -04:00
c3233739c5 [zephyr] Implement GPIO interrupts (ISRInternalGPIOPin) (#17077)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: tomaszduda23 <tomaszduda23@gmail.com>
2026-07-03 11:43:21 +02:00
Joseph Spiros 5fe36a45ed [core] Skip MAC-suffix mDNS discovery for non-mDNS addresses (#16874) 2026-07-03 11:48:55 +12:00
esphome[bot] 0725157bf5 Bump bundled esphome-device-builder to 1.0.26 (#17369) 2026-07-02 18:48:08 -05:00
Jonathan Swoboda 9f589ec4fc [api] Register homeassistant.action with synchronous=False to fix stale trigger args in response callbacks (#17367) 2026-07-02 19:47:12 -04:00
dependabot[bot] 5417a16f9d Update argcomplete requirement from >=3.6.3 to >=3.7.0 (#17334)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-02 18:37:22 -04:00
dependabot[bot] f447c88b4c Bump docker/build-push-action from 7.2.0 to 7.3.0 in /.github/actions/build-image (#17336)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-02 18:37:12 -04:00
dependabot[bot] 0b48ca0027 Bump the docker-actions group with 2 updates (#17361)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-02 18:36:33 -04:00
dependabot[bot] bef6773281 Bump github/codeql-action/init from 4.36.2 to 4.36.3 (#17362)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-02 18:36:01 -04:00
dependabot[bot] 4f0968f1df Bump github/codeql-action/analyze from 4.36.2 to 4.36.3 (#17363)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-02 18:35:46 -04:00
Jonathan Swoboda 648f5e1b06 [nrf52] Install native sdk-nrf into a machine-global cache dir (#17353) 2026-07-02 15:42:59 -04:00
Jonathan Swoboda 65fc10d627 [nrf52] Build PlatformIO libraries as Zephyr modules (sdk-nrf) (#17250) 2026-07-02 10:26:34 -04:00
tomaszduda23andJonathan Swoboda 41cf842d5d [zephyr][nrf52] Rebuild native build when config inputs change (#17318)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-07-02 14:13:56 +00:00
Sven KockschandClyde Stubbs 792dfbcbbf [st7123] add ST7123 touch controller component (M5Stack Tab5) (#12075)
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
2026-07-02 18:40:59 +10:00
Twisterss 06c7ac37d1 [epaper_spi] Add Waveshare 7.5" V2 BWR support (#15719) 2026-07-02 17:33:58 +10:00
Oliver Kleinecke 0666cb8635 [usb_uart] Add per-device-type maximum baud rate cap (#17259) 2026-07-02 13:44:09 +10:00
Clyde Stubbs 5b8bf51022 [power_supply] Make enable_on_boot high priority (#16914) 2026-07-02 13:56:01 +12:00
Oliver Kleinecke 4a7c58d5ae [usb_uart] Fix format specifier warnings for uint32_t in ft23xx and pl2303 (#17342) 2026-07-02 11:26:56 +10:00
J. Nick Koston 7522780c67 [esp8266] Strip dead libstdc++ throw message strings from DRAM (#17341) 2026-07-01 18:25:34 -05:00
dependabot[bot] e4a68c2da3 Bump pillow from 12.2.0 to 12.3.0 (#17335)
Signed-off-by: dependabot[bot] <support@github.com>
2026-07-01 15:25:55 -05:00
esphome[bot] 0427d20c5b Bump bundled esphome-device-builder to 1.0.25 (#17333) 2026-07-01 15:02:01 -05:00
d25d160686 [modbus_server] Fix register range issues and allow partial reads (#17205)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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-07-01 15:01:48 -05:00
esphome[bot] 0e260e5cbb Bump bundled esphome-device-builder to 1.0.24 (#17332) 2026-07-01 12:52:09 -05:00
Jesse Hills 58780cd765 Merge branch 'release' into dev 2026-07-01 16:26:24 +12:00
Jesse Hills 1fc73731a8 Merge pull request #17317 from esphome/bump-2026.6.4
2026.6.4
2026-07-01 16:25:39 +12:00
Jesse Hills e47feace11 Bump version to 2026.6.4 2026-07-01 13:18:54 +12:00
esphome[bot] 4472d3b61b Bump bundled esphome-device-builder to 1.0.23 (#17316) 2026-07-01 13:18:54 +12:00
Jonathan Swoboda 06c5bcbc66 [espnow] Drop oversized received frames to prevent buffer overflow (#17271) 2026-07-01 13:18:54 +12:00
Jonathan Swoboda 6c44775bf5 [bluetooth_proxy] Fix -Wtype-limits warning with active: false (#17273) 2026-07-01 13:18:54 +12:00
Clyde Stubbs b127363fa0 [mipi_spi] Bug fixes (#17247) 2026-07-01 13:18:54 +12:00
esphome[bot] 782b58bbeb Bump bundled esphome-device-builder to 1.0.22 2026-07-01 13:18:50 +12:00
Franck NijhofandJonathan Swoboda 5de508ad8c [es8388] Fix DAC unable to unmute once muted (#17221)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-07-01 13:18:40 +12:00
Jesse Hills 054c8ba485 [config_validation] Fix multicast typo in error message (#17206) 2026-07-01 13:18:35 +12:00
Julian Lunz 3b2be021b2 [adc] Only call cyw43_thread_enter/exit for VSYS when WiFi is active on RP2040 (#17203) 2026-07-01 13:11:21 +12:00
esphome[bot] 848defedd8 Bump bundled esphome-device-builder to 1.0.23 (#17316) 2026-07-01 13:09:48 +12:00
dependabot[bot] 4c9ed129cf Bump awalsh128/cache-apt-pkgs-action from 1.6.0 to 1.6.3 (#17310)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-30 18:28:04 -04:00
dependabot[bot] c8b37fb1c8 Bump platformdirs from 4.9.4 to 4.10.0 (#17309)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-30 17:18:33 -04:00
Jonathan Swoboda 1b556f5d0c [ethernet] Fix ETH_SPEED_1000M build on IDF 6.0 (enum added in 6.1) (#17311) 2026-06-30 17:17:47 -04:00
Jonathan Swoboda 8a3d0aeafb [tests] Add esp32-c61-idf base file for grouped component tests (#17293) 2026-06-30 19:33:17 +00:00
Jonathan Swoboda 9468ad628c [espnow] Drop oversized received frames to prevent buffer overflow (#17271) 2026-06-30 14:57:34 -04:00
Jonathan Swoboda 990431aa5b [bluetooth_proxy] Fix -Wtype-limits warning with active: false (#17273) 2026-06-30 14:56:30 -04:00
Jonathan Swoboda b79cbcbde7 [espidf] Install native ESP-IDF into a machine-global cache dir (#17306) 2026-06-30 14:56:18 -04:00
Bonne Eggleston afb5922f37 [modbus] Update client components to use ModbusClientDevice (#11987) 2026-06-30 13:26:51 -05:00
Jonathan Swoboda 3035355c0a [ci] Widen import-time margin for CI runner variance (#17287) 2026-06-30 11:38:31 -04:00
Jonathan Swoboda 43b3aa0712 [ci] Fix nRF52 zigbee/network test-grouping conflict (#17295) 2026-06-30 11:37:59 -04:00
Jonathan Swoboda 12b78e7c47 [qmi8658] Pin i2c_id in test config to fix grouped component test conflict (#17303) 2026-06-30 11:37:17 -04:00
Clyde Stubbs fb5d8b5d4c [mipi_spi] Bug fixes (#17247) 2026-06-30 08:43:01 -04:00
Bonne EgglestonandClaude Opus 4.8 9e72027b64 [devcontainer] Align base image with production, fix Python venv and build tools (#17296)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 08:33:33 -04:00
Edvard FilistovičandJonathan Swoboda faa5f72500 [mqtt] Add LN882X (LN882H) platform support (#17297)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-30 08:16:18 -04:00
Jonathan Swoboda 359c6a7265 [libretiny] Update LibreTiny to v1.13.0 (#17288) 2026-06-29 22:34:32 -04:00
J. Nick Koston a031da351d Merge pull request #17294 from esphome/bump-device-builder-1.0.22 2026-06-29 19:29:08 -07:00
esphome[bot] 091b6a0ba0 Bump bundled esphome-device-builder to 1.0.22 2026-06-30 02:07:06 +00:00
Jesse Hills cf9d97d5ae [pixoo] Add Divoom Pixoo display component (#16974) 2026-06-30 11:20:48 +12:00
Clyde Stubbs 3e1a6b4e11 [cst9220] Add CST9220 and CST9217 touchscreen support (#16888) 2026-06-30 11:18:01 +12:00
Clyde Stubbs 5c7245dfcd [qmi8658] Motion platform for QMI8658 IMU (#16889) 2026-06-30 11:04:25 +12:00
Clyde Stubbs 1611345c55 [agents] Add English language AI guidelines for documentation (#17290) 2026-06-29 22:37:17 +00:00
Jonathan Swoboda b36e20d60b Revert "Bump awalsh128/cache-apt-pkgs-action from 1.6.0 to 1.6.2 (#17286)" (#17289) 2026-06-29 18:25:16 -04:00
Ardumine 93eb6f78e0 [network] Enlarge Zephyr net buffer pool and TCP windows on nRF52/Zephyr plataform (#17278) 2026-06-29 17:32:57 -04:00
dependabot[bot] e308075e3f Bump puremagic from 1.30 to 2.2.0 (#17285)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-29 16:12:23 -04:00
dependabot[bot] 405607e9d2 Bump esptool from 5.3.0 to 5.3.1 (#17284)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-29 16:06:36 -04:00
dependabot[bot] 797ed23765 Bump tzlocal from 5.4.3 to 5.4.4 (#17283)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-29 16:02:11 -04:00
dependabot[bot]andJonathan Swoboda 8780c7e0ac Bump awalsh128/cache-apt-pkgs-action from 1.6.0 to 1.6.2 (#17286)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-29 16:01:41 -04:00
Jonathan Swoboda 136e343988 [ethernet] Generic and YT8531 PHY over RGMII (gigabit) for ESP32-S31 (#17277) 2026-06-29 14:13:11 -04:00
Jonathan Swoboda b8690c8e31 [core] Drop Python 3.11 support (#17280) 2026-06-29 12:32:28 -04:00
Kevin Ahrendt 2778c62d07 [audio] Bump microMP3 to v0.4.0 (#17279) 2026-06-29 11:33:56 -04:00
Jesse Hills 7984349c36 Merge branch 'release' into dev 2026-06-29 22:32:34 +12:00
Jesse Hills 0cbbd64577 Merge pull request #17223 from esphome/bump-2026.6.3
2026.6.3
2026-06-29 22:31:44 +12:00
Jesse Hills a618ee11b4 Bump version to 2026.6.3 2026-06-29 20:30:24 +12:00
Tom 6251c26cc6 [espnow] Fix espnow crash when send() is called without a callback (#17266) 2026-06-29 20:30:24 +12:00
Jonathan Swoboda 4fbe0d87ec [wifi] Fix crash when WiFi is enabled late alongside ESP-NOW (#17239) 2026-06-29 20:30:24 +12:00
esphome[bot] 24d8e99c50 Bump bundled esphome-device-builder to 1.0.21 (#17257)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-06-29 20:30:24 +12:00
Jonathan Swoboda 14b6a0ede1 [espnow] Don't throttle ESP-NOW RX when deep_sleep is present (#17240) 2026-06-29 20:30:24 +12:00
Jonathan Swoboda 1793ca5eac [core] Suppress unactionable legacy-redaction warning for substitutions (#17242) 2026-06-29 20:30:24 +12:00
esphome[bot] 62e19bcb27 Bump bundled esphome-device-builder to 1.0.20 (#17244) 2026-06-29 20:30:24 +12:00
Franck NijhofandJonathan Swoboda 84d1c34c28 [core] Fix area saved as null in storage.json (#17219)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-29 20:30:24 +12:00
esphome[bot] f78cbf9200 Bump bundled esphome-device-builder to 1.0.19 (#17217)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-06-29 20:30:23 +12:00
esphome[bot] eb711381d3 Bump bundled esphome-device-builder to 1.0.18 (#17212)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-06-29 20:30:23 +12:00
Jonathan Swoboda 9a1daa5247 [hbridge] Fix light stuck on one polarity (#17162) 2026-06-29 20:30:18 +12:00
Clyde StubbsandClaude Opus 4.8 f3d61ca3e1 [mipi][mipi_spi] Swap native dimensions for swap_xy hardware transform (#17201)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 20:29:44 +12:00
Jonathan Swoboda 29dfd820c6 [wifi] Report STA IP, not SoftAP IP, in wifi_info on ESP8266 (#17185) 2026-06-29 20:29:44 +12:00
Jonathan Swoboda 8bc5b97298 [network] Set IPv4 type tag on all lwIP platforms, not just esp32 (#17200) 2026-06-29 20:29:44 +12:00
Jonathan Swoboda 7a64163c4f [esp32] Accept '#' as ESP-IDF source ref separator (#17193) 2026-06-29 20:29:44 +12:00
esphome[bot] dfe14f9c3a Bump bundled esphome-device-builder to 1.0.17 (#17199) 2026-06-29 20:29:44 +12:00
esphome[bot] 26cf373ae7 Bump bundled esphome-device-builder to 1.0.16 (#17182) 2026-06-29 20:29:44 +12:00
Geoffrey Frogeyeandpre-commit-ci-lite[bot] 94ccddf176 [opentherm] Support power scaling disabled (#17183)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-06-29 20:29:44 +12:00
Clyde Stubbs 2ec24505d0 [mipi_spi] Suppress sequence errors when page selection used (#17176) 2026-06-29 20:29:44 +12:00
esphome[bot] 4f7faa7712 Bump bundled esphome-device-builder to 1.0.15 (#17170) 2026-06-29 20:29:44 +12:00
Clyde Stubbs b3dcaac262 [mipi_spi] Warn on MODE3 default for display without CS pin (#17153) 2026-06-29 20:29:44 +12:00
mnewton25andJonathan Swoboda ee118d384a [esp32] Use POSIX path for secure-boot signing/verification keys Fixes #17164 (#17166)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-29 20:29:44 +12:00
Jonathan Swoboda 8d36167e11 [esp32_ble_server] Fix set_value action with by-reference triggers (#17156) 2026-06-29 20:29:44 +12:00
esphome[bot] 6d559a32df Bump bundled esphome-device-builder to 1.0.14 (#17139) 2026-06-29 20:29:37 +12:00
Jonathan Swoboda bf0d31b3ab [espidf] Don't fail framework check on broken unrelated PATH tools (#17053) 2026-06-29 20:23:23 +12:00
dependabot[bot] d8ffb732b7 Bump zeroconf from 0.149.16 to 0.150.0 (#17137)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-29 20:23:23 +12:00
Tom 9e8261056c [espnow] Fix espnow crash when send() is called without a callback (#17266) 2026-06-28 23:06:12 -04:00
Clyde StubbsandCopilot Autofix powered by AI 5f311d281e [esphome] Warn when a YAML merge (<<:) drops a key (#17246)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-29 07:17:01 +10:00
J. Nick Koston a336ad6732 [mcp4725] Use constexpr bit shift instead of powf for full-scale value (#17261) 2026-06-28 17:07:51 -04:00
Bonne EgglestonandJonathan Swoboda 8434d54cc7 [modbus] Reinstate turnaround delay after broadcasts (Revert #17209) (#17263)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-28 17:07:25 -04:00
Jonathan Swoboda b62f7a41c9 [multiple] Single-precision float math, avoid double promotion (stragglers) (#17260) 2026-06-28 16:15:38 -04:00
4ebecf514a [modbus_server] Simplify server response handling (#12376)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-06-28 19:41:47 +00:00
Jonathan Swoboda 2f32c88ae5 [wifi] Fix crash when WiFi is enabled late alongside ESP-NOW (#17239) 2026-06-28 15:16:42 -04:00
Jonathan Swoboda 95449068e7 [multiple] Single-precision float math, avoid double promotion (batch 4/4) (#17256) 2026-06-28 14:18:41 -04:00
Jonathan Swoboda 556def78aa [multiple] Single-precision float math, avoid double promotion (batch 3/4) (#17255) 2026-06-28 14:18:30 -04:00
Jonathan Swoboda b7803cf9b5 [multiple] Single-precision float math, avoid double promotion (batch 2/4) (#17254) 2026-06-28 14:18:20 -04:00
Jonathan Swoboda 40820287f1 [multiple] Single-precision float math, avoid double promotion (batch 1/4) (#17253) 2026-06-28 14:18:13 -04:00
Jonathan Swoboda 6210dfb4d0 [core] Use single-precision float math to avoid double promotion (#17252) 2026-06-28 14:18:01 -04:00
esphome[bot] 45c712b17b Bump bundled esphome-device-builder to 1.0.21 (#17257)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-06-28 09:41:49 -07:00
8e23065b86 [it8951] Add IT8951 e-paper controller support to epaper_spi (#15346)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Citric Li <37475446+limengdu@users.noreply.github.com>
Co-authored-by: koosoli <koosoli@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 21:14:05 +10:00
Jonathan Swoboda d3892b8399 [platformio] Extract toolchain-agnostic PlatformIO library converter (#17243) 2026-06-28 07:03:09 -04:00
Jonathan Swoboda bda789052d [espnow] Don't throttle ESP-NOW RX when deep_sleep is present (#17240) 2026-06-27 22:17:09 +00:00
Jonathan Swoboda 0fb100f2d1 [core] Suppress unactionable legacy-redaction warning for substitutions (#17242) 2026-06-27 18:05:00 -04:00
esphome[bot] fd7fc6b8e8 Bump bundled esphome-device-builder to 1.0.20 (#17244) 2026-06-27 15:00:23 -07:00
tomaszduda23andJonathan Swoboda 690e8c3fb9 [nrf52] add upload for native build (#17100)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-27 15:50:28 -04:00
ArdumineandJonathan Swoboda a0742a9535 [api] Add nRF52 support (#17226)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-27 14:22:34 -04:00
Jonathan Swoboda ccc57475b7 [deep_sleep] Add ESP32-C5 support (#17237) 2026-06-27 12:04:45 -04:00
Franck NijhofandJonathan Swoboda 24ec65e68e [esp32] Only warn about S3 PSRAM pins (GPIO33-37) in octal mode (#17222)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-27 11:26:47 -04:00
dependabot[bot] 436938b931 Bump actions/cache/restore from 6.0.0 to 6.1.0 (#17231)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-27 10:33:13 -04:00
dependabot[bot] 063c4371de Bump actions/cache from 6.0.0 to 6.1.0 (#17230)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-27 10:33:01 -04:00
dependabot[bot] 7ad4cbf46f Bump actions/cache/save from 6.0.0 to 6.1.0 (#17229)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-27 10:32:50 -04:00
dependabot[bot] 88875daf52 Bump actions/cache/restore from 6.0.0 to 6.1.0 in /.github/actions/restore-python (#17228)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-27 10:32:39 -04:00
Franck NijhofandJonathan Swoboda 7811781a96 [es8388] Fix DAC unable to unmute once muted (#17221)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-27 10:21:36 -04:00
Franck NijhofandJonathan Swoboda da5e11d196 [core] Fix area saved as null in storage.json (#17219)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-27 09:49:56 -04:00
75cdabee3d [socket] Add BSD socket support for nRF52 (#16699)
Co-authored-by: tomaszduda23 <tomaszduda23@gmail.com>
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>
2026-06-26 09:30:07 -04:00
esphome[bot] f9f28a6a00 Bump bundled esphome-device-builder to 1.0.19 (#17217)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-06-26 07:48:52 +02:00
ArdumineandJonathan Swoboda be8523a73c [mdns] Add mDNS to Zephyr and nRF52 (#16924)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-25 16:33:38 -04:00
dependabot[bot] f49bed47de Bump ruff from 0.15.19 to 0.15.20 (#17216)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-25 16:07:55 -04:00
Franck Nijhof 239211e521 [time] Defer aioesphomeapi import to speed up config validation (#17214) 2026-06-25 15:34:44 -04:00
Franck Nijhof cc646b2213 [core] Defer requests import in framework_helpers to speed up config validation (#17215) 2026-06-25 15:34:33 -04:00
dependabot[bot] ddf075a2dd Bump aioesphomeapi from 45.3.1 to 45.5.2 (#17211)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-25 18:00:52 +00:00
esphome[bot] e304c318fb Bump bundled esphome-device-builder to 1.0.18 (#17212)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-06-25 19:47:24 +02:00
Jonathan Swoboda e27390bddb [hbridge] Fix light stuck on one polarity (#17162) 2026-06-25 12:36:10 -04:00
6f36ce6429 [openthread] Provide action to control poll_period when device MTD (#11766)
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: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 12:35:15 -04:00
Jonathan Swoboda 1d5490fd91 [modbus] Only apply turnaround delay after broadcasts (#17209) 2026-06-25 11:38:34 -04:00
Jonathan Swoboda 18c7f60410 [uart] Validate fixed UART settings at config time for fixed-baud components (#17207) 2026-06-25 10:19:05 -04:00
Clyde StubbsandClaude Opus 4.8 4f70f6b2a6 [mipi][mipi_spi] Swap native dimensions for swap_xy hardware transform (#17201)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 08:36:36 -04:00
Jesse Hills 29a6105730 [ms8607] Mark configurable classes as final (#17147) 2026-06-25 08:31:15 -04:00
Jesse Hills 46cf052ec5 [config_validation] Fix multicast typo in error message (#17206) 2026-06-25 08:28:43 -04:00
Jesse Hills e5d8c22b47 Mark configurable classes as final (13/21: pmsa003i-rc522) (#16964) 2026-06-25 13:20:11 +02:00
Jesse Hills 64acb358a5 Mark configurable classes as final (8/21: hm3301-integration) (#16959) 2026-06-25 13:20:00 +02:00
Jesse Hills d511f0614d Mark configurable classes as final (18/21: template-tx20) (#16969) 2026-06-25 13:19:51 +02:00
Jesse Hills eb9ca517e3 Mark configurable classes as final (14/21: rc522_i2c-scd4x) (#16965) 2026-06-25 13:19:39 +02:00
Jesse Hills f769457bb0 Mark configurable classes as final (15/21: script-slow_pwm) (#16966) 2026-06-25 13:19:30 +02:00
Tomasz Witke 0fcf512148 [image] Use LVGL 9 color formats (#16871) 2026-06-25 21:03:50 +10:00
Jesse Hills 8c68e95568 [config_validation] Add tests for 100% validator coverage (#17204) 2026-06-25 22:33:28 +12:00
Fae d8eee03556 [host] Fix handling of directory for preferences (#11160) 2026-06-25 10:20:15 +00:00
Julian Lunz 23933c1b58 [adc] Only call cyw43_thread_enter/exit for VSYS when WiFi is active on RP2040 (#17203) 2026-06-24 23:21:41 -07:00
Jonathan Swoboda 8c9f4fba8f [wifi] Report STA IP, not SoftAP IP, in wifi_info on ESP8266 (#17185) 2026-06-24 22:28:15 -04:00
Jonathan Swoboda 92554f4e67 [network] Set IPv4 type tag on all lwIP platforms, not just esp32 (#17200) 2026-06-24 22:28:06 -04:00
Jonathan Swoboda 1dfafce06a [i2c][spi] Wire ESP32-S31/H4/H21 bus capabilities (#17188) 2026-06-24 21:05:29 -04:00
Jonathan Swoboda abbcfd213f [tinyusb][usb_cdc_acm][usb_host][usb_uart] Support ESP32-S31/H4 (#17190) 2026-06-24 20:51:03 -04:00
Jonathan Swoboda 23aff5202b [wifi][openthread] Wire ESP32-S31/H4/H21 radio support (#17186) 2026-06-24 20:42:41 -04:00
Jonathan Swoboda 91e515ca7c [esp32] Accept '#' as ESP-IDF source ref separator (#17193) 2026-06-24 20:40:28 -04:00
Jonathan Swoboda 538f554bdb [psram] Support ESP32-S31/H4 (#17192) 2026-06-24 20:38:55 -04:00
Jonathan Swoboda e96717f6cd [waveshare_io_ch32v003] Pin i2c_id in test to avoid grouping conflict (#17191) 2026-06-24 20:16:53 -04:00
dependabot[bot] aff5e248ed Bump actions/setup-python from 6.2.0 to 6.3.0 in /.github/actions/restore-python (#17194)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-25 02:05:30 +02:00
dependabot[bot] 155439be74 Bump actions/setup-python from 6.2.0 to 6.3.0 (#17197)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-25 02:05:13 +02:00
dependabot[bot] fa34c67950 Bump CodSpeedHQ/action from 4.17.6 to 4.18.1 (#17198)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-25 02:04:52 +02:00
dependabot[bot] b688474444 Bump ruff from 0.15.18 to 0.15.19 (#17195)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-25 02:04:37 +02:00
esphome[bot] 72b663fc40 Bump bundled esphome-device-builder to 1.0.17 (#17199) 2026-06-25 02:04:22 +02:00
esphome[bot] f471329d60 Bump bundled esphome-device-builder to 1.0.16 (#17182) 2026-06-24 17:15:00 +02:00
Geoffrey Frogeyeandpre-commit-ci-lite[bot] e8acd24fd9 [opentherm] Support power scaling disabled (#17183)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-06-24 09:29:57 -04:00
Clyde Stubbs 18f29f8d2b [mipi_spi] Suppress sequence errors when page selection used (#17176) 2026-06-24 08:05:23 -04:00
Anton Viktorov cbcf23426d [waveshare_io_ch32v003] Waveshare I/O Expander component (#10071) 2026-06-24 20:08:59 +10:00
Jesse Hills e6455c5b44 Mark configurable classes as final (12/21: msa3xx-pm2005) (#16963) 2026-06-23 18:27:07 -05:00
Jesse Hills 2b8916fc4e [ci] Exclude test changes from small-pr/medium-pr size labels (#17172) 2026-06-24 11:13:34 +12:00
esphome[bot] dae078fc56 Bump bundled esphome-device-builder to 1.0.15 (#17170) 2026-06-24 11:06:15 +12:00
Clyde Stubbs 72686bd4af [mipi_spi] Warn on MODE3 default for display without CS pin (#17153) 2026-06-24 08:43:39 +10:00
Jonathan SwobodaandJesse Hills 344da7c4f4 [docker] Move build deps to base image, drop app apt step (#17167)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-06-23 17:35:07 -04:00
Jesse Hills 84de814e6f [config_validation] Make bind_key a sensitive dual-mode validator (#17146) 2026-06-24 09:05:39 +12:00
Jonathan Swoboda 1d32b6c9e0 [espidf] Enable ccache by default for ESP-IDF builds (#17163) 2026-06-23 16:41:13 -04:00
mnewton25andJonathan Swoboda 49536693b7 [esp32] Use POSIX path for secure-boot signing/verification keys Fixes #17164 (#17166)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-23 16:40:49 -04:00
dependabot[bot] a24a63e61b Bump actions/cache from 5.0.5 to 6.0.0 (#17168)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-23 15:03:28 -05:00
dependabot[bot] e3b644c2a0 Bump actions/cache from 5.0.5 to 6.0.0 in /.github/actions/restore-python (#17169)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-23 15:03:16 -05:00
Jonathan Swoboda 7763ce958d [tests] Disable Hypothesis deadline on IP validation property tests (#17138) 2026-06-23 15:21:40 -04:00
Jonathan Swoboda ff001b9e45 [esp32_ble_server] Fix set_value action with by-reference triggers (#17156) 2026-06-23 15:21:26 -04:00
Jonathan Swoboda c2d79c972c [docker] Install ccache in the image (#17157) 2026-06-23 15:04:42 -04:00
Jonathan Swoboda e0377bbbd3 [ci] Enable ccache for component batch builds (~7% faster) (#17136) 2026-06-23 15:04:23 -04:00
Berik Visschers eae65a6b88 [bme680_bsec][bme68x_bsec2][const] Move BME sensor constants to shared component consts (#17160) 2026-06-23 11:44:48 -04:00
Jesse Hills 225d426d95 [core] Use CORE.is_* platform helpers in __main__ (#17144) 2026-06-23 08:40:16 -04:00
Zach Isbach 9614bc20a0 [epaper_spi] Add support for Waveshare 2.13" V4 series B (R/B/W) (#16828) 2026-06-23 11:00:19 +00:00
arunderwood 41747c2de7 [epaper_spi] Add support for the Inkplate 2 (#16856) 2026-06-23 16:50:02 +10:00
Jesse Hills c70d56807f [motion] Make motion test configs mergeable in CI (#17149) 2026-06-23 16:44:58 +12:00
Jesse Hills 69d700727d [docker] Remove dead HA addon env exports (streamer_mode, relative_url) (#17140) 2026-06-23 11:25:24 +12:00
esphome[bot] 5fcf656806 Bump bundled esphome-device-builder to 1.0.14 (#17139) 2026-06-22 17:45:22 -05:00
Jonathan Swoboda 1ace836744 [espidf] Don't fail framework check on broken unrelated PATH tools (#17053) 2026-06-22 18:41:21 -04:00
3a4831bd7e [ble_nus] Atomic log-line framing (no partial ring-buffer writes) (#17105)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: tomaszduda23 <tomaszduda23@gmail.com>
2026-06-22 21:04:11 +00:00
dependabot[bot] 6c1724874b Bump zeroconf from 0.149.16 to 0.150.0 (#17137)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-22 15:04:22 -05:00
Joseph C. LehnerandJonathan Swoboda 2483576909 [sx126x] Add data whitening options (#17102)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-22 10:51:10 -04:00
esphome[bot] 0df1db6205 Bump bundled esphome-device-builder to 1.0.13 (#17132) 2026-06-22 00:01:22 -05:00
J. Nick Koston 614eae7a3b [dashboard_import] Store package_import_url in flash on ESP8266 (#17127) 2026-06-21 23:18:06 -05:00
Jesse Hills 2fe67a6eda [graphical_display_menu] Mark configurable classes as final (#17129) 2026-06-21 23:17:47 -05:00
Jesse Hills e88f69b5f8 Mark configurable classes as final (7/21: gcja5-hlw8032) (#16958) 2026-06-21 21:05:05 -05:00
Jesse Hills c69cfd44be Mark configurable classes as final (5/21) (#16956) 2026-06-21 21:04:55 -05:00
Jesse Hills 9f5ed6fdfd Mark configurable classes as final (6/21) (#16957) 2026-06-21 21:04:45 -05:00
Jesse Hills 0891473280 Mark configurable classes as final (10/21: matrix_keypad-micronova) (#16961) 2026-06-21 21:04:34 -05:00
Jesse Hills 2982d7c834 Mark configurable classes as final (9/21) (#16960) 2026-06-21 21:04:16 -05:00
Jesse Hills 026bac4cd1 [ld2420] Mark configurable classes as final (#17130) 2026-06-22 13:27:56 +12:00
J. Nick Koston 7fcc890e84 [rp2040] Bump arduino-pico framework to 5.6.1 (#17122) 2026-06-22 13:02:46 +12:00
J. Nick Koston 44c54b3a75 [json] Bump ArduinoJson to 7.4.3 (#17126) 2026-06-21 23:09:54 +00:00
Clyde Stubbs faabafad2b [mipi_rgb] Fix offsets for Wave 5 1024x600 (#17057) 2026-06-22 09:54:05 +12:00
Jesse Hills cce7cfff29 Mark configurable classes as final (3/21: ble_scanner-ch423) (#16954) 2026-06-22 09:52:32 +12:00
Kevin AhrendtandJonathan Swoboda 77a91853be [i2s_audio] Narrow wider streams to the speaker's configured bit depth (#16821)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-22 09:52:05 +12:00
Jesse Hills 73dbc8214b Mark configurable classes as final (4/21: chsc6x-dfplayer) (#16955) 2026-06-22 09:51:31 +12:00
Jesse Hills 7d7cdb6c66 Mark configurable classes as final (21/21: zhlt01-zyaura) (#16972) 2026-06-22 09:51:11 +12:00
J. Nick Koston 0d7130c499 [docs] Remove leftover dashboard references after dashboard removal (#17125) 2026-06-22 09:48:21 +12:00
J. Nick Koston 1d5d581734 [esp8266] Drop stale esphome-docker-base reference (#17123) 2026-06-22 09:34:09 +12:00
Jesse Hills d0e3e98d55 [dashboard] Remove legacy web dashboard (#17124) 2026-06-22 09:33:27 +12:00
J. Nick Koston c4abc5476e [core] Remove deprecated std::string scheduler/timer overloads (#17111) 2026-06-21 16:22:08 -05:00
J. Nick Koston 6c10fc1272 [hub75] Remove deprecated scan_wiring name aliases (#17118) 2026-06-21 16:21:50 -05:00
Kevin Ahrendt 036768c399 [audio] Fix mono channel MP3 playback (#17106) 2026-06-21 15:19:13 -05:00
J. Nick Koston 921758f87d [core] Clarify resolve error when a device has no network log/OTA transport (#17107) 2026-06-21 15:00:55 -05:00
J. Nick Koston c6ead57a9e [packages] Remove deprecated single-package include syntax (#17119) 2026-06-22 08:00:46 +12:00
J. Nick Koston 78c6131bbf [web_server] Deprecate version 1 (#17109) 2026-06-21 15:00:36 -05:00
J. Nick Koston d8f883bd9d [core] Remove deprecated get_object_id() and get_compilation_time() (#17112) 2026-06-22 07:54:05 +12:00
J. Nick Koston d1d77fc217 [remote_base] Remove deprecated MideaData::to_string() (#17117) 2026-06-22 07:51:08 +12:00
J. Nick Koston f273221cf4 [core] Remove deprecated value_accuracy_to_string() (#17116) 2026-06-22 07:50:32 +12:00
J. Nick Koston 03121d2efe [core] Remove deprecated std::string GPIOPin::dump_summary() (#17115) 2026-06-22 07:49:27 +12:00
J. Nick Koston 7c2603d9bc [ethernet] Defer clk_mode removal to 2026.9.0 (#17114) 2026-06-22 07:47:15 +12:00
J. Nick Koston 21aee91e67 [web_server] Remove deprecated object ID URL matching (#17113) 2026-06-22 07:45:03 +12:00
J. Nick Koston 1bd937d89c [api] Remove pre-1.14 object_id backward-compat code (#17108) 2026-06-22 07:44:00 +12:00
Bonne Eggleston 63d8a344c5 [modbus] Fix parsing & split out server mode (#11969) 2026-06-21 13:32:35 -05:00
Jonathan Swoboda dbdf125ec8 Merge branch 'release' into dev 2026-06-20 14:18:09 -04:00
Jonathan Swoboda 9ab2a573ab Merge pull request #17093 from esphome/bump-2026.6.2
2026.6.2
2026-06-20 14:17:55 -04:00
Jonathan Swoboda 99d1c4eb69 Bump version to 2026.6.2 2026-06-20 13:33:41 -04:00
esphome[bot] b079be756f Bump bundled esphome-device-builder to 1.0.12 (#17091) 2026-06-20 13:33:41 -04:00
J. Nick Koston 039a1f063e [ha-addon] Expose the device-builder public port only when port 6052 is mapped (#17076) 2026-06-20 13:33:41 -04:00
esphome[bot] 2354165e41 Bump bundled esphome-device-builder to 1.0.11 (#17081) 2026-06-20 13:33:41 -04:00
Jonathan Swoboda f5697b0ae5 [packet_transport] Mark encryption key as cv.sensitive (#17066) 2026-06-20 13:33:41 -04:00
Jonathan Swoboda fe794a26e8 [fastled_base] Fix RMT5 intr_priority conflict (#17072) 2026-06-20 13:33:41 -04:00
Jonathan Swoboda 8d77051b9a [espidf] Resolve IDF tools path to avoid unnormalized path warning (#17055) 2026-06-20 13:33:41 -04:00
esphome[bot] 9609d370c0 Bump bundled esphome-device-builder to 1.0.12 (#17091) 2026-06-20 12:22:19 -05:00
J. Nick KostonandCopilot Autofix powered by AI 59711b8e6a Add THREAT_MODEL.md (#17089)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-20 11:51:42 -05:00
J. Nick Koston d77c0d2bc5 [ha-addon] Expose the device-builder public port only when port 6052 is mapped (#17076) 2026-06-20 11:33:54 -05:00
esphome[bot] 657d9bf4d0 Bump bundled esphome-device-builder to 1.0.11 (#17081) 2026-06-20 00:30:30 -05:00
dependabot[bot] 3fb250133f Bump pytest from 9.1.0 to 9.1.1 (#17069)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-19 23:20:37 -04:00
dependabot[bot] d8bd80ef38 Bump resvg-py from 0.3.2 to 0.3.3 (#17070)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-19 23:20:28 -04:00
dependabot[bot] db6bd36cf9 Bump py7zr from 1.1.0 to 1.1.3 (#17071)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-19 23:20:17 -04:00
Jonathan Swoboda f57d31374e [packet_transport] Mark encryption key as cv.sensitive (#17066) 2026-06-19 23:19:30 -04:00
Jonathan Swoboda 50994704a3 [fastled_base] Fix RMT5 intr_priority conflict (#17072) 2026-06-19 23:19:17 -04:00
Jonathan Swoboda 350e7bb763 [espidf] Resolve IDF tools path to avoid unnormalized path warning (#17055) 2026-06-19 17:17:06 +12:00
J. Nick Koston 4ae6dc355f [select] Remove deprecated state member (#17027) 2026-06-19 17:08:07 +12:00
dependabot[bot] 6a79dfb5c5 Bump ruff from 0.15.17 to 0.15.18 (#17046)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-19 17:07:32 +12:00
Big Mike 1dbd9af617 [sen6x] Remove codeowner (#17056) 2026-06-19 17:04:11 +12:00
Jesse Hills 995eba9178 Merge branch 'release' into dev 2026-06-19 11:35:46 +12:00
Jesse Hills 9534ab2a19 Merge pull request #17052 from esphome/bump-2026.6.1
2026.6.1
2026-06-19 11:35:03 +12:00
Jesse Hills 1b1c8d767d Bump version to 2026.6.1 2026-06-19 10:06:13 +12:00
esphome[bot] e3d68deef9 Bump bundled esphome-device-builder to 1.0.10 (#17051) 2026-06-19 10:06:13 +12:00
J. Nick Koston 20cd6a1771 [logger] Hold recursion guard while draining the task log buffer (#17044) 2026-06-19 10:06:13 +12:00
Jonathan Swoboda d27229a1c7 [esp32] Don't overwrite PlatformIO's factory.bin (#17042) 2026-06-19 10:06:13 +12:00
Jonathan Swoboda 129aebe8f4 [esp32] Support esphome idedata with the native ESP-IDF toolchain (#17040) 2026-06-19 10:06:13 +12:00
Jonathan Swoboda a84ad7b1f8 [uptime] Revert timestamp sensor device_class to timestamp (#17037) 2026-06-19 10:06:13 +12:00
Jonathan Swoboda 86096b96f5 [build] Skip target-platform deps when populating host unit-test config (#17039) 2026-06-19 10:06:13 +12:00
J. Nick KostonandCopilot Autofix powered by AI ac5a28301a [core] Honor transferred address cache in has_resolvable_address (#17025)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-19 10:06:13 +12:00
esphome[bot] a497174da2 Bump bundled esphome-device-builder to 1.0.10 (#17051) 2026-06-19 10:05:20 +12:00
J. Nick Koston b97182d302 [logger] Hold recursion guard while draining the task log buffer (#17044) 2026-06-19 09:16:14 +12:00
Jonathan Swoboda 8e7518fe9d [esp32] Don't overwrite PlatformIO's factory.bin (#17042) 2026-06-19 09:15:38 +12:00
Jonathan Swoboda a0f546e375 [ci] Smoke-test Arduino framework in esp32 PlatformIO job (#17034) 2026-06-18 16:08:22 -04:00
Jonathan Swoboda 53e85e07d4 [esp32] Support esphome idedata with the native ESP-IDF toolchain (#17040) 2026-06-18 15:56:21 -04:00
Jonathan Swoboda f6c78f7415 [uptime] Revert timestamp sensor device_class to timestamp (#17037) 2026-06-18 15:43:17 -04:00
Jonathan Swoboda 19cca9e177 [esp32] Remove framework migration notice (#17023) 2026-06-18 15:41:03 -04:00
Jonathan Swoboda 1a553018bf [build] Skip target-platform deps when populating host unit-test config (#17039) 2026-06-18 15:38:57 -04:00
dependabot[bot] a39505f5ef Bump CodSpeedHQ/action from 4.17.5 to 4.17.6 (#17047)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-18 19:33:01 +00:00
dependabot[bot] 14e89f3dae Bump actions/checkout from 6.0.3 to 7.0.0 (#17049)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-18 19:31:17 +00:00
Kevin AhrendtandJ. Nick Koston bf12af4645 [wifi] Add runtime suppression of post-connect roaming scans (#17012)
Co-authored-by: J. Nick Koston <nick+github@koston.org>
2026-06-18 08:31:49 -05:00
Jonathan SwobodaandJesse Hills 1753ccd811 [ci] Update component-test CI for ESP-IDF default toolchain (#16383)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-06-18 08:57:59 -04:00
J. Nick Koston 69f905f154 [ci] Revert "Bump awalsh128/cache-apt-pkgs-action from 1.6.0 to 1.6.1" (#17028) 2026-06-18 04:18:12 -05:00
Jesse Hills 92028e53b5 Mark configurable classes as final (2/21: as3935_i2c-ble_rssi) (#16953) 2026-06-18 15:35:12 +12:00
Jesse Hills 11deff2bed Mark configurable classes as final (1/21: a01nyub-aqi) (#16952) 2026-06-18 15:35:03 +12:00
Kevin AhrendtandJonathan Swoboda 2b38e4b7e2 [audio] Bump microMP3 to v0.3.0 (#17009)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-18 03:23:18 +00:00
dependabot[bot] c63bed8c21 Bump pytest from 9.0.3 to 9.1.0 (#16981)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-17 23:16:04 -04:00
dependabot[bot] 3b2564bbf3 Bump cryptography from 48.0.1 to 49.0.0 (#16985)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-17 23:15:56 -04:00
dependabot[bot] 26c42af354 Bump awalsh128/cache-apt-pkgs-action from 1.6.0 to 1.6.1 (#16986)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-17 23:15:46 -04:00
dependabot[bot] 9ace0ffb26 Bump pylint from 4.0.5 to 4.0.6 (#16983)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-17 23:15:15 -04:00
d4b6426087 [esp32] Pin Names for Seeed XIAO C3 / C6 / S3 (#17002)
Co-authored-by: Thomas A <1294885+zeroflow@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-17 23:12:22 -04:00
J. Nick KostonandCopilot Autofix powered by AI bd9375117a [core] Honor transferred address cache in has_resolvable_address (#17025)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-17 22:11:24 -05:00
Keith BurzinskiandClaude Opus 4.8 c2784c9fd8 [esp32] Consolidate network/coexistence sdkconfig into a single reconciler (#17008)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 03:09:39 +00:00
Jesse HillsandClaude Opus 4.7 3a1a8a8955 [ci] Fail CI Status job when workflow is cancelled (#17024)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-18 15:02:22 +12:00
Jesse HillsandClaude Opus 4.7 b6763cfaed [ci] Smoke-test docker image by compiling each target toolchain (#16995)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-18 15:02:07 +12:00
f76dfd579c [openthread] Add basic Openthread support to Zephyr/nRF52 platform (#16854)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: tomaszduda23 <tomaszduda23@gmail.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-18 01:58:51 +00:00
rwrozelleandClaude Sonnet 4.6 4b8568e948 [socket] bugfix Set wake-request gate flag on LwIP socket receive event (#17010)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 13:54:29 +12:00
Jonathan Swoboda ac6a0f34ec [esp32] Make ESP-IDF the default toolchain (#16910) 2026-06-18 13:45:30 +12:00
Jesse Hills c214a8ce79 [core] Add generic component alias infrastructure (#16826) 2026-06-18 01:21:00 +00:00
tomaszduda23andJonathan Swoboda e3f164fff2 [nrf52] add support for native builds (#16898)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-17 21:17:07 -04:00
c9095841ae [ufm01] Add UFM-01 ultrasonic flow meter component (#16582)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-17 21:16:28 -04:00
Jonathan Swoboda 7cb6cf2f2a [ci] Replace clang-tidy hash with direct config-file diff check (#17019) 2026-06-17 21:12:39 -04:00
Jesse Hills 34844da668 Merge branch 'release' into dev 2026-06-18 13:00:38 +12:00
Jesse Hills e2157a3d26 Merge pull request #17022 from esphome/bump-2026.6.0
2026.6.0
2026-06-18 12:59:50 +12:00
esphome[bot]andJ. Nick Koston d934fb3910 Bump bundled esphome-device-builder to 1.0.9 (#17021)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-06-18 10:46:22 +12:00
esphome[bot] c4076ec8a9 Bump bundled esphome-device-builder to 1.0.8 (#17020) 2026-06-18 10:46:12 +12:00
esphome[bot] 9ac22f9244 Bump bundled esphome-device-builder to 1.0.7 (#17018) 2026-06-18 10:46:06 +12:00
esphome[bot]andJ. Nick Koston 77a99bceb2 Bump bundled esphome-device-builder to 1.0.9 (#17021)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-06-17 17:38:39 -05:00
esphome[bot] ae7c800de8 Bump bundled esphome-device-builder to 1.0.8 (#17020) 2026-06-17 17:32:37 -05:00
Jesse Hills 9e7b3e0330 Bump version to 2026.6.0 2026-06-18 10:18:37 +12:00
Jesse Hills 084398436d Merge branch 'beta' into dev 2026-06-18 10:08:51 +12:00
Jesse Hills 2abe272867 Merge pull request #17017 from esphome/bump-2026.6.0b4
2026.6.0b4
2026-06-18 10:08:15 +12:00
esphome[bot] 6d9490b5a3 Bump bundled esphome-device-builder to 1.0.7 (#17018) 2026-06-17 15:53:10 -05:00
Jesse Hills db6b9166f4 Bump version to 2026.6.0b4 2026-06-18 08:20:15 +12:00
esphome[bot] 7ab95ddcb1 Bump bundled esphome-device-builder to 1.0.6 (#17016) 2026-06-18 08:20:02 +12:00
esphome[bot] cdd2bfbc60 Bump bundled esphome-device-builder to 1.0.4 (#17013) 2026-06-18 08:19:05 +12:00
esphome[bot] 41f7f8cccb Bump bundled esphome-device-builder to 1.0.3 (#17005) 2026-06-18 08:19:05 +12:00
Jonathan Swoboda 045de436ba [ota] Scale ESP-IDF OTA erase watchdog to image size (#16998) 2026-06-18 08:19:05 +12:00
Jonathan Swoboda 24e276c3f9 [esp32_hosted] Bump esp_hosted to 2.12.9 (#16999) 2026-06-18 08:18:25 +12:00
dependabot[bot] 0f5defa67e Bump tzlocal from 5.3.1 to 5.4.3 (#17015)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-17 14:51:08 -05:00
esphome[bot] 900e0b8566 Bump bundled esphome-device-builder to 1.0.6 (#17016) 2026-06-17 14:50:56 -05:00
esphome[bot] 40d0cbee3f Bump bundled esphome-device-builder to 1.0.5 (#17014) 2026-06-17 14:07:36 -05:00
esphome[bot] 009c6dd995 Bump bundled esphome-device-builder to 1.0.4 (#17013) 2026-06-17 12:38:23 -05:00
esphome[bot] e80461eba9 Bump bundled esphome-device-builder to 1.0.3 (#17005) 2026-06-16 22:28:27 -05:00
Jonathan Swoboda 29e8949e3e [ota] Scale ESP-IDF OTA erase watchdog to image size (#16998) 2026-06-16 13:23:46 -04:00
Jonathan Swoboda ce11d38c9b [esp32_hosted] Bump esp_hosted to 2.12.9 (#16999) 2026-06-16 11:53:11 -04:00
Jesse Hills f62d804a60 Merge branch 'beta' into dev 2026-06-16 23:54:03 +12:00
Jesse Hills 9e768bb510 Merge pull request #16997 from esphome/bump-2026.6.0b3
2026.6.0b3
2026-06-16 23:52:22 +12:00
Jesse Hills 53fd99578a Bump version to 2026.6.0b3 2026-06-16 23:02:55 +12:00
Jesse HillsandJ. Nick Koston 310baab524 [docker] Bundle device-builder 1.0.1, make HA add-on builder-only (#16989)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-06-16 23:02:55 +12:00
Jesse Hills 0422b581cb [core] Stop parent git repos from breaking ESP-IDF/PlatformIO builds (#16994) 2026-06-16 23:02:55 +12:00
Jesse Hills 0ce89c17ab [ci] Push branch-tagged docker images to ghcr.io for local testing (#16992) 2026-06-16 23:02:55 +12:00
Jesse Hills 66be793cd8 [docker] Remove alpine base, build only on debian (#16991) 2026-06-16 23:02:54 +12:00
Jonathan Swoboda 1d38498ca7 [openthread] Fix InstanceLock releasing the lock twice on try_acquire (#16980) 2026-06-16 23:02:54 +12:00
Kevin Ahrendt aef9b5b72f [audio] Bump microMP3 to v0.2.3 (#16977) 2026-06-16 23:02:54 +12:00
J. Nick Koston 9bf35ab8fb [core] Attribute "took a long time" blocking warning to the owning script (#16768) 2026-06-16 23:02:54 +12:00
Clyde Stubbs 33ace9d698 [mipi_dsi] Add SWRESET command to M5Stack Tab5-V2 init sequence (#16975) 2026-06-16 23:02:54 +12:00
Jesse HillsandJ. Nick Koston 32ab3abd7c [psram] Make schema extractable with per-variant options (#16949)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-06-16 23:02:54 +12:00
Jesse HillsandJ. Nick Koston 930cf2b5b9 [docker] Bundle device-builder 1.0.1, make HA add-on builder-only (#16989)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-06-16 22:47:14 +12:00
Jesse Hills d8fa0e4140 [core] Stop parent git repos from breaking ESP-IDF/PlatformIO builds (#16994) 2026-06-16 20:24:26 +12:00
Jesse Hills b09a5f9e43 [ci] Push branch-tagged docker images to ghcr.io for local testing (#16992) 2026-06-16 13:37:31 +12:00
dependabot[bot]andJonathan Swoboda bb6cd97948 Bump clang-tidy from 22.1.0.1 to 22.1.7 (#16984)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-15 21:15:12 -04:00
Jesse Hills 73f839437e [docker] Remove alpine base, build only on debian (#16991) 2026-06-16 13:12:53 +12:00
Jonathan Swoboda a7a407c22c [openthread] Fix InstanceLock releasing the lock twice on try_acquire (#16980) 2026-06-16 09:05:50 +12:00
Kevin Ahrendt 7a2657cea1 [audio] Bump microMP3 to v0.2.3 (#16977) 2026-06-16 08:48:07 +12:00
J. Nick Koston 3420cff316 [core] Attribute "took a long time" blocking warning to the owning script (#16768) 2026-06-16 08:46:33 +12:00
Clyde Stubbs 963465a0a6 [mipi_dsi] Add SWRESET command to M5Stack Tab5-V2 init sequence (#16975) 2026-06-15 08:25:54 -04:00
Jesse HillsandJ. Nick Koston 1ee49720c7 [psram] Make schema extractable with per-variant options (#16949)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-06-15 19:55:21 +12:00
Jesse Hills c1a7a8ff55 Add PEP 572 walrus operator preference to coding conventions (#16951) 2026-06-15 16:01:44 +12:00
Clyde Stubbs f1fd5f2f49 [epaper_spi] Metadata, bug fixes, new model (#16950) 2026-06-15 12:10:58 +10:00
Jesse Hills 8d2c2e6adc Merge branch 'beta' into dev 2026-06-15 12:05:55 +12:00
Jesse Hills 94b248527d Merge pull request #16948 from esphome/bump-2026.6.0b2
2026.6.0b2
2026-06-15 12:05:19 +12:00
Jesse Hills a46aa594b3 Bump version to 2026.6.0b2 2026-06-15 11:04:46 +12:00
Jonathan SwobodaandJesse Hills 99425e3a97 [esp32] Add flash_mode and flash_frequency config options (#16920)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-06-15 11:04:46 +12:00
Jonathan Swoboda f83e3ad6a6 [core] Support platformio_options on the native ESP-IDF toolchain (#16917) 2026-06-15 11:04:46 +12:00
Jonathan Swoboda c768e2eabc [esp32] Fix idedata generation failing on unset ESPHOME_ARDUINO (#16925) 2026-06-15 11:04:46 +12:00
9ffd350095 [mipi_spi] Implement automatic mapping of offsets (#16722)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-15 11:04:46 +12:00
Clyde StubbsandClaude Opus 4.8 26ccaf70db [lvgl] Fix schema extraction (#16895)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 11:04:46 +12:00
Tobiasz Jakubowskiandpre-commit-ci-lite[bot] 20925b3220 [spi] Skip logging on begin_transaction() of an auto-releasing write-only SPI device (#16921)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-06-15 11:04:46 +12:00
J. Nick Koston 83504d2de2 [esp8266] Decode crash handler PC and backtrace in logs (#16911) 2026-06-15 11:04:46 +12:00
Jonathan SwobodaandJesse Hills efebea3296 [esp32] Add flash_mode and flash_frequency config options (#16920)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-06-15 10:56:18 +12:00
Jonathan Swoboda e191fc5d47 [core] Support platformio_options on the native ESP-IDF toolchain (#16917) 2026-06-15 10:56:03 +12:00
Jonathan Swoboda 1e5771a3fa [esp32] Fix idedata generation failing on unset ESPHOME_ARDUINO (#16925) 2026-06-15 09:48:43 +12:00
5b7f8cf90d [mipi_spi] Implement automatic mapping of offsets (#16722)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-15 09:36:38 +12:00
guillempages 35e5c7c7c3 [runtime_image] Improve error logging (#16943) 2026-06-14 07:40:49 +10:00
Clyde StubbsandClaude Opus 4.8 10ce6024bf [lvgl] Fix schema extraction (#16895)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 08:21:38 -04:00
dependabot[bot] bf6c8568d3 Bump CodSpeedHQ/action from 4.17.0 to 4.17.5 (#16919)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-12 14:33:28 -04:00
dependabot[bot] 88084f2ec7 Bump ruff from 0.15.16 to 0.15.17 (#16918)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-12 14:32:51 -04:00
Tobiasz Jakubowskiandpre-commit-ci-lite[bot] 6ef35b6d3d [spi] Skip logging on begin_transaction() of an auto-releasing write-only SPI device (#16921)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-06-11 19:50:51 -04:00
28dd935359 [xpt2046] touchscreen driver enhancement (#16414)
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-11 12:35:44 -04:00
J. Nick Koston 750cf1995b [esp8266] Decode crash handler PC and backtrace in logs (#16911) 2026-06-11 08:47:50 -05:00
Jesse Hills a56b6d8993 Merge branch 'beta' into dev 2026-06-11 16:09:15 +12:00
Jesse Hills acbb662316 Merge pull request #16912 from esphome/bump-2026.6.0b1
2026.6.0b1
2026-06-11 16:06:59 +12:00
Jesse Hills abf6212a5a [tests] Mock target branch in memory-impact exclusion test (#16913) 2026-06-11 14:05:10 +12:00
Jesse Hills 6a527c7efc [tests] Mock target branch in memory-impact exclusion test (#16913) 2026-06-11 14:04:22 +12:00
Jesse Hills 4dbc5ce920 Bump version to 2026.6.0b1 2026-06-11 12:41:19 +12:00
Jesse Hills e0b0c1e8d3 Bump version to 2026.7.0-dev 2026-06-11 12:41:19 +12:00
Keith BurzinskiandClaude Opus 4.8 92c82f3d25 [improv_serial] Report stopped state when Wi-Fi is disabled (#16904)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 10:26:50 +12:00
Kevin AhrendtandCopilot Autofix powered by AI 77009cfafe [resampler] Allow resampler to passthrough bits per sample instead of converting (#16892)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-11 10:21:04 +12:00
dependabot[bot] cd7e54dbf2 Bump cryptography from 48.0.0 to 48.0.1 (#16909)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-10 16:32:17 -04:00
Jonathan Swoboda 29a79b1373 [core] Make set_cpp_standard work on the native IDF toolchain (#16907) 2026-06-11 07:25:03 +12:00
Clyde StubbsandClaude Opus 4.8 dafc3560dd [tests] Isolate ESPHOME_LOG_STATES in main logs-states tests (#16905)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 07:44:58 -04:00
a25ac28ae5 [lsm6ds] Add motion platform for STMicro LSM6DS IMU (#16232)
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: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-06-10 01:22:44 +00:00
Jonathan Swoboda 6809af3de0 [espidf] Warn when the install path is too long for Windows MAX_PATH (#16896) 2026-06-10 13:12:28 +12:00
Jonathan Swoboda e16a877745 [platformio] De-duplicate non-ESP32 lib_deps into common:idf-component-libs (#16893) 2026-06-10 13:11:11 +12:00
Jonathan Swoboda 4963ddcb95 [espidf] Fix idedata generation on Windows (#16894) 2026-06-10 13:09:50 +12:00
Clyde StubbsandJ. Nick Koston 4f62bb7171 [bmi270] Support Bosch BMI270 IMU (#16202)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-06-10 11:04:28 +10:00
eb6d6eac7d [xdb401] XDB401 Pressure Sensor (#15108)
Co-authored-by: Ricky Tsai <ricky@rtnztech.com>
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: Copilot <175728472+Copilot@users.noreply.github.com>
2026-06-09 19:58:02 -04:00
dependabot[bot] 7533835e04 Bump py7zr from 0.22.0 to 1.1.0 (#16901)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-09 16:03:31 -04:00
Oliver Kleinecke 2310b9e3fe [usb_uart] Add Prolific PL2303 USB-serial driver (#16885) 2026-06-10 04:27:37 +10:00
8206df6e4e [dlms_meter] dlms_parser library (#15458)
Co-authored-by: PolarGoose <35307286+PolarGoose@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
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>
2026-06-09 08:57:13 -04:00
5faed9d5f5 [nrf52] native build - download toolchain and sdk in venv (#16388)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <swoboda1337@users.noreply.github.com>
2026-06-09 07:04:51 -04:00
PolarGoose 25d656d468 [dsmr] Update dsmr_parser library to 1.9.0 (#16881) 2026-06-09 07:04:10 -04:00
cdc63f0fed [pcm5122] Add PCM5122 audio DAC component (#15709)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: kbx81 <kbx81x@gmail.com>
2026-06-09 01:33:15 -05:00
Clyde Stubbs ddd21ba442 [mipi_spi] add WAVESHARE-ESP32-S3-TOUCH-AMOLED-2.16 (#16887) 2026-06-09 13:06:13 +10:00
Jonathan Swoboda a32817207c [ade7880] Fix reverse active energy reading from reserved register (#16822) 2026-06-08 20:30:03 -04:00
Jonathan Swoboda 6e01f3fccd [heatpumpir] Bump tonia/HeatpumpIR to 1.0.42 (#16880) 2026-06-08 20:29:35 -04:00
dependabot[bot] e0072ef4c5 Bump tornado from 6.5.6 to 6.5.7 (#16883)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-08 19:22:48 -05:00
dependabot[bot] b21a69f07a Bump codecov/codecov-action from 6.0.1 to 7.0.0 (#16884)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-09 08:08:39 +12:00
J. Nick Koston 36e043debb [tests] Fail component test merge on conflicting duplicate IDs (#16849) 2026-06-08 12:49:25 -05:00
Kevin P. Fleming 54c73bf1bc [ade7880][airthings_wave_base] Remove kpfleming from CODEOWNERS (#16858) 2026-06-08 09:04:09 -04:00
J. Nick Koston cbc3770b11 Include model-driven display schemas in the language schema dump (#16872) 2026-06-07 17:30:43 -05:00
Jonathan Swoboda 64fc09646c [esp32] Fix clang-tidy on ESP-IDF 6 (#16850) 2026-06-06 20:00:42 -04:00
Jonathan Swoboda 8400bab926 [esp32] Make no-default-board variant test explicit about platformio toolchain (#16847) 2026-06-06 19:58:25 -04:00
745db9f705 [motion] Implement hub component for IMUs (#16226)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-06 18:10:08 +10:00
Jonathan Swoboda 6996b7ed1c [ci] Add ESP32 Variants clang-tidy run (S3/P4/C6) (#16825) 2026-06-05 22:03:08 -04:00
Jonathan Swoboda 8aa4157574 [fastled_base] Use FastLED IDF component on ESP32 (#16804) 2026-06-05 21:01:29 -04:00
J. Nick Koston 2a4913713a Revert "[tests] Fail component test merge on conflicting duplicate IDs" (#16848) 2026-06-05 19:37:19 -05:00
J. Nick Koston 8f8a70b2be Exit nginx bypass placeholder cleanly on SIGTERM (#16845) 2026-06-05 17:58:50 -05:00
J. Nick Koston 70d9ab25f3 [tests] Fail component test merge on conflicting duplicate IDs (#16795) 2026-06-05 17:57:42 -05:00
Jonathan Swoboda f18cf954ba [improv_serial] Fix build on ESP32-C5/P4 and simplify variant guards (#16833) 2026-06-05 17:30:26 -05:00
Jonathan Swoboda 85fd83288d [esp32_camera] Bump esp32-camera to 2.1.7 (#16846) 2026-06-05 17:29:33 -05:00
Clyde StubbsandJonathan Swoboda 93334d4e60 [scripts] Fix build_language_schema (#16816)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-05 21:44:31 +00:00
i-am-no-magicandpre-commit-ci-lite[bot] 913b9f5ca4 [tuya] Fixed hysteresis bug for Tuya climate (#16832)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-06-05 17:37:40 -04:00
Kevin Ahrendt b63e327ae3 [audio] Deprecate unused scale_audio_samples helper (#16831) 2026-06-05 17:22:03 -04:00
Jonathan Swoboda 77f644f576 [ci] Share a cached native ESP-IDF install across clang-tidy and build jobs (#16841) 2026-06-05 16:42:51 -04:00
Ross Tyler 4cb6f2c046 [qmp6988] fix publishing bogus zero values on i2c error (#16840) 2026-06-05 14:35:33 -04:00
Ross Tyler 2ab4399ae5 [qmp6988] fix false report of software reset error (#16843) 2026-06-05 14:31:17 -04:00
Jonathan Swoboda aa11ddb333 [zigbee][openthread][esp32_hosted] Fix clang-tidy findings (#16838) 2026-06-05 14:22:55 -04:00
Jonathan Swoboda 2b581ecd3c [esp32] Bump platform to 55.03.39, Arduino to 3.3.9 (#16803) 2026-06-05 14:22:20 -04:00
Jonathan Swoboda 42cf421f5c [usb_uart] Fix clang-tidy findings (#16835) 2026-06-05 12:03:22 -04:00
Jonathan SwobodaandJ. Nick Koston 351b986896 [ci] Make ESP32 IDF the comprehensive clang-tidy pass (#16823)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-06-05 12:01:53 -04:00
Jonathan Swoboda b0e1b94c45 [mipi_dsi][mipi_rgb][st7701s][rpi_dpi_rgb] Fix clang-tidy findings (#16837) 2026-06-05 11:56:48 -04:00
Jonathan Swoboda 80c84d6665 [usb_host][usb_cdc_acm][tinyusb] Fix clang-tidy findings (#16836) 2026-06-05 11:55:39 -04:00
J. Nick Koston 61bb1805b1 [api] Fix nullptr deref when client teardown reenters state dispatch (#16834) 2026-06-05 10:47:32 -05:00
Jesse Hills cbd3aaa1e0 [ci] Add codecov.yml to enforce 100% patch coverage on PRs (#16827) 2026-06-05 19:40:18 +12:00
e209a3fa91 [usb_uart] Add FTDI FT23XX USB UART driver (#14587)
Co-authored-by: Oliver Kleinecke <kleinecke.oliver@googlemail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: clydebarrow <2366188+clydebarrow@users.noreply.github.com>
2026-06-05 13:57:05 +10:00
Jesse Hills d72f119dd2 Merge branch 'release' into dev 2026-06-05 14:31:50 +12:00
Jesse Hills 0cd3734148 Merge pull request #16817 from esphome/bump-2026.5.3
2026.5.3
2026-06-05 14:31:04 +12:00
Jonathan Swoboda ea3ac1ee96 [audio] Bump esp-audio-libs to v3.2.1 (#16818) 2026-06-04 20:02:22 -04:00
Jesse Hills 7f3feec3a3 Bump version to 2026.5.3 2026-06-05 11:11:36 +12:00
Jonathan Swoboda bcf5606b31 [esp32_ble_server] Fix duplicate Device Information Service with string UUIDs (#16784) 2026-06-05 11:11:36 +12:00
Jonathan Swoboda 5662e1b7cd [rp2040] Fix lwipopts template load on Windows extended-length paths (#16783) 2026-06-05 11:11:35 +12:00
Jonathan Swoboda 375ecdfb2c [esp32][core] Restore ESP-IDF version on logs/upload fast path and clean build on framework change (#16770) 2026-06-05 11:11:25 +12:00
Jonathan Swoboda a5b4a7cd51 [remote_base] Fix RC5 decoding at either receive polarity (#16767) 2026-06-05 11:07:33 +12:00
dependabot[bot] 772cae445f Bump github/codeql-action from 4.36.1 to 4.36.2 (#16808)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-04 17:30:29 -05:00
dependabot[bot] ef64d27ed4 Bump ruff from 0.15.15 to 0.15.16 (#16807)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-04 17:30:18 -05:00
Jesse Hills a8032054ea [light] Pass light reference into lambda light effect (#16815) 2026-06-05 10:28:50 +12:00
J. Nick Koston 9fbd4c38ae [i2s_audio] Move test bus into a shared package and give fixtures unique ids (#16793) 2026-06-04 17:28:32 -05:00
Jonathan Swoboda 82efa45187 [multiple] Avoid float-to-double promotion in math calls (#16812) 2026-06-04 18:16:18 -04:00
Jonathan Swoboda d2c388f893 [ota][logger][esp32][internal_temperature] Fix clang-tidy findings surfaced by RISC-V analysis (#16811) 2026-06-04 18:01:00 -04:00
Jonathan Swoboda 5288767abf [clang-tidy] Add --exclude-grep to skip files by content (#16813) 2026-06-04 17:58:22 -04:00
Jonathan Swoboda e2459a3923 [clang-tidy] Support RISC-V targets natively (#16809) 2026-06-04 17:57:56 -04:00
Kevin Ahrendt 419bde18b0 [audio] Bump esp-audio-libs to v3.2.0 (#16806) 2026-06-04 16:24:47 -04:00
Jonathan Swoboda 148a5ba68e [esp32] Run clang-tidy via the native ESP-IDF toolchain (#16748) 2026-06-04 11:47:42 -04:00
J. Nick Koston c765e22622 [ci] Exclude device-builder slow e2e tests from downstream CI (#16801) 2026-06-04 10:39:54 -05:00
Clyde Stubbs 1734dc85d2 [const][animation][dfplayer] Extract CONF_LOOP to const (#16797) 2026-06-04 07:42:01 -04:00
Jonathan Swoboda 891ec33c94 [esp32] Deduplicate PlatformIO library conversion by resolving the batch together (#16756) 2026-06-04 07:39:17 -04:00
ffaa31febc [clang-tidy] Hash idf_component.yml and trigger hash hook on more inputs (#16753)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-06-03 23:48:34 -04:00
Jonathan Swoboda 53d685f242 [mixer] Give mixer test its own speaker id to avoid CI grouping collision (#16792) 2026-06-03 23:37:29 -04:00
J. Nick Koston 3e562b9267 [ci] Fix memory impact build selecting unbuildable platform (#16788) 2026-06-03 22:30:36 -05:00
dependabot[bot] d47f6b896e Bump astral-sh/setup-uv from 8.1.0 to 8.2.0 in /.github/actions/restore-python (#16790)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-03 22:06:59 -05:00
dependabot[bot] a02b9c3796 Bump astral-sh/setup-uv from 8.1.0 to 8.2.0 (#16791)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-03 22:06:45 -05:00
Jesse Hills 93f25258ee [config] Add --no-defaults flag to config command (#16718) 2026-06-04 14:08:36 +12:00
Jonathan Swoboda 0d7d091e71 [esp32_ble_server] Fix duplicate Device Information Service with string UUIDs (#16784) 2026-06-04 09:46:17 +12:00
Jonathan Swoboda 0fcfd1e3d6 [rp2040] Fix lwipopts template load on Windows extended-length paths (#16783) 2026-06-04 09:46:08 +12:00
Jonathan Swoboda 74a1ff9fc7 [esp32][core] Restore ESP-IDF version on logs/upload fast path and clean build on framework change (#16770) 2026-06-04 09:46:01 +12:00
Jonathan Swoboda 78d8a93fff [remote_base] Fix RC5 decoding at either receive polarity (#16767) 2026-06-04 09:45:56 +12:00
92819d8658 [logger] Fix USB JTAG VFS symbols linked when logging is disabled (#15721)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-03 16:54:34 -04:00
Clyde Stubbs 7b8cbe2de1 [sdl] Add option to choose display screen (#16363) 2026-06-03 14:18:16 -04:00
Leonardo Rivera 3b0f669f47 [gree] Fix HEAT_COOL advertised when supports_heat is false; restrict YAN swing to vertical (#16199) 2026-06-03 13:38:00 -04:00
dependabot[bot] 87735d71a0 Bump actions/checkout from 6.0.2 to 6.0.3 (#16776)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-03 11:46:22 -04:00
dependabot[bot] eba70dc193 Bump github/codeql-action from 4.36.0 to 4.36.1 (#16775)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-03 11:46:07 -04:00
dependabot[bot] 712ef2ec0e Bump esptool from 5.2.0 to 5.3.0 (#16774)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-03 11:45:52 -04:00
Clyde Stubbs 2009f6cc5f [lvgl] Fix indicator updates (#16780) 2026-06-03 11:43:48 -04:00
PolarGoose 89ddd34cb9 [dmsr] [breaking] Fix decryption that uses custom auth key. Add CRC to telegram sensor. Automatic hex string detection in equipment_id fields. Support EON Hungary smart meters (#16561) 2026-06-03 10:55:51 -04:00
Jonathan Swoboda e4980713d1 [core] esphome clean wipes the whole build directory (#16772) 2026-06-03 07:35:23 -04:00
Clyde Stubbs 997ab11687 [lvgl][mipi_spi][mipi_rgb][mipi_dsi][display] Metadata (#16702) 2026-06-03 15:21:33 +10:00
Jesse HillsandJonathan Swoboda 792e1ff304 [i2c] Add basic host platform support (#14489)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-03 07:12:50 +12:00
4447 changed files with 191116 additions and 51131 deletions

No files matched your search

-1
View File
@@ -1 +0,0 @@
27aaab4e0ebfc10491720345aa746fc2dffa6a3985f73ec111b12dd99078d46f
+16
View File
@@ -0,0 +1,16 @@
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "d=\"${CLAUDE_PROJECT_DIR:-.}\"; [ -x \"$d/venv/bin/python\" ] || { mkdir -p \"$d/.temp\"; env -u VIRTUAL_ENV \"$d/script/setup\" >\"$d/.temp/setup.log\" 2>&1 || echo '{\"systemMessage\":\"script/setup failed; see .temp/setup.log\"}'; }",
"statusMessage": "Setting up dev environment (script/setup)...",
"timeout": 900
}
]
}
]
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
ARG BUILD_BASE_VERSION=2025.04.0
ARG BUILD_BASE_VERSION=2026.06.1
FROM ghcr.io/esphome/docker-base:debian-${BUILD_BASE_VERSION} AS base
+5 -2
View File
@@ -15,7 +15,6 @@
// uncomment and edit the path in order to pass through local USB serial to the container
// , "--device=/dev/ttyACM0"
],
"appPort": 6052,
// if you are using avahi in the host device, uncomment these to allow the
// devcontainer to find devices via mdns
//"mounts": [
@@ -41,7 +40,11 @@
],
"settings": {
"python.languageServer": "Pylance",
"python.pythonPath": "/usr/bin/python3",
// Use the container's pre-provisioned venv (built by the Dockerfile, outside the
// bind-mounted workspace) rather than a ./venv that may leak in from the host and
// mismatch the container's Python. See .devcontainer/Dockerfile (esphome-venv).
"python.defaultInterpreterPath": "/home/esphome/.local/esphome-venv/bin/python",
"python.terminal.activateEnvironment": true,
"pylint.args": [
"--rcfile=${workspaceFolder}/pyproject.toml"
],
+2
View File
@@ -1,3 +1,5 @@
# Normalize line endings to LF in the repository
* text eol=lf
*.png binary
*.gif binary
*.apng binary
+1 -1
View File
@@ -8,7 +8,7 @@ contact_links:
url: https://github.com/esphome/esphome-webserver/issues/new/choose
about: Report an issue with the ESPHome web server.
- name: Report an issue with the ESPHome Builder / Dashboard
url: https://github.com/esphome/dashboard/issues/new/choose
url: https://github.com/esphome/device-builder/issues/new/choose
about: Report an issue with the ESPHome Builder / Dashboard.
- name: Report an issue with the ESPHome API client
url: https://github.com/esphome/aioesphomeapi/issues/new/choose
+5
View File
@@ -6,6 +6,7 @@
- [ ] Bugfix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] New developer-facing feature (adds functionality for component developers; no end-user configuration change)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) — [policy](https://developers.esphome.io/contributing/code/#what-constitutes-a-c-breaking-change)
- [ ] Developer breaking change (an API change that could break external components) — [policy](https://developers.esphome.io/contributing/code/#what-is-considered-public-c-api)
- [ ] Undocumented C++ API change (removal or change of undocumented public methods that lambda users may depend on) — [policy](https://developers.esphome.io/contributing/code/#c-user-expectations)
@@ -20,6 +21,10 @@
- esphome/esphome.io#<esphome.io PR number goes here>
**Pull request in [developers.esphome.io](https://github.com/esphome/developers.esphome.io) with developer documentation (if applicable):**
- esphome/developers.esphome.io#<developers.esphome.io PR number goes here>
## Test Environment
- [ ] ESP32
+2 -9
View File
@@ -15,11 +15,6 @@ inputs:
description: "Version to build"
required: true
example: "2023.12.0"
base_os:
description: "Base OS to use"
required: false
default: "debian"
example: "debian"
runs:
using: "composite"
steps:
@@ -47,7 +42,7 @@ runs:
- name: Build and push to ghcr by digest
id: build-ghcr
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
env:
DOCKER_BUILD_SUMMARY: false
DOCKER_BUILD_RECORD_UPLOAD: false
@@ -60,7 +55,6 @@ runs:
build-args: |
BUILD_TYPE=${{ inputs.build_type }}
BUILD_VERSION=${{ inputs.version }}
BUILD_OS=${{ inputs.base_os }}
outputs: |
type=image,name=ghcr.io/${{ steps.tags.outputs.image_name }},push-by-digest=true,name-canonical=true,push=true
@@ -73,7 +67,7 @@ runs:
- name: Build and push to dockerhub by digest
id: build-dockerhub
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
env:
DOCKER_BUILD_SUMMARY: false
DOCKER_BUILD_RECORD_UPLOAD: false
@@ -86,7 +80,6 @@ runs:
build-args: |
BUILD_TYPE=${{ inputs.build_type }}
BUILD_VERSION=${{ inputs.version }}
BUILD_OS=${{ inputs.base_os }}
outputs: |
type=image,name=docker.io/${{ steps.tags.outputs.image_name }},push-by-digest=true,name-canonical=true,push=true
@@ -0,0 +1,50 @@
name: Cache clang-tidy idedata
description: >
Cache the clang-tidy idedata and the headers it references under .temp
(headers only, about 30MB per env). Run after restore-python and cache-esp-idf.
inputs:
environment:
description: 'clang-tidy environment (e.g. esp32-idf-tidy).'
required: true
runs:
using: composite
steps:
- name: Compute cache key
id: key
shell: bash
run: |
. venv/bin/activate
[ -n "${{ inputs.environment }}" ] || { echo "::error::cache-clang-tidy-idedata: 'environment' input is empty"; exit 1; }
hash=$(python -c 'import sys; sys.path.insert(0, "script"); from clang_tidy_hash import idedata_cache_hash; print(idedata_cache_hash("${{ inputs.environment }}"))')
pyver=$(python -c 'import platform; print(platform.python_version())')
# Generating idedata is what installs ESP-IDF; never skip it over a missing
# install. This also skips the save, so a dev run that installs ESP-IDF
# warms the idedata cache on the next run.
if [ -d ~/.esphome-idf/frameworks ]; then
echo "skip=false" >> "$GITHUB_OUTPUT"
else
echo "ESP-IDF install missing, not using the clang-tidy idedata cache"
echo "skip=true" >> "$GITHUB_OUTPUT"
fi
echo "key=${{ runner.os }}-tidy-idedata-${{ inputs.environment }}-$hash-py$pyver" >> "$GITHUB_OUTPUT"
{
echo "path<<EOF"
printf '%s\n' '.temp/idedata-*.json' '.temp/idedata-*.hash'
printf '.temp/**/*.%s\n' h hpp hh hxx inc inl ipp tpp
echo "EOF"
} >> "$GITHUB_OUTPUT"
# Mirror cache-esp-idf: write on dev, restore-only on PRs. The post-step
# save only runs when the job succeeded, so a failed generation is never saved.
# Extend the extension list if a component ships extensionless headers.
- name: Cache clang-tidy idedata (write on dev)
if: (github.ref == 'refs/heads/dev' || contains(github.event.pull_request.labels.*.name, 'ci-cache-write')) && steps.key.outputs.skip != 'true'
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ steps.key.outputs.path }}
key: ${{ steps.key.outputs.key }}
- name: Cache clang-tidy idedata (restore-only off dev)
if: github.ref != 'refs/heads/dev' && !contains(github.event.pull_request.labels.*.name, 'ci-cache-write') && steps.key.outputs.skip != 'true'
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ steps.key.outputs.path }}
key: ${{ steps.key.outputs.key }}
+70
View File
@@ -0,0 +1,70 @@
name: Cache ESP-IDF
description: >
Resolve the pinned ESP-IDF version and cache the native ESP-IDF install
(toolchains + source) at ~/.esphome-idf. Every job that installs ESP-IDF
natively (clang-tidy for IDF/Arduino and the component test batches) shares
one cache, since the install is identical: ESPHOME_IDF_DEFAULT_TARGETS
defaults to "all", and _get_configured_targets() in espidf/toolchain.py
skips per-variant narrowing whenever CI is set, so all toolchains are
present regardless of the chip a job builds.
Callers must set env ESPHOME_ESP_IDF_PREFIX: ~/.esphome-idf and have the
Python venv already restored.
inputs:
framework:
description: 'Which pinned IDF version to key on: "espidf" (recommended) or "arduino".'
default: espidf
restore-only:
description: >
When "true", only restore -- never save the cache, even on dev. Use from
jobs that may not produce an ESP-IDF install (e.g. a component batch with
no esp32 target), so a partial/empty install is never written to the key.
default: "false"
runs:
using: composite
steps:
- name: Resolve ESP-IDF version for cache key
# The native-IDF version is pinned in code, not in any file that feeds the
# other cache keys, so resolve it explicitly. Keying on it means the cache
# invalidates on a version bump (actions/cache never overwrites a key).
# Also key on the Python version: the cached IDF venv links to the
# runner's toolcache interpreter and is reinstalled every run after a
# runner image bump.
id: version
shell: bash
run: |
. venv/bin/activate
if [ "${{ inputs.framework }}" = "arduino" ]; then
version=$(python -c 'from esphome.components.esp32 import ARDUINO_FRAMEWORK_VERSION_LOOKUP as A, ARDUINO_IDF_VERSION_LOOKUP as L; print(L[A["recommended"]])')
else
version=$(python -c 'from esphome.components.esp32 import ESP_IDF_FRAMEWORK_VERSION_LOOKUP as L; print(L["recommended"])')
fi
echo "version=$version" >> "$GITHUB_OUTPUT"
echo "python-version=$(python -c 'import platform; print(platform.python_version())')" >> "$GITHUB_OUTPUT"
# Mirror the adjacent PlatformIO cache: only dev-branch runs write the
# shared cache (so it lives in the default-branch scope readable by all
# PRs), and PRs are restore-only -- they never push multi-GB artifacts into
# their own scope / the repo quota (e.g. on a version-bump PR). The
# ci-cache-write label lets a PR write into its own scope to test the hit path;
# that costs about 1GB of the repo cache quota per run, so remove it when done.
# -slim: bump when prune-esp-idf changes what it removes; a key is never overwritten.
- name: Cache ESP-IDF install (write on dev)
if: (github.ref == 'refs/heads/dev' || contains(github.event.pull_request.labels.*.name, 'ci-cache-write')) && inputs.restore-only != 'true'
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.esphome-idf
key: ${{ runner.os }}-esphome-idf-${{ steps.version.outputs.version }}-py${{ steps.version.outputs.python-version }}-slim
- name: Cache ESP-IDF install (restore-only off dev)
if: github.ref != 'refs/heads/dev' && !contains(github.event.pull_request.labels.*.name, 'ci-cache-write') || inputs.restore-only == 'true'
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.esphome-idf
key: ${{ runner.os }}-esphome-idf-${{ steps.version.outputs.version }}-py${{ steps.version.outputs.python-version }}-slim
# Install explicitly so the prune below sees the toolchains on a cache miss
# too, instead of the install happening inside the first build step.
- name: Install ESP-IDF
shell: bash
run: |
. venv/bin/activate
python -c 'from esphome.espidf.framework import check_esp_idf_install; check_esp_idf_install("${{ steps.version.outputs.version }}")'
- name: Prune ESP-IDF install
uses: ./.github/actions/prune-esp-idf
+49
View File
@@ -0,0 +1,49 @@
name: Cache nRF Connect SDK
description: >
Resolve the pinned sdk-nrf version and cache the native sdk-nrf install
(west workspace, Zephyr SDK toolchain, python env) at ~/.esphome-sdk-nrf.
Every job that installs sdk-nrf natively (the nrf52 clang-tidy job and,
once the component tests build natively, their batches) shares one cache.
Callers must set env ESPHOME_SDK_NRF_PREFIX: ~/.esphome-sdk-nrf and have
the Python venv already restored.
inputs:
restore-only:
description: >
When "true", only restore -- never save the cache, even on dev. Use from
jobs that may not produce a complete install (e.g. a component batch
that fails mid-install), so a partial install is never written.
default: "false"
runs:
using: composite
steps:
- name: Resolve sdk-nrf and toolchain versions for cache key
# Both versions are pinned in code, not in any file that feeds the
# other cache keys, so resolve them explicitly. Keying on them means
# the cache invalidates when either is bumped (actions/cache never
# overwrites a key).
id: version
shell: bash
run: |
. venv/bin/activate
version=$(python -c '
from esphome.components.nrf52 import RECOMMENDED_SDK_NRF_VERSION
from esphome.components.nrf52.framework import TOOLCHAIN_VERSION
print(f"{RECOMMENDED_SDK_NRF_VERSION}-{TOOLCHAIN_VERSION}")')
echo "version=$version" >> "$GITHUB_OUTPUT"
# Mirror cache-esp-idf: only dev-branch runs write the shared cache (so it
# lives in the default-branch scope readable by all PRs); PRs are
# restore-only and never push multi-GB artifacts into their own scope.
- name: Cache nRF Connect SDK install (write on dev)
if: github.ref == 'refs/heads/dev' && inputs.restore-only != 'true'
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/.esphome-sdk-nrf
# yamllint disable-line rule:line-length
key: ${{ runner.os }}-esphome-sdk-nrf-${{ steps.version.outputs.version }}-${{ hashFiles('esphome/components/nrf52/requirements.txt') }}
- name: Cache nRF Connect SDK install (restore-only off dev)
if: github.ref != 'refs/heads/dev' || inputs.restore-only == 'true'
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/.esphome-sdk-nrf
# yamllint disable-line rule:line-length
key: ${{ runner.os }}-esphome-sdk-nrf-${{ steps.version.outputs.version }}-${{ hashFiles('esphome/components/nrf52/requirements.txt') }}
+34
View File
@@ -0,0 +1,34 @@
name: Prune ESP-IDF install
description: >
Remove the picolibc sysroots (1.1GB of the 3.9GB install) from the native
ESP-IDF toolchains; IDF 5.x links newlib. Skipped when an IDF 6 install is
present, which links picolibc (see esp32/__init__.py).
runs:
using: composite
steps:
- name: Prune picolibc
shell: bash
run: |
shopt -s nullglob
prefix="${ESPHOME_ESP_IDF_PREFIX:-$HOME/.esphome-idf}"
prefix="${prefix/#\~/$HOME}"
for fw in "$prefix"/frameworks/*/; do
case "$(basename "$fw")" in
[6-9].*) echo "IDF $(basename "$fw") installed, keeping picolibc"; exit 0 ;;
esac
done
n=0
for dir in "$prefix"/tools/*-esp-elf/*/*-esp-elf/picolibc; do
echo "Removing $dir ($(du -sh "$dir" | cut -f1))"
rm -rf "$dir"
n=$((n + 1))
done
# The marker rides along in the cache entry so a restored slim tree stays quiet.
if [ "$n" -gt 0 ]; then
touch "$prefix/.picolibc-pruned"
elif [ -d "$prefix/tools" ] && [ ! -f "$prefix/.picolibc-pruned" ]; then
echo "::warning::no picolibc sysroots matched under $prefix/tools"
fi
if [ -d "$prefix" ]; then
du -sh "$prefix"
fi
+8 -5
View File
@@ -17,12 +17,12 @@ runs:
steps:
- name: Set up Python ${{ inputs.python-version }}
id: python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: ${{ inputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: venv
# yamllint disable-line rule:line-length
@@ -32,9 +32,12 @@ runs:
# detects the activated venv via ``VIRTUAL_ENV`` so the venv layout
# downstream jobs rely on is preserved.
if: steps.cache-venv.outputs.cache-hit != 'true'
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
enable-cache: true
# Pull request saves land in per-PR scopes nothing else can
# reuse; dev pushes seed the shared copy instead.
save-cache: ${{ github.event_name != 'pull_request' }}
# Pin uv version so the action does not have to fetch the
# manifest from raw.githubusercontent.com on every cache
# miss; that fetch flakes on Windows runners.
@@ -46,7 +49,7 @@ runs:
python -m venv venv
source venv/bin/activate
python --version
uv pip install -r requirements.txt -r requirements_test.txt
uv pip install -r requirements.txt -r requirements_dev.txt -r requirements_test.txt
uv pip install -e .
- name: Create Python virtual environment
if: steps.cache-venv.outputs.cache-hit != 'true' && runner.os == 'Windows'
@@ -55,5 +58,5 @@ runs:
python -m venv venv
source ./venv/Scripts/activate
python --version
uv pip install -r requirements.txt -r requirements_test.txt
uv pip install -r requirements.txt -r requirements_dev.txt -r requirements_test.txt
uv pip install -e .
@@ -13,6 +13,7 @@ module.exports = {
'merging-to-release',
'merging-to-beta',
'chained-pr',
'stacked-pr',
'core',
'small-pr',
'medium-pr',
@@ -22,11 +23,13 @@ module.exports = {
'has-tests',
'needs-tests',
'needs-docs',
'needs-developer-docs',
'needs-codeowners',
'too-big',
'labeller-recheck',
'bugfix',
'new-feature',
'new-feature-developer',
'breaking-change',
'developer-breaking-change',
'undocumented-api-change',
@@ -40,5 +43,17 @@ module.exports = {
// Keep matching the old esphome-docs name during the transition period
/https:\/\/github\.com\/esphome\/esphome-docs\/pull\/\d+/,
/esphome\/esphome-docs#\d+/
],
DEVELOPER_DOCS_PR_PATTERNS: [
/https:\/\/github\.com\/esphome\/developers\.esphome\.io\/pull\/\d+/,
/esphome\/developers\.esphome\.io#\d+/
],
// Files whose developer-facing changes are documented via Python docstrings
// only - developers.esphome.io has no reference page for them yet, so PRs
// touching nothing but these files (and tests/) skip needs-developer-docs.
DEV_DOCS_EXEMPT_FILES: [
'esphome/config_validation.py'
]
};
+81 -17
View File
@@ -1,4 +1,4 @@
const { DOCS_PR_PATTERNS } = require('./constants');
const { DOCS_PR_PATTERNS, DEVELOPER_DOCS_PR_PATTERNS, DEV_DOCS_EXEMPT_FILES } = require('./constants');
const {
COMPONENT_REGEX,
detectComponents,
@@ -33,16 +33,54 @@ async function fetchPrFileContent(github, context, path) {
}
}
// Check whether a pull request is part of a GitHub stack.
//
// GitHub's stacked pull request feature adds a `stack` object to the pull
// request resource. It is present on every pull request in the stack -
// including the bottom one, whose base is already `dev` - and is absent
// entirely on standalone pull requests.
//
// The `pull_request_target` webhook payload is not guaranteed to carry this
// field, so fall back to asking the API when it is missing. Guessing wrong
// here is costly: a stacked pull request mistaken for a manually chained one
// gets a label that blocks merging.
async function isStackedPr(github, context) {
const pr = context.payload.pull_request;
if (pr.stack != null) {
return true;
}
try {
const { owner, repo } = context.repo;
const { data } = await github.rest.pulls.get({
owner,
repo,
pull_number: pr.number,
});
return data.stack != null;
} catch (error) {
// Treat an API failure as "not stacked" so a chained pull request still
// gets its blocking label rather than silently slipping through.
console.log('Failed to check stack membership:', error.message);
return false;
}
}
// Strategy: Merge branch detection
async function detectMergeBranch(context) {
async function detectMergeBranch(github, context) {
const labels = new Set();
const baseRef = context.payload.pull_request.base.ref;
const defaultBranch = context.payload.repository.default_branch;
if (baseRef === 'release') {
labels.add('merging-to-release');
} else if (baseRef === 'beta') {
labels.add('merging-to-beta');
} else if (baseRef !== 'dev') {
} else if (await isStackedPr(github, context)) {
// GitHub manages the merge order for a stack, so these are not blocked.
labels.add('stacked-pr');
} else if (baseRef !== defaultBranch) {
// A chain built by hand: it must not merge until its base branch does.
labels.add('chained-pr');
}
@@ -147,19 +185,9 @@ async function detectCoreChanges(changedFiles) {
}
// Strategy: PR size detection
async function detectPRSize(prFiles, totalAdditions, totalDeletions, totalChanges, isMegaPR, SMALL_PR_THRESHOLD, MEDIUM_PR_THRESHOLD, TOO_BIG_THRESHOLD) {
async function detectPRSize(prFiles, totalAdditions, totalDeletions, isMegaPR, SMALL_PR_THRESHOLD, MEDIUM_PR_THRESHOLD, TOO_BIG_THRESHOLD) {
const labels = new Set();
if (totalChanges <= SMALL_PR_THRESHOLD) {
labels.add('small-pr');
return labels;
}
if (totalChanges <= MEDIUM_PR_THRESHOLD) {
labels.add('medium-pr');
return labels;
}
const testAdditions = prFiles
.filter(file => file.filename.startsWith('tests/'))
.reduce((sum, file) => sum + (file.additions || 0), 0);
@@ -167,7 +195,24 @@ async function detectPRSize(prFiles, totalAdditions, totalDeletions, totalChange
.filter(file => file.filename.startsWith('tests/'))
.reduce((sum, file) => sum + (file.deletions || 0), 0);
const nonTestChanges = (totalAdditions - testAdditions) - (totalDeletions - testDeletions);
const nonTestAdditions = totalAdditions - testAdditions;
const nonTestDeletions = totalDeletions - testDeletions;
// small/medium count churn (additions + deletions) so a balanced refactor isn't undersized.
const nonTestChurn = nonTestAdditions + nonTestDeletions;
if (nonTestChurn <= SMALL_PR_THRESHOLD) {
labels.add('small-pr');
return labels;
}
if (nonTestChurn <= MEDIUM_PR_THRESHOLD) {
labels.add('medium-pr');
return labels;
}
// too-big uses net line delta (additions - deletions), matching the review message in reviews.js.
const nonTestChanges = nonTestAdditions - nonTestDeletions;
// Don't add too-big if mega-pr label is already present
if (nonTestChanges > TOO_BIG_THRESHOLD && !isMegaPR) {
@@ -238,6 +283,7 @@ async function detectPRTemplateCheckboxes(context) {
const checkboxPatterns = [
{ pattern: /- \[x\] Bugfix \(non-breaking change which fixes an issue\)/i, label: 'bugfix' },
{ pattern: /- \[x\] New feature \(non-breaking change which adds functionality\)/i, label: 'new-feature' },
{ pattern: /- \[x\] New developer-facing feature \(adds functionality for component developers; no end-user configuration change\)/i, label: 'new-feature-developer' },
{ pattern: /- \[x\] Breaking change \(fix or feature that would cause existing functionality to not work as expected\)/i, label: 'breaking-change' },
{ pattern: /- \[x\] Developer breaking change \(an API change that could break external components\)/i, label: 'developer-breaking-change' },
{ pattern: /- \[x\] Undocumented C\+\+ API change \(removal or change of undocumented public methods that lambda users may depend on\)/i, label: 'undocumented-api-change' },
@@ -348,12 +394,14 @@ async function detectRequirements(allLabels, prFiles, context, hasYamlLoadable)
const labels = new Set();
// Check for missing tests
if ((allLabels.has('new-component') || allLabels.has('new-platform') || allLabels.has('new-feature')) && !allLabels.has('has-tests')) {
if ((allLabels.has('new-component') || allLabels.has('new-platform') || allLabels.has('new-feature') || allLabels.has('new-feature-developer')) && !allLabels.has('has-tests')) {
labels.add('needs-tests');
}
// Check for missing docs.
// `new-feature` (PR-body checkbox) always counts. `new-component` / `new-platform`
// `new-feature` (PR-body checkbox) always counts. `new-feature-developer` is
// deliberately excluded here: its docs live on developers.esphome.io and are
// checked separately below. `new-component` / `new-platform`
// only count when at least one newly added file defines a top-level CONFIG_SCHEMA,
// i.e. the new component/platform is actually loadable from YAML.
const docsEligible =
@@ -369,6 +417,22 @@ async function detectRequirements(allLabels, prFiles, context, hasYamlLoadable)
}
}
// Check for missing developer docs. `new-feature-developer` requires a
// developers.esphome.io PR link, unless every changed file outside tests/ is
// in DEV_DOCS_EXEMPT_FILES (core validators documented via docstrings only).
if (allLabels.has('new-feature-developer')) {
const prBody = context.payload.pull_request.body || '';
const nonTestFiles = prFiles
.map(file => file.filename)
.filter(file => !file.startsWith('tests/'));
const onlyExemptFiles = nonTestFiles.every(file => DEV_DOCS_EXEMPT_FILES.includes(file));
const hasDevDocsLink = DEVELOPER_DOCS_PR_PATTERNS.some(pattern => pattern.test(prBody));
if (!onlyExemptFiles && !hasDevDocsLink) {
labels.add('needs-developer-docs');
}
}
// Check for missing CODEOWNERS
if (allLabels.has('new-component')) {
const codeownersModified = prFiles.some(file =>
+3 -3
View File
@@ -88,7 +88,7 @@ module.exports = async ({ github, context }) => {
// Early exit for release and beta branches only
if (baseRef === 'release' || baseRef === 'beta') {
const branchLabels = await detectMergeBranch(context);
const branchLabels = await detectMergeBranch(github, context);
const finalLabels = Array.from(branchLabels);
console.log('Computed labels (merge branch only):', finalLabels.join(', '));
@@ -118,12 +118,12 @@ module.exports = async ({ github, context }) => {
deprecatedResult,
maintainerAccess
] = await Promise.all([
detectMergeBranch(context),
detectMergeBranch(github, context),
detectComponentPlatforms(changedFiles, apiData),
detectNewComponents(github, context, prFiles),
detectNewPlatforms(github, context, prFiles, apiData),
detectCoreChanges(changedFiles),
detectPRSize(prFiles, totalAdditions, totalDeletions, totalChanges, isMegaPR, SMALL_PR_THRESHOLD, MEDIUM_PR_THRESHOLD, TOO_BIG_THRESHOLD),
detectPRSize(prFiles, totalAdditions, totalDeletions, isMegaPR, SMALL_PR_THRESHOLD, MEDIUM_PR_THRESHOLD, TOO_BIG_THRESHOLD),
detectDashboardChanges(changedFiles),
detectGitHubActionsChanges(changedFiles),
detectCodeOwner(github, context, changedFiles),
@@ -1,6 +1,14 @@
const { describe, it } = require('node:test');
const assert = require('node:assert/strict');
const { detectNewPlatforms, detectNewComponents } = require('../detectors');
const {
detectMergeBranch,
detectNewPlatforms,
detectNewComponents,
detectPRSize,
detectPRTemplateCheckboxes,
detectRequirements,
} = require('../detectors');
const { MANAGED_LABELS } = require('../constants');
// Minimal GitHub API mock — only repos.getContent is called by detectNewPlatforms/detectNewComponents
// to check for CONFIG_SCHEMA in newly added files.
@@ -29,6 +37,122 @@ const API_DATA = {
const WITH_SCHEMA = 'CONFIG_SCHEMA = cv.Schema({})';
const WITHOUT_SCHEMA = 'CODEOWNERS = ["@esphome/core"]';
// ---------------------------------------------------------------------------
// detectMergeBranch
// ---------------------------------------------------------------------------
// Builds a fresh context for detectMergeBranch tests instead of mutating the
// shared CONTEXT fixture above (which other describe blocks rely on).
function makeMergeContext(baseRef, { stack, defaultBranch = 'dev' } = {}) {
const pull_request = { number: 1, base: { ref: baseRef } };
if (stack !== undefined) {
pull_request.stack = stack;
}
return {
repo: { owner: 'esphome', repo: 'esphome' },
payload: { pull_request, repository: { default_branch: defaultBranch } }
};
}
// A GitHub API mock exposing only rest.pulls.get, with a call counter so
// tests can assert whether the API fallback was actually invoked.
function makeStackGithub({ stack = null, error = null } = {}) {
const state = { calls: 0 };
const github = {
rest: {
pulls: {
get: async () => {
state.calls++;
if (error) throw error;
return { data: { stack } };
}
}
}
};
return { github, state };
}
const STACK_INFO = { base: { ref: 'dev' }, id: 71540, number: 17978, position: 3, size: 3 };
describe('detectMergeBranch', () => {
it('base ref release adds merging-to-release only and never checks the stack', async () => {
const { github, state } = makeStackGithub({ stack: STACK_INFO });
const context = makeMergeContext('release', { stack: STACK_INFO });
const labels = await detectMergeBranch(github, context);
assert.deepEqual(Array.from(labels).sort(), ['merging-to-release']);
assert.equal(state.calls, 0);
});
it('base ref beta adds merging-to-beta only and never checks the stack', async () => {
const { github, state } = makeStackGithub({ stack: STACK_INFO });
const context = makeMergeContext('beta', { stack: STACK_INFO });
const labels = await detectMergeBranch(github, context);
assert.deepEqual(Array.from(labels).sort(), ['merging-to-beta']);
assert.equal(state.calls, 0);
});
it('stack present on the webhook payload adds stacked-pr without calling the API', async () => {
const { github, state } = makeStackGithub();
const context = makeMergeContext('feature-branch', { stack: STACK_INFO });
const labels = await detectMergeBranch(github, context);
assert.deepEqual(Array.from(labels).sort(), ['stacked-pr']);
assert.equal(state.calls, 0);
});
it('stack absent from payload falls back to the API and adds stacked-pr', async () => {
const { github, state } = makeStackGithub({ stack: STACK_INFO });
const context = makeMergeContext('feature-branch');
const labels = await detectMergeBranch(github, context);
assert.deepEqual(Array.from(labels).sort(), ['stacked-pr']);
assert.equal(state.calls, 1);
});
it('bottom of a stack (base ref dev, stack present) still adds stacked-pr', async () => {
const { github, state } = makeStackGithub();
const context = makeMergeContext('dev', { stack: STACK_INFO });
const labels = await detectMergeBranch(github, context);
assert.deepEqual(Array.from(labels).sort(), ['stacked-pr']);
assert.equal(state.calls, 0);
});
it('not stacked, base ref not dev adds chained-pr', async () => {
const { github } = makeStackGithub({ stack: null });
const context = makeMergeContext('feature-branch');
const labels = await detectMergeBranch(github, context);
assert.deepEqual(Array.from(labels).sort(), ['chained-pr']);
});
it('not stacked, base ref dev adds no labels', async () => {
const { github } = makeStackGithub({ stack: null });
const context = makeMergeContext('dev');
const labels = await detectMergeBranch(github, context);
assert.deepEqual(Array.from(labels).sort(), []);
});
it('a failed stack lookup falls back to not-stacked, so a feature-branch base adds chained-pr', async () => {
const { github, state } = makeStackGithub({ error: new Error('API unavailable') });
const context = makeMergeContext('feature-branch');
const labels = await detectMergeBranch(github, context);
assert.deepEqual(Array.from(labels).sort(), ['chained-pr']);
assert.equal(state.calls, 1);
});
it('base ref matches default branch adds no labels', async () => {
const { github } = makeStackGithub({ stack: null });
const context = makeMergeContext('other', { defaultBranch: 'other' });
const labels = await detectMergeBranch(github, context);
assert.deepEqual(Array.from(labels).sort(), []);
});
it('base ref dev when the default branch is main adds chained-pr', async () => {
const { github } = makeStackGithub({ stack: null });
const context = makeMergeContext('dev', { defaultBranch: 'main' });
const labels = await detectMergeBranch(github, context);
assert.deepEqual(Array.from(labels).sort(), ['chained-pr']);
});
});
// ---------------------------------------------------------------------------
// detectNewPlatforms
// ---------------------------------------------------------------------------
@@ -145,3 +269,198 @@ describe('detectNewComponents', () => {
assert.equal(result.labels.size, 0);
});
});
// ---------------------------------------------------------------------------
// detectPRTemplateCheckboxes
// ---------------------------------------------------------------------------
const NEW_FEATURE_LINE = '- [x] New feature (non-breaking change which adds functionality)';
const DEV_FEATURE_LINE = '- [x] New developer-facing feature (adds functionality for component developers; no end-user configuration change)';
const DEV_FEATURE_LINE_UNTICKED = '- [ ] New developer-facing feature (adds functionality for component developers; no end-user configuration change)';
function makeBodyContext(body) {
return { payload: { pull_request: { body } } };
}
describe('detectPRTemplateCheckboxes', () => {
it('ticked developer-facing feature checkbox adds new-feature-developer only', async () => {
const labels = await detectPRTemplateCheckboxes(makeBodyContext(DEV_FEATURE_LINE));
assert.ok(labels.has('new-feature-developer'));
assert.ok(!labels.has('new-feature'));
});
it('unticked developer-facing feature checkbox adds no label', async () => {
const labels = await detectPRTemplateCheckboxes(makeBodyContext(DEV_FEATURE_LINE_UNTICKED));
assert.ok(!labels.has('new-feature-developer'));
});
it('ticked new feature checkbox does not add new-feature-developer', async () => {
const labels = await detectPRTemplateCheckboxes(makeBodyContext(NEW_FEATURE_LINE));
assert.ok(labels.has('new-feature'));
assert.ok(!labels.has('new-feature-developer'));
});
});
// ---------------------------------------------------------------------------
// detectRequirements
// ---------------------------------------------------------------------------
describe('detectRequirements', () => {
// PR body without any docs-PR link.
const NO_DOCS_CONTEXT = makeBodyContext('Just a description, no docs link.');
const USER_DOCS_CONTEXT = makeBodyContext('Docs: esphome/esphome.io#1234');
const DEV_DOCS_CONTEXT = makeBodyContext('Docs: esphome/developers.esphome.io#1234');
const DEV_DOCS_URL_CONTEXT = makeBodyContext('Docs: https://github.com/esphome/developers.esphome.io/pull/1234');
// File sets: a normal source change vs. one confined to the exempt core validators.
const SOURCE_FILES = [
{ filename: 'esphome/components/foo/foo.py' },
{ filename: 'tests/components/foo/common.yaml' },
];
const VALIDATOR_FILES = [
{ filename: 'esphome/config_validation.py' },
{ filename: 'tests/unit_tests/test_config_validation.py' },
];
it('new-feature-developer without has-tests adds needs-tests but not needs-docs', async () => {
const labels = await detectRequirements(new Set(['new-feature-developer']), SOURCE_FILES, NO_DOCS_CONTEXT, false);
assert.ok(labels.has('needs-tests'));
assert.ok(!labels.has('needs-docs'));
});
it('new-feature-developer with has-tests does not add needs-tests', async () => {
const labels = await detectRequirements(new Set(['new-feature-developer', 'has-tests']), SOURCE_FILES, NO_DOCS_CONTEXT, false);
assert.ok(!labels.has('needs-tests'));
});
it('new-feature without a docs link still adds needs-docs', async () => {
const labels = await detectRequirements(new Set(['new-feature', 'has-tests']), [], NO_DOCS_CONTEXT, false);
assert.ok(labels.has('needs-docs'));
});
it('new-feature-developer without a developer docs link adds needs-developer-docs', async () => {
const labels = await detectRequirements(new Set(['new-feature-developer', 'has-tests']), SOURCE_FILES, NO_DOCS_CONTEXT, false);
assert.ok(labels.has('needs-developer-docs'));
});
it('a developers.esphome.io shorthand link satisfies needs-developer-docs', async () => {
const labels = await detectRequirements(new Set(['new-feature-developer', 'has-tests']), SOURCE_FILES, DEV_DOCS_CONTEXT, false);
assert.ok(!labels.has('needs-developer-docs'));
});
it('a developers.esphome.io URL link satisfies needs-developer-docs', async () => {
const labels = await detectRequirements(new Set(['new-feature-developer', 'has-tests']), SOURCE_FILES, DEV_DOCS_URL_CONTEXT, false);
assert.ok(!labels.has('needs-developer-docs'));
});
it('a user docs (esphome.io) link does not satisfy needs-developer-docs', async () => {
const labels = await detectRequirements(new Set(['new-feature-developer', 'has-tests']), SOURCE_FILES, USER_DOCS_CONTEXT, false);
assert.ok(labels.has('needs-developer-docs'));
});
it('a developer docs link does not satisfy needs-docs for new-feature', async () => {
const labels = await detectRequirements(new Set(['new-feature', 'has-tests']), [], DEV_DOCS_CONTEXT, false);
assert.ok(labels.has('needs-docs'));
});
it('changes confined to core validator files are exempt from needs-developer-docs', async () => {
const labels = await detectRequirements(new Set(['new-feature-developer', 'has-tests']), VALIDATOR_FILES, NO_DOCS_CONTEXT, false);
assert.ok(!labels.has('needs-developer-docs'));
});
it('validator changes mixed with other source files are not exempt', async () => {
const prFiles = [...VALIDATOR_FILES, { filename: 'esphome/components/foo/foo.py' }];
const labels = await detectRequirements(new Set(['new-feature-developer', 'has-tests']), prFiles, NO_DOCS_CONTEXT, false);
assert.ok(labels.has('needs-developer-docs'));
});
});
// ---------------------------------------------------------------------------
// MANAGED_LABELS
// ---------------------------------------------------------------------------
describe('MANAGED_LABELS', () => {
it('includes new-feature-developer so the workflow syncs it', () => {
assert.ok(MANAGED_LABELS.includes('new-feature-developer'));
});
it('includes needs-developer-docs so the workflow syncs it', () => {
assert.ok(MANAGED_LABELS.includes('needs-developer-docs'));
});
});
// ---------------------------------------------------------------------------
// detectPRSize
// ---------------------------------------------------------------------------
describe('detectPRSize', () => {
const SMALL = 30;
const MEDIUM = 100;
const TOO_BIG = 1000;
function size(prFiles, isMegaPR = false) {
const totalAdditions = prFiles.reduce((sum, file) => sum + (file.additions || 0), 0);
const totalDeletions = prFiles.reduce((sum, file) => sum + (file.deletions || 0), 0);
return detectPRSize(prFiles, totalAdditions, totalDeletions, isMegaPR, SMALL, MEDIUM, TOO_BIG);
}
it('counts only non-test changes toward small-pr', async () => {
// 10 source + 5000 test lines -> non-test churn of 10 is still small.
const labels = await size([
{ filename: 'esphome/components/foo/foo.cpp', additions: 10, deletions: 0 },
{ filename: 'tests/components/foo/test.esp32-idf.yaml', additions: 5000, deletions: 0 },
]);
assert.ok(labels.has('small-pr'));
assert.equal(labels.size, 1);
});
it('counts additions and deletions as churn (not net delta)', async () => {
// A balanced refactor (40 added, 40 removed) is 80 lines of churn -> medium, not small.
const labels = await size([
{ filename: 'esphome/components/foo/foo.cpp', additions: 40, deletions: 40 },
]);
assert.ok(labels.has('medium-pr'));
assert.equal(labels.size, 1);
});
it('labels medium-pr when non-test changes exceed small threshold', async () => {
const labels = await size([
{ filename: 'esphome/components/foo/foo.cpp', additions: 60, deletions: 0 },
{ filename: 'tests/components/foo/test.esp32-idf.yaml', additions: 5000, deletions: 0 },
]);
assert.ok(labels.has('medium-pr'));
assert.equal(labels.size, 1);
});
it('uses net delta (not churn) for too-big', async () => {
// 600 added + 600 removed: 1200 churn (above too-big) but 0 net delta -> not too-big.
const labels = await size([
{ filename: 'esphome/components/foo/foo.cpp', additions: 600, deletions: 600 },
]);
assert.equal(labels.size, 0);
});
it('labels too-big when non-test changes exceed the big threshold', async () => {
const labels = await size([
{ filename: 'esphome/components/foo/foo.cpp', additions: 2000, deletions: 0 },
{ filename: 'tests/components/foo/test.esp32-idf.yaml', additions: 5000, deletions: 0 },
]);
assert.ok(labels.has('too-big'));
assert.equal(labels.size, 1);
});
it('does not label too-big when mega-pr is set', async () => {
const labels = await size([
{ filename: 'esphome/components/foo/foo.cpp', additions: 2000, deletions: 0 },
], true);
assert.equal(labels.size, 0);
});
it('produces no size label for a large mega-pr in the gap above medium', async () => {
// Non-test changes land between MEDIUM and TOO_BIG: not small/medium, and mega-pr suppresses too-big.
const labels = await size([
{ filename: 'esphome/components/foo/foo.cpp', additions: 500, deletions: 0 },
], true);
assert.equal(labels.size, 0);
});
});
-1
View File
@@ -41,7 +41,6 @@ function hasCoreChanges(changedFiles) {
*/
function hasDashboardChanges(changedFiles) {
return changedFiles.some(file =>
file.startsWith('esphome/dashboard/') ||
file.startsWith('esphome/components/dashboard_import/')
);
}
+2 -2
View File
@@ -24,7 +24,7 @@ jobs:
if: github.event.pull_request.state == 'open' && (github.event.action != 'labeled' || github.event.sender.type != 'Bot')
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Generate a token
id: generate-token
@@ -35,7 +35,7 @@ jobs:
# Scope the minted App token to the minimum needed by auto-label-pr/*.js.
permission-contents: read # repos.getContent for CODEOWNERS and file lookups in detectors.js
permission-issues: write # listLabelsOnIssue, addLabels, removeLabel, list/createComment
permission-pull-requests: write # pulls.listFiles, list/create/update/dismissReview
permission-pull-requests: write # pulls.get, pulls.listFiles, list/create/update/dismissReview
- name: Auto Label PR
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
+32 -7
View File
@@ -21,27 +21,52 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.11"
python-version: "3.12"
- name: Set up uv
# ``--system`` (below) installs into the setup-python interpreter;
# no venv is created or restored by this workflow.
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
enable-cache: true
# Pull-request-only workflow: a save could never be shared and
# would only consume quota.
save-cache: "false"
# Pin uv version so the action does not have to fetch the
# manifest from raw.githubusercontent.com on every cache
# miss; that fetch flakes on Windows runners.
version: "0.11.15"
- name: Install apt dependencies
# PR-only workflow, so nothing on dev could seed a shared apt cache
# entry; the cached apt action would save one copy per PR. Plain apt
# with every call bounded: the apt.conf.d timeouts make a dead
# mirror fail over in seconds, and timeout runs under sudo so it can
# kill apt-get itself. Install without update first: image lists are
# fresh, and the index refresh is what a congested mirror makes slow.
timeout-minutes: 15
run: |
sudo apt update
sudo apt-cache show protobuf-compiler
sudo apt install -y protobuf-compiler
sudo tee /etc/apt/apt.conf.d/99ci-acquire-timeouts >/dev/null <<'EOF'
Acquire::Retries "1";
Acquire::http::Timeout "15";
Acquire::https::Timeout "15";
EOF
# Common path: the image's package lists are fresh enough.
if sudo DEBIAN_FRONTEND=noninteractive timeout -k 15 90 \
apt-get install -y protobuf-compiler; then
protoc --version
exit 0
fi
# Rescue path: refresh the lists once with a generous bound; the
# apt config already fails a stalled mirror over quickly.
sudo DEBIAN_FRONTEND=noninteractive timeout -k 10 30 \
dpkg --configure -a || true
sudo timeout -k 15 300 apt-get update
sudo DEBIAN_FRONTEND=noninteractive timeout -k 15 300 \
apt-get install -y protobuf-compiler
protoc --version
- name: Install python dependencies
run: uv pip install --system aioesphomeapi -c requirements.txt -r requirements_dev.txt
-76
View File
@@ -1,76 +0,0 @@
name: Clang-tidy Hash CI
on:
pull_request:
paths:
- ".clang-tidy"
- "platformio.ini"
- "requirements_dev.txt"
- "sdkconfig.defaults"
- ".clang-tidy.hash"
- "script/clang_tidy_hash.py"
- ".github/workflows/ci-clang-tidy-hash.yml"
permissions:
contents: read # actions/checkout for the PR head
pull-requests: write # pulls.createReview / listReviews / dismissReview when the clang-tidy hash is out of date
jobs:
verify-hash:
name: Verify clang-tidy hash
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.11"
- name: Verify hash
run: |
python script/clang_tidy_hash.py --verify
- if: failure()
name: Show hash details
run: |
python script/clang_tidy_hash.py
echo "## Job Failed" | tee -a $GITHUB_STEP_SUMMARY
echo "You have modified clang-tidy configuration but have not updated the hash." | tee -a $GITHUB_STEP_SUMMARY
echo "Please run 'script/clang_tidy_hash.py --update' and commit the changes." | tee -a $GITHUB_STEP_SUMMARY
- if: failure() && github.event.pull_request.head.repo.full_name == github.repository
name: Request changes
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
await github.rest.pulls.createReview({
pull_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
event: 'REQUEST_CHANGES',
body: 'You have modified clang-tidy configuration but have not updated the hash.\nPlease run `script/clang_tidy_hash.py --update` and commit the changes.'
})
- if: success() && github.event.pull_request.head.repo.full_name == github.repository
name: Dismiss review
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
let reviews = await github.rest.pulls.listReviews({
pull_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo
});
for (let review of reviews.data) {
if (review.user.login === 'github-actions[bot]' && review.state === 'CHANGES_REQUESTED') {
await github.rest.pulls.dismissReview({
pull_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
review_id: review.id,
message: 'Clang-tidy hash now matches configuration.'
});
}
}
+179 -19
View File
@@ -1,28 +1,41 @@
---
name: CI for docker images
# Only run when docker paths change
# Only run on PRs that touch the docker image, its build inputs, or any code
# whose toolchain the compile smoke test exercises (core + target platforms).
on:
push:
branches: [dev, beta, release]
paths:
- "docker/**"
- ".github/workflows/ci-docker.yml"
- "requirements*.txt"
- "platformio.ini"
- "script/platformio_install_deps.py"
pull_request:
paths:
# Docker image and its build inputs.
- "docker/**"
- ".github/workflows/ci-docker.yml"
- "requirements*.txt"
- "pyproject.toml"
- "platformio.ini"
- "esphome/idf_component.yml"
- "script/platformio_install_deps.py"
# Core, build pipeline, toolchain, and target-platform changes can change
# how a toolchain is set up or built, so re-run the per-toolchain compile
# smoke test when they change.
- "esphome/core/**"
- "esphome/writer.py"
- "esphome/build_gen/**"
- "esphome/espidf/**"
- "esphome/platformio/**"
- "esphome/components/bk72xx/**"
- "esphome/components/esp32/**"
- "esphome/components/esp8266/**"
- "esphome/components/host/**"
- "esphome/components/libretiny/**"
- "esphome/components/ln882x/**"
- "esphome/components/nrf52/**"
- "esphome/components/rp2040/**"
- "esphome/components/rtl87xx/**"
- "esphome/components/zephyr/**"
permissions:
contents: read # actions/checkout only; the build does not push images
contents: read # actions/checkout only
concurrency:
# yamllint disable-line rule:line-length
@@ -33,6 +46,9 @@ jobs:
check-docker:
name: Build docker containers
runs-on: ${{ matrix.os }}
permissions:
contents: read # actions/checkout to load Dockerfile and build context
packages: write # push branch-tagged images to ghcr.io for local testing
strategy:
fail-fast: false
matrix:
@@ -41,23 +57,167 @@ jobs:
- "ha-addon"
- "docker"
# - "lint"
outputs:
tag: ${{ steps.tag.outputs.tag }}
push: ${{ steps.tag.outputs.push }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.11"
python-version: "3.12"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
- name: Set TAG
- name: Determine tag and whether to push
id: tag
env:
HEAD_REF: ${{ github.head_ref || github.ref_name }}
run: |
echo "TAG=check" >> $GITHUB_ENV
# Sanitize the branch name into a valid docker tag: replace invalid
# characters, ensure the first character is valid (tags must start
# with [A-Za-z0-9_]), and cap the length at 128 characters.
branch="$HEAD_REF"
tag="${branch//[^a-zA-Z0-9_.-]/-}"
case "$tag" in
[a-zA-Z0-9_]*) ;;
*) tag="pr-${tag}" ;;
esac
tag="${tag:0:128}"
echo "tag=${tag}" >> "$GITHUB_OUTPUT"
# Only push branch images for same-repo pull requests. Push events
# only fire for dev/beta/release, whose images are owned by the
# release pipeline -- never overwrite those from here.
if [ "${{ github.event_name }}" = "pull_request" ] \
&& [ "${{ github.repository }}" = "esphome/esphome" ] \
&& [ "${{ github.event.pull_request.head.repo.full_name }}" = "esphome/esphome" ]; then
echo "push=true" >> "$GITHUB_OUTPUT"
else
echo "push=false" >> "$GITHUB_OUTPUT"
fi
- name: Log in to the GitHub container registry
if: steps.tag.outputs.push == 'true'
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Run build
run: |
docker/build.py \
--tag "${TAG}" \
--tag "${{ steps.tag.outputs.tag }}" \
--arch "${{ matrix.os == 'ubuntu-24.04-arm' && 'aarch64' || 'amd64' }}" \
--build-type "${{ matrix.build_type }}" \
build
--registry ghcr \
build ${{ steps.tag.outputs.push == 'true' && '--push --no-cache-to' || '' }} ${{ (matrix.os == 'ubuntu-24.04' && matrix.build_type == 'docker') && '--load' || '' }}
# The amd64 "docker" image is also loaded locally (above) and handed to
# compile-test as an artifact, so the smoke test reuses this build instead
# of building the image a second time. Using an artifact (rather than the
# pushed image) keeps it working for fork PRs, which never push to ghcr.io.
- name: Export image for compile-test
if: matrix.os == 'ubuntu-24.04' && matrix.build_type == 'docker'
# zstd over gzip: docker save is on the critical path for every
# compile-test job, and zstd -T0 is multithreaded (export 50s -> 9s).
# docker load auto-detects the format; its time is layer extraction,
# not decompression, so it is unchanged. shell: bash adds pipefail so
# a failed docker save cannot upload a truncated artifact.
shell: bash
run: docker save "ghcr.io/esphome/esphome-amd64:${{ steps.tag.outputs.tag }}" | zstd -T0 -3 > compile-test-image.tar.zst
- name: Upload compile-test image artifact
if: matrix.os == 'ubuntu-24.04' && matrix.build_type == 'docker'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
# The tar is already compressed, so upload it as-is. archive: false
# skips the redundant zip and makes the file name the artifact name
# (the `name` input is ignored in that mode).
path: compile-test-image.tar.zst
retention-days: 1
archive: false
manifest:
name: Push ${{ matrix.build_type }} manifest to ghcr.io
needs: [check-docker]
if: needs.check-docker.outputs.push == 'true'
runs-on: ubuntu-24.04
permissions:
contents: read # actions/checkout to run docker/build.py
packages: write # buildx imagetools writes the multi-arch tag to ghcr.io
strategy:
fail-fast: false
matrix:
build_type:
- "ha-addon"
- "docker"
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
- name: Log in to the GitHub container registry
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create and push manifest
run: |
docker/build.py \
--tag "${{ needs.check-docker.outputs.tag }}" \
--build-type "${{ matrix.build_type }}" \
--registry ghcr \
manifest
# Smoke-test the built image by compiling one minimal config per target
# platform / toolchain. This catches missing system dependencies in the image
# that only surface when a given toolchain is downloaded and run. The image is
# the amd64 "docker" build produced by check-docker (shared as an artifact).
compile-test:
name: Compile ${{ matrix.id }}
needs: check-docker
runs-on: ubuntu-24.04
permissions:
contents: read # actions/checkout to load the test configs
strategy:
fail-fast: false
matrix:
# One entry per distinct toolchain. ESP32 variants (c3/c6/s2/s3/p4)
# share a toolchain bundle, so esp32 is exercised on the base variant
# across the full framework x toolchain cross-product (arduino/esp-idf
# framework, each built with the platformio and native esp-idf
# toolchains) so both toolchains stay covered regardless of which one is
# the default.
id:
- esp8266-arduino
- esp32-arduino-platformio
- esp32-arduino-esp-idf
- esp32-idf-platformio
- esp32-idf-esp-idf
- rp2040-arduino
- bk72xx-arduino
- rtl87xx-arduino
- ln882x-arduino
- nrf52
- host
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Download image artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: compile-test-image.tar.zst
- name: Load image
run: docker load --input compile-test-image.tar.zst
- name: Compile ${{ matrix.id }}
run: |
docker run --rm \
-v "${{ github.workspace }}/docker/test_configs:/config" \
"ghcr.io/esphome/esphome-amd64:${{ needs.check-docker.outputs.tag }}" \
compile "${{ matrix.id }}.yaml"
+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code from GitHub
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Run tests
working-directory: .github/scripts/auto-label-pr
@@ -49,7 +49,7 @@ jobs:
- name: Check out code from base repository
if: steps.pr.outputs.skip != 'true'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# Always check out from the base repository (esphome/esphome), never from forks
# Use the PR's target branch to ensure we run trusted code from the main repo
@@ -60,7 +60,7 @@ jobs:
if: steps.pr.outputs.skip != 'true'
uses: ./.github/actions/restore-python
with:
python-version: "3.11"
python-version: "3.12"
cache-key: ${{ hashFiles('.cache-key') }}
- name: Download memory analysis artifacts
+749 -418
View File
File diff suppressed because it is too large. Load diff
@@ -26,7 +26,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout base branch
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.pull_request.base.sha }}
sparse-checkout: |
@@ -29,7 +29,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout base branch
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.pull_request.base.sha }}
+3 -3
View File
@@ -52,11 +52,11 @@ jobs:
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
@@ -84,6 +84,6 @@ jobs:
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
with:
category: "/language:${{matrix.language}}"
@@ -1,119 +0,0 @@
name: Add Dashboard Deprecation Comment
on:
pull_request_target:
types: [opened, synchronize]
# All API calls (pulls.listFiles + issues.{list,create,update}Comment) are performed with
# the App token minted below, so the workflow's GITHUB_TOKEN does not need any scopes.
permissions: {}
jobs:
dashboard-deprecation-comment:
name: Dashboard deprecation comment
runs-on: ubuntu-latest
# Release-bump PRs (bump-X.Y.Z -> beta, beta -> release) inevitably
# roll up everything merged into dev since the last cut, which can
# include dashboard changes that have already been reviewed once.
# The bot's purpose is to warn new contributors before they invest
# time -- that only applies to PRs entering dev.
if: github.event.pull_request.base.ref == 'dev'
steps:
- name: Generate a token
id: generate-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
client-id: ${{ vars.ESPHOME_GITHUB_APP_CLIENT_ID }}
private-key: ${{ secrets.ESPHOME_GITHUB_APP_PRIVATE_KEY }}
# pulls.listFiles + issues.{list,create,update}Comment on PRs. For PR resources
# the issues.*Comment APIs require the pull-requests scope, not issues.
permission-pull-requests: write
- name: Add dashboard deprecation comment
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ steps.generate-token.outputs.token }}
script: |
const commentMarker = "<!-- This comment was generated automatically by the dashboard-deprecation-comment workflow. -->";
const commentBody = `Thanks for opening this PR!
Heads up: the legacy ESPHome dashboard (\`esphome/dashboard/\` and \`tests/dashboard/\`) is **deprecated** and is being replaced by [ESPHome Device Builder](https://github.com/esphome/device-builder). We are not adding new features to the legacy dashboard and it will eventually be removed from this repository.
What this means for your PR:
- **New features / enhancements**: please port the change to [esphome/device-builder](https://github.com/esphome/device-builder) instead. We are unlikely to review or merge new dashboard features here.
- **Bug fixes**: small fixes may still be considered, but please check first whether the same issue exists in Device Builder, where the fix will have a longer life.
- **Security issues**: please do not file a public PR. Report privately via [GitHub security advisories](https://github.com/esphome/esphome/security/advisories/new) so we can coordinate a fix.
We appreciate the contribution and apologize for the friction; flagging this early so your time isn't spent on a change that may not land.
---
(Added by the PR bot)
${commentMarker}`;
async function getDashboardChanges(github, owner, repo, prNumber) {
const changedFiles = await github.paginate(
github.rest.pulls.listFiles,
{
owner: owner,
repo: repo,
pull_number: prNumber,
per_page: 100,
}
);
return changedFiles.filter(file =>
file.filename.startsWith('esphome/dashboard/') ||
file.filename.startsWith('tests/dashboard/')
);
}
async function findBotComment(github, owner, repo, prNumber) {
const comments = await github.paginate(
github.rest.issues.listComments,
{
owner: owner,
repo: repo,
issue_number: prNumber,
per_page: 100,
}
);
return comments.find(comment =>
comment.body.includes(commentMarker) && comment.user.type === "Bot"
);
}
const prNumber = context.payload.pull_request.number;
const { owner, repo } = context.repo;
const dashboardChanges = await getDashboardChanges(github, owner, repo, prNumber);
const existingComment = await findBotComment(github, owner, repo, prNumber);
if (dashboardChanges.length === 0) {
// PR doesn't (or no longer) touches the legacy dashboard. If we previously
// commented (e.g. files were removed in a later push), leave the comment in
// place for history rather than thrash on edit/delete.
return;
}
if (existingComment) {
if (existingComment.body === commentBody) {
return;
}
await github.rest.issues.updateComment({
owner: owner,
repo: repo,
comment_id: existingComment.id,
body: commentBody,
});
} else {
await github.rest.issues.createComment({
owner: owner,
repo: repo,
issue_number: prNumber,
body: commentBody,
});
}
+1 -1
View File
@@ -14,4 +14,4 @@ jobs:
permissions:
issues: write # issues.lock on closed issues
pull-requests: write # issues.lock on closed pull requests
uses: esphome/workflows/.github/workflows/lock.yml@025a1e6255610c498ed590403b7e510b69e474df # 2026.4.1
uses: esphome/workflows/.github/workflows/lock.yml@0fdd5e311b7e744069166696072a1a9cbc5fbeb6 # 2026.8.1
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
name: Validate PR title
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
+38
View File
@@ -0,0 +1,38 @@
---
name: Nightly Dev Release
# Works out the dated dev tag and starts the release workflow with it, so that
# the release run is named after the tag it builds. A workflow run name is
# fixed when the run starts and cannot read a file or the current date.
on:
schedule:
- cron: "0 2 * * *"
permissions:
contents: read # actions/checkout to read the version from esphome/const.py
jobs:
trigger:
name: Start release build
if: github.repository == 'esphome/esphome'
runs-on: ubuntu-latest
permissions:
contents: read # actions/checkout to read the version from esphome/const.py
actions: write # gh workflow run starts release.yml
steps:
- name: Check out the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Start the release workflow
env:
GH_TOKEN: ${{ github.token }}
run: |
VERSION=$(sed -n -E "s/^__version__\s+=\s+\"(.+)\"$/\1/p" esphome/const.py)
if [[ -z "$VERSION" ]]; then
echo "::error::Could not read __version__ from esphome/const.py"
exit 1
fi
TAG="${VERSION}$(date --utc '+%Y%m%d')"
echo "Starting release build for ${TAG}"
gh workflow run release.yml --ref "${GITHUB_REF_NAME}" --field tag="${TAG}"
+44 -20
View File
@@ -1,12 +1,23 @@
---
name: Publish Release
# Releases (production and beta) are named after the version they publish.
# Dev builds are named after the dated dev tag, which is passed in by the
# nightly workflow because a run name cannot compute it itself.
run-name: ${{ github.event.inputs.tag || github.event.release.tag_name || format('Manual build ({0})', github.ref_name) }}
on:
workflow_dispatch:
inputs:
tag:
description: >-
Tag to build. Only supported on dev, where the nightly workflow
uses it. Leave empty to build the version from esphome/const.py
with today's date appended.
required: false
default: ""
release:
types: [published]
schedule:
- cron: "0 2 * * *"
permissions:
contents: read # actions/checkout for all jobs; deploy jobs add their own scopes when they need to write
@@ -20,9 +31,11 @@ jobs:
branch_build: ${{ steps.tag.outputs.branch_build }}
deploy_env: ${{ steps.tag.outputs.deploy_env }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Get tag
id: tag
env:
INPUT_TAG: ${{ github.event.inputs.tag }}
# yamllint disable rule:line-length
run: |
if [[ "${{ github.event_name }}" = "release" ]]; then
@@ -34,12 +47,23 @@ jobs:
ENVIRONMENT="production"
fi
else
TAG=$(cat esphome/const.py | sed -n -E "s/^__version__\s+=\s+\"(.+)\"$/\1/p")
today="$(date --utc '+%Y%m%d')"
TAG="${TAG}${today}"
BRANCH=${GITHUB_REF#refs/heads/}
# The nightly workflow passes the finished tag so that the run name
# matches what is built. Without it, work it out here.
TAG="${INPUT_TAG}"
if [[ -n "$TAG" && "$BRANCH" != "dev" ]]; then
echo "::error::The tag input is only supported on dev. A build from ${BRANCH} has to use the tag worked out here, which carries the branch name, so that it cannot publish over the dev, beta, latest or stable images."
exit 1
fi
if [[ -z "$TAG" ]]; then
TAG=$(cat esphome/const.py | sed -n -E "s/^__version__\s+=\s+\"(.+)\"$/\1/p")
today="$(date --utc '+%Y%m%d')"
TAG="${TAG}${today}"
if [[ "$BRANCH" != "dev" ]]; then
TAG="${TAG}-${BRANCH}"
fi
fi
if [[ "$BRANCH" != "dev" ]]; then
TAG="${TAG}-${BRANCH}"
BRANCH_BUILD="true"
ENVIRONMENT=""
else
@@ -60,9 +84,9 @@ jobs:
contents: read # actions/checkout to build the sdist/wheel
id-token: write # OIDC token for PyPI Trusted Publishing (pypa/gh-action-pypi-publish)
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.x"
- name: Build
@@ -70,7 +94,7 @@ jobs:
pip3 install build
python3 -m build
- name: Publish
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
with:
skip-existing: true
@@ -92,22 +116,22 @@ jobs:
os: "ubuntu-24.04-arm"
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.11"
python-version: "3.12"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
- name: Log in to docker hub
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Log in to the GitHub container registry
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
@@ -168,7 +192,7 @@ jobs:
- ghcr
- dockerhub
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Download digests
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
@@ -178,17 +202,17 @@ jobs:
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
- name: Log in to docker hub
if: matrix.registry == 'dockerhub'
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Log in to the GitHub container registry
if: matrix.registry == 'ghcr'
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
+35 -50
View File
@@ -6,61 +6,46 @@ on:
- cron: "30 0 * * *"
workflow_dispatch:
permissions:
issues: write # actions/stale labels, comments on, and closes stale issues
pull-requests: write # actions/stale labels, comments on, and closes stale pull requests
concurrency:
group: lock
# The reusable workflow authenticates as the ESPHome GitHub App, so GITHUB_TOKEN
# needs no permissions at all.
permissions: {}
jobs:
stale:
if: github.repository_owner == 'esphome'
runs-on: ubuntu-latest
steps:
- name: Stale
uses: actions/stale@eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899 # v10.3.0
with:
debug-only: ${{ github.ref != 'refs/heads/dev' }} # Dry-run when not run on dev branch
remove-stale-when-updated: true
operations-per-run: 400
# No GITHUB_TOKEN permissions: the reusable workflow mints an ESPHome
# GitHub App token so the labels, comments and closures come from
# esphome[bot] instead of github-actions[bot].
uses: esphome/workflows/.github/workflows/stale.yml@a1c1485ab46ef41a84a6a9d8abd7fa4b7628fd70 # main
secrets:
ESPHOME_GITHUB_APP_PRIVATE_KEY: ${{ secrets.ESPHOME_GITHUB_APP_PRIVATE_KEY }}
with:
# Live only on dev: a workflow_dispatch from any other branch is a dry run
dry-run: ${{ github.ref != 'refs/heads/dev' }}
days-before-stale: 90
days-before-close: 7
stale-label: stale
exempt-label: not-stale
ignored-users: esphbot,codecov-commenter
stale-pr-message: >
There hasn't been any activity on this pull request recently. This
pull request has been automatically marked as stale because of that
and will be closed if no further activity occurs within 7 days.
# The 90 day stale policy for PRs
# - PRs
# - No PRs marked as "not-stale"
# - No Issues (see below)
days-before-pr-stale: 90
days-before-pr-close: 7
stale-pr-label: "stale"
exempt-pr-labels: "not-stale"
stale-pr-message: >
There hasn't been any activity on this pull request recently. This
pull request has been automatically marked as stale because of that
and will be closed if no further activity occurs within 7 days.
If you are the author of this PR, please leave a comment if you want
to keep it open. Also, please merge the latest dev branch into your
branch to ensure that it's up to date with the latest changes.
If you are the author of this PR, please leave a comment if you want
to keep it open. Also, please rebase your PR onto the latest dev
branch to ensure that it's up to date with the latest changes.
Thank you for your contribution!
stale-issue-message: >
There hasn't been any activity on this issue recently. Due to the
high number of incoming GitHub notifications, we have to clean some
of the old issues, as many of them have already been resolved with
the latest updates.
Thank you for your contribution!
Please make sure to update to the latest ESPHome version and
check if that solves the issue. Let us know if that works for you by
adding a comment 👍
# The 90 day stale policy for Issues
# - Issues
# - No Issues marked as "not-stale"
# - No PRs (see above)
days-before-issue-stale: 90
days-before-issue-close: 7
stale-issue-label: "stale"
exempt-issue-labels: "not-stale"
stale-issue-message: >
There hasn't been any activity on this issue recently. Due to the
high number of incoming GitHub notifications, we have to clean some
of the old issues, as many of them have already been resolved with
the latest updates.
Please make sure to update to the latest ESPHome version and
check if that solves the issue. Let us know if that works for you by
adding a comment 👍
This issue has now been marked as stale and will be closed if no
further activity occurs. Thank you for your contributions.
This issue has now been marked as stale and will be closed if no
further activity occurs. Thank you for your contributions.
+2 -2
View File
@@ -5,7 +5,7 @@ on:
types: [opened, reopened, labeled, unlabeled, synchronize]
permissions:
pull-requests: read # issues.listLabelsOnIssue to detect blocking labels (needs-docs, merge-after-release, chained-pr)
pull-requests: read # issues.listLabelsOnIssue to detect blocking labels (needs-docs, needs-developer-docs, merge-after-release, chained-pr)
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
@@ -20,7 +20,7 @@ jobs:
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const blockingLabels = ['needs-docs', 'merge-after-release', 'chained-pr'];
const blockingLabels = ['needs-docs', 'needs-developer-docs', 'merge-after-release', 'chained-pr'];
const { data: labels } = await github.rest.issues.listLabelsOnIssue({
owner: context.repo.owner,
repo: context.repo.repo,
@@ -0,0 +1,94 @@
# Keeps pre-commit hook revs in sync with the requirements files.
#
# Dependabot only bumps the pins in requirements*.txt. Some of those tools
# are pinned again as hook revs in .pre-commit-config.yaml. This workflow
# runs script/sync_dependency_versions.py against the pull request branch
# and pushes a commit with the revs updated.
name: Sync dependency versions
on:
# pull_request_target rather than pull_request so the App secret is
# available on Dependabot pull requests (pull_request runs opened by
# Dependabot only see Dependabot secrets). The job below only touches
# branches in this repository and only ever executes the script from the
# base branch checkout, so fork code never runs with the token.
pull_request_target:
types: [opened, synchronize, reopened]
paths:
- requirements_dev.txt
- requirements_test.txt
- .pre-commit-config.yaml
- script/sync_dependency_versions.py
# The push to the pull request branch uses the App token minted below, so
# the workflow's GITHUB_TOKEN does not need any scopes.
permissions: {}
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
sync:
name: Sync pinned versions
runs-on: ubuntu-latest
# Same-repository branches only: a push to a fork is not possible with
# this token, and it keeps untrusted heads out of a privileged job.
if: >-
github.repository == 'esphome/esphome'
&& github.event.pull_request.head.repo.full_name == github.repository
steps:
- name: Generate a token
id: generate-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
client-id: ${{ vars.ESPHOME_GITHUB_APP_CLIENT_ID }}
private-key: ${{ secrets.ESPHOME_GITHUB_APP_PRIVATE_KEY }}
# A push made with the workflow's own GITHUB_TOKEN would not start
# CI on the new commit; a push with the App token does.
permission-contents: write # git push of the sync commit to the pull request branch
- name: Check out base branch
# Provides the script that runs below. Deliberately the base branch
# so the pull request cannot change what executes here.
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.pull_request.base.sha }}
persist-credentials: false
- name: Check out pull request branch
# No allow-unsafe-pr-checkout here on purpose: checkout v7 only
# refuses heads that live in a different repository, and the job
# condition above already limits runs to same-repository branches.
# Leaving it off keeps that refusal as a backstop for fork heads.
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.pull_request.head.ref }}
path: pull-request
token: ${{ steps.generate-token.outputs.token }}
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
- name: Install yamlrocks
# The script edits YAML through yamlrocks. Take the pin from the
# base branch requirements so this workflow has no copy of its own.
run: pip install "$(grep -E '^yamlrocks==' requirements_test.txt | cut -d'#' -f1)"
- name: Sync pinned versions
run: python script/sync_dependency_versions.py --root pull-request
- name: Push changes
working-directory: pull-request
run: |
if git diff --quiet; then
echo "All pinned versions already match the requirements files."
exit 0
fi
git config user.name "esphome[bot]"
git config user.email "115708604+esphome[bot]@users.noreply.github.com"
git commit -am "Sync pinned tool versions with requirements files"
git push
+17 -17
View File
@@ -28,26 +28,26 @@ jobs:
permission-pull-requests: write # pulls.create / pulls.update to open or refresh the sync PR
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Checkout Home Assistant
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: home-assistant/core
path: lib/home-assistant
- name: Setup Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.14"
- name: Set up uv
# An order of magnitude faster than pip on cold boots, with its
# own wheel cache. ``--system`` (below) installs into the
# setup-python interpreter so subsequent ``pre-commit`` /
# setup-python interpreter so subsequent ``prek`` /
# ``script/run-in-env.py`` steps find the deps without a
# ``uv run`` prefix.
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
enable-cache: true
# Pin uv version so the action does not have to fetch the
@@ -58,19 +58,19 @@ jobs:
- name: Install Home Assistant
run: |
uv pip install --system -e lib/home-assistant
uv pip install --system -r requirements.txt -r requirements_test.txt pre-commit
uv pip install --system -r requirements.txt -r requirements_test.txt
- name: Sync
run: |
python ./script/sync-device_class.py
- name: Apply pre-commit auto-fixes
- name: Apply prek auto-fixes
# First pass: let formatters (ruff, end-of-file-fixer, etc.) modify
# files. pre-commit exits non-zero whenever a hook touches anything,
# files. prek exits non-zero whenever a hook touches anything,
# which would otherwise abort the workflow before the auto-fixes
# can flow into the sync PR.
#
# SKIP:
# PREK_SKIP:
# - no-commit-to-branch is a local guard against committing on
# dev/release/beta; CI runs on dev by definition, and
# peter-evans/create-pull-request creates the branch itself.
@@ -79,25 +79,25 @@ jobs:
# the runtime deps (HA + requirements*.txt); main CI already
# gates pylint on real PRs.
env:
SKIP: pylint,no-commit-to-branch
run: python script/run-in-env.py pre-commit run --all-files || true
PREK_SKIP: pylint,no-commit-to-branch
run: python script/run-in-env.py prek run --all-files || true
- name: Verify pre-commit clean
- name: Verify prek clean
# Second pass: re-run all hooks against the now-fixed tree.
# Auto-fixers exit 0 (nothing to change); any remaining failure
# from a check-only hook (flake8 / yamllint / ci-custom) is a
# real issue and fails the workflow loudly. Same SKIP list as
# real issue and fails the workflow loudly. Same PREK_SKIP list as
# above for the same reasons.
env:
SKIP: pylint,no-commit-to-branch
run: python script/run-in-env.py pre-commit run --all-files
PREK_SKIP: pylint,no-commit-to-branch
run: python script/run-in-env.py prek run --all-files
- name: Commit changes
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
commit-message: "Synchronise Device Classes from Home Assistant"
committer: esphomebot <esphome@openhomefoundation.org>
author: esphomebot <esphome@openhomefoundation.org>
committer: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
author: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
branch: sync/device-classes
delete-branch: true
title: "Synchronise Device Classes from Home Assistant"
@@ -0,0 +1,98 @@
---
name: Refresh integration test durations
on:
workflow_dispatch:
schedule:
- cron: "45 5 * * 1"
# Repo writes (branch push, PR open) happen via the App token minted below,
# so the workflow's GITHUB_TOKEN does not need any write scopes.
permissions:
contents: read
actions: read # gh api / gh run download for the CI junit artifacts
jobs:
sync:
name: Refresh integration test durations
runs-on: ubuntu-latest
if: github.repository == 'esphome/esphome'
steps:
- name: Generate a token
id: generate-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
client-id: ${{ vars.ESPHOME_GITHUB_APP_CLIENT_ID }}
private-key: ${{ secrets.ESPHOME_GITHUB_APP_PRIVATE_KEY }}
permission-contents: write # push the sync branch
permission-pull-requests: write # open or refresh the sync PR
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.13"
- name: Refresh from the newest usable dev run
env:
GH_TOKEN: ${{ github.token }}
run: |
# Only full matrix dev runs upload junit-integration-* artifacts
# (see the integration-tests job); the merge script re-checks
# coverage regardless.
# Newest-first candidates via their bucket-0 artifact. Fork PRs run
# their own ci.yml, so name and branch are spoofable; require
# same-repo. Assignment failures trip set -e and fail loudly.
candidates=$(
gh api "repos/${GITHUB_REPOSITORY}/actions/artifacts?name=junit-integration-0&per_page=100" \
--jq '.artifacts[] | select(.expired | not) | .workflow_run
| select(.head_branch == "dev" and .head_repository_id != null
and .head_repository_id == .repository_id)
| .id'
)
# Green runs first, then the rest newest first; a run missing a
# bucket fails the coverage check and the next one is tried
green=""
rest=""
for id in ${candidates}; do
conclusion=$(gh api "repos/${GITHUB_REPOSITORY}/actions/runs/${id}" --jq '.conclusion // ""')
if [ "${conclusion}" = "success" ]; then
green="${green} ${id}"
elif [ -n "${conclusion}" ]; then
rest="${rest} ${id}"
fi
done
# helpers.py imports colorama; the script needs nothing else
pip install colorama
for id in ${green} ${rest}; do
rm -rf /tmp/junit
if ! gh run download "${id}" --repo "${GITHUB_REPOSITORY}" -p "junit-integration-*" -D /tmp/junit; then
echo "::warning::Could not download artifacts for run ${id}; trying the next"
continue
fi
status=0
python script/update_integration_test_durations.py /tmp/junit || status=$?
if [ "${status}" -eq 0 ]; then
echo "Refreshed from run ${id}"
exit 0
fi
# Only EXIT_LOW_COVERAGE (3) from the script advances to the next run
[ "${status}" -eq 3 ] || exit 1
echo "::warning::Run ${id} covers too few test files; trying the next"
done
echo "::error::No dev CI run with usable junit artifacts in range; the feed is starved"
exit 1
- name: Commit changes
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
commit-message: "[ci] Refresh integration test durations"
committer: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
author: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
branch: sync/integration-durations
delete-branch: true
title: "[ci] Refresh integration test durations"
body-path: .github/PULL_REQUEST_TEMPLATE.md
token: ${{ steps.generate-token.outputs.token }}
+5
View File
@@ -133,14 +133,19 @@ CTestTestfile.cmake
.gcc-flags.json
config/
# Test fixture config/ directories are tracked (the rule above is the dashboard dir)
!tests/component_tests/**/config/
tests/build/
tests/.esphome/
# Output kept by failing tests for inspection; uploaded by CI
test_artifacts/
/.temp-clang-tidy.cpp
/.temp/
.pio/
sdkconfig.*
!sdkconfig.defaults
!sdkconfig.defaults.*
.tests/
+4 -12
View File
@@ -1,17 +1,16 @@
---
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
ci:
autoupdate_commit_msg: 'pre-commit: autoupdate'
autoupdate_schedule: off # Disabled until ruff versions are synced between deps and pre-commit
# Skip hooks that have issues in pre-commit CI environment
skip: [pylint, clang-tidy-hash]
skip: [pylint]
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.15.15
rev: v0.16.6
hooks:
# Run the linter.
- id: ruff
@@ -40,9 +39,9 @@ repos:
rev: v3.21.2
hooks:
- id: pyupgrade
args: [--py311-plus]
args: [--py312-plus]
- repo: https://github.com/adrienverge/yamllint.git
rev: v1.37.1
rev: v1.38.0
hooks:
- id: yamllint
exclude: ^(\.clang-format|\.clang-tidy)$
@@ -59,13 +58,6 @@ repos:
language: system
types: [python]
files: ^esphome/.+\.py$
- id: clang-tidy-hash
name: Update clang-tidy hash
entry: python script/clang_tidy_hash.py --update-if-changed
language: python
files: ^(\.clang-tidy|platformio\.ini|requirements_dev\.txt)$
pass_filenames: false
additional_dependencies: []
- id: ci-custom
name: ci-custom
entry: python script/run-in-env.py script/ci-custom.py
+206 -33
View File
@@ -9,12 +9,12 @@ This document provides essential context for AI models interacting with this pro
## 2. Core Technologies & Stack
* **Languages:** Python (>=3.11), C++ (gnu++20)
* **Languages:** Python (>=3.12), C++ (gnu++20)
* **Frameworks & Runtimes:** PlatformIO, Arduino, ESP-IDF.
* **Build Systems:** PlatformIO is the primary build system. CMake is used as an alternative.
* **Configuration:** YAML.
* **Key Libraries/Dependencies:**
* **Python:** `voluptuous` (for configuration validation), `PyYAML` (for parsing configuration files), `paho-mqtt` (for MQTT communication), `tornado` (for the web server), `aioesphomeapi` (for the native API).
* **Python:** `voluptuous` (for configuration validation), `PyYAML` (for parsing configuration files), `paho-mqtt` (for MQTT communication), `aioesphomeapi` (for the native API).
* **C++:** `ArduinoJson` (for JSON serialization/deserialization), `AsyncMqttClient-esphome` (for MQTT), `ESPAsyncWebServer` (for the web server).
* **Package Manager(s):** `pip` (for Python dependencies), `platformio` (for C++/PlatformIO dependencies).
* **Communication Protocols:** Protobuf (for native API), MQTT, HTTP.
@@ -35,7 +35,6 @@ This document provides essential context for AI models interacting with this pro
2. **Code Generation** (`esphome/codegen.py`, `esphome/cpp_generator.py`): Manages Python to C++ code generation, template processing, and build flag management.
3. **Component System** (`esphome/components/`): Contains modular hardware and software components with platform-specific implementations and dependency management.
4. **Core Framework** (`esphome/core/`): Manages the application lifecycle, hardware abstraction, and component registration.
5. **Dashboard** (`esphome/dashboard/`): A web-based interface for device configuration, management, and OTA updates.
* **Platform Support:**
1. **ESP32** (`components/esp32/`): Espressif ESP32 family. Supports multiple variants (Original, C2, C3, C5, C6, H2, P4, S2, S3) with ESP-IDF framework. Arduino framework supports only a subset of the variants (Original, C3, S2, S3).
@@ -45,6 +44,16 @@ This document provides essential context for AI models interacting with this pro
## 4. Coding Conventions & Style Guide
**Read the developer documentation before writing a component.** https://developers.esphome.io covers the
component lifecycle, the main loop, and the reasoning behind the rules below in far more depth than this
file does, and it is the authority when they disagree. The most useful starting points:
* https://developers.esphome.io/architecture/components/ - component lifecycle, `setup()`, `loop()`,
setup priorities, and how a component is registered.
* https://developers.esphome.io/architecture/components/advanced/ - choosing between `loop()`,
`set_interval`, `set_timeout` and `defer`; waking the loop from another thread; the RAM cost of each.
* https://developers.esphome.io/contributing/code/ - contribution rules, public API and breaking changes.
* **Formatting:**
* **Python:** Uses `ruff` and `flake8` for linting and formatting. Configuration is in `pyproject.toml`.
* **C++:** Uses `clang-format` for formatting. Configuration is in `.clang-format`.
@@ -58,6 +67,25 @@ This document provides essential context for AI models interacting with this pro
- Function-local constants: `lower_snake_case`
- Protected/private fields: `lower_snake_case_with_trailing_underscore_`
- Favor descriptive names over abbreviations
- Enumerator names: prefix every value of an `enum class` with the enum name converted to
`UPPER_SNAKE_CASE` (e.g. `UARTFlushResult::UART_FLUSH_RESULT_SUCCESS`). Never use bare
names like `SUCCESS`, `FAILURE`, `OK`, or `FAIL`: platform SDK headers define macros with
these common names (for example the Realtek SDKs used by LibreTiny define
`#define SUCCESS 0` in `basic_types.h`), and the preprocessor replaces the enumerator
before the compiler sees it, breaking the build and clang-tidy on those platforms.
* **Python Idioms:**
* **Assignment expressions (PEP 572):** Prefer the walrus operator (`:=`) wherever it removes a redundant lookup or a throwaway temporary. The most common case in component code is presence-checking a config key and then indexing it separately — fetch once with `.get()` and bind in the condition instead:
```python
# Bad - looks up CONF_BLAH twice
if CONF_BLAH in config:
cg.add(var.set_blah(config[CONF_BLAH]))
# Good - single lookup, value bound inline
if (blah := config.get(CONF_BLAH)) is not None:
cg.add(var.set_blah(blah))
```
The same applies to `while` loops and comprehensions where it avoids recomputing a value. Don't contort code to use it — reach for `:=` only when it genuinely cuts repetition or an extra assignment line.
* **C++ Field Visibility:**
* **Prefer `protected`:** Use `protected` for most class fields to enable extensibility and testing. Fields should be `lower_snake_case_with_trailing_underscore_`.
@@ -124,6 +152,47 @@ This document provides essential context for AI models interacting with this pro
* **Indentation:** Use spaces (two per indentation level), not tabs
* **Type aliases:** Prefer `using type_t = int;` over `typedef int type_t;`
* **Line length:** Wrap lines at no more than 120 characters
* **Timing in `loop()`:** Never call `millis()` in a `loop()` body. The current tick's timestamp is
already cached - use `App.get_loop_component_start_time()` (from `esphome/core/application.h`).
Only reach for `millis()` when you genuinely need sub-tick resolution inside a long operation.
* **The main loop runs every 16 ms.** A rate-limit gate shorter than that does nothing: the check
passes on essentially every pass of the loop, so it costs a comparison and buys nothing. Pick an
interval comfortably coarser than 16 ms, or drop the gate entirely and accept running every loop.
```cpp
// Bad - a 10ms gate against a 16ms loop never holds anything back
static constexpr uint32_t POLL_INTERVAL_MS = 10;
const uint32_t now = millis();
if (now - this->last_poll_ < POLL_INTERVAL_MS)
return;
this->last_poll_ = now;
```
```cpp
// Good - an interval that actually rate limits, off the cached timestamp
static constexpr uint32_t POLL_INTERVAL_MS = 100;
const uint32_t now = App.get_loop_component_start_time();
if (now - this->last_poll_ < POLL_INTERVAL_MS)
return;
this->last_poll_ = now;
```
Pick the primitive by cadence: under 250 ms use a gated `loop()`; 500 ms and above use
`set_interval`. Full reasoning, including why `set_interval` costs more below 500 ms:
https://developers.esphome.io/architecture/components/advanced/#quick-rule-of-thumb
* **Don't override a default with the same value:** if a base class method already returns what you
want, do not override it. `Component::get_setup_priority()` returns `setup_priority::DATA`, so a
component that wants `DATA` should simply leave it alone.
```cpp
// Bad - this is exactly what the base class already does
float get_setup_priority() const override { return setup_priority::DATA; }
```
* **Logging string literals:** wrap literals passed as `%s` arguments in `LOG_STR_LITERAL()` so they
can be stored in flash rather than RAM.
```cpp
// Bad
ESP_LOGV(TAG, "Key %u %s", key, pressed ? "pressed" : "released");
// Good
ESP_LOGV(TAG, "Key %u %s", key, pressed ? LOG_STR_LITERAL("pressed") : LOG_STR_LITERAL("released"));
```
* **Constructor parameters vs setters:** Component properties that are both **required** and **invariant**
(never change after construction) should be constructor parameters rather than set via setter methods.
This makes the dependency explicit and prevents use of the object in an incompletely-initialized state.
@@ -179,11 +248,14 @@ This document provides essential context for AI models interacting with this pro
my_component_ns = cg.esphome_ns.namespace("my_component")
MyComponent = my_component_ns.class_("MyComponent", cg.Component)
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_id(MyComponent),
cv.Required(CONF_KEY): cv.string,
cv.Optional(CONF_PARAM, default=42): cv.int_,
}).extend(cv.COMPONENT_SCHEMA)
CONFIG_SCHEMA = cv.Schema(
{
cv.GenerateID(): cv.declare_id(MyComponent),
cv.Required(CONF_KEY): cv.string,
cv.Optional(CONF_PARAM, default=42): cv.int_,
}
).extend(cv.COMPONENT_SCHEMA)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
@@ -217,7 +289,12 @@ This document provides essential context for AI models interacting with this pro
- **Sensor:**
```python
from esphome.components import sensor
CONFIG_SCHEMA = sensor.sensor_schema(MySensor).extend(cv.polling_component_schema("60s"))
CONFIG_SCHEMA = sensor.sensor_schema(MySensor).extend(
cv.polling_component_schema("60s")
)
async def to_code(config):
var = await sensor.new_sensor(config)
await cg.register_component(var, config)
@@ -226,7 +303,10 @@ This document provides essential context for AI models interacting with this pro
- **Binary Sensor:**
```python
from esphome.components import binary_sensor
CONFIG_SCHEMA = binary_sensor.binary_sensor_schema().extend({ ... })
CONFIG_SCHEMA = binary_sensor.binary_sensor_schema().extend({...})
async def to_code(config):
var = await binary_sensor.new_binary_sensor(config)
```
@@ -234,7 +314,10 @@ This document provides essential context for AI models interacting with this pro
- **Switch:**
```python
from esphome.components import switch
CONFIG_SCHEMA = switch.switch_schema().extend({ ... })
CONFIG_SCHEMA = switch.switch_schema().extend({...})
async def to_code(config):
var = await switch.new_switch(config)
```
@@ -251,10 +334,13 @@ This document provides essential context for AI models interacting with this pro
```python
from esphome import automation
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_id(MyComponent),
cv.Optional(CONF_ON_STATE): automation.validate_automation({}),
}).extend(cv.COMPONENT_SCHEMA)
CONFIG_SCHEMA = cv.Schema(
{
cv.GenerateID(): cv.declare_id(MyComponent),
cv.Optional(CONF_ON_STATE): automation.validate_automation({}),
}
).extend(cv.COMPONENT_SCHEMA)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
@@ -304,11 +390,14 @@ This document provides essential context for AI models interacting with this pro
```python
TurnOnTrigger = my_ns.class_("TurnOnTrigger", automation.Trigger.template())
CONFIG_SCHEMA = cv.Schema({
cv.Optional(CONF_ON_TURN_ON): automation.validate_automation(
{cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(TurnOnTrigger)}
),
})
CONFIG_SCHEMA = cv.Schema(
{
cv.Optional(CONF_ON_TURN_ON): automation.validate_automation(
{cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(TurnOnTrigger)}
),
}
)
async def to_code(config):
for conf in config.get(CONF_ON_TURN_ON, []):
@@ -356,7 +445,10 @@ This document provides essential context for AI models interacting with this pro
```
Register with `@automation.register_condition("my_component.is_active", MyCondition, schema)`.
* **Type Hints:** Type-hint all function signatures, including test functions and config validators (e.g. `def validate_x(config: ConfigType) -> ConfigType:`, `def test_x() -> None:`). Import `ConfigType` from `esphome.types`.
* **Configuration Validation:**
* **Reuse existing validators:** Before writing a custom validator, check for an existing one in `config_validation.py` and compose it in `cv.All(...)` rather than duplicating logic across components. For example, rename a config key with `cv.rename_key(CONF_OLD, CONF_NEW, removed_in="2026.6.0")`, and reject mutually-exclusive keys with `cv.has_at_most_one_key(...)` / `cv.has_exactly_one_key(...)`. See how `api` composes `cv.has_exactly_one_key` + `cv.rename_key`.
* **Common Validators:** `cv.int_`, `cv.float_`, `cv.string`, `cv.boolean`, `cv.int_range(min=0, max=100)`, `cv.positive_int`, `cv.percentage`.
* **Complex Validation:** `cv.All(cv.string, cv.Length(min=1, max=50))`, `cv.Any(cv.int_, cv.string)`.
* **Platform-Specific:** `cv.only_on(["esp32", "esp8266"])`, `esp32.only_on_variant(...)`, `cv.only_on_esp32`, `cv.only_on_esp8266`, `cv.only_on_rp2040`.
@@ -369,6 +461,7 @@ This document provides essential context for AI models interacting with this pro
.extend(i2c.i2c_device_schema(0x48))
.extend(spi.spi_device_schema(cs_pin_required=True))
```
* **Constants:** `esphome/const.py` is frozen — do not add new `CONF_` constants there. Define a component-local constant in the component's own `.py` (as with `CONF_PARAM` above); for a constant shared by multiple components, add it to `esphome/components/const/__init__.py`. CI (`lint_constants_usage`) fails if the same constant is defined in three or more component files. Constants used in core files (i.e. those not under `esphome/components`) may be added to `esphome/const.py` but will require adjustment to the CI validation check.
## 5. Key Files & Entrypoints
@@ -376,7 +469,7 @@ This document provides essential context for AI models interacting with this pro
* **Configuration:**
* `pyproject.toml`: Defines the Python project metadata and dependencies.
* `platformio.ini`: Configures the PlatformIO build environments for different microcontrollers.
* `.pre-commit-config.yaml`: Configures the pre-commit hooks for linting and formatting.
* `.pre-commit-config.yaml`: Configures the lint and format hooks, run by `prek`.
* **CI/CD Pipeline:** Defined in `.github/workflows`.
* **Static Analysis & Development:**
* `esphome/core/defines.h`: A comprehensive header file containing all `#define` directives that can be added by components using `cg.add_define()` in Python. This file is used exclusively for development, static analysis tools, and CI testing - it is not used during runtime compilation. When developing components that add new defines, they must be added to this file to ensure proper IDE support and static analysis coverage. The file includes feature flags, build configurations, and platform-specific defines that help static analyzers understand the complete codebase without needing to compile for specific platforms.
@@ -384,7 +477,7 @@ This document provides essential context for AI models interacting with this pro
## 6. Development & Testing Workflow
* **Local Development Environment:** Use the provided Docker container or create a Python virtual environment and install dependencies from `requirements_dev.txt`.
* **Running Commands:** Use the `script/run-in-env.py` script to execute commands within the project's virtual environment. For example, to run the linter: `python3 script/run-in-env.py pre-commit run`.
* **Running Commands:** Use the `script/run-in-env.py` script to execute commands within the project's virtual environment. For example, to run the linter: `python3 script/run-in-env.py prek run`.
* **Testing:**
* **Python:** Run unit tests with `pytest`.
* **C++:** Use `clang-tidy` for static analysis.
@@ -415,13 +508,14 @@ This document provides essential context for AI models interacting with this pro
When a PR's only edits to a component are `validate.*.yaml` files (no source changes, no `test.*.yaml` changes, and the component isn't pulled in as a dependency of another changed component), CI skips the compile stage for that component entirely and only runs config validation. This is decided in `script/determine-jobs.py` via `_component_change_is_validate_only` and surfaced as the `validate_only_components` output that the `test-build-components-split` job consumes.
* **Test Grouping with Packages:** Components that use shared bus packages can be grouped together in CI to reduce build count. **Never define buses (uart, i2c, spi, modbus) directly in test YAML files** — always use packages from `test_build_components/common/`:
* **Test Grouping with Packages:** Components that use shared bus packages can be grouped together in CI to reduce build count. **Never define buses (uart, i2c, spi, modbus) directly in test YAML files** — always use packages from `test_build_components/common/`.
All includes in test files must go through dict-style `packages:` so that batch grouping works correctly — the grouping scripts only understand dict-style packages. Never use list-style packages (`packages: [- !include ...]`) or top-level merge keys (`<<: !include common.yaml`). Bus packages are keyed by the bus name; the component's `common.yaml` is keyed by the component name (e.g. `cst328: !include common.yaml`):
```yaml
# test.esp32-idf.yaml — use packages for buses
# test.esp32-idf.yaml — everything included via named packages
packages:
uart: !include ../../test_build_components/common/uart_115200/esp32-idf.yaml
<<: !include common.yaml
my_component: !include common.yaml
```
```yaml
# common.yaml — component config only, NO bus definitions
@@ -443,7 +537,6 @@ This document provides essential context for AI models interacting with this pro
* **Debug Tools:**
- `esphome config <file>.yaml` to validate configuration.
- `esphome compile <file>.yaml` to compile without uploading.
- Check the Dashboard for real-time logs.
- Use component-specific debug logging.
* **Common Issues:**
- **Import Errors**: Check component dependencies and `PYTHONPATH`.
@@ -457,9 +550,10 @@ This document provides essential context for AI models interacting with this pro
1. **Fork & Branch:** Create a new branch based on the `dev` branch (always use `git checkout -b <branch-name> dev` to ensure you're branching from `dev`, not the currently checked out branch).
2. **Make Changes:** Adhere to all coding conventions and patterns.
3. **Test:** Create component tests for all supported platforms and run the full test suite locally.
4. **Lint:** Run `pre-commit` to ensure code is compliant.
4. **Lint:** Run `prek` to ensure code is compliant.
5. **Commit:** Commit your changes. There is no strict format for commit messages.
6. **Pull Request:** Submit a PR against the `dev` branch. The Pull Request title should have a prefix of the component being worked on (e.g., `[display] Fix bug`, `[abc123] Add new component`). Update documentation, examples, and add `CODEOWNERS` entries as needed. Pull requests should always be made using the `.github/PULL_REQUEST_TEMPLATE.md` template - fill out all sections completely without removing any parts of the template.
6. **Pull Request:** Submit a PR against the `dev` branch. The Pull Request title must start with a `[tag]` prefix. For component work, use the component name (e.g., `[display] Fix bug`, `[abc123] Add new component`); for changes to shared/core code that isn't tied to a single component, use `[core]` (e.g., `[core] Add validator`). Update documentation, examples, and add `CODEOWNERS` entries as needed. Pull requests should always be made using the `.github/PULL_REQUEST_TEMPLATE.md` template - fill out all sections completely without removing any parts of the template.
7. **Comments:** When commenting on GitHub PRs or issues, don't tag contributors, especially bots. Avoid referring to list items (e.g. from reviews) with the form #nn - this will be interpreted by GitHub as a reference to issue or PR nn. Keep comments short and exclude irrelevant details, backstories, restatement of previous comments and anything that is already obvious to the reader.
* **Documentation Contributions:**
* Documentation is hosted in the separate `esphome/esphome.io` repository.
@@ -520,6 +614,36 @@ This document provides essential context for AI models interacting with this pro
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.
**Listener and child-entity registration lists are the most common case, and the most commonly
missed.** A `register_*()` method called once per child at code generation time has a count that
is known at compile time, so it should never be a `std::vector`. Use `cg.slot_counter()`: it
returns a function that each consumer calls once per slot it will occupy, and after every
`to_code` has run it emits the define with the final count. When nothing registers, no define is
emitted and the storage plus its registration method compile out entirely.
```python
# hub component's __init__.py
_request_listener_slot = cg.slot_counter("MY_COMPONENT_LISTENER_COUNT")
async def register_listener(hub: MockObj, var: MockObj) -> None:
_request_listener_slot()
cg.add(hub.register_listener(var))
```
When several instances each own a list declared at the same size (one per hub of a
`MULTI_CONF` component), pass the owning object as the key, `_request_listener_slot(str(hub))`;
the define is then the largest count any one key requested instead of the total.
```cpp
#ifdef MY_COMPONENT_LISTENER_COUNT
void register_listener(MyComponentListener *listener);
#endif
protected:
#ifdef MY_COMPONENT_LISTENER_COUNT
StaticVector<MyComponentListener *, MY_COMPONENT_LISTENER_COUNT> listeners_;
#endif
```
Request slots from `to_code`, not from a job that runs after `CoroPriority.FINAL` - a late
request raises rather than silently undercounting.
3. **Runtime-known sizes:** Use `FixedVector` from `esphome/core/helpers.h` when the size is only known at runtime initialization.
```cpp
// Bad - generates STL realloc code (_M_realloc_insert)
@@ -557,9 +681,25 @@ 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. **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.
5. **Strings set once from configuration:** Use `StringRef` (`esphome/core/string_ref.h`) rather than
`std::string`. Code generation passes a string literal that lives in flash for the life of the
program, so storing a `std::string` copies it onto the heap for nothing. `StringRef` is a
non-owning pointer plus length; it does not copy, and it must only ever refer to storage that
outlives it (a string literal, or a buffer owned elsewhere).
```cpp
// Bad - heap copy of a literal that is already in flash
void set_keys(std::string keys) { this->keys_ = std::move(keys); }
std::string keys_;
```
```cpp
// Good - no allocation
void set_keys(const char *keys) { this->keys_ = StringRef(keys); }
StringRef keys_;
```
6. **Detection:** Look for these patterns in compiler output:
6. **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.
7. **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)
@@ -605,6 +745,7 @@ This document provides essential context for AI models interacting with this pro
_component_state = []
_use_feature = None
def enable_feature():
global _use_feature
_use_feature = True
@@ -624,20 +765,24 @@ This document provides essential context for AI models interacting with this pro
DOMAIN = "my_component"
@dataclass
class MyComponentData:
feature_enabled: bool = False
item_count: int = 0
items: list[str] = field(default_factory=list)
def _get_data() -> MyComponentData:
if DOMAIN not in CORE.data:
CORE.data[DOMAIN] = MyComponentData()
return CORE.data[DOMAIN]
def request_feature() -> None:
_get_data().feature_enabled = True
def add_item(item: str) -> None:
_get_data().items.append(item)
```
@@ -645,7 +790,7 @@ This document provides essential context for AI models interacting with this pro
If you need a real-world example, search for components that use `@dataclass` with `CORE.data` in the codebase. Note: Some components may use `TypedDict` for dictionary-based storage; both patterns are acceptable depending on your needs.
**Why this matters:**
- Module-level globals persist between compilation runs if the dashboard doesn't fork/exec
- Module-level globals persist between compilation runs if the host process (e.g. device-builder) doesn't fork/exec
- `CORE.data` automatically clears between runs
- Namespacing under `DOMAIN` prevents key collisions between components
- `@dataclass` provides type safety and cleaner attribute access
@@ -692,9 +837,37 @@ This document provides essential context for AI models interacting with this pro
```
* **Deprecation Pattern (Python):**
For a renamed config key, use the shared `cv.rename_key` validator with `removed_in` (and `component` for context) — it warns and auto-migrates:
```python
CONFIG_SCHEMA = cv.All(
cv.rename_key(
CONF_OLD_KEY, CONF_NEW_KEY, removed_in="2026.6.0", component="my_component"
),
cv.Schema({...}),
)
```
For other deprecations, warn manually during validation:
```python
# Remove before 2026.6.0
if CONF_OLD_KEY in config:
_LOGGER.warning(f"'{CONF_OLD_KEY}' deprecated, use '{CONF_NEW_KEY}'. Removed in 2026.6.0")
_LOGGER.warning(
f"'{CONF_OLD_KEY}' deprecated, use '{CONF_NEW_KEY}'. Removed in 2026.6.0"
)
config[CONF_NEW_KEY] = config.pop(CONF_OLD_KEY) # Auto-migrate
```
## 9. English Language
The project uses English for non-code content. When drafting documentation, code comments, commit messages,
PR descriptions, and similar text, avoid technical jargon. Instead, express concepts in plain English,
using standard technical terms only when required. Ensure the text is readily comprehensible to a wide
audience, including non-native English speakers.
## 10. Code Comments
Code comments on individual lines should be used only where necessary to flag issues that may not be obvious
on a simple reading of the code. Keep them short (e.g. 1 or 2 lines).
Function and method comment blocks may include more detail as required to make
calling contracts clear and document parameter usage, but should still be kept concise.
Avoid redundancy and repetition; comments should never simply restate what the code already says.
+40 -5
View File
@@ -19,7 +19,6 @@ esphome/components/ac_dimmer/* @glmnet
esphome/components/adc/* @esphome/core
esphome/components/adc128s102/* @DeerMaximum
esphome/components/addressable_light/* @justfalter
esphome/components/ade7880/* @kpfleming
esphome/components/ade7953/* @angelnu
esphome/components/ade7953_base/* @angelnu
esphome/components/ade7953_i2c/* @angelnu
@@ -28,7 +27,7 @@ esphome/components/ads1118/* @solomondg1
esphome/components/ags10/* @mak-42
esphome/components/aic3204/* @kbx81
esphome/components/airthings_ble/* @jeromelaban
esphome/components/airthings_wave_base/* @jeromelaban @kpfleming @ncareau
esphome/components/airthings_wave_base/* @jeromelaban @ncareau
esphome/components/airthings_wave_mini/* @ncareau
esphome/components/airthings_wave_plus/* @jeromelaban @precurse
esphome/components/alarm_control_panel/* @grahambrown11 @hwstar
@@ -70,12 +69,16 @@ esphome/components/bh1750/* @OttoWinter
esphome/components/bh1900nux/* @B48D81EFCC
esphome/components/binary_sensor/* @esphome/core
esphome/components/bk72xx/* @kuba2k2
esphome/components/bk72xx_ble/* @Bl00d-B0b
esphome/components/bk72xx_ble_tracker/* @Bl00d-B0b
esphome/components/bl0906/* @athom-tech @jesserockz @tarontop
esphome/components/bl0939/* @ziceva
esphome/components/bl0940/* @dan-s-github @tobias-
esphome/components/bl0942/* @dbuezas @dwmw2
esphome/components/ble_client/* @buxtronix @clydebarrow
esphome/components/ble_device_base/* @Bl00d-B0b
esphome/components/ble_nus/* @tomaszduda23
esphome/components/bluetooth_connection/* @bdraco @jesserockz
esphome/components/bluetooth_proxy/* @bdraco @jesserockz
esphome/components/bm8563/* @abmantis
esphome/components/bme280_base/* @esphome/core
@@ -84,6 +87,7 @@ esphome/components/bme680_bsec/* @trvrnrth
esphome/components/bme68x_bsec2/* @kbx81 @neffs
esphome/components/bme68x_bsec2_i2c/* @kbx81 @neffs
esphome/components/bmi160/* @flaviut
esphome/components/bmi270/* @clydebarrow
esphome/components/bmp280_base/* @ademuri
esphome/components/bmp280_i2c/* @ademuri
esphome/components/bmp280_spi/* @ademuri
@@ -122,9 +126,12 @@ esphome/components/cover/* @esphome/core
esphome/components/cs5460a/* @balrog-kun
esphome/components/cse7761/* @berfenger
esphome/components/cst226/* @clydebarrow
esphome/components/cst328/* @latonita
esphome/components/cst816/* @clydebarrow
esphome/components/cst9220/* @clydebarrow
esphome/components/ct_clamp/* @jesserockz
esphome/components/current_based/* @djwmarcx
esphome/components/d01/* @ch604
esphome/components/dac7678/* @NickB1
esphome/components/daikin_arc/* @MagicBear
esphome/components/daikin_brc/* @hagak
@@ -139,10 +146,12 @@ esphome/components/dfplayer/* @glmnet
esphome/components/dfrobot_sen0395/* @niklasweber
esphome/components/dht/* @OttoWinter
esphome/components/display_menu_base/* @numo68
esphome/components/dlms_meter/* @SimonFischer04
esphome/components/dlms_meter/* @latonita @PolarGoose @SimonFischer04 @Tomer27cz
esphome/components/dps310/* @kbx81
esphome/components/ds1307/* @badbadc0ffee
esphome/components/ds1603l/* @JakeLC15
esphome/components/ds2484/* @mrk-its
esphome/components/ds248x/* @tomwellnitz
esphome/components/dsmr/* @glmnet @PolarGoose
esphome/components/duty_time/* @dudanov
esphome/components/ee895/* @Stock-M
@@ -185,6 +194,7 @@ esphome/components/ezo_pmp/* @carlos-sarmiento
esphome/components/factory_reset/* @anatoly-savchenkov
esphome/components/fastled_base/* @OttoWinter
esphome/components/feedback/* @ianchi
esphome/components/file/* @esphome/core
esphome/components/fingerprint_grow/* @alexborro @loongyh @OnFreund
esphome/components/font/* @clydebarrow @esphome/core
esphome/components/fs3000/* @kahrendt
@@ -206,6 +216,7 @@ esphome/components/gree/switch/* @nagyrobi
esphome/components/grove_gas_mc_v2/* @YorkshireIoT
esphome/components/grove_tb6612fng/* @max246
esphome/components/growatt_solar/* @leeuwte
esphome/components/gsl3670/* @clydebarrow
esphome/components/gt911/* @clydebarrow @jesserockz
esphome/components/haier/* @paveldn
esphome/components/haier/binary_sensor/* @paveldn
@@ -229,6 +240,7 @@ esphome/components/hlw8032/* @rici4kubicek
esphome/components/hm3301/* @freekode
esphome/components/hmac_md5/* @dwmw2
esphome/components/hmac_sha256/* @dwmw2
esphome/components/hoermann_hcp/* @zweckj
esphome/components/homeassistant/* @esphome/core @OttoWinter
esphome/components/homeassistant/number/* @landonr
esphome/components/homeassistant/switch/* @Links2004
@@ -266,6 +278,7 @@ esphome/components/integration/* @OttoWinter
esphome/components/internal_temperature/* @Mat931
esphome/components/interval/* @esphome/core
esphome/components/ir_rf_proxy/* @kbx81
esphome/components/it8951/* @koosoli @limengdu @Passific
esphome/components/jsn_sr04t/* @Mafus1
esphome/components/json/* @esphome/core
esphome/components/kamstrup_kmp/* @cfeenstra1024
@@ -279,6 +292,7 @@ esphome/components/ld2412/* @Rihan9
esphome/components/ld2420/* @descipher
esphome/components/ld2450/* @hareeshmu
esphome/components/ld24xx/* @kbx81
esphome/components/ld6002b/* @hepter
esphome/components/ledc/* @OttoWinter
esphome/components/libretiny/* @kuba2k2
esphome/components/libretiny_pwm/* @kuba2k2
@@ -286,11 +300,14 @@ esphome/components/light/* @esphome/core
esphome/components/lightwaverf/* @max246
esphome/components/lilygo_t5_47/touchscreen/* @jesserockz
esphome/components/lm75b/* @beormund
esphome/components/ln882h_ble/* @Bl00d-B0b
esphome/components/ln882h_ble_tracker/* @Bl00d-B0b
esphome/components/ln882x/* @lamauny
esphome/components/lock/* @esphome/core
esphome/components/logger/* @esphome/core
esphome/components/logger/select/* @clydebarrow
esphome/components/lps22/* @nagisa
esphome/components/lsm6ds/* @clydebarrow
esphome/components/ltr390/* @latonita @sjtrny
esphome/components/ltr501/* @latonita
esphome/components/ltr_als_ps/* @latonita
@@ -335,10 +352,12 @@ esphome/components/mipi_spi/* @clydebarrow
esphome/components/mitsubishi/* @RubyBailey
esphome/components/mitsubishi_cn105/* @crnjan
esphome/components/mixer/speaker/* @kahrendt
esphome/components/mk2pvrouter/* @FredM67
esphome/components/mlx90393/* @functionpointer
esphome/components/mlx90614/* @jesserockz
esphome/components/mmc5603/* @benhoff
esphome/components/mmc5983/* @agoode
esphome/components/modbus_client/* @exciton
esphome/components/modbus_controller/* @martgras
esphome/components/modbus_controller/binary_sensor/* @martgras
esphome/components/modbus_controller/number/* @martgras
@@ -351,6 +370,7 @@ esphome/components/modbus_server/* @exciton
esphome/components/mopeka_ble/* @Fabian-Schmidt @spbrogan
esphome/components/mopeka_pro_check/* @spbrogan
esphome/components/mopeka_std_check/* @Fabian-Schmidt
esphome/components/motion/* @esphome/core
esphome/components/mpl3115a2/* @kbickar
esphome/components/mpu6886/* @fabaff
esphome/components/ms8607/* @e28eta
@@ -364,6 +384,7 @@ esphome/components/nextion/switch/* @senexcrenshaw
esphome/components/nextion/text_sensor/* @senexcrenshaw
esphome/components/nfc/* @jesserockz @kbx81
esphome/components/noblex/* @AGalfra
esphome/components/noise/* @esphome/core
esphome/components/npi19/* @bakerkj
esphome/components/nrf52/* @tomaszduda23
esphome/components/number/* @esphome/core
@@ -379,9 +400,11 @@ esphome/components/pca6416a/* @Mat931
esphome/components/pca9554/* @bdraco @clydebarrow @hwstar
esphome/components/pcf85063/* @brogon
esphome/components/pcf8563/* @KoenBreeman
esphome/components/pcm5122/* @remcom
esphome/components/pi4ioe5v6408/* @jesserockz
esphome/components/pid/* @OttoWinter
esphome/components/pipsolar/* @andreashergert1984
esphome/components/pixoo/* @jesserockz
esphome/components/pm1006/* @habbie
esphome/components/pm2005/* @andrewjswan
esphome/components/pmsa003i/* @sjtrny
@@ -397,10 +420,12 @@ esphome/components/pn7160_i2c/* @jesserockz @kbx81
esphome/components/pn7160_spi/* @jesserockz @kbx81
esphome/components/power_supply/* @esphome/core
esphome/components/preferences/* @esphome/core
esphome/components/provisioning/* @esphome/core
esphome/components/psram/* @esphome/core
esphome/components/pulse_meter/* @cstaahl @stevebaxter @TrentHouliston
esphome/components/pvvx_mithermometer/* @pasiz
esphome/components/pylontech/* @functionpointer
esphome/components/qmi8658/* @clydebarrow
esphome/components/qmp6988/* @andrewpc
esphome/components/qr_code/* @wjtje
esphome/components/qspi_dbi/* @clydebarrow
@@ -418,10 +443,11 @@ esphome/components/rf_bridge/* @jesserockz
esphome/components/rgbct/* @jesserockz
esphome/components/ring_buffer/* @kahrendt
esphome/components/router/speaker/* @kahrendt
esphome/components/rp2040/* @jesserockz
esphome/components/rp2/* @jesserockz
esphome/components/rp2040_ble/* @bdraco
esphome/components/rp2040_pio_led_strip/* @Papa-DMan
esphome/components/rp2040_pwm/* @jesserockz
esphome/components/rp2_ble_tracker/* @bdraco
esphome/components/rpi_dpi_rgb/* @clydebarrow
esphome/components/rtl87xx/* @kuba2k2
esphome/components/rtttl/* @glmnet @ximex
@@ -442,8 +468,9 @@ esphome/components/select/* @esphome/core
esphome/components/sen0321/* @notjj
esphome/components/sen21231/* @shreyaskarnik
esphome/components/sen5x/* @martgras
esphome/components/sen6x/* @martgras @mebner86 @mikelawrence @tuct
esphome/components/sen6x/* @martgras @mebner86 @tuct
esphome/components/sendspin/* @kahrendt
esphome/components/sendspin/image/* @kahrendt
esphome/components/sendspin/media_player/* @kahrendt
esphome/components/sendspin/media_source/* @kahrendt
esphome/components/sendspin/sensor/* @kahrendt
@@ -452,6 +479,7 @@ esphome/components/sensirion_common/* @martgras
esphome/components/sensor/* @esphome/core
esphome/components/serial_proxy/* @kbx81
esphome/components/sfa30/* @ghsensdev
esphome/components/sfa40/* @NoQuarrel
esphome/components/sgp40/* @SenexCrenshaw
esphome/components/sgp4x/* @martgras @SenexCrenshaw
esphome/components/sha256/* @esphome/core
@@ -468,6 +496,7 @@ esphome/components/sm2335/* @Cossid
esphome/components/sml/* @alengwenus
esphome/components/smt100/* @piechade
esphome/components/sn74hc165/* @jesserockz
esphome/components/snapshot/* @clydebarrow
esphome/components/socket/* @esphome/core
esphome/components/sonoff_d1/* @anatoly-savchenkov
esphome/components/sound_level/* @kahrendt
@@ -494,6 +523,7 @@ esphome/components/ssd1331_base/* @kbx81
esphome/components/ssd1331_spi/* @kbx81
esphome/components/ssd1351_base/* @kbx81
esphome/components/ssd1351_spi/* @kbx81
esphome/components/st7123/* @miniskipper
esphome/components/st7567_base/* @latonita
esphome/components/st7567_i2c/* @latonita
esphome/components/st7567_spi/* @latonita
@@ -551,6 +581,7 @@ esphome/components/tuya/select/* @bearpawmaxim
esphome/components/tuya/sensor/* @jesserockz
esphome/components/tuya/switch/* @jesserockz
esphome/components/tuya/text_sensor/* @dentra
esphome/components/tuya/water_heater/* @iago-veiga
esphome/components/uart/* @esphome/core
esphome/components/uart/button/* @ssieb
esphome/components/uart/event/* @eoasmxd
@@ -558,6 +589,7 @@ esphome/components/uart/packet_transport/* @clydebarrow
esphome/components/udp/* @clydebarrow
esphome/components/ufire_ec/* @pvizeli
esphome/components/ufire_ise/* @pvizeli
esphome/components/ufm01/* @ljungqvist
esphome/components/ultrasonic/* @ssieb @swoboda1337
esphome/components/update/* @jesserockz
esphome/components/uponor_smatrix/* @kroimon
@@ -574,6 +606,7 @@ esphome/components/wake_on_lan/* @clydebarrow @willwill2will54
esphome/components/watchdog/* @oarcher
esphome/components/water_heater/* @dhoeben
esphome/components/waveshare_epaper/* @clydebarrow
esphome/components/waveshare_io_ch32v003/* @latonita
esphome/components/web_server/ota/* @esphome/core
esphome/components/web_server_base/* @esphome/core
esphome/components/web_server_idf/* @dentra
@@ -595,6 +628,7 @@ esphome/components/wk2212_spi/* @DrCoolZic
esphome/components/wl_134/* @hobbypunk90
esphome/components/wts01/* @alepee
esphome/components/x9c/* @EtienneMD
esphome/components/xdb401/* @RT530
esphome/components/xgzp68xx/* @gcormier
esphome/components/xiaomi_hhccjcy10/* @fariouche
esphome/components/xiaomi_lywsd02mmc/* @juanluss31
@@ -608,6 +642,7 @@ esphome/components/xpt2046/touchscreen/* @nielsnl68 @numo68
esphome/components/xxtea/* @clydebarrow
esphome/components/zephyr/* @tomaszduda23
esphome/components/zephyr_mcumgr/ota/* @tomaszduda23
esphome/components/zephyr_pwm/* @wiomoc
esphome/components/zhlt01/* @cfeenstra1024
esphome/components/zigbee/* @luar123 @tomaszduda23
esphome/components/zio_ultrasonic/* @kahrendt
+1 -1
View File
@@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 2026.6.0-dev
PROJECT_NUMBER = 2026.10.0-dev
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
+1
View File
@@ -6,3 +6,4 @@ recursive-include esphome *.cpp *.h *.tcc *.c
recursive-include esphome *.py.script
recursive-include esphome *.jinja
recursive-include esphome LICENSE.txt
recursive-include esphome requirements.txt
+197
View File
@@ -0,0 +1,197 @@
# ESPHome Threat Model
This document defines the trust boundary for the **ESPHome** repository — the
Python compiler/CLI and the device firmware it generates — so that real security
bugs can be told apart from defense-in-depth improvements. It gives contributors,
reviewers, and security researchers a clear answer to one question:
**does this issue let an _unauthenticated_ attacker do something they shouldn't?**
Related documents:
- Deployment guidance for operators:
https://esphome.io/guides/security_best_practices/
- The **Device Builder dashboard** (the web UI, its authentication, ingress,
Origin/Host gates, and peer-link pairing) lives in a separate repository and
has its own threat model. If your report concerns any of that, please read and
report there instead:
https://github.com/esphome/device-builder/blob/main/docs/THREAT_MODEL.md
## The trust boundary
For this repository there are two trusted inputs by design:
1. **The configuration.** Anyone who can supply or edit a YAML config is trusted
(see below).
2. **Authenticated peers of a running device** — clients holding the device's
API/OTA encryption key, API password, OTA password, or web server
credentials.
The security boundary is therefore **unauthenticated network traffic vs. those
trusted inputs.** A bug that lets an unauthenticated attacker cross it is a
security bug.
## Config authors are host-equivalent by design
Anyone who can supply or edit a configuration is **trusted with full code
execution on the host that runs `esphome`**, on purpose. This is what the product
does, not a flaw. A config author can already, through fully supported features:
- Run arbitrary **Python** at validation/compile time via `external_components:`
(and other component-import mechanisms) — ESPHome imports those packages as
ordinary Python.
- Run arbitrary **shell** commands through the compile/validate/flash toolchain
that ESPHome invokes as subprocesses.
- Read and write arbitrary files reachable by the process (e.g. via `!include`,
`packages:`, `dashboard_import:`, and generated build output).
Because of this, a malicious config author is equivalent to shell access on the
host running the build.
## What is *not* a security vulnerability
If exploiting an issue requires the ability to supply or edit configuration, it
is **not** a vulnerability in ESPHome, because that ability already grants host
code execution. This explicitly includes, among others:
- Template / expression injection in substitutions or any YAML string value
(e.g. Jinja `${...}` evaluation reaching Python internals). This grants no
capability a config author lacks.
- `!include` / `packages:` / `dashboard_import:` reading or fetching content
from surprising or remote locations.
- The validator or compiler crashing or behaving unexpectedly on adversarial
YAML.
- ESPHome running as root in the official container — that is the documented
deployment posture, reachable by the same caller through the features above.
These do not warrant a CVE or coordinated disclosure. Hardening in these areas
(for example, sandboxing template evaluation as least-surprise defense-in-depth)
is welcome as a normal enhancement PR, framed as cleanliness rather than a
security fix — not as a vulnerability remediation.
## What we do defend
These *are* security bugs in this repo, and we want to hear about them privately:
- Memory-safety or protocol bugs in the generated **device firmware** that are
remotely triggerable over the network (native API, web server, OTA, BLE,
captive portal, etc.) **without** valid credentials.
- Authentication or encryption bypass on the device — reaching API calls, OTA
updates, or the web server without the configured key/password.
- Flaws that weaken the device's API or OTA encryption (Noise), OTA auth, or
web server auth below their documented guarantees.
## The web server is an open HTTP API by design
The `web_server` component exposes a plain HTTP interface for viewing and
controlling entities, and, when the `web_server` OTA platform is enabled, for
uploading firmware at `/update`. Its only access controls are the optional
`web_server` `auth:` credentials and the network the device sits on.
When `auth:` is not configured, every endpoint is reachable by any client that
can reach the device. This is intentional; enabling `web_server` without `auth:`
is choosing an open control surface, in the same way that running native OTA
without a password leaves OTA open. The API is documented and is meant to be
called by other devices, scripts, and pages.
As defense-in-depth, the web server checks the `Origin` header on browser requests
to its entity control and state endpoints: a request whose `Origin` does not match
the address the device is served on is rejected, and the `allowed_origins` option
widens that list. This blocks the common "confused deputy" (CSRF) case where a page
the operator visits drives the device through their browser. It is **not** an
authentication boundary: it only constrains browsers. Any client that omits the
`Origin` header — `curl`, scripts, or other non-browser callers on the same
network — reaches every endpoint exactly as before. The check also does not cover
the web OTA `/update` endpoint. The device performs no CSRF-token or `Referer`
validation. The following are therefore **not** vulnerabilities in this repository:
- Requests without an `Origin` header (for example `curl`) reaching the control
endpoints, whether or not `web_server` `auth:` is set.
- Requests from an origin the operator added to `allowed_origins`.
- Cross-origin or CSRF firmware upload through the web OTA endpoint (`/update`) when
web OTA is enabled without `web_server` `auth:`. The `/update` endpoint is not
covered by the `Origin` check; this is the same exposure as running OTA without a
password.
The supported defenses are `web_server` `auth:`, protecting OTA (a web password or
a native OTA password), and keeping devices on a trusted, segmented network. See
the security best practices guide linked above.
What remains in scope is bypassing `web_server` `auth:` when it *is* configured,
and any memory-safety or protocol bug in the server reachable without credentials.
This section documents the current design and scope; it is not a judgment that the
design is optimal or that it will not change.
## OTA update encryption
The `esphome` OTA platform optionally encrypts updates with the same Noise
`NNpsk0` pattern the native API uses; one key protects the device. A device
whose `api:` block has an encryption key, static in the YAML or provisioned at
runtime, compiles in the transport and offers it on every OTA connection once
it holds a key, so an uploader presenting that key gets the guarantees below
even without an `ota: encryption:` block; only that block makes the device
require encryption. The guarantees are: the firmware image is confidential in
transit, the uploader is authenticated by the pre-shared key, and the plaintext
negotiation preceding the handshake is bound into the handshake prologue, so
stripping or tampering with it fails the first MAC. With `ota: encryption:`
configured both ends fail closed with no override: the device refuses
plaintext uploads, and the CLI refuses to send plaintext when a key is
configured. Without that block the CLI tries a static api key when the device
offers and, until 2027.3.0, falls back to plaintext with a warning when the
offer is missing or the handshake fails; a runtime provisioned key never
reaches the CLI, so those uploads stay plaintext.
Defeating any of that without the key is in scope: a device that requires
encryption accepting a plaintext or downgraded upload, getting past the MAC,
or recovering image contents from captured traffic.
The following are **not** vulnerabilities, by design:
- Plaintext OTA on a device with no `ota: encryption:` block, including one
that offers encryption because it has an api key. That is the documented
default, authenticated (if at all) by the OTA password. An uploader that
takes the offer skips the password; the key authenticates it. With a
runtime provisioned key and no `provisioning:` window, whoever provisions
the key gains that upload path too; validation warns about the pair.
- The CLI plaintext fallback until 2027.3.0: without `ota: encryption:` an
active attacker who strips the offer or breaks the handshake can make a
keyed CLI upload plaintext, with the pre-existing plaintext exposure. A
device that requires encryption still refuses that upload.
- The enablement window: firmware built with a static api key already offers
encryption, so turning on `ota: encryption:` is itself an encrypted upload.
Older firmware needs one last plaintext upload of an offering build, with
the pre-existing plaintext exposure.
- The web OTA `/update` endpoint alongside encryption. With the `web_server`
or `prometheus` component the shared listener is always up, so the endpoint
stays reachable and validation warns about that combination;
`captive_portal:` alone brings the listener up only for the fallback AP
window, which is the intended recovery path, so that is not warned about.
- CLI retry behavior on transport or MAC failures; every attempt renegotiates
a fresh handshake with fresh ephemerals, so retrying does not weaken
authentication.
## Explicitly out of scope
- Local attackers who already have shell access on the host that runs `esphome`.
- Supply-chain attacks against ESPHome or its dependencies.
- Operator-supplied hostile YAML (covered above — config authoring is trusted).
- Attacks that require an already-authenticated device peer (someone who already
holds the API key / OTA / web credentials).
- Access to the device web server or its web OTA endpoint by non-browser clients
(those that send no `Origin` header). The web server is an open HTTP API by
design (see above); browser cross-origin requests are blocked by default, but the
real controls are `web_server` `auth:` and network isolation.
- Anything in the dashboard / device-builder — report that in its own repository
(linked at the top).
- Deployments where the operator removed protections or exposed credentials. See
the security best practices guide:
https://esphome.io/guides/security_best_practices/
## Reporting a vulnerability
If you believe you've found an issue that crosses the unauthenticated boundary
above, please report it privately via GitHub Security Advisories rather than a
public issue. For issues that require config-write access, please review this
document first — they are very likely out of scope by design. For dashboard /
device-builder issues, report against that repository and consult its threat
model (linked at the top).
+18
View File
@@ -0,0 +1,18 @@
coverage:
status:
patch:
default:
target: 100%
threshold: 0%
project:
default:
informational: true
ignore:
- "esphome/components/**/*"
- "esphome/analyze_memory/**/*"
- "tests/integration/**/*"
comment:
layout: "reach, diff, flags, files"
require_changes: true
+6 -18
View File
@@ -1,10 +1,9 @@
ARG BUILD_VERSION=dev
ARG BUILD_OS=alpine
ARG BUILD_BASE_VERSION=2025.04.0
ARG BUILD_BASE_VERSION=2026.06.1
ARG BUILD_TYPE=docker
FROM ghcr.io/esphome/docker-base:${BUILD_OS}-${BUILD_BASE_VERSION} AS base-source-docker
FROM ghcr.io/esphome/docker-base:${BUILD_OS}-ha-addon-${BUILD_BASE_VERSION} AS base-source-ha-addon
FROM ghcr.io/esphome/docker-base:debian-${BUILD_BASE_VERSION} AS base-source-docker
FROM ghcr.io/esphome/docker-base:debian-ha-addon-${BUILD_BASE_VERSION} AS base-source-ha-addon
ARG BUILD_TYPE
FROM base-source-${BUILD_TYPE} AS base
@@ -12,20 +11,6 @@ FROM base-source-${BUILD_TYPE} AS base
RUN git config --system --add safe.directory "*" \
&& git config --system advice.detachedHead false
# Install build tools for Python packages that require compilation
# (e.g., ruamel.yaml.clib used by ESP-IDF's idf-component-manager).
# Also install libusb-1.0 at runtime so the ESP-IDF tools installer can
# validate openocd-esp32 (it dynamically links libusb-1.0.so.0); without
# it idf_tools.py rejects the openocd install with exit 127 and aborts
# the whole framework setup.
RUN if command -v apk > /dev/null; then \
apk add --no-cache build-base libusb; \
else \
apt-get update \
&& apt-get install -y --no-install-recommends build-essential libusb-1.0-0 \
&& rm -rf /var/lib/apt/lists/*; \
fi
ENV PIP_DISABLE_PIP_VERSION_CHECK=1
RUN pip install --no-cache-dir -U pip uv==0.10.1
@@ -36,6 +21,9 @@ RUN \
uv pip install --no-cache-dir \
-r /requirements.txt
# Install the ESPHome Device Builder dashboard.
RUN uv pip install --no-cache-dir esphome-device-builder==1.14.7
RUN \
platformio settings set enable_telemetry No \
&& platformio settings set check_platformio_interval 1000000 \
+42 -13
View File
@@ -20,6 +20,10 @@ TYPE_HA_ADDON = "ha-addon"
TYPE_LINT = "lint"
TYPES = [TYPE_DOCKER, TYPE_HA_ADDON, TYPE_LINT]
REGISTRY_GHCR = "ghcr"
REGISTRY_DOCKERHUB = "dockerhub"
REGISTRIES = [REGISTRY_GHCR, REGISTRY_DOCKERHUB]
parser = argparse.ArgumentParser()
parser.add_argument(
@@ -34,6 +38,12 @@ parser.add_argument(
parser.add_argument(
"--build-type", choices=TYPES, required=True, help="The type of build to run"
)
parser.add_argument(
"--registry",
choices=REGISTRIES,
action="append",
help="Restrict to specific registries (default: all). May be passed multiple times.",
)
parser.add_argument(
"--dry-run", action="store_true", help="Don't run any commands, just print them"
)
@@ -45,6 +55,11 @@ build_parser.add_argument("--push", help="Also push the images", action="store_t
build_parser.add_argument(
"--load", help="Load the docker image locally", action="store_true"
)
build_parser.add_argument(
"--no-cache-to",
help="Don't write the build cache (avoids polluting the shared cache)",
action="store_true",
)
manifest_parser = subparsers.add_parser(
"manifest", help="Create a manifest from already pushed images"
)
@@ -95,11 +110,14 @@ def main():
print("Command failed")
sys.exit(1)
registries = args.registry or REGISTRIES
# detect channel from tag
match = re.match(r"^(\d+\.\d+)(?:\.\d+)?(b\d+)?$", args.tag)
major_minor_version = None
if match is None:
channel = CHANNEL_DEV
# Custom tag (e.g. a branch name) -- push only the tag itself
channel = None
elif match.group(2) is None:
major_minor_version = match.group(1)
channel = CHANNEL_RELEASE
@@ -128,11 +146,18 @@ def main():
CHANNEL_DEV: "cache-dev",
CHANNEL_BETA: "cache-beta",
CHANNEL_RELEASE: "cache-latest",
}[channel]
cache_img = f"ghcr.io/{params.build_to}:{cache_tag}"
}.get(channel, "cache-dev")
# Cache images live alongside the pushed images; prefer GHCR when it is
# one of the selected registries, otherwise fall back to Docker Hub so a
# registry-restricted build doesn't need GHCR auth.
cache_prefix = "ghcr.io/" if REGISTRY_GHCR in registries else ""
cache_img = f"{cache_prefix}{params.build_to}:{cache_tag}"
imgs = [f"{params.build_to}:{tag}" for tag in tags_to_push]
imgs += [f"ghcr.io/{params.build_to}:{tag}" for tag in tags_to_push]
imgs = []
if REGISTRY_DOCKERHUB in registries:
imgs += [f"{params.build_to}:{tag}" for tag in tags_to_push]
if REGISTRY_GHCR in registries:
imgs += [f"ghcr.io/{params.build_to}:{tag}" for tag in tags_to_push]
# 3. build
cmd = [
@@ -155,7 +180,9 @@ def main():
for img in imgs:
cmd += ["--tag", img]
if args.push:
cmd += ["--push", "--cache-to", f"type=registry,ref={cache_img},mode=max"]
cmd += ["--push"]
if not args.no_cache_to:
cmd += ["--cache-to", f"type=registry,ref={cache_img},mode=max"]
if args.load:
cmd += ["--load"]
@@ -163,20 +190,22 @@ def main():
elif args.command == "manifest":
manifest = DockerParams.for_type_arch(args.build_type, ARCH_AMD64).manifest_to
targets = [f"{manifest}:{tag}" for tag in tags_to_push]
targets += [f"ghcr.io/{manifest}:{tag}" for tag in tags_to_push]
# 1. Create manifests
targets = []
if REGISTRY_DOCKERHUB in registries:
targets += [f"{manifest}:{tag}" for tag in tags_to_push]
if REGISTRY_GHCR in registries:
targets += [f"ghcr.io/{manifest}:{tag}" for tag in tags_to_push]
# Use buildx imagetools (not `docker manifest`) so the per-arch sources,
# which buildx pushes as single-platform manifest lists, are combined
# and pushed correctly in one step.
for target in targets:
cmd = ["docker", "manifest", "create", target]
cmd = ["docker", "buildx", "imagetools", "create", "--tag", target]
for arch in ARCHS:
src = f"{DockerParams.for_type_arch(args.build_type, arch).build_to}:{args.tag}"
if target.startswith("ghcr.io"):
src = f"ghcr.io/{src}"
cmd.append(src)
run_command(*cmd)
# 2. Push manifests
for target in targets:
run_command("docker", "manifest", "push", target)
if __name__ == "__main__":
+13
View File
@@ -21,10 +21,23 @@ export PLATFORMIO_PLATFORMS_DIR="${pio_cache_base}/platforms"
export PLATFORMIO_PACKAGES_DIR="${pio_cache_base}/packages"
export PLATFORMIO_CACHE_DIR="${pio_cache_base}/cache"
# Keep the native toolchain installs on the persistent cache root, not the
# container's ephemeral user cache dir (re-downloaded on every restart).
export ESPHOME_ESP_IDF_PREFIX="$(dirname "${pio_cache_base}")/idf"
export ESPHOME_SDK_NRF_PREFIX="$(dirname "${pio_cache_base}")/sdk-nrf"
# If /build is mounted, use that as the build path
# otherwise use path in /config (so that builds aren't lost on container restart)
if [[ -d /build ]]; then
export ESPHOME_BUILD_PATH=/build
fi
# The default CMD is "dashboard /config". Route the dashboard to the new
# Device Builder, but pass every other subcommand (compile, run, config,
# logs, ...) straight through to the esphome CLI so direct CLI use keeps working.
if [[ "$1" == "dashboard" ]]; then
shift
exec esphome-device-builder "$@"
fi
exec esphome "$@"
+5 -1
View File
@@ -1,5 +1,6 @@
#!/usr/bin/env python3
import argparse
import os
import re
CHANNEL_DEV = "dev"
@@ -64,7 +65,10 @@ def main():
suffix = f"-{args.suffix}" if args.suffix else ""
image_name = f"esphome/esphome{suffix}"
repository = (
(os.environ.get("GITHUB_REPOSITORY") or "esphome/esphome").strip().lower()
)
image_name = f"{repository}{suffix}"
print(f"channel={channel}")
@@ -1,22 +0,0 @@
#!/usr/bin/with-contenv bashio
# ==============================================================================
# Installs the latest prerelease of esphome-device-builder when the
# `use_new_device_builder` config option is enabled.
# This is a temporary install-on-boot step until esphome-device-builder
# becomes a direct dependency of esphome.
# ==============================================================================
if ! bashio::config.true 'use_new_device_builder'; then
exit 0
fi
bashio::log.info "Installing latest prerelease of esphome-device-builder..."
if command -v uv > /dev/null; then
uv pip install --system --no-cache-dir --prerelease=allow --upgrade \
esphome-device-builder ||
bashio::exit.nok "Failed installing esphome-device-builder."
else
pip install --no-cache-dir --pre --upgrade esphome-device-builder ||
bashio::exit.nok "Failed installing esphome-device-builder."
fi
bashio::log.info "Installed esphome-device-builder."
@@ -1,96 +0,0 @@
types {
text/html html htm shtml;
text/css css;
text/xml xml;
image/gif gif;
image/jpeg jpeg jpg;
application/javascript js;
application/atom+xml atom;
application/rss+xml rss;
text/mathml mml;
text/plain txt;
text/vnd.sun.j2me.app-descriptor jad;
text/vnd.wap.wml wml;
text/x-component htc;
image/png png;
image/svg+xml svg svgz;
image/tiff tif tiff;
image/vnd.wap.wbmp wbmp;
image/webp webp;
image/x-icon ico;
image/x-jng jng;
image/x-ms-bmp bmp;
font/woff woff;
font/woff2 woff2;
application/java-archive jar war ear;
application/json json;
application/mac-binhex40 hqx;
application/msword doc;
application/pdf pdf;
application/postscript ps eps ai;
application/rtf rtf;
application/vnd.apple.mpegurl m3u8;
application/vnd.google-earth.kml+xml kml;
application/vnd.google-earth.kmz kmz;
application/vnd.ms-excel xls;
application/vnd.ms-fontobject eot;
application/vnd.ms-powerpoint ppt;
application/vnd.oasis.opendocument.graphics odg;
application/vnd.oasis.opendocument.presentation odp;
application/vnd.oasis.opendocument.spreadsheet ods;
application/vnd.oasis.opendocument.text odt;
application/vnd.openxmlformats-officedocument.presentationml.presentation
pptx;
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
xlsx;
application/vnd.openxmlformats-officedocument.wordprocessingml.document
docx;
application/vnd.wap.wmlc wmlc;
application/x-7z-compressed 7z;
application/x-cocoa cco;
application/x-java-archive-diff jardiff;
application/x-java-jnlp-file jnlp;
application/x-makeself run;
application/x-perl pl pm;
application/x-pilot prc pdb;
application/x-rar-compressed rar;
application/x-redhat-package-manager rpm;
application/x-sea sea;
application/x-shockwave-flash swf;
application/x-stuffit sit;
application/x-tcl tcl tk;
application/x-x509-ca-cert der pem crt;
application/x-xpinstall xpi;
application/xhtml+xml xhtml;
application/xspf+xml xspf;
application/zip zip;
application/octet-stream bin exe dll;
application/octet-stream deb;
application/octet-stream dmg;
application/octet-stream iso img;
application/octet-stream msi msp msm;
audio/midi mid midi kar;
audio/mpeg mp3;
audio/ogg ogg;
audio/x-m4a m4a;
audio/x-realaudio ra;
video/3gpp 3gpp 3gp;
video/mp2t ts;
video/mp4 mp4;
video/mpeg mpeg mpg;
video/quicktime mov;
video/webm webm;
video/x-flv flv;
video/x-m4v m4v;
video/x-mng mng;
video/x-ms-asf asx asf;
video/x-ms-wmv wmv;
video/x-msvideo avi;
}
@@ -1,16 +0,0 @@
proxy_http_version 1.1;
proxy_ignore_client_abort off;
proxy_read_timeout 86400s;
proxy_redirect off;
proxy_send_timeout 86400s;
proxy_max_temp_file_size 0;
proxy_set_header Accept-Encoding "";
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Authorization "";
@@ -1,8 +0,0 @@
root /dev/null;
server_name $hostname;
client_max_body_size 512m;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
@@ -1,8 +0,0 @@
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_session_timeout 10m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
@@ -1,3 +0,0 @@
upstream esphome {
server unix:/var/run/esphome.sock;
}
@@ -1,30 +0,0 @@
daemon off;
user root;
pid /var/run/nginx.pid;
worker_processes 1;
error_log /proc/1/fd/1 error;
events {
worker_connections 1024;
}
http {
include /etc/nginx/includes/mime.types;
access_log off;
default_type application/octet-stream;
gzip on;
keepalive_timeout 65;
sendfile on;
server_tokens off;
tcp_nodelay on;
tcp_nopush on;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
include /etc/nginx/includes/upstream.conf;
include /etc/nginx/servers/*.conf;
}
@@ -1 +0,0 @@
Without requirements or design, programming is the art of adding bugs to an empty text file. (Louis Srygley)
@@ -1,28 +0,0 @@
server {
{{ if not .ssl }}
listen 6052 default_server;
{{ else }}
listen 6052 default_server ssl http2;
{{ end }}
include /etc/nginx/includes/server_params.conf;
include /etc/nginx/includes/proxy_params.conf;
{{ if .ssl }}
include /etc/nginx/includes/ssl_params.conf;
ssl_certificate /ssl/{{ .certfile }};
ssl_certificate_key /ssl/{{ .keyfile }};
# Redirect http requests to https on the same port.
# https://rageagainstshell.com/2016/11/redirect-http-to-https-on-the-same-port-in-nginx/
error_page 497 https://$http_host$request_uri;
{{ end }}
# Clear Home Assistant Ingress header
proxy_set_header X-HA-Ingress "";
location / {
proxy_pass http://esphome;
}
}
@@ -1,18 +0,0 @@
server {
listen 127.0.0.1:{{ .port }} default_server;
listen {{ .interface }}:{{ .port }} default_server;
include /etc/nginx/includes/server_params.conf;
include /etc/nginx/includes/proxy_params.conf;
# Set Home Assistant Ingress header
proxy_set_header X-HA-Ingress "YES";
location / {
allow 172.30.32.2;
allow 127.0.0.1;
deny all;
proxy_pass http://esphome;
}
}
@@ -16,7 +16,7 @@ fi
port=$(bashio::addon.ingress_port)
# Wait for NGINX to become available
# Wait for the ESPHome Device Builder to become available
bashio::net.wait_for "${port}" "127.0.0.1" 300
config=$(\
@@ -2,7 +2,7 @@
# shellcheck shell=bash
# ==============================================================================
# Home Assistant Community Add-on: ESPHome
# Take down the S6 supervision tree when ESPHome dashboard fails
# Take down the S6 supervision tree when ESPHome Device Builder fails
# ==============================================================================
declare exit_code
readonly exit_code_container=$(</run/s6-linux-init-container-results/exitcode)
@@ -10,7 +10,7 @@ readonly exit_code_service="${1}"
readonly exit_code_signal="${2}"
bashio::log.info \
"Service ESPHome dashboard exited with code ${exit_code_service}" \
"Service ESPHome Device Builder exited with code ${exit_code_service}" \
"(by signal ${exit_code_signal})"
if [[ "${exit_code_service}" -eq 256 ]]; then
@@ -2,7 +2,7 @@
# shellcheck shell=bash
# ==============================================================================
# Community Hass.io Add-ons: ESPHome
# Runs the ESPHome dashboard
# Runs the ESPHome Device Builder
# ==============================================================================
readonly pio_cache_base=/data/cache/platformio
@@ -15,18 +15,15 @@ export PLATFORMIO_PLATFORMS_DIR="${pio_cache_base}/platforms"
export PLATFORMIO_PACKAGES_DIR="${pio_cache_base}/packages"
export PLATFORMIO_CACHE_DIR="${pio_cache_base}/cache"
# Keep the native toolchain installs on the persistent /data volume, not the
# container's ephemeral user cache dir (wiped on every add-on update/restart).
export ESPHOME_ESP_IDF_PREFIX=/data/cache/idf
export ESPHOME_SDK_NRF_PREFIX=/data/cache/sdk-nrf
if bashio::config.true 'leave_front_door_open'; then
export DISABLE_HA_AUTHENTICATION=true
fi
if bashio::config.true 'streamer_mode'; then
export ESPHOME_STREAMER_MODE=true
fi
if bashio::config.has_value 'relative_url'; then
export ESPHOME_DASHBOARD_RELATIVE_URL=$(bashio::config 'relative_url')
fi
if bashio::config.has_value 'default_compile_process_limit'; then
export ESPHOME_DEFAULT_COMPILE_PROCESS_LIMIT=$(bashio::config 'default_compile_process_limit')
else
@@ -49,12 +46,21 @@ if bashio::fs.directory_exists '/config/esphome/.esphome'; then
rm -rf /config/esphome/.esphome
fi
if bashio::config.true 'use_new_device_builder'; then
bashio::log.info "Starting ESPHome Device Builder..."
exec esphome-device-builder /config/esphome \
--ha-addon \
--ingress-port "$(bashio::addon.ingress_port)"
# Only signal device-builder to expose the public LAN port when the operator
# mapped port 6052, matching the legacy dashboard where nginx listened on the
# fixed port 6052 only when it was configured. We use the mapping purely as a
# presence check and don't forward the published value; device-builder binds
# its default port 6052 (the fixed container port, as the legacy
# "listen 6052" did). --ha-addon-allow-public is inert on its own: the no-auth
# gate is the DISABLE_HA_AUTHENTICATION env var set above, so both opt-ins are
# required to bind 6052 unauthenticated; either alone stays ingress-only.
set --
if bashio::var.has_value "$(bashio::addon.port 6052)"; then
set -- --ha-addon-allow-public
fi
bashio::log.info "Starting ESPHome dashboard..."
exec esphome dashboard /config/esphome --socket /var/run/esphome.sock --ha-addon
bashio::log.info "Starting ESPHome Device Builder..."
exec esphome-device-builder /config/esphome \
--ha-addon \
--ingress-port "$(bashio::addon.ingress_port)" \
"$@"
@@ -1,35 +0,0 @@
#!/command/with-contenv bashio
# shellcheck shell=bash
# ==============================================================================
# Community Hass.io Add-ons: ESPHome
# Configures NGINX for use with ESPHome
# ==============================================================================
# When the new device builder is enabled it serves HA ingress directly,
# so nginx is not used at all -- skip configuration.
if bashio::config.true 'use_new_device_builder'; then
bashio::log.info "Skipping NGINX setup: new device builder serves ingress directly."
bashio::exit.ok
fi
mkdir -p /var/log/nginx
# Generate Ingress configuration
bashio::var.json \
interface "$(bashio::addon.ip_address)" \
port "^$(bashio::addon.ingress_port)" \
| tempio \
-template /etc/nginx/templates/ingress.gtpl \
-out /etc/nginx/servers/ingress.conf
# Generate direct access configuration, if enabled.
if bashio::var.has_value "$(bashio::addon.port 6052)"; then
bashio::config.require.ssl
bashio::var.json \
certfile "$(bashio::config 'certfile')" \
keyfile "$(bashio::config 'keyfile')" \
ssl "^$(bashio::config 'ssl')" \
| tempio \
-template /etc/nginx/templates/direct.gtpl \
-out /etc/nginx/servers/direct.conf
fi
@@ -1 +0,0 @@
oneshot
@@ -1 +0,0 @@
/etc/s6-overlay/s6-rc.d/init-nginx/run
@@ -1,25 +0,0 @@
#!/command/with-contenv bashio
# ==============================================================================
# Community Hass.io Add-ons: ESPHome
# Take down the S6 supervision tree when NGINX fails
# ==============================================================================
declare exit_code
readonly exit_code_container=$(</run/s6-linux-init-container-results/exitcode)
readonly exit_code_service="${1}"
readonly exit_code_signal="${2}"
bashio::log.info \
"Service NGINX exited with code ${exit_code_service}" \
"(by signal ${exit_code_signal})"
if [[ "${exit_code_service}" -eq 256 ]]; then
if [[ "${exit_code_container}" -eq 0 ]]; then
echo $((128 + $exit_code_signal)) > /run/s6-linux-init-container-results/exitcode
fi
[[ "${exit_code_signal}" -eq 15 ]] && exec /run/s6/basedir/bin/halt
elif [[ "${exit_code_service}" -ne 0 ]]; then
if [[ "${exit_code_container}" -eq 0 ]]; then
echo "${exit_code_service}" > /run/s6-linux-init-container-results/exitcode
fi
exec /run/s6/basedir/bin/halt
fi
@@ -1,23 +0,0 @@
#!/command/with-contenv bashio
# shellcheck shell=bash
# ==============================================================================
# Community Hass.io Add-ons: ESPHome
# Runs the NGINX proxy
# ==============================================================================
# The new device builder handles HA ingress itself, so nginx is bypassed.
# Block the longrun forever so s6 keeps the dependency satisfied and does
# not respawn it.
if bashio::config.true 'use_new_device_builder'; then
bashio::log.info "NGINX bypassed: new device builder serves ingress directly."
exec sleep infinity
fi
bashio::log.info "Waiting for ESPHome dashboard to come up..."
while [[ ! -S /var/run/esphome.sock ]]; do
sleep 0.5
done
bashio::log.info "Starting NGINX..."
exec nginx
@@ -1 +0,0 @@
longrun
+7
View File
@@ -0,0 +1,7 @@
esphome:
name: docker-test-bk72xx-arduino
bk72xx:
board: generic-bk7231n-qfn32-tuya
logger:
@@ -0,0 +1,10 @@
esphome:
name: docker-test-esp32-ard-idf
esp32:
variant: esp32
framework:
type: arduino
toolchain: esp-idf
logger:
@@ -0,0 +1,10 @@
esphome:
name: docker-test-esp32-ard-pio
esp32:
variant: esp32
framework:
type: arduino
toolchain: platformio
logger:
@@ -0,0 +1,10 @@
esphome:
name: docker-test-esp32-idf-idf
esp32:
variant: esp32
framework:
type: esp-idf
toolchain: esp-idf
logger:
@@ -0,0 +1,10 @@
esphome:
name: docker-test-esp32-idf-pio
esp32:
variant: esp32
framework:
type: esp-idf
toolchain: platformio
logger:
+7
View File
@@ -0,0 +1,7 @@
esphome:
name: docker-test-esp8266-arduino
esp8266:
board: d1_mini
logger:
+6
View File
@@ -0,0 +1,6 @@
esphome:
name: docker-test-host
host:
logger:
+7
View File
@@ -0,0 +1,7 @@
esphome:
name: docker-test-ln882x-arduino
ln882x:
board: generic-ln882h
logger:
+8
View File
@@ -0,0 +1,8 @@
esphome:
name: docker-test-nrf52
nrf52:
board: adafruit_itsybitsy_nrf52840
bootloader: adafruit_nrf52_sd140_v6
logger:
+7
View File
@@ -0,0 +1,7 @@
esphome:
name: docker-test-rp2040-arduino
rp2040:
variant: rp2040
logger:
+7
View File
@@ -0,0 +1,7 @@
esphome:
name: docker-test-rtl87xx-arduino
rtl87xx:
board: generic-rtl8710bn-2mb-788k
logger:
+503 -234
View File
File diff suppressed because it is too large. Load diff
+8 -27
View File
@@ -20,6 +20,7 @@ from . import (
RAM_SECTIONS,
MemoryAnalyzer,
)
from .toolchain import find_elf_path, find_idedata_path, idedata_candidates
if TYPE_CHECKING:
from . import ComponentMemory
@@ -759,45 +760,25 @@ def main():
print(f"Error: {build_path} is not a directory", file=sys.stderr)
sys.exit(1)
# Find firmware.elf
elf_file = None
for elf_candidate in [
build_path / "firmware.elf",
build_path / ".pioenvs" / build_path.name / "firmware.elf",
]:
if elf_candidate.exists():
elf_file = str(elf_candidate)
break
if not elf_file:
print(f"Error: firmware.elf not found in {build_dir}", file=sys.stderr)
elf_path = find_elf_path(build_path)
if not elf_path:
print(f"Error: no firmware ELF found in {build_dir}", file=sys.stderr)
sys.exit(1)
# Find idedata.json - check current directory first, then home
device_name = build_path.name
idedata_candidates = [
Path.cwd() / ".esphome" / "idedata" / f"{device_name}.json",
Path.home() / ".esphome" / "idedata" / f"{device_name}.json",
]
elf_file = str(elf_path)
idedata = None
for idedata_path in idedata_candidates:
if not idedata_path.exists():
continue
if idedata_path := find_idedata_path(build_path):
try:
with idedata_path.open(encoding="utf-8") as f:
raw_data = json.load(f)
idedata = IDEData(raw_data)
print(f"Loaded idedata from: {idedata_path}", file=sys.stderr)
break
except (json.JSONDecodeError, OSError) as e:
print(f"Warning: Failed to load idedata: {e}", file=sys.stderr)
if not idedata:
print(
f"Warning: idedata not found (searched {idedata_candidates[0]} and {idedata_candidates[1]})",
file=sys.stderr,
)
searched = "\n ".join(str(p) for p in idedata_candidates(build_path))
print(f"Warning: idedata not found, searched:\n {searched}", file=sys.stderr)
analyzer = MemoryAnalyzerCLI(elf_file, idedata=idedata)
analyzer.analyze()
+34 -10
View File
@@ -8,7 +8,7 @@ memory-constrained platforms like ESP8266.
from __future__ import annotations
from collections import defaultdict
from dataclasses import dataclass
from dataclasses import dataclass, field
import logging
from pathlib import Path
import re
@@ -65,6 +65,7 @@ class RamSymbol:
size: int
section: str
demangled: str = "" # Demangled name, set after batch demangling
aliases: list[str] = field(default_factory=list) # Other names at same address
class RamStringsAnalyzer:
@@ -235,6 +236,11 @@ class RamStringsAnalyzer:
except (subprocess.CalledProcessError, FileNotFoundError):
return
# Track symbols by address so aliases (multiple names for the same
# object, e.g. the newlib __lock___* mutexes that all alias one
# StaticSemaphore_t) are reported once instead of once per name.
symbols_by_addr: dict[int, RamSymbol] = {}
for line in output.split("\n"):
parts = line.split()
if len(parts) < 4:
@@ -253,6 +259,18 @@ class RamStringsAnalyzer:
if sym_type not in DATA_SYMBOL_TYPES:
continue
if (existing := symbols_by_addr.get(addr)) is not None:
# Prefer a global (uppercase type) name as the primary so
# nm output order can't hide it behind a local alias.
if sym_type.isupper() and existing.sym_type.islower():
existing.aliases.append(existing.name)
existing.name = name
existing.sym_type = sym_type
else:
existing.aliases.append(name)
existing.size = max(existing.size, size)
continue
# Check if symbol is in a RAM section
for section_name in self.ram_sections:
if section_name not in self.sections:
@@ -260,15 +278,15 @@ class RamStringsAnalyzer:
section = self.sections[section_name]
if section.address <= addr < section.address + section.size:
self.ram_symbols.append(
RamSymbol(
name=name,
sym_type=sym_type,
address=addr,
size=size,
section=section_name,
)
symbol = RamSymbol(
name=name,
sym_type=sym_type,
address=addr,
size=size,
section=section_name,
)
symbols_by_addr[addr] = symbol
self.ram_symbols.append(symbol)
break
def _demangle_symbols(self) -> None:
@@ -436,7 +454,13 @@ class RamStringsAnalyzer:
for symbol in largest_symbols:
# Use demangled name if available, otherwise raw name
display_name = symbol.demangled or symbol.name
name_display = display_name[:49] if len(display_name) > 49 else display_name
# Truncate the name, not the alias note, so merged aliases stay
# visible even for long demangled C++ names.
alias_note = f" (+{len(symbol.aliases)} aliases)" if symbol.aliases else ""
max_name_len = 49 - len(alias_note)
if len(display_name) > max_name_len:
display_name = display_name[:max_name_len]
name_display = display_name + alias_note
lines.append(
f"{name_display:<50} {symbol.sym_type:<6} {symbol.size:>8} B {symbol.section}"
)
+72
View File
@@ -23,6 +23,78 @@ TOOLCHAIN_PREFIXES = [
]
def find_elf_path(build_path: Path) -> Path | None:
"""Locate the firmware ELF inside an ESPHome build directory.
The layout depends on the toolchain that produced the build, so try each
known one in turn.
Args:
build_path: Path to an ESPHome build directory
Returns:
Path to the ELF file, or None if no known layout matches
"""
name = build_path.name
for candidate in (
# Native ESP-IDF: idf.py writes build/<name>.elf, which ESPHome copies
# to build/firmware.elf (see espidf.toolchain.create_elf_copy)
build_path / "build" / "firmware.elf",
# PlatformIO
build_path / "firmware.elf",
build_path / ".pioenvs" / name / "firmware.elf",
# LibreTiny uses raw_firmware.elf
build_path / "raw_firmware.elf",
build_path / ".pioenvs" / name / "raw_firmware.elf",
# Zephyr (nRF52); the SDK nests the artifacts one level deeper from 2.9.2
build_path / ".pioenvs" / name / "zephyr" / "zephyr" / "zephyr.elf",
build_path / ".pioenvs" / name / "zephyr" / "zephyr.elf",
):
if candidate.is_file():
return candidate
return None
def idedata_candidates(build_path: Path) -> list[Path]:
"""Return the idedata locations searched for a build directory, in order.
Exposed so a caller reporting "not found" can name the paths it tried
without keeping its own copy of the list.
Args:
build_path: Path to an ESPHome build directory
Returns:
The candidate idedata JSON paths, most specific first
"""
name = build_path.name
return [
# In .pioenvs for test builds
build_path / ".pioenvs" / name / "idedata.json",
# Both toolchains cache it in the data dir, which holds this build dir:
# <data_dir>/idedata/<name>.json next to <data_dir>/build/<name>
build_path.parent.parent / "idedata" / f"{name}.json",
# Regular builds, invoked from the config dir or from anywhere
Path.cwd() / ".esphome" / "idedata" / f"{name}.json",
Path.home() / ".esphome" / "idedata" / f"{name}.json",
]
def find_idedata_path(build_path: Path) -> Path | None:
"""Locate the idedata JSON belonging to an ESPHome build directory.
Args:
build_path: Path to an ESPHome build directory
Returns:
Path to the idedata JSON, or None if it was not found
"""
for candidate in idedata_candidates(build_path):
if candidate.is_file():
return candidate
return None
def _find_in_platformio_packages(tool_name: str) -> str | None:
"""Search for a tool in PlatformIO package directories.
+196
View File
@@ -0,0 +1,196 @@
from __future__ import annotations
import asyncio
from contextlib import suppress
import logging
import threading
from typing import TYPE_CHECKING, Any
import warnings
# Suppress protobuf version warnings
with warnings.catch_warnings():
warnings.filterwarnings(
"ignore", category=UserWarning, message=".*Protobuf gencode version.*"
)
from aioesphomeapi import APIClient, parse_log_message
from aioesphomeapi.log_runner import async_run
from esphome.const import CONF_ENCRYPTION, CONF_KEY, CONF_PORT, __version__
from esphome.core import CORE
from esphome.stacktrace import LogLineProcessor
from esphome.util import safe_print
if TYPE_CHECKING:
from collections.abc import Callable
from aioesphomeapi.api_pb2 import SubscribeLogsResponse # pylint: disable=no-name-in-module
_LOGGER = logging.getLogger(__name__)
async def async_run_logs(
config: dict[str, Any],
addresses: list[str],
subscribe_states: bool = True,
mqtt_resolver: Callable[[threading.Event], list[str]] | None = None,
) -> None:
"""Run the logs command in the event loop.
If ``mqtt_resolver`` is given, it is called in a worker thread (paho-mqtt
has no asyncio support on Windows) concurrently with the connection
attempts to ``addresses``, and any addresses it discovers are fed into
the running client. It owns its own failure handling (returning [] when
discovery fails) and must honor the ``threading.Event`` it is passed so
teardown is not delayed by the lookup's wait window; the initial broker
connect itself is only bounded by the socket timeout.
"""
from datetime import datetime
conf = config["api"]
name = config["esphome"]["name"]
port: int = int(conf[CONF_PORT])
noise_psk: str | None = None
if (encryption := conf.get(CONF_ENCRYPTION)) and (key := encryption.get(CONF_KEY)):
noise_psk = key
_LOGGER.info(
"Starting log output from %s using esphome API", " or ".join(addresses)
)
cli = APIClient(
addresses[0], # Primary address for compatibility
port,
"", # 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
provide_time=False,
)
# Decoder resolution policy lives in LogLineProcessor.
processor = LogLineProcessor(config, CORE.target_platform)
mqtt_task: asyncio.Task[None] | None = None
mqtt_stop_event = threading.Event()
def _cancel_mqtt_discovery() -> None:
"""Stop the broker lookup once a connection has been established.
Its answer is only useful while still disconnected: after that it
either duplicates the connected address or arrives too late to
matter, so don't keep an idle broker session open for it.
"""
mqtt_stop_event.set()
if mqtt_task is not None and not mqtt_task.done():
mqtt_task.cancel()
async def _resolve_mqtt_addresses() -> None:
"""Discover the device address via the MQTT broker in the background."""
try:
mqtt_ips = await asyncio.to_thread(mqtt_resolver, mqtt_stop_event)
if not mqtt_ips:
_LOGGER.debug(
"MQTT discovery %s",
"aborted" if mqtt_stop_event.is_set() else "found no addresses",
)
return
if cli.add_addresses(mqtt_ips):
_LOGGER.info("Discovered address(es) via MQTT: %s", ", ".join(mqtt_ips))
else:
_LOGGER.debug(
"MQTT-discovered address(es) already known: %s", ", ".join(mqtt_ips)
)
except Exception: # pylint: disable=broad-except
# A background task failure would otherwise stay invisible for
# the whole session and only re-raise at teardown
_LOGGER.exception("MQTT address discovery failed")
def on_log(msg: SubscribeLogsResponse) -> None:
"""Handle a new log message."""
time_ = datetime.now().astimezone()
message: bytes = msg.message
text = message.decode("utf8", "backslashreplace")
nanoseconds = time_.microsecond // 1000
timestamp = (
f"[{time_.hour:02}:{time_.minute:02}:{time_.second:02}.{nanoseconds:03}]"
)
for parsed_msg in parse_log_message(text, timestamp):
# safe_print handles the dashboard \033 escaping and falls back
# to backslashreplace encoding on stdouts that can't represent
# the wifi signal-bar block characters (Windows redirected
# cp1252 pipe).
safe_print(parsed_msg)
for raw_line in text.splitlines():
processor.process_line(raw_line)
# Safe to fall back to plaintext here only for this diagnostics use
# case: the stream is one-way from device to client, and this code
# never accepts commands or acts on any message the device sends.
# An on-path attacker could still both inject fabricated log lines
# and passively read the device's log output (and any state data
# delivered when subscribe_states is enabled), so this does lose
# confidentiality as well as authentication/integrity. That tradeoff
# is acceptable for operator-visible logs, which aioesphomeapi also
# warns may come from an unverified device. Never mirror this opt-in
# for any connection that sends data to the device or uses Home
# Assistant actions.
stop = await async_run(
cli,
on_log,
name=name,
subscribe_states=subscribe_states,
allow_plaintext_fallback=True,
# A top-level ``deep_sleep:`` block means the device is only awake
# briefly; cap the reconnect backoff so a wake window is not missed.
deep_sleep="deep_sleep" in config,
on_connect=_cancel_mqtt_discovery if mqtt_resolver is not None else None,
)
try:
# Don't start (or keep) the broker lookup if a connection already
# succeeded; the stop event doubles as the not-needed-anymore latch
# and get_esphome_device_ip returns immediately when it is set.
if mqtt_resolver is not None and not mqtt_stop_event.is_set():
mqtt_task = asyncio.create_task(_resolve_mqtt_addresses())
await asyncio.Event().wait()
finally:
try:
if mqtt_task is not None:
# Unblock the worker thread first so it can't hold up
# loop.shutdown_default_executor() for the full lookup timeout.
mqtt_stop_event.set()
# Give the worker a moment to exit through its own error
# handling; cancelling first would race out a late failure.
done, _ = await asyncio.wait([mqtt_task], timeout=1.0)
if not done:
mqtt_task.cancel()
# return_exceptions keeps a CancelledError from the cancel()
# above from re-raising here and jumping over the stop() below.
# The task handles Exception itself, so only a BaseException
# escape (e.g. SystemExit from the worker) can land here.
(result,) = await asyncio.gather(mqtt_task, return_exceptions=True)
if isinstance(result, BaseException) and not isinstance(
result, asyncio.CancelledError
):
_LOGGER.error("MQTT address discovery failed", exc_info=result)
finally:
# Must run even if a second cancellation lands mid-cleanup above
await stop()
def run_logs(
config: dict[str, Any],
addresses: list[str],
subscribe_states: bool = True,
mqtt_resolver: Callable[[threading.Event], list[str]] | None = None,
) -> None:
"""Run the logs command."""
with suppress(KeyboardInterrupt):
asyncio.run(
async_run_logs(
config,
addresses,
subscribe_states=subscribe_states,
mqtt_resolver=mqtt_resolver,
)
)
File renamed without changes.
+531
View File
@@ -0,0 +1,531 @@
"""Arduino-core backend for the shared PlatformIO library converter.
Bundled names build straight from the framework tree; everything else goes
through ``esphome.platformio.library``. Mirrors ``lib_ldf_mode=off``: each
library builds its own archive; all include dirs join one global path.
Deviations from PlatformIO: flat-layout libraries get the recursive default
source filter; ``dot_a_linkage`` is honored; bundled libraries never run a
manifest ``extraScript``; manifest ``-I`` flags join the global include path;
``precompiled``/``ldflags`` properties are refused by name.
"""
from __future__ import annotations
from dataclasses import dataclass, field
import logging
from pathlib import Path
import re
from esphome.core import CORE, EsphomeError, Library
from esphome.helpers import walk_files
from esphome.platformio.extra_script import apply_extra_script
from esphome.platformio.library import (
DEFAULT_BUILD_INCLUDE_DIR,
DEFAULT_BUILD_SRC_FILTER,
ESPHOME_DATA_KEY,
ESPHOME_DATA_LINK_FLAGS_KEY,
LIBRARY_HEADER_SUFFIXES,
SRC_FILE_EXTENSIONS,
ConvertedLibrary,
IncompatiblePlatform,
InvalidLibrary,
LibraryBackend,
_url_or_none,
check_library_data,
collect_filtered_files,
convert_libraries,
ensure_list,
is_lib_ignored,
lex_build_flags,
lib_ignore_set,
normalize_dependencies,
parse_library_json,
parse_library_properties,
warn_properties_depends,
)
_LOGGER = logging.getLogger(__name__)
@dataclass
class ArduinoLibrary:
"""One resolved library, ready for the ninja generator."""
name: str
sources: list[Path] = field(default_factory=list)
include_dirs: list[Path] = field(default_factory=list)
# Extra compile flags private to this library's own sources
flags: list[str] = field(default_factory=list)
# PlatformIO's build.libArchive / Arduino's dot_a_linkage: when False the
# objects go to the linker directly (symbols nothing references survive)
lib_archive: bool = True
# Link inputs the library contributes (-L dirs / -l libs, e.g. from
# precompiled vendor blobs) and -Wl, options for the firmware link
link_dirs: list[Path] = field(default_factory=list)
link_libs: list[str] = field(default_factory=list)
link_flags: list[str] = field(default_factory=list)
# Source-like suffixes the case-sensitive suffix map rejects
_UNMAPPED_SOURCE_SUFFIXES = frozenset(
{s.lower() for s in SRC_FILE_EXTENSIONS} | {".ino"}
)
# Filename-plain names: an allowlist excludes separators, drive colons,
# and dot-only names by shape
_SAFE_LIBRARY_NAME_RE = re.compile(r"[A-Za-z0-9_][A-Za-z0-9_. +-]*\Z")
def _is_safe_library_name(name: object) -> bool:
"""Whether a name may be joined under the framework's libraries dir."""
return isinstance(name, str) and _SAFE_LIBRARY_NAME_RE.fullmatch(name) is not None
def _manifest_build(name: str, data: object) -> dict:
"""The manifest's ``build`` section; malformed manifests fail by name."""
build = data.get("build", {}) if isinstance(data, dict) else None
if not isinstance(build, dict):
raise EsphomeError(f"Library {name} has a malformed manifest")
return build
def _resolve_src_dir(name: str, read_path: Path, build: dict) -> str:
"""Resolve PIO's source dir: manifest srcDir, else src/Src, else the root."""
if "srcDir" not in build:
return next((d for d in ("src", "Src") if (read_path / d).is_dir()), ".")
# A declared srcDir (falsy included) that does not resolve is a manifest error
src_dir = build["srcDir"]
if not (isinstance(src_dir, str) and src_dir and (read_path / src_dir).is_dir()):
raise EsphomeError(
f"Library {name} declares srcDir {src_dir!r} which does not exist"
)
return src_dir
def _reject_unsupported_link_fields(name: str, data: dict) -> None:
# PIO honors these; ignoring them would fail at link with no stated
# cause. Property values are strings, so "false" is not a declaration.
precompiled = data.get("precompiled")
if precompiled and str(precompiled).strip().lower() != "false":
raise EsphomeError(
f"Library {name} declares precompiled, which this backend does not support"
)
if data.get("ldflags"):
raise EsphomeError(
f"Library {name} declares ldflags, which this backend does not support"
)
def _resolve_lib_archive(name: str, data: dict, build: dict) -> bool:
"""build.libArchive, else dot_a_linkage (an Arduino IDE property PIO
ignores; a deliberate extra), else archive."""
# Strict parse: bool("false") is True
def _parse(key: str, raw: object) -> bool:
if isinstance(raw, bool):
return raw
value = str(raw).strip().lower()
if value in ("true", "false"):
return value == "true"
raise EsphomeError(f"Library {name} has a malformed {key} value {raw!r}")
if "libArchive" in build:
return _parse("libArchive", build["libArchive"])
if "dot_a_linkage" in data:
return _parse("dot_a_linkage", data["dot_a_linkage"])
return True
def _classify_build_flags(
name: str, read_path: Path, lib: ArduinoLibrary, flag_tokens: list[str]
) -> list[str]:
"""Route the lexed build.flags into the library's flag lists.
Returns the ``-I`` arguments for the include-dir resolution.
"""
include_flags: list[str] = []
for tok in flag_tokens:
if tok.startswith("-I"):
include_flags.append(tok[2:])
elif tok.startswith("-L"):
link_dir = (read_path / tok[2:]).resolve()
if not link_dir.is_dir():
# Kept (the linker ignores missing -L dirs); the warning
# names the culprit before a bare "cannot find -lfoo"
_LOGGER.warning(
"Library %s declares library dir %s which does not exist",
name,
tok[2:],
)
lib.link_dirs.append(link_dir)
elif tok.startswith("-l"):
lib.link_libs.append(tok[2:])
elif tok.startswith("-Wl,"):
lib.link_flags.append(tok)
else:
lib.flags.append(tok)
return include_flags
def _resolve_include_dirs(
name: str,
read_path: Path,
lib: ArduinoLibrary,
build: dict,
src_dir: str,
include_flags: list[str],
) -> None:
include_dir = build.get("includeDir", DEFAULT_BUILD_INCLUDE_DIR)
if not isinstance(include_dir, str):
raise EsphomeError(f"Library {name} has a malformed includeDir")
for d, explicit in [
(include_dir, "includeDir" in build),
(src_dir, False), # _resolve_src_dir already validated it
*((flag, True) for flag in include_flags),
]:
if (path := (read_path / d)).is_dir():
lib.include_dirs.append(path.resolve())
elif explicit:
# Warn-and-drop (unlike srcDir): a missing include dir is
# harmless until a header is needed, and the compile names it
_LOGGER.warning(
"Library %s declares include dir %s which does not exist", name, d
)
def _collect_lib_sources(
name: str,
read_path: Path,
lib: ArduinoLibrary,
src_dir: str,
src_filter: list[str],
) -> None:
sources: list[Path] = []
dropped: list[str] = []
saw_header = False
for f in collect_filtered_files(read_path / src_dir, src_filter):
path = Path(f)
suffix = path.suffix
if suffix in SRC_FILE_EXTENSIONS:
# resolve() per file: srcFilter patterns may escape src_dir
sources.append(path.resolve())
elif suffix.lower() in _UNMAPPED_SOURCE_SUFFIXES:
# A source-like suffix the case-sensitive map rejects (.CPP,
# .ino) is a dropped compilation unit; headers fall through
dropped.append(path.name)
elif suffix.lower() in LIBRARY_HEADER_SUFFIXES:
saw_header = True
lib.sources = sorted(sources)
if dropped:
_LOGGER.warning(
"Library %s: %d file(s) with unmapped source suffixes are not compiled: %s",
name,
len(dropped),
", ".join(sorted(dropped)),
)
if not lib.sources and not saw_header:
# Matched headers mean header-only; a filter matching nothing is
# a manifest/tree problem (a truly empty tree raises elsewhere)
_LOGGER.warning("Library %s: no source files matched", name)
def _library_info(name: str, read_path: Path, data: dict) -> ArduinoLibrary:
"""Resolve one library's sources, include dirs, and flags (PIO semantics)."""
build = _manifest_build(name, data)
_reject_unsupported_link_fields(name, data)
src_dir = _resolve_src_dir(name, read_path, build)
src_filter = ensure_list(build.get("srcFilter", DEFAULT_BUILD_SRC_FILTER))
if not all(isinstance(entry, str) for entry in src_filter):
raise EsphomeError(f"Library {name} has a malformed srcFilter")
lib = ArduinoLibrary(name=name, lib_archive=_resolve_lib_archive(name, data, build))
# PlatformIO shell-lexes each build.flags entry
include_flags = _classify_build_flags(
name, read_path, lib, lex_build_flags(build.get("flags", []), f"library {name}")
)
_resolve_include_dirs(name, read_path, lib, build, src_dir, include_flags)
_collect_lib_sources(name, read_path, lib, src_dir, src_filter)
return lib
def _bundled_library(framework_path: Path, name: str) -> ArduinoLibrary:
"""A library bundled with the Arduino core, read from the framework tree.
``library.json`` wins over ``library.properties`` when both exist, as in
PlatformIO's LibBuilderFactory; only the JSON manifest can carry a
``build`` section (srcDir, srcFilter, flags).
"""
lib_dir = framework_path / "libraries" / name
manifest_json = lib_dir / "library.json"
if manifest_json.is_file():
try:
data = parse_library_json(manifest_json)
except ValueError as err: # JSONDecodeError
raise EsphomeError(
f"Bundled library {name} has a corrupt library.json ({err}); "
"the framework install may be incomplete (run 'esphome clean-all')"
) from err
elif (manifest := lib_dir / "library.properties").is_file():
data = parse_library_properties(manifest)
else:
# Debug, not warning: the legacy manifest-less layout is legal and
# the 3.1.2 core ships one such library (FSTools), so a warning
# would be unactionable noise on every build using it
_LOGGER.debug("Bundled library %s has no manifest; using defaults", name)
data = {}
if isinstance(data, dict):
# Bundled manifest deps are never walked; make the skip visible
if data.get("dependencies"):
_LOGGER.warning(
"Bundled library %s declares dependencies, which are not "
"resolved automatically; add them with add_library() if needed",
name,
)
warn_properties_depends(name, data)
build = data.get("build")
if isinstance(build, dict) and build.get("extraScript"):
# Scripts only run on the converted path; building without
# the script's flags would miscompile
raise EsphomeError(
f"Bundled library {name} declares an extraScript, which is "
"not run for bundled libraries"
)
lib = _library_info(name, lib_dir, data)
_assert_tree_has_code(
name,
lib_dir,
"the framework install may be incomplete (run 'esphome clean-all')",
)
return lib
def _assert_tree_has_code(name: str, root: Path, hint: str) -> None:
"""An empty or half-extracted tree can never link; fail by name (a
warning would scroll away and resurface as undefined symbols)."""
if not any(
Path(p).suffix in SRC_FILE_EXTENSIONS
or Path(p).suffix.lower() in LIBRARY_HEADER_SUFFIXES
for p in walk_files(root)
):
raise EsphomeError(f"Library {name} has no sources or headers; {hint}")
def _external_short_name(name: str) -> str:
"""The short library name of a requested spec.
"owner/Name" and plain names take the last path segment; "Name=<url>"
takes the declared name. Git tails (".git", "#ref") are stripped like
the walk's URL normalization; the comparand is a manifest dependency
name, never a spec.
"""
head, sep, tail = name.partition("=")
if sep and "://" in tail:
return head
short = name.rsplit("/", maxsplit=1)[-1]
return short.partition("#")[0].removesuffix(".git")
def _check_unfulfilled_provides(
provided_requests: set[str], satisfied: set[str], still_requested: set[str]
) -> None:
"""Fail by name when a walk-skipped dependency was never added.
An unfulfilled provides() promise only surfaces as undefined symbols
at link. The walk records across re-resolutions, so a name no final
manifest still requests is stale state, never a failure.
"""
if missing := sorted((provided_requests & still_requested) - satisfied):
raise EsphomeError(
"provides() skipped these dependencies but nothing added them: "
f"{', '.join(missing)}; the build is missing libraries"
)
def resolve_libraries(
framework_path: Path, *, pio_platform: str, board_mcu: str, cache_key: str
) -> list[ArduinoLibrary]:
"""Resolve every ``cg.add_library()`` entry into an :class:`ArduinoLibrary`.
``pio_platform``/``board_mcu`` filter manifests the way PlatformIO would
for that core (e.g. ``espressif8266``/``esp8266``); ``cache_key`` keys the
shared converter's download cache.
The returned list is not topologically sorted, so the caller must link
the archives inside one ``--start-group``/``--end-group`` pair (the
bundled-first grouping is incidental).
"""
bundled: list[ArduinoLibrary] = []
external: list[Library] = []
# PlatformIO's lib_ignore covers framework-bundled libraries too; the
# shared converter only filters the registry/git ones.
lib_ignore = lib_ignore_set()
# Exact directory names keep membership case-sensitive everywhere
# (an is_dir() probe would match "wire" on macOS/Windows and build
# the bundled Wire twice)
libraries_dir = framework_path / "libraries"
if not libraries_dir.is_dir():
# A registry fallback would fail later with a misleading
# package-not-found error per bundled name
raise EsphomeError(
f"{libraries_dir} is missing; the framework install may be "
"incomplete (run 'esphome clean-all')"
)
bundled_dir_names = frozenset(p.name for p in libraries_dir.iterdir() if p.is_dir())
def _provided(name: object) -> bool:
return _is_safe_library_name(name) and name in bundled_dir_names
for library in CORE.platformio_libraries.values():
if is_lib_ignored(library.name, lib_ignore):
continue
# Bundled only for a bare name with a matching framework dir; pinned
# or unmatched names resolve from the registry, as under PlatformIO.
if not library.repository and not library.version and _provided(library.name):
# Bundled manifest deps are not walked; _bundled_library warns
bundled.append(_bundled_library(framework_path, library.name))
else:
external.append(library)
converted: list[ArduinoLibrary] = []
bundled_names = {lib.name for lib in bundled}
converted_manifest_names: set[str] = set()
# Bundled candidates skipped on purpose (platform filter); the
# provides() reconciliation must count them as satisfied
knowingly_skipped: set[str] = set()
# Dependency names of the manifests actually emitted; a walk recording
# for a since-re-resolved manifest must not fail the reconciliation
final_dep_names: set[str] = set()
# Ordered set of bundled dependency names to add once conversion is done
pending_bundled: dict[str, None] = {}
# Deps matching a separately-requested external are already in the build
# (a duplicate archive means duplicate-symbol link errors)
external_short_names = {
_external_short_name(lib.name) for lib in external if lib.name
}
def _add_bundled_dependencies(component: ConvertedLibrary) -> None:
# A version-less bare name ("Hash") is a core-bundled library the
# shared converter cannot resolve from the registry
for dep in normalize_dependencies(
component.data.get("dependencies"), component.name
):
# normalize_dependencies guarantees a non-empty str name
name = dep["name"]
final_dep_names.add(name)
if "/" in name:
owner, _, pkg = name.partition("/")
if _is_safe_library_name(owner) and _is_safe_library_name(pkg):
# Owner-qualified; the converter resolves it from the registry
continue
if not _is_safe_library_name(name):
# The name becomes a path component; never join a traversal
_LOGGER.warning(
"Ignoring malformed dependency entry %r of library %s",
dep,
component.name,
)
continue
if name in external_short_names:
if _provided(name):
# A bundled copy is suppressed; a coincidental name
# collision would surface as link errors
_LOGGER.warning(
"Dependency %s of %s is assumed satisfied by a "
"requested external library; the bundled copy is "
"not added",
name,
component.name,
)
else:
_LOGGER.debug(
"Dependency %s of %s assumed satisfied by a requested "
"external library",
name,
component.name,
)
continue
if name in bundled_names or is_lib_ignored(name, lib_ignore):
continue
if _url_or_none(dep.get("version")) is not None:
# A URL names one specific source; never add the bundled copy
continue
if dep.get("owner") or not _provided(name):
# Only owner-less framework-tree names take the bundled
# copy (PIO's process_dependencies); the walk reports drops
continue
try:
# framework=None: the walk already warned for non-platform
# causes; debug keeps one fault from warning twice (pinned
# by test_nonplatform_rejection_warns_once_through_real_converter)
check_library_data(dep, pio_platform, None)
except IncompatiblePlatform as err:
# A knowing skip (platform filter), not a broken promise
knowingly_skipped.add(name)
_LOGGER.debug("Skip bundled candidate %s: %s", name, err)
continue
except InvalidLibrary as err:
# Malformed manifest data never counts as satisfied; the
# walk owns the warning (see the warns-once test above)
_LOGGER.debug("Skip malformed bundled candidate %s: %s", name, err)
continue
# Deferred: a later manifest name may satisfy this
pending_bundled.setdefault(name)
def _emit(component: ConvertedLibrary) -> None:
apply_extra_script(
component, board_mcu=lambda: board_mcu, pio_platform=pio_platform
)
_assert_tree_has_code(
component.get_require_name(),
component.source_dir,
"the download may be incomplete (run 'esphome clean-all')",
)
if isinstance(manifest_name := component.data.get("name"), str):
converted_manifest_names.add(manifest_name)
lib = _library_info(
component.get_require_name(), component.source_dir, component.data
)
# Extra-script LINKFLAGS travel outside build.flags; dropping
# them would link wrong with no stated cause
lib.link_flags.extend(
component.data.get(ESPHOME_DATA_KEY, {}).get(
ESPHOME_DATA_LINK_FLAGS_KEY, []
)
)
converted.append(lib)
_add_bundled_dependencies(component)
backend = LibraryBackend(
platform=pio_platform,
framework="arduino",
emit=_emit,
cache_key=cache_key,
# The walk must not resolve bundled names from the registry;
# _add_bundled_dependencies adds them after emit
provides=_provided,
)
if external:
convert_libraries(external, backend)
for name in pending_bundled:
if name in converted_manifest_names:
# The converted library is this one; the bundled copy would
# double the archive. Warn like the external_short_names twin.
_LOGGER.warning(
"Dependency %s is assumed satisfied by a converted library's "
"manifest name; the bundled copy is not added",
name,
)
continue
bundled_names.add(name)
bundled.append(_bundled_library(framework_path, name))
_check_unfulfilled_provides(
backend.provided_requests,
bundled_names
| converted_manifest_names
| external_short_names
| knowingly_skipped,
final_dep_names,
)
return bundled + converted
+9
View File
@@ -0,0 +1,9 @@
"""Native (PlatformIO-free) build support for the ESP8266 Arduino core.
This package downloads the Arduino ESP8266 core and the xtensa-lx106
toolchain, generates a ninja build for them plus the ESPHome sources, and
drives the build directly — the ESP8266 equivalent of ``esphome.espidf``.
Deliberately importable without the esp8266 component to avoid circular
imports; the component wires these modules in via lazy imports.
"""
+159
View File
@@ -0,0 +1,159 @@
"""Download and install the Arduino ESP8266 core, toolchain, and ninja.
Artifacts land in a machine-global cache (shared across projects, like the
ESP-IDF install in ``esphome.espidf.framework``):
<cache>/arduino8266/frameworks/<version>/ framework-arduinoespressif8266
<cache>/arduino8266/toolchains/<version>/ toolchain-xtensa (gcc 10.3)
Packages come from the PlatformIO registry (identical bits to the PlatformIO
backend); ``ESPHOME_ARDUINO8266_*_MIRRORS`` overrides the URLs. ninja comes
from PATH or the ninja PyPI wheel.
"""
from __future__ import annotations
import os
from pathlib import Path
from typing import NamedTuple
from esphome.build_helpers.ccache import ccache_defaults_env
from esphome.build_helpers.ninja import find_ninja
from esphome.build_helpers.tools_cache import ARDUINO8266_TOOLS_CACHE, tools_cache_path
from esphome.core import EsphomeError, Version
from esphome.framework_helpers import str_to_lst_of_str
from esphome.platformio.registry import install_package, prefetch_packages
FRAMEWORK_PACKAGE = "framework-arduinoespressif8266"
TOOLCHAIN_PACKAGE = "toolchain-xtensa"
# gcc 10.3, the toolchain Arduino core 3.x builds with; the build
# generator's compile flags are tuned to it.
TOOLCHAIN_VERSION = "2.100300.220621"
ESPHOME_ARDUINO8266_FRAMEWORK_MIRRORS = str_to_lst_of_str(
os.environ.get("ESPHOME_ARDUINO8266_FRAMEWORK_MIRRORS", "")
)
ESPHOME_ARDUINO8266_TOOLCHAIN_MIRRORS = str_to_lst_of_str(
os.environ.get("ESPHOME_ARDUINO8266_TOOLCHAIN_MIRRORS", "")
)
def get_arduino8266_tools_path() -> Path:
# Machine-global so all projects share one install; see
# espidf.framework.get_idf_tools_path for the location rationale.
return tools_cache_path(*ARDUINO8266_TOOLS_CACHE)
# 3.1.1 rather than 3.1.0: the registry has no packages for 3.0.0, 3.0.1 or 3.1.0
MIN_FRAMEWORK_VERSION = Version(3, 1, 1)
def framework_package_version(ver: Version) -> str:
"""Map an Arduino core version to its registry package version (3.1.2 ->
3.30102.0; the leading 3 is the package major).
Exact registry names for 3.x cores; callers floor at MIN_FRAMEWORK_VERSION.
"""
if ver.major > 3:
raise EsphomeError(
f"Arduino core {ver} is not supported yet; "
"the newest known core series is 3.x"
)
if ver.major < 3:
raise EsphomeError(
f"Arduino core {ver} is not supported; ESPHome requires core 3.x"
)
return f"3.{ver.major}{ver.minor:02d}{ver.patch:02d}.0"
def get_framework_path(package_version: str) -> Path:
return get_arduino8266_tools_path() / "frameworks" / package_version
def get_toolchain_path() -> Path:
return get_arduino8266_tools_path() / "toolchains" / TOOLCHAIN_VERSION
class InstalledPaths(NamedTuple):
"""Locations of the installed framework, toolchain, and ninja binary."""
framework: Path
toolchain: Path
ninja: Path
def check_and_install(framework_version: Version) -> InstalledPaths:
"""Ensure framework, toolchain, and ninja are installed; return their paths."""
if framework_version < MIN_FRAMEWORK_VERSION:
# Config validation enforces this too; keep the module honest when
# called directly.
raise EsphomeError(
f"The native toolchain requires the Arduino core "
f">= {MIN_FRAMEWORK_VERSION}, got {framework_version}"
)
# Probe the cheap local dependency before ~110 MB of downloads
ninja_path = find_ninja()
package_version = framework_package_version(framework_version)
framework_path = get_framework_path(package_version)
downloads_dir = get_arduino8266_tools_path() / "downloads"
toolchain_path = get_toolchain_path()
# One spec per package: the prefetch and the installs must agree
specs = (
(
FRAMEWORK_PACKAGE,
package_version,
framework_path,
ESPHOME_ARDUINO8266_FRAMEWORK_MIRRORS,
("cores/esp8266", "tools/sdk", "libraries"),
),
(
TOOLCHAIN_PACKAGE,
TOOLCHAIN_VERSION,
toolchain_path,
ESPHOME_ARDUINO8266_TOOLCHAIN_MIRRORS,
# xtensa-lx106-elf pins the target: every gcc package has a bin/
("bin", "xtensa-lx106-elf"),
),
)
# Fetch both archives at once; the installs below verify and extract
prefetch_packages([spec[:4] for spec in specs], downloads_dir)
for name, version, dest, mirrors, expect in specs:
install_package(name, version, dest, mirrors, downloads_dir, expect=expect)
return InstalledPaths(
framework=framework_path, toolchain=toolchain_path, ninja=ninja_path
)
def toolchain_tool(toolchain_path: Path, name: str) -> Path:
"""Path to one toolchain tool (gcc, g++, ar, size, addr2line, ...).
The single owner of the ``bin/xtensa-lx106-elf-<name>`` layout and the
Windows suffix, so a toolchain package bump touches one spot.
"""
suffix = ".exe" if os.name == "nt" else ""
return toolchain_path / "bin" / f"xtensa-lx106-elf-{name}{suffix}"
def get_build_env(toolchain_path: Path, ccache: str | None) -> dict[str, str]:
env = os.environ.copy()
# Drop empty entries: a trailing separator from an absent PATH would
# make the shell search the current directory for tools
parts = [
str(toolchain_path / "bin"),
*filter(None, env.get("PATH", "").split(os.pathsep)),
]
env["PATH"] = os.pathsep.join(parts)
env.update(ccache_env(ccache))
return env
def ccache_env(ccache: str | None) -> dict[str, str]:
"""Return ccache settings for the build subprocess (not os.environ).
``ccache`` is the pre-resolved binary (resolve_ccache_path), or None
when disabled. Values the user already set in the environment are
respected.
"""
if ccache is None:
return {}
return ccache_defaults_env(get_arduino8266_tools_path() / "ccache")
+112 -22
View File
@@ -11,46 +11,136 @@ from __future__ import annotations
import asyncio
from collections.abc import Awaitable, Callable
from itertools import count
import logging
import threading
from typing import Generic, TypeVar
from typing import cast
_T = TypeVar("_T")
_LOGGER = logging.getLogger(__name__)
# How long the orphan watcher waits for an abandoned coroutine before giving
# up, so a hung operation does not park a watcher thread forever.
ORPHAN_WAIT_TIMEOUT = 300.0
class AsyncThreadRunner(threading.Thread, Generic[_T]):
"""Run an async coroutine in a daemon thread and expose its result.
_runner_ids = count(1)
The runner catches all exceptions from the coroutine and stores them in
``exception`` so ``event`` is always set — this prevents callers waiting
on ``event`` from hanging forever when the coroutine crashes.
Typical usage::
class AsyncDispatchTimeout(TimeoutError):
"""The caller stopped waiting; the coroutine was abandoned.
runner = AsyncThreadRunner(lambda: my_coro(arg))
runner.start()
if not runner.event.wait(timeout=5.0):
... # timed out
if runner.exception is not None:
raise runner.exception
result = runner.result
A subclass so callers can tell the dispatcher's own expiry apart from a
``TimeoutError`` raised inside the coroutine, while existing
``except TimeoutError`` handlers keep working.
"""
def __init__(self, coro_factory: Callable[[], Awaitable[_T]]) -> None:
super().__init__(daemon=True)
class AsyncThreadRunner[T](threading.Thread):
"""Run an async coroutine in a daemon thread and expose its result.
``event`` is always set, even when the coroutine crashes, so waiters
never hang; ``completed`` distinguishes a delivered result (even a
legitimate ``None``) from a coroutine that never finished. Prefer
:func:`run_async`; use this class directly only when a failure should
degrade to a default value instead of raising.
"""
def __init__(self, coro_factory: Callable[[], Awaitable[T]]) -> None:
super().__init__(daemon=True, name=f"async-thread-runner-{next(_runner_ids)}")
self._coro_factory = coro_factory
self.result: _T | None = None
self.result: T | None = None
self.exception: BaseException | None = None
self.completed = False
self.event = threading.Event()
async def _runner(self) -> None:
try:
self.result = await self._coro_factory()
except Exception as exc: # noqa: BLE001 # pylint: disable=broad-except
# Capture all exceptions so ``event`` is always set — otherwise a
# crash would hang the waiter forever.
# Distinguishes a delivered result from "never ran", since None
# is a valid result value.
self.completed = True
except BaseException as exc: # noqa: BLE001 # pylint: disable=broad-except
# Capture everything, including BaseException — otherwise a
# cancellation or SystemExit would leave ``exception`` unset and
# waiters would mistake the empty ``result`` for success.
self.exception = exc
finally:
self.event.set()
def run(self) -> None:
asyncio.run(self._runner())
try:
asyncio.run(self._runner())
except BaseException as exc: # noqa: BLE001 # pylint: disable=broad-except
# asyncio.run itself can fail before _runner executes (e.g. loop
# creation under fd exhaustion); record it so waiters never hang.
# A failure during loop cleanup after the coroutine completed
# must not clobber the delivered result, hence the guard.
if self.exception is None and not self.completed:
self.exception = exc
else:
_LOGGER.debug(
"Event loop teardown failed after outcome recorded",
exc_info=True,
)
finally:
self.event.set()
def run_async[T](
coro_factory: Callable[[], Awaitable[T]],
timeout: float | None = None,
on_orphan: Callable[[T], None] | None = None,
) -> T:
"""Run a coroutine in a daemon-thread event loop and return its result.
Raises :class:`AsyncDispatchTimeout` if the coroutine does not finish
within ``timeout`` seconds; the thread is abandoned and exits with the
interpreter. If the abandoned coroutine later produces a result,
``on_orphan`` (if given) is called with it so resources such as a
connected socket can be released; delivery is best effort and bounded
by ``ORPHAN_WAIT_TIMEOUT``.
"""
runner: AsyncThreadRunner[T] = AsyncThreadRunner(coro_factory)
runner.start()
if not runner.event.wait(timeout):
def _cleanup() -> None:
if not runner.event.wait(ORPHAN_WAIT_TIMEOUT):
# The one state where a resource can genuinely leak; leave
# a trace so a recurring hang is attributable.
_LOGGER.info(
"Orphan watcher gave up after %.0fs; a late result may leak",
ORPHAN_WAIT_TIMEOUT,
)
return
if not runner.completed:
# The only place an abandoned thread's real error surfaces;
# without it a late failure hides behind the TimeoutError.
# INFO, not DEBUG: it fires at most once per abandoned
# operation and the cause may not reproduce on a rerun.
_LOGGER.info(
"Abandoned async operation failed",
exc_info=runner.exception,
)
return
if (result := runner.result) is None:
return
if on_orphan is None:
_LOGGER.debug("Discarding late result; no on_orphan handler")
return
try:
on_orphan(result)
except Exception: # pylint: disable=broad-except
# INFO, not DEBUG: a failed release means a real leak, and
# it fires at most once per abandoned operation.
_LOGGER.info("Error releasing orphaned result", exc_info=True)
threading.Thread(
target=_cleanup, daemon=True, name="async-orphan-cleanup"
).start()
raise AsyncDispatchTimeout("Timed out waiting for async operation")
if (exc := runner.exception) is not None:
raise exc
if not runner.completed:
raise RuntimeError("Async operation finished without a result or an exception")
return cast("T", runner.result)
+108
View File
@@ -0,0 +1,108 @@
"""Tiny cross-platform build steps invoked from the generated ninja file.
Plain script (not ``python -m``): it runs from ninja with whatever Python
started esphome and must not depend on the package being importable.
Subcommands:
ar <ar-binary> <archive> <rspfile> remove stale archive, then ``ar rcs``
copy <src> <dst> copy a file
The ar rspfile carries one object path per line (the generating rule must
use ``$in_newline``, never ``$in``).
"""
from pathlib import Path
import shutil
import subprocess
import sys
def _read_rspfile(rspfile: str) -> list[str]:
r"""The object paths listed in ``rspfile``, unquoted.
GNU ar treats backslashes in response files as escapes (corrupts
Windows paths), so the caller expands the list into argv; strip the
simple surrounding quote ninja adds to special paths, then undo
ninja's POSIX escape for an embedded quote ('a'\\''b.o' -> a'b.o).
"""
return [
line[1:-1].replace("'\\''", "'")
if len(line) >= 2 and line[0] == line[-1] and line[0] in "'\""
else line
for line in Path(rspfile).read_text(encoding="utf-8").splitlines()
if line
]
def _run_ar(ar: str, archive: str, rspfile: str) -> int:
# Remove first: ``ar rcs`` replaces members but never drops ones whose
# source was removed from the build, which would leak stale objects.
Path(archive).unlink(missing_ok=True)
objects = _read_rspfile(rspfile)
if not objects:
# An empty archive would "succeed" here and fail far away at link
print(f"ar: no objects listed in {rspfile} for {archive}", file=sys.stderr)
return 1
# Batch by argv length: expanding the rspfile gives back the Windows
# 32767-char command-line limit it existed to avoid. "rcs" creates,
# "qs" appends; the s keeps the symbol index explicit on every ar.
op = "rcs"
ok = False
try:
while objects:
batch = [objects.pop(0)]
batch_len = len(batch[0])
while objects and batch_len + len(objects[0]) < 25000:
batch_len += len(objects[0]) + 1
batch.append(objects.pop(0))
rc = subprocess.run(
[ar, op, archive, *batch], check=False, close_fds=False
).returncode
if rc != 0:
return rc
op = "qs"
ok = True
return 0
finally:
if not ok:
# Any failure (bad exit, missing ar binary, interrupt) must not
# leave a truncated archive behind
Path(archive).unlink(missing_ok=True)
def _run_copy(src: str, dst: str) -> int:
try:
shutil.copyfile(src, dst)
except OSError as err:
# Never leave a partially written output (e.g. a firmware image);
# SameFileError means dst IS src, where unlinking destroys the input
if not isinstance(err, shutil.SameFileError):
Path(dst).unlink(missing_ok=True)
print(f"copy: {src} -> {dst} failed: {err}", file=sys.stderr)
return 1
return 0
# mode -> (handler, expected operand count); surplus argv means a
# mis-specified ninja rule and must error, not silently drop operands
_MODES = {"ar": (_run_ar, 3), "copy": (_run_copy, 2)}
def main() -> int:
mode = sys.argv[1] if len(sys.argv) > 1 else ""
if entry := _MODES.get(mode):
handler, argc = entry
args = sys.argv[2:]
if len(args) != argc:
print(
f"build_tool {mode}: expected {argc} arguments, got {len(args)}",
file=sys.stderr,
)
return 1
return handler(*args)
print(f"unknown build_tool mode: {mode}", file=sys.stderr)
return 1
if __name__ == "__main__": # pragma: no cover
sys.exit(main())
+129 -51
View File
@@ -1,21 +1,46 @@
"""ESP-IDF direct build generator for ESPHome."""
import json
import logging
from pathlib import Path
from esphome.components.esp32 import get_esp32_variant, idf_version
from esphome.components.esp32 import (
get_esp32_variant,
get_excluded_builtin_components,
get_managed_component_require_names,
idf_version,
)
import esphome.config_validation as cv
from esphome.core import CORE
from esphome.espidf import variant_to_idf_target
from esphome.framework_helpers import (
get_project_compile_flags,
get_project_cxx_compile_flags,
get_project_link_flags,
)
from esphome.helpers import mkdir_p, write_file_if_changed
from esphome.writer import update_storage_json
_LOGGER = logging.getLogger(__name__)
# Replaces the IDF default C++ standard (-std=gnu++2b appended to
# CXX_COMPILE_OPTIONS by project.cmake's __build_init) with the one set via
# cg.set_cpp_standard(). Emitted between include(project.cmake) and project(),
# i.e. after IDF appends its default and before the options are consumed, and
# applies project-wide like PlatformIO build_unflags.
CPP_STANDARD_TEMPLATE = """\
idf_build_get_property(esphome_cxx_compile_options CXX_COMPILE_OPTIONS)
list(FILTER esphome_cxx_compile_options EXCLUDE REGEX "^-std=")
list(APPEND esphome_cxx_compile_options "-std={standard}")
idf_build_set_property(CXX_COMPILE_OPTIONS "${{esphome_cxx_compile_options}}")"""
def get_available_components() -> list[str] | None:
"""Get list of built-in ESP-IDF components from project_description.json.
"""List the built-in ESP-IDF components from ``project_description.json``.
Excludes ``src``, IDF-managed components (``managed_components/``), and
converted PIO libs (``pio_components/``). Returns ``None`` if the build
dir or ``project_description.json`` isn't ready yet.
Only components below its ``idf_path/components`` count, which leaves out
``src``, IDF-managed components, converted PIO libs and project local
ones such as the Arduino ``component_stubs``. Returns ``None`` if the
build dir or ``project_description.json`` isn't ready yet.
"""
if CORE.build_path is None:
return None
@@ -26,41 +51,44 @@ def get_available_components() -> list[str] | None:
try:
with project_desc.open(encoding="utf-8") as f:
data = json.load(f)
component_info = data.get("build_component_info", {})
result = []
for name, info in component_info.items():
# Exclude our own src component
if name == "src":
continue
# Exclude IDF-managed and converted-PIO components (external).
comp_dir = info.get("dir", "")
if "managed_components" in comp_dir or "pio_components" in comp_dir:
continue
result.append(name)
return result
except (json.JSONDecodeError, OSError):
root = (Path(data["idf_path"]) / "components").resolve()
result = [
name
for name, info in data.get("build_component_info", {}).items()
if (comp_dir := info.get("dir"))
and Path(comp_dir).resolve().is_relative_to(root)
]
except (json.JSONDecodeError, KeyError, OSError) as err:
_LOGGER.debug("Could not read %s: %s", project_desc, err)
return None
if not result:
_LOGGER.warning("No ESP-IDF components found under %s", root)
return result
def has_discovered_components() -> bool:
"""Check if we have discovered components from a previous configure."""
return get_available_components() is not None
"""Check if a previous configure discovered any built-in components."""
return bool(get_available_components())
def get_project_cmakelists(minimal: bool = False) -> str:
def _cmake_quote(value: str) -> str:
"""Quote a cmake arg value for a set() line. add_cmake_arg rejects
whitespace, quotes, and '$', so only backslashes need escaping."""
escaped = value.replace("\\", "\\\\")
return f'"{escaped}"'
def get_project_cmakelists(
minimal: bool = False, builtin_components: list[str] | None = None
) -> str:
"""Generate the top-level CMakeLists.txt for ESP-IDF project.
When ``minimal`` is true, omit ``ESPHOME_PROJECT_BUILTIN_COMPONENTS``
since ``project_description.json`` may be stale on the first write.
``builtin_components`` supplies the discovered list (from the cache)
instead of reading it from ``project_description.json``.
"""
# Get IDF target from ESP32 variant (e.g., ESP32S3 -> esp32s3)
variant = get_esp32_variant()
idf_target = variant.lower().replace("-", "")
idf_target = variant_to_idf_target(get_esp32_variant())
# esp_idf_size 2.x (bundled with IDF >=6.0) made NG the default and
# removed the --ng flag; on 1.x (IDF 5.5) --ng is required to get
@@ -74,17 +102,35 @@ def get_project_cmakelists(minimal: bool = False) -> str:
# esphome__micro-mp3) rather than just src/. Required so suppressions
# like ``-Wno-error=maybe-uninitialized`` actually silence warnings in
# third-party components we don't author.
project_compile_opts = [
flag
for flag in sorted(CORE.build_flags)
if flag.startswith("-D")
or (flag.startswith("-W") and not flag.startswith("-Wl,"))
]
project_compile_opts = get_project_compile_flags()
extra_compile_options = "\n".join(
f'idf_build_set_property(COMPILE_OPTIONS "{flag}" APPEND)'
for flag in project_compile_opts
)
# Flags registered via cg.add_cxx_build_flag() go on CXX_COMPILE_OPTIONS
# (not COMPILE_OPTIONS) because GCC warns when a C++-only flag such as
# -Wno-volatile is passed on a C compile.
cxx_compile_options = "\n".join(
f'idf_build_set_property(CXX_COMPILE_OPTIONS "{flag}" APPEND)'
for flag in get_project_cxx_compile_flags()
)
cpp_standard_options = (
CPP_STANDARD_TEMPLATE.format(standard=CORE.cpp_standard)
if CORE.cpp_standard
else ""
)
# CMake variables registered via cg.add_cmake_arg(). Emitted before
# include(project.cmake) so values like EXCLUDE_COMPONENTS are already
# set when project.cmake seeds the component list, and on minimal
# (discovery) writes too so excluded components never register.
cmake_args = "\n".join(
f"set({name} {_cmake_quote(value)})"
for name, value in sorted(CORE.cmake_args.items())
)
# Per-project list exposed as a CMake variable so converted PIO libs
# can reference ${ESPHOME_PROJECT_MANAGED_COMPONENTS} without baking
# project-specific names into their cached CMakeLists.
@@ -95,8 +141,6 @@ def get_project_cmakelists(minimal: bool = False) -> str:
# runs as a separate CMake script invocation that doesn't load the
# project's top-level CMakeLists; without this, ${ESPHOME_PROJECT_
# MANAGED_COMPONENTS} in a converted-lib REQUIRES expands to empty).
from esphome.components.esp32 import get_managed_component_require_names
managed_components_property = "\n".join(
f"idf_build_set_property(ESPHOME_PROJECT_MANAGED_COMPONENTS {name} APPEND)"
for name in get_managed_component_require_names()
@@ -107,12 +151,24 @@ def get_project_cmakelists(minimal: bool = False) -> str:
# component's REQUIRES including real IDF components). Referenced by
# src/CMakeLists and by each converted PIO lib's CMakeLists. Skipped
# on minimal writes because project_description.json may be stale.
# Excluded components are dropped here as well: a stale
# project_description.json from a build without exclusions may still
# list them, and requiring an excluded component pulls it back into
# the build (IDF requirement expansion overrides EXCLUDE_COMPONENTS).
# Derived from the EXCLUDE_COMPONENTS cmake arg emitted above so the
# two can never disagree within one generated file.
builtin_components_property = (
""
if minimal
else "\n".join(
f"idf_build_set_property(ESPHOME_PROJECT_BUILTIN_COMPONENTS {name} APPEND)"
for name in sorted(get_available_components() or [])
for name in sorted(
set(
builtin_components
if builtin_components is not None
else get_available_components() or []
).difference(CORE.cmake_args.get("EXCLUDE_COMPONENTS", "").split(";"))
)
)
)
@@ -139,8 +195,14 @@ set(CMAKE_NINJA_FORCE_RESPONSE_FILE 1)
set(IDF_TARGET {idf_target})
set(EXTRA_COMPONENT_DIRS ${{CMAKE_SOURCE_DIR}}/src)
{cmake_args}
include($ENV{{IDF_PATH}}/tools/cmake/project.cmake)
{cpp_standard_options}
{cxx_compile_options}
{extra_compile_options}
{managed_components_property}
@@ -170,8 +232,8 @@ def get_component_cmakelists() -> str:
# Extract linker options (-Wl, flags). Compile flags (-D, -W) are
# emitted project-wide via idf_build_set_property in
# get_project_cmakelists so they reach every component, not just src/.
link_opts = [flag for flag in CORE.build_flags if flag.startswith("-Wl,")]
link_opts_str = "\n ".join(sorted(link_opts)) if link_opts else ""
link_opts = get_project_link_flags()
link_opts_str = "\n ".join(link_opts) if link_opts else ""
return f"""\
# Auto-generated by ESPHome
@@ -182,15 +244,27 @@ def get_component_cmakelists() -> str:
if(CMAKE_SCRIPT_MODE_FILE)
file(GLOB_RECURSE app_sources
"${{CMAKE_CURRENT_SOURCE_DIR}}/*.cpp"
"${{CMAKE_CURRENT_SOURCE_DIR}}/*.cc"
"${{CMAKE_CURRENT_SOURCE_DIR}}/*.cxx"
"${{CMAKE_CURRENT_SOURCE_DIR}}/*.c++"
"${{CMAKE_CURRENT_SOURCE_DIR}}/*.c"
"${{CMAKE_CURRENT_SOURCE_DIR}}/esphome/*.cpp"
"${{CMAKE_CURRENT_SOURCE_DIR}}/esphome/*.cc"
"${{CMAKE_CURRENT_SOURCE_DIR}}/esphome/*.cxx"
"${{CMAKE_CURRENT_SOURCE_DIR}}/esphome/*.c++"
"${{CMAKE_CURRENT_SOURCE_DIR}}/esphome/*.c"
)
else()
file(GLOB_RECURSE app_sources CONFIGURE_DEPENDS
"${{CMAKE_CURRENT_SOURCE_DIR}}/*.cpp"
"${{CMAKE_CURRENT_SOURCE_DIR}}/*.cc"
"${{CMAKE_CURRENT_SOURCE_DIR}}/*.cxx"
"${{CMAKE_CURRENT_SOURCE_DIR}}/*.c++"
"${{CMAKE_CURRENT_SOURCE_DIR}}/*.c"
"${{CMAKE_CURRENT_SOURCE_DIR}}/esphome/*.cpp"
"${{CMAKE_CURRENT_SOURCE_DIR}}/esphome/*.cc"
"${{CMAKE_CURRENT_SOURCE_DIR}}/esphome/*.cxx"
"${{CMAKE_CURRENT_SOURCE_DIR}}/esphome/*.c++"
"${{CMAKE_CURRENT_SOURCE_DIR}}/esphome/*.c"
)
endif()
@@ -201,9 +275,6 @@ idf_component_register(
REQUIRES ${{ESPHOME_PROJECT_BUILTIN_COMPONENTS}}
)
# Apply C++ standard
target_compile_features(${{COMPONENT_LIB}} PUBLIC cxx_std_20)
# ESPHome linker options
target_link_options(${{COMPONENT_LIB}} PUBLIC
{link_opts_str}
@@ -211,20 +282,17 @@ target_link_options(${{COMPONENT_LIB}} PUBLIC
"""
def write_project(minimal: bool = False) -> None:
def write_project(
minimal: bool = False, builtin_components: list[str] | None = None
) -> None:
"""Write ESP-IDF project files."""
# Refresh <data_dir>/storage/<name>.yaml.json so the dashboard's
# /info and /downloads endpoints can locate the build (they 404
# otherwise). This mirrors the PlatformIO build-gen path's call
# in build_gen/platformio.py:write_ini().
update_storage_json()
mkdir_p(CORE.build_path)
mkdir_p(CORE.relative_src_path())
# Write top-level CMakeLists.txt
write_file_if_changed(
CORE.relative_build_path("CMakeLists.txt"),
get_project_cmakelists(minimal=minimal),
get_project_cmakelists(minimal=minimal, builtin_components=builtin_components),
)
# Write component CMakeLists.txt in src/
@@ -232,3 +300,13 @@ def write_project(minimal: bool = False) -> None:
CORE.relative_src_path("CMakeLists.txt"),
get_component_cmakelists(),
)
# Snapshot the exclusion set so has_outdated_files() can trigger a
# discovery reconfigure when it changes. Excluded components never
# register in project_description.json, so re-including one (e.g. a
# config gains mqtt) requires a fresh discovery pass before the
# ESPHOME_PROJECT_BUILTIN_COMPONENTS property can list it.
write_file_if_changed(
CORE.relative_build_path("exclude_components.esphomeinternal"),
";".join(get_excluded_builtin_components()),
)
+29 -5
View File
@@ -1,7 +1,7 @@
from esphome.const import __version__
from esphome.core import CORE
from esphome.helpers import mkdir_p, read_file, write_file_if_changed
from esphome.writer import find_begin_end, update_storage_json
from esphome.writer import find_begin_end
INI_AUTO_GENERATE_BEGIN = "; ========== AUTO GENERATED CODE BEGIN ==========="
INI_AUTO_GENERATE_END = "; =========== AUTO GENERATED CODE END ============"
@@ -33,12 +33,27 @@ def format_ini(data: dict[str, str | list[str]]) -> str:
return content
# All -std= variants a platform/framework may set by default, in both the GNU
# and strict dialects; unflagged so the cg.set_cpp_standard() value is the
# only standard left in the build.
CPP_STD_VARIANTS = [
f"{prefix}{year}"
for year in ("11", "14", "17", "20", "23", "26", "2a", "2b", "2c")
for prefix in ("gnu++", "c++")
]
def get_ini_content():
CORE.add_platformio_option(
"lib_deps",
[x.as_lib_dep for x in CORE.platformio_libraries.values()]
+ ["${common.lib_deps}"],
)
if CORE.cpp_standard:
for variant in CPP_STD_VARIANTS:
if variant != CORE.cpp_standard:
CORE.add_build_unflag(f"-std={variant}")
CORE.add_build_flag(f"-std={CORE.cpp_standard}")
# Sort to avoid changing build flags order
CORE.add_platformio_option("build_flags", sorted(CORE.build_flags))
@@ -48,6 +63,17 @@ def get_ini_content():
# Add extra script for C++ flags
CORE.add_platformio_option("extra_scripts", [f"pre:{CXX_FLAGS_FILE_NAME}"])
# Add CMake args. A user-supplied value (str or list) is deliberately
# replaced; this option was always overwritten at FINAL priority.
if CORE.cmake_args:
CORE.add_platformio_option(
"board_build.cmake_extra_args",
" ".join(
f"-D{name}={value}" for name, value in sorted(CORE.cmake_args.items())
),
replace=True,
)
content = "[platformio]\n"
content += f"description = ESPHome {__version__}\n"
@@ -58,7 +84,6 @@ def get_ini_content():
def write_ini(content):
update_storage_json()
path = CORE.relative_build_path("platformio.ini")
if path.is_file():
@@ -94,7 +119,6 @@ Import("env")
def write_cxx_flags_script() -> None:
path = CORE.relative_build_path(CXX_FLAGS_FILE_NAME)
contents = CXX_FLAGS_FILE_CONTENTS
if not CORE.is_host:
contents += 'env.Append(CXXFLAGS=["-Wno-volatile"])'
contents += "\n"
for flag in sorted(CORE.cxx_build_flags):
contents += f'env.Append(CXXFLAGS=["{flag}"])\n'
write_file_if_changed(path, contents)
+1
View File
@@ -0,0 +1 @@
"""Build helpers shared by the native (non-PlatformIO) toolchains."""
+92
View File
@@ -0,0 +1,92 @@
"""Shared ccache policy for build backends: env-knob parsing, binary
resolution, and default ``CCACHE_*`` values."""
from __future__ import annotations
import logging
import os
from pathlib import Path
from esphome.framework_helpers import strip_win_long_path_prefix, tool_version_runs
from esphome.helpers import FALSY_ENV_STRINGS, TRUTHY_ENV_STRINGS
_LOGGER = logging.getLogger(__name__)
def _ccache_runs(ccache: str) -> bool:
"""Return True when the ``ccache`` found on PATH actually runs."""
return tool_version_runs(
ccache,
"Ignoring ccache at %s because it failed to run; compiling without ccache",
)
def parse_enable_env(name: str) -> bool | None:
"""Strictly parse an on/off environment knob; None when unset or invalid.
``bool(str)`` truthiness would flip ``no``/``off`` to enabled, so only
1/true/yes/on and 0/false/no/off count; anything else warns and reads
as unset so the caller's default policy applies.
"""
raw = os.environ.get(name)
if raw is None:
return None
lowered = raw.strip().lower()
if not lowered:
# ENV KNOB= (Docker/CI) has always read as a disable
return False
if lowered in TRUTHY_ENV_STRINGS:
return True
if lowered in FALSY_ENV_STRINGS:
return False
_LOGGER.warning("Ignoring unrecognized %s=%r; use 1 or 0", name, raw)
return None
def resolve_ccache_path() -> str | None:
"""The ccache binary to wrap compiles with, or None when disabled.
An explicit ``ESPHOME_CCACHE_ENABLE=1`` skips the runnability probe; the
Windows extended-length prefix is stripped before probing (#18399).
"""
import shutil
explicit = parse_enable_env("ESPHOME_CCACHE_ENABLE")
if explicit is False:
return None
ccache = shutil.which("ccache")
if ccache is None:
if explicit:
_LOGGER.warning(
"ESPHOME_CCACHE_ENABLE is set but no ccache binary is on PATH; "
"compiling without ccache"
)
return None
ccache = strip_win_long_path_prefix(ccache)
if not explicit and not _ccache_runs(ccache):
return None
return ccache
def ccache_defaults_env(cache_dir: Path) -> dict[str, str]:
"""Default ``CCACHE_*`` values for a build subprocess (not os.environ).
Values the user already set in the environment are respected. Depend
mode is on: both native backends emit depfiles (-MMD / CMake), which
keeps cache-miss overhead low.
"""
from esphome.core import CORE
# An unset build_path means the env was built before preload; fail loudly
# rather than silently drop CCACHE_BASEDIR.
if CORE.build_path is None:
raise ValueError(
"CORE.build_path must be set before constructing the build environment"
)
defaults = {
"CCACHE_DIR": str(cache_dir),
"CCACHE_NOHASHDIR": "true",
"CCACHE_DEPEND": "1",
"CCACHE_BASEDIR": str(Path(CORE.build_path).resolve()),
}
return {k: v for k, v in defaults.items() if k not in os.environ}
+380
View File
@@ -0,0 +1,380 @@
"""Derive idedata from a native (non-PlatformIO) build's ``compile_commands.json``.
PlatformIO exposes a curated ``pio run -t idedata`` JSON; the native
toolchains have no such command, but each build produces a
``compile_commands.json`` (CMAKE_EXPORT_COMPILE_COMMANDS for ESP-IDF, ninja's
compdb tool otherwise). This module turns that file into the same fields
consumers (IDE integration, clang-tidy) expect:
{cc_path, cxx_path, cxx_flags, defines, includes: {build, toolchain}}
"""
from __future__ import annotations
import json
import logging
import os
from pathlib import Path
import shlex
import subprocess
from esphome.core import EsphomeError
from esphome.helpers import write_file
# Everything idedata generation may raise after a successful link; idedata
# is a bonus artifact, so consumers warn instead of failing the build
IDEDATA_BEST_EFFORT_ERRORS = (
EsphomeError,
LookupError,
OSError,
RuntimeError,
ValueError,
)
_LOGGER = logging.getLogger(__name__)
# C++ translation-unit suffixes used to identify ESPHome source files.
_CXX_SUFFIXES = (".cpp", ".cc")
# Suffixes of input/output files that appear bare on the command line (and so
# must not be mistaken for compiler flags).
_INPUT_FILE_SUFFIXES = (*_CXX_SUFFIXES, ".c", ".o", ".S", ".s")
# Path marker identifying an ESPHome source translation unit.
_ESPHOME_SRC_MARKER = "/src/esphome/"
def _is_esphome_src(file: str) -> bool:
"""Whether ``file`` is an ESPHome C++ translation unit; normalized to
``/`` first since Windows compile DBs use backslashes."""
return _ESPHOME_SRC_MARKER in file.replace("\\", "/") and file.endswith(
_CXX_SUFFIXES
)
def _split_command(command: str) -> list[str]:
r"""Tokenize a compile_commands.json / response-file command string.
On Windows, tokenize per Windows ``argv`` rules via ``CommandLineToArgvW``.
ESP-IDF's compile_commands.json there mixes two backslash conventions in one
string: literal path separators in the compiler path (``C:\Users\...g++.exe``,
no quote follows) and shell quote-escaping in -D defines (``-DVER=\"1.2.3\"``).
Only the real Windows parser — where a backslash escapes solely a following
quote — handles both, and it is the exact tokenizer the compiler is launched
with. ``shlex`` cannot: POSIX mode eats the path separators, and disabling
its escape mangles the defines.
"""
if os.name != "nt":
return shlex.split(command)
import ctypes
from ctypes import wintypes
# CommandLineToArgvW("") returns the current process name, not []; guard it
# so an empty response file tokenizes the same as it would via shlex.
if not command.strip():
return []
CommandLineToArgvW = ctypes.windll.shell32.CommandLineToArgvW
CommandLineToArgvW.argtypes = [wintypes.LPCWSTR, ctypes.POINTER(ctypes.c_int)]
CommandLineToArgvW.restype = ctypes.POINTER(wintypes.LPWSTR)
argc = ctypes.c_int()
argv = CommandLineToArgvW(command, ctypes.byref(argc))
if not argv: # pragma: no cover
raise ctypes.WinError()
try:
return [argv[i] for i in range(argc.value)]
finally:
ctypes.windll.kernel32.LocalFree(argv)
def _expand_response_files(tokens: list[str], directory: Path) -> list[str]:
"""Inline any ``@response-file`` arguments (paths relative to ``directory``).
GCC response files embed flags that must be expanded so GCC-only flags
inside them (e.g. ``-mlongcalls``) can be filtered downstream; left as
``@file`` clang would read them and choke.
"""
out: list[str] = []
for tok in tokens:
if tok.startswith("@"):
rf = Path(tok[1:])
if not rf.is_absolute():
rf = directory / rf
try:
out.extend(
_expand_response_files(
_split_command(rf.read_text(encoding="utf-8")), directory
)
)
continue
except OSError as err:
# Keep the literal token if the file can't be read, but log it
# so the (otherwise opaque) downstream clang failure is traceable.
_LOGGER.warning("Could not read response file %s: %s", rf, err)
out.append(tok)
return out
def _pick_entry(entries: list[dict]) -> dict:
"""Pick a representative ESPHome C++ TU; all share the same component
flags/defines."""
for entry in entries:
if _is_esphome_src(entry["file"]):
return entry
for entry in entries:
if entry["file"].endswith(_CXX_SUFFIXES):
return entry
raise ValueError("no C++ translation unit found in compile_commands.json")
# Compiler launchers that may prefix a compile command; a closed launcher
# denylist beats enumerating compiler names, an open set.
_LAUNCHER_STEMS = frozenset({"ccache", "sccache", "distcc", "icecc", "buildcache"})
def _is_launcher(token: str) -> bool:
return Path(token).stem.lower() in _LAUNCHER_STEMS
def parse_entry(
entry: dict, launcher: str | None = None
) -> tuple[str, list[str], list[str], list[str]]:
"""Parse one compile_commands entry -> (cxx_path, defines, includes, cxx_flags)."""
directory = Path(entry["directory"])
tokens = _expand_response_files(_split_command(entry["command"]), directory)
def _include(raw: str) -> str:
# Resolve against the entry's ``directory`` so cached idedata works
# from any cwd; emit forward slashes to match the JSON's own entries
raw = raw.strip()
if raw and not Path(raw).is_absolute():
raw = os.path.normpath(directory / raw)
return raw.replace("\\", "/")
# A launcher-wrapped command ("ccache g++ ...") names the compiler second
if launcher is not None and tokens[:1] == [launcher]:
tokens = tokens[1:]
if not tokens:
# An empty command, or one that was only the launcher; fail by name
raise ValueError(f"empty compile command for {entry.get('file')}")
if _is_launcher(tokens[0]) and len(tokens) > 1 and not tokens[1].startswith("-"):
# Stale DB built with a launcher this run no longer configures; the
# real compiler is the next token
_LOGGER.warning("Stripping unconfigured launcher %s", tokens[0])
tokens = tokens[1:]
# token0 is the compiler path; the rest of the command already uses forward
# slashes on Windows, so normalize it too for a consistent idedata file.
cxx_path = tokens[0].replace("\\", "/")
# Enforced here so no caller can record ccache as the compiler
reject_launcher_compiler(cxx_path)
defines: list[str] = []
includes: list[str] = []
cxx_flags: list[str] = []
it = iter(tokens[1:])
for tok in it:
if tok in ("-c", "-o"):
next(it, None) # drop the flag and its argument (input/output)
elif tok.startswith("-D"):
# ``.strip()`` handles tokens like ``-D CONFIGURED=1`` (a single
# quoted arg with a space after -D) that some flags arrive as.
defines.append(tok[2:].strip() if len(tok) > 2 else next(it, "").strip())
elif tok.startswith("-I"):
includes.append(_include(tok[2:] if len(tok) > 2 else next(it, "")))
elif tok == "-isystem":
includes.append(_include(next(it, "")))
elif tok.startswith("-isystem"):
includes.append(_include(tok[len("-isystem") :]))
elif tok in ("-MT", "-MF", "-MQ"):
next(it, None) # dependency-file flag + its argument
elif tok.startswith(("-MD", "-MMD", "-MP", "-MM")):
pass # dependency-generation flags, no argument
elif tok.endswith(_INPUT_FILE_SUFFIXES):
pass # input/output files
else:
cxx_flags.append(tok)
return cxx_path, defines, includes, cxx_flags
def get_toolchain_includes(cxx_path: str) -> list[str]:
"""Query the compiler for its builtin ``#include <...>`` search dirs."""
result = subprocess.run(
[cxx_path, "-E", "-x", "c++", "-", "-v"],
input="",
text=True,
stdout=subprocess.DEVNULL,
stderr=subprocess.PIPE,
check=False,
close_fds=False,
)
includes: list[str] = []
capture = False
for line in result.stderr.splitlines():
if "#include <...> search starts here:" in line:
capture = True
continue
if "End of search list." in line:
break
if capture:
includes.append(line.strip())
if result.returncode != 0 or not includes:
raise RuntimeError(
f"Could not query builtin include dirs from {cxx_path} "
f"(return code {result.returncode}); stderr:\n{result.stderr.strip()}"
)
return includes
def _cc_path_from_cxx(cxx_path: str) -> str:
"""Derive the C compiler path from the C++ compiler path.
compile_commands.json only names the C++ compiler, but consumers reach the
rest of the toolchain (objdump, readelf, addr2line) by rewriting the tail of
``cc_path``, so they need the ``gcc``-suffixed name.
"""
stem, suffix = (
(cxx_path[: -len(".exe")], ".exe")
if cxx_path.endswith(".exe")
else (cxx_path, "")
)
# Rewrite the program name only when it is g++ itself, or a toolchain
# prefixed one such as xtensa-esp32-elf-g++ -> xtensa-esp32-elf-gcc.
# Requiring a separator before the "g++" keeps names that merely end in
# those three characters intact: "clang++" must not become "clangcc".
head = stem[: -len("g++")]
if stem.endswith("g++") and (not head or head.endswith(("-", "/", "\\"))):
stem = f"{head}gcc"
return f"{stem}{suffix}"
def _cache_usable(cached: object) -> bool:
"""Check a cached idedata dict against the guarantees of the write path.
Caches written by older versions predate the launcher rejection and the
include-union shape; serving one would bypass both. The dict check also
keeps "in" from substring-matching a bare JSON string.
"""
if not isinstance(cached, dict) or "cc_path" not in cached:
return False
cxx_path = cached.get("cxx_path")
if not isinstance(cxx_path, str) or _is_launcher(cxx_path):
return False
includes = cached.get("includes")
return isinstance(includes, dict) and isinstance(includes.get("build"), list)
def load_or_build_idedata(
compile_commands: Path,
elf_path: Path,
cache: Path,
launcher: str | None = None,
) -> dict | None:
"""Return idedata for a compile_commands.json build, cached on mtime.
Shared by the native ESP-IDF and ESP8266 Arduino toolchains. Returns None
when the compile DB doesn't exist yet (nothing was built). ``launcher``
is the compiler-launcher path (ccache) the build was generated with, if
any; commands in the compile DB are prefixed with it.
"""
if not compile_commands.is_file():
_LOGGER.debug("No %s yet; skipping idedata generation", compile_commands)
return None
if cache.is_file() and cache.stat().st_mtime >= compile_commands.stat().st_mtime:
try:
cached = json.loads(cache.read_text(encoding="utf-8"))
except (ValueError, OSError) as err:
# A recurring cause (interrupted write, disk full) would otherwise
# look like unexplained slow builds
_LOGGER.warning("Discarding unreadable idedata cache %s: %s", cache, err)
else:
if _cache_usable(cached):
# Re-stamp so a relocated build dir cannot serve a stale ELF path
cached["prog_path"] = str(elf_path)
return cached
_LOGGER.debug("Regenerating idedata: cache %s fails validation", cache)
data = idedata_from_build(compile_commands, launcher)
data["prog_path"] = str(elf_path)
cache.parent.mkdir(parents=True, exist_ok=True)
# Atomic so a crash mid-write cannot leave a truncated cache
write_file(cache, json.dumps(data, indent=2) + "\n")
return data
def reject_launcher_compiler(cxx_path: str) -> None:
"""Reject a compile DB naming a launcher (ccache) as the compiler; it
must never be probed, cached, or consumed."""
if _is_launcher(cxx_path):
raise EsphomeError(
f"compile_commands.json names the launcher {cxx_path} as the "
"compiler; the compile database is unusable"
)
def idedata_from_build(compile_commands: Path, launcher: str | None = None) -> dict:
"""Parse compile_commands.json into the idedata fields consumers expect.
A single compile entry only carries the include set its own translation
unit was built with (per-component under ESP-IDF), but consumers
(clang-tidy) analyze ESPHome headers that transitively pull in other
components. So take cxx_path / cxx_flags / defines from a representative
ESPHome TU, but union the include dirs across all ESPHome TUs to get a
project-wide superset (as PlatformIO's idedata provides).
"""
entries = json.loads(Path(compile_commands).read_text(encoding="utf-8"))
if not isinstance(entries, list) or not all(isinstance(e, dict) for e in entries):
# A TypeError here would escape IDEDATA_BEST_EFFORT_ERRORS
raise EsphomeError(f"{compile_commands} is not a compile-command list")
representative = _pick_entry(entries)
cxx_path, defines, rep_includes, cxx_flags = parse_entry(representative, launcher)
# Seed with the representative's includes so it is not parsed twice
has_esphome_tu = _is_esphome_src(representative["file"])
build_includes: dict[str, None] = dict.fromkeys(
rep_includes if has_esphome_tu else ()
)
def _shape(entry: dict) -> str:
# directory + command minus TU-specific paths: same shape means the
# same include set, so tokenize once per shape. Response-file
# commands never dedupe (the .rsp contents differ per object)
command = entry["command"]
directory = entry.get("directory", "")
if "@" in command:
return f"unique:{directory}|{entry.get('output') or command}"
stripped = command.replace(entry.get("file", ""), "").replace(
entry.get("output", ""), ""
)
return f"{directory}|{stripped}"
seen_shapes = {_shape(representative)}
for entry in entries:
if entry is representative or not _is_esphome_src(entry["file"]):
continue
has_esphome_tu = True
if (shape := _shape(entry)) in seen_shapes:
_LOGGER.debug("Include union: %s shares a command shape", entry["file"])
continue
seen_shapes.add(shape)
for inc in parse_entry(entry, launcher)[2]:
build_includes.setdefault(inc, None)
if not has_esphome_tu:
# An arbitrary fallback TU breaks clang-tidy/IDE consumers, and a
# warning would be cached into permanence; call sites downgrade this
raise EsphomeError(
f"No ESPHome translation unit found in {compile_commands}; "
"refusing to cache unusable idedata"
)
return {
"cc_path": _cc_path_from_cxx(cxx_path),
"cxx_path": cxx_path,
"cxx_flags": cxx_flags,
"defines": defines,
"includes": {
"build": list(build_includes),
"toolchain": get_toolchain_includes(cxx_path),
},
}
+92
View File
@@ -0,0 +1,92 @@
"""Platform-neutral helpers for ninja-driven native builds."""
from __future__ import annotations
import logging
import os
from pathlib import Path
import re
import shutil
from esphome.core import EsphomeError
from esphome.framework_helpers import strip_win_long_path_prefix, tool_version_runs
_LOGGER = logging.getLogger(__name__)
def _ninja_runs(binary: str) -> bool:
"""Whether the ninja found on PATH actually runs (see tool_version_runs)."""
return tool_version_runs(
binary,
"Ignoring ninja at %s because it failed to run; "
"falling back to the bundled wheel",
)
def find_ninja() -> Path:
"""Locate the ninja binary: a runnable PATH hit first, else the ninja
PyPI wheel."""
if binary := shutil.which("ninja"):
binary = strip_win_long_path_prefix(binary)
if _ninja_runs(binary):
return Path(binary)
import_error: ImportError | None = None
try:
import ninja
except ImportError as err:
import_error = err
wheel_binary = None
else:
wheel_binary = Path(ninja.BIN_DIR) / (
"ninja.exe" if os.name == "nt" else "ninja"
)
if wheel_binary is None or not wheel_binary.is_file():
raise EsphomeError(
"ninja not found on PATH or in the ninja package; reinstall the "
"esphome Python environment"
) from import_error
return wheel_binary
def escape(value: Path | str) -> str:
"""Escape a path or token for a ninja file."""
return str(value).replace("$", "$$").replace(":", "$:").replace(" ", "$ ")
def quote_arg(tok: str) -> str:
"""Quote with the CreateProcess argv rule (as ``subprocess.list2cmdline``):
backslash runs double only before a quote. Windows-only; ``$`` must
already be doubled for ninja.
"""
quoted = re.sub(r'(\\*)"', lambda m: m.group(1) * 2 + '\\"', tok)
quoted = re.sub(r"(\\+)\Z", lambda m: m.group(1) * 2, quoted)
return f'"{quoted}"'
# Force-quote any token containing a character outside the shlex.quote-style
# safe set: ninja hands POSIX commands to /bin/sh -c, so bare (, ;, <, *, `
# and friends would be re-parsed as shell syntax.
_NEEDS_QUOTE = re.compile(r"[^\w@%+=:,./-]")
def shell_token(tok: str, force: bool = False) -> str:
"""Re-quote a lexed token for the platform shell; ``force`` always quotes.
Single quotes on POSIX (/bin/sh), the argv rule on Windows
(CreateProcess). ``$`` is doubled first because ninja expands it before
the command reaches the shell.
"""
tok = tok.replace("$", "$$") # ninja would expand a bare $ to nothing
if not (force or not tok or _NEEDS_QUOTE.search(tok)):
return tok
# An empty token must become '' / "" or it vanishes from the argv
if os.name == "nt":
return quote_arg(tok)
# shlex.quote's rule; inlined because the $-doubled token must not be
# re-examined for safe characters
return "'" + tok.replace("'", "'\"'\"'") + "'"
def quote_path(value: Path | str) -> str:
"""Force-quote a path for the ninja command line (shell/CreateProcess)."""
return shell_token(str(value), force=True)
+24
View File
@@ -0,0 +1,24 @@
"""The PlatformIO-format size bar shared by the native toolchains."""
from __future__ import annotations
def format_bar(used: int, total: int) -> str:
"""Match PlatformIO's ``_format_availale_bytes`` (sic, pioupload.py) exactly."""
pct_raw = used / total if total else 0
blocks = 10
filled = min(int(round(blocks * pct_raw)), blocks)
progress = "=" * filled
return (
f"[{progress:<{blocks}}] {pct_raw: 6.1%} "
f"(used {used:d} bytes from {total:d} bytes)"
)
def print_size_line(label: str, used: int, total: int) -> None:
"""One PlatformIO-format summary line (``RAM``/``Flash``).
The label padding is part of the format: ``script/ci_memory_impact_extract.py``
matches these lines verbatim.
"""
print(f"{label + ':':<7}{format_bar(used, total)}")
+36
View File
@@ -0,0 +1,36 @@
"""Machine-global tools cache location shared by the native backends."""
from __future__ import annotations
from pathlib import Path
def tools_cache_path(env_var: str, subdir: str) -> Path:
"""A backend's machine-global tools directory, with an env override.
A blank/whitespace override is treated as unset: ``Path("")`` resolves
to the CWD, which ``clean-all`` would then delete.
"""
import platformdirs
from esphome.helpers import get_str_env
if prefix := get_str_env(env_var, "").strip():
# resolve(): symlinked prefixes otherwise trip idf.py's
# venv-mismatch warning on every build
return Path(prefix).expanduser().resolve()
# appauthor=False keeps the Windows path short (no vendor segment);
# deep IDF trees run into MAX_PATH otherwise
return (
Path(platformdirs.user_cache_dir("esphome", appauthor=False)) / subdir
).resolve()
# (env override, cache subdir) per native backend. writer.clean_all wipes
# every entry via tools_cache_path, so listing a cache here is the single
# step that registers it for removal; the backends' own path getters use
# the same named pairs so the two cannot drift.
IDF_TOOLS_CACHE = ("ESPHOME_ESP_IDF_PREFIX", "idf")
SDK_NRF_TOOLS_CACHE = ("ESPHOME_SDK_NRF_PREFIX", "sdk-nrf")
ARDUINO8266_TOOLS_CACHE = ("ESPHOME_ARDUINO8266_PREFIX", "arduino8266")
TOOLS_CACHE_SPECS = (IDF_TOOLS_CACHE, SDK_NRF_TOOLS_CACHE, ARDUINO8266_TOOLS_CACHE)
+172 -9
View File
@@ -7,12 +7,12 @@ and compiled directly: ``esphome compile my_device.esphomebundle.tar.gz``
from __future__ import annotations
from dataclasses import dataclass
from dataclasses import dataclass, field
from enum import StrEnum
import io
import json
import logging
from pathlib import Path
from pathlib import Path, PurePath, PurePosixPath, PureWindowsPath
import re
import shutil
import tarfile
@@ -20,6 +20,7 @@ from typing import Any
from esphome import const, yaml_util
from esphome.const import (
BUNDLE_EXTENSION,
CONF_ESPHOME,
CONF_EXTERNAL_COMPONENTS,
CONF_INCLUDES,
@@ -29,10 +30,12 @@ from esphome.const import (
CONF_TYPE,
)
from esphome.core import CORE, EsphomeError
from esphome.util import filter_yaml_files
_LOGGER = logging.getLogger(__name__)
BUNDLE_EXTENSION = ".esphomebundle.tar.gz"
DOMAIN = "bundle"
MANIFEST_FILENAME = "manifest.json"
CURRENT_MANIFEST_VERSION = 1
MAX_DECOMPRESSED_SIZE = 500 * 1024 * 1024 # 500 MB
@@ -49,6 +52,7 @@ class ManifestKey(StrEnum):
MANIFEST_VERSION = "manifest_version"
ESPHOME_VERSION = "esphome_version"
CONFIG_FILENAME = "config_filename"
CONFIG_DIR = "config_dir"
FILES = "files"
HAS_SECRETS = "has_secrets"
@@ -120,6 +124,153 @@ def _find_used_secret_keys(yaml_files: list[Path]) -> set[str]:
return keys
@dataclass
class BundleData:
"""Files components asked to include, keyed under DOMAIN in CORE.data."""
extra_files: list[Path] = field(default_factory=list)
# Directories whose YAML files are scanned for !secret references but
# never bundled, e.g. git package checkouts the builder re-fetches.
secret_scan_dirs: set[Path] = field(default_factory=set)
# Original config dir parsed from an extracted bundle's manifest.json,
# kept in the path flavor of the machine the bundle was created on.
# The checked flag makes the manifest lookup happen at most once per run;
# CORE.data is cleared between runs.
original_config_dir: PurePath | None = None
original_config_dir_checked: bool = False
def _get_data() -> BundleData:
if DOMAIN not in CORE.data:
CORE.data[DOMAIN] = BundleData()
return CORE.data[DOMAIN]
def add_bundle_file(path: Path) -> None:
"""Register a file that a bundle must include.
Bundle discovery walks the validated config, so it only finds files the config
names. Components call this during validation for files it cannot see, such as a
file that is referenced from inside another file.
A relative path is taken as relative to the config directory. Files outside the
config directory are skipped when the bundle is built.
"""
_get_data().extra_files.append(CORE.relative_config_path(path))
def add_secret_scan_dir(path: Path) -> None:
"""Register a directory to scan for ``!secret`` references when bundling.
The directory's files are not added to the bundle. Components call this
for YAML the build consumes without bundling it — such as git-fetched
packages, which the builder re-fetches — so the secrets those files
reference are still shipped in the filtered secrets file.
A relative path is taken as relative to the config directory.
"""
if not path.is_absolute():
path = CORE.relative_config_path(path)
_get_data().secret_scan_dirs.add(path)
def _secret_scan_yaml_files() -> list[Path]:
"""Return the YAML files inside registered secret-scan directories."""
return filter_yaml_files(
f
for scan_dir in _get_data().secret_scan_dirs
for f in yaml_util.find_files(scan_dir, "*")
)
# Windows paths start with a drive letter or contain backslashes; POSIX
# paths do neither in practice, so this is how the flavor of a recorded
# path string is recognized on any host.
_WINDOWS_DRIVE_RE = re.compile(r"^[A-Za-z]:")
def _path_flavor(value: str) -> type[PurePath]:
"""Pick the pure path class matching the flavor ``value`` was written in."""
if "\\" in value or _WINDOWS_DRIVE_RE.match(value):
return PureWindowsPath
return PurePosixPath
def _load_original_config_dir() -> PurePath | None:
"""Read the original config dir from an extracted bundle's manifest.
Returns None when the current config dir is not an extracted bundle or
the manifest does not record the original config dir.
"""
manifest_path = CORE.config_dir / MANIFEST_FILENAME
try:
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
except FileNotFoundError:
# The common case: this config dir is not an extracted bundle.
return None
except (OSError, UnicodeDecodeError, json.JSONDecodeError) as err:
# A manifest.json is present but unreadable or malformed. Say so
# instead of letting it look identical to "not a bundle".
_LOGGER.warning("Bundle: ignoring unreadable %s: %s", manifest_path, err)
return None
if not isinstance(manifest, dict):
return None
# A manifest.json in the config dir does not have to be ours. Only trust
# one that looks like a bundle manifest for exactly this config file.
version = manifest.get(ManifestKey.MANIFEST_VERSION)
if not isinstance(version, int) or version < 1:
return None
if manifest.get(ManifestKey.CONFIG_FILENAME) != CORE.config_path.name:
return None
config_dir = manifest.get(ManifestKey.CONFIG_DIR)
if not isinstance(config_dir, str) or not config_dir:
return None
return _path_flavor(config_dir)(config_dir)
def remap_bundle_path(value: str) -> Path | None:
"""Remap an absolute path from the machine a bundle was created on.
A bundled config may reference files by absolute path. The referenced
files ship inside the bundle at their config-relative locations, but the
YAML text is copied verbatim, so after extraction on another machine the
absolute reference points at a path that only existed on the creating
machine. The bundle manifest records that machine's config dir; when
``value`` names a path that lived under it, return the corresponding
file next to the extracted config.
``value`` is the raw path string from the config. It is parsed with the
original machine's path flavor, so a bundle created on Windows remaps on
a POSIX build server and vice versa.
Returns None when not compiling an extracted bundle, when ``value`` was
not under the original config dir, or when the bundle does not contain
the file.
"""
data = _get_data()
if not data.original_config_dir_checked:
data.original_config_dir_checked = True
data.original_config_dir = _load_original_config_dir()
original_dir = data.original_config_dir
if original_dir is None:
return None
path = type(original_dir)(value)
if not path.is_absolute():
return None
try:
rel = path.relative_to(original_dir)
except ValueError:
return None
# relative_to is lexical, so ".." segments survive it. Refuse them: the
# remapped file must land strictly inside the extracted config tree.
if ".." in rel.parts:
return None
remapped = CORE.relative_config_path(Path(*rel.parts))
if not remapped.exists():
return None
return remapped
@dataclass
class BundleFile:
"""A file to include in the bundle."""
@@ -146,6 +297,7 @@ class BundleManifest:
config_filename: str
files: list[str]
has_secrets: bool
config_dir: str | None = None
class ConfigBundleCreator:
@@ -186,6 +338,7 @@ class ConfigBundleCreator:
yaml_sources = [
bf.source for bf in files if bf.source.suffix in (".yaml", ".yml")
]
yaml_sources.extend(_secret_scan_yaml_files())
used_secret_keys = _find_used_secret_keys(yaml_sources)
filtered_secrets = self._build_filtered_secrets(used_secret_keys)
@@ -270,6 +423,13 @@ class ConfigBundleCreator:
"""
discovered = yaml_util.discover_user_yaml_files(self._config_path)
self._secrets_paths.update(discovered.secrets)
# A !secret inside a file this re-parse does not reach (for example
# a git-fetched package the builder re-fetches) still resolves
# against the config-dir secrets.yaml at build time, so always
# consider that file; filtering no-ops when no key matches.
default_secrets = self._config_dir / yaml_util.SECRET_YAML
if default_secrets.is_file():
self._secrets_paths.add(default_secrets.resolve())
config_resolved = self._config_path.resolve()
for fpath in discovered.files:
if fpath == config_resolved:
@@ -286,13 +446,18 @@ class ConfigBundleCreator:
with known file extensions are also resolved and checked.
Core ESPHome concepts that use relative paths or directories
are handled explicitly.
are handled explicitly. Files the config does not name at all are
registered by their component with add_bundle_file().
"""
config = self._config
# Generic walk: find all file paths in the validated config
self._walk_config_for_files(config)
# Files registered by components during validation
for extra_file in _get_data().extra_files:
self._add_file(extra_file)
# --- Core ESPHome concepts needing explicit handling ---
# esphome.includes / includes_c - can be relative paths and directories
@@ -405,6 +570,7 @@ class ConfigBundleCreator:
ManifestKey.MANIFEST_VERSION: CURRENT_MANIFEST_VERSION,
ManifestKey.ESPHOME_VERSION: const.__version__,
ManifestKey.CONFIG_FILENAME: self._config_path.name,
ManifestKey.CONFIG_DIR: str(self._config_dir),
ManifestKey.FILES: [f.path for f in files],
ManifestKey.HAS_SECRETS: has_secrets,
}
@@ -489,12 +655,14 @@ def read_bundle_manifest(bundle_path: Path) -> BundleManifest:
except tarfile.TarError as err:
raise EsphomeError(f"Failed to read bundle: {err}") from err
config_dir = manifest.get(ManifestKey.CONFIG_DIR)
return BundleManifest(
manifest_version=manifest[ManifestKey.MANIFEST_VERSION],
esphome_version=manifest.get(ManifestKey.ESPHOME_VERSION, "unknown"),
config_filename=manifest[ManifestKey.CONFIG_FILENAME],
files=manifest.get(ManifestKey.FILES, []),
has_secrets=manifest.get(ManifestKey.HAS_SECRETS, False),
config_dir=config_dir if isinstance(config_dir, str) else None,
)
@@ -587,11 +755,6 @@ def _validate_tar_members(tar: tarfile.TarFile, target_dir: Path) -> None:
)
def is_bundle_path(path: Path) -> bool:
"""Check if a path looks like a bundle file."""
return path.name.lower().endswith(BUNDLE_EXTENSION)
def _add_bytes_to_tar(tar: tarfile.TarFile, name: str, data: bytes) -> None:
"""Add in-memory bytes to a tar archive with deterministic metadata."""
info = tarfile.TarInfo(name=name)
Loaded 100 of 4447 files, more files were not shown because too many files have changed in this diff. Show more