Compare commits

..

573 Commits

Author SHA1 Message Date
J. Nick Koston
b82666002d
Bump esp-idf to 5.1.6 (#8566)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-04-18 05:21:07 +00:00
Jonathan Swoboda
e11883e431
[psram] Add version check to fix 5.3.2 (#8588) 2025-04-17 21:06:41 -05:00
dependabot[bot]
ff5b9df607
Bump ruff from 0.11.5 to 0.11.6 (#8587)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-17 20:24:31 +00:00
Jesse Hills
e5b7e3039a
Fix psram below idf 5 (#8584) 2025-04-17 00:04:43 -05:00
Jonathan Swoboda
31ed1eb6f0
[remote_receiver] Filtering fixes (#7777)
Co-authored-by: Jonathan Swoboda <jonathan.swoboda>
2025-04-16 23:33:46 -05:00
Michael Giacomelli
0c3daab649
Remove duplicate co2 and pressure constants (#8583) 2025-04-17 13:40:33 +12:00
dependabot[bot]
816371e3e9
Bump aioesphomeapi from 29.10.0 to 30.0.1 (#8579) 2025-04-16 15:24:15 -10:00
David Woodhouse
3c7bb65a23
Sort resolved IP addresses for dashboard (#8536)
Co-authored-by: J. Nick Koston <nick+github@koston.org>
2025-04-17 13:19:55 +12:00
Jonathan Swoboda
4a65fd76b3
[internal_temperature] Add p4 ifdefs (#8484) 2025-04-17 13:19:33 +12:00
Clyde Stubbs
2704db5eef
[analog_threshold] Make thresholds templatable (#8452) 2025-04-17 13:19:12 +12:00
Clyde Stubbs
f10bc73d31
[mapping] Implement yaml-configured maps (#8333) 2025-04-17 13:18:48 +12:00
Clyde Stubbs
55e099450c
[uptime] Add format config for text_sensor (#8304) 2025-04-17 13:18:08 +12:00
Andrew J.Swan
248dbd32a5
Add CUBIC PM2005/PM2105 Laser Particle Sensor Module (#8292)
Co-authored-by: Djordje <6750655+DjordjeMandic@users.noreply.github.com>
2025-04-17 13:17:35 +12:00
Jonathan Swoboda
a7b676231a
[esp32_rmt_led_strip] Add use_dma option (#8270) 2025-04-17 13:16:10 +12:00
Keith Burzinski
2fd5f9ac58
[api] Allow noise encryption key to be set at runtime (#7296)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2025-04-17 13:15:25 +12:00
Jordan Zucker
ca4838a5f4
[prometheus] Add climate metrics (#8247) 2025-04-17 13:13:24 +12:00
Jesse Hills
1b72550236
Merge branch 'release' into dev 2025-04-17 12:56:09 +12:00
Jesse Hills
71afd49e3e
Merge pull request #8581 from esphome/bump-2025.4.0
2025.4.0
2025-04-17 12:55:25 +12:00
Thomas Rupprecht
e5d718d1b1
fix typo USE_ESP32_VARIANT_ESP32H6 (#8580) 2025-04-16 21:23:58 +00:00
Jesse Hills
61f33d6401
Bump version to 2025.4.0 2025-04-17 09:03:08 +12:00
Jesse Hills
af9b568778
Merge branch 'beta' into dev 2025-04-16 12:13:17 +12:00
Jesse Hills
4a1eec567f
Merge pull request #8573 from esphome/bump-2025.4.0b3
2025.4.0b3
2025-04-16 12:12:43 +12:00
Jesse Hills
5706b8476f
Bump version to 2025.4.0b3 2025-04-16 08:48:38 +12:00
Marius Greuel
8981a86793
SML runtime optimizations (#8571) 2025-04-16 08:48:38 +12:00
Guillermo Ruffino
a7fd6dc382
Fix vscode validation not showing error squiggles (#8500)
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-04-16 08:48:38 +12:00
dependabot[bot]
cb0a87c1f9
Bump zeroconf from 0.146.4 to 0.146.5 (#8569)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-16 08:48:38 +12:00
Jonathan Swoboda
b913a0b178
[am2315c] Use warning not fail during update (#8499) 2025-04-16 08:48:38 +12:00
David Woodhouse
214454ff51
Fix '--device MQTT' for devices with static IP (#8535) 2025-04-16 08:48:38 +12:00
J. Nick Koston
3677ef71d1
Add typing to protobuf code generator (#8541) 2025-04-16 08:19:22 +12:00
Marius Greuel
7e133171e0
SML runtime optimizations (#8571) 2025-04-16 07:58:14 +12:00
Guillermo Ruffino
bc56d319b5
Fix vscode validation not showing error squiggles (#8500)
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-04-16 07:52:07 +12:00
dependabot[bot]
c423a6fb61
Bump codecov/codecov-action from 5.4.0 to 5.4.2 (#8572)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-15 19:48:51 +00:00
dependabot[bot]
4034bf4f04
Bump zeroconf from 0.146.4 to 0.146.5 (#8569)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-15 07:58:57 +00:00
Jonathan Swoboda
477abc05ae
[am2315c] Use warning not fail during update (#8499) 2025-04-15 17:00:44 +12:00
David Woodhouse
ff2b93a3e4
Fix '--device MQTT' for devices with static IP (#8535) 2025-04-15 16:30:07 +12:00
Calum McConnell
a52d6388a9
Use python3 in place of python, as some systems don't emulate the former (#8568) 2025-04-15 04:13:37 +00:00
Clyde Stubbs
6259ca9ded
[lvgl] Small buffers in internal RAM (#8523) 2025-04-15 13:10:44 +12:00
Jesse Hills
f6ef50505b
Merge branch 'beta' into dev 2025-04-15 12:13:03 +12:00
Jesse Hills
b4cf437761
Merge pull request #8567 from esphome/bump-2025.4.0b2
2025.4.0b2
2025-04-15 12:12:31 +12:00
Jesse Hills
1d9f5f1f1e
Bump version to 2025.4.0b2 2025-04-15 09:35:53 +12:00
Jonathan Swoboda
e47489708e
Bump esphome-dashboard to 20250415.0 (#8565) 2025-04-15 09:35:53 +12:00
dependabot[bot]
8e1bdcd211
Bump zeroconf from 0.146.3 to 0.146.4 (#8563)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2025-04-15 09:35:53 +12:00
dependabot[bot]
3432d73584
Bump aioesphomeapi from 29.9.0 to 29.10.0 (#8562)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-15 09:35:53 +12:00
Clyde Stubbs
2bb86641f8
[lvgl] Ensure captured lambdas are in correct order (#8560) 2025-04-15 09:35:53 +12:00
Mischa Siekmann
6ca72a3a26
Speaker-Media-Player: Fix potential deadlock in audio pipeline (#8548) 2025-04-15 09:35:53 +12:00
Clyde Stubbs
c215098cb7
[lvgl] Add restore_value to select and number (#8494) 2025-04-15 09:35:53 +12:00
Clyde Stubbs
566968b6be
[lvgl] Fix initial focus on roller (#8547) 2025-04-15 09:35:53 +12:00
Clyde Stubbs
fe51ee6257
[axs15231] Don't overwrite manual dimensions (#8553) 2025-04-15 09:35:53 +12:00
J. Nick Koston
2c499b326a
Include MAC address in noise hello (#8551) 2025-04-15 09:35:53 +12:00
Clyde Stubbs
7c4ab7abfe
[lvgl] Fix use of image without canvas (Bugfix) (#8540) 2025-04-15 09:35:52 +12:00
Jonathan Swoboda
3c242b7296
Bump esphome-dashboard to 20250415.0 (#8565) 2025-04-14 21:03:43 +00:00
Jesse Hills
00dd5b8339
[ci] Pin codecov action to v5.4.0 (#8564) 2025-04-15 08:09:51 +12:00
dependabot[bot]
a007a8237a
Bump zeroconf from 0.146.3 to 0.146.4 (#8563)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2025-04-15 08:07:29 +12:00
dependabot[bot]
9b86cc37f0
Bump aioesphomeapi from 29.9.0 to 29.10.0 (#8562)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-15 08:06:48 +12:00
Clyde Stubbs
2dfcf950fa
[lvgl] Ensure captured lambdas are in correct order (#8560) 2025-04-15 07:39:56 +12:00
Mischa Siekmann
5908b93e82
Speaker-Media-Player: Fix potential deadlock in audio pipeline (#8548) 2025-04-14 13:51:10 -05:00
Norbert Schulz
995db1f961
Add support for Waveshare 5.65" ACeP 7-Color display (#8557) 2025-04-14 12:02:40 +10:00
dependabot[bot]
abcc656a6f
Bump ruff from 0.11.4 to 0.11.5 (#8546)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-13 14:41:33 -10:00
tomaszduda23
4a9f323d92
[core] make require_framework_version generic (#8412) 2025-04-14 10:59:40 +12:00
Calum McConnell
34a4e70cc5
Update setup to make .temp directory (#8558) 2025-04-14 10:48:45 +12:00
Clyde Stubbs
fb5d697c22
[lvgl] Add restore_value to select and number (#8494) 2025-04-14 10:45:30 +12:00
Clyde Stubbs
df4642208e
[lvgl] Fix initial focus on roller (#8547) 2025-04-14 10:41:42 +12:00
Clyde Stubbs
264e234efc
[axs15231] Don't overwrite manual dimensions (#8553) 2025-04-14 10:41:11 +12:00
J. Nick Koston
ca78dd44b5
Include MAC address in noise hello (#8551) 2025-04-12 09:16:14 -10:00
Jonathan Swoboda
7edf458898
[esp32] Allow pioarduino version 5.3.3 and 5.5.0 (#8526) 2025-04-11 21:34:43 -05:00
Clyde Stubbs
d9873e24a7
[lvgl] Fix use of image without canvas (Bugfix) (#8540) 2025-04-10 01:28:44 +00:00
dependabot[bot]
645bd490ba
Bump pytest-cov from 6.0.0 to 6.1.1 (#8537)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-09 10:28:22 -10:00
dependabot[bot]
27f6d00e7a
Bump ruff from 0.11.2 to 0.11.4 (#8538)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-09 10:28:07 -10:00
Jesse Hills
f9d668eeca
Merge branch 'beta' into dev 2025-04-09 19:50:59 +12:00
Jesse Hills
92d1557efd
Merge pull request #8534 from esphome/bump-2025.4.0b1
2025.4.0b1
2025-04-09 19:50:23 +12:00
Jesse Hills
6b930595e2
Bump version to 2025.5.0-dev 2025-04-09 14:19:05 +12:00
Jesse Hills
4a1cbfc533
Bump version to 2025.4.0b1 2025-04-09 14:19:05 +12:00
Clyde Stubbs
1f7a84cc8e
[lvgl] Implement canvas widget (#8504) 2025-04-09 12:15:39 +12:00
David Woodhouse
8c5adfb33f
real_time_clock: Apply timezone immediately in set_timezone() (#8531) 2025-04-09 12:03:38 +12:00
dependabot[bot]
399c9ba4be
Bump pytest from 8.2.0 to 8.3.5 (#8528) 2025-04-08 23:38:06 +00:00
Clyde Stubbs
a866370a2e
[spi] Implement octal mode (#8386) 2025-04-09 11:07:59 +12:00
Clyde Stubbs
6240bfff97
[lvgl] Make line points templatable (#8502) 2025-04-09 11:03:29 +12:00
Clyde Stubbs
1c72fd4674
[lvgl] add on_boot trigger (#8498) 2025-04-09 11:00:39 +12:00
J. Nick Koston
2291a1dc39
Bump aioesphomeapi to 29.9.0 (#8522) 2025-04-09 10:58:26 +12:00
J. Nick Koston
8269e2c961
Ensure plaintext responds with bad indicator byte before dropping the connection (#8521) 2025-04-09 10:27:23 +12:00
Clyde Stubbs
23dec912ad
[psram] Allow use of experimental 120MHz octal mode (#8519) 2025-04-07 12:49:40 +00:00
Clyde Stubbs
9637ef35bd
[component] Show error message for failed component (#8478) 2025-04-07 09:26:34 +00:00
J. Nick Koston
23e5cdb30e
Rework max connections for BLE to avoid exceeding the hard limit (#8303) 2025-04-07 00:48:12 +00:00
dependabot[bot]
f3b1b11eba
Bump flake8 from 7.0.0 to 7.2.0 (#8493)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-04-06 00:58:39 +00:00
dependabot[bot]
5ceba618f6
Bump setuptools from 76.0.0 to 78.1.0 (#8512)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-05 21:28:37 +00:00
victorclaessen
99d5ca3266
[ethernet_info] return actual ethernet MAC address (#8492)
Co-authored-by: clydebarrow <2366188+clydebarrow@users.noreply.github.com>
2025-04-04 18:59:46 +11:00
Jonathan Swoboda
219ba6152c
[CI] Clang tidy fixes for 5.3.2 (#8510)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-04-03 07:32:17 +00:00
Jonathan Swoboda
ef0f969604
[core, qspi_dbi] Clang tidy fixes for 5.3.2 (#8509) 2025-04-03 02:03:04 -05:00
Curtis Malainey
82adcd656f
[nau7802] fix bad blocking code (#8070) 2025-04-02 23:04:43 +00:00
Jesse Hills
fe35eee8df
Update emails from nabucasa to OHF (#8508) 2025-04-03 11:08:46 +13:00
Shivam Maurya
864dd69038
Bump platformio to 6.1.18 (#8430)
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-04-02 21:38:13 +00:00
dependabot[bot]
79f198ebff
Bump zeroconf from 0.146.1 to 0.146.3 (#8507)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 20:47:46 +00:00
dependabot[bot]
4b0622aa23
Bump voluptuous from 0.14.2 to 0.15.2 (#8506)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 10:14:12 -10:00
dependabot[bot]
4ecc72ed54
Bump pyupgrade from 3.15.2 to 3.19.1 (#8496)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 23:50:30 +13:00
dependabot[bot]
791740e554
Bump yamllint from 1.35.1 to 1.37.0 (#8495)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 23:18:01 +13:00
dependabot[bot]
6bccc7e389
Bump ruamel-yaml from 0.18.6 to 0.18.10 (#8446)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-04-02 23:17:34 +13:00
dependabot[bot]
655075e71b
Bump actions/upload-artifact from 4.6.1 to 4.6.2 (#8435)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 23:17:08 +13:00
dependabot[bot]
1df1e3cf48
Bump actions/download-artifact from 4.1.9 to 4.2.1 (#8434)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 23:16:42 +13:00
dependabot[bot]
05e52cae2b
Bump docker/login-action from 3.3.0 to 3.4.0 in the docker-actions group (#8408)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 23:16:31 +13:00
dependabot[bot]
be60d9be9b
Bump peter-evans/create-pull-request from 7.0.7 to 7.0.8 (#8362)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 23:16:17 +13:00
Oliver Kleinecke
e3eb3ee5d2
Add support for MCP4461 quad i2c digipot/rheostat (#8180)
Co-authored-by: Oliver Kleinecke <kleinecke.oliver@googlemail.com>
Co-authored-by: Djordje Mandic <6750655+DjordjeMandic@users.noreply.github.com>
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-04-01 23:55:06 +00:00
Clyde Stubbs
0812b3dd70
[lvgl] Add some defines (#8501) 2025-04-01 22:42:23 +00:00
NP v/d Spek
28a9f12595
Move CONF_DEFAULT to const.py (#8497) 2025-03-31 22:48:43 +00:00
Keith Burzinski
36b75c3faa
Merge branch 'release' into dev 2025-03-31 17:07:16 -05:00
Keith Burzinski
584c5bd5be
Merge pull request #8489 from esphome/bump-2025.3.3
2025.3.3
2025-03-31 17:07:02 -05:00
dependabot[bot]
bc372dbeb2
Bump platformio from 6.1.16 to 6.1.18 (#8449)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-31 21:28:47 +00:00
dependabot[bot]
37a03de849
Bump async-timeout from 4.0.3 to 5.0.1 (#8491)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-31 20:57:23 +00:00
dependabot[bot]
c8395cdf0a
Bump pytest-asyncio from 0.25.3 to 0.26.0 (#8490)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-31 20:26:22 +00:00
Keith Burzinski
79c8a55459
Bump version to 2025.3.3 2025-03-31 12:48:16 -05:00
Kevin Ahrendt
36d6fe29f2
[speaker] Bugfixes: two pause state issues (#8488) 2025-03-31 12:48:16 -05:00
Clyde Stubbs
e1868ddecb
[lvgl] Implement switch restore (#8481) 2025-03-31 12:48:16 -05:00
Kevin Ahrendt
6151644b96
[speaker] Bugfix: Media player always unpauses when receiving a stop command (#8474) 2025-03-31 12:48:15 -05:00
J. Nick Koston
a4914eb5b7
Bump ESP mdns to 1.8.2 (#8482) 2025-03-31 12:48:15 -05:00
Clyde Stubbs
57a57f0d6a
[display] Don't assume glyph x_offset is zero. (#8473) 2025-03-31 12:48:15 -05:00
Kevin Ahrendt
7e9f93a290
[speaker] Bugfixes: two pause state issues (#8488) 2025-03-31 17:02:53 +00:00
dependabot[bot]
402ada07b5
Bump pytest-cov from 5.0.0 to 6.0.0 (#8462)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-31 14:33:00 +02:00
dependabot[bot]
9aa9abfc08
Bump actions/setup-python from 5.4.0 to 5.5.0 in /.github/actions/restore-python (#8467)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-31 14:28:21 +02:00
dependabot[bot]
4c1f83614b
Bump actions/setup-python from 5.4.0 to 5.5.0 (#8468)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-31 14:28:11 +02:00
Clyde Stubbs
d1763f9831
[psram] 120MHz does not work in octal mode (#8477) 2025-03-31 09:03:59 +00:00
dependabot[bot]
c49391427f
Bump ruff from 0.11.0 to 0.11.2 (#8461)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-31 01:52:10 +00:00
Clyde Stubbs
c42343be3a
[lvgl] Implement switch restore (#8481) 2025-03-30 09:09:19 +00:00
Kevin Ahrendt
ffc233d99d
[speaker] Bugfix: Media player always unpauses when receiving a stop command (#8474) 2025-03-30 08:41:08 +00:00
Jonathan Swoboda
5ed0046bdd
[esp32] Allow pioarduino version 5.4.1 (#8480)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-03-29 07:28:10 +00:00
J. Nick Koston
2e16dd788c
Bump ESP mdns to 1.8.2 (#8482) 2025-03-28 23:29:53 -05:00
Clyde Stubbs
58fe8b39b2
[scheduler] Properly handle millis() overflow (#8197) 2025-03-27 02:09:22 -05:00
Clyde Stubbs
ccd55a8e84
[display] Don't assume glyph x_offset is zero. (#8473) 2025-03-27 00:31:55 +00:00
Patrick
4bb59ce1d1
[esp32_can] Configurable enqueue timeout (#8453) 2025-03-26 04:06:23 +00:00
Keith Burzinski
bb988604c8
Merge branch 'release' into dev 2025-03-25 18:06:56 -05:00
Keith Burzinski
573088aadb
Merge pull request #8469 from esphome/bump-2025.3.2
2025.3.2
2025-03-25 18:06:42 -05:00
Keith Burzinski
031b1c8bd0
Bump version to 2025.3.2 2025-03-25 15:22:11 -05:00
Keith Burzinski
f95b2ba898
[ld2450] Fix bluetooth state not reported correctly (#8458) 2025-03-25 15:22:11 -05:00
Kevin Ahrendt
ea4b573f9a
[speaker] Bugfix: Fix rapidly adding items to playlist (#8466)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-03-25 15:22:11 -05:00
Kevin Ahrendt
8fcbd57f2f
[media_player] Don't reset enqueue command (#8465) 2025-03-25 15:22:11 -05:00
Samuel Sieb
f131186e6b
fix 1bpp rendering (#8463) 2025-03-25 15:22:11 -05:00
Clyde Stubbs
20c7778524
[font] More robust handling of fixed font sizes. (#8443)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-03-25 15:22:11 -05:00
Clyde Stubbs
2d8e86324b
[gt911][cst226][ektf2232] Swap x and y calibration values (#8450)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-03-25 15:22:10 -05:00
Keith Burzinski
2dfd28ba3e
[ld2450] Fix bluetooth state not reported correctly (#8458) 2025-03-25 15:21:10 -05:00
Kevin Ahrendt
63221d7a1f
[speaker] Bugfix: Fix rapidly adding items to playlist (#8466)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-03-25 20:20:56 +00:00
Kevin Ahrendt
fb9a15f0af
[media_player] Don't reset enqueue command (#8465) 2025-03-25 11:16:12 -05:00
Samuel Sieb
ce2e966005
fix 1bpp rendering (#8463) 2025-03-25 19:33:53 +11:00
Jonathan Swoboda
e7d1072c85
[core] Fix s2 build after crc header fix (#8459) 2025-03-24 18:04:25 -05:00
Clyde Stubbs
bc999b50b3
[font] More robust handling of fixed font sizes. (#8443)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-03-24 09:35:42 +00:00
Clyde Stubbs
6cfe3ac44d
[gt911][cst226][ektf2232] Swap x and y calibration values (#8450)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-03-24 09:07:21 +00:00
Jonathan Swoboda
6787730aa4
[core] Fix 5.4.0 build issue (#8455)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-03-24 02:46:31 +00:00
Keith Burzinski
48a7927a60
Merge branch 'release' into dev 2025-03-22 23:45:32 -05:00
Keith Burzinski
8ea4d8402f
Merge pull request #8451 from esphome/bump-2025.3.1
2025.3.1
2025-03-22 23:45:18 -05:00
Keith Burzinski
2c53408cfc
Bump version to 2025.3.1 2025-03-22 23:14:32 -05:00
Clyde Stubbs
33dce6e522
[lvgl] Ensure non-zero screen dimensions during init (#8444) 2025-03-22 23:14:32 -05:00
Clyde Stubbs
e213932b7c
[lvgl] Set correct buffer size (#8442) 2025-03-22 23:14:32 -05:00
Clyde Stubbs
42fb0e2809
[ft63x6] Get correct dimensions from display (#8417) 2025-03-22 23:14:31 -05:00
Clyde Stubbs
acce0bc45b
[lvgl] Ensure non-zero screen dimensions during init (#8444) 2025-03-22 23:09:29 -05:00
dependabot[bot]
f5885de6f1
Bump pytest-asyncio from 0.23.6 to 0.25.3 (#8447)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-21 22:19:09 +00:00
dependabot[bot]
17e3bb7324
Bump aioesphomeapi from 29.6.0 to 29.7.0 (#8448)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-21 11:44:47 -10:00
Clyde Stubbs
d891521ce2
[lvgl] Set correct buffer size (#8442) 2025-03-21 04:12:27 +00:00
Clyde Stubbs
3320e4112b
[cli] Add --reset and --upload_speed options (#8380) 2025-03-20 21:38:59 -05:00
Jonathan Swoboda
c0e4701e1d
[esp32] Allow pioarduino versions 5.3.2 and 5.4.0 (#8440)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-03-20 21:31:58 -05:00
dependabot[bot]
f3390ff7f5
Bump tzlocal from 5.2 to 5.3.1 (#8423)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-20 14:41:23 -10:00
dependabot[bot]
dfbfb2a2bb
Update wheel requirement from ~=0.43.0 to >=0.43,<0.46 (#8421)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-20 13:08:25 -10:00
dependabot[bot]
874026ca8f
Bump pylint from 3.2.7 to 3.3.6 (#8441)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2025-03-20 22:07:38 +00:00
dependabot[bot]
4adda632bb
Bump ruff from 0.9.2 to 0.11.0 (#8409) 2025-03-20 09:51:23 -10:00
Clyde Stubbs
6ea89644e7
[ft63x6] Get correct dimensions from display (#8417) 2025-03-19 23:37:44 -05:00
Keith Burzinski
64ff62c005
Merge branch 'release' into dev 2025-03-19 23:37:27 -05:00
Keith Burzinski
c4de9e87e4
Merge pull request #8438 from esphome/bump-2025.3.0
2025.3.0
2025-03-19 23:37:13 -05:00
Keith Burzinski
918924d697
Bump version to 2025.3.0 2025-03-19 20:54:32 -05:00
dependabot[bot]
43805e6c56
Bump actions/cache from 4.2.2 to 4.2.3 (#8433)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-19 12:46:38 -10:00
dependabot[bot]
38bbfaccc6
Bump actions/cache from 4.2.2 to 4.2.3 in /.github/actions/restore-python (#8437)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-19 12:46:01 -10:00
Keith Burzinski
56b32aae11
Merge branch 'beta' into dev 2025-03-19 16:01:54 -05:00
Keith Burzinski
e2c16b4baa
Merge pull request #8436 from esphome/bump-2025.3.0b5
2025.3.0b5
2025-03-19 16:01:39 -05:00
Keith Burzinski
10a9162f48
Bump version to 2025.3.0b5 2025-03-19 14:36:04 -05:00
Kevin Ahrendt
fbc884772c
[audio] Bugfix: fix flac decoding glitches by using esp-audio-libs v1.1.3 (#8431) 2025-03-19 14:36:03 -05:00
Kevin Ahrendt
cbf68f1fd2
[audio] Bugfix: fix flac decoding glitches by using esp-audio-libs v1.1.3 (#8431) 2025-03-19 10:14:42 -05:00
Keith Burzinski
cf227d6f32
Merge branch 'beta' into dev 2025-03-18 15:21:26 -05:00
Keith Burzinski
54e3153f27
Merge pull request #8428 from esphome/bump-2025.3.0b4
2025.3.0b4
2025-03-18 15:21:15 -05:00
Keith Burzinski
c2e0a01106
Bump version to 2025.3.0b4 2025-03-18 14:43:26 -05:00
Clyde Stubbs
d2c2439b97
[core] Handle mis-typed platform name more cleanly (#8424) 2025-03-18 14:43:25 -05:00
Keith Burzinski
a8d33dd26a
[docker] Bump libfreetype (#8426) 2025-03-18 14:43:25 -05:00
Keith Burzinski
da41a9204e
[docker] Bump curl, git, openssh-client, libopenjp2-7, nginx-light (#8419) 2025-03-18 14:43:25 -05:00
Clyde Stubbs
f993bb08c7
[core] Handle mis-typed platform name more cleanly (#8424) 2025-03-18 14:42:14 -05:00
Keith Burzinski
afa481aeea
[docker] Bump libfreetype (#8426) 2025-03-18 17:28:15 +13:00
Keith Burzinski
dfb162e7a6
[docker] Bump curl, git, openssh-client, libopenjp2-7, nginx-light (#8419) 2025-03-17 01:55:29 -05:00
Keith Burzinski
098921b88f
Merge branch 'beta' into dev 2025-03-16 01:54:05 -05:00
Keith Burzinski
5c6368b6b8
Merge pull request #8415 from esphome/bump-2025.3.0b3
2025.3.0b3
2025-03-16 01:53:55 -05:00
Keith Burzinski
9bd7060f6b
Bump version to 2025.3.0b3 2025-03-16 01:23:06 -05:00
Mikkel Jeppesen
fb1d178abc
Added getters for graphs ymin and ymax (#8112)
Co-authored-by: guillempages <guillempages@users.noreply.github.com>
2025-03-16 01:23:06 -05:00
Clyde Stubbs
90c96a0a0f
[font] Fix issues with bitmap fonts (#8407) 2025-03-16 01:23:05 -05:00
dependabot[bot]
c63a545750
Bump esphome-glyphsets from 0.1.0 to 0.2.0 (#8403)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-14 21:36:12 -10:00
dependabot[bot]
89f82be4cd
Bump puremagic from 1.27 to 1.28 (#8406)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-14 21:35:51 -10:00
dependabot[bot]
c336dd9436
Bump setuptools from 69.2.0 to 76.0.0 (#8405)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-14 21:35:15 -10:00
Mikkel Jeppesen
fa25cebed5
Added getters for graphs ymin and ymax (#8112)
Co-authored-by: guillempages <guillempages@users.noreply.github.com>
2025-03-15 18:55:20 +13:00
Clyde Stubbs
7679c716b3
[font] Fix issues with bitmap fonts (#8407) 2025-03-14 20:17:16 +11:00
Keith Burzinski
225e2585e8
Merge branch 'beta' into dev 2025-03-13 01:31:27 -05:00
Keith Burzinski
1bdf0fdc57
Merge pull request #8400 from esphome/bump-2025.3.0b2
2025.3.0b2
2025-03-13 01:31:17 -05:00
Keith Burzinski
4d95ff2ae0
Bump version to 2025.3.0b2 2025-03-12 23:23:27 -05:00
dependabot[bot]
f36d400058
Bump tornado from 6.4 to 6.4.2 (#8398)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-12 23:23:26 -05:00
J. Nick Koston
c63cf9d151
Bump cryptography to 44.0.2 (#8399) 2025-03-12 23:23:26 -05:00
J. Nick Koston
0a02c1461e
Rework pyproject.toml to make it parseable by dependabot (#8397) 2025-03-12 23:23:26 -05:00
J. Nick Koston
b3a69c6c05
Bump aioesphomeapi to 29.6.0 (#8396) 2025-03-12 23:23:26 -05:00
Kevin Ahrendt
dd113f2972
[api] add voice assistant announce to the api (#8395) 2025-03-12 23:23:26 -05:00
Kevin Ahrendt
3c5a0091ee
[core] add reallocation support to RAMAllocator (#8390) 2025-03-12 23:23:26 -05:00
Kevin Ahrendt
bf65b73569
[speaker, resampler, mixer] Make volume and mute getters virtual (#8391) 2025-03-12 23:23:26 -05:00
Kevin Ahrendt
a2b123a29a
[audio, mixer] Memory and CPU performance improvements (#8387) 2025-03-12 23:23:25 -05:00
J. Nick Koston
3575f52cdf
Bump mdns library to 1.8.0 (#8378)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-03-12 23:23:25 -05:00
dependabot[bot]
c90185854e
Bump tornado from 6.4 to 6.4.2 (#8398)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-12 23:22:08 -05:00
J. Nick Koston
7d8c39d295
Bump cryptography to 44.0.2 (#8399) 2025-03-12 23:21:45 -05:00
J. Nick Koston
59d282489a
Rework pyproject.toml to make it parseable by dependabot (#8397) 2025-03-13 01:16:59 +00:00
J. Nick Koston
f9a0a63290
Bump aioesphomeapi to 29.6.0 (#8396) 2025-03-13 01:00:31 +00:00
Kevin Ahrendt
00000e0ea8
[api] add voice assistant announce to the api (#8395) 2025-03-12 14:35:10 -10:00
Kevin Ahrendt
bd853e6883
[core] add reallocation support to RAMAllocator (#8390) 2025-03-13 07:04:05 +11:00
Kevin Ahrendt
64d1d93fe0
[speaker, resampler, mixer] Make volume and mute getters virtual (#8391) 2025-03-12 14:34:38 -05:00
Kevin Ahrendt
266c2ef337
[audio, mixer] Memory and CPU performance improvements (#8387) 2025-03-12 14:18:31 -05:00
J. Nick Koston
35199c9b96
Bump mdns library to 1.8.0 (#8378)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-03-12 14:18:21 -05:00
Keith Burzinski
0a29138045
Merge branch 'beta' into dev 2025-03-12 03:40:43 -05:00
Keith Burzinski
52269305ec
Merge pull request #8389 from esphome/bump-2025.3.0b1
2025.3.0b1
2025-03-12 03:40:31 -05:00
Keith Burzinski
04dc0ed129
Bump version to 2025.4.0-dev 2025-03-12 01:11:50 -05:00
Keith Burzinski
37fabd7c0a
Bump version to 2025.3.0b1 2025-03-12 01:11:50 -05:00
djasper-ha
4aa7ad1e33
mcp2515: Add missing CFG1 assignment to be able to use 50kbps with a 16MHz crystal. (#8375) 2025-03-11 22:31:01 +11:00
J. Nick Koston
42e432754e
Bump zeroconf to 0.146.1 (#8365)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-03-11 08:08:02 +00:00
Shivam Maurya
2379f02008
Bump esptool to 4.8.1latest (#8367)
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
2025-03-11 02:34:47 -05:00
J. Nick Koston
d3145dd95b
Bump aioesphomeapi to 29.5.1 (#8364) 2025-03-11 02:31:09 -05:00
Clyde Stubbs
ab77dd691b
Revert "[io_bus] Initial implementation" (#8384) 2025-03-11 20:02:01 +13:00
Clyde Stubbs
b54c0fd60a
[cst816] Remove binary sensor (#8377) 2025-03-09 23:54:40 -05:00
Clyde Stubbs
75d1eeeffe
[touchscreen] Axis swap bugfix (#8376) 2025-03-09 22:04:34 -05:00
Dennis Marinus
10cea51739
allow touchscreen buttons outside of display dimensions (#8296)
Co-authored-by: Dennis Marinus <dmarinus@apple.com>
Co-authored-by: clydebarrow <2366188+clydebarrow@users.noreply.github.com>
2025-03-08 10:41:54 +11:00
Quentin Raynaud
83e090cc7e
[time] fix recalc_timestamp_local (#8239) 2025-03-07 00:34:04 -08:00
Clyde Stubbs
583f8f598a
[lvgl] Fix initialisation race condition (Bugfix) (#8369) 2025-03-07 01:58:21 -06:00
Chris Djali
3e9556c6c2
Initialise h-bridge switch to requested initial state (#8363) 2025-03-06 16:43:04 -08:00
Kevin Ahrendt
83cba0d7bd
[i2s_audio] Bugfix: Speaker incorrectly delays when sending data (#8361) 2025-03-05 21:32:45 -06:00
tomaszduda23
1d6d0d66dc
[udp] fix clang tidy (#8351) 2025-03-03 15:08:42 -06:00
Gustavo de León
4ed78023b6
[bmp085] Fix error in read of pressure (#8359) 2025-03-03 15:06:30 -06:00
Damien Sorel
323209523b
[ld2450] fix null exception & zone target_count not published (#8348)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-03-03 10:44:15 -06:00
Jesse Hills
46a4f4eba9 Merge branch 'release' into dev 2025-03-03 21:24:04 +13:00
Jesse Hills
53fda0e96d
Merge pull request #8358 from esphome/bump-2025.2.2
2025.2.2
2025-03-03 21:23:20 +13:00
Jesse Hills
0350eafc1e
[helpers] Allow RAMAllocator to be told the size of the object manually (#8356) 2025-03-03 01:11:19 -06:00
Jesse Hills
7b8e68c73a Bump version to 2025.2.2 2025-03-03 17:15:40 +13:00
Jesse Hills
db666e44a7 [ltr390] Move calculation to allow dynamic setting of gain and resolution (#8343) 2025-03-03 17:15:40 +13:00
J. Nick Koston
903d033e0f Bump aioesphomeapi to 29.3.2 (#8353) 2025-03-03 17:15:40 +13:00
Kevin Ahrendt
19d938ce48 [audio] Determine http timeout based on duration since last successful read (#8341) 2025-03-03 17:15:40 +13:00
J. Nick Koston
653318479a Fix end_of_scan_ not being called while disconnecting (#8328) 2025-03-03 17:15:40 +13:00
Jesse Hills
2af5fd5210
[ltr390] Move calculation to allow dynamic setting of gain and resolution (#8343) 2025-03-03 15:35:52 +13:00
J. Nick Koston
29e388b231
Bump aioesphomeapi to 29.3.2 (#8353) 2025-03-03 15:35:32 +13:00
Jesse Hills
d9e23fdb5c
[dashboard] Rename trash/delete to archive (#8357) 2025-03-03 15:24:05 +13:00
dependabot[bot]
10eacaccba
Bump docker/setup-qemu-action from 3.5.0 to 3.6.0 in the docker-actions group (#8346)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 22:23:26 +01:00
Samuel Sieb
23687b2afd
[tmp1075] fix component for TMP1075N (#8317) 2025-03-02 07:10:18 -08:00
Clyde Stubbs
f11ad9ad5b
[io_bus] Initial implementation (#8227) 2025-02-28 16:04:36 +13:00
Timo Beckers
74a25a7e76
Cover component for Tormatic and Novoferm garage doors (#5933) 2025-02-28 15:57:30 +13:00
Kevin Ahrendt
23e04e18f8
[audio] Determine http timeout based on duration since last successful read (#8341) 2025-02-28 11:43:51 +13:00
tomaszduda23
aed5020a83
[nrf52, core] unified way how all platforms handle SplitDefault (#7715)
Co-authored-by: Tomasz Duda <tomaszduda23@gmai.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2025-02-28 09:24:28 +13:00
Jesse Hills
476f1b701b
[zeroconf] Ruff formatting (#8338) 2025-02-28 09:12:21 +13:00
dependabot[bot]
7c3a7b68d3
Bump actions/cache from 4.2.1 to 4.2.2 in /.github/actions/restore-python (#8337)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-28 09:12:04 +13:00
dependabot[bot]
75dc0d3fb7
Bump actions/cache from 4.2.1 to 4.2.2 (#8336)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-28 09:11:40 +13:00
Clyde Stubbs
9bc4f68d87
[font] Use freetype instead of Pillow for font rendering (#8300) 2025-02-28 08:50:51 +13:00
functionpointer
1029202848
[mlx90393] Fix inverted gain and resolution. Expose temperature_compensation and hallconf. (#7635)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2025-02-28 07:28:12 +13:00
dependabot[bot]
a831905bba
Bump docker/build-push-action from 6.14.0 to 6.15.0 in /.github/actions/build-image (#8332)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-28 07:00:23 +13:00
dependabot[bot]
faffd79545
Bump actions/download-artifact from 4.1.8 to 4.1.9 (#8331)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-28 07:00:10 +13:00
dependabot[bot]
7714147071
Bump the docker-actions group with 2 updates (#8330)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-28 06:59:58 +13:00
Keith Burzinski
4da42dedc8
[ld2450] Fix misplaced `ifdef` and related logic (#8335) 2025-02-28 06:58:19 +13:00
J. Nick Koston
28f283d545
Fix end_of_scan_ not being called while disconnecting (#8328) 2025-02-28 06:56:55 +13:00
J. Nick Koston
3048f303c5
dashboard: Implement automatic ping fallback (#8263) 2025-02-27 15:17:07 +00:00
J. Nick Koston
63a7234767
Include the bluetooth mac address in the device info when proxy is enabled (#8203) 2025-02-27 13:37:11 +00:00
Anton Viktorov
c19621e238
MSA311 and MSA301 accelerometer support (#6795)
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
2025-02-27 14:48:47 +11:00
barchasse38
bc96eb9d52
Update arduino-heatpumpir and add new protocol for Panasonic AC (#8309) 2025-02-26 04:29:33 -06:00
Keith Burzinski
7375dde39c
[ld2450] Fix for "unknown" sensor states (#8305) 2025-02-25 20:49:12 -06:00
Pawel
1b7111affb
Add option to include vars in remote packages (#7606)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2025-02-26 14:02:51 +13:00
tomaszduda23
a511926aed
[core] SplitDefault unit test (#8324) 2025-02-26 11:29:55 +13:00
Jesse Hills
6b36cb95c9
Merge branch 'release' into dev 2025-02-26 11:01:56 +13:00
Jesse Hills
c13174c318
Merge pull request #8326 from esphome/bump-2025.2.1
2025.2.1
2025-02-26 11:01:14 +13:00
Jonathan Swoboda
d5da341138
[i2c] Fix i2c issue on idf 5.3 (#8283) 2025-02-26 10:49:09 +13:00
Jesse Hills
8fa157581e
Bump version to 2025.2.1 2025-02-26 09:49:22 +13:00
Keith Burzinski
7114d6bdd1
[esp32_touch] Fix variants, add tests for variants (#8320) 2025-02-26 09:49:22 +13:00
J. Nick Koston
eca0c21966
Fix bluetooth race when disconnect called while still connecting (#8297) 2025-02-26 09:49:22 +13:00
esphomebot
20c9c410af
Update webserver local assets to 20250224-195901 (#8312) 2025-02-26 09:49:22 +13:00
J. Nick Koston
79af437f48
Fix BLE max notifications with ESP-IDF 5.x (#8301) 2025-02-26 09:49:22 +13:00
J. Nick Koston
6e27003787
Bump aioesphomeapi to 29.1.1 (#8274) 2025-02-26 09:49:22 +13:00
tomaszduda23
b7b2f3e61c
[core] make upload_program more generic (#8321) 2025-02-26 09:24:05 +13:00
Keith Burzinski
9448737a92
[esp32_touch] Fix variants, add tests for variants (#8320) 2025-02-26 09:14:39 +13:00
J. Nick Koston
6f2bf4ec4c
Fix bluetooth race when disconnect called while still connecting (#8297) 2025-02-26 09:13:30 +13:00
kkosik20
54cea6c41e
Adding support for chsc6x touch controller (#8258) 2025-02-25 15:03:28 +11:00
tomaszduda23
e754d0a58b
[i2c] python code style (#8311) 2025-02-25 16:10:49 +13:00
Nick Kinnan
5e44a035a3
web_server: ensure fair network sharing + prevent lost state changes via deferred publish at high event load (#7538)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-02-25 13:19:31 +11:00
rforro
c424fea524
ili9xxx: Add support for GC9D01N circle display (#8302) 2025-02-25 10:45:45 +11:00
Nick Kinnan
6aba1dbd73
[api] ensure fair network sharing + prevent lost state changes via deferred publish at high event load (#7547)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-02-25 10:20:21 +11:00
dependabot[bot]
422fb8f1a5
Bump actions/upload-artifact from 4.6.0 to 4.6.1 (#8295) 2025-02-25 10:04:00 +13:00
dependabot[bot]
2988bbb8ce
Bump peter-evans/create-pull-request from 7.0.6 to 7.0.7 (#8314) 2025-02-25 10:03:18 +13:00
esphomebot
59299bffc8
Update webserver local assets to 20250224-195901 (#8312) 2025-02-25 10:02:54 +13:00
Kevin Ahrendt
3410aee42e
[socket] add connect method (#8308) 2025-02-25 09:32:54 +13:00
J. Nick Koston
96682f5cbe
Fix BLE max notifications with ESP-IDF 5.x (#8301) 2025-02-24 14:12:15 +00:00
J. Nick Koston
bfa3254d6c
Bump aioesphomeapi to 29.1.1 (#8274) 2025-02-24 07:34:20 +13:00
tomaszduda23
990d1e3bb0
[ota] set USE_OTA_VERSION 2 in defines (#8299) 2025-02-24 07:33:52 +13:00
tomaszduda23
755b0bbfc7
[core, dashboard] load external component to get get_download_types (#8139) 2025-02-22 14:19:17 -06:00
Katherine Whitlock
c281351732
Finish up transition from black-format to ruff (#8294) 2025-02-21 13:02:55 -06:00
dependabot[bot]
9f603a474f
Bump docker/build-push-action from 6.13.0 to 6.14.0 in /.github/actions/build-image (#8281)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-21 00:59:18 +01:00
Hareesh M U
bf739506c3
[ld2450] Add new component (#5674)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Co-authored-by: Marcus Better <marcus@better.se>
Co-authored-by: Trevor Schirmer <24777085+TrevorSchirmer@users.noreply.github.com>
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-02-20 03:16:08 -06:00
Katherine Whitlock
3020083564
Ruff format for CI (#8276) 2025-02-19 13:24:43 -06:00
Jesse Hills
31e90e5544
Merge branch 'release' into dev 2025-02-19 22:19:56 +13:00
Jesse Hills
7c9726859f
Merge pull request #8275 from esphome/bump-2025.2.0
2025.2.0
2025-02-19 22:19:09 +13:00
dependabot[bot]
7529fb10b4
Bump actions/cache from 4.2.0 to 4.2.1 (#8271)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-19 16:46:22 +13:00
Jesse Hills
ba79e2d7b1
Bump version to 2025.2.0 2025-02-19 13:40:15 +13:00
dependabot[bot]
7006bd24a5
Bump actions/cache from 4.2.0 to 4.2.1 in /.github/actions/restore-python (#8273) 2025-02-18 23:23:56 +00:00
Jesse Hills
58311c9a0d
Merge branch 'beta' into dev 2025-02-19 10:44:39 +13:00
Jesse Hills
ae65f76dfe
Merge pull request #8272 from esphome/bump-2025.2.0b6
2025.2.0b6
2025-02-19 10:44:08 +13:00
Jesse Hills
4d380214df
Bump version to 2025.2.0b6 2025-02-19 09:22:52 +13:00
J. Nick Koston
c5ebf7683e
Bump zeroconf to 0.145.1 (#8267) 2025-02-19 09:22:52 +13:00
G-Two
a973adda67
Increase default repeat delay for Toto remote transmitter protocol (#8265) 2025-02-19 09:22:52 +13:00
J. Nick Koston
d9b419eaf5
Bump openssh-client to 1:9.2p1-2+deb12u4 to fix docker builds (#8269) 2025-02-19 09:22:52 +13:00
J. Nick Koston
02bf33c548
Bump zeroconf to 0.145.1 (#8267) 2025-02-18 17:38:41 +00:00
G-Two
b3db04a3d3
Increase default repeat delay for Toto remote transmitter protocol (#8265) 2025-02-19 06:30:03 +13:00
J. Nick Koston
56034e3e79
Bump openssh-client to 1:9.2p1-2+deb12u4 to fix docker builds (#8269) 2025-02-19 06:11:58 +13:00
J. Nick Koston
abbd72e802
Use the process CPU count to determine how many children to create (#8268) 2025-02-19 06:10:33 +13:00
Jesse Hills
1257640e48
Merge branch 'beta' into dev 2025-02-18 14:14:05 +13:00
Jesse Hills
2bc9782ce7
Merge pull request #8264 from esphome/bump-2025.2.0b5
2025.2.0b5
2025-02-18 14:13:33 +13:00
Jesse Hills
6583e17810
Bump version to 2025.2.0b5 2025-02-18 13:39:42 +13:00
J. Nick Koston
64c8bcef2e
Bump aioesphomeapi to 29.1.0 (#8105) 2025-02-18 13:39:42 +13:00
J. Nick Koston
f9da8dbfb8
Replace glyphsets with esphome_glyphsets (#8261) 2025-02-18 13:39:42 +13:00
J. Nick Koston
74f7197543
Bump aioesphomeapi to 29.1.0 (#8105) 2025-02-17 16:27:06 -06:00
J. Nick Koston
c21b8bd417
Switch to native arm runners for docker CI (#8262) 2025-02-18 11:19:11 +13:00
J. Nick Koston
1eb658cc5b
Replace glyphsets with esphome_glyphsets (#8261) 2025-02-17 21:48:24 +00:00
Jesse Hills
8b251efb75
Merge branch 'beta' into dev 2025-02-17 13:10:17 +13:00
Jesse Hills
26d25464da
Merge pull request #8259 from esphome/bump-2025.2.0b4
2025.2.0b4
2025-02-17 13:09:45 +13:00
Jesse Hills
78b55e22ee
Bump version to 2025.2.0b4 2025-02-17 12:14:06 +13:00
Ali Jafri
9ee5227fe0
DHT platform now supports modules with inbuilt external resistor (#8257) 2025-02-17 12:14:06 +13:00
J. Nick Koston
e89603fe3b
Bump zeroconf to 0.144.3 (#8253) 2025-02-17 12:14:06 +13:00
Djordje Mandic
c0804d665d
[scd30] Increase minimal CONF_UPDATE_INTERVAL from 1 to 2 seconds (#8256) 2025-02-17 12:14:05 +13:00
Samuel Sieb
a67b85eabf
don't crash on null pages (#8254)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2025-02-17 12:14:05 +13:00
Ali Jafri
a47e27885f
DHT platform now supports modules with inbuilt external resistor (#8257) 2025-02-17 11:05:54 +13:00
J. Nick Koston
2e66b33672
Bump zeroconf to 0.144.3 (#8253) 2025-02-17 08:53:19 +13:00
Djordje Mandic
e21ef22706
[scd30] Increase minimal CONF_UPDATE_INTERVAL from 1 to 2 seconds (#8256) 2025-02-17 08:09:42 +13:00
Samuel Sieb
93c2878c21
don't crash on null pages (#8254)
Co-authored-by: Samuel Sieb <samuel@sieb.net>
2025-02-16 01:02:51 -06:00
Jesse Hills
b3ad6a03e6
Merge branch 'beta' into dev 2025-02-14 16:47:17 +13:00
Jesse Hills
6e45a7c9af
Merge pull request #8251 from esphome/bump-2025.2.0b3
2025.2.0b3
2025-02-14 16:43:58 +13:00
Jesse Hills
e17582544e
Bump version to 2025.2.0b3 2025-02-14 14:28:42 +13:00
Jesse Hills
daa7960031
Fix crash when storage file doesnt exist yet (#8249) 2025-02-14 14:28:41 +13:00
Dániel Márai
6999cc0581
Add support for the DAC on the S2 (#8030)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2025-02-14 14:28:41 +13:00
Jonathan Swoboda
92ad6286aa
[logger] Fix bug causing global log level to be overwritten (#8248) 2025-02-14 14:28:41 +13:00
guillempages
1111aa167f
[online_image]Fix reset if buffer not allocated (#8236) 2025-02-14 14:28:41 +13:00
Jesse Hills
143b0d3de4
Fix crash when storage file doesnt exist yet (#8249) 2025-02-14 14:27:11 +13:00
Dániel Márai
788c41e6f4
Add support for the DAC on the S2 (#8030)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2025-02-14 13:15:01 +13:00
Jonathan Swoboda
46b6dcdfbf
[logger] Fix bug causing global log level to be overwritten (#8248) 2025-02-13 19:56:08 +00:00
Jesse Hills
d05f641dd0
Merge branch 'beta' into dev 2025-02-13 21:31:40 +13:00
Jesse Hills
897873496a
Merge pull request #8246 from esphome/bump-2025.2.0b2
2025.2.0b2
2025-02-13 21:31:05 +13:00
Jesse Hills
b0f6dd7d9c
Bump version to 2025.2.0b2 2025-02-13 20:44:12 +13:00
Keith Burzinski
be5639faf1
[modbus_controller] Remove stream dependency (#8244) 2025-02-13 20:44:12 +13:00
Keith Burzinski
e9a537784e
[graph] Remove `stream` dependency (#8243) 2025-02-13 20:44:12 +13:00
Gábor Poczkodi
35d303809e
[cse7766] Remove stream dependency (#7720)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-02-13 20:44:12 +13:00
Jesse Hills
4740f12ce8
[core] Fix `config_dir` for dashboard (#8242) 2025-02-13 20:44:12 +13:00
J. Nick Koston
c8e7e275a4
Bump zeroconf to 0.144.1 (#8238) 2025-02-13 20:44:12 +13:00
Jesse Hills
077ee5b714
[core] Ignore dot-prefixed config entries when looking for target platform (#8240) 2025-02-13 20:44:12 +13:00
Keith Burzinski
fa029e8fc7
[modbus_controller] Extend tests (#8245) 2025-02-13 20:40:02 +13:00
Keith Burzinski
ace953bd50
[modbus_controller] Remove stream dependency (#8244) 2025-02-13 04:34:16 +00:00
Keith Burzinski
e190ef9e9b
[graph] Remove `stream` dependency (#8243) 2025-02-13 03:37:29 +00:00
Gábor Poczkodi
2868210d46
[cse7766] Remove stream dependency (#7720)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-02-13 03:07:14 +00:00
Jesse Hills
72f6461871
[core] Fix `config_dir` for dashboard (#8242) 2025-02-13 02:57:57 +00:00
J. Nick Koston
4a95468fd2
Bump zeroconf to 0.144.1 (#8238) 2025-02-13 14:17:00 +13:00
Jesse Hills
43319d4c8a
[core] Ignore dot-prefixed config entries when looking for target platform (#8240) 2025-02-12 21:05:46 +00:00
guillempages
3b7a7a2262
[online_image]Fix reset if buffer not allocated (#8236) 2025-02-12 20:55:32 +11:00
Jesse Hills
de2d21862b
Merge branch 'beta' into dev 2025-02-12 17:24:36 +13:00
Jesse Hills
3d48eb26cd
Merge pull request #8237 from esphome/bump-2025.2.0b1
2025.2.0b1
2025-02-12 17:24:00 +13:00
Jesse Hills
ab0d38fbda
Bump version to 2025.3.0-dev 2025-02-12 13:53:43 +13:00
Jesse Hills
2b75e34719
Bump version to 2025.2.0b1 2025-02-12 13:53:43 +13:00
Jesse Hills
0b6c416680
Bump esphome-dashboard to 20250212.0 (#8235) 2025-02-12 13:16:17 +13:00
Neil Ségard
7bb2c3c496
Add support for Waveshare 7.3" ACeP 7-Color display (#6380) 2025-02-12 10:31:56 +11:00
Michael Grüner
88cfdc33d4
GDEY042T81 e-paper displays support (#8061)
Co-authored-by: clydebarrow <2366188+clydebarrow@users.noreply.github.com>
2025-02-12 10:17:34 +11:00
Daniël Koek
a2f1b90238
Add GDEY029T94 support (#7931)
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
2025-02-12 10:16:33 +11:00
Rachasak Ragkamnerd
0401ee9428
added Waveshare BWR Mode for the 4.2in Display (#7995)
Co-authored-by: rrachasak <dev@rachasak.org>
Co-authored-by: clydebarrow <2366188+clydebarrow@users.noreply.github.com>
2025-02-12 08:35:07 +11:00
tmpeh
14d7931bd6
Added Waveshare e-paper display model "7.50inv2p" to the waveshare_epaper component. (#7751)
Co-authored-by: Tim Pehla <tim.pehla@uni-bielefeld.de>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
2025-02-12 09:41:52 +13:00
Jordan Zucker
6b3f3e1da6
[prometheus] Adding valve entity metrics (#8223) 2025-02-12 08:51:55 +13:00
Kevin Ahrendt
33f9d66e81
[voice_assistant] Add announce support (#8232) 2025-02-12 07:20:39 +13:00
Kevin Ahrendt
46d19d82c2
[speaker] Bugfix: Ensure all audio is played after completely decoding a file (#8231) 2025-02-12 07:14:59 +13:00
guillempages
c9e7562aff
[online_image] Improve error handling (#8212) 2025-02-11 22:12:13 +11:00
guillempages
8b7aa4c110
[http_request]Use std::string for headers (#8225) 2025-02-11 11:39:03 +11:00
Táta GEEK
b667ceaced
Add waveshare 2.9inch e-Paper HAT (D) (#7906)
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
2025-02-11 11:35:56 +11:00
mystster
abdf215d3a
Add partial update of GDEW029T5 e-paper display (#8162)
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
2025-02-11 07:29:27 +11:00
Kevin Ahrendt
84836f15db
[speaker] Media Player Components PR9 (#8171)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2025-02-11 08:00:23 +13:00
Jonathan Swoboda
8be9f02693
[ota] Increase socket timeout earlier in OTA script (#8129) 2025-02-10 17:42:40 +13:00
Igor Novgorodov
1ab1768b6a
Add ADC sampling method option (#8131)
Co-authored-by: Djordje Mandic <6750655+DjordjeMandic@users.noreply.github.com>
2025-02-10 17:32:54 +13:00
Stefan Rado
0d13e2040d
Don't activate venv in devcontainer (#8128) 2025-02-10 17:12:46 +13:00
Awesome Walrus
fd24b1423c
Fix pref conflict of WiFi creds and fast_connect (#8219) 2025-02-10 16:54:37 +13:00
Clyde Stubbs
66c35a9432
[waveshare_epaper] Rationalise and complete tests (#8221) 2025-02-10 16:46:05 +13:00
Craig Andrews
45b8810ab8
[online_image] Set Accept header (#8216) 2025-02-10 15:55:16 +13:00
Clyde Stubbs
ff7d232ee6
[logger] Add runtime level select (#8222)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2025-02-10 15:53:26 +13:00
guillempages
0cd3af2fcd
[online_image]Pin specific version of JPEG library (#8217) 2025-02-10 13:17:29 +13:00
Keith Burzinski
8897a9866d
[CI] Consolidate some tests (T) (#8208) 2025-02-10 10:43:21 +13:00
Keith Burzinski
dc8646cda6
[CI] Consolidate some tests (U, V, W, X, Y, Z) (#8210) 2025-02-10 10:43:17 +13:00
Keith Burzinski
353924257a
[CI] Consolidate some tests (S) (#8206) 2025-02-10 10:43:10 +13:00
Keith Burzinski
da3d007d7b
Markdown tweaks/updates (#8211) 2025-02-10 10:40:19 +13:00
G-Two
9e3359cdf2
Add Toto protocol to remote receiver and transmitter (#8177) 2025-02-06 23:08:06 -06:00
Jonathan Swoboda
7e626b04f2
[esp32_rmt] Set pull-up and open-drain modes based on pin schema (#8178)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-02-06 22:09:24 -06:00
dependabot[bot]
4eb551864d
Bump the docker-actions group with 2 updates (#8215)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-06 20:33:57 +01:00
bdm310
e337bd7beb
[sdl] Implement binary sensors from keystrokes (#8207)
Co-authored-by: clydebarrow <2366188+clydebarrow@users.noreply.github.com>
2025-02-05 21:53:23 +11:00
Jan Schröter
57739b8bb0
[uponor_smatrix] add target temperature as sensor (#7745) 2025-02-05 15:53:05 +13:00
Jordan Zucker
65ca000e6d
[prometheus] Add update entity to prometheus metrics (#8173) 2025-02-05 15:43:44 +13:00
Keith Burzinski
bf6874b52e
[CI] Consolidate some tests (Q, R) (#8205) 2025-02-05 15:37:22 +13:00
Keith Burzinski
cecce0f3cb
[CI] Consolidate some tests (N, O, P) (#8204) 2025-02-05 15:37:15 +13:00
Clyde Stubbs
4d8f58db94
[preferences] Better handling of flash_write_interval (#8199) 2025-02-05 15:34:30 +13:00
Clyde Stubbs
977333a73c
[lvgl] Make layouts work properly on base display (#8193) 2025-02-05 14:44:51 +13:00
Clyde Stubbs
1215d2ffeb
[xxtea] Extract encryption functions to separate component (#8183)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2025-02-05 12:22:40 +13:00
Clyde Stubbs
9b56f9cc6d
[lvgl] add triggers for swipe gestures (#8190) 2025-02-05 12:13:21 +13:00
Jonathan Swoboda
2e61229aed
[i2c] Workaround for i2c on s2 (#8188) 2025-02-05 12:09:37 +13:00
Keith Burzinski
55203143df
[CI] Consolidate some tests (I, J) (#8200) 2025-02-05 12:06:08 +13:00
Keith Burzinski
4e4566361f
[CI] Consolidate some tests (M) (#8202) 2025-02-05 12:05:59 +13:00
Keith Burzinski
4273449003
[CI] Consolidate some tests (K, L) (#8201) 2025-02-05 12:05:53 +13:00
Keith Burzinski
f8fae676b1
[CI] Consolidate some tests (H) (#8198) 2025-02-05 12:05:50 +13:00
Keith Burzinski
211aee91e5
[CI] Consolidate some tests (G) (#8196) 2025-02-05 12:05:45 +13:00
Keith Burzinski
6e3527a88b
[CI] Consolidate some tests (F) (#8195) 2025-02-05 12:05:35 +13:00
Keith Burzinski
06f9764f51
[CI] Consolidate some tests (E) (#8191) 2025-02-05 12:05:24 +13:00
Keith Burzinski
693d813c4b
[CI] Consolidate some tests (D) (#8189) 2025-02-05 12:05:17 +13:00
Keith Burzinski
61ad2510fc
[CI] Consolidate some tests (C) (#8186) 2025-02-05 12:05:08 +13:00
Keith Burzinski
53c15f6716
[CI] Consolidate some tests (B) (#8185) 2025-02-05 12:05:02 +13:00
Keith Burzinski
d4ac2d3c7e
[CI] Consolidate some tests (A) (#8184) 2025-02-05 12:04:53 +13:00
Kevin Ahrendt
6f4e8f1fbf
[mixer] Media Player Components PR8 (#8170)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2025-02-04 23:00:02 +00:00
Kevin Ahrendt
847cff06b3
[resampler] Media Player Components PR7 (#8169)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2025-02-05 09:18:11 +13:00
Jesse Hills
bd34697715
Remove arm/v7 container image support (#8194) 2025-02-05 07:56:38 +13:00
Kevin Ahrendt
6b55df36c7
[audio] Media Player Components PR6 (#8168)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2025-02-04 15:58:35 +13:00
Kevin Ahrendt
b8f9eaecd8
[audio] Media Player Components PR5 (#8167) 2025-02-03 23:47:50 +00:00
Kevin Ahrendt
c8bbc2e84c
[audio] Media Player Components PR4 (#8166)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2025-02-03 22:34:20 +00:00
Djordje Mandic
5108b9a8b7
Make get_flags() in GPIOPin mandatory (#8182)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-02-03 11:14:55 -06:00
Djordje Mandic
8de5af4eec
Add virtual get_flags() to GPIOPin and implementation in InternalGPIOPin derivatives (#8151) 2025-02-02 21:55:55 -06:00
Kevin Ahrendt
6e5e681055
[audio] Media Player Components PR3 (#8165) 2025-02-03 02:54:55 +00:00
Kevin Ahrendt
f6cf99384b
[audio, i2s_audio, speaker] Media Player Components PR2 (#8164)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2025-02-03 15:25:41 +13:00
Kevin Ahrendt
2b711e532b
[i2s_audio] Media Player Components PR1 (#8163) 2025-02-02 21:38:10 +01:00
J. Nick Koston
72c6f04a97
Bump zeroconf to 0.143.0 (#8104) 2025-02-02 21:35:52 +01:00
Rodrigo Martín
03e2701bd0
feat(core): Add support for <...> includes (#8132) 2025-02-02 21:34:38 +01:00
Jonathan Swoboda
051fa3a49f
[remote_base] Add default value for offset in is_valid (#8159) 2025-02-01 04:13:38 -06:00
NicoIIT
7392397630
Use abspath for config path dir (#8044) 2025-01-29 15:03:42 +01:00
Jonathan Swoboda
714e2d3e56
[remote_transmitter] Fix issues with 32bit rollover on esp8266 and libretiny (#8056)
Co-authored-by: Jonathan Swoboda <jonathan.swoboda>
2025-01-29 07:34:10 -06:00
dependabot[bot]
12d6c1bbca
Bump actions/setup-python from 5.3.0 to 5.4.0 in /.github/actions/restore-python (#8153)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-29 14:31:49 +01:00
dependabot[bot]
7727879f01
Bump actions/setup-python from 5.3.0 to 5.4.0 (#8154)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-29 14:30:30 +01:00
dependabot[bot]
334e952a34
Bump pypa/gh-action-pypi-publish from 1.12.3 to 1.12.4 (#8137)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-29 13:40:31 +01:00
dependabot[bot]
f9856135d0
Bump docker/build-push-action from 6.12.0 to 6.13.0 in /.github/actions/build-image (#8136)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-29 13:40:25 +01:00
Olliver Schinagl
ba3e5e8ecb
[climate] Accept °K as intended (#8134) 2025-01-30 00:27:55 +13:00
Jonathan Swoboda
67ccd0eb7f
[esp32_rmt] Increase default symbols in led strip and remove IRAM config (#8133) 2025-01-29 04:51:04 -06:00
Clyde Stubbs
619ce93dec
[display] Properly handle case of auto_clear_enabled: false (#8156) 2025-01-29 04:45:29 -06:00
Jimmy Hedman
9957840dfc
Add multicast support to udp component (#8051) 2025-01-29 21:00:18 +11:00
Stefan Rado
a23ce416ea
Fix forgotten uses of use_transparency (#8115) 2025-01-29 14:54:10 +11:00
Clyde Stubbs
2489f95107
[logger] Ensure PRIu32 and friends are available (#8155) 2025-01-28 23:58:06 +00:00
guillempages
7dab1a6082
[online_image] Add JPEG support to online_image (#8127)
Co-authored-by: Jimmy Hedman <jimmy.hedman@gmail.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: Rodrigo Martín <contact@rodrigomartin.dev>
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
2025-01-29 10:35:43 +11:00
Rodrigo Martín
f7f8bf4da4
[esp32_ble_server] Create custom services, characteristics and descriptors (#7009)
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
2025-01-28 22:00:28 +11:00
J. Nick Koston
dd18a219db
Include Bluetooth connection slot allocations in connections free message (#8148) 2025-01-28 06:57:52 +04:00
Jimmy Hedman
dbf4c2c4da
Update mdns for ESP-IDF (#8145) 2025-01-26 22:23:57 -06:00
guillempages
fc847c1de8
[online_image] Code Improvements (#8130) 2025-01-24 07:32:03 +11:00
Jesse Hills
7fccc9ff86
[online_image] Add binary bmp support (#8116)
Co-authored-by: guillempages <guillempages@users.noreply.github.com>
2025-01-23 15:10:19 +13:00
Olliver Schinagl
dee1d84979
[spi] Fix data type in bitbash transfer_() (#8125) 2025-01-22 23:41:55 +00:00
Oskari Lemmelä
65b2d48a6f
Fix mqtt climate step rounding (#8121) 2025-01-23 12:32:45 +13:00
brambo123
8aeb08f868
[ads1115] Add sample rate control (#8102) 2025-01-23 12:31:07 +13:00
Djordje Mandic
d4857a1727
Add verbose logging for pulse width calculation in pulse_meter (#8124) 2025-01-23 12:07:26 +13:00
tomaszduda23
0c032bc431
[core] add support for custom platform (#7616)
Co-authored-by: Tomasz Duda <tomaszduda23@gmai.com>
2025-01-23 12:06:07 +13:00
Keith Burzinski
5a103543c4
[esp32] Set logger default interface for C6 (#8126) 2025-01-22 23:00:40 +00:00
Frederik
01ab6d3ddc
[debug] fix debug_esp32 printf for partition size and address (#8122)
Co-authored-by: Djordje Mandic <6750655+DjordjeMandic@users.noreply.github.com>
2025-01-23 09:37:32 +11:00
Keith Burzinski
f2170c633a
[es7243e] Add support for ES7243E audio ADC (#8098) 2025-01-23 09:23:22 +13:00
Citric Li
c2e52f4b11
Add: Human Presence and Target Count to the Seeed Studio MR60BHA2 (#8010)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Co-authored-by: Spencer Yan <spencer@spenyan.com>
2025-01-22 13:01:15 +13:00
Keith Burzinski
4843bbd38a
[custom] Remove platforms (#8119) 2025-01-22 12:56:51 +13:00
dependabot[bot]
78ce8f014a
Bump actions/stale from 9.0.0 to 9.1.0 (#8120)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-22 08:15:56 +13:00
Jesse Hills
b454f63b36
[core] Remove old style platform configuration (#8118) 2025-01-21 00:32:47 -06:00
Jonathan Swoboda
db644542ed
[esp32_touch] Fix deprecated warning (#8092)
Co-authored-by: Jonathan Swoboda <jonathan.swoboda>
2025-01-21 16:17:32 +13:00
Keith Burzinski
716a8b87e1
[es8156] Add support for ES8156 audio DAC (#8085)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2025-01-21 16:15:18 +13:00
Clyde Stubbs
0f4e274e52
[uptime] Cosmetic improvements for uptime text_sensor (#8101) 2025-01-21 15:43:50 +13:00
Keith Burzinski
576dbd6f0c
[audio_adc] Add new `audio_adc` component (#8094) 2025-01-21 15:35:40 +13:00
Jesse Hills
c3d00b45f7
Update defines.h for esp-idf 5.1.5 (#8117) 2025-01-21 01:50:04 +00:00
Mikkel Jeppesen
98b872abc7
Fixed incorrect display dimension (#8110) 2025-01-20 09:36:07 +11:00
guillempages
75026be951
[online_image] Use RAMAllocator (#8114) 2025-01-19 22:16:37 +00:00
guillempages
47a0ec467a
[image]Rename option "use_transparency" (#8113) 2025-01-20 08:34:38 +11:00
Jesse Hills
9e40d4cf45
Merge branch 'release' into dev 2025-01-17 14:47:56 +13:00
Jesse Hills
fecae2f740
Merge pull request #8100 from esphome/bump-2024.12.4
2024.12.4
2025-01-17 14:47:16 +13:00
Jesse Hills
5a01670803
Bump version to 2024.12.4 2025-01-17 13:40:12 +13:00
Jesse Hills
c2423b18cb
Bump python3-setuptools to 66.1.1-1+deb12u1 (#8074) 2025-01-17 13:40:11 +13:00
Jesse Hills
2363b3dfd6
Merge branch 'release' into dev 2025-01-17 13:32:53 +13:00
Jesse Hills
628e47f670
Merge pull request #8099 from esphome/bump-2024.12.3
2024.12.3
2025-01-17 13:32:12 +13:00
Jesse Hills
7666581c54
Bump version to 2024.12.3 2025-01-17 12:24:22 +13:00
Kevin Ahrendt
03c36920ff
[http_request] Bugfix: run update function in a task (#8018) 2025-01-17 12:24:22 +13:00
Piotr Szulc
abdd6b232f
Fixed libretiny preference wrongly detecting change in the data to store (#7990) 2025-01-17 12:24:22 +13:00
j-sepul
07be7ad7e2
Increase Daly-BMS coltage cells from 16 to 18 cells (#8057) 2025-01-17 11:08:04 +13:00
Katherine Whitlock
820e3488d0
Remove black-formatter from pre-commit hooks (#8097) 2025-01-17 10:44:26 +13:00
Kevin Ahrendt
8c6c45e6c1
[http_request] Bugfix: run update function in a task (#8018) 2025-01-17 10:43:41 +13:00
Katherine Whitlock
16bf56b0f9
Fix running pre-commit on Windows (#8095) 2025-01-17 09:10:20 +13:00
Clyde Stubbs
49c01c26f1
Revert "Add resistance_sampler interface for config validation" (#8093)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2025-01-16 16:12:30 +11:00
dependabot[bot]
b4a804cc77
Bump docker/build-push-action from 6.11.0 to 6.12.0 in /.github/actions/build-image (#8090)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-16 14:53:23 +13:00
Jordan Zucker
df26ace0f1
[prometheus] Select, media_player, and number prometheus metrics (#7895) 2025-01-15 16:56:22 +13:00
Jesse Hills
e779a8bcb2
[event] Store `last_event_type` in class (#8088) 2025-01-15 16:54:45 +13:00
Jesse Hills
c458fd18df
Bump version to 2025.2.0-dev 2025-01-15 16:49:58 +13:00
Kevin Ahrendt
98817a5bbf
[es7210] add support for es7210 ADC (#8007) 2025-01-15 16:47:22 +13:00
Saninn Salas Diaz
c43d8460bd
fix(web_server/fan): send speed update values even when fan is off (#8086) 2025-01-15 15:14:58 +13:00
Clyde Stubbs
17b88f2e3e
[lvgl] fix lvgl.widget.update and friends (#8087) 2025-01-15 14:29:51 +13:00
Clyde Stubbs
dac9768f6a
[spi] Restore `SPIDelegateDummy` (#8019) 2025-01-15 13:56:52 +13:00
Clyde Stubbs
e8d2ad4ce8
[ili9xxx] psram and 8 bit changes (#8084) 2025-01-15 11:53:44 +13:00
Clyde Stubbs
c3412df169
[image] Fix mdi images (#8082) 2025-01-15 11:29:27 +13:00
Clyde Stubbs
fc2b15e307
[uptime] Add text_sensor (#8028) 2025-01-15 11:27:47 +13:00
Stefan Rado
bdb1094b47
Allow external libraries to use ESP_LOGx macros (#8078) 2025-01-14 14:20:52 +11:00
Clyde Stubbs
6262fb8fcf
[lvgl] fix tests (#8075) 2025-01-13 15:32:54 -06:00
Nate Clark
f319472066
web_server: Adds REST API POST endpoints to arm and disarm (#7985) 2025-01-13 17:35:29 +13:00
Dusan Cervenka
b4a2b50ee0
Fixed topic when mac is used (#7988) 2025-01-13 17:34:07 +13:00
Piotr Szulc
30bb806f26
Fixed libretiny preference wrongly detecting change in the data to store (#7990) 2025-01-13 17:31:01 +13:00
NP v/d Spek
9874d17613
add missing include in base_automation.h (#8001) 2025-01-13 17:29:38 +13:00
Ryan Henderson
13909b7994
[esp32_wifi] Enhance WiFi component with TCPIP core locking. (#7997) 2025-01-13 17:26:23 +13:00
Ryan Henderson
df50e57409
Include esp_mac.h and C++20 str_startswith/str_ends (#7999) 2025-01-13 17:18:20 +13:00
Ryan Henderson
3fa67fad32
Fix compile errors with pioarduino/platform-espressif32: wifi_component_esp32_arduino.cpp (#7998) 2025-01-13 17:17:28 +13:00
Douglas
8fbd512952
Use ESPHome logo on readme page according to theme (light/dark) (#7992) 2025-01-13 17:16:43 +13:00
Edward Firmo
528d3672b4
[psram] Improve total PSRAM display in logs by using rounded KB values (#8008)
Co-authored-by: Djordje Mandic <6750655+DjordjeMandic@users.noreply.github.com>
2025-01-13 17:11:48 +13:00
Edward Firmo
fef50afef8
[debug] Add ESP32 partition table logging to dump_config (#8012) 2025-01-13 17:08:20 +13:00
Edward Firmo
aa1879082c
[debug] Add framework type to debug info (#8013) 2025-01-13 17:06:44 +13:00
Djordje Mandic
d8c943972b
[core] fix comment for crc8 function in helpers.h (#8016) 2025-01-13 17:05:53 +13:00
Kyle Cascade
f3ebb4eb39
Added VERY_VERBOSE dfplayer printing (#8026) 2025-01-13 16:23:35 +13:00
Clyde Stubbs
f1c0570e3b
[image] Transparency changes; code refactor (#7908) 2025-01-13 16:21:42 +13:00
Keith Burzinski
aa87c60717
[nextion] Brightness control tweaks (#8027) 2025-01-13 16:12:54 +13:00
Clyde Stubbs
92a8ebe1f8
[json] use correct formatting (#8039) 2025-01-13 15:56:42 +13:00
Marcin Żbik
dd3ffc7f29
Fix Waveshare 7in5bv3bwr image quality in BWR mode (#8043)
Co-authored-by: zbikmarc <zbimarc+github@gmail.com>
2025-01-13 15:55:30 +13:00
Jonathan Swoboda
aac3841991
[esp32] Fix arch_get_cpu_freq_hz (#8047)
Co-authored-by: Jonathan Swoboda <jonathan.swoboda>
2025-01-13 14:45:35 +13:00
Mischa Siekmann
fb87a1c0bc
Allow CONF_RMT_CHANNEL parameter for IDF 4.X (#8035) 2025-01-13 14:42:03 +13:00
Jesse Hills
4409471cd1
Bump python3-setuptools to 66.1.1-1+deb12u1 (#8074) 2025-01-13 14:32:10 +13:00
dependabot[bot]
739edce268
Bump docker/build-push-action from 6.10.0 to 6.11.0 in /.github/actions/build-image (#8053)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-13 12:55:53 +13:00
dependabot[bot]
f25f3334d1
Bump docker/setup-qemu-action from 3.2.0 to 3.3.0 in the docker-actions group (#8052)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-13 12:55:37 +13:00
dependabot[bot]
571935fb3b
Bump peter-evans/create-pull-request from 7.0.5 to 7.0.6 (#8024)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-13 12:55:00 +13:00
dependabot[bot]
7c39422692
Bump actions/upload-artifact from 4.5.0 to 4.6.0 (#8058)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-13 12:54:44 +13:00
tomaszduda23
731fb1d172
[spi] relay on KEY_TARGET_PLATFORM as the other platforms does (#8066) 2025-01-13 11:15:39 +13:00
Brian Whicheloe
40bee2a854
Add log level env var (#7604)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2025-01-13 08:15:22 +13:00
Jimmy Hedman
d69926485c
Convert IPAddress to use Pythonmodule ipaddress (#8072) 2025-01-13 08:12:38 +13:00
Clyde Stubbs
fe80750743
[display] auto_clear_enabled defaults (#7986) 2025-01-13 07:56:54 +13:00
Clyde Stubbs
109d737d5d
[lvgl] Implement lvgl.page.is_showing: condition (#8055) 2025-01-13 07:53:26 +13:00
Clyde Stubbs
bd17ee8e33
[config] Early check for required version (#8000) 2025-01-13 07:50:13 +13:00
Clyde Stubbs
f1712cffa8
[spi_led_strip] Fix priority (#8021) 2025-01-13 07:49:05 +13:00
Clyde Stubbs
0df6a913b3
[lgvl] disp_bg_image and disp_bg_opa changes (#8025) 2025-01-13 07:46:17 +13:00
Clyde Stubbs
8a98b69a57
[lvgl] fix bg_image_src (#8005)
Co-authored-by: clydeps <U5yx99dok9>
2025-01-13 07:42:03 +13:00
Clyde Stubbs
4530e4d60f
[lvgl] remove default state (#8038) 2025-01-13 07:40:50 +13:00
Juan Jose Restrepo
4d7c6b28e1
Update sprinkler.cpp (#7996) 2025-01-10 17:22:30 -06:00
Jimmy Hedman
de603c7565
Enable udp to work (on ipv4) when ipv6 is enabled (#8060)
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
2025-01-10 21:10:19 +00:00
Peter Zich
a498fb5dcf
Fix braceless else statements (#7799) 2025-01-09 00:47:30 -06:00
Samu Németh
78543e1e15
Fixed comment typo in light_color_values.h (#8050)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2025-01-08 22:37:52 +00:00
Clyde Stubbs
5e72b7196b
Remove rmt channel from idf tests (#8054) 2025-01-08 21:14:08 +00:00
Clyde Stubbs
a0615a92f0
[addressable_light] Remove rmt channel from idf tests (#7987) 2025-01-08 14:25:10 -06:00
Peter Zich
dc5b408748
Initialize esp32_rmt_led_strip buffer (#8036) 2025-01-05 19:50:35 -06:00
Jonathan Swoboda
387bde665e
[esp32_rmt] IDF 5+ update fixes (#8002)
Co-authored-by: Jonathan Swoboda <jonathan.swoboda>
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2024-12-24 03:15:40 -06:00
tomaszduda23
45beea68eb
[ble_client, bluetooth_proxy, esp32_ble_client, esp32_ble_tracker] fix ble proxy stop working (#7901)
Co-authored-by: J. Nick Koston <nick@koston.org>
2024-12-22 19:49:04 -10:00
Keith Burzinski
c457d8835e
Merge branch 'release' into dev 2024-12-20 18:56:18 -06:00
Keith Burzinski
4b51ba3fa4
Merge pull request #7989 from esphome/bump-2024.12.2
2024.12.2
2024-12-20 18:56:03 -06:00
Keith Burzinski
499953e3f4
Bump version to 2024.12.2 2024-12-20 14:34:11 -06:00
Keith Burzinski
69f1a81e1d
[esp32_ble] Fix for Improv (#7984) 2024-12-20 14:34:11 -06:00
Keith Burzinski
37fcccbb1c
[esp32] Fix flash size warning when using IDF (#7983) 2024-12-20 14:34:10 -06:00
Keith Burzinski
f3cb179f54
[esp32_ble] Fix for Improv (#7984) 2024-12-20 14:16:18 -06:00
Keith Burzinski
ba2edbc189
[esp32] Fix flash size warning when using IDF (#7983) 2024-12-20 01:28:08 -06:00
tomaszduda23
f33b4a714e
[esp32_ble] do not skip events if queue is blocked (#7960) 2024-12-19 14:45:40 -10:00
Jesse Hills
85d863601b
Merge branch 'release' into dev 2024-12-19 19:48:11 +13:00
Jesse Hills
fe0700166a
Merge pull request #7982 from esphome/bump-2024.12.1
2024.12.1
2024-12-19 19:47:30 +13:00
Jesse Hills
d28cf011d1
Bump version to 2024.12.1 2024-12-19 17:07:43 +13:00
Kevin Ahrendt
434879ea04
[core] Bugfix: Implement ring buffer with xRingbuffer (#7973) 2024-12-19 17:07:43 +13:00
dependabot[bot]
7da07303c9
Bump actions/upload-artifact from 4.4.3 to 4.5.0 (#7981)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-19 16:42:29 +13:00
Clyde Stubbs
b33b4481ea
[helpers] Provide calls to get free heap and largest available block. (#7978) 2024-12-19 16:40:08 +13:00
Clyde Stubbs
ac631711ab
[qspi_dbi] Bugfix and new features (#7979) 2024-12-19 16:30:23 +13:00
Jonathan Swoboda
265b6ec445
[esp32_rmt] Updates for IDF 5+ (#7770)
Co-authored-by: Jonathan Swoboda <jonathan.swoboda>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
2024-12-18 20:31:22 -06:00
Kevin Ahrendt
61499dbdd8
[core] Bugfix: Implement ring buffer with xRingbuffer (#7973) 2024-12-19 15:07:07 +13:00
Jesse Hills
0aaef9293b
Merge branch 'release' into dev 2024-12-18 17:07:26 +13:00
Djordje Mandic
a9d883b65a
[midea] Add Fahrenheit support to midea_ac.follow_me action (#7762) 2024-12-18 13:47:43 +13:00
Jonathan Swoboda
7554e954fe
[core] Add c6 and h2 to split default (#7974)
Co-authored-by: Jonathan Swoboda <jonathan.swoboda>
2024-12-18 10:12:14 +13:00
Jesse Hills
752af94a75
Merge branch 'beta' into dev 2024-12-18 10:03:48 +13:00
Jesse Hills
ccc9fd4a3f
[esp32_ble] Use RAMAllocator to avoid panic abort from `new` (#7936) 2024-12-17 12:10:38 -06:00
Jesse Hills
54fbf5184e
Bump esphome-dashboard to 20241217.1 (#7971) 2024-12-17 17:32:52 +13:00
Jesse Hills
759df7ae6c
[dashboard] Accept basic auth header (#7965) 2024-12-16 22:26:16 -06:00
dependabot[bot]
3d56397e58
Bump docker/setup-buildx-action from 3.7.1 to 3.8.0 in the docker-actions group (#7969)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-17 14:09:09 +13:00
Clyde Stubbs
9f6c64afa6
[font] cleanly handle font file format exception (Bugfix) (#7970) 2024-12-17 14:07:43 +13:00
Jesse Hills
663e18310d
[ci] Dont run main ci suite on docker files (#7966) 2024-12-16 16:58:42 -06:00
Jesse Hills
1a89aa8fbf
[uart] Use `SOC_UART_NUM as number of uarts instead of UART_NUM_MAX` (#7967) 2024-12-16 05:52:34 +00:00
Edward Firmo
e04743e381
[debug] Detailed reset reason (#7729)
Co-authored-by: Ramil Valitov <ramilvalitov@gmail.com>
2024-12-16 12:12:45 +13:00
Oleg Tarasov
a6957b9d3b
[opentherm] Message ordering, on-the-fly message editing, code improvements (#7903) 2024-12-16 12:04:26 +13:00
Edward Firmo
9816c27031
[nextion] Remove _internal from non-protected functions (#7656) 2024-12-16 11:00:44 +13:00
luar123
ea06740b46
Fix adc channel for ESP32-H2 (#7964) 2024-12-16 10:59:54 +13:00
Jesse Hills
9a5ec1b9e6
Merge branch 'beta' into dev 2024-12-16 10:42:53 +13:00
Edward Firmo
df4224e779
[nextion] Publishes is_connected() (#7961) 2024-12-16 07:30:47 +13:00
Edward Firmo
5877c57a35
[adc] Restore missing LIBRETINY code in a separated file (#7955) 2024-12-15 07:55:04 +13:00
Kevin Ahrendt
7f2ca800c1
[i2s_audio] Bugfix: Correctly set ring buffer size (#7959) 2024-12-13 23:17:58 -06:00
Edward Firmo
ce7ff15c8a
[pulse_counter] Fix volatile increment/decrement deprecation warnings (#7954) 2024-12-14 08:21:54 +11:00
Edward Firmo
88742e0399
[rotary_encoder] Fix volatile increment/decrement deprecation warnings (#7958) 2024-12-14 08:16:11 +11:00
Jonathan Swoboda
c187cb547c
[core] Move delay_microseconds_safe to iram (#7957)
Co-authored-by: Jonathan Swoboda <jonathan.swoboda>
2024-12-13 11:45:10 -08:00
Jesse Hills
42bc960a36
[sgp30] Set default update interval to 60s (#7952) 2024-12-12 03:37:51 -06:00
Jonathan Swoboda
ba63d266d8
[const] Add RMT CONF variables to const.py (#7953)
Co-authored-by: Jonathan Swoboda <jonathan.swoboda>
2024-12-12 04:37:22 +00:00
Jesse Hills
90baba4db7
Merge branch 'beta' into dev 2024-12-11 21:19:19 +13:00
Jesse Hills
1dfd15e607
Bump version to 2025.1.0-dev 2024-12-11 15:55:29 +13:00
3453 changed files with 54322 additions and 50480 deletions

View File

@ -31,7 +31,7 @@
"ms-python.python",
"ms-python.pylint",
"ms-python.flake8",
"ms-python.black-formatter",
"charliermarsh.ruff",
"visualstudioexptteam.vscodeintellicode",
// yaml
"redhat.vscode-yaml",
@ -49,14 +49,11 @@
"flake8.args": [
"--config=${workspaceFolder}/.flake8"
],
"black-formatter.args": [
"--config",
"${workspaceFolder}/pyproject.toml"
],
"ruff.configuration": "${workspaceFolder}/pyproject.toml",
"[python]": {
// VS will say "Value is not accepted" before building the devcontainer, but the warning
// should go away after build is completed.
"editor.defaultFormatter": "ms-python.black-formatter"
"editor.defaultFormatter": "charliermarsh.ruff"
},
"editor.formatOnPaste": false,
"editor.formatOnSave": true,

4
.github/FUNDING.yml vendored
View File

@ -1,4 +0,0 @@
---
# These are supported funding model platforms
custom: https://www.nabucasa.com

View File

@ -46,7 +46,7 @@ runs:
- name: Build and push to ghcr by digest
id: build-ghcr
uses: docker/build-push-action@v6.10.0
uses: docker/build-push-action@v6.15.0
env:
DOCKER_BUILD_SUMMARY: false
DOCKER_BUILD_RECORD_UPLOAD: false
@ -72,7 +72,7 @@ runs:
- name: Build and push to dockerhub by digest
id: build-dockerhub
uses: docker/build-push-action@v6.10.0
uses: docker/build-push-action@v6.15.0
env:
DOCKER_BUILD_SUMMARY: false
DOCKER_BUILD_RECORD_UPLOAD: false

View File

@ -17,12 +17,12 @@ runs:
steps:
- name: Set up Python ${{ inputs.python-version }}
id: python
uses: actions/setup-python@v5.3.0
uses: actions/setup-python@v5.5.0
with:
python-version: ${{ inputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache/restore@v4.2.0
uses: actions/cache/restore@v4.2.3
with:
path: venv
# yamllint disable-line rule:line-length

View File

@ -23,7 +23,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v4.1.7
- name: Set up Python
uses: actions/setup-python@v5.3.0
uses: actions/setup-python@v5.5.0
with:
python-version: "3.11"

View File

@ -33,22 +33,20 @@ concurrency:
jobs:
check-docker:
name: Build docker containers
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
arch: [amd64, armv7, aarch64]
os: ["ubuntu-latest", "ubuntu-24.04-arm"]
build_type: ["ha-addon", "docker", "lint"]
steps:
- uses: actions/checkout@v4.1.7
- name: Set up Python
uses: actions/setup-python@v5.3.0
uses: actions/setup-python@v5.5.0
with:
python-version: "3.9"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.7.1
- name: Set up QEMU
uses: docker/setup-qemu-action@v3.2.0
uses: docker/setup-buildx-action@v3.10.0
- name: Set TAG
run: |
@ -58,6 +56,6 @@ jobs:
run: |
docker/build.py \
--tag "${TAG}" \
--arch "${{ matrix.arch }}" \
--arch "${{ matrix.os == 'ubuntu-24.04-arm' && 'aarch64' || 'amd64' }}" \
--build-type "${{ matrix.build_type }}" \
build

View File

@ -13,6 +13,7 @@ on:
- ".github/workflows/ci.yml"
- "!.yamllint"
- "!.github/dependabot.yml"
- "!docker/**"
merge_group:
permissions:
@ -41,12 +42,12 @@ jobs:
run: echo key="${{ hashFiles('requirements.txt', 'requirements_optional.txt', 'requirements_test.txt') }}" >> $GITHUB_OUTPUT
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
id: python
uses: actions/setup-python@v5.3.0
uses: actions/setup-python@v5.5.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v4.2.0
uses: actions/cache@v4.2.3
with:
path: venv
# yamllint disable-line rule:line-length
@ -60,8 +61,8 @@ jobs:
pip install -r requirements.txt -r requirements_optional.txt -r requirements_test.txt
pip install -e .
black:
name: Check black
ruff:
name: Check ruff
runs-on: ubuntu-24.04
needs:
- common
@ -73,10 +74,10 @@ jobs:
with:
python-version: ${{ env.DEFAULT_PYTHON }}
cache-key: ${{ needs.common.outputs.cache-key }}
- name: Run black
- name: Run Ruff
run: |
. venv/bin/activate
black --verbose esphome tests
ruff format esphome tests
- name: Suggested changes
run: script/ci-suggest-changes
if: always()
@ -219,7 +220,7 @@ jobs:
. venv/bin/activate
pytest -vv --cov-report=xml --tb=native tests
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
uses: codecov/codecov-action@v5.4.2
with:
token: ${{ secrets.CODECOV_TOKEN }}
@ -254,7 +255,7 @@ jobs:
runs-on: ubuntu-24.04
needs:
- common
- black
- ruff
- ci-custom
- clang-format
- flake8
@ -302,14 +303,14 @@ jobs:
- name: Cache platformio
if: github.ref == 'refs/heads/dev'
uses: actions/cache@v4.2.0
uses: actions/cache@v4.2.3
with:
path: ~/.platformio
key: platformio-${{ matrix.pio_cache_key }}
- name: Cache platformio
if: github.ref != 'refs/heads/dev'
uses: actions/cache/restore@v4.2.0
uses: actions/cache/restore@v4.2.3
with:
path: ~/.platformio
key: platformio-${{ matrix.pio_cache_key }}
@ -481,7 +482,7 @@ jobs:
runs-on: ubuntu-24.04
needs:
- common
- black
- ruff
- ci-custom
- clang-format
- flake8

View File

@ -1,11 +1,11 @@
{
"problemMatcher": [
{
"owner": "black",
"owner": "ruff",
"severity": "error",
"pattern": [
{
"regexp": "^(.*): (Please format this file with the black formatter)",
"regexp": "^(.*): (Please format this file with the ruff formatter)",
"file": 1,
"message": 2
}

View File

@ -53,7 +53,7 @@ jobs:
steps:
- uses: actions/checkout@v4.1.7
- name: Set up Python
uses: actions/setup-python@v5.3.0
uses: actions/setup-python@v5.5.0
with:
python-version: "3.x"
- name: Set up python environment
@ -65,7 +65,7 @@ jobs:
pip3 install build
python3 -m build
- name: Publish
uses: pypa/gh-action-pypi-publish@v1.12.3
uses: pypa/gh-action-pypi-publish@v1.12.4
deploy-docker:
name: Build ESPHome ${{ matrix.platform }}
@ -80,28 +80,27 @@ jobs:
matrix:
platform:
- linux/amd64
- linux/arm/v7
- linux/arm64
steps:
- uses: actions/checkout@v4.1.7
- name: Set up Python
uses: actions/setup-python@v5.3.0
uses: actions/setup-python@v5.5.0
with:
python-version: "3.9"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.7.1
uses: docker/setup-buildx-action@v3.10.0
- name: Set up QEMU
if: matrix.platform != 'linux/amd64'
uses: docker/setup-qemu-action@v3.2.0
uses: docker/setup-qemu-action@v3.6.0
- name: Log in to docker hub
uses: docker/login-action@v3.3.0
uses: docker/login-action@v3.4.0
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Log in to the GitHub container registry
uses: docker/login-action@v3.3.0
uses: docker/login-action@v3.4.0
with:
registry: ghcr.io
username: ${{ github.actor }}
@ -141,7 +140,7 @@ jobs:
echo name=$(cat /tmp/platform) >> $GITHUB_OUTPUT
- name: Upload digests
uses: actions/upload-artifact@v4.4.3
uses: actions/upload-artifact@v4.6.2
with:
name: digests-${{ steps.sanitize.outputs.name }}
path: /tmp/digests
@ -177,24 +176,24 @@ jobs:
- uses: actions/checkout@v4.1.7
- name: Download digests
uses: actions/download-artifact@v4.1.8
uses: actions/download-artifact@v4.2.1
with:
pattern: digests-*
path: /tmp/digests
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.7.1
uses: docker/setup-buildx-action@v3.10.0
- name: Log in to docker hub
if: matrix.registry == 'dockerhub'
uses: docker/login-action@v3.3.0
uses: docker/login-action@v3.4.0
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Log in to the GitHub container registry
if: matrix.registry == 'ghcr'
uses: docker/login-action@v3.3.0
uses: docker/login-action@v3.4.0
with:
registry: ghcr.io
username: ${{ github.actor }}

View File

@ -17,7 +17,7 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v9.0.0
- uses: actions/stale@v9.1.0
with:
days-before-pr-stale: 90
days-before-pr-close: 7
@ -37,7 +37,7 @@ jobs:
close-issues:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v9.0.0
- uses: actions/stale@v9.1.0
with:
days-before-pr-stale: -1
days-before-pr-close: -1

View File

@ -22,7 +22,7 @@ jobs:
path: lib/home-assistant
- name: Setup Python
uses: actions/setup-python@v5.3.0
uses: actions/setup-python@v5.5.0
with:
python-version: 3.12
@ -36,11 +36,11 @@ jobs:
python ./script/sync-device_class.py
- name: Commit changes
uses: peter-evans/create-pull-request@v7.0.5
uses: peter-evans/create-pull-request@v7.0.8
with:
commit-message: "Synchronise Device Classes from Home Assistant"
committer: esphomebot <esphome@nabucasa.com>
author: esphomebot <esphome@nabucasa.com>
committer: esphomebot <esphome@openhomefoundation.org>
author: esphomebot <esphome@openhomefoundation.org>
branch: sync/device-classes
delete-branch: true
title: "Synchronise Device Classes from Home Assistant"

View File

@ -4,27 +4,19 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.5.4
rev: v0.11.0
hooks:
# Run the linter.
- id: ruff
args: [--fix]
# Run the formatter.
- id: ruff-format
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 24.4.2
hooks:
- id: black
args:
- --safe
- --quiet
files: ^((esphome|script|tests)/.+)?[^/]+\.py$
- repo: https://github.com/PyCQA/flake8
rev: 6.1.0
rev: 7.2.0
hooks:
- id: flake8
additional_dependencies:
- flake8-docstrings==1.5.0
- flake8-docstrings==1.7.0
- pydocstyle==5.1.1
files: ^(esphome|tests)/.+\.py$
- repo: https://github.com/pre-commit/pre-commit-hooks
@ -53,6 +45,6 @@ repos:
hooks:
- id: pylint
name: pylint
entry: script/run-in-env.sh pylint
language: script
entry: python3 script/run-in-env.py pylint
language: system
types: [python]

View File

@ -49,6 +49,7 @@ esphome/components/atc_mithermometer/* @ahpohl
esphome/components/atm90e26/* @danieltwagner
esphome/components/atm90e32/* @circuitsetup @descipher
esphome/components/audio/* @kahrendt
esphome/components/audio_adc/* @kbx81
esphome/components/audio_dac/* @kbx81
esphome/components/axs15231/* @clydebarrow
esphome/components/b_parasite/* @rbaron
@ -92,6 +93,7 @@ esphome/components/captive_portal/* @OttoWinter
esphome/components/ccs811/* @habbie
esphome/components/cd74hc4067/* @asoehlke
esphome/components/ch422g/* @clydebarrow @jesterret
esphome/components/chsc6x/* @kkosik20
esphome/components/climate/* @esphome/core
esphome/components/climate_ir/* @glmnet
esphome/components/color_temperature/* @jesserockz
@ -131,6 +133,9 @@ esphome/components/ens160_base/* @latonita @vincentscode
esphome/components/ens160_i2c/* @latonita
esphome/components/ens160_spi/* @latonita
esphome/components/ens210/* @itn3rd77
esphome/components/es7210/* @kahrendt
esphome/components/es7243e/* @kbx81
esphome/components/es8156/* @kbx81
esphome/components/es8311/* @kahrendt @kroimon
esphome/components/esp32/* @esphome/core
esphome/components/esp32_ble/* @Rapsssito @jesserockz
@ -144,6 +149,7 @@ esphome/components/esp32_rmt_led_strip/* @jesserockz
esphome/components/esp8266/* @esphome/core
esphome/components/ethernet_info/* @gtjadsonsantos
esphome/components/event/* @nohat
esphome/components/event_emitter/* @Rapsssito
esphome/components/exposure_notifications/* @OttoWinter
esphome/components/ezo/* @ssieb
esphome/components/ezo_pmp/* @carlos-sarmiento
@ -229,6 +235,7 @@ esphome/components/kuntze/* @ssieb
esphome/components/lcd_menu/* @numo68
esphome/components/ld2410/* @regevbr @sebcaps
esphome/components/ld2420/* @descipher
esphome/components/ld2450/* @hareeshmu
esphome/components/ledc/* @OttoWinter
esphome/components/libretiny/* @kuba2k2
esphome/components/libretiny_pwm/* @kuba2k2
@ -237,11 +244,13 @@ esphome/components/lightwaverf/* @max246
esphome/components/lilygo_t5_47/touchscreen/* @jesserockz
esphome/components/lock/* @esphome/core
esphome/components/logger/* @esphome/core
esphome/components/logger/select/* @clydebarrow
esphome/components/ltr390/* @latonita @sjtrny
esphome/components/ltr501/* @latonita
esphome/components/ltr_als_ps/* @latonita
esphome/components/lvgl/* @clydebarrow
esphome/components/m5stack_8angle/* @rnauber
esphome/components/mapping/* @clydebarrow
esphome/components/matrix_keypad/* @ssieb
esphome/components/max17043/* @blacknell
esphome/components/max31865/* @DAVe3283
@ -258,6 +267,7 @@ esphome/components/mcp23x17_base/* @jesserockz
esphome/components/mcp23xxx_base/* @jesserockz
esphome/components/mcp2515/* @danielschramm @mvturnho
esphome/components/mcp3204/* @rsumner
esphome/components/mcp4461/* @p1ngb4ck
esphome/components/mcp4728/* @berfenger
esphome/components/mcp47a1/* @jesserockz
esphome/components/mcp9600/* @mreditor97
@ -272,6 +282,7 @@ esphome/components/mics_4514/* @jesserockz
esphome/components/midea/* @dudanov
esphome/components/midea_ir/* @dudanov
esphome/components/mitsubishi/* @RubyBailey
esphome/components/mixer/speaker/* @kahrendt
esphome/components/mlx90393/* @functionpointer
esphome/components/mlx90614/* @jesserockz
esphome/components/mmc5603/* @benhoff
@ -290,6 +301,7 @@ esphome/components/mopeka_std_check/* @Fabian-Schmidt
esphome/components/mpl3115a2/* @kbickar
esphome/components/mpu6886/* @fabaff
esphome/components/ms8607/* @e28eta
esphome/components/msa3xx/* @latonita
esphome/components/nau7802/* @cujomalainey
esphome/components/network/* @esphome/core
esphome/components/nextion/* @edwardtfn @senexcrenshaw
@ -302,7 +314,7 @@ esphome/components/noblex/* @AGalfra
esphome/components/npi19/* @bakerkj
esphome/components/number/* @esphome/core
esphome/components/one_wire/* @ssieb
esphome/components/online_image/* @guillempages
esphome/components/online_image/* @clydebarrow @guillempages
esphome/components/opentherm/* @olegtarasov
esphome/components/ota/* @esphome/core
esphome/components/output/* @esphome/core
@ -313,6 +325,7 @@ esphome/components/pcf8563/* @KoenBreeman
esphome/components/pid/* @OttoWinter
esphome/components/pipsolar/* @andreashergert1984
esphome/components/pm1006/* @habbie
esphome/components/pm2005/* @andrewjswan
esphome/components/pmsa003i/* @sjtrny
esphome/components/pmwcs3/* @SeByDocKy
esphome/components/pn532/* @OttoWinter @jesserockz
@ -338,7 +351,7 @@ esphome/components/radon_eye_rd200/* @jeffeb3
esphome/components/rc522/* @glmnet
esphome/components/rc522_i2c/* @glmnet
esphome/components/rc522_spi/* @glmnet
esphome/components/resistance_sampler/* @jesserockz
esphome/components/resampler/speaker/* @kahrendt
esphome/components/restart/* @esphome/core
esphome/components/rf_bridge/* @jesserockz
esphome/components/rgbct/* @jesserockz
@ -351,7 +364,7 @@ esphome/components/rtttl/* @glmnet
esphome/components/safe_mode/* @jsuanet @kbx81 @paulmonigatti
esphome/components/scd4x/* @martgras @sjtrny
esphome/components/script/* @esphome/core
esphome/components/sdl/* @clydebarrow
esphome/components/sdl/* @bdm310 @clydebarrow
esphome/components/sdm_meter/* @jesserockz @polyfaces
esphome/components/sdp3x/* @Azimath
esphome/components/seeed_mr24hpc1/* @limengdu
@ -383,6 +396,7 @@ esphome/components/sn74hc165/* @jesserockz
esphome/components/socket/* @esphome/core
esphome/components/sonoff_d1/* @anatoly-savchenkov
esphome/components/speaker/* @jesserockz @kahrendt
esphome/components/speaker/media_player/* @kahrendt @synesthesiam
esphome/components/spi/* @clydebarrow @esphome/core
esphome/components/spi_device/* @clydebarrow
esphome/components/spi_led_strip/* @clydebarrow
@ -437,6 +451,7 @@ esphome/components/tmp102/* @timsavage
esphome/components/tmp1075/* @sybrenstuvel
esphome/components/tmp117/* @Azimath
esphome/components/tof10120/* @wstrzalka
esphome/components/tormatic/* @ti-mo
esphome/components/toshiba/* @kbx81
esphome/components/touchscreen/* @jesserockz @nielsnl68
esphome/components/tsl2591/* @wjcarpenter
@ -493,5 +508,6 @@ esphome/components/xiaomi_mhoc401/* @vevsvevs
esphome/components/xiaomi_rtcgq02lm/* @jesserockz
esphome/components/xl9535/* @mreditor97
esphome/components/xpt2046/touchscreen/* @nielsnl68 @numo68
esphome/components/xxtea/* @clydebarrow
esphome/components/zhlt01/* @cfeenstra1024
esphome/components/zio_ultrasonic/* @kahrendt

View File

@ -34,7 +34,7 @@ This Code of Conduct applies both within project spaces and in public spaces whe
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at esphome@nabucasa.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at esphome@openhomefoundation.org. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.

View File

@ -1,12 +1,14 @@
# Contributing to ESPHome
# Contributing to ESPHome [![Discord Chat](https://img.shields.io/discord/429907082951524364.svg)](https://discord.gg/KhAMKrd) [![GitHub release](https://img.shields.io/github/release/esphome/esphome.svg)](https://GitHub.com/esphome/esphome/releases/)
For a detailed guide, please see https://esphome.io/guides/contributing.html#contributing-to-esphome
We welcome contributions to the ESPHome suite of code and documentation!
Things to note when contributing:
Please read our [contributing guide](https://esphome.io/guides/contributing.html) if you wish to contribute to the
project and be sure to join us on [Discord](https://discord.gg/KhAMKrd).
- Please test your changes :)
- If a new feature is added or an existing user-facing feature is changed, you should also
update the [docs](https://github.com/esphome/esphome-docs). See [contributing to esphome-docs](https://esphome.io/guides/contributing.html#contributing-to-esphomedocs)
for more information.
- Please also update the tests in the `tests/` folder. You can do so by just adding a line in one of the YAML files
which checks if your new feature compiles correctly.
**See also:**
[Documentation](https://esphome.io) -- [Issues](https://github.com/esphome/issues/issues) -- [Feature requests](https://github.com/esphome/feature-requests/issues)
---
[![ESPHome - A project from the Open Home Foundation](https://www.openhomefoundation.org/badges/esphome.png)](https://www.openhomefoundation.org/)

View File

@ -1,11 +1,16 @@
# ESPHome [![Discord Chat](https://img.shields.io/discord/429907082951524364.svg)](https://discord.gg/KhAMKrd) [![GitHub release](https://img.shields.io/github/release/esphome/esphome.svg)](https://GitHub.com/esphome/esphome/releases/)
[![ESPHome Logo](https://esphome.io/_images/logo-text.png)](https://esphome.io/)
<a href="https://esphome.io/">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://esphome.io/_static/logo-text-on-dark.svg", alt="ESPHome Logo">
<img src="https://esphome.io/_static/logo-text-on-light.svg" alt="ESPHome Logo">
</picture>
</a>
**Documentation:** https://esphome.io/
---
For issues, please go to [the issue tracker](https://github.com/esphome/issues/issues).
[Documentation](https://esphome.io) -- [Issues](https://github.com/esphome/issues/issues) -- [Feature requests](https://github.com/esphome/feature-requests/issues)
For feature requests, please see [feature requests](https://github.com/esphome/feature-requests/issues).
---
[![ESPHome - A project from the Open Home Foundation](https://www.openhomefoundation.org/badges/esphome.png)](https://www.openhomefoundation.org/)

View File

@ -29,13 +29,13 @@ RUN \
# Use pinned versions so that we get updates with build caching
&& apt-get install -y --no-install-recommends \
python3-pip=23.0.1+dfsg-1 \
python3-setuptools=66.1.1-1 \
python3-setuptools=66.1.1-1+deb12u1 \
python3-venv=3.11.2-1+b1 \
python3-wheel=0.38.4-2 \
iputils-ping=3:20221126-1+deb12u1 \
git=1:2.39.5-0+deb12u1 \
curl=7.88.1-10+deb12u8 \
openssh-client=1:9.2p1-2+deb12u3 \
git=1:2.39.5-0+deb12u2 \
curl=7.88.1-10+deb12u12 \
openssh-client=1:9.2p1-2+deb12u5 \
python3-cffi=1.15.1-5 \
libcairo2=1.16.0-7 \
libmagic1=1:5.44-3 \
@ -51,23 +51,11 @@ ENV \
# Store globally installed pio libs in /piolibs
PLATFORMIO_GLOBALLIB_DIR=/piolibs
# Support legacy binaries on Debian multiarch system. There is no "correct" way
# to do this, other than using properly built toolchains...
# See: https://unix.stackexchange.com/questions/553743/correct-way-to-add-lib-ld-linux-so-3-in-debian
RUN \
if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
ln -s /lib/arm-linux-gnueabihf/ld-linux-armhf.so.3 /lib/ld-linux.so.3; \
fi
RUN \
# Ubuntu python3-pip is missing wheel
if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
export PIP_EXTRA_INDEX_URL="https://www.piwheels.org/simple"; \
fi; \
pip3 install \
--break-system-packages --no-cache-dir \
# Keep platformio version in sync with requirements.txt
platformio==6.1.16 \
platformio==6.1.18 \
# Change some platformio settings
&& platformio settings set enable_telemetry No \
&& platformio settings set check_platformio_interval 1000000 \
@ -82,21 +70,13 @@ RUN --mount=type=tmpfs,target=/root/.cargo <<END-OF-RUN
# Fail on any non-zero status
set -e
if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]
then
curl -L https://www.piwheels.org/cp311/cryptography-43.0.0-cp37-abi3-linux_armv7l.whl -o /tmp/cryptography-43.0.0-cp37-abi3-linux_armv7l.whl
pip3 install --break-system-packages --no-cache-dir /tmp/cryptography-43.0.0-cp37-abi3-linux_armv7l.whl
rm /tmp/cryptography-43.0.0-cp37-abi3-linux_armv7l.whl
export PIP_EXTRA_INDEX_URL="https://www.piwheels.org/simple";
fi
# install build tools in case wheels are not available
BUILD_DEPS="
build-essential=12.9
python3-dev=3.11.2-1+b1
zlib1g-dev=1:1.2.13.dfsg-1
libjpeg-dev=1:2.1.5-2
libfreetype-dev=2.12.1+dfsg-5+deb12u3
libfreetype-dev=2.12.1+dfsg-5+deb12u4
libssl-dev=3.0.15-1~deb12u1
libffi-dev=3.4.4-1
cargo=0.66.0+ds1-1
@ -104,9 +84,9 @@ BUILD_DEPS="
"
LIB_DEPS="
libtiff6=4.5.0-6+deb12u1
libopenjp2-7=2.5.0-2
libopenjp2-7=2.5.0-2+deb12u1
"
if [ "$TARGETARCH$TARGETVARIANT" = "arm64" ] || [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]
if [ "$TARGETARCH$TARGETVARIANT" = "arm64" ]
then
apt-get update
apt-get install -y --no-install-recommends $BUILD_DEPS $LIB_DEPS
@ -115,7 +95,7 @@ fi
CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse CARGO_HOME=/root/.cargo
pip3 install --break-system-packages --no-cache-dir -r /requirements.txt -r /requirements_optional.txt
if [ "$TARGETARCH$TARGETVARIANT" = "arm64" ] || [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]
if [ "$TARGETARCH$TARGETVARIANT" = "arm64" ]
then
apt-get remove -y --purge --auto-remove $BUILD_DEPS
rm -rf /tmp/* /var/{cache,log}/* /var/lib/apt/lists/*
@ -135,11 +115,7 @@ FROM base AS docker
# Copy esphome and install
COPY . /esphome
RUN if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
export PIP_EXTRA_INDEX_URL="https://www.piwheels.org/simple"; \
fi; \
pip3 install \
--break-system-packages --no-cache-dir -e /esphome
RUN pip3 install --break-system-packages --no-cache-dir -e /esphome
# Settings for dashboard
ENV USERNAME="" PASSWORD=""
@ -184,7 +160,7 @@ RUN \
apt-get update \
# Use pinned versions so that we get updates with build caching
&& apt-get install -y --no-install-recommends \
nginx-light=1.22.1-9 \
nginx-light=1.22.1-9+deb12u1 \
&& rm -rf \
/tmp/* \
/var/{cache,log}/* \
@ -197,11 +173,7 @@ COPY docker/ha-addon-rootfs/ /
# Copy esphome and install
COPY . /esphome
RUN if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
export PIP_EXTRA_INDEX_URL="https://www.piwheels.org/simple"; \
fi; \
pip3 install \
--break-system-packages --no-cache-dir -e /esphome
RUN pip3 install --break-system-packages --no-cache-dir -e /esphome
# Labels
LABEL \
@ -232,21 +204,14 @@ RUN \
nano=7.2-1+deb12u1 \
build-essential=12.9 \
python3-dev=3.11.2-1+b1 \
&& if [ "$TARGETARCH$TARGETVARIANT" != "armv7" ]; then \
# move this up after armv7 is retired
apt-get install -y --no-install-recommends clang-tidy-18=1:18.1.8~++20240731024826+3b5b5c1ec4a3-1~exp1~20240731144843.145 ; \
fi; \
rm -rf \
clang-tidy-18=1:18.1.8~++20240731024826+3b5b5c1ec4a3-1~exp1~20240731144843.145 \
&& rm -rf \
/tmp/* \
/var/{cache,log}/* \
/var/lib/apt/lists/*
COPY requirements_test.txt /
RUN if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
export PIP_EXTRA_INDEX_URL="https://www.piwheels.org/simple"; \
fi; \
pip3 install \
--break-system-packages --no-cache-dir -r /requirements_test.txt
RUN pip3 install --break-system-packages --no-cache-dir -r /requirements_test.txt
VOLUME ["/esphome"]
WORKDIR /esphome

View File

@ -1,22 +1,19 @@
#!/usr/bin/env python3
from dataclasses import dataclass
import subprocess
import argparse
from platform import machine
import shlex
from dataclasses import dataclass
import re
import shlex
import subprocess
import sys
CHANNEL_DEV = "dev"
CHANNEL_BETA = "beta"
CHANNEL_RELEASE = "release"
CHANNELS = [CHANNEL_DEV, CHANNEL_BETA, CHANNEL_RELEASE]
ARCH_AMD64 = "amd64"
ARCH_ARMV7 = "armv7"
ARCH_AARCH64 = "aarch64"
ARCHS = [ARCH_AMD64, ARCH_ARMV7, ARCH_AARCH64]
ARCHS = [ARCH_AMD64, ARCH_AARCH64]
TYPE_DOCKER = "docker"
TYPE_HA_ADDON = "ha-addon"
@ -76,7 +73,6 @@ class DockerParams:
}[build_type]
platform = {
ARCH_AMD64: "linux/amd64",
ARCH_ARMV7: "linux/arm/v7",
ARCH_AARCH64: "linux/arm64",
}[arch]
target = {

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python3
import re
import argparse
import re
CHANNEL_DEV = "dev"
CHANNEL_BETA = "beta"

View File

@ -23,10 +23,6 @@ if bashio::config.true 'streamer_mode'; then
export ESPHOME_STREAMER_MODE=true
fi
if bashio::config.true 'status_use_ping'; then
export ESPHOME_DASHBOARD_USE_PING=true
fi
if bashio::config.has_value 'relative_url'; then
export ESPHOME_DASHBOARD_RELATIVE_URL=$(bashio::config 'relative_url')
fi

View File

@ -2,6 +2,7 @@
import argparse
from datetime import datetime
import functools
import importlib
import logging
import os
import re
@ -66,7 +67,7 @@ def choose_prompt(options, purpose: str = None):
return options[0][1]
safe_print(
f'Found multiple options{f" for {purpose}" if purpose else ""}, please choose one:'
f"Found multiple options{f' for {purpose}' if purpose else ''}, please choose one:"
)
for i, (desc, _) in enumerate(options):
safe_print(f" [{i + 1}] {desc}")
@ -132,7 +133,7 @@ def get_port_type(port):
return "NETWORK"
def run_miniterm(config, port):
def run_miniterm(config, port, args):
import serial
from esphome import platformio_api
@ -153,7 +154,7 @@ def run_miniterm(config, port):
# We can't set to False by default since it leads to toggling and hence
# ESP32 resets on some platforms.
if config["logger"][CONF_DEASSERT_RTS_DTR]:
if config["logger"][CONF_DEASSERT_RTS_DTR] or args.reset:
ser.dtr = False
ser.rts = False
@ -243,11 +244,11 @@ def compile_program(args, config):
return 0 if idedata is not None else 1
def upload_using_esptool(config, port, file):
def upload_using_esptool(config, port, file, speed):
from esphome import platformio_api
first_baudrate = config[CONF_ESPHOME][CONF_PLATFORMIO_OPTIONS].get(
"upload_speed", 460800
first_baudrate = speed or config[CONF_ESPHOME][CONF_PLATFORMIO_OPTIONS].get(
"upload_speed", os.getenv("ESPHOME_UPLOAD_SPEED", "460800")
)
if file is not None:
@ -336,11 +337,18 @@ def check_permissions(port):
def upload_program(config, args, host):
try:
module = importlib.import_module("esphome.components." + CORE.target_platform)
if getattr(module, "upload_program")(config, args, host):
return 0
except AttributeError:
pass
if get_port_type(host) == "SERIAL":
check_permissions(host)
if CORE.target_platform in (PLATFORM_ESP32, PLATFORM_ESP8266):
file = getattr(args, "file", None)
return upload_using_esptool(config, host, file)
return upload_using_esptool(config, host, file, args.upload_speed)
if CORE.target_platform in (PLATFORM_RP2040):
return upload_using_platformio(config, args.device)
@ -367,10 +375,12 @@ def upload_program(config, args, host):
password = ota_conf.get(CONF_PASSWORD, "")
if (
not is_ip_address(CORE.address) # pylint: disable=too-many-boolean-expressions
and (get_port_type(host) == "MQTT" or config[CONF_MDNS][CONF_DISABLED])
and CONF_MQTT in config
CONF_MQTT in config # pylint: disable=too-many-boolean-expressions
and (not args.device or args.device in ("MQTT", "OTA"))
and (
((config[CONF_MDNS][CONF_DISABLED]) and not is_ip_address(CORE.address))
or get_port_type(host) == "MQTT"
)
):
from esphome import mqtt
@ -389,7 +399,7 @@ def show_logs(config, args, port):
raise EsphomeError("Logger is not configured!")
if get_port_type(port) == "SERIAL":
check_permissions(port)
return run_miniterm(config, port)
return run_miniterm(config, port, args)
if get_port_type(port) == "NETWORK" and "api" in config:
if config[CONF_MDNS][CONF_DISABLED] and CONF_MQTT in config:
from esphome import mqtt
@ -758,6 +768,14 @@ def parse_args(argv):
options_parser.add_argument(
"-q", "--quiet", help="Disable all ESPHome logs.", action="store_true"
)
options_parser.add_argument(
"-l",
"--log-level",
help="Set the log level.",
default=os.getenv("ESPHOME_LOG_LEVEL", "INFO"),
action="store",
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
)
options_parser.add_argument(
"--dashboard", help=argparse.SUPPRESS, action="store_true"
)
@ -826,6 +844,10 @@ def parse_args(argv):
"--device",
help="Manually specify the serial port/address to use, for example /dev/ttyUSB0.",
)
parser_upload.add_argument(
"--upload_speed",
help="Override the default or configured upload speed.",
)
parser_upload.add_argument(
"--file",
help="Manually specify the binary file to upload.",
@ -844,6 +866,13 @@ def parse_args(argv):
"--device",
help="Manually specify the serial port/address to use, for example /dev/ttyUSB0.",
)
parser_logs.add_argument(
"--reset",
"-r",
action="store_true",
help="Reset the device before starting serial logs.",
default=os.getenv("ESPHOME_SERIAL_LOGGING_RESET"),
)
parser_discover = subparsers.add_parser(
"discover",
@ -866,9 +895,20 @@ def parse_args(argv):
"--device",
help="Manually specify the serial port/address to use, for example /dev/ttyUSB0.",
)
parser_run.add_argument(
"--upload_speed",
help="Override the default or configured upload speed.",
)
parser_run.add_argument(
"--no-logs", help="Disable starting logs.", action="store_true"
)
parser_run.add_argument(
"--reset",
"-r",
action="store_true",
help="Reset the device before starting serial logs.",
default=os.getenv("ESPHOME_SERIAL_LOGGING_RESET"),
)
parser_clean = subparsers.add_parser(
"clean-mqtt",
@ -987,11 +1027,16 @@ def run_esphome(argv):
args = parse_args(argv)
CORE.dashboard = args.dashboard
# Override log level if verbose is set
if args.verbose:
args.log_level = "DEBUG"
elif args.quiet:
args.log_level = "CRITICAL"
setup_log(
args.verbose,
args.quiet,
log_level=args.log_level,
# Show timestamp for dashboard access logs
args.command == "dashboard",
include_timestamp=args.command == "dashboard",
)
if args.command in PRE_CONFIG_ACTIONS:

View File

@ -1,10 +1,10 @@
import esphome.codegen as cg
from esphome.components import sensor, uart
from esphome.const import (
DEVICE_CLASS_DISTANCE,
ICON_ARROW_EXPAND_VERTICAL,
STATE_CLASS_MEASUREMENT,
UNIT_METER,
ICON_ARROW_EXPAND_VERTICAL,
DEVICE_CLASS_DISTANCE,
)
CODEOWNERS = ["@MrSuicideParrot"]

View File

@ -1,9 +1,9 @@
import esphome.codegen as cg
from esphome.components import sensor, uart
from esphome.const import (
STATE_CLASS_MEASUREMENT,
ICON_ARROW_EXPAND_VERTICAL,
DEVICE_CLASS_DISTANCE,
ICON_ARROW_EXPAND_VERTICAL,
STATE_CLASS_MEASUREMENT,
UNIT_MILLIMETER,
)

View File

@ -1,10 +1,9 @@
from esphome import pins
import esphome.codegen as cg
from esphome.components import stepper
import esphome.config_validation as cv
import esphome.codegen as cg
from esphome.const import CONF_DIR_PIN, CONF_ID, CONF_SLEEP_PIN, CONF_STEP_PIN
a4988_ns = cg.esphome_ns.namespace("a4988")
A4988 = a4988_ns.class_("A4988", stepper.Stepper, cg.Component)

View File

@ -1,12 +1,12 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_EQUATION,
CONF_HUMIDITY,
CONF_TEMPERATURE,
STATE_CLASS_MEASUREMENT,
CONF_EQUATION,
ICON_WATER,
STATE_CLASS_MEASUREMENT,
UNIT_GRAMS_PER_CUBIC_METER,
)

View File

@ -1,8 +1,8 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import pins
import esphome.codegen as cg
from esphome.components import output
from esphome.const import CONF_ID, CONF_MIN_POWER, CONF_METHOD
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_METHOD, CONF_MIN_POWER
CODEOWNERS = ["@glmnet"]

View File

@ -1,8 +1,8 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import uart
from esphome.components.light.types import AddressableLightEffect
from esphome.components.light.effects import register_addressable_effect
from esphome.components.light.types import AddressableLightEffect
import esphome.config_validation as cv
from esphome.const import CONF_NAME, CONF_UART_ID
DEPENDENCIES = ["uart"]

View File

@ -1,11 +1,6 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import pins
from esphome.const import CONF_ANALOG, CONF_INPUT, CONF_NUMBER
from esphome.core import CORE
import esphome.codegen as cg
from esphome.components.esp32 import get_esp32_variant
from esphome.const import PLATFORM_ESP8266
from esphome.components.esp32.const import (
VARIANT_ESP32,
VARIANT_ESP32C2,
@ -15,6 +10,9 @@ from esphome.components.esp32.const import (
VARIANT_ESP32S2,
VARIANT_ESP32S3,
)
import esphome.config_validation as cv
from esphome.const import CONF_ANALOG, CONF_INPUT, CONF_NUMBER, PLATFORM_ESP8266
from esphome.core import CORE
CODEOWNERS = ["@esphome/core"]
@ -38,6 +36,14 @@ ATTENUATION_MODES = {
"auto": "auto",
}
sampling_mode = adc_ns.enum("SamplingMode", is_class=True)
SAMPLING_MODES = {
"avg": sampling_mode.AVG,
"min": sampling_mode.MIN,
"max": sampling_mode.MAX,
}
adc1_channel_t = cg.global_ns.enum("adc1_channel_t")
adc2_channel_t = cg.global_ns.enum("adc2_channel_t")
@ -102,11 +108,11 @@ ESP32_VARIANT_ADC1_PIN_TO_CHANNEL = {
6: adc1_channel_t.ADC1_CHANNEL_6,
},
VARIANT_ESP32H2: {
0: adc1_channel_t.ADC1_CHANNEL_0,
1: adc1_channel_t.ADC1_CHANNEL_1,
2: adc1_channel_t.ADC1_CHANNEL_2,
3: adc1_channel_t.ADC1_CHANNEL_3,
4: adc1_channel_t.ADC1_CHANNEL_4,
1: adc1_channel_t.ADC1_CHANNEL_0,
2: adc1_channel_t.ADC1_CHANNEL_1,
3: adc1_channel_t.ADC1_CHANNEL_2,
4: adc1_channel_t.ADC1_CHANNEL_3,
5: adc1_channel_t.ADC1_CHANNEL_4,
},
}

View File

@ -28,6 +28,21 @@ static const adc_atten_t ADC_ATTEN_DB_12_COMPAT = ADC_ATTEN_DB_11;
#endif
#endif // USE_ESP32
enum class SamplingMode : uint8_t { AVG = 0, MIN = 1, MAX = 2 };
const LogString *sampling_mode_to_str(SamplingMode mode);
class Aggregator {
public:
void add_sample(uint32_t value);
uint32_t aggregate();
Aggregator(SamplingMode mode);
protected:
SamplingMode mode_{SamplingMode::AVG};
uint32_t aggr_{0};
uint32_t samples_{0};
};
class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage_sampler::VoltageSampler {
public:
#ifdef USE_ESP32
@ -54,6 +69,7 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage
void set_pin(InternalGPIOPin *pin) { this->pin_ = pin; }
void set_output_raw(bool output_raw) { this->output_raw_ = output_raw; }
void set_sample_count(uint8_t sample_count);
void set_sampling_mode(SamplingMode sampling_mode);
float sample() override;
#ifdef USE_ESP8266
@ -68,6 +84,7 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage
InternalGPIOPin *pin_;
bool output_raw_{false};
uint8_t sample_count_{1};
SamplingMode sampling_mode_{SamplingMode::AVG};
#ifdef USE_RP2040
bool is_temperature_{false};

View File

@ -6,6 +6,59 @@ namespace adc {
static const char *const TAG = "adc.common";
const LogString *sampling_mode_to_str(SamplingMode mode) {
switch (mode) {
case SamplingMode::AVG:
return LOG_STR("average");
case SamplingMode::MIN:
return LOG_STR("minimum");
case SamplingMode::MAX:
return LOG_STR("maximum");
}
return LOG_STR("unknown");
}
Aggregator::Aggregator(SamplingMode mode) {
this->mode_ = mode;
// set to max uint if mode is "min"
if (mode == SamplingMode::MIN) {
this->aggr_ = UINT32_MAX;
}
}
void Aggregator::add_sample(uint32_t value) {
this->samples_ += 1;
switch (this->mode_) {
case SamplingMode::AVG:
this->aggr_ += value;
break;
case SamplingMode::MIN:
if (value < this->aggr_) {
this->aggr_ = value;
}
break;
case SamplingMode::MAX:
if (value > this->aggr_) {
this->aggr_ = value;
}
}
}
uint32_t Aggregator::aggregate() {
if (this->mode_ == SamplingMode::AVG) {
if (this->samples_ == 0) {
return this->aggr_;
}
return (this->aggr_ + (this->samples_ >> 1)) / this->samples_; // NOLINT(clang-analyzer-core.DivideZero)
}
return this->aggr_;
}
void ADCSensor::update() {
float value_v = this->sample();
ESP_LOGV(TAG, "'%s': Got voltage=%.4fV", this->get_name().c_str(), value_v);
@ -18,6 +71,8 @@ void ADCSensor::set_sample_count(uint8_t sample_count) {
}
}
void ADCSensor::set_sampling_mode(SamplingMode sampling_mode) { this->sampling_mode_ = sampling_mode; }
float ADCSensor::get_setup_priority() const { return setup_priority::DATA; }
} // namespace adc

View File

@ -78,12 +78,14 @@ void ADCSensor::dump_config() {
}
}
ESP_LOGCONFIG(TAG, " Samples: %i", this->sample_count_);
ESP_LOGCONFIG(TAG, " Sampling mode: %s", LOG_STR_ARG(sampling_mode_to_str(this->sampling_mode_)));
LOG_UPDATE_INTERVAL(this);
}
float ADCSensor::sample() {
if (!this->autorange_) {
uint32_t sum = 0;
auto aggr = Aggregator(this->sampling_mode_);
for (uint8_t sample = 0; sample < this->sample_count_; sample++) {
int raw = -1;
if (this->channel1_ != ADC1_CHANNEL_MAX) {
@ -94,13 +96,14 @@ float ADCSensor::sample() {
if (raw == -1) {
return NAN;
}
sum += raw;
aggr.add_sample(raw);
}
sum = (sum + (this->sample_count_ >> 1)) / this->sample_count_; // NOLINT(clang-analyzer-core.DivideZero)
if (this->output_raw_) {
return sum;
return aggr.aggregate();
}
uint32_t mv = esp_adc_cal_raw_to_voltage(sum, &this->cal_characteristics_[(int32_t) this->attenuation_]);
uint32_t mv =
esp_adc_cal_raw_to_voltage(aggr.aggregate(), &this->cal_characteristics_[(int32_t) this->attenuation_]);
return mv / 1000.0f;
}

View File

@ -31,23 +31,27 @@ void ADCSensor::dump_config() {
LOG_PIN(" Pin: ", this->pin_);
#endif // USE_ADC_SENSOR_VCC
ESP_LOGCONFIG(TAG, " Samples: %i", this->sample_count_);
ESP_LOGCONFIG(TAG, " Sampling mode: %s", LOG_STR_ARG(sampling_mode_to_str(this->sampling_mode_)));
LOG_UPDATE_INTERVAL(this);
}
float ADCSensor::sample() {
uint32_t raw = 0;
auto aggr = Aggregator(this->sampling_mode_);
for (uint8_t sample = 0; sample < this->sample_count_; sample++) {
uint32_t raw = 0;
#ifdef USE_ADC_SENSOR_VCC
raw += ESP.getVcc(); // NOLINT(readability-static-accessed-through-instance)
raw = ESP.getVcc(); // NOLINT(readability-static-accessed-through-instance)
#else
raw += analogRead(this->pin_->get_pin()); // NOLINT
raw = analogRead(this->pin_->get_pin()); // NOLINT
#endif // USE_ADC_SENSOR_VCC
aggr.add_sample(raw);
}
raw = (raw + (this->sample_count_ >> 1)) / this->sample_count_; // NOLINT(clang-analyzer-core.DivideZero)
if (this->output_raw_) {
return raw;
return aggr.aggregate();
}
return raw / 1024.0f;
return aggr.aggregate() / 1024.0f;
}
std::string ADCSensor::unique_id() { return get_mac_address() + "-adc"; }

View File

@ -23,23 +23,28 @@ void ADCSensor::dump_config() {
LOG_PIN(" Pin: ", this->pin_);
#endif // USE_ADC_SENSOR_VCC
ESP_LOGCONFIG(TAG, " Samples: %i", this->sample_count_);
ESP_LOGCONFIG(TAG, " Sampling mode: %s", LOG_STR_ARG(sampling_mode_to_str(this->sampling_mode_)));
LOG_UPDATE_INTERVAL(this);
}
float ADCSensor::sample() {
uint32_t raw = 0;
auto aggr = Aggregator(this->sampling_mode_);
if (this->output_raw_) {
for (uint8_t sample = 0; sample < this->sample_count_; sample++) {
raw += analogRead(this->pin_->get_pin()); // NOLINT
raw = analogRead(this->pin_->get_pin()); // NOLINT
aggr.add_sample(raw);
}
raw = (raw + (this->sample_count_ >> 1)) / this->sample_count_; // NOLINT(clang-analyzer-core.DivideZero)
return raw;
return aggr.aggregate();
}
for (uint8_t sample = 0; sample < this->sample_count_; sample++) {
raw += analogReadVoltage(this->pin_->get_pin()); // NOLINT
raw = analogReadVoltage(this->pin_->get_pin()); // NOLINT
aggr.add_sample(raw);
}
raw = (raw + (this->sample_count_ >> 1)) / this->sample_count_; // NOLINT(clang-analyzer-core.DivideZero)
return raw / 1000.0f;
return aggr.aggregate() / 1000.0f;
}
} // namespace adc

View File

@ -34,24 +34,28 @@ void ADCSensor::dump_config() {
#endif // USE_ADC_SENSOR_VCC
}
ESP_LOGCONFIG(TAG, " Samples: %i", this->sample_count_);
ESP_LOGCONFIG(TAG, " Sampling mode: %s", LOG_STR_ARG(sampling_mode_to_str(this->sampling_mode_)));
LOG_UPDATE_INTERVAL(this);
}
float ADCSensor::sample() {
uint32_t raw = 0;
auto aggr = Aggregator(this->sampling_mode_);
if (this->is_temperature_) {
adc_set_temp_sensor_enabled(true);
delay(1);
adc_select_input(4);
uint32_t raw = 0;
for (uint8_t sample = 0; sample < this->sample_count_; sample++) {
raw += adc_read();
raw = adc_read();
aggr.add_sample(raw);
}
raw = (raw + (this->sample_count_ >> 1)) / this->sample_count_; // NOLINT(clang-analyzer-core.DivideZero)
adc_set_temp_sensor_enabled(false);
if (this->output_raw_) {
return raw;
return aggr.aggregate();
}
return raw * 3.3f / 4096.0f;
return aggr.aggregate() * 3.3f / 4096.0f;
}
uint8_t pin = this->pin_->get_pin();
@ -68,11 +72,10 @@ float ADCSensor::sample() {
adc_gpio_init(pin);
adc_select_input(pin - 26);
uint32_t raw = 0;
for (uint8_t sample = 0; sample < this->sample_count_; sample++) {
raw += adc_read();
raw = adc_read();
aggr.add_sample(raw);
}
raw = (raw + (this->sample_count_ >> 1)) / this->sample_count_; // NOLINT(clang-analyzer-core.DivideZero)
#ifdef CYW43_USES_VSYS_PIN
if (pin == PICO_VSYS_PIN) {
@ -81,10 +84,10 @@ float ADCSensor::sample() {
#endif // CYW43_USES_VSYS_PIN
if (this->output_raw_) {
return raw;
return aggr.aggregate();
}
float coeff = pin == PICO_VSYS_PIN ? 3.0f : 1.0f;
return raw * 3.3f / 4096.0f * coeff;
return aggr.aggregate() * 3.3f / 4096.0f * coeff;
}
} // namespace adc

View File

@ -1,11 +1,9 @@
import logging
import esphome.codegen as cg
import esphome.config_validation as cv
import esphome.final_validate as fv
from esphome.core import CORE
from esphome.components import sensor, voltage_sampler
from esphome.components.esp32 import get_esp32_variant
import esphome.config_validation as cv
from esphome.const import (
CONF_ATTENUATION,
CONF_ID,
@ -17,10 +15,14 @@ from esphome.const import (
STATE_CLASS_MEASUREMENT,
UNIT_VOLT,
)
from esphome.core import CORE
import esphome.final_validate as fv
from . import (
ATTENUATION_MODES,
ESP32_VARIANT_ADC1_PIN_TO_CHANNEL,
ESP32_VARIANT_ADC2_PIN_TO_CHANNEL,
SAMPLING_MODES,
adc_ns,
validate_adc_pin,
)
@ -30,9 +32,11 @@ _LOGGER = logging.getLogger(__name__)
AUTO_LOAD = ["voltage_sampler"]
CONF_SAMPLES = "samples"
CONF_SAMPLING_MODE = "sampling_mode"
_attenuation = cv.enum(ATTENUATION_MODES, lower=True)
_sampling_mode = cv.enum(SAMPLING_MODES, lower=True)
def validate_config(config):
@ -88,6 +92,7 @@ CONFIG_SCHEMA = cv.All(
cv.only_on_esp32, _attenuation
),
cv.Optional(CONF_SAMPLES, default=1): cv.int_range(min=1, max=255),
cv.Optional(CONF_SAMPLING_MODE, default="avg"): _sampling_mode,
}
)
.extend(cv.polling_component_schema("60s")),
@ -112,6 +117,7 @@ async def to_code(config):
cg.add(var.set_output_raw(config[CONF_RAW]))
cg.add(var.set_sample_count(config[CONF_SAMPLES]))
cg.add(var.set_sampling_mode(config[CONF_SAMPLING_MODE]))
if attenuation := config.get(CONF_ATTENUATION):
if attenuation == "auto":

View File

@ -1,6 +1,6 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import spi
import esphome.config_validation as cv
from esphome.const import CONF_ID
DEPENDENCIES = ["spi"]

View File

@ -1,9 +1,9 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor, voltage_sampler
from esphome.const import CONF_ID, CONF_CHANNEL
import esphome.config_validation as cv
from esphome.const import CONF_CHANNEL, CONF_ID
from .. import adc128s102_ns, ADC128S102
from .. import ADC128S102, adc128s102_ns
AUTO_LOAD = ["voltage_sampler"]
DEPENDENCIES = ["adc128s102"]

View File

@ -1,15 +1,15 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import display, light
import esphome.config_validation as cv
from esphome.const import (
CONF_ADDRESSABLE_LIGHT_ID,
CONF_HEIGHT,
CONF_ID,
CONF_LAMBDA,
CONF_PAGES,
CONF_ADDRESSABLE_LIGHT_ID,
CONF_HEIGHT,
CONF_WIDTH,
CONF_UPDATE_INTERVAL,
CONF_PIXEL_MAPPER,
CONF_UPDATE_INTERVAL,
CONF_WIDTH,
)
CODEOWNERS = ["@justfalter"]

View File

@ -1,7 +1,7 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor, i2c
from esphome import pins
import esphome.codegen as cg
from esphome.components import i2c, sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_ACTIVE_POWER,
CONF_APPARENT_POWER,

View File

@ -1,27 +1,27 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor
from esphome import pins
import esphome.codegen as cg
from esphome.components import sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_FREQUENCY,
CONF_IRQ_PIN,
CONF_VOLTAGE,
CONF_FREQUENCY,
CONF_VOLTAGE_GAIN,
DEVICE_CLASS_CURRENT,
DEVICE_CLASS_APPARENT_POWER,
DEVICE_CLASS_POWER,
DEVICE_CLASS_REACTIVE_POWER,
DEVICE_CLASS_POWER_FACTOR,
DEVICE_CLASS_VOLTAGE,
DEVICE_CLASS_CURRENT,
DEVICE_CLASS_FREQUENCY,
DEVICE_CLASS_POWER,
DEVICE_CLASS_POWER_FACTOR,
DEVICE_CLASS_REACTIVE_POWER,
DEVICE_CLASS_VOLTAGE,
STATE_CLASS_MEASUREMENT,
UNIT_VOLT,
UNIT_HERTZ,
UNIT_AMPERE,
UNIT_VOLT_AMPS,
UNIT_WATT,
UNIT_VOLT_AMPS_REACTIVE,
UNIT_HERTZ,
UNIT_PERCENT,
UNIT_VOLT,
UNIT_VOLT_AMPS,
UNIT_VOLT_AMPS_REACTIVE,
UNIT_WATT,
)
CONF_CURRENT_A = "current_a"

View File

@ -1,9 +1,8 @@
import esphome.codegen as cg
from esphome.components import ade7953_base, i2c
import esphome.config_validation as cv
from esphome.components import i2c, ade7953_base
from esphome.const import CONF_ID
DEPENDENCIES = ["i2c"]
AUTO_LOAD = ["ade7953_base"]

View File

@ -1,9 +1,8 @@
import esphome.codegen as cg
from esphome.components import ade7953_base, spi
import esphome.config_validation as cv
from esphome.components import spi, ade7953_base
from esphome.const import CONF_ID
DEPENDENCIES = ["spi"]
AUTO_LOAD = ["ade7953_base"]

View File

@ -1,6 +1,6 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import i2c
import esphome.config_validation as cv
from esphome.const import CONF_ID
DEPENDENCIES = ["i2c"]

View File

@ -9,8 +9,6 @@ static const char *const TAG = "ads1115";
static const uint8_t ADS1115_REGISTER_CONVERSION = 0x00;
static const uint8_t ADS1115_REGISTER_CONFIG = 0x01;
static const uint8_t ADS1115_DATA_RATE_860_SPS = 0b111; // 3300_SPS for ADS1015
void ADS1115Component::setup() {
ESP_LOGCONFIG(TAG, "Setting up ADS1115...");
uint16_t value;
@ -43,9 +41,9 @@ void ADS1115Component::setup() {
config |= 0b0000000100000000;
}
// Set data rate - 860 samples per second (we're in singleshot mode)
// Set data rate - 860 samples per second
// 0bxxxxxxxx100xxxxx
config |= ADS1115_DATA_RATE_860_SPS << 5;
config |= ADS1115_860SPS << 5;
// Set comparator mode - hysteresis
// 0bxxxxxxxxxxx0xxxx
@ -77,7 +75,7 @@ void ADS1115Component::dump_config() {
}
}
float ADS1115Component::request_measurement(ADS1115Multiplexer multiplexer, ADS1115Gain gain,
ADS1115Resolution resolution) {
ADS1115Resolution resolution, ADS1115Samplerate samplerate) {
uint16_t config = this->prev_config_;
// Multiplexer
// 0bxBBBxxxxxxxxxxxx
@ -89,6 +87,11 @@ float ADS1115Component::request_measurement(ADS1115Multiplexer multiplexer, ADS1
config &= 0b1111000111111111;
config |= (gain & 0b111) << 9;
// Sample rate
// 0bxxxxxxxxBBBxxxxx
config &= 0b1111111100011111;
config |= (samplerate & 0b111) << 5;
if (!this->continuous_mode_) {
// Start conversion
config |= 0b1000000000000000;
@ -101,8 +104,54 @@ float ADS1115Component::request_measurement(ADS1115Multiplexer multiplexer, ADS1
}
this->prev_config_ = config;
// about 1.2 ms with 860 samples per second
delay(2);
// Delay calculated as: ceil((1000/SPS)+.5)
if (resolution == ADS1015_12_BITS) {
switch (samplerate) {
case ADS1115_8SPS:
delay(9);
break;
case ADS1115_16SPS:
delay(5);
break;
case ADS1115_32SPS:
delay(3);
break;
case ADS1115_64SPS:
case ADS1115_128SPS:
delay(2);
break;
default:
delay(1);
break;
}
} else {
switch (samplerate) {
case ADS1115_8SPS:
delay(126); // NOLINT
break;
case ADS1115_16SPS:
delay(63); // NOLINT
break;
case ADS1115_32SPS:
delay(32);
break;
case ADS1115_64SPS:
delay(17);
break;
case ADS1115_128SPS:
delay(9);
break;
case ADS1115_250SPS:
delay(5);
break;
case ADS1115_475SPS:
delay(3);
break;
case ADS1115_860SPS:
delay(2);
break;
}
}
// in continuous mode, conversion will always be running, rely on the delay
// to ensure conversion is taking place with the correct settings

View File

@ -33,6 +33,17 @@ enum ADS1115Resolution {
ADS1015_12_BITS = 12,
};
enum ADS1115Samplerate {
ADS1115_8SPS = 0b000,
ADS1115_16SPS = 0b001,
ADS1115_32SPS = 0b010,
ADS1115_64SPS = 0b011,
ADS1115_128SPS = 0b100,
ADS1115_250SPS = 0b101,
ADS1115_475SPS = 0b110,
ADS1115_860SPS = 0b111
};
class ADS1115Component : public Component, public i2c::I2CDevice {
public:
void setup() override;
@ -42,7 +53,8 @@ class ADS1115Component : public Component, public i2c::I2CDevice {
void set_continuous_mode(bool continuous_mode) { continuous_mode_ = continuous_mode; }
/// Helper method to request a measurement from a sensor.
float request_measurement(ADS1115Multiplexer multiplexer, ADS1115Gain gain, ADS1115Resolution resolution);
float request_measurement(ADS1115Multiplexer multiplexer, ADS1115Gain gain, ADS1115Resolution resolution,
ADS1115Samplerate samplerate);
protected:
uint16_t prev_config_{0};

View File

@ -1,16 +1,18 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor, voltage_sampler
import esphome.config_validation as cv
from esphome.const import (
CONF_GAIN,
CONF_ID,
CONF_MULTIPLEXER,
CONF_RESOLUTION,
CONF_SAMPLE_RATE,
DEVICE_CLASS_VOLTAGE,
STATE_CLASS_MEASUREMENT,
UNIT_VOLT,
CONF_ID,
)
from .. import ads1115_ns, ADS1115Component, CONF_ADS1115_ID
from .. import CONF_ADS1115_ID, ADS1115Component, ads1115_ns
AUTO_LOAD = ["voltage_sampler"]
DEPENDENCIES = ["ads1115"]
@ -43,6 +45,17 @@ RESOLUTION = {
"12_BITS": ADS1115Resolution.ADS1015_12_BITS,
}
ADS1115Samplerate = ads1115_ns.enum("ADS1115Samplerate")
SAMPLERATE = {
"8": ADS1115Samplerate.ADS1115_8SPS,
"16": ADS1115Samplerate.ADS1115_16SPS,
"32": ADS1115Samplerate.ADS1115_32SPS,
"64": ADS1115Samplerate.ADS1115_64SPS,
"128": ADS1115Samplerate.ADS1115_128SPS,
"250": ADS1115Samplerate.ADS1115_250SPS,
"475": ADS1115Samplerate.ADS1115_475SPS,
"860": ADS1115Samplerate.ADS1115_860SPS,
}
ADS1115Sensor = ads1115_ns.class_(
"ADS1115Sensor", sensor.Sensor, cg.PollingComponent, voltage_sampler.VoltageSampler
@ -64,6 +77,9 @@ CONFIG_SCHEMA = (
cv.Optional(CONF_RESOLUTION, default="16_BITS"): cv.enum(
RESOLUTION, upper=True, space="_"
),
cv.Optional(CONF_SAMPLE_RATE, default="860"): cv.enum(
SAMPLERATE, string=True
),
}
)
.extend(cv.polling_component_schema("60s"))
@ -79,3 +95,4 @@ async def to_code(config):
cg.add(var.set_multiplexer(config[CONF_MULTIPLEXER]))
cg.add(var.set_gain(config[CONF_GAIN]))
cg.add(var.set_resolution(config[CONF_RESOLUTION]))
cg.add(var.set_samplerate(config[CONF_SAMPLE_RATE]))

View File

@ -8,7 +8,7 @@ namespace ads1115 {
static const char *const TAG = "ads1115.sensor";
float ADS1115Sensor::sample() {
return this->parent_->request_measurement(this->multiplexer_, this->gain_, this->resolution_);
return this->parent_->request_measurement(this->multiplexer_, this->gain_, this->resolution_, this->samplerate_);
}
void ADS1115Sensor::update() {
@ -24,6 +24,7 @@ void ADS1115Sensor::dump_config() {
ESP_LOGCONFIG(TAG, " Multiplexer: %u", this->multiplexer_);
ESP_LOGCONFIG(TAG, " Gain: %u", this->gain_);
ESP_LOGCONFIG(TAG, " Resolution: %u", this->resolution_);
ESP_LOGCONFIG(TAG, " Sample rate: %u", this->samplerate_);
}
} // namespace ads1115

View File

@ -21,6 +21,7 @@ class ADS1115Sensor : public sensor::Sensor,
void set_multiplexer(ADS1115Multiplexer multiplexer) { this->multiplexer_ = multiplexer; }
void set_gain(ADS1115Gain gain) { this->gain_ = gain; }
void set_resolution(ADS1115Resolution resolution) { this->resolution_ = resolution; }
void set_samplerate(ADS1115Samplerate samplerate) { this->samplerate_ = samplerate; }
float sample() override;
void dump_config() override;
@ -29,6 +30,7 @@ class ADS1115Sensor : public sensor::Sensor,
ADS1115Multiplexer multiplexer_;
ADS1115Gain gain_;
ADS1115Resolution resolution_;
ADS1115Samplerate samplerate_;
};
} // namespace ads1115

View File

@ -1,6 +1,6 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import spi
import esphome.config_validation as cv
from esphome.const import CONF_ID
CODEOWNERS = ["@solomondg1"]

View File

@ -1,17 +1,18 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor, voltage_sampler
import esphome.config_validation as cv
from esphome.const import (
CONF_GAIN,
CONF_MULTIPLEXER,
DEVICE_CLASS_VOLTAGE,
CONF_TYPE,
DEVICE_CLASS_TEMPERATURE,
DEVICE_CLASS_VOLTAGE,
STATE_CLASS_MEASUREMENT,
UNIT_CELSIUS,
UNIT_VOLT,
CONF_TYPE,
)
from .. import ads1118_ns, ADS1118, CONF_ADS1118_ID
from .. import ADS1118, CONF_ADS1118_ID, ads1118_ns
AUTO_LOAD = ["voltage_sampler"]
DEPENDENCIES = ["ads1118"]

View File

@ -1,21 +1,21 @@
import esphome.codegen as cg
from esphome import automation
import esphome.config_validation as cv
import esphome.codegen as cg
from esphome.components import i2c, sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_ADDRESS,
CONF_ID,
ICON_RADIATOR,
ICON_RESTART,
CONF_MODE,
CONF_TVOC,
CONF_VALUE,
CONF_VERSION,
DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS_PARTS,
ENTITY_CATEGORY_DIAGNOSTIC,
ICON_RADIATOR,
ICON_RESTART,
STATE_CLASS_MEASUREMENT,
UNIT_OHM,
UNIT_PARTS_PER_BILLION,
CONF_ADDRESS,
CONF_TVOC,
CONF_VERSION,
CONF_MODE,
CONF_VALUE,
)
CONF_RESISTANCE = "resistance"

View File

@ -1,16 +1,16 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import i2c, sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_HUMIDITY,
CONF_ID,
CONF_TEMPERATURE,
CONF_VARIANT,
DEVICE_CLASS_HUMIDITY,
DEVICE_CLASS_TEMPERATURE,
STATE_CLASS_MEASUREMENT,
UNIT_CELSIUS,
UNIT_PERCENT,
CONF_VARIANT,
)
DEPENDENCIES = ["i2c"]

View File

@ -1,6 +1,6 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import esp32_ble_tracker
import esphome.config_validation as cv
from esphome.const import CONF_ID
DEPENDENCIES = ["esp32_ble_tracker"]

View File

@ -1,18 +1,17 @@
import esphome.codegen as cg
from esphome.components import ble_client, sensor
import esphome.config_validation as cv
from esphome.components import sensor, ble_client
from esphome.const import (
CONF_BATTERY_VOLTAGE,
CONF_HUMIDITY,
CONF_PRESSURE,
CONF_TEMPERATURE,
CONF_TVOC,
DEVICE_CLASS_VOLTAGE,
DEVICE_CLASS_HUMIDITY,
DEVICE_CLASS_PRESSURE,
DEVICE_CLASS_TEMPERATURE,
DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS_PARTS,
DEVICE_CLASS_VOLTAGE,
ENTITY_CATEGORY_DIAGNOSTIC,
STATE_CLASS_MEASUREMENT,
UNIT_CELSIUS,

View File

@ -1,10 +1,7 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import airthings_wave_base
from esphome.const import (
CONF_ID,
)
import esphome.config_validation as cv
from esphome.const import CONF_ID
DEPENDENCIES = airthings_wave_base.DEPENDENCIES

View File

@ -1,20 +1,19 @@
import esphome.codegen as cg
from esphome.components import airthings_wave_base, sensor
import esphome.config_validation as cv
from esphome.components import sensor, airthings_wave_base
from esphome.const import (
DEVICE_CLASS_CARBON_DIOXIDE,
STATE_CLASS_MEASUREMENT,
ICON_RADIOACTIVE,
CONF_CO2,
CONF_ID,
CONF_ILLUMINANCE,
CONF_RADON,
CONF_RADON_LONG_TERM,
CONF_CO2,
UNIT_BECQUEREL_PER_CUBIC_METER,
UNIT_PARTS_PER_MILLION,
CONF_ILLUMINANCE,
UNIT_LUX,
DEVICE_CLASS_CARBON_DIOXIDE,
DEVICE_CLASS_ILLUMINANCE,
ICON_RADIOACTIVE,
STATE_CLASS_MEASUREMENT,
UNIT_BECQUEREL_PER_CUBIC_METER,
UNIT_LUX,
UNIT_PARTS_PER_MILLION,
)
DEPENDENCIES = airthings_wave_base.DEPENDENCIES

View File

@ -1,20 +1,20 @@
import esphome.codegen as cg
from esphome.components import ble_client, sensor
import esphome.config_validation as cv
from esphome.components import sensor, ble_client
from esphome.const import (
CONF_ID,
CONF_CURRENT,
CONF_FLOW,
CONF_HEAD,
CONF_ID,
CONF_POWER,
CONF_SPEED,
CONF_VOLTAGE,
UNIT_AMPERE,
UNIT_CUBIC_METER_PER_HOUR,
UNIT_METER,
UNIT_REVOLUTIONS_PER_MINUTE,
UNIT_VOLT,
UNIT_WATT,
UNIT_METER,
UNIT_CUBIC_METER_PER_HOUR,
UNIT_REVOLUTIONS_PER_MINUTE,
)
alpha3_ns = cg.esphome_ns.namespace("alpha3")

View File

@ -128,7 +128,7 @@ void AM2315C::update() {
data[2] = 0x00;
if (this->write(data, 3) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "Write failed!");
this->mark_failed();
this->status_set_warning();
return;
}
@ -138,12 +138,12 @@ void AM2315C::update() {
uint8_t status = 0;
if (this->read(&status, 1) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "Read failed!");
this->mark_failed();
this->status_set_warning();
return;
}
if ((status & 0x80) == 0x80) {
ESP_LOGE(TAG, "HW still busy!");
this->mark_failed();
this->status_set_warning();
return;
}
@ -151,7 +151,7 @@ void AM2315C::update() {
uint8_t data[7];
if (this->read(data, 7) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "Read failed!");
this->mark_failed();
this->status_set_warning();
return;
}

View File

@ -1,6 +1,6 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import i2c, sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_HUMIDITY,
CONF_ID,

View File

@ -1,6 +1,6 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import i2c, sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_HUMIDITY,
CONF_ID,

View File

@ -1,6 +1,6 @@
import esphome.codegen as cg
from esphome.components import ble_client, cover
import esphome.config_validation as cv
from esphome.components import cover, ble_client
from esphome.const import CONF_ID, CONF_PIN
CODEOWNERS = ["@buxtronix"]

View File

@ -1,12 +1,12 @@
import esphome.codegen as cg
from esphome.components import ble_client, sensor
import esphome.config_validation as cv
from esphome.components import sensor, ble_client
from esphome.const import (
CONF_ID,
CONF_BATTERY_LEVEL,
CONF_ID,
CONF_ILLUMINANCE,
DEVICE_CLASS_BATTERY,
ENTITY_CATEGORY_DIAGNOSTIC,
CONF_ILLUMINANCE,
ICON_BRIGHTNESS_5,
UNIT_PERCENT,
)

View File

@ -14,7 +14,8 @@ void AnalogThresholdBinarySensor::setup() {
if (std::isnan(sensor_value)) {
this->publish_initial_state(false);
} else {
this->publish_initial_state(sensor_value >= (this->lower_threshold_ + this->upper_threshold_) / 2.0f);
this->publish_initial_state(sensor_value >=
(this->lower_threshold_.value() + this->upper_threshold_.value()) / 2.0f);
}
}
@ -24,7 +25,8 @@ void AnalogThresholdBinarySensor::set_sensor(sensor::Sensor *analog_sensor) {
this->sensor_->add_on_state_callback([this](float sensor_value) {
// if there is an invalid sensor reading, ignore the change and keep the current state
if (!std::isnan(sensor_value)) {
this->publish_state(sensor_value >= (this->state ? this->lower_threshold_ : this->upper_threshold_));
this->publish_state(sensor_value >=
(this->state ? this->lower_threshold_.value() : this->upper_threshold_.value()));
}
});
}
@ -32,8 +34,8 @@ void AnalogThresholdBinarySensor::set_sensor(sensor::Sensor *analog_sensor) {
void AnalogThresholdBinarySensor::dump_config() {
LOG_BINARY_SENSOR("", "Analog Threshold Binary Sensor", this);
LOG_SENSOR(" ", "Sensor", this->sensor_);
ESP_LOGCONFIG(TAG, " Upper threshold: %.11f", this->upper_threshold_);
ESP_LOGCONFIG(TAG, " Lower threshold: %.11f", this->lower_threshold_);
ESP_LOGCONFIG(TAG, " Upper threshold: %.11f", this->upper_threshold_.value());
ESP_LOGCONFIG(TAG, " Lower threshold: %.11f", this->lower_threshold_.value());
}
} // namespace analog_threshold

View File

@ -15,14 +15,13 @@ class AnalogThresholdBinarySensor : public Component, public binary_sensor::Bina
float get_setup_priority() const override { return setup_priority::DATA; }
void set_sensor(sensor::Sensor *analog_sensor);
void set_upper_threshold(float threshold) { this->upper_threshold_ = threshold; }
void set_lower_threshold(float threshold) { this->lower_threshold_ = threshold; }
template<typename T> void set_upper_threshold(T upper_threshold) { this->upper_threshold_ = upper_threshold; }
template<typename T> void set_lower_threshold(T lower_threshold) { this->lower_threshold_ = lower_threshold; }
protected:
sensor::Sensor *sensor_{nullptr};
float upper_threshold_;
float lower_threshold_;
TemplatableValue<float> upper_threshold_{};
TemplatableValue<float> lower_threshold_{};
};
} // namespace analog_threshold

View File

@ -1,10 +1,7 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import binary_sensor, sensor
from esphome.const import (
CONF_SENSOR_ID,
CONF_THRESHOLD,
)
import esphome.config_validation as cv
from esphome.const import CONF_SENSOR_ID, CONF_THRESHOLD
analog_threshold_ns = cg.esphome_ns.namespace("analog_threshold")
@ -21,11 +18,11 @@ CONFIG_SCHEMA = (
{
cv.Required(CONF_SENSOR_ID): cv.use_id(sensor.Sensor),
cv.Required(CONF_THRESHOLD): cv.Any(
cv.float_,
cv.templatable(cv.float_),
cv.Schema(
{
cv.Required(CONF_UPPER): cv.float_,
cv.Required(CONF_LOWER): cv.float_,
cv.Required(CONF_UPPER): cv.templatable(cv.float_),
cv.Required(CONF_LOWER): cv.templatable(cv.float_),
}
),
),
@ -42,9 +39,11 @@ async def to_code(config):
sens = await cg.get_variable(config[CONF_SENSOR_ID])
cg.add(var.set_sensor(sens))
if isinstance(config[CONF_THRESHOLD], float):
cg.add(var.set_upper_threshold(config[CONF_THRESHOLD]))
cg.add(var.set_lower_threshold(config[CONF_THRESHOLD]))
if isinstance(config[CONF_THRESHOLD], dict):
lower = await cg.templatable(config[CONF_THRESHOLD][CONF_LOWER], [], float)
upper = await cg.templatable(config[CONF_THRESHOLD][CONF_UPPER], [], float)
else:
cg.add(var.set_upper_threshold(config[CONF_THRESHOLD][CONF_UPPER]))
cg.add(var.set_lower_threshold(config[CONF_THRESHOLD][CONF_LOWER]))
lower = await cg.templatable(config[CONF_THRESHOLD], [], float)
upper = lower
cg.add(var.set_upper_threshold(upper))
cg.add(var.set_lower_threshold(lower))

View File

@ -1,28 +1,10 @@
import logging
from esphome import automation, core
from esphome import automation
import esphome.codegen as cg
import esphome.components.image as espImage
from esphome.components.image import (
CONF_USE_TRANSPARENCY,
LOCAL_SCHEMA,
SOURCE_LOCAL,
SOURCE_WEB,
WEB_SCHEMA,
)
import esphome.config_validation as cv
from esphome.const import (
CONF_FILE,
CONF_ID,
CONF_PATH,
CONF_RAW_DATA_ID,
CONF_REPEAT,
CONF_RESIZE,
CONF_SOURCE,
CONF_TYPE,
CONF_URL,
)
from esphome.core import CORE, HexInt
from esphome.const import CONF_ID, CONF_REPEAT
_LOGGER = logging.getLogger(__name__)
@ -30,6 +12,7 @@ AUTO_LOAD = ["image"]
CODEOWNERS = ["@syndlex"]
DEPENDENCIES = ["display"]
MULTI_CONF = True
MULTI_CONF_NO_DEFAULT = True
CONF_LOOP = "loop"
CONF_START_FRAME = "start_frame"
@ -51,86 +34,19 @@ SetFrameAction = animation_ns.class_(
"AnimationSetFrameAction", automation.Action, cg.Parented.template(Animation_)
)
TYPED_FILE_SCHEMA = cv.typed_schema(
CONFIG_SCHEMA = espImage.IMAGE_SCHEMA.extend(
{
SOURCE_LOCAL: LOCAL_SCHEMA,
SOURCE_WEB: WEB_SCHEMA,
},
key=CONF_SOURCE,
)
def _file_schema(value):
if isinstance(value, str):
return validate_file_shorthand(value)
return TYPED_FILE_SCHEMA(value)
FILE_SCHEMA = cv.Schema(_file_schema)
def validate_file_shorthand(value):
value = cv.string_strict(value)
if value.startswith("http://") or value.startswith("https://"):
return FILE_SCHEMA(
cv.Required(CONF_ID): cv.declare_id(Animation_),
cv.Optional(CONF_LOOP): cv.All(
{
CONF_SOURCE: SOURCE_WEB,
CONF_URL: value,
cv.Optional(CONF_START_FRAME, default=0): cv.positive_int,
cv.Optional(CONF_END_FRAME): cv.positive_int,
cv.Optional(CONF_REPEAT): cv.positive_int,
}
)
return FILE_SCHEMA(
{
CONF_SOURCE: SOURCE_LOCAL,
CONF_PATH: value,
}
)
def validate_cross_dependencies(config):
"""
Validate fields whose possible values depend on other fields.
For example, validate that explicitly transparent image types
have "use_transparency" set to True.
Also set the default value for those kind of dependent fields.
"""
image_type = config[CONF_TYPE]
is_transparent_type = image_type in ["TRANSPARENT_BINARY", "RGBA"]
# If the use_transparency option was not specified, set the default depending on the image type
if CONF_USE_TRANSPARENCY not in config:
config[CONF_USE_TRANSPARENCY] = is_transparent_type
if is_transparent_type and not config[CONF_USE_TRANSPARENCY]:
raise cv.Invalid(f"Image type {image_type} must always be transparent.")
return config
ANIMATION_SCHEMA = cv.Schema(
cv.All(
{
cv.Required(CONF_ID): cv.declare_id(Animation_),
cv.Required(CONF_FILE): FILE_SCHEMA,
cv.Optional(CONF_RESIZE): cv.dimensions,
cv.Optional(CONF_TYPE, default="BINARY"): cv.enum(
espImage.IMAGE_TYPE, upper=True
),
# Not setting default here on purpose; the default depends on the image type,
# and thus will be set in the "validate_cross_dependencies" validator.
cv.Optional(CONF_USE_TRANSPARENCY): cv.boolean,
cv.Optional(CONF_LOOP): cv.All(
{
cv.Optional(CONF_START_FRAME, default=0): cv.positive_int,
cv.Optional(CONF_END_FRAME): cv.positive_int,
cv.Optional(CONF_REPEAT): cv.positive_int,
}
),
cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_id(cg.uint8),
},
validate_cross_dependencies,
)
),
},
)
CONFIG_SCHEMA = ANIMATION_SCHEMA
NEXT_FRAME_SCHEMA = automation.maybe_simple_id(
{
@ -164,180 +80,26 @@ async def animation_action_to_code(config, action_id, template_arg, args):
async def to_code(config):
from PIL import Image
(
prog_arr,
width,
height,
image_type,
trans_value,
frame_count,
) = await espImage.write_image(config, all_frames=True)
conf_file = config[CONF_FILE]
if conf_file[CONF_SOURCE] == SOURCE_LOCAL:
path = CORE.relative_config_path(conf_file[CONF_PATH])
elif conf_file[CONF_SOURCE] == SOURCE_WEB:
path = espImage.compute_local_image_path(conf_file).as_posix()
else:
raise core.EsphomeError(f"Unknown animation source: {conf_file[CONF_SOURCE]}")
try:
image = Image.open(path)
except Exception as e:
raise core.EsphomeError(f"Could not load image file {path}: {e}")
width, height = image.size
frames = image.n_frames
if CONF_RESIZE in config:
new_width_max, new_height_max = config[CONF_RESIZE]
ratio = min(new_width_max / width, new_height_max / height)
width, height = int(width * ratio), int(height * ratio)
elif width > 500 or height > 500:
_LOGGER.warning(
'The image "%s" you requested is very big. Please consider'
" using the resize parameter.",
path,
)
transparent = config[CONF_USE_TRANSPARENCY]
if config[CONF_TYPE] == "GRAYSCALE":
data = [0 for _ in range(height * width * frames)]
pos = 0
for frameIndex in range(frames):
image.seek(frameIndex)
frame = image.convert("LA", dither=Image.Dither.NONE)
if CONF_RESIZE in config:
frame = frame.resize([width, height])
pixels = list(frame.getdata())
if len(pixels) != height * width:
raise core.EsphomeError(
f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height * width})"
)
for pix, a in pixels:
if transparent:
if pix == 1:
pix = 0
if a < 0x80:
pix = 1
data[pos] = pix
pos += 1
elif config[CONF_TYPE] == "RGBA":
data = [0 for _ in range(height * width * 4 * frames)]
pos = 0
for frameIndex in range(frames):
image.seek(frameIndex)
frame = image.convert("RGBA")
if CONF_RESIZE in config:
frame = frame.resize([width, height])
pixels = list(frame.getdata())
if len(pixels) != height * width:
raise core.EsphomeError(
f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height * width})"
)
for pix in pixels:
data[pos] = pix[0]
pos += 1
data[pos] = pix[1]
pos += 1
data[pos] = pix[2]
pos += 1
data[pos] = pix[3]
pos += 1
elif config[CONF_TYPE] == "RGB24":
data = [0 for _ in range(height * width * 3 * frames)]
pos = 0
for frameIndex in range(frames):
image.seek(frameIndex)
frame = image.convert("RGBA")
if CONF_RESIZE in config:
frame = frame.resize([width, height])
pixels = list(frame.getdata())
if len(pixels) != height * width:
raise core.EsphomeError(
f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height * width})"
)
for r, g, b, a in pixels:
if transparent:
if r == 0 and g == 0 and b == 1:
b = 0
if a < 0x80:
r = 0
g = 0
b = 1
data[pos] = r
pos += 1
data[pos] = g
pos += 1
data[pos] = b
pos += 1
elif config[CONF_TYPE] in ["RGB565", "TRANSPARENT_IMAGE"]:
bytes_per_pixel = 3 if transparent else 2
data = [0 for _ in range(height * width * bytes_per_pixel * frames)]
pos = 0
for frameIndex in range(frames):
image.seek(frameIndex)
frame = image.convert("RGBA")
if CONF_RESIZE in config:
frame = frame.resize([width, height])
pixels = list(frame.getdata())
if len(pixels) != height * width:
raise core.EsphomeError(
f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height * width})"
)
for r, g, b, a in pixels:
R = r >> 3
G = g >> 2
B = b >> 3
rgb = (R << 11) | (G << 5) | B
data[pos] = rgb >> 8
pos += 1
data[pos] = rgb & 0xFF
pos += 1
if transparent:
data[pos] = a
pos += 1
elif config[CONF_TYPE] in ["BINARY", "TRANSPARENT_BINARY"]:
width8 = ((width + 7) // 8) * 8
data = [0 for _ in range((height * width8 // 8) * frames)]
for frameIndex in range(frames):
image.seek(frameIndex)
if transparent:
alpha = image.split()[-1]
has_alpha = alpha.getextrema()[0] < 0xFF
else:
has_alpha = False
frame = image.convert("1", dither=Image.Dither.NONE)
if CONF_RESIZE in config:
frame = frame.resize([width, height])
if transparent:
alpha = alpha.resize([width, height])
for x, y in [(i, j) for i in range(width) for j in range(height)]:
if transparent and has_alpha:
if not alpha.getpixel((x, y)):
continue
elif frame.getpixel((x, y)):
continue
pos = x + y * width8 + (height * width8 * frameIndex)
data[pos // 8] |= 0x80 >> (pos % 8)
else:
raise core.EsphomeError(
f"Animation f{config[CONF_ID]} has not supported type {config[CONF_TYPE]}."
)
rhs = [HexInt(x) for x in data]
prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs)
var = cg.new_Pvariable(
config[CONF_ID],
prog_arr,
width,
height,
frames,
espImage.IMAGE_TYPE[config[CONF_TYPE]],
frame_count,
image_type,
trans_value,
)
cg.add(var.set_transparency(transparent))
if loop_config := config.get(CONF_LOOP):
start = loop_config[CONF_START_FRAME]
end = loop_config.get(CONF_END_FRAME, frames)
end = loop_config.get(CONF_END_FRAME, frame_count)
count = loop_config.get(CONF_REPEAT, -1)
cg.add(var.set_loop(start, end, count))

View File

@ -6,8 +6,8 @@ namespace esphome {
namespace animation {
Animation::Animation(const uint8_t *data_start, int width, int height, uint32_t animation_frame_count,
image::ImageType type)
: Image(data_start, width, height, type),
image::ImageType type, image::Transparency transparent)
: Image(data_start, width, height, type, transparent),
animation_data_start_(data_start),
current_frame_(0),
animation_frame_count_(animation_frame_count),

View File

@ -8,7 +8,8 @@ namespace animation {
class Animation : public image::Image {
public:
Animation(const uint8_t *data_start, int width, int height, uint32_t animation_frame_count, image::ImageType type);
Animation(const uint8_t *data_start, int width, int height, uint32_t animation_frame_count, image::ImageType type,
image::Transparency transparent);
uint32_t get_animation_frame_count() const;
int get_current_frame() const;

View File

@ -1,6 +1,6 @@
import esphome.codegen as cg
from esphome.components import ble_client, climate
import esphome.config_validation as cv
from esphome.components import climate, ble_client
from esphome.const import CONF_ID, CONF_UNIT_OF_MEASUREMENT
UNITS = {

View File

@ -2,8 +2,8 @@
# https://www.mouser.ca/datasheet/2/678/AVGO_S_A0002854364_1-2574547.pdf
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import i2c, sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_GAIN,
DEVICE_CLASS_ILLUMINANCE,

View File

@ -1,6 +1,6 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import i2c
import esphome.config_validation as cv
from esphome.const import CONF_ID
DEPENDENCIES = ["i2c"]

View File

@ -1,7 +1,8 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import binary_sensor
import esphome.config_validation as cv
from esphome.const import CONF_DIRECTION, DEVICE_CLASS_MOVING
from . import APDS9960, CONF_APDS9960_ID
DEPENDENCIES = ["apds9960"]

View File

@ -1,12 +1,13 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_TYPE,
ICON_LIGHTBULB,
STATE_CLASS_MEASUREMENT,
UNIT_PERCENT,
ICON_LIGHTBULB,
)
from . import APDS9960, CONF_APDS9960_ID
DEPENDENCIES = ["apds9960"]

View File

@ -82,6 +82,19 @@ ACTIONS_SCHEMA = automation.validate_automation(
),
)
ENCRYPTION_SCHEMA = cv.Schema(
{
cv.Optional(CONF_KEY): validate_encryption_key,
}
)
def _encryption_schema(config):
if config is None:
config = {}
return ENCRYPTION_SCHEMA(config)
CONFIG_SCHEMA = cv.All(
cv.Schema(
{
@ -95,11 +108,7 @@ CONFIG_SCHEMA = cv.All(
CONF_SERVICES, group_of_exclusion=CONF_ACTIONS
): ACTIONS_SCHEMA,
cv.Exclusive(CONF_ACTIONS, group_of_exclusion=CONF_ACTIONS): ACTIONS_SCHEMA,
cv.Optional(CONF_ENCRYPTION): cv.Schema(
{
cv.Required(CONF_KEY): validate_encryption_key,
}
),
cv.Optional(CONF_ENCRYPTION): _encryption_schema,
cv.Optional(CONF_ON_CLIENT_CONNECTED): automation.validate_automation(
single=True
),
@ -151,9 +160,17 @@ async def to_code(config):
config[CONF_ON_CLIENT_DISCONNECTED],
)
if encryption_config := config.get(CONF_ENCRYPTION):
decoded = base64.b64decode(encryption_config[CONF_KEY])
cg.add(var.set_noise_psk(list(decoded)))
if (encryption_config := config.get(CONF_ENCRYPTION, None)) is not None:
if key := encryption_config.get(CONF_KEY):
decoded = base64.b64decode(key)
cg.add(var.set_noise_psk(list(decoded)))
else:
# No key provided, but encryption desired
# This will allow a plaintext client to provide a noise key,
# send it to the device, and then switch to noise.
# The key will be saved in flash and used for future connections
# and plaintext disabled. Only a factory reset can remove it.
cg.add_define("USE_API_PLAINTEXT")
cg.add_define("USE_API_NOISE")
cg.add_library("esphome/noise-c", "0.1.6")
else:

View File

@ -31,6 +31,7 @@ service APIConnection {
option (needs_authentication) = false;
}
rpc execute_service (ExecuteServiceRequest) returns (void) {}
rpc noise_encryption_set_key (NoiseEncryptionSetKeyRequest) returns (NoiseEncryptionSetKeyResponse) {}
rpc cover_command (CoverCommandRequest) returns (void) {}
rpc fan_command (FanCommandRequest) returns (void) {}
@ -227,6 +228,12 @@ message DeviceInfoResponse {
uint32 voice_assistant_feature_flags = 17;
string suggested_area = 16;
// The Bluetooth mac address of the device. For example "AC:BC:32:89:0E:AA"
string bluetooth_mac_address = 18;
// Supports receiving and saving api encryption key
bool api_encryption_supported = 19;
}
message ListEntitiesRequest {
@ -651,6 +658,23 @@ message SubscribeLogsResponse {
bool send_failed = 4;
}
// ==================== NOISE ENCRYPTION ====================
message NoiseEncryptionSetKeyRequest {
option (id) = 124;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_API_NOISE";
bytes key = 1;
}
message NoiseEncryptionSetKeyResponse {
option (id) = 125;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_API_NOISE";
bool success = 1;
}
// ==================== HOMEASSISTANT.SERVICE ====================
message SubscribeHomeassistantServicesRequest {
option (id) = 34;
@ -1381,6 +1405,7 @@ message BluetoothConnectionsFreeResponse {
uint32 free = 1;
uint32 limit = 2;
repeated uint64 allocated = 3;
}
message BluetoothGATTErrorResponse {
@ -1563,6 +1588,8 @@ message VoiceAssistantAnnounceRequest {
string media_id = 1;
string text = 2;
string preannounce_media_id = 3;
bool start_conversation = 4;
}
message VoiceAssistantAnnounceFinished {

View File

@ -28,11 +28,48 @@ namespace api {
static const char *const TAG = "api.connection";
static const int ESP32_CAMERA_STOP_STREAM = 5000;
// helper for allowing only unique entries in the queue
void DeferredMessageQueue::dmq_push_back_with_dedup_(void *source, send_message_t *send_message) {
DeferredMessage item(source, send_message);
auto iter = std::find_if(this->deferred_queue_.begin(), this->deferred_queue_.end(),
[&item](const DeferredMessage &test) -> bool { return test == item; });
if (iter != this->deferred_queue_.end()) {
(*iter) = item;
} else {
this->deferred_queue_.push_back(item);
}
}
void DeferredMessageQueue::process_queue() {
while (!deferred_queue_.empty()) {
DeferredMessage &de = deferred_queue_.front();
if (de.send_message_(this->api_connection_, de.source_)) {
// O(n) but memory efficiency is more important than speed here which is why std::vector was chosen
deferred_queue_.erase(deferred_queue_.begin());
} else {
break;
}
}
}
void DeferredMessageQueue::defer(void *source, send_message_t *send_message) {
this->dmq_push_back_with_dedup_(source, send_message);
}
APIConnection::APIConnection(std::unique_ptr<socket::Socket> sock, APIServer *parent)
: parent_(parent), initial_state_iterator_(this), list_entities_iterator_(this) {
: parent_(parent), deferred_message_queue_(this), initial_state_iterator_(this), list_entities_iterator_(this) {
this->proto_write_buffer_.reserve(64);
#if defined(USE_API_PLAINTEXT)
#if defined(USE_API_PLAINTEXT) && defined(USE_API_NOISE)
auto noise_ctx = parent->get_noise_ctx();
if (noise_ctx->has_psk()) {
this->helper_ = std::unique_ptr<APIFrameHelper>{new APINoiseFrameHelper(std::move(sock), noise_ctx)};
} else {
this->helper_ = std::unique_ptr<APIFrameHelper>{new APIPlaintextFrameHelper(std::move(sock))};
}
#elif defined(USE_API_PLAINTEXT)
this->helper_ = std::unique_ptr<APIFrameHelper>{new APIPlaintextFrameHelper(std::move(sock))};
#elif defined(USE_API_NOISE)
this->helper_ = std::unique_ptr<APIFrameHelper>{new APINoiseFrameHelper(std::move(sock), parent->get_noise_ctx())};
@ -116,8 +153,12 @@ void APIConnection::loop() {
return;
}
this->list_entities_iterator_.advance();
this->initial_state_iterator_.advance();
this->deferred_message_queue_.process_queue();
if (!this->list_entities_iterator_.completed())
this->list_entities_iterator_.advance();
if (!this->initial_state_iterator_.completed() && this->list_entities_iterator_.completed())
this->initial_state_iterator_.advance();
static uint32_t keepalive = 60000;
static uint8_t max_ping_retries = 60;
@ -210,13 +251,31 @@ bool APIConnection::send_binary_sensor_state(binary_sensor::BinarySensor *binary
if (!this->state_subscription_)
return false;
if (!APIConnection::try_send_binary_sensor_state(this, binary_sensor, state)) {
this->deferred_message_queue_.defer(binary_sensor, try_send_binary_sensor_state);
}
return true;
}
void APIConnection::send_binary_sensor_info(binary_sensor::BinarySensor *binary_sensor) {
if (!APIConnection::try_send_binary_sensor_info(this, binary_sensor)) {
this->deferred_message_queue_.defer(binary_sensor, try_send_binary_sensor_info);
}
}
bool APIConnection::try_send_binary_sensor_state(APIConnection *api, void *v_binary_sensor) {
binary_sensor::BinarySensor *binary_sensor = reinterpret_cast<binary_sensor::BinarySensor *>(v_binary_sensor);
return APIConnection::try_send_binary_sensor_state(api, binary_sensor, binary_sensor->state);
}
bool APIConnection::try_send_binary_sensor_state(APIConnection *api, binary_sensor::BinarySensor *binary_sensor,
bool state) {
BinarySensorStateResponse resp;
resp.key = binary_sensor->get_object_id_hash();
resp.state = state;
resp.missing_state = !binary_sensor->has_state();
return this->send_binary_sensor_state_response(resp);
return api->send_binary_sensor_state_response(resp);
}
bool APIConnection::send_binary_sensor_info(binary_sensor::BinarySensor *binary_sensor) {
bool APIConnection::try_send_binary_sensor_info(APIConnection *api, void *v_binary_sensor) {
binary_sensor::BinarySensor *binary_sensor = reinterpret_cast<binary_sensor::BinarySensor *>(v_binary_sensor);
ListEntitiesBinarySensorResponse msg;
msg.object_id = binary_sensor->get_object_id();
msg.key = binary_sensor->get_object_id_hash();
@ -228,7 +287,7 @@ bool APIConnection::send_binary_sensor_info(binary_sensor::BinarySensor *binary_
msg.disabled_by_default = binary_sensor->is_disabled_by_default();
msg.icon = binary_sensor->get_icon();
msg.entity_category = static_cast<enums::EntityCategory>(binary_sensor->get_entity_category());
return this->send_list_entities_binary_sensor_response(msg);
return api->send_list_entities_binary_sensor_response(msg);
}
#endif
@ -237,6 +296,19 @@ bool APIConnection::send_cover_state(cover::Cover *cover) {
if (!this->state_subscription_)
return false;
if (!APIConnection::try_send_cover_state(this, cover)) {
this->deferred_message_queue_.defer(cover, try_send_cover_state);
}
return true;
}
void APIConnection::send_cover_info(cover::Cover *cover) {
if (!APIConnection::try_send_cover_info(this, cover)) {
this->deferred_message_queue_.defer(cover, try_send_cover_info);
}
}
bool APIConnection::try_send_cover_state(APIConnection *api, void *v_cover) {
cover::Cover *cover = reinterpret_cast<cover::Cover *>(v_cover);
auto traits = cover->get_traits();
CoverStateResponse resp{};
resp.key = cover->get_object_id_hash();
@ -246,9 +318,10 @@ bool APIConnection::send_cover_state(cover::Cover *cover) {
if (traits.get_supports_tilt())
resp.tilt = cover->tilt;
resp.current_operation = static_cast<enums::CoverOperation>(cover->current_operation);
return this->send_cover_state_response(resp);
return api->send_cover_state_response(resp);
}
bool APIConnection::send_cover_info(cover::Cover *cover) {
bool APIConnection::try_send_cover_info(APIConnection *api, void *v_cover) {
cover::Cover *cover = reinterpret_cast<cover::Cover *>(v_cover);
auto traits = cover->get_traits();
ListEntitiesCoverResponse msg;
msg.key = cover->get_object_id_hash();
@ -264,7 +337,7 @@ bool APIConnection::send_cover_info(cover::Cover *cover) {
msg.disabled_by_default = cover->is_disabled_by_default();
msg.icon = cover->get_icon();
msg.entity_category = static_cast<enums::EntityCategory>(cover->get_entity_category());
return this->send_list_entities_cover_response(msg);
return api->send_list_entities_cover_response(msg);
}
void APIConnection::cover_command(const CoverCommandRequest &msg) {
cover::Cover *cover = App.get_cover_by_key(msg.key);
@ -300,6 +373,19 @@ bool APIConnection::send_fan_state(fan::Fan *fan) {
if (!this->state_subscription_)
return false;
if (!APIConnection::try_send_fan_state(this, fan)) {
this->deferred_message_queue_.defer(fan, try_send_fan_state);
}
return true;
}
void APIConnection::send_fan_info(fan::Fan *fan) {
if (!APIConnection::try_send_fan_info(this, fan)) {
this->deferred_message_queue_.defer(fan, try_send_fan_info);
}
}
bool APIConnection::try_send_fan_state(APIConnection *api, void *v_fan) {
fan::Fan *fan = reinterpret_cast<fan::Fan *>(v_fan);
auto traits = fan->get_traits();
FanStateResponse resp{};
resp.key = fan->get_object_id_hash();
@ -313,9 +399,10 @@ bool APIConnection::send_fan_state(fan::Fan *fan) {
resp.direction = static_cast<enums::FanDirection>(fan->direction);
if (traits.supports_preset_modes())
resp.preset_mode = fan->preset_mode;
return this->send_fan_state_response(resp);
return api->send_fan_state_response(resp);
}
bool APIConnection::send_fan_info(fan::Fan *fan) {
bool APIConnection::try_send_fan_info(APIConnection *api, void *v_fan) {
fan::Fan *fan = reinterpret_cast<fan::Fan *>(v_fan);
auto traits = fan->get_traits();
ListEntitiesFanResponse msg;
msg.key = fan->get_object_id_hash();
@ -332,7 +419,7 @@ bool APIConnection::send_fan_info(fan::Fan *fan) {
msg.disabled_by_default = fan->is_disabled_by_default();
msg.icon = fan->get_icon();
msg.entity_category = static_cast<enums::EntityCategory>(fan->get_entity_category());
return this->send_list_entities_fan_response(msg);
return api->send_list_entities_fan_response(msg);
}
void APIConnection::fan_command(const FanCommandRequest &msg) {
fan::Fan *fan = App.get_fan_by_key(msg.key);
@ -361,6 +448,19 @@ bool APIConnection::send_light_state(light::LightState *light) {
if (!this->state_subscription_)
return false;
if (!APIConnection::try_send_light_state(this, light)) {
this->deferred_message_queue_.defer(light, try_send_light_state);
}
return true;
}
void APIConnection::send_light_info(light::LightState *light) {
if (!APIConnection::try_send_light_info(this, light)) {
this->deferred_message_queue_.defer(light, try_send_light_info);
}
}
bool APIConnection::try_send_light_state(APIConnection *api, void *v_light) {
light::LightState *light = reinterpret_cast<light::LightState *>(v_light);
auto traits = light->get_traits();
auto values = light->remote_values;
auto color_mode = values.get_color_mode();
@ -380,9 +480,10 @@ bool APIConnection::send_light_state(light::LightState *light) {
resp.warm_white = values.get_warm_white();
if (light->supports_effects())
resp.effect = light->get_effect_name();
return this->send_light_state_response(resp);
return api->send_light_state_response(resp);
}
bool APIConnection::send_light_info(light::LightState *light) {
bool APIConnection::try_send_light_info(APIConnection *api, void *v_light) {
light::LightState *light = reinterpret_cast<light::LightState *>(v_light);
auto traits = light->get_traits();
ListEntitiesLightResponse msg;
msg.key = light->get_object_id_hash();
@ -415,7 +516,7 @@ bool APIConnection::send_light_info(light::LightState *light) {
for (auto *effect : light->get_effects())
msg.effects.push_back(effect->get_name());
}
return this->send_list_entities_light_response(msg);
return api->send_list_entities_light_response(msg);
}
void APIConnection::light_command(const LightCommandRequest &msg) {
light::LightState *light = App.get_light_by_key(msg.key);
@ -459,13 +560,30 @@ bool APIConnection::send_sensor_state(sensor::Sensor *sensor, float state) {
if (!this->state_subscription_)
return false;
if (!APIConnection::try_send_sensor_state(this, sensor, state)) {
this->deferred_message_queue_.defer(sensor, try_send_sensor_state);
}
return true;
}
void APIConnection::send_sensor_info(sensor::Sensor *sensor) {
if (!APIConnection::try_send_sensor_info(this, sensor)) {
this->deferred_message_queue_.defer(sensor, try_send_sensor_info);
}
}
bool APIConnection::try_send_sensor_state(APIConnection *api, void *v_sensor) {
sensor::Sensor *sensor = reinterpret_cast<sensor::Sensor *>(v_sensor);
return APIConnection::try_send_sensor_state(api, sensor, sensor->state);
}
bool APIConnection::try_send_sensor_state(APIConnection *api, sensor::Sensor *sensor, float state) {
SensorStateResponse resp{};
resp.key = sensor->get_object_id_hash();
resp.state = state;
resp.missing_state = !sensor->has_state();
return this->send_sensor_state_response(resp);
return api->send_sensor_state_response(resp);
}
bool APIConnection::send_sensor_info(sensor::Sensor *sensor) {
bool APIConnection::try_send_sensor_info(APIConnection *api, void *v_sensor) {
sensor::Sensor *sensor = reinterpret_cast<sensor::Sensor *>(v_sensor);
ListEntitiesSensorResponse msg;
msg.key = sensor->get_object_id_hash();
msg.object_id = sensor->get_object_id();
@ -482,7 +600,7 @@ bool APIConnection::send_sensor_info(sensor::Sensor *sensor) {
msg.state_class = static_cast<enums::SensorStateClass>(sensor->get_state_class());
msg.disabled_by_default = sensor->is_disabled_by_default();
msg.entity_category = static_cast<enums::EntityCategory>(sensor->get_entity_category());
return this->send_list_entities_sensor_response(msg);
return api->send_list_entities_sensor_response(msg);
}
#endif
@ -491,12 +609,29 @@ bool APIConnection::send_switch_state(switch_::Switch *a_switch, bool state) {
if (!this->state_subscription_)
return false;
if (!APIConnection::try_send_switch_state(this, a_switch, state)) {
this->deferred_message_queue_.defer(a_switch, try_send_switch_state);
}
return true;
}
void APIConnection::send_switch_info(switch_::Switch *a_switch) {
if (!APIConnection::try_send_switch_info(this, a_switch)) {
this->deferred_message_queue_.defer(a_switch, try_send_switch_info);
}
}
bool APIConnection::try_send_switch_state(APIConnection *api, void *v_a_switch) {
switch_::Switch *a_switch = reinterpret_cast<switch_::Switch *>(v_a_switch);
return APIConnection::try_send_switch_state(api, a_switch, a_switch->state);
}
bool APIConnection::try_send_switch_state(APIConnection *api, switch_::Switch *a_switch, bool state) {
SwitchStateResponse resp{};
resp.key = a_switch->get_object_id_hash();
resp.state = state;
return this->send_switch_state_response(resp);
return api->send_switch_state_response(resp);
}
bool APIConnection::send_switch_info(switch_::Switch *a_switch) {
bool APIConnection::try_send_switch_info(APIConnection *api, void *v_a_switch) {
switch_::Switch *a_switch = reinterpret_cast<switch_::Switch *>(v_a_switch);
ListEntitiesSwitchResponse msg;
msg.key = a_switch->get_object_id_hash();
msg.object_id = a_switch->get_object_id();
@ -508,7 +643,7 @@ bool APIConnection::send_switch_info(switch_::Switch *a_switch) {
msg.disabled_by_default = a_switch->is_disabled_by_default();
msg.entity_category = static_cast<enums::EntityCategory>(a_switch->get_entity_category());
msg.device_class = a_switch->get_device_class();
return this->send_list_entities_switch_response(msg);
return api->send_list_entities_switch_response(msg);
}
void APIConnection::switch_command(const SwitchCommandRequest &msg) {
switch_::Switch *a_switch = App.get_switch_by_key(msg.key);
@ -528,13 +663,31 @@ bool APIConnection::send_text_sensor_state(text_sensor::TextSensor *text_sensor,
if (!this->state_subscription_)
return false;
if (!APIConnection::try_send_text_sensor_state(this, text_sensor, std::move(state))) {
this->deferred_message_queue_.defer(text_sensor, try_send_text_sensor_state);
}
return true;
}
void APIConnection::send_text_sensor_info(text_sensor::TextSensor *text_sensor) {
if (!APIConnection::try_send_text_sensor_info(this, text_sensor)) {
this->deferred_message_queue_.defer(text_sensor, try_send_text_sensor_info);
}
}
bool APIConnection::try_send_text_sensor_state(APIConnection *api, void *v_text_sensor) {
text_sensor::TextSensor *text_sensor = reinterpret_cast<text_sensor::TextSensor *>(v_text_sensor);
return APIConnection::try_send_text_sensor_state(api, text_sensor, text_sensor->state);
}
bool APIConnection::try_send_text_sensor_state(APIConnection *api, text_sensor::TextSensor *text_sensor,
std::string state) {
TextSensorStateResponse resp{};
resp.key = text_sensor->get_object_id_hash();
resp.state = std::move(state);
resp.missing_state = !text_sensor->has_state();
return this->send_text_sensor_state_response(resp);
return api->send_text_sensor_state_response(resp);
}
bool APIConnection::send_text_sensor_info(text_sensor::TextSensor *text_sensor) {
bool APIConnection::try_send_text_sensor_info(APIConnection *api, void *v_text_sensor) {
text_sensor::TextSensor *text_sensor = reinterpret_cast<text_sensor::TextSensor *>(v_text_sensor);
ListEntitiesTextSensorResponse msg;
msg.key = text_sensor->get_object_id_hash();
msg.object_id = text_sensor->get_object_id();
@ -546,7 +699,7 @@ bool APIConnection::send_text_sensor_info(text_sensor::TextSensor *text_sensor)
msg.disabled_by_default = text_sensor->is_disabled_by_default();
msg.entity_category = static_cast<enums::EntityCategory>(text_sensor->get_entity_category());
msg.device_class = text_sensor->get_device_class();
return this->send_list_entities_text_sensor_response(msg);
return api->send_list_entities_text_sensor_response(msg);
}
#endif
@ -555,6 +708,19 @@ bool APIConnection::send_climate_state(climate::Climate *climate) {
if (!this->state_subscription_)
return false;
if (!APIConnection::try_send_climate_state(this, climate)) {
this->deferred_message_queue_.defer(climate, try_send_climate_state);
}
return true;
}
void APIConnection::send_climate_info(climate::Climate *climate) {
if (!APIConnection::try_send_climate_info(this, climate)) {
this->deferred_message_queue_.defer(climate, try_send_climate_info);
}
}
bool APIConnection::try_send_climate_state(APIConnection *api, void *v_climate) {
climate::Climate *climate = reinterpret_cast<climate::Climate *>(v_climate);
auto traits = climate->get_traits();
ClimateStateResponse resp{};
resp.key = climate->get_object_id_hash();
@ -583,9 +749,10 @@ bool APIConnection::send_climate_state(climate::Climate *climate) {
resp.current_humidity = climate->current_humidity;
if (traits.get_supports_target_humidity())
resp.target_humidity = climate->target_humidity;
return this->send_climate_state_response(resp);
return api->send_climate_state_response(resp);
}
bool APIConnection::send_climate_info(climate::Climate *climate) {
bool APIConnection::try_send_climate_info(APIConnection *api, void *v_climate) {
climate::Climate *climate = reinterpret_cast<climate::Climate *>(v_climate);
auto traits = climate->get_traits();
ListEntitiesClimateResponse msg;
msg.key = climate->get_object_id_hash();
@ -626,7 +793,7 @@ bool APIConnection::send_climate_info(climate::Climate *climate) {
msg.supported_custom_presets.push_back(custom_preset);
for (auto swing_mode : traits.get_supported_swing_modes())
msg.supported_swing_modes.push_back(static_cast<enums::ClimateSwingMode>(swing_mode));
return this->send_list_entities_climate_response(msg);
return api->send_list_entities_climate_response(msg);
}
void APIConnection::climate_command(const ClimateCommandRequest &msg) {
climate::Climate *climate = App.get_climate_by_key(msg.key);
@ -663,13 +830,30 @@ bool APIConnection::send_number_state(number::Number *number, float state) {
if (!this->state_subscription_)
return false;
if (!APIConnection::try_send_number_state(this, number, state)) {
this->deferred_message_queue_.defer(number, try_send_number_state);
}
return true;
}
void APIConnection::send_number_info(number::Number *number) {
if (!APIConnection::try_send_number_info(this, number)) {
this->deferred_message_queue_.defer(number, try_send_number_info);
}
}
bool APIConnection::try_send_number_state(APIConnection *api, void *v_number) {
number::Number *number = reinterpret_cast<number::Number *>(v_number);
return APIConnection::try_send_number_state(api, number, number->state);
}
bool APIConnection::try_send_number_state(APIConnection *api, number::Number *number, float state) {
NumberStateResponse resp{};
resp.key = number->get_object_id_hash();
resp.state = state;
resp.missing_state = !number->has_state();
return this->send_number_state_response(resp);
return api->send_number_state_response(resp);
}
bool APIConnection::send_number_info(number::Number *number) {
bool APIConnection::try_send_number_info(APIConnection *api, void *v_number) {
number::Number *number = reinterpret_cast<number::Number *>(v_number);
ListEntitiesNumberResponse msg;
msg.key = number->get_object_id_hash();
msg.object_id = number->get_object_id();
@ -687,7 +871,7 @@ bool APIConnection::send_number_info(number::Number *number) {
msg.max_value = number->traits.get_max_value();
msg.step = number->traits.get_step();
return this->send_list_entities_number_response(msg);
return api->send_list_entities_number_response(msg);
}
void APIConnection::number_command(const NumberCommandRequest &msg) {
number::Number *number = App.get_number_by_key(msg.key);
@ -705,15 +889,29 @@ bool APIConnection::send_date_state(datetime::DateEntity *date) {
if (!this->state_subscription_)
return false;
if (!APIConnection::try_send_date_state(this, date)) {
this->deferred_message_queue_.defer(date, try_send_date_state);
}
return true;
}
void APIConnection::send_date_info(datetime::DateEntity *date) {
if (!APIConnection::try_send_date_info(this, date)) {
this->deferred_message_queue_.defer(date, try_send_date_info);
}
}
bool APIConnection::try_send_date_state(APIConnection *api, void *v_date) {
datetime::DateEntity *date = reinterpret_cast<datetime::DateEntity *>(v_date);
DateStateResponse resp{};
resp.key = date->get_object_id_hash();
resp.missing_state = !date->has_state();
resp.year = date->year;
resp.month = date->month;
resp.day = date->day;
return this->send_date_state_response(resp);
return api->send_date_state_response(resp);
}
bool APIConnection::send_date_info(datetime::DateEntity *date) {
bool APIConnection::try_send_date_info(APIConnection *api, void *v_date) {
datetime::DateEntity *date = reinterpret_cast<datetime::DateEntity *>(v_date);
ListEntitiesDateResponse msg;
msg.key = date->get_object_id_hash();
msg.object_id = date->get_object_id();
@ -724,7 +922,7 @@ bool APIConnection::send_date_info(datetime::DateEntity *date) {
msg.disabled_by_default = date->is_disabled_by_default();
msg.entity_category = static_cast<enums::EntityCategory>(date->get_entity_category());
return this->send_list_entities_date_response(msg);
return api->send_list_entities_date_response(msg);
}
void APIConnection::date_command(const DateCommandRequest &msg) {
datetime::DateEntity *date = App.get_date_by_key(msg.key);
@ -742,15 +940,29 @@ bool APIConnection::send_time_state(datetime::TimeEntity *time) {
if (!this->state_subscription_)
return false;
if (!APIConnection::try_send_time_state(this, time)) {
this->deferred_message_queue_.defer(time, try_send_time_state);
}
return true;
}
void APIConnection::send_time_info(datetime::TimeEntity *time) {
if (!APIConnection::try_send_time_info(this, time)) {
this->deferred_message_queue_.defer(time, try_send_time_info);
}
}
bool APIConnection::try_send_time_state(APIConnection *api, void *v_time) {
datetime::TimeEntity *time = reinterpret_cast<datetime::TimeEntity *>(v_time);
TimeStateResponse resp{};
resp.key = time->get_object_id_hash();
resp.missing_state = !time->has_state();
resp.hour = time->hour;
resp.minute = time->minute;
resp.second = time->second;
return this->send_time_state_response(resp);
return api->send_time_state_response(resp);
}
bool APIConnection::send_time_info(datetime::TimeEntity *time) {
bool APIConnection::try_send_time_info(APIConnection *api, void *v_time) {
datetime::TimeEntity *time = reinterpret_cast<datetime::TimeEntity *>(v_time);
ListEntitiesTimeResponse msg;
msg.key = time->get_object_id_hash();
msg.object_id = time->get_object_id();
@ -761,7 +973,7 @@ bool APIConnection::send_time_info(datetime::TimeEntity *time) {
msg.disabled_by_default = time->is_disabled_by_default();
msg.entity_category = static_cast<enums::EntityCategory>(time->get_entity_category());
return this->send_list_entities_time_response(msg);
return api->send_list_entities_time_response(msg);
}
void APIConnection::time_command(const TimeCommandRequest &msg) {
datetime::TimeEntity *time = App.get_time_by_key(msg.key);
@ -779,6 +991,19 @@ bool APIConnection::send_datetime_state(datetime::DateTimeEntity *datetime) {
if (!this->state_subscription_)
return false;
if (!APIConnection::try_send_datetime_state(this, datetime)) {
this->deferred_message_queue_.defer(datetime, try_send_datetime_state);
}
return true;
}
void APIConnection::send_datetime_info(datetime::DateTimeEntity *datetime) {
if (!APIConnection::try_send_datetime_info(this, datetime)) {
this->deferred_message_queue_.defer(datetime, try_send_datetime_info);
}
}
bool APIConnection::try_send_datetime_state(APIConnection *api, void *v_datetime) {
datetime::DateTimeEntity *datetime = reinterpret_cast<datetime::DateTimeEntity *>(v_datetime);
DateTimeStateResponse resp{};
resp.key = datetime->get_object_id_hash();
resp.missing_state = !datetime->has_state();
@ -786,9 +1011,10 @@ bool APIConnection::send_datetime_state(datetime::DateTimeEntity *datetime) {
ESPTime state = datetime->state_as_esptime();
resp.epoch_seconds = state.timestamp;
}
return this->send_date_time_state_response(resp);
return api->send_date_time_state_response(resp);
}
bool APIConnection::send_datetime_info(datetime::DateTimeEntity *datetime) {
bool APIConnection::try_send_datetime_info(APIConnection *api, void *v_datetime) {
datetime::DateTimeEntity *datetime = reinterpret_cast<datetime::DateTimeEntity *>(v_datetime);
ListEntitiesDateTimeResponse msg;
msg.key = datetime->get_object_id_hash();
msg.object_id = datetime->get_object_id();
@ -799,7 +1025,7 @@ bool APIConnection::send_datetime_info(datetime::DateTimeEntity *datetime) {
msg.disabled_by_default = datetime->is_disabled_by_default();
msg.entity_category = static_cast<enums::EntityCategory>(datetime->get_entity_category());
return this->send_list_entities_date_time_response(msg);
return api->send_list_entities_date_time_response(msg);
}
void APIConnection::datetime_command(const DateTimeCommandRequest &msg) {
datetime::DateTimeEntity *datetime = App.get_datetime_by_key(msg.key);
@ -817,13 +1043,30 @@ bool APIConnection::send_text_state(text::Text *text, std::string state) {
if (!this->state_subscription_)
return false;
if (!APIConnection::try_send_text_state(this, text, std::move(state))) {
this->deferred_message_queue_.defer(text, try_send_text_state);
}
return true;
}
void APIConnection::send_text_info(text::Text *text) {
if (!APIConnection::try_send_text_info(this, text)) {
this->deferred_message_queue_.defer(text, try_send_text_info);
}
}
bool APIConnection::try_send_text_state(APIConnection *api, void *v_text) {
text::Text *text = reinterpret_cast<text::Text *>(v_text);
return APIConnection::try_send_text_state(api, text, text->state);
}
bool APIConnection::try_send_text_state(APIConnection *api, text::Text *text, std::string state) {
TextStateResponse resp{};
resp.key = text->get_object_id_hash();
resp.state = std::move(state);
resp.missing_state = !text->has_state();
return this->send_text_state_response(resp);
return api->send_text_state_response(resp);
}
bool APIConnection::send_text_info(text::Text *text) {
bool APIConnection::try_send_text_info(APIConnection *api, void *v_text) {
text::Text *text = reinterpret_cast<text::Text *>(v_text);
ListEntitiesTextResponse msg;
msg.key = text->get_object_id_hash();
msg.object_id = text->get_object_id();
@ -837,7 +1080,7 @@ bool APIConnection::send_text_info(text::Text *text) {
msg.max_length = text->traits.get_max_length();
msg.pattern = text->traits.get_pattern();
return this->send_list_entities_text_response(msg);
return api->send_list_entities_text_response(msg);
}
void APIConnection::text_command(const TextCommandRequest &msg) {
text::Text *text = App.get_text_by_key(msg.key);
@ -855,13 +1098,30 @@ bool APIConnection::send_select_state(select::Select *select, std::string state)
if (!this->state_subscription_)
return false;
if (!APIConnection::try_send_select_state(this, select, std::move(state))) {
this->deferred_message_queue_.defer(select, try_send_select_state);
}
return true;
}
void APIConnection::send_select_info(select::Select *select) {
if (!APIConnection::try_send_select_info(this, select)) {
this->deferred_message_queue_.defer(select, try_send_select_info);
}
}
bool APIConnection::try_send_select_state(APIConnection *api, void *v_select) {
select::Select *select = reinterpret_cast<select::Select *>(v_select);
return APIConnection::try_send_select_state(api, select, select->state);
}
bool APIConnection::try_send_select_state(APIConnection *api, select::Select *select, std::string state) {
SelectStateResponse resp{};
resp.key = select->get_object_id_hash();
resp.state = std::move(state);
resp.missing_state = !select->has_state();
return this->send_select_state_response(resp);
return api->send_select_state_response(resp);
}
bool APIConnection::send_select_info(select::Select *select) {
bool APIConnection::try_send_select_info(APIConnection *api, void *v_select) {
select::Select *select = reinterpret_cast<select::Select *>(v_select);
ListEntitiesSelectResponse msg;
msg.key = select->get_object_id_hash();
msg.object_id = select->get_object_id();
@ -875,7 +1135,7 @@ bool APIConnection::send_select_info(select::Select *select) {
for (const auto &option : select->traits.get_options())
msg.options.push_back(option);
return this->send_list_entities_select_response(msg);
return api->send_list_entities_select_response(msg);
}
void APIConnection::select_command(const SelectCommandRequest &msg) {
select::Select *select = App.get_select_by_key(msg.key);
@ -889,7 +1149,13 @@ void APIConnection::select_command(const SelectCommandRequest &msg) {
#endif
#ifdef USE_BUTTON
bool APIConnection::send_button_info(button::Button *button) {
void APIConnection::send_button_info(button::Button *button) {
if (!APIConnection::try_send_button_info(this, button)) {
this->deferred_message_queue_.defer(button, try_send_button_info);
}
}
bool APIConnection::try_send_button_info(APIConnection *api, void *v_button) {
button::Button *button = reinterpret_cast<button::Button *>(v_button);
ListEntitiesButtonResponse msg;
msg.key = button->get_object_id_hash();
msg.object_id = button->get_object_id();
@ -900,7 +1166,7 @@ bool APIConnection::send_button_info(button::Button *button) {
msg.disabled_by_default = button->is_disabled_by_default();
msg.entity_category = static_cast<enums::EntityCategory>(button->get_entity_category());
msg.device_class = button->get_device_class();
return this->send_list_entities_button_response(msg);
return api->send_list_entities_button_response(msg);
}
void APIConnection::button_command(const ButtonCommandRequest &msg) {
button::Button *button = App.get_button_by_key(msg.key);
@ -916,12 +1182,29 @@ bool APIConnection::send_lock_state(lock::Lock *a_lock, lock::LockState state) {
if (!this->state_subscription_)
return false;
if (!APIConnection::try_send_lock_state(this, a_lock, state)) {
this->deferred_message_queue_.defer(a_lock, try_send_lock_state);
}
return true;
}
void APIConnection::send_lock_info(lock::Lock *a_lock) {
if (!APIConnection::try_send_lock_info(this, a_lock)) {
this->deferred_message_queue_.defer(a_lock, try_send_lock_info);
}
}
bool APIConnection::try_send_lock_state(APIConnection *api, void *v_a_lock) {
lock::Lock *a_lock = reinterpret_cast<lock::Lock *>(v_a_lock);
return APIConnection::try_send_lock_state(api, a_lock, a_lock->state);
}
bool APIConnection::try_send_lock_state(APIConnection *api, lock::Lock *a_lock, lock::LockState state) {
LockStateResponse resp{};
resp.key = a_lock->get_object_id_hash();
resp.state = static_cast<enums::LockState>(state);
return this->send_lock_state_response(resp);
return api->send_lock_state_response(resp);
}
bool APIConnection::send_lock_info(lock::Lock *a_lock) {
bool APIConnection::try_send_lock_info(APIConnection *api, void *v_a_lock) {
lock::Lock *a_lock = reinterpret_cast<lock::Lock *>(v_a_lock);
ListEntitiesLockResponse msg;
msg.key = a_lock->get_object_id_hash();
msg.object_id = a_lock->get_object_id();
@ -934,7 +1217,7 @@ bool APIConnection::send_lock_info(lock::Lock *a_lock) {
msg.entity_category = static_cast<enums::EntityCategory>(a_lock->get_entity_category());
msg.supports_open = a_lock->traits.get_supports_open();
msg.requires_code = a_lock->traits.get_requires_code();
return this->send_list_entities_lock_response(msg);
return api->send_list_entities_lock_response(msg);
}
void APIConnection::lock_command(const LockCommandRequest &msg) {
lock::Lock *a_lock = App.get_lock_by_key(msg.key);
@ -960,13 +1243,27 @@ bool APIConnection::send_valve_state(valve::Valve *valve) {
if (!this->state_subscription_)
return false;
if (!APIConnection::try_send_valve_state(this, valve)) {
this->deferred_message_queue_.defer(valve, try_send_valve_state);
}
return true;
}
void APIConnection::send_valve_info(valve::Valve *valve) {
if (!APIConnection::try_send_valve_info(this, valve)) {
this->deferred_message_queue_.defer(valve, try_send_valve_info);
}
}
bool APIConnection::try_send_valve_state(APIConnection *api, void *v_valve) {
valve::Valve *valve = reinterpret_cast<valve::Valve *>(v_valve);
ValveStateResponse resp{};
resp.key = valve->get_object_id_hash();
resp.position = valve->position;
resp.current_operation = static_cast<enums::ValveOperation>(valve->current_operation);
return this->send_valve_state_response(resp);
return api->send_valve_state_response(resp);
}
bool APIConnection::send_valve_info(valve::Valve *valve) {
bool APIConnection::try_send_valve_info(APIConnection *api, void *v_valve) {
valve::Valve *valve = reinterpret_cast<valve::Valve *>(v_valve);
auto traits = valve->get_traits();
ListEntitiesValveResponse msg;
msg.key = valve->get_object_id_hash();
@ -981,7 +1278,7 @@ bool APIConnection::send_valve_info(valve::Valve *valve) {
msg.assumed_state = traits.get_is_assumed_state();
msg.supports_position = traits.get_supports_position();
msg.supports_stop = traits.get_supports_stop();
return this->send_list_entities_valve_response(msg);
return api->send_list_entities_valve_response(msg);
}
void APIConnection::valve_command(const ValveCommandRequest &msg) {
valve::Valve *valve = App.get_valve_by_key(msg.key);
@ -1002,6 +1299,19 @@ bool APIConnection::send_media_player_state(media_player::MediaPlayer *media_pla
if (!this->state_subscription_)
return false;
if (!APIConnection::try_send_media_player_state(this, media_player)) {
this->deferred_message_queue_.defer(media_player, try_send_media_player_state);
}
return true;
}
void APIConnection::send_media_player_info(media_player::MediaPlayer *media_player) {
if (!APIConnection::try_send_media_player_info(this, media_player)) {
this->deferred_message_queue_.defer(media_player, try_send_media_player_info);
}
}
bool APIConnection::try_send_media_player_state(APIConnection *api, void *v_media_player) {
media_player::MediaPlayer *media_player = reinterpret_cast<media_player::MediaPlayer *>(v_media_player);
MediaPlayerStateResponse resp{};
resp.key = media_player->get_object_id_hash();
@ -1011,9 +1321,10 @@ bool APIConnection::send_media_player_state(media_player::MediaPlayer *media_pla
resp.state = static_cast<enums::MediaPlayerState>(report_state);
resp.volume = media_player->volume;
resp.muted = media_player->is_muted();
return this->send_media_player_state_response(resp);
return api->send_media_player_state_response(resp);
}
bool APIConnection::send_media_player_info(media_player::MediaPlayer *media_player) {
bool APIConnection::try_send_media_player_info(APIConnection *api, void *v_media_player) {
media_player::MediaPlayer *media_player = reinterpret_cast<media_player::MediaPlayer *>(v_media_player);
ListEntitiesMediaPlayerResponse msg;
msg.key = media_player->get_object_id_hash();
msg.object_id = media_player->get_object_id();
@ -1037,7 +1348,7 @@ bool APIConnection::send_media_player_info(media_player::MediaPlayer *media_play
msg.supported_formats.push_back(media_format);
}
return this->send_list_entities_media_player_response(msg);
return api->send_list_entities_media_player_response(msg);
}
void APIConnection::media_player_command(const MediaPlayerCommandRequest &msg) {
media_player::MediaPlayer *media_player = App.get_media_player_by_key(msg.key);
@ -1062,7 +1373,7 @@ void APIConnection::media_player_command(const MediaPlayerCommandRequest &msg) {
#endif
#ifdef USE_ESP32_CAMERA
void APIConnection::send_camera_state(std::shared_ptr<esp32_camera::CameraImage> image) {
void APIConnection::set_camera_state(std::shared_ptr<esp32_camera::CameraImage> image) {
if (!this->state_subscription_)
return;
if (this->image_reader_.available())
@ -1071,7 +1382,13 @@ void APIConnection::send_camera_state(std::shared_ptr<esp32_camera::CameraImage>
image->was_requested_by(esphome::esp32_camera::IDLE))
this->image_reader_.set_image(std::move(image));
}
bool APIConnection::send_camera_info(esp32_camera::ESP32Camera *camera) {
void APIConnection::send_camera_info(esp32_camera::ESP32Camera *camera) {
if (!APIConnection::try_send_camera_info(this, camera)) {
this->deferred_message_queue_.defer(camera, try_send_camera_info);
}
}
bool APIConnection::try_send_camera_info(APIConnection *api, void *v_camera) {
esp32_camera::ESP32Camera *camera = reinterpret_cast<esp32_camera::ESP32Camera *>(v_camera);
ListEntitiesCameraResponse msg;
msg.key = camera->get_object_id_hash();
msg.object_id = camera->get_object_id();
@ -1081,7 +1398,7 @@ bool APIConnection::send_camera_info(esp32_camera::ESP32Camera *camera) {
msg.disabled_by_default = camera->is_disabled_by_default();
msg.icon = camera->get_icon();
msg.entity_category = static_cast<enums::EntityCategory>(camera->get_entity_category());
return this->send_list_entities_camera_response(msg);
return api->send_list_entities_camera_response(msg);
}
void APIConnection::camera_image(const CameraImageRequest &msg) {
if (esp32_camera::global_esp32_camera == nullptr)
@ -1268,12 +1585,28 @@ bool APIConnection::send_alarm_control_panel_state(alarm_control_panel::AlarmCon
if (!this->state_subscription_)
return false;
if (!APIConnection::try_send_alarm_control_panel_state(this, a_alarm_control_panel)) {
this->deferred_message_queue_.defer(a_alarm_control_panel, try_send_alarm_control_panel_state);
}
return true;
}
void APIConnection::send_alarm_control_panel_info(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) {
if (!APIConnection::try_send_alarm_control_panel_info(this, a_alarm_control_panel)) {
this->deferred_message_queue_.defer(a_alarm_control_panel, try_send_alarm_control_panel_info);
}
}
bool APIConnection::try_send_alarm_control_panel_state(APIConnection *api, void *v_a_alarm_control_panel) {
alarm_control_panel::AlarmControlPanel *a_alarm_control_panel =
reinterpret_cast<alarm_control_panel::AlarmControlPanel *>(v_a_alarm_control_panel);
AlarmControlPanelStateResponse resp{};
resp.key = a_alarm_control_panel->get_object_id_hash();
resp.state = static_cast<enums::AlarmControlPanelState>(a_alarm_control_panel->get_state());
return this->send_alarm_control_panel_state_response(resp);
return api->send_alarm_control_panel_state_response(resp);
}
bool APIConnection::send_alarm_control_panel_info(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) {
bool APIConnection::try_send_alarm_control_panel_info(APIConnection *api, void *v_a_alarm_control_panel) {
alarm_control_panel::AlarmControlPanel *a_alarm_control_panel =
reinterpret_cast<alarm_control_panel::AlarmControlPanel *>(v_a_alarm_control_panel);
ListEntitiesAlarmControlPanelResponse msg;
msg.key = a_alarm_control_panel->get_object_id_hash();
msg.object_id = a_alarm_control_panel->get_object_id();
@ -1285,7 +1618,7 @@ bool APIConnection::send_alarm_control_panel_info(alarm_control_panel::AlarmCont
msg.supported_features = a_alarm_control_panel->get_supported_features();
msg.requires_code = a_alarm_control_panel->get_requires_code();
msg.requires_code_to_arm = a_alarm_control_panel->get_requires_code_to_arm();
return this->send_list_entities_alarm_control_panel_response(msg);
return api->send_list_entities_alarm_control_panel_response(msg);
}
void APIConnection::alarm_control_panel_command(const AlarmControlPanelCommandRequest &msg) {
alarm_control_panel::AlarmControlPanel *a_alarm_control_panel = App.get_alarm_control_panel_by_key(msg.key);
@ -1322,13 +1655,28 @@ void APIConnection::alarm_control_panel_command(const AlarmControlPanelCommandRe
#endif
#ifdef USE_EVENT
bool APIConnection::send_event(event::Event *event, std::string event_type) {
void APIConnection::send_event(event::Event *event, std::string event_type) {
if (!APIConnection::try_send_event(this, event, std::move(event_type))) {
this->deferred_message_queue_.defer(event, try_send_event);
}
}
void APIConnection::send_event_info(event::Event *event) {
if (!APIConnection::try_send_event_info(this, event)) {
this->deferred_message_queue_.defer(event, try_send_event_info);
}
}
bool APIConnection::try_send_event(APIConnection *api, void *v_event) {
event::Event *event = reinterpret_cast<event::Event *>(v_event);
return APIConnection::try_send_event(api, event, *(event->last_event_type));
}
bool APIConnection::try_send_event(APIConnection *api, event::Event *event, std::string event_type) {
EventResponse resp{};
resp.key = event->get_object_id_hash();
resp.event_type = std::move(event_type);
return this->send_event_response(resp);
return api->send_event_response(resp);
}
bool APIConnection::send_event_info(event::Event *event) {
bool APIConnection::try_send_event_info(APIConnection *api, void *v_event) {
event::Event *event = reinterpret_cast<event::Event *>(v_event);
ListEntitiesEventResponse msg;
msg.key = event->get_object_id_hash();
msg.object_id = event->get_object_id();
@ -1341,7 +1689,7 @@ bool APIConnection::send_event_info(event::Event *event) {
msg.device_class = event->get_device_class();
for (const auto &event_type : event->get_event_types())
msg.event_types.push_back(event_type);
return this->send_list_entities_event_response(msg);
return api->send_list_entities_event_response(msg);
}
#endif
@ -1350,6 +1698,19 @@ bool APIConnection::send_update_state(update::UpdateEntity *update) {
if (!this->state_subscription_)
return false;
if (!APIConnection::try_send_update_state(this, update)) {
this->deferred_message_queue_.defer(update, try_send_update_state);
}
return true;
}
void APIConnection::send_update_info(update::UpdateEntity *update) {
if (!APIConnection::try_send_update_info(this, update)) {
this->deferred_message_queue_.defer(update, try_send_update_info);
}
}
bool APIConnection::try_send_update_state(APIConnection *api, void *v_update) {
update::UpdateEntity *update = reinterpret_cast<update::UpdateEntity *>(v_update);
UpdateStateResponse resp{};
resp.key = update->get_object_id_hash();
resp.missing_state = !update->has_state();
@ -1366,9 +1727,10 @@ bool APIConnection::send_update_state(update::UpdateEntity *update) {
resp.release_url = update->update_info.release_url;
}
return this->send_update_state_response(resp);
return api->send_update_state_response(resp);
}
bool APIConnection::send_update_info(update::UpdateEntity *update) {
bool APIConnection::try_send_update_info(APIConnection *api, void *v_update) {
update::UpdateEntity *update = reinterpret_cast<update::UpdateEntity *>(v_update);
ListEntitiesUpdateResponse msg;
msg.key = update->get_object_id_hash();
msg.object_id = update->get_object_id();
@ -1379,7 +1741,7 @@ bool APIConnection::send_update_info(update::UpdateEntity *update) {
msg.disabled_by_default = update->is_disabled_by_default();
msg.entity_category = static_cast<enums::EntityCategory>(update->get_entity_category());
msg.device_class = update->get_device_class();
return this->send_list_entities_update_response(msg);
return api->send_list_entities_update_response(msg);
}
void APIConnection::update_command(const UpdateCommandRequest &msg) {
update::UpdateEntity *update = App.get_update_by_key(msg.key);
@ -1403,7 +1765,7 @@ void APIConnection::update_command(const UpdateCommandRequest &msg) {
}
#endif
bool APIConnection::send_log_message(int level, const char *tag, const char *line) {
bool APIConnection::try_send_log_message(int level, const char *tag, const char *line) {
if (this->log_subscription_ < level)
return false;
@ -1488,10 +1850,14 @@ DeviceInfoResponse APIConnection::device_info(const DeviceInfoRequest &msg) {
#ifdef USE_BLUETOOTH_PROXY
resp.legacy_bluetooth_proxy_version = bluetooth_proxy::global_bluetooth_proxy->get_legacy_version();
resp.bluetooth_proxy_feature_flags = bluetooth_proxy::global_bluetooth_proxy->get_feature_flags();
resp.bluetooth_mac_address = bluetooth_proxy::global_bluetooth_proxy->get_bluetooth_mac_address_pretty();
#endif
#ifdef USE_VOICE_ASSISTANT
resp.legacy_voice_assistant_version = voice_assistant::global_voice_assistant->get_legacy_version();
resp.voice_assistant_feature_flags = voice_assistant::global_voice_assistant->get_feature_flags();
#endif
#ifdef USE_API_NOISE
resp.api_encryption_supported = true;
#endif
return resp;
}
@ -1513,6 +1879,26 @@ void APIConnection::execute_service(const ExecuteServiceRequest &msg) {
ESP_LOGV(TAG, "Could not find matching service!");
}
}
#ifdef USE_API_NOISE
NoiseEncryptionSetKeyResponse APIConnection::noise_encryption_set_key(const NoiseEncryptionSetKeyRequest &msg) {
psk_t psk{};
NoiseEncryptionSetKeyResponse resp;
if (base64_decode(msg.key, psk.data(), msg.key.size()) != psk.size()) {
ESP_LOGW(TAG, "Invalid encryption key length");
resp.success = false;
return resp;
}
if (!this->parent_->save_noise_psk(psk, true)) {
ESP_LOGW(TAG, "Failed to save encryption key");
resp.success = false;
return resp;
}
resp.success = true;
return resp;
}
#endif
void APIConnection::subscribe_home_assistant_states(const SubscribeHomeAssistantStatesRequest &msg) {
state_subs_at_ = 0;
}

View File

@ -14,6 +14,46 @@
namespace esphome {
namespace api {
using send_message_t = bool(APIConnection *, void *);
/*
This class holds a pointer to the source component that wants to publish a message, and a pointer to a function that
will lazily publish that message. The two pointers allow dedup in the deferred queue if multiple publishes for the
same component are backed up, and take up only 8 bytes of memory. The entry in the deferred queue (a std::vector) is
the DeferredMessage instance itself (not a pointer to one elsewhere in heap) so still only 8 bytes per entry. Even
100 backed up messages (you'd have to have at least 100 sensors publishing because of dedup) would take up only 0.8
kB.
*/
class DeferredMessageQueue {
struct DeferredMessage {
friend class DeferredMessageQueue;
protected:
void *source_;
send_message_t *send_message_;
public:
DeferredMessage(void *source, send_message_t *send_message) : source_(source), send_message_(send_message) {}
bool operator==(const DeferredMessage &test) const {
return (source_ == test.source_ && send_message_ == test.send_message_);
}
} __attribute__((packed));
protected:
// vector is used very specifically for its zero memory overhead even though items are popped from the front (memory
// footprint is more important than speed here)
std::vector<DeferredMessage> deferred_queue_;
APIConnection *api_connection_;
// helper for allowing only unique entries in the queue
void dmq_push_back_with_dedup_(void *source, send_message_t *send_message);
public:
DeferredMessageQueue(APIConnection *api_connection) : api_connection_(api_connection) {}
void process_queue();
void defer(void *source, send_message_t *send_message);
};
class APIConnection : public APIServerConnection {
public:
APIConnection(std::unique_ptr<socket::Socket> socket, APIServer *parent);
@ -28,96 +68,140 @@ class APIConnection : public APIServerConnection {
}
#ifdef USE_BINARY_SENSOR
bool send_binary_sensor_state(binary_sensor::BinarySensor *binary_sensor, bool state);
bool send_binary_sensor_info(binary_sensor::BinarySensor *binary_sensor);
void send_binary_sensor_info(binary_sensor::BinarySensor *binary_sensor);
static bool try_send_binary_sensor_state(APIConnection *api, void *v_binary_sensor);
static bool try_send_binary_sensor_state(APIConnection *api, binary_sensor::BinarySensor *binary_sensor, bool state);
static bool try_send_binary_sensor_info(APIConnection *api, void *v_binary_sensor);
#endif
#ifdef USE_COVER
bool send_cover_state(cover::Cover *cover);
bool send_cover_info(cover::Cover *cover);
void send_cover_info(cover::Cover *cover);
static bool try_send_cover_state(APIConnection *api, void *v_cover);
static bool try_send_cover_info(APIConnection *api, void *v_cover);
void cover_command(const CoverCommandRequest &msg) override;
#endif
#ifdef USE_FAN
bool send_fan_state(fan::Fan *fan);
bool send_fan_info(fan::Fan *fan);
void send_fan_info(fan::Fan *fan);
static bool try_send_fan_state(APIConnection *api, void *v_fan);
static bool try_send_fan_info(APIConnection *api, void *v_fan);
void fan_command(const FanCommandRequest &msg) override;
#endif
#ifdef USE_LIGHT
bool send_light_state(light::LightState *light);
bool send_light_info(light::LightState *light);
void send_light_info(light::LightState *light);
static bool try_send_light_state(APIConnection *api, void *v_light);
static bool try_send_light_info(APIConnection *api, void *v_light);
void light_command(const LightCommandRequest &msg) override;
#endif
#ifdef USE_SENSOR
bool send_sensor_state(sensor::Sensor *sensor, float state);
bool send_sensor_info(sensor::Sensor *sensor);
void send_sensor_info(sensor::Sensor *sensor);
static bool try_send_sensor_state(APIConnection *api, void *v_sensor);
static bool try_send_sensor_state(APIConnection *api, sensor::Sensor *sensor, float state);
static bool try_send_sensor_info(APIConnection *api, void *v_sensor);
#endif
#ifdef USE_SWITCH
bool send_switch_state(switch_::Switch *a_switch, bool state);
bool send_switch_info(switch_::Switch *a_switch);
void send_switch_info(switch_::Switch *a_switch);
static bool try_send_switch_state(APIConnection *api, void *v_a_switch);
static bool try_send_switch_state(APIConnection *api, switch_::Switch *a_switch, bool state);
static bool try_send_switch_info(APIConnection *api, void *v_a_switch);
void switch_command(const SwitchCommandRequest &msg) override;
#endif
#ifdef USE_TEXT_SENSOR
bool send_text_sensor_state(text_sensor::TextSensor *text_sensor, std::string state);
bool send_text_sensor_info(text_sensor::TextSensor *text_sensor);
void send_text_sensor_info(text_sensor::TextSensor *text_sensor);
static bool try_send_text_sensor_state(APIConnection *api, void *v_text_sensor);
static bool try_send_text_sensor_state(APIConnection *api, text_sensor::TextSensor *text_sensor, std::string state);
static bool try_send_text_sensor_info(APIConnection *api, void *v_text_sensor);
#endif
#ifdef USE_ESP32_CAMERA
void send_camera_state(std::shared_ptr<esp32_camera::CameraImage> image);
bool send_camera_info(esp32_camera::ESP32Camera *camera);
void set_camera_state(std::shared_ptr<esp32_camera::CameraImage> image);
void send_camera_info(esp32_camera::ESP32Camera *camera);
static bool try_send_camera_info(APIConnection *api, void *v_camera);
void camera_image(const CameraImageRequest &msg) override;
#endif
#ifdef USE_CLIMATE
bool send_climate_state(climate::Climate *climate);
bool send_climate_info(climate::Climate *climate);
void send_climate_info(climate::Climate *climate);
static bool try_send_climate_state(APIConnection *api, void *v_climate);
static bool try_send_climate_info(APIConnection *api, void *v_climate);
void climate_command(const ClimateCommandRequest &msg) override;
#endif
#ifdef USE_NUMBER
bool send_number_state(number::Number *number, float state);
bool send_number_info(number::Number *number);
void send_number_info(number::Number *number);
static bool try_send_number_state(APIConnection *api, void *v_number);
static bool try_send_number_state(APIConnection *api, number::Number *number, float state);
static bool try_send_number_info(APIConnection *api, void *v_number);
void number_command(const NumberCommandRequest &msg) override;
#endif
#ifdef USE_DATETIME_DATE
bool send_date_state(datetime::DateEntity *date);
bool send_date_info(datetime::DateEntity *date);
void send_date_info(datetime::DateEntity *date);
static bool try_send_date_state(APIConnection *api, void *v_date);
static bool try_send_date_info(APIConnection *api, void *v_date);
void date_command(const DateCommandRequest &msg) override;
#endif
#ifdef USE_DATETIME_TIME
bool send_time_state(datetime::TimeEntity *time);
bool send_time_info(datetime::TimeEntity *time);
void send_time_info(datetime::TimeEntity *time);
static bool try_send_time_state(APIConnection *api, void *v_time);
static bool try_send_time_info(APIConnection *api, void *v_time);
void time_command(const TimeCommandRequest &msg) override;
#endif
#ifdef USE_DATETIME_DATETIME
bool send_datetime_state(datetime::DateTimeEntity *datetime);
bool send_datetime_info(datetime::DateTimeEntity *datetime);
void send_datetime_info(datetime::DateTimeEntity *datetime);
static bool try_send_datetime_state(APIConnection *api, void *v_datetime);
static bool try_send_datetime_info(APIConnection *api, void *v_datetime);
void datetime_command(const DateTimeCommandRequest &msg) override;
#endif
#ifdef USE_TEXT
bool send_text_state(text::Text *text, std::string state);
bool send_text_info(text::Text *text);
void send_text_info(text::Text *text);
static bool try_send_text_state(APIConnection *api, void *v_text);
static bool try_send_text_state(APIConnection *api, text::Text *text, std::string state);
static bool try_send_text_info(APIConnection *api, void *v_text);
void text_command(const TextCommandRequest &msg) override;
#endif
#ifdef USE_SELECT
bool send_select_state(select::Select *select, std::string state);
bool send_select_info(select::Select *select);
void send_select_info(select::Select *select);
static bool try_send_select_state(APIConnection *api, void *v_select);
static bool try_send_select_state(APIConnection *api, select::Select *select, std::string state);
static bool try_send_select_info(APIConnection *api, void *v_select);
void select_command(const SelectCommandRequest &msg) override;
#endif
#ifdef USE_BUTTON
bool send_button_info(button::Button *button);
void send_button_info(button::Button *button);
static bool try_send_button_info(APIConnection *api, void *v_button);
void button_command(const ButtonCommandRequest &msg) override;
#endif
#ifdef USE_LOCK
bool send_lock_state(lock::Lock *a_lock, lock::LockState state);
bool send_lock_info(lock::Lock *a_lock);
void send_lock_info(lock::Lock *a_lock);
static bool try_send_lock_state(APIConnection *api, void *v_a_lock);
static bool try_send_lock_state(APIConnection *api, lock::Lock *a_lock, lock::LockState state);
static bool try_send_lock_info(APIConnection *api, void *v_a_lock);
void lock_command(const LockCommandRequest &msg) override;
#endif
#ifdef USE_VALVE
bool send_valve_state(valve::Valve *valve);
bool send_valve_info(valve::Valve *valve);
void send_valve_info(valve::Valve *valve);
static bool try_send_valve_state(APIConnection *api, void *v_valve);
static bool try_send_valve_info(APIConnection *api, void *v_valve);
void valve_command(const ValveCommandRequest &msg) override;
#endif
#ifdef USE_MEDIA_PLAYER
bool send_media_player_state(media_player::MediaPlayer *media_player);
bool send_media_player_info(media_player::MediaPlayer *media_player);
void send_media_player_info(media_player::MediaPlayer *media_player);
static bool try_send_media_player_state(APIConnection *api, void *v_media_player);
static bool try_send_media_player_info(APIConnection *api, void *v_media_player);
void media_player_command(const MediaPlayerCommandRequest &msg) override;
#endif
bool send_log_message(int level, const char *tag, const char *line);
bool try_send_log_message(int level, const char *tag, const char *line);
void send_homeassistant_service_call(const HomeassistantServiceResponse &call) {
if (!this->service_call_subscription_)
return;
@ -160,18 +244,25 @@ class APIConnection : public APIServerConnection {
#ifdef USE_ALARM_CONTROL_PANEL
bool send_alarm_control_panel_state(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel);
bool send_alarm_control_panel_info(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel);
void send_alarm_control_panel_info(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel);
static bool try_send_alarm_control_panel_state(APIConnection *api, void *v_a_alarm_control_panel);
static bool try_send_alarm_control_panel_info(APIConnection *api, void *v_a_alarm_control_panel);
void alarm_control_panel_command(const AlarmControlPanelCommandRequest &msg) override;
#endif
#ifdef USE_EVENT
bool send_event(event::Event *event, std::string event_type);
bool send_event_info(event::Event *event);
void send_event(event::Event *event, std::string event_type);
void send_event_info(event::Event *event);
static bool try_send_event(APIConnection *api, void *v_event);
static bool try_send_event(APIConnection *api, event::Event *event, std::string event_type);
static bool try_send_event_info(APIConnection *api, void *v_event);
#endif
#ifdef USE_UPDATE
bool send_update_state(update::UpdateEntity *update);
bool send_update_info(update::UpdateEntity *update);
void send_update_info(update::UpdateEntity *update);
static bool try_send_update_state(APIConnection *api, void *v_update);
static bool try_send_update_info(APIConnection *api, void *v_update);
void update_command(const UpdateCommandRequest &msg) override;
#endif
@ -209,6 +300,9 @@ class APIConnection : public APIServerConnection {
return {};
}
void execute_service(const ExecuteServiceRequest &msg) override;
#ifdef USE_API_NOISE
NoiseEncryptionSetKeyResponse noise_encryption_set_key(const NoiseEncryptionSetKeyRequest &msg) override;
#endif
bool is_authenticated() override { return this->connection_state_ == ConnectionState::AUTHENTICATED; }
bool is_connection_setup() override {
@ -262,6 +356,7 @@ class APIConnection : public APIServerConnection {
bool service_call_subscription_{false};
bool next_close_ = false;
APIServer *parent_;
DeferredMessageQueue deferred_message_queue_;
InitialStateIterator initial_state_iterator_;
ListEntitiesIterator list_entities_iterator_;
int state_subs_at_ = -1;

View File

@ -311,6 +311,10 @@ APIError APINoiseFrameHelper::state_action_() {
const std::string &name = App.get_name();
const uint8_t *name_ptr = reinterpret_cast<const uint8_t *>(name.c_str());
msg.insert(msg.end(), name_ptr, name_ptr + name.size() + 1);
// node mac, terminated by null byte
const std::string &mac = get_mac_address();
const uint8_t *mac_ptr = reinterpret_cast<const uint8_t *>(mac.c_str());
msg.insert(msg.end(), mac_ptr, mac_ptr + mac.size() + 1);
aerr = write_frame_(msg.data(), msg.size());
if (aerr != APIError::OK)
@ -893,8 +897,28 @@ APIError APIPlaintextFrameHelper::read_packet(ReadPacketBuffer *buffer) {
ParsedFrame frame;
aerr = try_read_frame_(&frame);
if (aerr != APIError::OK)
if (aerr != APIError::OK) {
if (aerr == APIError::BAD_INDICATOR) {
// Make sure to tell the remote that we don't
// understand the indicator byte so it knows
// we do not support it.
struct iovec iov[1];
// The \x00 first byte is the marker for plaintext.
//
// The remote will know how to handle the indicator byte,
// but it likely won't understand the rest of the message.
//
// We must send at least 3 bytes to be read, so we add
// a message after the indicator byte to ensures its long
// enough and can aid in debugging.
const char msg[] = "\x00"
"Bad indicator byte";
iov[0].iov_base = (void *) msg;
iov[0].iov_len = 19;
write_raw_(iov, 1);
}
return aerr;
}
buffer->container = std::move(frame.msg);
buffer->data_offset = 0;

View File

@ -1,6 +1,6 @@
#pragma once
#include <cstdint>
#include <array>
#include <cstdint>
#include "esphome/core/defines.h"
namespace esphome {
@ -11,11 +11,20 @@ using psk_t = std::array<uint8_t, 32>;
class APINoiseContext {
public:
void set_psk(psk_t psk) { psk_ = psk; }
const psk_t &get_psk() const { return psk_; }
void set_psk(psk_t psk) {
this->psk_ = psk;
bool has_psk = false;
for (auto i : psk) {
has_psk |= i;
}
this->has_psk_ = has_psk;
}
const psk_t &get_psk() const { return this->psk_; }
bool has_psk() const { return this->has_psk_; }
protected:
psk_t psk_;
psk_t psk_{};
bool has_psk_{false};
};
#endif // USE_API_NOISE

View File

@ -792,6 +792,10 @@ bool DeviceInfoResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
this->voice_assistant_feature_flags = value.as_uint32();
return true;
}
case 19: {
this->api_encryption_supported = value.as_bool();
return true;
}
default:
return false;
}
@ -838,6 +842,10 @@ bool DeviceInfoResponse::decode_length(uint32_t field_id, ProtoLengthDelimited v
this->suggested_area = value.as_string();
return true;
}
case 18: {
this->bluetooth_mac_address = value.as_string();
return true;
}
default:
return false;
}
@ -860,6 +868,8 @@ void DeviceInfoResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_uint32(14, this->legacy_voice_assistant_version);
buffer.encode_uint32(17, this->voice_assistant_feature_flags);
buffer.encode_string(16, this->suggested_area);
buffer.encode_string(18, this->bluetooth_mac_address);
buffer.encode_bool(19, this->api_encryption_supported);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void DeviceInfoResponse::dump_to(std::string &out) const {
@ -937,6 +947,14 @@ void DeviceInfoResponse::dump_to(std::string &out) const {
out.append(" suggested_area: ");
out.append("'").append(this->suggested_area).append("'");
out.append("\n");
out.append(" bluetooth_mac_address: ");
out.append("'").append(this->bluetooth_mac_address).append("'");
out.append("\n");
out.append(" api_encryption_supported: ");
out.append(YESNO(this->api_encryption_supported));
out.append("\n");
out.append("}");
}
#endif
@ -3000,6 +3018,48 @@ void SubscribeLogsResponse::dump_to(std::string &out) const {
out.append("}");
}
#endif
bool NoiseEncryptionSetKeyRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
switch (field_id) {
case 1: {
this->key = value.as_string();
return true;
}
default:
return false;
}
}
void NoiseEncryptionSetKeyRequest::encode(ProtoWriteBuffer buffer) const { buffer.encode_string(1, this->key); }
#ifdef HAS_PROTO_MESSAGE_DUMP
void NoiseEncryptionSetKeyRequest::dump_to(std::string &out) const {
__attribute__((unused)) char buffer[64];
out.append("NoiseEncryptionSetKeyRequest {\n");
out.append(" key: ");
out.append("'").append(this->key).append("'");
out.append("\n");
out.append("}");
}
#endif
bool NoiseEncryptionSetKeyResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
switch (field_id) {
case 1: {
this->success = value.as_bool();
return true;
}
default:
return false;
}
}
void NoiseEncryptionSetKeyResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_bool(1, this->success); }
#ifdef HAS_PROTO_MESSAGE_DUMP
void NoiseEncryptionSetKeyResponse::dump_to(std::string &out) const {
__attribute__((unused)) char buffer[64];
out.append("NoiseEncryptionSetKeyResponse {\n");
out.append(" success: ");
out.append(YESNO(this->success));
out.append("\n");
out.append("}");
}
#endif
void SubscribeHomeassistantServicesRequest::encode(ProtoWriteBuffer buffer) const {}
#ifdef HAS_PROTO_MESSAGE_DUMP
void SubscribeHomeassistantServicesRequest::dump_to(std::string &out) const {
@ -6430,6 +6490,10 @@ bool BluetoothConnectionsFreeResponse::decode_varint(uint32_t field_id, ProtoVar
this->limit = value.as_uint32();
return true;
}
case 3: {
this->allocated.push_back(value.as_uint64());
return true;
}
default:
return false;
}
@ -6437,6 +6501,9 @@ bool BluetoothConnectionsFreeResponse::decode_varint(uint32_t field_id, ProtoVar
void BluetoothConnectionsFreeResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_uint32(1, this->free);
buffer.encode_uint32(2, this->limit);
for (auto &it : this->allocated) {
buffer.encode_uint64(3, it, true);
}
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void BluetoothConnectionsFreeResponse::dump_to(std::string &out) const {
@ -6451,6 +6518,13 @@ void BluetoothConnectionsFreeResponse::dump_to(std::string &out) const {
sprintf(buffer, "%" PRIu32, this->limit);
out.append(buffer);
out.append("\n");
for (const auto &it : this->allocated) {
out.append(" allocated: ");
sprintf(buffer, "%llu", it);
out.append(buffer);
out.append("\n");
}
out.append("}");
}
#endif
@ -7071,6 +7145,16 @@ void VoiceAssistantTimerEventResponse::dump_to(std::string &out) const {
out.append("}");
}
#endif
bool VoiceAssistantAnnounceRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
switch (field_id) {
case 4: {
this->start_conversation = value.as_bool();
return true;
}
default:
return false;
}
}
bool VoiceAssistantAnnounceRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
switch (field_id) {
case 1: {
@ -7081,6 +7165,10 @@ bool VoiceAssistantAnnounceRequest::decode_length(uint32_t field_id, ProtoLength
this->text = value.as_string();
return true;
}
case 3: {
this->preannounce_media_id = value.as_string();
return true;
}
default:
return false;
}
@ -7088,6 +7176,8 @@ bool VoiceAssistantAnnounceRequest::decode_length(uint32_t field_id, ProtoLength
void VoiceAssistantAnnounceRequest::encode(ProtoWriteBuffer buffer) const {
buffer.encode_string(1, this->media_id);
buffer.encode_string(2, this->text);
buffer.encode_string(3, this->preannounce_media_id);
buffer.encode_bool(4, this->start_conversation);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void VoiceAssistantAnnounceRequest::dump_to(std::string &out) const {
@ -7100,6 +7190,14 @@ void VoiceAssistantAnnounceRequest::dump_to(std::string &out) const {
out.append(" text: ");
out.append("'").append(this->text).append("'");
out.append("\n");
out.append(" preannounce_media_id: ");
out.append("'").append(this->preannounce_media_id).append("'");
out.append("\n");
out.append(" start_conversation: ");
out.append(YESNO(this->start_conversation));
out.append("\n");
out.append("}");
}
#endif

View File

@ -354,6 +354,8 @@ class DeviceInfoResponse : public ProtoMessage {
uint32_t legacy_voice_assistant_version{0};
uint32_t voice_assistant_feature_flags{0};
std::string suggested_area{};
std::string bluetooth_mac_address{};
bool api_encryption_supported{false};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
@ -790,6 +792,28 @@ class SubscribeLogsResponse : public ProtoMessage {
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
class NoiseEncryptionSetKeyRequest : public ProtoMessage {
public:
std::string key{};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
#endif
protected:
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
};
class NoiseEncryptionSetKeyResponse : public ProtoMessage {
public:
bool success{false};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
#endif
protected:
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
class SubscribeHomeassistantServicesRequest : public ProtoMessage {
public:
void encode(ProtoWriteBuffer buffer) const override;
@ -1624,6 +1648,7 @@ class BluetoothConnectionsFreeResponse : public ProtoMessage {
public:
uint32_t free{0};
uint32_t limit{0};
std::vector<uint64_t> allocated{};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
@ -1830,6 +1855,8 @@ class VoiceAssistantAnnounceRequest : public ProtoMessage {
public:
std::string media_id{};
std::string text{};
std::string preannounce_media_id{};
bool start_conversation{false};
void encode(ProtoWriteBuffer buffer) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
@ -1837,6 +1864,7 @@ class VoiceAssistantAnnounceRequest : public ProtoMessage {
protected:
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
class VoiceAssistantAnnounceFinished : public ProtoMessage {
public:

View File

@ -179,6 +179,16 @@ bool APIServerConnectionBase::send_text_sensor_state_response(const TextSensorSt
bool APIServerConnectionBase::send_subscribe_logs_response(const SubscribeLogsResponse &msg) {
return this->send_message_<SubscribeLogsResponse>(msg, 29);
}
#ifdef USE_API_NOISE
#endif
#ifdef USE_API_NOISE
bool APIServerConnectionBase::send_noise_encryption_set_key_response(const NoiseEncryptionSetKeyResponse &msg) {
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "send_noise_encryption_set_key_response: %s", msg.dump().c_str());
#endif
return this->send_message_<NoiseEncryptionSetKeyResponse>(msg, 125);
}
#endif
bool APIServerConnectionBase::send_homeassistant_service_response(const HomeassistantServiceResponse &msg) {
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "send_homeassistant_service_response: %s", msg.dump().c_str());
@ -1191,6 +1201,17 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
ESP_LOGVV(TAG, "on_voice_assistant_set_configuration: %s", msg.dump().c_str());
#endif
this->on_voice_assistant_set_configuration(msg);
#endif
break;
}
case 124: {
#ifdef USE_API_NOISE
NoiseEncryptionSetKeyRequest msg;
msg.decode(msg_data, msg_size);
#ifdef HAS_PROTO_MESSAGE_DUMP
ESP_LOGVV(TAG, "on_noise_encryption_set_key_request: %s", msg.dump().c_str());
#endif
this->on_noise_encryption_set_key_request(msg);
#endif
break;
}
@ -1311,6 +1332,22 @@ void APIServerConnection::on_execute_service_request(const ExecuteServiceRequest
}
this->execute_service(msg);
}
#ifdef USE_API_NOISE
void APIServerConnection::on_noise_encryption_set_key_request(const NoiseEncryptionSetKeyRequest &msg) {
if (!this->is_connection_setup()) {
this->on_no_setup_connection();
return;
}
if (!this->is_authenticated()) {
this->on_unauthenticated_access();
return;
}
NoiseEncryptionSetKeyResponse ret = this->noise_encryption_set_key(msg);
if (!this->send_noise_encryption_set_key_response(ret)) {
this->on_fatal_error();
}
}
#endif
#ifdef USE_COVER
void APIServerConnection::on_cover_command_request(const CoverCommandRequest &msg) {
if (!this->is_connection_setup()) {

View File

@ -83,6 +83,12 @@ class APIServerConnectionBase : public ProtoService {
#endif
virtual void on_subscribe_logs_request(const SubscribeLogsRequest &value){};
bool send_subscribe_logs_response(const SubscribeLogsResponse &msg);
#ifdef USE_API_NOISE
virtual void on_noise_encryption_set_key_request(const NoiseEncryptionSetKeyRequest &value){};
#endif
#ifdef USE_API_NOISE
bool send_noise_encryption_set_key_response(const NoiseEncryptionSetKeyResponse &msg);
#endif
virtual void on_subscribe_homeassistant_services_request(const SubscribeHomeassistantServicesRequest &value){};
bool send_homeassistant_service_response(const HomeassistantServiceResponse &msg);
virtual void on_subscribe_home_assistant_states_request(const SubscribeHomeAssistantStatesRequest &value){};
@ -349,6 +355,9 @@ class APIServerConnection : public APIServerConnectionBase {
virtual void subscribe_home_assistant_states(const SubscribeHomeAssistantStatesRequest &msg) = 0;
virtual GetTimeResponse get_time(const GetTimeRequest &msg) = 0;
virtual void execute_service(const ExecuteServiceRequest &msg) = 0;
#ifdef USE_API_NOISE
virtual NoiseEncryptionSetKeyResponse noise_encryption_set_key(const NoiseEncryptionSetKeyRequest &msg) = 0;
#endif
#ifdef USE_COVER
virtual void cover_command(const CoverCommandRequest &msg) = 0;
#endif
@ -457,6 +466,9 @@ class APIServerConnection : public APIServerConnectionBase {
void on_subscribe_home_assistant_states_request(const SubscribeHomeAssistantStatesRequest &msg) override;
void on_get_time_request(const GetTimeRequest &msg) override;
void on_execute_service_request(const ExecuteServiceRequest &msg) override;
#ifdef USE_API_NOISE
void on_noise_encryption_set_key_request(const NoiseEncryptionSetKeyRequest &msg) override;
#endif
#ifdef USE_COVER
void on_cover_command_request(const CoverCommandRequest &msg) override;
#endif

View File

@ -22,22 +22,40 @@ namespace api {
static const char *const TAG = "api";
// APIServer
APIServer *global_api_server = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
APIServer::APIServer() { global_api_server = this; }
void APIServer::setup() {
ESP_LOGCONFIG(TAG, "Setting up Home Assistant API server...");
this->setup_controller();
socket_ = socket::socket_ip(SOCK_STREAM, 0);
if (socket_ == nullptr) {
ESP_LOGW(TAG, "Could not create socket.");
#ifdef USE_API_NOISE
uint32_t hash = 88491486UL;
this->noise_pref_ = global_preferences->make_preference<SavedNoisePsk>(hash, true);
SavedNoisePsk noise_pref_saved{};
if (this->noise_pref_.load(&noise_pref_saved)) {
ESP_LOGD(TAG, "Loaded saved Noise PSK");
this->set_noise_psk(noise_pref_saved.psk);
}
#endif
this->socket_ = socket::socket_ip(SOCK_STREAM, 0);
if (this->socket_ == nullptr) {
ESP_LOGW(TAG, "Could not create socket");
this->mark_failed();
return;
}
int enable = 1;
int err = socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
int err = this->socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
if (err != 0) {
ESP_LOGW(TAG, "Socket unable to set reuseaddr: errno %d", err);
// we can still continue
}
err = socket_->setblocking(false);
err = this->socket_->setblocking(false);
if (err != 0) {
ESP_LOGW(TAG, "Socket unable to set nonblocking mode: errno %d", err);
this->mark_failed();
@ -53,14 +71,14 @@ void APIServer::setup() {
return;
}
err = socket_->bind((struct sockaddr *) &server, sl);
err = this->socket_->bind((struct sockaddr *) &server, sl);
if (err != 0) {
ESP_LOGW(TAG, "Socket unable to bind: errno %d", errno);
this->mark_failed();
return;
}
err = socket_->listen(4);
err = this->socket_->listen(4);
if (err != 0) {
ESP_LOGW(TAG, "Socket unable to listen: errno %d", errno);
this->mark_failed();
@ -72,7 +90,7 @@ void APIServer::setup() {
logger::global_logger->add_on_log_callback([this](int level, const char *tag, const char *message) {
for (auto &c : this->clients_) {
if (!c->remove_)
c->send_log_message(level, tag, message);
c->try_send_log_message(level, tag, message);
}
});
}
@ -86,24 +104,25 @@ void APIServer::setup() {
[this](const std::shared_ptr<esp32_camera::CameraImage> &image) {
for (auto &c : this->clients_) {
if (!c->remove_)
c->send_camera_state(image);
c->set_camera_state(image);
}
});
}
#endif
}
void APIServer::loop() {
// Accept new clients
while (true) {
struct sockaddr_storage source_addr;
socklen_t addr_len = sizeof(source_addr);
auto sock = socket_->accept((struct sockaddr *) &source_addr, &addr_len);
auto sock = this->socket_->accept((struct sockaddr *) &source_addr, &addr_len);
if (!sock)
break;
ESP_LOGD(TAG, "Accepted %s", sock->getpeername().c_str());
auto *conn = new APIConnection(std::move(sock), this);
clients_.emplace_back(conn);
this->clients_.emplace_back(conn);
conn->start();
}
@ -136,16 +155,22 @@ void APIServer::loop() {
}
}
}
void APIServer::dump_config() {
ESP_LOGCONFIG(TAG, "API Server:");
ESP_LOGCONFIG(TAG, " Address: %s:%u", network::get_use_address().c_str(), this->port_);
#ifdef USE_API_NOISE
ESP_LOGCONFIG(TAG, " Using noise encryption: YES");
ESP_LOGCONFIG(TAG, " Using noise encryption: %s", YESNO(this->noise_ctx_->has_psk()));
if (!this->noise_ctx_->has_psk()) {
ESP_LOGCONFIG(TAG, " Supports noise encryption: YES");
}
#else
ESP_LOGCONFIG(TAG, " Using noise encryption: NO");
#endif
}
bool APIServer::uses_password() const { return !this->password_.empty(); }
bool APIServer::check_password(const std::string &password) const {
// depend only on input password length
const char *a = this->password_.c_str();
@ -174,7 +199,9 @@ bool APIServer::check_password(const std::string &password) const {
return result == 0;
}
void APIServer::handle_disconnect(APIConnection *conn) {}
#ifdef USE_BINARY_SENSOR
void APIServer::on_binary_sensor_update(binary_sensor::BinarySensor *obj, bool state) {
if (obj->is_internal())
@ -342,57 +369,6 @@ void APIServer::on_update(update::UpdateEntity *obj) {
}
#endif
float APIServer::get_setup_priority() const { return setup_priority::AFTER_WIFI; }
void APIServer::set_port(uint16_t port) { this->port_ = port; }
APIServer *global_api_server = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
void APIServer::set_password(const std::string &password) { this->password_ = password; }
void APIServer::send_homeassistant_service_call(const HomeassistantServiceResponse &call) {
for (auto &client : this->clients_) {
client->send_homeassistant_service_call(call);
}
}
APIServer::APIServer() { global_api_server = this; }
void APIServer::subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute,
std::function<void(std::string)> f) {
this->state_subs_.push_back(HomeAssistantStateSubscription{
.entity_id = std::move(entity_id),
.attribute = std::move(attribute),
.callback = std::move(f),
.once = false,
});
}
void APIServer::get_home_assistant_state(std::string entity_id, optional<std::string> attribute,
std::function<void(std::string)> f) {
this->state_subs_.push_back(HomeAssistantStateSubscription{
.entity_id = std::move(entity_id),
.attribute = std::move(attribute),
.callback = std::move(f),
.once = true,
});
};
const std::vector<APIServer::HomeAssistantStateSubscription> &APIServer::get_state_subs() const {
return this->state_subs_;
}
uint16_t APIServer::get_port() const { return this->port_; }
void APIServer::set_reboot_timeout(uint32_t reboot_timeout) { this->reboot_timeout_ = reboot_timeout; }
#ifdef USE_HOMEASSISTANT_TIME
void APIServer::request_time() {
for (auto &client : this->clients_) {
if (!client->remove_ && client->is_authenticated())
client->send_time_request();
}
}
#endif
bool APIServer::is_connected() const { return !this->clients_.empty(); }
void APIServer::on_shutdown() {
for (auto &c : this->clients_) {
c->send_disconnect_request(DisconnectRequest());
}
delay(10);
}
#ifdef USE_ALARM_CONTROL_PANEL
void APIServer::on_alarm_control_panel_update(alarm_control_panel::AlarmControlPanel *obj) {
if (obj->is_internal())
@ -402,6 +378,96 @@ void APIServer::on_alarm_control_panel_update(alarm_control_panel::AlarmControlP
}
#endif
float APIServer::get_setup_priority() const { return setup_priority::AFTER_WIFI; }
void APIServer::set_port(uint16_t port) { this->port_ = port; }
void APIServer::set_password(const std::string &password) { this->password_ = password; }
void APIServer::send_homeassistant_service_call(const HomeassistantServiceResponse &call) {
for (auto &client : this->clients_) {
client->send_homeassistant_service_call(call);
}
}
void APIServer::subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute,
std::function<void(std::string)> f) {
this->state_subs_.push_back(HomeAssistantStateSubscription{
.entity_id = std::move(entity_id),
.attribute = std::move(attribute),
.callback = std::move(f),
.once = false,
});
}
void APIServer::get_home_assistant_state(std::string entity_id, optional<std::string> attribute,
std::function<void(std::string)> f) {
this->state_subs_.push_back(HomeAssistantStateSubscription{
.entity_id = std::move(entity_id),
.attribute = std::move(attribute),
.callback = std::move(f),
.once = true,
});
};
const std::vector<APIServer::HomeAssistantStateSubscription> &APIServer::get_state_subs() const {
return this->state_subs_;
}
uint16_t APIServer::get_port() const { return this->port_; }
void APIServer::set_reboot_timeout(uint32_t reboot_timeout) { this->reboot_timeout_ = reboot_timeout; }
#ifdef USE_API_NOISE
bool APIServer::save_noise_psk(psk_t psk, bool make_active) {
auto &old_psk = this->noise_ctx_->get_psk();
if (std::equal(old_psk.begin(), old_psk.end(), psk.begin())) {
ESP_LOGW(TAG, "New PSK matches old");
return true;
}
SavedNoisePsk new_saved_psk{psk};
if (!this->noise_pref_.save(&new_saved_psk)) {
ESP_LOGW(TAG, "Failed to save Noise PSK");
return false;
}
// ensure it's written immediately
if (!global_preferences->sync()) {
ESP_LOGW(TAG, "Failed to sync preferences");
return false;
}
ESP_LOGD(TAG, "Noise PSK saved");
if (make_active) {
this->set_timeout(100, [this, psk]() {
ESP_LOGW(TAG, "Disconnecting all clients to reset connections");
this->set_noise_psk(psk);
for (auto &c : this->clients_) {
c->send_disconnect_request(DisconnectRequest());
}
});
}
return true;
}
#endif
#ifdef USE_HOMEASSISTANT_TIME
void APIServer::request_time() {
for (auto &client : this->clients_) {
if (!client->remove_ && client->is_authenticated())
client->send_time_request();
}
}
#endif
bool APIServer::is_connected() const { return !this->clients_.empty(); }
void APIServer::on_shutdown() {
for (auto &c : this->clients_) {
c->send_disconnect_request(DisconnectRequest());
}
delay(10);
}
} // namespace api
} // namespace esphome
#endif

View File

@ -19,6 +19,12 @@
namespace esphome {
namespace api {
#ifdef USE_API_NOISE
struct SavedNoisePsk {
psk_t psk;
} PACKED; // NOLINT
#endif
class APIServer : public Component, public Controller {
public:
APIServer();
@ -35,6 +41,7 @@ class APIServer : public Component, public Controller {
void set_reboot_timeout(uint32_t reboot_timeout);
#ifdef USE_API_NOISE
bool save_noise_psk(psk_t psk, bool make_active = true);
void set_noise_psk(psk_t psk) { noise_ctx_->set_psk(psk); }
std::shared_ptr<APINoiseContext> get_noise_ctx() { return noise_ctx_; }
#endif // USE_API_NOISE
@ -142,6 +149,7 @@ class APIServer : public Component, public Controller {
#ifdef USE_API_NOISE
std::shared_ptr<APINoiseContext> noise_ctx_ = std::make_shared<APINoiseContext>();
ESPPreferenceObject noise_pref_;
#endif // USE_API_NOISE
};

View File

@ -1,12 +1,11 @@
from __future__ import annotations
import asyncio
import logging
from datetime import datetime
from typing import Any
import logging
from typing import TYPE_CHECKING, Any
from aioesphomeapi import APIClient
from aioesphomeapi.api_pb2 import SubscribeLogsResponse
from aioesphomeapi.log_runner import async_run
from esphome.const import CONF_KEY, CONF_PASSWORD, CONF_PORT, __version__
@ -14,6 +13,12 @@ from esphome.core import CORE
from . import CONF_ENCRYPTION
if TYPE_CHECKING:
from aioesphomeapi.api_pb2 import (
SubscribeLogsResponse, # pylint: disable=no-name-in-module
)
_LOGGER = logging.getLogger(__name__)

View File

@ -10,37 +10,63 @@ namespace api {
#ifdef USE_BINARY_SENSOR
bool ListEntitiesIterator::on_binary_sensor(binary_sensor::BinarySensor *binary_sensor) {
return this->client_->send_binary_sensor_info(binary_sensor);
this->client_->send_binary_sensor_info(binary_sensor);
return true;
}
#endif
#ifdef USE_COVER
bool ListEntitiesIterator::on_cover(cover::Cover *cover) { return this->client_->send_cover_info(cover); }
bool ListEntitiesIterator::on_cover(cover::Cover *cover) {
this->client_->send_cover_info(cover);
return true;
}
#endif
#ifdef USE_FAN
bool ListEntitiesIterator::on_fan(fan::Fan *fan) { return this->client_->send_fan_info(fan); }
bool ListEntitiesIterator::on_fan(fan::Fan *fan) {
this->client_->send_fan_info(fan);
return true;
}
#endif
#ifdef USE_LIGHT
bool ListEntitiesIterator::on_light(light::LightState *light) { return this->client_->send_light_info(light); }
bool ListEntitiesIterator::on_light(light::LightState *light) {
this->client_->send_light_info(light);
return true;
}
#endif
#ifdef USE_SENSOR
bool ListEntitiesIterator::on_sensor(sensor::Sensor *sensor) { return this->client_->send_sensor_info(sensor); }
bool ListEntitiesIterator::on_sensor(sensor::Sensor *sensor) {
this->client_->send_sensor_info(sensor);
return true;
}
#endif
#ifdef USE_SWITCH
bool ListEntitiesIterator::on_switch(switch_::Switch *a_switch) { return this->client_->send_switch_info(a_switch); }
bool ListEntitiesIterator::on_switch(switch_::Switch *a_switch) {
this->client_->send_switch_info(a_switch);
return true;
}
#endif
#ifdef USE_BUTTON
bool ListEntitiesIterator::on_button(button::Button *button) { return this->client_->send_button_info(button); }
bool ListEntitiesIterator::on_button(button::Button *button) {
this->client_->send_button_info(button);
return true;
}
#endif
#ifdef USE_TEXT_SENSOR
bool ListEntitiesIterator::on_text_sensor(text_sensor::TextSensor *text_sensor) {
return this->client_->send_text_sensor_info(text_sensor);
this->client_->send_text_sensor_info(text_sensor);
return true;
}
#endif
#ifdef USE_LOCK
bool ListEntitiesIterator::on_lock(lock::Lock *a_lock) { return this->client_->send_lock_info(a_lock); }
bool ListEntitiesIterator::on_lock(lock::Lock *a_lock) {
this->client_->send_lock_info(a_lock);
return true;
}
#endif
#ifdef USE_VALVE
bool ListEntitiesIterator::on_valve(valve::Valve *valve) { return this->client_->send_valve_info(valve); }
bool ListEntitiesIterator::on_valve(valve::Valve *valve) {
this->client_->send_valve_info(valve);
return true;
}
#endif
bool ListEntitiesIterator::on_end() { return this->client_->send_list_info_done(); }
@ -52,55 +78,83 @@ bool ListEntitiesIterator::on_service(UserServiceDescriptor *service) {
#ifdef USE_ESP32_CAMERA
bool ListEntitiesIterator::on_camera(esp32_camera::ESP32Camera *camera) {
return this->client_->send_camera_info(camera);
this->client_->send_camera_info(camera);
return true;
}
#endif
#ifdef USE_CLIMATE
bool ListEntitiesIterator::on_climate(climate::Climate *climate) { return this->client_->send_climate_info(climate); }
bool ListEntitiesIterator::on_climate(climate::Climate *climate) {
this->client_->send_climate_info(climate);
return true;
}
#endif
#ifdef USE_NUMBER
bool ListEntitiesIterator::on_number(number::Number *number) { return this->client_->send_number_info(number); }
bool ListEntitiesIterator::on_number(number::Number *number) {
this->client_->send_number_info(number);
return true;
}
#endif
#ifdef USE_DATETIME_DATE
bool ListEntitiesIterator::on_date(datetime::DateEntity *date) { return this->client_->send_date_info(date); }
bool ListEntitiesIterator::on_date(datetime::DateEntity *date) {
this->client_->send_date_info(date);
return true;
}
#endif
#ifdef USE_DATETIME_TIME
bool ListEntitiesIterator::on_time(datetime::TimeEntity *time) { return this->client_->send_time_info(time); }
bool ListEntitiesIterator::on_time(datetime::TimeEntity *time) {
this->client_->send_time_info(time);
return true;
}
#endif
#ifdef USE_DATETIME_DATETIME
bool ListEntitiesIterator::on_datetime(datetime::DateTimeEntity *datetime) {
return this->client_->send_datetime_info(datetime);
this->client_->send_datetime_info(datetime);
return true;
}
#endif
#ifdef USE_TEXT
bool ListEntitiesIterator::on_text(text::Text *text) { return this->client_->send_text_info(text); }
bool ListEntitiesIterator::on_text(text::Text *text) {
this->client_->send_text_info(text);
return true;
}
#endif
#ifdef USE_SELECT
bool ListEntitiesIterator::on_select(select::Select *select) { return this->client_->send_select_info(select); }
bool ListEntitiesIterator::on_select(select::Select *select) {
this->client_->send_select_info(select);
return true;
}
#endif
#ifdef USE_MEDIA_PLAYER
bool ListEntitiesIterator::on_media_player(media_player::MediaPlayer *media_player) {
return this->client_->send_media_player_info(media_player);
this->client_->send_media_player_info(media_player);
return true;
}
#endif
#ifdef USE_ALARM_CONTROL_PANEL
bool ListEntitiesIterator::on_alarm_control_panel(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) {
return this->client_->send_alarm_control_panel_info(a_alarm_control_panel);
this->client_->send_alarm_control_panel_info(a_alarm_control_panel);
return true;
}
#endif
#ifdef USE_EVENT
bool ListEntitiesIterator::on_event(event::Event *event) { return this->client_->send_event_info(event); }
bool ListEntitiesIterator::on_event(event::Event *event) {
this->client_->send_event_info(event);
return true;
}
#endif
#ifdef USE_UPDATE
bool ListEntitiesIterator::on_update(update::UpdateEntity *update) { return this->client_->send_update_info(update); }
bool ListEntitiesIterator::on_update(update::UpdateEntity *update) {
this->client_->send_update_info(update);
return true;
}
#endif
} // namespace api

View File

@ -80,6 +80,7 @@ class ListEntitiesIterator : public ComponentIterator {
bool on_update(update::UpdateEntity *update) override;
#endif
bool on_end() override;
bool completed() { return this->state_ == IteratorState::NONE; }
protected:
APIConnection *client_;

View File

@ -76,6 +76,8 @@ class InitialStateIterator : public ComponentIterator {
#ifdef USE_UPDATE
bool on_update(update::UpdateEntity *update) override;
#endif
bool completed() { return this->state_ == IteratorState::NONE; }
protected:
APIConnection *client_;
};

View File

@ -1,17 +1,17 @@
from esphome import pins
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import pins
from esphome.const import (
CONF_CALIBRATION,
CONF_CAPACITANCE,
CONF_DIV_RATIO,
CONF_INDOOR,
CONF_IRQ_PIN,
CONF_LIGHTNING_THRESHOLD,
CONF_MASK_DISTURBER,
CONF_CALIBRATION,
CONF_TUNE_ANTENNA,
CONF_NOISE_LEVEL,
CONF_SPIKE_REJECTION,
CONF_TUNE_ANTENNA,
CONF_WATCHDOG_THRESHOLD,
)

View File

@ -1,6 +1,7 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import binary_sensor
import esphome.config_validation as cv
from . import AS3935, CONF_AS3935_ID
DEPENDENCIES = ["as3935"]

View File

@ -1,13 +1,14 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_DISTANCE,
CONF_LIGHTNING_ENERGY,
UNIT_KILOMETER,
ICON_SIGNAL_DISTANCE_VARIANT,
ICON_FLASH,
ICON_SIGNAL_DISTANCE_VARIANT,
UNIT_KILOMETER,
)
from . import AS3935, CONF_AS3935_ID
DEPENDENCIES = ["as3935"]

View File

@ -1,6 +1,6 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import as3935, i2c
import esphome.config_validation as cv
from esphome.const import CONF_ID
AUTO_LOAD = ["as3935"]

View File

@ -1,6 +1,6 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import as3935, spi
import esphome.config_validation as cv
from esphome.const import CONF_ID
AUTO_LOAD = ["as3935"]

View File

@ -1,12 +1,12 @@
from esphome import pins
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import i2c
import esphome.config_validation as cv
from esphome.const import (
CONF_ID,
CONF_DIR_PIN,
CONF_DIRECTION,
CONF_HYSTERESIS,
CONF_ID,
CONF_RANGE,
)

View File

@ -1,19 +1,20 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_ANGLE,
CONF_GAIN,
CONF_ID,
STATE_CLASS_MEASUREMENT,
CONF_MAGNITUDE,
CONF_POSITION,
CONF_STATUS,
ENTITY_CATEGORY_DIAGNOSTIC,
ICON_MAGNET,
ICON_ROTATE_RIGHT,
CONF_GAIN,
ENTITY_CATEGORY_DIAGNOSTIC,
CONF_MAGNITUDE,
CONF_STATUS,
CONF_POSITION,
CONF_ANGLE,
STATE_CLASS_MEASUREMENT,
)
from .. import as5600_ns, AS5600Component
from .. import AS5600Component, as5600_ns
CODEOWNERS = ["@ammmze"]
DEPENDENCIES = ["as5600"]

View File

@ -1,6 +1,6 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import i2c, sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_GAIN,
CONF_ID,
@ -9,7 +9,6 @@ from esphome.const import (
STATE_CLASS_MEASUREMENT,
)
CODEOWNERS = ["@mrgnr"]
DEPENDENCIES = ["i2c"]

View File

@ -1,13 +1,9 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import automation, core
from esphome.components import i2c
from esphome.automation import maybe_simple_id
from esphome.const import (
CONF_ID,
CONF_FREQUENCY,
)
import esphome.codegen as cg
from esphome.components import i2c
import esphome.config_validation as cv
from esphome.const import CONF_FREQUENCY, CONF_ID
CODEOWNERS = ["@X-Ryl669"]
DEPENDENCIES = ["i2c"]

View File

@ -1,10 +1,8 @@
import esphome.codegen as cg
from esphome.components import switch
import esphome.config_validation as cv
from esphome.const import (
DEVICE_CLASS_SWITCH,
ICON_WIFI,
)
from esphome.const import DEVICE_CLASS_SWITCH, ICON_WIFI
from .. import CONF_AT581X_ID, AT581XComponent, at581x_ns
DEPENDENCIES = ["at581x"]

View File

@ -1,14 +1,14 @@
import esphome.codegen as cg
from esphome.components import esp32_ble_tracker, sensor
import esphome.config_validation as cv
from esphome.components import sensor, esp32_ble_tracker
from esphome.const import (
CONF_BATTERY_LEVEL,
CONF_BATTERY_VOLTAGE,
CONF_MAC_ADDRESS,
CONF_HUMIDITY,
CONF_ID,
CONF_MAC_ADDRESS,
CONF_SIGNAL_STRENGTH,
CONF_TEMPERATURE,
CONF_ID,
DEVICE_CLASS_BATTERY,
DEVICE_CLASS_HUMIDITY,
DEVICE_CLASS_SIGNAL_STRENGTH,

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