Compare commits

...

546 Commits

Author SHA1 Message Date
kbx81
70c6021986 Merge branch 'central-netif' into multi-interface-poc
# Conflicts:
#	esphome/components/wifi/wifi_component.cpp
2026-05-23 20:19:32 -05:00
Keith Burzinski
1485675928 Merge branch 'dev' into central-netif 2026-05-23 20:09:33 -05:00
Keith Burzinski
3ed1356bb6 type
Co-authored-by: J. Nick Koston <nick+github@koston.org>
2026-05-23 20:08:08 -05:00
Kevin Ahrendt
5cb145a8c3 [ethernet] Offload W5500 bulk SPI transfers from the busy-wait path (#16596) 2026-05-23 17:53:53 -04:00
Kevin Ahrendt
74001ccf05 [wifi] Wake main loop when requesting high performance mode (#16598) 2026-05-23 17:39:20 -04:00
Kevin Ahrendt
58931f2610 [audio] Add clear_buffered_data method to RingBufferAudioSource (#16594) 2026-05-23 17:37:59 -04:00
Jonathan Swoboda
f616103621 [esp32] Replace per-class -Wno-error=X demotes with blanket -Wno-error for ESP-IDF toolchain (#16599) 2026-05-23 15:44:25 -04:00
J. Nick Koston
188ff7ebfd [bluetooth_proxy] Recover slot stuck in DISCONNECTING when CLOSE_EVT is dropped (#16588) 2026-05-23 14:30:12 -05:00
J. Nick Koston
d6bc4fea1c Merge branch 'dev' into central-netif 2026-05-23 13:34:04 -05:00
Clyde Stubbs
be99553fd4 [ci] Fix flash memory overflow on tests (#16587) 2026-05-23 14:26:53 +10:00
Jonathan Swoboda
b0dc688c14 [esp32] Demote IDF #warning deprecations from error under ESP-IDF toolchain (#16584) 2026-05-22 20:30:25 -04:00
J. Nick Koston
2b422cbd99 [lvgl] Build widget update action schemas lazily (#16569)
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
2026-05-23 00:20:39 +00:00
dependabot[bot]
9930b3c216 Bump github/codeql-action from 4.35.5 to 4.36.0 (#16579)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-22 19:18:31 -05:00
dependabot[bot]
55f4e5cb75 Bump the docker-actions group across 1 directory with 2 updates (#16578)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-22 19:18:20 -05:00
J. Nick Koston
71550bb3be [lvgl] Memoize and lazily build container_schema (#16567) 2026-05-22 18:39:25 -05:00
J. Nick Koston
a58b4edb6a [ci] Gate unconditional CI jobs on a single determine-jobs output instead of a path filter (#16580) 2026-05-22 18:39:06 -05:00
Clyde Stubbs
f85fdb475a [homeassistant] Reduce log spam for sensors (#16555) 2026-05-23 08:07:51 +10:00
dependabot[bot]
4a78c8d45a Bump pytest-codspeed from 5.0.2 to 5.0.3 (#16575)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-22 15:55:49 -05:00
Kevin Ahrendt
c3bef24389 [i2s_audio] Reset dout GPIO when stopping speaker driver (#16573) 2026-05-22 14:43:50 -05:00
J. Nick Koston
7182b1a8ae [uart] Wake main loop on ESP8266 software serial RX (#16562) 2026-05-22 14:30:43 -05:00
J. Nick Koston
64e32ebe04 [esp8266] Use os_timer-based esp_delay() in delay() (#16563) 2026-05-22 14:30:28 -05:00
Edvard Filistovič
94b10981e1 [libretiny] Fix LN882H IRAM_ATTR injection point in patch_linker.py (#16570) 2026-05-22 14:09:32 -05:00
J. Nick Koston
680c9fc9c0 [dashboard] Fix flaky test_websocket_refresh_command on Windows CI (#16565) 2026-05-22 08:49:03 -05:00
dependabot[bot]
99de741f99 Bump docker/build-push-action from 7.1.0 to 7.2.0 in /.github/actions/build-image (#16545)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-22 08:08:29 -05:00
dependabot[bot]
ac530c33b0 Bump actions/stale from 10.2.0 to 10.3.0 (#16544)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-22 08:08:14 -05:00
Kevin Ahrendt
0b5e7ae8fa [sendspin] Bump sendspin-cpp to v0.6.1 (#16553) 2026-05-22 06:43:08 -04:00
kbx81
f818bddac8 Merge remote-tracking branch 'upstream/dev' into multi-interface-poc 2026-05-21 21:39:48 -05:00
kbx81
1f0af903ea feat(ethernet): Unit B + B+ — enable_on_boot lifecycle with lazy-init
Brings ethernet to feature parity with wifi's per-interface lifecycle, and
applies the same lazy-init pattern as wifi's Unit B+ so enable_on_boot:false
genuinely reclaims DMA-capable internal SRAM.

Unit B — lifecycle API surface (mirrors WiFiComponent):
- New `enable_on_boot: true` (default) YAML option on ethernet.
- New set_enable_on_boot(), enable(), disable(), is_disabled(), is_enabled()
  methods on EthernetComponent.
- ESP32 path: enable() calls esp_eth_start(), disable() calls esp_eth_stop().
- RP2040 path: stub methods that log a warning — arduino-pico's
  LwipIntfDev doesn't expose a clean start/stop hook; schema parity only.

Unit B+ — lazy-init refactor (mirrors WiFiComponent::wifi_lazy_init_()):
- New ethernet_lazy_init_() method (idempotent, guarded by
  ethernet_initialized_ flag) holds the entire heavy init body that used to
  live in setup(): SPI bus init, netif creation, MAC/PHY allocation, eth
  driver install, netif attach, event handler registration.
- setup() becomes thin: 300ms power-stabilization delay, then if
  enable_on_boot_=true call lazy_init + esp_eth_start, else mark
  disabled_=true and return.
- enable() calls ethernet_lazy_init_() first, then esp_eth_start() — so a
  runtime enable after enable_on_boot:false works end-to-end.

Safe-default getter guards — external callers (sendspin, ethernet_info,
mdns, etc.) may invoke MAC/IP/duplex queries before/regardless of whether
ethernet is enabled. Without guards these call into esp_eth_ioctl(null, ...)
and esp_netif_get_*(null, ...), producing error spam + erroneous
mark_failed() calls during dump_config():
- get_eth_mac_address_raw() falls back to esp_read_mac(ESP_MAC_ETH) — the
  hardware MAC, same value the driver would have returned.
- get_duplex_mode() returns ETH_DUPLEX_HALF.
- get_link_speed() returns ETH_SPEED_10M.
- get_ip_addresses() returns empty (zero) addresses.
- dump_connect_params_() early-returns with "(uninitialized)" log line.

For a user's reboot-to-toggle workflow with both interfaces declared but
only one active per boot: the inactive interface costs zero DMA-capable
memory. WiFi-side reclaims ~15-30KB DMA-capable, ethernet-side reclaims
~3-8KB (W5500 SPI driver is gentler than wifi).

Field-tested on ESP32-S3 + W5500. Verifies clean dump_config() output and
no false "ethernet was marked as failed" state when ethernet is dormant.
2026-05-21 21:38:45 -05:00
kbx81
ed289390df feat(wifi): Unit B+ — defer esp_wifi_init() to lazy-init
WiFi already had enable_on_boot + enable()/disable()/is_disabled() lifecycle,
but enable_on_boot:false didn't actually save any memory. wifi_pre_setup_()
called esp_wifi_init() and esp_netif_create_default_wifi_sta() unconditionally
during setup(), which allocates ~15-30KB of DMA-capable internal SRAM (RX/TX
buffers, driver state, PHY init). The flag only skipped esp_wifi_start() in
the followup branch — the driver was already resident, just not associated.

This commit splits wifi_pre_setup_() into two parts:

- wifi_pre_setup_() (light, kept in setup() always): MAC setup, event group
  creation, WIFI_EVENT/IP_EVENT handler registration. No DMA allocation.

- wifi_lazy_init_() (heavy, NEW): esp_netif_create_default_wifi_sta()/_ap(),
  esp_wifi_init(), esp_wifi_set_storage(). The DMA-allocating calls.
  Guarded by wifi_initialized_ flag for idempotency.

setup() calls wifi_lazy_init_() only when enable_on_boot_=true. The else
branch sets WIFI_COMPONENT_STATE_DISABLED without any heavy init — the
dormant interface costs zero DMA-capable memory.

enable() calls wifi_lazy_init_() before start(), so a runtime enable after
boot-time disable does the heavy init on demand. Idempotent — subsequent
enable/disable cycles don't re-allocate.

disable() is unchanged — it stops wifi but doesn't deinit. A future
"release_on_disable" variant could call esp_wifi_deinit() to actually free
the memory at runtime, but that requires coordinating with consumers
holding wifi-bound sockets and is out of scope here.

ESP-IDF only. Other platforms (Arduino on ESP32, ESP8266) keep the existing
behavior — their wifi_pre_setup_() lives in different per-platform files.

Field-tested on ESP32-S3 with W5500 SPI ethernet + audio + bluetooth_proxy.
Before Unit B+: ~14KB free internal during peak load, crash on W5500 SPI
DMA buffer allocation. After Unit B+: ~32KB free internal, Min Free 78KB
in some test configurations — sufficient headroom for the other DMA
consumers (I2S audio, BT controller) to operate.
2026-05-21 21:32:38 -05:00
kbx81
8f3010ac64 feat(network): Unit A — explicit default-route management
Builds on PR #14012's NetworkComponent + PR #14255's priority list to make
the user's stated interface priority actually drive runtime default-route
selection. Without this, ESP-IDF's auto-selection picks the default netif by
each netif's hardcoded `route_prio` field (WiFi STA = 100, Ethernet = 50,
WiFi AP = 10) — which inverts the user's intent on same-subnet
multi-homing configurations where wifi+ethernet share a broadcast domain.

Changes:

- NetworkComponent gains an IP_EVENT handler registered in setup() that
  re-arbitrates the default netif on every interface up/down. The handler
  walks the priority list in order, picks the highest-priority netif that
  is up, and calls esp_netif_set_default_netif() on it. ESP-IDF then sets
  its internal "manual override" flag so subsequent auto-selection events
  don't undo our choice.
- New StaticVector<NetworkPriorityEntry, 4> stores the priority list with
  zero heap allocation. The interface-name string pointer is a YAML literal
  with static storage duration.
- The timeout_ms field is parsed and stored but not yet consumed by Unit A;
  it's wired up for Unit D (runtime timeout fallback).
- New getters get_active_interface() / get_active_netif() expose the
  currently-active interface for Unit C consumers.
- Python codegen iterates CORE.data[KEY_NETWORK_PRIORITY] and emits
  add_priority_entry() calls per YAML order.

Field-tested on ESP32-S3 with W5500 SPI ethernet + WiFi STA on the same
subnet. The log line "[network] Default interface: <name>" confirms the
arbitration logic fires correctly on IP_EVENT_*_GOT_IP.

Standalone — no schema changes, single-interface configs unaffected.
2026-05-21 21:29:47 -05:00
Jesse Hills
0b2eb6481f [light] Add light.effect.next / light.effect.previous actions (#16491) 2026-05-22 13:42:50 +12:00
Jesse Hills
1d3eea098e [core] Support YAML frontmatter for arbitrary user metadata (#16552) 2026-05-22 13:00:22 +12:00
dependabot[bot]
4ff8eb4b15 Bump ruff from 0.15.13 to 0.15.14 (#16543)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-21 22:08:56 +00:00
J. Nick Koston
aea1e4d136 [core] Refresh compiled config cache after upload/logs fallback (#16548) 2026-05-21 17:05:17 -05:00
Jonathan Swoboda
38b8b41ccc [sx126x] Assert NSS before wait_busy so commands wake the chip from sleep (#16546) 2026-05-21 18:03:07 -04:00
J. Nick Koston
96eced0378 [api] Break api_connection/api_server include cycle to drop custom unique_ptr deleter (#16542) 2026-05-21 15:42:57 -05:00
Jonathan Swoboda
1ea95264bd [tuya] Restore null guard on status_pin lost in #16353 (#16539) 2026-05-21 18:08:09 +00:00
Jonathan Swoboda
d2bda0a402 [esp32] Defer esp_panic_handler wrap so arduino-esp32 IDF component skips it (#16538) 2026-05-21 14:03:55 -04:00
Jonathan Swoboda
56fd77e4c8 [espidf] Honor the dict shorthand for library.json dependencies (#16537) 2026-05-21 13:01:54 -05:00
Jonathan Swoboda
3719ea740a [espidf] Default to remote HEAD when cg.add_library URL has no #ref (#16535) 2026-05-21 13:01:19 -05:00
Jonathan Swoboda
750ae56778 [espidf] Backport ninja linux-arm64 entry into tools.json on aarch64 hosts (#16527) 2026-05-21 12:05:27 -04:00
Kevin Ahrendt
01494f7431 [audio] Bump esp-audio-libs to v3.1.0 (#16519) 2026-05-21 11:57:32 -04:00
J. Nick Koston
233a60f106 [ci] Pin uv version in setup-uv to fix Windows manifest fetch flake (#16534) 2026-05-21 10:53:34 -05:00
Jonathan Swoboda
e0076cb1a8 [core] Persist & restore CORE.toolchain through StorageJSON (#16531) 2026-05-21 10:37:46 -05:00
Jonathan Swoboda
b619e3e8c7 [espidf] Write version.txt after extract so bootloader shows the real version (#16532) 2026-05-21 10:37:10 -05:00
Jonathan Swoboda
f2bfe5cd17 [espidf] Fix tarfile extract crashing on Python 3.11 with None mode (#16530) 2026-05-21 10:36:27 -05:00
Jonathan Swoboda
90715373f2 [espidf] Filter noisy 'git rev-parse' errors when .git is stripped (#16521) 2026-05-21 10:35:51 -05:00
Jonathan Swoboda
52e7d3ccfb [esp32] Use new sdkconfig key names that replaced deprecated ones (#16522) 2026-05-21 10:35:25 -05:00
dependabot[bot]
a70e358cea Bump zeroconf from 0.149.13 to 0.149.16 (#16533)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-21 09:55:28 -05:00
dependabot[bot]
43a1c2067e Bump zeroconf from 0.149.12 to 0.149.13 (#16520)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-21 08:28:09 -05:00
kbx81
9d9af645ac Merge remote-tracking branch 'upstream/dev' into multi-interface-poc 2026-05-20 23:52:07 -05:00
Jesse Hills
11760307f7 Merge branch 'release' into dev 2026-05-21 13:49:17 +12:00
Jesse Hills
15c546b809 Merge pull request #16523 from esphome/bump-2026.5.0
2026.5.0
2026-05-21 13:48:28 +12:00
Jesse Hills
104c8bed41 Bump version to 2026.5.0 2026-05-21 11:16:58 +12:00
Jesse Hills
49bfa12eb7 Merge branch 'beta' into dev 2026-05-21 10:14:14 +12:00
Jesse Hills
ca859de212 Merge pull request #16518 from esphome/bump-2026.5.0b4
2026.5.0b4
2026-05-21 10:13:39 +12:00
Jesse Hills
de783e72d5 Bump version to 2026.5.0b4 2026-05-21 09:10:52 +12:00
Jonathan Swoboda
cd7e2d79c4 [esp32] Decouple esp-idf toolchain version check from PIO, honor framework source: override (#16516) 2026-05-21 09:10:52 +12:00
Jonathan Swoboda
ecf823b871 [espidf] Drop version field from generated idf_component.yml (#16511) 2026-05-21 09:10:52 +12:00
dependabot[bot]
9fdad68138 Bump aioesphomeapi from 45.0.3 to 45.0.4 (#16513)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-21 09:10:51 +12:00
dependabot[bot]
b79a306d02 Bump zeroconf from 0.149.7 to 0.149.12 (#16510)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-21 09:10:51 +12:00
Jonathan Swoboda
870f628637 [esp32] Decouple esp-idf toolchain version check from PIO, honor framework source: override (#16516) 2026-05-20 20:40:59 +00:00
Jonathan Swoboda
52c9a2d07b [espidf] Drop version field from generated idf_component.yml (#16511) 2026-05-20 14:31:58 -04:00
Jonathan Swoboda
60afad442c [esp32] Fix sdkconfig int values silently clamped to default (#16515) 2026-05-20 13:36:18 -04:00
dependabot[bot]
fbe212944b Bump aioesphomeapi from 45.0.3 to 45.0.4 (#16513)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-20 10:51:53 -05:00
dependabot[bot]
8927ade789 Bump zeroconf from 0.149.7 to 0.149.12 (#16510)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-20 15:40:20 +00:00
Rapsssito
9bfae9e782 Remove redundant esp_netif_init 2026-05-20 09:07:57 +02:00
kbx81
eb64707d94 fix(network): lower NETWORK_PRIORITY_BASE below NetworkComponent's own priority
PR #14255 sets NETWORK_PRIORITY_BASE = 300.0, but PR #14012's
NetworkComponent uses setup_priority::AFTER_BLUETOOTH = 300.0f. When the
highest-priority interface (first in the priority list) tied with
NetworkComponent at 300, the runtime tie-break was determined by
registration order — and NetworkComponent registers AFTER ethernet (its
codegen runs at CoroPriority.NETWORK_SERVICES = 55, below COMMUNICATION
= 60 used by ethernet/wifi).

Result: ethernet's setup() ran before NetworkComponent::setup(),
esp_netif_init() had not yet been called, esp_netif_new() returned
NULL, and EthernetComponent::setup() dereferenced NULL in
esp_netif_attach() — LoadProhibited crash at boot.

Drop the base to 250.0 (matches the historical setup_priority::WIFI /
::ETHERNET default, so a single-entry priority list behaves identically
to a no-priority-block config) and shrink the step to 5.0 to keep all
interfaces in the same priority band, above BEFORE_CONNECTION (220.0)
and below AFTER_BLUETOOTH (300.0).
2026-05-19 23:16:01 -05:00
kbx81
7814e99b6f fix(network): enable USE_SETUP_PRIORITY_OVERRIDE when priority is configured
PR #14255 generates calls to Component::set_setup_priority(float) from
ethernet/wifi to_code(), but that method's body in core/component.cpp is
gated by #ifdef USE_SETUP_PRIORITY_OVERRIDE. Without the define the
declaration exists but no implementation is linked, producing:

  undefined reference to `esphome::Component::set_setup_priority(float)`

The existing convention in cpp_helpers.register_component() is to add
the define whenever CONF_SETUP_PRIORITY appears in a component's YAML.
Mirror that here: when the user declares `network: priority:`, the
priority-driven setup_priority overrides will be emitted, so the define
must be on.
2026-05-19 23:10:32 -05:00
kbx81
8ad6813d44 Merge PR #14255: network priority
Resolves conflicts with PR #14012 (centralized netif init):
- wifi_component_esp_idf.cpp: dropped pr-14255's ESP_ERR_INVALID_STATE
  tolerance hunk (made moot by #14012 removing the call entirely).
- ethernet/__init__.py: kept dev's refactored _to_code_esp32 structure;
  added pr-14255's priority lookup and conditional CONFIG_ESP_WIFI_ENABLED
  gating; preserved dev's top-level import shape.
- network/__init__.py: merged CONF_ID import (#14012) with CONF_PRIORITY
  + CONF_TIMEOUT imports (pr-14255).

Also fixed two latent bugs in pr-14255 where `"wifi" in net_priority`
compared a string against a list of dicts (always False). Replaced with
set comprehension over the normalized interface names.
2026-05-19 22:45:14 -05:00
kbx81
1aa0a489f6 Merge PR #14012: centralize ESP32 network init 2026-05-19 22:37:40 -05:00
Jesse Hills
63fe977adb Merge branch 'beta' into dev 2026-05-20 14:34:33 +12:00
Jesse Hills
94badfcb19 Merge pull request #16507 from esphome/bump-2026.5.0b3
2026.5.0b3
2026-05-20 14:33:57 +12:00
Jesse Hills
19c4da2aa5 Bump version to 2026.5.0b3 2026-05-20 12:53:26 +12:00
Kevin Ahrendt
e4c8d1f430 [sendspin] Bump sendspin to v0.6.0 (#16496) 2026-05-20 12:53:26 +12:00
Kevin Ahrendt
302938f875 [i2s_audio] Optimize SPDIF encoder and suport higher bit depth audio (#16504)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2026-05-20 12:53:26 +12:00
Jonathan Swoboda
65e1e210de [espidf] Print RAM summary on ESP32-S3 / unified-DIRAM variants (#16494) 2026-05-20 12:53:26 +12:00
luar123
43cc9fc879 [zigbee] don't allow zigbee + thread or access point (#16499) 2026-05-20 12:53:25 +12:00
Kevin Ahrendt
41ad2ba763 [i2s_audio] Compute ring buffer size with SPDIF sample count (#16400) 2026-05-20 12:53:25 +12:00
Brandon Harvey
25739091da [sen6x] Remove incorrect AQI device class from VOC and NOx Index sensors (#16465) 2026-05-20 12:53:25 +12:00
Brandon Harvey
bbf5fe8450 [sgp4x] Remove incorrect AQI device class from VOC and NOx Index sensors (#16464) 2026-05-20 12:53:25 +12:00
Brandon Harvey
e9ef58d99d [sen5x] Remove incorrect AQI device class from VOC and NOx Index sensors (#16463) 2026-05-20 12:53:25 +12:00
dependabot[bot]
e1793a1eff Bump zeroconf from 0.149.3 to 0.149.7 (#16492)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-20 12:53:25 +12:00
Jesse Hills
9bb70d568d [ci] Move ha-addon and schema release triggers to version-notifier (#16490) 2026-05-20 12:53:25 +12:00
Keith Burzinski
be3ccd29f6 Merge branch 'dev' into central-netif 2026-05-19 18:03:15 -05:00
Kevin Ahrendt
0912122634 [sendspin] Bump sendspin to v0.6.0 (#16496) 2026-05-19 15:16:00 -04:00
Kevin Ahrendt
9924d998f1 [i2s_audio] Optimize SPDIF encoder and suport higher bit depth audio (#16504)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2026-05-19 13:37:41 -05:00
dependabot[bot]
e979d461f0 Bump codecov/codecov-action from 6.0.0 to 6.0.1 (#16500)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-19 12:15:50 -05:00
J. Nick Koston
863af482ec [esp32_ble_server] Honor client offset and MTU in long reads (#16458) 2026-05-19 12:14:15 -05:00
J. Nick Koston
80ed541032 [core] Add progmem_memcpy HAL helper (#16470) 2026-05-19 12:13:58 -05:00
Jonathan Swoboda
1d0ddfac5d [espidf] Print RAM summary on ESP32-S3 / unified-DIRAM variants (#16494) 2026-05-19 12:57:18 -04:00
luar123
c0e71fc713 [zigbee] don't allow zigbee + thread or access point (#16499) 2026-05-19 12:53:36 -04:00
Rodrigo Martín
73b8491936 Update esphome/components/network/network_component.h
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2026-05-19 17:50:02 +02:00
Rapsssito
1332ebe729 Exclude from non ESP32 devices 2026-05-19 09:20:08 +02:00
Kevin Ahrendt
7ecfe4b5c9 [i2s_audio] Compute ring buffer size with SPDIF sample count (#16400) 2026-05-18 21:53:19 -05:00
kbx81
028a54422e preen 2026-05-18 18:31:31 -05:00
kbx81
de53e7a6b1 preen 2026-05-18 18:24:54 -05:00
Brandon Harvey
36fc36071d [sen6x] Remove incorrect AQI device class from VOC and NOx Index sensors (#16465) 2026-05-19 11:20:08 +12:00
Brandon Harvey
cb581271ed [sgp4x] Remove incorrect AQI device class from VOC and NOx Index sensors (#16464) 2026-05-19 11:19:51 +12:00
Brandon Harvey
b0af4a9f0d [sen5x] Remove incorrect AQI device class from VOC and NOx Index sensors (#16463) 2026-05-19 11:19:48 +12:00
kbx81
0d1d00b654 Merge branch 'dev' into central-netif 2026-05-18 18:19:46 -05:00
dependabot[bot]
edb59476b1 Bump zeroconf from 0.149.3 to 0.149.7 (#16492)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-17 23:29:03 -07:00
Jesse Hills
9c696f5de1 [ci] Move ha-addon and schema release triggers to version-notifier (#16490) 2026-05-18 15:56:44 +12:00
Jesse Hills
6804965bd8 Merge branch 'beta' into dev 2026-05-18 15:31:01 +12:00
Jesse Hills
213df0412d Merge pull request #16488 from esphome/bump-2026.5.0b2
2026.5.0b2
2026-05-18 15:28:53 +12:00
Jesse Hills
cdf74c180e Bump version to 2026.5.0b2 2026-05-18 11:11:54 +12:00
Jonathan Swoboda
df31c72e4e [espidf] Switch direct framework downloader to esphome-libs/esp-idf tarballs (#16484) 2026-05-18 11:11:54 +12:00
dependabot[bot]
4f188bf9bb Bump zeroconf from 0.148.0 to 0.149.3 (#16480)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-18 11:11:54 +12:00
dependabot[bot]
20f92ad5e9 Bump aioesphomeapi from 45.0.2 to 45.0.3 (#16479)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-18 11:11:54 +12:00
J. Nick Koston
f301e90fd9 [ci] Use larger app partition for esp32-s3-idf component test grouping (#16430) 2026-05-18 11:11:54 +12:00
dependabot[bot]
2dbaaf1efd Bump aioesphomeapi from 45.0.1 to 45.0.2 (#16469)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-18 11:11:54 +12:00
Clyde Stubbs
da237b5070 [lvgl] Fix image define (#16468) 2026-05-18 11:11:54 +12:00
Clyde Stubbs
6a8f24b951 [ft5x06] Fix setting calibration values (#16446) 2026-05-18 11:11:54 +12:00
dependabot[bot]
26907f17f5 Bump aioesphomeapi from 45.0.0 to 45.0.1 (#16467)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-18 11:11:54 +12:00
Jonathan Swoboda
c6a74222f1 [esp32_hosted][fingerprint_grow] Fix two remaining ESP32 toolchain warnings (#16442) 2026-05-18 11:11:54 +12:00
J. Nick Koston
5ec0879a10 [core] Fix KeyError: 'esp32' on upload when validated-config cache is used (#16457) 2026-05-18 11:11:54 +12:00
J. Nick Koston
50495c7085 [wifi] Refuse to compile when wifi_ssid is the device-builder placeholder (#16444) 2026-05-18 11:11:54 +12:00
Kevin Ahrendt
25dbef83de [sound_level] Use RingBufferAudioSource (#16436) 2026-05-18 11:11:54 +12:00
Kevin Ahrendt
4f895425ca [audio] Bump microMP3 to v0.2.1 (#16429) 2026-05-18 11:11:54 +12:00
Jonathan Swoboda
c037058c19 [esp32_hosted] Bump esp_hosted to 2.12.7 (#16440) 2026-05-18 11:11:54 +12:00
Jonathan Swoboda
ecac6b64ec [espidf] Gate esp_idf_size --ng on IDF version (#16441) 2026-05-18 11:11:54 +12:00
Jonathan Swoboda
3831aa809f [multiple] Fix -Wformat= mismatches in component .cpp sources (#16433) 2026-05-18 11:11:54 +12:00
Jonathan Swoboda
da8286f554 [docker] Install libusb-1.0 so ESP-IDF tools can validate openocd (#16424)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-18 11:11:54 +12:00
Jonathan Swoboda
d5c6efb2fe [tests] Fix -Wformat= mismatches in test YAML lambdas/logger.log (#16435) 2026-05-18 11:11:54 +12:00
Jonathan Swoboda
dd1818661c [esp32] Sweep ESP-IDF toolchain warnings + bump deprecated mark_failed (#16432) 2026-05-18 11:11:53 +12:00
Keith Burzinski
fb659f9ac4 [tinyusb] Reject logger.hardware_uart: USB_CDC (#16417)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 11:11:53 +12:00
Keith Burzinski
ab273a1f8f [tinyusb] Reject tinyusb: configured without a USB class companion (#16413)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 11:11:53 +12:00
Jonathan Swoboda
84b5931299 [espidf] Trim has_outdated_files watch list; embed IDF version in sdkconfig (#16416) 2026-05-18 11:11:53 +12:00
Jonathan Swoboda
c863d58999 [espidf] Stop perpetual reconfigure loop on native ESP-IDF builds (#16415) 2026-05-18 11:11:53 +12:00
Jesse Hills
42ad2a6272 [espidf] Accept list input in _str_to_lst_of_str helper (#16485) 2026-05-18 10:49:03 +12:00
Jonathan Swoboda
6690725860 [espidf] Switch direct framework downloader to esphome-libs/esp-idf tarballs (#16484) 2026-05-18 07:29:38 +12:00
dependabot[bot]
155232875a Bump zeroconf from 0.148.0 to 0.149.3 (#16480)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-16 19:08:19 -07:00
dependabot[bot]
01c0d3163e Bump aioesphomeapi from 45.0.2 to 45.0.3 (#16479)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-16 18:41:09 -07:00
J. Nick Koston
7c5d5f75dc [ci] Use larger app partition for esp32-s3-idf component test grouping (#16430) 2026-05-15 22:16:52 -07:00
dependabot[bot]
fb0bfea1c8 Bump aioesphomeapi from 45.0.1 to 45.0.2 (#16469)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-15 22:06:33 -07:00
J. Nick Koston
48d17571c8 [tests] Mock determine_cpp_unit_tests in clang_tidy_mode tests (#16456) 2026-05-15 15:50:58 -07:00
Clyde Stubbs
df100681e0 [lvgl] Fix image define (#16468) 2026-05-15 22:36:53 +00:00
Clyde Stubbs
1a287bf785 [ft5x06] Fix setting calibration values (#16446) 2026-05-16 10:30:04 +12:00
dependabot[bot]
ff34e1061b Bump resvg-py from 0.3.1 to 0.3.2 (#16466)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-15 14:43:08 -07:00
dependabot[bot]
b78b78cbbb Bump aioesphomeapi from 45.0.0 to 45.0.1 (#16467)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-15 14:42:51 -07:00
dependabot[bot]
4c090c6b85 Bump github/codeql-action from 4.35.4 to 4.35.5 (#16461)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-15 12:37:56 -07:00
dependabot[bot]
ec6669fa67 Bump requests from 2.34.1 to 2.34.2 (#16460)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-15 12:37:41 -07:00
dependabot[bot]
59f8c1019f Bump pytest-codspeed from 5.0.1 to 5.0.2 (#16459)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-15 12:37:28 -07:00
david-collett
fb70095ba1 [esp32_ble_server] Fix incorrect BLECharacteristic read truncation (#16420) (#16422)
Co-authored-by: Dave <dave@morty>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-05-15 10:47:26 -07:00
Jonathan Swoboda
65d6bb18ed [esp32_hosted][fingerprint_grow] Fix two remaining ESP32 toolchain warnings (#16442) 2026-05-15 17:32:51 +00:00
J. Nick Koston
47eb2adbf2 [core] Fix KeyError: 'esp32' on upload when validated-config cache is used (#16457) 2026-05-15 10:29:15 -07:00
J. Nick Koston
35631be260 [writer] Mark storage_should_clean as public API for device-builder (#16443) 2026-05-15 10:20:31 -07:00
J. Nick Koston
96106d25bc [wifi] Refuse to compile when wifi_ssid is the device-builder placeholder (#16444) 2026-05-15 10:20:15 -07:00
J. Nick Koston
1674ed9744 [ci] Use uv for pip installs across CI workflows (#16451) 2026-05-15 10:18:27 -07:00
J. Nick Koston
46be0f4f62 [ci] Log top 30 pytest durations (#16455) 2026-05-15 10:18:07 -07:00
J. Nick Koston
ec1826a6ed [yaml_util] Promote include-discovery helper, share it with bundle (#16447) 2026-05-15 10:17:50 -07:00
Simone Chemelli
8b3bc47547 [uptime] Update device_class for Uptime sensor (#16434)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-05-15 17:16:01 +00:00
J. Nick Koston
4381a8baaa [ci] pr-title-check: skip all bot authors, not just dependabot (#16453) 2026-05-15 09:59:35 -07:00
esphome[bot]
4189979391 Synchronise Device Classes from Home Assistant (#16452)
Co-authored-by: esphomebot <esphome@openhomefoundation.org>
2026-05-15 09:57:49 -07:00
J. Nick Koston
1b1e21d470 [ci] sync-device-classes: drop branch-switch hack, skip no-commit-to-branch instead (#16450) 2026-05-15 09:54:01 -07:00
J. Nick Koston
5b6c54c961 [ci] sync-device-classes: use uv for installs and skip pylint (#16449) 2026-05-15 09:45:11 -07:00
Jonathan Swoboda
ff968a4629 [ci] Fix sync-device-classes workflow (failing daily for weeks) (#16448) 2026-05-15 09:36:01 -07:00
Edward Firmo
d832ce51cd [nextion] Replace connect_info vector with fixed-size field parser, always log device info (#16059)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-05-14 22:42:10 -05:00
Kevin Ahrendt
d663d80fde [sound_level] Use RingBufferAudioSource (#16436) 2026-05-14 20:33:36 -07:00
Kevin Ahrendt
c5c627d534 [audio] Bump microMP3 to v0.2.1 (#16429) 2026-05-14 20:31:11 -07:00
Jonathan Swoboda
d046dd7276 [esp32_hosted] Bump esp_hosted to 2.12.7 (#16440) 2026-05-14 22:51:14 -04:00
Jonathan Swoboda
56983f414f [espidf] Gate esp_idf_size --ng on IDF version (#16441) 2026-05-14 22:41:36 -04:00
Jonathan Swoboda
a92b607754 [ci] Add ci-run-all label to force full CI matrix (#16421) 2026-05-14 18:54:13 -04:00
Jonathan Swoboda
313d974983 [multiple] Fix -Wformat= mismatches in component .cpp sources (#16433) 2026-05-14 18:53:42 -04:00
Jonathan Swoboda
1d86d856d1 [docker] Install libusb-1.0 so ESP-IDF tools can validate openocd (#16424)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-14 15:51:59 -07:00
Jonathan Swoboda
1bb191aa77 [ci] Skip dashboard-deprecation bot on release/beta-bump PRs (#16427) 2026-05-14 15:51:36 -07:00
dependabot[bot]
5d9d6e83f7 Bump ruff from 0.15.12 to 0.15.13 (#16437)
Signed-off-by: dependabot[bot] <support@github.com>
2026-05-14 15:41:32 -07:00
Jonathan Swoboda
f3d7743460 [tests] Fix -Wformat= mismatches in test YAML lambdas/logger.log (#16435) 2026-05-14 18:40:40 -04:00
Jonathan Swoboda
f291dc8d2f [esp32] Sweep ESP-IDF toolchain warnings + bump deprecated mark_failed (#16432) 2026-05-14 18:39:16 -04:00
Jonathan Swoboda
a8e69a15e4 [clang-tidy] Enable readability-container-contains (#16438) 2026-05-14 18:38:09 -04:00
Keith Burzinski
7436d1c199 [tinyusb] Reject logger.hardware_uart: USB_CDC (#16417)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 20:29:56 +00:00
Keith Burzinski
348b92910e [tinyusb] Reject tinyusb: configured without a USB class companion (#16413)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 15:07:38 -05:00
Jonathan Swoboda
f89a6f4f9c [espidf] Trim has_outdated_files watch list; embed IDF version in sdkconfig (#16416) 2026-05-14 04:02:22 +00:00
Jesse Hills
c3ee962b83 Merge branch 'beta' into dev 2026-05-14 15:25:38 +12:00
Jesse Hills
59847d56e8 Merge pull request #16411 from esphome/bump-2026.5.0b1
2026.5.0b1
2026-05-14 15:24:58 +12:00
Jonathan Swoboda
e593cb6efc [espidf] Stop perpetual reconfigure loop on native ESP-IDF builds (#16415) 2026-05-13 23:19:30 -04:00
J. Nick Koston
d2107e40c8 [ci] Prohibit curly braces in PR titles for MDX safety (#16412) 2026-05-14 14:03:45 +12:00
Jesse Hills
09a926fa13 Bump version to 2026.5.0b1 2026-05-14 12:33:43 +12:00
Jesse Hills
78b60ac6fa Bump version to 2026.6.0-dev 2026-05-14 12:33:43 +12:00
Jonathan Swoboda
a3b6f92433 [espidf] Regenerate bundled CMakeLists; auto-REQUIRE via IDF build properties (#16406) 2026-05-13 23:58:48 +00:00
dependabot[bot]
06786da7dd Bump actions/create-github-app-token from 3.1.1 to 3.2.0 (#16409)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-13 16:28:47 -07:00
Jonathan Swoboda
910cc38dd7 [writer] Clean ESP-IDF build artifacts in clean_build (#16410) 2026-05-13 19:25:35 -04:00
dependabot[bot]
c8aba6913b Bump requests from 2.34.0 to 2.34.1 (#16408)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-13 15:38:13 -05:00
Boris Krivonog
ce8810bc42 [mitsubishi_cn105] Add vane and wide-vane support (#16405) 2026-05-13 13:25:32 -05:00
Jonathan Swoboda
1c6966b761 [espidf] Run PIO extraScript with SCons-env shim (#16404) 2026-05-13 13:07:59 -04:00
J. Nick Koston
03f5e4775c [tests] Add CodSpeed benchmark for compiled-config cache fast path (#16402)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-05-13 12:06:20 -05:00
Boris Krivonog
445d841229 [mitsubishi_cn105] Simplified protocol lookups (#16399) 2026-05-13 16:49:32 +00:00
Jonathan Swoboda
d7b00047bd [espidf] Emit -W warning flags at project scope so managed components also see them (#16403) 2026-05-13 12:27:06 -04:00
Jonathan Swoboda
3fee97ae5a [espidf] Partition pio_components cache by framework (#16401) 2026-05-13 12:08:51 -04:00
J. Nick Koston
cb520cda6b [core] Retry PlatformIO downloads on transport-layer errors (#16397) 2026-05-13 10:01:42 -05:00
J. Nick Koston
8bce32ec35 [tests] Cover top-level !include failure path in track_yaml_loads (#16396) 2026-05-13 10:01:26 -05:00
J. Nick Koston
b866525437 [ci] Skip native ESP-IDF compile test when no relevant files changed (#16395) 2026-05-13 10:01:11 -05:00
J. Nick Koston
0e4922a340 [core] Cache validated config to skip re-validation on upload/logs (#16381) 2026-05-13 22:14:19 +12:00
Boris Krivonog
45a4811bb4 [mitsubishi_cn105] Unified timeout handling (#16385) 2026-05-13 01:40:19 -05:00
Dmitrii Kuminov
65ea29b44a [core] Fix !include vars not being substituted in !lambda values (#16320)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-05-12 22:41:30 -05:00
Keith Burzinski
480c23012c [radio_frequency] Add on_control trigger; ir_rf_proxy driver-agnostic (#16368)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 22:13:29 -05:00
Jonathan Swoboda
1dfd3fe9c2 [esp32] Print PlatformIO-format RAM/Flash summary after native ESP-IDF builds (#16394)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-12 22:52:11 -04:00
Michael Hansen
f94735dc62 [api][voice_assistant] Add second audio channel for voice_assistant (#16265)
Co-authored-by: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-05-13 13:38:39 +12:00
Kevin Ahrendt
65b53692bd [i2s_audio] Properly track DMA input/output (#16317) 2026-05-12 20:36:26 -05:00
Kevin Ahrendt
3df0527c1f [audio] Document ring buffer source thread safety (#16393) 2026-05-13 00:10:32 +00:00
Mat931
dc95b22c76 [safe_mode] Allow recovering soft-bricked devices via reboot to recovery partition (#16339)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-05-13 12:07:49 +12:00
Jonathan Swoboda
1c2043e054 [esp32] Relax -Werror=reorder and -Werror=maybe-uninitialized on native ESP-IDF (#16392) 2026-05-12 20:04:54 -04:00
Kevin Ahrendt
7f37ee3c53 [mixer] Use RingBufferAudioSource (#16316) 2026-05-12 23:58:32 +00:00
Kevin Ahrendt
8b6cbc9f2b [i2s_audio] Speaker uses new RingBufferAudioSource (#16315)
Thanks!
2026-05-12 23:58:03 +00:00
George Galt
531367d7e1 [micro_wake_word] Increase INFERENCE_TASK_STACK_SIZE to 8192 for P4 chip (#16390) 2026-05-12 19:47:54 -04:00
Jesse Hills
cb2dbcd70d [ci] Add validate.*.yaml for config-only component tests (#16384) 2026-05-13 11:37:33 +12:00
Kevin Ahrendt
45a8bd49c3 [audio] Add a RingBufferAudioSource (#16314) 2026-05-12 19:33:03 -04:00
Jonathan Swoboda
9195b9898e [ms8607] Pin humidity i2c_id in test fixture (#16386) 2026-05-12 18:20:09 -05:00
dependabot[bot]
aec48cf231 Bump aioesphomeapi from 44.24.2 to 45.0.0 (#16391)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-12 23:19:07 +00:00
Jonathan Swoboda
907ae46aba [zigbee] Fix init-order and missing-field warnings on native ESP-IDF (#16389) 2026-05-12 19:13:04 -04:00
Jesse Hills
057fc4c1a8 Move AI instructions to AGENTS.md (#16382) 2026-05-13 09:19:27 +12:00
Cody Cutrer
76d3433425 [cli] Add config-hash command (#15548)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-05-12 20:43:48 +00:00
Kevin Ahrendt
b512cc42a8 [sendspin] Updates sendspin-cpp to v0.5.0 (#16380) 2026-05-12 16:42:44 -04:00
Boris Krivonog
66e4a1dfa8 [mitsubishi_cn105] Add C++ API for setting/clearing remote room temperature (#15558)
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-05-12 15:39:21 -05:00
Kevin Ahrendt
ee72efa760 [sendspin] Fix client_id MAC mismatch with ethernet (#16331) 2026-05-12 16:27:25 -04:00
J. Nick Koston
f54480ec48 [rp2040] Bump arduino-pico framework to 5.6.0 (#16375) 2026-05-12 15:20:25 -05:00
J. Nick Koston
34f69e0d6e [ci] Comment on PRs that touch the legacy dashboard (#16378) 2026-05-12 14:42:23 -05:00
dependabot[bot]
57893a8eb1 Bump aioesphomeapi from 44.23.0 to 44.24.2 (#16376)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-12 19:37:31 +00:00
tomaszduda23
c511dddf2a [core] allow defining run_compile in external_components (#16179)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-12 14:59:54 -04:00
Jesse Hills
76ce45c59e [script] Preserve source order of enum options in language schema (#16371) 2026-05-13 06:28:39 +12:00
J. Nick Koston
727c74da3f [script] Fix array-type parameters in script.execute (#16374) 2026-05-12 12:17:23 -05:00
Jonathan Swoboda
365ed19319 [core] Fix PROGMEM_STRING_TABLE placement on ESP8266 without flash log strings (#16373) 2026-05-12 11:19:10 -04:00
Clyde Stubbs
4ff946ac15 [cli] Add --no-states flag to run command (#16366) 2026-05-12 07:52:07 -04:00
Mat931
b5e50144e3 [ota] Improve OTA error messages (#16327)
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>
Co-authored-by: J. Nick Koston <nick+github@koston.org>
2026-05-12 02:32:58 +00:00
dependabot[bot]
49df1bd30e Bump actions/cache from 5.0.3 to 5.0.5 (#16365)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-12 02:18:06 +00:00
dependabot[bot]
7dce58c58d Bump requests from 2.33.1 to 2.34.0 (#16364)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-12 02:17:42 +00:00
Clyde Stubbs
a232aedebd [lvgl] Check for user defined LV_USE items (#16362) 2026-05-12 12:09:42 +10:00
Clyde Stubbs
4e31b71304 [lvgl] Add new trigger on_update and new number option (#16312) 2026-05-12 08:52:33 +10:00
J. Nick Koston
55ef66cc26 [helpers] Re-enable ProgressBar under --dashboard mode (#16357) 2026-05-11 13:12:55 -05:00
luar123
e479e8b641 [zigbee] Add power_source option to esp32 (#16062)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-05-11 14:08:52 -04:00
luar123
ee8ca2a3bf [zigbee] add on_join trigger for esp32 (#16060)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
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-05-11 11:54:35 -04:00
J. Nick Koston
a52ca4f80a [ota] Implement host platform OTA backend with re-exec for integration testing (#16304) 2026-05-11 10:51:08 -05:00
luar123
4ac7bc4606 [zigbee] Add sensor support on esp32 (#16026) 2026-05-11 10:51:47 -04:00
tomaszduda23
8cf0eba043 [nrf52][zephyr] prepare for native builds (#16193)
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-05-11 14:47:06 +00:00
Keith Burzinski
30e2f7e8e9 [thermostat] Fix supplemental action never firing via max run time (#16308) 2026-05-11 10:13:43 -04:00
@RubenKelevra
a7299cb95b [esp32_camera] Downgrade esp32-camera to 2.1.5 (#16293) 2026-05-11 10:09:15 -04:00
tomaszduda23
2edb7ca5c2 [nrf52] add message that west update is running (#16321) 2026-05-11 10:05:41 -04:00
tomaszduda23
68534ea24d [logger] fix crash on zephyr (#16330) 2026-05-11 10:04:48 -04:00
rwrozelle
105842366e [openthread] Remove-freertos-portmacro-header-include (#16338) 2026-05-11 09:57:01 -04:00
J. Nick Koston
4d9d6e02e5 [core] Add stable esphome.upload_targets module for port classification (#16346) 2026-05-11 09:13:16 -04:00
J. Nick Koston
b967adeb9d [wifi] Accept lowercase variant in variant_has_wifi (#16345) 2026-05-11 09:11:36 -04:00
Jonathan Swoboda
e4d9786f00 [core] Move platformio files to subfolder (#16347) 2026-05-11 21:34:47 +12:00
Samuel Sieb
267836d098 [tuya] allow status pin that doesn't match the reported one (#16353) 2026-05-11 01:27:07 -07:00
Jesse Hills
c82adc3892 [ci] Fix external-component-bot 403 on PR comments (#16354) 2026-05-11 19:52:39 +12:00
Jesse Hills
fe66f9ba41 [ci] Tighten workflow permissions to least-privilege (#16349) 2026-05-11 17:15:53 +12:00
Jesse Hills
5dadfe6367 [ci] codeowner-review-request: mint least-privilege App token (#16351) 2026-05-11 17:04:09 +12:00
Jesse Hills
c4e85fbfc1 [ci] sync-device-classes: mint least-privilege App token (#16350) 2026-05-11 16:57:10 +12:00
Diorcet Yann
e9cc10fedc [core] Native idf full support (#14678)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <swoboda1337@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: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-05-11 02:12:07 +00:00
J. Nick Koston
66e2dcffc4 [cli] Tighten command_rename: scoped name rewrite, target-collision check (#16296) 2026-05-11 13:00:09 +12:00
J. Nick Koston
17080ddce6 [wifi][rp2040] Add stable wifi-capability helpers for device-builder (#16300) 2026-05-11 12:56:56 +12:00
J. Nick Koston
930d539969 [config_validation] Add a visibility UI-hint kwarg (#16267) 2026-05-11 12:07:15 +12:00
Clyde Stubbs
3c042e2e44 [lvgl] Ensure that on_value events fire on checked change (#16119) 2026-05-11 11:58:18 +12:00
Jesse Hills
ed10fbea3e [docker] Silence CopyIgnoredFile warning for build context root (#16311) 2026-05-11 07:25:49 +12:00
Mat931
1365251365 [ota] Add bootloader update functionality to ota component (#16238)
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-05-08 21:36:06 +00:00
rwrozelle
3abf2c99a2 [openthread] add coroutine-with-priority COMMUNICATION (#16318) 2026-05-08 16:35:47 -05:00
Kevin Ahrendt
70b9edfabe [i2s_audio] Refactor SPDIF output, fixing synchronization problems (#16319) 2026-05-08 21:26:09 +00:00
John Boiles
88c2a1c096 [speaker] Add SPDIF output support (#8065)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
Co-authored-by: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org>
2026-05-08 14:43:55 -04:00
Mat931
3d8fffbea9 [htu31d][kamstrup_kmp][ms8607] Use CRC functions from helpers.h (#16313) 2026-05-08 09:17:14 -04:00
Jonathan Swoboda
eb52ca61fe [climate][ektf2232] Remove deprecations scheduled for 2026.5.0 (#16289) 2026-05-08 07:26:14 -04:00
Jonathan Swoboda
a970f05b69 [clang-tidy] Enable readability-redundant-string-init (#16310) 2026-05-08 07:26:03 -04:00
Clyde Stubbs
7b6e2589f1 [modbus_server] Reduce log spam (#16283) 2026-05-08 14:09:22 +10:00
Jonathan Swoboda
696a654733 [clang-tidy] Concatenate nested namespaces (7/7: tests, platform-gated, enable check) (#16307) 2026-05-07 23:05:17 -04:00
Kevin Ahrendt
08b17c9da1 [core] Move core ring buffer to helper component (#16298) 2026-05-08 14:01:37 +12:00
Jesse Hills
e152c6155b [ci] Skip needs-docs for new components without CONFIG_SCHEMA (#16303) 2026-05-08 14:00:50 +12:00
Jonathan Swoboda
6ffcb821ca [clang-tidy] Concatenate nested namespaces (6/7: components t-z) (#16305) 2026-05-08 01:13:38 +00:00
Jonathan Swoboda
ded83812f4 [clang-tidy] Concatenate nested namespaces (5/7: components s) (#16302) 2026-05-08 00:16:51 +00:00
Jonathan Swoboda
ab1d2de78e [clang-tidy] Concatenate nested namespaces (4/7: components n-r) (#16301) 2026-05-07 23:28:30 +00:00
Jonathan Swoboda
cbe192df49 [clang-tidy] Concatenate nested namespaces (3/7: components i-m) (#16297) 2026-05-07 19:00:17 -04:00
dependabot[bot]
56ef357162 Bump github/codeql-action from 4.35.3 to 4.35.4 (#16299)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-07 17:51:30 -05:00
Jonathan Swoboda
4e4e4b4411 [clang-tidy] Concatenate nested namespaces (2/7: components d-h) (#16295) 2026-05-07 16:49:55 -04:00
Jonathan Swoboda
06bd92c388 [clang-tidy] Concatenate nested namespaces (1/7: components a-c) (#16294) 2026-05-07 14:21:39 -04:00
J. Nick Koston
71193e2b2c [helpers] Document write_file's external consumer contract (esphome-device-builder) (#16290) 2026-05-07 13:21:35 -05:00
Clyde Stubbs
9301f76482 [sensor] Add alternate calibration format for ntc (#15937) 2026-05-07 06:59:22 +10:00
Clyde Stubbs
004aa49131 [lvgl] Pass touch point to touch event lambdas (#16272) 2026-05-07 06:57:53 +10:00
dependabot[bot]
3b6250bcee Bump CodSpeedHQ/action from 4.15.0 to 4.15.1 (#16281)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-06 15:23:58 -05:00
Jesse Hills
a7b4a2006a Merge branch 'release' into dev 2026-05-07 08:13:00 +12:00
Jesse Hills
09dc41435c Merge pull request #16282 from esphome/bump-2026.4.5
2026.4.5
2026-05-07 08:12:15 +12:00
Jesse Hills
5283cdec12 Bump version to 2026.4.5 2026-05-07 07:25:35 +12:00
Edward Firmo
d9835c8705 [nextion] Fix text sensor state not updated on string response (#16280) 2026-05-07 07:25:35 +12:00
Mat931
b89c71c1ea [core] Fix WiFi connection in safe mode (#16269)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
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-05-07 07:25:35 +12:00
J. Nick Koston
7f6aef4f33 [substitutions] Fix sibling references inside dict-valued substitutions (#16273) 2026-05-07 07:25:35 +12:00
J. Nick Koston
016b509b55 [bundle] Include secrets.yaml when !secret keys are quoted (#16271) 2026-05-07 07:25:35 +12:00
Jesse Hills
d2bbaeccf3 [ha-addon] Add opt-in toggle for the new ESPHome Device Builder (#16247) 2026-05-07 07:25:35 +12:00
puddly
1e58e8729a [uart] Use tcdrain for flushing instead oftcflush on host (#14877)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-05-06 18:53:48 +00:00
J. Nick Koston
6173656bf8 [schema] Surface OnlyWith / OnlyWithout default + gate components in schema generator (#16276) 2026-05-06 13:49:00 -04:00
dbl-0
0d94ffe15d [resolver] Make RESOLVE_TIMEOUT configurable via environment variable (#15951)
Co-authored-by: Daniel Lowe <dan@auth.dxj.app>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-05-06 17:48:38 +00:00
Edward Firmo
4da62067cf [nextion] Fix text sensor state not updated on string response (#16280) 2026-05-06 13:32:50 -04:00
Kevin Ahrendt
9f49e3f80e [audio] Bump microFLAC to v0.2.0 (#16279) 2026-05-06 17:22:18 +00:00
Kevin Ahrendt
fc25ab0246 [i2s_audio] Optimize software volume control (#16278) 2026-05-06 12:57:03 -04:00
Kevin Ahrendt
a4a57a540d [core] Adds acquire and release methods to the ring buffer class (#16277) 2026-05-06 12:56:54 -04:00
Didier A
cfd2c9182c [bl0942] Remove broken 24-bit overflow tracking (#15650)
Co-authored-by: DidierA <1620015+didiera@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-05-06 12:34:55 -04:00
Mat931
2864922ac0 [ota] Partition table update: Fix log messages (#16241)
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: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-06 09:59:10 -05:00
Mat931
90693fb39a [core] Fix WiFi connection in safe mode (#16269)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
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-05-06 09:56:33 -05:00
J. Nick Koston
6e1a59da3e [packages] Make package !include vars visible to its substitutions block (#16274) 2026-05-06 09:53:14 -05:00
John
545ee03f42 [atm90e32] Fix calibration instance not saving in flash properly (#14152)
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-05-06 10:15:04 -04:00
J. Nick Koston
caaa1aefc7 [substitutions] Fix sibling references inside dict-valued substitutions (#16273) 2026-05-06 08:41:17 -05:00
J. Nick Koston
ff0c5f575e [bundle] Include secrets.yaml when !secret keys are quoted (#16271) 2026-05-06 07:32:35 -05:00
J. Nick Koston
f06ad8c436 [http_request] Add regression test for light action inside on_response (#16270) 2026-05-06 07:32:19 -05:00
Jonathan Swoboda
29db5fa4bb [script] Make pre-commit and helpers work on Windows (#16260)
Co-authored-by: Jonathan Swoboda <swoboda1337@users.noreply.github.com>
2026-05-06 07:11:06 -05:00
J. Nick Koston
85f33978e7 [core] Skip external component update on esphome clean (#16268) 2026-05-06 07:23:35 -04:00
Clyde Stubbs
79786f1cc7 [lvgl] Allow line points as percentages (#16209) 2026-05-06 07:22:43 -04:00
Kevin Ahrendt
febf8815c7 [audio_file][speaker] Eliminate code duplication for files built into firmware (#16266) 2026-05-06 05:59:51 -04:00
Jesse Hills
6f6d991dd2 [ha-addon] Add opt-in toggle for the new ESPHome Device Builder (#16247) 2026-05-06 21:42:11 +12:00
tomaszduda23
e9f7579910 [logger] give a chance to print crash (#16203)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-05-06 01:37:40 +00:00
tomaszduda23
a99c1b3e08 [nrf52] add reserve area for bootloader (#16204) 2026-05-05 20:37:03 -04:00
Kevin Ahrendt
2d6af1f7e5 [audio] Bump esp-audio-libs to v3.0.0 (#16263) 2026-05-05 20:22:53 -04:00
J. Nick Koston
700676b340 [api] Use entity_types.h X-macro for InitialStateIterator declarations (#16075) 2026-05-05 18:29:48 -05:00
J. Nick Koston
bf1c339dc1 [api] Use entity_types.h X-macro for ListEntitiesIterator declarations (#16076) 2026-05-05 18:29:32 -05:00
J. Nick Koston
f5c1b8839d [web_server] Use entity_types.h X-macro for ListEntitiesIterator declarations (#16077) 2026-05-05 18:29:10 -05:00
J. Nick Koston
4404dd68ba [cover] Fix ControlAction / CoverPublishAction trigger args with reference types (#16227) 2026-05-05 18:27:18 -05:00
J. Nick Koston
67491c3194 [packages] Add resolve_packages single-call seam (#16235) 2026-05-05 18:26:52 -05:00
J. Nick Koston
39b2b901f7 [core] Replace scheduler pool vector with unbounded intrusive freelist (#16172) 2026-05-05 18:26:19 -05:00
J. Nick Koston
f30ad588ea [cli] Add --ota-platform flag to pick web_server or native API OTA (#16207) 2026-05-05 18:25:53 -05:00
tomaszduda23
be82e8faeb [debug] Remove unused buffer in uicr lambda function (#16208) 2026-05-05 19:02:26 -04:00
Kevin Ahrendt
57397a318a [audio] Use the microWAV library for decoding (#16251) 2026-05-05 11:21:02 -05:00
Kevin Ahrendt
87a705b1cc [audio] Bump microOpus to v0.4.1 (#16255) 2026-05-05 12:47:07 +00:00
Keith Burzinski
edbb9f7b28 [i2s_audio] Fix stereo playback when slot bit width exceeds data bit width (#16248) 2026-05-05 08:15:32 -04:00
Jesse Hills
efff8fe8be [platformio_api] Remove duplicated _strip_win_long_path_prefix (#16249) 2026-05-05 14:29:23 +12:00
Jesse Hills
f248302370 Merge branch 'release' into dev 2026-05-05 14:22:23 +12:00
Jesse Hills
6fda5f41b2 Merge pull request #16240 from esphome/bump-2026.4.4
2026.4.4
2026-05-05 14:21:38 +12:00
Kevin Ahrendt
ea2b2b3920 [audio_file] Use microDecoder library instead of manual task management/decoding (#16237) 2026-05-04 20:12:26 -05:00
Kevin Ahrendt
f33d137669 [audio][media_player][speaker] WAV decoding is no longer always built (#16244) 2026-05-04 23:45:11 +00:00
dependabot[bot]
d28498ac2c Bump cryptography from 47.0.0 to 48.0.0 (#16245)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-04 23:39:44 +00:00
Olivier ARCHER
556783b95b [http_request] remove slow http_request warning on 8266 (#16239) 2026-05-04 18:19:52 -05:00
Kevin Ahrendt
857e529803 [audio] Use the microMP3 library instead of esp-audio-libs (#16236) 2026-05-04 18:41:50 -04:00
Jesse Hills
197d4dac8e Bump version to 2026.4.4 2026-05-05 08:27:10 +12:00
Jesse Hills
2d7f9dc48d [api] Use safe_print for log output and fix safe_print bytes-repr fallback (#16160) 2026-05-05 08:27:04 +12:00
J. Nick Koston
be84e6c9f4 [api] Fall back to owning types for service array args used after a delay (#16140) 2026-05-05 08:22:05 +12:00
J. Nick Koston
0418f2138a [esp32] Drop printf wrap on IDF 6.0+ (picolibc no longer needs it) (#16189) 2026-05-05 08:22:05 +12:00
Clyde Stubbs
d9c22d6b56 [lvgl] Clamp values for meter line indicators (#16180) 2026-05-05 08:22:05 +12:00
J. Nick Koston
60a94fd109 [esp32] Replace 512B stack buffer in printf wraps with picolibc cookie FILE (#16170) 2026-05-05 08:22:05 +12:00
Jesse Hills
9371ec319a [core] Strip \\?\ prefix from sys.executable for PlatformIO subprocess (#16158) 2026-05-05 08:21:58 +12:00
J. Nick Koston
ce466c6b60 [mcp23xxx_base] Reject unsupported interrupt_pin options (inverted, allow_other_uses) (#16149) 2026-05-05 08:14:03 +12:00
Brandon Harvey
a460f5343c [automation] Fix codegen type for component.resume update_interval (#16069)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 08:14:02 +12:00
Jesse Hills
7c2a63bf82 [api] Use safe_print for log output and fix safe_print bytes-repr fallback (#16160) 2026-05-05 08:12:20 +12:00
Diorcet Yann
690a197346 [main] Move stacktrace handling out of platformio_api and FlashImage into platform components/util (#16186) 2026-05-04 15:07:31 -04:00
J. Nick Koston
24d4da1021 [sensor] Document why TimeoutFilterBase intentionally keeps Component (#16194)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-05-04 01:18:28 +00:00
J. Nick Koston
53c4e6f386 [tests] Drop duplicate on_boot_restore_from in host_mode_climate_basic_state (#16228) 2026-05-03 20:12:51 -05:00
J. Nick Koston
1d63158480 [zephyr] Add nRF52 component tests so CI runs on zephyr-only changes (#16188) 2026-05-03 20:05:56 -05:00
J. Nick Koston
013dee44eb [binary_sensor] Drop Component from AutorepeatFilter, use self-keyed scheduler (#16191) 2026-05-03 20:05:27 -05:00
J. Nick Koston
9ddb828da3 [api] Don't tear down log connection on stack-trace decode failure (#16196) 2026-05-03 20:05:13 -05:00
J. Nick Koston
120d1e51fb [tests] Fix flaky host_mode_climate_basic_state integration test (#16192) 2026-05-03 20:04:34 -05:00
J. Nick Koston
844a36f7a1 [api] Mark high-volume proxy messages as speed_optimized (Infrared/RF, Z-Wave, serial) (#16159) 2026-05-03 20:03:52 -05:00
J. Nick Koston
72a75f2d3f [cover] Fold ControlAction/CoverPublishAction fields into stateless lambdas (#16046) 2026-05-03 20:02:07 -05:00
J. Nick Koston
b5eb444015 [dashboard] Stabilize device-builder dashboard backend's API surface (#16206)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-03 20:01:51 -05:00
J. Nick Koston
15ab5422c7 [ci] Run downstream device-builder tests against PR Python code (#16214) 2026-05-03 19:45:08 -05:00
J. Nick Koston
33f88619da [valve] Fix ControlAction trigger args with reference types (#16223) 2026-05-03 19:44:21 -05:00
J. Nick Koston
df1200629f [tests] Fix flaky host_mode_climate_basic_state (#16225) 2026-05-03 19:44:11 -05:00
J. Nick Koston
41bd570d30 [light] Fix LightControlAction trigger args with reference types (#16220) 2026-05-03 19:44:01 -05:00
J. Nick Koston
cf223674e5 [climate] Fix ControlAction trigger args with reference types (#16221) 2026-05-03 19:43:49 -05:00
J. Nick Koston
af74b639cf [fan] Fix TurnOnAction trigger args with reference types (#16222) 2026-05-03 19:43:35 -05:00
J. Nick Koston
4108b27197 [esp8266] Lower WDT_FEED_INTERVAL_MS to 100 ms (#16197) 2026-05-03 19:43:09 -05:00
Mat931
7cfab58a05 [ota] Add partition table update functionality to ota component (#15780)
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-05-03 19:42:10 -05:00
tomaszduda23
85e1e4b95e [zephyr] feed watchdog early. Otherwise OTA may rollback. (#16218) 2026-05-03 20:37:32 -04:00
J. Nick Koston
0f174ee626 [api] Fall back to owning types for service array args used after a delay (#16140) 2026-05-04 10:55:40 +12:00
Edward Firmo
8046ff7e1e [nextion] TFT upload no longer fails when the display sends a split 0x08 ack (#16205)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-05-03 03:40:09 -05:00
dependabot[bot]
5e9db1c8c6 Bump github/codeql-action from 4.35.2 to 4.35.3 (#16201)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-01 21:46:29 -05:00
J. Nick Koston
81d147ff9e [esp32] Drop printf wrap on IDF 6.0+ (picolibc no longer needs it) (#16189) 2026-05-01 14:31:56 -05:00
Mat931
58cb7effd4 [ota] Add extended OTA protocol (#16164)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-05-01 10:40:14 -05:00
Kevin Ahrendt
3dd60c5713 [core] Support allocating ring buffer in internal memory (#16187) 2026-05-01 07:55:08 -05:00
Oliver Kleinecke
f073c1cabe [usb_host][usb_uart] Add configurable max packet size (#14584) 2026-05-01 20:43:13 +10:00
J. Nick Koston
5cc447e0da [core] Move per-platform hal_platform.h into components/platform/hal.h (#16183) 2026-04-30 21:27:31 -05:00
Clyde Stubbs
0980630f68 [lvgl] Clamp values for meter line indicators (#16180) 2026-04-30 22:23:14 -04:00
J. Nick Koston
b8dfffdf06 [core] Enable ruff FLY (flynt) lint family (#16182) 2026-04-30 21:20:07 -05:00
luar123
f6e39d305d [zigbee] Add newlib compatibility for zigbee sdk in idf 6 (#16174) 2026-04-30 22:08:55 -04:00
Jonathan Swoboda
08e5cb5576 [esp32_hosted] Bump esp_hosted to 2.12.6 and esp_wifi_remote to 1.5.1 (#16176) 2026-04-30 20:47:22 -05:00
Kevin Ahrendt
faa61696e0 [sendspin] Use sendspin-cpp to v0.4.0 to reduce stuttering (#16178) 2026-04-30 20:43:24 -05:00
J. Nick Koston
9999913d07 [zephyr] Move HAL bodies into components/zephyr/hal.cpp + inline trivial dispatches (#16116) 2026-04-30 20:10:51 -05:00
J. Nick Koston
92aa98f680 [host] Move HAL bodies into components/host/hal.cpp + inline trivial dispatches (#16115) 2026-05-01 00:42:38 +00:00
J. Nick Koston
3d69169141 [climate] Fold ControlAction fields into a single stateless lambda (#16044) 2026-04-30 19:16:16 -05:00
J. Nick Koston
24fdfcf1a1 [rp2040] Move HAL bodies into components/rp2040/hal.cpp + inline trivial dispatches (#16114) 2026-04-30 19:15:41 -05:00
J. Nick Koston
550444dc34 [binary_sensor] Drop Component from filter classes, use self-keyed scheduler (#16131) 2026-04-30 19:15:18 -05:00
J. Nick Koston
ba7c06785a [mdns] Broadcast config_hash TXT record on _esphomelib._tcp (#16145) 2026-04-30 19:14:55 -05:00
J. Nick Koston
b708d1a826 [core] Drop unused DELAY_ACTION from InternalSchedulerID enum (#16151) 2026-04-30 19:14:34 -05:00
J. Nick Koston
148d478dec [api] Add encode/decode benchmarks for Z-Wave, IR/RF, and serial proxy messages (#16157) 2026-04-30 19:14:20 -05:00
J. Nick Koston
45e78e4114 [core] Inline loop gate expression to avoid stale local reuse (#16167) 2026-04-30 19:13:54 -05:00
J. Nick Koston
3b3e003aa3 [sensor] Pack ThrottleAverageFilter have_nan_ into n_ bitfield (-4 B/instance) (#16169) 2026-04-30 19:13:10 -05:00
J. Nick Koston
2f3e16b482 [bk72xx] Apply CFG_SUPPORT_BLE=0 SDK option to BK7238 (#16181) 2026-04-30 19:12:06 -05:00
J. Nick Koston
e085cb50d9 [sensor] Drop Component from filter classes, use self-keyed scheduler (#16132) 2026-04-30 19:11:30 -05:00
J. Nick Koston
2fbfb4c385 [ci] Split integration tests into 3 buckets when count is more than 10 (#16152) 2026-04-30 19:10:53 -05:00
J. Nick Koston
61261b4a59 [libretiny] Move HAL bodies into components/libretiny/hal.cpp + inline trivial dispatches (#16113) 2026-04-30 12:33:22 -05:00
J. Nick Koston
d48aad8c4d [esp32] Replace 512B stack buffer in printf wraps with picolibc cookie FILE (#16170) 2026-04-30 13:27:54 -04:00
Kevin Ahrendt
f1d3be4bda [core] Simplify RAMAllocator and add internal fallback to external mode (#16171) 2026-04-30 12:03:40 -04:00
Kevin Ahrendt
2758aa5517 [audio] bump microOpus to v0.4.0 to use fixed-point by default on ESP32 (#16168) 2026-04-30 09:12:39 -04:00
Kevin Ahrendt
a8b0133ec1 [audio] Enable specific codecs and configure advanced features (#16166) 2026-04-30 08:49:28 -04:00
Clyde Stubbs
1398dcebb4 [st7789v] Add deprecation warnings (#16162) 2026-04-30 00:53:37 -05:00
dependabot[bot]
096d0c4279 Bump aioesphomeapi from 44.22.0 to 44.23.0 (#16161)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-30 04:45:19 +00:00
Jesse Hills
e127268dac [core] Strip \\?\ prefix from sys.executable for PlatformIO subprocess (#16158) 2026-04-30 16:04:52 +12:00
J. Nick Koston
f0bffed3c0 [esp8266] Move HAL bodies into components/esp8266/hal.cpp + inline arch_init (#16112) 2026-04-30 15:42:17 +12:00
Jesse Hills
1a871e231d [ci] Use client-id for GitHub App token generation (#16155) 2026-04-30 13:09:37 +12:00
Jesse Hills
47765bd2d0 [ci] Correct version comment on create-github-app-token pin (#16156) 2026-04-30 13:08:56 +12:00
dependabot[bot]
8066325e0b Bump esphome/workflows/.github/workflows/lock.yml from 2026.4.0 to 2026.4.1 (#16143)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-30 12:52:25 +12:00
J. Nick Koston
b8d24c9e49 [mcp23xxx_base] Reject unsupported interrupt_pin options (inverted, allow_other_uses) (#16149) 2026-04-30 11:14:07 +12:00
J. Nick Koston
9b1f5c59bb [core] Fix null deref in WarnIfComponentBlockingGuard for self-keyed scheduler timers (#16150) 2026-04-29 23:05:38 +00:00
Jonathan Swoboda
e4b33fddf5 [esp32] Add ESP-IDF 6.0.1 platform entry (#16146) 2026-04-29 18:43:15 -04:00
Jonathan Swoboda
77da64a367 [sx126x] Add cold sleep option and drop unused RTC wakeup bit (#16144) 2026-04-29 17:05:51 -04:00
J. Nick Koston
cecccebc64 [core] DelayAction: drop Component inheritance, use self-keyed scheduler (#16129) 2026-04-29 20:35:04 +00:00
Jonathan Swoboda
53b682e48f [ci] Bump clang-tidy from 18.1.8 to 22.1.0.1 (#16078)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-29 20:19:33 +00:00
Mat931
14910e65d9 [ota] Use WatchdogManager for OTA on ESP32 (#16138)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-04-29 20:15:21 +00:00
J. Nick Koston
813964714c [esp32] Move HAL bodies into components/esp32/hal.cpp + inline trivial dispatches (#16111) 2026-04-29 20:09:08 +00:00
J. Nick Koston
5a146ab6b7 [valve] Fold ControlAction fields into a single stateless lambda (#16123) 2026-04-29 19:20:15 +00:00
J. Nick Koston
61a41402df [fan] Fold TurnOnAction fields into a single stateless lambda (#16122) 2026-04-29 19:16:05 +00:00
Mat931
59b4cfd07c [watchdog] Use default CHECK_IDLE_TASK and PANIC when configuring the watchdog (#16142) 2026-04-29 18:41:12 +00:00
J. Nick Koston
c41f38e16d [scheduler] Add self-keyed timer API for callers without a Component (#16127) 2026-04-29 13:24:37 -05:00
Clyde Stubbs
0ad8a071a7 [espnow] Cleanup method visibility and naming (#16109) 2026-04-29 14:18:21 -04:00
J. Nick Koston
985dba9332 [core] Defer heavy module-scope imports in __main__, loader, and config (#15955) 2026-04-29 13:17:59 -05:00
GelidusResearch
ca3f7251d4 [ens160] Fix sensor initialization timing (#16024)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-29 14:07:28 -04:00
J. Nick Koston
44cabc191d [core] Catch body-read errors in download_content (#16023) 2026-04-29 14:06:41 -04:00
J. Nick Koston
e5b1991cf7 [fan] Add tests for fan.turn_on action field combinations (#16125) 2026-04-29 12:46:06 -05:00
J. Nick Koston
7fba57ce51 [valve] Add tests for valve.control action field combinations (#16126) 2026-04-29 12:45:30 -05:00
J. Nick Koston
69a33d8ac0 [core] Inline HAL clock wrappers and split hal.h into per-platform headers (#15977) 2026-04-29 12:31:55 -05:00
Jonathan Swoboda
ce61dcf387 [remote_base][core] Drop redundant typename in dependent type contexts (#16137) 2026-04-29 16:54:17 +00:00
Jonathan Swoboda
bae6b51652 [kamstrup_kmp][toshiba] Fix signed/unsigned comparisons against sizeof (#16135) 2026-04-29 11:33:57 -04:00
Jonathan Swoboda
557c3d4436 [aqi] Use std::max initializer-list for non-negative AQI clamp (#16134) 2026-04-29 11:33:29 -04:00
Jonathan Swoboda
bacee89bca [mixer_speaker] NOLINT bugprone-unchecked-optional-access in audio_mixer_task (#16130) 2026-04-29 10:56:13 -04:00
Jonathan Swoboda
2157d11913 [haier] Fix bugprone-unchecked-optional-access; switch HardwareInfo to char[9] (#16124) 2026-04-29 14:26:53 +00:00
Jonathan Swoboda
42b8597719 [api] Extend NOLINT to cover bugprone-random-generator-seed in MAC varint test (#16120) 2026-04-29 13:58:19 +00:00
Jonathan Swoboda
2bd28eee9d [tormatic] Use .value() for checked optional access in read_gate_status_ (#16121) 2026-04-29 09:51:31 -04:00
J. Nick Koston
0a497d3c22 [light] Fold LightControlAction fields into a single stateless lambda (#16118) 2026-04-29 08:35:17 -05:00
Jonathan Swoboda
79da2b9704 [time] Fix bugprone-unchecked-optional-access in CronTrigger::check_time_ (#16107) 2026-04-29 08:30:46 -04:00
Jonathan Swoboda
ae5b211c89 [api] Avoid JsonDocument copy-and-swap operator= in ActionResponse ctor (#16106) 2026-04-29 08:30:35 -04:00
J. Nick Koston
8ceada8d04 [core] Download external_files in parallel (#16021) 2026-04-29 14:32:30 +12:00
J. Nick Koston
49c7a6928e [script] Fix cpp_unit_test crash for non-MULTI_CONF platform components (#16104) 2026-04-29 14:32:13 +12:00
J. Nick Koston
2fce71e0d4 [wifi] Add phy_mode option for ESP8266 (#16055) 2026-04-29 14:31:07 +12:00
J. Nick Koston
80251c54be [climate] Add climate.control coverage to component tests via thermostat (#16052) 2026-04-29 14:27:56 +12:00
J. Nick Koston
0d51a122d0 [cover] Add cover.control / cover.template.publish coverage to template tests (#16051) 2026-04-29 14:27:40 +12:00
J. Nick Koston
5a33c50015 [light] Use constexpr template for DimRelativeAction transition_length (#16038) 2026-04-29 14:26:38 +12:00
J. Nick Koston
0d150dc57e [light] Use constexpr template for ToggleAction transition_length (#16037) 2026-04-29 14:25:18 +12:00
J. Nick Koston
d287876d8d [light] Use bitmask template for LightControlAction unused fields (#16039) 2026-04-29 14:20:37 +12:00
J. Nick Koston
592486ae9a [analyze_memory] Attribute main.cpp setup()/loop() to esphome core (#16033) 2026-04-29 14:06:54 +12:00
Jonathan Swoboda
c3bd38af77 [feedback] Fix bugprone-unchecked-optional-access in start_direction_ (#16103) 2026-04-28 21:54:15 -04:00
J. Nick Koston
eec770d622 [core] Use ETag in external_files cache to fix re-downloads from raw.githubusercontent.com (#16020) 2026-04-29 13:52:09 +12:00
J. Nick Koston
d7b21a84a3 [git] Make ref fetches and submodule updates shallow (#16014) 2026-04-29 13:49:51 +12:00
J. Nick Koston
f05243bd9d [api] Add 48-bit MAC address varint fast path for BLE advertisements (#15988) 2026-04-29 13:48:35 +12:00
J. Nick Koston
35cb28edfe [output] Gate FloatOutput power scaling fields behind USE_OUTPUT_FLOAT_POWER_SCALING (#15998) 2026-04-29 13:27:22 +12:00
J. Nick Koston
1363f661e6 [core] Inline ContinuationAction in If/While/RepeatAction (#16040) 2026-04-28 21:26:25 -04:00
J. Nick Koston
8af499b591 [api] Use custom deleter to fix incomplete-type error on macOS libc++ (#16050) 2026-04-28 21:26:21 -04:00
Jonathan Swoboda
1a57d9bc2f [sprinkler][pn532] Fix bugprone-unchecked-optional-access (#16102) 2026-04-29 01:04:19 +00:00
J. Nick Koston
9768380856 [api] Hoist memw out of socket ready check to once per main-loop iter (#15996) 2026-04-29 13:04:10 +12:00
J. Nick Koston
676f26919e [mdns] Drive MDNS.update() polling from IP state events on ESP8266/RP2040 (#15961) 2026-04-29 13:02:21 +12:00
J. Nick Koston
29d3a3a498 [esp8266] Replace millis() with fast accumulator, wrap Arduino callers (#15662) 2026-04-29 12:58:00 +12:00
Jonathan Swoboda
77b76ac48a [inkbird_ibsth1_mini][speaker][speaker_source] Fix performance-unnecessary-copy-initialization (#16101) 2026-04-29 00:56:03 +00:00
Clyde Stubbs
0b5835284a [lvgl] Additional layout features (#16041) 2026-04-29 12:35:24 +12:00
Jonathan Swoboda
15df477472 [core] Reduce copies in Callback/CallbackManager call paths (#16093)
Co-authored-by: J. Nick Koston <nick+github@koston.org>
2026-04-28 19:41:28 -04:00
Jonathan Swoboda
be0ee73847 [i2c] NOLINT readability-identifier-naming on Zephyr struct forward-decl (#16099) 2026-04-28 19:22:42 -04:00
Jonathan Swoboda
a241c9e622 [online_image][sim800l] Use std::string::starts_with for prefix checks (#16097) 2026-04-28 19:02:39 -04:00
Jonathan Swoboda
2f433c78bd [haier] Brace single-statement else-if in smartair2_climate (#16098) 2026-04-28 18:56:36 -04:00
Jonathan Swoboda
e39c474577 [binary_sensor] Bind at_index_ once in MultiClick on_state_ (#16095) 2026-04-28 22:13:35 +00:00
Jonathan Swoboda
a62e3fe4fc [json] NOLINT StackAddressEscape false positive in parse_json (#16091) 2026-04-28 21:35:40 +00:00
Jonathan Swoboda
7d6b9bee19 [wifi] Avoid copying EAP config in three connect handlers (#16094) 2026-04-28 21:22:29 +00:00
Jonathan Swoboda
ab6bda50e4 [esp32_ble] Widen loop variable in as_128bit() to match uuid_.len type (#16088) 2026-04-28 20:58:40 +00:00
Jonathan Swoboda
3d195d748c [ezo] Use make_unique to construct EzoCommand (#16092) 2026-04-28 20:50:15 +00:00
Jonathan Swoboda
16cf4fb5e8 [nextion] Use std::string::starts_with for HTTPS URL check (#16090) 2026-04-28 20:47:20 +00:00
Jonathan Swoboda
70503442f4 [dfrobot_sen0395] Brace single-statement else-if in enqueue() (#16089) 2026-04-28 20:37:29 +00:00
Jonathan Swoboda
594b269dba [bme680] Rename cal1/cal2 to coeff1/coeff2 (#16087) 2026-04-28 20:33:57 +00:00
Clyde Stubbs
8157c721a5 [mapping] Implement default value (#15861) 2026-04-29 06:31:37 +10:00
Clyde Stubbs
9af557de6d [lvgl] Add utility gradient function (#16048) 2026-04-29 06:29:38 +10:00
Jonathan Swoboda
1f4136e76f [pipsolar] Guard handle_qmod_ against empty message (#16085) 2026-04-28 16:29:09 -04:00
Jonathan Swoboda
c8dffcc9b8 [tlc5971] Remove dead bit-banging delay code (#16086) 2026-04-28 15:28:33 -05:00
dependabot[bot]
44fbb7f5a9 Bump CodSpeedHQ/action from 4.14.0 to 4.15.0 (#16084)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-28 15:10:21 -05:00
Jonathan Swoboda
eb01d43feb [spi][http_request][demo] Fix latent clang-tidy issues in headers (#16080) 2026-04-28 16:09:35 -04:00
Jonathan Swoboda
7891fd5cf1 Add dependencies.lock to .gitignore (#16081) 2026-04-29 07:38:31 +12:00
Jonathan Swoboda
4ee9cc432b [ci] Install requirements_dev.txt in the cached venv (#16082) 2026-04-29 07:37:46 +12:00
Mat931
42ff10afe5 [watchdog] Fix WatchdogManager on single core apps (#16074) 2026-04-28 17:32:44 +00:00
tomaszduda23
6b3df66bdc [nrf52] make reset pin optional (#11684)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-04-28 12:20:38 -05:00
tomaszduda23
968878a62d [nrf52] implement wake_loop_threadsafe/wakeable_delay (#16032)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-28 16:35:12 +00:00
J. Nick Koston
daf3f4d2f1 [core] wakeable_delay: yield on already-woken fast path (ESP8266, RP2040) (#16045) 2026-04-28 10:41:17 -05:00
Bonne Eggleston
52e8c50f45 [modbus] Split modbus_server from modbus_controller (#15509)
Co-authored-by: J. Nick Koston <nick+github@koston.org>
2026-04-28 10:21:25 -05:00
J. Nick Koston
0a4d9b430f [ci] Add import-time regression check for esphome.__main__ (#15954) 2026-04-28 14:05:12 +00:00
J. Nick Koston
0759a3c681 [core] Split wake.{h,cpp} into per-platform files (#15978) 2026-04-28 08:48:13 -05:00
Egor Vorontsov
8921e3bb3f [api] add open states for lock to api.proto (#15901)
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-04-28 07:49:16 -05:00
Clyde Stubbs
52f80618d4 [lvgl] Allow a binary sensor to report checked or pressed state (#16073)
Co-authored-by: J. Nick Koston <nick+github@koston.org>
2026-04-28 22:00:29 +10:00
Jesse Hills
876c8c4c2a [ci-custom] Lint imports of esphome.components.const outside components (#16068)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 05:59:02 -05:00
Darafei Praliaskouski
41458d72e0 [esp32] Make Arduino app metadata reproducible (#16053) 2026-04-28 05:58:34 -05:00
Brandon Harvey
49d3df2698 [automation] Fix codegen type for component.resume update_interval (#16069)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 05:27:20 -05:00
J. Nick Koston
792f2e8363 [ota] Add wall-clock timeout to OTA data transfer loop (#16047) 2026-04-28 17:29:42 +12:00
J. Nick Koston
42c9fdc87e [feedback] Use App.get_loop_component_start_time() and constexpr timeout id (#16063) 2026-04-28 16:39:08 +12:00
Jesse Hills
5f6bbb98ce Merge branch 'release' into dev 2026-04-28 15:40:19 +12:00
Jesse Hills
4e0509435a Merge pull request #16067 from esphome/bump-2026.4.3
2026.4.3
2026-04-28 15:39:24 +12:00
J. Nick Koston
a03de7cea2 [core] Freshen loop_component_start_time_ before scheduler dispatch (#16064) 2026-04-28 13:23:08 +12:00
Jesse Hills
95b5ab7e78 Bump version to 2026.4.3 2026-04-28 12:58:29 +12:00
J. Nick Koston
3ac0939f55 [image] Fix RGB565+alpha rendering for multi-frame animations (#16017)
Co-authored-by: Claude <noreply@anthropic.com>
2026-04-28 12:58:29 +12:00
Jesse Hills
191d3bc7e4 [esp32_touch] Feed wdt (#16066) 2026-04-28 12:58:29 +12:00
Edward Firmo
a186f6fea9 [nextion] Unify TFT upload ack timeout to 5000ms (#15960) 2026-04-28 12:58:29 +12:00
Mat931
aea88aef5e [esp32][wifi] Fix bootloop and WiFi connection issue if nvs partition is missing or has non-default label (#16025)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-04-28 12:58:29 +12:00
J. Nick Koston
433bbdb016 [rotary_encoder][at581x] Fix templatable int field types (#16015) 2026-04-28 12:58:29 +12:00
J. Nick Koston
4137d93cbf [wifi] Fix stale wifi.connected after state transition (#15966) 2026-04-28 12:58:29 +12:00
J. Nick Koston
6a5919ee87 [deep_sleep] Fix sleep_duration codegen type to uint32_t (#15965) 2026-04-28 12:58:29 +12:00
Jesse Hills
b753ee4e94 [time] Handle Windows EINVAL when validating POSIX TZ strings (#15934) 2026-04-28 12:58:29 +12:00
Clyde Stubbs
c26ea52620 [lvgl] Triggers on tabview tabs fix (#15935) 2026-04-28 12:58:29 +12:00
J. Nick Koston
39a69385fb [image] Fix RGB565+alpha rendering for multi-frame animations (#16017)
Co-authored-by: Claude <noreply@anthropic.com>
2026-04-28 12:57:42 +12:00
Jesse Hills
a34836c290 [esp32_touch] Feed wdt (#16066) 2026-04-28 11:27:08 +12:00
Edward Firmo
01ac223913 [nextion] Unify TFT upload ack timeout to 5000ms (#15960) 2026-04-28 08:30:40 +12:00
Mat931
7198c912c7 [esp32][wifi] Fix bootloop and WiFi connection issue if nvs partition is missing or has non-default label (#16025)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-04-27 12:41:28 -05:00
Kevin Ahrendt
24c6a0d711 [audio] Bump microDecoder library to v0.2.0 (#16054) 2026-04-27 12:17:02 +00:00
plazarre
dec5d0449b [esp32_ble_tracker] Hold COEX_PREFER_BT for the lifetime of any active connection (#16036)
Co-authored-by: Paul Lazarre <plazarre@gmail.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-04-27 06:51:54 -05:00
J. Nick Koston
79b741b8dc [core] Combine entity register + configure_entity_ into one call (#16030) 2026-04-27 03:03:39 +00:00
tomaszduda23
112646a9c4 [zigbee] add router for nrf52 (#16034) 2026-04-26 23:02:09 -04:00
J. Nick Koston
2e096bb036 [core] Combine set_component_source_ + register_component_ into one call (#16029) 2026-04-26 21:54:15 -05:00
Johan Henkens
e87e78c544 [api] Expose TemperatureUnit in water heater and climate api (#15815)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick+github@koston.org>
2026-04-26 12:58:14 +00:00
J. Nick Koston
0f25d91e68 [core] Unify skip_external_update and honor it in external_files for faster esphome logs (#16016) 2026-04-26 07:24:33 -05:00
J. Nick Koston
8dbdcfc128 [bk72xx] Prepare for BK7238 support (#16018) 2026-04-26 07:24:07 -05:00
J. Nick Koston
8950afc3c4 [bluetooth_proxy] Drop redundant remote_bda_ write in connect handler (#16000) 2026-04-26 07:23:53 -05:00
J. Nick Koston
04d067196d [rotary_encoder][at581x] Fix templatable int field types (#16015) 2026-04-26 07:23:41 -05:00
J. Nick Koston
502c010465 [bh1750] Downgrade per-reading Illuminance log to verbose (#16005) 2026-04-26 07:23:24 -05:00
J. Nick Koston
180105bb4b [bluetooth_proxy] Partial revert of loop() → set_interval migration (#15992) 2026-04-26 07:23:08 -05:00
J. Nick Koston
4c0dfb0e0d [core] Raise ESP32 WDT feed interval to 1/5 of configured timeout (#15984) 2026-04-26 07:22:50 -05:00
J. Nick Koston
df987a7ffb [ci-custom] Suggest uint32_to_str/int8_to_str for integer formatting (#15970) 2026-04-26 07:22:34 -05:00
Boris Krivonog
c8d4420408 [mitsubishi_cn105] add support for half-degree temperature setpoint (#15919) 2026-04-26 07:19:49 -05:00
Darafei Praliaskouski
b084fa4490 [esp32] Make ESP-IDF builds reproducible (#16008)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-04-26 06:31:32 -05:00
Darafei Praliaskouski
68625a1b76 [core] Isolate generated build metadata (#16007)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-04-26 09:11:09 +00:00
J. Nick Koston
dc57969afd [host] Use integer math in millis()/micros() (#15994) 2026-04-26 08:39:24 +00:00
J. Nick Koston
f092e619d8 [rtttl] Gate on_finished_playback callback storage behind define (#16003) 2026-04-26 00:03:59 -05:00
J. Nick Koston
58f6ad2d0c [safe_mode] Use StaticCallbackManager for on_safe_mode (#16002) 2026-04-26 00:01:21 -05:00
Keith Burzinski
bc33260c61 [ir_rf_proxy] Extend for RF (#15744)
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-04-25 22:33:02 -05:00
J. Nick Koston
4cab262ef8 [ci] Trigger CodSpeed benchmarks on host platform changes (#15995) 2026-04-25 17:18:21 -04:00
dependabot[bot]
9ad820c921 Bump esphome-dashboard from 20260408.1 to 20260425.0 (#16006)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-25 20:59:01 +00:00
J. Nick Koston
4f8feb86f0 [dashboard] Add --no-states support to logs WebSocket handler (#15993) 2026-04-25 15:43:05 -05:00
Javier Peletier
b5ccd55f4e [packages] Fix premature substitution of vars in remote package files (#15997)
Co-authored-by: J. Nick Koston <nick+github@koston.org>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-25 17:06:58 +00:00
dependabot[bot]
a437b3086b Bump cryptography from 46.0.7 to 47.0.0 (#15990)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-25 02:30:10 +00:00
dependabot[bot]
c27f9e512b Bump aioesphomeapi from 44.21.0 to 44.22.0 (#15989)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-25 02:28:04 +00:00
dependabot[bot]
f62972c2c6 Bump ruff from 0.15.11 to 0.15.12 (#15981)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-04-24 19:34:00 +00:00
dependabot[bot]
f36efbc762 Update tzdata requirement from >=2026.1 to >=2026.2 (#15980)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-24 19:27:12 +00:00
Kevin Ahrendt
9caf9ee023 [sendspin] Bumps sendspin-cpp library for a bugfix (#15976) 2026-04-24 11:53:03 -05:00
pre-commit-ci-lite[bot]
578196ab85 [pre-commit.ci lite] apply automatic fixes 2026-02-28 22:24:08 +00:00
Roy Walker
d9b712ee5f Fix timeout to use ESPhome built-in function. 2026-02-28 16:22:28 -06:00
Roy Walker
1a61cd622e Add support for timeouts before next network connection is turned up and add support for openthread and modem. 2026-02-28 13:41:55 -06:00
pre-commit-ci-lite[bot]
26bdf58daf [pre-commit.ci lite] apply automatic fixes 2026-02-26 17:36:14 +00:00
Roy Walker
c915a2b8f5 Remove duplicate logger and fix import. 2026-02-26 11:34:18 -06:00
Roy Walker
7fdb95c2ef Merge branch 'rwalker777-network-priority' of https://github.com/rwalker777/esphome into rwalker777-network-priority 2026-02-26 11:31:10 -06:00
Roy Walker
e44365abca Remove duplicate CONF_OUTPUT_POWER from import. 2026-02-26 11:30:20 -06:00
rwalker777
532641d523 Merge branch 'esphome:dev' into rwalker777-network-priority 2026-02-26 11:30:07 -06:00
rwalker777
bc36892e7d Merge branch 'dev' into rwalker777-network-priority 2026-02-24 13:45:27 -06:00
Roy Walker
3a02c2f8af Fix validation on priority import. 2026-02-24 11:16:21 -06:00
pre-commit-ci-lite[bot]
4a1f9af319 [pre-commit.ci lite] apply automatic fixes 2026-02-24 17:08:56 +00:00
rwalker777
9e29bdfdad Merge branch 'esphome:dev' into rwalker777-network-priority 2026-02-24 11:03:34 -06:00
Roy Walker
20c975103b Fix Wifi not connecting with Ethernet config but disconnected. 2026-02-22 20:30:34 -06:00
Roy Walker
549b9f85ae Fix wifi so it doesn't double register. 2026-02-22 19:20:13 -06:00
Roy Walker
0fe2310db4 Fix wifi and ethernet coexisting. 2026-02-22 18:42:35 -06:00
Roy Walker
5af3e5caef Fix stab at network priority support. 2026-02-22 18:22:47 -06:00
Rapsssito
47854ff9de Add missing imports 2026-02-16 13:31:19 +01:00
Rapsssito
8a1ddfb1cc Typo 2026-02-16 13:21:13 +01:00
Rapsssito
cde89212fc Typo 2026-02-16 13:17:00 +01:00
Rapsssito
0a518c1e4c Switch to a network component 2026-02-16 13:13:23 +01:00
Rapsssito
8c7d2d984e Just store if it is initialized 2026-02-16 12:47:14 +01:00
Rapsssito
8390a98614 [ethernet, network, openthread, wifi] centralize esp32 netif intialization 2026-02-16 12:36:22 +01:00
2260 changed files with 37795 additions and 13493 deletions

View File

@@ -5,24 +5,30 @@ Checks: >-
-altera-*,
-android-*,
-boost-*,
-bugprone-derived-method-shadowing-base-method,
-bugprone-easily-swappable-parameters,
-bugprone-implicit-widening-of-multiplication-result,
-bugprone-invalid-enum-default-initialization,
-bugprone-multi-level-implicit-pointer-conversion,
-bugprone-narrowing-conversions,
-bugprone-tagged-union-member-count,
-bugprone-signed-char-misuse,
-bugprone-switch-missing-default-case,
-cert-dcl50-cpp,
-cert-err33-c,
-cert-err58-cpp,
-cert-int09-c,
-cert-oop57-cpp,
-cert-str34-c,
-clang-analyzer-optin.core.EnumCastOutOfRange,
-clang-analyzer-optin.cplusplus.UninitializedObject,
-clang-analyzer-osx.*,
-clang-analyzer-security.ArrayBound,
-clang-diagnostic-delete-abstract-non-virtual-dtor,
-clang-diagnostic-delete-non-abstract-non-virtual-dtor,
-clang-diagnostic-deprecated-declarations,
-clang-diagnostic-ignored-optimization-argument,
-clang-diagnostic-missing-designated-field-initializers,
-clang-diagnostic-missing-field-initializers,
-clang-diagnostic-shadow-field,
-clang-diagnostic-unused-const-variable,
@@ -42,6 +48,7 @@ Checks: >-
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-prefer-member-initializer,
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
-cppcoreguidelines-pro-bounds-avoid-unchecked-container-access,
-cppcoreguidelines-pro-bounds-constant-array-index,
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
-cppcoreguidelines-pro-type-const-cast,
@@ -54,12 +61,13 @@ Checks: >-
-cppcoreguidelines-rvalue-reference-param-not-moved,
-cppcoreguidelines-special-member-functions,
-cppcoreguidelines-use-default-member-init,
-cppcoreguidelines-use-enum-class,
-cppcoreguidelines-virtual-class-destructor,
-fuchsia-default-arguments-calls,
-fuchsia-default-arguments-declarations,
-fuchsia-multiple-inheritance,
-fuchsia-overloaded-operator,
-fuchsia-statically-constructed-objects,
-fuchsia-default-arguments-declarations,
-fuchsia-default-arguments-calls,
-google-build-using-namespace,
-google-explicit-constructor,
-google-readability-braces-around-statements,
@@ -71,49 +79,63 @@ Checks: >-
-llvm-else-after-return,
-llvm-header-guard,
-llvm-include-order,
-llvm-prefer-static-over-anonymous-namespace,
-llvm-qualified-auto,
-llvm-use-ranges,
-llvmlibc-*,
-misc-const-correctness,
-misc-include-cleaner,
-misc-multiple-inheritance,
-misc-no-recursion,
-misc-non-private-member-variables-in-classes,
-misc-override-with-different-visibility,
-misc-unused-parameters,
-misc-use-anonymous-namespace,
-misc-use-internal-linkage,
-modernize-avoid-bind,
-modernize-avoid-variadic-functions,
-modernize-avoid-c-arrays,
-modernize-concat-nested-namespaces,
-modernize-avoid-c-style-cast,
-modernize-macro-to-enum,
-modernize-return-braced-init-list,
-modernize-type-traits,
-modernize-use-auto,
-modernize-use-constraints,
-modernize-use-default-member-init,
-modernize-use-designated-initializers,
-modernize-use-equals-default,
-modernize-use-integer-sign-comparison,
-modernize-use-nodiscard,
-modernize-use-nullptr,
-modernize-use-nodiscard,
-modernize-use-nullptr,
-modernize-use-ranges,
-modernize-use-trailing-return-type,
-mpi-*,
-objc-*,
-performance-enum-size,
-portability-avoid-pragma-once,
-portability-template-virtual-member-function,
-readability-ambiguous-smartptr-reset-call,
-readability-avoid-nested-conditional-operator,
-readability-container-contains,
-readability-container-data-pointer,
-readability-convert-member-functions-to-static,
-readability-else-after-return,
-readability-enum-initial-value,
-readability-function-cognitive-complexity,
-readability-implicit-bool-conversion,
-readability-isolate-declaration,
-readability-magic-numbers,
-readability-make-member-function-const,
-readability-math-missing-parentheses,
-readability-named-parameter,
-readability-redundant-casting,
-readability-redundant-inline-specifier,
-readability-redundant-member-init,
-readability-redundant-string-init,
-readability-redundant-parentheses,
-readability-redundant-typename,
-readability-uppercase-literal-suffix,
-readability-use-anyofallof,
-readability-use-std-min-max,
-readability-use-concise-preprocessor-directives,
WarningsAsErrors: '*'
FormatStyle: google
CheckOptions:

View File

@@ -1 +1 @@
1b1ce6324c50c4595703c7df0a8a479b4fe84b71ff1a8793cce1a16f17a33324
27aaab4e0ebfc10491720345aa746fc2dffa6a3985f73ec111b12dd99078d46f

View File

@@ -115,4 +115,4 @@ examples/
Dockerfile
.git/
tests/
.*
.?*

View File

@@ -47,7 +47,7 @@ runs:
- name: Build and push to ghcr by digest
id: build-ghcr
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
env:
DOCKER_BUILD_SUMMARY: false
DOCKER_BUILD_RECORD_UPLOAD: false
@@ -73,7 +73,7 @@ runs:
- name: Build and push to dockerhub by digest
id: build-dockerhub
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
env:
DOCKER_BUILD_SUMMARY: false
DOCKER_BUILD_RECORD_UPLOAD: false

View File

@@ -27,6 +27,18 @@ runs:
path: venv
# yamllint disable-line rule:line-length
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-venv-${{ inputs.cache-key }}
- name: Set up uv
# Only needed on cache miss to populate the venv. ``uv pip install``
# 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
with:
enable-cache: true
# 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: Create Python virtual environment
if: steps.cache-venv.outputs.cache-hit != 'true' && runner.os != 'Windows'
shell: bash
@@ -34,8 +46,8 @@ runs:
python -m venv venv
source venv/bin/activate
python --version
pip install -r requirements.txt -r requirements_test.txt
pip install -e .
uv pip install -r requirements.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'
shell: bash
@@ -43,5 +55,5 @@ runs:
python -m venv venv
source ./venv/Scripts/activate
python --version
pip install -r requirements.txt -r requirements_test.txt
pip install -e .
uv pip install -r requirements.txt -r requirements_test.txt
uv pip install -e .

View File

@@ -1 +1 @@
../.ai/instructions.md
../AGENTS.md

View File

@@ -1,4 +1,3 @@
const fs = require('fs');
const { DOCS_PR_PATTERNS } = require('./constants');
const {
COMPONENT_REGEX,
@@ -9,6 +8,31 @@ const {
} = require('../detect-tags');
const { loadCodeowners, getEffectiveOwners } = require('../codeowners');
// Top-level `CONFIG_SCHEMA = ...` (assignment) or `CONFIG_SCHEMA: ConfigType = ...` (annotation).
// Ruff/Black enforce exactly one space around `=` and no space before `:`,
// so we can match strictly: `CONFIG_SCHEMA ` or `CONFIG_SCHEMA:`.
const CONFIG_SCHEMA_REGEX = /^CONFIG_SCHEMA[ :]/m;
// Fetch a file's contents from the PR head SHA via the GitHub API.
// The auto-label workflow runs on `pull_request_target`, which checks out the
// base branch — files added by the PR don't exist in the workspace, so we have
// to fetch them from the head SHA. Returns null if the file can't be fetched.
async function fetchPrFileContent(github, context, path) {
try {
const { owner, repo } = context.repo;
const { data } = await github.rest.repos.getContent({
owner,
repo,
path,
ref: context.payload.pull_request.head.sha,
});
return Buffer.from(data.content, 'base64').toString('utf8');
} catch (error) {
console.log(`Failed to fetch ${path} from PR head:`, error.message);
return null;
}
}
// Strategy: Merge branch detection
async function detectMergeBranch(context) {
const labels = new Set();
@@ -45,52 +69,64 @@ async function detectComponentPlatforms(changedFiles, apiData) {
}
// Strategy: New component detection
async function detectNewComponents(prFiles) {
async function detectNewComponents(github, context, prFiles) {
const labels = new Set();
let hasYamlLoadable = false;
const addedFiles = prFiles.filter(file => file.status === 'added').map(file => file.filename);
for (const file of addedFiles) {
const componentMatch = file.match(/^esphome\/components\/([^\/]+)\/__init__\.py$/);
if (componentMatch) {
try {
const content = fs.readFileSync(file, 'utf8');
if (content.includes('IS_TARGET_PLATFORM = True')) {
labels.add('new-target-platform');
}
} catch (error) {
console.log(`Failed to read content of ${file}:`, error.message);
}
labels.add('new-component');
if (!componentMatch) continue;
labels.add('new-component');
const content = await fetchPrFileContent(github, context, file);
if (content === null) {
// Safe default: assume YAML-loadable so needs-docs behaviour is unchanged on fetch failure
hasYamlLoadable = true;
continue;
}
if (content.includes('IS_TARGET_PLATFORM = True')) {
labels.add('new-target-platform');
}
if (CONFIG_SCHEMA_REGEX.test(content)) {
hasYamlLoadable = true;
}
}
return labels;
return { labels, hasYamlLoadable };
}
// Strategy: New platform detection
async function detectNewPlatforms(prFiles, apiData) {
async function detectNewPlatforms(github, context, prFiles, apiData) {
const labels = new Set();
let hasYamlLoadable = false;
const addedFiles = prFiles.filter(file => file.status === 'added').map(file => file.filename);
for (const file of addedFiles) {
const platformFileMatch = file.match(/^esphome\/components\/([^\/]+)\/([^\/]+)\.py$/);
if (platformFileMatch) {
const [, component, platform] = platformFileMatch;
if (apiData.platformComponents.includes(platform)) {
labels.add('new-platform');
}
}
const platformPathPatterns = [
/^esphome\/components\/([^\/]+)\/([^\/]+)\.py$/,
/^esphome\/components\/([^\/]+)\/([^\/]+)\/__init__\.py$/,
];
const platformDirMatch = file.match(/^esphome\/components\/([^\/]+)\/([^\/]+)\/__init__\.py$/);
if (platformDirMatch) {
const [, component, platform] = platformDirMatch;
if (apiData.platformComponents.includes(platform)) {
labels.add('new-platform');
for (const file of addedFiles) {
for (const re of platformPathPatterns) {
const match = file.match(re);
if (!match) continue;
const platform = match[2];
if (!apiData.platformComponents.includes(platform)) break;
labels.add('new-platform');
const content = await fetchPrFileContent(github, context, file);
if (content === null) {
// Safe default: assume YAML-loadable so needs-docs behaviour is unchanged on fetch failure
hasYamlLoadable = true;
} else if (CONFIG_SCHEMA_REGEX.test(content)) {
hasYamlLoadable = true;
}
break;
}
}
return labels;
return { labels, hasYamlLoadable };
}
// Strategy: Core files detection
@@ -300,7 +336,7 @@ function detectMaintainerAccess(context) {
}
// Strategy: Requirements detection
async function detectRequirements(allLabels, prFiles, context) {
async function detectRequirements(allLabels, prFiles, context, hasYamlLoadable) {
const labels = new Set();
// Check for missing tests
@@ -308,8 +344,15 @@ async function detectRequirements(allLabels, prFiles, context) {
labels.add('needs-tests');
}
// Check for missing docs
if (allLabels.has('new-component') || allLabels.has('new-platform') || allLabels.has('new-feature')) {
// Check for missing docs.
// `new-feature` (PR-body checkbox) always counts. `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 =
allLabels.has('new-feature') ||
((allLabels.has('new-component') || allLabels.has('new-platform')) && hasYamlLoadable);
if (docsEligible) {
const prBody = context.payload.pull_request.body || '';
const hasDocsLink = DOCS_PR_PATTERNS.some(pattern => pattern.test(prBody));

View File

@@ -106,8 +106,8 @@ module.exports = async ({ github, context }) => {
const [
branchLabels,
componentLabels,
newComponentLabels,
newPlatformLabels,
newComponentResult,
newPlatformResult,
coreLabels,
sizeLabels,
dashboardLabels,
@@ -120,8 +120,8 @@ module.exports = async ({ github, context }) => {
] = await Promise.all([
detectMergeBranch(context),
detectComponentPlatforms(changedFiles, apiData),
detectNewComponents(prFiles),
detectNewPlatforms(prFiles, 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),
detectDashboardChanges(changedFiles),
@@ -133,6 +133,13 @@ module.exports = async ({ github, context }) => {
detectMaintainerAccess(context)
]);
// Extract new-component / new-platform results
const newComponentLabels = newComponentResult.labels;
const newPlatformLabels = newPlatformResult.labels;
// Eligible for needs-docs only if any newly added component or platform file
// defines a top-level CONFIG_SCHEMA (i.e. is actually loadable from YAML).
const hasYamlLoadable = newComponentResult.hasYamlLoadable || newPlatformResult.hasYamlLoadable;
// Extract deprecated component info
const deprecatedLabels = deprecatedResult.labels;
const deprecatedInfo = deprecatedResult.deprecatedInfo;
@@ -154,7 +161,7 @@ module.exports = async ({ github, context }) => {
]);
// Detect requirements based on all other labels
const requirementLabels = await detectRequirements(allLabels, prFiles, context);
const requirementLabels = await detectRequirements(allLabels, prFiles, context, hasYamlLoadable);
for (const label of requirementLabels) {
allLabels.add(label);
}

View File

@@ -6,9 +6,10 @@ on:
pull_request_target:
types: [labeled, opened, reopened, synchronize, edited]
# All PR/label/review writes are performed with the App token minted below,
# so the workflow's GITHUB_TOKEN only needs read access for checkout.
permissions:
pull-requests: write
contents: read
contents: read # actions/checkout reads the workflow source
env:
SMALL_PR_THRESHOLD: 30
@@ -27,10 +28,14 @@ jobs:
- name: Generate a token
id: generate-token
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v2
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ secrets.ESPHOME_GITHUB_APP_ID }}
client-id: ${{ vars.ESPHOME_GITHUB_APP_CLIENT_ID }}
private-key: ${{ secrets.ESPHOME_GITHUB_APP_PRIVATE_KEY }}
# 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
- name: Auto Label PR
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0

View File

@@ -12,8 +12,8 @@ on:
- ".github/workflows/ci-api-proto.yml"
permissions:
contents: read
pull-requests: write
contents: read # actions/checkout for the PR head
pull-requests: write # pulls.createReview / listReviews / dismissReview when generated proto files are stale
jobs:
check:
@@ -26,6 +26,16 @@ jobs:
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.11"
- 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
with:
enable-cache: true
# 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
run: |
@@ -34,7 +44,7 @@ jobs:
sudo apt install -y protobuf-compiler
protoc --version
- name: Install python dependencies
run: pip install aioesphomeapi -c requirements.txt -r requirements_dev.txt
run: uv pip install --system aioesphomeapi -c requirements.txt -r requirements_dev.txt
- name: Generate files
run: script/api_protobuf/api_protobuf.py
- name: Check for changes

View File

@@ -12,8 +12,8 @@ on:
- ".github/workflows/ci-clang-tidy-hash.yml"
permissions:
contents: read
pull-requests: write
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:

View File

@@ -22,8 +22,7 @@ on:
- "script/platformio_install_deps.py"
permissions:
contents: read
packages: read
contents: read # actions/checkout only; the build does not push images
concurrency:
# yamllint disable-line rule:line-length
@@ -49,7 +48,7 @@ jobs:
with:
python-version: "3.11"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: Set TAG
run: |

View File

@@ -7,9 +7,9 @@ on:
types: [completed]
permissions:
contents: read
pull-requests: write
actions: read
contents: read # actions/checkout of the base repo at the PR's target branch
pull-requests: write # gh api to look up the PR by head SHA and post/update the memory-impact comment
actions: read # gh run download for the memory-analysis artifacts produced by the CI workflow run
jobs:
memory-impact-comment:

View File

@@ -6,18 +6,10 @@ on:
branches: [dev, beta, release]
pull_request:
paths:
- "**"
- "!.github/workflows/*.yml"
- "!.github/actions/build-image/*"
- ".github/workflows/ci.yml"
- "!.yamllint"
- "!.github/dependabot.yml"
- "!docker/**"
merge_group:
permissions:
contents: read
contents: read # actions/checkout for all jobs; individual jobs add their own scopes when they need to write
env:
DEFAULT_PYTHON: "3.11"
@@ -39,7 +31,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Generate cache-key
id: cache-key
run: echo key="${{ hashFiles('requirements.txt', 'requirements_test.txt', '.pre-commit-config.yaml') }}" >> $GITHUB_OUTPUT
run: echo key="${{ hashFiles('requirements.txt', 'requirements_dev.txt', 'requirements_test.txt', '.pre-commit-config.yaml') }}" >> $GITHUB_OUTPUT
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
id: python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
@@ -52,14 +44,26 @@ jobs:
path: venv
# yamllint disable-line rule:line-length
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-venv-${{ steps.cache-key.outputs.key }}
- name: Set up uv
# Only needed on cache miss to populate the venv. ``uv pip install``
# detects the activated venv via ``VIRTUAL_ENV`` so downstream jobs
# that ``. venv/bin/activate`` see an identical layout.
if: steps.cache-venv.outputs.cache-hit != 'true'
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
enable-cache: true
# 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: Create Python virtual environment
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
python -m venv venv
. venv/bin/activate
python --version
pip install -r requirements.txt -r requirements_test.txt pre-commit
pip install -e .
uv pip install -r requirements.txt -r requirements_dev.txt -r requirements_test.txt pre-commit
uv pip install -e .
pylint:
name: Check pylint
@@ -89,6 +93,8 @@ jobs:
runs-on: ubuntu-24.04
needs:
- common
- determine-jobs
if: needs.determine-jobs.outputs.core-ci == 'true'
steps:
- name: Check out code from GitHub
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@@ -108,6 +114,85 @@ jobs:
script/generate-esp32-boards.py --check
script/generate-rp2040-boards.py --check
import-time:
name: Check import esphome.__main__ time
runs-on: ubuntu-24.04
needs:
- common
- determine-jobs
if: needs.determine-jobs.outputs.import-time == 'true'
steps:
- name: Check out code from GitHub
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Restore Python
uses: ./.github/actions/restore-python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
cache-key: ${{ needs.common.outputs.cache-key }}
- name: Check import time against budget and write waterfall HAR
run: |
. venv/bin/activate
script/check_import_time.py --check --har importtime.har
- name: Upload waterfall HAR
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: import-time-waterfall
path: importtime.har
if-no-files-found: ignore
retention-days: 14
device-builder:
name: Test downstream esphome/device-builder
runs-on: ubuntu-24.04
needs:
- common
- determine-jobs
if: needs.determine-jobs.outputs.device-builder == 'true'
steps:
- name: Check out esphome (this PR)
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
path: esphome
- name: Check out esphome/device-builder
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
repository: esphome/device-builder
ref: main
path: device-builder
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.13"
- name: Set up uv
# Mirrors the install shape device-builder's own CI uses
# (esphome/device-builder#192): uv replaces pip for the
# install step (order-of-magnitude faster on cold boots,
# with its own wheel cache). actions/setup-python still
# provides the interpreter.
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
enable-cache: true
# 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 device-builder + esphome from PR
# Install device-builder with its esphome + test extras
# first so its pinned versions of pytest/etc. land, then
# overlay the PR's esphome so the downstream tests run
# against this PR's Python code. ``--system`` installs into
# the runner's Python instead of a venv.
run: |
uv pip install --system -e './device-builder[esphome,test]'
uv pip install --system -e ./esphome
- name: Run device-builder pytest
# ``-n auto`` runs under pytest-xdist (matches device-builder's
# own CI). No ``--cov`` here -- this is purely a downstream
# smoke check against this PR's esphome code.
working-directory: device-builder
run: pytest -q -n auto --maxfail=5 --durations=30 --no-cov --ignore=tests/benchmarks
pytest:
name: Run pytest
strategy:
@@ -132,6 +217,8 @@ jobs:
runs-on: ${{ matrix.os }}
needs:
- common
- determine-jobs
if: needs.determine-jobs.outputs.core-ci == 'true'
steps:
- name: Check out code from GitHub
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@@ -147,14 +234,14 @@ jobs:
if: matrix.os == 'windows-latest'
run: |
. ./venv/Scripts/activate.ps1
pytest -vv --cov-report=xml --tb=native -n auto tests --ignore=tests/integration/
pytest -vv --cov-report=xml --tb=native --durations=30 -n auto tests --ignore=tests/integration/
- name: Run pytest
if: matrix.os == 'ubuntu-latest' || matrix.os == 'macOS-latest'
run: |
. venv/bin/activate
pytest -vv --cov-report=xml --tb=native -n auto tests --ignore=tests/integration/
pytest -vv --cov-report=xml --tb=native --durations=30 -n auto tests --ignore=tests/integration/
- name: Upload coverage to Codecov
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1
with:
token: ${{ secrets.CODECOV_TOKEN }}
- name: Save Python virtual environment cache
@@ -170,12 +257,17 @@ jobs:
needs:
- common
outputs:
core-ci: ${{ steps.determine.outputs.core-ci }}
integration-tests: ${{ steps.determine.outputs.integration-tests }}
integration-tests-run-all: ${{ steps.determine.outputs.integration-tests-run-all }}
integration-test-files: ${{ steps.determine.outputs.integration-test-files }}
integration-test-buckets: ${{ steps.determine.outputs.integration-test-buckets }}
clang-tidy: ${{ steps.determine.outputs.clang-tidy }}
clang-tidy-mode: ${{ steps.determine.outputs.clang-tidy-mode }}
clang-tidy-full-scan: ${{ steps.determine.outputs.clang-tidy-full-scan }}
python-linters: ${{ steps.determine.outputs.python-linters }}
import-time: ${{ steps.determine.outputs.import-time }}
device-builder: ${{ steps.determine.outputs.device-builder }}
native-idf: ${{ steps.determine.outputs.native-idf }}
native-idf-components: ${{ steps.determine.outputs.native-idf-components }}
changed-components: ${{ steps.determine.outputs.changed-components }}
changed-components-with-tests: ${{ steps.determine.outputs.changed-components-with-tests }}
directly-changed-components-with-tests: ${{ steps.determine.outputs.directly-changed-components-with-tests }}
@@ -185,6 +277,7 @@ jobs:
cpp-unit-tests-run-all: ${{ steps.determine.outputs.cpp-unit-tests-run-all }}
cpp-unit-tests-components: ${{ steps.determine.outputs.cpp-unit-tests-components }}
component-test-batches: ${{ steps.determine.outputs.component-test-batches }}
validate-only-components: ${{ steps.determine.outputs.validate-only-components }}
benchmarks: ${{ steps.determine.outputs.benchmarks }}
steps:
- name: Check out code from GitHub
@@ -208,17 +301,27 @@ jobs:
GH_TOKEN: ${{ github.token }}
run: |
. venv/bin/activate
output=$(python script/determine-jobs.py)
EXTRA_ARGS=""
if [[ "${{ contains(github.event.pull_request.labels.*.name, 'ci-run-all') }}" == "true" ]]; then
EXTRA_ARGS="--force-all"
echo "::notice::ci-run-all label detected -- forcing every CI job to run"
fi
output=$(python script/determine-jobs.py $EXTRA_ARGS)
echo "Test determination output:"
echo "$output" | jq
# Extract individual fields
echo "core-ci=$(echo "$output" | jq -r '.core_ci')" >> $GITHUB_OUTPUT
echo "integration-tests=$(echo "$output" | jq -r '.integration_tests')" >> $GITHUB_OUTPUT
echo "integration-tests-run-all=$(echo "$output" | jq -r '.integration_tests_run_all')" >> $GITHUB_OUTPUT
echo "integration-test-files=$(echo "$output" | jq -c '.integration_test_files')" >> $GITHUB_OUTPUT
echo "integration-test-buckets=$(echo "$output" | jq -c '.integration_test_buckets')" >> $GITHUB_OUTPUT
echo "clang-tidy=$(echo "$output" | jq -r '.clang_tidy')" >> $GITHUB_OUTPUT
echo "clang-tidy-mode=$(echo "$output" | jq -r '.clang_tidy_mode')" >> $GITHUB_OUTPUT
echo "clang-tidy-full-scan=$(echo "$output" | jq -r '.clang_tidy_full_scan')" >> $GITHUB_OUTPUT
echo "python-linters=$(echo "$output" | jq -r '.python_linters')" >> $GITHUB_OUTPUT
echo "import-time=$(echo "$output" | jq -r '.import_time')" >> $GITHUB_OUTPUT
echo "device-builder=$(echo "$output" | jq -r '.device_builder')" >> $GITHUB_OUTPUT
echo "native-idf=$(echo "$output" | jq -r '.native_idf')" >> $GITHUB_OUTPUT
echo "native-idf-components=$(echo "$output" | jq -r '.native_idf_components')" >> $GITHUB_OUTPUT
echo "changed-components=$(echo "$output" | jq -c '.changed_components')" >> $GITHUB_OUTPUT
echo "changed-components-with-tests=$(echo "$output" | jq -c '.changed_components_with_tests')" >> $GITHUB_OUTPUT
echo "directly-changed-components-with-tests=$(echo "$output" | jq -c '.directly_changed_components_with_tests')" >> $GITHUB_OUTPUT
@@ -228,6 +331,7 @@ jobs:
echo "cpp-unit-tests-run-all=$(echo "$output" | jq -r '.cpp_unit_tests_run_all')" >> $GITHUB_OUTPUT
echo "cpp-unit-tests-components=$(echo "$output" | jq -c '.cpp_unit_tests_components')" >> $GITHUB_OUTPUT
echo "component-test-batches=$(echo "$output" | jq -c '.component_test_batches')" >> $GITHUB_OUTPUT
echo "validate-only-components=$(echo "$output" | jq -c '.validate_only_components')" >> $GITHUB_OUTPUT
echo "benchmarks=$(echo "$output" | jq -r '.benchmarks')" >> $GITHUB_OUTPUT
- name: Save components graph cache
if: github.ref == 'refs/heads/dev'
@@ -237,12 +341,16 @@ jobs:
key: components-graph-${{ hashFiles('esphome/components/**/*.py') }}
integration-tests:
name: Run integration tests
name: Run integration tests (${{ matrix.bucket.name }})
runs-on: ubuntu-latest
needs:
- common
- determine-jobs
if: needs.determine-jobs.outputs.integration-tests == 'true'
strategy:
fail-fast: false
matrix:
bucket: ${{ fromJson(needs.determine-jobs.outputs.integration-test-buckets) }}
steps:
- name: Check out code from GitHub
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@@ -257,31 +365,36 @@ jobs:
with:
path: venv
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-venv-${{ needs.common.outputs.cache-key }}
- name: Set up uv
# Only needed on cache miss to populate the venv.
if: steps.cache-venv.outputs.cache-hit != 'true'
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
enable-cache: true
# 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: Create Python virtual environment
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
python -m venv venv
. venv/bin/activate
python --version
pip install -r requirements.txt -r requirements_test.txt
pip install -e .
uv pip install -r requirements.txt -r requirements_test.txt
uv pip install -e .
- name: Register matcher
run: echo "::add-matcher::.github/workflows/matchers/pytest.json"
- name: Run integration tests
env:
INTEGRATION_TEST_FILES: ${{ needs.determine-jobs.outputs.integration-test-files }}
INTEGRATION_TESTS_RUN_ALL: ${{ needs.determine-jobs.outputs.integration-tests-run-all }}
# JSON array of test paths; parsed into a bash array below to avoid
# shell word-splitting / glob hazards.
BUCKET_TESTS: ${{ toJson(matrix.bucket.tests) }}
run: |
. venv/bin/activate
if [[ "$INTEGRATION_TESTS_RUN_ALL" == "true" ]]; then
echo "Running all integration tests"
pytest -vv --no-cov --tb=native -n auto tests/integration/
else
# Parse JSON array into bash array to avoid shell expansion issues
mapfile -t test_files < <(echo "$INTEGRATION_TEST_FILES" | jq -r '.[]')
echo "Running ${#test_files[@]} specific integration tests"
pytest -vv --no-cov --tb=native -n auto "${test_files[@]}"
fi
mapfile -t test_files < <(echo "$BUCKET_TESTS" | jq -r '.[]')
echo "Bucket ${{ matrix.bucket.name }}: running ${#test_files[@]} integration tests"
pytest -vv --no-cov --tb=native --durations=30 -n auto "${test_files[@]}"
cpp-unit-tests:
name: Run C++ unit tests
@@ -339,9 +452,12 @@ jobs:
echo "binary=$BINARY" >> $GITHUB_OUTPUT
- name: Run CodSpeed benchmarks
uses: CodSpeedHQ/action@658a901452bb54c799643e060733b7afe9121b8d # v4.14.0
uses: CodSpeedHQ/action@3194d9a39c4d46684cb44bf7207fc56626aad8fd # v4.15.1
with:
run: ${{ steps.build.outputs.binary }}
run: |
. venv/bin/activate
${{ steps.build.outputs.binary }}
pytest tests/benchmarks/python/ --codspeed --no-cov
mode: simulation
clang-tidy-single:
@@ -415,7 +531,13 @@ jobs:
id: check_full_scan
run: |
. venv/bin/activate
if python script/clang_tidy_hash.py --check; then
# determine-jobs.clang-tidy-full-scan is true when core C++ changed
# OR the ci-run-all label forced --force-all. Independent of the
# hash check, both must produce a full scan in the job itself.
if [ "${{ needs.determine-jobs.outputs.clang-tidy-full-scan }}" = "true" ]; then
echo "full_scan=true" >> $GITHUB_OUTPUT
echo "reason=determine_jobs" >> $GITHUB_OUTPUT
elif python script/clang_tidy_hash.py --check; then
echo "full_scan=true" >> $GITHUB_OUTPUT
echo "reason=hash_changed" >> $GITHUB_OUTPUT
else
@@ -427,7 +549,7 @@ jobs:
run: |
. venv/bin/activate
if [ "${{ steps.check_full_scan.outputs.full_scan }}" = "true" ]; then
echo "Running FULL clang-tidy scan (hash changed)"
echo "Running FULL clang-tidy scan (reason: ${{ steps.check_full_scan.outputs.reason }})"
script/clang-tidy --all-headers --fix ${{ matrix.options }} ${{ matrix.ignore_errors && '|| true' || '' }}
else
echo "Running clang-tidy on changed files only"
@@ -487,7 +609,13 @@ jobs:
id: check_full_scan
run: |
. venv/bin/activate
if python script/clang_tidy_hash.py --check; then
# determine-jobs.clang-tidy-full-scan is true when core C++ changed
# OR the ci-run-all label forced --force-all. Independent of the
# hash check, both must produce a full scan in the job itself.
if [ "${{ needs.determine-jobs.outputs.clang-tidy-full-scan }}" = "true" ]; then
echo "full_scan=true" >> $GITHUB_OUTPUT
echo "reason=determine_jobs" >> $GITHUB_OUTPUT
elif python script/clang_tidy_hash.py --check; then
echo "full_scan=true" >> $GITHUB_OUTPUT
echo "reason=hash_changed" >> $GITHUB_OUTPUT
else
@@ -499,7 +627,7 @@ jobs:
run: |
. venv/bin/activate
if [ "${{ steps.check_full_scan.outputs.full_scan }}" = "true" ]; then
echo "Running FULL clang-tidy scan (hash changed)"
echo "Running FULL clang-tidy scan (reason: ${{ steps.check_full_scan.outputs.reason }})"
script/clang-tidy --all-headers --fix --environment esp32-arduino-tidy
else
echo "Running clang-tidy on changed files only"
@@ -576,7 +704,13 @@ jobs:
id: check_full_scan
run: |
. venv/bin/activate
if python script/clang_tidy_hash.py --check; then
# determine-jobs.clang-tidy-full-scan is true when core C++ changed
# OR the ci-run-all label forced --force-all. Independent of the
# hash check, both must produce a full scan in the job itself.
if [ "${{ needs.determine-jobs.outputs.clang-tidy-full-scan }}" = "true" ]; then
echo "full_scan=true" >> $GITHUB_OUTPUT
echo "reason=determine_jobs" >> $GITHUB_OUTPUT
elif python script/clang_tidy_hash.py --check; then
echo "full_scan=true" >> $GITHUB_OUTPUT
echo "reason=hash_changed" >> $GITHUB_OUTPUT
else
@@ -588,7 +722,7 @@ jobs:
run: |
. venv/bin/activate
if [ "${{ steps.check_full_scan.outputs.full_scan }}" = "true" ]; then
echo "Running FULL clang-tidy scan (hash changed)"
echo "Running FULL clang-tidy scan (reason: ${{ steps.check_full_scan.outputs.reason }})"
script/clang-tidy --all-headers --fix ${{ matrix.options }}
else
echo "Running clang-tidy on changed files only"
@@ -699,20 +833,142 @@ jobs:
echo "Config validation passed! Starting compilation..."
echo ""
# Compute the compile-stage component list. Components whose only
# changes are validate.*.yaml files are config-only -- their source
# and test fixtures didn't move, so rebuilding firmware adds no
# signal. Subtract them from this batch before invoking compile.
validate_only_json='${{ needs.determine-jobs.outputs.validate-only-components }}'
if [ -z "$validate_only_json" ]; then
validate_only_json='[]'
fi
if ! validate_only_csv=$(echo "$validate_only_json" | jq -r 'join(",")'); then
echo "::error::Failed to render validate-only-components as CSV from: $validate_only_json"
exit 1
fi
if [ -z "$validate_only_csv" ]; then
compile_csv="$components_csv"
else
components_sorted=$(echo "$components_csv" | tr ',' '\n' | sort -u)
validate_sorted=$(echo "$validate_only_csv" | tr ',' '\n' | sort -u)
if ! diff_out=$(comm -23 <(echo "$components_sorted") <(echo "$validate_sorted")); then
echo "::error::Failed to compute compile component subset."
exit 1
fi
compile_csv=$(echo "$diff_out" | paste -sd ',' -)
skipped=$(comm -12 <(echo "$components_sorted") <(echo "$validate_sorted") | paste -sd ',' -)
if [ -n "$skipped" ]; then
echo "Validate-only components in this batch (skipping compile): $skipped"
fi
fi
# Show disk space before compilation
echo "Disk space before compilation:"
df -h
echo ""
# Run compilation with grouping and isolation
python3 script/test_build_components.py -e compile -c "$components_csv" -f --isolate "$directly_changed_csv"
if [ -n "$compile_csv" ]; then
# Run compilation with grouping and isolation
python3 script/test_build_components.py -e compile -c "$compile_csv" -f --isolate "$directly_changed_csv"
else
echo "All components in this batch are validate-only -- skipping compile stage."
fi
test-native-idf:
name: Test components with native ESP-IDF
runs-on: ubuntu-24.04
needs:
- common
- determine-jobs
if: github.event_name == 'pull_request' && needs.determine-jobs.outputs.native-idf == 'true'
env:
ESPHOME_ESP_IDF_PREFIX: ~/.esphome-idf
# Comma-joined subset of the native-IDF representative component list,
# computed by script/determine-jobs.py (native_idf_components_to_test).
# Single source of truth -- the full list lives in
# script/determine-jobs.py::NATIVE_IDF_TEST_COMPONENTS.
TEST_COMPONENTS: ${{ needs.determine-jobs.outputs.native-idf-components }}
steps:
- name: Check out code from GitHub
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Restore Python
uses: ./.github/actions/restore-python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
cache-key: ${{ needs.common.outputs.cache-key }}
- name: Cache ESPHome
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.esphome-idf
key: ${{ runner.os }}-esphome-${{ needs.common.outputs.cache-key }}
- name: Run native ESP-IDF compile test
run: |
. venv/bin/activate
# Check if /mnt has more free space than / before bind mounting
# Extract available space in KB for comparison
root_avail=$(df -k / | awk 'NR==2 {print $4}')
mnt_avail=$(df -k /mnt 2>/dev/null | awk 'NR==2 {print $4}')
echo "Available space: / has ${root_avail}KB, /mnt has ${mnt_avail}KB"
# Only use /mnt if it has more space than /
if [ -n "$mnt_avail" ] && [ "$mnt_avail" -gt "$root_avail" ]; then
echo "Using /mnt for build files (more space available)"
# Bind mount PlatformIO directory to /mnt (tools, packages, build cache all go there)
sudo mkdir -p /mnt/esphome-idf
sudo chown $USER:$USER /mnt/esphome-idf
mkdir -p ~/.esphome-idf
sudo mount --bind /mnt/esphome-idf ~/.esphome-idf
# Bind mount test build directory to /mnt
sudo mkdir -p /mnt/test_build_components_build
sudo chown $USER:$USER /mnt/test_build_components_build
mkdir -p tests/test_build_components/build
sudo mount --bind /mnt/test_build_components_build tests/test_build_components/build
else
echo "Using / for build files (more space available than /mnt or /mnt unavailable)"
fi
echo "Testing components: $TEST_COMPONENTS"
echo ""
# Show disk space before validation (after bind mounts setup)
echo "Disk space before config validation:"
df -h
echo ""
# Run config validation (auto-grouped by test_build_components.py)
python3 script/test_build_components.py -e config -t esp32-idf -c "$TEST_COMPONENTS" -f --toolchain esp-idf
echo ""
echo "Config validation passed! Starting compilation..."
echo ""
# Show disk space before compilation
echo "Disk space before compilation:"
df -h
echo ""
# Run compilation (auto-grouped by test_build_components.py)
python3 script/test_build_components.py -e compile -t esp32-idf -c "$TEST_COMPONENTS" -f --toolchain esp-idf
- name: Save ESPHome cache
if: github.ref == 'refs/heads/dev'
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.esphome-idf
key: ${{ runner.os }}-esphome-${{ needs.common.outputs.cache-key }}
pre-commit-ci-lite:
name: pre-commit.ci lite
runs-on: ubuntu-latest
needs:
- common
if: github.event_name == 'pull_request' && !startsWith(github.base_ref, 'beta') && !startsWith(github.base_ref, 'release')
- determine-jobs
if: github.event_name == 'pull_request' && !startsWith(github.base_ref, 'beta') && !startsWith(github.base_ref, 'release') && needs.determine-jobs.outputs.core-ci == 'true'
steps:
- name: Check out code from GitHub
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@@ -986,8 +1242,8 @@ jobs:
- memory-impact-pr-branch
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && fromJSON(needs.determine-jobs.outputs.memory_impact).should_run == 'true' && needs.memory-impact-target-branch.outputs.skip != 'true'
permissions:
contents: read
pull-requests: write
contents: read # actions/checkout to load the comment-posting script
pull-requests: write # ci_memory_impact_comment.py posts/updates the memory-impact comment on the PR
env:
GH_TOKEN: ${{ github.token }}
steps:
@@ -1036,7 +1292,9 @@ jobs:
- clang-tidy-nosplit
- clang-tidy-split
- determine-jobs
- device-builder
- test-build-components-split
- test-native-idf
- pre-commit-ci-lite
- memory-impact-target-branch
- memory-impact-pr-branch

View File

@@ -6,8 +6,8 @@ on:
types: [opened, reopened]
permissions:
pull-requests: write
issues: write
pull-requests: write # pulls.update to close the PR opened from a fork's default branch
issues: write # issues.createComment to explain to the contributor why the PR was closed
jobs:
close:

View File

@@ -15,9 +15,9 @@ on:
- beta
permissions:
issues: write
pull-requests: read
contents: read
issues: write # issues.addLabels / removeLabel to manage the 'code-owner-approved' label on the PR
pull-requests: read # listReviews to determine whether a codeowner has approved
contents: read # actions/checkout to read CODEOWNERS and the shared codeowners.js helper
jobs:
codeowner-approved:

View File

@@ -17,9 +17,10 @@ on:
- release
- beta
# PR/review writes (requestReviewers, issues.createComment) are performed with the App token minted below,
# so the workflow's GITHUB_TOKEN only needs read access for checkout.
permissions:
pull-requests: write
contents: read
contents: read # actions/checkout to read CODEOWNERS and the shared codeowners.js helper
jobs:
request-codeowner-reviews:
@@ -32,9 +33,20 @@ jobs:
with:
ref: ${{ github.event.pull_request.base.sha }}
- 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 }}
# Scope the minted App token to the minimum needed by the github-script step below.
permission-pull-requests: write # pulls.listFiles, pulls.get, pulls.listReviews, pulls.requestReviewers
permission-issues: write # issues.listComments and issues.createComment (PR comments use the issues API)
- name: Request reviews from component codeowners
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ steps.generate-token.outputs.token }}
script: |
const { loadCodeowners, getEffectiveOwners } = require('./.github/scripts/codeowners.js');

View File

@@ -16,6 +16,9 @@ on:
schedule:
- cron: "30 18 * * 4"
# Deny by default; the analyze job opts in to exactly what it needs.
permissions: {}
jobs:
analyze:
name: Analyze (${{ matrix.language }})
@@ -26,15 +29,10 @@ jobs:
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
permissions:
# required for all workflows
security-events: write
# required to fetch internal or private CodeQL packs
packages: read
# only required for workflows in private repositories
actions: read
contents: read
security-events: write # upload CodeQL SARIF results to the Code Scanning API
packages: read # fetch internal or private CodeQL query packs
actions: read # required by codeql-action when run from a private repo
contents: read # actions/checkout to scan the repository
strategy:
fail-fast: false
@@ -58,7 +56,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
@@ -86,6 +84,6 @@ jobs:
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
with:
category: "/language:${{matrix.language}}"

View File

@@ -0,0 +1,119 @@
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,
});
}

View File

@@ -4,20 +4,29 @@ on:
pull_request_target:
types: [opened, synchronize]
permissions:
contents: read # Needed to fetch PR details
issues: write # Needed to create and update comments (PR comments are managed via the issues REST API)
pull-requests: write # also needed?
# 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:
external-comment:
name: External component comment
runs-on: ubuntu-latest
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 external component comment
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
github-token: ${{ steps.generate-token.outputs.token }}
script: |
// Generate external component usage instructions
function generateExternalComponentInstructions(prNumber, componentNames, owner, repo) {

View File

@@ -9,8 +9,8 @@ on:
types: [labeled]
permissions:
issues: write
contents: read
issues: write # issues.createComment to mention component codeowners on the newly labelled issue
contents: read # repos.getContent to fetch CODEOWNERS from the default branch
jobs:
notify-codeowners:

View File

@@ -6,6 +6,12 @@ on:
- cron: "30 0 * * *" # Run daily at 00:30 UTC
workflow_dispatch:
# Deny by default; the lock job opts in to exactly what the reusable workflow needs.
permissions: {}
jobs:
lock:
uses: esphome/workflows/.github/workflows/lock.yml@3c4e8446aa1029f1c346a482034b3ee1489077ca # 2026.4.0
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

View File

@@ -8,8 +8,8 @@ on:
- beta
permissions:
contents: read
pull-requests: read
contents: read # actions/checkout to load detect-tags.js
pull-requests: read # pulls.listFiles to map changed files to component/core/dashboard/ci tags
jobs:
check:
@@ -29,10 +29,11 @@ jobs:
} = require('./.github/scripts/detect-tags.js');
const title = context.payload.pull_request.title;
const author = context.payload.pull_request.user.login;
const user = context.payload.pull_request.user;
// Skip bot PRs (e.g. dependabot) - they have their own title format
if (author === 'dependabot[bot]') {
// Skip bot PRs (e.g. dependabot, esphome[bot] device-class sync) -
// they have their own title formats.
if (user.type === 'Bot') {
return;
}
@@ -68,14 +69,15 @@ jobs:
return;
}
// Check for angle brackets not wrapped in backticks.
// Astro docs MDX treats bare < as JSX component opening tags.
// Check for MDX syntax characters not wrapped in backticks.
// Astro docs MDX treats bare `<` as JSX component opening tags and
// bare `{` as JS expressions, so both must be escaped in changelog entries.
const stripped = title.replace(/`[^`]*`/g, '');
if (/[<>]/.test(stripped)) {
if (/[<>{}]/.test(stripped)) {
core.setFailed(
'PR title contains `<` or `>` not wrapped in backticks.\n' +
'Astro docs MDX interprets bare `<` as JSX components.\n' +
'Please wrap angle brackets with backticks, e.g.: [component] Add `<feature>` support'
'PR title contains `<`, `>`, `{`, or `}` not wrapped in backticks.\n' +
'Astro docs MDX interprets bare `<` as JSX components and bare `{` as JS expressions.\n' +
'Please wrap these characters with backticks, e.g.: [component] Add `<feature>` support'
);
return;
}

View File

@@ -9,7 +9,7 @@ on:
- cron: "0 2 * * *"
permissions:
contents: read
contents: read # actions/checkout for all jobs; deploy jobs add their own scopes when they need to write
jobs:
init:
@@ -57,8 +57,8 @@ jobs:
if: github.repository == 'esphome/esphome' && github.event_name == 'release'
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
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
- name: Set up Python
@@ -78,8 +78,8 @@ jobs:
name: Build ESPHome ${{ matrix.platform.arch }}
if: github.repository == 'esphome/esphome'
permissions:
contents: read
packages: write
contents: read # actions/checkout to load Dockerfile and build context
packages: write # docker/login-action + build-push-action push image digests to ghcr.io
runs-on: ${{ matrix.platform.os }}
needs: [init]
strategy:
@@ -99,15 +99,15 @@ jobs:
python-version: "3.11"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: Log in to docker hub
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Log in to the GitHub container registry
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ghcr.io
username: ${{ github.actor }}
@@ -152,8 +152,8 @@ jobs:
- deploy-docker
if: github.repository == 'esphome/esphome'
permissions:
contents: read
packages: write
contents: read # actions/checkout to load Dockerfile and build context
packages: write # docker/login-action + build-push-action push image digests to ghcr.io
strategy:
fail-fast: false
matrix:
@@ -178,17 +178,17 @@ jobs:
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: Log in to docker hub
if: matrix.registry == 'dockerhub'
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.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@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ghcr.io
username: ${{ github.actor }}
@@ -212,72 +212,6 @@ jobs:
docker buildx imagetools create $(jq -Rcnr 'inputs | . / "," | map("-t " + .) | join(" ")' <<< "${{ steps.tags.outputs.tags}}") \
$(printf '${{ steps.tags.outputs.image }}@sha256:%s ' *)
deploy-ha-addon-repo:
if: github.repository == 'esphome/esphome' && needs.init.outputs.branch_build == 'false'
runs-on: ubuntu-latest
needs:
- init
- deploy-manifest
steps:
- name: Generate a token
id: generate-token
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
with:
app-id: ${{ secrets.ESPHOME_GITHUB_APP_ID }}
private-key: ${{ secrets.ESPHOME_GITHUB_APP_PRIVATE_KEY }}
owner: esphome
repositories: home-assistant-addon
- name: Trigger Workflow
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ steps.generate-token.outputs.token }}
script: |
let description = "ESPHome";
if (context.eventName == "release") {
description = ${{ toJSON(github.event.release.body) }};
}
github.rest.actions.createWorkflowDispatch({
owner: "esphome",
repo: "home-assistant-addon",
workflow_id: "bump-version.yml",
ref: "main",
inputs: {
version: "${{ needs.init.outputs.tag }}",
content: description
}
})
deploy-esphome-schema:
if: github.repository == 'esphome/esphome' && needs.init.outputs.branch_build == 'false'
runs-on: ubuntu-latest
needs: [init]
environment: ${{ needs.init.outputs.deploy_env }}
steps:
- name: Generate a token
id: generate-token
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
with:
app-id: ${{ secrets.ESPHOME_GITHUB_APP_ID }}
private-key: ${{ secrets.ESPHOME_GITHUB_APP_PRIVATE_KEY }}
owner: esphome
repositories: esphome-schema
- name: Trigger Workflow
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ steps.generate-token.outputs.token }}
script: |
github.rest.actions.createWorkflowDispatch({
owner: "esphome",
repo: "esphome-schema",
workflow_id: "generate-schemas.yml",
ref: "main",
inputs: {
version: "${{ needs.init.outputs.tag }}",
}
})
version-notifier:
if: github.repository == 'esphome/esphome' && needs.init.outputs.branch_build == 'false'
runs-on: ubuntu-latest
@@ -287,19 +221,20 @@ jobs:
steps:
- name: Generate a token
id: generate-token
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ secrets.ESPHOME_GITHUB_APP_ID }}
client-id: ${{ vars.ESPHOME_GITHUB_APP_CLIENT_ID }}
private-key: ${{ secrets.ESPHOME_GITHUB_APP_PRIVATE_KEY }}
owner: esphome
repositories: version-notifier
permission-actions: write # actions.createWorkflowDispatch on the target repo (only API call made with this token)
- name: Trigger Workflow
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ steps.generate-token.outputs.token }}
script: |
github.rest.actions.createWorkflowDispatch({
await github.rest.actions.createWorkflowDispatch({
owner: "esphome",
repo: "version-notifier",
workflow_id: "notify.yml",

View File

@@ -7,8 +7,8 @@ on:
workflow_dispatch:
permissions:
issues: write
pull-requests: write
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
@@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Stale
uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0
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

View File

@@ -4,6 +4,9 @@ on:
pull_request:
types: [opened, reopened, labeled, unlabeled, synchronize]
permissions:
pull-requests: read # issues.listLabelsOnIssue to detect blocking labels (needs-docs, merge-after-release, chained-pr)
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true

View File

@@ -6,12 +6,27 @@ on:
schedule:
- cron: "45 6 * * *"
# 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/checkout for this repo and home-assistant/core
jobs:
sync:
name: Sync Device Classes
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 }}
# Scope the minted App token to the minimum needed by peter-evans/create-pull-request.
permission-contents: write # git.createCommit + refs.create/update to push the sync/device-classes branch
permission-pull-requests: write # pulls.create / pulls.update to open or refresh the sync PR
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@@ -26,19 +41,56 @@ jobs:
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`` /
# ``script/run-in-env.py`` steps find the deps without a
# ``uv run`` prefix.
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
enable-cache: true
# 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 Home Assistant
run: |
python -m pip install --upgrade pip
pip install -e lib/home-assistant
pip install -r requirements_test.txt pre-commit
uv pip install --system -e lib/home-assistant
uv pip install --system -r requirements.txt -r requirements_test.txt pre-commit
- name: Sync
run: |
python ./script/sync-device_class.py
- name: Run pre-commit hooks
run: |
python script/run-in-env.py pre-commit run --all-files
- name: Apply pre-commit auto-fixes
# First pass: let formatters (ruff, end-of-file-fixer, etc.) modify
# files. pre-commit 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:
# - 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.
# - pylint surfaces import-error / relative-beyond-top-level
# noise here because this workflow installs only a subset of
# 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
- name: Verify pre-commit 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
# above for the same reasons.
env:
SKIP: pylint,no-commit-to-branch
run: python script/run-in-env.py pre-commit run --all-files
- name: Commit changes
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
@@ -50,4 +102,4 @@ jobs:
delete-branch: true
title: "Synchronise Device Classes from Home Assistant"
body-path: .github/PULL_REQUEST_TEMPLATE.md
token: ${{ secrets.DEVICE_CLASS_SYNC_TOKEN }}
token: ${{ steps.generate-token.outputs.token }}

1
.gitignore vendored
View File

@@ -146,5 +146,6 @@ sdkconfig.*
/components
/managed_components
/dependencies.lock
api-docs/

View File

@@ -11,7 +11,7 @@ ci:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.15.11
rev: v0.15.14
hooks:
# Run the linter.
- id: ruff
@@ -55,7 +55,7 @@ repos:
hooks:
- id: pylint
name: pylint
entry: python3 script/run-in-env.py pylint
entry: python script/run-in-env.py pylint
language: system
types: [python]
files: ^esphome/.+\.py$
@@ -68,5 +68,5 @@ repos:
additional_dependencies: []
- id: ci-custom
name: ci-custom
entry: python3 script/run-in-env.py script/ci-custom.py
entry: python script/run-in-env.py script/ci-custom.py
language: system

View File

@@ -398,13 +398,23 @@ This document provides essential context for AI models interacting with this pro
│ ├── i2c/ # I2C bus
│ └── spi/ # SPI bus
└── components/[component]/
├── common.yaml # Component-only config (no bus definitions)
├── test.esp32-idf.yaml
├── test.esp8266-ard.yaml
── test.rp2040-ard.yaml
├── common.yaml # Component-only config (no bus definitions)
├── test.esp32-idf.yaml # config + compile
├── test.esp8266-ard.yaml # config + compile
── test-variant.esp32-idf.yaml # variant test, config + compile
├── validate.esp32-idf.yaml # config-only (never compiled)
└── validate-legacy.esp32-idf.yaml # config-only variant
```
Run them using `script/test_build_components`. Use `-c <component>` to test specific components and `-t <target>` for specific platforms.
* **Config-only test files (`validate.*.yaml`):** Use this prefix when a YAML file only needs to exercise schema/validation paths and does not need to be compiled. CI runs `validate.*.yaml` files with `esphome config` only and skips them during compile. The grammar mirrors `test.*.yaml`:
- `validate.<platform>.yaml` — base config-only test
- `validate-<variant>.<platform>.yaml` — config-only variant
Use this for things like deprecated-syntax migration tests, schema edge cases, or platform-specific validation branches where building firmware adds no signal. A component may have any mix of `test.*.yaml` and `validate.*.yaml` files. Validate files never participate in bus-grouping; each one runs as its own `esphome config` invocation.
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/`:
```yaml
# test.esp32-idf.yaml — use packages for buses

View File

@@ -1 +1 @@
.ai/instructions.md
AGENTS.md

View File

@@ -347,6 +347,7 @@ esphome/components/modbus_controller/select/* @martgras @stegm
esphome/components/modbus_controller/sensor/* @martgras
esphome/components/modbus_controller/switch/* @martgras
esphome/components/modbus_controller/text_sensor/* @martgras
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
@@ -415,6 +416,7 @@ esphome/components/resampler/speaker/* @kahrendt
esphome/components/restart/* @esphome/core
esphome/components/rf_bridge/* @jesserockz
esphome/components/rgbct/* @jesserockz
esphome/components/ring_buffer/* @kahrendt
esphome/components/rp2040/* @jesserockz
esphome/components/rp2040_ble/* @bdraco
esphome/components/rp2040_pio_led_strip/* @Papa-DMan

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.5.0-dev
PROJECT_NUMBER = 2026.6.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

View File

@@ -1 +1 @@
.ai/instructions.md
AGENTS.md

View File

@@ -13,12 +13,16 @@ 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.clibz used by ESP-IDF's idf-component-manager)
# (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; \
apk add --no-cache build-base libusb; \
else \
apt-get update \
&& apt-get install -y --no-install-recommends build-essential \
&& apt-get install -y --no-install-recommends build-essential libusb-1.0-0 \
&& rm -rf /var/lib/apt/lists/*; \
fi

View File

@@ -0,0 +1,22 @@
#!/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."

View File

@@ -49,5 +49,12 @@ 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)"
fi
bashio::log.info "Starting ESPHome dashboard..."
exec esphome dashboard /config/esphome --socket /var/run/esphome.sock --ha-addon

View File

@@ -4,6 +4,14 @@
# 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

View File

@@ -5,6 +5,14 @@
# 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

File diff suppressed because it is too large Load Diff

View File

@@ -24,7 +24,7 @@ from .helpers import (
from .toolchain import find_tool, resolve_tool_path, run_tool
if TYPE_CHECKING:
from esphome.platformio_api import IDEData
from esphome.platformio.toolchain import IDEData
_LOGGER = logging.getLogger(__name__)
@@ -793,8 +793,11 @@ class MemoryAnalyzer:
"""Scan ESPHome source object files to map extern "C" symbols to components.
When no linker map file is available, this uses ``nm`` to scan ``.o`` files
under ``src/esphome/`` and build a symbol-to-component mapping. This catches
``extern "C"`` functions and other symbols that lack C++ namespace prefixes.
under ``src/`` (including ``src/main.cpp.o`` and everything beneath
``src/esphome/``) and build a symbol-to-component mapping. This catches
``extern "C"`` functions, the ESPHome-generated ``setup()``/``loop()``
entry points in ``main.cpp``, and other symbols that lack C++ namespace
prefixes.
Skips scanning if ``_source_symbol_map`` was already populated by
``_parse_map_file()``.
@@ -806,12 +809,12 @@ class MemoryAnalyzer:
if obj_dir is None:
return
# Find ESPHome source object files
esphome_src_dir = obj_dir / "src" / "esphome"
if not esphome_src_dir.is_dir():
# Scan all ESPHome-owned source object files: src/main.cpp.o and src/esphome/...
src_dir = obj_dir / "src"
if not src_dir.is_dir():
return
obj_files = sorted(esphome_src_dir.rglob("*.o"))
obj_files = sorted(src_dir.rglob("*.o"))
if not obj_files:
return
@@ -1064,6 +1067,10 @@ class MemoryAnalyzer:
if component_name in self.external_components:
return f"{_COMPONENT_PREFIX_EXTERNAL}{component_name}"
# ESPHome-generated entry point: src/main.cpp.o (contains setup()/loop())
if len(parts) >= 2 and parts[-2:] == ("src", "main.cpp.o"):
return _COMPONENT_CORE
# ESPHome core: src/esphome/core/... or src/esphome/...
if "core" in parts and "esphome" in parts:
return _COMPONENT_CORE

View File

@@ -739,7 +739,7 @@ def main():
import json
from pathlib import Path
from esphome.platformio_api import IDEData
from esphome.platformio.toolchain import IDEData
build_path = Path(build_dir)

View File

@@ -127,7 +127,7 @@ def validate_potentially_or_condition(value):
return validate_condition(value)
DelayAction = cg.esphome_ns.class_("DelayAction", Action, cg.Component)
DelayAction = cg.esphome_ns.class_("DelayAction", Action)
LambdaAction = cg.esphome_ns.class_("LambdaAction", Action)
StatelessLambdaAction = cg.esphome_ns.class_("StatelessLambdaAction", Action)
IfAction = cg.esphome_ns.class_("IfAction", Action)
@@ -396,7 +396,6 @@ async def delay_action_to_code(
args: TemplateArgsType,
) -> MockObj:
var = cg.new_Pvariable(action_id, template_arg)
await cg.register_component(var, {})
template_ = await cg.templatable(config, args, cg.uint32)
cg.add(var.set_delay(template_))
return var
@@ -597,7 +596,7 @@ async def component_resume_action_to_code(
comp = await cg.get_variable(config[CONF_ID])
var = cg.new_Pvariable(action_id, template_arg, comp)
if CONF_UPDATE_INTERVAL in config:
template_ = await cg.templatable(config[CONF_UPDATE_INTERVAL], args, int)
template_ = await cg.templatable(config[CONF_UPDATE_INTERVAL], args, cg.uint32)
cg.add(var.set_update_interval(template_))
return var

View File

@@ -3,17 +3,22 @@
import json
from pathlib import Path
from esphome.components.esp32 import get_esp32_variant
from esphome.components.esp32 import get_esp32_variant, idf_version
import esphome.config_validation as cv
from esphome.core import CORE
from esphome.helpers import mkdir_p, write_file_if_changed
from esphome.writer import update_storage_json
def get_available_components() -> list[str] | None:
"""Get list of available ESP-IDF components from project_description.json.
"""Get list of built-in ESP-IDF components from project_description.json.
Returns only internal ESP-IDF components, excluding external/managed
components (from idf_component.yml).
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.
"""
if CORE.build_path is None:
return None
project_desc = Path(CORE.build_path) / "build" / "project_description.json"
if not project_desc.exists():
return None
@@ -30,9 +35,9 @@ def get_available_components() -> list[str] | None:
if name == "src":
continue
# Exclude managed/external components
# Exclude IDF-managed and converted-PIO components (external).
comp_dir = info.get("dir", "")
if "managed_components" in comp_dir:
if "managed_components" in comp_dir or "pio_components" in comp_dir:
continue
result.append(name)
@@ -47,23 +52,90 @@ def has_discovered_components() -> bool:
return get_available_components() is not None
def get_project_cmakelists() -> str:
"""Generate the top-level CMakeLists.txt for ESP-IDF project."""
def get_project_cmakelists(minimal: bool = False) -> 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.
"""
# Get IDF target from ESP32 variant (e.g., ESP32S3 -> esp32s3)
variant = get_esp32_variant()
idf_target = variant.lower().replace("-", "")
# Extract compile definitions from build flags (-DXXX -> XXX)
compile_defs = [flag for flag in CORE.build_flags if flag.startswith("-D")]
# 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
# --format=raw because the legacy mode doesn't support it.
size_ng_flag = "--ng" if idf_version() < cv.Version(6, 0, 0) else ""
# Project-wide compile options: -D defines and -W warning flags (skip
# -Wl, linker flags — those go on the src component via
# target_link_options below). Emitted via idf_build_set_property so the
# flags propagate to every IDF component (including managed ones like
# 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,"))
]
extra_compile_options = "\n".join(
f'idf_build_set_property(COMPILE_OPTIONS "{compile_def}" APPEND)'
for compile_def in compile_defs
f'idf_build_set_property(COMPILE_OPTIONS "{flag}" APPEND)'
for flag in project_compile_opts
)
# 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.
#
# Emit via idf_build_set_property (not plain set()) so the value is
# serialised into build_properties.temp.cmake and visible to IDF's
# early requirements-expansion pass (component_get_requirements.cmake
# 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()
)
# Built-in IDF components exposed via our own property (not IDF's
# __COMPONENT_REQUIRES_COMMON, which would append them to every
# 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.
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 [])
)
)
return f"""\
# Auto-generated by ESPHome
cmake_minimum_required(VERSION 3.16)
# On Windows, Ninja can fail with:
# "CreateProcess: The parameter is incorrect (is the command line too long?)"
# when compiler/linker command lines exceed the OS length limit.
#
# The following settings force CMake/Ninja to use *response files* (@file.rsp)
# to pass long lists of includes, objects, and other arguments indirectly,
# avoiding command-line length limits and fixing the build failure.
#
# This is especially useful for large ESP-IDF / ESPHome projects with many
# source files or include directories.
set(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES 1)
set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES 1)
set(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1)
set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 1)
set(CMAKE_NINJA_FORCE_RESPONSE_FILE 1)
set(IDF_TARGET {idf_target})
set(EXTRA_COMPONENT_DIRS ${{CMAKE_SOURCE_DIR}}/src)
@@ -71,50 +143,67 @@ include($ENV{{IDF_PATH}}/tools/cmake/project.cmake)
{extra_compile_options}
{managed_components_property}
{builtin_components_property}
project({CORE.name})
# Emit raw JSON size data for ESPHome to read post-build.
add_custom_command(
TARGET ${{CMAKE_PROJECT_NAME}}.elf POST_BUILD
COMMAND ${{PYTHON}} -m esp_idf_size {size_ng_flag} --format=raw
-o ${{CMAKE_BINARY_DIR}}/esp_idf_size.json
${{CMAKE_PROJECT_NAME}}.map
WORKING_DIRECTORY ${{CMAKE_BINARY_DIR}}
VERBATIM
)
"""
def get_component_cmakelists(minimal: bool = False) -> str:
"""Generate the main component CMakeLists.txt."""
idf_requires = [] if minimal else (get_available_components() or [])
requires_str = " ".join(idf_requires)
def get_component_cmakelists() -> str:
"""Generate the main component CMakeLists.txt.
# Extract compile options (-W flags, excluding linker flags)
compile_opts = [
flag
for flag in CORE.build_flags
if flag.startswith("-W") and not flag.startswith("-Wl,")
]
compile_opts_str = "\n ".join(sorted(compile_opts)) if compile_opts else ""
# Extract linker options (-Wl, flags)
REQUIRES pulls in the discovered built-in IDF components via the
project-level variables set in the top-level CMakeLists.
"""
# 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 ""
return f"""\
# Auto-generated by ESPHome
file(GLOB_RECURSE app_sources
"${{CMAKE_CURRENT_SOURCE_DIR}}/*.cpp"
"${{CMAKE_CURRENT_SOURCE_DIR}}/*.c"
"${{CMAKE_CURRENT_SOURCE_DIR}}/esphome/*.cpp"
"${{CMAKE_CURRENT_SOURCE_DIR}}/esphome/*.c"
)
# CONFIGURE_DEPENDS asks CMake to re-check the glob each build so test
# runs that reuse the build dir don't compile stale source paths. It's
# invalid in script mode (cmake -P), which is how IDF's
# component_get_requirements.cmake includes us, so skip it there.
if(CMAKE_SCRIPT_MODE_FILE)
file(GLOB_RECURSE app_sources
"${{CMAKE_CURRENT_SOURCE_DIR}}/*.cpp"
"${{CMAKE_CURRENT_SOURCE_DIR}}/*.c"
"${{CMAKE_CURRENT_SOURCE_DIR}}/esphome/*.cpp"
"${{CMAKE_CURRENT_SOURCE_DIR}}/esphome/*.c"
)
else()
file(GLOB_RECURSE app_sources CONFIGURE_DEPENDS
"${{CMAKE_CURRENT_SOURCE_DIR}}/*.cpp"
"${{CMAKE_CURRENT_SOURCE_DIR}}/*.c"
"${{CMAKE_CURRENT_SOURCE_DIR}}/esphome/*.cpp"
"${{CMAKE_CURRENT_SOURCE_DIR}}/esphome/*.c"
)
endif()
idf_component_register(
SRCS ${{app_sources}}
INCLUDE_DIRS "." "esphome"
REQUIRES {requires_str}
REQUIRES ${{ESPHOME_PROJECT_BUILTIN_COMPONENTS}}
)
# Apply C++ standard
target_compile_features(${{COMPONENT_LIB}} PUBLIC cxx_std_20)
# ESPHome compile options
target_compile_options(${{COMPONENT_LIB}} PUBLIC
{compile_opts_str}
)
# ESPHome linker options
target_link_options(${{COMPONENT_LIB}} PUBLIC
{link_opts_str}
@@ -124,17 +213,22 @@ target_link_options(${{COMPONENT_LIB}} PUBLIC
def write_project(minimal: bool = False) -> 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(),
get_project_cmakelists(minimal=minimal),
)
# Write component CMakeLists.txt in src/
write_file_if_changed(
CORE.relative_src_path("CMakeLists.txt"),
get_component_cmakelists(minimal=minimal),
get_component_cmakelists(),
)

View File

@@ -98,11 +98,13 @@ _KNOWN_FILE_EXTENSIONS = frozenset(
)
# Matches !secret references in YAML text. This is intentionally a simple
# regex scan rather than a YAML parse — it may match inside comments or
# multi-line strings, which is the conservative direction (include more
# secrets rather than fewer).
_SECRET_RE = re.compile(r"!secret\s+(\S+)")
# Matches !secret references in YAML text. An optional surrounding
# quote pair around the key is allowed and ignored: YAML treats
# ``!secret 'foo'`` and ``!secret foo`` as the same key. This is
# intentionally a simple regex scan rather than a YAML parse — it may
# match inside comments or multi-line strings, which is the conservative
# direction (include more secrets rather than fewer).
_SECRET_RE = re.compile(r"""!secret\s+['"]?([^\s'"]+)""")
def _find_used_secret_keys(yaml_files: list[Path]) -> set[str]:
@@ -258,42 +260,20 @@ class ConfigBundleCreator:
def _discover_yaml_includes(self) -> None:
"""Discover YAML files loaded during config parsing.
Deliberately uses a fresh re-parse and force-loads every deferred
``IncludeFile`` to include *all* potentially-reachable includes,
even branches not selected by the local substitutions. Bundles are
meant to be compiled on another system where command-line
substitution overrides may choose a different branch — e.g.
``!include network/${eth_model}/config.yaml`` must ship every
candidate so the remote build can pick any one.
Entries with unresolved substitution variables in the filename
path are skipped with a warning (they cannot be resolved without
the substitution pass).
Secrets files are tracked separately so we can filter them to
only include the keys this config actually references.
Delegates to :func:`yaml_util.discover_user_yaml_files`, which does a
fresh re-parse and force-loads every deferred ``IncludeFile`` so that
*all* potentially-reachable includes are captured (even branches not
selected by local substitutions). Bundles are meant to be compiled on
another system where command-line substitution overrides may choose a
different branch — e.g. ``!include network/${eth_model}/config.yaml``
must ship every candidate so the remote build can pick any one.
"""
# Must be a fresh parse: IncludeFile.load() caches its result in
# _content, and we discover files by listening for loader calls. On
# an already-parsed tree the cache is populated, .load() returns
# without calling the loader, the listener never fires, and the
# referenced files would be silently dropped from the bundle.
with yaml_util.track_yaml_loads() as loaded_files:
try:
data = yaml_util.load_yaml(self._config_path)
except EsphomeError:
_LOGGER.debug(
"Bundle: re-loading YAML for include discovery failed, "
"proceeding with partial file list"
)
else:
_force_load_include_files(data)
for fpath in loaded_files:
if fpath == self._config_path.resolve():
discovered = yaml_util.discover_user_yaml_files(self._config_path)
self._secrets_paths.update(discovered.secrets)
config_resolved = self._config_path.resolve()
for fpath in discovered.files:
if fpath == config_resolved:
continue # Already added as config
if fpath.name in const.SECRETS_FILES:
self._secrets_paths.add(fpath)
self._add_file(fpath)
def _discover_component_files(self) -> None:
@@ -623,57 +603,6 @@ def _add_bytes_to_tar(tar: tarfile.TarFile, name: str, data: bytes) -> None:
tar.addfile(info, io.BytesIO(data))
def _force_load_include_files(obj: Any, _seen: set[int] | None = None) -> None:
"""Recursively resolve any ``IncludeFile`` instances in a YAML tree.
Nested ``!include`` returns a deferred ``IncludeFile`` that is only
resolved during the substitution pass. During bundle discovery we need
the referenced files to actually load so the ``track_yaml_loads``
listener fires for them.
``IncludeFile`` instances with unresolved substitution variables in the
filename cannot be loaded — we skip and warn about those.
"""
if _seen is None:
_seen = set()
if isinstance(obj, yaml_util.IncludeFile):
if id(obj) in _seen:
return
_seen.add(id(obj))
if obj.has_unresolved_expressions():
_LOGGER.warning(
"Bundle: cannot resolve !include %s (referenced from %s) "
"with substitutions in path",
obj.file,
obj.parent_file,
)
return
try:
loaded = obj.load()
except EsphomeError as err:
_LOGGER.warning(
"Bundle: failed to load !include %s (referenced from %s): %s",
obj.file,
obj.parent_file,
err,
)
return
_force_load_include_files(loaded, _seen)
elif isinstance(obj, dict):
if id(obj) in _seen:
return
_seen.add(id(obj))
for value in obj.values():
_force_load_include_files(value, _seen)
elif isinstance(obj, (list, tuple)):
if id(obj) in _seen:
return
_seen.add(id(obj))
for item in obj:
_force_load_include_files(item, _seen)
def _resolve_include_path(include_path: Any) -> Path | None:
"""Resolve an include path to absolute, skipping system includes."""
if isinstance(include_path, str) and include_path.startswith("<"):

View File

@@ -0,0 +1,76 @@
"""Validated-config cache for the upload/logs fast path.
compile dumps the validated config to <data_dir>/storage/<file>.validated.yaml;
the next upload/logs for that YAML reuses it instead of running the full
read_config pipeline. YAML round-trip (yaml_util.dump/load_yaml) keeps
!lambda/!include/IDs/paths intact; mtime gates staleness.
"""
from __future__ import annotations
import logging
from pathlib import Path
from esphome.core import CORE
from esphome.helpers import write_file
from esphome.storage_json import StorageJSON, ext_storage_path
from esphome.types import ConfigType
_LOGGER = logging.getLogger(__name__)
def compiled_config_path(config_filename: str) -> Path:
"""Path to the cached validated config alongside the storage sidecar."""
return CORE.data_dir / "storage" / f"{config_filename}.validated.yaml"
def _cache_is_fresh(cache_path: Path, source_path: Path) -> bool:
"""True iff the cache file exists and isn't older than the source."""
try:
return cache_path.stat().st_mtime >= source_path.stat().st_mtime
except OSError:
return False
def save_compiled_config(config: ConfigType) -> None:
"""Write the validated-config cache. Always-write so mtime stays fresh.
Mode 0600 because show_secrets=True resolves !secret inline.
Failures are non-fatal: the fast path falls back to read_config.
"""
from esphome import yaml_util
try:
rendered = yaml_util.dump(config, show_secrets=True)
write_file(compiled_config_path(CORE.config_filename), rendered, private=True)
except Exception as err: # pylint: disable=broad-except
_LOGGER.debug("Skipping compiled config cache write: %s", err)
def load_compiled_config(conf_path: Path) -> ConfigType | None:
"""Load the cached validated config and apply storage metadata to CORE.
Returns None (caller falls back to read_config) when the cache is
missing, older than the source YAML, unparseable, or the sidecar
is incomplete.
"""
cache_path = compiled_config_path(conf_path.name)
if not _cache_is_fresh(cache_path, conf_path):
return None
from esphome import yaml_util
try:
config = yaml_util.load_yaml(cache_path, clear_secrets=False)
except Exception: # pylint: disable=broad-except
return None
storage = StorageJSON.load(ext_storage_path(conf_path.name))
if storage is None:
return None
# apply_to_core assumes a real compile wrote the sidecar; wizard-only
# sidecars leave both of these unset and can't drive upload/logs.
if not storage.core_platform and not storage.target_platform:
return None
storage.apply_to_core()
return config

View File

@@ -4,8 +4,7 @@
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
namespace esphome {
namespace a01nyub {
namespace esphome::a01nyub {
static const char *const TAG = "a01nyub.sensor";
@@ -42,5 +41,4 @@ void A01nyubComponent::check_buffer_() {
void A01nyubComponent::dump_config() { LOG_SENSOR("", "A01nyub Sensor", this); }
} // namespace a01nyub
} // namespace esphome
} // namespace esphome::a01nyub

View File

@@ -6,8 +6,7 @@
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/uart/uart.h"
namespace esphome {
namespace a01nyub {
namespace esphome::a01nyub {
class A01nyubComponent : public sensor::Sensor, public Component, public uart::UARTDevice {
public:
@@ -23,5 +22,4 @@ class A01nyubComponent : public sensor::Sensor, public Component, public uart::U
std::vector<uint8_t> buffer_;
};
} // namespace a01nyub
} // namespace esphome
} // namespace esphome::a01nyub

View File

@@ -4,8 +4,7 @@
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
namespace esphome {
namespace a02yyuw {
namespace esphome::a02yyuw {
static const char *const TAG = "a02yyuw.sensor";
@@ -41,5 +40,4 @@ void A02yyuwComponent::check_buffer_() {
void A02yyuwComponent::dump_config() { LOG_SENSOR("", "A02yyuw Sensor", this); }
} // namespace a02yyuw
} // namespace esphome
} // namespace esphome::a02yyuw

View File

@@ -6,8 +6,7 @@
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/uart/uart.h"
namespace esphome {
namespace a02yyuw {
namespace esphome::a02yyuw {
class A02yyuwComponent : public sensor::Sensor, public Component, public uart::UARTDevice {
public:
@@ -23,5 +22,4 @@ class A02yyuwComponent : public sensor::Sensor, public Component, public uart::U
std::vector<uint8_t> buffer_;
};
} // namespace a02yyuw
} // namespace esphome
} // namespace esphome::a02yyuw

View File

@@ -1,8 +1,7 @@
#include "a4988.h"
#include "esphome/core/log.h"
namespace esphome {
namespace a4988 {
namespace esphome::a4988 {
static const char *const TAG = "a4988.stepper";
@@ -51,5 +50,4 @@ void A4988::loop() {
this->step_pin_->digital_write(false);
}
} // namespace a4988
} // namespace esphome
} // namespace esphome::a4988

View File

@@ -4,8 +4,7 @@
#include "esphome/core/hal.h"
#include "esphome/components/stepper/stepper.h"
namespace esphome {
namespace a4988 {
namespace esphome::a4988 {
class A4988 : public stepper::Stepper, public Component {
public:
@@ -25,5 +24,4 @@ class A4988 : public stepper::Stepper, public Component {
HighFrequencyLoopRequester high_freq_;
};
} // namespace a4988
} // namespace esphome
} // namespace esphome::a4988

View File

@@ -1,8 +1,7 @@
#include "adalight_light_effect.h"
#include "esphome/core/log.h"
namespace esphome {
namespace adalight {
namespace esphome::adalight {
static const char *const TAG = "adalight_light_effect";
@@ -129,7 +128,7 @@ AdalightLightEffect::Frame AdalightLightEffect::parse_frame_(light::AddressableL
uint8_t *led_data = &frame_[6];
for (int led = 0; led < accepted_led_count; led++, led_data += 3) {
auto white = std::min(std::min(led_data[0], led_data[1]), led_data[2]);
auto white = std::min({led_data[0], led_data[1], led_data[2]});
it[led].set(Color(led_data[0], led_data[1], led_data[2], white));
}
@@ -138,5 +137,4 @@ AdalightLightEffect::Frame AdalightLightEffect::parse_frame_(light::AddressableL
return CONSUMED;
}
} // namespace adalight
} // namespace esphome
} // namespace esphome::adalight

View File

@@ -6,8 +6,7 @@
#include <vector>
namespace esphome {
namespace adalight {
namespace esphome::adalight {
class AdalightLightEffect : public light::AddressableLightEffect, public uart::UARTDevice {
public:
@@ -35,5 +34,4 @@ class AdalightLightEffect : public light::AddressableLightEffect, public uart::U
std::vector<uint8_t> frame_;
};
} // namespace adalight
} // namespace esphome
} // namespace esphome::adalight

View File

@@ -17,8 +17,7 @@
#include <zephyr/drivers/adc.h>
#endif
namespace esphome {
namespace adc {
namespace esphome::adc {
#ifdef USE_ESP32
// clang-format off
@@ -162,5 +161,4 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage
#endif
};
} // namespace adc
} // namespace esphome
} // namespace esphome::adc

View File

@@ -1,8 +1,7 @@
#include "adc_sensor.h"
#include "esphome/core/log.h"
namespace esphome {
namespace adc {
namespace esphome::adc {
static const char *const TAG = "adc.common";
@@ -79,5 +78,4 @@ void ADCSensor::set_sample_count(uint8_t sample_count) {
void ADCSensor::set_sampling_mode(SamplingMode sampling_mode) { this->sampling_mode_ = sampling_mode; }
} // namespace adc
} // namespace esphome
} // namespace esphome::adc

View File

@@ -4,8 +4,7 @@
#include "esphome/core/log.h"
#include <cinttypes>
namespace esphome {
namespace adc {
namespace esphome::adc {
static const char *const TAG = "adc.esp32";
@@ -364,7 +363,6 @@ float ADCSensor::sample_autorange_() {
return final_result;
}
} // namespace adc
} // namespace esphome
} // namespace esphome::adc
#endif // USE_ESP32

View File

@@ -11,8 +11,7 @@ ADC_MODE(ADC_VCC)
#include <Arduino.h>
#endif // USE_ADC_SENSOR_VCC
namespace esphome {
namespace adc {
namespace esphome::adc {
static const char *const TAG = "adc.esp8266";
@@ -55,7 +54,6 @@ float ADCSensor::sample() {
return aggr.aggregate() / 1024.0f;
}
} // namespace adc
} // namespace esphome
} // namespace esphome::adc
#endif // USE_ESP8266

View File

@@ -3,8 +3,7 @@
#include "adc_sensor.h"
#include "esphome/core/log.h"
namespace esphome {
namespace adc {
namespace esphome::adc {
static const char *const TAG = "adc.libretiny";
@@ -48,7 +47,6 @@ float ADCSensor::sample() {
return aggr.aggregate() / 1000.0f;
}
} // namespace adc
} // namespace esphome
} // namespace esphome::adc
#endif // USE_LIBRETINY

View File

@@ -15,8 +15,7 @@
#define PICO_VSYS_PIN 29 // NOLINT(cppcoreguidelines-macro-usage)
#endif
namespace esphome {
namespace adc {
namespace esphome::adc {
static const char *const TAG = "adc.rp2040";
@@ -98,7 +97,6 @@ float ADCSensor::sample() {
return aggr.aggregate() * 3.3f / 4096.0f * coeff;
}
} // namespace adc
} // namespace esphome
} // namespace esphome::adc
#endif // USE_RP2040

View File

@@ -5,8 +5,7 @@
#include "hal/nrf_saadc.h"
namespace esphome {
namespace adc {
namespace esphome::adc {
static const char *const TAG = "adc.zephyr";
@@ -202,6 +201,5 @@ float ADCSensor::sample() {
return val_mv / 1000.0f;
}
} // namespace adc
} // namespace esphome
} // namespace esphome::adc
#endif

View File

@@ -1,8 +1,7 @@
#include "adc128s102.h"
#include "esphome/core/log.h"
namespace esphome {
namespace adc128s102 {
namespace esphome::adc128s102 {
static const char *const TAG = "adc128s102";
@@ -28,5 +27,4 @@ uint16_t ADC128S102::read_data(uint8_t channel) {
return digital_value;
}
} // namespace adc128s102
} // namespace esphome
} // namespace esphome::adc128s102

View File

@@ -4,8 +4,7 @@
#include "esphome/core/hal.h"
#include "esphome/components/spi/spi.h"
namespace esphome {
namespace adc128s102 {
namespace esphome::adc128s102 {
class ADC128S102 : public Component,
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_LEADING,
@@ -19,5 +18,4 @@ class ADC128S102 : public Component,
uint16_t read_data(uint8_t channel);
};
} // namespace adc128s102
} // namespace esphome
} // namespace esphome::adc128s102

View File

@@ -2,8 +2,7 @@
#include "esphome/core/log.h"
namespace esphome {
namespace adc128s102 {
namespace esphome::adc128s102 {
static const char *const TAG = "adc128s102.sensor";
@@ -18,5 +17,4 @@ void ADC128S102Sensor::dump_config() {
float ADC128S102Sensor::sample() { return this->parent_->read_data(this->channel_); }
void ADC128S102Sensor::update() { this->publish_state(this->sample()); }
} // namespace adc128s102
} // namespace esphome
} // namespace esphome::adc128s102

View File

@@ -7,8 +7,7 @@
#include "../adc128s102.h"
namespace esphome {
namespace adc128s102 {
namespace esphome::adc128s102 {
class ADC128S102Sensor : public PollingComponent,
public Parented<ADC128S102>,
@@ -24,5 +23,4 @@ class ADC128S102Sensor : public PollingComponent,
protected:
uint8_t channel_;
};
} // namespace adc128s102
} // namespace esphome
} // namespace esphome::adc128s102

View File

@@ -1,8 +1,7 @@
#include "addressable_light_display.h"
#include "esphome/core/log.h"
namespace esphome {
namespace addressable_light {
namespace esphome::addressable_light {
static const char *const TAG = "addressable_light.display";
@@ -66,5 +65,4 @@ void HOT AddressableLightDisplay::draw_absolute_pixel_internal(int x, int y, Col
this->addressable_light_buffer_[y * this->get_width_internal() + x] = color;
}
}
} // namespace addressable_light
} // namespace esphome
} // namespace esphome::addressable_light

View File

@@ -7,8 +7,7 @@
#include <vector>
namespace esphome {
namespace addressable_light {
namespace esphome::addressable_light {
class AddressableLightDisplay : public display::DisplayBuffer {
public:
@@ -61,5 +60,4 @@ class AddressableLightDisplay : public display::DisplayBuffer {
optional<uint32_t> last_effect_index_;
optional<std::function<int(int, int)>> pixel_mapper_f_;
};
} // namespace addressable_light
} // namespace esphome
} // namespace esphome::addressable_light

View File

@@ -13,8 +13,7 @@
#include <cinttypes>
namespace esphome {
namespace ade7880 {
namespace esphome::ade7880 {
static const char *const TAG = "ade7880";
@@ -313,5 +312,4 @@ void ADE7880::reset_device_() {
this->store_.reset_pending = true;
}
} // namespace ade7880
} // namespace esphome
} // namespace esphome::ade7880

View File

@@ -16,8 +16,7 @@
#include "ade7880_registers.h"
namespace esphome {
namespace ade7880 {
namespace esphome::ade7880 {
struct NeutralChannel {
void set_current(sensor::Sensor *sens) { this->current = sens; }
@@ -125,5 +124,4 @@ class ADE7880 : public i2c::I2CDevice, public PollingComponent {
void write_u32_register16_(uint16_t a_register, uint32_t value);
};
} // namespace ade7880
} // namespace esphome
} // namespace esphome::ade7880

View File

@@ -9,8 +9,7 @@
#include "ade7880.h"
namespace esphome {
namespace ade7880 {
namespace esphome::ade7880 {
// adapted from https://stackoverflow.com/a/55912127/1886371
template<size_t Bits, typename T> inline T sign_extend(const T &v) noexcept {
@@ -97,5 +96,4 @@ void ADE7880::write_u32_register16_(uint16_t a_register, uint32_t value) {
this->write_register16(a_register, reinterpret_cast<uint8_t *>(&out), sizeof(out));
}
} // namespace ade7880
} // namespace esphome
} // namespace esphome::ade7880

View File

@@ -4,8 +4,7 @@
// Source: https://www.analog.com/media/en/technical-documentation/application-notes/AN-1127.pdf
namespace esphome {
namespace ade7880 {
namespace esphome::ade7880 {
// DSP Data Memory RAM registers
constexpr uint16_t AIGAIN = 0x4380;
@@ -242,5 +241,4 @@ constexpr uint8_t DSPWP_SET_RO = (1 << 7);
// DSPWP_SEL Register Bits
constexpr uint8_t DSPWP_SEL_SET = 0xAD;
} // namespace ade7880
} // namespace esphome
} // namespace esphome::ade7880

View File

@@ -3,8 +3,7 @@
#include <cinttypes>
namespace esphome {
namespace ade7953_base {
namespace esphome::ade7953_base {
static const char *const TAG = "ade7953";
@@ -160,5 +159,4 @@ void ADE7953::update() {
ADE_PUBLISH(frequency, 223750.0f, 1 + val_16);
}
} // namespace ade7953_base
} // namespace esphome
} // namespace esphome::ade7953_base

View File

@@ -6,8 +6,7 @@
#include <vector>
namespace esphome {
namespace ade7953_base {
namespace esphome::ade7953_base {
static constexpr uint8_t PGA_V_8 =
0x007; // PGA_V, (R/W) Default: 0x00, Unsigned, Voltage channel gain configuration (Bits[2:0])
@@ -131,5 +130,4 @@ class ADE7953 : public PollingComponent, public sensor::Sensor {
virtual bool ade_read_32(uint16_t reg, uint32_t *value) = 0;
};
} // namespace ade7953_base
} // namespace esphome
} // namespace esphome::ade7953_base

View File

@@ -2,8 +2,7 @@
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
namespace esphome {
namespace ade7953_i2c {
namespace esphome::ade7953_i2c {
static const char *const TAG = "ade7953";
@@ -76,5 +75,4 @@ bool AdE7953I2c::ade_read_32(uint16_t reg, uint32_t *value) {
return false;
}
} // namespace ade7953_i2c
} // namespace esphome
} // namespace esphome::ade7953_i2c

View File

@@ -8,8 +8,7 @@
#include <vector>
namespace esphome {
namespace ade7953_i2c {
namespace esphome::ade7953_i2c {
class AdE7953I2c : public ade7953_base::ADE7953, public i2c::I2CDevice {
public:
@@ -24,5 +23,4 @@ class AdE7953I2c : public ade7953_base::ADE7953, public i2c::I2CDevice {
bool ade_read_32(uint16_t reg, uint32_t *value) override;
};
} // namespace ade7953_i2c
} // namespace esphome
} // namespace esphome::ade7953_i2c

View File

@@ -2,8 +2,7 @@
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
namespace esphome {
namespace ade7953_spi {
namespace esphome::ade7953_spi {
static const char *const TAG = "ade7953";
@@ -83,5 +82,4 @@ bool AdE7953Spi::ade_read_32(uint16_t reg, uint32_t *value) {
return false;
}
} // namespace ade7953_spi
} // namespace esphome
} // namespace esphome::ade7953_spi

View File

@@ -8,8 +8,7 @@
#include <vector>
namespace esphome {
namespace ade7953_spi {
namespace esphome::ade7953_spi {
class AdE7953Spi : public ade7953_base::ADE7953,
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_HIGH, spi::CLOCK_PHASE_TRAILING,
@@ -28,5 +27,4 @@ class AdE7953Spi : public ade7953_base::ADE7953,
bool ade_read_32(uint16_t reg, uint32_t *value) override;
};
} // namespace ade7953_spi
} // namespace esphome
} // namespace esphome::ade7953_spi

View File

@@ -2,8 +2,7 @@
#include "esphome/core/hal.h"
#include "esphome/core/log.h"
namespace esphome {
namespace ads1115 {
namespace esphome::ads1115 {
static const char *const TAG = "ads1115";
static const uint8_t ADS1115_REGISTER_CONVERSION = 0x00;
@@ -208,5 +207,4 @@ float ADS1115Component::request_measurement(ADS1115Multiplexer multiplexer, ADS1
return millivolts / 1e3f;
}
} // namespace ads1115
} // namespace esphome
} // namespace esphome::ads1115

View File

@@ -5,8 +5,7 @@
#include <vector>
namespace esphome {
namespace ads1115 {
namespace esphome::ads1115 {
enum ADS1115Multiplexer {
ADS1115_MULTIPLEXER_P0_N1 = 0b000,
@@ -60,5 +59,4 @@ class ADS1115Component : public Component, public i2c::I2CDevice {
bool continuous_mode_;
};
} // namespace ads1115
} // namespace esphome
} // namespace esphome::ads1115

View File

@@ -2,8 +2,7 @@
#include "esphome/core/log.h"
namespace esphome {
namespace ads1115 {
namespace esphome::ads1115 {
static const char *const TAG = "ads1115.sensor";
@@ -29,5 +28,4 @@ void ADS1115Sensor::dump_config() {
this->multiplexer_, this->gain_, this->resolution_, this->samplerate_);
}
} // namespace ads1115
} // namespace esphome
} // namespace esphome::ads1115

View File

@@ -8,8 +8,7 @@
#include "../ads1115.h"
namespace esphome {
namespace ads1115 {
namespace esphome::ads1115 {
/// Internal holder class that is in instance of Sensor so that the hub can create individual sensors.
class ADS1115Sensor : public sensor::Sensor,
@@ -33,5 +32,4 @@ class ADS1115Sensor : public sensor::Sensor,
ADS1115Samplerate samplerate_;
};
} // namespace ads1115
} // namespace esphome
} // namespace esphome::ads1115

View File

@@ -2,8 +2,7 @@
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
namespace esphome {
namespace ads1118 {
namespace esphome::ads1118 {
static const char *const TAG = "ads1118";
static const uint8_t ADS1118_DATA_RATE_860_SPS = 0b111;
@@ -122,5 +121,4 @@ float ADS1118::request_measurement(ADS1118Multiplexer multiplexer, ADS1118Gain g
}
}
} // namespace ads1118
} // namespace esphome
} // namespace esphome::ads1118

View File

@@ -4,8 +4,7 @@
#include "esphome/core/component.h"
#include "esphome/core/hal.h"
namespace esphome {
namespace ads1118 {
namespace esphome::ads1118 {
enum ADS1118Multiplexer {
ADS1118_MULTIPLEXER_P0_N1 = 0b000,
@@ -41,5 +40,4 @@ class ADS1118 : public Component,
uint16_t config_{0};
};
} // namespace ads1118
} // namespace esphome
} // namespace esphome::ads1118

View File

@@ -2,8 +2,7 @@
#include "esphome/core/log.h"
namespace esphome {
namespace ads1118 {
namespace esphome::ads1118 {
static const char *const TAG = "ads1118.sensor";
@@ -27,5 +26,4 @@ void ADS1118Sensor::update() {
}
}
} // namespace ads1118
} // namespace esphome
} // namespace esphome::ads1118

View File

@@ -8,8 +8,7 @@
#include "../ads1118.h"
namespace esphome {
namespace ads1118 {
namespace esphome::ads1118 {
class ADS1118Sensor : public PollingComponent,
public sensor::Sensor,
@@ -32,5 +31,4 @@ class ADS1118Sensor : public PollingComponent,
bool temperature_mode_;
};
} // namespace ads1118
} // namespace esphome
} // namespace esphome::ads1118

View File

@@ -3,8 +3,7 @@
#include <cinttypes>
namespace esphome {
namespace ags10 {
namespace esphome::ags10 {
static const char *const TAG = "ags10";
// Data acquisition.
@@ -192,5 +191,4 @@ template<size_t N> optional<std::array<uint8_t, N>> AGS10Component::read_and_che
return data;
}
} // namespace ags10
} // namespace esphome
} // namespace esphome::ags10

View File

@@ -5,8 +5,7 @@
#include "esphome/core/automation.h"
#include "esphome/core/component.h"
namespace esphome {
namespace ags10 {
namespace esphome::ags10 {
class AGS10Component : public PollingComponent, public i2c::I2CDevice {
public:
@@ -136,5 +135,4 @@ template<typename... Ts> class AGS10SetZeroPointAction : public Action<Ts...>, p
}
}
};
} // namespace ags10
} // namespace esphome
} // namespace esphome::ags10

View File

@@ -17,8 +17,7 @@
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
namespace esphome {
namespace aht10 {
namespace esphome::aht10 {
static const char *const TAG = "aht10";
static const uint8_t AHT10_INITIALIZE_CMD[] = {0xE1, 0x08, 0x00};
@@ -160,5 +159,4 @@ void AHT10Component::dump_config() {
LOG_SENSOR(" ", "Humidity", this->humidity_sensor_);
}
} // namespace aht10
} // namespace esphome
} // namespace esphome::aht10

View File

@@ -6,8 +6,7 @@
#include "esphome/components/sensor/sensor.h"
#include "esphome/components/i2c/i2c.h"
namespace esphome {
namespace aht10 {
namespace esphome::aht10 {
enum AHT10Variant { AHT10, AHT20 };
@@ -31,5 +30,4 @@ class AHT10Component : public PollingComponent, public i2c::I2CDevice {
uint32_t start_time_{};
};
} // namespace aht10
} // namespace esphome
} // namespace esphome::aht10

View File

@@ -4,8 +4,7 @@
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
namespace esphome {
namespace aic3204 {
namespace esphome::aic3204 {
static const char *const TAG = "aic3204";
@@ -167,5 +166,4 @@ bool AIC3204::write_volume_() {
return true;
}
} // namespace aic3204
} // namespace esphome
} // namespace esphome::aic3204

View File

@@ -6,8 +6,7 @@
#include "esphome/core/defines.h"
#include "esphome/core/hal.h"
namespace esphome {
namespace aic3204 {
namespace esphome::aic3204 {
// TLV320AIC3204 Register Addresses
// Page 0
@@ -83,5 +82,4 @@ class AIC3204 : public audio_dac::AudioDac, public Component, public i2c::I2CDev
float volume_{0};
};
} // namespace aic3204
} // namespace esphome
} // namespace esphome::aic3204

View File

@@ -4,8 +4,7 @@
#include "esphome/core/component.h"
#include "aic3204.h"
namespace esphome {
namespace aic3204 {
namespace esphome::aic3204 {
template<typename... Ts> class SetAutoMuteAction : public Action<Ts...> {
public:
@@ -19,5 +18,4 @@ template<typename... Ts> class SetAutoMuteAction : public Action<Ts...> {
AIC3204 *aic3204_;
};
} // namespace aic3204
} // namespace esphome
} // namespace esphome::aic3204

View File

@@ -4,8 +4,7 @@
#ifdef USE_ESP32
namespace esphome {
namespace airthings_ble {
namespace esphome::airthings_ble {
static const char *const TAG = "airthings_ble";
@@ -29,7 +28,6 @@ bool AirthingsListener::parse_device(const esp32_ble_tracker::ESPBTDevice &devic
return false;
}
} // namespace airthings_ble
} // namespace esphome
} // namespace esphome::airthings_ble
#endif

View File

@@ -5,15 +5,13 @@
#include "esphome/core/component.h"
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
namespace esphome {
namespace airthings_ble {
namespace esphome::airthings_ble {
class AirthingsListener : public esp32_ble_tracker::ESPBTDeviceListener {
public:
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
};
} // namespace airthings_ble
} // namespace esphome
} // namespace esphome::airthings_ble
#endif

View File

@@ -6,8 +6,7 @@
#ifdef USE_ESP32
namespace esphome {
namespace airthings_wave_base {
namespace esphome::airthings_wave_base {
static const char *const TAG = "airthings_wave_base";
@@ -211,7 +210,6 @@ void AirthingsWaveBase::set_response_timeout_() {
});
}
} // namespace airthings_wave_base
} // namespace esphome
} // namespace esphome::airthings_wave_base
#endif // USE_ESP32

View File

@@ -14,8 +14,7 @@
#include "esphome/core/component.h"
#include "esphome/core/log.h"
namespace esphome {
namespace airthings_wave_base {
namespace esphome::airthings_wave_base {
namespace espbt = esphome::esp32_ble_tracker;
@@ -84,7 +83,6 @@ class AirthingsWaveBase : public PollingComponent, public ble_client::BLEClientN
};
};
} // namespace airthings_wave_base
} // namespace esphome
} // namespace esphome::airthings_wave_base
#endif // USE_ESP32

View File

@@ -2,8 +2,7 @@
#ifdef USE_ESP32
namespace esphome {
namespace airthings_wave_mini {
namespace esphome::airthings_wave_mini {
static const char *const TAG = "airthings_wave_mini";
@@ -49,7 +48,6 @@ AirthingsWaveMini::AirthingsWaveMini() {
espbt::ESPBTUUID::from_raw(ACCESS_CONTROL_POINT_CHARACTERISTIC_UUID);
}
} // namespace airthings_wave_mini
} // namespace esphome
} // namespace esphome::airthings_wave_mini
#endif // USE_ESP32

View File

@@ -4,8 +4,7 @@
#include "esphome/components/airthings_wave_base/airthings_wave_base.h"
namespace esphome {
namespace airthings_wave_mini {
namespace esphome::airthings_wave_mini {
namespace espbt = esphome::esp32_ble_tracker;
@@ -34,7 +33,6 @@ class AirthingsWaveMini : public airthings_wave_base::AirthingsWaveBase {
};
};
} // namespace airthings_wave_mini
} // namespace esphome
} // namespace esphome::airthings_wave_mini
#endif // USE_ESP32

View File

@@ -2,8 +2,7 @@
#ifdef USE_ESP32
namespace esphome {
namespace airthings_wave_plus {
namespace esphome::airthings_wave_plus {
static const char *const TAG = "airthings_wave_plus";
@@ -98,7 +97,6 @@ void AirthingsWavePlus::setup() {
espbt::ESPBTUUID::from_raw(access_control_point_characteristic_uuid);
}
} // namespace airthings_wave_plus
} // namespace esphome
} // namespace esphome::airthings_wave_plus
#endif // USE_ESP32

View File

@@ -4,8 +4,7 @@
#include "esphome/components/airthings_wave_base/airthings_wave_base.h"
namespace esphome {
namespace airthings_wave_plus {
namespace esphome::airthings_wave_plus {
namespace espbt = esphome::esp32_ble_tracker;
@@ -58,7 +57,6 @@ class AirthingsWavePlus : public airthings_wave_base::AirthingsWaveBase {
};
};
} // namespace airthings_wave_plus
} // namespace esphome
} // namespace esphome::airthings_wave_plus
#endif // USE_ESP32

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