Compare commits

...

139 Commits

Author SHA1 Message Date
dependabot[bot] e308075e3f Bump puremagic from 1.30 to 2.2.0 (#17285)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-29 16:12:23 -04:00
dependabot[bot] 405607e9d2 Bump esptool from 5.3.0 to 5.3.1 (#17284)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-29 16:06:36 -04:00
dependabot[bot] 797ed23765 Bump tzlocal from 5.4.3 to 5.4.4 (#17283)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-29 16:02:11 -04:00
dependabot[bot] 8780c7e0ac Bump awalsh128/cache-apt-pkgs-action from 1.6.0 to 1.6.2 (#17286)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-29 16:01:41 -04:00
Jonathan Swoboda 136e343988 [ethernet] Generic and YT8531 PHY over RGMII (gigabit) for ESP32-S31 (#17277) 2026-06-29 14:13:11 -04:00
Jonathan Swoboda b8690c8e31 [core] Drop Python 3.11 support (#17280) 2026-06-29 12:32:28 -04:00
Kevin Ahrendt 2778c62d07 [audio] Bump microMP3 to v0.4.0 (#17279) 2026-06-29 11:33:56 -04:00
Jesse Hills 7984349c36 Merge branch 'release' into dev 2026-06-29 22:32:34 +12:00
Jesse Hills 0cbbd64577 Merge pull request #17223 from esphome/bump-2026.6.3
2026.6.3
2026-06-29 22:31:44 +12:00
Jesse Hills a618ee11b4 Bump version to 2026.6.3 2026-06-29 20:30:24 +12:00
Tom 6251c26cc6 [espnow] Fix espnow crash when send() is called without a callback (#17266) 2026-06-29 20:30:24 +12:00
Jonathan Swoboda 4fbe0d87ec [wifi] Fix crash when WiFi is enabled late alongside ESP-NOW (#17239) 2026-06-29 20:30:24 +12:00
esphome[bot] 24d8e99c50 Bump bundled esphome-device-builder to 1.0.21 (#17257)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-06-29 20:30:24 +12:00
Jonathan Swoboda 14b6a0ede1 [espnow] Don't throttle ESP-NOW RX when deep_sleep is present (#17240) 2026-06-29 20:30:24 +12:00
Jonathan Swoboda 1793ca5eac [core] Suppress unactionable legacy-redaction warning for substitutions (#17242) 2026-06-29 20:30:24 +12:00
esphome[bot] 62e19bcb27 Bump bundled esphome-device-builder to 1.0.20 (#17244) 2026-06-29 20:30:24 +12:00
Franck Nijhof 84d1c34c28 [core] Fix area saved as null in storage.json (#17219)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-29 20:30:24 +12:00
esphome[bot] f78cbf9200 Bump bundled esphome-device-builder to 1.0.19 (#17217)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-06-29 20:30:23 +12:00
esphome[bot] eb711381d3 Bump bundled esphome-device-builder to 1.0.18 (#17212)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-06-29 20:30:23 +12:00
Jonathan Swoboda 9a1daa5247 [hbridge] Fix light stuck on one polarity (#17162) 2026-06-29 20:30:18 +12:00
Clyde Stubbs f3d61ca3e1 [mipi][mipi_spi] Swap native dimensions for swap_xy hardware transform (#17201)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 20:29:44 +12:00
Jonathan Swoboda 29dfd820c6 [wifi] Report STA IP, not SoftAP IP, in wifi_info on ESP8266 (#17185) 2026-06-29 20:29:44 +12:00
Jonathan Swoboda 8bc5b97298 [network] Set IPv4 type tag on all lwIP platforms, not just esp32 (#17200) 2026-06-29 20:29:44 +12:00
Jonathan Swoboda 7a64163c4f [esp32] Accept '#' as ESP-IDF source ref separator (#17193) 2026-06-29 20:29:44 +12:00
esphome[bot] dfe14f9c3a Bump bundled esphome-device-builder to 1.0.17 (#17199) 2026-06-29 20:29:44 +12:00
esphome[bot] 26cf373ae7 Bump bundled esphome-device-builder to 1.0.16 (#17182) 2026-06-29 20:29:44 +12:00
Geoffrey Frogeye 94ccddf176 [opentherm] Support power scaling disabled (#17183)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-06-29 20:29:44 +12:00
Clyde Stubbs 2ec24505d0 [mipi_spi] Suppress sequence errors when page selection used (#17176) 2026-06-29 20:29:44 +12:00
esphome[bot] 4f7faa7712 Bump bundled esphome-device-builder to 1.0.15 (#17170) 2026-06-29 20:29:44 +12:00
Clyde Stubbs b3dcaac262 [mipi_spi] Warn on MODE3 default for display without CS pin (#17153) 2026-06-29 20:29:44 +12:00
mnewton25 ee118d384a [esp32] Use POSIX path for secure-boot signing/verification keys Fixes #17164 (#17166)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-29 20:29:44 +12:00
Jonathan Swoboda 8d36167e11 [esp32_ble_server] Fix set_value action with by-reference triggers (#17156) 2026-06-29 20:29:44 +12:00
esphome[bot] 6d559a32df Bump bundled esphome-device-builder to 1.0.14 (#17139) 2026-06-29 20:29:37 +12:00
Jonathan Swoboda bf0d31b3ab [espidf] Don't fail framework check on broken unrelated PATH tools (#17053) 2026-06-29 20:23:23 +12:00
dependabot[bot] d8ffb732b7 Bump zeroconf from 0.149.16 to 0.150.0 (#17137)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-29 20:23:23 +12:00
Tom 9e8261056c [espnow] Fix espnow crash when send() is called without a callback (#17266) 2026-06-28 23:06:12 -04:00
Clyde Stubbs 5f311d281e [esphome] Warn when a YAML merge (<<:) drops a key (#17246)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-29 07:17:01 +10:00
J. Nick Koston a336ad6732 [mcp4725] Use constexpr bit shift instead of powf for full-scale value (#17261) 2026-06-28 17:07:51 -04:00
Bonne Eggleston 8434d54cc7 [modbus] Reinstate turnaround delay after broadcasts (Revert #17209) (#17263)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-28 17:07:25 -04:00
Jonathan Swoboda b62f7a41c9 [multiple] Single-precision float math, avoid double promotion (stragglers) (#17260) 2026-06-28 16:15:38 -04:00
Bonne Eggleston 4ebecf514a [modbus_server] Simplify server response handling (#12376)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-06-28 19:41:47 +00:00
Jonathan Swoboda 2f32c88ae5 [wifi] Fix crash when WiFi is enabled late alongside ESP-NOW (#17239) 2026-06-28 15:16:42 -04:00
Jonathan Swoboda 95449068e7 [multiple] Single-precision float math, avoid double promotion (batch 4/4) (#17256) 2026-06-28 14:18:41 -04:00
Jonathan Swoboda 556def78aa [multiple] Single-precision float math, avoid double promotion (batch 3/4) (#17255) 2026-06-28 14:18:30 -04:00
Jonathan Swoboda b7803cf9b5 [multiple] Single-precision float math, avoid double promotion (batch 2/4) (#17254) 2026-06-28 14:18:20 -04:00
Jonathan Swoboda 40820287f1 [multiple] Single-precision float math, avoid double promotion (batch 1/4) (#17253) 2026-06-28 14:18:13 -04:00
Jonathan Swoboda 6210dfb4d0 [core] Use single-precision float math to avoid double promotion (#17252) 2026-06-28 14:18:01 -04:00
esphome[bot] 45c712b17b Bump bundled esphome-device-builder to 1.0.21 (#17257)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-06-28 09:41:49 -07:00
alorente 8e23065b86 [it8951] Add IT8951 e-paper controller support to epaper_spi (#15346)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Citric Li <37475446+limengdu@users.noreply.github.com>
Co-authored-by: koosoli <koosoli@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 21:14:05 +10:00
Jonathan Swoboda d3892b8399 [platformio] Extract toolchain-agnostic PlatformIO library converter (#17243) 2026-06-28 07:03:09 -04:00
Jonathan Swoboda bda789052d [espnow] Don't throttle ESP-NOW RX when deep_sleep is present (#17240) 2026-06-27 22:17:09 +00:00
Jonathan Swoboda 0fb100f2d1 [core] Suppress unactionable legacy-redaction warning for substitutions (#17242) 2026-06-27 18:05:00 -04:00
esphome[bot] fd7fc6b8e8 Bump bundled esphome-device-builder to 1.0.20 (#17244) 2026-06-27 15:00:23 -07:00
tomaszduda23 690e8c3fb9 [nrf52] add upload for native build (#17100)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-27 15:50:28 -04:00
Ardumine a0742a9535 [api] Add nRF52 support (#17226)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-27 14:22:34 -04:00
Jonathan Swoboda ccc57475b7 [deep_sleep] Add ESP32-C5 support (#17237) 2026-06-27 12:04:45 -04:00
Franck Nijhof 24ec65e68e [esp32] Only warn about S3 PSRAM pins (GPIO33-37) in octal mode (#17222)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-27 11:26:47 -04:00
dependabot[bot] 436938b931 Bump actions/cache/restore from 6.0.0 to 6.1.0 (#17231)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-27 10:33:13 -04:00
dependabot[bot] 063c4371de Bump actions/cache from 6.0.0 to 6.1.0 (#17230)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-27 10:33:01 -04:00
dependabot[bot] 7ad4cbf46f Bump actions/cache/save from 6.0.0 to 6.1.0 (#17229)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-27 10:32:50 -04:00
dependabot[bot] 88875daf52 Bump actions/cache/restore from 6.0.0 to 6.1.0 in /.github/actions/restore-python (#17228)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-27 10:32:39 -04:00
Franck Nijhof 7811781a96 [es8388] Fix DAC unable to unmute once muted (#17221)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-27 10:21:36 -04:00
Franck Nijhof da5e11d196 [core] Fix area saved as null in storage.json (#17219)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-27 09:49:56 -04:00
Ardumine 75cdabee3d [socket] Add BSD socket support for nRF52 (#16699)
Co-authored-by: tomaszduda23 <tomaszduda23@gmail.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-26 09:30:07 -04:00
esphome[bot] f9f28a6a00 Bump bundled esphome-device-builder to 1.0.19 (#17217)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-06-26 07:48:52 +02:00
Ardumine be8523a73c [mdns] Add mDNS to Zephyr and nRF52 (#16924)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-25 16:33:38 -04:00
dependabot[bot] f49bed47de Bump ruff from 0.15.19 to 0.15.20 (#17216)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-25 16:07:55 -04:00
Franck Nijhof 239211e521 [time] Defer aioesphomeapi import to speed up config validation (#17214) 2026-06-25 15:34:44 -04:00
Franck Nijhof cc646b2213 [core] Defer requests import in framework_helpers to speed up config validation (#17215) 2026-06-25 15:34:33 -04:00
dependabot[bot] ddf075a2dd Bump aioesphomeapi from 45.3.1 to 45.5.2 (#17211)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-25 18:00:52 +00:00
esphome[bot] e304c318fb Bump bundled esphome-device-builder to 1.0.18 (#17212)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-06-25 19:47:24 +02:00
Jonathan Swoboda e27390bddb [hbridge] Fix light stuck on one polarity (#17162) 2026-06-25 12:36:10 -04:00
rwrozelle 6f36ce6429 [openthread] Provide action to control poll_period when device MTD (#11766)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 12:35:15 -04:00
Jonathan Swoboda 1d5490fd91 [modbus] Only apply turnaround delay after broadcasts (#17209) 2026-06-25 11:38:34 -04:00
Jonathan Swoboda 18c7f60410 [uart] Validate fixed UART settings at config time for fixed-baud components (#17207) 2026-06-25 10:19:05 -04:00
Clyde Stubbs 4f70f6b2a6 [mipi][mipi_spi] Swap native dimensions for swap_xy hardware transform (#17201)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 08:36:36 -04:00
Jesse Hills 29a6105730 [ms8607] Mark configurable classes as final (#17147) 2026-06-25 08:31:15 -04:00
Jesse Hills 46cf052ec5 [config_validation] Fix multicast typo in error message (#17206) 2026-06-25 08:28:43 -04:00
Jesse Hills e5d8c22b47 Mark configurable classes as final (13/21: pmsa003i-rc522) (#16964) 2026-06-25 13:20:11 +02:00
Jesse Hills 64acb358a5 Mark configurable classes as final (8/21: hm3301-integration) (#16959) 2026-06-25 13:20:00 +02:00
Jesse Hills d511f0614d Mark configurable classes as final (18/21: template-tx20) (#16969) 2026-06-25 13:19:51 +02:00
Jesse Hills eb9ca517e3 Mark configurable classes as final (14/21: rc522_i2c-scd4x) (#16965) 2026-06-25 13:19:39 +02:00
Jesse Hills f769457bb0 Mark configurable classes as final (15/21: script-slow_pwm) (#16966) 2026-06-25 13:19:30 +02:00
Tomasz Witke 0fcf512148 [image] Use LVGL 9 color formats (#16871) 2026-06-25 21:03:50 +10:00
Jesse Hills 8c68e95568 [config_validation] Add tests for 100% validator coverage (#17204) 2026-06-25 22:33:28 +12:00
Fae d8eee03556 [host] Fix handling of directory for preferences (#11160) 2026-06-25 10:20:15 +00:00
Julian Lunz 23933c1b58 [adc] Only call cyw43_thread_enter/exit for VSYS when WiFi is active on RP2040 (#17203) 2026-06-24 23:21:41 -07:00
Jonathan Swoboda 8c9f4fba8f [wifi] Report STA IP, not SoftAP IP, in wifi_info on ESP8266 (#17185) 2026-06-24 22:28:15 -04:00
Jonathan Swoboda 92554f4e67 [network] Set IPv4 type tag on all lwIP platforms, not just esp32 (#17200) 2026-06-24 22:28:06 -04:00
Jonathan Swoboda 1dfafce06a [i2c][spi] Wire ESP32-S31/H4/H21 bus capabilities (#17188) 2026-06-24 21:05:29 -04:00
Jonathan Swoboda abbcfd213f [tinyusb][usb_cdc_acm][usb_host][usb_uart] Support ESP32-S31/H4 (#17190) 2026-06-24 20:51:03 -04:00
Jonathan Swoboda 23aff5202b [wifi][openthread] Wire ESP32-S31/H4/H21 radio support (#17186) 2026-06-24 20:42:41 -04:00
Jonathan Swoboda 91e515ca7c [esp32] Accept '#' as ESP-IDF source ref separator (#17193) 2026-06-24 20:40:28 -04:00
Jonathan Swoboda 538f554bdb [psram] Support ESP32-S31/H4 (#17192) 2026-06-24 20:38:55 -04:00
Jonathan Swoboda e96717f6cd [waveshare_io_ch32v003] Pin i2c_id in test to avoid grouping conflict (#17191) 2026-06-24 20:16:53 -04:00
dependabot[bot] aff5e248ed Bump actions/setup-python from 6.2.0 to 6.3.0 in /.github/actions/restore-python (#17194)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-25 02:05:30 +02:00
dependabot[bot] 155439be74 Bump actions/setup-python from 6.2.0 to 6.3.0 (#17197)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-25 02:05:13 +02:00
dependabot[bot] fa34c67950 Bump CodSpeedHQ/action from 4.17.6 to 4.18.1 (#17198)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-25 02:04:52 +02:00
dependabot[bot] b688474444 Bump ruff from 0.15.18 to 0.15.19 (#17195)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-25 02:04:37 +02:00
esphome[bot] 72b663fc40 Bump bundled esphome-device-builder to 1.0.17 (#17199) 2026-06-25 02:04:22 +02:00
esphome[bot] f471329d60 Bump bundled esphome-device-builder to 1.0.16 (#17182) 2026-06-24 17:15:00 +02:00
Geoffrey Frogeye e8acd24fd9 [opentherm] Support power scaling disabled (#17183)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-06-24 09:29:57 -04:00
Clyde Stubbs 18f29f8d2b [mipi_spi] Suppress sequence errors when page selection used (#17176) 2026-06-24 08:05:23 -04:00
Anton Viktorov cbcf23426d [waveshare_io_ch32v003] Waveshare I/O Expander component (#10071) 2026-06-24 20:08:59 +10:00
Jesse Hills e6455c5b44 Mark configurable classes as final (12/21: msa3xx-pm2005) (#16963) 2026-06-23 18:27:07 -05:00
Jesse Hills 2b8916fc4e [ci] Exclude test changes from small-pr/medium-pr size labels (#17172) 2026-06-24 11:13:34 +12:00
esphome[bot] dae078fc56 Bump bundled esphome-device-builder to 1.0.15 (#17170) 2026-06-24 11:06:15 +12:00
Clyde Stubbs 72686bd4af [mipi_spi] Warn on MODE3 default for display without CS pin (#17153) 2026-06-24 08:43:39 +10:00
Jonathan Swoboda 344da7c4f4 [docker] Move build deps to base image, drop app apt step (#17167)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-06-23 17:35:07 -04:00
Jesse Hills 84de814e6f [config_validation] Make bind_key a sensitive dual-mode validator (#17146) 2026-06-24 09:05:39 +12:00
Jonathan Swoboda 1d32b6c9e0 [espidf] Enable ccache by default for ESP-IDF builds (#17163) 2026-06-23 16:41:13 -04:00
mnewton25 49536693b7 [esp32] Use POSIX path for secure-boot signing/verification keys Fixes #17164 (#17166)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-23 16:40:49 -04:00
dependabot[bot] a24a63e61b Bump actions/cache from 5.0.5 to 6.0.0 (#17168)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-23 15:03:28 -05:00
dependabot[bot] e3b644c2a0 Bump actions/cache from 5.0.5 to 6.0.0 in /.github/actions/restore-python (#17169)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-23 15:03:16 -05:00
Jonathan Swoboda 7763ce958d [tests] Disable Hypothesis deadline on IP validation property tests (#17138) 2026-06-23 15:21:40 -04:00
Jonathan Swoboda ff001b9e45 [esp32_ble_server] Fix set_value action with by-reference triggers (#17156) 2026-06-23 15:21:26 -04:00
Jonathan Swoboda c2d79c972c [docker] Install ccache in the image (#17157) 2026-06-23 15:04:42 -04:00
Jonathan Swoboda e0377bbbd3 [ci] Enable ccache for component batch builds (~7% faster) (#17136) 2026-06-23 15:04:23 -04:00
Berik Visschers eae65a6b88 [bme680_bsec][bme68x_bsec2][const] Move BME sensor constants to shared component consts (#17160) 2026-06-23 11:44:48 -04:00
Jesse Hills 225d426d95 [core] Use CORE.is_* platform helpers in __main__ (#17144) 2026-06-23 08:40:16 -04:00
Zach Isbach 9614bc20a0 [epaper_spi] Add support for Waveshare 2.13" V4 series B (R/B/W) (#16828) 2026-06-23 11:00:19 +00:00
arunderwood 41747c2de7 [epaper_spi] Add support for the Inkplate 2 (#16856) 2026-06-23 16:50:02 +10:00
Jesse Hills c70d56807f [motion] Make motion test configs mergeable in CI (#17149) 2026-06-23 16:44:58 +12:00
Jesse Hills 69d700727d [docker] Remove dead HA addon env exports (streamer_mode, relative_url) (#17140) 2026-06-23 11:25:24 +12:00
esphome[bot] 5fcf656806 Bump bundled esphome-device-builder to 1.0.14 (#17139) 2026-06-22 17:45:22 -05:00
Jonathan Swoboda 1ace836744 [espidf] Don't fail framework check on broken unrelated PATH tools (#17053) 2026-06-22 18:41:21 -04:00
Anunay Kulshrestha 3a4831bd7e [ble_nus] Atomic log-line framing (no partial ring-buffer writes) (#17105)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: tomaszduda23 <tomaszduda23@gmail.com>
2026-06-22 21:04:11 +00:00
dependabot[bot] 6c1724874b Bump zeroconf from 0.149.16 to 0.150.0 (#17137)
Signed-off-by: dependabot[bot] <support@github.com>
2026-06-22 15:04:22 -05:00
Joseph C. Lehner 2483576909 [sx126x] Add data whitening options (#17102)
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
2026-06-22 10:51:10 -04:00
esphome[bot] 0df1db6205 Bump bundled esphome-device-builder to 1.0.13 (#17132) 2026-06-22 00:01:22 -05:00
J. Nick Koston 614eae7a3b [dashboard_import] Store package_import_url in flash on ESP8266 (#17127) 2026-06-21 23:18:06 -05:00
Jesse Hills 2fe67a6eda [graphical_display_menu] Mark configurable classes as final (#17129) 2026-06-21 23:17:47 -05:00
Jesse Hills e88f69b5f8 Mark configurable classes as final (7/21: gcja5-hlw8032) (#16958) 2026-06-21 21:05:05 -05:00
Jesse Hills c69cfd44be Mark configurable classes as final (5/21) (#16956) 2026-06-21 21:04:55 -05:00
Jesse Hills 9f5ed6fdfd Mark configurable classes as final (6/21) (#16957) 2026-06-21 21:04:45 -05:00
Jesse Hills 0891473280 Mark configurable classes as final (10/21: matrix_keypad-micronova) (#16961) 2026-06-21 21:04:34 -05:00
Jesse Hills 2982d7c834 Mark configurable classes as final (9/21) (#16960) 2026-06-21 21:04:16 -05:00
Jesse Hills 026bac4cd1 [ld2420] Mark configurable classes as final (#17130) 2026-06-22 13:27:56 +12:00
J. Nick Koston 7fcc890e84 [rp2040] Bump arduino-pico framework to 5.6.1 (#17122) 2026-06-22 13:02:46 +12:00
790 changed files with 10688 additions and 2855 deletions
+2 -2
View File
@@ -17,12 +17,12 @@ runs:
steps:
- name: Set up Python ${{ inputs.python-version }}
id: python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: ${{ inputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: venv
# yamllint disable-line rule:line-length
+19 -12
View File
@@ -147,19 +147,9 @@ async function detectCoreChanges(changedFiles) {
}
// Strategy: PR size detection
async function detectPRSize(prFiles, totalAdditions, totalDeletions, totalChanges, isMegaPR, SMALL_PR_THRESHOLD, MEDIUM_PR_THRESHOLD, TOO_BIG_THRESHOLD) {
async function detectPRSize(prFiles, totalAdditions, totalDeletions, isMegaPR, SMALL_PR_THRESHOLD, MEDIUM_PR_THRESHOLD, TOO_BIG_THRESHOLD) {
const labels = new Set();
if (totalChanges <= SMALL_PR_THRESHOLD) {
labels.add('small-pr');
return labels;
}
if (totalChanges <= MEDIUM_PR_THRESHOLD) {
labels.add('medium-pr');
return labels;
}
const testAdditions = prFiles
.filter(file => file.filename.startsWith('tests/'))
.reduce((sum, file) => sum + (file.additions || 0), 0);
@@ -167,7 +157,24 @@ async function detectPRSize(prFiles, totalAdditions, totalDeletions, totalChange
.filter(file => file.filename.startsWith('tests/'))
.reduce((sum, file) => sum + (file.deletions || 0), 0);
const nonTestChanges = (totalAdditions - testAdditions) - (totalDeletions - testDeletions);
const nonTestAdditions = totalAdditions - testAdditions;
const nonTestDeletions = totalDeletions - testDeletions;
// small/medium count churn (additions + deletions) so a balanced refactor isn't undersized.
const nonTestChurn = nonTestAdditions + nonTestDeletions;
if (nonTestChurn <= SMALL_PR_THRESHOLD) {
labels.add('small-pr');
return labels;
}
if (nonTestChurn <= MEDIUM_PR_THRESHOLD) {
labels.add('medium-pr');
return labels;
}
// too-big uses net line delta (additions - deletions), matching the review message in reviews.js.
const nonTestChanges = nonTestAdditions - nonTestDeletions;
// Don't add too-big if mega-pr label is already present
if (nonTestChanges > TOO_BIG_THRESHOLD && !isMegaPR) {
+1 -1
View File
@@ -123,7 +123,7 @@ module.exports = async ({ github, context }) => {
detectNewComponents(github, context, prFiles),
detectNewPlatforms(github, context, prFiles, apiData),
detectCoreChanges(changedFiles),
detectPRSize(prFiles, totalAdditions, totalDeletions, totalChanges, isMegaPR, SMALL_PR_THRESHOLD, MEDIUM_PR_THRESHOLD, TOO_BIG_THRESHOLD),
detectPRSize(prFiles, totalAdditions, totalDeletions, isMegaPR, SMALL_PR_THRESHOLD, MEDIUM_PR_THRESHOLD, TOO_BIG_THRESHOLD),
detectDashboardChanges(changedFiles),
detectGitHubActionsChanges(changedFiles),
detectCodeOwner(github, context, changedFiles),
@@ -1,6 +1,6 @@
const { describe, it } = require('node:test');
const assert = require('node:assert/strict');
const { detectNewPlatforms, detectNewComponents } = require('../detectors');
const { detectNewPlatforms, detectNewComponents, detectPRSize } = require('../detectors');
// Minimal GitHub API mock — only repos.getContent is called by detectNewPlatforms/detectNewComponents
// to check for CONFIG_SCHEMA in newly added files.
@@ -145,3 +145,79 @@ describe('detectNewComponents', () => {
assert.equal(result.labels.size, 0);
});
});
// ---------------------------------------------------------------------------
// detectPRSize
// ---------------------------------------------------------------------------
describe('detectPRSize', () => {
const SMALL = 30;
const MEDIUM = 100;
const TOO_BIG = 1000;
function size(prFiles, isMegaPR = false) {
const totalAdditions = prFiles.reduce((sum, file) => sum + (file.additions || 0), 0);
const totalDeletions = prFiles.reduce((sum, file) => sum + (file.deletions || 0), 0);
return detectPRSize(prFiles, totalAdditions, totalDeletions, isMegaPR, SMALL, MEDIUM, TOO_BIG);
}
it('counts only non-test changes toward small-pr', async () => {
// 10 source + 5000 test lines -> non-test churn of 10 is still small.
const labels = await size([
{ filename: 'esphome/components/foo/foo.cpp', additions: 10, deletions: 0 },
{ filename: 'tests/components/foo/test.esp32-idf.yaml', additions: 5000, deletions: 0 },
]);
assert.ok(labels.has('small-pr'));
assert.equal(labels.size, 1);
});
it('counts additions and deletions as churn (not net delta)', async () => {
// A balanced refactor (40 added, 40 removed) is 80 lines of churn -> medium, not small.
const labels = await size([
{ filename: 'esphome/components/foo/foo.cpp', additions: 40, deletions: 40 },
]);
assert.ok(labels.has('medium-pr'));
assert.equal(labels.size, 1);
});
it('labels medium-pr when non-test changes exceed small threshold', async () => {
const labels = await size([
{ filename: 'esphome/components/foo/foo.cpp', additions: 60, deletions: 0 },
{ filename: 'tests/components/foo/test.esp32-idf.yaml', additions: 5000, deletions: 0 },
]);
assert.ok(labels.has('medium-pr'));
assert.equal(labels.size, 1);
});
it('uses net delta (not churn) for too-big', async () => {
// 600 added + 600 removed: 1200 churn (above too-big) but 0 net delta -> not too-big.
const labels = await size([
{ filename: 'esphome/components/foo/foo.cpp', additions: 600, deletions: 600 },
]);
assert.equal(labels.size, 0);
});
it('labels too-big when non-test changes exceed the big threshold', async () => {
const labels = await size([
{ filename: 'esphome/components/foo/foo.cpp', additions: 2000, deletions: 0 },
{ filename: 'tests/components/foo/test.esp32-idf.yaml', additions: 5000, deletions: 0 },
]);
assert.ok(labels.has('too-big'));
assert.equal(labels.size, 1);
});
it('does not label too-big when mega-pr is set', async () => {
const labels = await size([
{ filename: 'esphome/components/foo/foo.cpp', additions: 2000, deletions: 0 },
], true);
assert.equal(labels.size, 0);
});
it('produces no size label for a large mega-pr in the gap above medium', async () => {
// Non-test changes land between MEDIUM and TOO_BIG: not small/medium, and mega-pr suppresses too-big.
const labels = await size([
{ filename: 'esphome/components/foo/foo.cpp', additions: 500, deletions: 0 },
], true);
assert.equal(labels.size, 0);
});
});
+2 -2
View File
@@ -23,9 +23,9 @@ jobs:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.11"
python-version: "3.12"
- name: Set up uv
# ``--system`` (below) installs into the setup-python interpreter;
# no venv is created or restored by this workflow.
+4 -4
View File
@@ -63,9 +63,9 @@ jobs:
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.11"
python-version: "3.12"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
@@ -147,9 +147,9 @@ jobs:
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.11"
python-version: "3.12"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
@@ -60,7 +60,7 @@ jobs:
if: steps.pr.outputs.skip != 'true'
uses: ./.github/actions/restore-python
with:
python-version: "3.11"
python-version: "3.12"
cache-key: ${{ hashFiles('.cache-key') }}
- name: Download memory analysis artifacts
+26 -21
View File
@@ -12,8 +12,8 @@ permissions:
contents: read # actions/checkout for all jobs; individual jobs add their own scopes when they need to write
env:
DEFAULT_PYTHON: "3.11"
PYUPGRADE_TARGET: "--py311-plus"
DEFAULT_PYTHON: "3.12"
PYUPGRADE_TARGET: "--py312-plus"
concurrency:
# yamllint disable-line rule:line-length
@@ -34,12 +34,12 @@ jobs:
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
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: venv
# yamllint disable-line rule:line-length
@@ -162,7 +162,7 @@ jobs:
ref: main
path: device-builder
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.13"
- name: Set up uv
@@ -203,7 +203,7 @@ jobs:
fail-fast: false
matrix:
python-version:
- "3.11"
- "3.12"
- "3.13"
- "3.14"
os:
@@ -250,7 +250,7 @@ jobs:
token: ${{ secrets.CODECOV_TOKEN }}
- name: Save Python virtual environment cache
if: github.ref == 'refs/heads/dev'
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: venv
key: ${{ runner.os }}-${{ steps.restore-python.outputs.python-version }}-venv-${{ needs.common.outputs.cache-key }}
@@ -295,7 +295,7 @@ jobs:
python-version: ${{ env.DEFAULT_PYTHON }}
cache-key: ${{ needs.common.outputs.cache-key }}
- name: Restore components graph cache
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: .temp/components_graph.json
key: components-graph-${{ hashFiles('esphome/components/**/*.py') }}
@@ -339,7 +339,7 @@ jobs:
echo "benchmarks=$(echo "$output" | jq -r '.benchmarks')" >> $GITHUB_OUTPUT
- name: Save components graph cache
if: github.ref == 'refs/heads/dev'
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: .temp/components_graph.json
key: components-graph-${{ hashFiles('esphome/components/**/*.py') }}
@@ -360,12 +360,12 @@ jobs:
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Set up Python 3.13
id: python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.13"
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: venv
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-venv-${{ needs.common.outputs.cache-key }}
@@ -456,7 +456,7 @@ jobs:
echo "binary=$BINARY" >> $GITHUB_OUTPUT
- name: Run CodSpeed benchmarks
uses: CodSpeedHQ/action@63f3e98b61959fe67f146a3ff022e4136fe9bb9c # v4.17.6
uses: CodSpeedHQ/action@a4a36bb07c0638b0b4ca52bf1f3dad1b4289e52f # v4.18.1
with:
run: |
. venv/bin/activate
@@ -509,14 +509,14 @@ jobs:
- name: Cache platformio
if: github.ref == 'refs/heads/dev' && matrix.pio_cache_key
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/.platformio
key: platformio-${{ matrix.pio_cache_key }}-${{ hashFiles('platformio.ini') }}
- name: Cache platformio
if: github.ref != 'refs/heads/dev' && matrix.pio_cache_key
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/.platformio
key: platformio-${{ matrix.pio_cache_key }}-${{ hashFiles('platformio.ini') }}
@@ -820,10 +820,10 @@ jobs:
run: echo ${{ matrix.components }}
- name: Cache apt packages
uses: awalsh128/cache-apt-pkgs-action@acb598e5ddbc6f68a970c5da0688d2f3a9f04d05 # v1.5.3
uses: awalsh128/cache-apt-pkgs-action@5513791f75b039e2a79653b1a92238d3fb8d99b4 # v1.6.2
with:
packages: libsdl2-dev
version: 1.0
packages: libsdl2-dev ccache
version: 1.1
- name: Check out code from GitHub
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
@@ -941,6 +941,11 @@ jobs:
echo "All components in this batch are validate-only -- skipping compile stage."
fi
- name: Print ccache statistics
# esphome stores the cache under the IDF tools path; expand the leading
# ~ in ESPHOME_ESP_IDF_PREFIX so ccache reads the dir the build used.
run: CCACHE_DIR="${ESPHOME_ESP_IDF_PREFIX/#\~/$HOME}/ccache" ccache -s
test-esp32-platformio:
name: Test esp32 components with PlatformIO
runs-on: ubuntu-24.04
@@ -1093,7 +1098,7 @@ jobs:
- name: Restore cached memory analysis
id: cache-memory-analysis
if: steps.check-script.outputs.skip != 'true' && steps.check-tests.outputs.skip != 'true'
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: memory-analysis-target.json
key: ${{ steps.cache-key.outputs.cache-key }}
@@ -1117,7 +1122,7 @@ jobs:
- name: Cache platformio
if: steps.check-script.outputs.skip != 'true' && steps.check-tests.outputs.skip != 'true' && steps.cache-memory-analysis.outputs.cache-hit != 'true'
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/.platformio
key: platformio-memory-${{ fromJSON(needs.determine-jobs.outputs.memory_impact).platform }}-${{ hashFiles('platformio.ini') }}
@@ -1159,7 +1164,7 @@ jobs:
- name: Save memory analysis to cache
if: steps.check-script.outputs.skip != 'true' && steps.check-tests.outputs.skip != 'true' && steps.cache-memory-analysis.outputs.cache-hit != 'true' && steps.build.outcome == 'success'
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: memory-analysis-target.json
key: ${{ steps.cache-key.outputs.cache-key }}
@@ -1206,7 +1211,7 @@ jobs:
python-version: ${{ env.DEFAULT_PYTHON }}
cache-key: ${{ needs.common.outputs.cache-key }}
- name: Cache platformio
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/.platformio
key: platformio-memory-${{ fromJSON(needs.determine-jobs.outputs.memory_impact).platform }}-${{ hashFiles('platformio.ini') }}
+3 -3
View File
@@ -62,7 +62,7 @@ jobs:
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.x"
- name: Build
@@ -94,9 +94,9 @@ jobs:
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.11"
python-version: "3.12"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
+1 -1
View File
@@ -37,7 +37,7 @@ jobs:
path: lib/home-assistant
- name: Setup Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.14"
+1 -1
View File
@@ -40,7 +40,7 @@ repos:
rev: v3.21.2
hooks:
- id: pyupgrade
args: [--py311-plus]
args: [--py312-plus]
- repo: https://github.com/adrienverge/yamllint.git
rev: v1.37.1
hooks:
+1 -1
View File
@@ -9,7 +9,7 @@ This document provides essential context for AI models interacting with this pro
## 2. Core Technologies & Stack
* **Languages:** Python (>=3.11), C++ (gnu++20)
* **Languages:** Python (>=3.12), C++ (gnu++20)
* **Frameworks & Runtimes:** PlatformIO, Arduino, ESP-IDF.
* **Build Systems:** PlatformIO is the primary build system. CMake is used as an alternative.
* **Configuration:** YAML.
+2
View File
@@ -266,6 +266,7 @@ esphome/components/integration/* @OttoWinter
esphome/components/internal_temperature/* @Mat931
esphome/components/interval/* @esphome/core
esphome/components/ir_rf_proxy/* @kbx81
esphome/components/it8951/* @koosoli @limengdu @Passific
esphome/components/jsn_sr04t/* @Mafus1
esphome/components/json/* @esphome/core
esphome/components/kamstrup_kmp/* @cfeenstra1024
@@ -578,6 +579,7 @@ esphome/components/wake_on_lan/* @clydebarrow @willwill2will54
esphome/components/watchdog/* @oarcher
esphome/components/water_heater/* @dhoeben
esphome/components/waveshare_epaper/* @clydebarrow
esphome/components/waveshare_io_ch32v003/* @latonita
esphome/components/web_server/ota/* @esphome/core
esphome/components/web_server_base/* @esphome/core
esphome/components/web_server_idf/* @dentra
+2 -12
View File
@@ -1,5 +1,5 @@
ARG BUILD_VERSION=dev
ARG BUILD_BASE_VERSION=2026.06.0
ARG BUILD_BASE_VERSION=2026.06.1
ARG BUILD_TYPE=docker
FROM ghcr.io/esphome/docker-base:debian-${BUILD_BASE_VERSION} AS base-source-docker
@@ -11,16 +11,6 @@ FROM base-source-${BUILD_TYPE} AS base
RUN git config --system --add safe.directory "*" \
&& git config --system advice.detachedHead false
# Install build tools for Python packages that require compilation
# (e.g., ruamel.yaml.clib used by ESP-IDF's idf-component-manager).
# Also install libusb-1.0 at runtime so the ESP-IDF tools installer can
# validate openocd-esp32 (it dynamically links libusb-1.0.so.0); without
# it idf_tools.py rejects the openocd install with exit 127 and aborts
# the whole framework setup.
RUN apt-get update \
&& apt-get install -y --no-install-recommends build-essential libusb-1.0-0 \
&& rm -rf /var/lib/apt/lists/*
ENV PIP_DISABLE_PIP_VERSION_CHECK=1
RUN pip install --no-cache-dir -U pip uv==0.10.1
@@ -32,7 +22,7 @@ RUN \
-r /requirements.txt
# Install the ESPHome Device Builder dashboard.
RUN uv pip install --no-cache-dir esphome-device-builder==1.0.12
RUN uv pip install --no-cache-dir esphome-device-builder==1.0.21
RUN \
platformio settings set enable_telemetry No \
@@ -19,14 +19,6 @@ if bashio::config.true 'leave_front_door_open'; then
export DISABLE_HA_AUTHENTICATION=true
fi
if bashio::config.true 'streamer_mode'; then
export ESPHOME_STREAMER_MODE=true
fi
if bashio::config.has_value 'relative_url'; then
export ESPHOME_DASHBOARD_RELATIVE_URL=$(bashio::config 'relative_url')
fi
if bashio::config.has_value 'default_compile_process_limit'; then
export ESPHOME_DEFAULT_COMPILE_PROCESS_LIMIT=$(bashio::config 'default_compile_process_limit')
else
+28 -19
View File
@@ -52,11 +52,6 @@ from esphome.const import (
CONF_WEB_SERVER,
CONF_WIFI,
ENV_NOGITIGNORE,
KEY_CORE,
KEY_TARGET_PLATFORM,
PLATFORM_ESP32,
PLATFORM_ESP8266,
PLATFORM_RP2040,
SECRETS_FILES,
Toolchain,
)
@@ -359,7 +354,7 @@ def choose_upload_log_host(
bootsel_permission_error = False
if (
purpose == Purpose.UPLOADING
and CORE.data.get(KEY_CORE, {}).get(KEY_TARGET_PLATFORM) == PLATFORM_RP2040
and CORE.is_rp2040
and (picotool := _find_picotool()) is not None
):
bootsel = detect_rp2040_bootsel(picotool)
@@ -406,7 +401,7 @@ def choose_upload_log_host(
# Show helpful BOOTSEL instructions for RP2040 when no BOOTSEL device is found
if (
purpose == Purpose.UPLOADING
and CORE.data.get(KEY_CORE, {}).get(KEY_TARGET_PLATFORM) == PLATFORM_RP2040
and CORE.is_rp2040
and not any(get_port_type(opt[1]) == PortType.BOOTSEL for opt in options)
):
if bootsel_permission_error:
@@ -984,7 +979,7 @@ def upload_using_platformio(config: ConfigType, port: str) -> int:
# RP2040 platform-raspberrypi build recipe expects firmware.bin.signed for
# the upload target, but 'nobuild' skips the build phase that creates it.
# Create it here so the upload doesn't fail.
if CORE.data.get(KEY_CORE, {}).get(KEY_TARGET_PLATFORM) == PLATFORM_RP2040:
if CORE.is_rp2040:
idedata = toolchain.get_idedata(config)
build_dir = Path(idedata.firmware_elf_path).parent
firmware_bin = build_dir / "firmware.bin"
@@ -1169,10 +1164,10 @@ def upload_program(
check_permissions(host)
exit_code = 1
if CORE.target_platform in (PLATFORM_ESP32, PLATFORM_ESP8266):
if CORE.is_esp32 or CORE.is_esp8266:
file = getattr(args, "file", None)
exit_code = upload_using_esptool(config, host, file, args.upload_speed)
elif CORE.target_platform == PLATFORM_RP2040 or CORE.is_libretiny:
elif CORE.is_rp2040 or CORE.is_libretiny:
exit_code = upload_using_platformio(config, host)
# else: Unknown target platform, exit_code remains 1
@@ -1493,12 +1488,29 @@ _LEGACY_REDACTION_REMOVAL = "2026.12.0"
def _redact_with_legacy_fallback(output: str) -> str:
unmarked: set[str] = set()
# Track the top-level ``substitutions:`` block. Its keys are arbitrary
# user-chosen names with no schema validator, so the ``cv.sensitive(...)``
# migration named in the warning can't be applied to them. Their values are
# still redacted, but emitting the (unactionable) deprecation warning would
# only confuse users.
in_substitutions = False
def _replace(m: re.Match[str]) -> str:
unmarked.add(m.group("key"))
return f"{m.group('key')}: \\033[8m{m.group('val')}\\033[28m"
output = _LEGACY_REDACTION_RE.sub(_replace, output)
lines = output.split("\n")
for i, line in enumerate(lines):
# A non-indented, non-blank line is a top-level key that opens or
# closes the substitutions block.
if line and not line[0].isspace():
in_substitutions = line.startswith(f"{CONF_SUBSTITUTIONS}:")
m = _LEGACY_REDACTION_RE.search(line)
if m is None:
continue
if not in_substitutions:
unmarked.add(m.group("key"))
lines[i] = (
f"{line[: m.start()]}{m.group('key')}: "
f"\\033[8m{m.group('val')}\\033[28m{line[m.end() :]}"
)
output = "\n".join(lines)
for key in sorted(unmarked):
_LOGGER.warning(
"Field '%s' is being redacted by a legacy substring heuristic. "
@@ -1629,10 +1641,7 @@ def command_run(args: ArgsProtocol, config: ConfigType) -> int | None:
# After BOOTSEL upload, wait for a new serial port to appear
# so it shows up in the log chooser
if (
successful_device is None
and CORE.data.get(KEY_CORE, {}).get(KEY_TARGET_PLATFORM) == PLATFORM_RP2040
):
if successful_device is None and CORE.is_rp2040:
_wait_for_serial_port(known_ports=pre_upload_ports)
# If exactly one new serial port appeared, use it directly
serial_ports = get_serial_ports()
+3 -6
View File
@@ -12,12 +12,9 @@ from __future__ import annotations
import asyncio
from collections.abc import Awaitable, Callable
import threading
from typing import Generic, TypeVar
_T = TypeVar("_T")
class AsyncThreadRunner(threading.Thread, Generic[_T]):
class AsyncThreadRunner[T](threading.Thread):
"""Run an async coroutine in a daemon thread and expose its result.
The runner catches all exceptions from the coroutine and stores them in
@@ -35,10 +32,10 @@ class AsyncThreadRunner(threading.Thread, Generic[_T]):
result = runner.result
"""
def __init__(self, coro_factory: Callable[[], Awaitable[_T]]) -> None:
def __init__(self, coro_factory: Callable[[], Awaitable[T]]) -> None:
super().__init__(daemon=True)
self._coro_factory = coro_factory
self.result: _T | None = None
self.result: T | None = None
self.exception: BaseException | None = None
self.event = threading.Event()
+1 -1
View File
@@ -25,7 +25,7 @@ void A01nyubComponent::check_buffer_() {
if (this->buffer_[3] == checksum) {
float distance = (this->buffer_[1] << 8) + this->buffer_[2];
if (distance > 280) {
float meters = distance / 1000.0;
float meters = distance / 1000.0f;
ESP_LOGV(TAG, "Distance from sensor: %f mm, %f m", distance, meters);
this->publish_state(meters);
} else {
+1 -1
View File
@@ -216,7 +216,7 @@ void AcDimmer::setup() {
}
void AcDimmer::write_state(float state) {
state = std::acos(1 - (2 * state)) / std::numbers::pi; // RMS power compensation
state = std::acos(1 - (2 * state)) / std::numbers::pi_v<float>; // RMS power compensation
auto new_value = static_cast<uint16_t>(roundf(state * 65535));
if (new_value != 0 && this->store_.value == 0)
this->store_.init_cycle = this->init_with_half_cycle_;
+8 -5
View File
@@ -66,15 +66,18 @@ float ADCSensor::sample() {
}
uint8_t pin = this->pin_->get_pin();
#ifdef CYW43_USES_VSYS_PIN
#if defined(CYW43_USES_VSYS_PIN) && defined(USE_WIFI)
if (pin == PICO_VSYS_PIN) {
// Measuring VSYS on Raspberry Pico W needs to be wrapped with
// `cyw43_thread_enter()`/`cyw43_thread_exit()` as discussed in
// https://github.com/raspberrypi/pico-sdk/issues/1222, since Wifi chip and
// VSYS ADC both share GPIO29
// VSYS ADC both share GPIO29.
// The USE_WIFI guard is required because CYW43_USES_VSYS_PIN can be defined
// transitively (e.g. via lwip_wrap.h) even on non-WiFi boards where the CYW43
// driver is never initialized; calling cyw43_thread_enter() there hard-faults.
cyw43_thread_enter();
}
#endif // CYW43_USES_VSYS_PIN
#endif // defined(CYW43_USES_VSYS_PIN) && defined(USE_WIFI)
adc_gpio_init(pin);
adc_select_input(pin - 26);
@@ -84,11 +87,11 @@ float ADCSensor::sample() {
aggr.add_sample(raw);
}
#ifdef CYW43_USES_VSYS_PIN
#if defined(CYW43_USES_VSYS_PIN) && defined(USE_WIFI)
if (pin == PICO_VSYS_PIN) {
cyw43_thread_exit();
}
#endif // CYW43_USES_VSYS_PIN
#endif // defined(CYW43_USES_VSYS_PIN) && defined(USE_WIFI)
if (this->output_raw_) {
return aggr.aggregate();
+5 -5
View File
@@ -114,13 +114,13 @@ void Am43Component::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
this->decoder_->decode(param->notify.value, param->notify.value_len);
if (this->decoder_->has_position()) {
this->position = ((float) this->decoder_->position_ / 100.0);
this->position = ((float) this->decoder_->position_ / 100.0f);
if (!this->invert_position_)
this->position = 1 - this->position;
if (this->position > 0.97)
this->position = 1.0;
if (this->position < 0.02)
this->position = 0.0;
if (this->position > 0.97f)
this->position = 1.0f;
if (this->position < 0.02f)
this->position = 0.0f;
this->publish_state();
}
+2 -2
View File
@@ -6,9 +6,9 @@
namespace esphome::anova {
float ftoc(float f) { return (f - 32.0) * (5.0f / 9.0f); }
float ftoc(float f) { return (f - 32.0f) * (5.0f / 9.0f); }
float ctof(float c) { return (c * 9.0f / 5.0f) + 32.0; }
float ctof(float c) { return (c * 9.0f / 5.0f) + 32.0f; }
AnovaPacket *AnovaCodec::clean_packet_() {
this->packet_.length = strlen((char *) this->packet_.data);
+2
View File
@@ -305,6 +305,7 @@ CONFIG_SCHEMA = cv.All(
rtl87xx=4, # Moderate RAM, BSD-style sockets
host=4, # Abundant resources
ln882x=4, # Moderate RAM
nrf52=4, # ~256KB RAM, BSD sockets
): cv.int_range(min=1, max=10),
cv.SplitDefault(
CONF_MAX_CONNECTIONS,
@@ -315,6 +316,7 @@ CONFIG_SCHEMA = cv.All(
rtl87xx=5, # Moderate RAM
host=8, # Abundant resources
ln882x=5, # Moderate RAM
nrf52=4, # ~256KB RAM, BSD sockets, Thread (single HA controller)
): cv.int_range(min=1, max=20),
# Maximum queued send buffers per connection before dropping connection
# Each buffer uses ~8-12 bytes overhead plus actual message size
@@ -31,6 +31,13 @@
#include <vector>
#include <string>
#if defined(LOG_LEVEL_NONE)
// Zephyr defines LOG_LEVEL_NONE as a logging macro that collides with the LogLevel enum value of
// the same name in the generated api_pb2.h. Undefine it for the rest of this translation unit so
// the enum parses; nothing below needs Zephyr's logging macro.
#undef LOG_LEVEL_NONE
#endif
namespace esphome::api {
// This file only provides includes, no actual code
+1 -1
View File
@@ -395,7 +395,7 @@ async def to_code(config):
)
if data.mp3_support:
cg.add_define("USE_AUDIO_MP3_SUPPORT")
add_idf_component(name="esphome/micro-mp3", ref="0.3.0")
add_idf_component(name="esphome/micro-mp3", ref="0.4.0")
_emit_memory_pair(
data.mp3.buffer_memory,
"CONFIG_MICRO_MP3_PREFER_PSRAM",
@@ -112,7 +112,7 @@ float BinarySensorMap::bayesian_predicate_(bool sensor_state, float prior, float
prob_state_source_false = 1 - prob_given_false;
}
return prob_state_source_true / (prior * prob_state_source_true + (1.0 - prior) * prob_state_source_false);
return prob_state_source_true / (prior * prob_state_source_true + (1.0f - prior) * prob_state_source_false);
}
void BinarySensorMap::add_channel(binary_sensor::BinarySensor *sensor, float value) {
+1 -1
View File
@@ -205,7 +205,7 @@ void BL0906::read_data_(const uint8_t address, const float reference, sensor::Se
// Chip temperature
if (reference == BL0906_TREF) {
value = (float) to_int32_t(data_s24);
value = (value - 64) * 12.5 / 59 - 40;
value = (value - 64) * 12.5f / 59 - 40;
}
sensor->publish_state(value);
}
+1 -1
View File
@@ -120,7 +120,7 @@ float BL0940::calculate_power_reference_() {
float BL0940::calculate_energy_reference_() {
// formula: 3600000 * 4046 * RL * R1 * 1000 / (1638.4 * 256) / Vref² / (R1 + R2)
// or: power_reference_ * 3600000 / (1638.4 * 256)
return this->power_reference_cal_ * 3600000 / (1638.4 * 256);
return this->power_reference_cal_ * 3600000 / (1638.4f * 256);
}
float BL0940::calculate_calibration_value_(float state) { return (100 + state) / 100; }
+11
View File
@@ -211,6 +211,17 @@ CONFIG_SCHEMA = (
.add_extra(set_reference_values)
)
# BL0940 datasheet: 4800 baud, 8 data bits, no parity (stop bits are 1.5 -- not
# representable in the uart schema, so it isn't asserted).
FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema(
"bl0940",
baud_rate=4800,
data_bits=8,
parity="NONE",
require_rx=True,
require_tx=True,
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
+2 -2
View File
@@ -124,14 +124,14 @@ void BL0942::setup() {
// If either current or voltage references are set explicitly by the user,
// calculate the power reference from it unless that is also explicitly set.
if ((this->current_reference_set_ || this->voltage_reference_set_) && !this->power_reference_set_) {
this->power_reference_ = (this->voltage_reference_ * this->current_reference_ * 3537.0 / 305978.0) / 73989.0;
this->power_reference_ = (this->voltage_reference_ * this->current_reference_ * 3537.0f / 305978.0f) / 73989.0f;
this->power_reference_set_ = true;
}
// Similarly for energy reference, if the power reference was set by the user
// either implicitly or explicitly.
if (this->power_reference_set_ && !this->energy_reference_set_) {
this->energy_reference_ = this->power_reference_ * 3600000 / 419430.4;
this->energy_reference_ = this->power_reference_ * 3600000 / 419430.4f;
this->energy_reference_set_ = true;
}
+10 -3
View File
@@ -25,11 +25,14 @@ void BLENUS::write_array(const uint8_t *data, size_t len) {
if (atomic_get(&this->tx_status_) == TX_DISABLED) {
return;
}
auto sent = ring_buf_put(&global_ble_tx_ring_buf, data, len);
if (sent < len) {
ESP_LOGE(TAG, "TX dropping %u bytes", len - sent);
// ring_buf_put() performs a partial write when the buffer is nearly full, which would commit a
// truncated fragment and corrupt the stream. Only write when the whole payload fits, so the byte
// stream never contains a partial message.
if (ring_buf_space_get(&global_ble_tx_ring_buf) < len) {
ESP_LOGE(TAG, "TX dropping %u bytes", len);
return;
}
ring_buf_put(&global_ble_tx_ring_buf, data, len);
#ifdef USE_UART_DEBUGGER
for (size_t i = 0; i < len; i++) {
this->debug_callback_.call(uart::UART_DIRECTION_TX, data[i]);
@@ -197,6 +200,10 @@ void BLENUS::setup() {
void BLENUS::on_log(uint8_t level, const char *tag, const char *message, size_t message_len) {
(void) level;
(void) tag;
// make sure there is space for '\n' or entire message is dropped
if (ring_buf_space_get(&global_ble_tx_ring_buf) < message_len + 1) {
return;
}
this->write_array(reinterpret_cast<const uint8_t *>(message), message_len);
const char c = '\n';
this->write_array(reinterpret_cast<const uint8_t *>(&c), 1);
+1 -1
View File
@@ -1,5 +1,6 @@
import esphome.codegen as cg
from esphome.components import esp32, i2c
from esphome.components.const import CONF_STATE_SAVE_INTERVAL
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_SAMPLE_RATE, CONF_TEMPERATURE_OFFSET, Framework
@@ -12,7 +13,6 @@ MULTI_CONF = True
CONF_BME680_BSEC_ID = "bme680_bsec_id"
CONF_IAQ_MODE = "iaq_mode"
CONF_SUPPLY_VOLTAGE = "supply_voltage"
CONF_STATE_SAVE_INTERVAL = "state_save_interval"
bme680_bsec_ns = cg.esphome_ns.namespace("bme680_bsec")
+5 -3
View File
@@ -1,5 +1,10 @@
import esphome.codegen as cg
from esphome.components import sensor
from esphome.components.const import (
CONF_BREATH_VOC_EQUIVALENT,
CONF_CO2_EQUIVALENT,
CONF_IAQ,
)
import esphome.config_validation as cv
from esphome.const import (
CONF_GAS_RESISTANCE,
@@ -29,9 +34,6 @@ from . import CONF_BME680_BSEC_ID, SAMPLE_RATE_OPTIONS, BME680BSECComponent
DEPENDENCIES = ["bme680_bsec"]
CONF_BREATH_VOC_EQUIVALENT = "breath_voc_equivalent"
CONF_CO2_EQUIVALENT = "co2_equivalent"
CONF_IAQ = "iaq"
ICON_ACCURACY = "mdi:checkbox-marked-circle-outline"
UNIT_IAQ = "IAQ"
+1 -1
View File
@@ -3,6 +3,7 @@ from pathlib import Path
from esphome import core, external_files
import esphome.codegen as cg
from esphome.components.const import CONF_STATE_SAVE_INTERVAL
import esphome.config_validation as cv
from esphome.const import (
CONF_ID,
@@ -24,7 +25,6 @@ CONF_ALGORITHM_OUTPUT = "algorithm_output"
CONF_BME68X_BSEC2_ID = "bme68x_bsec2_id"
CONF_IAQ_MODE = "iaq_mode"
CONF_OPERATING_AGE = "operating_age"
CONF_STATE_SAVE_INTERVAL = "state_save_interval"
CONF_SUPPLY_VOLTAGE = "supply_voltage"
bme68x_bsec2_ns = cg.esphome_ns.namespace("bme68x_bsec2")
+5 -3
View File
@@ -1,5 +1,10 @@
import esphome.codegen as cg
from esphome.components import sensor
from esphome.components.const import (
CONF_BREATH_VOC_EQUIVALENT,
CONF_CO2_EQUIVALENT,
CONF_IAQ,
)
import esphome.config_validation as cv
from esphome.const import (
CONF_GAS_RESISTANCE,
@@ -29,9 +34,6 @@ from . import CONF_BME68X_BSEC2_ID, SAMPLE_RATE_OPTIONS, BME68xBSEC2Component
DEPENDENCIES = ["bme68x_bsec2"]
CONF_BREATH_VOC_EQUIVALENT = "breath_voc_equivalent"
CONF_CO2_EQUIVALENT = "co2_equivalent"
CONF_IAQ = "iaq"
CONF_IAQ_STATIC = "iaq_static"
ICON_ACCURACY = "mdi:checkbox-marked-circle-outline"
UNIT_IAQ = "IAQ"
@@ -204,7 +204,7 @@ void MedianCombinationComponent::handle_new_value(float value) {
median = sensor_states[sensor_states_size / 2];
} else {
// Even number of measurements, use the average of the two middle measurements
median = (sensor_states[sensor_states_size / 2] + sensor_states[sensor_states_size / 2 - 1]) / 2.0;
median = (sensor_states[sensor_states_size / 2] + sensor_states[sensor_states_size / 2 - 1]) / 2.0f;
}
}
+4
View File
@@ -8,8 +8,10 @@ BYTE_ORDER_BIG = "big_endian"
CONF_ACCELEROMETER_ODR = "accelerometer_odr"
CONF_ACCELEROMETER_RANGE = "accelerometer_range"
CONF_B_CONSTANT = "b_constant"
CONF_BREATH_VOC_EQUIVALENT = "breath_voc_equivalent"
CONF_BYTE_ORDER = "byte_order"
CONF_CLIMATE_ID = "climate_id"
CONF_CO2_EQUIVALENT = "co2_equivalent"
CONF_COLOR_DEPTH = "color_depth"
CONF_CRC_ENABLE = "crc_enable"
CONF_DATA_BITS = "data_bits"
@@ -17,6 +19,7 @@ CONF_DRAW_ROUNDING = "draw_rounding"
CONF_ENABLED = "enabled"
CONF_GYROSCOPE_ODR = "gyroscope_odr"
CONF_GYROSCOPE_RANGE = "gyroscope_range"
CONF_IAQ = "iaq"
CONF_IGNORE_NOT_FOUND = "ignore_not_found"
CONF_LIBRETINY = "libretiny"
CONF_LOOP = "loop"
@@ -28,6 +31,7 @@ CONF_RECEIVER_FREQUENCY = "receiver_frequency"
CONF_REQUEST_HEADERS = "request_headers"
CONF_ROWS = "rows"
CONF_SHA256 = "sha256"
CONF_STATE_SAVE_INTERVAL = "state_save_interval"
CONF_STOP_BITS = "stop_bits"
CONF_USE_PSRAM = "use_psram"
CONF_VOLUME_INCREMENT = "volume_increment"
@@ -39,7 +39,7 @@ void CurrentBasedCover::control(const CoverCall &call) {
auto opt_pos = call.get_position();
if (opt_pos.has_value()) {
auto pos = *opt_pos;
if (fabsf(this->position - pos) < 0.01) {
if (fabsf(this->position - pos) < 0.01f) {
// already at target
} else {
auto op = pos < this->position ? COVER_OPERATION_CLOSING : COVER_OPERATION_OPENING;
+1 -1
View File
@@ -151,7 +151,7 @@ uint8_t DaikinBrcClimate::temperature_() {
// Temperature in remote is in F
if (this->fahrenheit_) {
temperature = (uint8_t) roundf(
clamp<float>(((this->target_temperature * 1.8) + 32), DAIKIN_BRC_TEMP_MIN_F, DAIKIN_BRC_TEMP_MAX_F));
clamp<float>(((this->target_temperature * 1.8f) + 32), DAIKIN_BRC_TEMP_MIN_F, DAIKIN_BRC_TEMP_MAX_F));
} else {
temperature = ((uint8_t) roundf(this->target_temperature) - 9) << 1;
}
@@ -138,7 +138,7 @@ float DallasTemperatureSensor::get_temp_c_() {
if (this->scratch_pad_[7] == 0) {
return NAN;
}
return (temp >> 1) + (this->scratch_pad_[7] - this->scratch_pad_[6]) / float(this->scratch_pad_[7]) - 0.25;
return (temp >> 1) + (this->scratch_pad_[7] - this->scratch_pad_[6]) / float(this->scratch_pad_[7]) - 0.25f;
}
switch (this->resolution_) {
case 9:
@@ -77,7 +77,7 @@ async def to_code(config):
url = config[CONF_PACKAGE_IMPORT_URL]
if config[CONF_IMPORT_FULL_CONFIG]:
url += "?full_config"
cg.add(dashboard_import_ns.set_package_import_url(url))
cg.add(dashboard_import_ns.set_package_import_url(cg.FlashStringLiteral(url)))
def import_config(
@@ -2,9 +2,10 @@
namespace esphome::dashboard_import {
static const char *g_package_import_url = ""; // NOLINT
static const char EMPTY_URL[] PROGMEM = ""; // NOLINT
static ProgmemStr g_package_import_url = reinterpret_cast<ProgmemStr>(EMPTY_URL); // NOLINT
const char *get_package_import_url() { return g_package_import_url; }
void set_package_import_url(const char *url) { g_package_import_url = url; }
ProgmemStr get_package_import_url() { return g_package_import_url; }
void set_package_import_url(ProgmemStr url) { g_package_import_url = url; }
} // namespace esphome::dashboard_import
@@ -1,8 +1,10 @@
#pragma once
#include "esphome/core/progmem.h"
namespace esphome::dashboard_import {
const char *get_package_import_url();
void set_package_import_url(const char *url);
ProgmemStr get_package_import_url();
void set_package_import_url(ProgmemStr url);
} // namespace esphome::dashboard_import
@@ -96,7 +96,8 @@ class DeepSleepComponent final : public Component {
#endif
#if !defined(USE_ESP32_VARIANT_ESP32C2) && !defined(USE_ESP32_VARIANT_ESP32C3) && \
!defined(USE_ESP32_VARIANT_ESP32C6) && !defined(USE_ESP32_VARIANT_ESP32C61) && !defined(USE_ESP32_VARIANT_ESP32H2)
!defined(USE_ESP32_VARIANT_ESP32C5) && !defined(USE_ESP32_VARIANT_ESP32C6) && \
!defined(USE_ESP32_VARIANT_ESP32C61) && !defined(USE_ESP32_VARIANT_ESP32H2)
void set_touch_wakeup(bool touch_wakeup);
#endif
@@ -16,7 +16,7 @@ namespace esphome::deep_sleep {
// | ESP32-S3 | ✓ | ✓ | ✓ | |
// | ESP32-C2 | | | | ✓ |
// | ESP32-C3 | | | | ✓ |
// | ESP32-C5 | | (✓) | | (✓) |
// | ESP32-C5 | | | | |
// | ESP32-C6 | | ✓ | | ✓ |
// | ESP32-C61 | | ✓ | | ✓ |
// | ESP32-H2 | | ✓ | | |
@@ -56,7 +56,8 @@ void DeepSleepComponent::set_ext1_wakeup(Ext1Wakeup ext1_wakeup) { this->ext1_wa
#endif
#if !defined(USE_ESP32_VARIANT_ESP32C2) && !defined(USE_ESP32_VARIANT_ESP32C3) && \
!defined(USE_ESP32_VARIANT_ESP32C6) && !defined(USE_ESP32_VARIANT_ESP32C61) && !defined(USE_ESP32_VARIANT_ESP32H2)
!defined(USE_ESP32_VARIANT_ESP32C5) && !defined(USE_ESP32_VARIANT_ESP32C6) && \
!defined(USE_ESP32_VARIANT_ESP32C61) && !defined(USE_ESP32_VARIANT_ESP32H2)
void DeepSleepComponent::set_touch_wakeup(bool touch_wakeup) { this->touch_wakeup_ = touch_wakeup; }
#endif
@@ -99,7 +100,8 @@ void DeepSleepComponent::deep_sleep_() {
// Single pin wakeup (ext0) - ESP32, S2, S3 only
#if !defined(USE_ESP32_VARIANT_ESP32C2) && !defined(USE_ESP32_VARIANT_ESP32C3) && \
!defined(USE_ESP32_VARIANT_ESP32C6) && !defined(USE_ESP32_VARIANT_ESP32H2)
!defined(USE_ESP32_VARIANT_ESP32C5) && !defined(USE_ESP32_VARIANT_ESP32C6) && \
!defined(USE_ESP32_VARIANT_ESP32C61) && !defined(USE_ESP32_VARIANT_ESP32H2)
if (this->wakeup_pin_ != nullptr) {
const auto gpio_pin = gpio_num_t(this->wakeup_pin_->get_pin());
if (this->wakeup_pin_->get_flags() & gpio::FLAG_PULLUP) {
@@ -122,9 +124,9 @@ void DeepSleepComponent::deep_sleep_() {
}
#endif
// GPIO wakeup - C2, C3, C6, C61 only
#if defined(USE_ESP32_VARIANT_ESP32C2) || defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || \
defined(USE_ESP32_VARIANT_ESP32C61)
// GPIO wakeup - C2, C3, C5, C6, C61 only
#if defined(USE_ESP32_VARIANT_ESP32C2) || defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C5) || \
defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32C61)
if (this->wakeup_pin_ != nullptr) {
const auto gpio_pin = gpio_num_t(this->wakeup_pin_->get_pin());
// Make sure GPIO is in input mode, not all RTC GPIO pins are input by default
@@ -154,7 +156,8 @@ void DeepSleepComponent::deep_sleep_() {
// Touch wakeup - ESP32, S2, S3 only
#if !defined(USE_ESP32_VARIANT_ESP32C2) && !defined(USE_ESP32_VARIANT_ESP32C3) && \
!defined(USE_ESP32_VARIANT_ESP32C6) && !defined(USE_ESP32_VARIANT_ESP32C61) && !defined(USE_ESP32_VARIANT_ESP32H2)
!defined(USE_ESP32_VARIANT_ESP32C5) && !defined(USE_ESP32_VARIANT_ESP32C6) && \
!defined(USE_ESP32_VARIANT_ESP32C61) && !defined(USE_ESP32_VARIANT_ESP32H2)
if (this->touch_wakeup_.has_value() && *(this->touch_wakeup_)) {
esp_sleep_enable_touchpad_wakeup();
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
+1 -1
View File
@@ -15,7 +15,7 @@ class DemoSensor final : public sensor::Sensor, public PollingComponent {
float base = std::isnan(this->state) ? 0.0f : this->state;
this->publish_state(base + val * 10);
} else {
if (val < 0.1) {
if (val < 0.1f) {
this->publish_state(NAN);
} else {
this->publish_state(val * 100);
+1 -1
View File
@@ -9,7 +9,7 @@ namespace esphome::demo {
class DemoSwitch final : public switch_::Switch, public Component {
public:
void setup() override {
bool initial = random_float() < 0.5;
bool initial = random_float() < 0.5f;
this->publish_state(initial);
}
+2 -2
View File
@@ -10,9 +10,9 @@ class DemoTextSensor final : public text_sensor::TextSensor, public PollingCompo
public:
void update() override {
float val = random_float();
if (val < 0.33) {
if (val < 0.33f) {
this->publish_state("foo");
} else if (val < 0.66) {
} else if (val < 0.66f) {
this->publish_state("bar");
} else {
this->publish_state("foobar");
@@ -8,13 +8,13 @@
namespace esphome::dfrobot_sen0395 {
template<typename... Ts>
class DfrobotSen0395ResetAction : public Action<Ts...>, public Parented<DfrobotSen0395Component> {
class DfrobotSen0395ResetAction final : public Action<Ts...>, public Parented<DfrobotSen0395Component> {
public:
void play(const Ts &...x) { this->parent_->enqueue(make_unique<ResetSystemCommand>()); }
};
template<typename... Ts>
class DfrobotSen0395SettingsAction : public Action<Ts...>, public Parented<DfrobotSen0395Component> {
class DfrobotSen0395SettingsAction final : public Action<Ts...>, public Parented<DfrobotSen0395Component> {
public:
TEMPLATABLE_VALUE(int8_t, factory_reset)
TEMPLATABLE_VALUE(int8_t, start_after_power_on)
+27 -27
View File
@@ -121,51 +121,51 @@ DetRangeCfgCommand::DetRangeCfgCommand(float min1, float max1, float min2, float
this->cmd_ = "detRangeCfg -1 0 0";
} else if (min2 < 0 || max2 < 0) {
this->min1_ = min1 = round(min1 / 0.15) * 0.15;
this->max1_ = max1 = round(max1 / 0.15) * 0.15;
this->min1_ = min1 = roundf(min1 / 0.15f) * 0.15f;
this->max1_ = max1 = roundf(max1 / 0.15f) * 0.15f;
this->min2_ = min2 = this->max2_ = max2 = this->min3_ = min3 = this->max3_ = max3 = this->min4_ = min4 =
this->max4_ = max4 = -1;
char buf[72]; // max 72: "detRangeCfg -1 "(15) + 8 * (float(5) + space(1)) + null
snprintf(buf, sizeof(buf), "detRangeCfg -1 %.0f %.0f", min1 / 0.15, max1 / 0.15);
snprintf(buf, sizeof(buf), "detRangeCfg -1 %.0f %.0f", min1 / 0.15f, max1 / 0.15f);
this->cmd_ = buf;
} else if (min3 < 0 || max3 < 0) {
this->min1_ = min1 = round(min1 / 0.15) * 0.15;
this->max1_ = max1 = round(max1 / 0.15) * 0.15;
this->min2_ = min2 = round(min2 / 0.15) * 0.15;
this->max2_ = max2 = round(max2 / 0.15) * 0.15;
this->min1_ = min1 = roundf(min1 / 0.15f) * 0.15f;
this->max1_ = max1 = roundf(max1 / 0.15f) * 0.15f;
this->min2_ = min2 = roundf(min2 / 0.15f) * 0.15f;
this->max2_ = max2 = roundf(max2 / 0.15f) * 0.15f;
this->min3_ = min3 = this->max3_ = max3 = this->min4_ = min4 = this->max4_ = max4 = -1;
char buf[72]; // max 72: "detRangeCfg -1 "(15) + 8 * (float(5) + space(1)) + null
snprintf(buf, sizeof(buf), "detRangeCfg -1 %.0f %.0f %.0f %.0f", min1 / 0.15, max1 / 0.15, min2 / 0.15,
max2 / 0.15);
snprintf(buf, sizeof(buf), "detRangeCfg -1 %.0f %.0f %.0f %.0f", min1 / 0.15f, max1 / 0.15f, min2 / 0.15f,
max2 / 0.15f);
this->cmd_ = buf;
} else if (min4 < 0 || max4 < 0) {
this->min1_ = min1 = round(min1 / 0.15) * 0.15;
this->max1_ = max1 = round(max1 / 0.15) * 0.15;
this->min2_ = min2 = round(min2 / 0.15) * 0.15;
this->max2_ = max2 = round(max2 / 0.15) * 0.15;
this->min3_ = min3 = round(min3 / 0.15) * 0.15;
this->max3_ = max3 = round(max3 / 0.15) * 0.15;
this->min1_ = min1 = roundf(min1 / 0.15f) * 0.15f;
this->max1_ = max1 = roundf(max1 / 0.15f) * 0.15f;
this->min2_ = min2 = roundf(min2 / 0.15f) * 0.15f;
this->max2_ = max2 = roundf(max2 / 0.15f) * 0.15f;
this->min3_ = min3 = roundf(min3 / 0.15f) * 0.15f;
this->max3_ = max3 = roundf(max3 / 0.15f) * 0.15f;
this->min4_ = min4 = this->max4_ = max4 = -1;
char buf[72]; // max 72: "detRangeCfg -1 "(15) + 8 * (float(5) + space(1)) + null
snprintf(buf, sizeof(buf), "detRangeCfg -1 %.0f %.0f %.0f %.0f %.0f %.0f", min1 / 0.15, max1 / 0.15, min2 / 0.15,
max2 / 0.15, min3 / 0.15, max3 / 0.15);
snprintf(buf, sizeof(buf), "detRangeCfg -1 %.0f %.0f %.0f %.0f %.0f %.0f", min1 / 0.15f, max1 / 0.15f, min2 / 0.15f,
max2 / 0.15f, min3 / 0.15f, max3 / 0.15f);
this->cmd_ = buf;
} else {
this->min1_ = min1 = round(min1 / 0.15) * 0.15;
this->max1_ = max1 = round(max1 / 0.15) * 0.15;
this->min2_ = min2 = round(min2 / 0.15) * 0.15;
this->max2_ = max2 = round(max2 / 0.15) * 0.15;
this->min3_ = min3 = round(min3 / 0.15) * 0.15;
this->max3_ = max3 = round(max3 / 0.15) * 0.15;
this->min4_ = min4 = round(min4 / 0.15) * 0.15;
this->max4_ = max4 = round(max4 / 0.15) * 0.15;
this->min1_ = min1 = roundf(min1 / 0.15f) * 0.15f;
this->max1_ = max1 = roundf(max1 / 0.15f) * 0.15f;
this->min2_ = min2 = roundf(min2 / 0.15f) * 0.15f;
this->max2_ = max2 = roundf(max2 / 0.15f) * 0.15f;
this->min3_ = min3 = roundf(min3 / 0.15f) * 0.15f;
this->max3_ = max3 = roundf(max3 / 0.15f) * 0.15f;
this->min4_ = min4 = roundf(min4 / 0.15f) * 0.15f;
this->max4_ = max4 = roundf(max4 / 0.15f) * 0.15f;
char buf[72]; // max 72: "detRangeCfg -1 "(15) + 8 * (float(5) + space(1)) + null
snprintf(buf, sizeof(buf), "detRangeCfg -1 %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f", min1 / 0.15, max1 / 0.15,
min2 / 0.15, max2 / 0.15, min3 / 0.15, max3 / 0.15, min4 / 0.15, max4 / 0.15);
snprintf(buf, sizeof(buf), "detRangeCfg -1 %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f", min1 / 0.15f, max1 / 0.15f,
min2 / 0.15f, max2 / 0.15f, min3 / 0.15f, max3 / 0.15f, min4 / 0.15f, max4 / 0.15f);
this->cmd_ = buf;
}
@@ -36,7 +36,7 @@ class CircularCommandQueue {
std::unique_ptr<Command> commands_[COMMAND_QUEUE_SIZE];
};
class DfrobotSen0395Component : public uart::UARTDevice, public Component {
class DfrobotSen0395Component final : public uart::UARTDevice, public Component {
#ifdef USE_SWITCH
SUB_SWITCH(sensor_active)
SUB_SWITCH(turn_on_led)
@@ -9,22 +9,22 @@ namespace esphome::dfrobot_sen0395 {
class DfrobotSen0395Switch : public switch_::Switch, public Component, public Parented<DfrobotSen0395Component> {};
class Sen0395PowerSwitch : public DfrobotSen0395Switch {
class Sen0395PowerSwitch final : public DfrobotSen0395Switch {
public:
void write_state(bool state) override;
};
class Sen0395LedSwitch : public DfrobotSen0395Switch {
class Sen0395LedSwitch final : public DfrobotSen0395Switch {
public:
void write_state(bool state) override;
};
class Sen0395UartPresenceSwitch : public DfrobotSen0395Switch {
class Sen0395UartPresenceSwitch final : public DfrobotSen0395Switch {
public:
void write_state(bool state) override;
};
class Sen0395StartAfterBootSwitch : public DfrobotSen0395Switch {
class Sen0395StartAfterBootSwitch final : public DfrobotSen0395Switch {
public:
void write_state(bool state) override;
};
+1 -1
View File
@@ -18,7 +18,7 @@ enum DHTModel : uint8_t {
};
/// Component for reading temperature/humidity measurements from DHT11/DHT22 sensors.
class DHT : public PollingComponent {
class DHT final : public PollingComponent {
public:
/** Manually select the DHT model.
*
+1 -1
View File
@@ -6,7 +6,7 @@
namespace esphome::dht12 {
class DHT12Component : public PollingComponent, public i2c::I2CDevice {
class DHT12Component final : public PollingComponent, public i2c::I2CDevice {
public:
void setup() override;
void dump_config() override;
+8 -8
View File
@@ -42,10 +42,10 @@ void Display::line_at_angle(int x, int y, int angle, int length, Color color) {
void Display::line_at_angle(int x, int y, int angle, int start_radius, int stop_radius, Color color) {
// Calculate start and end points
int x1 = (start_radius * cos(angle * M_PI / 180)) + x;
int y1 = (start_radius * sin(angle * M_PI / 180)) + y;
int x2 = (stop_radius * cos(angle * M_PI / 180)) + x;
int y2 = (stop_radius * sin(angle * M_PI / 180)) + y;
int x1 = (start_radius * std::cos(angle * std::numbers::pi_v<float> / 180)) + x;
int y1 = (start_radius * std::sin(angle * std::numbers::pi_v<float> / 180)) + y;
int x2 = (stop_radius * std::cos(angle * std::numbers::pi_v<float> / 180)) + x;
int y2 = (stop_radius * std::sin(angle * std::numbers::pi_v<float> / 180)) + y;
// Draw line
this->line(x1, y1, x2, y2, color);
@@ -228,7 +228,7 @@ void Display::filled_gauge(int center_x, int center_y, int radius1, int radius2,
int e2max, e2min;
progress = std::max(0, std::min(progress, 100)); // 0..100
int draw_progress = progress > 50 ? (100 - progress) : progress;
float tan_a = (progress == 50) ? 65535 : tan(float(draw_progress) * M_PI / 100); // slope
float tan_a = (progress == 50) ? 65535 : tanf(float(draw_progress) * std::numbers::pi_v<float> / 100); // slope
do {
// outer dots
@@ -444,15 +444,15 @@ void HOT Display::get_regular_polygon_vertex(int vertex_id, int *vertex_x, int *
// hence we rotate the shape by 270° to orient the polygon up.
rotation_degrees += ROTATION_270_DEGREES;
// Convert the rotation to radians, easier to use in trigonometrical calculations
float rotation_radians = rotation_degrees * std::numbers::pi / 180;
float rotation_radians = rotation_degrees * std::numbers::pi_v<float> / 180;
// A pointy top variation means the first vertex of the polygon is at the top center of the shape, this requires no
// additional rotation of the shape.
// A flat top variation means the first point of the polygon has to be rotated so that the first edge is horizontal,
// this requires to rotate the shape by π/edges radians counter-clockwise so that the first point is located on the
// left side of the first horizontal edge.
rotation_radians -= (variation == VARIATION_FLAT_TOP) ? std::numbers::pi / edges : 0.0;
rotation_radians -= (variation == VARIATION_FLAT_TOP) ? std::numbers::pi_v<float> / edges : 0.0f;
float vertex_angle = ((float) vertex_id) / edges * 2 * std::numbers::pi + rotation_radians;
float vertex_angle = ((float) vertex_id) / edges * 2 * std::numbers::pi_v<float> + rotation_radians;
*vertex_x = (int) std::round(std::cos(vertex_angle) * radius) + center_x;
*vertex_y = (int) std::round(std::sin(vertex_angle) * radius) + center_y;
}
+6 -6
View File
@@ -796,7 +796,7 @@ class Display : public PollingComponent {
bool show_test_card_{false};
};
class DisplayPage {
class DisplayPage final {
public:
DisplayPage(display_writer_t writer);
void show();
@@ -814,7 +814,7 @@ class DisplayPage {
DisplayPage *next_{nullptr};
};
template<typename... Ts> class DisplayPageShowAction : public Action<Ts...> {
template<typename... Ts> class DisplayPageShowAction final : public Action<Ts...> {
public:
TEMPLATABLE_VALUE(DisplayPage *, page)
@@ -826,7 +826,7 @@ template<typename... Ts> class DisplayPageShowAction : public Action<Ts...> {
}
};
template<typename... Ts> class DisplayPageShowNextAction : public Action<Ts...> {
template<typename... Ts> class DisplayPageShowNextAction final : public Action<Ts...> {
public:
DisplayPageShowNextAction(Display *buffer) : buffer_(buffer) {}
@@ -835,7 +835,7 @@ template<typename... Ts> class DisplayPageShowNextAction : public Action<Ts...>
Display *buffer_;
};
template<typename... Ts> class DisplayPageShowPrevAction : public Action<Ts...> {
template<typename... Ts> class DisplayPageShowPrevAction final : public Action<Ts...> {
public:
DisplayPageShowPrevAction(Display *buffer) : buffer_(buffer) {}
@@ -844,7 +844,7 @@ template<typename... Ts> class DisplayPageShowPrevAction : public Action<Ts...>
Display *buffer_;
};
template<typename... Ts> class DisplayIsDisplayingPageCondition : public Condition<Ts...> {
template<typename... Ts> class DisplayIsDisplayingPageCondition final : public Condition<Ts...> {
public:
DisplayIsDisplayingPageCondition(Display *parent) : parent_(parent) {}
@@ -856,7 +856,7 @@ template<typename... Ts> class DisplayIsDisplayingPageCondition : public Conditi
DisplayPage *page_;
};
class DisplayOnPageChangeTrigger : public Trigger<DisplayPage *, DisplayPage *> {
class DisplayOnPageChangeTrigger final : public Trigger<DisplayPage *, DisplayPage *> {
public:
explicit DisplayOnPageChangeTrigger(Display *parent) { parent->add_on_page_change_trigger(this); }
void process(DisplayPage *from, DisplayPage *to);
@@ -5,7 +5,7 @@
namespace esphome::display_menu_base {
template<typename... Ts> class UpAction : public Action<Ts...> {
template<typename... Ts> class UpAction final : public Action<Ts...> {
public:
explicit UpAction(DisplayMenuComponent *menu) : menu_(menu) {}
@@ -15,7 +15,7 @@ template<typename... Ts> class UpAction : public Action<Ts...> {
DisplayMenuComponent *menu_;
};
template<typename... Ts> class DownAction : public Action<Ts...> {
template<typename... Ts> class DownAction final : public Action<Ts...> {
public:
explicit DownAction(DisplayMenuComponent *menu) : menu_(menu) {}
@@ -25,7 +25,7 @@ template<typename... Ts> class DownAction : public Action<Ts...> {
DisplayMenuComponent *menu_;
};
template<typename... Ts> class LeftAction : public Action<Ts...> {
template<typename... Ts> class LeftAction final : public Action<Ts...> {
public:
explicit LeftAction(DisplayMenuComponent *menu) : menu_(menu) {}
@@ -35,7 +35,7 @@ template<typename... Ts> class LeftAction : public Action<Ts...> {
DisplayMenuComponent *menu_;
};
template<typename... Ts> class RightAction : public Action<Ts...> {
template<typename... Ts> class RightAction final : public Action<Ts...> {
public:
explicit RightAction(DisplayMenuComponent *menu) : menu_(menu) {}
@@ -45,7 +45,7 @@ template<typename... Ts> class RightAction : public Action<Ts...> {
DisplayMenuComponent *menu_;
};
template<typename... Ts> class EnterAction : public Action<Ts...> {
template<typename... Ts> class EnterAction final : public Action<Ts...> {
public:
explicit EnterAction(DisplayMenuComponent *menu) : menu_(menu) {}
@@ -55,7 +55,7 @@ template<typename... Ts> class EnterAction : public Action<Ts...> {
DisplayMenuComponent *menu_;
};
template<typename... Ts> class ShowAction : public Action<Ts...> {
template<typename... Ts> class ShowAction final : public Action<Ts...> {
public:
explicit ShowAction(DisplayMenuComponent *menu) : menu_(menu) {}
@@ -65,7 +65,7 @@ template<typename... Ts> class ShowAction : public Action<Ts...> {
DisplayMenuComponent *menu_;
};
template<typename... Ts> class HideAction : public Action<Ts...> {
template<typename... Ts> class HideAction final : public Action<Ts...> {
public:
explicit HideAction(DisplayMenuComponent *menu) : menu_(menu) {}
@@ -75,7 +75,7 @@ template<typename... Ts> class HideAction : public Action<Ts...> {
DisplayMenuComponent *menu_;
};
template<typename... Ts> class ShowMainAction : public Action<Ts...> {
template<typename... Ts> class ShowMainAction final : public Action<Ts...> {
public:
explicit ShowMainAction(DisplayMenuComponent *menu) : menu_(menu) {}
@@ -84,7 +84,7 @@ template<typename... Ts> class ShowMainAction : public Action<Ts...> {
protected:
DisplayMenuComponent *menu_;
};
template<typename... Ts> class IsActiveCondition : public Condition<Ts...> {
template<typename... Ts> class IsActiveCondition final : public Condition<Ts...> {
public:
explicit IsActiveCondition(DisplayMenuComponent *menu) : menu_(menu) {}
bool check(const Ts &...x) override { return this->menu_->is_active(); }
@@ -93,7 +93,7 @@ template<typename... Ts> class IsActiveCondition : public Condition<Ts...> {
DisplayMenuComponent *menu_;
};
class DisplayMenuOnEnterTrigger : public Trigger<const MenuItem *> {
class DisplayMenuOnEnterTrigger final : public Trigger<const MenuItem *> {
public:
explicit DisplayMenuOnEnterTrigger(MenuItem *parent) : parent_(parent) {
parent->add_on_enter_callback([this]() { this->trigger(this->parent_); });
@@ -103,7 +103,7 @@ class DisplayMenuOnEnterTrigger : public Trigger<const MenuItem *> {
MenuItem *parent_;
};
class DisplayMenuOnLeaveTrigger : public Trigger<const MenuItem *> {
class DisplayMenuOnLeaveTrigger final : public Trigger<const MenuItem *> {
public:
explicit DisplayMenuOnLeaveTrigger(MenuItem *parent) : parent_(parent) {
parent->add_on_leave_callback([this]() { this->trigger(this->parent_); });
@@ -113,7 +113,7 @@ class DisplayMenuOnLeaveTrigger : public Trigger<const MenuItem *> {
MenuItem *parent_;
};
class DisplayMenuOnValueTrigger : public Trigger<const MenuItem *> {
class DisplayMenuOnValueTrigger final : public Trigger<const MenuItem *> {
public:
explicit DisplayMenuOnValueTrigger(MenuItem *parent) : parent_(parent) {
parent->add_on_value_callback([this]() { this->trigger(this->parent_); });
@@ -123,7 +123,7 @@ class DisplayMenuOnValueTrigger : public Trigger<const MenuItem *> {
MenuItem *parent_;
};
class DisplayMenuOnNextTrigger : public Trigger<const MenuItem *> {
class DisplayMenuOnNextTrigger final : public Trigger<const MenuItem *> {
public:
explicit DisplayMenuOnNextTrigger(MenuItemCustom *parent) : parent_(parent) {
parent->add_on_next_callback([this]() { this->trigger(this->parent_); });
@@ -133,7 +133,7 @@ class DisplayMenuOnNextTrigger : public Trigger<const MenuItem *> {
MenuItemCustom *parent_;
};
class DisplayMenuOnPrevTrigger : public Trigger<const MenuItem *> {
class DisplayMenuOnPrevTrigger final : public Trigger<const MenuItem *> {
public:
explicit DisplayMenuOnPrevTrigger(MenuItemCustom *parent) : parent_(parent) {
parent->add_on_prev_callback([this]() { this->trigger(this->parent_); });
@@ -70,7 +70,7 @@ class MenuItem {
CallbackManager<void()> on_value_callbacks_{};
};
class MenuItemMenu : public MenuItem {
class MenuItemMenu final : public MenuItem {
public:
explicit MenuItemMenu() : MenuItem(MENU_ITEM_MENU) {}
void add_item(MenuItem *item) {
@@ -97,7 +97,7 @@ class MenuItemEditable : public MenuItem {
};
#ifdef USE_SELECT
class MenuItemSelect : public MenuItemEditable {
class MenuItemSelect final : public MenuItemEditable {
public:
explicit MenuItemSelect() : MenuItemEditable(MENU_ITEM_SELECT) {}
void set_select_variable(select::Select *var) { this->select_var_ = var; }
@@ -114,7 +114,7 @@ class MenuItemSelect : public MenuItemEditable {
#endif
#ifdef USE_NUMBER
class MenuItemNumber : public MenuItemEditable {
class MenuItemNumber final : public MenuItemEditable {
public:
explicit MenuItemNumber() : MenuItemEditable(MENU_ITEM_NUMBER) {}
void set_number_variable(number::Number *var) { this->number_var_ = var; }
@@ -135,7 +135,7 @@ class MenuItemNumber : public MenuItemEditable {
#endif
#ifdef USE_SWITCH
class MenuItemSwitch : public MenuItemEditable {
class MenuItemSwitch final : public MenuItemEditable {
public:
explicit MenuItemSwitch() : MenuItemEditable(MENU_ITEM_SWITCH) {}
void set_switch_variable(switch_::Switch *var) { this->switch_var_ = var; }
@@ -158,7 +158,7 @@ class MenuItemSwitch : public MenuItemEditable {
};
#endif
class MenuItemCommand : public MenuItem {
class MenuItemCommand final : public MenuItem {
public:
explicit MenuItemCommand() : MenuItem(MENU_ITEM_COMMAND) {}
@@ -166,7 +166,7 @@ class MenuItemCommand : public MenuItem {
bool select_prev() override;
};
class MenuItemCustom : public MenuItemEditable {
class MenuItemCustom final : public MenuItemEditable {
public:
explicit MenuItemCustom() : MenuItemEditable(MENU_ITEM_CUSTOM) {}
template<typename F> void add_on_next_callback(F &&cb) { this->on_next_callbacks_.add(std::forward<F>(cb)); }
+2 -6
View File
@@ -136,12 +136,8 @@ CONFIG_SCHEMA = cv.All(
cv.Schema(
{
cv.GenerateID(): cv.declare_id(DlmsMeterComponent),
cv.Optional(CONF_DECRYPTION_KEY): lambda value: cv.bind_key(
value, name="Decryption key"
),
cv.Optional(CONF_AUTH_KEY): lambda value: cv.bind_key(
value, name="Authentication key"
),
cv.Optional(CONF_DECRYPTION_KEY): cv.bind_key(name="Decryption key"),
cv.Optional(CONF_AUTH_KEY): cv.bind_key(name="Authentication key"),
cv.Optional(CONF_CUSTOM_PATTERNS): cv.ensure_list(CUSTOM_PATTERN_SCHEMA),
cv.Optional(CONF_SKIP_CRC, default=False): cv.boolean,
cv.Optional(CONF_PROVIDER): cv.string,
+1 -1
View File
@@ -98,7 +98,7 @@ struct CustomPattern {
std::optional<std::array<uint8_t, 6>> default_obis;
};
class DlmsMeterComponent : public Component, public uart::UARTDevice {
class DlmsMeterComponent final : public Component, public uart::UARTDevice {
public:
DlmsMeterComponent(uint32_t receive_timeout_ms, bool skip_crc_check,
std::optional<std::array<uint8_t, 16>> decryption_key,
+1 -1
View File
@@ -35,7 +35,7 @@ static const uint8_t DPS310_INIT_TIMEOUT = 20; // How long to wait for DPS
static const uint8_t DPS310_NUM_COEF_REGS = 18; // Number of coefficients we need to read from the device
static const int32_t DPS310_SCALE_FACTOR = 1572864; // Measurement compensation scale factor
class DPS310Component : public PollingComponent, public i2c::I2CDevice {
class DPS310Component final : public PollingComponent, public i2c::I2CDevice {
public:
void setup() override;
void dump_config() override;
+3 -3
View File
@@ -6,7 +6,7 @@
namespace esphome::ds1307 {
class DS1307Component : public time::RealTimeClock, public i2c::I2CDevice {
class DS1307Component final : public time::RealTimeClock, public i2c::I2CDevice {
public:
void setup() override;
void update() override;
@@ -55,12 +55,12 @@ class DS1307Component : public time::RealTimeClock, public i2c::I2CDevice {
} ds1307_;
};
template<typename... Ts> class WriteAction : public Action<Ts...>, public Parented<DS1307Component> {
template<typename... Ts> class WriteAction final : public Action<Ts...>, public Parented<DS1307Component> {
public:
void play(const Ts &...x) override { this->parent_->write_time(); }
};
template<typename... Ts> class ReadAction : public Action<Ts...>, public Parented<DS1307Component> {
template<typename... Ts> class ReadAction final : public Action<Ts...>, public Parented<DS1307Component> {
public:
void play(const Ts &...x) override { this->parent_->read_time(); }
};
+2 -2
View File
@@ -8,11 +8,11 @@
namespace esphome::ds2484 {
class DS2484OneWireBus : public one_wire::OneWireBus, public i2c::I2CDevice, public Component {
class DS2484OneWireBus final : public one_wire::OneWireBus, public i2c::I2CDevice, public Component {
public:
void setup() override;
void dump_config() override;
float get_setup_priority() const override { return setup_priority::BUS - 1.0; }
float get_setup_priority() const override { return setup_priority::BUS - 1.0f; }
bool reset_device();
int reset_int() override;
+1 -3
View File
@@ -40,9 +40,7 @@ CONFIG_SCHEMA = cv.All(
cv.Schema(
{
cv.GenerateID(): cv.declare_id(Dsmr),
cv.Optional(CONF_DECRYPTION_KEY): lambda value: cv.bind_key(
value, name="Decryption key"
),
cv.Optional(CONF_DECRYPTION_KEY): cv.bind_key(name="Decryption key"),
cv.Optional(CONF_CRC_CHECK, default=True): cv.boolean,
cv.Optional(CONF_GAS_MBUS_ID, default=1): cv.int_,
cv.Optional(CONF_WATER_MBUS_ID, default=2): cv.int_,
+1 -1
View File
@@ -65,7 +65,7 @@ using MyData = dsmr_parser::ParsedData<DSMR_TEXT_SENSOR_LIST(DSMR_IDENTITY, DSMR
using MyData = dsmr_parser::ParsedData<DSMR_SENSOR_LIST(DSMR_IDENTITY, DSMR_COMMA)>;
#endif
class Dsmr : public Component, public uart::UARTDevice {
class Dsmr final : public Component, public uart::UARTDevice {
public:
Dsmr(uart::UARTComponent *uart, bool crc_check, size_t max_telegram_length, uint32_t request_interval,
uint32_t receive_timeout, GPIOPin *request_pin, const char *decryption_key)
@@ -16,7 +16,7 @@ struct DutyCycleSensorStore {
static void gpio_intr(DutyCycleSensorStore *arg);
};
class DutyCycleSensor : public sensor::Sensor, public PollingComponent {
class DutyCycleSensor final : public sensor::Sensor, public PollingComponent {
public:
void set_pin(InternalGPIOPin *pin) { pin_ = pin; }
@@ -12,7 +12,7 @@
namespace esphome::duty_time_sensor {
class DutyTimeSensor : public sensor::Sensor, public PollingComponent {
class DutyTimeSensor final : public sensor::Sensor, public PollingComponent {
public:
void setup() override;
void update() override;
@@ -61,7 +61,7 @@ template<typename... Ts> class ResetAction : public BaseAction<Ts...> {
void play(const Ts &...x) override { this->parent_->reset(); }
};
template<typename... Ts> class RunningCondition : public Condition<Ts...>, public Parented<DutyTimeSensor> {
template<typename... Ts> class RunningCondition final : public Condition<Ts...>, public Parented<DutyTimeSensor> {
public:
explicit RunningCondition(DutyTimeSensor *parent, bool state) : Parented(parent), state_(state) {}
+1 -1
View File
@@ -30,7 +30,7 @@ struct UniverseConsumer {
uint16_t consumers;
};
class E131Component : public esphome::Component {
class E131Component final : public esphome::Component {
public:
E131Component();
~E131Component();
+1 -1
View File
@@ -7,7 +7,7 @@
namespace esphome::ee895 {
/// This class implements support for the ee895 of temperature i2c sensors.
class EE895Component : public PollingComponent, public i2c::I2CDevice {
class EE895Component final : public PollingComponent, public i2c::I2CDevice {
public:
void set_co2_sensor(sensor::Sensor *co2) { co2_sensor_ = co2; }
void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; }
@@ -10,7 +10,7 @@ namespace esphome::ektf2232 {
using namespace touchscreen;
class EKTF2232Touchscreen : public Touchscreen, public i2c::I2CDevice {
class EKTF2232Touchscreen final : public Touchscreen, public i2c::I2CDevice {
public:
void setup() override;
void dump_config() override;
+1 -1
View File
@@ -25,7 +25,7 @@ enum Emc2101DACConversionRate {
/// This class includes support for the EMC2101 i2c fan controller.
/// The device has an output (PWM or DAC) and several sensors and this
/// class is for the EMC2101 configuration.
class Emc2101Component : public Component, public i2c::I2CDevice {
class Emc2101Component final : public Component, public i2c::I2CDevice {
public:
/** Sets the mode of the output.
*
@@ -6,7 +6,7 @@
namespace esphome::emc2101 {
/// This class allows to control the EMC2101 output.
class EMC2101Output : public output::FloatOutput {
class EMC2101Output final : public output::FloatOutput {
public:
EMC2101Output(Emc2101Component *parent) : parent_(parent) {}
@@ -7,7 +7,7 @@
namespace esphome::emc2101 {
/// This class exposes the EMC2101 sensors.
class EMC2101Sensor : public PollingComponent {
class EMC2101Sensor final : public PollingComponent {
public:
EMC2101Sensor(Emc2101Component *parent) : parent_(parent) {}
/** Used by ESPHome framework. */
+1 -1
View File
@@ -60,7 +60,7 @@ struct EmmetiState {
uint8_t checksum = 0;
};
class EmmetiClimate : public climate_ir::ClimateIR {
class EmmetiClimate final : public climate_ir::ClimateIR {
public:
EmmetiClimate()
: climate_ir::ClimateIR(EMMETI_TEMP_MIN, EMMETI_TEMP_MAX, 1.0f, true, true,
+2 -2
View File
@@ -26,7 +26,7 @@ static constexpr size_t MAX_LINE_LENGTH = 1024;
* The EmonTx processes incoming data frames via UART,
* extracts tags and values, and publishes them to registered sensors.
*/
class EmonTx : public Component, public uart::UARTDevice {
class EmonTx final : public Component, public uart::UARTDevice {
public:
EmonTx() = default;
@@ -59,7 +59,7 @@ class EmonTx : public Component, public uart::UARTDevice {
};
// Action to send command to emonTx
template<typename... Ts> class EmonTxSendCommandAction : public Action<Ts...>, public Parented<EmonTx> {
template<typename... Ts> class EmonTxSendCommandAction final : public Action<Ts...>, public Parented<EmonTx> {
public:
TEMPLATABLE_VALUE(std::string, command)
@@ -5,7 +5,7 @@
namespace esphome::emontx {
class EmonTxSensor : public sensor::Sensor, public Component {
class EmonTxSensor final : public sensor::Sensor, public Component {
public:
void dump_config() override;
};
+1 -1
View File
@@ -7,7 +7,7 @@
namespace esphome::endstop {
class EndstopCover : public cover::Cover, public Component {
class EndstopCover final : public cover::Cover, public Component {
public:
void setup() override;
void loop() override;
+1 -1
View File
@@ -5,7 +5,7 @@
namespace esphome::ens160_i2c {
class ENS160I2CComponent : public esphome::ens160_base::ENS160Component, public i2c::I2CDevice {
class ENS160I2CComponent final : public esphome::ens160_base::ENS160Component, public i2c::I2CDevice {
void dump_config() override;
bool read_byte(uint8_t a_register, uint8_t *data) override;
+3 -3
View File
@@ -5,9 +5,9 @@
namespace esphome::ens160_spi {
class ENS160SPIComponent : public esphome::ens160_base::ENS160Component,
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW,
spi::CLOCK_PHASE_LEADING, spi::DATA_RATE_200KHZ> {
class ENS160SPIComponent final : public esphome::ens160_base::ENS160Component,
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW,
spi::CLOCK_PHASE_LEADING, spi::DATA_RATE_200KHZ> {
void setup() override;
void dump_config() override;
+1 -1
View File
@@ -7,7 +7,7 @@
namespace esphome::ens210 {
/// This class implements support for the ENS210 relative humidity and temperature i2c sensor.
class ENS210Component : public PollingComponent, public i2c::I2CDevice {
class ENS210Component final : public PollingComponent, public i2c::I2CDevice {
public:
void dump_config() override;
void setup() override;
+17
View File
@@ -64,4 +64,21 @@ constexpr NATIVE_COLOR color_to_bwyr(Color color, NATIVE_COLOR hw_black, NATIVE_
}
}
/** Map RGB color to discrete BWR (black/white/red) 3 color key
*
* Convenience wrapper over color_to_bwyr for panels without a yellow ink; the yellow corner is
* folded into white.
*
* @tparam NATIVE_COLOR Type of native hardware color values
* @param color RGB color to convert from
* @param hw_black Native value for black
* @param hw_white Native value for white
* @param hw_red Native value for red
* @return Converted native hardware color value
*/
template<typename NATIVE_COLOR>
constexpr NATIVE_COLOR color_to_bwr(Color color, NATIVE_COLOR hw_black, NATIVE_COLOR hw_white, NATIVE_COLOR hw_red) {
return color_to_bwyr<NATIVE_COLOR>(color, hw_black, hw_white, /*hw_yellow=*/hw_white, hw_red);
}
} // namespace esphome::epaper_spi
@@ -0,0 +1,148 @@
// Reference: https://github.com/SolderedElectronics/Inkplate-Arduino-library (src/boards/Inkplate2)
#include "epaper_spi_inkplate2.h"
#include "colorconv.h"
#include "esphome/core/log.h"
namespace esphome::epaper_spi {
static constexpr const char *const TAG = "epaper_spi.inkplate2";
// Map RGB to the panel's black/white/red via the shared converter.
enum class Inkplate2Color : uint8_t { BLACK, WHITE, RED };
static Inkplate2Color to_inkplate2_color(Color color) {
return color_to_bwr<Inkplate2Color>(color, Inkplate2Color::BLACK, Inkplate2Color::WHITE, Inkplate2Color::RED);
}
void EPaperInkplate2::power_on() {
// Power-on (0x04) leads the init sequence, so there is nothing to do here.
ESP_LOGV(TAG, "Power on");
}
void EPaperInkplate2::power_off() {
ESP_LOGV(TAG, "Power off");
this->cmd_data(0x50, {0xF7}); // VCOM and data interval
this->command(0x02); // power off
}
void EPaperInkplate2::refresh_screen(bool partial) {
ESP_LOGV(TAG, "Refresh screen"); // full refresh only; partial is unused
// Send 0x11 then 0x12 back-to-back: 0x11 raises busy until the refresh finishes, so waiting for idle
// between them (as the state machine does between states) would add a ~16s stall.
this->cmd_data(0x11, {0x00}); // stop data transfer
this->command(0x12); // display refresh
}
void EPaperInkplate2::deep_sleep() {
ESP_LOGV(TAG, "Deep sleep");
this->cmd_data(0x07, {0xA5});
}
void EPaperInkplate2::fill(Color color) {
if (this->get_clipping().is_set()) {
EPaperBase::fill(color); // clipping active: defer to the base per-pixel path
return;
}
const size_t half_buffer = this->buffer_length_ / 2;
// Plane encoding: B/W plane 1=white, 0=black; red plane 0=red, 1=no-red.
uint8_t bw_byte;
uint8_t red_byte;
switch (to_inkplate2_color(color)) {
case Inkplate2Color::BLACK:
bw_byte = 0x00;
red_byte = 0xFF;
break;
case Inkplate2Color::RED:
bw_byte = 0xFF;
red_byte = 0x00;
break;
case Inkplate2Color::WHITE:
default:
bw_byte = 0xFF;
red_byte = 0xFF;
break;
}
for (size_t i = 0; i < half_buffer; i++)
this->buffer_[i] = bw_byte;
for (size_t i = half_buffer; i < this->buffer_length_; i++)
this->buffer_[i] = red_byte;
this->x_low_ = 0;
this->y_low_ = 0;
this->x_high_ = this->width_;
this->y_high_ = this->height_;
}
void EPaperInkplate2::clear() { this->fill(COLOR_ON); }
void HOT EPaperInkplate2::draw_pixel_at(int x, int y, Color color) {
if (!this->rotate_coordinates_(x, y))
return;
const size_t half_buffer = this->buffer_length_ / 2;
const size_t pos = y * this->row_width_ + x / 8;
const uint8_t mask = 0x80 >> (x & 0x07); // MSB first; see fill() for plane encoding
switch (to_inkplate2_color(color)) {
case Inkplate2Color::BLACK:
this->buffer_[pos] &= ~mask;
this->buffer_[pos + half_buffer] |= mask;
break;
case Inkplate2Color::RED:
this->buffer_[pos] |= mask;
this->buffer_[pos + half_buffer] &= ~mask;
break;
case Inkplate2Color::WHITE:
default:
this->buffer_[pos] |= mask;
this->buffer_[pos + half_buffer] |= mask;
break;
}
}
bool HOT EPaperInkplate2::send_buffer_range_(size_t end, uint32_t start_time) {
uint8_t bytes_to_send[MAX_TRANSFER_SIZE];
size_t buf_idx = 0;
while (this->current_data_index_ < end) {
bytes_to_send[buf_idx++] = this->buffer_[this->current_data_index_++];
if (buf_idx == sizeof bytes_to_send) {
this->start_data_();
this->write_array(bytes_to_send, buf_idx);
this->disable();
buf_idx = 0;
if (millis() - start_time > MAX_TRANSFER_TIME)
return false; // yield; resume next loop
}
}
if (buf_idx != 0) {
this->start_data_();
this->write_array(bytes_to_send, buf_idx);
this->disable();
}
return true;
}
bool HOT EPaperInkplate2::transfer_data() {
const uint32_t start_time = millis();
const size_t half_buffer = this->buffer_length_ / 2;
// Black/white plane (first half) then red plane (second half).
if (this->current_data_index_ == 0)
this->command(0x10);
if (this->current_data_index_ < half_buffer && !this->send_buffer_range_(half_buffer, start_time))
return false;
if (this->current_data_index_ == half_buffer)
this->command(0x13);
if (!this->send_buffer_range_(this->buffer_length_, start_time))
return false;
this->current_data_index_ = 0;
return true;
}
} // namespace esphome::epaper_spi
@@ -0,0 +1,33 @@
#pragma once
#include "epaper_spi.h"
namespace esphome::epaper_spi {
// Soldered Inkplate 2: 104x212 black/white/red (BWR) e-paper, UC8xxx-family controller.
class EPaperInkplate2 final : public EPaperBase {
public:
EPaperInkplate2(const char *name, uint16_t width, uint16_t height, const uint8_t *init_sequence,
size_t init_sequence_length)
: EPaperBase(name, width, height, init_sequence, init_sequence_length, DISPLAY_TYPE_COLOR) {
// Dual-plane buffer: black/white plane followed by red plane, 1 bit per pixel each.
this->buffer_length_ = this->row_width_ * this->height_ * 2;
}
void fill(Color color) override;
void clear() override;
void draw_pixel_at(int x, int y, Color color) override;
protected:
void refresh_screen(bool partial) override;
void power_on() override;
void power_off() override;
void deep_sleep() override;
bool transfer_data() override;
// Streams buffer_[current_data_index_ .. end) in chunks; returns false if it yields on MAX_TRANSFER_TIME.
bool send_buffer_range_(size_t end, uint32_t start_time);
};
} // namespace esphome::epaper_spi
@@ -0,0 +1,13 @@
#include "epaper_waveshare_b.h"
namespace esphome::epaper_spi {
bool EpaperWaveshareB::reset() {
if (EPaperBase::reset()) {
this->command(0x12);
return true;
}
return false;
}
} // namespace esphome::epaper_spi
@@ -0,0 +1,19 @@
#pragma once
#include "epaper_weact_3c.h"
namespace esphome::epaper_spi {
/**
* Waveshare (B) series BWR e-paper displays using SSD1680-compatible controllers.
* Waveshare uses 0=red, 1=no-red, the inverse of EPaperWeAct3C
*/
class EpaperWaveshareB : public EPaperWeAct3C {
public:
using EPaperWeAct3C::EPaperWeAct3C;
protected:
bool reset() override;
uint8_t transform_red_byte(uint8_t byte) const override { return static_cast<uint8_t>(~byte); }
};
} // namespace esphome::epaper_spi
@@ -144,7 +144,7 @@ bool HOT EPaperWeAct3C::transfer_data() {
size_t bytes_to_copy = std::min(MAX_TRANSFER_SIZE, half_buffer - this->current_data_index_);
for (size_t i = 0; i < bytes_to_copy; i++) {
bytes_to_send[i] = this->buffer_[red_offset + this->current_data_index_ + i];
bytes_to_send[i] = this->transform_red_byte(this->buffer_[red_offset + this->current_data_index_ + i]);
}
this->write_array(bytes_to_send, bytes_to_copy);
@@ -34,6 +34,9 @@ class EPaperWeAct3C : public EPaperBase {
void draw_pixel_at(int x, int y, Color color) override;
bool transfer_data() override;
// Hook for subclasses to transform red plane bytes before they go on the wire.
virtual uint8_t transform_red_byte(uint8_t byte) const { return byte; }
};
} // namespace esphome::epaper_spi
@@ -0,0 +1,52 @@
# Reference: https://github.com/SolderedElectronics/Inkplate-Arduino-library
from . import EpaperModel
class Inkplate2Model(EpaperModel):
def __init__(self, name, class_name="EPaperInkplate2", **kwargs):
super().__init__(name, class_name, **kwargs)
def get_init_sequence(self, config: dict):
width, height = self.get_dimensions(config)
return (
(0x04,), # power on
(
0x00, # panel setting
0x0F, # LUT from OTP
0x89, # temperature/boost/timing
),
(
0x61, # resolution
width, # width: 1 byte
height >> 8, # height: 2 bytes, high byte first ...
height & 0xFF, # ... then low byte
),
(
0x50, # VCOM and data interval
0x77,
),
)
# Native orientation is portrait (104x212); use `rotation: 90` for the board's landscape orientation.
inkplate2 = Inkplate2Model(
"inkplate2",
width=104,
height=212,
data_rate="10MHz",
# A full 3-color refresh takes ~20s, so don't allow updates faster than that.
minimum_update_interval="30s",
# Default GPIO pins for the on-board Inkplate 2 wiring.
reset_pin=19,
dc_pin=33,
cs_pin=15,
busy_pin={
"number": 32,
"inverted": True, # hardware: LOW=busy, HIGH=idle
"mode": {
"input": True,
"pullup": True,
},
},
)
@@ -0,0 +1,26 @@
from . import EpaperModel
class WaveshareB(EpaperModel):
def __init__(self, name, **defaults):
super().__init__(name, "EpaperWaveshareB", **defaults)
def get_init_sequence(self, config):
_, height = self.get_dimensions(config)
h = height - 1
return (
(0x01, h & 0xFF, h >> 8, 0x00), # Driver output control
(0x11, 0x03), # Data entry mode
(0x3C, 0x05), # Border waveform
(0x18, 0x80), # Internal temperature sensor
(0x21, 0x80, 0x80), # Display update control
)
WaveshareB(
"waveshare-2.13in-bv4",
width=122,
height=250,
data_rate="10MHz",
minimum_update_interval="1s",
)
+4 -4
View File
@@ -169,14 +169,14 @@ bool ES7210::configure_mic_gain_() {
uint8_t ES7210::es7210_gain_reg_value_(float mic_gain) {
// reg: 12 - 34.5dB, 13 - 36dB, 14 - 37.5dB
mic_gain += 0.5;
if (mic_gain <= 33.0) {
mic_gain += 0.5f;
if (mic_gain <= 33.0f) {
return (uint8_t) (mic_gain / 3);
}
if (mic_gain < 36.0) {
if (mic_gain < 36.0f) {
return 12;
}
if (mic_gain < 37.0) {
if (mic_gain < 37.0f) {
return 13;
}
return 14;
+1 -1
View File
@@ -16,7 +16,7 @@ enum ES7210BitsPerSample : uint8_t {
ES7210_BITS_PER_SAMPLE_32 = 32,
};
class ES7210 : public audio_adc::AudioAdc, public Component, public i2c::I2CDevice {
class ES7210 final : public audio_adc::AudioAdc, public Component, public i2c::I2CDevice {
/* Class for configuring an ES7210 ADC for microphone input.
* Based on code from:
* - https://github.com/espressif/esp-bsp/ (accessed 20241219)
+4 -4
View File
@@ -105,14 +105,14 @@ bool ES7243E::configure_mic_gain_() {
uint8_t ES7243E::es7243e_gain_reg_value_(float mic_gain) {
// reg: 12 - 34.5dB, 13 - 36dB, 14 - 37.5dB
mic_gain += 0.5;
if (mic_gain <= 33.0) {
mic_gain += 0.5f;
if (mic_gain <= 33.0f) {
return (uint8_t) mic_gain / 3;
}
if (mic_gain < 36.0) {
if (mic_gain < 36.0f) {
return 12;
}
if (mic_gain < 37.0) {
if (mic_gain < 37.0f) {
return 13;
}
return 14;
+1 -1
View File
@@ -6,7 +6,7 @@
namespace esphome::es7243e {
class ES7243E : public audio_adc::AudioAdc, public Component, public i2c::I2CDevice {
class ES7243E final : public audio_adc::AudioAdc, public Component, public i2c::I2CDevice {
/* Class for configuring an ES7243E ADC for microphone input.
* Based on code from:
* - https://github.com/espressif/esp-adf/ (accessed 20250116)
+1 -1
View File
@@ -6,7 +6,7 @@
namespace esphome::es8156 {
class ES8156 : public audio_dac::AudioDac, public Component, public i2c::I2CDevice {
class ES8156 final : public audio_dac::AudioDac, public Component, public i2c::I2CDevice {
public:
/////////////////////////
// Component overrides //
+1 -1
View File
@@ -42,7 +42,7 @@ struct ES8311Coefficient {
uint8_t dac_osr; // dac osr
};
class ES8311 : public audio_dac::AudioDac, public Component, public i2c::I2CDevice {
class ES8311 final : public audio_dac::AudioDac, public Component, public i2c::I2CDevice {
public:
/////////////////////////
// Component overrides //
+7 -1
View File
@@ -173,8 +173,14 @@ bool ES8388::set_mute_state_(bool mute_state) {
ES8388_ERROR_CHECK(this->read_byte(ES8388_DACCONTROL3, &value));
ESP_LOGV(TAG, "Read ES8388_DACCONTROL3: 0x%02X", value);
// Only toggle the DACMute bit; the other bits of this register hold unrelated
// DAC settings that must be preserved. Previously muting overwrote the whole
// register with 0x3C and unmuting never cleared the bit, so once muted the DAC
// could not be unmuted again.
if (mute_state) {
value = 0x3C;
value |= ES8388_DACCONTROL3_DAC_MUTE;
} else {
value &= ~ES8388_DACCONTROL3_DAC_MUTE;
}
ESP_LOGV(TAG, "Setting ES8388_DACCONTROL3 to 0x%02X (muted: %s)", value, YESNO(mute_state));
+1 -1
View File
@@ -25,7 +25,7 @@ enum AdcInputMicLine : uint8_t {
ADC_INPUT_MIC_DIFFERENCE,
};
class ES8388 : public audio_dac::AudioDac, public Component, public i2c::I2CDevice {
class ES8388 final : public audio_dac::AudioDac, public Component, public i2c::I2CDevice {
#ifdef USE_SELECT
SUB_SELECT(dac_output)
SUB_SELECT(adc_input_mic)
+1
View File
@@ -38,6 +38,7 @@ static const uint8_t ES8388_ADCCONTROL14 = 0x16;
static const uint8_t ES8388_DACCONTROL1 = 0x17;
static const uint8_t ES8388_DACCONTROL2 = 0x18;
static const uint8_t ES8388_DACCONTROL3 = 0x19;
static const uint8_t ES8388_DACCONTROL3_DAC_MUTE = 0x04; // DACMute, bit 2 of DACCONTROL3
static const uint8_t ES8388_DACCONTROL4 = 0x1a;
static const uint8_t ES8388_DACCONTROL5 = 0x1b;
static const uint8_t ES8388_DACCONTROL6 = 0x1c;
@@ -5,7 +5,7 @@
namespace esphome::es8388 {
class ADCInputMicSelect : public select::Select, public Parented<ES8388> {
class ADCInputMicSelect final : public select::Select, public Parented<ES8388> {
protected:
void control(size_t index) override;
};
@@ -5,7 +5,7 @@
namespace esphome::es8388 {
class DacOutputSelect : public select::Select, public Parented<ES8388> {
class DacOutputSelect final : public select::Select, public Parented<ES8388> {
protected:
void control(size_t index) override;
};

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