Compare commits

...
Author SHA1 Message Date
J. Nick Koston d0b0cd6e13 Merge remote-tracking branch 'origin/dev' into HEAD 2026-10-09 18:27:34 -10:00
J. Nick Koston d3e7bb119c [core] Deprecate the named status_momentary_warning/error overloads (#20369) 2026-10-10 02:39:21 +00:00
J. Nick Koston dd45f8a6f8 [usb_host] Warn instead of failing when a device duplicates a usb_uart entry (#20373) 2026-10-09 16:38:05 -10:00
ba7d3bd770 [gpio][esp32][uart] Add option to hold gpio during (deep)sleep and reboot (3/3) (#18964)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-10 02:37:46 +00:00
J. Nick Koston dc553aae55 [core] Use status_momentary_warning/error without a name in components (#20363) 2026-10-09 22:27:19 -04:00
J. Nick Koston f7b9646705 [improv_ble] Build the state triggers with build_callback_automation (#20444) 2026-10-09 16:06:14 -10:00
J. Nick Koston 0ae24f7536 [core] Catch heap allocating helper calls with explicit template arguments (#20391) 2026-10-10 02:00:41 +00:00
J. Nick Kostonandpre-commit-ci-lite[bot] 41cc96bbb8 [light] Keep the effect list in a flash table (#20204)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-10-09 15:55:09 -10:00
Zhaoqi Xu 6b03d68fac [heatpumpir] Fix fan speeds for mitsubishi_msc protocol (#20460) 2026-10-09 21:53:38 -04:00
J. Nick Koston 640d677913 [st7735][st7789v][waveshare_epaper] Declare log tags with ESPHOME_LOG_TAG (#20295) 2026-10-09 15:51:55 -10:00
J. Nick Koston 8567e69d46 [core] Add status_momentary_warning/error overloads without a name (#20362) 2026-10-09 15:51:38 -10:00
J. Nick Koston 4d187a2bb7 [valve] Build on_open and on_closed with build_callback_automation (#20442) 2026-10-09 15:43:22 -10:00
J. Nick Koston 073394b1eb [core] Let a trigger filter name its parent with {parent} (#20448) 2026-10-09 15:43:22 -10:00
J. Nick Koston 02bfa07819 [opentherm] Build before_send and before_process_response with build_callback_automation (#20450) 2026-10-09 15:42:55 -10:00
J. Nick Koston fdc163a30d [tuya] Build on_datapoint_update with build_trigger_callback (#20453) 2026-10-09 15:42:43 -10:00
J. Nick Koston bc44e8b550 [display] Test on_page_change with each from and to combination (#20457) 2026-10-09 21:40:40 -04:00
J. Nick Koston e894397503 [datetime] Build on_value with build_callback_automation (#20445) 2026-10-09 15:39:25 -10:00
J. Nick Koston f1a23a02c2 [time] Build on_time_sync with build_callback_automation (#20441) 2026-10-09 15:39:06 -10:00
J. Nick Koston 95dc9a749b [display_menu_base] Build the menu item triggers with build_parent_callback_automation (#20443) 2026-10-09 15:39:00 -10:00
J. Nick Koston 59963dd246 [espidf] Declare the map byproduct only when IDF has not (#20462) 2026-10-09 15:38:16 -10:00
J. Nick Koston 79fd5edc7f [core] Bind InternalGPIOPin to the platform pin class instead of a virtual base (#20455) 2026-10-09 15:37:10 -10:00
J. Nick Koston 5d2433f69a [graphical_display_menu] Build on_redraw with build_callback_automation (#20452) 2026-10-09 15:36:57 -10:00
J. Nick Koston 1b49e79bf8 [microphone] Build on_data with build_callback_automation (#20451) 2026-10-09 15:35:38 -10:00
Bascht74 4e4056d790 [uart] Share uart_tcp's write pacing and uart_id matcher (#20464) 2026-10-09 15:11:48 -10:00
Ali Alaeiandtomaszduda23 e5f5ca07c4 [zephyr_mcumgr] Enable MCUMGR_GRP_OS for UART transport, not just BLE (#18319)
Co-authored-by: tomaszduda23 <tomaszduda23@gmail.com>
2026-10-09 12:50:50 -10:00
a4a09043ec [deep_sleep][gpio][core][power_supply] Prepare for gpio hold (2/3) (#18966)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-09 11:32:24 -10:00
esphome[bot] a613073ee3 Bump bundled esphome-device-builder to 1.23.0 (#20446) 2026-10-09 10:06:10 -10:00
PolarGooseandJ. Nick Koston 8416a29862 [dlms_meter] Add support for "Landis+Gyr E450 HDLC Cyprus". Adapt the code for new API of dlms_parser (#16942)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-09 10:03:38 -10:00
J. Nick Koston 9ab0fa9669 [dlms_meter] Remove deprecated predefined sensor keys (#20386) 2026-10-09 09:36:28 -10:00
J. Nick Koston 05aeb2f094 [http_request] Test shared, lambda and trigger argument request headers (#20224) 2026-10-09 09:25:36 -10:00
J. Nick Koston c859c347cb [core] Pass a single condition to actions directly instead of wrapping it in a group (#19223) 2026-10-09 09:24:32 -10:00
J. Nick Koston 7ab24bf850 [nextion] Remove deprecated dump_device_info option (#20388) 2026-10-09 09:23:46 -10:00
J. Nick Koston cfbdd58e4a [lvgl] Remove deprecated update_on_release option (#20387) 2026-10-09 09:23:28 -10:00
8084916e30 [remote_base] Add Onkyo RI Wired Serial Support (#18595)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-09 19:23:10 +00:00
J. Nick Koston 9d02ab3734 [remote_base] Keep constant IR codes in flash (#20083) 2026-10-09 09:22:32 -10:00
J. Nick Koston 3442bb6624 [core] Remove deprecated esphome::RingBuffer alias (#20390) 2026-10-09 09:21:29 -10:00
J. Nick Koston 23d13d3a6e [core] Stop re-exporting alloc_helpers.h from helpers.h (#20389) 2026-10-09 09:21:16 -10:00
J. Nick Kostonandpre-commit-ci-lite[bot] 5cd7bf5993 [wireguard] Keep allowed IPs in a shared flash table (#20087)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-10-09 09:20:46 -10:00
J. Nick Koston f7b80e6d44 [dlms_meter] Remove deprecated provider option (#20385) 2026-10-09 09:20:17 -10:00
J. Nick Koston 588fde91b2 [template] Keep alarm codes in a shared flash table (#20084) 2026-10-09 09:19:35 -10:00
J. Nick Koston 94e6bd90d8 [sensor] Merge the radar timeout and throttle filters into one (#20118) 2026-10-09 09:19:22 -10:00
J. Nick Koston 456e3d8979 [ci] Keep bus group partners on the same runner (#20431) 2026-10-09 09:10:18 -10:00
J. Nick Koston 76ba7f0c88 [espidf] Cache the discovered component list once per target (#20432) 2026-10-09 09:10:06 -10:00
J. Nick Koston 0652e6c3fb [esp32][libretiny] Skip registering static destructors that never run (#20440) 2026-10-09 19:02:22 +00:00
luar123andJ. Nick Koston dbad1d4629 [core][zigbee] Wake main loop on defer/set_timeout from background task (#20356)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-09 18:58:33 +00:00
J. Nick Koston dd8315059c [core] Document the trigger callback helpers in AGENTS.md (#20435) 2026-10-09 08:56:50 -10:00
J. Nick Koston 822bbb85dc [core] Build trigger callbacks as stateless lambdas (#19606) 2026-10-09 08:50:32 -10:00
J. Nick Koston daea315b13 [nrf52] Fake a larger flash in testing mode (#20439) 2026-10-09 08:36:42 -10:00
J. Nick Koston 52b274c5e8 [improv_serial] Collapse duplicate CI test variants (#20405) 2026-10-09 07:34:34 -10:00
J. Nick Koston b5716a70c2 [ethernet] Remove deprecated clk_mode option (#20384) 2026-10-09 17:26:47 +00:00
J. Nick Koston 3eb8155ed2 [logger] Collapse duplicate CI test variants (#20402) 2026-10-09 07:22:48 -10:00
J. Nick Koston 11368a0b16 [adc] Collapse duplicate CI test variants (#20400) 2026-10-09 07:22:20 -10:00
J. Nick Koston cf0e64f84c [improv_serial] Use a numeric scheduler id for the Wi-Fi connect timeout (#20360) 2026-10-09 07:21:53 -10:00
J. Nick Koston d98ddeeb56 [mqtt] Use a numeric scheduler id for the deferred state publish (#20359) 2026-10-09 07:21:29 -10:00
J. Nick Koston 0701329ea7 [wifi] Use numeric scheduler ids instead of string names (#20357) 2026-10-09 07:20:59 -10:00
J. Nick Koston f5ce33a8de [esp32_ble_client] Track conn_id per attempt and stop logging an error on a failed open (#20417) 2026-10-09 07:16:17 -10:00
J. Nick Koston f89a603582 [esp8266] Keep switch lookup tables out of RAM (#20398) 2026-10-09 07:15:59 -10:00
J. Nick Koston 279f68c432 [tuya] Use numeric scheduler ids instead of string names (#20365) 2026-10-09 07:15:33 -10:00
J. Nick Koston b6ee8f8035 [power_supply] Use a numeric scheduler id for the power off timeout (#20367) 2026-10-09 07:15:14 -10:00
J. Nick Koston cea872be0b [modbus] Use a numeric scheduler id for the deferred server reply (#20368) 2026-10-09 07:14:59 -10:00
J. Nick Koston 558de5ebee [core] Use numeric scheduler ids instead of string names (5/5) (#20378) 2026-10-09 07:14:39 -10:00
J. Nick Koston aba0c5d7ee [dallas_temp] Use a numeric scheduler id and drop the cached address string (#20361) 2026-10-09 07:14:19 -10:00
J. Nick Koston 4c17ee7393 [core] Use numeric scheduler ids instead of string names (2/5) (#20375) 2026-10-09 07:13:46 -10:00
J. Nick Koston 24237a07c9 [ci] Refit component batch estimates to a full run (#20401) 2026-10-09 07:12:35 -10:00
J. Nick Koston d4d5ee87cb [ir_rf_proxy] Collapse duplicate CI test variants (#20399) 2026-10-09 07:12:14 -10:00
J. Nick Koston 56e6e332cb [ci] Skip the static analyzer on the generated protobuf dump file (#20414) 2026-10-09 07:11:45 -10:00
J. Nick Koston 7ac679aa04 [esp8266] Keep ArduinoJson's float tables in flash (Arduino core 3.1.2-esphome.3) (#20416) 2026-10-09 07:11:30 -10:00
J. Nick Koston 8a09e49e31 [ci] Skip the memory impact target build when the base test is missing (#20410) 2026-10-09 07:11:18 -10:00
J. Nick Koston 3485297e6e [core] Use numeric scheduler ids instead of string names (4/5) (#20377) 2026-10-09 07:11:01 -10:00
J. Nick Koston 541562451e [sprinkler] Key timers by index and keep them in a fixed array (#20379) 2026-10-09 07:10:48 -10:00
J. Nick Koston 824834f847 [core] Use numeric scheduler ids instead of string names (3/5) (#20376) 2026-10-09 07:10:19 -10:00
J. Nick Koston bc6fecfadb [core] Use numeric scheduler ids instead of string names (1/5) (#20374) 2026-10-09 07:10:04 -10:00
J. Nick Koston a2434f9aa3 [core] Document numeric scheduler ids in AGENTS.md (#20382) 2026-10-09 07:09:33 -10:00
J. Nick Koston 466081acc1 [core] Use numeric scheduler ids instead of string names (ESP32 2/2) (#20381) 2026-10-09 07:09:04 -10:00
J. Nick Koston d9b9ce2909 [core] Use numeric scheduler ids instead of string names (ESP32 1/2) (#20380) 2026-10-09 07:07:56 -10:00
J. Nick Koston a0f0949078 [mdns] Collapse duplicate CI test variants (#20403) 2026-10-09 06:42:00 -10:00
J. Nick Koston 6f4d0e9488 [debug] Collapse duplicate CI test variants (#20404) 2026-10-09 06:32:33 -10:00
J. Nick Koston 65e8345ab8 [ota] Collapse duplicate CI test variants (#20407) 2026-10-09 06:32:07 -10:00
J. Nick Koston de5c2cda09 [mcp23xxx_base] Keep the interrupt handler in IRAM on ESP8266 (#20409) 2026-10-09 06:31:42 -10:00
J. Nick Koston 9adb7e92e1 [ethernet] Collapse duplicate CI test variants (#20406) 2026-10-09 06:31:26 -10:00
J. Nick Koston c7d6a2e898 [sendspin] Fix duplicate definitions after the beta merge (#20424) 2026-10-08 22:13:45 -10:00
Jesse Hills 6188778538 Merge branch 'beta' into dev 2026-10-09 15:42:24 +13:00
Clyde Stubbs 6513b176f4 [spd2010] Fix DOMAIN (#20422) 2026-10-09 02:23:56 +00:00
646f386f12 [spd2010] Add touchscreen platform (#19057)
Co-authored-by: clydebarrow <2366188+clydebarrow@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-10-09 12:50:09 +11:00
J. Nick Koston 6a463c801e [ci] Stop the toolchain tests from installing ESP-IDF (#20413) 2026-10-08 21:42:45 -04:00
Jesse Hills d9795399ad [core] Use component DOMAIN constants instead of name literals (#20419) 2026-10-09 13:50:29 +13:00
J. Nick Koston 0d596a20f8 [esp32] Record the PC for cache error and interrupt watchdog crashes (#20415) 2026-10-09 00:25:11 +00:00
Jesse Hills 5ca272b262 [mipi_dsi] Make config tests pass in isolation (#20420) 2026-10-09 13:20:52 +13:00
J. Nick Koston ff0d4347d6 [api] Fix C++ unit test link failure when api is only a dependency (#20418) 2026-10-08 14:05:18 -10:00
Jesse Hills e03db60a52 [core] Add a DOMAIN constant to every component (#20395) 2026-10-08 14:04:26 -10:00
J. Nick Koston b4bd95b2ac [ci] Deal clang-tidy files across five shards (#20411) 2026-10-08 13:48:03 -10:00
J. Nick Koston fe21e3ad16 [ci] Pin the shared I2C bus in test configs that left it implicit (#20412) 2026-10-08 13:14:00 -10:00
Jesse Hills 85108bfd84 [qspi_amoled] Remove legacy renamed component stub (#20396) 2026-10-08 12:58:20 -10:00
J. Nick Koston 92bfd0ea7e [mdns] Bump espressif/mdns to 1.14.0 (#20383) 2026-10-08 21:18:21 +00:00
dependabot[bot] 542de8f03a Bump j178/prek-action from 3.0.0 to 3.0.1 (#20372)
Signed-off-by: dependabot[bot] <support@github.com>
2026-10-08 09:36:01 -10:00
dependabot[bot] 06864917a5 Bump filelock from 4.0.10 to 4.0.12 (#20371)
Signed-off-by: dependabot[bot] <support@github.com>
2026-10-08 19:31:14 +00:00
dependabot[bot] bcfe6fd1d2 Bump prek from 0.5.4 to 0.5.5 (#20370)
Signed-off-by: dependabot[bot] <support@github.com>
2026-10-08 19:30:04 +00:00
Kevin AhrendtandJ. Nick Koston e395e626ec [api][sendspin] Add a request for the Sendspin pairing token (#20355)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-10-08 19:12:20 +00:00
esphome[bot] f9b5eca2b9 Bump aioesphomeapi from 46.8.0 to 46.9.0 (#20358) 2026-10-08 18:48:19 +00:00
Kevin Ahrendt 920295527f [sendspin] Add an unpaired access switch (#20350) 2026-10-08 08:13:31 -10:00
Kevin Ahrendt 9c79fa7430 [sendspin] Add the dynamic pairing code (#20349) 2026-10-08 13:36:12 -04:00
J. Nick Koston 4b2f8122e3 [udp] Keep constant write payloads in shared flash tables (#20268) 2026-10-08 07:31:09 -10:00
J. Nick Koston 052f5a4cc6 [core] Declare component log tags with ESPHOME_LOG_TAG (#20291) 2026-10-08 07:24:17 -10:00
Kevin Ahrendt 78bf74eafb [sendspin] Add the static pairing code, pairing window and unpaired access option (#20348) 2026-10-08 07:19:14 -10:00
Kevin Ahrendt b1c145dd5f [sendspin] Update to sendspin-cpp v0.9.3 (#20347) 2026-10-08 06:33:46 -10:00
J. Nick Koston 3055343b6d [esp8266] Use toolchain 10.3.0-esphome.3, which trims newlib RAM (#20335) 2026-10-08 06:15:11 -10:00
J. Nick Koston 70f64374d4 [esp8266] Use toolchain 10.3.0-esphome.3, which trims newlib RAM (#20335) 2026-10-08 06:11:51 -10:00
J. Nick Koston 1362e52aa7 [esp8266] Fix Arduino core regressions that keep data in RAM and link the unused unwinder (#20337) 2026-10-08 06:09:39 -10:00
J. Nick Koston e51e0e683f [esp8266] Force-include the throw stubs into the core and libraries on the native toolchain (#20336) 2026-10-08 06:06:45 -10:00
J. Nick Koston 7910d02b71 [web_server] Emit the resource tables with cg.extern_progmem_array (#20300) 2026-10-08 11:34:34 -04:00
J. Nick Koston f224cb37d6 [esp32_ble_server] Cover string, typed number, repeated and trigger argument set_value payloads in the component test (#20308) 2026-10-08 11:32:50 -04:00
J. Nick Koston 79813a1eac [canbus] Keep constant send payloads in shared flash tables (#20309) 2026-10-08 11:14:02 -04:00
J. Nick Koston 9066ad6cd0 [modbus_client] Cover shared constant and trigger argument write values in the component test (#20327) 2026-10-08 11:13:03 -04:00
J. Nick Koston f5e4c0356f [core] Move zstd_module from the api wizard to esphome.helpers (#20342) 2026-10-08 11:08:38 -04:00
J. Nick Koston 3c634ecfd8 [noise] Bump noise-c to 0.1.31 and libsodium to 1.10021.12 (#20345) 2026-10-08 06:48:08 -04:00
Jesse HillsandJ. Nick Koston 57eeca6341 [combination] Use cv.rename_key for the deprecated coeffecient key (#20159)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-10-07 20:15:43 -10:00
esphome[bot] 23ba80c9c7 Bump bundled esphome-device-builder to 1.22.0 (#20334) 2026-10-07 20:03:30 -10:00
Jesse Hills 73bbd75d3f [core] Let cv.rename_key pass non-dict input through (#20331) 2026-10-08 17:29:56 +13:00
J. Nick Koston 0a7763d902 [esp8266] Normalize misspelled boards and fall back to PlatformIO for unknown ones (#20322) 2026-10-08 17:05:18 +13:00
J. Nick Koston 7aeed8455e [api] Add a progmem option for bytes fields kept in flash (#20318) 2026-10-08 16:24:27 +13:00
J. Nick Koston 8eba5a1c28 [core] Warn on every run that Intel Mac support ends by 2027.6.0 (#20303) 2026-10-08 16:23:01 +13:00
J. Nick Koston 0f552a8eef Pin smp to 4.1.0 on Intel macOS so cbor2 installs from a wheel (#20302) 2026-10-08 16:14:40 +13:00
David Buezas 31c488e5b0 [cc1101] Keep the remote_receiver interrupt on a shared GDO0 pin in begin_tx (#20296) 2026-10-07 22:53:12 -04:00
J. Nick Koston 1ee4940d4d [remote_base] Cover shared, empty and trigger argument abbwelcome payloads in the component test (#20307) 2026-10-07 16:43:44 -10:00
J. Nick Koston 640ef1bb17 [canbus] Cover shared, string and trigger argument send payloads in the component tests (#20306) 2026-10-07 16:43:34 -10:00
luar123 42edfe0681 [CI] Remove obsolete platform labels (#20301) 2026-10-07 22:18:47 -04:00
Keith BurzinskiandClaude Opus 5.5 6a6d263c0d [core] Wake the main loop on its own task notification index on ESP32 (#20326)
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-07 21:17:16 -05:00
esphome[bot] 68a5e33182 Bump aioesphomeapi from 46.7.0 to 46.8.0 (#20321) 2026-10-08 00:17:23 +00:00
mrtoy-me 883af036a9 [tas58xx] Improve TAS5805M audio performance and use GPIO1 for TAS5825M faults (#20319) 2026-10-07 13:57:46 -10:00
esphome[bot] 8f003dfa3b Bump aioesphomeapi from 46.6.0 to 46.7.0 (#20317) 2026-10-07 13:31:24 -10:00
Jesse Hills 6d3792e5c5 [ci] Only run sync dependency versions workflow on PRs targeting dev (#20316) 2026-10-08 12:22:07 +13:00
Jesse Hills c73ec262e9 Merge branch 'beta' into dev 2026-10-08 12:15:20 +13:00
Jesse Hills 7a1bfed81f Bump version to 2026.11.0-dev 2026-10-08 12:01:52 +13:00
J. Nick Koston 12c03d539a [cc1101] Keep constant send_packet payloads in shared flash tables (#20264) 2026-10-07 10:54:56 -10:00
J. Nick Koston 24fc86c2c4 [core] Deprecate TemplatableValue::is_static_string and get_static_string (#20280) 2026-10-07 20:48:46 +00:00
J. Nick Koston 18e93a96fc Merge remote-tracking branch 'origin/dev' into autorepeat-progmem-timing 2026-10-04 18:06:30 -05:00
J. Nick Koston 01f1139476 Also guard the struct size so an added field fails the build 2026-10-03 05:48:38 -05:00
J. Nick Koston 053cb337aa Split the field type guards into one static_assert per field
clang-tidy flags the chained is_same_v checks as a redundant expression.
2026-10-02 21:42:31 -05:00
J. Nick Koston 3ac5918ec8 [core] Let shared_progmem_array emit an unshared array
Identical lambdas can carry separate static state, so callers need a way
to keep such tables apart while still getting a collision free name.
2026-10-02 21:19:12 -05:00
J. Nick Koston bf5d095cf6 End the autorepeat table with a never-run step so the filter stores no count 2026-10-02 20:59:52 -05:00
J. Nick Koston eae1b99232 Guard the AutorepeatFilterTiming field types read from flash 2026-10-02 20:59:52 -05:00
J. Nick Koston 15936f9a55 [core] Emit shared PROGMEM arrays at namespace scope
A setup() local table could only be reused from the scope of its first
use. The arrays are now globals. A lambda in a table only references
variables that codegen has already declared, so writing the global
straight away keeps the order valid.
2026-10-02 20:03:21 -05:00
J. Nick Koston aac085c5c7 Build the autorepeat timing table with cg.shared_progmem_array 2026-10-02 19:49:24 -05:00
J. Nick Koston fe66ac546a [core] Add cg.shared_progmem_array for deduplicated PROGMEM tables
Emits one PROGMEM array per distinct type and contents and returns the
same variable to later callers. The array name is made unique against
every config id and registered variable, so a generated table can never
collide with a user id.
2026-10-02 19:48:06 -05:00
J. Nick Koston a8e5fd0d2f Build the default autorepeat timing from the schema and tidy the tests 2026-10-02 19:07:18 -05:00
J. Nick Koston 93afb0d092 [binary_sensor] Keep autorepeat filter timings in a shared PROGMEM table 2026-10-02 18:53:18 -05:00
2151 changed files with 8215 additions and 4545 deletions
+1 -1
View File
@@ -53,7 +53,7 @@ module.exports = async ({ github, context }) => {
});
const currentLabels = currentLabelsData.map(label => label.name);
const managedLabels = currentLabels.filter(label =>
label.startsWith('component: ') || MANAGED_LABELS.includes(label)
label.startsWith('component: ') || label.startsWith('platform: ') || MANAGED_LABELS.includes(label)
);
// Check for mega-PR early - if present, skip most automatic labeling
+13 -17
View File
@@ -286,7 +286,7 @@ jobs:
fi
echo "version=$version" >> "$GITHUB_OUTPUT"
- name: Run prek
uses: j178/prek-action@4e14d07f9231acabce116ccfca13b13dd9755ece # v3.0.0
uses: j178/prek-action@1382ad72dea72f9d53832f2bcb65b3e87a947204 # v3.0.1
with:
prek-version: ${{ steps.prek.outputs.version }}
# This job only runs on pull requests, so nothing ever populates
@@ -1422,31 +1422,27 @@ jobs:
echo "::warning::ci_memory_impact_extract.py not found on target branch, skipping memory impact analysis"
fi
# Check if test files exist on the target branch for the requested
# components and platform. When a PR adds new test files for a platform,
# the target branch won't have them yet, so skip instead of failing.
# This check must be done here (not in determine-jobs.py) because
# determine-jobs runs on the PR branch and cannot see what the target
# branch has.
# The build below uses --base-only, so skip unless the target branch has
# test.<platform>.yaml for every requested component (test-*.yaml
# variants alone compile nothing, and a partial set would compare a
# smaller target build against the PR build). Checked here, not in
# determine-jobs.py, because determine-jobs runs on the PR branch and
# cannot see the target branch.
- name: Check for test files on target branch
id: check-tests
if: steps.check-script.outputs.skip != 'true'
run: |
components='${{ toJSON(fromJSON(needs.determine-jobs.outputs.memory_impact).components) }}'
platform="${{ fromJSON(needs.determine-jobs.outputs.memory_impact).platform }}"
found=false
missing=""
for component in $(echo "$components" | jq -r '.[]'); do
# Check for test files matching the platform (test.platform.yaml or test-*.platform.yaml)
for f in tests/components/${component}/test*.${platform}.yaml; do
if [ -f "$f" ]; then
found=true
break 2
fi
done
if [ ! -f "tests/components/${component}/test.${platform}.yaml" ]; then
missing="${missing} ${component}"
fi
done
if [ "$found" = false ]; then
if [ -n "$missing" ]; then
echo "skip=true" >> $GITHUB_OUTPUT
echo "::warning::No test files found on target branch for platform ${platform}, skipping memory impact analysis"
echo "::warning::No test.${platform}.yaml on target branch for${missing}, skipping memory impact analysis"
else
echo "skip=false" >> $GITHUB_OUTPUT
fi
@@ -15,6 +15,8 @@ on:
# base branch checkout, so fork code never runs with the token.
pull_request_target:
types: [opened, synchronize, reopened]
branches:
- dev
paths:
- requirements_dev.txt
- requirements_test.txt
+31
View File
@@ -177,6 +177,13 @@ file does, and it is the authority when they disagree. The most useful starting
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
* **Scheduler ids:** name a timer only when it must be cancelled or replaced, and use a
`static constexpr uint32_t` id, never a string. Ids are per component instance and cannot clash with other
components, so number them from 0 and keep all of a component's ids together in one place.
```cpp
static constexpr uint32_t READ_TIMEOUT_ID = 0;
this->set_timeout(READ_TIMEOUT_ID, 50, [this]() { this->read_(); });
```
* **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.
@@ -230,6 +237,10 @@ file does, and it is the authority when they disagree. The most useful starting
```
* **Component Metadata:**
- `DOMAIN`: Required in every component's `__init__.py`, set to the component's own name as a plain
string (e.g. `DOMAIN = "my_component"`). Other code refers to the component through it, e.g.
`from esphome.components.my_component import DOMAIN`. Keep it in alphabetical order with the other
metadata constants. CI (`lint_component_domain`) fails without it.
- `DEPENDENCIES`: List of required components
- `AUTO_LOAD`: Components to automatically load
- `CONFLICTS_WITH`: Incompatible components
@@ -243,6 +254,7 @@ file does, and it is the authority when they disagree. The most useful starting
import esphome.config_validation as cv
from esphome.const import CONF_KEY, CONF_ID
DOMAIN = "my_component"
CONF_PARAM = "param" # A constant that does not yet exist in esphome/const.py
my_component_ns = cg.esphome_ns.namespace("my_component")
@@ -384,6 +396,25 @@ file does, and it is the authority when they disagree. The most useful starting
)
```
When the callback's parameters differ from the automation's arguments, or the trigger should only
fire for some values, pass `params`, `forward` and `when`; the helper then generates a capture-less
lambda (stored inline, nothing allocated). Name the parent with `automation.parent_ref(var)` and build
`forward` from `MockObj` calls, not f-strings of C++:
```python
parent = automation.parent_ref(var)
index = cg.RawExpression("index")
await automation.build_callback_automation(
var,
"add_on_state_callback",
[(cg.StringRef, "x"), (cg.size_t, "i")],
conf,
params=[(cg.size_t, "index")],
forward=[cg.StringRef(parent.option_at(index)), index],
)
```
`build_parent_callback_automation`, `build_trigger_callback`, `build_callback_automations` and
`build_trigger_automations` cover the other shapes; see their docstrings in `esphome/automation.py`.
**C++ -- no trigger class needed.** The callback registration method must be templatized to accept both `std::function` and lightweight forwarder structs (which avoid heap allocation):
```cpp
class MyComponent : public Component {
+2
View File
@@ -188,6 +188,7 @@ esphome/components/esp32_rmt_led_strip/* @jesserockz
esphome/components/esp8266/* @esphome/core
esphome/components/esp_ldo/* @clydebarrow
esphome/components/espectre/* @francescopace
esphome/components/esphome/ota/* @esphome/core
esphome/components/espnow/* @jesserockz
esphome/components/espnow/packet_transport/* @EasilyBoredEngineer
esphome/components/ethernet_info/* @gtjadsonsantos
@@ -518,6 +519,7 @@ esphome/components/sound_level/* @kahrendt
esphome/components/spa06_base/* @danielkent-net
esphome/components/spa06_i2c/* @danielkent-net
esphome/components/spa06_spi/* @danielkent-net
esphome/components/spd2010/* @grischard
esphome/components/speaker/* @jesserockz @kahrendt
esphome/components/speaker/media_player/* @kahrendt @synesthesiam
esphome/components/speaker_source/* @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.10.0b2
PROJECT_NUMBER = 2026.11.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 -1
View File
@@ -22,7 +22,7 @@ RUN \
-r /requirements.txt
# Install the ESPHome Device Builder dashboard.
RUN uv pip install --no-cache-dir esphome-device-builder==1.22.0
RUN uv pip install --no-cache-dir esphome-device-builder==1.23.0
RUN \
platformio settings set enable_telemetry No \
+14 -14
View File
@@ -49,40 +49,40 @@ class FrameworkRelease(NamedTuple):
# Arduino core version -> its build in esphome-libs/arduino-esp8266
FRAMEWORK_RELEASES: dict[Version, FrameworkRelease] = {
Version(3, 1, 2): FrameworkRelease(
"3.1.2-esphome.2",
"9377d63f569c524823199b1897ed7fde2063e50e2676dd519a0d758ab73678f7",
37192128,
"3.1.2-esphome.3",
"3af533a85163804e164500a5b254dc23b922080e25ecb7dc37b3dd8ac84651db",
37185650,
),
}
TOOLCHAIN_PACKAGE = "toolchain-xtensa-lx106-elf"
# gcc 10.3, the toolchain Arduino core 3.x builds with; the build
# generator's compile flags are tuned to it.
TOOLCHAIN_VERSION = "10.3.0-esphome.2"
TOOLCHAIN_VERSION = "10.3.0-esphome.3"
_TOOLCHAIN_RELEASES = (
"https://github.com/esphome-libs/xtensa-lx106-elf-toolchain/releases/"
)
# Registry system tag -> (sha256, size) of that host's archive
TOOLCHAIN_BUILDS: dict[str, tuple[str, int]] = {
"darwin_arm64": (
"849cede44d4d5c6ea0f14099783239f559f46327bea314281814f2652b486201",
60830321,
"ad0ea929238d9b527c43e0d20257acc2a5680bdb0d2b1cf8f2c99169786217e9",
60747260,
),
"darwin_x86_64": (
"ca69904daabf0c5983b372423e5e62f49182a793e992c052e94666852470c897",
64149487,
"997090cac80c8eb59604ec52b73fb3568e5f2d9b2971f83c3f2a5c545c9c949c",
64065752,
),
"linux_aarch64": (
"60a49a4f082bf246544bd409a9517dbbcab19bb30ac9decbee544b896aaccbd6",
67573397,
"403f14d0d5755682fcd6eaea1e4c457a1d8cad30690e52fb0c804d8db266b908",
67487067,
),
"linux_x86_64": (
"1fba33ca1494ec79f2776e0e37eca93282d30f8bb9992f5f4f9a655d6fff1db4",
68431336,
"64f21fa3ba736b363dc8c234dbbb39e005e574e33de08a78e9a00c55a64ae706",
68343668,
),
"windows_amd64": (
"af9066b0e5bf036f04f2bd9d08b89b81a7f183c57dac0abcaff71dd861cf5f3b",
67664137,
"1e62abf8df041ce5158f5770dffef955f2f981ce7f7adee88fcd5a8197705aa6",
67536405,
),
}
+178 -88
View File
@@ -1,4 +1,4 @@
from collections.abc import Callable
from collections.abc import Callable, Sequence
from dataclasses import dataclass, field
import logging
import string
@@ -23,7 +23,7 @@ from esphome.const import (
)
from esphome.core import CORE, ID, EsphomeError, HexInt, Lambda
from esphome.cpp_generator import (
FlashStringLiteral,
Expression,
LambdaExpression,
MockObj,
MockObjClass,
@@ -245,9 +245,7 @@ ApplyCondition = cg.esphome_ns.class_("ApplyCondition", Condition)
def flash_string(config: ConfigType, value: str) -> str:
"""Default renderer for ``std::string`` constants; copies the literal out of flash on ESP8266."""
if CORE.is_esp8266:
return f"progmem_string({FlashStringLiteral(value)})"
return str(cg.safe_exp(value))
return str(cg.progmem_string(value))
def literal_with_length(config: ConfigType, value: str) -> str:
@@ -259,13 +257,24 @@ def literal_with_length(config: ConfigType, value: str) -> str:
return f"{cg.safe_exp(value)}, {len(value.encode('utf-8'))}"
def string_ref_literal(config: ConfigType, value: str) -> str:
"""Renderer for a ``StringRef`` comparison: a flash literal on ESP8266, else ``StringRef(literal, length)``."""
if CORE.is_esp8266:
return str(cg.FlashStringLiteral(value))
return f"StringRef({literal_with_length(config, value)})"
def _names_parent(text: str) -> bool:
return any(f == "parent" for _, f, _, _ in string.Formatter().parse(text))
@dataclass(frozen=True)
class ApplyCall:
"""One statement from config keys, e.g. ``"set_range({}, {})"`` with ``((CONF_LOW, cg.float_), ...)``.
Each arg is ``(conf_key, type_)`` or ``(conf_key, type_, const_fn)``. A ``conf_key`` may be a
path into nested sections. A plain ``str`` ``type_`` is raw C++ type text and may use
``{parent}``. ``const_fn(config, value)`` renders a constant's argument text; a lambda or an
path into nested sections. ``target`` and a plain ``str`` ``type_`` (raw C++ type text) may
name the parent object as ``{parent}``. ``const_fn(config, value)`` renders a constant's argument text; a lambda or an
id bypasses it. The statement is skipped when none of its keys is set, always emitted when it
has no keys, and a partial set is a config error.
"""
@@ -277,13 +286,13 @@ class ApplyCall:
fields = [
f for _, f, _, _ in string.Formatter().parse(self.target) if f is not None
]
if any(fields):
if any(f not in ("", "parent") for f in fields):
raise ValueError(
f"apply target {self.target!r}: only bare {{}} placeholders"
f"apply target {self.target!r}: only {{}} and {{parent}} placeholders"
)
if len(fields) != len(self.args):
if (count := fields.count("")) != len(self.args):
raise ValueError(
f"apply target {self.target!r} has {len(fields)} "
f"apply target {self.target!r} has {count} "
f"placeholder(s) for {len(self.args)} config key(s)"
)
if any(len(arg) not in (2, 3) for arg in self.args):
@@ -291,6 +300,12 @@ class ApplyCall:
f"apply target {self.target!r}: each arg is (conf_key, type_[, const_fn])"
)
@property
def names_parent(self) -> bool:
return _names_parent(self.target) or any(
isinstance(arg[1], str) and _names_parent(arg[1]) for arg in self.args
)
@property
def members(self) -> list[tuple[Any, Any, Any]]:
"""Each arg as ``(conf_key, type_, const_fn or None)``."""
@@ -365,9 +380,16 @@ def _check_key_in_schema(
schema = schema.schema[markers[part]]
def parent_ref(var: MockObj) -> MockObj:
"""``var`` named from global scope, so a trigger argument cannot shadow it.
Also how a generated callback names its Automation.
"""
return MockObj(f"::{var}", "->")
async def _apply_parent(config: ConfigType, id_key: str = CONF_ID) -> str:
# Global-scope qualified so a trigger arg named like the id cannot shadow it.
return f"::{await cg.get_variable(config[id_key])}"
return str(parent_ref(await cg.get_variable(config[id_key])))
def _apply_lambda_args(args: TemplateArgsType) -> TemplateArgsType:
@@ -399,7 +421,7 @@ async def _render_values(
members: list[tuple[Any, Any, Any]],
values: list[Any],
config: ConfigType,
parent: str,
parent: str | None,
lambda_args: TemplateArgsType,
compare: bool = False,
) -> list[str]:
@@ -477,12 +499,12 @@ def register_apply_action(
statements: list[str] = []
for target, members in statements_spec:
values = _apply_values(config, members)
if members and all(value is None for value in values):
if not _apply_call_active(members, values):
continue
exprs = await _render_values(
name, target, members, values, config, parent, lambda_args
)
statements.append(f"{receiver}{target.format(*exprs)};")
statements.append(f"{receiver}{target.format(*exprs, parent=parent)};")
if call:
statements = [
f"auto apply_call = {parent}->{call}();",
@@ -496,6 +518,27 @@ def register_apply_action(
register_action(name, ApplyAction, schema, synchronous=True)(builder)
def _apply_call_active(members: list[tuple[Any, Any, Any]], values: list[Any]) -> bool:
"""An ``ApplyCall`` is emitted unless it has keys and none of them is set."""
return not members or any(value is not None for value in values)
async def _render_check(
name: str,
target: str,
members: list[tuple[Any, Any, Any]],
values: list[Any],
config: ConfigType,
parent: str | None,
lambda_args: TemplateArgsType,
) -> str:
"""Render a boolean check with ``values`` compared against config."""
exprs = await _render_values(
name, target, members, values, config, parent, lambda_args, compare=True
)
return target.format(*exprs, parent=parent)
def register_apply_condition(
name: str, schema: cv.Schema, check: str | ApplyCall, id_key: str = CONF_ID
) -> None:
@@ -521,22 +564,16 @@ def register_apply_condition(
) -> MockObj:
parent = await _apply_parent(config, id_key)
lambda_args = _apply_lambda_args(args)
exprs = await _render_values(
name,
call.target,
members,
_apply_values(config, members),
config,
parent,
lambda_args,
compare=True,
values = _apply_values(config, members)
check = await _render_check(
name, call.target, members, values, config, parent, lambda_args
)
return _apply_function(
condition_id,
cg.bool_,
template_arg,
lambda_args,
[f"return {parent}->{call.target.format(*exprs)};"],
[f"return {parent}->{check};"],
)
register_condition(name, ApplyCondition, schema)(builder)
@@ -672,52 +709,20 @@ XorCondition = cg.esphome_ns.class_("XorCondition", Condition)
@register_condition("and", AndCondition, validate_condition_list)
async def and_condition_to_code(
config: ConfigType,
condition_id: ID,
template_arg: cg.TemplateArguments,
args: TemplateArgsType,
) -> MockObj:
conditions = await build_condition_list(config, template_arg, args)
return cg.new_Pvariable(
condition_id, cg.TemplateArguments(len(conditions), *template_arg), conditions
)
@register_condition("or", OrCondition, validate_condition_list)
async def or_condition_to_code(
config: ConfigType,
condition_id: ID,
template_arg: cg.TemplateArguments,
args: TemplateArgsType,
) -> MockObj:
conditions = await build_condition_list(config, template_arg, args)
return cg.new_Pvariable(
condition_id, cg.TemplateArguments(len(conditions), *template_arg), conditions
)
@register_condition("all", AndCondition, validate_condition_list)
async def all_condition_to_code(
config: ConfigType,
condition_id: ID,
template_arg: cg.TemplateArguments,
args: TemplateArgsType,
) -> MockObj:
conditions = await build_condition_list(config, template_arg, args)
return cg.new_Pvariable(
condition_id, cg.TemplateArguments(len(conditions), *template_arg), conditions
)
@register_condition("or", OrCondition, validate_condition_list)
@register_condition("any", OrCondition, validate_condition_list)
async def any_condition_to_code(
@register_condition("xor", XorCondition, validate_condition_list)
async def condition_group_to_code(
config: ConfigType,
condition_id: ID,
template_arg: cg.TemplateArguments,
args: TemplateArgsType,
) -> MockObj:
conditions = await build_condition_list(config, template_arg, args)
# A group of one is that condition for and, or and xor; skip the wrapper.
if len(conditions) == 1:
return conditions[0]
return cg.new_Pvariable(
condition_id, cg.TemplateArguments(len(conditions), *template_arg), conditions
)
@@ -734,19 +739,6 @@ async def not_condition_to_code(
return cg.new_Pvariable(condition_id, template_arg, condition)
@register_condition("xor", XorCondition, validate_condition_list)
async def xor_condition_to_code(
config: ConfigType,
condition_id: ID,
template_arg: cg.TemplateArguments,
args: TemplateArgsType,
) -> MockObj:
conditions = await build_condition_list(config, template_arg, args)
return cg.new_Pvariable(
condition_id, cg.TemplateArguments(len(conditions), *template_arg), conditions
)
@register_condition("lambda", LambdaCondition, cv.returning_lambda)
async def lambda_condition_to_code(
config: ConfigType,
@@ -1056,23 +1048,78 @@ def has_non_synchronous_actions(actions: ConfigType) -> bool:
return False
async def build_automation(
trigger: MockObj, args: TemplateArgsType, config: ConfigType
async def _new_automation(
args: TemplateArgsType, config: ConfigType, *ctor_args: MockObj
) -> MockObj:
arg_types = [arg[0] for arg in args]
templ = cg.TemplateArguments(*arg_types)
obj = cg.new_Pvariable(config[CONF_AUTOMATION_ID], templ, trigger)
"""Create the Automation for ``config`` with its actions."""
templ = cg.TemplateArguments(*(arg[0] for arg in args))
obj = cg.new_Pvariable(config[CONF_AUTOMATION_ID], templ, *ctor_args)
actions = await build_action_list(config[CONF_THEN], templ, args)
cg.add(obj.add_actions(actions))
return obj
async def build_automation(
trigger: MockObj, args: TemplateArgsType, config: ConfigType
) -> MockObj:
return await _new_automation(args, config, trigger)
async def build_trigger_callback(
args: TemplateArgsType,
config: ConfigType,
params: TemplateArgsType,
forward: Sequence[str | Expression] | None = None,
when: str | ApplyCall | None = None,
parent: MockObj | None = None,
) -> LambdaExpression:
"""Build the Automation for ``config`` and return a stateless callback that triggers it.
``params`` are the parent callback's parameters, ``forward`` the expressions passed to
``trigger()`` (default: the parameter names; write the parent as ``parent_ref(var)``),
``when`` a filter the callback returns early on, skipped like any ``ApplyCall`` when none
of its keys is set. ``when`` may name ``parent`` as ``{parent}``, e.g.
``"{parent}->is_fully_open()"``.
"""
members: list[tuple[Any, Any, Any]] = []
if when is not None:
call = when if isinstance(when, ApplyCall) else ApplyCall(when)
members = call.members
if parent is None and call.names_parent:
raise ValueError(f"trigger filter {call.target!r} names {{parent}}")
obj = await _new_automation(args, config)
lambda_args = _apply_lambda_args(params)
statements: list[str] = []
if when is not None:
values = _apply_values(config, members)
if _apply_call_active(members, values):
check = await _render_check(
"trigger filter",
call.target,
members,
values,
config,
None if parent is None else str(parent_ref(parent)),
lambda_args,
)
statements.append(f"if (!({check}))\n return;")
if forward is None:
forward = [name for _, name in params]
statements.append(f"{parent_ref(obj)}->trigger({', '.join(map(str, forward))});")
return LambdaExpression(
["\n".join(statements)], lambda_args, capture="", return_type=cg.void
)
async def build_callback_automation(
parent: MockObj,
callback_method: str,
args: TemplateArgsType,
config: ConfigType,
forwarder: MockObj | MockObjClass | None = None,
params: TemplateArgsType | None = None,
forward: Sequence[str | Expression] | None = None,
when: str | ApplyCall | None = None,
) -> None:
"""Build an Automation and register it as a callback on the parent.
@@ -1084,6 +1131,9 @@ async def build_callback_automation(
pointer-sized (single Automation* field) to fit inline in Callback::ctx_
and avoid heap allocation.
With ``params``, ``forward`` or ``when`` the callback is instead the stateless
lambda of ``build_trigger_callback``; ``forwarder`` cannot be combined with them.
:param parent: The component object (e.g., button, sensor).
:param callback_method: Name of the callback method (e.g., "add_on_press_callback").
:param args: Automation template args as list of (type, name) tuples.
@@ -1092,22 +1142,56 @@ async def build_callback_automation(
TriggerForwarder<Ts...>. Pass any struct type whose aggregate init takes
a single Automation pointer (e.g., TriggerOnTrueForwarder).
"""
arg_types = [arg[0] for arg in args]
templ = cg.TemplateArguments(*arg_types)
obj = cg.new_Pvariable(config[CONF_AUTOMATION_ID], templ)
actions = await build_action_list(config[CONF_THEN], templ, args)
cg.add(obj.add_actions(actions))
if params is not None or forward is not None or when is not None:
if forwarder is not None:
raise ValueError(
"forwarder cannot be combined with params, forward or when"
)
callback = await build_trigger_callback(
args, config, args if params is None else params, forward, when, parent
)
cg.add(getattr(parent, callback_method)(callback))
return
obj = await _new_automation(args, config)
# Use template forwarder structs for deduplication. The compiler generates
# one operator() per forwarder type; different automation pointers are just
# data in the struct.
if forwarder is None:
forwarder = TriggerForwarder.template(templ)
forwarder = TriggerForwarder.template(*(arg[0] for arg in args))
# RawExpression for aggregate init — both forwarder and obj are codegen
# MockObjs (not user input), and there's no Expression type for positional
# aggregate initialization (StructInitializer uses named fields).
cg.add(getattr(parent, callback_method)(cg.RawExpression(f"{forwarder}{{{obj}}}")))
async def build_parent_callback_automation(
parent: MockObj, callback_method: str, arg: tuple[Any, str], config: ConfigType
) -> None:
"""Register an Automation that receives ``parent`` from a callback that carries nothing.
``arg`` is the automation's ``(type, name)``, e.g. ``(Fan.operator("ptr"), "x")``.
"""
await build_callback_automation(
parent, callback_method, [arg], config, params=[], forward=[parent_ref(parent)]
)
async def build_trigger_automations(
parent: MockObj | None,
config: ConfigType,
entries: tuple[tuple[str, TemplateArgsType], ...],
) -> None:
"""Instantiate each entry's Trigger class, with ``parent`` when given, and build its automations.
``entries`` are ``(conf_key, args)`` pairs; the class comes from the entry's ``CONF_TRIGGER_ID``.
"""
ctor_args = () if parent is None else (parent,)
for conf_key, args in entries:
for conf in config.get(conf_key, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], *ctor_args)
await build_automation(trigger, args, conf)
@dataclass(frozen=True, slots=True)
class CallbackAutomation:
"""A single callback automation entry for build_callback_automations."""
@@ -1116,6 +1200,9 @@ class CallbackAutomation:
callback_method: str
args: TemplateArgsType = field(default_factory=list)
forwarder: MockObj | MockObjClass | None = None
params: TemplateArgsType | None = None
forward: Sequence[str | Expression] | None = None
when: str | ApplyCall | None = None
async def build_callback_automations(
@@ -1137,4 +1224,7 @@ async def build_callback_automations(
entry.args,
conf,
forwarder=entry.forwarder,
params=entry.params,
forward=entry.forward,
when=entry.when,
)
+51 -15
View File
@@ -237,6 +237,35 @@ def idf_macro_matches(idf_path: Path) -> bool:
return live == _EXPECTED_MACRO
def _cmake_args_for_write(minimal: bool) -> dict[str, str]:
"""The cg.add_cmake_arg() values for one project write.
The discovery (minimal) write lets every built-in component register so
the list it finds, cached per target, serves any exclusion set; the full
write drops the excluded names from that list and passes all of them to
IDF. Names outside the framework's components directory (managed
components) stay excluded on the discovery write too, since the list
only holds built-in ones. A checkout supplied through IDF_PATH caches
nothing, so its discovery keeps every exclusion.
"""
from esphome.espidf.toolchain import _esphome_manages_idf, _get_idf_path
args = dict(CORE.cmake_args)
if (
not minimal
or not _esphome_manages_idf()
or not (excluded := args.get("EXCLUDE_COMPONENTS"))
):
return args
root = _get_idf_path() / "components"
outside = [name for name in excluded.split(";") if not (root / name).is_dir()]
if outside:
args["EXCLUDE_COMPONENTS"] = ";".join(outside)
else:
del args["EXCLUDE_COMPONENTS"]
return args
def get_project_cmakelists(
minimal: bool = False, builtin_components: list[str] | None = None
) -> str:
@@ -300,11 +329,10 @@ def get_project_cmakelists(
# 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.
# set when project.cmake seeds the component list.
cmake_args = "\n".join(
f"set({name} {_cmake_quote(value)})"
for name, value in sorted(CORE.cmake_args.items())
for name, value in sorted(_cmake_args_for_write(minimal).items())
)
# Per-project list exposed as a CMake variable so converted PIO libs
@@ -327,10 +355,10 @@ def get_project_cmakelists(
# 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).
# Excluded components are dropped here as well: the discovery list
# (cached per target) still holds 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 = (
@@ -397,15 +425,24 @@ project({CORE.name})
# Emit per-memory-type JSON size data for ESPHome to read post-build.
# json2 stays small; raw dumps every symbol (~2s on a large map) and
# this command runs inside the link edge, blocking everything downstream.
# The map is a BYPRODUCT so ninja knows the link writes it; IDF's size
# target depends on the map and can then be built in the same run as all.
# IDF's cmakev2 declares the map itself, so drop this line on that switch.
# IDF's size target depends on the map, so ninja has to know the link
# writes it for size to build in the same run as all. IDF declares the
# map itself since espressif/esp-idf#19201 (and in cmakev2), and ninja
# rejects two rules for one output, so declare it here only when IDF has
# not. add_custom_command(OUTPUT) marks its outputs GENERATED.
get_source_file_property(esphome_map_declared
${{CMAKE_BINARY_DIR}}/${{CMAKE_PROJECT_NAME}}.map GENERATED)
if(esphome_map_declared)
set(esphome_map_byproducts)
else()
set(esphome_map_byproducts BYPRODUCTS ${{CMAKE_BINARY_DIR}}/${{CMAKE_PROJECT_NAME}}.map)
endif()
add_custom_command(
TARGET ${{CMAKE_PROJECT_NAME}}.elf POST_BUILD
COMMAND ${{PYTHON}} -m esp_idf_size {size_ng_flag} --format=json2
-o ${{CMAKE_BINARY_DIR}}/esp_idf_size.json
${{CMAKE_PROJECT_NAME}}.map
BYPRODUCTS ${{CMAKE_BINARY_DIR}}/${{CMAKE_PROJECT_NAME}}.map
${{esphome_map_byproducts}}
WORKING_DIRECTORY ${{CMAKE_BINARY_DIR}}
VERBATIM
)
@@ -554,10 +591,9 @@ def write_project(
)
# 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.
# reconfigure when it changes. The ESPHOME_PROJECT_BUILTIN_COMPONENTS
# property drops excluded names, so re-including one (e.g. a config
# gains mqtt) needs a reconfigure to rebuild it from the discovery list.
write_file_if_changed(
CORE.relative_build_path("exclude_components.esphomeinternal"),
";".join(get_excluded_builtin_components()),
+2
View File
@@ -34,11 +34,13 @@ from esphome.cpp_generator import ( # noqa: F401
extern_progmem_array,
get_variable,
get_variable_with_full_id,
is_static_pointer,
is_template,
new_Pvariable,
new_variable,
process_lambda,
progmem_array,
progmem_string,
safe_exp,
set_cpp_standard,
shared_progmem_array,
+1
View File
@@ -1 +1,2 @@
CODEOWNERS = ["@MrSuicideParrot"]
DOMAIN = "a01nyub"
+1 -1
View File
@@ -6,7 +6,7 @@
namespace esphome::a01nyub {
static const char *const TAG = "a01nyub.sensor";
ESPHOME_LOG_TAG(TAG, "a01nyub.sensor");
void A01nyubComponent::loop() {
uint8_t data;
+1
View File
@@ -1 +1,2 @@
CODEOWNERS = ["@TH-Braemer"]
DOMAIN = "a02yyuw"
+1 -1
View File
@@ -6,7 +6,7 @@
namespace esphome::a02yyuw {
static const char *const TAG = "a02yyuw.sensor";
ESPHOME_LOG_TAG(TAG, "a02yyuw.sensor");
void A02yyuwComponent::loop() {
uint8_t data;
+1
View File
@@ -0,0 +1 @@
DOMAIN = "a4988"
+1 -1
View File
@@ -3,7 +3,7 @@
namespace esphome::a4988 {
static const char *const TAG = "a4988.stepper";
ESPHOME_LOG_TAG(TAG, "a4988.stepper");
void A4988::setup() {
if (this->sleep_pin_ != nullptr) {
@@ -1 +1,2 @@
CODEOWNERS = ["@DAVe3283"]
DOMAIN = "absolute_humidity"
@@ -3,7 +3,7 @@
namespace esphome::absolute_humidity {
static const char *const TAG{"absolute_humidity.sensor"};
ESPHOME_LOG_TAG(TAG, "absolute_humidity.sensor");
void AbsoluteHumidityComponent::setup() {
this->temperature_sensor_->add_on_state_callback([this](float state) {
+1
View File
@@ -0,0 +1 @@
DOMAIN = "ac_dimmer"
+1 -1
View File
@@ -14,7 +14,7 @@
namespace esphome::ac_dimmer {
static const char *const TAG = "ac_dimmer";
ESPHOME_LOG_TAG(TAG, "ac_dimmer");
// Global array to store dimmer objects
static AcDimmerDataStore *all_dimmers[32]; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
@@ -9,7 +9,7 @@
#include "esp_clk_tree.h"
#include "soc/clk_tree_defs.h"
static const char *const TAG = "hw_timer_esp_idf";
ESPHOME_LOG_TAG(TAG, "hw_timer_esp_idf");
namespace esphome::ac_dimmer {
+1
View File
@@ -9,6 +9,7 @@ from esphome.cpp_generator import MockObj
from esphome.types import ConfigType
DEPENDENCIES = ["uart"]
DOMAIN = "adalight"
adalight_ns = cg.esphome_ns.namespace("adalight")
AdalightLightEffect = adalight_ns.class_(
@@ -3,7 +3,7 @@
namespace esphome::adalight {
static const char *const TAG = "adalight_light_effect";
ESPHOME_LOG_TAG(TAG, "adalight_light_effect");
static const uint32_t ADALIGHT_ACK_INTERVAL = 1000;
static const uint32_t ADALIGHT_RECEIVE_TIMEOUT = 1000;
+1
View File
@@ -22,6 +22,7 @@ from esphome.core import CORE
from esphome.types import ConfigType
CODEOWNERS = ["@esphome/core"]
DOMAIN = "adc"
adc_ns = cg.esphome_ns.namespace("adc")
+1 -1
View File
@@ -3,7 +3,7 @@
namespace esphome::adc {
static const char *const TAG = "adc";
ESPHOME_LOG_TAG(TAG, "adc");
const LogString *sampling_mode_to_str(SamplingMode mode) {
switch (mode) {
+1 -1
View File
@@ -6,7 +6,7 @@
namespace esphome::adc {
static const char *const TAG = "adc";
ESPHOME_LOG_TAG(TAG, "adc");
adc_oneshot_unit_handle_t ADCSensor::shared_adc_handles[2] = {nullptr, nullptr};
@@ -13,7 +13,7 @@ ADC_MODE(ADC_VCC)
namespace esphome::adc {
static const char *const TAG = "adc";
ESPHOME_LOG_TAG(TAG, "adc");
void ADCSensor::setup() {
#ifndef USE_ADC_SENSOR_VCC
@@ -5,7 +5,7 @@
namespace esphome::adc {
static const char *const TAG = "adc";
ESPHOME_LOG_TAG(TAG, "adc");
void ADCSensor::setup() {
#ifndef USE_ADC_SENSOR_VCC
+1 -1
View File
@@ -17,7 +17,7 @@
namespace esphome::adc {
static const char *const TAG = "adc";
ESPHOME_LOG_TAG(TAG, "adc");
// The on-die temperature sensor sits on the last ADC channel: input 4 on RP2040
// and RP2350A, but input 8 on RP2350B, which has eight external channels rather
+1 -1
View File
@@ -7,7 +7,7 @@
namespace esphome::adc {
static const char *const TAG = "adc";
ESPHOME_LOG_TAG(TAG, "adc");
void ADCSensor::setup() {
if (!adc_is_ready_dt(this->channel_)) {
@@ -5,6 +5,7 @@ from esphome.const import CONF_ID
from esphome.types import ConfigType
DEPENDENCIES = ["spi"]
DOMAIN = "adc128s102"
MULTI_CONF = True
CODEOWNERS = ["@DeerMaximum"]
+1 -1
View File
@@ -3,7 +3,7 @@
namespace esphome::adc128s102 {
static const char *const TAG = "adc128s102";
ESPHOME_LOG_TAG(TAG, "adc128s102");
float ADC128S102::get_setup_priority() const { return setup_priority::HARDWARE; }
@@ -4,7 +4,7 @@
namespace esphome::adc128s102 {
static const char *const TAG = "adc128s102.sensor";
ESPHOME_LOG_TAG(TAG, "adc128s102.sensor");
ADC128S102Sensor::ADC128S102Sensor(uint8_t channel) : channel_(channel) {}
@@ -0,0 +1 @@
DOMAIN = "addressable_light"
@@ -3,7 +3,7 @@
namespace esphome::addressable_light {
static const char *const TAG = "addressable_light.display";
ESPHOME_LOG_TAG(TAG, "addressable_light.display");
int AddressableLightDisplay::get_width_internal() { return this->width_; }
int AddressableLightDisplay::get_height_internal() { return this->height_; }
+1
View File
@@ -0,0 +1 @@
DOMAIN = "ade7880"
+1 -1
View File
@@ -15,7 +15,7 @@
namespace esphome::ade7880 {
static const char *const TAG = "ade7880";
ESPHOME_LOG_TAG(TAG, "ade7880");
void IRAM_ATTR ADE7880Store::gpio_intr(ADE7880Store *arg) { arg->reset_done = true; }
+1
View File
@@ -1 +1,2 @@
CODEOWNERS = ["@angelnu"]
DOMAIN = "ade7953"
@@ -27,6 +27,7 @@ from esphome.cpp_generator import MockObj
from esphome.types import ConfigType
CODEOWNERS = ["@angelnu"]
DOMAIN = "ade7953_base"
CONF_CURRENT_A = "current_a"
CONF_CURRENT_B = "current_b"
@@ -5,7 +5,7 @@
namespace esphome::ade7953_base {
static const char *const TAG = "ade7953";
ESPHOME_LOG_TAG(TAG, "ade7953");
constexpr uint16_t CONFIG_DEFAULT = 0x8004u;
constexpr uint16_t CONFIG_LOCK_BIT = 0x8000u;
@@ -1 +1,2 @@
CODEOWNERS = ["@angelnu"]
DOMAIN = "ade7953_i2c"
@@ -4,7 +4,7 @@
namespace esphome::ade7953_i2c {
static const char *const TAG = "ade7953";
ESPHOME_LOG_TAG(TAG, "ade7953");
void AdE7953I2c::dump_config() {
ESP_LOGCONFIG(TAG, "ADE7953_i2c:");
@@ -1 +1,2 @@
CODEOWNERS = ["@angelnu"]
DOMAIN = "ade7953_spi"
@@ -4,7 +4,7 @@
namespace esphome::ade7953_spi {
static const char *const TAG = "ade7953";
ESPHOME_LOG_TAG(TAG, "ade7953");
// Datasheet requires at least 1.2µs after clearing CONFIG LOCK_BIT before raising CS
constexpr uint8_t CONFIG_LOCK_SETTLE_US = 2;
+1
View File
@@ -5,6 +5,7 @@ from esphome.const import CONF_ID
from esphome.types import ConfigType
DEPENDENCIES = ["i2c"]
DOMAIN = "ads1115"
MULTI_CONF = True
ads1115_ns = cg.esphome_ns.namespace("ads1115")
+1 -1
View File
@@ -4,7 +4,7 @@
namespace esphome::ads1115 {
static const char *const TAG = "ads1115";
ESPHOME_LOG_TAG(TAG, "ads1115");
static const uint8_t ADS1115_REGISTER_CONVERSION = 0x00;
static const uint8_t ADS1115_REGISTER_CONFIG = 0x01;
@@ -4,7 +4,7 @@
namespace esphome::ads1115 {
static const char *const TAG = "ads1115.sensor";
ESPHOME_LOG_TAG(TAG, "ads1115.sensor");
float ADS1115Sensor::sample() {
return this->parent_->request_measurement(this->multiplexer_, this->gain_, this->resolution_, this->samplerate_);
+1
View File
@@ -6,6 +6,7 @@ from esphome.types import ConfigType
CODEOWNERS = ["@solomondg1"]
DEPENDENCIES = ["spi"]
DOMAIN = "ads1118"
MULTI_CONF = True
CONF_ADS1118_ID = "ads1118_id"
+1 -1
View File
@@ -4,7 +4,7 @@
namespace esphome::ads1118 {
static const char *const TAG = "ads1118";
ESPHOME_LOG_TAG(TAG, "ads1118");
static const uint8_t ADS1118_DATA_RATE_860_SPS = 0b111;
void ADS1118::setup() {
@@ -4,7 +4,7 @@
namespace esphome::ads1118 {
static const char *const TAG = "ads1118.sensor";
ESPHOME_LOG_TAG(TAG, "ads1118.sensor");
void ADS1118Sensor::dump_config() {
LOG_SENSOR(" ", "ADS1118 Sensor", this);
+1
View File
@@ -1 +1,2 @@
CODEOWNERS = ["@mak-42"]
DOMAIN = "ags10"
+1 -1
View File
@@ -4,7 +4,7 @@
#include <cinttypes>
namespace esphome::ags10 {
static const char *const TAG = "ags10";
ESPHOME_LOG_TAG(TAG, "ags10");
// Data acquisition.
static const uint8_t REG_TVOC = 0x00;
+1
View File
@@ -0,0 +1 @@
DOMAIN = "aht10"
+1 -1
View File
@@ -19,7 +19,7 @@
namespace esphome::aht10 {
static const char *const TAG = "aht10";
ESPHOME_LOG_TAG(TAG, "aht10");
static const uint8_t AHT10_INITIALIZE_CMD[] = {0xE1, 0x08, 0x00};
static const uint8_t AHT20_INITIALIZE_CMD[] = {0xBE, 0x08, 0x00};
static const uint8_t AHT10_MEASURE_CMD[] = {0xAC, 0x33, 0x00};
+1
View File
@@ -0,0 +1 @@
DOMAIN = "aic3204"
+1 -1
View File
@@ -6,7 +6,7 @@
namespace esphome::aic3204 {
static const char *const TAG = "aic3204";
ESPHOME_LOG_TAG(TAG, "aic3204");
#define ERROR_CHECK(err, msg) \
if (!(err)) { \
@@ -6,6 +6,7 @@ from esphome.types import ConfigType
AUTO_LOAD = ["ble_device_base"]
CODEOWNERS = ["@jeromelaban"]
DOMAIN = "airthings_ble"
airthings_ble_ns = cg.esphome_ns.namespace("airthings_ble")
AirthingsListener = airthings_ble_ns.class_(
@@ -4,7 +4,7 @@
namespace esphome::airthings_ble {
static const char *const TAG = "airthings_ble";
ESPHOME_LOG_TAG(TAG, "airthings_ble");
bool AirthingsListener::parse_device(const ble_device_base::ESPBTDevice &device) {
for (auto &it : device.get_manufacturer_datas()) {
@@ -24,6 +24,7 @@ from esphome.cpp_generator import MockObj
from esphome.types import ConfigType
CODEOWNERS = ["@ncareau", "@jeromelaban"]
DOMAIN = "airthings_wave_base"
DEPENDENCIES = ["ble_client"]
@@ -8,7 +8,10 @@
namespace esphome::airthings_wave_base {
static const char *const TAG = "airthings_wave_base";
ESPHOME_LOG_TAG(TAG, "airthings_wave_base");
static constexpr uint32_t BATTERY_READ_TIMEOUT_ID = 0;
static constexpr uint32_t RESPONSE_TIMEOUT_ID = 1;
void AirthingsWaveBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
esp_ble_gattc_cb_param_t *param) {
@@ -181,7 +184,7 @@ void AirthingsWaveBase::read_battery_(uint8_t *raw_value, uint16_t value_len) {
// read the battery again at the configured update interval
if (this->battery_update_interval_ != this->update_interval_) {
this->read_battery_next_update_ = false;
this->set_timeout("battery", this->battery_update_interval_,
this->set_timeout(BATTERY_READ_TIMEOUT_ID, this->battery_update_interval_,
[this]() { this->read_battery_next_update_ = true; });
}
}
@@ -204,7 +207,7 @@ void AirthingsWaveBase::response_received_() {
}
void AirthingsWaveBase::set_response_timeout_() {
this->set_timeout("response_timeout", 30 * 1000, [this]() {
this->set_timeout(RESPONSE_TIMEOUT_ID, 30 * 1000, [this]() {
this->responses_pending_ = 1;
this->response_received_();
});
@@ -1 +1,2 @@
CODEOWNERS = ["@ncareau"]
DOMAIN = "airthings_wave_mini"
@@ -4,7 +4,7 @@
namespace esphome::airthings_wave_mini {
static const char *const TAG = "airthings_wave_mini";
ESPHOME_LOG_TAG(TAG, "airthings_wave_mini");
void AirthingsWaveMini::read_sensors(uint8_t *raw_value, uint16_t value_len) {
auto *value = (WaveMiniReadings *) raw_value;
@@ -1 +1,2 @@
CODEOWNERS = ["@jeromelaban", "@precurse"]
DOMAIN = "airthings_wave_plus"
@@ -4,7 +4,7 @@
namespace esphome::airthings_wave_plus {
static const char *const TAG = "airthings_wave_plus";
ESPHOME_LOG_TAG(TAG, "airthings_wave_plus");
void AirthingsWavePlus::read_sensors(uint8_t *raw_value, uint16_t value_len) {
auto *value = (WavePlusReadings *) raw_value;
@@ -21,6 +21,7 @@ from esphome.core.entity_helpers import (
from esphome.cpp_generator import MockObjClass
CODEOWNERS = ["@grahambrown11", "@hwstar"]
DOMAIN = "alarm_control_panel"
IS_PLATFORM_COMPONENT = True
CONF_ON_TRIGGERED = "on_triggered"
@@ -10,7 +10,7 @@
namespace esphome::alarm_control_panel {
static const char *const TAG = "alarm_control_panel";
ESPHOME_LOG_TAG(TAG, "alarm_control_panel");
AlarmControlPanelCall AlarmControlPanel::make_call() { return AlarmControlPanelCall(this); }
@@ -6,7 +6,7 @@
namespace esphome::alarm_control_panel {
static const char *const TAG = "alarm_control_panel";
ESPHOME_LOG_TAG(TAG, "alarm_control_panel");
AlarmControlPanelCall::AlarmControlPanelCall(AlarmControlPanel *parent) : parent_(parent) {}
+1
View File
@@ -1 +1,2 @@
CODEOWNERS = ["@jan-hofmeier"]
DOMAIN = "alpha3"
+1 -1
View File
@@ -7,7 +7,7 @@
namespace esphome::alpha3 {
static const char *const TAG = "alpha3";
ESPHOME_LOG_TAG(TAG, "alpha3");
void Alpha3::dump_config() {
ESP_LOGCONFIG(TAG, "ALPHA3");
+1
View File
@@ -1 +1,2 @@
CODEOWNERS = ["@swoboda1337"]
DOMAIN = "am2315c"
+1 -1
View File
@@ -26,7 +26,7 @@
namespace esphome::am2315c {
static const char *const TAG = "am2315c";
ESPHOME_LOG_TAG(TAG, "am2315c");
bool AM2315C::reset_register_(uint8_t reg) {
// code based on demo code sent by www.aosong.com
+1
View File
@@ -0,0 +1 @@
DOMAIN = "am2320"
+1 -1
View File
@@ -10,7 +10,7 @@
namespace esphome::am2320 {
static const char *const TAG = "am2320";
ESPHOME_LOG_TAG(TAG, "am2320");
void AM2320Component::update() {
uint8_t data[8];
+1
View File
@@ -1 +1,2 @@
CODEOWNERS = ["@buxtronix"]
DOMAIN = "am43"
+1 -1
View File
@@ -5,7 +5,7 @@
namespace esphome::am43 {
static const char *const TAG = "am43_cover";
ESPHOME_LOG_TAG(TAG, "am43_cover");
using namespace esphome::cover;
@@ -6,7 +6,7 @@
namespace esphome::am43 {
static const char *const TAG = "am43";
ESPHOME_LOG_TAG(TAG, "am43");
void Am43::dump_config() {
ESP_LOGCONFIG(TAG, "AM43");
@@ -1 +1,2 @@
CODEOWNERS = ["@ianchi"]
DOMAIN = "analog_threshold"
@@ -3,7 +3,7 @@
namespace esphome::analog_threshold {
static const char *const TAG = "analog_threshold.binary_sensor";
ESPHOME_LOG_TAG(TAG, "analog_threshold.binary_sensor");
void AnalogThresholdBinarySensor::setup() {
float sensor_value = this->sensor_->get_state();
+1
View File
@@ -0,0 +1 @@
DOMAIN = "anova"
+1 -1
View File
@@ -5,7 +5,7 @@
namespace esphome::anova {
static const char *const TAG = "anova";
ESPHOME_LOG_TAG(TAG, "anova");
using namespace esphome::climate;
+1
View File
@@ -2,3 +2,4 @@
# https://www.mouser.ca/datasheet/2/678/AVGO_S_A0002854364_1-2574547.pdf
CODEOWNERS = ["@aodrenah"]
DOMAIN = "apds9306"
+1 -1
View File
@@ -7,7 +7,7 @@
namespace esphome::apds9306 {
static const char *const TAG = "apds9306";
ESPHOME_LOG_TAG(TAG, "apds9306");
enum { // APDS9306 registers
APDS9306_MAIN_CTRL = 0x00,
+1
View File
@@ -5,6 +5,7 @@ from esphome.const import CONF_ID
from esphome.types import ConfigType
DEPENDENCIES = ["i2c"]
DOMAIN = "apds9960"
MULTI_CONF = True
CONF_APDS9960_ID = "apds9960_id"
+1 -1
View File
@@ -4,7 +4,7 @@
namespace esphome::apds9960 {
static const char *const TAG = "apds9960";
ESPHOME_LOG_TAG(TAG, "apds9960");
#define APDS9960_ERROR_CHECK(func) \
if (!(func)) { \
+2 -1
View File
@@ -8,6 +8,7 @@ from esphome.automation import Condition
import esphome.codegen as cg
from esphome.components.const import CONF_DESCRIPTION, CONF_HOST
from esphome.components.logger import request_log_listener
from esphome.components.network import DOMAIN as NETWORK_DOMAIN
# ENCRYPTION_SCHEMA and validate_encryption_key are re-exported for external
# components and downstream consumers that import them from api
@@ -514,7 +515,7 @@ def _validate_outgoing_host_ipv6(config: ConfigType) -> ConfigType:
or host.version != 6
):
return config
network_conf = fv.full_config.get().get("network") or {}
network_conf = fv.full_config.get().get(NETWORK_DOMAIN) or {}
if not network_conf.get(CONF_ENABLE_IPV6):
raise cv.Invalid(
"outgoing_connection host is an IPv6 address but IPv6 is not "
+1 -1
View File
@@ -760,7 +760,7 @@ message ListEntitiesLightResponse {
bool legacy_supports_color_temperature = 8 [deprecated=true];
float min_mireds = 9;
float max_mireds = 10;
repeated string effects = 11 [(container_pointer_no_template) = "FixedVector<const char *>"];
repeated string effects = 11 [(container_pointer_no_template) = "light::LightEffectNames"];
bool disabled_by_default = 13;
string icon = 14 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
EntityCategory entity_category = 15;
+2 -11
View File
@@ -91,7 +91,7 @@ static_assert(sizeof(ESPHOME_VERSION) - 1 <= 32, "Update max_data_length for esp
static_assert(ESPHOME_DEVICE_NAME_MAX_LEN <= 31, "Update max_data_length for name in api.proto");
static_assert(ESPHOME_FRIENDLY_NAME_MAX_LEN <= 120, "Update max_data_length for friendly_name in api.proto");
static const char *const TAG = "api.connection";
ESPHOME_LOG_TAG(TAG, "api.connection");
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_WARN
void log_dropped_message(const char *tag, int line, const LogString *what) {
@@ -644,16 +644,7 @@ uint16_t APIConnection::try_send_light_info(EntityBase *entity, APIConnection *c
msg.min_mireds = traits.get_min_mireds();
msg.max_mireds = traits.get_max_mireds();
}
FixedVector<const char *> effects_list;
if (light->supports_effects()) {
auto &light_effects = light->get_effects();
effects_list.init(light_effects.size() + 1);
effects_list.push_back("None");
for (auto *effect : light_effects) {
// c_str() is safe as effect names are null-terminated strings from codegen
effects_list.push_back(effect->get_name().c_str());
}
}
light::LightEffectNames effects_list(light->get_effects());
msg.effects = &effects_list;
return fill_and_encode_entity_info(light, msg, conn, remaining_size);
}
+1 -1
View File
@@ -10,7 +10,7 @@
namespace esphome::api {
static const char *const TAG = "api.frame_helper";
ESPHOME_LOG_TAG(TAG, "api.frame_helper");
// Maximum bytes to log in hex format (168 * 3 = 504, under TX buffer size of 512)
static constexpr size_t API_MAX_LOG_BYTES = 168;
@@ -22,7 +22,7 @@ using noise::noise_err_to_logstr;
static_assert(MAX_HANDSHAKE_SIZE == noise::MAX_HANDSHAKE_SIZE,
"api and noise component handshake size limits must match");
static const char *const TAG = "api.noise";
ESPHOME_LOG_TAG(TAG, "api.noise");
static constexpr char PROLOGUE_INIT[] PROGMEM = "NoiseAPIInit";
static constexpr size_t PROLOGUE_INIT_LEN = 12; // strlen("NoiseAPIInit")
@@ -16,7 +16,7 @@
namespace esphome::api {
static const char *const TAG = "api.plaintext";
ESPHOME_LOG_TAG(TAG, "api.plaintext");
// Maximum bytes to log in hex format (168 * 3 = 504, under TX buffer size of 512)
static constexpr size_t API_MAX_LOG_BYTES = 168;
@@ -15,7 +15,7 @@
namespace esphome::api {
static const char *const TAG = "api.outgoing";
ESPHOME_LOG_TAG(TAG, "api.outgoing");
#ifndef API_OUTGOING_CONNECTION_HOST
static constexpr uint32_t OUTGOING_TARGET_PREF_HASH = 629847102UL;
+4 -4
View File
@@ -688,8 +688,8 @@ uint8_t *ListEntitiesLightResponse::encode_msg(const void *self, uint8_t *__rest
if (uint32_t raw = float_to_raw(msg.max_mireds); raw != 0) [[likely]] {
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 85, raw);
}
for (const char *it : *msg.effects) {
pos = ProtoEncode::encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, 11, it, strlen(it));
for (const auto &it : *msg.effects) {
pos = ProtoEncode::encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, 11, it);
}
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 13, msg.disabled_by_default);
#ifdef USE_ENTITY_ICON
@@ -713,8 +713,8 @@ uint32_t ListEntitiesLightResponse::calc_size_msg(const void *self) {
size += ProtoSize::calc_float(1, msg.min_mireds);
size += ProtoSize::calc_float(1, msg.max_mireds);
if (!msg.effects->empty()) {
for (const char *it : *msg.effects) {
size += ProtoSize::calc_length_force(1, strlen(it));
for (const auto &it : *msg.effects) {
size += ProtoSize::calc_length_force(1, it.size());
}
}
size += ProtoSize::calc_bool(1, msg.disabled_by_default);
+1 -1
View File
@@ -1059,7 +1059,7 @@ class ListEntitiesLightResponse final : public InfoResponseProtoMessage {
const light::ColorModeMask *supported_color_modes{};
float min_mireds{0.0f};
float max_mireds{0.0f};
const FixedVector<const char *> *effects{};
const light::LightEffectNames *effects{};
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer.get_pos() PROTO_ENCODE_DEBUG_ARG);
@@ -15,6 +15,7 @@
#endif
#ifdef USE_LIGHT
#include "esphome/components/light/light_effect_names.h"
#include "esphome/components/light/light_traits.h"
#endif
+1 -1
View File
@@ -6,7 +6,7 @@
namespace esphome::api {
static const char *const TAG = "api.service";
ESPHOME_LOG_TAG(TAG, "api.service");
#ifdef HAS_PROTO_MESSAGE_DUMP
void APIServerConnectionBase::log_send_message_(const LogString *name, const char *dump) {
+1 -1
View File
@@ -23,7 +23,7 @@
namespace esphome::api {
static const char *const TAG = "api";
ESPHOME_LOG_TAG(TAG, "api");
// APIServer
APIServer *global_api_server = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
+1 -1
View File
@@ -11,7 +11,7 @@
namespace esphome::api {
static const char *const TAG = "api.wizard";
ESPHOME_LOG_TAG(TAG, "api.wizard");
#ifdef USE_API_WIZARD_INPUTS
static bool wizard_entity_id_valid(const char *entity_id, size_t length) {
+1 -1
View File
@@ -6,7 +6,7 @@
namespace esphome::api {
static const char *const TAG = "api.proto";
ESPHOME_LOG_TAG(TAG, "api.proto");
uint32_t ProtoSize::varint_slow(uint32_t value) { return varint_wide(value); }
+8 -11
View File
@@ -6,12 +6,12 @@ Home Assistant shows the wizard when the device is added. See api_wizard.h for t
from collections.abc import Callable
import importlib
import json
from types import ModuleType
from typing import Any
from esphome import automation
import esphome.codegen as cg
from esphome.components.const import CONF_DESCRIPTION
from esphome.components.homeassistant import DOMAIN as HOMEASSISTANT_DOMAIN
import esphome.config_validation as cv
from esphome.const import (
CONF_DEVICE_CLASS,
@@ -27,7 +27,12 @@ from esphome.const import (
)
from esphome.core import CORE, ID
import esphome.final_validate as fv
from esphome.helpers import fnv1_hash, fnv1_hash_object_id, fnv1a_32bit_hash
from esphome.helpers import (
fnv1_hash,
fnv1_hash_object_id,
fnv1a_32bit_hash,
zstd_module,
)
from esphome.types import ConfigType
API_DOMAIN = "api"
@@ -261,7 +266,7 @@ def _validate_wizard_input(conf: ConfigType) -> ConfigType:
fv.full_config.get(), conf[CONF_ENTITY]
)
if (
declaration.get(CONF_PLATFORM) != "homeassistant"
declaration.get(CONF_PLATFORM) != HOMEASSISTANT_DOMAIN
or domain not in WIZARD_INPUT_DOMAINS
):
raise cv.Invalid(
@@ -351,14 +356,6 @@ automation.register_apply_condition(
)
def zstd_module() -> ModuleType:
"""The zstd module: the standard library one from Python 3.14, otherwise the backport."""
try:
return importlib.import_module("compression.zstd")
except ImportError:
return importlib.import_module("backports.zstd")
def _entity_document(conf: ConfigType, config: fv.FinalValidateConfig) -> ConfigType:
"""An entity of the device that the page shows, keyed as ListEntitiesResponse keys it."""
_, declaration = _wizard_input_declaration(config, conf[CONF_ID])

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